Mercurial > projects > dwt-addons
view dwtx/draw2d/SWTGraphics.d @ 200:eb3414669eb0 default tip
fix for dmd 1.041 and tango 0.99.8
author | Frank Benoit <benoit@tionex.de> |
---|---|
date | Sat, 28 Mar 2009 03:09:57 +0100 |
parents | d994a8b2cdf7 |
children |
line wrap: on
line source
/******************************************************************************* * Copyright (c) 2000, 2007 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Port to the D programming language: * Frank Benoit <benoit@tionex.de> *******************************************************************************/ module dwtx.draw2d.SWTGraphics; import dwt.dwthelper.utils; import dwtx.dwtxhelper.Collection; static import dwt.graphics.Rectangle; import dwt.DWT; import dwt.graphics.Color; import dwt.graphics.Font; import dwt.graphics.FontMetrics; import dwt.graphics.GC; import dwt.graphics.Image; import dwt.graphics.Path; import dwt.graphics.Pattern; import dwt.graphics.TextLayout; import dwt.graphics.Transform; import dwt.widgets.Display; import dwtx.draw2d.geometry.PointList; import dwtx.draw2d.geometry.Rectangle; import dwtx.draw2d.Graphics; /** * A concrete implementation of <code>Graphics</code> using an DWT * <code>GC</code>. There are 2 states contained in this graphics class -- the * applied state which is the actual state of the GC and the current state which * is the current state of this graphics object. Certain properties can be * changed multiple times and the GC won't be updated until it's actually used. * <P> * WARNING: This class is not intended to be subclassed. */ public class SWTGraphics : Graphics { /** * An internal type used to represent and update the GC's clipping. * @since 3.1 */ interface Clipping { /** * Sets the clip's bounding rectangle into the provided argument and returns it for convenince. * @param rect the rect * @return the given rect * @since 3.1 */ Rectangle getBoundingBox(Rectangle rect); Clipping getCopy(); void intersect(int left, int top, int right, int bottom); void scale(float horizontal, float vertical); void setOn(GC gc, int translateX, int translateY); void translate(float dx, float dy); } /** * Any state stored in this class is only applied when it is needed by a * specific graphics call. * @since 3.1 */ static class LazyState { Color bgColor; Color fgColor; Font font; int graphicHints; int lineWidth; Clipping relativeClip; this(){ } this(LazyState other){ bgColor = other.bgColor; fgColor = other.fgColor; font = other.font; graphicHints = other.graphicHints; lineWidth = other.lineWidth; relativeClip = other.relativeClip; } } static class RectangleClipping : Clipping { private float top, left, bottom, right; this(float left, float top, float right, float bottom) { this.left = left; this.right = right; this.bottom = bottom; this.top = top; } this(dwt.graphics.Rectangle.Rectangle rect) { left = rect.x; top = rect.y; right = rect.x + rect.width; bottom = rect.y + rect.height; } this(Rectangle rect) { left = rect.x; top = rect.y; right = rect.right(); bottom = rect.bottom(); } public Rectangle getBoundingBox(Rectangle rect) { rect.x = cast(int)left; rect.y = cast(int)top; rect.width = cast(int)Math.ceil(right) - rect.x; rect.height = cast(int)Math.ceil(bottom) - rect.y; return rect; } public Clipping getCopy() { return new RectangleClipping(left, top, right, bottom); } public void intersect(int left, int top, int right, int bottom) { this.left = Math.max(this.left, left); this.right = Math.min(this.right, right); this.top = Math.max(this.top, top); this.bottom = Math.min(this.bottom, bottom); if (right < left || bottom < top) { //width and height of -1 to avoid ceiling function from re-adding a pixel. this.right = left - 1; this.bottom = top - 1; } } public void scale(float horz, float vert) { left /= horz; right /= horz; top /= vert; bottom /= vert; } public void setOn(GC gc, int translateX, int translateY) { int xInt = cast(int)Math.floor(left); int yInt = cast(int)Math.floor(top); gc.setClipping(xInt + translateX, yInt + translateY, cast(int)Math.ceil(right) - xInt, cast(int)Math.ceil(bottom) - yInt); } public void translate(float dx, float dy) { left += dx; right += dx; top += dy; bottom += dy; } } /** * Contains the entire state of the Graphics. */ static class State : LazyState , Cloneable { float affineMatrix[]; int alpha; Pattern bgPattern; int dx, dy; Pattern fgPattern; int lineDash[]; this(){ } this(State other){ super(other); affineMatrix = other.affineMatrix.dup; alpha = other.alpha; bgPattern = other.bgPattern; dx = other.dx; dy = other.dy; fgPattern = other.fgPattern; lineDash = other.lineDash.dup; } public Object clone() { return new State(this); } /** * Copies all state information from the given State to this State * @param state The State to copy from */ public void copyFrom(State state) { bgColor = state.bgColor; fgColor = state.fgColor; lineWidth = state.lineWidth; dx = state.dx; dy = state.dy; bgPattern = state.bgPattern; fgPattern = state.fgPattern; font = state.font; lineDash = state.lineDash; graphicHints = state.graphicHints; affineMatrix = state.affineMatrix; relativeClip = state.relativeClip; alpha = state.alpha; } } static const int AA_MASK = 3 << AA_SHIFT; static const int AA_SHIFT = 8; static const int AA_WHOLE_NUMBER = 1; static const int ADVANCED_GRAPHICS_MASK = 1 << ADVANCED_SHIFT; static const int ADVANCED_HINTS_DEFAULTS = ((DWT.DEFAULT + AA_WHOLE_NUMBER) << TEXT_AA_SHIFT) | ((DWT.DEFAULT + AA_WHOLE_NUMBER) << AA_SHIFT) | ((DWT.DEFAULT + INTERPOLATION_WHOLE_NUMBER) << INTERPOLATION_SHIFT); static const int ADVANCED_HINTS_MASK = TEXT_AA_MASK | AA_MASK | INTERPOLATION_MASK; static const int ADVANCED_SHIFT = 15; static const int CAP_MASK = 3 << CAP_SHIFT; static const int CAP_SHIFT = 4; static const int FILL_RULE_MASK = 1 << FILL_RULE_SHIFT; static const int FILL_RULE_SHIFT = 14; static const int FILL_RULE_WHOLE_NUMBER = -1; static const int INTERPOLATION_MASK = 3 << INTERPOLATION_SHIFT; static const int INTERPOLATION_SHIFT = 12; static const int INTERPOLATION_WHOLE_NUMBER = 1; static const int JOIN_MASK = 3 << JOIN_SHIFT; static const int JOIN_SHIFT = 6; static const int LINE_STYLE_MASK = 7; static const int TEXT_AA_MASK = 3 << TEXT_AA_SHIFT; static const int TEXT_AA_SHIFT = 10; static const int XOR_MASK = 1 << XOR_SHIFT; static const int XOR_SHIFT = 3; private const LazyState appliedState; private const State currentState; private bool elementsNeedUpdate; private GC gc; private bool sharedClipping; private List stack; private int stackPointer = 0; Transform transform; private int translateX = 0; private int translateY = 0; /** * Constructs a new SWTGraphics that draws to the Canvas using the given GC. * @param gc the GC */ public this(GC gc) { appliedState = new LazyState(); currentState = new State(); stack = new ArrayList(); this.gc = gc; init(); } /** * If the background color has changed, this change will be pushed to the GC. Also calls * {@link #checkGC()}. */ protected final void checkFill() { if (!currentState.bgColor.opEquals(appliedState.bgColor) && currentState.bgPattern is null) gc.setBackground(appliedState.bgColor = currentState.bgColor); checkGC(); } /** * If the rendering hints or the clip region has changed, these changes will be pushed to * the GC. Rendering hints include anti-alias, xor, join, cap, line style, fill rule, * interpolation, and other settings. */ protected /+final+/ void checkGC() { if (appliedState.relativeClip !is currentState.relativeClip) { appliedState.relativeClip = currentState.relativeClip; currentState.relativeClip.setOn(gc, translateX, translateY); } if (appliedState.graphicHints !is currentState.graphicHints) { reconcileHints(appliedState.graphicHints, currentState.graphicHints); appliedState.graphicHints = currentState.graphicHints; } } /** * If the line width, line style, foreground or background colors have changed, these * changes will be pushed to the GC. Also calls {@link #checkGC()}. */ protected /+final+/ void checkPaint() { checkGC(); if (!currentState.fgColor.opEquals(appliedState.fgColor) && currentState.fgPattern is null) gc.setForeground(appliedState.fgColor = currentState.fgColor); if (appliedState.lineWidth !is currentState.lineWidth) gc.setLineWidth(appliedState.lineWidth = currentState.lineWidth); if (!currentState.bgColor.opEquals(appliedState.bgColor) && currentState.bgPattern is null) gc.setBackground(appliedState.bgColor = currentState.bgColor); } /** * @since 3.1 */ private void checkSharedClipping() { if (sharedClipping) { sharedClipping = false; bool previouslyApplied = (appliedState is cast(Object)currentState.relativeClip); currentState.relativeClip = currentState.relativeClip.getCopy(); if (previouslyApplied) appliedState.relativeClip = currentState.relativeClip; } } /** * If the font has changed, this change will be pushed to the GC. Also calls * {@link #checkPaint()} and {@link #checkFill()}. */ protected /+final+/ void checkText() { checkPaint(); if (!appliedState.font.opEquals(currentState.font)) gc.setFont(appliedState.font = currentState.font); } /** * @see Graphics#clipRect(Rectangle) */ public void clipRect(Rectangle rect) { if (currentState.relativeClip is null) throw new IllegalStateException("The current clipping area does not " //$NON-NLS-1$ "support intersection."); //$NON-NLS-1$ checkSharedClipping(); currentState.relativeClip.intersect(rect.x, rect.y, rect.right(), rect.bottom()); appliedState.relativeClip = null; } /** * @see Graphics#dispose() */ public void dispose() { while (stackPointer > 0) popState(); if (transform !is null) transform.dispose(); } /** * @see Graphics#drawArc(int, int, int, int, int, int) */ public void drawArc(int x, int y, int width, int height, int offset, int length) { checkPaint(); gc.drawArc(x + translateX, y + translateY, width, height, offset, length); } /** * @see Graphics#drawFocus(int, int, int, int) */ public void drawFocus(int x, int y, int w, int h) { checkPaint(); gc.drawFocus(x + translateX, y + translateY, w + 1, h + 1); } /** * @see Graphics#drawImage(Image, int, int) */ public void drawImage(Image srcImage, int x, int y) { checkGC(); gc.drawImage(srcImage, x + translateX, y + translateY); } /** * @see Graphics#drawImage(Image, int, int, int, int, int, int, int, int) */ public void drawImage(Image srcImage, int x1, int y1, int w1, int h1, int x2, int y2, int w2, int h2) { checkGC(); gc.drawImage(srcImage, x1, y1, w1, h1, x2 + translateX, y2 + translateY, w2, h2); } /** * @see Graphics#drawLine(int, int, int, int) */ public void drawLine(int x1, int y1, int x2, int y2) { checkPaint(); gc.drawLine(x1 + translateX, y1 + translateY, x2 + translateX, y2 + translateY); } /** * @see Graphics#drawOval(int, int, int, int) */ public void drawOval(int x, int y, int width, int height) { checkPaint(); gc.drawOval(x + translateX, y + translateY, width, height); } /** * This method requires advanced graphics support. A check should be made to * ensure advanced graphics is supported in the user's environment before * calling this method. See {@link GC#getAdvanced()}. * * @see Graphics#drawPath(Path) */ public void drawPath(Path path) { checkPaint(); initTransform(false); gc.drawPath(path); } /** * @see Graphics#drawPoint(int, int) */ public void drawPoint(int x, int y) { checkPaint(); gc.drawPoint(x + translateX, y + translateY); } /** * @see Graphics#drawPolygon(int[]) */ public void drawPolygon(int[] points) { checkPaint(); try { translatePointArray(points, translateX, translateY); gc.drawPolygon(points); } finally { translatePointArray(points, -translateX, -translateY); } } /** * @see Graphics#drawPolygon(PointList) */ public void drawPolygon(PointList points) { drawPolygon(points.toIntArray()); } /** * @see Graphics#drawPolyline(int[]) */ public void drawPolyline(int[] points) { checkPaint(); try { translatePointArray(points, translateX, translateY); gc.drawPolyline(points); } finally { translatePointArray(points, -translateX, -translateY); } } /** * @see Graphics#drawPolyline(PointList) */ public void drawPolyline(PointList points) { drawPolyline(points.toIntArray()); } /** * @see Graphics#drawRectangle(int, int, int, int) */ public void drawRectangle(int x, int y, int width, int height) { checkPaint(); gc.drawRectangle(x + translateX, y + translateY, width, height); } /** * @see Graphics#drawRoundRectangle(Rectangle, int, int) */ public void drawRoundRectangle(Rectangle r, int arcWidth, int arcHeight) { checkPaint(); gc.drawRoundRectangle(r.x + translateX, r.y + translateY, r.width, r.height, arcWidth, arcHeight); } /** * @see Graphics#drawString(String, int, int) */ public void drawString(String s, int x, int y) { checkText(); gc.drawString(s, x + translateX, y + translateY, true); } /** * @see Graphics#drawText(String, int, int) */ public void drawText(String s, int x, int y) { checkText(); gc.drawText(s, x + translateX, y + translateY, true); } /** * @see Graphics#drawTextLayout(TextLayout, int, int, int, int, Color, Color) */ public void drawTextLayout(TextLayout layout, int x, int y, int selectionStart, int selectionEnd, Color selectionForeground, Color selectionBackground) { //$TODO probably just call checkPaint since Font and BG color don't apply checkText(); layout.draw(gc, x + translateX, y + translateY, selectionStart, selectionEnd, selectionForeground, selectionBackground); } /** * @see Graphics#fillArc(int, int, int, int, int, int) */ public void fillArc(int x, int y, int width, int height, int offset, int length) { checkFill(); gc.fillArc(x + translateX, y + translateY, width, height, offset, length); } /** * @see Graphics#fillGradient(int, int, int, int, bool) */ public void fillGradient(int x, int y, int w, int h, bool vertical) { checkPaint(); gc.fillGradientRectangle(x + translateX, y + translateY, w, h, vertical); } /** * @see Graphics#fillOval(int, int, int, int) */ public void fillOval(int x, int y, int width, int height) { checkFill(); gc.fillOval(x + translateX, y + translateY, width, height); } /** * This method requires advanced graphics support. A check should be made to * ensure advanced graphics is supported in the user's environment before * calling this method. See {@link GC#getAdvanced()}. * * @see Graphics#fillPath(Path) */ public void fillPath(Path path) { checkFill(); initTransform(false); gc.fillPath(path); } /** * @see Graphics#fillPolygon(int[]) */ public void fillPolygon(int[] points) { checkFill(); try { translatePointArray(points, translateX, translateY); gc.fillPolygon(points); } finally { translatePointArray(points, -translateX, -translateY); } } /** * @see Graphics#fillPolygon(PointList) */ public void fillPolygon(PointList points) { fillPolygon(points.toIntArray()); } /** * @see Graphics#fillRectangle(int, int, int, int) */ public void fillRectangle(int x, int y, int width, int height) { checkFill(); gc.fillRectangle(x + translateX, y + translateY, width, height); } /** * @see Graphics#fillRoundRectangle(Rectangle, int, int) */ public void fillRoundRectangle(Rectangle r, int arcWidth, int arcHeight) { checkFill(); gc.fillRoundRectangle(r.x + translateX, r.y + translateY, r.width, r.height, arcWidth, arcHeight); } /** * @see Graphics#fillString(String, int, int) */ public void fillString(String s, int x, int y) { checkText(); gc.drawString(s, x + translateX, y + translateY, false); } /** * @see Graphics#fillText(String, int, int) */ public void fillText(String s, int x, int y) { checkText(); gc.drawText(s, x + translateX, y + translateY, false); } /** * @see Graphics#getAlpha() */ public int getAlpha() { return currentState.alpha; } /** * @see Graphics#getAntialias() */ public int getAntialias() { return ((currentState.graphicHints & AA_MASK) >> AA_SHIFT) - AA_WHOLE_NUMBER; } /** * @see Graphics#getBackgroundColor() */ public Color getBackgroundColor() { return currentState.bgColor; } /** * @see Graphics#getClip(Rectangle) */ public Rectangle getClip(Rectangle rect) { if (currentState.relativeClip !is null) { currentState.relativeClip.getBoundingBox(rect); return rect; } throw new IllegalStateException( "Clipping can no longer be queried due to transformations"); //$NON-NLS-1$ } /** * @see Graphics#getFillRule() */ public int getFillRule() { return ((currentState.graphicHints & FILL_RULE_MASK) >> FILL_RULE_SHIFT) - FILL_RULE_WHOLE_NUMBER; } /** * @see Graphics#getFont() */ public Font getFont() { return currentState.font; } /** * @see Graphics#getFontMetrics() */ public FontMetrics getFontMetrics() { checkText(); return gc.getFontMetrics(); } /** * @see Graphics#getForegroundColor() */ public Color getForegroundColor() { return currentState.fgColor; } /** * @see Graphics#getInterpolation() */ public int getInterpolation() { return ((currentState.graphicHints & INTERPOLATION_MASK) >> INTERPOLATION_SHIFT) - INTERPOLATION_WHOLE_NUMBER; } /** * @see Graphics#getLineCap() */ public int getLineCap() { return (currentState.graphicHints & CAP_MASK) >> CAP_SHIFT; } /** * @see Graphics#getLineJoin() */ public int getLineJoin() { return (currentState.graphicHints & JOIN_MASK) >> JOIN_SHIFT; } /** * @see Graphics#getLineStyle() */ public int getLineStyle() { return currentState.graphicHints & LINE_STYLE_MASK; } /** * @see Graphics#getLineWidth() */ public int getLineWidth() { return currentState.lineWidth; } /** * @see Graphics#getTextAntialias() */ public int getTextAntialias() { return ((currentState.graphicHints & TEXT_AA_MASK) >> TEXT_AA_SHIFT) - AA_WHOLE_NUMBER; } /** * @see Graphics#getXORMode() */ public bool getXORMode() { return (currentState.graphicHints & XOR_MASK) !is 0; } /** * Called by constructor, initializes all State information for currentState */ protected void init() { currentState.bgColor = appliedState.bgColor = gc.getBackground(); currentState.fgColor = appliedState.fgColor = gc.getForeground(); currentState.font = appliedState.font = gc.getFont(); currentState.lineWidth = appliedState.lineWidth = gc.getLineWidth(); currentState.graphicHints |= gc.getLineStyle(); currentState.graphicHints |= gc.getLineCap() << CAP_SHIFT; currentState.graphicHints |= gc.getLineJoin() << JOIN_SHIFT; currentState.graphicHints |= gc.getAdvanced() ? ADVANCED_GRAPHICS_MASK : 0; currentState.graphicHints |= gc.getXORMode() ? XOR_MASK : 0; appliedState.graphicHints = currentState.graphicHints; currentState.relativeClip = new RectangleClipping(gc.getClipping()); currentState.lineDash = gc.getLineDash(); currentState.alpha = gc.getAlpha(); } private void initTransform(bool force) { if (!force && translateX is 0 && translateY is 0) return; if (transform is null) { transform = new Transform(Display.getCurrent()); elementsNeedUpdate = true; transform.translate(translateX, translateY); translateX = 0; translateY = 0; gc.setTransform(transform); currentState.graphicHints |= ADVANCED_GRAPHICS_MASK; } } /** * @see Graphics#popState() */ public void popState() { stackPointer--; restoreState(cast(State)stack.get(stackPointer)); } /** * @see Graphics#pushState() */ public void pushState() { if (currentState.relativeClip is null) throw new IllegalStateException("The clipping has been modified in" //$NON-NLS-1$ "a way that cannot be saved and restored."); //$NON-NLS-1$ // try { State s; currentState.dx = translateX; currentState.dy = translateY; if (elementsNeedUpdate) { elementsNeedUpdate = false; transform.getElements(currentState.affineMatrix = new float[6]); } if (stack.size() > stackPointer) { s = cast(State)stack.get(stackPointer); s.copyFrom(currentState); } else { stack.add(currentState.clone()); } sharedClipping = true; stackPointer++; // } catch (CloneNotSupportedException e) { // throw new RuntimeException(e); // } } private void reconcileHints(int applied, int hints) { if (applied !is hints) { int changes = hints ^ applied; if ((changes & LINE_STYLE_MASK) !is 0) gc.setLineStyle(hints & LINE_STYLE_MASK); if ((changes & XOR_MASK) !is 0) gc.setXORMode((hints & XOR_MASK) !is 0); //Check to see if there is anything remaining changes &= ~(XOR_MASK | LINE_STYLE_MASK); if (changes is 0) return; if ((changes & JOIN_MASK) !is 0) gc.setLineJoin((hints & JOIN_MASK) >> JOIN_SHIFT); if ((changes & CAP_MASK) !is 0) gc.setLineCap((hints & CAP_MASK) >> CAP_SHIFT); if ((changes & INTERPOLATION_MASK) !is 0) gc.setInterpolation(((hints & INTERPOLATION_MASK) >> INTERPOLATION_SHIFT) - INTERPOLATION_WHOLE_NUMBER); if ((changes & FILL_RULE_MASK) !is 0) gc.setFillRule(((hints & FILL_RULE_MASK) >> FILL_RULE_SHIFT) - FILL_RULE_WHOLE_NUMBER); if ((changes & AA_MASK) !is 0) gc.setAntialias(((hints & AA_MASK) >> AA_SHIFT) - AA_WHOLE_NUMBER); if ((changes & TEXT_AA_MASK) !is 0) gc.setTextAntialias(((hints & TEXT_AA_MASK) >> TEXT_AA_SHIFT) - AA_WHOLE_NUMBER); // If advanced was flagged, but none of the conditions which trigger advanced // actually got applied, force advanced graphics on. if ((changes & ADVANCED_GRAPHICS_MASK) !is 0) { if ((hints & ADVANCED_GRAPHICS_MASK) !is 0 && !gc.getAdvanced()) gc.setAdvanced(true); } } } /** * @see Graphics#restoreState() */ public void restoreState() { restoreState(cast(State)stack.get(stackPointer - 1)); } /** * Sets all State information to that of the given State, called by restoreState() * @param s the State */ protected void restoreState(State s) { /* * We must set the transformation matrix first since it affects things like clipping * regions and patterns. */ setAffineMatrix(s.affineMatrix); currentState.relativeClip = s.relativeClip; sharedClipping = true; //If the GC is currently advanced, but it was not when pushed, revert if (gc.getAdvanced() && (s.graphicHints & ADVANCED_GRAPHICS_MASK) is 0) { //Set applied clip to null to force a re-setting of the clipping. appliedState.relativeClip = null; gc.setAdvanced(false); appliedState.graphicHints &= ~ADVANCED_HINTS_MASK; appliedState.graphicHints |= ADVANCED_HINTS_DEFAULTS; } setBackgroundColor(s.bgColor); setBackgroundPattern(s.bgPattern); setForegroundColor(s.fgColor); setForegroundPattern(s.fgPattern); setAlpha(s.alpha); setLineWidth(s.lineWidth); setFont(s.font); //This method must come last because above methods will incorrectly set advanced state setGraphicHints(s.graphicHints); translateX = currentState.dx = s.dx; translateY = currentState.dy = s.dy; } /** * This method requires advanced graphics support. A check should be made to * ensure advanced graphics is supported in the user's environment before * calling this method. See {@link GC#getAdvanced()}. * * @see Graphics#rotate(float) */ public void rotate(float degrees) { //Flush clipping, patter, etc., before applying transform checkGC(); initTransform(true); transform.rotate(degrees); gc.setTransform(transform); elementsNeedUpdate = true; //Can no longer operate or maintain clipping appliedState.relativeClip = currentState.relativeClip = null; } /** * @see Graphics#scale(double) */ public void scale(double factor) { scale(cast(float)factor, cast(float)factor); } /** * This method requires advanced graphics support. A check should be made to * ensure advanced graphics is supported in the user's environment before * calling this method. See {@link GC#getAdvanced()}. * * @see dwtx.draw2d.Graphics#scale(float, float) */ public void scale(float horizontal, float vertical) { //Flush any clipping before scaling checkGC(); initTransform(true); transform.scale(horizontal, vertical); gc.setTransform(transform); elementsNeedUpdate = true; checkSharedClipping(); if (currentState.relativeClip !is null) currentState.relativeClip.scale(horizontal, vertical); } private void setAffineMatrix(float[] m) { if (!elementsNeedUpdate && currentState.affineMatrix is m) return; currentState.affineMatrix = m; if (m !is null) transform.setElements(m[0], m[1], m[2], m[3], m[4], m[5]); else if (transform !is null) { transform.dispose(); transform = null; elementsNeedUpdate = false; } gc.setTransform(transform); } /** * This method requires advanced graphics support. A check should be made to * ensure advanced graphics is supported in the user's environment before * calling this method. See {@link GC#getAdvanced()}. * * @see Graphics#setAlpha(int) */ public void setAlpha(int alpha) { currentState.graphicHints |= ADVANCED_GRAPHICS_MASK; if (currentState.alpha !is alpha) gc.setAlpha(this.currentState.alpha = alpha); } /** * This method requires advanced graphics support. A check should be made to * ensure advanced graphics is supported in the user's environment before * calling this method. See {@link GC#getAdvanced()}. * * @see Graphics#setAntialias(int) */ public void setAntialias(int value) { currentState.graphicHints &= ~AA_MASK; currentState.graphicHints |= ADVANCED_GRAPHICS_MASK | (value + AA_WHOLE_NUMBER) << AA_SHIFT; } /** * @see Graphics#setBackgroundColor(Color) */ public void setBackgroundColor(Color color) { currentState.bgColor = color; if (currentState.bgPattern !is null) { currentState.bgPattern = null; //Force the BG color to be stale appliedState.bgColor = null; } } /** * @see Graphics#setBackgroundPattern(Pattern) */ public void setBackgroundPattern(Pattern pattern) { currentState.graphicHints |= ADVANCED_GRAPHICS_MASK; if (currentState.bgPattern is pattern) return; currentState.bgPattern = pattern; if (pattern !is null) initTransform(true); gc.setBackgroundPattern(pattern); } /** * This method requires advanced graphics support. A check should be made to * ensure advanced graphics is supported in the user's environment before * calling this method. See {@link GC#getAdvanced()}. * * @see Graphics#setClip(Path) */ public void setClip(Path path) { initTransform(false); gc.setClipping(path); appliedState.relativeClip = currentState.relativeClip = null; } /** * @see Graphics#setClip(Rectangle) */ public void setClip(Rectangle rect) { currentState.relativeClip = new RectangleClipping(rect); } /** * @see Graphics#setFillRule(int) */ public void setFillRule(int rule) { currentState.graphicHints &= ~FILL_RULE_MASK; currentState.graphicHints |= (rule + FILL_RULE_WHOLE_NUMBER) << FILL_RULE_SHIFT; } /** * @see Graphics#setFont(Font) */ public void setFont(Font f) { currentState.font = f; } /** * @see Graphics#setForegroundColor(Color) */ public void setForegroundColor(Color color) { currentState.fgColor = color; if (currentState.fgPattern !is null) { currentState.fgPattern = null; //Force fgColor to be stale appliedState.fgColor = null; } } /** * @see Graphics#setForegroundPattern(Pattern) */ public void setForegroundPattern(Pattern pattern) { currentState.graphicHints |= ADVANCED_GRAPHICS_MASK; if (currentState.fgPattern is pattern) return; currentState.fgPattern = pattern; if (pattern !is null) initTransform(true); gc.setForegroundPattern(pattern); } private void setGraphicHints(int hints) { currentState.graphicHints = hints; } /** * This method requires advanced graphics support. A check should be made to * ensure advanced graphics is supported in the user's environment before * calling this method. See {@link GC#getAdvanced()}. * * @see Graphics#setInterpolation(int) */ public void setInterpolation(int interpolation) { //values range [-1, 3] currentState.graphicHints &= ~INTERPOLATION_MASK; currentState.graphicHints |= ADVANCED_GRAPHICS_MASK | (interpolation + INTERPOLATION_WHOLE_NUMBER) << INTERPOLATION_SHIFT; } /** * @see Graphics#setLineCap(int) */ public void setLineCap(int cap) { currentState.graphicHints &= ~CAP_MASK; currentState.graphicHints |= cap << CAP_SHIFT; } /** * @see Graphics#setLineDash(int[]) */ public void setLineDash(int[] dashes) { if (dashes !is null) { int copy[] = new int[dashes.length]; for (int i = 0; i < dashes.length; i++) { int dash = dashes[i]; if (dash <= 0) DWT.error(DWT.ERROR_INVALID_ARGUMENT); copy[i] = dash; } currentState.lineDash = copy; setLineStyle(DWT.LINE_CUSTOM); gc.setLineDash(copy); } else { currentState.lineDash = null; setLineStyle(DWT.LINE_SOLID); } } /** * @see Graphics#setLineJoin(int) */ public void setLineJoin(int join) { currentState.graphicHints &= ~JOIN_MASK; currentState.graphicHints |= join << JOIN_SHIFT; } /** * @see Graphics#setLineStyle(int) */ public void setLineStyle(int style) { currentState.graphicHints &= ~LINE_STYLE_MASK; currentState.graphicHints |= style; } /** * @see Graphics#setLineWidth(int) */ public void setLineWidth(int width) { currentState.lineWidth = width; } /** * This method requires advanced graphics support. A check should be made to * ensure advanced graphics is supported in the user's environment before * calling this method. See {@link GC#getAdvanced()}. * * @see Graphics#setTextAntialias(int) */ public void setTextAntialias(int value) { currentState.graphicHints &= ~TEXT_AA_MASK; currentState.graphicHints |= ADVANCED_GRAPHICS_MASK | (value + AA_WHOLE_NUMBER) << TEXT_AA_SHIFT; } /** * @see Graphics#setXORMode(bool) */ public void setXORMode(bool xor) { currentState.graphicHints &= ~XOR_MASK; if (xor) currentState.graphicHints |= XOR_MASK; } /** * This method requires advanced graphics support. A check should be made to * ensure advanced graphics is supported in the user's environment before * calling this method. See {@link GC#getAdvanced()}. * * @see Graphics#shear(float, float) */ public void shear(float horz, float vert) { //Flush any clipping changes before shearing checkGC(); initTransform(true); float matrix[] = new float[6]; transform.getElements(matrix); transform.setElements( matrix[0] + matrix[2] * vert, matrix[1] + matrix[3] * vert, matrix[0] * horz + matrix[2], matrix[1] * horz + matrix[3], matrix[4], matrix[5]); gc.setTransform(transform); elementsNeedUpdate = true; //Can no longer track clipping changes appliedState.relativeClip = currentState.relativeClip = null; } /** * This method may require advanced graphics support if using a transform, * in this case, a check should be made to ensure advanced graphics is * supported in the user's environment before calling this method. See * {@link GC#getAdvanced()}. * * @see Graphics#translate(int, int) */ public void translate(int dx, int dy) { if (dx is 0 && dy is 0) return; if (transform !is null) { //Flush clipping, pattern, etc. before applying transform checkGC(); transform.translate(dx, dy); elementsNeedUpdate = true; gc.setTransform(transform); } else { translateX += dx; translateY += dy; } checkSharedClipping(); if (currentState.relativeClip !is null) currentState.relativeClip.translate(-dx, -dy); } /** * This method requires advanced graphics support. A check should be made to * ensure advanced graphics is supported in the user's environment before * calling this method. See {@link GC#getAdvanced()}. * * @see Graphics#translate(float, float) */ public void translate(float dx, float dy) { initTransform(true); checkGC(); transform.translate(dx, dy); elementsNeedUpdate = true; gc.setTransform(transform); checkSharedClipping(); if (currentState.relativeClip !is null) currentState.relativeClip.translate(-dx, -dy); } private void translatePointArray(int[] points, int translateX, int translateY) { if (translateX is 0 && translateY is 0) return; for (int i = 0; (i + 1) < points.length; i += 2) { points[i] += translateX; points[i + 1] += translateY; } } }