diff dwt/graphics/GC.d @ 240:ce446666f5a2

Update to SWT 3.4M7
author Frank Benoit <benoit@tionex.de>
date Mon, 12 May 2008 19:13:01 +0200
parents 380bad9f6852
children 448eacc3a526
line wrap: on
line diff
--- a/dwt/graphics/GC.d	Mon May 12 15:36:37 2008 +0200
+++ b/dwt/graphics/GC.d	Mon May 12 19:13:01 2008 +0200
@@ -78,6 +78,9 @@
  * @see dwt.events.PaintEvent
  */
 public final class GC : Resource {
+
+    alias Resource.init_ init_;
+
     /**
      * the handle to the OS device context
      * (Warning: This field is platform dependent)
@@ -180,8 +183,8 @@
     if (device is null) device = Device.getDevice();
     if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT);
     this.device = data.device = device;
-    init(drawable, data, gdkGC);
-    if (device.tracking) device.new_Object(this);
+    init_(drawable, data, gdkGC);
+    init_();
 }
 
 static void addCairoString(cairo_t* cairo, String str, float x, float y, Font font) {
@@ -191,7 +194,11 @@
         if (layout is null) DWT.error(DWT.ERROR_NO_HANDLES);
         OS.pango_layout_set_text(layout, buffer, -1);
         OS.pango_layout_set_font_description(layout, font.handle);
-        Cairo.cairo_move_to(cairo, x, y);
+        double currentX, currentY;
+        Cairo.cairo_get_current_point(cairo, &currentX, &currentY);
+        if (currentX !is x || currentY !is y) {
+            Cairo.cairo_move_to(cairo, x, y);
+        }
         OS.pango_cairo_layout_path(cairo, layout);
         OS.g_object_unref(layout);
     } else {
@@ -209,11 +216,18 @@
     return style & (DWT.LEFT_TO_RIGHT | DWT.RIGHT_TO_LEFT);
 }
 
+public static GC gtk_new(GdkGC* handle, GCData data) {
+    GC gc = new GC();
+    gc.device = data.device;
+    gc.init_(null, data, handle);
+    return gc;
+}
+
 public static GC gtk_new(Drawable drawable, GCData data) {
     GC gc = new GC();
     auto gdkGC = drawable.internal_new_GC(data);
     gc.device = data.device;
-    gc.init(drawable, data, gdkGC);
+    gc.init_(drawable, data, gdkGC);
     return gc;
 }
 
@@ -237,14 +251,25 @@
                 data.state &= ~FOREGROUND;
             }
             if  (pattern !is null) {
-                Cairo.cairo_set_source(cairo, pattern.handle);
+                if ((data.style & DWT.MIRRORED) !is 0 && pattern.surface !is null) {
+                    auto newPattern = Cairo.cairo_pattern_create_for_surface(pattern.surface);
+                    if (newPattern is null) DWT.error(DWT.ERROR_NO_HANDLES);
+                    Cairo.cairo_pattern_set_extend(newPattern, Cairo.CAIRO_EXTEND_REPEAT);
+                    double[6] matrix; matrix[0] = -1; matrix[1] = 0; matrix[2] = 0; matrix[3] = 1; matrix[4] = 0; matrix[5] = 0;
+                    Cairo.cairo_pattern_set_matrix(newPattern, cast(cairo_matrix_t*) matrix.ptr);
+                    Cairo.cairo_set_source(cairo, newPattern);
+                    Cairo.cairo_pattern_destroy(newPattern);
+                } else {
+                    Cairo.cairo_set_source(cairo, pattern.handle);
+                }
             } else {
                 Cairo.cairo_set_source_rgba(cairo, (color.red & 0xFFFF) / cast(float)0xFFFF, (color.green & 0xFFFF) / cast(float)0xFFFF, (color.blue & 0xFFFF) / cast(float)0xFFFF, data.alpha / cast(float)0xFF);
             }
         }
         if ((state & FONT) !is 0) {
             if (data.layout !is null) {
-                OS.pango_layout_set_font_description(data.layout, data.font);
+                Font font = data.font;
+                OS.pango_layout_set_font_description(data.layout, font.handle);
             }
             if (OS.GTK_VERSION < OS.buildVERSION(2, 8, 0)) {
                 setCairoFont(cairo, data.font);
@@ -312,13 +337,16 @@
             data.cairoXoffset = data.cairoYoffset = 0;
             double[] matrix = new double[6];
             Cairo.cairo_get_matrix(cairo,cast(cairo_matrix_t*) matrix.ptr);
-            double scaling = matrix[0];
+            double dx = 1;
+            double dy = 1;
+            Cairo.cairo_user_to_device_distance(cairo, &dx, &dy);
+            double scaling = dx;
             if (scaling < 0) scaling = -scaling;
             double strokeWidth = data.lineWidth * scaling;
             if (strokeWidth is 0 || (cast(int)strokeWidth % 2) is 1) {
                 data.cairoXoffset = 0.5 / scaling;
             }
-            scaling = matrix[3];
+            scaling = dy;
             if (scaling < 0) scaling = -scaling;
             strokeWidth = data.lineWidth * scaling;
             if (strokeWidth is 0 || (cast(int)strokeWidth % 2) is 1) {
@@ -344,7 +372,8 @@
     }
     if ((state & FONT) !is 0) {
         if (data.layout !is null) {
-            OS.pango_layout_set_font_description(data.layout, data.font);
+            Font font = data.font;
+            OS.pango_layout_set_font_description(data.layout, font.handle);
         }
     }
     if ((state & (LINE_CAP | LINE_JOIN | LINE_STYLE | LINE_WIDTH)) !is 0) {
@@ -544,7 +573,7 @@
     if (layout is null) DWT.error(DWT.ERROR_NO_HANDLES);
     data.layout = layout;
     OS.pango_context_set_language(context, OS.gtk_get_default_language());
-    OS.pango_context_set_base_dir(context, OS.PANGO_DIRECTION_LTR);
+    OS.pango_context_set_base_dir(context, (data.style & DWT.MIRRORED) !is 0 ? OS.PANGO_DIRECTION_RTL : OS.PANGO_DIRECTION_LTR);
     OS.gdk_pango_context_set_colormap(context, OS.gdk_colormap_get_system());
     if (OS.GTK_VERSION >= OS.buildVERSION(2, 4, 0)) {
         OS.pango_layout_set_auto_dir(layout, false);
@@ -559,19 +588,7 @@
     data.context = null;
 }
 
-/**
- * Disposes of the operating system resources associated with
- * the graphics context. Applications must dispose of all GCs
- * which they allocate.
- *
- * @exception DWTError <ul>
- *    <li>ERROR_THREAD_INVALID_ACCESS if not called from the thread that created the drawable</li>
- * </ul>
- */
-public override void dispose() {
-    if (handle is null) return;
-    if (data.device.isDisposed()) return;
-
+void destroy() {
     if (data.disposeCairo) {
         auto cairo = data.cairo;
         if (cairo !is null) Cairo.cairo_destroy(cairo);
@@ -590,17 +607,15 @@
     disposeLayout();
 
     /* Dispose the GC */
-    Device device = data.device;
-    drawable.internal_dispose_GC(handle, data);
-
+    if (drawable !is null) {
+        drawable.internal_dispose_GC(handle, data);
+    }
     data.drawable = null;
     data.clipRgn = null;
     drawable = null;
     handle = null;
     data.image = null;
     data.str = null;
-    if (device.tracking) device.dispose_Object(this);
-    data.device = null;
     data = null;
 }
 
@@ -808,6 +823,10 @@
         if (data.alpha !is 0) {
             srcImage.createSurface();
             Cairo.cairo_save(cairo);
+            if ((data.style & DWT.MIRRORED) !is 0) {
+                Cairo.cairo_scale(cairo, -1f,  1);
+                Cairo.cairo_translate(cairo, - 2 * destX - destWidth, 0);
+            }
             Cairo.cairo_rectangle(cairo, destX , destY, destWidth, destHeight);
             Cairo.cairo_clip(cairo);
             Cairo.cairo_translate(cairo, destX - srcX, destY - srcY);
@@ -1054,7 +1073,7 @@
 void drawImageXRender(Image srcImage, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight, bool simple, int imgWidth, int imgHeight, GdkDrawable* maskPixmap, int maskType) {
     int translateX = 0, translateY = 0;
     auto drawable = data.drawable;
-    if (data.image is null) {
+    if (data.image is null && !data.realDrawable) {
         int x, y;
         GdkDrawable* real_drawable;
         OS.gdk_window_get_internal_paint_info(cast(GdkWindow*)drawable, &real_drawable, &x, &y);
@@ -1448,21 +1467,25 @@
     if (nah < 0) nah = 0 - nah;
     auto cairo = data.cairo;
     if (cairo !is null) {
-        float naw2 = naw / 2f;
-        float nah2 = nah / 2f;
-        float fw = nw / naw2;
-        float fh = nh / nah2;
-        Cairo.cairo_save(cairo);
         double xOffset = data.cairoXoffset, yOffset = data.cairoYoffset;
-        Cairo.cairo_translate(cairo, nx + xOffset, ny + yOffset);
-        Cairo.cairo_scale(cairo, naw2, nah2);
-        Cairo.cairo_move_to(cairo, fw - 1, 0);
-        Cairo.cairo_arc(cairo, fw - 1, 1, 1, Compatibility.PI + Compatibility.PI/2.0, Compatibility.PI*2.0);
-        Cairo.cairo_arc(cairo, fw - 1, fh - 1, 1, 0, Compatibility.PI/2.0);
-        Cairo.cairo_arc(cairo, 1, fh - 1, 1, Compatibility.PI/2, Compatibility.PI);
-        Cairo.cairo_arc(cairo, 1, 1, 1, Compatibility.PI, 270.0*Compatibility.PI/180.0);
-        Cairo.cairo_close_path(cairo);
-        Cairo.cairo_restore(cairo);
+        if (naw is 0 || nah is 0) {
+            Cairo.cairo_rectangle(cairo, x + xOffset, y + yOffset, width, height);
+        } else {
+            float naw2 = naw / 2f;
+            float nah2 = nah / 2f;
+            float fw = nw / naw2;
+            float fh = nh / nah2;
+            Cairo.cairo_save(cairo);
+            Cairo.cairo_translate(cairo, nx + xOffset, ny + yOffset);
+            Cairo.cairo_scale(cairo, naw2, nah2);
+            Cairo.cairo_move_to(cairo, fw - 1, 0);
+            Cairo.cairo_arc(cairo, fw - 1, 1, 1, Compatibility.PI + Compatibility.PI/2.0, Compatibility.PI*2.0);
+            Cairo.cairo_arc(cairo, fw - 1, fh - 1, 1, 0, Compatibility.PI/2.0);
+            Cairo.cairo_arc(cairo, 1, fh - 1, 1, Compatibility.PI/2, Compatibility.PI);
+            Cairo.cairo_arc(cairo, 1, 1, 1, Compatibility.PI, 270.0*Compatibility.PI/180.0);
+            Cairo.cairo_close_path(cairo);
+            Cairo.cairo_restore(cairo);
+        }
         Cairo.cairo_stroke(cairo);
         return;
     }
@@ -1653,8 +1676,19 @@
             Cairo.cairo_fill(cairo);
         }
         checkGC(FOREGROUND | FONT);
+        if ((data.style & DWT.MIRRORED) !is 0) {
+            Cairo.cairo_save(cairo);
+            int width, height;
+            OS.pango_layout_get_size(data.layout, &width, &height);
+            Cairo.cairo_scale(cairo, -1f,  1);
+            Cairo.cairo_translate(cairo, -2 * x - OS.PANGO_PIXELS(width), 0);
+        }
         Cairo.cairo_move_to(cairo, x, y);
         OS.pango_cairo_show_layout(cairo, data.layout);
+        if ((data.style & DWT.MIRRORED) !is 0) {
+            Cairo.cairo_restore(cairo);
+        }
+        Cairo.cairo_new_path(cairo);
         return;
     }
     checkGC(FOREGROUND | FONT | BACKGROUND_BG);
@@ -2055,20 +2089,24 @@
     if (nah < 0) nah = 0 - nah;
     auto cairo = data.cairo;
     if (cairo !is null) {
-        float naw2 = naw / 2f;
-        float nah2 = nah / 2f;
-        float fw = nw / naw2;
-        float fh = nh / nah2;
-        Cairo.cairo_save(cairo);
-        Cairo.cairo_translate(cairo, nx, ny);
-        Cairo.cairo_scale(cairo, naw2, nah2);
-        Cairo.cairo_move_to(cairo, fw - 1, 0);
-        Cairo.cairo_arc(cairo, fw - 1, 1, 1, Compatibility.PI + Compatibility.PI/2.0, Compatibility.PI*2.0);
-        Cairo.cairo_arc(cairo, fw - 1, fh - 1, 1, 0, Compatibility.PI/2.0);
-        Cairo.cairo_arc(cairo, 1, fh - 1, 1, Compatibility.PI/2, Compatibility.PI);
-        Cairo.cairo_arc(cairo, 1, 1, 1, Compatibility.PI, 270.0*Compatibility.PI/180.0);
-        Cairo.cairo_close_path(cairo);
-        Cairo.cairo_restore(cairo);
+        if (naw is 0 || nah is 0) {
+            Cairo.cairo_rectangle(cairo, x, y, width, height);
+        } else {
+            float naw2 = naw / 2f;
+            float nah2 = nah / 2f;
+            float fw = nw / naw2;
+            float fh = nh / nah2;
+            Cairo.cairo_save(cairo);
+            Cairo.cairo_translate(cairo, nx, ny);
+            Cairo.cairo_scale(cairo, naw2, nah2);
+            Cairo.cairo_move_to(cairo, fw - 1, 0);
+            Cairo.cairo_arc(cairo, fw - 1, 1, 1, Compatibility.PI + Compatibility.PI/2.0, Compatibility.PI*2.0);
+            Cairo.cairo_arc(cairo, fw - 1, fh - 1, 1, 0, Compatibility.PI/2.0);
+            Cairo.cairo_arc(cairo, 1, fh - 1, 1, Compatibility.PI/2, Compatibility.PI);
+            Cairo.cairo_arc(cairo, 1, 1, 1, Compatibility.PI, 270.0*Compatibility.PI/180.0);
+            Cairo.cairo_close_path(cairo);
+            Cairo.cairo_restore(cairo);
+        }
         Cairo.cairo_fill(cairo);
         return;
     }
@@ -2283,10 +2321,15 @@
     if (handle is null) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED);
     /* Calculate visible bounds in device space */
     int x = 0, y = 0, width = 0, height = 0;
-    int w, h;
-    OS.gdk_drawable_get_size(data.drawable, &w, &h);
-    width = w;
-    height = h;
+    if (data.width !is -1 && data.height !is -1) {
+        width = data.width;
+        height = data.height;
+    } else {
+        int w, h;
+        OS.gdk_drawable_get_size(data.drawable, &w, &h);
+        width = w;
+        height = h;
+    }
     /* Intersect visible bounds with clipping in device space and then convert then to user space */
     auto cairo = data.cairo;
     auto clipRgn = data.clipRgn;
@@ -2353,11 +2396,16 @@
     auto cairo = data.cairo;
     auto clipRgn = data.clipRgn;
     if (clipRgn is null) {
-        int width,height;
-        OS.gdk_drawable_get_size(data.drawable, &width, &height);
         GdkRectangle rect;
-        rect.width = width;
-        rect.height = height;
+        if (data.width !is -1 && data.height !is -1) {
+            rect.width = data.width;
+            rect.height = data.height;
+        } else {
+            int width, height;
+            OS.gdk_drawable_get_size(data.drawable, &width, &height);
+            rect.width = width;
+            rect.height = height;
+        }
         OS.gdk_region_union_with_rect(clipping, &rect);
     } else {
         /* Convert clipping to device space if needed */
@@ -2415,7 +2463,7 @@
  */
 public Font getFont() {
     if (handle is null) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED);
-    return Font.gtk_new(data.device, data.font);
+    return data.font;
 }
 
 /**
@@ -2433,9 +2481,10 @@
     if (handle is null) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED);
     if (data.context is null) createLayout();
     checkGC(FONT);
+    Font font = data.font;
     auto context = data.context;
     auto lang = OS.pango_context_get_language(context);
-    auto metrics = OS.pango_context_get_metrics(context, data.font, lang);
+    auto metrics = OS.pango_context_get_metrics(context, font.handle, lang);
     FontMetrics fm = new FontMetrics();
     fm.ascent = OS.PANGO_PIXELS(OS.pango_font_metrics_get_ascent(metrics));
     fm.descent = OS.PANGO_PIXELS(OS.pango_font_metrics_get_descent(metrics));
@@ -2723,6 +2772,9 @@
     auto cairo = data.cairo;
     if (cairo !is null) {
         Cairo.cairo_get_matrix(cairo, cast(cairo_matrix_t*)transform.handle.ptr);
+        double[] identity = identity();
+        Cairo.cairo_matrix_invert(cast(cairo_matrix_t*)identity.ptr);
+        Cairo.cairo_matrix_multiply(cast(cairo_matrix_t*)transform.handle.ptr, cast(cairo_matrix_t*)transform.handle.ptr, cast(cairo_matrix_t*)identity.ptr);
     } else {
         transform.setElements(1, 0, 0, 1, 0, 0);
     }
@@ -2765,7 +2817,19 @@
     return cast(hash_t)/*64*/handle;
 }
 
-void init(Drawable drawable, GCData data, GdkGC* gdkGC) {
+double[] identity() {
+    double[] identity = new double[6];
+    if ((data.style & DWT.MIRRORED) !is 0) {
+        int w, h;
+        OS.gdk_drawable_get_size(data.drawable, &w, &h);
+        Cairo.cairo_matrix_init(cast(cairo_matrix_t*)identity.ptr, -1, 0, 0, 1, w, 0);
+    } else {
+        Cairo.cairo_matrix_init_identity(cast(cairo_matrix_t*)identity.ptr);
+    }
+    return identity;
+}
+
+void init_(Drawable drawable, GCData data, GdkGC* gdkGC) {
     if (data.foreground !is null) data.state &= ~FOREGROUND;
     if (data.background !is null) data.state &= ~(BACKGROUND | BACKGROUND_BG);
     if (data.font !is null) data.state &= ~FONT;
@@ -2783,6 +2847,11 @@
     this.drawable = drawable;
     this.data = data;
     handle = gdkGC;
+    if ((data.style & DWT.MIRRORED) !is 0) {
+      initCairo();
+      auto cairo = data.cairo;
+      Cairo.cairo_set_matrix(cairo, cast(cairo_matrix_t*) identity().ptr);
+    }
 }
 
 void initCairo() {
@@ -2797,12 +2866,14 @@
     if (data.image !is null) {
         xDrawable = OS.GDK_PIXMAP_XID(drawable);
     } else {
-        int x, y;
-        GdkDrawable* real_drawable;
-        OS.gdk_window_get_internal_paint_info(cast(GdkWindow*)drawable, &real_drawable, &x, &y);
-        xDrawable = OS.gdk_x11_drawable_get_xid(real_drawable);
-        translateX = -x;
-        translateY = -y;
+        if (!data.realDrawable) {
+            int x, y;
+            GdkDrawable* real_drawable;
+            OS.gdk_window_get_internal_paint_info(cast(GdkWindow*)drawable, &real_drawable, &x, &y);
+            xDrawable = OS.gdk_x11_drawable_get_xid(real_drawable);
+            translateX = -x;
+            translateY = -y;
+        }
     }
     int w, h;
     OS.gdk_drawable_get_size(drawable, &w, &h);
@@ -2901,6 +2972,19 @@
  */
 public void setAdvanced(bool advanced) {
     if (handle is null) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED);
+    if ((data.style & DWT.MIRRORED) !is 0) {
+        if (!advanced) {
+            setAlpha(0xFF);
+            setAntialias(DWT.DEFAULT);
+            setBackgroundPattern(null);
+            setClipping(cast(GdkRegion*)null);
+            setForegroundPattern(null);
+            setInterpolation(DWT.DEFAULT);
+            setTextAntialias(DWT.DEFAULT);
+            setTransform(null);
+        }
+        return;
+    }
     if (advanced && data.cairo !is null) return;
     if (advanced) {
         try {
@@ -3268,9 +3352,8 @@
  */
 public void setFont(Font font) {
     if (handle is null) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED);
-    if (font is null) font = data.device.systemFont;
-    if (font.isDisposed()) DWT.error(DWT.ERROR_INVALID_ARGUMENT);
-    data.font = font.handle;
+    if (font !is null && font.isDisposed()) DWT.error(DWT.ERROR_INVALID_ARGUMENT);
+    data.font = font !is null ? font : data.device.systemFont;
     data.state &= ~FONT;
     data.stringWidth = data.stringHeight = -1;
 }
@@ -3469,7 +3552,7 @@
                 DWT.error(DWT.ERROR_INVALID_ARGUMENT);
         }
     }
-    int cap = attributes.join;
+    int cap = attributes.cap;
     if (cap !is data.lineCap) {
         mask |= LINE_CAP;
         switch (cap) {
@@ -3810,11 +3893,11 @@
     if (data.cairo is null && transform is null) return;
     initCairo();
     auto cairo = data.cairo;
+    double[] identity = identity();
     if (transform !is null) {
-        Cairo.cairo_set_matrix(cairo,cast(cairo_matrix_t*) transform.handle.ptr);
-    } else {
-        Cairo.cairo_identity_matrix(cairo);
+        Cairo.cairo_matrix_multiply(cast(cairo_matrix_t*)identity.ptr, cast(cairo_matrix_t*)transform.handle.ptr, cast(cairo_matrix_t*)identity.ptr);
     }
+    Cairo.cairo_set_matrix(cairo, cast(cairo_matrix_t*)identity.ptr);
     data.state &= ~DRAW_OFFSET;
 }