diff options
author | Silenio <Silenio_Quarti@ca.ibm.com> | 2011-09-20 10:59:06 -0400 |
---|---|---|
committer | Silenio <Silenio_Quarti@ca.ibm.com> | 2011-09-20 10:59:06 -0400 |
commit | 78b034106c080360cc188a981bb53f8356762fbe (patch) | |
tree | d73b3770e92d4cf76efe8deb9f93a7618bf8ef58 | |
parent | d089b2cf79ce87d2a82f677ea1a4ce5a5ba9d4a4 (diff) | |
download | eclipse.platform.swt-78b034106c080360cc188a981bb53f8356762fbe.tar.gz eclipse.platform.swt-78b034106c080360cc188a981bb53f8356762fbe.tar.xz eclipse.platform.swt-78b034106c080360cc188a981bb53f8356762fbe.zip |
Bug354978 - work in progress - all images are cairo images surfaces
6 files changed, 377 insertions, 146 deletions
diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/OS.java b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/OS.java index 6d631ef093..02f3383419 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/OS.java +++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/OS.java @@ -557,6 +557,7 @@ public class OS extends C { public static final byte[] GTK_STOCK_CLEAR = ascii("gtk-clear"); public static final int GTK_VERSION = VERSION(gtk_major_version(), gtk_minor_version(), gtk_micro_version()); + public static final boolean USE_CAIRO_SURFACE = GTK_VERSION >= VERSION(2, 18, 0);//TODO this should probably be 2.22.0 protected static byte [] ascii (String name) { int length = name.length (); diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/graphics/Device.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/graphics/Device.java index ba668ccb3c..95945aedb3 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/graphics/Device.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/graphics/Device.java @@ -580,7 +580,7 @@ public boolean getWarnings () { protected void init () { this.dpi = getDPI(); - if (xDisplay != 0 && OS.GTK_VERSION < OS.VERSION(2, 22, 0)) { + if (xDisplay != 0 && !OS.USE_CAIRO_SURFACE) { int[] event_basep = new int[1], error_basep = new int [1]; if (OS.XRenderQueryExtension (xDisplay, event_basep, error_basep)) { int[] major_versionp = new int[1], minor_versionp = new int [1]; diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/graphics/GC.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/graphics/GC.java index 298ad0b212..1849226e9a 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/graphics/GC.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/graphics/GC.java @@ -2854,7 +2854,11 @@ void initCairo() { data.cairo = cairo = Cairo.cairo_create(surface); Cairo.cairo_surface_destroy(surface); } else { - data.cairo = cairo = OS.gdk_cairo_create(data.drawable); + if (OS.USE_CAIRO_SURFACE && data.image != null) { + data.cairo = cairo = Cairo.cairo_create(data.image.surface); + } else { + data.cairo = cairo = OS.gdk_cairo_create(data.drawable); + } } if (cairo == 0) SWT.error(SWT.ERROR_NO_HANDLES); data.disposeCairo = true; @@ -3163,7 +3167,7 @@ static void setCairoPatternColor(int /*long*/ pattern, int offset, Color c, int void setCairoClip(int /*long*/ damageRgn, int /*long*/ clipRgn) { int /*long*/ cairo = data.cairo; - if (OS.GTK_VERSION < OS.VERSION(2,18,0)) { + if (OS.GTK_VERSION < OS.VERSION(2,18,0) || data.drawable == 0) { Cairo.cairo_reset_clip(cairo); } else { OS.gdk_cairo_reset_clip(cairo, data.drawable); diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/graphics/Image.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/graphics/Image.java index 36c0370911..e3d7e970ae 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/graphics/Image.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/graphics/Image.java @@ -112,7 +112,7 @@ public final class Image extends Resource implements Drawable { */ public int /*long*/ mask; - int /*long*/ surface, surfaceData; + public int /*long*/ surface, surfaceData; /** * specifies the transparent pixel @@ -535,7 +535,7 @@ public Image(Device device, String filename) { super(device); if (filename == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); initNative(filename); - if (this.pixmap == 0) init(new ImageData(filename)); + if (this.pixmap == 0 && this.surface == 0) init(new ImageData(filename)); init(); } @@ -547,37 +547,79 @@ void initNative(String filename) { byte [] buffer = Converter.wcsToMbcs(null, chars, true); int /*long*/ pixbuf = OS.gdk_pixbuf_new_from_file(buffer, null); if (pixbuf != 0) { - boolean hasAlpha = OS.gdk_pixbuf_get_has_alpha(pixbuf); - if (hasAlpha) { - /* - * Bug in GTK. Depending on the image (seems to affect images that have - * some degree of transparency all over the image), gdk_pixbuff_render_pixmap_and_mask() - * will return a corrupt pixmap. To avoid this, read in and store the alpha channel data - * for the image and then set it to 0xFF to prevent any possible corruption from - * gdk_pixbuff_render_pixmap_and_mask(). - */ - int width = OS.gdk_pixbuf_get_width(pixbuf); - int height = OS.gdk_pixbuf_get_height(pixbuf); + if (OS.USE_CAIRO_SURFACE) { + int width = this.width = OS.gdk_pixbuf_get_width(pixbuf); + int height = this.height = OS.gdk_pixbuf_get_height(pixbuf); int stride = OS.gdk_pixbuf_get_rowstride(pixbuf); int /*long*/ pixels = OS.gdk_pixbuf_get_pixels(pixbuf); - byte[] line = new byte[stride]; - alphaData = new byte[width * height]; + int cairoStride = Cairo.cairo_format_stride_for_width(Cairo.CAIRO_FORMAT_ARGB32, width); + int /*long*/ data = surfaceData = OS.g_malloc(cairoStride * height); + if (surfaceData == 0) SWT.error(SWT.ERROR_NO_HANDLES); + surface = Cairo.cairo_image_surface_create_for_data(surfaceData, Cairo.CAIRO_FORMAT_ARGB32, width, height, cairoStride); + if (surface == 0) SWT.error(SWT.ERROR_NO_HANDLES); + byte[] line = new byte[Math.max(cairoStride, stride)]; + int /*long*/ ptr = OS.malloc(4); + OS.memmove(ptr, new int[]{1}, 4); + OS.memmove(line, ptr, 1); + OS.free(ptr); + boolean bigendian = line[0] == 0; + int oa = 0, or = 0, og = 0, ob = 0; + if (bigendian) { + oa = 0; or = 1; og = 2; ob = 3; + } else { + oa = 3; or = 2; og = 1; ob = 0; + } for (int y = 0; y < height; y++) { OS.memmove(line, pixels + (y * stride), stride); - for (int x = 0; x < width; x++) { - alphaData[y*width+x] = line[x*4 + 3]; - line[x*4 + 3] = (byte) 0xFF; + for (int x = 0, offset = 0; x < width; x++, offset += 4) { + int a = line[offset + 3] & 0xFF; + int r = ((line[offset + 0] & 0xFF) * a) + 128; + r = (r + (r >> 8)) >> 8; + int g = ((line[offset + 1] & 0xFF) * a) + 128; + g = (g + (g >> 8)) >> 8; + int b = ((line[offset + 2] & 0xFF) * a) + 128; + b = (b + (b >> 8)) >> 8; + line[offset + oa] = (byte)a; + line[offset + or] = (byte)r; + line[offset + og] = (byte)g; + line[offset + ob] = (byte)b; } - OS.memmove(pixels + (y * stride), line, stride); + OS.memmove(data + (y * cairoStride), line, cairoStride); } - createAlphaMask(width, height); + OS.g_object_unref (pixbuf); + } else { + boolean hasAlpha = OS.gdk_pixbuf_get_has_alpha(pixbuf); + if (hasAlpha) { + /* + * Bug in GTK. Depending on the image (seems to affect images that have + * some degree of transparency all over the image), gdk_pixbuff_render_pixmap_and_mask() + * will return a corrupt pixmap. To avoid this, read in and store the alpha channel data + * for the image and then set it to 0xFF to prevent any possible corruption from + * gdk_pixbuff_render_pixmap_and_mask(). + */ + int width = OS.gdk_pixbuf_get_width(pixbuf); + int height = OS.gdk_pixbuf_get_height(pixbuf); + int stride = OS.gdk_pixbuf_get_rowstride(pixbuf); + int /*long*/ pixels = OS.gdk_pixbuf_get_pixels(pixbuf); + byte[] line = new byte[stride]; + alphaData = new byte[width * height]; + for (int y = 0; y < height; y++) { + OS.memmove(line, pixels + (y * stride), stride); + for (int x = 0; x < width; x++) { + alphaData[y*width+x] = line[x*4 + 3]; + line[x*4 + 3] = (byte) 0xFF; + } + OS.memmove(pixels + (y * stride), line, stride); + } + createAlphaMask(width, height); + } + int /*long*/ [] pixmap_return = new int /*long*/ [1]; + OS.gdk_pixbuf_render_pixmap_and_mask(pixbuf, pixmap_return, null, 0); + OS.g_object_unref (pixbuf); + this.type = SWT.BITMAP; + this.pixmap = pixmap_return[0]; + if (pixmap == 0) SWT.error(SWT.ERROR_NO_HANDLES); } - int /*long*/ [] pixmap_return = new int /*long*/ [1]; - OS.gdk_pixbuf_render_pixmap_and_mask(pixbuf, pixmap_return, null, 0); - this.type = SWT.BITMAP; - this.pixmap = pixmap_return[0]; - if (pixmap == 0) SWT.error(SWT.ERROR_NO_HANDLES); - OS.g_object_unref (pixbuf); } } catch (SWTException e) {} } @@ -796,7 +838,11 @@ public boolean equals (Object object) { if (object == this) return true; if (!(object instanceof Image)) return false; Image image = (Image)object; - return device == image.device && pixmap == image.pixmap; + if (OS.USE_CAIRO_SURFACE) { + return device == image.device && surface == image.surface; + } else { + return device == image.device && pixmap == image.pixmap; + } } /** @@ -862,51 +908,87 @@ public Rectangle getBounds() { */ public ImageData getImageData() { if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); - - int[] w = new int[1], h = new int[1]; - OS.gdk_drawable_get_size(pixmap, w, h); - int width = w[0], height = h[0]; - int /*long*/ pixbuf = OS.gdk_pixbuf_new(OS.GDK_COLORSPACE_RGB, false, 8, width, height); - if (pixbuf == 0) SWT.error(SWT.ERROR_NO_HANDLES); - int /*long*/ colormap = OS.gdk_colormap_get_system(); - OS.gdk_pixbuf_get_from_drawable(pixbuf, pixmap, colormap, 0, 0, 0, 0, width, height); - int stride = OS.gdk_pixbuf_get_rowstride(pixbuf); - int /*long*/ pixels = OS.gdk_pixbuf_get_pixels(pixbuf); - byte[] srcData = new byte[stride * height]; - OS.memmove(srcData, pixels, srcData.length); - OS.g_object_unref(pixbuf); - - PaletteData palette = new PaletteData(0xFF0000, 0xFF00, 0xFF); - ImageData data = new ImageData(width, height, 24, palette, 4, srcData); - data.bytesPerLine = stride; - - if (transparentPixel == -1 && type == SWT.ICON && mask != 0) { - /* Get the icon mask data */ - int /*long*/ gdkImagePtr = OS.gdk_drawable_get_image(mask, 0, 0, width, height); - if (gdkImagePtr == 0) SWT.error(SWT.ERROR_NO_HANDLES); - GdkImage gdkImage = new GdkImage(); - OS.memmove(gdkImage, gdkImagePtr); - byte[] maskData = new byte[gdkImage.bpl * gdkImage.height]; - OS.memmove(maskData, gdkImage.mem, maskData.length); - OS.g_object_unref(gdkImagePtr); - int maskPad; - for (maskPad = 1; maskPad < 128; maskPad++) { - int bpl = (((width + 7) / 8) + (maskPad - 1)) / maskPad * maskPad; - if (gdkImage.bpl == bpl) break; + ImageData data; + if (OS.USE_CAIRO_SURFACE) { + int width = this.width; + int height = this.height; + int stride = Cairo.cairo_format_stride_for_width(Cairo.CAIRO_FORMAT_ARGB32, width); + byte[] srcData = new byte[stride * height]; + int /*long*/ ptr = OS.malloc(4); + OS.memmove(ptr, new int[]{1}, 4); + OS.memmove(srcData, ptr, 1); + OS.free(ptr); + int oa, or, og, ob; + boolean bigendian = srcData[0] == 0; + if (bigendian) { + oa = 0; or = 1; og = 2; ob = 3; + } else { + oa = 3; or = 2; og = 1; ob = 0; } - /* Make mask scanline pad equals to 2 */ - data.maskPad = 2; - maskData = ImageData.convertPad(maskData, width, height, 1, maskPad, data.maskPad); - /* Bit swap the mask data if necessary */ - if (gdkImage.byte_order == OS.GDK_LSB_FIRST) { - for (int i = 0; i < maskData.length; i++) { - byte b = maskData[i]; - maskData[i] = (byte)(((b & 0x01) << 7) | ((b & 0x02) << 5) | - ((b & 0x04) << 3) | ((b & 0x08) << 1) | ((b & 0x10) >> 1) | - ((b & 0x20) >> 3) | ((b & 0x40) >> 5) | ((b & 0x80) >> 7)); + OS.memmove(srcData, this.surfaceData, srcData.length); + PaletteData palette = new PaletteData(0xFF0000, 0xFF00, 0xFF); + data = new ImageData(width, height, 32, palette, 4, srcData); + int offset = 0; + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++, offset += 4) { + int a = srcData[offset + oa] & 0xFF; + int r = srcData[offset + or] & 0xFF; + int g = srcData[offset + og] & 0xFF; + int b = srcData[offset + ob] & 0xFF; + srcData[offset + 3] = (byte)a; + if (a != 0) { + srcData[offset + 2] = (byte)(((r) / (float)a) * 0xFF); + srcData[offset + 1] = (byte)(((g) / (float)a) * 0xFF); + srcData[offset + 0] = (byte)(((b) / (float)a) * 0xFF); + } + } + } + } else { + int[] w = new int[1], h = new int[1]; + OS.gdk_drawable_get_size(pixmap, w, h); + int width = w[0], height = h[0]; + int /*long*/ pixbuf = OS.gdk_pixbuf_new(OS.GDK_COLORSPACE_RGB, false, 8, width, height); + if (pixbuf == 0) SWT.error(SWT.ERROR_NO_HANDLES); + int /*long*/ colormap = OS.gdk_colormap_get_system(); + OS.gdk_pixbuf_get_from_drawable(pixbuf, pixmap, colormap, 0, 0, 0, 0, width, height); + int stride = OS.gdk_pixbuf_get_rowstride(pixbuf); + int /*long*/ pixels = OS.gdk_pixbuf_get_pixels(pixbuf); + byte[] srcData = new byte[stride * height]; + OS.memmove(srcData, pixels, srcData.length); + OS.g_object_unref(pixbuf); + + PaletteData palette = new PaletteData(0xFF0000, 0xFF00, 0xFF); + data = new ImageData(width, height, 24, palette, 4, srcData); + data.bytesPerLine = stride; + + if (transparentPixel == -1 && type == SWT.ICON && mask != 0) { + /* Get the icon mask data */ + int /*long*/ gdkImagePtr = OS.gdk_drawable_get_image(mask, 0, 0, width, height); + if (gdkImagePtr == 0) SWT.error(SWT.ERROR_NO_HANDLES); + GdkImage gdkImage = new GdkImage(); + OS.memmove(gdkImage, gdkImagePtr); + byte[] maskData = new byte[gdkImage.bpl * gdkImage.height]; + OS.memmove(maskData, gdkImage.mem, maskData.length); + OS.g_object_unref(gdkImagePtr); + int maskPad; + for (maskPad = 1; maskPad < 128; maskPad++) { + int bpl = (((width + 7) / 8) + (maskPad - 1)) / maskPad * maskPad; + if (gdkImage.bpl == bpl) break; + } + /* Make mask scanline pad equals to 2 */ + data.maskPad = 2; + maskData = ImageData.convertPad(maskData, width, height, 1, maskPad, data.maskPad); + /* Bit swap the mask data if necessary */ + if (gdkImage.byte_order == OS.GDK_LSB_FIRST) { + for (int i = 0; i < maskData.length; i++) { + byte b = maskData[i]; + maskData[i] = (byte)(((b & 0x01) << 7) | ((b & 0x02) << 5) | + ((b & 0x04) << 3) | ((b & 0x08) << 1) | ((b & 0x10) >> 1) | + ((b & 0x20) >> 3) | ((b & 0x40) >> 5) | ((b & 0x80) >> 7)); + } } + data.maskData = maskData; } - data.maskData = maskData; } data.transparentPixel = transparentPixel; data.alpha = alpha; @@ -953,7 +1035,11 @@ public static Image gtk_new(Device device, int type, int /*long*/ pixmap, int /* * @see #equals */ public int hashCode () { - return (int)/*64*/pixmap; + if (OS.USE_CAIRO_SURFACE) { + return (int)/*64*/surface; + } else { + return (int)/*64*/pixmap; + } } void init(int width, int height) { @@ -963,20 +1049,31 @@ void init(int width, int height) { this.type = SWT.BITMAP; /* Create the pixmap */ - this.pixmap = OS.gdk_pixmap_new(OS.GDK_ROOT_PARENT(), width, height, -1); - if (pixmap == 0) SWT.error(SWT.ERROR_NO_HANDLES); - /* Fill the bitmap with white */ - GdkColor white = new GdkColor(); - white.red = (short)0xFFFF; - white.green = (short)0xFFFF; - white.blue = (short)0xFFFF; - int /*long*/ colormap = OS.gdk_colormap_get_system(); - OS.gdk_colormap_alloc_color(colormap, white, true, true); - int /*long*/ gdkGC = OS.gdk_gc_new(pixmap); - OS.gdk_gc_set_foreground(gdkGC, white); - OS.gdk_draw_rectangle(pixmap, gdkGC, 1, 0, 0, width, height); - OS.g_object_unref(gdkGC); - OS.gdk_colormap_free_colors(colormap, white, 1); + if (OS.USE_CAIRO_SURFACE) { + int stride = Cairo.cairo_format_stride_for_width(Cairo.CAIRO_FORMAT_ARGB32, width); + int /*long*/ data = surfaceData = OS.g_malloc(stride * height); + if (surfaceData == 0) SWT.error(SWT.ERROR_NO_HANDLES); + surface = Cairo.cairo_image_surface_create_for_data(surfaceData, Cairo.CAIRO_FORMAT_ARGB32, width, height, stride); + if (surface == 0) SWT.error(SWT.ERROR_NO_HANDLES); + OS.memset(data, 0xff, stride * height); + this.width = width; + this.height = height; + } else { + this.pixmap = OS.gdk_pixmap_new(OS.GDK_ROOT_PARENT(), width, height, -1); + if (pixmap == 0) SWT.error(SWT.ERROR_NO_HANDLES); + /* Fill the bitmap with white */ + GdkColor white = new GdkColor(); + white.red = (short)0xFFFF; + white.green = (short)0xFFFF; + white.blue = (short)0xFFFF; + int /*long*/ colormap = OS.gdk_colormap_get_system(); + OS.gdk_colormap_alloc_color(colormap, white, true, true); + int /*long*/ gdkGC = OS.gdk_gc_new(pixmap); + OS.gdk_gc_set_foreground(gdkGC, white); + OS.gdk_draw_rectangle(pixmap, gdkGC, 1, 0, 0, width, height); + OS.g_object_unref(gdkGC); + OS.gdk_colormap_free_colors(colormap, white, 1); + } } void init(ImageData image) { @@ -987,15 +1084,34 @@ void init(ImageData image) { if (!(((image.depth == 1 || image.depth == 2 || image.depth == 4 || image.depth == 8) && !palette.isDirect) || ((image.depth == 8) || (image.depth == 16 || image.depth == 24 || image.depth == 32) && palette.isDirect))) SWT.error (SWT.ERROR_UNSUPPORTED_DEPTH); - int stride, destDepth; + int stride, destDepth, redMask = 0xFF0000, greenMask = 0xFF00, blueMask = 0xFF, srcOrder = ImageData.MSB_FIRST; int /*long*/ data, pixbuf = 0; - if (OS.GTK_VERSION >= OS.VERSION(2, 22, 0)) { + int oa = 0, or = 0, og = 0, ob = 0; + if (OS.USE_CAIRO_SURFACE) { stride = Cairo.cairo_format_stride_for_width(Cairo.CAIRO_FORMAT_ARGB32, width); data = surfaceData = OS.g_malloc(stride * height); if (surfaceData == 0) SWT.error(SWT.ERROR_NO_HANDLES); surface = Cairo.cairo_image_surface_create_for_data(surfaceData, Cairo.CAIRO_FORMAT_ARGB32, width, height, stride); if (surface == 0) SWT.error(SWT.ERROR_NO_HANDLES); destDepth = 32; + byte[] line = new byte[stride]; + int /*long*/ ptr = OS.malloc(4); + OS.memmove(ptr, new int[]{1}, 4); + OS.memmove(line, ptr, 1); + OS.free(ptr); + boolean bigendian = line[0] == 0; + if (bigendian) { + oa = 0; or = 1; og = 2; ob = 3; + redMask = 0xFF00; + greenMask = 0xFF0000; + blueMask = 0xFF000000; + } else { + oa = 3; or = 2; og = 1; ob = 0; + redMask = 0xFF0000; + greenMask = 0xFF00; + blueMask = 0xFF; + srcOrder = ImageData.LSB_FIRST; + } } else { pixbuf = OS.gdk_pixbuf_new(OS.GDK_COLORSPACE_RGB, false, 8, width, height); if (pixbuf == 0) SWT.error(SWT.ERROR_NO_HANDLES); @@ -1004,13 +1120,13 @@ void init(ImageData image) { destDepth = 24; } byte[] buffer = image.data; - if (!palette.isDirect || image.depth != destDepth || stride != image.bytesPerLine || palette.redMask != 0xFF0000 || palette.greenMask != 0xFF00 || palette.blueMask != 0xFF) { + if (!palette.isDirect || image.depth != destDepth || stride != image.bytesPerLine || palette.redMask != redMask || palette.greenMask != greenMask || palette.blueMask != blueMask) { buffer = new byte[stride * height]; if (palette.isDirect) { ImageData.blit(ImageData.BLIT_SRC, image.data, image.depth, image.bytesPerLine, image.getByteOrder(), 0, 0, width, height, palette.redMask, palette.greenMask, palette.blueMask, ImageData.ALPHA_OPAQUE, null, 0, 0, 0, - buffer, destDepth, stride, ImageData.MSB_FIRST, 0, 0, width, height, 0xFF0000, 0xFF00, 0xFF, + buffer, destDepth, stride, srcOrder, 0, 0, width, height, redMask, greenMask, blueMask, false, false); } else { RGB[] rgbs = palette.getRGBs(); @@ -1028,12 +1144,12 @@ void init(ImageData image) { ImageData.blit(ImageData.BLIT_SRC, image.data, image.depth, image.bytesPerLine, image.getByteOrder(), 0, 0, width, height, srcReds, srcGreens, srcBlues, ImageData.ALPHA_OPAQUE, null, 0, 0, 0, - buffer, destDepth, stride, ImageData.MSB_FIRST, 0, 0, width, height, 0xFF0000, 0xFF00, 0xFF, + buffer, destDepth, stride, srcOrder, 0, 0, width, height, redMask, greenMask, blueMask, false, false); } } OS.memmove(data, buffer, stride * height); - if (OS.GTK_VERSION < OS.VERSION(2, 22, 0) ) { + if (!OS.USE_CAIRO_SURFACE) { int /*long*/ pixmap = OS.gdk_pixmap_new (OS.GDK_ROOT_PARENT(), width, height, -1); if (pixmap == 0) SWT.error(SWT.ERROR_NO_HANDLES); int /*long*/ gdkGC = OS.gdk_gc_new(pixmap); @@ -1041,6 +1157,7 @@ void init(ImageData image) { OS.gdk_pixbuf_render_to_drawable(pixbuf, pixmap, gdkGC, 0, 0, 0, 0, width, height, OS.GDK_RGB_DITHER_NORMAL, 0, 0); OS.g_object_unref(gdkGC); OS.g_object_unref(pixbuf); + this.pixmap = pixmap; } boolean isIcon = image.getTransparencyType() == SWT.TRANSPARENCY_MASK; if (isIcon || image.transparentPixel != -1) { @@ -1057,9 +1174,31 @@ void init(ImageData image) { transparentPixel = rgb.red << 16 | rgb.green << 8 | rgb.blue; } } - int /*long*/ mask = createMask(image, isIcon); - if (mask == 0) SWT.error(SWT.ERROR_NO_HANDLES); - this.mask = mask; + if (OS.USE_CAIRO_SURFACE) { + ImageData mask = image.getTransparencyMask(); + int offset = 0; + for (int y = 0; y < height; y++) { + for (int x=0; x<width; x++, offset += 4) { + int alpha = mask.getPixel(x, y) == 0 ? 0 : 0xff; + /* pre-multiplied alpha */ + int r = ((buffer[offset + or] & 0xFF) * alpha) + 128; + r = (r + (r >> 8)) >> 8; + int g = ((buffer[offset + og] & 0xFF) * alpha) + 128; + g = (g + (g >> 8)) >> 8; + int b = ((buffer[offset + ob] & 0xFF) * alpha) + 128; + b = (b + (b >> 8)) >> 8; + buffer[offset + oa] = (byte)alpha; + buffer[offset + or] = (byte)r; + buffer[offset + og] = (byte)g; + buffer[offset + ob] = (byte)b; + } + } + OS.memmove(data, buffer, stride * height); + } else { + int /*long*/ mask = createMask(image, isIcon); + if (mask == 0) SWT.error(SWT.ERROR_NO_HANDLES); + this.mask = mask; + } if (isIcon) { this.type = SWT.ICON; } else { @@ -1073,9 +1212,49 @@ void init(ImageData image) { this.alphaData = new byte[image.alphaData.length]; System.arraycopy(image.alphaData, 0, this.alphaData, 0, alphaData.length); } + if (OS.USE_CAIRO_SURFACE) { + if (this.alpha != -1) { + int offset = 0; + for (int y = 0; y < height; y++) { + for (int x=0; x<width; x++, offset += 4) { + int alpha = this.alpha; + /* pre-multiplied alpha */ + int r = ((buffer[offset + or] & 0xFF) * alpha) + 128; + r = (r + (r >> 8)) >> 8; + int g = ((buffer[offset + og] & 0xFF) * alpha) + 128; + g = (g + (g >> 8)) >> 8; + int b = ((buffer[offset + ob] & 0xFF) * alpha) + 128; + b = (b + (b >> 8)) >> 8; + buffer[offset + oa] = (byte)alpha; + buffer[offset + or] = (byte)r; + buffer[offset + og] = (byte)g; + buffer[offset + ob] = (byte)b; + } + } + OS.memmove(data, buffer, stride * height); + } else if (this.alphaData != null) { + int offset = 0; + for (int y = 0; y < height; y++) { + for (int x=0; x<width; x++, offset += 4) { + int alpha = alphaData [y*width+x] & 0xFF; + /* pre-multiplied alpha */ + int r = ((buffer[offset + or] & 0xFF) * alpha) + 128; + r = (r + (r >> 8)) >> 8; + int g = ((buffer[offset + og] & 0xFF) * alpha) + 128; + g = (g + (g >> 8)) >> 8; + int b = ((buffer[offset + ob] & 0xFF) * alpha) + 128; + b = (b + (b >> 8)) >> 8; + buffer[offset + oa] = (byte)alpha; + buffer[offset + or] = (byte)r; + buffer[offset + og] = (byte)g; + buffer[offset + ob] = (byte)b; + } + } + OS.memmove(data, buffer, stride * height); + } + } createAlphaMask(width, height); } - this.pixmap = pixmap; } /** @@ -1094,11 +1273,12 @@ void init(ImageData image) { * @noreference This method is not intended to be referenced by clients. */ public int /*long*/ internal_new_GC (GCData data) { - if (pixmap == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); + if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); if (type != SWT.BITMAP || memGC != null) { SWT.error(SWT.ERROR_INVALID_ARGUMENT); } - int /*long*/ gdkGC = OS.gdk_gc_new(pixmap); + //TODO the handle of the GC should be a cairo object instead of GdkGC. + int /*long*/ gdkGC = OS.gdk_gc_new(OS.USE_CAIRO_SURFACE ? OS.GDK_ROOT_PARENT() : pixmap); if (data != null) { int mask = SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT; if ((data.style & mask) == 0) { @@ -1148,7 +1328,11 @@ public void internal_dispose_GC (int /*long*/ gdkGC, GCData data) { * @return <code>true</code> when the image is disposed and <code>false</code> otherwise */ public boolean isDisposed() { - return pixmap == 0; + if (OS.USE_CAIRO_SURFACE) { + return surface == 0; + } else { + return pixmap == 0; + } } /** @@ -1201,7 +1385,11 @@ public void setBackground(Color color) { */ public String toString () { if (isDisposed()) return "Image {*DISPOSED*}"; - return "Image {" + pixmap + "}"; + if (OS.USE_CAIRO_SURFACE) { + return "Image {" + surface + "}"; + } else { + return "Image {" + pixmap + "}"; + } } } diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Display.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Display.java index 1e44e55bdc..094e3a9718 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Display.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Display.java @@ -1059,55 +1059,93 @@ Image createImage (String name) { } static int /*long*/ createPixbuf(Image image) { - int [] w = new int [1], h = new int [1]; - OS.gdk_drawable_get_size (image.pixmap, w, h); - int /*long*/ colormap = OS.gdk_colormap_get_system (); int /*long*/ pixbuf; - boolean hasMask = image.mask != 0 && OS.gdk_drawable_get_depth (image.mask) == 1; - if (hasMask) { - pixbuf = OS.gdk_pixbuf_new (OS.GDK_COLORSPACE_RGB, true, 8, w [0], h [0]); + if (OS.USE_CAIRO_SURFACE) { + Rectangle bounds = image.getBounds(); + int w = bounds.width, h = bounds.height; + pixbuf = OS.gdk_pixbuf_new (OS.GDK_COLORSPACE_RGB, true, 8, w, h); if (pixbuf == 0) SWT.error (SWT.ERROR_NO_HANDLES); - OS.gdk_pixbuf_get_from_drawable (pixbuf, image.pixmap, colormap, 0, 0, 0, 0, w [0], h [0]); - int /*long*/ maskPixbuf = OS.gdk_pixbuf_new(OS.GDK_COLORSPACE_RGB, false, 8, w [0], h [0]); - if (maskPixbuf == 0) SWT.error (SWT.ERROR_NO_HANDLES); - OS.gdk_pixbuf_get_from_drawable(maskPixbuf, image.mask, 0, 0, 0, 0, 0, w [0], h [0]); - int stride = OS.gdk_pixbuf_get_rowstride(pixbuf); - int /*long*/ pixels = OS.gdk_pixbuf_get_pixels(pixbuf); + int stride = OS.gdk_pixbuf_get_rowstride (pixbuf); + int /*long*/ pixels = OS.gdk_pixbuf_get_pixels (pixbuf); byte[] line = new byte[stride]; - int maskStride = OS.gdk_pixbuf_get_rowstride(maskPixbuf); - int /*long*/ maskPixels = OS.gdk_pixbuf_get_pixels(maskPixbuf); - byte[] maskLine = new byte[maskStride]; - for (int y=0; y<h[0]; y++) { - int /*long*/ offset = pixels + (y * stride); - OS.memmove(line, offset, stride); - int /*long*/ maskOffset = maskPixels + (y * maskStride); - OS.memmove(maskLine, maskOffset, maskStride); - for (int x=0; x<w[0]; x++) { - if (maskLine[x * 3] == 0) { - line[x * 4 + 3] = 0; + int /*long*/ ptr = OS.malloc(4); + OS.memmove(ptr, new int[]{1}, 4); + OS.memmove(line, ptr, 1); + OS.free(ptr); + int oa, or, og, ob; + boolean bigendian = line[0] == 0; + if (bigendian) { + oa = 0; or = 1; og = 2; ob = 3; + } else { + oa = 3; or = 2; og = 1; ob = 0; + } + int /*long*/ surfaceData = image.surfaceData; + for (int y = 0; y < h; y++) { + OS.memmove (line, surfaceData + (y * stride), stride); + for (int x = 0, offset = 0; x < w; x++, offset += 4) { + int a = line[offset + oa] & 0xFF; + int r = line[offset + or] & 0xFF; + int g = line[offset + og] & 0xFF; + int b = line[offset + ob] & 0xFF; + line[offset + 3] = (byte)a; + if (a != 0) { + line[offset + 0] = (byte)(((r) / (float)a) * 0xFF); + line[offset + 1] = (byte)(((g) / (float)a) * 0xFF); + line[offset + 2] = (byte)(((b) / (float)a) * 0xFF); } } - OS.memmove(offset, line, stride); + OS.memmove (pixels + (y * stride), line, stride); } - OS.g_object_unref(maskPixbuf); } else { - ImageData data = image.getImageData (); - boolean hasAlpha = data.getTransparencyType () == SWT.TRANSPARENCY_ALPHA; - pixbuf = OS.gdk_pixbuf_new (OS.GDK_COLORSPACE_RGB, hasAlpha, 8, w [0], h [0]); - if (pixbuf == 0) SWT.error (SWT.ERROR_NO_HANDLES); - OS.gdk_pixbuf_get_from_drawable (pixbuf, image.pixmap, colormap, 0, 0, 0, 0, w [0], h [0]); - if (hasAlpha) { - byte [] alpha = data.alphaData; - int stride = OS.gdk_pixbuf_get_rowstride (pixbuf); - int /*long*/ pixels = OS.gdk_pixbuf_get_pixels (pixbuf); - byte [] line = new byte [stride]; - for (int y = 0; y < h [0]; y++) { + int [] w = new int [1], h = new int [1]; + OS.gdk_drawable_get_size (image.pixmap, w, h); + int /*long*/ colormap = OS.gdk_colormap_get_system (); + boolean hasMask = image.mask != 0 && OS.gdk_drawable_get_depth (image.mask) == 1; + if (hasMask) { + pixbuf = OS.gdk_pixbuf_new (OS.GDK_COLORSPACE_RGB, true, 8, w [0], h [0]); + if (pixbuf == 0) SWT.error (SWT.ERROR_NO_HANDLES); + OS.gdk_pixbuf_get_from_drawable (pixbuf, image.pixmap, colormap, 0, 0, 0, 0, w [0], h [0]); + int /*long*/ maskPixbuf = OS.gdk_pixbuf_new(OS.GDK_COLORSPACE_RGB, false, 8, w [0], h [0]); + if (maskPixbuf == 0) SWT.error (SWT.ERROR_NO_HANDLES); + OS.gdk_pixbuf_get_from_drawable(maskPixbuf, image.mask, 0, 0, 0, 0, 0, w [0], h [0]); + int stride = OS.gdk_pixbuf_get_rowstride(pixbuf); + int /*long*/ pixels = OS.gdk_pixbuf_get_pixels(pixbuf); + byte[] line = new byte[stride]; + int maskStride = OS.gdk_pixbuf_get_rowstride(maskPixbuf); + int /*long*/ maskPixels = OS.gdk_pixbuf_get_pixels(maskPixbuf); + byte[] maskLine = new byte[maskStride]; + for (int y=0; y<h[0]; y++) { int /*long*/ offset = pixels + (y * stride); - OS.memmove (line, offset, stride); - for (int x = 0; x < w [0]; x++) { - line [x*4+3] = alpha [y*w [0]+x]; + OS.memmove(line, offset, stride); + int /*long*/ maskOffset = maskPixels + (y * maskStride); + OS.memmove(maskLine, maskOffset, maskStride); + for (int x=0; x<w[0]; x++) { + if (maskLine[x * 3] == 0) { + line[x * 4 + 3] = 0; + } + } + OS.memmove(offset, line, stride); + } + OS.g_object_unref(maskPixbuf); + } else { + ImageData data = image.getImageData (); + boolean hasAlpha = data.getTransparencyType () == SWT.TRANSPARENCY_ALPHA; + pixbuf = OS.gdk_pixbuf_new (OS.GDK_COLORSPACE_RGB, hasAlpha, 8, w [0], h [0]); + if (pixbuf == 0) SWT.error (SWT.ERROR_NO_HANDLES); + OS.gdk_pixbuf_get_from_drawable (pixbuf, image.pixmap, colormap, 0, 0, 0, 0, w [0], h [0]); + if (hasAlpha) { + byte [] alpha = data.alphaData; + int stride = OS.gdk_pixbuf_get_rowstride (pixbuf); + int /*long*/ pixels = OS.gdk_pixbuf_get_pixels (pixbuf); + byte [] line = new byte [stride]; + for (int y = 0; y < h [0]; y++) { + int /*long*/ offset = pixels + (y * stride); + OS.memmove (line, offset, stride); + for (int x = 0; x < w [0]; x++) { + line [x*4+3] = alpha [y*w [0]+x]; + } + OS.memmove (offset, line, stride); } - OS.memmove (offset, line, stride); } } } diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/ImageList.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/ImageList.java index cab405e065..f7a098e53e 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/ImageList.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/ImageList.java @@ -110,14 +110,14 @@ public void remove (Image image) { } void set (int index, Image image) { - int [] w = new int [1], h = new int [1]; - OS.gdk_drawable_get_size (image.pixmap, w, h); int /*long*/ pixbuf = Display.createPixbuf (image); + int w = OS.gdk_pixbuf_get_width(pixbuf); + int h = OS.gdk_pixbuf_get_height(pixbuf); if (width == -1 || height == -1) { - width = w [0]; - height = h [0]; + width = w; + height = h; } - if (w [0] != width || h [0] != height) { + if (w != width || h != height) { int /*long*/ scaledPixbuf = OS.gdk_pixbuf_scale_simple(pixbuf, width, height, OS.GDK_INTERP_BILINEAR); OS.g_object_unref (pixbuf); pixbuf = scaledPixbuf; |