/******************************************************************************* * Copyright (c) 2000, 2012 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.swt.graphics; import org.eclipse.swt.internal.cairo.*; import org.eclipse.swt.internal.gtk.*; import org.eclipse.swt.internal.*; import org.eclipse.swt.*; /** * Class GC is where all of the drawing capabilities that are * supported by SWT are located. Instances are used to draw on either an * Image, a Control, or directly on a Display. *
*
Styles:
*
LEFT_TO_RIGHT, RIGHT_TO_LEFT
*
* *

* The SWT drawing coordinate system is the two-dimensional space with the origin * (0,0) at the top left corner of the drawing area and with (x,y) values increasing * to the right and downward respectively. *

* *

* The result of drawing on an image that was created with an indexed * palette using a color that is not in the palette is platform specific. * Some platforms will match to the nearest color while other will draw * the color itself. This happens because the allocated image might use * a direct palette on platforms that do not support indexed palette. *

* *

* Application code must explicitly invoke the GC.dispose() * method to release the operating system resources managed by each instance * when those instances are no longer required. This is particularly * important on Windows95 and Windows98 where the operating system has a limited * number of device contexts available. *

* *

* Note: Only one of LEFT_TO_RIGHT and RIGHT_TO_LEFT may be specified. *

* * @see org.eclipse.swt.events.PaintEvent * @see GC snippets * @see SWT Examples: GraphicsExample, PaintExample * @see Sample code and further information */ public final class GC extends Resource { /** * the handle to the OS device context * (Warning: This field is platform dependent) *

* IMPORTANT: This field is not part of the SWT * public API. It is marked public only so that it can be shared * within the packages provided by SWT. It is not available on all * platforms and should never be accessed from application code. *

* * @noreference This field is not intended to be referenced by clients. */ public long /*int*/ handle; Drawable drawable; GCData data; final static int FOREGROUND = 1 << 0; final static int BACKGROUND = 1 << 1; final static int FONT = 1 << 2; final static int LINE_STYLE = 1 << 3; final static int LINE_CAP = 1 << 4; final static int LINE_JOIN = 1 << 5; final static int LINE_WIDTH = 1 << 6; final static int LINE_MITERLIMIT = 1 << 7; final static int BACKGROUND_BG = 1 << 8; final static int DRAW_OFFSET = 1 << 9; final static int DRAW = FOREGROUND | LINE_WIDTH | LINE_STYLE | LINE_CAP | LINE_JOIN | LINE_MITERLIMIT | DRAW_OFFSET; final static int FILL = BACKGROUND; static final float[] LINE_DOT = new float[]{1, 1}; static final float[] LINE_DASH = new float[]{3, 1}; static final float[] LINE_DASHDOT = new float[]{3, 1, 1, 1}; static final float[] LINE_DASHDOTDOT = new float[]{3, 1, 1, 1, 1, 1}; static final float[] LINE_DOT_ZERO = new float[]{3, 3}; static final float[] LINE_DASH_ZERO = new float[]{18, 6}; static final float[] LINE_DASHDOT_ZERO = new float[]{9, 6, 3, 6}; static final float[] LINE_DASHDOTDOT_ZERO = new float[]{9, 3, 3, 3, 3, 3}; GC() { } /** * Constructs a new instance of this class which has been * configured to draw on the specified drawable. Sets the * foreground color, background color and font in the GC * to match those in the drawable. *

* You must dispose the graphics context when it is no longer required. *

* @param drawable the drawable to draw on * @exception IllegalArgumentException * @exception SWTError */ public GC(Drawable drawable) { this(drawable, 0); } /** * Constructs a new instance of this class which has been * configured to draw on the specified drawable. Sets the * foreground color, background color and font in the GC * to match those in the drawable. *

* You must dispose the graphics context when it is no longer required. *

* * @param drawable the drawable to draw on * @param style the style of GC to construct * * @exception IllegalArgumentException * @exception SWTError * * @since 2.1.2 */ public GC(Drawable drawable, int style) { if (drawable == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); GCData data = new GCData(); data.style = checkStyle(style); long /*int*/ gdkGC = drawable.internal_new_GC(data); Device device = data.device; if (device == null) device = Device.getDevice(); if (device == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); this.device = data.device = device; init(drawable, data, gdkGC); init(); } static void addCairoString(long /*int*/ cairo, String string, float x, float y, Font font) { byte[] buffer = Converter.wcsToMbcs(null, string, true); if (OS.GTK_VERSION >= OS.VERSION(2, 8, 0)) { long /*int*/ layout = OS.pango_cairo_create_layout(cairo); if (layout == 0) SWT.error(SWT.ERROR_NO_HANDLES); OS.pango_layout_set_text(layout, buffer, -1); OS.pango_layout_set_font_description(layout, font.handle); double[] currentX = new double[1], currentY = new double[1]; Cairo.cairo_get_current_point(cairo, currentX, currentY); if (currentX[0] != x || currentY[0] != y) { Cairo.cairo_move_to(cairo, x, y); } OS.pango_cairo_layout_path(cairo, layout); OS.g_object_unref(layout); } else { GC.setCairoFont(cairo, font); cairo_font_extents_t extents = new cairo_font_extents_t(); Cairo.cairo_font_extents(cairo, extents); double baseline = y + extents.ascent; Cairo.cairo_move_to(cairo, x, baseline); Cairo.cairo_text_path(cairo, buffer); } } static int checkStyle (int style) { if ((style & SWT.LEFT_TO_RIGHT) != 0) style &= ~SWT.RIGHT_TO_LEFT; return style & (SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT); } /** * Invokes platform specific functionality to wrap a graphics context. *

* IMPORTANT: This method is not part of the public * API for GC. It is marked public only so that it * can be shared within the packages provided by SWT. It is not * available on all platforms, and should never be called from * application code. *

* * @param handle the handle to the OS device context * @param data the data for the receiver. * * @return a new GC * * @noreference This method is not intended to be referenced by clients. */ public static GC gtk_new(long /*int*/ handle, GCData data) { GC gc = new GC(); gc.device = data.device; gc.init(null, data, handle); return gc; } /** * Invokes platform specific functionality to allocate a new graphics context. *

* IMPORTANT: This method is not part of the public * API for GC. It is marked public only so that it * can be shared within the packages provided by SWT. It is not * available on all platforms, and should never be called from * application code. *

* * @param drawable the Drawable for the receiver. * @param data the data for the receiver. * * @return a new GC * * @noreference This method is not intended to be referenced by clients. */ public static GC gtk_new(Drawable drawable, GCData data) { GC gc = new GC(); long /*int*/ gdkGC = drawable.internal_new_GC(data); gc.device = data.device; gc.init(drawable, data, gdkGC); return gc; } void checkGC (int mask) { int state = data.state; if ((state & mask) == mask) return; state = (state ^ mask) & mask; data.state |= mask; long /*int*/ cairo = data.cairo; if (cairo != 0) { if ((state & (BACKGROUND | FOREGROUND)) != 0) { GdkColor color; Pattern pattern; if ((state & FOREGROUND) != 0) { color = data.foreground; pattern = data.foregroundPattern; data.state &= ~BACKGROUND; } else { color = data.background; pattern = data.backgroundPattern; data.state &= ~FOREGROUND; } if (pattern != null) { if ((data.style & SWT.MIRRORED) != 0 && pattern.surface != 0) { long /*int*/ newPattern = Cairo.cairo_pattern_create_for_surface(pattern.surface); if (newPattern == 0) SWT.error(SWT.ERROR_NO_HANDLES); Cairo.cairo_pattern_set_extend(newPattern, Cairo.CAIRO_EXTEND_REPEAT); double[] matrix = {-1, 0, 0, 1, 0, 0}; Cairo.cairo_pattern_set_matrix(newPattern, matrix); 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) / (float)0xFFFF, (color.green & 0xFFFF) / (float)0xFFFF, (color.blue & 0xFFFF) / (float)0xFFFF, data.alpha / (float)0xFF); } } if ((state & FONT) != 0) { if (data.layout != 0) { Font font = data.font; OS.pango_layout_set_font_description(data.layout, font.handle); } if (OS.GTK_VERSION < OS.VERSION(2, 8, 0)) { setCairoFont(cairo, data.font); } } if ((state & LINE_CAP) != 0) { int cap_style = 0; switch (data.lineCap) { case SWT.CAP_ROUND: cap_style = Cairo.CAIRO_LINE_CAP_ROUND; break; case SWT.CAP_FLAT: cap_style = Cairo.CAIRO_LINE_CAP_BUTT; break; case SWT.CAP_SQUARE: cap_style = Cairo.CAIRO_LINE_CAP_SQUARE; break; } Cairo.cairo_set_line_cap(cairo, cap_style); } if ((state & LINE_JOIN) != 0) { int join_style = 0; switch (data.lineJoin) { case SWT.JOIN_MITER: join_style = Cairo.CAIRO_LINE_JOIN_MITER; break; case SWT.JOIN_ROUND: join_style = Cairo.CAIRO_LINE_JOIN_ROUND; break; case SWT.JOIN_BEVEL: join_style = Cairo.CAIRO_LINE_JOIN_BEVEL; break; } Cairo.cairo_set_line_join(cairo, join_style); } if ((state & LINE_WIDTH) != 0) { Cairo.cairo_set_line_width(cairo, data.lineWidth == 0 ? 1 : data.lineWidth); switch (data.lineStyle) { case SWT.LINE_DOT: case SWT.LINE_DASH: case SWT.LINE_DASHDOT: case SWT.LINE_DASHDOTDOT: state |= LINE_STYLE; } } if ((state & LINE_STYLE) != 0) { float dashesOffset = 0; float[] dashes = null; float width = data.lineWidth; switch (data.lineStyle) { case SWT.LINE_SOLID: break; case SWT.LINE_DASH: dashes = width != 0 ? LINE_DASH : LINE_DASH_ZERO; break; case SWT.LINE_DOT: dashes = width != 0 ? LINE_DOT : LINE_DOT_ZERO; break; case SWT.LINE_DASHDOT: dashes = width != 0 ? LINE_DASHDOT : LINE_DASHDOT_ZERO; break; case SWT.LINE_DASHDOTDOT: dashes = width != 0 ? LINE_DASHDOTDOT : LINE_DASHDOTDOT_ZERO; break; case SWT.LINE_CUSTOM: dashes = data.lineDashes; break; } if (dashes != null) { dashesOffset = data.lineDashesOffset; double[] cairoDashes = new double[dashes.length]; for (int i = 0; i < cairoDashes.length; i++) { cairoDashes[i] = width == 0 || data.lineStyle == SWT.LINE_CUSTOM ? dashes[i] : dashes[i] * width; } Cairo.cairo_set_dash(cairo, cairoDashes, cairoDashes.length, dashesOffset); } else { Cairo.cairo_set_dash(cairo, null, 0, 0); } } if ((state & LINE_MITERLIMIT) != 0) { Cairo.cairo_set_miter_limit(cairo, data.lineMiterLimit); } if ((state & DRAW_OFFSET) != 0) { data.cairoXoffset = data.cairoYoffset = 0; double[] matrix = new double[6]; Cairo.cairo_get_matrix(cairo, matrix); double[] dx = new double[]{1}; double[] dy = new double[]{1}; Cairo.cairo_user_to_device_distance(cairo, dx, dy); double scaling = dx[0]; if (scaling < 0) scaling = -scaling; double strokeWidth = data.lineWidth * scaling; if (strokeWidth == 0 || ((int)strokeWidth % 2) == 1) { data.cairoXoffset = 0.5 / scaling; } scaling = dy[0]; if (scaling < 0) scaling = -scaling; strokeWidth = data.lineWidth * scaling; if (strokeWidth == 0 || ((int)strokeWidth % 2) == 1) { data.cairoYoffset = 0.5 / scaling; } } return; } if ((state & (BACKGROUND | FOREGROUND)) != 0) { GdkColor foreground; if ((state & FOREGROUND) != 0) { foreground = data.foreground; data.state &= ~BACKGROUND; } else { foreground = data.background; data.state &= ~FOREGROUND; } OS.gdk_gc_set_foreground(handle, foreground); } if ((state & BACKGROUND_BG) != 0) { GdkColor background = data.background; OS.gdk_gc_set_background(handle, background); } if ((state & FONT) != 0) { if (data.layout != 0) { Font font = data.font; OS.pango_layout_set_font_description(data.layout, font.handle); } } if ((state & (LINE_CAP | LINE_JOIN | LINE_STYLE | LINE_WIDTH)) != 0) { int cap_style = 0; int join_style = 0; int width = (int)data.lineWidth; int line_style = 0; float[] dashes = null; switch (data.lineCap) { case SWT.CAP_ROUND: cap_style = OS.GDK_CAP_ROUND; break; case SWT.CAP_FLAT: cap_style = OS.GDK_CAP_BUTT; break; case SWT.CAP_SQUARE: cap_style = OS.GDK_CAP_PROJECTING; break; } switch (data.lineJoin) { case SWT.JOIN_ROUND: join_style = OS.GDK_JOIN_ROUND; break; case SWT.JOIN_MITER: join_style = OS.GDK_JOIN_MITER; break; case SWT.JOIN_BEVEL: join_style = OS.GDK_JOIN_BEVEL; break; } switch (data.lineStyle) { case SWT.LINE_SOLID: break; case SWT.LINE_DASH: dashes = width != 0 ? LINE_DASH : LINE_DASH_ZERO; break; case SWT.LINE_DOT: dashes = width != 0 ? LINE_DOT : LINE_DOT_ZERO; break; case SWT.LINE_DASHDOT: dashes = width != 0 ? LINE_DASHDOT : LINE_DASHDOT_ZERO; break; case SWT.LINE_DASHDOTDOT: dashes = width != 0 ? LINE_DASHDOTDOT : LINE_DASHDOTDOT_ZERO; break; case SWT.LINE_CUSTOM: dashes = data.lineDashes; break; } if (dashes != null) { if ((state & LINE_STYLE) != 0) { byte[] dash_list = new byte[dashes.length]; for (int i = 0; i < dash_list.length; i++) { dash_list[i] = (byte)(width == 0 || data.lineStyle == SWT.LINE_CUSTOM ? dashes[i] : dashes[i] * width); } OS.gdk_gc_set_dashes(handle, 0, dash_list, dash_list.length); } line_style = OS.GDK_LINE_ON_OFF_DASH; } else { line_style = OS.GDK_LINE_SOLID; } OS.gdk_gc_set_line_attributes(handle, width, line_style, cap_style, join_style); } } long /*int*/ convertRgn(long /*int*/ rgn, double[] matrix) { long /*int*/ newRgn = cairo_region_create (); int[] nRects = new int[1]; long /*int*/[] rects = new long /*int*/[1]; OS.gdk_region_get_rectangles(rgn, rects, nRects); GdkRectangle rect = new GdkRectangle(); int[] pointArray = new int[8]; double[] x = new double[1], y = new double[1]; for (int i=0; iSWT.BITMAP. * * @param image the image to copy into * @param x the x coordinate in the receiver of the area to be copied * @param y the y coordinate in the receiver of the area to be copied * * @exception IllegalArgumentException * @exception SWTException */ public void copyArea(Image image, int x, int y) { if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); if (image == null) SWT.error(SWT.ERROR_NULL_ARGUMENT); if (image.type != SWT.BITMAP || image.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT); if (OS.USE_CAIRO) { long /*int*/ cairo = Cairo.cairo_create(image.surface); if (cairo == 0) SWT.error(SWT.ERROR_NO_HANDLES); Cairo.cairo_translate(cairo, -x, -y); if (data.image != null) { Cairo.cairo_set_source_surface(cairo, data.image.surface, 0, 0); } else if (data.drawable != 0) { if (OS.GTK_VERSION >= OS.VERSION(2, 24, 0)) { OS.gdk_cairo_set_source_window(cairo, data.drawable, 0, 0); } else { int[] w = new int[1], h = new int[1]; OS.gdk_drawable_get_size(data.drawable, w, h); int width = w[0], height = h[0]; long /*int*/ xDisplay = OS.gdk_x11_display_get_xdisplay(OS.gdk_display_get_default()); long /*int*/ xDrawable = OS.gdk_x11_drawable_get_xid(data.drawable); long /*int*/ xVisual = OS.gdk_x11_visual_get_xvisual(OS.gdk_visual_get_system()); long /*int*/ srcSurface = Cairo.cairo_xlib_surface_create(xDisplay, xDrawable, xVisual, width, height); Cairo.cairo_set_source_surface(cairo, srcSurface, 0, 0); } } else { return; } Cairo.cairo_set_operator(cairo, Cairo.CAIRO_OPERATOR_SOURCE); Cairo.cairo_paint(cairo); Cairo.cairo_destroy(cairo); return; } Rectangle rect = image.getBounds(); long /*int*/ gdkGC = OS.gdk_gc_new(image.pixmap); if (gdkGC == 0) SWT.error(SWT.ERROR_NO_HANDLES); OS.gdk_gc_set_subwindow(gdkGC, OS.GDK_INCLUDE_INFERIORS); OS.gdk_draw_drawable(image.pixmap, gdkGC, data.drawable, x, y, 0, 0, rect.width, rect.height); OS.g_object_unref(gdkGC); } /** * Copies a rectangular area of the receiver at the source * position onto the receiver at the destination position. * * @param srcX the x coordinate in the receiver of the area to be copied * @param srcY the y coordinate in the receiver of the area to be copied * @param width the width of the area to copy * @param height the height of the area to copy * @param destX the x coordinate in the receiver of the area to copy to * @param destY the y coordinate in the receiver of the area to copy to * * @exception SWTException */ public void copyArea(int srcX, int srcY, int width, int height, int destX, int destY) { copyArea(srcX, srcY, width, height, destX, destY, true); } /** * Copies a rectangular area of the receiver at the source * position onto the receiver at the destination position. * * @param srcX the x coordinate in the receiver of the area to be copied * @param srcY the y coordinate in the receiver of the area to be copied * @param width the width of the area to copy * @param height the height of the area to copy * @param destX the x coordinate in the receiver of the area to copy to * @param destY the y coordinate in the receiver of the area to copy to * @param paint if true paint events will be generated for old and obscured areas * * @exception SWTException * * @since 3.1 */ public void copyArea(int srcX, int srcY, int width, int height, int destX, int destY, boolean paint) { if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); if (width <= 0 || height <= 0) return; int deltaX = destX - srcX, deltaY = destY - srcY; if (deltaX == 0 && deltaY == 0) return; long /*int*/ drawable = data.drawable; if (OS.USE_CAIRO) { if (data.image != null) { Cairo.cairo_set_source_surface(handle, data.image.surface, deltaX, deltaY); Cairo.cairo_rectangle(handle, destX, destY, width, height); Cairo.cairo_set_operator(handle, Cairo.CAIRO_OPERATOR_SOURCE); Cairo.cairo_fill(handle); } else if (drawable != 0) { Cairo.cairo_save(handle); Cairo.cairo_rectangle(handle, destX, destY, width, height); Cairo.cairo_clip(handle); Cairo.cairo_translate(handle, deltaX, deltaY); Cairo.cairo_set_operator(handle, Cairo.CAIRO_OPERATOR_SOURCE); Cairo.cairo_push_group(handle); OS.gdk_cairo_set_source_window(handle, drawable, 0, 0); Cairo.cairo_paint(handle); Cairo.cairo_pop_group_to_source(handle); Cairo.cairo_rectangle(handle, destX - deltaX, destY - deltaY, width, height); Cairo.cairo_clip(handle); Cairo.cairo_paint(handle); Cairo.cairo_restore(handle); if (paint) { long /*int*/ visibleRegion = OS.gdk_drawable_get_visible_region (drawable); if (OS.GTK_VERSION >= OS.VERSION(3, 0, 0)) { cairo_rectangle_int_t srcRect = new cairo_rectangle_int_t (); srcRect.x = srcX; srcRect.y = srcY; srcRect.width = width; srcRect.height = height; long /*int*/ copyRegion = Cairo.cairo_region_create_rectangle (srcRect); Cairo.cairo_region_intersect (copyRegion, visibleRegion); long /*int*/ invalidateRegion = Cairo.cairo_region_create_rectangle (srcRect); Cairo.cairo_region_subtract (invalidateRegion, visibleRegion); Cairo.cairo_region_translate (invalidateRegion, deltaX, deltaY); OS.gdk_window_invalidate_region(drawable, invalidateRegion, false); Cairo.cairo_region_destroy (visibleRegion); Cairo.cairo_region_destroy (copyRegion); Cairo.cairo_region_destroy (invalidateRegion); } else { GdkRectangle srcRect = new GdkRectangle (); srcRect.x = srcX; srcRect.y = srcY; srcRect.width = width; srcRect.height = height; long /*int*/ copyRegion = OS.gdk_region_rectangle (srcRect); OS.gdk_region_intersect (copyRegion, visibleRegion); long /*int*/ invalidateRegion = OS.gdk_region_rectangle (srcRect); OS.gdk_region_subtract (invalidateRegion, visibleRegion); OS.gdk_region_offset (invalidateRegion, deltaX, deltaY); OS.gdk_window_invalidate_region(drawable, invalidateRegion, false); OS.gdk_region_destroy (visibleRegion); OS.gdk_region_destroy (copyRegion); OS.gdk_region_destroy (invalidateRegion); } } } } else { if (data.image == null && paint) OS.gdk_gc_set_exposures(handle, true); OS.gdk_draw_drawable(drawable, handle, drawable, srcX, srcY, destX, destY, width, height); } if (data.image == null & paint) { if (!OS.USE_CAIRO) OS.gdk_gc_set_exposures(handle, false); boolean disjoint = (destX + width < srcX) || (srcX + width < destX) || (destY + height < srcY) || (srcY + height < destY); GdkRectangle rect = new GdkRectangle (); if (disjoint) { rect.x = srcX; rect.y = srcY; rect.width = width; rect.height = height; OS.gdk_window_invalidate_rect (drawable, rect, false); // OS.gdk_window_clear_area_e(drawable, srcX, srcY, width, height); } else { if (deltaX != 0) { int newX = destX - deltaX; if (deltaX < 0) newX = destX + width; rect.x = newX; rect.y = srcY; rect.width = Math.abs(deltaX); rect.height = height; OS.gdk_window_invalidate_rect (drawable, rect, false); // OS.gdk_window_clear_area_e(drawable, newX, srcY, Math.abs(deltaX), height); } if (deltaY != 0) { int newY = destY - deltaY; if (deltaY < 0) newY = destY + height; rect.x = srcX; rect.y = newY; rect.width = width; rect.height = Math.abs(deltaY); OS.gdk_window_invalidate_rect (drawable, rect, false); // OS.gdk_window_clear_area_e(drawable, srcX, newY, width, Math.abs(deltaY)); } } } } void createLayout() { long /*int*/ context = OS.gdk_pango_context_get(); if (context == 0) SWT.error(SWT.ERROR_NO_HANDLES); data.context = context; long /*int*/ layout = OS.pango_layout_new(context); if (layout == 0) SWT.error(SWT.ERROR_NO_HANDLES); data.layout = layout; OS.pango_context_set_language(context, OS.gtk_get_default_language()); OS.pango_context_set_base_dir(context, (data.style & SWT.MIRRORED) != 0 ? OS.PANGO_DIRECTION_RTL : OS.PANGO_DIRECTION_LTR); /* * Colormap is automatically set for GTK 2.6.0 and newer. */ if (OS.GTK_VERSION < OS.VERSION(2, 6, 0)) { OS.gdk_pango_context_set_colormap(context, OS.gdk_colormap_get_system()); } if (OS.GTK_VERSION >= OS.VERSION(2, 4, 0)) { OS.pango_layout_set_auto_dir(layout, false); } } void disposeLayout() { data.string = null; if (data.context != 0) OS.g_object_unref(data.context); if (data.layout != 0) OS.g_object_unref(data.layout); data.layout = data.context = 0; } void destroy() { if (data.disposeCairo) { long /*int*/ cairo = data.cairo; if (cairo != 0) Cairo.cairo_destroy(cairo); } data.cairo = 0; /* Free resources */ long /*int*/ clipRgn = data.clipRgn; if (clipRgn != 0) cairo_region_destroy (clipRgn); Image image = data.image; if (image != null) { image.memGC = null; if (image.transparentPixel != -1) image.createMask(); } disposeLayout(); /* Dispose the GC */ if (drawable != null) { drawable.internal_dispose_GC(handle, data); } data.drawable = data.clipRgn = 0; drawable = null; handle = 0; data.image = null; data.string = null; data = null; } /** * Draws the outline of a circular or elliptical arc * within the specified rectangular area. *

* The resulting arc begins at startAngle and extends * for arcAngle degrees, using the current color. * Angles are interpreted such that 0 degrees is at the 3 o'clock * position. A positive value indicates a counter-clockwise rotation * while a negative value indicates a clockwise rotation. *

* The center of the arc is the center of the rectangle whose origin * is (x, y) and whose size is specified by the * width and height arguments. *

* The resulting arc covers an area width + 1 pixels wide * by height + 1 pixels tall. *

* * @param x the x coordinate of the upper-left corner of the arc to be drawn * @param y the y coordinate of the upper-left corner of the arc to be drawn * @param width the width of the arc to be drawn * @param height the height of the arc to be drawn * @param startAngle the beginning angle * @param arcAngle the angular extent of the arc, relative to the start angle * * @exception SWTException */ public void drawArc(int x, int y, int width, int height, int startAngle, int arcAngle) { if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); checkGC(DRAW); if (width < 0) { x = x + width; width = -width; } if (height < 0) { y = y + height; height = -height; } if (width == 0 || height == 0 || arcAngle == 0) return; long /*int*/ cairo = data.cairo; if (cairo != 0) { double xOffset = data.cairoXoffset, yOffset = data.cairoYoffset; if (width == height) { if (arcAngle >= 0) { Cairo.cairo_arc_negative(cairo, x + xOffset + width / 2f, y + yOffset + height / 2f, width / 2f, -startAngle * (float)Compatibility.PI / 180, -(startAngle + arcAngle) * (float)Compatibility.PI / 180); } else { Cairo.cairo_arc(cairo, x + xOffset + width / 2f, y + yOffset + height / 2f, width / 2f, -startAngle * (float)Compatibility.PI / 180, -(startAngle + arcAngle) * (float)Compatibility.PI / 180); } } else { Cairo.cairo_save(cairo); Cairo.cairo_translate(cairo, x + xOffset + width / 2f, y + yOffset + height / 2f); Cairo.cairo_scale(cairo, width / 2f, height / 2f); if (arcAngle >= 0) { Cairo.cairo_arc_negative(cairo, 0, 0, 1, -startAngle * (float)Compatibility.PI / 180, -(startAngle + arcAngle) * (float)Compatibility.PI / 180); } else { Cairo.cairo_arc(cairo, 0, 0, 1, -startAngle * (float)Compatibility.PI / 180, -(startAngle + arcAngle) * (float)Compatibility.PI / 180); } Cairo.cairo_restore(cairo); } Cairo.cairo_stroke(cairo); return; } OS.gdk_draw_arc(data.drawable, handle, 0, x, y, width, height, startAngle * 64, arcAngle * 64); } /** * Draws a rectangle, based on the specified arguments, which has * the appearance of the platform's focus rectangle if the * platform supports such a notion, and otherwise draws a simple * rectangle in the receiver's foreground color. * * @param x the x coordinate of the rectangle * @param y the y coordinate of the rectangle * @param width the width of the rectangle * @param height the height of the rectangle * * @exception SWTException * * @see #drawRectangle(int, int, int, int) */ public void drawFocus(int x, int y, int width, int height) { if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED); /* * Feature in GTK. The function gtk_widget_get_default_style() * can't be used here because gtk_paint_focus() uses GCs, which * are not valid in the default style. The fix is to use a style * from a widget. */ long /*int*/ style = OS.gtk_widget_get_style(data.device.shellHandle); long /*int*/ cairo = data.cairo; if (cairo != 0) { checkGC(FOREGROUND); int[] lineWidth = new int[1]; OS.gtk_widget_style_get(data.device.shellHandle, OS.focus_line_width, lineWidth, 0); Cairo.cairo_save(cairo); Cairo.cairo_set_line_width(cairo, lineWidth[0]); double[] dashes = new double[]{1, 1}; double dash_offset = -lineWidth[0] / 2f; while (dash_offset < 0) dash_offset += 2; Cairo.cairo_set_dash(cairo, dashes, dashes.length, dash_offset); Cairo.cairo_rectangle(cairo, x + lineWidth[0] / 2f, y + lineWidth[0] / 2f, width, height); Cairo.cairo_stroke(cairo); Cairo.cairo_restore(cairo); return; } gtk_render_focus (style, data.drawable, OS.GTK_STATE_NORMAL, null, data.device.shellHandle, new byte[1], x, y, width, height); } /** * Draws the given image in the receiver at the specified * coordinates. * * @param image the image to draw * @param x the x coordinate of where to draw * @param y the y coordinate of where to draw * * @exception IllegalArgumentException