comparison 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
comparison
equal deleted inserted replaced
239:06a1f6829310 240:ce446666f5a2
76 * </p> 76 * </p>
77 * 77 *
78 * @see dwt.events.PaintEvent 78 * @see dwt.events.PaintEvent
79 */ 79 */
80 public final class GC : Resource { 80 public final class GC : Resource {
81
82 alias Resource.init_ init_;
83
81 /** 84 /**
82 * the handle to the OS device context 85 * the handle to the OS device context
83 * (Warning: This field is platform dependent) 86 * (Warning: This field is platform dependent)
84 * <p> 87 * <p>
85 * <b>IMPORTANT:</b> This field is <em>not</em> part of the DWT 88 * <b>IMPORTANT:</b> This field is <em>not</em> part of the DWT
178 auto gdkGC = drawable.internal_new_GC(data); 181 auto gdkGC = drawable.internal_new_GC(data);
179 Device device = data.device; 182 Device device = data.device;
180 if (device is null) device = Device.getDevice(); 183 if (device is null) device = Device.getDevice();
181 if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); 184 if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT);
182 this.device = data.device = device; 185 this.device = data.device = device;
183 init(drawable, data, gdkGC); 186 init_(drawable, data, gdkGC);
184 if (device.tracking) device.new_Object(this); 187 init_();
185 } 188 }
186 189
187 static void addCairoString(cairo_t* cairo, String str, float x, float y, Font font) { 190 static void addCairoString(cairo_t* cairo, String str, float x, float y, Font font) {
188 char* buffer = toStringz( str ); 191 char* buffer = toStringz( str );
189 if (OS.GTK_VERSION >= OS.buildVERSION(2, 8, 0)) { 192 if (OS.GTK_VERSION >= OS.buildVERSION(2, 8, 0)) {
190 auto layout = OS.pango_cairo_create_layout(cairo); 193 auto layout = OS.pango_cairo_create_layout(cairo);
191 if (layout is null) DWT.error(DWT.ERROR_NO_HANDLES); 194 if (layout is null) DWT.error(DWT.ERROR_NO_HANDLES);
192 OS.pango_layout_set_text(layout, buffer, -1); 195 OS.pango_layout_set_text(layout, buffer, -1);
193 OS.pango_layout_set_font_description(layout, font.handle); 196 OS.pango_layout_set_font_description(layout, font.handle);
194 Cairo.cairo_move_to(cairo, x, y); 197 double currentX, currentY;
198 Cairo.cairo_get_current_point(cairo, &currentX, &currentY);
199 if (currentX !is x || currentY !is y) {
200 Cairo.cairo_move_to(cairo, x, y);
201 }
195 OS.pango_cairo_layout_path(cairo, layout); 202 OS.pango_cairo_layout_path(cairo, layout);
196 OS.g_object_unref(layout); 203 OS.g_object_unref(layout);
197 } else { 204 } else {
198 GC.setCairoFont(cairo, font); 205 GC.setCairoFont(cairo, font);
199 cairo_font_extents_t* extents = new cairo_font_extents_t(); 206 cairo_font_extents_t* extents = new cairo_font_extents_t();
207 static int checkStyle (int style) { 214 static int checkStyle (int style) {
208 if ((style & DWT.LEFT_TO_RIGHT) !is 0) style &= ~DWT.RIGHT_TO_LEFT; 215 if ((style & DWT.LEFT_TO_RIGHT) !is 0) style &= ~DWT.RIGHT_TO_LEFT;
209 return style & (DWT.LEFT_TO_RIGHT | DWT.RIGHT_TO_LEFT); 216 return style & (DWT.LEFT_TO_RIGHT | DWT.RIGHT_TO_LEFT);
210 } 217 }
211 218
219 public static GC gtk_new(GdkGC* handle, GCData data) {
220 GC gc = new GC();
221 gc.device = data.device;
222 gc.init_(null, data, handle);
223 return gc;
224 }
225
212 public static GC gtk_new(Drawable drawable, GCData data) { 226 public static GC gtk_new(Drawable drawable, GCData data) {
213 GC gc = new GC(); 227 GC gc = new GC();
214 auto gdkGC = drawable.internal_new_GC(data); 228 auto gdkGC = drawable.internal_new_GC(data);
215 gc.device = data.device; 229 gc.device = data.device;
216 gc.init(drawable, data, gdkGC); 230 gc.init_(drawable, data, gdkGC);
217 return gc; 231 return gc;
218 } 232 }
219 233
220 void checkGC (int mask) { 234 void checkGC (int mask) {
221 int state = data.state; 235 int state = data.state;
235 color = data.background; 249 color = data.background;
236 pattern = data.backgroundPattern; 250 pattern = data.backgroundPattern;
237 data.state &= ~FOREGROUND; 251 data.state &= ~FOREGROUND;
238 } 252 }
239 if (pattern !is null) { 253 if (pattern !is null) {
240 Cairo.cairo_set_source(cairo, pattern.handle); 254 if ((data.style & DWT.MIRRORED) !is 0 && pattern.surface !is null) {
255 auto newPattern = Cairo.cairo_pattern_create_for_surface(pattern.surface);
256 if (newPattern is null) DWT.error(DWT.ERROR_NO_HANDLES);
257 Cairo.cairo_pattern_set_extend(newPattern, Cairo.CAIRO_EXTEND_REPEAT);
258 double[6] matrix; matrix[0] = -1; matrix[1] = 0; matrix[2] = 0; matrix[3] = 1; matrix[4] = 0; matrix[5] = 0;
259 Cairo.cairo_pattern_set_matrix(newPattern, cast(cairo_matrix_t*) matrix.ptr);
260 Cairo.cairo_set_source(cairo, newPattern);
261 Cairo.cairo_pattern_destroy(newPattern);
262 } else {
263 Cairo.cairo_set_source(cairo, pattern.handle);
264 }
241 } else { 265 } else {
242 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); 266 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);
243 } 267 }
244 } 268 }
245 if ((state & FONT) !is 0) { 269 if ((state & FONT) !is 0) {
246 if (data.layout !is null) { 270 if (data.layout !is null) {
247 OS.pango_layout_set_font_description(data.layout, data.font); 271 Font font = data.font;
272 OS.pango_layout_set_font_description(data.layout, font.handle);
248 } 273 }
249 if (OS.GTK_VERSION < OS.buildVERSION(2, 8, 0)) { 274 if (OS.GTK_VERSION < OS.buildVERSION(2, 8, 0)) {
250 setCairoFont(cairo, data.font); 275 setCairoFont(cairo, data.font);
251 } 276 }
252 } 277 }
310 } 335 }
311 if ((state & DRAW_OFFSET) !is 0) { 336 if ((state & DRAW_OFFSET) !is 0) {
312 data.cairoXoffset = data.cairoYoffset = 0; 337 data.cairoXoffset = data.cairoYoffset = 0;
313 double[] matrix = new double[6]; 338 double[] matrix = new double[6];
314 Cairo.cairo_get_matrix(cairo,cast(cairo_matrix_t*) matrix.ptr); 339 Cairo.cairo_get_matrix(cairo,cast(cairo_matrix_t*) matrix.ptr);
315 double scaling = matrix[0]; 340 double dx = 1;
341 double dy = 1;
342 Cairo.cairo_user_to_device_distance(cairo, &dx, &dy);
343 double scaling = dx;
316 if (scaling < 0) scaling = -scaling; 344 if (scaling < 0) scaling = -scaling;
317 double strokeWidth = data.lineWidth * scaling; 345 double strokeWidth = data.lineWidth * scaling;
318 if (strokeWidth is 0 || (cast(int)strokeWidth % 2) is 1) { 346 if (strokeWidth is 0 || (cast(int)strokeWidth % 2) is 1) {
319 data.cairoXoffset = 0.5 / scaling; 347 data.cairoXoffset = 0.5 / scaling;
320 } 348 }
321 scaling = matrix[3]; 349 scaling = dy;
322 if (scaling < 0) scaling = -scaling; 350 if (scaling < 0) scaling = -scaling;
323 strokeWidth = data.lineWidth * scaling; 351 strokeWidth = data.lineWidth * scaling;
324 if (strokeWidth is 0 || (cast(int)strokeWidth % 2) is 1) { 352 if (strokeWidth is 0 || (cast(int)strokeWidth % 2) is 1) {
325 data.cairoYoffset = 0.5 / scaling; 353 data.cairoYoffset = 0.5 / scaling;
326 } 354 }
342 GdkColor* background = data.background; 370 GdkColor* background = data.background;
343 OS.gdk_gc_set_background(handle, background); 371 OS.gdk_gc_set_background(handle, background);
344 } 372 }
345 if ((state & FONT) !is 0) { 373 if ((state & FONT) !is 0) {
346 if (data.layout !is null) { 374 if (data.layout !is null) {
347 OS.pango_layout_set_font_description(data.layout, data.font); 375 Font font = data.font;
376 OS.pango_layout_set_font_description(data.layout, font.handle);
348 } 377 }
349 } 378 }
350 if ((state & (LINE_CAP | LINE_JOIN | LINE_STYLE | LINE_WIDTH)) !is 0) { 379 if ((state & (LINE_CAP | LINE_JOIN | LINE_STYLE | LINE_WIDTH)) !is 0) {
351 int cap_style = 0; 380 int cap_style = 0;
352 int join_style = 0; 381 int join_style = 0;
542 data.context = context; 571 data.context = context;
543 auto layout = OS.pango_layout_new(context); 572 auto layout = OS.pango_layout_new(context);
544 if (layout is null) DWT.error(DWT.ERROR_NO_HANDLES); 573 if (layout is null) DWT.error(DWT.ERROR_NO_HANDLES);
545 data.layout = layout; 574 data.layout = layout;
546 OS.pango_context_set_language(context, OS.gtk_get_default_language()); 575 OS.pango_context_set_language(context, OS.gtk_get_default_language());
547 OS.pango_context_set_base_dir(context, OS.PANGO_DIRECTION_LTR); 576 OS.pango_context_set_base_dir(context, (data.style & DWT.MIRRORED) !is 0 ? OS.PANGO_DIRECTION_RTL : OS.PANGO_DIRECTION_LTR);
548 OS.gdk_pango_context_set_colormap(context, OS.gdk_colormap_get_system()); 577 OS.gdk_pango_context_set_colormap(context, OS.gdk_colormap_get_system());
549 if (OS.GTK_VERSION >= OS.buildVERSION(2, 4, 0)) { 578 if (OS.GTK_VERSION >= OS.buildVERSION(2, 4, 0)) {
550 OS.pango_layout_set_auto_dir(layout, false); 579 OS.pango_layout_set_auto_dir(layout, false);
551 } 580 }
552 } 581 }
557 if (data.layout !is null) OS.g_object_unref(data.layout); 586 if (data.layout !is null) OS.g_object_unref(data.layout);
558 data.layout = null; 587 data.layout = null;
559 data.context = null; 588 data.context = null;
560 } 589 }
561 590
562 /** 591 void destroy() {
563 * Disposes of the operating system resources associated with
564 * the graphics context. Applications must dispose of all GCs
565 * which they allocate.
566 *
567 * @exception DWTError <ul>
568 * <li>ERROR_THREAD_INVALID_ACCESS if not called from the thread that created the drawable</li>
569 * </ul>
570 */
571 public override void dispose() {
572 if (handle is null) return;
573 if (data.device.isDisposed()) return;
574
575 if (data.disposeCairo) { 592 if (data.disposeCairo) {
576 auto cairo = data.cairo; 593 auto cairo = data.cairo;
577 if (cairo !is null) Cairo.cairo_destroy(cairo); 594 if (cairo !is null) Cairo.cairo_destroy(cairo);
578 data.cairo = null; 595 data.cairo = null;
579 } 596 }
588 } 605 }
589 606
590 disposeLayout(); 607 disposeLayout();
591 608
592 /* Dispose the GC */ 609 /* Dispose the GC */
593 Device device = data.device; 610 if (drawable !is null) {
594 drawable.internal_dispose_GC(handle, data); 611 drawable.internal_dispose_GC(handle, data);
595 612 }
596 data.drawable = null; 613 data.drawable = null;
597 data.clipRgn = null; 614 data.clipRgn = null;
598 drawable = null; 615 drawable = null;
599 handle = null; 616 handle = null;
600 data.image = null; 617 data.image = null;
601 data.str = null; 618 data.str = null;
602 if (device.tracking) device.dispose_Object(this);
603 data.device = null;
604 data = null; 619 data = null;
605 } 620 }
606 621
607 /** 622 /**
608 * Draws the outline of a circular or elliptical arc 623 * Draws the outline of a circular or elliptical arc
806 auto cairo = data.cairo; 821 auto cairo = data.cairo;
807 if (cairo !is null) { 822 if (cairo !is null) {
808 if (data.alpha !is 0) { 823 if (data.alpha !is 0) {
809 srcImage.createSurface(); 824 srcImage.createSurface();
810 Cairo.cairo_save(cairo); 825 Cairo.cairo_save(cairo);
826 if ((data.style & DWT.MIRRORED) !is 0) {
827 Cairo.cairo_scale(cairo, -1f, 1);
828 Cairo.cairo_translate(cairo, - 2 * destX - destWidth, 0);
829 }
811 Cairo.cairo_rectangle(cairo, destX , destY, destWidth, destHeight); 830 Cairo.cairo_rectangle(cairo, destX , destY, destWidth, destHeight);
812 Cairo.cairo_clip(cairo); 831 Cairo.cairo_clip(cairo);
813 Cairo.cairo_translate(cairo, destX - srcX, destY - srcY); 832 Cairo.cairo_translate(cairo, destX - srcX, destY - srcY);
814 if (srcWidth !is destWidth || srcHeight !is destHeight) { 833 if (srcWidth !is destWidth || srcHeight !is destHeight) {
815 Cairo.cairo_scale(cairo, destWidth / cast(float)srcWidth, destHeight / cast(float)srcHeight); 834 Cairo.cairo_scale(cairo, destWidth / cast(float)srcWidth, destHeight / cast(float)srcHeight);
1052 if (srcImage.transparentPixel !is -1 && srcImage.memGC !is null) srcImage.destroyMask(); 1071 if (srcImage.transparentPixel !is -1 && srcImage.memGC !is null) srcImage.destroyMask();
1053 } 1072 }
1054 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) { 1073 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) {
1055 int translateX = 0, translateY = 0; 1074 int translateX = 0, translateY = 0;
1056 auto drawable = data.drawable; 1075 auto drawable = data.drawable;
1057 if (data.image is null) { 1076 if (data.image is null && !data.realDrawable) {
1058 int x, y; 1077 int x, y;
1059 GdkDrawable* real_drawable; 1078 GdkDrawable* real_drawable;
1060 OS.gdk_window_get_internal_paint_info(cast(GdkWindow*)drawable, &real_drawable, &x, &y); 1079 OS.gdk_window_get_internal_paint_info(cast(GdkWindow*)drawable, &real_drawable, &x, &y);
1061 drawable = real_drawable; 1080 drawable = real_drawable;
1062 translateX = -x; 1081 translateX = -x;
1446 } 1465 }
1447 if (naw < 0) naw = 0 - naw; 1466 if (naw < 0) naw = 0 - naw;
1448 if (nah < 0) nah = 0 - nah; 1467 if (nah < 0) nah = 0 - nah;
1449 auto cairo = data.cairo; 1468 auto cairo = data.cairo;
1450 if (cairo !is null) { 1469 if (cairo !is null) {
1451 float naw2 = naw / 2f;
1452 float nah2 = nah / 2f;
1453 float fw = nw / naw2;
1454 float fh = nh / nah2;
1455 Cairo.cairo_save(cairo);
1456 double xOffset = data.cairoXoffset, yOffset = data.cairoYoffset; 1470 double xOffset = data.cairoXoffset, yOffset = data.cairoYoffset;
1457 Cairo.cairo_translate(cairo, nx + xOffset, ny + yOffset); 1471 if (naw is 0 || nah is 0) {
1458 Cairo.cairo_scale(cairo, naw2, nah2); 1472 Cairo.cairo_rectangle(cairo, x + xOffset, y + yOffset, width, height);
1459 Cairo.cairo_move_to(cairo, fw - 1, 0); 1473 } else {
1460 Cairo.cairo_arc(cairo, fw - 1, 1, 1, Compatibility.PI + Compatibility.PI/2.0, Compatibility.PI*2.0); 1474 float naw2 = naw / 2f;
1461 Cairo.cairo_arc(cairo, fw - 1, fh - 1, 1, 0, Compatibility.PI/2.0); 1475 float nah2 = nah / 2f;
1462 Cairo.cairo_arc(cairo, 1, fh - 1, 1, Compatibility.PI/2, Compatibility.PI); 1476 float fw = nw / naw2;
1463 Cairo.cairo_arc(cairo, 1, 1, 1, Compatibility.PI, 270.0*Compatibility.PI/180.0); 1477 float fh = nh / nah2;
1464 Cairo.cairo_close_path(cairo); 1478 Cairo.cairo_save(cairo);
1465 Cairo.cairo_restore(cairo); 1479 Cairo.cairo_translate(cairo, nx + xOffset, ny + yOffset);
1480 Cairo.cairo_scale(cairo, naw2, nah2);
1481 Cairo.cairo_move_to(cairo, fw - 1, 0);
1482 Cairo.cairo_arc(cairo, fw - 1, 1, 1, Compatibility.PI + Compatibility.PI/2.0, Compatibility.PI*2.0);
1483 Cairo.cairo_arc(cairo, fw - 1, fh - 1, 1, 0, Compatibility.PI/2.0);
1484 Cairo.cairo_arc(cairo, 1, fh - 1, 1, Compatibility.PI/2, Compatibility.PI);
1485 Cairo.cairo_arc(cairo, 1, 1, 1, Compatibility.PI, 270.0*Compatibility.PI/180.0);
1486 Cairo.cairo_close_path(cairo);
1487 Cairo.cairo_restore(cairo);
1488 }
1466 Cairo.cairo_stroke(cairo); 1489 Cairo.cairo_stroke(cairo);
1467 return; 1490 return;
1468 } 1491 }
1469 int naw2 = naw / 2; 1492 int naw2 = naw / 2;
1470 int nah2 = nah / 2; 1493 int nah2 = nah / 2;
1651 OS.pango_layout_get_size(data.layout, &width, &height); 1674 OS.pango_layout_get_size(data.layout, &width, &height);
1652 Cairo.cairo_rectangle(cairo, x, y, OS.PANGO_PIXELS(width), OS.PANGO_PIXELS(height)); 1675 Cairo.cairo_rectangle(cairo, x, y, OS.PANGO_PIXELS(width), OS.PANGO_PIXELS(height));
1653 Cairo.cairo_fill(cairo); 1676 Cairo.cairo_fill(cairo);
1654 } 1677 }
1655 checkGC(FOREGROUND | FONT); 1678 checkGC(FOREGROUND | FONT);
1679 if ((data.style & DWT.MIRRORED) !is 0) {
1680 Cairo.cairo_save(cairo);
1681 int width, height;
1682 OS.pango_layout_get_size(data.layout, &width, &height);
1683 Cairo.cairo_scale(cairo, -1f, 1);
1684 Cairo.cairo_translate(cairo, -2 * x - OS.PANGO_PIXELS(width), 0);
1685 }
1656 Cairo.cairo_move_to(cairo, x, y); 1686 Cairo.cairo_move_to(cairo, x, y);
1657 OS.pango_cairo_show_layout(cairo, data.layout); 1687 OS.pango_cairo_show_layout(cairo, data.layout);
1688 if ((data.style & DWT.MIRRORED) !is 0) {
1689 Cairo.cairo_restore(cairo);
1690 }
1691 Cairo.cairo_new_path(cairo);
1658 return; 1692 return;
1659 } 1693 }
1660 checkGC(FOREGROUND | FONT | BACKGROUND_BG); 1694 checkGC(FOREGROUND | FONT | BACKGROUND_BG);
1661 GdkColor* background = null; 1695 GdkColor* background = null;
1662 if ((flags & DWT.DRAW_TRANSPARENT) is 0) background = data.background; 1696 if ((flags & DWT.DRAW_TRANSPARENT) is 0) background = data.background;
2053 } 2087 }
2054 if (naw < 0) naw = 0 - naw; 2088 if (naw < 0) naw = 0 - naw;
2055 if (nah < 0) nah = 0 - nah; 2089 if (nah < 0) nah = 0 - nah;
2056 auto cairo = data.cairo; 2090 auto cairo = data.cairo;
2057 if (cairo !is null) { 2091 if (cairo !is null) {
2058 float naw2 = naw / 2f; 2092 if (naw is 0 || nah is 0) {
2059 float nah2 = nah / 2f; 2093 Cairo.cairo_rectangle(cairo, x, y, width, height);
2060 float fw = nw / naw2; 2094 } else {
2061 float fh = nh / nah2; 2095 float naw2 = naw / 2f;
2062 Cairo.cairo_save(cairo); 2096 float nah2 = nah / 2f;
2063 Cairo.cairo_translate(cairo, nx, ny); 2097 float fw = nw / naw2;
2064 Cairo.cairo_scale(cairo, naw2, nah2); 2098 float fh = nh / nah2;
2065 Cairo.cairo_move_to(cairo, fw - 1, 0); 2099 Cairo.cairo_save(cairo);
2066 Cairo.cairo_arc(cairo, fw - 1, 1, 1, Compatibility.PI + Compatibility.PI/2.0, Compatibility.PI*2.0); 2100 Cairo.cairo_translate(cairo, nx, ny);
2067 Cairo.cairo_arc(cairo, fw - 1, fh - 1, 1, 0, Compatibility.PI/2.0); 2101 Cairo.cairo_scale(cairo, naw2, nah2);
2068 Cairo.cairo_arc(cairo, 1, fh - 1, 1, Compatibility.PI/2, Compatibility.PI); 2102 Cairo.cairo_move_to(cairo, fw - 1, 0);
2069 Cairo.cairo_arc(cairo, 1, 1, 1, Compatibility.PI, 270.0*Compatibility.PI/180.0); 2103 Cairo.cairo_arc(cairo, fw - 1, 1, 1, Compatibility.PI + Compatibility.PI/2.0, Compatibility.PI*2.0);
2070 Cairo.cairo_close_path(cairo); 2104 Cairo.cairo_arc(cairo, fw - 1, fh - 1, 1, 0, Compatibility.PI/2.0);
2071 Cairo.cairo_restore(cairo); 2105 Cairo.cairo_arc(cairo, 1, fh - 1, 1, Compatibility.PI/2, Compatibility.PI);
2106 Cairo.cairo_arc(cairo, 1, 1, 1, Compatibility.PI, 270.0*Compatibility.PI/180.0);
2107 Cairo.cairo_close_path(cairo);
2108 Cairo.cairo_restore(cairo);
2109 }
2072 Cairo.cairo_fill(cairo); 2110 Cairo.cairo_fill(cairo);
2073 return; 2111 return;
2074 } 2112 }
2075 int naw2 = naw / 2; 2113 int naw2 = naw / 2;
2076 int nah2 = nah / 2; 2114 int nah2 = nah / 2;
2281 */ 2319 */
2282 public Rectangle getClipping() { 2320 public Rectangle getClipping() {
2283 if (handle is null) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED); 2321 if (handle is null) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED);
2284 /* Calculate visible bounds in device space */ 2322 /* Calculate visible bounds in device space */
2285 int x = 0, y = 0, width = 0, height = 0; 2323 int x = 0, y = 0, width = 0, height = 0;
2286 int w, h; 2324 if (data.width !is -1 && data.height !is -1) {
2287 OS.gdk_drawable_get_size(data.drawable, &w, &h); 2325 width = data.width;
2288 width = w; 2326 height = data.height;
2289 height = h; 2327 } else {
2328 int w, h;
2329 OS.gdk_drawable_get_size(data.drawable, &w, &h);
2330 width = w;
2331 height = h;
2332 }
2290 /* Intersect visible bounds with clipping in device space and then convert then to user space */ 2333 /* Intersect visible bounds with clipping in device space and then convert then to user space */
2291 auto cairo = data.cairo; 2334 auto cairo = data.cairo;
2292 auto clipRgn = data.clipRgn; 2335 auto clipRgn = data.clipRgn;
2293 auto damageRgn = data.damageRgn; 2336 auto damageRgn = data.damageRgn;
2294 if (clipRgn !is null || damageRgn !is null || cairo !is null) { 2337 if (clipRgn !is null || damageRgn !is null || cairo !is null) {
2351 auto clipping = region.handle; 2394 auto clipping = region.handle;
2352 OS.gdk_region_subtract(clipping, clipping); 2395 OS.gdk_region_subtract(clipping, clipping);
2353 auto cairo = data.cairo; 2396 auto cairo = data.cairo;
2354 auto clipRgn = data.clipRgn; 2397 auto clipRgn = data.clipRgn;
2355 if (clipRgn is null) { 2398 if (clipRgn is null) {
2356 int width,height;
2357 OS.gdk_drawable_get_size(data.drawable, &width, &height);
2358 GdkRectangle rect; 2399 GdkRectangle rect;
2359 rect.width = width; 2400 if (data.width !is -1 && data.height !is -1) {
2360 rect.height = height; 2401 rect.width = data.width;
2402 rect.height = data.height;
2403 } else {
2404 int width, height;
2405 OS.gdk_drawable_get_size(data.drawable, &width, &height);
2406 rect.width = width;
2407 rect.height = height;
2408 }
2361 OS.gdk_region_union_with_rect(clipping, &rect); 2409 OS.gdk_region_union_with_rect(clipping, &rect);
2362 } else { 2410 } else {
2363 /* Convert clipping to device space if needed */ 2411 /* Convert clipping to device space if needed */
2364 if (data.clippingTransform !is null) { 2412 if (data.clippingTransform !is null) {
2365 auto rgn = convertRgn(clipRgn, data.clippingTransform); 2413 auto rgn = convertRgn(clipRgn, data.clippingTransform);
2413 * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li> 2461 * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
2414 * </ul> 2462 * </ul>
2415 */ 2463 */
2416 public Font getFont() { 2464 public Font getFont() {
2417 if (handle is null) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED); 2465 if (handle is null) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED);
2418 return Font.gtk_new(data.device, data.font); 2466 return data.font;
2419 } 2467 }
2420 2468
2421 /** 2469 /**
2422 * Returns a FontMetrics which contains information 2470 * Returns a FontMetrics which contains information
2423 * about the font currently being used by the receiver 2471 * about the font currently being used by the receiver
2431 */ 2479 */
2432 public FontMetrics getFontMetrics() { 2480 public FontMetrics getFontMetrics() {
2433 if (handle is null) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED); 2481 if (handle is null) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED);
2434 if (data.context is null) createLayout(); 2482 if (data.context is null) createLayout();
2435 checkGC(FONT); 2483 checkGC(FONT);
2484 Font font = data.font;
2436 auto context = data.context; 2485 auto context = data.context;
2437 auto lang = OS.pango_context_get_language(context); 2486 auto lang = OS.pango_context_get_language(context);
2438 auto metrics = OS.pango_context_get_metrics(context, data.font, lang); 2487 auto metrics = OS.pango_context_get_metrics(context, font.handle, lang);
2439 FontMetrics fm = new FontMetrics(); 2488 FontMetrics fm = new FontMetrics();
2440 fm.ascent = OS.PANGO_PIXELS(OS.pango_font_metrics_get_ascent(metrics)); 2489 fm.ascent = OS.PANGO_PIXELS(OS.pango_font_metrics_get_ascent(metrics));
2441 fm.descent = OS.PANGO_PIXELS(OS.pango_font_metrics_get_descent(metrics)); 2490 fm.descent = OS.PANGO_PIXELS(OS.pango_font_metrics_get_descent(metrics));
2442 fm.averageCharWidth = OS.PANGO_PIXELS(OS.pango_font_metrics_get_approximate_char_width(metrics)); 2491 fm.averageCharWidth = OS.PANGO_PIXELS(OS.pango_font_metrics_get_approximate_char_width(metrics));
2443 fm.height = fm.ascent + fm.descent; 2492 fm.height = fm.ascent + fm.descent;
2721 if (transform is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); 2770 if (transform is null) DWT.error(DWT.ERROR_NULL_ARGUMENT);
2722 if (transform.isDisposed()) DWT.error(DWT.ERROR_INVALID_ARGUMENT); 2771 if (transform.isDisposed()) DWT.error(DWT.ERROR_INVALID_ARGUMENT);
2723 auto cairo = data.cairo; 2772 auto cairo = data.cairo;
2724 if (cairo !is null) { 2773 if (cairo !is null) {
2725 Cairo.cairo_get_matrix(cairo, cast(cairo_matrix_t*)transform.handle.ptr); 2774 Cairo.cairo_get_matrix(cairo, cast(cairo_matrix_t*)transform.handle.ptr);
2775 double[] identity = identity();
2776 Cairo.cairo_matrix_invert(cast(cairo_matrix_t*)identity.ptr);
2777 Cairo.cairo_matrix_multiply(cast(cairo_matrix_t*)transform.handle.ptr, cast(cairo_matrix_t*)transform.handle.ptr, cast(cairo_matrix_t*)identity.ptr);
2726 } else { 2778 } else {
2727 transform.setElements(1, 0, 0, 1, 0, 0); 2779 transform.setElements(1, 0, 0, 1, 0, 0);
2728 } 2780 }
2729 } 2781 }
2730 2782
2763 */ 2815 */
2764 public override hash_t toHash() { 2816 public override hash_t toHash() {
2765 return cast(hash_t)/*64*/handle; 2817 return cast(hash_t)/*64*/handle;
2766 } 2818 }
2767 2819
2768 void init(Drawable drawable, GCData data, GdkGC* gdkGC) { 2820 double[] identity() {
2821 double[] identity = new double[6];
2822 if ((data.style & DWT.MIRRORED) !is 0) {
2823 int w, h;
2824 OS.gdk_drawable_get_size(data.drawable, &w, &h);
2825 Cairo.cairo_matrix_init(cast(cairo_matrix_t*)identity.ptr, -1, 0, 0, 1, w, 0);
2826 } else {
2827 Cairo.cairo_matrix_init_identity(cast(cairo_matrix_t*)identity.ptr);
2828 }
2829 return identity;
2830 }
2831
2832 void init_(Drawable drawable, GCData data, GdkGC* gdkGC) {
2769 if (data.foreground !is null) data.state &= ~FOREGROUND; 2833 if (data.foreground !is null) data.state &= ~FOREGROUND;
2770 if (data.background !is null) data.state &= ~(BACKGROUND | BACKGROUND_BG); 2834 if (data.background !is null) data.state &= ~(BACKGROUND | BACKGROUND_BG);
2771 if (data.font !is null) data.state &= ~FONT; 2835 if (data.font !is null) data.state &= ~FONT;
2772 2836
2773 Image image = data.image; 2837 Image image = data.image;
2781 if (image.transparentPixel !is -1) image.destroyMask(); 2845 if (image.transparentPixel !is -1) image.destroyMask();
2782 } 2846 }
2783 this.drawable = drawable; 2847 this.drawable = drawable;
2784 this.data = data; 2848 this.data = data;
2785 handle = gdkGC; 2849 handle = gdkGC;
2850 if ((data.style & DWT.MIRRORED) !is 0) {
2851 initCairo();
2852 auto cairo = data.cairo;
2853 Cairo.cairo_set_matrix(cairo, cast(cairo_matrix_t*) identity().ptr);
2854 }
2786 } 2855 }
2787 2856
2788 void initCairo() { 2857 void initCairo() {
2789 data.device.checkCairo(); 2858 data.device.checkCairo();
2790 auto cairo = data.cairo; 2859 auto cairo = data.cairo;
2795 int translateX = 0, translateY = 0; 2864 int translateX = 0, translateY = 0;
2796 auto drawable = data.drawable; 2865 auto drawable = data.drawable;
2797 if (data.image !is null) { 2866 if (data.image !is null) {
2798 xDrawable = OS.GDK_PIXMAP_XID(drawable); 2867 xDrawable = OS.GDK_PIXMAP_XID(drawable);
2799 } else { 2868 } else {
2800 int x, y; 2869 if (!data.realDrawable) {
2801 GdkDrawable* real_drawable; 2870 int x, y;
2802 OS.gdk_window_get_internal_paint_info(cast(GdkWindow*)drawable, &real_drawable, &x, &y); 2871 GdkDrawable* real_drawable;
2803 xDrawable = OS.gdk_x11_drawable_get_xid(real_drawable); 2872 OS.gdk_window_get_internal_paint_info(cast(GdkWindow*)drawable, &real_drawable, &x, &y);
2804 translateX = -x; 2873 xDrawable = OS.gdk_x11_drawable_get_xid(real_drawable);
2805 translateY = -y; 2874 translateX = -x;
2875 translateY = -y;
2876 }
2806 } 2877 }
2807 int w, h; 2878 int w, h;
2808 OS.gdk_drawable_get_size(drawable, &w, &h); 2879 OS.gdk_drawable_get_size(drawable, &w, &h);
2809 int width = w, height = h; 2880 int width = w, height = h;
2810 auto surface = Cairo.cairo_xlib_surface_create(cast(void*)xDisplay, xDrawable, xVisual, width, height); 2881 auto surface = Cairo.cairo_xlib_surface_create(cast(void*)xDisplay, xDrawable, xVisual, width, height);
2899 * 2970 *
2900 * @since 3.1 2971 * @since 3.1
2901 */ 2972 */
2902 public void setAdvanced(bool advanced) { 2973 public void setAdvanced(bool advanced) {
2903 if (handle is null) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED); 2974 if (handle is null) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED);
2975 if ((data.style & DWT.MIRRORED) !is 0) {
2976 if (!advanced) {
2977 setAlpha(0xFF);
2978 setAntialias(DWT.DEFAULT);
2979 setBackgroundPattern(null);
2980 setClipping(cast(GdkRegion*)null);
2981 setForegroundPattern(null);
2982 setInterpolation(DWT.DEFAULT);
2983 setTextAntialias(DWT.DEFAULT);
2984 setTransform(null);
2985 }
2986 return;
2987 }
2904 if (advanced && data.cairo !is null) return; 2988 if (advanced && data.cairo !is null) return;
2905 if (advanced) { 2989 if (advanced) {
2906 try { 2990 try {
2907 initCairo(); 2991 initCairo();
2908 } catch (DWTException e) {} 2992 } catch (DWTException e) {}
3266 * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li> 3350 * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
3267 * </ul> 3351 * </ul>
3268 */ 3352 */
3269 public void setFont(Font font) { 3353 public void setFont(Font font) {
3270 if (handle is null) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED); 3354 if (handle is null) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED);
3271 if (font is null) font = data.device.systemFont; 3355 if (font !is null && font.isDisposed()) DWT.error(DWT.ERROR_INVALID_ARGUMENT);
3272 if (font.isDisposed()) DWT.error(DWT.ERROR_INVALID_ARGUMENT); 3356 data.font = font !is null ? font : data.device.systemFont;
3273 data.font = font.handle;
3274 data.state &= ~FONT; 3357 data.state &= ~FONT;
3275 data.stringWidth = data.stringHeight = -1; 3358 data.stringWidth = data.stringHeight = -1;
3276 } 3359 }
3277 3360
3278 /** 3361 /**
3467 break; 3550 break;
3468 default: 3551 default:
3469 DWT.error(DWT.ERROR_INVALID_ARGUMENT); 3552 DWT.error(DWT.ERROR_INVALID_ARGUMENT);
3470 } 3553 }
3471 } 3554 }
3472 int cap = attributes.join; 3555 int cap = attributes.cap;
3473 if (cap !is data.lineCap) { 3556 if (cap !is data.lineCap) {
3474 mask |= LINE_CAP; 3557 mask |= LINE_CAP;
3475 switch (cap) { 3558 switch (cap) {
3476 case DWT.JOIN_MITER: 3559 case DWT.JOIN_MITER:
3477 case DWT.JOIN_ROUND: 3560 case DWT.JOIN_ROUND:
3808 if (handle is null) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED); 3891 if (handle is null) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED);
3809 if (transform !is null && transform.isDisposed()) DWT.error(DWT.ERROR_INVALID_ARGUMENT); 3892 if (transform !is null && transform.isDisposed()) DWT.error(DWT.ERROR_INVALID_ARGUMENT);
3810 if (data.cairo is null && transform is null) return; 3893 if (data.cairo is null && transform is null) return;
3811 initCairo(); 3894 initCairo();
3812 auto cairo = data.cairo; 3895 auto cairo = data.cairo;
3896 double[] identity = identity();
3813 if (transform !is null) { 3897 if (transform !is null) {
3814 Cairo.cairo_set_matrix(cairo,cast(cairo_matrix_t*) transform.handle.ptr); 3898 Cairo.cairo_matrix_multiply(cast(cairo_matrix_t*)identity.ptr, cast(cairo_matrix_t*)transform.handle.ptr, cast(cairo_matrix_t*)identity.ptr);
3815 } else { 3899 }
3816 Cairo.cairo_identity_matrix(cairo); 3900 Cairo.cairo_set_matrix(cairo, cast(cairo_matrix_t*)identity.ptr);
3817 }
3818 data.state &= ~DRAW_OFFSET; 3901 data.state &= ~DRAW_OFFSET;
3819 } 3902 }
3820 3903
3821 /** 3904 /**
3822 * If the argument is <code>true</code>, puts the receiver 3905 * If the argument is <code>true</code>, puts the receiver