001: /*
002: * @(#)QtGraphics.java 1.9 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 java.awt;
028:
029: import java.io.*;
030: import java.util.*;
031: import java.awt.image.BufferedImage;
032: import java.awt.image.ImageObserver;
033: import sun.awt.ConstrainableGraphics;
034: import java.text.AttributedCharacterIterator;
035: import java.awt.font.TextAttribute;
036:
037: /**
038: * QtGraphics is an object that encapsulates a graphics context for drawing with Qt.
039: *
040: * @version 1.12, 11/27/01
041: */
042:
043: final class QtGraphics extends Graphics2D implements
044: ConstrainableGraphics {
045:
046: /** The default font to use when no font has been set or null is used. */
047:
048: private static final Font DEFAULT_FONT = new Font("Dialog",
049: Font.PLAIN, 12);
050:
051: private AlphaComposite composite;
052:
053: /** The current foreground color. */
054:
055: private Color foreground;
056:
057: /** The current background color. This is used by clearRect. */
058:
059: private Color background;
060:
061: /** The current xor color. If null then we are in paint mode. */
062:
063: private Color xorColor;
064:
065: /** The currently selected font for text operations. */
066:
067: private Font font;
068:
069: /** The font metrics for the font. Cached for performance. */
070:
071: private QtFontMetrics fontMetrics;
072:
073: /** Translated X offset from native offset. */
074:
075: private int originX;
076:
077: /** Translated Y offset from native offset. */
078:
079: private int originY;
080:
081: /** The index of the native peer for this graphics object. */
082:
083: int psd;
084:
085: /** The current user clip rectangle or null if no clip has been set. This is stored in the
086: native coordinate system and not the possibly translated Java coordinate system. */
087:
088: private Rectangle clip;
089:
090: private Stroke stroke;
091: private int lineWidth;
092:
093: // private int clipWidth, clipHeight;
094:
095: /** The rectangle this graphics object has been constrained too. This is stored in the
096: native coordinate system and not the (possibly) translated Java coordinate system.
097: If it is null then this graphics has not been constrained. The constrained rectangle
098: is another layer of clipping independant of the user clip. The actaul clip used is the
099: intersection */
100:
101: private Rectangle constrainedRect;
102:
103: /** The GraphicsConfiguration that this graphics uses. */
104:
105: private GraphicsConfiguration graphicsConfiguration;
106:
107: static native int pCloneGraphPSD(int Gpsd, boolean fresh);
108:
109: static native int pCloneImagePSD(int Ipsd, boolean fresh);
110:
111: static native void pDisposePSD(int psd);
112:
113: private static native void pSetColor(int psd, int argb);
114:
115: private static native void pSetFont(int psd, int font);
116:
117: private static native void pSetStroke(int psd, int width, int cap,
118: int join, int style);
119:
120: private static native void pSetComposite(int psd, int rule,
121: int extraAlpha);
122:
123: private static native void pSetPaintMode(int psd);
124:
125: private static native void pSetXORMode(int psd, int rgb);
126:
127: private static native void pChangeClipRect(int psd, int x, int y,
128: int w, int h);
129:
130: private static native void pRemoveClip(int psd);
131:
132: private static native void pDrawString(int psd, String string,
133: int x, int y);
134:
135: private static native void pFillRect(int psd, int x, int y,
136: int width, int height);
137:
138: private static native void pClearRect(int psd, int x, int y,
139: int width, int height, int rgb);
140:
141: private static native void pDrawRect(int psd, int x, int y,
142: int width, int height);
143:
144: private static native void pCopyArea(int psd, int x, int y,
145: int width, int height, int dx, int dy);
146:
147: private static native void pDrawLine(int psd, int x1, int y1,
148: int x2, int y2);
149:
150: private static native void pDrawPolygon(int psd, int orinX,
151: int originY, int xPoints[], int yPoints[], int nPoints,
152: boolean close);
153:
154: private static native void pFillPolygon(int psd, int orinX,
155: int originY, int xPoints[], int yPoints[], int nPoints);
156:
157: private static native void pDrawArc(int psd, int x, int y,
158: int width, int height, int start, int end);
159:
160: private static native void pFillArc(int psd, int x, int y,
161: int width, int height, int start, int end);
162:
163: private static native void pDrawOval(int psd, int x, int y,
164: int width, int height);
165:
166: private static native void pFillOval(int psd, int x, int y,
167: int width, int height);
168:
169: private static native void pDrawRoundRect(int psd, int x, int y,
170: int width, int height, int arcWidth, int arcHeight);
171:
172: private static native void pFillRoundRect(int psd, int x, int y,
173: int width, int height, int arcWidth, int arcHeight);
174:
175: private static native QtImage getBufferedImagePeer(BufferedImage bi);
176:
177: QtGraphics(Window window) {
178: try {
179: psd = pCloneGraphPSD(((QtGraphicsDevice) window
180: .getGraphicsConfiguration().getDevice()).psd, false);
181: } catch (OutOfMemoryError e) {
182: System.gc();
183: psd = pCloneGraphPSD(((QtGraphicsDevice) window
184: .getGraphicsConfiguration().getDevice()).psd, true);
185: }
186:
187: foreground = window.foreground;
188:
189: if (foreground == null)
190: foreground = Color.black;
191:
192: // clipWidth = window.getWidth()-1;
193: // clipHeight = window.getHeight()-1;
194: // clip = null;
195: // setupClip();
196:
197: background = window.background;
198:
199: if (background == null)
200: background = Color.black;
201:
202: composite = AlphaComposite.SrcOver;
203: graphicsConfiguration = window.getGraphicsConfiguration();
204: setFont(DEFAULT_FONT);
205: setColorNative(); // 6241180
206: }
207:
208: QtGraphics(QtGraphics g) {
209: try {
210: psd = pCloneGraphPSD(g.psd, false);
211: } catch (OutOfMemoryError e) {
212: System.gc();
213: psd = pCloneGraphPSD(g.psd, true);
214: }
215: composite = g.composite;
216: graphicsConfiguration = g.graphicsConfiguration;
217: originX = g.originX;
218: originY = g.originY;
219: // clipWidth = g.clipWidth;
220: // clipHeight = g.clipHeight;
221: // clip = g.clip;
222: if (g.clip != null) {
223: clip = new Rectangle(g.clip);
224: setupClip();
225: }
226: // constrainedRect = g.constrainedRect;
227: stroke = g.stroke;
228: // setupClip();
229: foreground = g.foreground;
230: background = g.background;
231: setColorNative(); // 6241180
232: setFont(g.font);
233: }
234:
235: QtGraphics(QtOffscreenImage image) {
236: try {
237: psd = pCloneImagePSD(image.psd, false);
238: } catch (OutOfMemoryError e) {
239: System.gc();
240: psd = pCloneImagePSD(image.psd, true);
241: }
242:
243: foreground = image.foreground;
244:
245: if (foreground == null)
246: foreground = Color.black;
247:
248: background = image.background;
249:
250: if (background == null)
251: background = Color.black;
252:
253: composite = AlphaComposite.SrcOver;
254: graphicsConfiguration = image.gc;
255:
256: // 5104620
257: // If the image.font is null, use the default font. Fixes the
258: // crash in the native code
259: setFont(((image.font == null) ? DEFAULT_FONT : image.font));
260:
261: // 6205694,6205693,6206487,6206315
262: // Changed the width and height to the image's width and
263: // height. Got sidetracked by the "clipWidth" and "clipHeight"
264: pChangeClipRect(psd, 0, 0, image.getWidth(), image.getHeight());
265: // 6205694,6205693,6206487,6206315,
266: }
267:
268: QtGraphics(QtSubimage image, int x, int y) {
269: try {
270: psd = pCloneImagePSD(image.psd, false);
271: } catch (OutOfMemoryError e) {
272: System.gc();
273: psd = pCloneImagePSD(image.psd, true);
274: }
275:
276: composite = AlphaComposite.SrcOver;
277:
278: originX = x;
279: originY = y;
280:
281: // clipWidth = image.getWidth() - 1 + originX;
282: // clipHeight = image.getHeight() - 1 + originY;
283: clip = null;
284: pChangeClipRect(psd, x, y, image.getWidth() - 1 + x, image
285: .getHeight()
286: - 1 + y);
287: }
288:
289: /**
290: * Create a new QtGraphics Object based on this one.
291: */
292: public Graphics create() {
293: return new QtGraphics(this );
294: }
295:
296: /**
297: * Translate
298: */
299: public void translate(int x, int y) {
300: originX += x;
301: originY += y;
302: }
303:
304: public void finalize() {
305: dispose();
306: try {
307: super .finalize();
308: } catch (Throwable t) {
309: }
310: ;
311: }
312:
313: public final void dispose() {
314: if (psd > 0) {
315: pDisposePSD(psd);
316: psd = -1;
317: }
318: }
319:
320: private void setFont(Font font, boolean backwardCompat) {
321: this .font = font;
322: fontMetrics = QtFontMetrics
323: .getFontMetrics(font, backwardCompat);
324: pSetFont(psd, fontMetrics.nativeFont);
325: }
326:
327: public void setFont(Font font) {
328: if (font != null && !font.equals(this .font))
329: setFont(font, true);
330: }
331:
332: public Font getFont() {
333: return font;
334: }
335:
336: /**
337: * Gets the font metrics of the current font.
338: * @return the font metrics of this graphics
339: * context's current font.
340: * @see java.awt.Graphics#getFont
341: * @see java.awt.FontMetrics
342: * @see java.awt.Graphics#getFontMetrics(Font)
343: * @since JDK1.0
344: */
345: public FontMetrics getFontMetrics() {
346: return fontMetrics;
347: }
348:
349: /**
350: * Gets font metrics for the given font.
351: */
352: public FontMetrics getFontMetrics(Font font) {
353: return QtFontMetrics.getFontMetrics(font, true);
354: }
355:
356: public void setStroke(Stroke stroke) {
357: /* Don't know about this case !!! FIXME!!! */
358: if (stroke == null) {
359: this .stroke = null;
360: return;
361: }
362:
363: if (!(stroke instanceof BasicStroke))
364: // 6189931: Throwing IAE as per the spec instead of
365: // UnsupportedOperationException
366: throw new IllegalArgumentException(
367: "Only BasicStroke Supported!");
368: // 6189931
369:
370: this .stroke = stroke;
371:
372: BasicStroke bs = (BasicStroke) stroke;
373: int cap, join;
374:
375: lineWidth = (int) bs.getLineWidth();
376: cap = bs.getEndCap();
377: join = bs.getLineJoin();
378:
379: pSetStroke(psd, lineWidth, cap, join, 0);
380: }
381:
382: public Stroke getStroke() {
383: return stroke;
384: }
385:
386: /**
387: * Sets the foreground color.
388: */
389:
390: public void setColor(Color c) {
391: if ((c != null) && (c != foreground)) {
392: foreground = c;
393: setColorNative(); // 6241180
394: }
395: }
396:
397: // 6241180
398: // Uses this.foreground and this.composite to figure out if a new
399: // foreground color should be set for SRC rule and Extra Alpha 0.0
400: private void setColorNative() {
401: float[] rgbaSrc = foreground.getRGBComponents(null);
402: // compute the actual alpha of the source color using the
403: // composite's extraAlpha and source color alpha
404: float alphasource = composite.getAlpha() * rgbaSrc[3];
405: // if the colormodel does not have an alpha channel, and the
406: // source has zero intensity alpha, then the source color
407: // that should be copied as part of the SRC rule is forced
408: // to black (the color channels multiplied by the alpha)
409: Color fg = this .foreground;
410: if (this .composite.getRule() == AlphaComposite.SRC
411: && !this .graphicsConfiguration.getColorModel()
412: .hasAlpha() && alphasource == 0.0f) {
413: fg = new Color(0.0f, 0.0f, 0.0f, 1.0f);
414: }
415: pSetColor(psd, fg.value);
416: }
417:
418: // 6241180
419:
420: public Color getColor() {
421: return foreground;
422: }
423:
424: public Composite getComposite() {
425: return composite;
426: }
427:
428: public GraphicsConfiguration getDeviceConfiguration() {
429: return graphicsConfiguration;
430: }
431:
432: public void setComposite(Composite comp) {
433: if ((comp != null) && (comp != composite)) {
434: if (!(comp instanceof AlphaComposite))
435: throw new IllegalArgumentException(
436: "Only AlphaComposite is supported");
437:
438: composite = (AlphaComposite) comp;
439:
440: pSetComposite(psd, composite.rule,
441: (int) (composite.extraAlpha * 0xFF));
442: setColorNative(); // 6241180
443: }
444: }
445:
446: /**
447: * Sets the paint mode to overwrite the destination with the
448: * current color. This is the default paint mode.
449: */
450: public void setPaintMode() {
451: xorColor = null;
452:
453: pSetPaintMode(psd);
454: }
455:
456: /**
457: * Sets the paint mode to alternate between the current color
458: * and the given color.
459: */
460: public void setXORMode(Color color) {
461: xorColor = color;
462:
463: pSetXORMode(psd, color.value);
464: }
465:
466: /** Clears the rectangle indicated by x,y,w,h. */
467:
468: final public void clearRect(int x, int y, final int w, final int h) {
469:
470: x += originX;
471: y += originY;
472:
473: pClearRect(psd, x, y, w, h, background.value);
474: }
475:
476: /** Fills the given rectangle with the foreground color. */
477:
478: public void fillRect(final int x, final int y, final int w,
479: final int h) {
480: pFillRect(psd, x + originX, y + originY, w, h);
481: }
482:
483: /** Draws the given rectangle. */
484: public void drawRect(final int x, final int y, final int w,
485: final int h) {
486: pDrawRect(psd, x + originX, y + originY, w, h);
487: }
488:
489: /** Draws the given line. */
490:
491: public void drawLine(final int x1, final int y1, final int x2,
492: final int y2) {
493: pDrawLine(psd, x1 + originX, y1 + originY, x2 + originX, y2
494: + originY);
495: }
496:
497: /**
498: * Copies an area of the canvas that this graphics context paints to.
499: * @param X the x-coordinate of the source.
500: * @param Y the y-coordinate of the source.
501: * @param W the width.
502: * @param H the height.
503: * @param dx the horizontal distance to copy the pixels.
504: * @param dy the vertical distance to copy the pixels.
505: */
506: public void copyArea(int X, int Y, final int W, final int H,
507: final int dx, final int dy) {
508: X += originX;
509: Y += originY;
510: pCopyArea(psd, X, Y, W, H, dx, dy);
511: }
512:
513: /** Draws lines defined by an array of x points and y points */
514:
515: public void drawPolyline(final int xPoints[], final int yPoints[],
516: final int nPoints) {
517: pDrawPolygon(psd, originX, originY, xPoints, yPoints, nPoints,
518: false);
519: }
520:
521: /** Draws a polygon defined by an array of x points and y points */
522:
523: public void drawPolygon(final int xPoints[], final int yPoints[],
524: final int nPoints) {
525: pDrawPolygon(psd, originX, originY, xPoints, yPoints, nPoints,
526: true);
527: }
528:
529: /** Fills a polygon with the current fill mask */
530:
531: public void fillPolygon(final int xPoints[], final int yPoints[],
532: final int nPoints) {
533: pFillPolygon(psd, originX, originY, xPoints, yPoints, nPoints);
534: }
535:
536: /** Draws an oval to fit in the given rectangle */
537: public void drawOval(final int x, final int y, final int w,
538: final int h) {
539: pDrawOval(psd, x + originX, y + originY, w, h);
540: }
541:
542: /** Fills an oval to fit in the given rectangle */
543: public void fillOval(final int x, final int y, final int w,
544: final int h) {
545: pFillOval(psd, x + originX, y + originY, w, h);
546: }
547:
548: /**
549: * Draws an arc bounded by the given rectangle from startAngle to
550: * endAngle. 0 degrees is a vertical line straight up from the
551: * center of the rectangle. Positive start angle indicate clockwise
552: * rotations, negative angle are counter-clockwise.
553: */
554: public void drawArc(final int x, final int y, final int w,
555: final int h, final int startAngle, final int endAngle) {
556: pDrawArc(psd, x + originX, y + originY, w, h, startAngle,
557: endAngle);
558: }
559:
560: /** fills an arc. arguments are the same as drawArc. */
561: public void fillArc(final int x, final int y, final int w,
562: final int h, final int startAngle, final int endAngle) {
563: pFillArc(psd, x + originX, y + originY, w, h, startAngle,
564: endAngle);
565: }
566:
567: /** Draws a rounded rectangle. */
568: public void drawRoundRect(final int x, final int y, final int w,
569: final int h, final int arcWidth, final int arcHeight) {
570: pDrawRoundRect(psd, x + originX, y + originY, w, h, arcWidth,
571: arcHeight);
572: }
573:
574: /** Draws a filled rounded rectangle. */
575: public void fillRoundRect(final int x, final int y, final int w,
576: final int h, final int arcWidth, final int arcHeight) {
577: pFillRoundRect(psd, x + originX, y + originY, w, h, arcWidth,
578: arcHeight);
579: }
580:
581: /** Draws the given string. */
582: public void drawString(final String string, final int x, final int y) {
583: // 6259215
584: // throw NPE instead of returning
585: if (string == null)
586: throw new NullPointerException("string is null");
587: // 6259215
588:
589: pDrawString(psd, string, x + originX, y + originY);
590: }
591:
592: public void drawString(AttributedCharacterIterator iterator, int x,
593: int y) {
594: char c = iterator.first();
595: Graphics ng = new QtGraphics(this );
596:
597: while (c != iterator.DONE) {
598: Map attrs = iterator.getAttributes();
599: Object obj;
600: FontMetrics fm;
601: Font fn;
602:
603: if ((obj = attrs.get(TextAttribute.FONT)) != null)
604: fn = (Font) obj;
605: else
606: fn = new Font(attrs);
607:
608: ((QtGraphics) ng).setFont(fn, false);
609: fm = ng.getFontMetrics();
610:
611: // Might have to query the FONT first to see if it has a Colour set.
612: if ((obj = attrs.get(TextAttribute.FOREGROUND)) != null)
613: ng.setColor((Color) obj);
614: else
615: ng.setColor(this .foreground);
616:
617: int runIdx = iterator.getRunLimit();
618: char[] str = new char[runIdx - iterator.getIndex()];
619:
620: for (int lc = 0; iterator.getIndex() < runIdx; c = iterator
621: .next())
622: str[lc++] = c;
623:
624: String ns = new String(str);
625:
626: ng.drawString(ns, x, y);
627:
628: x += fm.stringWidth(ns);
629: }
630:
631: ng.dispose();
632: }
633:
634: /** Draws the given character array. */
635: public void drawChars(final char chars[], final int offset,
636: final int length, final int x, final int y) {
637: pDrawString(psd, new String(chars, offset, length),
638: x + originX, y + originY);
639: }
640:
641: /**
642: * Gets the current clipping area
643: */
644: public Rectangle getClipBounds() {
645: if (clip != null)
646: return new Rectangle(clip.x - originX, clip.y - originY,
647: clip.width, clip.height);
648:
649: return null;
650: }
651:
652: /** Returns a Shape object representing the MicroWindows clip. */
653:
654: public Shape getClip() {
655: return getClipBounds();
656: }
657:
658: public void constrain(final int x, final int y, final int w,
659: final int h) {
660: originX += x;
661: originY += y;
662: Rectangle rect = new Rectangle(originX, originY, w, h);
663:
664: if (constrainedRect != null)
665: constrainedRect = constrainedRect.intersection(rect);
666:
667: else
668: constrainedRect = rect;
669:
670: setupClip();
671: }
672:
673: /** Crops the clipping rectangle for this MicroWindows context. */
674:
675: public void clipRect(final int x, final int y, final int w,
676: final int h) {
677: Rectangle rect = new Rectangle(x + originX, y + originY, w, h);
678:
679: if (clip != null)
680: clip = clip.intersection(rect);
681: else
682: clip = rect;
683:
684: setupClip();
685: }
686:
687: /** Sets up the clip for this Graphics. The clip is the result of combining the user clip
688: with the constrainedRect. */
689:
690: private void setupClip() {
691: int clipX, clipY, clipW, clipH;
692: if (constrainedRect != null) {
693: Rectangle c = this .constrainedRect;
694: if (clip != null) {
695: c = constrainedRect.intersection(clip);
696: }
697: clipX = c.x;
698: clipY = c.y;
699: clipW = c.width;
700: clipH = c.height;
701: } else if (clip != null) {
702: clipX = clip.x;
703: clipY = clip.y;
704: clipW = clip.width;
705: clipH = clip.height;
706: } else {
707: return; // this should not happen
708: }
709:
710: pChangeClipRect(psd, clipX, clipY, clipW, clipH);
711: }
712:
713: /** Sets the clipping rectangle for this X11Graphics context. */
714: public void setClip(final int x, final int y, final int w,
715: final int h) {
716: if (clip == null)
717: clip = new Rectangle(x + originX, y + originY, w, h);
718: else {
719: clip.x = x + originX;
720: clip.y = y + originY;
721: clip.width = w;
722: clip.height = h;
723: }
724: setupClip();
725: }
726:
727: /** Sets the clip to a Shape (only Rectangle allowed). */
728:
729: public void setClip(Shape clip) {
730: if (clip == null) {
731: this .clip = null;
732: pRemoveClip(psd);
733: } else if (clip instanceof Rectangle) {
734: Rectangle rect = (Rectangle) clip;
735:
736: setClip(rect.x, rect.y, rect.width, rect.height);
737: } else
738: throw new IllegalArgumentException(
739: "setClip(Shape) only supports Rectangle objects");
740: }
741:
742: /**
743: * Draws an image at x,y in nonblocking mode with a callback object.
744: */
745: public boolean drawImage(Image img, final int x, final int y,
746: ImageObserver observer) {
747: return drawImage(img, x, y, null, observer);
748: }
749:
750: /**
751: * Draws an image at x,y in nonblocking mode with a solid background
752: * color and a callback object.
753: */
754: public boolean drawImage(Image img, final int x, final int y,
755: Color bg, ImageObserver observer) {
756:
757: QtImage qtimg;
758:
759: if (img == null)
760: throw new NullPointerException("Image can't be null");
761:
762: if (img instanceof BufferedImage)
763: qtimg = getBufferedImagePeer((BufferedImage) img);
764: else if (img instanceof QtVolatileImage)
765: qtimg = ((QtVolatileImage) img).qtimage;
766: else
767: qtimg = (QtImage) img;
768:
769: boolean isComplete = qtimg.isComplete();
770: if (!isComplete) {
771: qtimg.addObserver(observer);
772: qtimg.startProduction();
773: isComplete = qtimg.isComplete();
774: }
775:
776: int width = qtimg.getWidth();
777: int height = qtimg.getHeight();
778:
779: if (width > 0 && height > 0) {
780: qtimg.drawImage(psd, x + originX, y + originY, bg);
781: }
782:
783: return isComplete;
784: }
785:
786: /**
787: * Draws an image scaled to x,y,w,h in nonblocking mode with a
788: * callback object.
789: */
790: public boolean drawImage(Image img, final int x, final int y,
791: final int width, final int height, ImageObserver observer) {
792:
793: return drawImage(img, x, y, width, height, null, observer);
794: }
795:
796: /**
797: * Draws an image scaled to x,y,w,h in nonblocking mode with a
798: * solid background color and a callback object.
799: */
800: public boolean drawImage(Image img, int x, int y, final int width,
801: final int height, Color bg, ImageObserver observer) {
802: QtImage qtimg;
803:
804: if (img == null)
805: throw new NullPointerException("Image can't be null");
806:
807: if (img instanceof BufferedImage)
808: qtimg = getBufferedImagePeer((BufferedImage) img);
809: else if (img instanceof QtVolatileImage)
810: qtimg = ((QtVolatileImage) img).qtimage;
811: else
812: qtimg = (QtImage) img;
813:
814: boolean isComplete = qtimg.isComplete();
815: if (!isComplete) {
816: qtimg.addObserver(observer);
817: qtimg.startProduction();
818: isComplete = qtimg.isComplete();
819: }
820:
821: int imgWidth = qtimg.getWidth();
822: int imgHeight = qtimg.getHeight();
823:
824: if (imgWidth > 0 && imgHeight > 0) {
825:
826: x += originX;
827: y += originY;
828:
829: if (imgWidth == width && imgHeight == height)
830: qtimg.drawImage(psd, x, y, bg);
831: else
832: qtimg.drawImage(psd, x, y, x + width - 1, y + height
833: - 1, 0, 0, imgWidth - 1, imgHeight - 1, bg);
834: }
835:
836: return isComplete;
837: }
838:
839: /**
840: * Draws a subrectangle of an image scaled to a destination rectangle
841: * in nonblocking mode with a callback object.
842: */
843: public boolean drawImage(Image img, final int dx1, final int dy1,
844: final int dx2, final int dy2, final int sx1, final int sy1,
845: final int sx2, final int sy2, ImageObserver observer) {
846:
847: return drawImage(img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2,
848: null, observer);
849: }
850:
851: /**
852: * Draws a subrectangle of an image scaled to a destination rectangle in
853: * nonblocking mode with a solid background color and a callback object.
854: */
855: public boolean drawImage(Image img, final int dx1, final int dy1,
856: final int dx2, final int dy2, final int sx1, final int sy1,
857: final int sx2, final int sy2, Color bg,
858: ImageObserver observer) {
859:
860: QtImage qtimg;
861:
862: if (img == null)
863: throw new NullPointerException("Image can't be null");
864:
865: if (img instanceof BufferedImage)
866: qtimg = getBufferedImagePeer((BufferedImage) img);
867: else if (img instanceof QtVolatileImage)
868: qtimg = ((QtVolatileImage) img).qtimage;
869: else
870: qtimg = (QtImage) img;
871:
872: boolean isComplete = qtimg.isComplete();
873: if (!isComplete) {
874: qtimg.addObserver(observer);
875: qtimg.startProduction();
876: isComplete = qtimg.isComplete();
877: }
878:
879: int imgWidth = qtimg.getWidth();
880: int imgHeight = qtimg.getHeight();
881:
882: if (imgWidth > 0 || imgHeight > 0) {
883: qtimg.drawImage(psd, dx1 + originX, dy1 + originY, dx2
884: + originX, dy2 + originY, sx1, sy1, sx2, sy2, bg);
885: }
886:
887: return isComplete;
888: }
889:
890: public String toString() {
891: return getClass().getName() + "[" + originX + "," + originY
892: + "]";
893: }
894:
895: }
|