blob: 24374928a333f7baf56497ead1ec78c3f5d05b5d [file] [log] [blame]
package org.eclipse.swt.graphics;
/*
* (c) Copyright IBM Corp. 2000, 2001.
* All Rights Reserved
*/
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.internal.gtk.*;
import org.eclipse.swt.internal.*;
import org.eclipse.swt.*;
/**
* Class <code>GC</code> is where all of the drawing capabilities that are
* supported by SWT are located. Instances are used to draw on either an
* <code>Image</code>, a <code>Control</code>, or directly on a <code>Display</code>.
* <p>
* Application code must explicitly invoke the <code>GC.dispose()</code>
* method to release the operating system resources managed by each instance
* when those instances are no longer required. This is <em>particularly</em>
* important on Windows95 and Windows98 where the operating system has a limited
* number of device contexts available.
* </p>
*
* @see org.eclipse.swt.events.PaintEvent
*/
public final class GC {
/**
* the handle to the OS device context
* (Warning: This field is platform dependent)
*/
public int handle;
Drawable drawable;
GCData data;
/*
* === Constructors ===
*/
GC() {
}
/**
* Constructs a new instance of this class which has been
* configured to draw on the specified drawable. Sets the
* foreground and background color in the GC to match those
* in the drawable.
* <p>
* You must dispose the graphics context when it is no longer required.
* </p>
* @param drawable the drawable to draw on
* @exception IllegalArgumentException <ul>
* <li>ERROR_NULL_ARGUMENT - if the drawable is null</li>
* <li>ERROR_INVALID_ARGUMENT
* - if the drawable is an image that is not a bitmap or an icon
* - if the drawable is an image or printer that is already selected
* into another graphics context</li>
* </ul>
*/
public GC(Drawable drawable) {
if (drawable == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
data = new GCData();
handle = drawable.internal_new_GC(data);
this.drawable = drawable;
// The colors we get from the widget are not always right.
// Get the default GTK_STATE_NORMAL colors
setBackground( DefaultGtkStyle.instance().backgroundColorNORMAL() );
setForeground( DefaultGtkStyle.instance().foregroundColorNORMAL() );
// Feature in GDK.
// Sometimes, gdk_gc_new() doesn't get the font from the control,
// and also, some controls don't contain a font; so when the GC
// was created in internal_new_gc(), the font might or might not
// be set; if the font isn't there, just fall back to default.
GdkGCValues values = new GdkGCValues();
OS.gdk_gc_get_values(handle, values);
if (values.font == 0) {
OS.gdk_gc_set_font(handle, DefaultGtkStyle.instance().loadDefaultFont() );
}
if (data.image != null) {
data.image.memGC = this;
/*
* The transparent pixel mask might change when drawing on
* the image. Destroy it so that it is regenerated when
* necessary.
*/
//if (image.transparentPixel != -1) image.destroyMask();
}
}
/**
* Returns the background color.
*
* @return the receiver's background color
*
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*/
/*
* === Access - Get/Set ===
*/
public Color getBackground() {
if (handle == 0) error(SWT.ERROR_WIDGET_DISPOSED);
GdkColor gdkColor = _getBackgroundGdkColor();
return Color.gtk_new(gdkColor);
}
/**
* Sets the background color. The background color is used
* for fill operations and as the background color when text
* is drawn.
*
* @param color the new background color for the receiver
*
* @exception IllegalArgumentException <ul>
* <li>ERROR_NULL_ARGUMENT - if the color is null</li>
* <li>ERROR_INVALID_ARGUMENT - if the color has been disposed</li>
* </ul>
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*/
public void setBackground(Color color) {
if (color == null) error(SWT.ERROR_NULL_ARGUMENT);
if (color.handle == null) error(SWT.ERROR_NULL_ARGUMENT);
if (handle == 0) error(SWT.ERROR_WIDGET_DISPOSED);
OS.gdk_gc_set_background(handle, color.handle);
}
/**
* Returns the receiver's foreground color.
*
* @return the color used for drawing foreground things
*
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*/
public Color getForeground() {
if (handle == 0) error(SWT.ERROR_WIDGET_DISPOSED);
GdkColor gdkColor = _getForegroundGdkColor();
return Color.gtk_new(gdkColor);
}
/**
* Sets the foreground color. The foreground color is used
* for drawing operations including when text is drawn.
*
* @param color the new foreground color for the receiver
*
* @exception IllegalArgumentException <ul>
* <li>ERROR_NULL_ARGUMENT - if the color is null</li>
* <li>ERROR_INVALID_ARGUMENT - if the color has been disposed</li>
* </ul>
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*/
public void setForeground(Color color) {
if (handle == 0) error(SWT.ERROR_WIDGET_DISPOSED);
if (color == null) error(SWT.ERROR_NULL_ARGUMENT);
if (color.handle == null) error(SWT.ERROR_NULL_ARGUMENT);
OS.gdk_gc_set_foreground(handle, color.handle);
}
/**
* Returns the <em>advance width</em> of the specified character in
* the font which is currently selected into the receiver.
* <p>
* The advance width is defined as the horizontal distance the cursor
* should move after printing the character in the selected font.
* </p>
*
* @param ch the character to measure
* @return the distance in the x direction to move past the character before painting the next
*
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*/
/*
* === Access - Get - Calculated ===
*/
public int getAdvanceWidth(char ch) {
byte[] charBuffer = Converter.wcsToMbcs(null, new char[] { ch });
return OS.gdk_char_width(_getGCFont(), charBuffer[0]);
}
/**
* Returns the width of the specified character in the font
* selected into the receiver.
* <p>
* The width is defined as the space taken up by the actual
* character, not including the leading and tailing whitespace
* or overhang.
* </p>
*
* @param ch the character to measure
* @return the width of the character
*
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*/
public int getCharWidth(char ch) {
byte[] charBuffer = Converter.wcsToMbcs(null, new char[] { ch });
int[] lbearing = new int[1];
int[] rbearing = new int[1];
int[] unused = new int[1];
OS.gdk_string_extents(_getGCFont(), charBuffer, lbearing, rbearing, unused, unused, unused);
return rbearing[0] - lbearing[0];
}
/**
* Returns the bounding rectangle of the receiver's clipping
* region. If no clipping region is set, the return value
* will be a rectangle which covers the entire bounds of the
* object the receiver is drawing on.
*
* @return the bounding rectangle of the clipping region
*
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*/
public Rectangle getClipping() {
if (data.clipRgn == 0) {
int[] width = new int[1]; int[] height = new int[1];
int[] unused = new int[1];
OS.gdk_window_get_geometry(data.drawable, unused, unused, width, height, unused);
return new Rectangle(0, 0, width[0], height[0]);
}
GdkRectangle rect = new GdkRectangle();
OS.gdk_region_get_clipbox(data.clipRgn, rect);
return new Rectangle(rect.x, rect.y, rect.width, rect.height);
}
/**
* Sets the region managed by the argument to the current
* clipping region of the receiver.
*
* @param region the region to fill with the clipping region
*
* @exception IllegalArgumentException <ul>
* <li>ERROR_NULL_ARGUMENT - if the region is null</li>
* </ul>
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*/
public void getClipping(Region region) {
if (region == null) error(SWT.ERROR_NULL_ARGUMENT);
int hRegion = region.handle;
if (data.clipRgn == 0) {
int[] width = new int[1]; int[] height = new int[1];
int[] unused = new int[1];
OS.gdk_window_get_geometry(data.drawable, unused, unused, width, height, unused);
hRegion = OS.gdk_region_new();
GdkRectangle rect = new GdkRectangle();
rect.x = 0; rect.y = 0;
rect.width = (short)width[0]; rect.height = (short)height[0];
region.handle = OS.gdk_region_union_with_rect(hRegion, rect);
return;
}
hRegion = OS.gdk_region_new();
region.handle = OS.gdk_regions_union(data.clipRgn, hRegion);
}
/**
* Returns the font currently being used by the receiver
* to draw and measure text.
*
* @return the receiver's font
*
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*/
public Font getFont() {
return Font.gtk_new(_getGCFont());
}
/**
* Returns a FontMetrics which contains information
* about the font currently being used by the receiver
* to draw and measure text.
*
* @return font metrics for the receiver's font
*
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*/
// Not done
public FontMetrics getFontMetrics() {
int fontHandle = _getGCFont();
if (fontHandle==0) {
error(SWT.ERROR_UNSPECIFIED);
}
GdkFont gdkFont = new GdkFont();
OS.memmove(gdkFont, fontHandle, GdkFont.sizeof);
byte [] w = Converter.wcsToMbcs (null, "w", true);
return FontMetrics.gtk_new(fontHandle);
}
/**
* Returns the receiver's line style, which will be one
* of the constants <code>SWT.LINE_SOLID</code>, <code>SWT.LINE_DASH</code>,
* <code>SWT.LINE_DOT</code>, <code>SWT.LINE_DASHDOT</code> or
* <code>SWT.LINE_DASHDOTDOT</code>.
*
* @return the style used for drawing lines
*
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*/
public int getLineStyle() {
return data.lineStyle;
}
/**
* Returns the width that will be used when drawing lines
* for all of the figure drawing operations (that is,
* <code>drawLine</code>, <code>drawRectangle</code>,
* <code>drawPolyline</code>, and so forth.
*
* @return the receiver's line width
*
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*/
public int getLineWidth() {
GdkGCValues values = new GdkGCValues();
OS.gdk_gc_get_values(handle, values);
return values.line_width;
}
/**
* Returns <code>true</code> if this GC is drawing in the mode
* where the resulting color in the destination is the
* <em>exclusive or</em> of the color values in the source
* and the destination, and <code>false</code> if it is
* drawing in the mode where the destination color is being
* replaced with the source color value.
*
* @return <code>true</code> true if the receiver is in XOR mode, and false otherwise
*
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*/
public boolean getXORMode() {
GdkGCValues values = new GdkGCValues();
OS.gdk_gc_get_values(handle, values);
return values.function == OS.GDK_XOR;
}
/**
* Returns <code>true</code> if the receiver has a clipping
* region set into it, and <code>false</code> otherwise.
* If this method returns false, the receiver will draw on all
* available space in the destination. If it returns true,
* it will draw only in the area that is covered by the region
* that can be accessed with <code>getClipping(region)</code>.
*
* @return <code>true</code> if the GC has a clipping region, and <code>false</code> otherwise
*
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*/
public boolean isClipped() {
return data.clipRgn != 0;
}
/**
* Sets the area of the receiver which can be changed
* by drawing operations to the rectangular area specified
* by the arguments.
*
* @param x the x coordinate of the clipping rectangle
* @param y the y coordinate of the clipping rectangle
* @param width the width of the clipping rectangle
* @param height the height of the clipping rectangle
*
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*/
public void setClipping(int x, int y, int width, int height) {
if (data.clipRgn == 0) data.clipRgn = OS.gdk_region_new();
GdkRectangle rect = new GdkRectangle();
rect.x = (short)x; rect.y = (short)y;
rect.width = (short)width; rect.height = (short)height;
OS.gdk_gc_set_clip_rectangle(handle, rect);
data.clipRgn = OS.gdk_regions_subtract(data.clipRgn, data.clipRgn);
data.clipRgn = OS.gdk_region_union_with_rect(data.clipRgn, rect);
}
/**
* Sets the area of the receiver which can be changed
* by drawing operations to the rectangular area specified
* by the argument.
*
* @param rect the clipping rectangle
*
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*/
public void setClipping(Rectangle rect) {
if (rect == null) error(SWT.ERROR_NULL_ARGUMENT);
setClipping (rect.x, rect.y, rect.width, rect.height);
}
/**
* Sets the area of the receiver which can be changed
* by drawing operations to the region specified
* by the argument.
*
* @param rect the clipping region.
*
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*/
public void setClipping(Region region) {
if (data.clipRgn == 0) data.clipRgn = OS.gdk_region_new();
if (region == null) {
data.clipRgn = OS.gdk_regions_subtract(data.clipRgn, data.clipRgn);
OS.gdk_gc_set_clip_mask(handle, OS.GDK_NONE);
} else {
data.clipRgn = OS.gdk_regions_subtract(data.clipRgn, data.clipRgn);
data.clipRgn = OS.gdk_regions_union(region.handle, data.clipRgn);
OS.gdk_gc_set_clip_region(handle, region.handle);
}
}
/**
* Sets the font which will be used by the receiver
* to draw and measure text to the argument. If the
* argument is null, then a default font appropriate
* for the platform will be used instead.
*
* @param font the new font for the receiver, or null to indicate a default font
*
* @exception IllegalArgumentException <ul>
* <li>ERROR_INVALID_ARGUMENT - if the font has been disposed</li>
* </ul>
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*/
public void setFont(Font font) {
int fontHandle = 0;
if (font == null) {
GtkStyle gtkStyle = new GtkStyle();
int style = OS.gtk_widget_get_default_style();
OS.memmove(gtkStyle, style, GtkStyle.sizeof);
fontHandle = gtkStyle.font;
} else {
fontHandle = font.handle;
}
OS.gdk_gc_set_font(handle, fontHandle);
}
/**
* Sets the receiver's line style to the argument, which must be one
* of the constants <code>SWT.LINE_SOLID</code>, <code>SWT.LINE_DASH</code>,
* <code>SWT.LINE_DOT</code>, <code>SWT.LINE_DASHDOT</code> or
* <code>SWT.LINE_DASHDOTDOT</code>.
*
* @param lineStyle the style to be used for drawing lines
*
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*/
public void setLineStyle(int lineStyle) {
switch (lineStyle) {
case SWT.LINE_SOLID:
this.data.lineStyle = lineStyle;
OS.gdk_gc_set_line_attributes(handle, 0, OS.GDK_LINE_SOLID, OS.GDK_CAP_BUTT, OS.GDK_JOIN_MITER);
return;
case SWT.LINE_DASH:
OS.gdk_gc_set_dashes(handle, 0, new byte[] {6, 2}, 2);
break;
case SWT.LINE_DOT:
OS.gdk_gc_set_dashes(handle, 0, new byte[] {3, 1}, 2);
break;
case SWT.LINE_DASHDOT:
OS.gdk_gc_set_dashes(handle, 0, new byte[] {6, 2, 3, 1}, 4);
break;
case SWT.LINE_DASHDOTDOT:
OS.gdk_gc_set_dashes(handle, 0, new byte[] {6, 2, 3, 1, 3, 1}, 6);
break;
default:
error(SWT.ERROR_INVALID_ARGUMENT);
}
this.data.lineStyle = lineStyle;
OS.gdk_gc_set_line_attributes(handle, 0, OS.GDK_LINE_DOUBLE_DASH, OS.GDK_CAP_BUTT, OS.GDK_JOIN_MITER);
}
/**
* Sets the width that will be used when drawing lines
* for all of the figure drawing operations (that is,
* <code>drawLine</code>, <code>drawRectangle</code>,
* <code>drawPolyline</code>, and so forth.
*
* @param lineWidth the width of a line
*
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*/
public void setLineWidth(int width) {
if (data.lineStyle == SWT.LINE_SOLID) {
OS.gdk_gc_set_line_attributes(handle, width, OS.GDK_LINE_SOLID, OS.GDK_CAP_BUTT, OS.GDK_JOIN_MITER);
} else {
OS.gdk_gc_set_line_attributes(handle, width, OS.GDK_LINE_DOUBLE_DASH, OS.GDK_CAP_BUTT, OS.GDK_JOIN_MITER);
}
}
/**
* If the argument is <code>true</code>, puts the receiver
* in a drawing mode where the resulting color in the destination
* is the <em>exclusive or</em> of the color values in the source
* and the destination, and if the argument is <code>false</code>,
* puts the receiver in a drawing mode where the destination color
* is replaced with the source color value.
*
* @param xor if <code>true</code>, then <em>xor</em> mode is used, otherwise <em>source copy</em> mode is used
*
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*/
public void setXORMode(boolean val) {
if (val) {
OS.gdk_gc_set_function(handle, OS.GDK_XOR);
} else {
OS.gdk_gc_set_function(handle, OS.GDK_COPY);
}
}
/**
* Returns the extent of the given string. No tab
* expansion or carriage return processing will be performed.
* <p>
* The <em>extent</em> of a string is the width and height of
* the rectangular area it would cover if drawn in a particular
* font (in this case, the current font in the receiver).
* </p>
*
* @param string the string to measure
* @return a point containing the extent of the string
*
* @exception IllegalArgumentException <ul>
* <li>ERROR_NULL_ARGUMENT - if the string is null</li>
* </ul>
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*/
public Point stringExtent(String string) {
if (string == null) error(SWT.ERROR_NULL_ARGUMENT);
byte[] buffer = Converter.wcsToMbcs(null, string, true);
int width = OS.gdk_string_width(_getGCFont(), buffer);
int height = OS.gdk_string_height(_getGCFont(), buffer);
return new Point(width, height);
}
/**
* Returns the extent of the given string. Tab expansion and
* carriage return processing are performed.
* <p>
* The <em>extent</em> of a string is the width and height of
* the rectangular area it would cover if drawn in a particular
* font (in this case, the current font in the receiver).
* </p>
*
* @param string the string to measure
* @return a point containing the extent of the string
*
* @exception IllegalArgumentException <ul>
* <li>ERROR_NULL_ARGUMENT - if the string is null</li>
* </ul>
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*/
public Point textExtent(String string) {
if (string == null) error(SWT.ERROR_NULL_ARGUMENT);
byte[] buffer = Converter.wcsToMbcs(null, string, true);
int width = OS.gdk_string_width(_getGCFont(), buffer);
int height = OS.gdk_string_height(_getGCFont(), buffer);
return new Point(width, height);
}
/*
* === Access - Internal utils ===
*/
private GdkGCValues _getGCValues() {
GdkGCValues values = new GdkGCValues();
OS.gdk_gc_get_values(handle, values);
return values;
}
private GdkColor _getForegroundGdkColor() {
GdkGCValues values = _getGCValues();
GdkColor color = new GdkColor();
color.pixel = values.foreground_pixel;
color.red = values.foreground_red;
color.green = values.foreground_green;
color.blue = values.foreground_blue;
return color;
}
private GdkColor _getBackgroundGdkColor() {
GdkGCValues values = _getGCValues();
GdkColor color = new GdkColor();
color.pixel = values.background_pixel;
color.red = values.background_red;
color.green = values.background_green;
color.blue = values.background_blue;
return color;
}
private int _getGCFont() {
GdkGCValues values = _getGCValues();
if (values.font==0) {
SWT.error(SWT.ERROR_UNSPECIFIED);
}
return values.font;
}
/**
* 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 <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*/
/*
* === Drawing operations proper ===
*/
/**
* Copies a rectangular area of the receiver at the specified
* position into the image, which must be of type <code>SWT.BITMAP</code>.
*
* @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 <ul>
* <li>ERROR_NULL_ARGUMENT - if the image is null</li>
* <li>ERROR_INVALID_ARGUMENT - if the image is not a bitmap or has been disposed</li>
* </ul>
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*/
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);
Rectangle rect = image.getBounds();
int xGC = OS.gdk_gc_new(image.pixmap);
if (xGC == 0) SWT.error(SWT.ERROR_NO_HANDLES);
// is it possible/necessary to set the subwindow mode??
OS.gdk_window_copy_area (image.pixmap, // dest window
xGC,
0, 0, // dest coords
image.pixmap, // src window
x, y, // src coords
rect.width, rect.height);
OS.gdk_gc_destroy(xGC);
}
/**
* 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 <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*/
public void copyArea(int srcX, int srcY, int width, int height, int destX, int destY) {
OS.gdk_window_copy_area (data.drawable, handle,
destX, destY,
data.drawable,
srcX, srcY, width, height);
}
/**
* Draws the outline of a circular or elliptical arc
* within the specified rectangular area.
* <p>
* The resulting arc begins at <code>startAngle</code> and extends
* for <code>arcAngle</code> 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.
* </p><p>
* The center of the arc is the center of the rectangle whose origin
* is (<code>x</code>, <code>y</code>) and whose size is specified by the
* <code>width</code> and <code>height</code> arguments.
* </p><p>
* The resulting arc covers an area <code>width + 1</code> pixels wide
* by <code>height + 1</code> pixels tall.
* </p>
*
* @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 IllegalArgumentException <ul>
* <li>ERROR_INVALID_ARGUMENT - if any of the width, height or endAngle is zero.</li>
* </ul>
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*/
public void drawArc(int x, int y, int width, int height, int startAngle, int endAngle) {
if (width < 0) {
x = x + width;
width = -width;
}
if (height < 0) {
y = y + height;
height = -height;
}
if (width == 0 || height == 0 || endAngle == 0) {
error(SWT.ERROR_INVALID_ARGUMENT);
}
OS.gdk_draw_arc(data.drawable, handle, 0, x, y, width, height, startAngle * 64, endAngle * 64);
}
/**
* Draws a rectangle, based on the specified arguments, which has
* the appearance of the platform's <em>focus rectangle</em> if the
* platform supports such a notion, and otherwise draws a simple
* rectangle in the receiver's forground 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 <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*
* @see #drawRectangle
*/
public void drawFocus(int x, int y, int width, int height) {
GtkStyle style = new GtkStyle();
int hStyle = OS.gtk_widget_get_default_style();
OS.memmove(style, hStyle, GtkStyle.sizeof);
GdkColor color = new GdkColor();
color.pixel = style.fg0_pixel;
color.red = style.fg0_red;
color.green = style.fg0_green;
color.blue = style.fg0_blue;
GdkGCValues values = new GdkGCValues();
OS.gdk_gc_get_values(handle, values);
OS.gdk_gc_set_foreground(handle, color);
OS.gdk_draw_rectangle(data.drawable, handle, 0, x, y, width, height);
color.pixel = values.foreground_pixel;
color.red = values.foreground_red;
color.green = values.foreground_green;
color.blue = values.foreground_blue;
OS.gdk_gc_set_foreground(handle, color);
}
/**
* 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 <ul>
* <li>ERROR_NULL_ARGUMENT - if the image is null</li>
* <li>ERROR_INVALID_ARGUMENT - if the image has been disposed</li>
* <li>ERROR_INVALID_ARGUMENT - if the given coordinates are outside the bounds of the image</li>
* @exception SWTError <ul>
* <li>ERROR_NO_HANDLES - if no handles are available to perform the operation</li>
* </ul>
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*/
public void drawImage(Image image, int x, int y) {
if (image == null) error(SWT.ERROR_NULL_ARGUMENT);
int pixmap = image.pixmap;
int [] unused = new int [1]; int [] width = new int [1]; int [] height = new int [1];
OS.gdk_window_get_geometry(pixmap, unused, unused, width, height, unused);
drawImage(image, 0, 0, width[0], height[0], x, y, width[0], height[0]);
}
/**
* Copies a rectangular area from the source image into a (potentially
* different sized) rectangular area in the receiver. If the source
* and destination areas are of differing sizes, then the source
* area will be stretched or shrunk to fit the destination area
* as it is copied. The copy fails if any of the given coordinates
* are negative or lie outside the bounds of their respective images.
*
* @param image the source image
* @param srcX the x coordinate in the source image to copy from
* @param srcY the y coordinate in the source image to copy from
* @param srcWidth the width in pixels to copy from the source
* @param srcHeight the height in pixels to copy from the source
* @param destX the x coordinate in the destination to copy to
* @param destY the y coordinate in the destination to copy to
* @param destWidth the width in pixels of the destination rectangle
* @param destHeight the height in pixels of the destination rectangle
*
* @exception IllegalArgumentException <ul>
* <li>ERROR_NULL_ARGUMENT - if the image is null</li>
* <li>ERROR_INVALID_ARGUMENT - if the image has been disposed</li>
* <li>ERROR_INVALID_ARGUMENT - if the given coordinates are outside the bounds of their respective images</li>
* </ul>
* @exception SWTError <ul>
* <li>ERROR_NO_HANDLES - if no handles are available to perform the operation</li>
* </ul>
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*/
public void drawImage(Image srcImage, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight) {
/* basic sanity checks */
if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
if (srcWidth == 0 || srcHeight == 0 || destWidth == 0 || destHeight == 0) return;
if (srcX < 0 || srcY < 0 || srcWidth < 0 || srcHeight < 0 || destWidth < 0 || destHeight < 0) {
SWT.error (SWT.ERROR_INVALID_ARGUMENT);
}
if (srcImage == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
if (srcImage.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
/* source image properties */
int[] width = new int[1];
int[] height = new int[1];
int[] unused = new int[1];
OS.gdk_window_get_geometry(srcImage.pixmap, unused, unused, width, height, unused);
if ((srcY + srcWidth > width[0]) ||
(srcY + srcHeight > height[0])) {
error(SWT.ERROR_INVALID_ARGUMENT);
}
/* Special case: If we don't need to scale, and there is no alpha/mask,
* then we can just blit the image inside the X server - no net traffic
*/
boolean needScaling = (srcWidth != destWidth) || (srcHeight != destHeight);
boolean simple = !needScaling & (srcImage.mask == 0);
if (simple) {
OS.gdk_draw_pixmap(data.drawable, handle, srcImage.pixmap,
srcX, srcY,
destX, destY,
width[0], height[0]);
return;
}
/* Fetch a local GdkPixbuf from server */
Pixbuffer pixbuf = new Pixbuffer(srcImage);
/* Scale if necessary */
if ((srcWidth != destWidth) || (srcHeight != destHeight)) {
double scale_x = (double)destWidth / (double)srcWidth;
double scale_y = (double)destHeight / (double)srcHeight;
double offset_x = - srcX * scale_x;
double offset_y = - srcY * scale_y;
int destSizePixbuf = GDKPIXBUF.gdk_pixbuf_new (
GDKPIXBUF.GDK_COLORSPACE_RGB,
true, 8, destWidth, destHeight);
GDKPIXBUF.gdk_pixbuf_scale(
pixbuf.handle, // src,
destSizePixbuf,
0,
0,
destWidth, destHeight,
offset_x, offset_y,
scale_x, scale_y,
GDKPIXBUF.GDK_INTERP_BILINEAR);
pixbuf.handle = destSizePixbuf;
}
/* Paint it */
GDKPIXBUF.gdk_pixbuf_render_to_drawable_alpha(
pixbuf.handle,
data.drawable,
0, 0,
destX, destY,
destWidth, destHeight,
GDKPIXBUF.GDK_PIXBUF_ALPHA_BILEVEL, 128,
GDKPIXBUF.GDK_RGB_DITHER_NORMAL,
0, 0
);
}
/**
* Draws a line, using the foreground color, between the points
* (<code>x1</code>, <code>y1</code>) and (<code>x2</code>, <code>y2</code>).
*
* @param x1 the first point's x coordinate
* @param y1 the first point's y coordinate
* @param x2 the second point's x coordinate
* @param y2 the second point's y coordinate
*
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*/
public void drawLine(int x1, int y1, int x2, int y2) {
OS.gdk_draw_line (data.drawable, handle, x1, y1, x2, y2);
}
/**
* Draws the outline of an oval, using the foreground color,
* within the specified rectangular area.
* <p>
* The result is a circle or ellipse that fits within the
* rectangle specified by the <code>x</code>, <code>y</code>,
* <code>width</code>, and <code>height</code> arguments.
* </p><p>
* The oval covers an area that is <code>width + 1</code>
* pixels wide and <code>height + 1</code> pixels tall.
* </p>
*
* @param x the x coordinate of the upper left corner of the oval to be drawn
* @param y the y coordinate of the upper left corner of the oval to be drawn
* @param width the width of the oval to be drawn
* @param height the height of the oval to be drawn
*
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*/
public void drawOval(int x, int y, int width, int height) {
if (width < 0) {
x = x + width;
width = -width;
}
if (height < 0) {
y = y + height;
height = -height;
}
OS.gdk_draw_arc(data.drawable, handle, 0, x, y, width, height, 0, 23040);
}
/**
* Draws the closed polygon which is defined by the specified array
* of integer coordinates, using the receiver's foreground color. The array
* contains alternating x and y values which are considered to represent
* points which are the vertices of the polygon. Lines are drawn between
* each consecutive pair, and between the first pair and last pair in the
* array.
*
* @param pointArray an array of alternating x and y values which are the vertices of the polygon
*
* @exception IllegalArgumentException <ul>
* <li>ERROR_NULL_ARGUMENT if pointArray is null</li>
* </ul>
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*/
public void drawPolygon(int[] pointArray) {
if (pointArray == null) error(SWT.ERROR_NULL_ARGUMENT);
short[] points = new short[pointArray.length];
for (int i = 0; i < pointArray.length; i++) {
points[i] = (short)pointArray[i];
}
OS.gdk_draw_polygon(data.drawable, handle, 0, points, points.length / 2);
}
/**
* Draws the polyline which is defined by the specified array
* of integer coordinates, using the receiver's foreground color. The array
* contains alternating x and y values which are considered to represent
* points which are the corners of the polyline. Lines are drawn between
* each consecutive pair, but not between the first pair and last pair in
* the array.
*
* @param pointArray an array of alternating x and y values which are the corners of the polyline
*
* @exception IllegalArgumentException <ul>
* <li>ERROR_NULL_ARGUMENT - if the point array is null</li>
* </ul>
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*/
public void drawPolyline(int[] pointArray) {
if (pointArray == null) error(SWT.ERROR_NULL_ARGUMENT);
short[] points = new short[pointArray.length];
for (int i = 0; i < pointArray.length; i++) {
points[i] = (short)pointArray[i];
}
OS.gdk_draw_lines(data.drawable, handle, points, points.length / 2);
}
/**
* Draws the outline of the rectangle specified by the arguments,
* using the receiver's foreground color. The left and right edges
* of the rectangle are at <code>x</code> and <code>x + width</code>.
* The top and bottom edges are at <code>y</code> and <code>y + height</code>.
*
* @param x the x coordinate of the rectangle to be drawn
* @param y the y coordinate of the rectangle to be drawn
* @param width the width of the rectangle to be drawn
* @param height the height of the rectangle to be drawn
*
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*/
public void drawRectangle(int x, int y, int width, int height) {
if (width < 0) {
x = x + width;
width = -width;
}
if (height < 0) {
y = y + height;
height = -height;
}
OS.gdk_draw_rectangle(data.drawable, handle, 0, x, y, width, height);
}
/**
* Draws the outline of the specified rectangle, using the receiver's
* foreground color. The left and right edges of the rectangle are at
* <code>rect.x</code> and <code>rect.x + rect.width</code>. The top
* and bottom edges are at <code>rect.y</code> and
* <code>rect.y + rect.height</code>.
*
* @param rect the rectangle to draw
*
* @exception IllegalArgumentException <ul>
* <li>ERROR_NULL_ARGUMENT - if the rectangle is null</li>
* </ul>
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*/
public void drawRectangle(Rectangle rect) {
if (rect == null) error(SWT.ERROR_NULL_ARGUMENT);
drawRectangle (rect.x, rect.y, rect.width, rect.height);
}
/**
* Draws the outline of the round-cornered rectangle specified by
* the arguments, using the receiver's foreground color. The left and
* right edges of the rectangle are at <code>x</code> and <code>x + width</code>.
* The top and bottom edges are at <code>y</code> and <code>y + height</code>.
* The <em>roundness</em> of the corners is specified by the
* <code>arcWidth</code> and <code>arcHeight</code> arguments.
*
* @param x the x coordinate of the rectangle to be drawn
* @param y the y coordinate of the rectangle to be drawn
* @param width the width of the rectangle to be drawn
* @param height the height of the rectangle to be drawn
* @param arcWidth the horizontal diameter of the arc at the four corners
* @param arcHeight the vertical diameter of the arc at the four corners
*
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*/
public void drawRoundRectangle(int x, int y, int width, int height, int arcWidth, int arcHeight) {
int nx = x;
int ny = y;
int nw = width;
int nh = height;
int naw = arcWidth;
int nah = arcHeight;
if (nw < 0) {
nw = 0 - nw;
nx = nx - nw;
}
if (nh < 0) {
nh = 0 - nh;
ny = ny -nh;
}
if (naw < 0) naw = 0 - naw;
if (nah < 0) nah = 0 - nah;
int naw2 = Compatibility.floor(naw, 2);
int nah2 = Compatibility.floor(nah, 2);
OS.gdk_draw_arc(data.drawable, handle, 0, nx, ny, naw, nah, 5760, 5760);
OS.gdk_draw_arc(data.drawable, handle, 0, nx, ny + nh - nah, naw, nah, 11520, 5760);
OS.gdk_draw_arc(data.drawable, handle, 0, nx + nw - naw, ny + nh - nah, naw, nah, 17280, 5760);
OS.gdk_draw_arc(data.drawable, handle, 0, nx + nw - naw, ny, naw, nah, 0, 5760);
OS.gdk_draw_line(data.drawable, handle, nx + naw2, ny, nx + nw - naw2, ny);
OS.gdk_draw_line(data.drawable, handle, nx,ny + nah2, nx, ny + nh - nah2);
OS.gdk_draw_line(data.drawable, handle, nx + naw2, ny + nh, nx + nw - naw2, ny + nh);
OS.gdk_draw_line(data.drawable, handle, nx + nw, ny + nah2, nx + nw, ny + nh - nah2);
}
/**
* Draws the given string, using the receiver's current font and
* foreground color. No tab expansion or carriage return processing
* will be performed. The background of the rectangular area where
* the string is being drawn will be filled with the receiver's
* background color.
*
* @param string the string to be drawn
* @param x the x coordinate of the top left corner of the rectangular area where the string is to be drawn
* @param y the y coordinate of the top left corner of the rectangular area where the string is to be drawn
*
* @exception IllegalArgumentException <ul>
* <li>ERROR_NULL_ARGUMENT - if the string is null</li>
* </ul>
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*/
public void drawString (String string, int x, int y) {
drawString(string, x, y, false);
}
/**
* Draws the given string, using the receiver's current font and
* foreground color. No tab expansion or carriage return processing
* will be performed. If <code>isTransparent</code> is <code>true</code>,
* then the background of the rectangular area where the string is being
* drawn will not be modified, otherwise it will be filled with the
* receiver's background color.
*
* @param string the string to be drawn
* @param x the x coordinate of the top left corner of the rectangular area where the string is to be drawn
* @param y the y coordinate of the top left corner of the rectangular area where the string is to be drawn
* @param isTransparent if <code>true</code> the background will be transparent, otherwise it will be opaque
*
* @exception IllegalArgumentException <ul>
* <li>ERROR_NULL_ARGUMENT - if the string is null</li>
* </ul>
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*/
public void drawString(String string, int x, int y, boolean isTransparent) {
if (string == null) error(SWT.ERROR_NULL_ARGUMENT);
byte[] buffer = Converter.wcsToMbcs(null, string, true);
byte[] buffer1 = Converter.wcsToMbcs(null, "Y", true);
int[] unused = new int[1];
int[] width = new int[1];
int[] ascent = new int[1];
int[] average_ascent = new int [1];
int fontHandle = _getGCFont();
OS.gdk_string_extents(fontHandle, buffer, unused, unused, width, ascent, unused);
OS.gdk_string_extents(fontHandle, buffer1, unused, unused, unused, average_ascent, unused);
if (ascent[0]<average_ascent[0]) ascent[0] = average_ascent[0];
if (!isTransparent) {
int height = OS.gdk_string_height(fontHandle, buffer);
GdkGCValues values = new GdkGCValues();
OS.gdk_gc_get_values(handle, values);
GdkColor color = new GdkColor();
color.pixel = values.background_pixel;
color.red = values.background_red;
color.green = values.background_green;
color.blue = values.background_blue;
OS.gdk_gc_set_foreground(handle, color);
OS.gdk_draw_rectangle(data.drawable, handle, 1, x, y, width[0], height);
color.pixel = values.foreground_pixel;
color.red = values.foreground_red;
color.green = values.foreground_green;
color.blue = values.foreground_blue;
OS.gdk_gc_set_foreground(handle, color);
}
OS.gdk_draw_string(data.drawable, fontHandle, handle, x, y + ascent[0], buffer);
}
/**
* Draws the given string, using the receiver's current font and
* foreground color. Tab expansion and carriage return processing
* are performed. The background of the rectangular area where
* the text is being drawn will be filled with the receiver's
* background color.
*
* @param string the string to be drawn
* @param x the x coordinate of the top left corner of the rectangular area where the text is to be drawn
* @param y the y coordinate of the top left corner of the rectangular area where the text is to be drawn
*
* @exception IllegalArgumentException <ul>
* <li>ERROR_NULL_ARGUMENT - if the string is null</li>
* </ul>
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*/
public void drawText(String string, int x, int y) {
drawText(string, x, y, false);
}
/**
* Draws the given string, using the receiver's current font and
* foreground color. Tab expansion and carriage return processing
* are performed. If <code>isTransparent</code> is <code>true</code>,
* then the background of the rectangular area where the text is being
* drawn will not be modified, otherwise it will be filled with the
* receiver's background color.
*
* @param string the string to be drawn
* @param x the x coordinate of the top left corner of the rectangular area where the text is to be drawn
* @param y the y coordinate of the top left corner of the rectangular area where the text is to be drawn
* @param isTransparent if <code>true</code> the background will be transparent, otherwise it will be opaque
*
* @exception IllegalArgumentException <ul>
* <li>ERROR_NULL_ARGUMENT - if the string is null</li>
* </ul>
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*/
public void drawText(String string, int x, int y, boolean isTransparent) {
if (string == null) error(SWT.ERROR_NULL_ARGUMENT);
byte[] buffer = Converter.wcsToMbcs(null, string, true);
byte[] buffer1 = Converter.wcsToMbcs(null, "Y", true);
int fontHandle = _getGCFont();
int[] unused = new int[1];
int[] width = new int[1];
int[] ascent = new int[1];
int[] average_ascent = new int [1];
OS.gdk_string_extents(fontHandle, buffer, unused, unused, width, ascent, unused);
OS.gdk_string_extents(fontHandle, buffer1, unused, unused, unused, average_ascent, unused);
if (ascent[0]<average_ascent[0]) ascent[0] = average_ascent[0];
if (!isTransparent) {
int height = OS.gdk_string_height(fontHandle, buffer);
GdkGCValues values = new GdkGCValues();
OS.gdk_gc_get_values(handle, values);
GdkColor color = new GdkColor();
color.pixel = values.background_pixel;
color.red = values.background_red;
color.green = values.background_green;
color.blue = values.background_blue;
OS.gdk_gc_set_foreground(handle, color);
OS.gdk_draw_rectangle(data.drawable, handle, 1, x, y, width[0], height);
color.pixel = values.foreground_pixel;
color.red = values.foreground_red;
color.green = values.foreground_green;
color.blue = values.foreground_blue;
OS.gdk_gc_set_foreground(handle, color);
}
OS.gdk_draw_string(data.drawable, fontHandle, handle, x, y + ascent[0], buffer);
}
/**
* Draws the given string, using the receiver's current font and
* foreground color. Tab expansion, line delimiter and mnemonic
* processing are performed according to the specified flags. If
* <code>flags</code> includes <code>DRAW_TRANSPARENT</code>,
* then the background of the rectangular area where the text is being
* drawn will not be modified, otherwise it will be filled with the
* receiver's background color.
* <p>
* The parameter <code>flags</code> may be a combination of:
* <dl>
* <dt><b>DRAW_DELIMITER</b></dt>
* <dd>draw multiple lines</dd>
* <dt><b>DRAW_TAB</b></dt>
* <dd>expand tabs</dd>
* <dt><b>DRAW_MNEMONIC</b></dt>
* <dd>underline the mnemonic character</dd>
* <dt><b>DRAW_TRANSPARENT</b></dt>
* <dd>transparent background</dd>
* </dl>
* </p>
*
* @param string the string to be drawn
* @param x the x coordinate of the top left corner of the rectangular area where the text is to be drawn
* @param y the y coordinate of the top left corner of the rectangular area where the text is to be drawn
* @param flags the flags specifing how to process the text
*
* @exception IllegalArgumentException <ul>
* <li>ERROR_NULL_ARGUMENT - if the string is null</li>
* </ul>
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*/
public void drawText (String string, int x, int y, int flags) {
// NOT IMPLEMENTED
drawText(string, x, y, (flags & SWT.DRAW_TRANSPARENT) != 0);
}
/**
* Fills the interior of a circular or elliptical arc within
* the specified rectangular area, with the receiver's background
* color.
* <p>
* The resulting arc begins at <code>startAngle</code> and extends
* for <code>arcAngle</code> 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.
* </p><p>
* The center of the arc is the center of the rectangle whose origin
* is (<code>x</code>, <code>y</code>) and whose size is specified by the
* <code>width</code> and <code>height</code> arguments.
* </p><p>
* The resulting arc covers an area <code>width + 1</code> pixels wide
* by <code>height + 1</code> pixels tall.
* </p>
*
* @param x the x coordinate of the upper-left corner of the arc to be filled
* @param y the y coordinate of the upper-left corner of the arc to be filled
* @param width the width of the arc to be filled
* @param height the height of the arc to be filled
* @param startAngle the beginning angle
* @param arcAngle the angular extent of the arc, relative to the start angle
*
* @exception IllegalArgumentException <ul>
* <li>ERROR_INVALID_ARGUMENT - if any of the width, height or endAngle is zero.</li>
* </ul>
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*
* @see #drawArc
*/
public void fillArc(int x, int y, int width, int height, int startAngle, int endAngle) {
if (width < 0) {
x = x + width;
width = -width;
}
if (height < 0) {
y = y + height;
height = -height;
}
if (width == 0 || height == 0 || endAngle == 0) {
error(SWT.ERROR_INVALID_ARGUMENT);
}
GdkGCValues values = new GdkGCValues();
OS.gdk_gc_get_values(handle, values);
GdkColor color = new GdkColor();
color.pixel = values.background_pixel;
color.red = values.background_red;
color.green = values.background_green;
color.blue = values.background_blue;
OS.gdk_gc_set_foreground(handle, color);
OS.gdk_draw_arc(data.drawable, handle, 1, x, y, width, height, startAngle * 64, endAngle * 64);
color.pixel = values.foreground_pixel;
color.red = values.foreground_red;
color.green = values.foreground_green;
color.blue = values.foreground_blue;
OS.gdk_gc_set_foreground(handle, color);
}
/**
* Fills the interior of the specified rectangle with a gradient
* sweeping from left to right or top to bottom progressing
* from the receiver's foreground color to its background color.
*
* @param x the x coordinate of the rectangle to be filled
* @param y the y coordinate of the rectangle to be filled
* @param width the width of the rectangle to be filled, may be negative
* (inverts direction of gradient if horizontal)
* @param height the height of the rectangle to be filled, may be negative
* (inverts direction of gradient if vertical)
* @param vertical if true sweeps from top to bottom, else
* sweeps from left to right
*
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*
* @see #drawRectangle
*/
public void fillGradientRectangle(int x, int y, int width, int height, boolean vertical) {
if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
if ((width == 0) || (height == 0)) return;
GdkGCValues values = new GdkGCValues();
OS.gdk_gc_get_values(handle, values);
GdkColor foregroundGdkColor = new GdkColor();
RGB backgroundRGB, foregroundRGB;
backgroundRGB = Color.gtk_getRGBIntensities(_getBackgroundGdkColor());
foregroundRGB = Color.gtk_getRGBIntensities(_getForegroundGdkColor());
RGB fromRGB, toRGB;
fromRGB = foregroundRGB;
toRGB = backgroundRGB;
boolean swapColors = false;
if (width < 0) {
x += width; width = -width;
if (! vertical) swapColors = true;
}
if (height < 0) {
y += height; height = -height;
if (vertical) swapColors = true;
}
if (swapColors) {
fromRGB = backgroundRGB;
toRGB = foregroundRGB;
}
if (fromRGB == toRGB) {
fillRectangle(x, y, width, height);
return;
}
ImageData.fillGradientRectangle(this, Display.getCurrent(),
x, y, width, height, vertical, fromRGB, toRGB,
8, 8, 8);
}
/**
* Fills the interior of an oval, within the specified
* rectangular area, with the receiver's background
* color.
*
* @param x the x coordinate of the upper left corner of the oval to be filled
* @param y the y coordinate of the upper left corner of the oval to be filled
* @param width the width of the oval to be filled
* @param height the height of the oval to be filled
*
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*
* @see #drawOval
*/
public void fillOval(int x, int y, int width, int height) {
if (width < 0) {
x = x + width;
width = -width;
}
if (height < 0) {
y = y + height;
height = -height;
}
GdkGCValues values = new GdkGCValues();
OS.gdk_gc_get_values(handle, values);
GdkColor color = new GdkColor();
color.pixel = values.background_pixel;
color.red = values.background_red;
color.green = values.background_green;
color.blue = values.background_blue;
OS.gdk_gc_set_foreground(handle, color);
OS.gdk_draw_arc(data.drawable, handle, 1, x, y, width, height, 0, 23040);
color.pixel = values.foreground_pixel;
color.red = values.foreground_red;
color.green = values.foreground_green;
color.blue = values.foreground_blue;
OS.gdk_gc_set_foreground(handle, color);
}
/**
* Fills the interior of the closed polygon which is defined by the
* specified array of integer coordinates, using the receiver's
* background color. The array contains alternating x and y values
* which are considered to represent points which are the vertices of
* the polygon. Lines are drawn between each consecutive pair, and
* between the first pair and last pair in the array.
*
* @param pointArray an array of alternating x and y values which are the vertices of the polygon
*
* @exception IllegalArgumentException <ul>
* <li>ERROR_NULL_ARGUMENT if pointArray is null</li>
* </ul>
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*
* @see #drawPolygon
*/
public void fillPolygon(int[] pointArray) {
if (pointArray == null) error(SWT.ERROR_NULL_ARGUMENT);
short[] points = new short[pointArray.length];
for (int i = 0; i < pointArray.length; i++) {
points[i] = (short)pointArray[i];
}
GdkGCValues values = new GdkGCValues();
OS.gdk_gc_get_values(handle, values);
GdkColor color = new GdkColor();
color.pixel = values.background_pixel;
color.red = values.background_red;
color.green = values.background_green;
color.blue = values.background_blue;
OS.gdk_gc_set_foreground(handle, color);
OS.gdk_draw_polygon(data.drawable, handle, 1, points, points.length / 2);
color.pixel = values.foreground_pixel;
color.red = values.foreground_red;
color.green = values.foreground_green;
color.blue = values.foreground_blue;
OS.gdk_gc_set_foreground(handle, color);
}
/**
* Fills the interior of the rectangle specified by the arguments,
* using the receiver's background color.
*
* @param x the x coordinate of the rectangle to be filled
* @param y the y coordinate of the rectangle to be filled
* @param width the width of the rectangle to be filled
* @param height the height of the rectangle to be filled
*
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*
* @see #drawRectangle
*/
public void fillRectangle(int x, int y, int width, int height) {
if (width < 0) {
x = x + width;
width = -width;
}
if (height < 0) {
y = y + height;
height = -height;
}
GdkGCValues values = new GdkGCValues();
OS.gdk_gc_get_values(handle, values);
GdkColor color = new GdkColor();
color.pixel = values.background_pixel;
color.red = values.background_red;
color.green = values.background_green;
color.blue = values.background_blue;
OS.gdk_gc_set_foreground(handle, color);
OS.gdk_draw_rectangle(data.drawable, handle, 1, x, y, width, height);
color.pixel = values.foreground_pixel;
color.red = values.foreground_red;
color.green = values.foreground_green;
color.blue = values.foreground_blue;
OS.gdk_gc_set_foreground(handle, color);
}
/**
* Fills the interior of the specified rectangle, using the receiver's
* background color.
*
* @param rectangle the rectangle to be filled
*
* @exception IllegalArgumentException <ul>
* <li>ERROR_NULL_ARGUMENT - if the rectangle is null</li>
* </ul>
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*
* @see #drawRectangle
*/
public void fillRectangle(Rectangle rect) {
if (rect == null) error(SWT.ERROR_NULL_ARGUMENT);
fillRectangle(rect.x, rect.y, rect.width, rect.height);
}
/**
* Fills the interior of the round-cornered rectangle specified by
* the arguments, using the receiver's background color.
*
* @param x the x coordinate of the rectangle to be filled
* @param y the y coordinate of the rectangle to be filled
* @param width the width of the rectangle to be filled
* @param height the height of the rectangle to be filled
* @param arcWidth the horizontal diameter of the arc at the four corners
* @param arcHeight the vertical diameter of the arc at the four corners
*
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*
* @see #drawRoundRectangle
*/
public void fillRoundRectangle(int x, int y, int width, int height, int arcWidth, int arcHeight) {
int nx = x;
int ny = y;
int nw = width;
int nh = height;
int naw = arcWidth;
int nah = arcHeight;
if (nw < 0) {
nw = 0 - nw;
nx = nx - nw;
}
if (nh < 0) {
nh = 0 - nh;
ny = ny -nh;
}
if (naw < 0)
naw = 0 - naw;
if (nah < 0)
nah = 0 - nah;
naw = Math.min(naw,nw);
nah = Math.min(nah, nh);
int naw2 = Compatibility.round(naw, 2);
int nah2 = Compatibility.round(nah, 2);
GdkGCValues values = new GdkGCValues();
OS.gdk_gc_get_values(handle, values);
GdkColor color = new GdkColor();
color.pixel = values.background_pixel;
color.red = values.background_red;
color.green = values.background_green;
color.blue = values.background_blue;
OS.gdk_gc_set_foreground(handle, color);
OS.gdk_draw_arc(data.drawable, handle, 1, nx, ny, naw, nah, 5760, 5760);
OS.gdk_draw_arc(data.drawable, handle, 1, nx, ny + nh - nah, naw, nah, 11520, 5760);
OS.gdk_draw_arc(data.drawable, handle, 1, nx + nw - naw, ny + nh - nah, naw, nah, 17280, 5760);
OS.gdk_draw_arc(data.drawable, handle, 1, nx + nw - naw, ny, naw, nah, 0, 5760);
OS.gdk_draw_rectangle(data.drawable, handle, 1, nx + naw2, ny, nw - naw, nh);
OS.gdk_draw_rectangle(data.drawable, handle, 1, nx, ny + nah2, naw2, nh - nah);
OS.gdk_draw_rectangle(data.drawable, handle, 1, nx + nw - (naw / 2), ny + nah2, naw2, nh -nah);
color.pixel = values.foreground_pixel;
color.red = values.foreground_red;
color.green = values.foreground_green;
color.blue = values.foreground_blue;
OS.gdk_gc_set_foreground(handle, color);
}
/**
* Compares the argument to the receiver, and returns true
* if they represent the <em>same</em> object using a class
* specific comparison.
*
* @param object the object to compare with this object
* @return <code>true</code> if the object is the same as this object and <code>false</code> otherwise
*
* @see #hashCode
*/
/*
* === As yet unclassified ===
*/
public boolean equals(Object object) {
return (object == this) || ((object instanceof GC) && (handle == ((GC)object).handle));
}
/**
* Returns an integer hash code for the receiver. Any two
* objects which return <code>true</code> when passed to
* <code>equals</code> must return the same value for this
* method.
*
* @return the receiver's hash
*
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*
* @see #equals
*/
public int hashCode() {
return handle;
}
void error(int code) {
throw new SWTError(code);
}
/**
* Returns <code>true</code> if the GC has been disposed,
* and <code>false</code> otherwise.
* <p>
* This method gets the dispose state for the GC.
* When a GC has been disposed, it is an error to
* invoke any other method using the GC.
*
* @return <code>true</code> when the GC is disposed and <code>false</code> otherwise
*/
public boolean isDisposed() {
return handle == 0;
}
/**
* Disposes of the operating system resources associated with
* the graphics context. Applications must dispose of all GCs
* which they allocate.
*/
public void dispose() {
if (handle == 0) return;
/* Free resources */
int clipRgn = data.clipRgn;
if (clipRgn != 0) OS.gdk_region_destroy(clipRgn);
Image image = data.image;
if (image != null) image.memGC = null;
/* Dispose the GC */
if(drawable == null)
OS.gdk_gc_unref(handle);
else
drawable.internal_dispose_GC(handle, data);
data.drawable = // data.colormap = data.fontList =
data.clipRgn = data.renderTable = 0;
drawable = null;
data.image = null;
data = null;
handle = 0;
}
/**
* Returns a string containing a concise, human-readable
* description of the receiver.
*
* @return a string representation of the receiver
*/
public String toString () {
if (isDisposed()) return "GC {*DISPOSED*}";
return "GC {" + handle + "}";
}
/**
* Returns the extent of the given string. Tab expansion, line
* delimiter and mnemonic processing are performed according to
* the specified flags, which can be a combination of:
* <dl>
* <dt><b>DRAW_DELIMITER</b></dt>
* <dd>draw multiple lines</dd>
* <dt><b>DRAW_TAB</b></dt>
* <dd>expand tabs</dd>
* <dt><b>DRAW_MNEMONIC</b></dt>
* <dd>underline the mnemonic character</dd>
* <dt><b>DRAW_TRANSPARENT</b></dt>
* <dd>transparent background</dd>
* </dl>
* <p>
* The <em>extent</em> of a string is the width and height of
* the rectangular area it would cover if drawn in a particular
* font (in this case, the current font in the receiver).
* </p>
*
* @param string the string to measure
* @param flags the flags specifing how to process the text
* @return a point containing the extent of the string
*
* @exception IllegalArgumentException <ul>
* <li>ERROR_NULL_ARGUMENT - if the string is null</li>
* </ul>
* @exception SWTException <ul>
* <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
* </ul>
*/
public Point textExtent(String string, int flags) {
//NOT IMPLEMENTED
return textExtent(string);
}
}