001: /*
002: * @(#)QtGraphics.java 1.32 06/10/10
003: *
004: * Copyright 1990-2006 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: *
026: */
027: package sun.awt.qt;
028:
029: /**
030: * QtGraphics.java
031: *
032: * @author Indrayana Rustandi
033: * @author Nicholas Allen
034: */
035:
036: import java.awt.*;
037: import java.io.*;
038: import java.util.*;
039: import java.awt.image.ImageObserver;
040: import java.awt.image.BufferedImage;
041: import sun.awt.image.ImageRepresentation;
042: import sun.awt.ConstrainableGraphics;
043: import java.text.AttributedCharacterIterator;
044: import java.awt.font.TextAttribute;
045:
046: /**
047: * QtGraphics is an object that encapsulates a graphics context for a
048: * particular drawing area using the Qt library.
049: */
050:
051: class QtGraphics extends Graphics2D implements ConstrainableGraphics,
052: Cloneable {
053: private static native void initIDs();
054:
055: private native void setLinePropertiesNative(int lineWidth,
056: int capStyle, int joinStyle);
057:
058: static {
059: initIDs();
060: }
061:
062: private boolean disposed = false;
063:
064: int data;
065:
066: /** The peer that created this graphics. This is needed by
067: clearRect which needs to clear the background with the
068: background color of the heavyweight component that created
069: it. */
070:
071: QtComponentPeer peer;
072:
073: private static final Font defaultFont = new Font("Dialog",
074: Font.PLAIN, 12);
075: Color foreground;
076: Font font;
077: int originX;
078: int originY;
079:
080: private AlphaComposite composite;
081:
082: /** GTK+ does not support alpha. So alpha is approximated.
083: * The approximation is: if alpha is 0.0 then the colour is transparent,
084: * else the colour is opaque. This flag indicates whether the extra alpha in
085: * the AlphaComposite is not 0.0. The source colour alpha is premultiplied by the
086: * extra alpha, hence an extra alpha of 0.0 will create transparent pixels.
087: */
088: private static final int DRAW_NONE = 0x00;
089: private static final int DRAW_PRIMATIVE = 0x01;
090: private static final int DRAW_BITMAP = 0x02;
091: private static final int DRAW_NORMAL = DRAW_PRIMATIVE | DRAW_BITMAP;
092: private static final int DRAW_CLEAR = 0x04 | DRAW_PRIMATIVE;
093:
094: private int drawType = DRAW_NORMAL;
095:
096: /** The current user clip rectangle or null if no clip has been
097: set. This is stored in the native coordinate system and not
098: the possibly translated Java coordinate system. */
099:
100: private Rectangle clip;
101:
102: /** The rectangle this graphics object has been constrained
103: too. This is stored in the native coordinate system and not
104: the (possibly) translated Java coordinate system. If it is
105: null then this graphics has not been constrained. The
106: constrained rectangle is another layer of clipping independant
107: of the user clip. The actual clip used is the intersection */
108:
109: private Rectangle constrainedRect;
110:
111: // WIDELINE //
112: private BasicStroke stroke = new BasicStroke();
113:
114: public Stroke getStroke() {
115: return stroke;
116: }
117:
118: public void setStroke(Stroke s) {
119: if (s == null) {
120: throw new IllegalArgumentException("null stroke");
121: }
122:
123: if (s instanceof BasicStroke) {
124: this .stroke = (BasicStroke) s;
125:
126: setLinePropertiesNative((int) Math.round(stroke
127: .getLineWidth()), stroke.getEndCap(), stroke
128: .getLineJoin());
129: } else {
130: // 6189934: Throwing IAE as per the spec instead of
131: // UnsupportedOperationException
132: throw new IllegalArgumentException(s.getClass().getName());
133: // 6189934
134: }
135: }
136:
137: /** The GraphicsConfiguration that this graphics uses. */
138: private GraphicsConfiguration graphicsConfiguration;
139:
140: private static native QtGraphics createFromComponentNative(
141: QtComponentPeer peer);
142:
143: static QtGraphics createFromComponent(QtComponentPeer peer) {
144: QtGraphics g = createFromComponentNative(peer);
145:
146: if (g != null) {
147: g.setFont(peer.target.getFont());
148: //g.setColor(peer.target.getForeground());
149: }
150: if (g instanceof QtGraphics)
151: g.setupApproximatedAlpha();
152: return g;
153: }
154:
155: private native void createFromGraphics(QtGraphics g);
156:
157: private native void createFromImage(ImageRepresentation imageRep);
158:
159: private native void setForegroundNative(Color c);
160:
161: sun.awt.image.Image image;
162:
163: private QtGraphics(QtComponentPeer peer) {
164: this .peer = peer;
165: composite = AlphaComposite.SrcOver;
166: //drawType = DRAW_NORMAL;
167: foreground = peer.target.getForeground();
168: if (foreground == null)
169: foreground = SystemColor.windowText;
170: GraphicsEnvironment ge = GraphicsEnvironment
171: .getLocalGraphicsEnvironment();
172: graphicsConfiguration = ge.getDefaultScreenDevice()
173: .getDefaultConfiguration();
174: }
175:
176: /*
177: * Fixed 6178102.
178: * Commented out the following code, because we now use clone()
179: * from create(). Note the constrainedRect was not copied, the
180: * major cause of the bug.
181:
182: private QtGraphics(QtGraphics g) {
183: createFromGraphics(g);
184: graphicsConfiguration = g.graphicsConfiguration;
185: peer = g.peer;
186: originX = g.originX;
187: originY = g.originY;
188: clip = g.clip;
189: image = g.image;
190: composite = g.composite;
191: //setColor(g.getColor());
192: foreground = g.foreground;
193: setFont(g.getFont());
194: setupApproximatedAlpha();
195: }
196: */
197:
198: public QtGraphics(QtImage image) {
199: createFromImage(image.getImageRep());
200: composite = AlphaComposite.SrcOver;
201: foreground = Color.white;
202: graphicsConfiguration = image.gc;
203: this .image = image;
204: setupApproximatedAlpha();
205: }
206:
207: /**
208: * Create a new QtGraphics Object based on this one.
209: */
210: public Graphics create() {
211: /*
212: * Fixed 6178102.
213: * Commented out the following code, because we now use clone()
214: * from create().
215: */
216: //return new QtGraphics(this);
217: return (Graphics) clone();
218: }
219:
220: /*
221: * Fixed 6178102.
222: * We now use clone() from create().
223: */
224: protected Object clone() {
225: try {
226: QtGraphics g = (QtGraphics) super .clone();
227: g.createFromGraphics(this );
228: if (this .clip != null) {
229: clip = (Rectangle) this .clip.clone();
230: }
231: if (this .constrainedRect != null) {
232: constrainedRect = (Rectangle) this .constrainedRect
233: .clone();
234: }
235: setFont(this .getFont());
236: g.setupApproximatedAlpha();
237:
238: return g;
239: } catch (CloneNotSupportedException e) {
240: }
241: return null;
242: }
243:
244: /**
245: * Translate
246: */
247: public void translate(int x, int y) {
248: originX += x;
249: originY += y;
250: }
251:
252: /*
253: * Subclasses should override disposeImpl() instead of dispose(). Client
254: * code should always invoke dispose(), never disposeImpl().
255: *
256: * An QtGraphics cannot be used after being disposed.
257: */
258: protected native void disposeImpl();
259:
260: public final void dispose() {
261: if (!disposed) {
262: disposed = true;
263: disposeImpl();
264: }
265: }
266:
267: public void finalize() {
268: dispose();
269: }
270:
271: public void setFont(Font font) {
272: if (font == null)
273: this .font = defaultFont;
274: else
275: this .font = font;
276: }
277:
278: public Font getFont() {
279: return font;
280: }
281:
282: /**
283: * Gets font metrics for the given font.
284: */
285: public FontMetrics getFontMetrics(Font font) {
286: return QtFontPeer.getFontPeer(font);
287: }
288:
289: /**
290: * Sets the graphics color.
291: */
292: public void setColor(Color c) {
293: if ((c != null) && (c != foreground)) {
294: if (c instanceof SystemColor) {
295: c = new Color(c.getRGB());
296: }
297: foreground = c;
298: setupApproximatedAlpha();
299: }
300: }
301:
302: public Color getColor() {
303: return foreground;
304: }
305:
306: public Composite getComposite() {
307: return composite;
308: }
309:
310: public void setComposite(Composite comp) {
311: if ((comp != null) && (comp != composite)) {
312: if (!(comp instanceof AlphaComposite))
313: throw new IllegalArgumentException(
314: "Only AlphaComposite is supported");
315: composite = (AlphaComposite) comp;
316: setupApproximatedAlpha();
317: }
318: }
319:
320: private void setupApproximatedAlpha() {
321: int rule = composite.getRule();
322: if (rule == AlphaComposite.CLEAR) {
323: //setForegroundNative(Color.black);
324: setForegroundNative(new Color(0, 0, 0, 0));
325: drawType = DRAW_CLEAR;
326: } else if (rule == AlphaComposite.SRC_OVER) {
327: if (composite.getAlpha() == 0)
328: drawType = DRAW_NONE;
329: else if (foreground.getAlpha() == 0)
330: drawType = DRAW_BITMAP;
331: else {
332: drawType = DRAW_NORMAL;
333: setForegroundNative(foreground);
334: }
335: } else {
336: drawType = DRAW_NORMAL;
337: //4721253
338: float[] rgbaSrc = foreground.getRGBComponents(null);
339: // compute the actual alpha of the source color using the
340: // composite's extraAlpha and source color alpha
341: float alphasource = composite.getAlpha() * rgbaSrc[3];
342:
343: // if the colormodel does not have an alpha channel, and the
344: // source has zero intensity alpha, then the source color
345: // that should be copied as part of the SRC rule is forced
346: // to black (the color channels multiplied by the alpha)
347: Color fg = this .foreground;
348: if (!this .graphicsConfiguration.getColorModel().hasAlpha()
349: && alphasource == 0.0f) {
350: fg = new Color(0.0f, 0.0f, 0.0f, 1.0f);
351: }
352: //4721253
353:
354: setForegroundNative(fg);
355: }
356: }
357:
358: public GraphicsConfiguration getDeviceConfiguration() {
359: return graphicsConfiguration;
360: }
361:
362: /**
363: * Sets the paint mode to overwrite the destination with the
364: * current color. This is the default paint mode.
365: */
366: public native void setPaintMode();
367:
368: /**
369: * Sets the paint mode to alternate between the current color
370: * and the given color.
371: */
372: public native void setXORMode(Color c1);
373:
374: /**
375: * Gets the current clipping area
376: */
377: public Rectangle getClipBounds() {
378: if (clip != null)
379: return new Rectangle(clip.x - originX, clip.y - originY,
380: clip.width, clip.height);
381:
382: return null;
383: }
384:
385: /** Returns a Shape object representing the MicroWindows clip. */
386:
387: public Shape getClip() {
388: return getClipBounds();
389: }
390:
391: public void constrain(int x, int y, int w, int h) {
392: originX += x;
393: originY += y;
394: Rectangle rect = new Rectangle(originX, originY, w, h);
395:
396: if (constrainedRect != null)
397: constrainedRect = constrainedRect.intersection(rect);
398:
399: else
400: constrainedRect = rect;
401:
402: setupClip();
403: }
404:
405: private native void setClipNative(int X, int Y, int W, int H);
406:
407: private native void removeClip();
408:
409: /** Crops the clipping rectangle for this QtGraphics context. */
410: public void clipRect(int x, int y, int w, int h) {
411: Rectangle rect = new Rectangle(x + originX, y + originY, w, h);
412:
413: if (clip != null)
414: clip = clip.intersection(rect);
415:
416: else
417: clip = rect;
418:
419: setupClip();
420: }
421:
422: /** Sets up the clip for this Graphics. The clip is the result of combining the user clip
423: with the constrainedRect. */
424:
425: private void setupClip() {
426: if (constrainedRect != null) {
427: if (clip != null) {
428: Rectangle intersection = constrainedRect
429: .intersection(clip);
430: setClipNative(intersection.x, intersection.y,
431: intersection.width, intersection.height);
432: } else {
433: setClipNative(constrainedRect.x, constrainedRect.y,
434: constrainedRect.width, constrainedRect.height);
435: }
436: } else {
437: if (clip != null) {
438: setClipNative(clip.x, clip.y, clip.width, clip.height);
439: } else {
440: removeClip();
441: }
442: }
443: }
444:
445: /** Sets the clipping rectangle for this QtGraphics context. */
446: public void setClip(int x, int y, int w, int h) {
447: clip = new Rectangle(x + originX, y + originY, w, h);
448:
449: setupClip();
450: }
451:
452: /** Sets the QtGraphics clip to a Shape (only Rectangle allowed). */
453: public void setClip(Shape clip) {
454: if (clip == null) {
455: this .clip = null;
456: setupClip();
457: } else if (clip instanceof Rectangle) {
458: Rectangle rect = (Rectangle) clip;
459:
460: setClip(rect.x, rect.y, rect.width, rect.height);
461: } else
462: throw new IllegalArgumentException(
463: "setClip(Shape) only supports Rectangle objects");
464: }
465:
466: /** Clears the rectangle indicated by x,y,w,h. */
467: public native void clearRect(int x, int y, int w, int h);
468:
469: /** Fills the given rectangle with the foreground color. */
470: public void fillRect(int X, int Y, int W, int H) {
471: if ((drawType & DRAW_PRIMATIVE) == DRAW_PRIMATIVE) {
472: drawRectNative(true, X, Y, W, H);
473: }
474: }
475:
476: /** Draws the given rectangle. */
477: public void drawRect(int X, int Y, int W, int H) {
478: if ((drawType & DRAW_PRIMATIVE) == DRAW_PRIMATIVE) {
479: drawRectNative(false, X, Y, W, H);
480: }
481: }
482:
483: private native void drawRectNative(boolean fill, int X, int Y,
484: int W, int H);
485:
486: public void drawString(AttributedCharacterIterator text, int x,
487: int y) {
488: int limit = 0, start = 0;
489: if (text != null) {
490: start = text.getBeginIndex();
491: limit = text.getEndIndex();
492: if (start == limit) {
493: throw new IllegalArgumentException(
494: "Zero length iterator passed to drawString.");
495: }
496: }
497: int len = limit - start;
498: text.first();
499: char[] chars = new char[len];
500: int n = 0;
501: for (char c = text.first(); c != text.DONE; c = text.next()) {
502: chars[n++] = c;
503: }
504: String string = new String(chars);
505: text.first();
506: Map attributes = text.getAttributes();
507: Font currentFont = null;
508: Color color = null;
509: Object obj = null;
510: if (text.getRunLimit() == limit) {
511: if ((obj = attributes.get(TextAttribute.FONT)) != null)
512: currentFont = (Font) obj;
513: else
514: currentFont = new Font(attributes);
515: if ((obj = attributes.get(TextAttribute.FOREGROUND)) != null)
516: color = (Color) obj;
517: drawAttributedStringNative(QtFontPeer
518: .getFontPeer(currentFont), string, x, y, color,
519: false);
520: } else { // have to slice and dice
521: int nextx;
522: // Fixed 5106119: TextAttribute.UNDERLINE when applied to
523: // AttributedString does not work correctly if other attributes
524: // are also applied.
525: //
526: // The derivedAttributes hashtable is used to collect strikethrough
527: // and/or underline attributes when the TextAttribute.FONT
528: // attribute has been specified. If it is not empty, it is combined
529: // with the attributes of the existing font object to derive a new
530: // font object.
531: Hashtable derivedAttributes = new Hashtable();
532:
533: while (text.getIndex() != text.getEndIndex()) {
534: attributes = text.getAttributes();
535: derivedAttributes.clear();
536:
537: if ((obj = attributes.get(TextAttribute.FONT)) != null) {
538: currentFont = (Font) obj;
539: if (TextAttribute.STRIKETHROUGH_ON
540: .equals(attributes
541: .get(TextAttribute.STRIKETHROUGH))) {
542: derivedAttributes.put(
543: TextAttribute.STRIKETHROUGH,
544: TextAttribute.STRIKETHROUGH_ON);
545: }
546: if (TextAttribute.UNDERLINE_ON.equals(attributes
547: .get(TextAttribute.UNDERLINE))) {
548: derivedAttributes.put(TextAttribute.UNDERLINE,
549: TextAttribute.UNDERLINE_ON);
550: }
551: if (!derivedAttributes.isEmpty()) {
552: derivedAttributes.putAll(currentFont
553: .getAttributes());
554: currentFont = new Font(derivedAttributes);
555: }
556: } else {
557: currentFont = new Font(attributes);
558: }
559:
560: if ((obj = attributes.get(TextAttribute.FOREGROUND)) != null)
561: color = (Color) obj;
562: else
563: color = null;
564:
565: nextx = drawAttributedStringNative(QtFontPeer
566: .getFontPeer(currentFont), string.substring(
567: text.getIndex(), text.getRunLimit()), x, y,
568: color, true);
569: x += nextx;
570: text.setIndex(text.getRunLimit());
571: }
572: }
573: }
574:
575: /** Draws the given string. */
576: public void drawString(String string, int x, int y) {
577: if ((drawType & DRAW_PRIMATIVE) == DRAW_PRIMATIVE)
578: drawStringNative(QtFontPeer.getFontPeer(font), string, x, y);
579: }
580:
581: private native int drawAttributedStringNative(QtFontPeer fontPeer,
582: String string, int x, int y, Color color, boolean returnVal);
583:
584: private native void drawStringNative(QtFontPeer fontPeer,
585: String string, int x, int y);
586:
587: /** Draws the given character array. */
588: public void drawChars(char chars[], int offset, int length, int x,
589: int y) {
590: if ((drawType & DRAW_PRIMATIVE) == DRAW_PRIMATIVE)
591: drawString(new String(chars, offset, length), x, y);
592: }
593:
594: /** Draws the given byte array. */
595: public void drawBytes(byte data[], int offset, int length, int x,
596: int y) {
597: if (drawType == DRAW_NONE)
598: return;
599:
600: /*
601: byte[] string = new byte[length];
602:
603: System.arraycopy(data, offset, string, 0, length);
604: */
605:
606: drawStringNative(QtFontPeer.getFontPeer(font),
607: new String(data), x, y);
608: }
609:
610: private native void drawLineNative(int x1, int y1, int x2, int y2);
611:
612: /** Draws the given line. */
613: public void drawLine(int x1, int y1, int x2, int y2) {
614: if ((drawType & DRAW_PRIMATIVE) == DRAW_PRIMATIVE) {
615: drawLineNative(x1, y1, x2, y2);
616: }
617: }
618:
619: /**
620: * Draws an image at x,y in nonblocking mode with a callback object.
621: */
622: public boolean drawImage(Image img, int x, int y,
623: ImageObserver observer) {
624: QtDrawableImage qtimage;
625:
626: if (img instanceof BufferedImage) {
627: qtimage = (QtDrawableImage) QtToolkit
628: .getBufferedImagePeer((BufferedImage) img);
629: }
630:
631: else if (img instanceof QtVolatileImage) {
632: qtimage = ((QtVolatileImage) img).getQtImage();
633: }
634:
635: else {
636: qtimage = (QtDrawableImage) img;
637: }
638:
639: switch (drawType) {
640: case DRAW_BITMAP:
641: case DRAW_NORMAL:
642: return qtimage.draw(this , x, y, observer);
643: case DRAW_CLEAR:
644: drawRectNative(true, x, y, qtimage.getWidth(), qtimage
645: .getHeight());
646: case DRAW_NONE:
647: default:
648: return qtimage.isComplete();
649: }
650: }
651:
652: /**
653: * Draws an image scaled to x,y,w,h in nonblocking mode with a
654: * callback object.
655: */
656: public boolean drawImage(Image img, int x, int y, int width,
657: int height, ImageObserver observer) {
658: QtDrawableImage qtimage;
659:
660: if (img instanceof BufferedImage)
661: qtimage = (QtDrawableImage) QtToolkit
662: .getBufferedImagePeer((BufferedImage) img);
663:
664: else
665: qtimage = (QtDrawableImage) img;
666:
667: switch (drawType) {
668: case DRAW_BITMAP:
669: case DRAW_NORMAL:
670: return qtimage.draw(this , x, y, width, height, observer);
671: case DRAW_CLEAR:
672: drawRectNative(true, x, y, width, height);
673: case DRAW_NONE:
674: default:
675: return qtimage.isComplete();
676: }
677: }
678:
679: /**
680: * Draws an image at x,y in nonblocking mode with a solid background
681: * color and a callback object.
682: */
683: public boolean drawImage(Image img, int x, int y, Color bg,
684: ImageObserver observer) {
685:
686: QtDrawableImage qtimage;
687:
688: if (img instanceof BufferedImage)
689: qtimage = (QtDrawableImage) QtToolkit
690: .getBufferedImagePeer((BufferedImage) img);
691:
692: else
693: qtimage = (QtDrawableImage) img;
694:
695: switch (drawType) {
696: case DRAW_BITMAP:
697: case DRAW_NORMAL:
698: return qtimage.draw(this , x, y, bg, observer);
699: case DRAW_CLEAR:
700: drawRectNative(true, x, y, qtimage.getWidth(), qtimage
701: .getHeight());
702: case DRAW_NONE:
703: default:
704: return qtimage.isComplete();
705: }
706: }
707:
708: /**
709: * Draws an image scaled to x,y,w,h in nonblocking mode with a
710: * solid background color and a callback object.
711: */
712: public boolean drawImage(Image img, int x, int y, int width,
713: int height, Color bg, ImageObserver observer) {
714:
715: QtDrawableImage qtimage;
716:
717: if (img instanceof BufferedImage)
718: qtimage = (QtDrawableImage) QtToolkit
719: .getBufferedImagePeer((BufferedImage) img);
720:
721: else
722: qtimage = (QtDrawableImage) img;
723:
724: switch (drawType) {
725: case DRAW_BITMAP:
726: case DRAW_NORMAL:
727: return qtimage
728: .draw(this , x, y, width, height, bg, observer);
729: case DRAW_CLEAR:
730: drawRectNative(true, x, y, width, height);
731: case DRAW_NONE:
732: default:
733: return qtimage.isComplete();
734: }
735: }
736:
737: /**
738: * Draws a subrectangle of an image scaled to a destination rectangle
739: * in nonblocking mode with a callback object.
740: */
741: public boolean drawImage(Image img, int dx1, int dy1, int dx2,
742: int dy2, int sx1, int sy1, int sx2, int sy2,
743: ImageObserver observer) {
744:
745: QtDrawableImage qtimage;
746:
747: if (img instanceof BufferedImage)
748: qtimage = (QtDrawableImage) QtToolkit
749: .getBufferedImagePeer((BufferedImage) img);
750:
751: else
752: qtimage = (QtDrawableImage) img;
753:
754: switch (drawType) {
755: case DRAW_BITMAP:
756: case DRAW_NORMAL:
757: return qtimage.draw(this , dx1, dy1, dx2, dy2, sx1, sy1,
758: sx2, sy2, observer);
759: case DRAW_CLEAR: {
760: int w = dx2 - dx1;
761: int h = dy2 - dy1;
762: int x = dx1, y = dy1;
763: if (w < 0) {
764: x = dx2;
765: w *= -1;
766: }
767:
768: if (h < 0) {
769: y = dy2;
770: h *= -1;
771: }
772:
773: drawRectNative(true, x, y, w, h);
774: }
775: case DRAW_NONE:
776: default:
777: return qtimage.isComplete();
778: }
779:
780: }
781:
782: /**
783: * Draws a subrectangle of an image scaled to a destination rectangle in
784: * nonblocking mode with a solid background color and a callback object.
785: */
786: public boolean drawImage(Image img, int dx1, int dy1, int dx2,
787: int dy2, int sx1, int sy1, int sx2, int sy2, Color bgcolor,
788: ImageObserver observer) {
789:
790: QtDrawableImage qtimage;
791:
792: if (img instanceof BufferedImage)
793: qtimage = (QtDrawableImage) QtToolkit
794: .getBufferedImagePeer((BufferedImage) img);
795:
796: else
797: qtimage = (QtDrawableImage) img;
798:
799: switch (drawType) {
800: case DRAW_BITMAP:
801: case DRAW_NORMAL:
802: return qtimage.draw(this , dx1, dy1, dx2, dy2, sx1, sy1,
803: sx2, sy2, bgcolor, observer);
804: case DRAW_CLEAR: {
805: int w = dx2 - dx1;
806: int h = dy2 - dy1;
807: int x = dx1, y = dy1;
808: if (w < 0) {
809: x = dx2;
810: w *= -1;
811: }
812:
813: if (h < 0) {
814: y = dy2;
815: h *= -1;
816: }
817:
818: drawRectNative(true, x, y, w, h);
819: }
820: case DRAW_NONE:
821: default:
822: return qtimage.isComplete();
823: }
824: }
825:
826: /**
827: * Copies an area of the canvas that this graphics context paints to.
828: * @param X the x-coordinate of the source.
829: * @param Y the y-coordinate of the source.
830: * @param W the width.
831: * @param H the height.
832: * @param dx the x-coordinate of the destination.
833: * @param dy the y-coordinate of the destination.
834: */
835: public native void copyArea(int X, int Y, int W, int H, int dx,
836: int dy);
837:
838: private native void drawRoundRectNative(int x, int y, int w, int h,
839: int arcWidth, int arcHeight);
840:
841: private native void fillRoundRectNative(int x, int y, int w, int h,
842: int arcWidth, int arcHeight);
843:
844: /** Draws a rounded rectangle. */
845: public void drawRoundRect(int x, int y, int w, int h, int arcWidth,
846: int arcHeight) {
847: if ((drawType & DRAW_PRIMATIVE) == DRAW_PRIMATIVE) {
848: drawRoundRectNative(x, y, w, h, arcWidth, arcHeight);
849: }
850: }
851:
852: /** Draws a filled rounded rectangle. */
853: public void fillRoundRect(int x, int y, int w, int h, int arcWidth,
854: int arcHeight) {
855: if ((drawType & DRAW_PRIMATIVE) == DRAW_PRIMATIVE)
856: fillRoundRectNative(x, y, w, h, arcWidth, arcHeight);
857: }
858:
859: /** Draws a bunch of lines defined by an array of x points and y points */
860: private native void drawPolygonNative(boolean filled,
861: int xPoints[], int yPoints[], int nPoints, boolean close);
862:
863: /** Draws a bunch of lines defined by an array of x points and y points */
864: public void drawPolyline(int xPoints[], int yPoints[], int nPoints) {
865: if ((drawType & DRAW_PRIMATIVE) == DRAW_PRIMATIVE) {
866: drawPolygonNative(false, xPoints, yPoints, nPoints, false);
867: }
868: }
869:
870: /** Draws a polygon defined by an array of x points and y points */
871: public void drawPolygon(int xPoints[], int yPoints[], int nPoints) {
872: if ((drawType & DRAW_PRIMATIVE) == DRAW_PRIMATIVE) {
873: drawPolygonNative(false, xPoints, yPoints, nPoints, true);
874: }
875: }
876:
877: /** Fills a polygon with the current fill mask */
878: public void fillPolygon(int xPoints[], int yPoints[], int nPoints) {
879: if ((drawType & DRAW_PRIMATIVE) == DRAW_PRIMATIVE) {
880: drawPolygonNative(true, xPoints, yPoints, nPoints, false);
881: }
882: }
883:
884: /** Draws an oval to fit in the given rectangle */
885: public void drawOval(int x, int y, int w, int h) {
886: if ((drawType & DRAW_PRIMATIVE) == DRAW_PRIMATIVE) {
887: drawArc(x, y, w, h, 0, 360);
888: }
889: }
890:
891: /** Fills an oval to fit in the given rectangle */
892: public void fillOval(int x, int y, int w, int h) {
893: if ((drawType & DRAW_PRIMATIVE) == DRAW_PRIMATIVE) {
894: fillArc(x, y, w, h, 0, 360);
895: }
896: }
897:
898: /**
899: * Draws an arc bounded by the given rectangle from startAngle to
900: * endAngle. 0 degrees is a vertical line straight up from the
901: * center of the rectangle. Positive angles indicate clockwise
902: * rotations, negative angle are counter-clockwise.
903: */
904: public void drawArc(int x, int y, int w, int h, int startAngle,
905: int arcAngle) {
906: if ((drawType & DRAW_PRIMATIVE) == DRAW_PRIMATIVE) {
907: drawArcNative(x, y, w, h, startAngle, arcAngle);
908: }
909: }
910:
911: /** fills an arc. arguments are the same as drawArc. */
912: public void fillArc(int x, int y, int w, int h, int startAngle,
913: int endAngle) {
914: if ((drawType & DRAW_PRIMATIVE) == DRAW_PRIMATIVE) {
915: fillArcNative(x, y, w, h, startAngle, endAngle);
916: }
917: }
918:
919: private native void drawArcNative(int x, int y, int w, int h,
920: int startAngle, int endAngle);
921:
922: private native void fillArcNative(int x, int y, int w, int h,
923: int startAngle, int endAngle);
924:
925: public String toString() {
926: return getClass().getName() + "[" + originX + "," + originY
927: + ", data=" + data + "]: " + "clip=" + clip
928: + ", constrainedRect=" + constrainedRect;
929: }
930: }
|