0001: /*******************************************************************************
0002: * Copyright (c) 2000, 2003 IBM Corporation and others.
0003: * All rights reserved. This program and the accompanying materials
0004: * are made available under the terms of the Eclipse Public License v1.0
0005: * which accompanies this distribution, and is available at
0006: * http://www.eclipse.org/legal/epl-v10.html
0007: *
0008: * Contributors:
0009: * IBM Corporation - initial API and implementation
0010: *******************************************************************************/package org.eclipse.swt.graphics;
0011:
0012: import org.eclipse.swt.internal.gtk.*;
0013: import org.eclipse.swt.internal.*;
0014: import org.eclipse.swt.*;
0015:
0016: /**
0017: * Class <code>GC</code> is where all of the drawing capabilities that are
0018: * supported by SWT are located. Instances are used to draw on either an
0019: * <code>Image</code>, a <code>Control</code>, or directly on a <code>Display</code>.
0020: * <p>
0021: * Application code must explicitly invoke the <code>GC.dispose()</code>
0022: * method to release the operating system resources managed by each instance
0023: * when those instances are no longer required. This is <em>particularly</em>
0024: * important on Windows95 and Windows98 where the operating system has a limited
0025: * number of device contexts available.
0026: * </p>
0027: *
0028: * @see org.eclipse.swt.events.PaintEvent
0029: */
0030: public final class GC {
0031: /**
0032: * the handle to the OS device context
0033: * (Warning: This field is platform dependent)
0034: */
0035: public int handle;
0036:
0037: Drawable drawable;
0038: GCData data;
0039:
0040: GC() {
0041: }
0042:
0043: /**
0044: * Constructs a new instance of this class which has been
0045: * configured to draw on the specified drawable. Sets the
0046: * foreground and background color in the GC to match those
0047: * in the drawable.
0048: * <p>
0049: * You must dispose the graphics context when it is no longer required.
0050: * </p>
0051: * @param drawable the drawable to draw on
0052: * @exception IllegalArgumentException <ul>
0053: * <li>ERROR_NULL_ARGUMENT - if the drawable is null</li>
0054: * <li>ERROR_NULL_ARGUMENT - if there is no current device</li>
0055: * <li>ERROR_INVALID_ARGUMENT
0056: * - if the drawable is an image that is not a bitmap or an icon
0057: * - if the drawable is an image or printer that is already selected
0058: * into another graphics context</li>
0059: * </ul>
0060: * @exception SWTError <ul>
0061: * <li>ERROR_NO_HANDLES if a handle could not be obtained for gc creation</li>
0062: * </ul>
0063: */
0064: public GC(Drawable drawable) {
0065: this (drawable, 0);
0066: }
0067:
0068: public GC(Drawable drawable, int style) {
0069: if (drawable == null)
0070: SWT.error(SWT.ERROR_NULL_ARGUMENT);
0071: GCData data = new GCData();
0072: data.style = checkStyle(style);
0073: int gdkGC = drawable.internal_new_GC(data);
0074: Device device = data.device;
0075: if (device == null)
0076: device = Device.getDevice();
0077: if (device == null)
0078: SWT.error(SWT.ERROR_NULL_ARGUMENT);
0079: data.device = device;
0080: init(drawable, data, gdkGC);
0081: if (device.tracking)
0082: device.new_Object(this );
0083: }
0084:
0085: static int checkStyle(int style) {
0086: if ((style & SWT.LEFT_TO_RIGHT) != 0)
0087: style &= ~SWT.RIGHT_TO_LEFT;
0088: return style & (SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT);
0089: }
0090:
0091: public static GC gtk_new(Drawable drawable, GCData data) {
0092: GC gc = new GC();
0093: int gdkGC = drawable.internal_new_GC(data);
0094: gc.init(drawable, data, gdkGC);
0095: return gc;
0096: }
0097:
0098: /**
0099: * Copies a rectangular area of the receiver at the specified
0100: * position into the image, which must be of type <code>SWT.BITMAP</code>.
0101: *
0102: * @param x the x coordinate in the receiver of the area to be copied
0103: * @param y the y coordinate in the receiver of the area to be copied
0104: *
0105: * @exception IllegalArgumentException <ul>
0106: * <li>ERROR_NULL_ARGUMENT - if the image is null</li>
0107: * <li>ERROR_INVALID_ARGUMENT - if the image is not a bitmap or has been disposed</li>
0108: * </ul>
0109: * @exception SWTException <ul>
0110: * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
0111: * </ul>
0112: */
0113: public void copyArea(Image image, int x, int y) {
0114: if (handle == 0)
0115: SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
0116: if (image == null)
0117: SWT.error(SWT.ERROR_NULL_ARGUMENT);
0118: if (image.type != SWT.BITMAP || image.isDisposed())
0119: SWT.error(SWT.ERROR_INVALID_ARGUMENT);
0120: Rectangle rect = image.getBounds();
0121: int gdkGC = OS.gdk_gc_new(image.pixmap);
0122: if (gdkGC == 0)
0123: SWT.error(SWT.ERROR_NO_HANDLES);
0124: OS.gdk_gc_set_subwindow(gdkGC, OS.GDK_INCLUDE_INFERIORS);
0125: OS.gdk_draw_drawable(image.pixmap, gdkGC, data.drawable, x, y,
0126: 0, 0, rect.width, rect.height);
0127: OS.g_object_unref(gdkGC);
0128: }
0129:
0130: /**
0131: * Copies a rectangular area of the receiver at the source
0132: * position onto the receiver at the destination position.
0133: *
0134: * @param srcX the x coordinate in the receiver of the area to be copied
0135: * @param srcY the y coordinate in the receiver of the area to be copied
0136: * @param width the width of the area to copy
0137: * @param height the height of the area to copy
0138: * @param destX the x coordinate in the receiver of the area to copy to
0139: * @param destY the y coordinate in the receiver of the area to copy to
0140: *
0141: * @exception SWTException <ul>
0142: * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
0143: * </ul>
0144: */
0145: public void copyArea(int srcX, int srcY, int width, int height,
0146: int destX, int destY) {
0147: if (handle == 0)
0148: SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
0149: if (width <= 0 || height <= 0)
0150: return;
0151: int deltaX = destX - srcX, deltaY = destY - srcY;
0152: if (deltaX == 0 && deltaY == 0)
0153: return;
0154: int drawable = data.drawable;
0155: OS.gdk_gc_set_exposures(handle, true);
0156: OS.gdk_draw_drawable(drawable, handle, drawable, srcX, srcY,
0157: destX, destY, width, height);
0158: OS.gdk_gc_set_exposures(handle, false);
0159: if (data.image != null)
0160: return;
0161: boolean disjoint = (destX + width < srcX)
0162: || (srcX + width < destX) || (destY + height < srcY)
0163: || (srcY + height < destY);
0164: GdkRectangle rect = new GdkRectangle();
0165: if (disjoint) {
0166: rect.x = srcX;
0167: rect.y = srcY;
0168: rect.width = width;
0169: rect.height = height;
0170: OS.gdk_window_invalidate_rect(drawable, rect, false);
0171: // OS.gdk_window_clear_area_e(drawable, srcX, srcY, width, height);
0172: } else {
0173: if (deltaX != 0) {
0174: int newX = destX - deltaX;
0175: if (deltaX < 0)
0176: newX = destX + width;
0177: rect.x = newX;
0178: rect.y = srcY;
0179: rect.width = Math.abs(deltaX);
0180: rect.height = height;
0181: OS.gdk_window_invalidate_rect(drawable, rect, false);
0182: // OS.gdk_window_clear_area_e(drawable, newX, srcY, Math.abs(deltaX), height);
0183: }
0184: if (deltaY != 0) {
0185: int newY = destY - deltaY;
0186: if (deltaY < 0)
0187: newY = destY + height;
0188: rect.x = srcX;
0189: rect.y = newY;
0190: rect.width = width;
0191: rect.height = Math.abs(deltaY);
0192: OS.gdk_window_invalidate_rect(drawable, rect, false);
0193: // OS.gdk_window_clear_area_e(drawable, srcX, newY, width, Math.abs(deltaY));
0194: }
0195: }
0196: }
0197:
0198: /**
0199: * Disposes of the operating system resources associated with
0200: * the graphics context. Applications must dispose of all GCs
0201: * which they allocate.
0202: */
0203: public void dispose() {
0204: if (handle == 0)
0205: return;
0206: if (data.device.isDisposed())
0207: return;
0208:
0209: /* Free resources */
0210: int clipRgn = data.clipRgn;
0211: if (clipRgn != 0)
0212: OS.gdk_region_destroy(clipRgn);
0213: Image image = data.image;
0214: if (image != null) {
0215: image.memGC = null;
0216: if (image.transparentPixel != -1)
0217: image.createMask();
0218: }
0219:
0220: int context = data.context;
0221: if (context != 0)
0222: OS.g_object_unref(context);
0223: int layout = data.layout;
0224: if (layout != 0)
0225: OS.g_object_unref(layout);
0226:
0227: /* Dispose the GC */
0228: Device device = data.device;
0229: drawable.internal_dispose_GC(handle, data);
0230:
0231: data.layout = data.context = data.drawable = data.clipRgn = 0;
0232: drawable = null;
0233: handle = 0;
0234: data.image = null;
0235: data.string = null;
0236: if (device.tracking)
0237: device.dispose_Object(this );
0238: data.device = null;
0239: data = null;
0240: }
0241:
0242: /**
0243: * Draws the outline of a circular or elliptical arc
0244: * within the specified rectangular area.
0245: * <p>
0246: * The resulting arc begins at <code>startAngle</code> and extends
0247: * for <code>arcAngle</code> degrees, using the current color.
0248: * Angles are interpreted such that 0 degrees is at the 3 o'clock
0249: * position. A positive value indicates a counter-clockwise rotation
0250: * while a negative value indicates a clockwise rotation.
0251: * </p><p>
0252: * The center of the arc is the center of the rectangle whose origin
0253: * is (<code>x</code>, <code>y</code>) and whose size is specified by the
0254: * <code>width</code> and <code>height</code> arguments.
0255: * </p><p>
0256: * The resulting arc covers an area <code>width + 1</code> pixels wide
0257: * by <code>height + 1</code> pixels tall.
0258: * </p>
0259: *
0260: * @param x the x coordinate of the upper-left corner of the arc to be drawn
0261: * @param y the y coordinate of the upper-left corner of the arc to be drawn
0262: * @param width the width of the arc to be drawn
0263: * @param height the height of the arc to be drawn
0264: * @param startAngle the beginning angle
0265: * @param arcAngle the angular extent of the arc, relative to the start angle
0266: *
0267: * @exception IllegalArgumentException <ul>
0268: * <li>ERROR_INVALID_ARGUMENT - if any of the width, height or endAngle is zero.</li>
0269: * </ul>
0270: * @exception SWTException <ul>
0271: * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
0272: * </ul>
0273: */
0274: public void drawArc(int x, int y, int width, int height,
0275: int startAngle, int arcAngle) {
0276: if (handle == 0)
0277: SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
0278: if (width < 0) {
0279: x = x + width;
0280: width = -width;
0281: }
0282: if (height < 0) {
0283: y = y + height;
0284: height = -height;
0285: }
0286: if (width == 0 || height == 0 || arcAngle == 0)
0287: return;
0288: OS.gdk_draw_arc(data.drawable, handle, 0, x, y, width, height,
0289: startAngle * 64, arcAngle * 64);
0290: }
0291:
0292: /**
0293: * Draws a rectangle, based on the specified arguments, which has
0294: * the appearance of the platform's <em>focus rectangle</em> if the
0295: * platform supports such a notion, and otherwise draws a simple
0296: * rectangle in the receiver's foreground color.
0297: *
0298: * @param x the x coordinate of the rectangle
0299: * @param y the y coordinate of the rectangle
0300: * @param width the width of the rectangle
0301: * @param height the height of the rectangle
0302: *
0303: * @exception SWTException <ul>
0304: * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
0305: * </ul>
0306: *
0307: * @see #drawRectangle
0308: */
0309: public void drawFocus(int x, int y, int width, int height) {
0310: if (handle == 0)
0311: SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
0312: //CHECK - default style might not be attached to any window
0313: GdkColor color = new GdkColor();
0314: OS
0315: .gtk_style_get_fg(OS.gtk_widget_get_default_style(), 0,
0316: color);
0317: GdkGCValues values = new GdkGCValues();
0318: OS.gdk_gc_get_values(handle, values);
0319: OS.gdk_gc_set_foreground(handle, color);
0320: OS.gdk_draw_rectangle(data.drawable, handle, 0, x, y,
0321: width - 1, height - 1);
0322: color.pixel = values.foreground_pixel;
0323: color.red = values.foreground_red;
0324: color.green = values.foreground_green;
0325: color.blue = values.foreground_blue;
0326: OS.gdk_gc_set_foreground(handle, color);
0327: }
0328:
0329: /**
0330: * Draws the given image in the receiver at the specified
0331: * coordinates.
0332: *
0333: * @param image the image to draw
0334: * @param x the x coordinate of where to draw
0335: * @param y the y coordinate of where to draw
0336: *
0337: * @exception IllegalArgumentException <ul>
0338: * <li>ERROR_NULL_ARGUMENT - if the image is null</li>
0339: * <li>ERROR_INVALID_ARGUMENT - if the image has been disposed</li>
0340: * <li>ERROR_INVALID_ARGUMENT - if the given coordinates are outside the bounds of the image</li>
0341: * @exception SWTError <ul>
0342: * <li>ERROR_NO_HANDLES - if no handles are available to perform the operation</li>
0343: * </ul>
0344: * @exception SWTException <ul>
0345: * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
0346: * </ul>
0347: */
0348: public void drawImage(Image image, int x, int y) {
0349: if (handle == 0)
0350: SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
0351: if (image == null)
0352: SWT.error(SWT.ERROR_NULL_ARGUMENT);
0353: if (image.isDisposed())
0354: SWT.error(SWT.ERROR_INVALID_ARGUMENT);
0355: drawImage(image, 0, 0, -1, -1, x, y, -1, -1, true);
0356: }
0357:
0358: /**
0359: * Copies a rectangular area from the source image into a (potentially
0360: * different sized) rectangular area in the receiver. If the source
0361: * and destination areas are of differing sizes, then the source
0362: * area will be stretched or shrunk to fit the destination area
0363: * as it is copied. The copy fails if any part of the source rectangle
0364: * lies outside the bounds of the source image, or if any of the width
0365: * or height arguments are negative.
0366: *
0367: * @param image the source image
0368: * @param srcX the x coordinate in the source image to copy from
0369: * @param srcY the y coordinate in the source image to copy from
0370: * @param srcWidth the width in pixels to copy from the source
0371: * @param srcHeight the height in pixels to copy from the source
0372: * @param destX the x coordinate in the destination to copy to
0373: * @param destY the y coordinate in the destination to copy to
0374: * @param destWidth the width in pixels of the destination rectangle
0375: * @param destHeight the height in pixels of the destination rectangle
0376: *
0377: * @exception IllegalArgumentException <ul>
0378: * <li>ERROR_NULL_ARGUMENT - if the image is null</li>
0379: * <li>ERROR_INVALID_ARGUMENT - if the image has been disposed</li>
0380: * <li>ERROR_INVALID_ARGUMENT - if any of the width or height arguments are negative.
0381: * <li>ERROR_INVALID_ARGUMENT - if the source rectangle is not contained within the bounds of the source image</li>
0382: * </ul>
0383: * @exception SWTError <ul>
0384: * <li>ERROR_NO_HANDLES - if no handles are available to perform the operation</li>
0385: * </ul>
0386: * @exception SWTException <ul>
0387: * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
0388: * </ul>
0389: */
0390: public void drawImage(Image image, int srcX, int srcY,
0391: int srcWidth, int srcHeight, int destX, int destY,
0392: int destWidth, int destHeight) {
0393: if (handle == 0)
0394: SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
0395: if (srcWidth == 0 || srcHeight == 0 || destWidth == 0
0396: || destHeight == 0)
0397: return;
0398: if (srcX < 0 || srcY < 0 || srcWidth < 0 || srcHeight < 0
0399: || destWidth < 0 || destHeight < 0) {
0400: SWT.error(SWT.ERROR_INVALID_ARGUMENT);
0401: }
0402: if (image == null)
0403: SWT.error(SWT.ERROR_NULL_ARGUMENT);
0404: if (image.isDisposed())
0405: SWT.error(SWT.ERROR_INVALID_ARGUMENT);
0406: drawImage(image, srcX, srcY, srcWidth, srcHeight, destX, destY,
0407: destWidth, destHeight, false);
0408: }
0409:
0410: void drawImage(Image srcImage, int srcX, int srcY, int srcWidth,
0411: int srcHeight, int destX, int destY, int destWidth,
0412: int destHeight, boolean simple) {
0413: int[] width = new int[1];
0414: int[] height = new int[1];
0415: OS.gdk_drawable_get_size(srcImage.pixmap, width, height);
0416: int imgWidth = width[0];
0417: int imgHeight = height[0];
0418: if (simple) {
0419: srcWidth = destWidth = imgWidth;
0420: srcHeight = destHeight = imgHeight;
0421: } else {
0422: simple = srcX == 0 && srcY == 0 && srcWidth == destWidth
0423: && destWidth == imgWidth && srcHeight == destHeight
0424: && destHeight == imgHeight;
0425: if (srcX + srcWidth > imgWidth
0426: || srcY + srcHeight > imgHeight) {
0427: SWT.error(SWT.ERROR_INVALID_ARGUMENT);
0428: }
0429: }
0430: if (srcImage.alpha != -1 || srcImage.alphaData != null) {
0431: drawImageAlpha(srcImage, srcX, srcY, srcWidth, srcHeight,
0432: destX, destY, destWidth, destHeight, simple,
0433: imgWidth, imgHeight);
0434: } else if (srcImage.transparentPixel != -1
0435: || srcImage.mask != 0) {
0436: drawImageMask(srcImage, srcX, srcY, srcWidth, srcHeight,
0437: destX, destY, destWidth, destHeight, simple,
0438: imgWidth, imgHeight);
0439: } else {
0440: drawImage(srcImage, srcX, srcY, srcWidth, srcHeight, destX,
0441: destY, destWidth, destHeight, simple, imgWidth,
0442: imgHeight);
0443: }
0444: }
0445:
0446: void drawImage(Image srcImage, int srcX, int srcY, int srcWidth,
0447: int srcHeight, int destX, int destY, int destWidth,
0448: int destHeight, boolean simple, int imgWidth, int imgHeight) {
0449: if (srcWidth == destWidth && srcHeight == destHeight) {
0450: OS.gdk_draw_drawable(data.drawable, handle,
0451: srcImage.pixmap, srcX, srcY, destX, destY,
0452: destWidth, destHeight);
0453: } else {
0454: int pixbuf = scale(srcImage.pixmap, srcX, srcY, srcWidth,
0455: srcHeight, destWidth, destHeight);
0456: if (pixbuf != 0) {
0457: OS.gdk_pixbuf_render_to_drawable(pixbuf, data.drawable,
0458: handle, 0, 0, destX, destY, destWidth,
0459: destHeight, OS.GDK_RGB_DITHER_NORMAL, 0, 0);
0460: OS.g_object_unref(pixbuf);
0461: }
0462: }
0463: }
0464:
0465: void drawImageAlpha(Image srcImage, int srcX, int srcY,
0466: int srcWidth, int srcHeight, int destX, int destY,
0467: int destWidth, int destHeight, boolean simple,
0468: int imgWidth, int imgHeight) {
0469: if (srcImage.alpha == 0)
0470: return;
0471: if (srcImage.alpha == 255) {
0472: drawImage(srcImage, srcX, srcY, srcWidth, srcHeight, destX,
0473: destY, destWidth, destHeight, simple, imgWidth,
0474: imgHeight);
0475: return;
0476: }
0477: int pixbuf = OS.gdk_pixbuf_new(OS.GDK_COLORSPACE_RGB, true, 8,
0478: srcWidth, srcHeight);
0479: if (pixbuf == 0)
0480: return;
0481: int colormap = OS.gdk_colormap_get_system();
0482: OS.gdk_pixbuf_get_from_drawable(pixbuf, srcImage.pixmap,
0483: colormap, srcX, srcY, 0, 0, srcWidth, srcHeight);
0484: int stride = OS.gdk_pixbuf_get_rowstride(pixbuf);
0485: int pixels = OS.gdk_pixbuf_get_pixels(pixbuf);
0486: byte[] line = new byte[stride];
0487: byte alpha = (byte) srcImage.alpha;
0488: byte[] alphaData = srcImage.alphaData;
0489: for (int y = 0; y < srcHeight; y++) {
0490: int alphaIndex = (y + srcY) * imgWidth + srcX;
0491: OS.memmove(line, pixels + (y * stride), stride);
0492: for (int x = 3; x < stride; x += 4) {
0493: line[x] = alphaData == null ? alpha
0494: : alphaData[alphaIndex++];
0495: }
0496: OS.memmove(pixels + (y * stride), line, stride);
0497: }
0498: if (srcWidth != destWidth || srcHeight != destHeight) {
0499: int scaledPixbuf = OS.gdk_pixbuf_scale_simple(pixbuf,
0500: destWidth, destHeight, OS.GDK_INTERP_BILINEAR);
0501: OS.g_object_unref(pixbuf);
0502: if (scaledPixbuf == 0)
0503: return;
0504: pixbuf = scaledPixbuf;
0505: }
0506: OS.gdk_pixbuf_render_to_drawable_alpha(pixbuf, data.drawable,
0507: 0, 0, destX, destY, destWidth, destHeight,
0508: OS.GDK_PIXBUF_ALPHA_BILEVEL, 128,
0509: OS.GDK_RGB_DITHER_NORMAL, 0, 0);
0510: OS.g_object_unref(pixbuf);
0511: }
0512:
0513: void drawImageMask(Image srcImage, int srcX, int srcY,
0514: int srcWidth, int srcHeight, int destX, int destY,
0515: int destWidth, int destHeight, boolean simple,
0516: int imgWidth, int imgHeight) {
0517: int drawable = data.drawable;
0518: int colorPixmap = srcImage.pixmap;
0519: /* Generate the mask if necessary. */
0520: if (srcImage.transparentPixel != -1)
0521: srcImage.createMask();
0522: int maskPixmap = srcImage.mask;
0523:
0524: if (srcWidth != destWidth || srcHeight != destHeight) {
0525: //NOT DONE - there must be a better way of scaling a GdkBitmap
0526: int pixbuf = OS.gdk_pixbuf_new(OS.GDK_COLORSPACE_RGB, true,
0527: 8, srcWidth, srcHeight);
0528: if (pixbuf != 0) {
0529: int colormap = OS.gdk_colormap_get_system();
0530: OS
0531: .gdk_pixbuf_get_from_drawable(pixbuf,
0532: colorPixmap, colormap, srcX, srcY, 0,
0533: 0, srcWidth, srcHeight);
0534: int gdkImagePtr = OS.gdk_drawable_get_image(maskPixmap,
0535: 0, 0, imgWidth, imgHeight);
0536: if (gdkImagePtr != 0) {
0537: int stride = OS.gdk_pixbuf_get_rowstride(pixbuf);
0538: int pixels = OS.gdk_pixbuf_get_pixels(pixbuf);
0539: byte[] line = new byte[stride];
0540: for (int y = 0; y < srcHeight; y++) {
0541: int offset = pixels + (y * stride);
0542: OS.memmove(line, offset, stride);
0543: for (int x = 0; x < srcWidth; x++) {
0544: if (OS.gdk_image_get_pixel(gdkImagePtr, x
0545: + srcX, y + srcY) == 0) {
0546: line[x * 4 + 3] = 0;
0547: }
0548: }
0549: OS.memmove(offset, line, stride);
0550: }
0551: OS.g_object_unref(gdkImagePtr);
0552: int scaledPixbuf = OS.gdk_pixbuf_scale_simple(
0553: pixbuf, destWidth, destHeight,
0554: OS.GDK_INTERP_BILINEAR);
0555: if (scaledPixbuf != 0) {
0556: int[] colorBuffer = new int[1];
0557: int[] maskBuffer = new int[1];
0558: OS.gdk_pixbuf_render_pixmap_and_mask(
0559: scaledPixbuf, colorBuffer, maskBuffer,
0560: 128);
0561: colorPixmap = colorBuffer[0];
0562: maskPixmap = maskBuffer[0];
0563: OS.g_object_unref(scaledPixbuf);
0564: }
0565: }
0566: OS.g_object_unref(pixbuf);
0567: }
0568: srcX = 0;
0569: srcY = 0;
0570: srcWidth = destWidth;
0571: srcHeight = destHeight;
0572: }
0573:
0574: /* Merge clipping with mask if necessary */
0575: if (data.clipRgn != 0) {
0576: int newWidth = srcX + srcWidth;
0577: int newHeight = srcY + srcHeight;
0578: int bytesPerLine = (((newWidth + 7) / 8) + 3) / 4 * 4;
0579: byte[] maskData = new byte[bytesPerLine * newHeight];
0580: int mask = OS.gdk_bitmap_create_from_data(0, maskData,
0581: bytesPerLine * 8, newHeight);
0582: if (mask != 0) {
0583: int gc = OS.gdk_gc_new(mask);
0584: OS.gdk_region_offset(data.clipRgn, -destX + srcX,
0585: -destY + srcY);
0586: OS.gdk_gc_set_clip_region(gc, data.clipRgn);
0587: OS.gdk_region_offset(data.clipRgn, destX - srcX, destY
0588: - srcY);
0589: GdkColor color = new GdkColor();
0590: color.pixel = 1;
0591: OS.gdk_gc_set_foreground(gc, color);
0592: OS.gdk_draw_rectangle(mask, gc, 1, 0, 0, newWidth,
0593: newHeight);
0594: OS.gdk_gc_set_function(gc, OS.GDK_AND);
0595: OS.gdk_draw_drawable(mask, gc, maskPixmap, 0, 0, 0, 0,
0596: newWidth, newHeight);
0597: OS.g_object_unref(gc);
0598: if (maskPixmap != 0 && srcImage.mask != maskPixmap)
0599: OS.g_object_unref(maskPixmap);
0600: maskPixmap = mask;
0601: }
0602: }
0603:
0604: /* Blit cliping the mask */
0605: GdkGCValues values = new GdkGCValues();
0606: OS.gdk_gc_get_values(handle, values);
0607: OS.gdk_gc_set_clip_mask(handle, maskPixmap);
0608: OS.gdk_gc_set_clip_origin(handle, destX - srcX, destY - srcY);
0609: OS.gdk_draw_drawable(drawable, handle, colorPixmap, srcX, srcY,
0610: destX, destY, srcWidth, srcHeight);
0611: OS.gdk_gc_set_values(handle, values, OS.GDK_GC_CLIP_MASK
0612: | OS.GDK_GC_CLIP_X_ORIGIN | OS.GDK_GC_CLIP_Y_ORIGIN);
0613: if (data.clipRgn != 0)
0614: OS.gdk_gc_set_clip_region(handle, data.clipRgn);
0615:
0616: /* Destroy scaled pixmaps */
0617: if (colorPixmap != 0 && srcImage.pixmap != colorPixmap)
0618: OS.g_object_unref(colorPixmap);
0619: if (maskPixmap != 0 && srcImage.mask != maskPixmap)
0620: OS.g_object_unref(maskPixmap);
0621: /* Destroy the image mask if the there is a GC created on the image */
0622: if (srcImage.transparentPixel != -1 && srcImage.memGC != null)
0623: srcImage.destroyMask();
0624: }
0625:
0626: int scale(int src, int srcX, int srcY, int srcWidth, int srcHeight,
0627: int destWidth, int destHeight) {
0628: int pixbuf = OS.gdk_pixbuf_new(OS.GDK_COLORSPACE_RGB, false, 8,
0629: srcWidth, srcHeight);
0630: if (pixbuf == 0)
0631: return 0;
0632: int colormap = OS.gdk_colormap_get_system();
0633: OS.gdk_pixbuf_get_from_drawable(pixbuf, src, colormap, srcX,
0634: srcY, 0, 0, srcWidth, srcHeight);
0635: int scaledPixbuf = OS.gdk_pixbuf_scale_simple(pixbuf,
0636: destWidth, destHeight, OS.GDK_INTERP_BILINEAR);
0637: OS.g_object_unref(pixbuf);
0638: return scaledPixbuf;
0639: }
0640:
0641: /**
0642: * Draws a line, using the foreground color, between the points
0643: * (<code>x1</code>, <code>y1</code>) and (<code>x2</code>, <code>y2</code>).
0644: *
0645: * @param x1 the first point's x coordinate
0646: * @param y1 the first point's y coordinate
0647: * @param x2 the second point's x coordinate
0648: * @param y2 the second point's y coordinate
0649: *
0650: * @exception SWTException <ul>
0651: * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
0652: * </ul>
0653: */
0654: public void drawLine(int x1, int y1, int x2, int y2) {
0655: if (handle == 0)
0656: SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
0657: OS.gdk_draw_line(data.drawable, handle, x1, y1, x2, y2);
0658: }
0659:
0660: /**
0661: * Draws the outline of an oval, using the foreground color,
0662: * within the specified rectangular area.
0663: * <p>
0664: * The result is a circle or ellipse that fits within the
0665: * rectangle specified by the <code>x</code>, <code>y</code>,
0666: * <code>width</code>, and <code>height</code> arguments.
0667: * </p><p>
0668: * The oval covers an area that is <code>width + 1</code>
0669: * pixels wide and <code>height + 1</code> pixels tall.
0670: * </p>
0671: *
0672: * @param x the x coordinate of the upper left corner of the oval to be drawn
0673: * @param y the y coordinate of the upper left corner of the oval to be drawn
0674: * @param width the width of the oval to be drawn
0675: * @param height the height of the oval to be drawn
0676: *
0677: * @exception SWTException <ul>
0678: * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
0679: * </ul>
0680: */
0681: public void drawOval(int x, int y, int width, int height) {
0682: if (handle == 0)
0683: SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
0684: if (width < 0) {
0685: x = x + width;
0686: width = -width;
0687: }
0688: if (height < 0) {
0689: y = y + height;
0690: height = -height;
0691: }
0692: OS.gdk_draw_arc(data.drawable, handle, 0, x, y, width, height,
0693: 0, 23040);
0694: }
0695:
0696: /**
0697: * Draws the closed polygon which is defined by the specified array
0698: * of integer coordinates, using the receiver's foreground color. The array
0699: * contains alternating x and y values which are considered to represent
0700: * points which are the vertices of the polygon. Lines are drawn between
0701: * each consecutive pair, and between the first pair and last pair in the
0702: * array.
0703: *
0704: * @param pointArray an array of alternating x and y values which are the vertices of the polygon
0705: *
0706: * @exception IllegalArgumentException <ul>
0707: * <li>ERROR_NULL_ARGUMENT if pointArray is null</li>
0708: * </ul>
0709: * @exception SWTException <ul>
0710: * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
0711: * </ul>
0712: */
0713: public void drawPolygon(int[] pointArray) {
0714: if (handle == 0)
0715: SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
0716: if (pointArray == null)
0717: SWT.error(SWT.ERROR_NULL_ARGUMENT);
0718: OS.gdk_draw_polygon(data.drawable, handle, 0, pointArray,
0719: pointArray.length / 2);
0720: }
0721:
0722: /**
0723: * Draws the polyline which is defined by the specified array
0724: * of integer coordinates, using the receiver's foreground color. The array
0725: * contains alternating x and y values which are considered to represent
0726: * points which are the corners of the polyline. Lines are drawn between
0727: * each consecutive pair, but not between the first pair and last pair in
0728: * the array.
0729: *
0730: * @param pointArray an array of alternating x and y values which are the corners of the polyline
0731: *
0732: * @exception IllegalArgumentException <ul>
0733: * <li>ERROR_NULL_ARGUMENT - if the point array is null</li>
0734: * </ul>
0735: * @exception SWTException <ul>
0736: * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
0737: * </ul>
0738: */
0739: public void drawPolyline(int[] pointArray) {
0740: if (handle == 0)
0741: SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
0742: if (pointArray == null)
0743: SWT.error(SWT.ERROR_NULL_ARGUMENT);
0744: OS.gdk_draw_lines(data.drawable, handle, pointArray,
0745: pointArray.length / 2);
0746: }
0747:
0748: /**
0749: * Draws the outline of the rectangle specified by the arguments,
0750: * using the receiver's foreground color. The left and right edges
0751: * of the rectangle are at <code>x</code> and <code>x + width</code>.
0752: * The top and bottom edges are at <code>y</code> and <code>y + height</code>.
0753: *
0754: * @param x the x coordinate of the rectangle to be drawn
0755: * @param y the y coordinate of the rectangle to be drawn
0756: * @param width the width of the rectangle to be drawn
0757: * @param height the height of the rectangle to be drawn
0758: *
0759: * @exception SWTException <ul>
0760: * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
0761: * </ul>
0762: */
0763: public void drawRectangle(int x, int y, int width, int height) {
0764: if (handle == 0)
0765: SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
0766: if (width < 0) {
0767: x = x + width;
0768: width = -width;
0769: }
0770: if (height < 0) {
0771: y = y + height;
0772: height = -height;
0773: }
0774: OS.gdk_draw_rectangle(data.drawable, handle, 0, x, y, width,
0775: height);
0776: }
0777:
0778: /**
0779: * Draws the outline of the specified rectangle, using the receiver's
0780: * foreground color. The left and right edges of the rectangle are at
0781: * <code>rect.x</code> and <code>rect.x + rect.width</code>. The top
0782: * and bottom edges are at <code>rect.y</code> and
0783: * <code>rect.y + rect.height</code>.
0784: *
0785: * @param rect the rectangle to draw
0786: *
0787: * @exception IllegalArgumentException <ul>
0788: * <li>ERROR_NULL_ARGUMENT - if the rectangle is null</li>
0789: * </ul>
0790: * @exception SWTException <ul>
0791: * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
0792: * </ul>
0793: */
0794: public void drawRectangle(Rectangle rect) {
0795: if (rect == null)
0796: SWT.error(SWT.ERROR_NULL_ARGUMENT);
0797: drawRectangle(rect.x, rect.y, rect.width, rect.height);
0798: }
0799:
0800: /**
0801: * Draws the outline of the round-cornered rectangle specified by
0802: * the arguments, using the receiver's foreground color. The left and
0803: * right edges of the rectangle are at <code>x</code> and <code>x + width</code>.
0804: * The top and bottom edges are at <code>y</code> and <code>y + height</code>.
0805: * The <em>roundness</em> of the corners is specified by the
0806: * <code>arcWidth</code> and <code>arcHeight</code> arguments.
0807: *
0808: * @param x the x coordinate of the rectangle to be drawn
0809: * @param y the y coordinate of the rectangle to be drawn
0810: * @param width the width of the rectangle to be drawn
0811: * @param height the height of the rectangle to be drawn
0812: * @param arcWidth the horizontal diameter of the arc at the four corners
0813: * @param arcHeight the vertical diameter of the arc at the four corners
0814: *
0815: * @exception SWTException <ul>
0816: * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
0817: * </ul>
0818: */
0819: public void drawRoundRectangle(int x, int y, int width, int height,
0820: int arcWidth, int arcHeight) {
0821: if (handle == 0)
0822: SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
0823: int nx = x;
0824: int ny = y;
0825: int nw = width;
0826: int nh = height;
0827: int naw = arcWidth;
0828: int nah = arcHeight;
0829:
0830: if (nw < 0) {
0831: nw = 0 - nw;
0832: nx = nx - nw;
0833: }
0834: if (nh < 0) {
0835: nh = 0 - nh;
0836: ny = ny - nh;
0837: }
0838: if (naw < 0)
0839: naw = 0 - naw;
0840: if (nah < 0)
0841: nah = 0 - nah;
0842:
0843: int naw2 = naw / 2;
0844: int nah2 = nah / 2;
0845:
0846: int drawable = data.drawable;
0847: if (nw > naw) {
0848: if (nh > nah) {
0849: OS.gdk_draw_arc(drawable, handle, 0, nx, ny, naw, nah,
0850: 5760, 5760);
0851: OS.gdk_draw_line(drawable, handle, nx + naw2, ny, nx
0852: + nw - naw2, ny);
0853: OS.gdk_draw_arc(drawable, handle, 0, nx + nw - naw, ny,
0854: naw, nah, 0, 5760);
0855: OS.gdk_draw_line(drawable, handle, nx + nw, ny + nah2,
0856: nx + nw, ny + nh - nah2);
0857: OS.gdk_draw_arc(drawable, handle, 0, nx + nw - naw, ny
0858: + nh - nah, naw, nah, 17280, 5760);
0859: OS.gdk_draw_line(drawable, handle, nx + naw2, ny + nh,
0860: nx + nw - naw2, ny + nh);
0861: OS.gdk_draw_arc(drawable, handle, 0, nx, ny + nh - nah,
0862: naw, nah, 11520, 5760);
0863: OS.gdk_draw_line(drawable, handle, nx, ny + nah2, nx,
0864: ny + nh - nah2);
0865: } else {
0866: OS.gdk_draw_arc(drawable, handle, 0, nx, ny, naw, nh,
0867: 5760, 11520);
0868: OS.gdk_draw_line(drawable, handle, nx + naw2, ny, nx
0869: + nw - naw2, ny);
0870: OS.gdk_draw_arc(drawable, handle, 0, nx + nw - naw, ny,
0871: naw, nh, 17280, 11520);
0872: OS.gdk_draw_line(drawable, handle, nx + naw2, ny + nh,
0873: nx + nw - naw2, ny + nh);
0874: }
0875: } else {
0876: if (nh > nah) {
0877: OS.gdk_draw_arc(drawable, handle, 0, nx, ny, nw, nah,
0878: 0, 11520);
0879: OS.gdk_draw_line(drawable, handle, nx + nw, ny + nah2,
0880: nx + nw, ny + nh - nah2);
0881: OS.gdk_draw_arc(drawable, handle, 0, nx, ny + nh - nah,
0882: nw, nah, 11520, 11520);
0883: OS.gdk_draw_line(drawable, handle, nx, ny + nah2, nx,
0884: ny + nh - nah2);
0885: } else {
0886: OS.gdk_draw_arc(drawable, handle, 0, nx, ny, nw, nh, 0,
0887: 23040);
0888: }
0889: }
0890: }
0891:
0892: /**
0893: * Draws the given string, using the receiver's current font and
0894: * foreground color. No tab expansion or carriage return processing
0895: * will be performed. The background of the rectangular area where
0896: * the string is being drawn will be filled with the receiver's
0897: * background color.
0898: *
0899: * @param string the string to be drawn
0900: * @param x the x coordinate of the top left corner of the rectangular area where the string is to be drawn
0901: * @param y the y coordinate of the top left corner of the rectangular area where the string is to be drawn
0902: *
0903: * @exception IllegalArgumentException <ul>
0904: * <li>ERROR_NULL_ARGUMENT - if the string is null</li>
0905: * </ul>
0906: * @exception SWTException <ul>
0907: * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
0908: * </ul>
0909: */
0910: public void drawString(String string, int x, int y) {
0911: drawString(string, x, y, false);
0912: }
0913:
0914: /**
0915: * Draws the given string, using the receiver's current font and
0916: * foreground color. No tab expansion or carriage return processing
0917: * will be performed. If <code>isTransparent</code> is <code>true</code>,
0918: * then the background of the rectangular area where the string is being
0919: * drawn will not be modified, otherwise it will be filled with the
0920: * receiver's background color.
0921: *
0922: * @param string the string to be drawn
0923: * @param x the x coordinate of the top left corner of the rectangular area where the string is to be drawn
0924: * @param y the y coordinate of the top left corner of the rectangular area where the string is to be drawn
0925: * @param isTransparent if <code>true</code> the background will be transparent, otherwise it will be opaque
0926: *
0927: * @exception IllegalArgumentException <ul>
0928: * <li>ERROR_NULL_ARGUMENT - if the string is null</li>
0929: * </ul>
0930: * @exception SWTException <ul>
0931: * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
0932: * </ul>
0933: */
0934: public void drawString(String string, int x, int y,
0935: boolean isTransparent) {
0936: drawText(string, x, y, isTransparent ? SWT.DRAW_TRANSPARENT : 0);
0937: }
0938:
0939: /**
0940: * Draws the given string, using the receiver's current font and
0941: * foreground color. Tab expansion and carriage return processing
0942: * are performed. The background of the rectangular area where
0943: * the text is being drawn will be filled with the receiver's
0944: * background color.
0945: *
0946: * @param string the string to be drawn
0947: * @param x the x coordinate of the top left corner of the rectangular area where the text is to be drawn
0948: * @param y the y coordinate of the top left corner of the rectangular area where the text is to be drawn
0949: *
0950: * @exception IllegalArgumentException <ul>
0951: * <li>ERROR_NULL_ARGUMENT - if the string is null</li>
0952: * </ul>
0953: * @exception SWTException <ul>
0954: * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
0955: * </ul>
0956: */
0957: public void drawText(String string, int x, int y) {
0958: drawText(string, x, y, SWT.DRAW_DELIMITER | SWT.DRAW_TAB);
0959: }
0960:
0961: /**
0962: * Draws the given string, using the receiver's current font and
0963: * foreground color. Tab expansion and carriage return processing
0964: * are performed. If <code>isTransparent</code> is <code>true</code>,
0965: * then the background of the rectangular area where the text is being
0966: * drawn will not be modified, otherwise it will be filled with the
0967: * receiver's background color.
0968: *
0969: * @param string the string to be drawn
0970: * @param x the x coordinate of the top left corner of the rectangular area where the text is to be drawn
0971: * @param y the y coordinate of the top left corner of the rectangular area where the text is to be drawn
0972: * @param isTransparent if <code>true</code> the background will be transparent, otherwise it will be opaque
0973: *
0974: * @exception IllegalArgumentException <ul>
0975: * <li>ERROR_NULL_ARGUMENT - if the string is null</li>
0976: * </ul>
0977: * @exception SWTException <ul>
0978: * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
0979: * </ul>
0980: */
0981: public void drawText(String string, int x, int y,
0982: boolean isTransparent) {
0983: int flags = SWT.DRAW_DELIMITER | SWT.DRAW_TAB;
0984: if (isTransparent)
0985: flags |= SWT.DRAW_TRANSPARENT;
0986: drawText(string, x, y, flags);
0987: }
0988:
0989: /**
0990: * Draws the given string, using the receiver's current font and
0991: * foreground color. Tab expansion, line delimiter and mnemonic
0992: * processing are performed according to the specified flags. If
0993: * <code>flags</code> includes <code>DRAW_TRANSPARENT</code>,
0994: * then the background of the rectangular area where the text is being
0995: * drawn will not be modified, otherwise it will be filled with the
0996: * receiver's background color.
0997: * <p>
0998: * The parameter <code>flags</code> may be a combination of:
0999: * <dl>
1000: * <dt><b>DRAW_DELIMITER</b></dt>
1001: * <dd>draw multiple lines</dd>
1002: * <dt><b>DRAW_TAB</b></dt>
1003: * <dd>expand tabs</dd>
1004: * <dt><b>DRAW_MNEMONIC</b></dt>
1005: * <dd>underline the mnemonic character</dd>
1006: * <dt><b>DRAW_TRANSPARENT</b></dt>
1007: * <dd>transparent background</dd>
1008: * </dl>
1009: * </p>
1010: *
1011: * @param string the string to be drawn
1012: * @param x the x coordinate of the top left corner of the rectangular area where the text is to be drawn
1013: * @param y the y coordinate of the top left corner of the rectangular area where the text is to be drawn
1014: * @param flags the flags specifing how to process the text
1015: *
1016: * @exception IllegalArgumentException <ul>
1017: * <li>ERROR_NULL_ARGUMENT - if the string is null</li>
1018: * </ul>
1019: * @exception SWTException <ul>
1020: * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
1021: * </ul>
1022: */
1023: public void drawText(String string, int x, int y, int flags) {
1024: if (handle == 0)
1025: SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
1026: if (string == null)
1027: SWT.error(SWT.ERROR_NULL_ARGUMENT);
1028: if (string.length() == 0)
1029: return;
1030: setString(string, flags);
1031: GdkColor background = null;
1032: GdkGCValues values = null;
1033: if ((flags & SWT.DRAW_TRANSPARENT) == 0) {
1034: values = new GdkGCValues();
1035: OS.gdk_gc_get_values(handle, values);
1036: background = new GdkColor();
1037: background.pixel = values.background_pixel;
1038: int colormap = OS.gdk_colormap_get_system();
1039: OS.gdk_colormap_query_color(colormap, background.pixel,
1040: background);
1041: }
1042: if (!data.xorMode) {
1043: OS.gdk_draw_layout_with_colors(data.drawable, handle, x, y,
1044: data.layout, null, background);
1045: } else {
1046: int layout = data.layout;
1047: int[] w = new int[1], h = new int[1];
1048: OS.pango_layout_get_size(layout, w, h);
1049: int width = OS.PANGO_PIXELS(w[0]);
1050: int height = OS.PANGO_PIXELS(h[0]);
1051: int pixmap = OS.gdk_pixmap_new(OS.GDK_ROOT_PARENT(), width,
1052: height, -1);
1053: if (pixmap == 0)
1054: SWT.error(SWT.ERROR_NO_HANDLES);
1055: int gdkGC = OS.gdk_gc_new(pixmap);
1056: if (gdkGC == 0)
1057: SWT.error(SWT.ERROR_NO_HANDLES);
1058: GdkColor foreground = new GdkColor();
1059: OS.gdk_gc_set_foreground(gdkGC, foreground);
1060: OS
1061: .gdk_draw_rectangle(pixmap, gdkGC, 1, 0, 0, width,
1062: height);
1063: if (values == null) {
1064: values = new GdkGCValues();
1065: OS.gdk_gc_get_values(handle, values);
1066: }
1067: foreground.pixel = values.foreground_pixel;
1068: OS.gdk_gc_set_foreground(gdkGC, foreground);
1069: OS.gdk_draw_layout_with_colors(pixmap, gdkGC, 0, 0, layout,
1070: null, background);
1071: OS.g_object_unref(gdkGC);
1072: OS.gdk_draw_drawable(data.drawable, handle, pixmap, 0, 0,
1073: x, y, width, height);
1074: OS.g_object_unref(pixmap);
1075: }
1076: }
1077:
1078: /**
1079: * Draws the given string, using the receiver's current font and
1080: * foreground color. No tab expansion or carriage return processing
1081: * will be performed. If <code>isTransparent</code> is <code>true</code>,
1082: * then the background of the rectangular area where the string is being
1083: * drawn will not be modified, otherwise it will be filled with the
1084: * receiver's background color.
1085: *
1086: * @param string the string to be drawn
1087: * @param x the x coordinate of the top left corner of the rectangular area where the string is to be drawn
1088: * @param y the y coordinate of the top left corner of the rectangular area where the string is to be drawn
1089: * @param isTransparent if <code>true</code> the background will be transparent, otherwise it will be opaque
1090: *
1091: * @exception IllegalArgumentException <ul>
1092: * <li>ERROR_NULL_ARGUMENT - if the string is null</li>
1093: * </ul>
1094: * @exception SWTException <ul>
1095: * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
1096: * </ul>
1097: */
1098: public void drawSubstring(String string, int xSrc, int srcWidth,
1099: int x, int y, int width, boolean isTransparent) {
1100: // TODO: xor mode.
1101: if (string == null)
1102: SWT.error(SWT.ERROR_NULL_ARGUMENT);
1103: if (handle == 0)
1104: SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
1105:
1106: int layout = data.layout;
1107: byte[] buffer = Converter.wcsToMbcs(null, string, false);
1108: OS.pango_layout_set_text(layout, buffer, buffer.length);
1109:
1110: int[] w = new int[1], h = new int[1];
1111: OS.pango_layout_get_size(data.layout, w, h);
1112: //int width = OS.PANGO_PIXELS(w[0]);
1113: int height = OS.PANGO_PIXELS(h[0]);
1114: int pixmap = OS.gdk_pixmap_new(OS.GDK_ROOT_PARENT(), width,
1115: height, -1);
1116: if (pixmap == 0)
1117: SWT.error(SWT.ERROR_NO_HANDLES);
1118: int gdkGC = OS.gdk_gc_new(pixmap);
1119: if (gdkGC == 0)
1120: SWT.error(SWT.ERROR_NO_HANDLES);
1121: OS.gdk_pango_context_set_colormap(data.context, OS
1122: .gdk_colormap_get_system());
1123: OS.gdk_draw_layout_with_colors(pixmap, gdkGC, 0, 0, layout,
1124: getForeground().handle, getBackground().handle);
1125: OS.g_object_unref(gdkGC);
1126: OS.gdk_draw_drawable(data.drawable, handle, pixmap, xSrc, 0, x,
1127: y, srcWidth, height);
1128: OS.g_object_unref(pixmap);
1129: }
1130:
1131: /**
1132: * Compares the argument to the receiver, and returns true
1133: * if they represent the <em>same</em> object using a class
1134: * specific comparison.
1135: *
1136: * @param object the object to compare with this object
1137: * @return <code>true</code> if the object is the same as this object and <code>false</code> otherwise
1138: *
1139: * @see #hashCode
1140: */
1141: public boolean equals(Object object) {
1142: if (object == this )
1143: return true;
1144: if (!(object instanceof GC))
1145: return false;
1146: return handle == ((GC) object).handle;
1147: }
1148:
1149: /**
1150: * Fills the interior of a circular or elliptical arc within
1151: * the specified rectangular area, with the receiver's background
1152: * color.
1153: * <p>
1154: * The resulting arc begins at <code>startAngle</code> and extends
1155: * for <code>arcAngle</code> degrees, using the current color.
1156: * Angles are interpreted such that 0 degrees is at the 3 o'clock
1157: * position. A positive value indicates a counter-clockwise rotation
1158: * while a negative value indicates a clockwise rotation.
1159: * </p><p>
1160: * The center of the arc is the center of the rectangle whose origin
1161: * is (<code>x</code>, <code>y</code>) and whose size is specified by the
1162: * <code>width</code> and <code>height</code> arguments.
1163: * </p><p>
1164: * The resulting arc covers an area <code>width + 1</code> pixels wide
1165: * by <code>height + 1</code> pixels tall.
1166: * </p>
1167: *
1168: * @param x the x coordinate of the upper-left corner of the arc to be filled
1169: * @param y the y coordinate of the upper-left corner of the arc to be filled
1170: * @param width the width of the arc to be filled
1171: * @param height the height of the arc to be filled
1172: * @param startAngle the beginning angle
1173: * @param arcAngle the angular extent of the arc, relative to the start angle
1174: *
1175: * @exception IllegalArgumentException <ul>
1176: * <li>ERROR_INVALID_ARGUMENT - if any of the width, height or endAngle is zero.</li>
1177: * </ul>
1178: * @exception SWTException <ul>
1179: * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
1180: * </ul>
1181: *
1182: * @see #drawArc
1183: */
1184: public void fillArc(int x, int y, int width, int height,
1185: int startAngle, int arcAngle) {
1186: if (handle == 0)
1187: SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
1188: if (width < 0) {
1189: x = x + width;
1190: width = -width;
1191: }
1192: if (height < 0) {
1193: y = y + height;
1194: height = -height;
1195: }
1196: if (width == 0 || height == 0 || arcAngle == 0)
1197: return;
1198: GdkGCValues values = new GdkGCValues();
1199: OS.gdk_gc_get_values(handle, values);
1200: GdkColor color = new GdkColor();
1201: color.pixel = values.background_pixel;
1202: OS.gdk_gc_set_foreground(handle, color);
1203: OS.gdk_draw_arc(data.drawable, handle, 1, x, y, width, height,
1204: startAngle * 64, arcAngle * 64);
1205: color.pixel = values.foreground_pixel;
1206: OS.gdk_gc_set_foreground(handle, color);
1207: }
1208:
1209: /**
1210: * Fills the interior of the specified rectangle with a gradient
1211: * sweeping from left to right or top to bottom progressing
1212: * from the receiver's foreground color to its background color.
1213: *
1214: * @param x the x coordinate of the rectangle to be filled
1215: * @param y the y coordinate of the rectangle to be filled
1216: * @param width the width of the rectangle to be filled, may be negative
1217: * (inverts direction of gradient if horizontal)
1218: * @param height the height of the rectangle to be filled, may be negative
1219: * (inverts direction of gradient if vertical)
1220: * @param vertical if true sweeps from top to bottom, else
1221: * sweeps from left to right
1222: *
1223: * @exception SWTException <ul>
1224: * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
1225: * </ul>
1226: *
1227: * @see #drawRectangle
1228: */
1229: public void fillGradientRectangle(int x, int y, int width,
1230: int height, boolean vertical) {
1231: if (handle == 0)
1232: SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
1233: if ((width == 0) || (height == 0))
1234: return;
1235:
1236: /* Rewrite this to use GdkPixbuf */
1237:
1238: GdkGCValues values = new GdkGCValues();
1239: OS.gdk_gc_get_values(handle, values);
1240:
1241: RGB backgroundRGB, foregroundRGB;
1242: backgroundRGB = getBackground().getRGB();
1243: foregroundRGB = getForeground().getRGB();
1244:
1245: RGB fromRGB, toRGB;
1246: fromRGB = foregroundRGB;
1247: toRGB = backgroundRGB;
1248: boolean swapColors = false;
1249: if (width < 0) {
1250: x += width;
1251: width = -width;
1252: if (!vertical)
1253: swapColors = true;
1254: }
1255: if (height < 0) {
1256: y += height;
1257: height = -height;
1258: if (vertical)
1259: swapColors = true;
1260: }
1261: if (swapColors) {
1262: fromRGB = backgroundRGB;
1263: toRGB = foregroundRGB;
1264: }
1265: if (fromRGB == toRGB) {
1266: fillRectangle(x, y, width, height);
1267: return;
1268: }
1269: ImageData.fillGradientRectangle(this , data.device, x, y, width,
1270: height, vertical, fromRGB, toRGB, 8, 8, 8);
1271: }
1272:
1273: /**
1274: * Fills the interior of an oval, within the specified
1275: * rectangular area, with the receiver's background
1276: * color.
1277: *
1278: * @param x the x coordinate of the upper left corner of the oval to be filled
1279: * @param y the y coordinate of the upper left corner of the oval to be filled
1280: * @param width the width of the oval to be filled
1281: * @param height the height of the oval to be filled
1282: *
1283: * @exception SWTException <ul>
1284: * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
1285: * </ul>
1286: *
1287: * @see #drawOval
1288: */
1289: public void fillOval(int x, int y, int width, int height) {
1290: if (handle == 0)
1291: SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
1292: if (width < 0) {
1293: x = x + width;
1294: width = -width;
1295: }
1296: if (height < 0) {
1297: y = y + height;
1298: height = -height;
1299: }
1300: GdkGCValues values = new GdkGCValues();
1301: OS.gdk_gc_get_values(handle, values);
1302: GdkColor color = new GdkColor();
1303: color.pixel = values.background_pixel;
1304: OS.gdk_gc_set_foreground(handle, color);
1305: OS.gdk_draw_arc(data.drawable, handle, 1, x, y, width, height,
1306: 0, 23040);
1307: color.pixel = values.foreground_pixel;
1308: OS.gdk_gc_set_foreground(handle, color);
1309: }
1310:
1311: /**
1312: * Fills the interior of the closed polygon which is defined by the
1313: * specified array of integer coordinates, using the receiver's
1314: * background color. The array contains alternating x and y values
1315: * which are considered to represent points which are the vertices of
1316: * the polygon. Lines are drawn between each consecutive pair, and
1317: * between the first pair and last pair in the array.
1318: *
1319: * @param pointArray an array of alternating x and y values which are the vertices of the polygon
1320: *
1321: * @exception IllegalArgumentException <ul>
1322: * <li>ERROR_NULL_ARGUMENT if pointArray is null</li>
1323: * </ul>
1324: * @exception SWTException <ul>
1325: * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
1326: * </ul>
1327: *
1328: * @see #drawPolygon
1329: */
1330: public void fillPolygon(int[] pointArray) {
1331: if (handle == 0)
1332: SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
1333: if (pointArray == null)
1334: SWT.error(SWT.ERROR_NULL_ARGUMENT);
1335: GdkGCValues values = new GdkGCValues();
1336: OS.gdk_gc_get_values(handle, values);
1337: GdkColor color = new GdkColor();
1338: color.pixel = values.background_pixel;
1339: OS.gdk_gc_set_foreground(handle, color);
1340: OS.gdk_draw_polygon(data.drawable, handle, 1, pointArray,
1341: pointArray.length / 2);
1342: color.pixel = values.foreground_pixel;
1343: OS.gdk_gc_set_foreground(handle, color);
1344: }
1345:
1346: /**
1347: * Fills the interior of the rectangle specified by the arguments,
1348: * using the receiver's background color.
1349: *
1350: * @param x the x coordinate of the rectangle to be filled
1351: * @param y the y coordinate of the rectangle to be filled
1352: * @param width the width of the rectangle to be filled
1353: * @param height the height of the rectangle to be filled
1354: *
1355: * @exception SWTException <ul>
1356: * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
1357: * </ul>
1358: *
1359: * @see #drawRectangle
1360: */
1361: public void fillRectangle(int x, int y, int width, int height) {
1362: if (handle == 0)
1363: SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
1364: if (width < 0) {
1365: x = x + width;
1366: width = -width;
1367: }
1368: if (height < 0) {
1369: y = y + height;
1370: height = -height;
1371: }
1372: GdkGCValues values = new GdkGCValues();
1373: OS.gdk_gc_get_values(handle, values);
1374: GdkColor color = new GdkColor();
1375: color.pixel = values.background_pixel;
1376: OS.gdk_gc_set_foreground(handle, color);
1377: OS.gdk_draw_rectangle(data.drawable, handle, 1, x, y, width,
1378: height);
1379: color.pixel = values.foreground_pixel;
1380: OS.gdk_gc_set_foreground(handle, color);
1381: }
1382:
1383: /**
1384: * Fills the interior of the specified rectangle, using the receiver's
1385: * background color.
1386: *
1387: * @param rectangle the rectangle to be filled
1388: *
1389: * @exception IllegalArgumentException <ul>
1390: * <li>ERROR_NULL_ARGUMENT - if the rectangle is null</li>
1391: * </ul>
1392: * @exception SWTException <ul>
1393: * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
1394: * </ul>
1395: *
1396: * @see #drawRectangle
1397: */
1398: public void fillRectangle(Rectangle rect) {
1399: if (handle == 0)
1400: SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
1401: if (rect == null)
1402: SWT.error(SWT.ERROR_NULL_ARGUMENT);
1403: fillRectangle(rect.x, rect.y, rect.width, rect.height);
1404: }
1405:
1406: /**
1407: * Fills the interior of the round-cornered rectangle specified by
1408: * the arguments, using the receiver's background color.
1409: *
1410: * @param x the x coordinate of the rectangle to be filled
1411: * @param y the y coordinate of the rectangle to be filled
1412: * @param width the width of the rectangle to be filled
1413: * @param height the height of the rectangle to be filled
1414: * @param arcWidth the horizontal diameter of the arc at the four corners
1415: * @param arcHeight the vertical diameter of the arc at the four corners
1416: *
1417: * @exception SWTException <ul>
1418: * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
1419: * </ul>
1420: *
1421: * @see #drawRoundRectangle
1422: */
1423: public void fillRoundRectangle(int x, int y, int width, int height,
1424: int arcWidth, int arcHeight) {
1425: if (handle == 0)
1426: SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
1427: int nx = x;
1428: int ny = y;
1429: int nw = width;
1430: int nh = height;
1431: int naw = arcWidth;
1432: int nah = arcHeight;
1433:
1434: if (nw < 0) {
1435: nw = 0 - nw;
1436: nx = nx - nw;
1437: }
1438: if (nh < 0) {
1439: nh = 0 - nh;
1440: ny = ny - nh;
1441: }
1442: if (naw < 0)
1443: naw = 0 - naw;
1444: if (nah < 0)
1445: nah = 0 - nah;
1446:
1447: int naw2 = naw / 2;
1448: int nah2 = nah / 2;
1449:
1450: GdkGCValues values = new GdkGCValues();
1451: OS.gdk_gc_get_values(handle, values);
1452: GdkColor color = new GdkColor();
1453: color.pixel = values.background_pixel;
1454: OS.gdk_gc_set_foreground(handle, color);
1455:
1456: int drawable = data.drawable;
1457: if (nw > naw) {
1458: if (nh > nah) {
1459: OS.gdk_draw_arc(drawable, handle, 1, nx, ny, naw, nah,
1460: 5760, 5760);
1461: OS.gdk_draw_rectangle(drawable, handle, 1, nx + naw2,
1462: ny, nw - naw2 * 2, nh);
1463: OS.gdk_draw_arc(drawable, handle, 1, nx + nw - naw, ny,
1464: naw, nah, 0, 5760);
1465: OS.gdk_draw_rectangle(drawable, handle, 1, nx, ny
1466: + nah2, naw2, nh - nah2 * 2);
1467: OS.gdk_draw_arc(drawable, handle, 1, nx + nw - naw, ny
1468: + nh - nah, naw, nah, 17280, 5760);
1469: OS.gdk_draw_rectangle(drawable, handle, 1, nx + nw
1470: - naw2, ny + nah2, naw2, nh - nah2 * 2);
1471: OS.gdk_draw_arc(drawable, handle, 1, nx, ny + nh - nah,
1472: naw, nah, 11520, 5760);
1473: } else {
1474: OS.gdk_draw_arc(drawable, handle, 1, nx, ny, naw, nh,
1475: 5760, 11520);
1476: OS.gdk_draw_rectangle(drawable, handle, 1, nx + naw2,
1477: ny, nw - naw2 * 2, nh);
1478: OS.gdk_draw_arc(drawable, handle, 1, nx + nw - naw, ny,
1479: naw, nh, 17280, 11520);
1480: }
1481: } else {
1482: if (nh > nah) {
1483: OS.gdk_draw_arc(drawable, handle, 1, nx, ny, nw, nah,
1484: 0, 11520);
1485: OS.gdk_draw_rectangle(drawable, handle, 1, nx, ny
1486: + nah2, nw, nh - nah2 * 2);
1487: OS.gdk_draw_arc(drawable, handle, 1, nx, ny + nh - nah,
1488: nw, nah, 11520, 11520);
1489: } else {
1490: OS.gdk_draw_arc(drawable, handle, 1, nx, ny, nw, nh, 0,
1491: 23040);
1492: }
1493: }
1494:
1495: color.pixel = values.foreground_pixel;
1496: OS.gdk_gc_set_foreground(handle, color);
1497: }
1498:
1499: int fixMnemonic(char[] buffer) {
1500: int i = 0, j = 0;
1501: int mnemonic = -1;
1502: while (i < buffer.length) {
1503: if ((buffer[j++] = buffer[i++]) == '&') {
1504: if (i == buffer.length) {
1505: continue;
1506: }
1507: if (buffer[i] == '&') {
1508: i++;
1509: continue;
1510: }
1511: if (mnemonic == -1)
1512: mnemonic = j;
1513: j--;
1514: }
1515: }
1516: while (j < buffer.length)
1517: buffer[j++] = 0;
1518: return mnemonic;
1519: }
1520:
1521: /**
1522: * Returns the <em>advance width</em> of the specified character in
1523: * the font which is currently selected into the receiver.
1524: * <p>
1525: * The advance width is defined as the horizontal distance the cursor
1526: * should move after printing the character in the selected font.
1527: * </p>
1528: *
1529: * @param ch the character to measure
1530: * @return the distance in the x direction to move past the character before painting the next
1531: *
1532: * @exception SWTException <ul>
1533: * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
1534: * </ul>
1535: */
1536: public int getAdvanceWidth(char ch) {
1537: if (handle == 0)
1538: SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
1539: //BOGUS
1540: return stringExtent(new String(new char[] { ch })).x;
1541: }
1542:
1543: /**
1544: * Returns the background color.
1545: *
1546: * @return the receiver's background color
1547: *
1548: * @exception SWTException <ul>
1549: * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
1550: * </ul>
1551: */
1552: public Color getBackground() {
1553: if (handle == 0)
1554: SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
1555: GdkGCValues values = new GdkGCValues();
1556: OS.gdk_gc_get_values(handle, values);
1557: GdkColor color = new GdkColor();
1558: color.pixel = values.background_pixel;
1559: int colormap = OS.gdk_colormap_get_system();
1560: OS.gdk_colormap_query_color(colormap, color.pixel, color);
1561: return Color.gtk_new(data.device, color);
1562: }
1563:
1564: /**
1565: * Returns the width of the specified character in the font
1566: * selected into the receiver.
1567: * <p>
1568: * The width is defined as the space taken up by the actual
1569: * character, not including the leading and tailing whitespace
1570: * or overhang.
1571: * </p>
1572: *
1573: * @param ch the character to measure
1574: * @return the width of the character
1575: *
1576: * @exception SWTException <ul>
1577: * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
1578: * </ul>
1579: */
1580: public int getCharWidth(char ch) {
1581: if (handle == 0)
1582: SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
1583: //BOGUS
1584: return stringExtent(new String(new char[] { ch })).x;
1585: }
1586:
1587: /**
1588: * Returns the bounding rectangle of the receiver's clipping
1589: * region. If no clipping region is set, the return value
1590: * will be a rectangle which covers the entire bounds of the
1591: * object the receiver is drawing on.
1592: *
1593: * @return the bounding rectangle of the clipping region
1594: *
1595: * @exception SWTException <ul>
1596: * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
1597: * </ul>
1598: */
1599: public Rectangle getClipping() {
1600: if (handle == 0)
1601: SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
1602: int clipRgn = data.clipRgn;
1603: if (clipRgn == 0) {
1604: int[] width = new int[1];
1605: int[] height = new int[1];
1606: OS.gdk_drawable_get_size(data.drawable, width, height);
1607: return new Rectangle(0, 0, width[0], height[0]);
1608: }
1609: GdkRectangle rect = new GdkRectangle();
1610: OS.gdk_region_get_clipbox(clipRgn, rect);
1611: return new Rectangle(rect.x, rect.y, rect.width, rect.height);
1612: }
1613:
1614: /**
1615: * Sets the region managed by the argument to the current
1616: * clipping region of the receiver.
1617: *
1618: * @param region the region to fill with the clipping region
1619: *
1620: * @exception IllegalArgumentException <ul>
1621: * <li>ERROR_NULL_ARGUMENT - if the region is null</li>
1622: * </ul>
1623: * @exception SWTException <ul>
1624: * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
1625: * </ul>
1626: */
1627: public void getClipping(Region region) {
1628: if (handle == 0)
1629: SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
1630: if (region == null)
1631: SWT.error(SWT.ERROR_NULL_ARGUMENT);
1632: int hRegion = region.handle;
1633: int clipRgn = data.clipRgn;
1634: OS.gdk_region_subtract(hRegion, hRegion);
1635: if (data.clipRgn == 0) {
1636: int[] width = new int[1];
1637: int[] height = new int[1];
1638: OS.gdk_drawable_get_size(data.drawable, width, height);
1639: GdkRectangle rect = new GdkRectangle();
1640: rect.x = 0;
1641: rect.y = 0;
1642: rect.width = width[0];
1643: rect.height = height[0];
1644: OS.gdk_region_union_with_rect(hRegion, rect);
1645: } else {
1646: OS.gdk_region_union(hRegion, clipRgn);
1647: }
1648: }
1649:
1650: /**
1651: * Returns the font currently being used by the receiver
1652: * to draw and measure text.
1653: *
1654: * @return the receiver's font
1655: *
1656: * @exception SWTException <ul>
1657: * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
1658: * </ul>
1659: */
1660: public Font getFont() {
1661: if (handle == 0)
1662: SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
1663: return Font.gtk_new(data.device, data.font);
1664: }
1665:
1666: /**
1667: * Returns a FontMetrics which contains information
1668: * about the font currently being used by the receiver
1669: * to draw and measure text.
1670: *
1671: * @return font metrics for the receiver's font
1672: *
1673: * @exception SWTException <ul>
1674: * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
1675: * </ul>
1676: */
1677: public FontMetrics getFontMetrics() {
1678: if (handle == 0)
1679: SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
1680: int context = data.context;
1681: int lang = OS.pango_context_get_language(context);
1682: int metrics = OS.pango_context_get_metrics(context, data.font,
1683: lang);
1684: FontMetrics fm = new FontMetrics();
1685: fm.ascent = OS.PANGO_PIXELS(OS
1686: .pango_font_metrics_get_ascent(metrics));
1687: fm.descent = OS.PANGO_PIXELS(OS
1688: .pango_font_metrics_get_descent(metrics));
1689: fm.averageCharWidth = OS
1690: .PANGO_PIXELS(OS
1691: .pango_font_metrics_get_approximate_char_width(metrics));
1692: fm.height = fm.ascent + fm.descent;
1693: OS.pango_font_metrics_unref(metrics);
1694: return fm;
1695: }
1696:
1697: /**
1698: * Returns the receiver's foreground color.
1699: *
1700: * @return the color used for drawing foreground things
1701: *
1702: * @exception SWTException <ul>
1703: * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
1704: * </ul>
1705: */
1706: public Color getForeground() {
1707: if (handle == 0)
1708: SWT.error(SWT.ERROR_WIDGET_DISPOSED);
1709: GdkGCValues values = new GdkGCValues();
1710: OS.gdk_gc_get_values(handle, values);
1711: GdkColor color = new GdkColor();
1712: color.pixel = values.foreground_pixel;
1713: int colormap = OS.gdk_colormap_get_system();
1714: OS.gdk_colormap_query_color(colormap, color.pixel, color);
1715: return Color.gtk_new(data.device, color);
1716: }
1717:
1718: /**
1719: * Returns the receiver's line style, which will be one
1720: * of the constants <code>SWT.LINE_SOLID</code>, <code>SWT.LINE_DASH</code>,
1721: * <code>SWT.LINE_DOT</code>, <code>SWT.LINE_DASHDOT</code> or
1722: * <code>SWT.LINE_DASHDOTDOT</code>.
1723: *
1724: * @return the style used for drawing lines
1725: *
1726: * @exception SWTException <ul>
1727: * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
1728: * </ul>
1729: */
1730: public int getLineStyle() {
1731: if (handle == 0)
1732: SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
1733: return data.lineStyle;
1734: }
1735:
1736: /**
1737: * Returns the width that will be used when drawing lines
1738: * for all of the figure drawing operations (that is,
1739: * <code>drawLine</code>, <code>drawRectangle</code>,
1740: * <code>drawPolyline</code>, and so forth.
1741: *
1742: * @return the receiver's line width
1743: *
1744: * @exception SWTException <ul>
1745: * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
1746: * </ul>
1747: */
1748: public int getLineWidth() {
1749: if (handle == 0)
1750: SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
1751: GdkGCValues values = new GdkGCValues();
1752: OS.gdk_gc_get_values(handle, values);
1753: return values.line_width;
1754: }
1755:
1756: public int getStyle() {
1757: if (handle == 0)
1758: SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
1759: return data.style;
1760: }
1761:
1762: /**
1763: * Returns <code>true</code> if this GC is drawing in the mode
1764: * where the resulting color in the destination is the
1765: * <em>exclusive or</em> of the color values in the source
1766: * and the destination, and <code>false</code> if it is
1767: * drawing in the mode where the destination color is being
1768: * replaced with the source color value.
1769: *
1770: * @return <code>true</code> true if the receiver is in XOR mode, and false otherwise
1771: *
1772: * @exception SWTException <ul>
1773: * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
1774: * </ul>
1775: */
1776: public boolean getXORMode() {
1777: if (handle == 0)
1778: SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
1779: GdkGCValues values = new GdkGCValues();
1780: OS.gdk_gc_get_values(handle, values);
1781: return values.function == OS.GDK_XOR;
1782: }
1783:
1784: /**
1785: * Returns an integer hash code for the receiver. Any two
1786: * objects which return <code>true</code> when passed to
1787: * <code>equals</code> must return the same value for this
1788: * method.
1789: *
1790: * @return the receiver's hash
1791: *
1792: * @exception SWTException <ul>
1793: * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
1794: * </ul>
1795: *
1796: * @see #equals
1797: */
1798: public int hashCode() {
1799: return handle;
1800: }
1801:
1802: void init(Drawable drawable, GCData data, int gdkGC) {
1803: int context = OS.gdk_pango_context_get();
1804: if (context == 0)
1805: SWT.error(SWT.ERROR_NO_HANDLES);
1806: OS.pango_context_set_language(context, OS
1807: .gtk_get_default_language());
1808: OS.gdk_pango_context_set_colormap(context, OS
1809: .gdk_colormap_get_system());
1810: data.context = context;
1811: int layout = OS.pango_layout_new(context);
1812: if (layout == 0)
1813: SWT.error(SWT.ERROR_NO_HANDLES);
1814: data.layout = layout;
1815:
1816: GdkColor foreground = data.foreground;
1817: if (foreground != null)
1818: OS.gdk_gc_set_foreground(gdkGC, foreground);
1819: GdkColor background = data.background;
1820: if (background != null)
1821: OS.gdk_gc_set_background(gdkGC, background);
1822: int font = data.font;
1823: if (font != 0)
1824: OS.pango_layout_set_font_description(layout, font);
1825:
1826: Image image = data.image;
1827: if (image != null) {
1828: image.memGC = this ;
1829: /*
1830: * The transparent pixel mask might change when drawing on
1831: * the image. Destroy it so that it is regenerated when
1832: * necessary.
1833: */
1834: if (image.transparentPixel != -1)
1835: image.destroyMask();
1836: }
1837: this .drawable = drawable;
1838: this .data = data;
1839: handle = gdkGC;
1840: }
1841:
1842: /**
1843: * Returns <code>true</code> if the receiver has a clipping
1844: * region set into it, and <code>false</code> otherwise.
1845: * If this method returns false, the receiver will draw on all
1846: * available space in the destination. If it returns true,
1847: * it will draw only in the area that is covered by the region
1848: * that can be accessed with <code>getClipping(region)</code>.
1849: *
1850: * @return <code>true</code> if the GC has a clipping region, and <code>false</code> otherwise
1851: *
1852: * @exception SWTException <ul>
1853: * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
1854: * </ul>
1855: */
1856: public boolean isClipped() {
1857: if (handle == 0)
1858: SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
1859: return data.clipRgn != 0;
1860: }
1861:
1862: /**
1863: * Returns <code>true</code> if the GC has been disposed,
1864: * and <code>false</code> otherwise.
1865: * <p>
1866: * This method gets the dispose state for the GC.
1867: * When a GC has been disposed, it is an error to
1868: * invoke any other method using the GC.
1869: *
1870: * @return <code>true</code> when the GC is disposed and <code>false</code> otherwise
1871: */
1872: public boolean isDisposed() {
1873: return handle == 0;
1874: }
1875:
1876: /**
1877: * Sets the background color. The background color is used
1878: * for fill operations and as the background color when text
1879: * is drawn.
1880: *
1881: * @param color the new background color for the receiver
1882: *
1883: * @exception IllegalArgumentException <ul>
1884: * <li>ERROR_NULL_ARGUMENT - if the color is null</li>
1885: * <li>ERROR_INVALID_ARGUMENT - if the color has been disposed</li>
1886: * </ul>
1887: * @exception SWTException <ul>
1888: * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
1889: * </ul>
1890: */
1891: public void setBackground(Color color) {
1892: if (handle == 0)
1893: SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
1894: if (color == null)
1895: SWT.error(SWT.ERROR_NULL_ARGUMENT);
1896: if (color.isDisposed())
1897: SWT.error(SWT.ERROR_INVALID_ARGUMENT);
1898: OS.gdk_gc_set_background(handle, color.handle);
1899: }
1900:
1901: /**
1902: * Sets the area of the receiver which can be changed
1903: * by drawing operations to the rectangular area specified
1904: * by the arguments.
1905: *
1906: * @param x the x coordinate of the clipping rectangle
1907: * @param y the y coordinate of the clipping rectangle
1908: * @param width the width of the clipping rectangle
1909: * @param height the height of the clipping rectangle
1910: *
1911: * @exception SWTException <ul>
1912: * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
1913: * </ul>
1914: */
1915: public void setClipping(int x, int y, int width, int height) {
1916: if (handle == 0)
1917: SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
1918: int clipRgn = data.clipRgn;
1919: if (clipRgn == 0) {
1920: data.clipRgn = clipRgn = OS.gdk_region_new();
1921: } else {
1922: OS.gdk_region_subtract(clipRgn, clipRgn);
1923: }
1924: GdkRectangle rect = new GdkRectangle();
1925: rect.x = x;
1926: rect.y = y;
1927: rect.width = width;
1928: rect.height = height;
1929: OS.gdk_gc_set_clip_rectangle(handle, rect);
1930: OS.gdk_region_union_with_rect(clipRgn, rect);
1931: }
1932:
1933: /**
1934: * Sets the area of the receiver which can be changed
1935: * by drawing operations to the rectangular area specified
1936: * by the argument.
1937: *
1938: * @param rect the clipping rectangle
1939: *
1940: * @exception SWTException <ul>
1941: * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
1942: * </ul>
1943: */
1944: public void setClipping(Rectangle rect) {
1945: if (handle == 0)
1946: SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
1947: int clipRgn = data.clipRgn;
1948: if (rect == null) {
1949: OS.gdk_gc_set_clip_region(handle, 0);
1950: if (clipRgn != 0) {
1951: OS.gdk_region_destroy(clipRgn);
1952: data.clipRgn = clipRgn = 0;
1953: }
1954: return;
1955: }
1956: setClipping(rect.x, rect.y, rect.width, rect.height);
1957: }
1958:
1959: /**
1960: * Sets the area of the receiver which can be changed
1961: * by drawing operations to the region specified
1962: * by the argument.
1963: *
1964: * @param rect the clipping region.
1965: *
1966: * @exception SWTException <ul>
1967: * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
1968: * </ul>
1969: */
1970: public void setClipping(Region region) {
1971: if (handle == 0)
1972: SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
1973: int clipRgn = data.clipRgn;
1974: if (region == null) {
1975: OS.gdk_gc_set_clip_region(handle, 0);
1976: if (clipRgn != 0) {
1977: OS.gdk_region_destroy(clipRgn);
1978: data.clipRgn = clipRgn = 0;
1979: }
1980: } else {
1981: if (clipRgn == 0) {
1982: data.clipRgn = clipRgn = OS.gdk_region_new();
1983: } else {
1984: OS.gdk_region_subtract(clipRgn, clipRgn);
1985: }
1986: OS.gdk_region_union(clipRgn, region.handle);
1987: OS.gdk_gc_set_clip_region(handle, clipRgn);
1988: }
1989: }
1990:
1991: /**
1992: * Sets the font which will be used by the receiver
1993: * to draw and measure text to the argument. If the
1994: * argument is null, then a default font appropriate
1995: * for the platform will be used instead.
1996: *
1997: * @param font the new font for the receiver, or null to indicate a default font
1998: *
1999: * @exception IllegalArgumentException <ul>
2000: * <li>ERROR_INVALID_ARGUMENT - if the font has been disposed</li>
2001: * </ul>
2002: * @exception SWTException <ul>
2003: * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
2004: * </ul>
2005: */
2006: public void setFont(Font font) {
2007: if (handle == 0)
2008: SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
2009: if (font == null)
2010: font = data.device.systemFont;
2011: if (font.isDisposed())
2012: SWT.error(SWT.ERROR_INVALID_ARGUMENT);
2013: int fontHandle = data.font = font.handle;
2014: OS.pango_layout_set_font_description(data.layout, fontHandle);
2015: data.stringWidth = data.stringHeight = -1;
2016: }
2017:
2018: /**
2019: * Sets the foreground color. The foreground color is used
2020: * for drawing operations including when text is drawn.
2021: *
2022: * @param color the new foreground color for the receiver
2023: *
2024: * @exception IllegalArgumentException <ul>
2025: * <li>ERROR_NULL_ARGUMENT - if the color is null</li>
2026: * <li>ERROR_INVALID_ARGUMENT - if the color has been disposed</li>
2027: * </ul>
2028: * @exception SWTException <ul>
2029: * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
2030: * </ul>
2031: */
2032: public void setForeground(Color color) {
2033: if (handle == 0)
2034: SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
2035: if (color == null)
2036: SWT.error(SWT.ERROR_NULL_ARGUMENT);
2037: if (color.isDisposed())
2038: SWT.error(SWT.ERROR_INVALID_ARGUMENT);
2039: OS.gdk_gc_set_foreground(handle, color.handle);
2040: }
2041:
2042: /**
2043: * Sets the receiver's line style to the argument, which must be one
2044: * of the constants <code>SWT.LINE_SOLID</code>, <code>SWT.LINE_DASH</code>,
2045: * <code>SWT.LINE_DOT</code>, <code>SWT.LINE_DASHDOT</code> or
2046: * <code>SWT.LINE_DASHDOTDOT</code>.
2047: *
2048: * @param lineStyle the style to be used for drawing lines
2049: *
2050: * @exception SWTException <ul>
2051: * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
2052: * </ul>
2053: */
2054: public void setLineStyle(int lineStyle) {
2055: if (handle == 0)
2056: SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
2057: int line_style = OS.GDK_LINE_ON_OFF_DASH;
2058: switch (lineStyle) {
2059: case SWT.LINE_SOLID:
2060: line_style = OS.GDK_LINE_SOLID;
2061: break;
2062: case SWT.LINE_DASH:
2063: OS.gdk_gc_set_dashes(handle, 0, new byte[] { 6, 2 }, 2);
2064: break;
2065: case SWT.LINE_DOT:
2066: OS.gdk_gc_set_dashes(handle, 0, new byte[] { 3, 1 }, 2);
2067: break;
2068: case SWT.LINE_DASHDOT:
2069: OS.gdk_gc_set_dashes(handle, 0, new byte[] { 6, 2, 3, 1 },
2070: 4);
2071: break;
2072: case SWT.LINE_DASHDOTDOT:
2073: OS.gdk_gc_set_dashes(handle, 0, new byte[] { 6, 2, 3, 1, 3,
2074: 1 }, 6);
2075: break;
2076: default:
2077: SWT.error(SWT.ERROR_INVALID_ARGUMENT);
2078: }
2079: data.lineStyle = lineStyle;
2080: GdkGCValues values = new GdkGCValues();
2081: OS.gdk_gc_get_values(handle, values);
2082: OS.gdk_gc_set_line_attributes(handle, values.line_width,
2083: line_style, OS.GDK_CAP_BUTT, OS.GDK_JOIN_MITER);
2084: }
2085:
2086: /**
2087: * Sets the width that will be used when drawing lines
2088: * for all of the figure drawing operations (that is,
2089: * <code>drawLine</code>, <code>drawRectangle</code>,
2090: * <code>drawPolyline</code>, and so forth.
2091: *
2092: * @param lineWidth the width of a line
2093: *
2094: * @exception SWTException <ul>
2095: * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
2096: * </ul>
2097: */
2098: public void setLineWidth(int width) {
2099: if (handle == 0)
2100: SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
2101: int line_style = data.lineStyle == SWT.LINE_SOLID ? OS.GDK_LINE_SOLID
2102: : OS.GDK_LINE_ON_OFF_DASH;
2103: OS.gdk_gc_set_line_attributes(handle, width, line_style,
2104: OS.GDK_CAP_BUTT, OS.GDK_JOIN_MITER);
2105: }
2106:
2107: void setString(String string, int flags) {
2108: if (string == data.string
2109: && (flags & ~SWT.DRAW_TRANSPARENT) == (data.drawFlags & ~SWT.DRAW_TRANSPARENT)) {
2110: return;
2111: }
2112: byte[] buffer;
2113: int mnemonic, layout = data.layout, length = string.length();
2114: char[] text = new char[length];
2115: string.getChars(0, length, text, 0);
2116: if ((flags & SWT.DRAW_MNEMONIC) != 0
2117: && (mnemonic = fixMnemonic(text)) != -1) {
2118: char[] text1 = new char[mnemonic - 1];
2119: System.arraycopy(text, 0, text1, 0, text1.length);
2120: byte[] buffer1 = Converter.wcsToMbcs(null, text1, false);
2121: char[] text2 = new char[text.length - mnemonic];
2122: System
2123: .arraycopy(text, mnemonic - 1, text2, 0,
2124: text2.length);
2125: byte[] buffer2 = Converter.wcsToMbcs(null, text2, false);
2126: buffer = new byte[buffer1.length + buffer2.length];
2127: System.arraycopy(buffer1, 0, buffer, 0, buffer1.length);
2128: System.arraycopy(buffer2, 0, buffer, buffer1.length,
2129: buffer2.length);
2130: int attr_list = OS.pango_attr_list_new();
2131: int attr = OS
2132: .pango_attr_underline_new(OS.PANGO_UNDERLINE_LOW);
2133: PangoAttribute attribute = new PangoAttribute();
2134: OS.memmove(attribute, attr, PangoAttribute.sizeof);
2135: attribute.start_index = buffer1.length;
2136: attribute.end_index = buffer1.length + 1;
2137: OS.memmove(attr, attribute, PangoAttribute.sizeof);
2138: OS.pango_attr_list_insert(attr_list, attr);
2139: OS.pango_layout_set_attributes(layout, attr_list);
2140: OS.pango_attr_list_unref(attr_list);
2141: } else {
2142: buffer = Converter.wcsToMbcs(null, text, false);
2143: OS.pango_layout_set_attributes(layout, 0);
2144: }
2145: OS.pango_layout_set_text(layout, buffer, buffer.length);
2146: OS.pango_layout_set_single_paragraph_mode(layout,
2147: (flags & SWT.DRAW_DELIMITER) == 0);
2148: OS.pango_layout_set_tabs(layout,
2149: (flags & SWT.DRAW_TAB) != 0 ? 0 : data.device.emptyTab);
2150: data.string = string;
2151: data.stringWidth = data.stringHeight = -1;
2152: data.drawFlags = flags;
2153: }
2154:
2155: /**
2156: * If the argument is <code>true</code>, puts the receiver
2157: * in a drawing mode where the resulting color in the destination
2158: * is the <em>exclusive or</em> of the color values in the source
2159: * and the destination, and if the argument is <code>false</code>,
2160: * puts the receiver in a drawing mode where the destination color
2161: * is replaced with the source color value.
2162: *
2163: * @param xor if <code>true</code>, then <em>xor</em> mode is used, otherwise <em>source copy</em> mode is used
2164: *
2165: * @exception SWTException <ul>
2166: * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
2167: * </ul>
2168: */
2169: public void setXORMode(boolean xor) {
2170: if (handle == 0)
2171: SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
2172: OS.gdk_gc_set_function(handle, xor ? OS.GDK_XOR : OS.GDK_COPY);
2173: data.xorMode = xor;
2174: }
2175:
2176: /**
2177: * Returns the extent of the given string. No tab
2178: * expansion or carriage return processing will be performed.
2179: * <p>
2180: * The <em>extent</em> of a string is the width and height of
2181: * the rectangular area it would cover if drawn in a particular
2182: * font (in this case, the current font in the receiver).
2183: * </p>
2184: *
2185: * @param string the string to measure
2186: * @return a point containing the extent of the string
2187: *
2188: * @exception IllegalArgumentException <ul>
2189: * <li>ERROR_NULL_ARGUMENT - if the string is null</li>
2190: * </ul>
2191: * @exception SWTException <ul>
2192: * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
2193: * </ul>
2194: */
2195: public Point stringExtent(String string) {
2196: return textExtent(string, 0);
2197: }
2198:
2199: /**
2200: * Returns the extent of the given string. Tab expansion and
2201: * carriage return processing are performed.
2202: * <p>
2203: * The <em>extent</em> of a string is the width and height of
2204: * the rectangular area it would cover if drawn in a particular
2205: * font (in this case, the current font in the receiver).
2206: * </p>
2207: *
2208: * @param string the string to measure
2209: * @return a point containing the extent of the string
2210: *
2211: * @exception IllegalArgumentException <ul>
2212: * <li>ERROR_NULL_ARGUMENT - if the string is null</li>
2213: * </ul>
2214: * @exception SWTException <ul>
2215: * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
2216: * </ul>
2217: */
2218: public Point textExtent(String string) {
2219: return textExtent(string, SWT.DRAW_DELIMITER | SWT.DRAW_TAB);
2220: }
2221:
2222: /**
2223: * Returns the extent of the given string. Tab expansion, line
2224: * delimiter and mnemonic processing are performed according to
2225: * the specified flags, which can be a combination of:
2226: * <dl>
2227: * <dt><b>DRAW_DELIMITER</b></dt>
2228: * <dd>draw multiple lines</dd>
2229: * <dt><b>DRAW_TAB</b></dt>
2230: * <dd>expand tabs</dd>
2231: * <dt><b>DRAW_MNEMONIC</b></dt>
2232: * <dd>underline the mnemonic character</dd>
2233: * <dt><b>DRAW_TRANSPARENT</b></dt>
2234: * <dd>transparent background</dd>
2235: * </dl>
2236: * <p>
2237: * The <em>extent</em> of a string is the width and height of
2238: * the rectangular area it would cover if drawn in a particular
2239: * font (in this case, the current font in the receiver).
2240: * </p>
2241: *
2242: * @param string the string to measure
2243: * @param flags the flags specifing how to process the text
2244: * @return a point containing the extent of the string
2245: *
2246: * @exception IllegalArgumentException <ul>
2247: * <li>ERROR_NULL_ARGUMENT - if the string is null</li>
2248: * </ul>
2249: * @exception SWTException <ul>
2250: * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
2251: * </ul>
2252: */
2253: public Point textExtent(String string, int flags) {
2254: if (handle == 0)
2255: SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
2256: if (string == null)
2257: SWT.error(SWT.ERROR_NULL_ARGUMENT);
2258: setString(string, flags);
2259: if (data.stringWidth != -1)
2260: return new Point(data.stringWidth, data.stringHeight);
2261: int[] width = new int[1], height = new int[1];
2262: OS.pango_layout_get_size(data.layout, width, height);
2263: return new Point(data.stringWidth = OS.PANGO_PIXELS(width[0]),
2264: data.stringHeight = OS.PANGO_PIXELS(height[0]));
2265: }
2266:
2267: /**
2268: * Returns a string containing a concise, human-readable
2269: * description of the receiver.
2270: *
2271: * @return a string representation of the receiver
2272: */
2273: public String toString() {
2274: if (isDisposed())
2275: return "GC {*DISPOSED*}";
2276: return "GC {" + handle + "}";
2277: }
2278:
2279: /**
2280: * Returns the receiver's layout.
2281: *
2282: * @return the layout used for drawing.
2283: *
2284: * @exception SWTException <ul>
2285: * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
2286: * </ul>
2287: */
2288: public int getLayout() {
2289: if (handle == 0)
2290: SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
2291: return OS.g_object_ref(data.layout);
2292: }
2293:
2294: }
|