History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/sun/print/PeekGraphics.java (1 of 18352 files). Show all

Unified · Split

java/pkg/sun/print/PeekGraphics.java+1918−0
@@ -0,0 +1,1918 @@
1+/*
2+ * Copyright (c) 1998, 2006, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.print;
27+
28+import java.util.Map;
29+
30+import java.awt.BasicStroke;
31+import java.awt.Color;
32+import java.awt.Composite;
33+import java.awt.Graphics;
34+import java.awt.Graphics2D;
35+import java.awt.Font;
36+import java.awt.FontMetrics;
37+import java.awt.font.FontRenderContext;
38+import java.awt.Graphics;
39+import java.awt.GraphicsConfiguration;
40+import java.awt.Image;
41+import java.awt.Paint;
42+import java.awt.Rectangle;
43+import java.awt.Shape;
44+import java.awt.Stroke;
45+import java.awt.RenderingHints;
46+import java.awt.RenderingHints.Key;
47+
48+import java.awt.font.GlyphVector;
49+import java.awt.font.TextLayout;
50+
51+import java.awt.geom.AffineTransform;
52+import java.awt.geom.Line2D;
53+import java.awt.geom.Point2D;
54+import java.awt.geom.Rectangle2D;
55+import java.awt.geom.RoundRectangle2D;
56+import java.awt.image.BufferedImage;
57+import java.awt.image.BufferedImageOp;
58+import java.awt.image.ImageObserver;
59+import java.awt.image.RenderedImage;
60+import java.awt.image.renderable.RenderableImage;
61+import java.awt.print.PrinterGraphics;
62+import java.awt.print.PrinterJob;
63+
64+import java.text.AttributedCharacterIterator;
65+
66+import sun.java2d.Spans;
67+
68+public class PeekGraphics extends Graphics2D
69+ implements PrinterGraphics,
70+ ImageObserver,
71+ Cloneable {
72+
73+ /**
74+ * Drawing methods will be forwarded to this object.
75+ */
76+ Graphics2D mGraphics;
77+
78+ /**
79+ * The PrinterJob controlling the current printing.
80+ */
81+ PrinterJob mPrinterJob;
82+
83+ /**
84+ * Keeps track of where drawing occurs on the page.
85+ */
86+ private Spans mDrawingArea = new Spans();
87+
88+ /**
89+ * Track information about the types of drawing
90+ * performed by the printing application.
91+ */
92+ private PeekMetrics mPrintMetrics = new PeekMetrics();
93+
94+ /**
95+ * If true the application will only be drawing AWT style
96+ * graphics, no Java2D graphics.
97+ */
98+ private boolean mAWTDrawingOnly = false;
99+
100+ /**
101+ * The new PeekGraphics2D will forward state changing
102+ * calls to 'graphics'. 'printerJob' is stored away
103+ * so that the printing application can get the PrinterJob
104+ * if needed.
105+ */
106+ public PeekGraphics(Graphics2D graphics, PrinterJob printerJob) {
107+
108+ mGraphics = graphics;
109+ mPrinterJob = printerJob;
110+ }
111+
112+ /**
113+ * Return the Graphics2D object that does the drawing
114+ * for this instance.
115+ */
116+ public Graphics2D getDelegate() {
117+ return mGraphics;
118+ }
119+
120+ /**
121+ * Set the Graphics2D instance which will do the
122+ * drawing.
123+ */
124+ public void setDelegate(Graphics2D graphics) {
125+ mGraphics = graphics;
126+ }
127+
128+ public PrinterJob getPrinterJob() {
129+ return mPrinterJob;
130+ }
131+
132+ /**
133+ * The caller promises that only AWT graphics will be drawn.
134+ * The print system can use this information to make general
135+ * assumptions about the types of graphics to be drawn without
136+ * requiring the application to draw the contents multiple
137+ * times.
138+ */
139+ public void setAWTDrawingOnly() {
140+ mAWTDrawingOnly = true;
141+ }
142+
143+ public boolean getAWTDrawingOnly() {
144+ return mAWTDrawingOnly;
145+ }
146+
147+ /**
148+ * Return a Spans instance describing the parts of the page in
149+ * to which drawing occurred.
150+ */
151+ public Spans getDrawingArea() {
152+ return mDrawingArea;
153+ }
154+
155+ /**
156+ * Returns the device configuration associated with this Graphics2D.
157+ */
158+ public GraphicsConfiguration getDeviceConfiguration() {
159+ return ((RasterPrinterJob)mPrinterJob).getPrinterGraphicsConfig();
160+ }
161+
162+/* The Delegated Graphics Methods */
163+
164+ /**
165+ * Creates a new <code>Graphics</code> object that is
166+ * a copy of this <code>Graphics</code> object.
167+ * @return a new graphics context that is a copy of
168+ * this graphics context.
169+ * @since JDK1.0
170+ */
171+ public Graphics create() {
172+ PeekGraphics newGraphics = null;
173+
174+ try {
175+ newGraphics = (PeekGraphics) clone();
176+ newGraphics.mGraphics = (Graphics2D) mGraphics.create();
177+
178+ /* This exception can not happen unless this
179+ * class no longer implements the Cloneable
180+ * interface.
181+ */
182+ } catch (CloneNotSupportedException e) {
183+ // can never happen.
184+ }
185+
186+ return newGraphics;
187+ }
188+
189+ /**
190+ * Translates the origin of the graphics context to the point
191+ * (<i>x</i>,&nbsp;<i>y</i>) in the current coordinate system.
192+ * Modifies this graphics context so that its new origin corresponds
193+ * to the point (<i>x</i>,&nbsp;<i>y</i>) in this graphics context's
194+ * original coordinate system. All coordinates used in subsequent
195+ * rendering operations on this graphics context will be relative
196+ * to this new origin.
197+ * @param x the <i>x</i> coordinate.
198+ * @param y the <i>y</i> coordinate.
199+ * @since JDK1.0
200+ */
201+ public void translate(int x, int y) {
202+ mGraphics.translate(x, y);
203+ }
204+
205+ /**
206+ * Concatenates the current transform of this Graphics2D with a
207+ * translation transformation.
208+ * This is equivalent to calling transform(T), where T is an
209+ * AffineTransform represented by the following matrix:
210+ * <pre>
211+ * [ 1 0 tx ]
212+ * [ 0 1 ty ]
213+ * [ 0 0 1 ]
214+ * </pre>
215+ */
216+ public void translate(double tx, double ty) {
217+ mGraphics.translate(tx, ty);
218+ }
219+
220+ /**
221+ * Concatenates the current transform of this Graphics2D with a
222+ * rotation transformation.
223+ * This is equivalent to calling transform(R), where R is an
224+ * AffineTransform represented by the following matrix:
225+ * <pre>
226+ * [ cos(theta) -sin(theta) 0 ]
227+ * [ sin(theta) cos(theta) 0 ]
228+ * [ 0 0 1 ]
229+ * </pre>
230+ * Rotating with a positive angle theta rotates points on the positive
231+ * x axis toward the positive y axis.
232+ * @param theta The angle of rotation in radians.
233+ */
234+ public void rotate(double theta) {
235+ mGraphics.rotate(theta);
236+ }
237+
238+ /**
239+ * Concatenates the current transform of this Graphics2D with a
240+ * translated rotation transformation.
241+ * This is equivalent to the following sequence of calls:
242+ * <pre>
243+ * translate(x, y);
244+ * rotate(theta);
245+ * translate(-x, -y);
246+ * </pre>
247+ * Rotating with a positive angle theta rotates points on the positive
248+ * x axis toward the positive y axis.
249+ * @param theta The angle of rotation in radians.
250+ * @param x The x coordinate of the origin of the rotation
251+ * @param y The x coordinate of the origin of the rotation
252+ */
253+ public void rotate(double theta, double x, double y) {
254+ mGraphics.rotate(theta, x, y);
255+ }
256+
257+ /**
258+ * Concatenates the current transform of this Graphics2D with a
259+ * scaling transformation.
260+ * This is equivalent to calling transform(S), where S is an
261+ * AffineTransform represented by the following matrix:
262+ * <pre>
263+ * [ sx 0 0 ]
264+ * [ 0 sy 0 ]
265+ * [ 0 0 1 ]
266+ * </pre>
267+ */
268+ public void scale(double sx, double sy) {
269+ mGraphics.scale(sx, sy);
270+ }
271+
272+ /**
273+ * Concatenates the current transform of this Graphics2D with a
274+ * shearing transformation.
275+ * This is equivalent to calling transform(SH), where SH is an
276+ * AffineTransform represented by the following matrix:
277+ * <pre>
278+ * [ 1 shx 0 ]
279+ * [ shy 1 0 ]
280+ * [ 0 0 1 ]
281+ * </pre>
282+ * @param shx The factor by which coordinates are shifted towards the
283+ * positive X axis direction according to their Y coordinate
284+ * @param shy The factor by which coordinates are shifted towards the
285+ * positive Y axis direction according to their X coordinate
286+ */
287+ public void shear(double shx, double shy) {
288+ mGraphics.shear(shx, shy);
289+ }
290+
291+ /**
292+ * Gets this graphics context's current color.
293+ * @return this graphics context's current color.
294+ * @see java.awt.Color
295+ * @see java.awt.Graphics#setColor
296+ * @since JDK1.0
297+ */
298+ public Color getColor() {
299+ return mGraphics.getColor();
300+ }
301+
302+ /**
303+ * Sets this graphics context's current color to the specified
304+ * color. All subsequent graphics operations using this graphics
305+ * context use this specified color.
306+ * @param c the new rendering color.
307+ * @see java.awt.Color
308+ * @see java.awt.Graphics#getColor
309+ * @since JDK1.0
310+ */
311+ public void setColor(Color c) {
312+ mGraphics.setColor(c);
313+ }
314+
315+ /**
316+ * Sets the paint mode of this graphics context to overwrite the
317+ * destination with this graphics context's current color.
318+ * This sets the logical pixel operation function to the paint or
319+ * overwrite mode. All subsequent rendering operations will
320+ * overwrite the destination with the current color.
321+ * @since JDK1.0
322+ */
323+ public void setPaintMode() {
324+ mGraphics.setPaintMode();
325+ }
326+
327+ /**
328+ * Sets the paint mode of this graphics context to alternate between
329+ * this graphics context's current color and the new specified color.
330+ * This specifies that logical pixel operations are performed in the
331+ * XOR mode, which alternates pixels between the current color and
332+ * a specified XOR color.
333+ * <p>
334+ * When drawing operations are performed, pixels which are the
335+ * current color are changed to the specified color, and vice versa.
336+ * <p>
337+ * Pixels that are of colors other than those two colors are changed
338+ * in an unpredictable but reversible manner; if the same figure is
339+ * drawn twice, then all pixels are restored to their original values.
340+ * @param c1 the XOR alternation color
341+ * @since JDK1.0
342+ */
343+ public void setXORMode(Color c1) {
344+ mGraphics.setXORMode(c1);
345+ }
346+
347+ /**
348+ * Gets the current font.
349+ * @return this graphics context's current font.
350+ * @see java.awt.Font
351+ * @see java.awt.Graphics#setFont
352+ * @since JDK1.0
353+ */
354+ public Font getFont() {
355+ return mGraphics.getFont();
356+ }
357+
358+ /**
359+ * Sets this graphics context's font to the specified font.
360+ * All subsequent text operations using this graphics context
361+ * use this font.
362+ * @param font the font.
363+ * @see java.awt.Graphics#getFont
364+ * @see java.awt.Graphics#drawChars(java.lang.String, int, int)
365+ * @see java.awt.Graphics#drawString(byte[], int, int, int, int)
366+ * @see java.awt.Graphics#drawBytes(char[], int, int, int, int)
367+ * @since JDK1.0
368+ */
369+ public void setFont(Font font) {
370+ mGraphics.setFont(font);
371+ }
372+
373+ /**
374+ * Gets the font metrics for the specified font.
375+ * @return the font metrics for the specified font.
376+ * @param f the specified font
377+ * @see java.awt.Graphics#getFont
378+ * @see java.awt.FontMetrics
379+ * @see java.awt.Graphics#getFontMetrics()
380+ * @since JDK1.0
381+ */
382+ public FontMetrics getFontMetrics(Font f) {
383+ return mGraphics.getFontMetrics(f);
384+ }
385+
386+ /**
387+ * Get the rendering context of the font
388+ * within this Graphics2D context.
389+ */
390+ public FontRenderContext getFontRenderContext() {
391+ return mGraphics.getFontRenderContext();
392+ }
393+
394+ /**
395+ * Returns the bounding rectangle of the current clipping area.
396+ * The coordinates in the rectangle are relative to the coordinate
397+ * system origin of this graphics context.
398+ * @return the bounding rectangle of the current clipping area.
399+ * @see java.awt.Graphics#getClip
400+ * @see java.awt.Graphics#clipRect
401+ * @see java.awt.Graphics#setClip(int, int, int, int)
402+ * @see java.awt.Graphics#setClip(Shape)
403+ * @since JDK1.1
404+ */
405+ public Rectangle getClipBounds() {
406+ return mGraphics.getClipBounds();
407+ }
408+
409+
410+ /**
411+ * Intersects the current clip with the specified rectangle.
412+ * The resulting clipping area is the intersection of the current
413+ * clipping area and the specified rectangle.
414+ * This method can only be used to make the current clip smaller.
415+ * To set the current clip larger, use any of the setClip methods.
416+ * Rendering operations have no effect outside of the clipping area.
417+ * @param x the x coordinate of the rectangle to intersect the clip with
418+ * @param y the y coordinate of the rectangle to intersect the clip with
419+ * @param width the width of the rectangle to intersect the clip with
420+ * @param height the height of the rectangle to intersect the clip with
421+ * @see #setClip(int, int, int, int)
422+ * @see #setClip(Shape)
423+ */
424+ public void clipRect(int x, int y, int width, int height) {
425+ mGraphics.clipRect(x, y, width, height);
426+ }
427+
428+
429+ /**
430+ * Sets the current clip to the rectangle specified by the given
431+ * coordinates.
432+ * Rendering operations have no effect outside of the clipping area.
433+ * @param x the <i>x</i> coordinate of the new clip rectangle.
434+ * @param y the <i>y</i> coordinate of the new clip rectangle.
435+ * @param width the width of the new clip rectangle.
436+ * @param height the height of the new clip rectangle.
437+ * @see java.awt.Graphics#clipRect
438+ * @see java.awt.Graphics#setClip(Shape)
439+ * @since JDK1.1
440+ */
441+ public void setClip(int x, int y, int width, int height) {
442+ mGraphics.setClip(x, y, width, height);
443+ }
444+
445+ /**
446+ * Gets the current clipping area.
447+ * @return a <code>Shape</code> object representing the
448+ * current clipping area.
449+ * @see java.awt.Graphics#getClipBounds
450+ * @see java.awt.Graphics#clipRect
451+ * @see java.awt.Graphics#setClip(int, int, int, int)
452+ * @see java.awt.Graphics#setClip(Shape)
453+ * @since JDK1.1
454+ */
455+ public Shape getClip() {
456+ return mGraphics.getClip();
457+ }
458+
459+
460+ /**
461+ * Sets the current clipping area to an arbitrary clip shape.
462+ * Not all objects which implement the <code>Shape</code>
463+ * interface can be used to set the clip. The only
464+ * <code>Shape</code> objects which are guaranteed to be
465+ * supported are <code>Shape</code> objects which are
466+ * obtained via the <code>getClip</code> method and via
467+ * <code>Rectangle</code> objects.
468+ * @see java.awt.Graphics#getClip()
469+ * @see java.awt.Graphics#clipRect
470+ * @see java.awt.Graphics#setClip(int, int, int, int)
471+ * @since JDK1.1
472+ */
473+ public void setClip(Shape clip) {
474+ mGraphics.setClip(clip);
475+ }
476+
477+
478+ /**
479+ * Copies an area of the component by a distance specified by
480+ * <code>dx</code> and <code>dy</code>. From the point specified
481+ * by <code>x</code> and <code>y</code>, this method
482+ * copies downwards and to the right. To copy an area of the
483+ * component to the left or upwards, specify a negative value for
484+ * <code>dx</code> or <code>dy</code>.
485+ * If a portion of the source rectangle lies outside the bounds
486+ * of the component, or is obscured by another window or component,
487+ * <code>copyArea</code> will be unable to copy the associated
488+ * pixels. The area that is omitted can be refreshed by calling
489+ * the component's <code>paint</code> method.
490+ * @param x the <i>x</i> coordinate of the source rectangle.
491+ * @param y the <i>y</i> coordinate of the source rectangle.
492+ * @param width the width of the source rectangle.
493+ * @param height the height of the source rectangle.
494+ * @param dx the horizontal distance to copy the pixels.
495+ * @param dy the vertical distance to copy the pixels.
496+ * @since JDK1.0
497+ */
498+ public void copyArea(int x, int y, int width, int height,
499+ int dx, int dy) {
500+ // This method is not supported for printing so we do nothing here.
501+ }
502+
503+ /**
504+ * Draws a line, using the current color, between the points
505+ * <code>(x1,&nbsp;y1)</code> and <code>(x2,&nbsp;y2)</code>
506+ * in this graphics context's coordinate system.
507+ * @param x1 the first point's <i>x</i> coordinate.
508+ * @param y1 the first point's <i>y</i> coordinate.
509+ * @param x2 the second point's <i>x</i> coordinate.
510+ * @param y2 the second point's <i>y</i> coordinate.
511+ * @since JDK1.0
512+ */
513+ public void drawLine(int x1, int y1, int x2, int y2) {
514+ addStrokeShape(new Line2D.Float(x1, y1, x2, y2));
515+ mPrintMetrics.draw(this);
516+ }
517+
518+
519+
520+ /**
521+ * Fills the specified rectangle.
522+ * The left and right edges of the rectangle are at
523+ * <code>x</code> and <code>x&nbsp;+&nbsp;width&nbsp;-&nbsp;1</code>.
524+ * The top and bottom edges are at
525+ * <code>y</code> and <code>y&nbsp;+&nbsp;height&nbsp;-&nbsp;1</code>.
526+ * The resulting rectangle covers an area
527+ * <code>width</code> pixels wide by
528+ * <code>height</code> pixels tall.
529+ * The rectangle is filled using the graphics context's current color.
530+ * @param x the <i>x</i> coordinate
531+ * of the rectangle to be filled.
532+ * @param y the <i>y</i> coordinate
533+ * of the rectangle to be filled.
534+ * @param width the width of the rectangle to be filled.
535+ * @param height the height of the rectangle to be filled.
536+ * @see java.awt.Graphics#fillRect
537+ * @see java.awt.Graphics#clearRect
538+ * @since JDK1.0
539+ */
540+ public void fillRect(int x, int y, int width, int height) {
541+
542+ addDrawingRect(new Rectangle2D.Float(x, y, width, height));
543+ mPrintMetrics.fill(this);
544+
545+ }
546+
547+ /**
548+ * Clears the specified rectangle by filling it with the background
549+ * color of the current drawing surface. This operation does not
550+ * use the current paint mode.
551+ * <p>
552+ * Beginning with Java&nbsp;1.1, the background color
553+ * of offscreen images may be system dependent. Applications should
554+ * use <code>setColor</code> followed by <code>fillRect</code> to
555+ * ensure that an offscreen image is cleared to a specific color.
556+ * @param x the <i>x</i> coordinate of the rectangle to clear.
557+ * @param y the <i>y</i> coordinate of the rectangle to clear.
558+ * @param width the width of the rectangle to clear.
559+ * @param height the height of the rectangle to clear.
560+ * @see java.awt.Graphics#fillRect(int, int, int, int)
561+ * @see java.awt.Graphics#drawRect
562+ * @see java.awt.Graphics#setColor(java.awt.Color)
563+ * @see java.awt.Graphics#setPaintMode
564+ * @see java.awt.Graphics#setXORMode(java.awt.Color)
565+ * @since JDK1.0
566+ */
567+ public void clearRect(int x, int y, int width, int height) {
568+ Rectangle2D.Float rect = new Rectangle2D.Float(x, y, width, height);
569+ addDrawingRect(rect);
570+ mPrintMetrics.clear(this);
571+ }
572+
573+ /**
574+ * Draws an outlined round-cornered rectangle using this graphics
575+ * context's current color. The left and right edges of the rectangle
576+ * are at <code>x</code> and <code>x&nbsp;+&nbsp;width</code>,
577+ * respectively. The top and bottom edges of the rectangle are at
578+ * <code>y</code> and <code>y&nbsp;+&nbsp;height</code>.
579+ * @param x the <i>x</i> coordinate of the rectangle to be drawn.
580+ * @param y the <i>y</i> coordinate of the rectangle to be drawn.
581+ * @param width the width of the rectangle to be drawn.
582+ * @param height the height of the rectangle to be drawn.
583+ * @param arcWidth the horizontal diameter of the arc
584+ * at the four corners.
585+ * @param arcHeight the vertical diameter of the arc
586+ * at the four corners.
587+ * @see java.awt.Graphics#fillRoundRect
588+ * @since JDK1.0
589+ */
590+ public void drawRoundRect(int x, int y, int width, int height,
591+ int arcWidth, int arcHeight) {
592+ addStrokeShape(new RoundRectangle2D.Float(x, y, width, height, arcWidth, arcHeight));
593+ mPrintMetrics.draw(this);
594+
595+ }
596+
597+ /**
598+ * Fills the specified rounded corner rectangle with the current color.
599+ * The left and right edges of the rectangle
600+ * are at <code>x</code> and <code>x&nbsp;+&nbsp;width&nbsp;-&nbsp;1</code>,
601+ * respectively. The top and bottom edges of the rectangle are at
602+ * <code>y</code> and <code>y&nbsp;+&nbsp;height&nbsp;-&nbsp;1</code>.
603+ * @param x the <i>x</i> coordinate of the rectangle to be filled.
604+ * @param y the <i>y</i> coordinate of the rectangle to be filled.
605+ * @param width the width of the rectangle to be filled.
606+ * @param height the height of the rectangle to be filled.
607+ * @param arcWidth the horizontal diameter
608+ * of the arc at the four corners.
609+ * @param arcHeight the vertical diameter
610+ * of the arc at the four corners.
611+ * @see java.awt.Graphics#drawRoundRect
612+ * @since JDK1.0
613+ */
614+ public void fillRoundRect(int x, int y, int width, int height,
615+ int arcWidth, int arcHeight) {
616+ Rectangle2D.Float rect = new Rectangle2D.Float(x, y,width, height);
617+ addDrawingRect(rect);
618+ mPrintMetrics.fill(this);
619+ }
620+
621+ /**
622+ * Draws the outline of an oval.
623+ * The result is a circle or ellipse that fits within the
624+ * rectangle specified by the <code>x</code>, <code>y</code>,
625+ * <code>width</code>, and <code>height</code> arguments.
626+ * <p>
627+ * The oval covers an area that is
628+ * <code>width&nbsp;+&nbsp;1</code> pixels wide
629+ * and <code>height&nbsp;+&nbsp;1</code> pixels tall.
630+ * @param x the <i>x</i> coordinate of the upper left
631+ * corner of the oval to be drawn.
632+ * @param y the <i>y</i> coordinate of the upper left
633+ * corner of the oval to be drawn.
634+ * @param width the width of the oval to be drawn.
635+ * @param height the height of the oval to be drawn.
636+ * @see java.awt.Graphics#fillOval
637+ * @since JDK1.0
638+ */
639+ public void drawOval(int x, int y, int width, int height) {
640+ addStrokeShape(new Rectangle2D.Float(x, y, width, height));
641+ mPrintMetrics.draw(this);
642+ }
643+
644+ /**
645+ * Fills an oval bounded by the specified rectangle with the
646+ * current color.
647+ * @param x the <i>x</i> coordinate of the upper left corner
648+ * of the oval to be filled.
649+ * @param y the <i>y</i> coordinate of the upper left corner
650+ * of the oval to be filled.
651+ * @param width the width of the oval to be filled.
652+ * @param height the height of the oval to be filled.
653+ * @see java.awt.Graphics#drawOval
654+ * @since JDK1.0
655+ */
656+ public void fillOval(int x, int y, int width, int height) {
657+ Rectangle2D.Float rect = new Rectangle2D.Float(x, y, width, height);
658+ addDrawingRect(rect);
659+ mPrintMetrics.fill(this);
660+
661+ }
662+
663+
664+ /**
665+ * Draws the outline of a circular or elliptical arc
666+ * covering the specified rectangle.
667+ * <p>
668+ * The resulting arc begins at <code>startAngle</code> and extends
669+ * for <code>arcAngle</code> degrees, using the current color.
670+ * Angles are interpreted such that 0&nbsp;degrees
671+ * is at the 3&nbsp;o'clock position.
672+ * A positive value indicates a counter-clockwise rotation
673+ * while a negative value indicates a clockwise rotation.
674+ * <p>
675+ * The center of the arc is the center of the rectangle whose origin
676+ * is (<i>x</i>,&nbsp;<i>y</i>) and whose size is specified by the
677+ * <code>width</code> and <code>height</code> arguments.
678+ * <p>
679+ * The resulting arc covers an area
680+ * <code>width&nbsp;+&nbsp;1</code> pixels wide
681+ * by <code>height&nbsp;+&nbsp;1</code> pixels tall.
682+ * @param x the <i>x</i> coordinate of the
683+ * upper-left corner of the arc to be drawn.
684+ * @param y the <i>y</i> coordinate of the
685+ * upper-left corner of the arc to be drawn.
686+ * @param width the width of the arc to be drawn.
687+ * @param height the height of the arc to be drawn.
688+ * @param startAngle the beginning angle.
689+ * @param arcAngle the angular extent of the arc,
690+ * relative to the start angle.
691+ * @see java.awt.Graphics#fillArc
692+ * @since JDK1.0
693+ */
694+ public void drawArc(int x, int y, int width, int height,
695+ int startAngle, int arcAngle) {
696+ addStrokeShape(new Rectangle2D.Float(x, y, width, height));
697+ mPrintMetrics.draw(this);
698+
699+ }
700+
701+ /**
702+ * Fills a circular or elliptical arc covering the specified rectangle.
703+ * <p>
704+ * The resulting arc begins at <code>startAngle</code> and extends
705+ * for <code>arcAngle</code> degrees.
706+ * Angles are interpreted such that 0&nbsp;degrees
707+ * is at the 3&nbsp;o'clock position.
708+ * A positive value indicates a counter-clockwise rotation
709+ * while a negative value indicates a clockwise rotation.
710+ * <p>
711+ * The center of the arc is the center of the rectangle whose origin
712+ * is (<i>x</i>,&nbsp;<i>y</i>) and whose size is specified by the
713+ * <code>width</code> and <code>height</code> arguments.
714+ * <p>
715+ * The resulting arc covers an area
716+ * <code>width&nbsp;+&nbsp;1</code> pixels wide
717+ * by <code>height&nbsp;+&nbsp;1</code> pixels tall.
718+ * @param x the <i>x</i> coordinate of the
719+ * upper-left corner of the arc to be filled.
720+ * @param y the <i>y</i> coordinate of the
721+ * upper-left corner of the arc to be filled.
722+ * @param width the width of the arc to be filled.
723+ * @param height the height of the arc to be filled.
724+ * @param startAngle the beginning angle.
725+ * @param arcAngle the angular extent of the arc,
726+ * relative to the start angle.
727+ * @see java.awt.Graphics#drawArc
728+ * @since JDK1.0
729+ */
730+ public void fillArc(int x, int y, int width, int height,
731+ int startAngle, int arcAngle) {
732+ Rectangle2D.Float rect = new Rectangle2D.Float(x, y,width, height);
733+ addDrawingRect(rect);
734+ mPrintMetrics.fill(this);
735+
736+ }
737+
738+ /**
739+ * Draws a sequence of connected lines defined by
740+ * arrays of <i>x</i> and <i>y</i> coordinates.
741+ * Each pair of (<i>x</i>,&nbsp;<i>y</i>) coordinates defines a point.
742+ * The figure is not closed if the first point
743+ * differs from the last point.
744+ * @param xPoints an array of <i>x</i> points
745+ * @param yPoints an array of <i>y</i> points
746+ * @param nPoints the total number of points
747+ * @see java.awt.Graphics#drawPolygon(int[], int[], int)
748+ * @since JDK1.1
749+ */
750+ public void drawPolyline(int xPoints[], int yPoints[],
751+ int nPoints) {
752+ if (nPoints > 0) {
753+ int x = xPoints[0];
754+ int y = yPoints[0];
755+
756+ for (int i = 1; i < nPoints; i++) {
757+ drawLine(x, y, xPoints[i], yPoints[i]);
758+ x = xPoints[i];
759+ y = yPoints[i];
760+ }
761+ }
762+
763+ }
764+
765+ /**
766+ * Draws a closed polygon defined by
767+ * arrays of <i>x</i> and <i>y</i> coordinates.
768+ * Each pair of (<i>x</i>,&nbsp;<i>y</i>) coordinates defines a point.
769+ * <p>
770+ * This method draws the polygon defined by <code>nPoint</code> line
771+ * segments, where the first <code>nPoint&nbsp;-&nbsp;1</code>
772+ * line segments are line segments from
773+ * <code>(xPoints[i&nbsp;-&nbsp;1],&nbsp;yPoints[i&nbsp;-&nbsp;1])</code>
774+ * to <code>(xPoints[i],&nbsp;yPoints[i])</code>, for
775+ * 1&nbsp;&le;&nbsp;<i>i</i>&nbsp;&le;&nbsp;<code>nPoints</code>.
776+ * The figure is automatically closed by drawing a line connecting
777+ * the final point to the first point, if those points are different.
778+ * @param xPoints a an array of <code>x</code> coordinates.
779+ * @param yPoints a an array of <code>y</code> coordinates.
780+ * @param nPoints a the total number of points.
781+ * @see java.awt.Graphics#fillPolygon
782+ * @see java.awt.Graphics#drawPolyline
783+ * @since JDK1.0
784+ */
785+ public void drawPolygon(int xPoints[], int yPoints[],
786+ int nPoints) {
787+ if (nPoints > 0) {
788+ drawPolyline(xPoints, yPoints, nPoints);
789+ drawLine(xPoints[nPoints - 1], yPoints[nPoints - 1],
790+ xPoints[0], yPoints[0]);
791+ }
792+
793+ }
794+
795+ /**
796+ * Fills a closed polygon defined by
797+ * arrays of <i>x</i> and <i>y</i> coordinates.
798+ * <p>
799+ * This method draws the polygon defined by <code>nPoint</code> line
800+ * segments, where the first <code>nPoint&nbsp;-&nbsp;1</code>
801+ * line segments are line segments from
802+ * <code>(xPoints[i&nbsp;-&nbsp;1],&nbsp;yPoints[i&nbsp;-&nbsp;1])</code>
803+ * to <code>(xPoints[i],&nbsp;yPoints[i])</code>, for
804+ * 1&nbsp;&le;&nbsp;<i>i</i>&nbsp;&le;&nbsp;<code>nPoints</code>.
805+ * The figure is automatically closed by drawing a line connecting
806+ * the final point to the first point, if those points are different.
807+ * <p>
808+ * The area inside the polygon is defined using an
809+ * even-odd fill rule, also known as the alternating rule.
810+ * @param xPoints a an array of <code>x</code> coordinates.
811+ * @param yPoints a an array of <code>y</code> coordinates.
812+ * @param nPoints a the total number of points.
813+ * @see java.awt.Graphics#drawPolygon(int[], int[], int)
814+ * @since JDK1.0
815+ */
816+ public void fillPolygon(int xPoints[], int yPoints[],
817+ int nPoints) {
818+ if (nPoints > 0) {
819+ int minX = xPoints[0];
820+ int minY = yPoints[0];
821+ int maxX = xPoints[0];
822+ int maxY = yPoints[0];
823+
824+ for (int i = 1; i < nPoints; i++) {
825+
826+ if (xPoints[i] < minX) {
827+ minX = xPoints[i];
828+ } else if (xPoints[i] > maxX) {
829+ maxX = xPoints[i];
830+ }
831+
832+ if (yPoints[i] < minY) {
833+ minY = yPoints[i];
834+ } else if (yPoints[i] > maxY) {
835+ maxY = yPoints[i];
836+ }
837+ }
838+
839+ addDrawingRect(minX, minY, maxX - minX, maxY - minY);
840+ }
841+
842+ mPrintMetrics.fill(this);
843+
844+ }
845+
846+
847+ /**
848+ * Draws the text given by the specified string, using this
849+ * graphics context's current font and color. The baseline of the
850+ * first character is at position (<i>x</i>,&nbsp;<i>y</i>) in this
851+ * graphics context's coordinate system.
852+ * @param str the string to be drawn.
853+ * @param x the <i>x</i> coordinate.
854+ * @param y the <i>y</i> coordinate.
855+ * @see java.awt.Graphics#drawBytes
856+ * @see java.awt.Graphics#drawChars
857+ * @since JDK1.0
858+ */
859+ public void drawString(String str, int x, int y) {
860+
861+ drawString(str, (float)x, (float)y);
862+ }
863+
864+ /**
865+ * Draws the text given by the specified iterator, using this
866+ * graphics context's current color. The iterator has to specify a font
867+ * for each character. The baseline of the
868+ * first character is at position (<i>x</i>,&nbsp;<i>y</i>) in this
869+ * graphics context's coordinate system.
870+ * The rendering attributes applied include the clip, transform,
871+ * paint or color, and composite attributes.
872+ * For characters in script systems such as Hebrew and Arabic,
873+ * the glyphs may be draw from right to left, in which case the
874+ * coordinate supplied is the the location of the leftmost character
875+ * on the baseline.
876+ * @param iterator the iterator whose text is to be drawn
877+ * @param x,y the coordinates where the iterator's text should be drawn.
878+ * @see #setPaint
879+ * @see java.awt.Graphics#setColor
880+ * @see #setTransform
881+ * @see #setComposite
882+ * @see #setClip
883+ */
884+ public void drawString(AttributedCharacterIterator iterator,
885+ int x, int y) {
886+
887+ drawString(iterator, (float)x, (float)y);
888+ }
889+
890+ /**
891+ * Draws the text given by the specified iterator, using this
892+ * graphics context's current color. The iterator has to specify a font
893+ * for each character. The baseline of the
894+ * first character is at position (<i>x</i>,&nbsp;<i>y</i>) in this
895+ * graphics context's coordinate system.
896+ * The rendering attributes applied include the clip, transform,
897+ * paint or color, and composite attributes.
898+ * For characters in script systems such as Hebrew and Arabic,
899+ * the glyphs may be draw from right to left, in which case the
900+ * coordinate supplied is the the location of the leftmost character
901+ * on the baseline.
902+ * @param iterator the iterator whose text is to be drawn
903+ * @param x,y the coordinates where the iterator's text should be drawn.
904+ * @see #setPaint
905+ * @see java.awt.Graphics#setColor
906+ * @see #setTransform
907+ * @see #setComposite
908+ * @see #setClip
909+ */
910+ public void drawString(AttributedCharacterIterator iterator,
911+ float x, float y) {
912+ if (iterator == null) {
913+ throw new
914+ NullPointerException("AttributedCharacterIterator is null");
915+ }
916+
917+ TextLayout layout = new TextLayout(iterator, getFontRenderContext());
918+ layout.draw(this, x, y);
919+ }
920+
921+
922+ /**
923+ * Draws as much of the specified image as is currently available.
924+ * The image is drawn with its top-left corner at
925+ * (<i>x</i>,&nbsp;<i>y</i>) in this graphics context's coordinate
926+ * space. Transparent pixels in the image do not affect whatever
927+ * pixels are already there.
928+ * <p>
929+ * This method returns immediately in all cases, even if the
930+ * complete image has not yet been loaded, and it has not been dithered
931+ * and converted for the current output device.
932+ * <p>
933+ * If the image has not yet been completely loaded, then
934+ * <code>drawImage</code> returns <code>false</code>. As more of
935+ * the image becomes available, the process that draws the image notifies
936+ * the specified image observer.
937+ * @param img the specified image to be drawn.
938+ * @param x the <i>x</i> coordinate.
939+ * @param y the <i>y</i> coordinate.
940+ * @param observer object to be notified as more of
941+ * the image is converted.
942+ * @see java.awt.Image
943+ * @see java.awt.image.ImageObserver
944+ * @see java.awt.image.ImageObserver#imageUpdate(java.awt.Image, int, int, int, int, int)
945+ * @since JDK1.0
946+ */
947+ public boolean drawImage(Image img, int x, int y,
948+ ImageObserver observer) {
949+
950+ if (img == null) {
951+ return true;
952+ }
953+
954+ /* The ImageWaiter creation does not return until the
955+ * image is loaded.
956+ */
957+ ImageWaiter dim = new ImageWaiter(img);
958+
959+ addDrawingRect(x, y, dim.getWidth(), dim.getHeight());
960+ mPrintMetrics.drawImage(this, img);
961+
962+ return mGraphics.drawImage(img, x, y, observer);
963+ }
964+
965+
966+ /**
967+ * Draws as much of the specified image as has already been scaled
968+ * to fit inside the specified rectangle.
969+ * <p>
970+ * The image is drawn inside the specified rectangle of this
971+ * graphics context's coordinate space, and is scaled if
972+ * necessary. Transparent pixels do not affect whatever pixels
973+ * are already there.
974+ * <p>
975+ * This method returns immediately in all cases, even if the
976+ * entire image has not yet been scaled, dithered, and converted
977+ * for the current output device.
978+ * If the current output representation is not yet complete, then
979+ * <code>drawImage</code> returns <code>false</code>. As more of
980+ * the image becomes available, the process that draws the image notifies
981+ * the image observer by calling its <code>imageUpdate</code> method.
982+ * <p>
983+ * A scaled version of an image will not necessarily be
984+ * available immediately just because an unscaled version of the
985+ * image has been constructed for this output device. Each size of
986+ * the image may be cached separately and generated from the original
987+ * data in a separate image production sequence.
988+ * @param img the specified image to be drawn.
989+ * @param x the <i>x</i> coordinate.
990+ * @param y the <i>y</i> coordinate.
991+ * @param width the width of the rectangle.
992+ * @param height the height of the rectangle.
993+ * @param observer object to be notified as more of
994+ * the image is converted.
995+ * @see java.awt.Image
996+ * @see java.awt.image.ImageObserver
997+ * @see java.awt.image.ImageObserver#imageUpdate(java.awt.Image, int, int, int, int, int)
998+ * @since JDK1.0
999+ */
1000+ public boolean drawImage(Image img, int x, int y,
1001+ int width, int height,
1002+ ImageObserver observer) {
1003+
1004+ if (img == null) {
1005+ return true;
1006+ }
1007+ addDrawingRect(x, y, width, height);
1008+ mPrintMetrics.drawImage(this, img);
1009+
1010+ return mGraphics.drawImage(img, x, y, width, height, observer);
1011+
1012+ }
1013+
1014+ /**
1015+ * Draws as much of the specified image as is currently available.
1016+ * The image is drawn with its top-left corner at
1017+ * (<i>x</i>,&nbsp;<i>y</i>) in this graphics context's coordinate
1018+ * space. Transparent pixels are drawn in the specified
1019+ * background color.
1020+ * <p>
1021+ * This operation is equivalent to filling a rectangle of the
1022+ * width and height of the specified image with the given color and then
1023+ * drawing the image on top of it, but possibly more efficient.
1024+ * <p>
1025+ * This method returns immediately in all cases, even if the
1026+ * complete image has not yet been loaded, and it has not been dithered
1027+ * and converted for the current output device.
1028+ * <p>
1029+ * If the image has not yet been completely loaded, then
1030+ * <code>drawImage</code> returns <code>false</code>. As more of
1031+ * the image becomes available, the process that draws the image notifies
1032+ * the specified image observer.
1033+ * @param img the specified image to be drawn.
1034+ * @param x the <i>x</i> coordinate.
1035+ * @param y the <i>y</i> coordinate.
1036+ * @param bgcolor the background color to paint under the
1037+ * non-opaque portions of the image.
1038+ * @param observer object to be notified as more of
1039+ * the image is converted.
1040+ * @see java.awt.Image
1041+ * @see java.awt.image.ImageObserver
1042+ * @see java.awt.image.ImageObserver#imageUpdate(java.awt.Image, int, int, int, int, int)
1043+ * @since JDK1.0
1044+ */
1045+ public boolean drawImage(Image img, int x, int y,
1046+ Color bgcolor,
1047+ ImageObserver observer) {
1048+
1049+ if (img == null) {
1050+ return true;
1051+ }
1052+
1053+ /* The ImageWaiter creation does not return until the
1054+ * image is loaded.
1055+ */
1056+ ImageWaiter dim = new ImageWaiter(img);
1057+
1058+ addDrawingRect(x, y, dim.getWidth(), dim.getHeight());
1059+ mPrintMetrics.drawImage(this, img);
1060+
1061+ return mGraphics.drawImage(img, x, y, bgcolor, observer);
1062+ }
1063+
1064+
1065+ /**
1066+ * Draws as much of the specified image as has already been scaled
1067+ * to fit inside the specified rectangle.
1068+ * <p>
1069+ * The image is drawn inside the specified rectangle of this
1070+ * graphics context's coordinate space, and is scaled if
1071+ * necessary. Transparent pixels are drawn in the specified
1072+ * background color.
1073+ * This operation is equivalent to filling a rectangle of the
1074+ * width and height of the specified image with the given color and then
1075+ * drawing the image on top of it, but possibly more efficient.
1076+ * <p>
1077+ * This method returns immediately in all cases, even if the
1078+ * entire image has not yet been scaled, dithered, and converted
1079+ * for the current output device.
1080+ * If the current output representation is not yet complete then
1081+ * <code>drawImage</code> returns <code>false</code>. As more of
1082+ * the image becomes available, the process that draws the image notifies
1083+ * the specified image observer.
1084+ * <p>
1085+ * A scaled version of an image will not necessarily be
1086+ * available immediately just because an unscaled version of the
1087+ * image has been constructed for this output device. Each size of
1088+ * the image may be cached separately and generated from the original
1089+ * data in a separate image production sequence.
1090+ * @param img the specified image to be drawn.
1091+ * @param x the <i>x</i> coordinate.
1092+ * @param y the <i>y</i> coordinate.
1093+ * @param width the width of the rectangle.
1094+ * @param height the height of the rectangle.
1095+ * @param bgcolor the background color to paint under the
1096+ * non-opaque portions of the image.
1097+ * @param observer object to be notified as more of
1098+ * the image is converted.
1099+ * @see java.awt.Image
1100+ * @see java.awt.image.ImageObserver
1101+ * @see java.awt.image.ImageObserver#imageUpdate(java.awt.Image, int, int, int, int, int)
1102+ * @since JDK1.0
1103+ */
1104+ public boolean drawImage(Image img, int x, int y,
1105+ int width, int height,
1106+ Color bgcolor,
1107+ ImageObserver observer) {
1108+
1109+ if (img == null) {
1110+ return true;
1111+ }
1112+
1113+ addDrawingRect(x, y, width, height);
1114+ mPrintMetrics.drawImage(this, img);
1115+
1116+ return mGraphics.drawImage(img, x, y, width, height, bgcolor, observer);
1117+
1118+ }
1119+
1120+ /**
1121+ * Draws as much of the specified area of the specified image as is
1122+ * currently available, scaling it on the fly to fit inside the
1123+ * specified area of the destination drawable surface. Transparent pixels
1124+ * do not affect whatever pixels are already there.
1125+ * <p>
1126+ * This method returns immediately in all cases, even if the
1127+ * image area to be drawn has not yet been scaled, dithered, and converted
1128+ * for the current output device.
1129+ * If the current output representation is not yet complete then
1130+ * <code>drawImage</code> returns <code>false</code>. As more of
1131+ * the image becomes available, the process that draws the image notifies
1132+ * the specified image observer.
1133+ * <p>
1134+ * This method always uses the unscaled version of the image
1135+ * to render the scaled rectangle and performs the required
1136+ * scaling on the fly. It does not use a cached, scaled version
1137+ * of the image for this operation. Scaling of the image from source
1138+ * to destination is performed such that the first coordinate
1139+ * of the source rectangle is mapped to the first coordinate of
1140+ * the destination rectangle, and the second source coordinate is
1141+ * mapped to the second destination coordinate. The subimage is
1142+ * scaled and flipped as needed to preserve those mappings.
1143+ * @param img the specified image to be drawn
1144+ * @param dx1 the <i>x</i> coordinate of the first corner of the
1145+ * destination rectangle.
1146+ * @param dy1 the <i>y</i> coordinate of the first corner of the
1147+ * destination rectangle.
1148+ * @param dx2 the <i>x</i> coordinate of the second corner of the
1149+ * destination rectangle.
1150+ * @param dy2 the <i>y</i> coordinate of the second corner of the
1151+ * destination rectangle.
1152+ * @param sx1 the <i>x</i> coordinate of the first corner of the
1153+ * source rectangle.
1154+ * @param sy1 the <i>y</i> coordinate of the first corner of the
1155+ * source rectangle.
1156+ * @param sx2 the <i>x</i> coordinate of the second corner of the
1157+ * source rectangle.
1158+ * @param sy2 the <i>y</i> coordinate of the second corner of the
1159+ * source rectangle.
1160+ * @param observer object to be notified as more of the image is
1161+ * scaled and converted.
1162+ * @see java.awt.Image
1163+ * @see java.awt.image.ImageObserver
1164+ * @see java.awt.image.ImageObserver#imageUpdate(java.awt.Image, int, int, int, int, int)
1165+ * @since JDK1.1
1166+ */
1167+ public boolean drawImage(Image img,
1168+ int dx1, int dy1, int dx2, int dy2,
1169+ int sx1, int sy1, int sx2, int sy2,
1170+ ImageObserver observer) {
1171+
1172+ if (img == null) {
1173+ return true;
1174+ }
1175+
1176+ int width = dx2 - dx1;
1177+ int height = dy2 - dy1;
1178+
1179+ addDrawingRect(dx1, dy1, width, height);
1180+ mPrintMetrics.drawImage(this, img);
1181+
1182+ return mGraphics.drawImage(img, dx1, dy1, dx2, dy2,
1183+ sx1, sy1, sx2, sy2, observer);
1184+
1185+ }
1186+
1187+
1188+ /**
1189+ * Draws as much of the specified area of the specified image as is
1190+ * currently available, scaling it on the fly to fit inside the
1191+ * specified area of the destination drawable surface.
1192+ * <p>
1193+ * Transparent pixels are drawn in the specified background color.
1194+ * This operation is equivalent to filling a rectangle of the
1195+ * width and height of the specified image with the given color and then
1196+ * drawing the image on top of it, but possibly more efficient.
1197+ * <p>
1198+ * This method returns immediately in all cases, even if the
1199+ * image area to be drawn has not yet been scaled, dithered, and converted
1200+ * for the current output device.
1201+ * If the current output representation is not yet complete then
1202+ * <code>drawImage</code> returns <code>false</code>. As more of
1203+ * the image becomes available, the process that draws the image notifies
1204+ * the specified image observer.
1205+ * <p>
1206+ * This method always uses the unscaled version of the image
1207+ * to render the scaled rectangle and performs the required
1208+ * scaling on the fly. It does not use a cached, scaled version
1209+ * of the image for this operation. Scaling of the image from source
1210+ * to destination is performed such that the first coordinate
1211+ * of the source rectangle is mapped to the first coordinate of
1212+ * the destination rectangle, and the second source coordinate is
1213+ * mapped to the second destination coordinate. The subimage is
1214+ * scaled and flipped as needed to preserve those mappings.
1215+ * @param img the specified image to be drawn
1216+ * @param dx1 the <i>x</i> coordinate of the first corner of the
1217+ * destination rectangle.
1218+ * @param dy1 the <i>y</i> coordinate of the first corner of the
1219+ * destination rectangle.
1220+ * @param dx2 the <i>x</i> coordinate of the second corner of the
1221+ * destination rectangle.
1222+ * @param dy2 the <i>y</i> coordinate of the second corner of the
1223+ * destination rectangle.
1224+ * @param sx1 the <i>x</i> coordinate of the first corner of the
1225+ * source rectangle.
1226+ * @param sy1 the <i>y</i> coordinate of the first corner of the
1227+ * source rectangle.
1228+ * @param sx2 the <i>x</i> coordinate of the second corner of the
1229+ * source rectangle.
1230+ * @param sy2 the <i>y</i> coordinate of the second corner of the
1231+ * source rectangle.
1232+ * @param bgcolor the background color to paint under the
1233+ * non-opaque portions of the image.
1234+ * @param observer object to be notified as more of the image is
1235+ * scaled and converted.
1236+ * @see java.awt.Image
1237+ * @see java.awt.image.ImageObserver
1238+ * @see java.awt.image.ImageObserver#imageUpdate(java.awt.Image, int, int, int, int, int)
1239+ * @since JDK1.1
1240+ */
1241+ public boolean drawImage(Image img,
1242+ int dx1, int dy1, int dx2, int dy2,
1243+ int sx1, int sy1, int sx2, int sy2,
1244+ Color bgcolor,
1245+ ImageObserver observer) {
1246+
1247+ if (img == null) {
1248+ return true;
1249+ }
1250+
1251+ int width = dx2 - dx1;
1252+ int height = dy2 - dy1;
1253+
1254+ addDrawingRect(dx1, dy1, width, height);
1255+ mPrintMetrics.drawImage(this, img);
1256+
1257+ return mGraphics.drawImage(img, dx1, dy1, dx2, dy2,
1258+ sx1, sy1, sx2, sy2, bgcolor, observer);
1259+
1260+ }
1261+
1262+
1263+ /**
1264+ * Draws an image, applying a transform from image space into user space
1265+ * before drawing.
1266+ * The transformation from user space into device space is done with
1267+ * the current transform in the Graphics2D.
1268+ * The given transformation is applied to the image before the
1269+ * transform attribute in the Graphics2D state is applied.
1270+ * The rendering attributes applied include the clip, transform,
1271+ * and composite attributes. Note that the result is
1272+ * undefined, if the given transform is noninvertible.
1273+ * @param img The image to be drawn.
1274+ * @param xform The transformation from image space into user space.
1275+ * @see #transform
1276+ * @see #setTransform
1277+ * @see #setComposite
1278+ * @see #clip
1279+ * @see #setClip
1280+ */
1281+ public void drawRenderedImage(RenderedImage img,
1282+ AffineTransform xform) {
1283+
1284+ if (img == null) {
1285+ return;
1286+ }
1287+
1288+ mPrintMetrics.drawImage(this, img);
1289+ mDrawingArea.addInfinite();
1290+ }
1291+
1292+
1293+ public void drawRenderableImage(RenderableImage img,
1294+ AffineTransform xform) {
1295+
1296+ if (img == null) {
1297+ return;
1298+ }
1299+
1300+ mPrintMetrics.drawImage(this, img);
1301+ mDrawingArea.addInfinite();
1302+ }
1303+
1304+ /**
1305+ * Disposes of this graphics context and releases
1306+ * any system resources that it is using.
1307+ * A <code>Graphics</code> object cannot be used after
1308+ * <code>dispose</code>has been called.
1309+ * <p>
1310+ * When a Java program runs, a large number of <code>Graphics</code>
1311+ * objects can be created within a short time frame.
1312+ * Although the finalization process of the garbage collector
1313+ * also disposes of the same system resources, it is preferable
1314+ * to manually free the associated resources by calling this
1315+ * method rather than to rely on a finalization process which
1316+ * may not run to completion for a long period of time.
1317+ * <p>
1318+ * Graphics objects which are provided as arguments to the
1319+ * <code>paint</code> and <code>update</code> methods
1320+ * of components are automatically released by the system when
1321+ * those methods return. For efficiency, programmers should
1322+ * call <code>dispose</code> when finished using
1323+ * a <code>Graphics</code> object only if it was created
1324+ * directly from a component or another <code>Graphics</code> object.
1325+ * @see java.awt.Graphics#finalize
1326+ * @see java.awt.Component#paint
1327+ * @see java.awt.Component#update
1328+ * @see java.awt.Component#getGraphics
1329+ * @see java.awt.Graphics#create
1330+ * @since JDK1.0
1331+ */
1332+ public void dispose() {
1333+ mGraphics.dispose();
1334+ }
1335+
1336+ /**
1337+ * Empty finalizer as no clean up needed here.
1338+ */
1339+ public void finalize() {
1340+ }
1341+
1342+/* The Delegated Graphics2D Methods */
1343+
1344+ /**
1345+ * Strokes the outline of a Shape using the settings of the current
1346+ * graphics state. The rendering attributes applied include the
1347+ * clip, transform, paint or color, composite and stroke attributes.
1348+ * @param s The shape to be drawn.
1349+ * @see #setStroke
1350+ * @see #setPaint
1351+ * @see java.awt.Graphics#setColor
1352+ * @see #transform
1353+ * @see #setTransform
1354+ * @see #clip
1355+ * @see #setClip
1356+ * @see #setComposite
1357+ */
1358+ public void draw(Shape s) {
1359+ addStrokeShape(s);
1360+ mPrintMetrics.draw(this);
1361+ }
1362+
1363+
1364+ /**
1365+ * Draws an image, applying a transform from image space into user space
1366+ * before drawing.
1367+ * The transformation from user space into device space is done with
1368+ * the current transform in the Graphics2D.
1369+ * The given transformation is applied to the image before the
1370+ * transform attribute in the Graphics2D state is applied.
1371+ * The rendering attributes applied include the clip, transform,
1372+ * and composite attributes. Note that the result is
1373+ * undefined, if the given transform is noninvertible.
1374+ * @param img The image to be drawn.
1375+ * @param xform The transformation from image space into user space.
1376+ * @param obs The image observer to be notified as more of the image
1377+ * is converted.
1378+ * @see #transform
1379+ * @see #setTransform
1380+ * @see #setComposite
1381+ * @see #clip
1382+ * @see #setClip
1383+ */
1384+ public boolean drawImage(Image img,
1385+ AffineTransform xform,
1386+ ImageObserver obs) {
1387+
1388+ if (img == null) {
1389+ return true;
1390+ }
1391+
1392+ mDrawingArea.addInfinite();
1393+ mPrintMetrics.drawImage(this, img);
1394+
1395+ return mGraphics.drawImage(img, xform, obs);
1396+
1397+
1398+// if (mDrawingArea[0] != null) {
1399+// Rectangle2D.Double bbox = new Rectangle2D.Double();
1400+// Point2D leftTop = new Point2D.Double(0, 0);
1401+// Point2D rightBottom = new Point2D.Double(getImageWidth(img),
1402+// getImageHeight(img));
1403+
1404+// xform.transform(leftTop, leftTop);
1405+// xform.transform(rightBottom, rightBottom);
1406+
1407+// bbox.setBoundsFromDiagonal(leftTop, rightBottom);
1408+// addDrawingRect(bbox);
1409+
1410+// }
1411+ }
1412+
1413+
1414+ /**
1415+ * Draws a BufferedImage that is filtered with a BufferedImageOp.
1416+ * The rendering attributes applied include the clip, transform
1417+ * and composite attributes. This is equivalent to:
1418+ * <pre>
1419+ * img1 = op.filter(img, null);
1420+ * drawImage(img1, new AffineTransform(1f,0f,0f,1f,x,y), null);
1421+ * </pre>
1422+ * @param op The filter to be applied to the image before drawing.
1423+ * @param img The BufferedImage to be drawn.
1424+ * @param x,y The location in user space where the image should be drawn.
1425+ * @see #transform
1426+ * @see #setTransform
1427+ * @see #setComposite
1428+ * @see #clip
1429+ * @see #setClip
1430+ */
1431+ public void drawImage(BufferedImage img,
1432+ BufferedImageOp op,
1433+ int x,
1434+ int y) {
1435+
1436+ if (img == null) {
1437+ return;
1438+ }
1439+
1440+ mPrintMetrics.drawImage(this, (RenderedImage) img);
1441+ mDrawingArea.addInfinite();
1442+ }
1443+
1444+
1445+ /**
1446+ * Draws a string of text.
1447+ * The rendering attributes applied include the clip, transform,
1448+ * paint or color, font and composite attributes.
1449+ * @param s The string to be drawn.
1450+ * @param x,y The coordinates where the string should be drawn.
1451+ * @see #setPaint
1452+ * @see java.awt.Graphics#setColor
1453+ * @see java.awt.Graphics#setFont
1454+ * @see #transform
1455+ * @see #setTransform
1456+ * @see #setComposite
1457+ * @see #clip
1458+ * @see #setClip
1459+ */
1460+ public void drawString(String str,
1461+ float x,
1462+ float y) {
1463+
1464+ if (str.length() == 0) {
1465+ return;
1466+ }
1467+ /* Logical bounds close enough and is used for GlyphVector */
1468+ FontRenderContext frc = getFontRenderContext();
1469+ Rectangle2D bbox = getFont().getStringBounds(str, frc);
1470+ addDrawingRect(bbox, x, y);
1471+ mPrintMetrics.drawText(this);
1472+ }
1473+
1474+ /**
1475+ * Draws a GlyphVector.
1476+ * The rendering attributes applied include the clip, transform,
1477+ * paint or color, and composite attributes. The GlyphVector specifies
1478+ * individual glyphs from a Font.
1479+ * @param g The GlyphVector to be drawn.
1480+ * @param x,y The coordinates where the glyphs should be drawn.
1481+ * @see #setPaint
1482+ * @see java.awt.Graphics#setColor
1483+ * @see #transform
1484+ * @see #setTransform
1485+ * @see #setComposite
1486+ * @see #clip
1487+ * @see #setClip
1488+ */
1489+ public void drawGlyphVector(GlyphVector g,
1490+ float x,
1491+ float y) {
1492+
1493+ Rectangle2D bbox = g.getLogicalBounds();
1494+ addDrawingRect(bbox, x, y);
1495+ mPrintMetrics.drawText(this);
1496+
1497+ }
1498+
1499+ /**
1500+ * Fills the interior of a Shape using the settings of the current
1501+ * graphics state. The rendering attributes applied include the
1502+ * clip, transform, paint or color, and composite.
1503+ * @see #setPaint
1504+ * @see java.awt.Graphics#setColor
1505+ * @see #transform
1506+ * @see #setTransform
1507+ * @see #setComposite
1508+ * @see #clip
1509+ * @see #setClip
1510+ */
1511+ public void fill(Shape s) {
1512+ addDrawingRect(s.getBounds());
1513+ mPrintMetrics.fill(this);
1514+
1515+ }
1516+
1517+
1518+ /**
1519+ * Checks to see if the outline of a Shape intersects the specified
1520+ * Rectangle in device space.
1521+ * The rendering attributes taken into account include the
1522+ * clip, transform, and stroke attributes.
1523+ * @param rect The area in device space to check for a hit.
1524+ * @param s The shape to check for a hit.
1525+ * @param onStroke Flag to choose between testing the stroked or
1526+ * the filled shape.
1527+ * @return True if there is a hit, false otherwise.
1528+ * @see #setStroke
1529+ * @see #fill
1530+ * @see #draw
1531+ * @see #transform
1532+ * @see #setTransform
1533+ * @see #clip
1534+ * @see #setClip
1535+ */
1536+ public boolean hit(Rectangle rect,
1537+ Shape s,
1538+ boolean onStroke) {
1539+
1540+ return mGraphics.hit(rect, s, onStroke);
1541+ }
1542+
1543+ /**
1544+ * Sets the Composite in the current graphics state. Composite is used
1545+ * in all drawing methods such as drawImage, drawString, draw,
1546+ * and fill. It specifies how new pixels are to be combined with
1547+ * the existing pixels on the graphics device in the rendering process.
1548+ * @param comp The Composite object to be used for drawing.
1549+ * @see java.awt.Graphics#setXORMode
1550+ * @see java.awt.Graphics#setPaintMode
1551+ * @see AlphaComposite
1552+ */
1553+ public void setComposite(Composite comp) {
1554+ mGraphics.setComposite(comp);
1555+ }
1556+
1557+
1558+ /**
1559+ * Sets the Paint in the current graphics state.
1560+ * @param paint The Paint object to be used to generate color in
1561+ * the rendering process.
1562+ * @see java.awt.Graphics#setColor
1563+ * @see GradientPaint
1564+ * @see TexturePaint
1565+ */
1566+ public void setPaint(Paint paint) {
1567+ mGraphics.setPaint(paint);
1568+ }
1569+
1570+ /**
1571+ * Sets the Stroke in the current graphics state.
1572+ * @param s The Stroke object to be used to stroke a Shape in
1573+ * the rendering process.
1574+ * @see BasicStroke
1575+ */
1576+ public void setStroke(Stroke s) {
1577+ mGraphics.setStroke(s);
1578+ }
1579+
1580+ /**
1581+ * Sets the preferences for the rendering algorithms.
1582+ * Hint categories include controls for rendering quality and
1583+ * overall time/quality trade-off in the rendering process.
1584+ * @param hintCategory The category of hint to be set.
1585+ * @param hintValue The value indicating preferences for the specified
1586+ * hint category.
1587+ * @see RenderingHints
1588+ */
1589+ public void setRenderingHint(Key hintCategory, Object hintValue) {
1590+ mGraphics.setRenderingHint(hintCategory, hintValue);
1591+ }
1592+
1593+ /**
1594+ * Returns the preferences for the rendering algorithms.
1595+ * @param hintCategory The category of hint to be set.
1596+ * @return The preferences for rendering algorithms.
1597+ * @see RenderingHings
1598+ */
1599+ public Object getRenderingHint(Key hintCategory) {
1600+ return mGraphics.getRenderingHint(hintCategory);
1601+ }
1602+
1603+ /**
1604+ * Sets the preferences for the rendering algorithms.
1605+ * Hint categories include controls for rendering quality and
1606+ * overall time/quality trade-off in the rendering process.
1607+ * @param hints The rendering hints to be set
1608+ * @see RenderingHints
1609+ */
1610+ public void setRenderingHints(Map<?,?> hints) {
1611+ mGraphics.setRenderingHints(hints);
1612+ }
1613+
1614+ /**
1615+ * Adds a number of preferences for the rendering algorithms.
1616+ * Hint categories include controls for rendering quality and
1617+ * overall time/quality trade-off in the rendering process.
1618+ * @param hints The rendering hints to be set
1619+ * @see RenderingHints
1620+ */
1621+ public void addRenderingHints(Map<?,?> hints) {
1622+ mGraphics.addRenderingHints(hints);
1623+ }
1624+
1625+ /**
1626+ * Gets the preferences for the rendering algorithms.
1627+ * Hint categories include controls for rendering quality and
1628+ * overall time/quality trade-off in the rendering process.
1629+ * @see RenderingHints
1630+ */
1631+ public RenderingHints getRenderingHints() {
1632+ return mGraphics.getRenderingHints();
1633+ }
1634+
1635+ /**
1636+ * Composes a Transform object with the transform in this
1637+ * Graphics2D according to the rule last-specified-first-applied.
1638+ * If the currrent transform is Cx, the result of composition
1639+ * with Tx is a new transform Cx'. Cx' becomes the current
1640+ * transform for this Graphics2D.
1641+ * Transforming a point p by the updated transform Cx' is
1642+ * equivalent to first transforming p by Tx and then transforming
1643+ * the result by the original transform Cx. In other words,
1644+ * Cx'(p) = Cx(Tx(p)).
1645+ * A copy of the Tx is made, if necessary, so further
1646+ * modifications to Tx do not affect rendering.
1647+ * @param Tx The Transform object to be composed with the current
1648+ * transform.
1649+ * @see #setTransform
1650+ * @see TransformChain
1651+ * @see AffineTransform
1652+ */
1653+ public void transform(AffineTransform Tx) {
1654+ mGraphics.transform(Tx);
1655+ }
1656+
1657+ /**
1658+ * Sets the Transform in the current graphics state.
1659+ * @param Tx The Transform object to be used in the rendering process.
1660+ * @see #transform
1661+ * @see TransformChain
1662+ * @see AffineTransform
1663+ */
1664+ public void setTransform(AffineTransform Tx) {
1665+ mGraphics.setTransform(Tx);
1666+ }
1667+
1668+ /**
1669+ * Returns the current Transform in the Graphics2D state.
1670+ * @see #transform
1671+ * @see #setTransform
1672+ */
1673+ public AffineTransform getTransform() {
1674+ return mGraphics.getTransform();
1675+ }
1676+
1677+ /**
1678+ * Returns the current Paint in the Graphics2D state.
1679+ * @see #setPaint
1680+ * @see java.awt.Graphics#setColor
1681+ */
1682+ public Paint getPaint() {
1683+ return mGraphics.getPaint();
1684+ }
1685+
1686+ /**
1687+ * Returns the current Composite in the Graphics2D state.
1688+ * @see #setComposite
1689+ */
1690+ public Composite getComposite() {
1691+ return mGraphics.getComposite();
1692+ }
1693+
1694+ /**
1695+ * Sets the background color in this context used for clearing a region.
1696+ * When Graphics2D is constructed for a component, the backgroung color is
1697+ * inherited from the component. Setting the background color in the
1698+ * Graphics2D context only affects the subsequent clearRect() calls and
1699+ * not the background color of the component. To change the background
1700+ * of the component, use appropriate methods of the component.
1701+ * @param color The background color that should be used in
1702+ * subsequent calls to clearRect().
1703+ * @see getBackground
1704+ * @see Graphics.clearRect()
1705+ */
1706+ public void setBackground(Color color) {
1707+ mGraphics.setBackground(color);
1708+ }
1709+
1710+ /**
1711+ * Returns the background color used for clearing a region.
1712+ * @see setBackground
1713+ */
1714+ public Color getBackground() {
1715+ return mGraphics.getBackground();
1716+ }
1717+
1718+ /**
1719+ * Returns the current Stroke in the Graphics2D state.
1720+ * @see setStroke
1721+ */
1722+ public Stroke getStroke() {
1723+ return mGraphics.getStroke();
1724+ }
1725+
1726+ /**
1727+ * Intersects the current clip with the interior of the specified Shape
1728+ * and sets the current clip to the resulting intersection.
1729+ * The indicated shape is transformed with the current transform in the
1730+ * Graphics2D state before being intersected with the current clip.
1731+ * This method is used to make the current clip smaller.
1732+ * To make the clip larger, use any setClip method.
1733+ * @param s The Shape to be intersected with the current clip.
1734+ */
1735+ public void clip(Shape s) {
1736+ mGraphics.clip(s);
1737+ }
1738+
1739+ /**
1740+ * Return true if the Rectangle <code>rect</code>
1741+ * intersects the area into which the application
1742+ * has drawn.
1743+ */
1744+ public boolean hitsDrawingArea(Rectangle rect) {
1745+
1746+ return mDrawingArea.intersects((float) rect.getMinY(),
1747+ (float) rect.getMaxY());
1748+ }
1749+
1750+ /**
1751+ * Return the object holding the summary of the
1752+ * drawing done by the printing application.
1753+ */
1754+ public PeekMetrics getMetrics() {
1755+ return mPrintMetrics;
1756+ }
1757+
1758+ /* Support Routines for Calculating the Drawing Area */
1759+
1760+ /**
1761+ * Shift the rectangle 'rect' to the position ('x', 'y')
1762+ * and add the resulting rectangle to the area representing
1763+ * the part of the page which is drawn into.
1764+ */
1765+ private void addDrawingRect(Rectangle2D rect, float x, float y) {
1766+
1767+ addDrawingRect((float) (rect.getX() + x),
1768+ (float) (rect.getY() + y),
1769+ (float) rect.getWidth(),
1770+ (float) rect.getHeight());
1771+
1772+ }
1773+
1774+ private void addDrawingRect(float x, float y, float width, float height) {
1775+
1776+ Rectangle2D.Float bbox = new Rectangle2D.Float(x, y, width, height);
1777+ addDrawingRect(bbox);
1778+ }
1779+
1780+ /**
1781+ * Add the rectangle 'rect' to the area representing
1782+ * the part of the page which is drawn into.
1783+ */
1784+ private void addDrawingRect(Rectangle2D rect) {
1785+
1786+ /* For testing purposes the following line can be uncommented.
1787+ When uncommented it causes the entire page to be rasterized
1788+ thus eliminating errors caused by a faulty bounding box
1789+ calculation.
1790+ */
1791+ //mDrawingArea.addInfinite();
1792+
1793+
1794+
1795+ AffineTransform matrix = getTransform();
1796+
1797+ Shape transShape = matrix.createTransformedShape(rect);
1798+
1799+ Rectangle2D transRect = transShape.getBounds2D();
1800+
1801+ mDrawingArea.add((float) transRect.getMinY(),
1802+ (float) transRect.getMaxY());
1803+
1804+
1805+ }
1806+
1807+ /**
1808+ * Add the stroked shape to the area representing
1809+ * the part of the page which is drawn into.
1810+ */
1811+ private void addStrokeShape(Shape s) {
1812+ Shape transShape = getStroke().createStrokedShape(s);
1813+ addDrawingRect(transShape.getBounds2D());
1814+ }
1815+
1816+ /* Image Observer */
1817+
1818+ /**
1819+ * Notify this object when the height or width become available
1820+ * for an image.
1821+ */
1822+ public synchronized boolean imageUpdate(Image img, int infoFlags,
1823+ int x, int y,
1824+ int width, int height) {
1825+
1826+ boolean gotInfo = false;
1827+
1828+ if((infoFlags & (WIDTH | HEIGHT)) != 0) {
1829+ gotInfo = true;
1830+ notify();
1831+ }
1832+
1833+ return gotInfo;
1834+ }
1835+
1836+ private synchronized int getImageWidth(Image img) {
1837+
1838+ /* Wait for the width the image to
1839+ * become available.
1840+ */
1841+ while (img.getWidth(this) == -1) {
1842+ try {
1843+ wait();
1844+ } catch (InterruptedException e) {
1845+ }
1846+ }
1847+
1848+
1849+ return img.getWidth(this);
1850+ }
1851+
1852+ private synchronized int getImageHeight(Image img) {
1853+
1854+ /* Wait for the height the image to
1855+ * become available.
1856+ */
1857+ while (img.getHeight(this) == -1) {
1858+ try {
1859+ wait();
1860+ } catch (InterruptedException e) {
1861+ }
1862+ }
1863+
1864+
1865+ return img.getHeight(this);
1866+ }
1867+
1868+ /**
1869+ * This private class does not return from its constructor
1870+ * until 'img's width and height are available.
1871+ */
1872+ protected class ImageWaiter implements ImageObserver {
1873+
1874+ private int mWidth;
1875+ private int mHeight;
1876+ private boolean badImage = false;
1877+
1878+ ImageWaiter(Image img) {
1879+ waitForDimensions(img);
1880+ }
1881+
1882+ public int getWidth() {
1883+ return mWidth;
1884+ }
1885+
1886+ public int getHeight() {
1887+ return mHeight;
1888+ }
1889+
1890+ synchronized private void waitForDimensions(Image img) {
1891+ mHeight = img.getHeight(this);
1892+ mWidth = img.getWidth(this);
1893+ while (!badImage && (mWidth < 0 || mHeight < 0)) {
1894+ try {
1895+ Thread.sleep(50);
1896+ } catch(InterruptedException e) {
1897+ // do nothing.
1898+ }
1899+ mHeight = img.getHeight(this);
1900+ mWidth = img.getWidth(this);
1901+ }
1902+ if (badImage) {
1903+ mHeight = 0;
1904+ mWidth = 0;
1905+ }
1906+ }
1907+
1908+ synchronized public boolean imageUpdate(Image image, int flags,
1909+ int x, int y, int w, int h) {
1910+
1911+ boolean dontCallMeAgain = (flags & (HEIGHT | ABORT | ERROR)) != 0;
1912+ badImage = (flags & (ABORT | ERROR)) != 0;
1913+
1914+ return dontCallMeAgain;
1915+ }
1916+
1917+ }
1918+}