Source Code Cross Referenced for PathGraphics.java in  » 6.0-JDK-Modules-sun » print » sun » print » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » 6.0 JDK Modules sun » print » sun.print 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Copyright 1998-2007 Sun Microsystems, Inc.  All Rights Reserved.
0003:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004:         *
0005:         * This code is free software; you can redistribute it and/or modify it
0006:         * under the terms of the GNU General Public License version 2 only, as
0007:         * published by the Free Software Foundation.  Sun designates this
0008:         * particular file as subject to the "Classpath" exception as provided
0009:         * by Sun in the LICENSE file that accompanied this code.
0010:         *
0011:         * This code is distributed in the hope that it will be useful, but WITHOUT
0012:         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013:         * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
0014:         * version 2 for more details (a copy is included in the LICENSE file that
0015:         * accompanied this code).
0016:         *
0017:         * You should have received a copy of the GNU General Public License version
0018:         * 2 along with this work; if not, write to the Free Software Foundation,
0019:         * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020:         *
0021:         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022:         * CA 95054 USA or visit www.sun.com if you need additional information or
0023:         * have any questions.
0024:         */
0025:
0026:        package sun.print;
0027:
0028:        import java.lang.ref.SoftReference;
0029:        import java.util.Hashtable;
0030:        import sun.font.CharToGlyphMapper;
0031:        import sun.font.CompositeFont;
0032:        import sun.font.Font2D;
0033:        import sun.font.Font2DHandle;
0034:        import sun.font.FontManager;
0035:
0036:        import java.awt.Color;
0037:        import java.awt.Font;
0038:        import java.awt.Graphics2D;
0039:        import java.awt.Image;
0040:        import java.awt.Paint;
0041:        import java.awt.Polygon;
0042:        import java.awt.Shape;
0043:
0044:        import java.text.AttributedCharacterIterator;
0045:
0046:        import java.awt.font.FontRenderContext;
0047:        import java.awt.font.GlyphVector;
0048:        import java.awt.font.TextAttribute;
0049:        import java.awt.font.TextLayout;
0050:
0051:        import java.awt.geom.AffineTransform;
0052:        import java.awt.geom.Arc2D;
0053:        import java.awt.geom.Ellipse2D;
0054:        import java.awt.geom.Line2D;
0055:        import java.awt.geom.Point2D;
0056:        import java.awt.geom.Rectangle2D;
0057:        import java.awt.geom.RoundRectangle2D;
0058:        import java.awt.geom.PathIterator;
0059:
0060:        import java.awt.image.BufferedImage;
0061:        import java.awt.image.BufferedImageOp;
0062:        import java.awt.image.ColorModel;
0063:        import java.awt.image.DataBuffer;
0064:        import java.awt.image.DataBufferInt;
0065:        import java.awt.image.ImageObserver;
0066:        import java.awt.image.IndexColorModel;
0067:        import java.awt.image.Raster;
0068:        import java.awt.image.RenderedImage;
0069:        import java.awt.image.SampleModel;
0070:        import java.awt.image.SinglePixelPackedSampleModel;
0071:        import java.awt.image.VolatileImage;
0072:        import sun.awt.image.ByteComponentRaster;
0073:        import sun.awt.image.ToolkitImage;
0074:        import sun.awt.image.SunWritableRaster;
0075:
0076:        import java.awt.print.PageFormat;
0077:        import java.awt.print.Printable;
0078:        import java.awt.print.PrinterException;
0079:        import java.awt.print.PrinterGraphics;
0080:        import java.awt.print.PrinterJob;
0081:
0082:        import java.util.Map;
0083:
0084:        public abstract class PathGraphics extends ProxyGraphics2D {
0085:
0086:            private Printable mPainter;
0087:            private PageFormat mPageFormat;
0088:            private int mPageIndex;
0089:            private boolean mCanRedraw;
0090:            protected boolean printingGlyphVector;
0091:
0092:            protected PathGraphics(Graphics2D graphics, PrinterJob printerJob,
0093:                    Printable painter, PageFormat pageFormat, int pageIndex,
0094:                    boolean canRedraw) {
0095:                super (graphics, printerJob);
0096:
0097:                mPainter = painter;
0098:                mPageFormat = pageFormat;
0099:                mPageIndex = pageIndex;
0100:                mCanRedraw = canRedraw;
0101:            }
0102:
0103:            /**
0104:             * Return the Printable instance responsible for drawing
0105:             * into this Graphics.
0106:             */
0107:            protected Printable getPrintable() {
0108:                return mPainter;
0109:            }
0110:
0111:            /**
0112:             * Return the PageFormat associated with this page of
0113:             * Graphics.
0114:             */
0115:            protected PageFormat getPageFormat() {
0116:                return mPageFormat;
0117:            }
0118:
0119:            /**
0120:             * Return the page index associated with this Graphics.
0121:             */
0122:            protected int getPageIndex() {
0123:                return mPageIndex;
0124:            }
0125:
0126:            /**
0127:             * Return true if we are allowed to ask the application
0128:             * to redraw portions of the page. In general, with the
0129:             * PrinterJob API, the application can be asked to do a
0130:             * redraw. When PrinterJob is emulating PrintJob then we
0131:             * can not.
0132:             */
0133:            public boolean canDoRedraws() {
0134:                return mCanRedraw;
0135:            }
0136:
0137:            /** 
0138:             * Redraw a rectanglular area using a proxy graphics
0139:             */
0140:            public abstract void redrawRegion(Rectangle2D region,
0141:                    double scaleX, double scaleY, Shape clip,
0142:                    AffineTransform devTransform)
0143:
0144:            throws PrinterException;
0145:
0146:            /** 
0147:             * Draws a line, using the current color, between the points 
0148:             * <code>(x1,&nbsp;y1)</code> and <code>(x2,&nbsp;y2)</code> 
0149:             * in this graphics context's coordinate system. 
0150:             * @param   x1  the first point's <i>x</i> coordinate.
0151:             * @param   y1  the first point's <i>y</i> coordinate.
0152:             * @param   x2  the second point's <i>x</i> coordinate.
0153:             * @param   y2  the second point's <i>y</i> coordinate.
0154:             */
0155:            public void drawLine(int x1, int y1, int x2, int y2) {
0156:
0157:                Paint paint = getPaint();
0158:
0159:                try {
0160:                    AffineTransform deviceTransform = getTransform();
0161:                    if (getClip() != null) {
0162:                        deviceClip(getClip().getPathIterator(deviceTransform));
0163:                    }
0164:
0165:                    deviceDrawLine(x1, y1, x2, y2, (Color) paint);
0166:
0167:                } catch (ClassCastException e) {
0168:                    throw new IllegalArgumentException(
0169:                            "Expected a Color instance");
0170:                }
0171:            }
0172:
0173:            /** 
0174:             * Draws the outline of the specified rectangle. 
0175:             * The left and right edges of the rectangle are at 
0176:             * <code>x</code> and <code>x&nbsp;+&nbsp;width</code>. 
0177:             * The top and bottom edges are at 
0178:             * <code>y</code> and <code>y&nbsp;+&nbsp;height</code>. 
0179:             * The rectangle is drawn using the graphics context's current color.
0180:             * @param         x   the <i>x</i> coordinate 
0181:             *                         of the rectangle to be drawn.
0182:             * @param         y   the <i>y</i> coordinate 
0183:             *                         of the rectangle to be drawn.
0184:             * @param         width   the width of the rectangle to be drawn.
0185:             * @param         height   the height of the rectangle to be drawn.
0186:             * @see          java.awt.Graphics#fillRect
0187:             * @see          java.awt.Graphics#clearRect
0188:             */
0189:            public void drawRect(int x, int y, int width, int height) {
0190:
0191:                Paint paint = getPaint();
0192:
0193:                try {
0194:                    AffineTransform deviceTransform = getTransform();
0195:                    if (getClip() != null) {
0196:                        deviceClip(getClip().getPathIterator(deviceTransform));
0197:                    }
0198:
0199:                    deviceFrameRect(x, y, width, height, (Color) paint);
0200:
0201:                } catch (ClassCastException e) {
0202:                    throw new IllegalArgumentException(
0203:                            "Expected a Color instance");
0204:                }
0205:
0206:            }
0207:
0208:            /** 
0209:             * Fills the specified rectangle. 
0210:             * The left and right edges of the rectangle are at 
0211:             * <code>x</code> and <code>x&nbsp;+&nbsp;width&nbsp;-&nbsp;1</code>. 
0212:             * The top and bottom edges are at 
0213:             * <code>y</code> and <code>y&nbsp;+&nbsp;height&nbsp;-&nbsp;1</code>. 
0214:             * The resulting rectangle covers an area 
0215:             * <code>width</code> pixels wide by 
0216:             * <code>height</code> pixels tall.
0217:             * The rectangle is filled using the graphics context's current color. 
0218:             * @param         x   the <i>x</i> coordinate 
0219:             *                         of the rectangle to be filled.
0220:             * @param         y   the <i>y</i> coordinate 
0221:             *                         of the rectangle to be filled.
0222:             * @param         width   the width of the rectangle to be filled.
0223:             * @param         height   the height of the rectangle to be filled.
0224:             * @see           java.awt.Graphics#clearRect
0225:             * @see           java.awt.Graphics#drawRect
0226:             */
0227:            public void fillRect(int x, int y, int width, int height) {
0228:
0229:                Paint paint = getPaint();
0230:
0231:                try {
0232:                    AffineTransform deviceTransform = getTransform();
0233:                    if (getClip() != null) {
0234:                        deviceClip(getClip().getPathIterator(deviceTransform));
0235:                    }
0236:
0237:                    deviceFillRect(x, y, width, height, (Color) paint);
0238:
0239:                } catch (ClassCastException e) {
0240:                    throw new IllegalArgumentException(
0241:                            "Expected a Color instance");
0242:                }
0243:            }
0244:
0245:            /** 
0246:             * Clears the specified rectangle by filling it with the background
0247:             * color of the current drawing surface. This operation does not 
0248:             * use the current paint mode. 
0249:             * <p>
0250:             * Beginning with Java&nbsp;1.1, the background color 
0251:             * of offscreen images may be system dependent. Applications should 
0252:             * use <code>setColor</code> followed by <code>fillRect</code> to 
0253:             * ensure that an offscreen image is cleared to a specific color. 
0254:             * @param       x the <i>x</i> coordinate of the rectangle to clear.
0255:             * @param       y the <i>y</i> coordinate of the rectangle to clear.
0256:             * @param       width the width of the rectangle to clear.
0257:             * @param       height the height of the rectangle to clear.
0258:             * @see         java.awt.Graphics#fillRect(int, int, int, int)
0259:             * @see         java.awt.Graphics#drawRect
0260:             * @see         java.awt.Graphics#setColor(java.awt.Color)
0261:             * @see         java.awt.Graphics#setPaintMode
0262:             * @see         java.awt.Graphics#setXORMode(java.awt.Color)
0263:             */
0264:            public void clearRect(int x, int y, int width, int height) {
0265:
0266:                fill(new Rectangle2D.Float(x, y, width, height),
0267:                        getBackground());
0268:            }
0269:
0270:            /** 
0271:             * Draws an outlined round-cornered rectangle using this graphics 
0272:             * context's current color. The left and right edges of the rectangle 
0273:             * are at <code>x</code> and <code>x&nbsp;+&nbsp;width</code>, 
0274:             * respectively. The top and bottom edges of the rectangle are at 
0275:             * <code>y</code> and <code>y&nbsp;+&nbsp;height</code>. 
0276:             * @param      x the <i>x</i> coordinate of the rectangle to be drawn.
0277:             * @param      y the <i>y</i> coordinate of the rectangle to be drawn.
0278:             * @param      width the width of the rectangle to be drawn.
0279:             * @param      height the height of the rectangle to be drawn.
0280:             * @param      arcWidth the horizontal diameter of the arc 
0281:             *                    at the four corners.
0282:             * @param      arcHeight the vertical diameter of the arc 
0283:             *                    at the four corners.
0284:             * @see        java.awt.Graphics#fillRoundRect
0285:             */
0286:            public void drawRoundRect(int x, int y, int width, int height,
0287:                    int arcWidth, int arcHeight) {
0288:
0289:                draw(new RoundRectangle2D.Float(x, y, width, height, arcWidth,
0290:                        arcHeight));
0291:            }
0292:
0293:            /** 
0294:             * Fills the specified rounded corner rectangle with the current color.
0295:             * The left and right edges of the rectangle 
0296:             * are at <code>x</code> and <code>x&nbsp;+&nbsp;width&nbsp;-&nbsp;1</code>, 
0297:             * respectively. The top and bottom edges of the rectangle are at 
0298:             * <code>y</code> and <code>y&nbsp;+&nbsp;height&nbsp;-&nbsp;1</code>. 
0299:             * @param       x the <i>x</i> coordinate of the rectangle to be filled.
0300:             * @param       y the <i>y</i> coordinate of the rectangle to be filled.
0301:             * @param       width the width of the rectangle to be filled.
0302:             * @param       height the height of the rectangle to be filled.
0303:             * @param       arcWidth the horizontal diameter 
0304:             *                     of the arc at the four corners.
0305:             * @param       arcHeight the vertical diameter 
0306:             *                     of the arc at the four corners.
0307:             * @see         java.awt.Graphics#drawRoundRect
0308:             */
0309:            public void fillRoundRect(int x, int y, int width, int height,
0310:                    int arcWidth, int arcHeight) {
0311:
0312:                fill(new RoundRectangle2D.Float(x, y, width, height, arcWidth,
0313:                        arcHeight));
0314:            }
0315:
0316:            /** 
0317:             * Draws the outline of an oval.
0318:             * The result is a circle or ellipse that fits within the 
0319:             * rectangle specified by the <code>x</code>, <code>y</code>, 
0320:             * <code>width</code>, and <code>height</code> arguments. 
0321:             * <p> 
0322:             * The oval covers an area that is 
0323:             * <code>width&nbsp;+&nbsp;1</code> pixels wide 
0324:             * and <code>height&nbsp;+&nbsp;1</code> pixels tall. 
0325:             * @param       x the <i>x</i> coordinate of the upper left 
0326:             *                     corner of the oval to be drawn.
0327:             * @param       y the <i>y</i> coordinate of the upper left 
0328:             *                     corner of the oval to be drawn.
0329:             * @param       width the width of the oval to be drawn.
0330:             * @param       height the height of the oval to be drawn.
0331:             * @see         java.awt.Graphics#fillOval
0332:             * @since       JDK1.0
0333:             */
0334:            public void drawOval(int x, int y, int width, int height) {
0335:                draw(new Ellipse2D.Float(x, y, width, height));
0336:            }
0337:
0338:            /** 
0339:             * Fills an oval bounded by the specified rectangle with the
0340:             * current color.
0341:             * @param       x the <i>x</i> coordinate of the upper left corner 
0342:             *                     of the oval to be filled.
0343:             * @param       y the <i>y</i> coordinate of the upper left corner 
0344:             *                     of the oval to be filled.
0345:             * @param       width the width of the oval to be filled.
0346:             * @param       height the height of the oval to be filled.
0347:             * @see         java.awt.Graphics#drawOval
0348:             */
0349:            public void fillOval(int x, int y, int width, int height) {
0350:
0351:                fill(new Ellipse2D.Float(x, y, width, height));
0352:            }
0353:
0354:            /**
0355:             * Draws the outline of a circular or elliptical arc 
0356:             * covering the specified rectangle.
0357:             * <p>
0358:             * The resulting arc begins at <code>startAngle</code> and extends  
0359:             * for <code>arcAngle</code> degrees, using the current color.
0360:             * Angles are interpreted such that 0&nbsp;degrees 
0361:             * is at the 3&nbsp;o'clock position. 
0362:             * A positive value indicates a counter-clockwise rotation
0363:             * while a negative value indicates a clockwise rotation.
0364:             * <p>
0365:             * The center of the arc is the center of the rectangle whose origin 
0366:             * is (<i>x</i>,&nbsp;<i>y</i>) and whose size is specified by the 
0367:             * <code>width</code> and <code>height</code> arguments. 
0368:             * <p>
0369:             * The resulting arc covers an area 
0370:             * <code>width&nbsp;+&nbsp;1</code> pixels wide
0371:             * by <code>height&nbsp;+&nbsp;1</code> pixels tall.
0372:             * <p>
0373:             * The angles are specified relative to the non-square extents of
0374:             * the bounding rectangle such that 45 degrees always falls on the
0375:             * line from the center of the ellipse to the upper right corner of
0376:             * the bounding rectangle. As a result, if the bounding rectangle is
0377:             * noticeably longer in one axis than the other, the angles to the
0378:             * start and end of the arc segment will be skewed farther along the
0379:             * longer axis of the bounds.
0380:             * @param        x the <i>x</i> coordinate of the 
0381:             *                    upper-left corner of the arc to be drawn.
0382:             * @param        y the <i>y</i>  coordinate of the 
0383:             *                    upper-left corner of the arc to be drawn.
0384:             * @param        width the width of the arc to be drawn.
0385:             * @param        height the height of the arc to be drawn.
0386:             * @param        startAngle the beginning angle.
0387:             * @param        arcAngle the angular extent of the arc, 
0388:             *                    relative to the start angle.
0389:             * @see         java.awt.Graphics#fillArc
0390:             */
0391:            public void drawArc(int x, int y, int width, int height,
0392:                    int startAngle, int arcAngle) {
0393:                draw(new Arc2D.Float(x, y, width, height, startAngle, arcAngle,
0394:                        Arc2D.OPEN));
0395:            }
0396:
0397:            /** 
0398:             * Fills a circular or elliptical arc covering the specified rectangle.
0399:             * <p>
0400:             * The resulting arc begins at <code>startAngle</code> and extends  
0401:             * for <code>arcAngle</code> degrees.
0402:             * Angles are interpreted such that 0&nbsp;degrees 
0403:             * is at the 3&nbsp;o'clock position. 
0404:             * A positive value indicates a counter-clockwise rotation
0405:             * while a negative value indicates a clockwise rotation.
0406:             * <p>
0407:             * The center of the arc is the center of the rectangle whose origin 
0408:             * is (<i>x</i>,&nbsp;<i>y</i>) and whose size is specified by the 
0409:             * <code>width</code> and <code>height</code> arguments. 
0410:             * <p>
0411:             * The resulting arc covers an area 
0412:             * <code>width&nbsp;+&nbsp;1</code> pixels wide
0413:             * by <code>height&nbsp;+&nbsp;1</code> pixels tall.
0414:             * <p>
0415:             * The angles are specified relative to the non-square extents of
0416:             * the bounding rectangle such that 45 degrees always falls on the
0417:             * line from the center of the ellipse to the upper right corner of
0418:             * the bounding rectangle. As a result, if the bounding rectangle is
0419:             * noticeably longer in one axis than the other, the angles to the
0420:             * start and end of the arc segment will be skewed farther along the
0421:             * longer axis of the bounds.
0422:             * @param        x the <i>x</i> coordinate of the 
0423:             *                    upper-left corner of the arc to be filled.
0424:             * @param        y the <i>y</i>  coordinate of the 
0425:             *                    upper-left corner of the arc to be filled.
0426:             * @param        width the width of the arc to be filled.
0427:             * @param        height the height of the arc to be filled.
0428:             * @param        startAngle the beginning angle.
0429:             * @param        arcAngle the angular extent of the arc, 
0430:             *                    relative to the start angle.
0431:             * @see         java.awt.Graphics#drawArc
0432:             */
0433:            public void fillArc(int x, int y, int width, int height,
0434:                    int startAngle, int arcAngle) {
0435:
0436:                fill(new Arc2D.Float(x, y, width, height, startAngle, arcAngle,
0437:                        Arc2D.PIE));
0438:            }
0439:
0440:            /** 
0441:             * Draws a sequence of connected lines defined by 
0442:             * arrays of <i>x</i> and <i>y</i> coordinates. 
0443:             * Each pair of (<i>x</i>,&nbsp;<i>y</i>) coordinates defines a point.
0444:             * The figure is not closed if the first point 
0445:             * differs from the last point.
0446:             * @param       xPoints an array of <i>x</i> points
0447:             * @param       yPoints an array of <i>y</i> points
0448:             * @param       nPoints the total number of points
0449:             * @see         java.awt.Graphics#drawPolygon(int[], int[], int)
0450:             * @since       JDK1.1
0451:             */
0452:            public void drawPolyline(int xPoints[], int yPoints[], int nPoints) {
0453:                float fromX;
0454:                float fromY;
0455:                float toX;
0456:                float toY;
0457:
0458:                if (nPoints > 0) {
0459:                    fromX = xPoints[0];
0460:                    fromY = yPoints[0];
0461:                    for (int i = 1; i < nPoints; i++) {
0462:                        toX = xPoints[i];
0463:                        toY = yPoints[i];
0464:                        draw(new Line2D.Float(fromX, fromY, toX, toY));
0465:                        fromX = toX;
0466:                        fromY = toY;
0467:                    }
0468:                }
0469:
0470:            }
0471:
0472:            /** 
0473:             * Draws a closed polygon defined by 
0474:             * arrays of <i>x</i> and <i>y</i> coordinates. 
0475:             * Each pair of (<i>x</i>,&nbsp;<i>y</i>) coordinates defines a point.
0476:             * <p>
0477:             * This method draws the polygon defined by <code>nPoint</code> line 
0478:             * segments, where the first <code>nPoint&nbsp;-&nbsp;1</code> 
0479:             * line segments are line segments from 
0480:             * <code>(xPoints[i&nbsp;-&nbsp;1],&nbsp;yPoints[i&nbsp;-&nbsp;1])</code> 
0481:             * to <code>(xPoints[i],&nbsp;yPoints[i])</code>, for 
0482:             * 1&nbsp;&le;&nbsp;<i>i</i>&nbsp;&le;&nbsp;<code>nPoints</code>.  
0483:             * The figure is automatically closed by drawing a line connecting
0484:             * the final point to the first point, if those points are different.
0485:             * @param        xPoints   a an array of <code>x</code> coordinates.
0486:             * @param        yPoints   a an array of <code>y</code> coordinates.
0487:             * @param        nPoints   a the total number of points.
0488:             * @see          java.awt.Graphics#fillPolygon
0489:             * @see          java.awt.Graphics#drawPolyline
0490:             */
0491:            public void drawPolygon(int xPoints[], int yPoints[], int nPoints) {
0492:
0493:                draw(new Polygon(xPoints, yPoints, nPoints));
0494:            }
0495:
0496:            /** 
0497:             * Draws the outline of a polygon defined by the specified 
0498:             * <code>Polygon</code> object. 
0499:             * @param        p the polygon to draw.
0500:             * @see          java.awt.Graphics#fillPolygon
0501:             * @see          java.awt.Graphics#drawPolyline
0502:             */
0503:            public void drawPolygon(Polygon p) {
0504:                draw(p);
0505:            }
0506:
0507:            /** 
0508:             * Fills a closed polygon defined by 
0509:             * arrays of <i>x</i> and <i>y</i> coordinates. 
0510:             * <p>
0511:             * This method draws the polygon defined by <code>nPoint</code> line 
0512:             * segments, where the first <code>nPoint&nbsp;-&nbsp;1</code> 
0513:             * line segments are line segments from 
0514:             * <code>(xPoints[i&nbsp;-&nbsp;1],&nbsp;yPoints[i&nbsp;-&nbsp;1])</code> 
0515:             * to <code>(xPoints[i],&nbsp;yPoints[i])</code>, for 
0516:             * 1&nbsp;&le;&nbsp;<i>i</i>&nbsp;&le;&nbsp;<code>nPoints</code>.  
0517:             * The figure is automatically closed by drawing a line connecting
0518:             * the final point to the first point, if those points are different.
0519:             * <p>
0520:             * The area inside the polygon is defined using an 
0521:             * even-odd fill rule, also known as the alternating rule.
0522:             * @param        xPoints   a an array of <code>x</code> coordinates.
0523:             * @param        yPoints   a an array of <code>y</code> coordinates.
0524:             * @param        nPoints   a the total number of points.
0525:             * @see          java.awt.Graphics#drawPolygon(int[], int[], int)
0526:             */
0527:            public void fillPolygon(int xPoints[], int yPoints[], int nPoints) {
0528:
0529:                fill(new Polygon(xPoints, yPoints, nPoints));
0530:            }
0531:
0532:            /** 
0533:             * Fills the polygon defined by the specified Polygon object with
0534:             * the graphics context's current color. 
0535:             * <p>
0536:             * The area inside the polygon is defined using an 
0537:             * even-odd fill rule, also known as the alternating rule.
0538:             * @param        p the polygon to fill.
0539:             * @see          java.awt.Graphics#drawPolygon(int[], int[], int)
0540:             */
0541:            public void fillPolygon(Polygon p) {
0542:
0543:                fill(p);
0544:            }
0545:
0546:            /** 
0547:             * Draws the text given by the specified string, using this 
0548:             * graphics context's current font and color. The baseline of the 
0549:             * first character is at position (<i>x</i>,&nbsp;<i>y</i>) in this 
0550:             * graphics context's coordinate system. 
0551:             * @param       str      the string to be drawn.
0552:             * @param       x        the <i>x</i> coordinate.
0553:             * @param       y        the <i>y</i> coordinate.
0554:             * @see         java.awt.Graphics#drawBytes
0555:             * @see         java.awt.Graphics#drawChars
0556:             * @since       JDK1.0
0557:             */
0558:            public void drawString(String str, int x, int y) {
0559:                drawString(str, (float) x, (float) y);
0560:            }
0561:
0562:            public void drawString(String str, float x, float y) {
0563:                if (str.length() == 0) {
0564:                    return;
0565:                }
0566:                TextLayout layout = new TextLayout(str, getFont(),
0567:                        getFontRenderContext());
0568:                layout.draw(this , x, y);
0569:            }
0570:
0571:            protected void drawString(String str, float x, float y, Font font,
0572:                    FontRenderContext frc, float w) {
0573:                TextLayout layout = new TextLayout(str, font, frc);
0574:                Shape textShape = layout.getOutline(AffineTransform
0575:                        .getTranslateInstance(x, y));
0576:                fill(textShape);
0577:            }
0578:
0579:            /**
0580:             * Draws the text given by the specified iterator, using this 
0581:             * graphics context's current color. The iterator has to specify a font
0582:             * for each character. The baseline of the 
0583:             * first character is at position (<i>x</i>,&nbsp;<i>y</i>) in this 
0584:             * graphics context's coordinate system. 
0585:             * @param       iterator the iterator whose text is to be drawn
0586:             * @param       x        the <i>x</i> coordinate.
0587:             * @param       y        the <i>y</i> coordinate.
0588:             * @see         java.awt.Graphics#drawBytes
0589:             * @see         java.awt.Graphics#drawChars
0590:             */
0591:            public void drawString(AttributedCharacterIterator iterator, int x,
0592:                    int y) {
0593:                drawString(iterator, (float) x, (float) y);
0594:            }
0595:
0596:            public void drawString(AttributedCharacterIterator iterator,
0597:                    float x, float y) {
0598:                if (iterator == null) {
0599:                    throw new NullPointerException(
0600:                            "attributedcharacteriterator is null");
0601:                }
0602:                TextLayout layout = new TextLayout(iterator,
0603:                        getFontRenderContext());
0604:                layout.draw(this , x, y);
0605:            }
0606:
0607:            /**
0608:             * Draws a GlyphVector.
0609:             * The rendering attributes applied include the clip, transform,
0610:             * paint or color, and composite attributes.  The GlyphVector specifies
0611:             * individual glyphs from a Font.
0612:             * @param g The GlyphVector to be drawn.
0613:             * @param x,y The coordinates where the glyphs should be drawn.
0614:             * @see #setPaint
0615:             * @see java.awt.Graphics#setColor
0616:             * @see #transform
0617:             * @see #setTransform
0618:             * @see #setComposite
0619:             * @see #clip
0620:             * @see #setClip
0621:             */
0622:            public void drawGlyphVector(GlyphVector g, float x, float y) {
0623:
0624:                /* We should not reach here if printingGlyphVector is already true.
0625:                 * Add an assert so this can be tested if need be.
0626:                 * But also ensure that we do at least render properly by filling
0627:                 * the outline.
0628:                 */
0629:                if (printingGlyphVector) {
0630:                    assert !printingGlyphVector; // ie false.
0631:                    fill(g.getOutline(x, y));
0632:                    return;
0633:                }
0634:
0635:                try {
0636:                    printingGlyphVector = true;
0637:                    if (RasterPrinterJob.shapeTextProp
0638:                            || !printedSimpleGlyphVector(g, x, y)) {
0639:                        fill(g.getOutline(x, y));
0640:                    }
0641:                } finally {
0642:                    printingGlyphVector = false;
0643:                }
0644:            }
0645:
0646:            protected static SoftReference<Hashtable<Font2DHandle, Object>> fontMapRef = new SoftReference<Hashtable<Font2DHandle, Object>>(
0647:                    null);
0648:
0649:            protected int platformFontCount(Font font, String str) {
0650:                return 0;
0651:            }
0652:
0653:            /**
0654:             * Default implementation returns false.
0655:             * Callers of this method must always be prepared for this,
0656:             * and delegate to outlines or some other solution.
0657:             */
0658:            protected boolean printGlyphVector(GlyphVector gv, float x, float y) {
0659:                return false;
0660:            }
0661:
0662:            /* GlyphVectors are usually encountered because TextLayout is in use.
0663:             * Some times TextLayout is needed to handle complex text or some
0664:             * rendering attributes trigger it.
0665:             * We try to print GlyphVectors by reconstituting into a String,
0666:             * as that is most recoverable for applications that export to formats
0667:             * such as Postscript or PDF. In some cases (eg where its not complex
0668:             * text and its just that positions aren't what we'd expect) we print
0669:             * one character at a time. positioning individually.
0670:             * Failing that, if we can directly send glyph codes to the printer
0671:             * then we do that (printGlyphVector).
0672:             * As a last resort we return false and let the caller print as filled
0673:             * shapes.
0674:             */
0675:            boolean printedSimpleGlyphVector(GlyphVector g, float x, float y) {
0676:
0677:                int flags = g.getLayoutFlags();
0678:
0679:                /* We can't handle RTL, re-ordering, complex glyphs etc by
0680:                 * reconstituting glyphs into a String. So if any flags besides
0681:                 * position adjustments are set, see if we can directly
0682:                 * print the GlyphVector as glyph codes, using the positions
0683:                 * layout has assigned. If that fails return false;
0684:                 */
0685:                if (flags != 0
0686:                        && flags != GlyphVector.FLAG_HAS_POSITION_ADJUSTMENTS) {
0687:                    return printGlyphVector(g, x, y);
0688:                }
0689:
0690:                Font font = g.getFont();
0691:                Font2D font2D = FontManager.getFont2D(font);
0692:                if (font2D.handle.font2D != font2D) {
0693:                    /* suspicious, may be a bad font. lets bail */
0694:                    return false;
0695:                }
0696:                Hashtable<Font2DHandle, Object> fontMap;
0697:                synchronized (PathGraphics.class) {
0698:                    fontMap = fontMapRef.get();
0699:                    if (fontMap == null) {
0700:                        fontMap = new Hashtable<Font2DHandle, Object>();
0701:                        fontMapRef = new SoftReference<Hashtable<Font2DHandle, Object>>(
0702:                                fontMap);
0703:                    }
0704:                }
0705:
0706:                int numGlyphs = g.getNumGlyphs();
0707:                int[] glyphCodes = g.getGlyphCodes(0, numGlyphs, null);
0708:
0709:                char[] glyphToCharMap = null;
0710:                char[][] mapArray = null;
0711:                CompositeFont cf = null;
0712:
0713:                /* Build the needed maps for this font in a synchronized block */
0714:                synchronized (fontMap) {
0715:                    if (font2D instanceof  CompositeFont) {
0716:                        cf = (CompositeFont) font2D;
0717:                        int numSlots = cf.getNumSlots();
0718:                        mapArray = (char[][]) fontMap.get(font2D.handle);
0719:                        if (mapArray == null) {
0720:                            mapArray = new char[numSlots][];
0721:                            fontMap.put(font2D.handle, mapArray);
0722:                        }
0723:                        for (int i = 0; i < numGlyphs; i++) {
0724:                            int slot = glyphCodes[i] >>> 24;
0725:                            if (slot >= numSlots) { /* shouldn't happen */
0726:                                return false;
0727:                            }
0728:                            if (mapArray[slot] == null) {
0729:                                Font2D slotFont = cf.getSlotFont(slot);
0730:                                char[] map = (char[]) fontMap
0731:                                        .get(slotFont.handle);
0732:                                if (map == null) {
0733:                                    map = getGlyphToCharMapForFont(slotFont);
0734:                                }
0735:                                mapArray[slot] = map;
0736:                            }
0737:                        }
0738:                    } else {
0739:                        glyphToCharMap = (char[]) fontMap.get(font2D.handle);
0740:                        if (glyphToCharMap == null) {
0741:                            glyphToCharMap = getGlyphToCharMapForFont(font2D);
0742:                            fontMap.put(font2D.handle, glyphToCharMap);
0743:                        }
0744:                    }
0745:                }
0746:
0747:                char[] chars = new char[numGlyphs];
0748:                if (cf != null) {
0749:                    for (int i = 0; i < numGlyphs; i++) {
0750:                        int gc = glyphCodes[i];
0751:                        char[] map = mapArray[gc >>> 24];
0752:                        gc = gc & 0xffffff;
0753:                        if (map == null) {
0754:                            return false;
0755:                        }
0756:                        /* X11 symbol & dingbats fonts used only for global metrics,
0757:                         * so the glyph codes we have really refer to Lucida Sans
0758:                         * Regular.
0759:                         * So its possible the glyph code may appear out of range.
0760:                         * Note that later on we double-check the glyph codes that
0761:                         * we get from re-creating the GV from the string are the
0762:                         * same as those we started with.
0763:                         *
0764:                         * If the glyphcode is INVISIBLE_GLYPH_ID then this may
0765:                         * be \t, \n or \r which are mapped to that by layout.
0766:                         * This is a case we can handle. It doesn't matter what
0767:                         * character we use (we use \n) so long as layout maps it
0768:                         * back to this in the verification, since the invisible
0769:                         * glyph isn't visible :)
0770:                         */
0771:                        char ch;
0772:                        if (gc == CharToGlyphMapper.INVISIBLE_GLYPH_ID) {
0773:                            ch = '\n';
0774:                        } else if (gc < 0 || gc >= map.length) {
0775:                            return false;
0776:                        } else {
0777:                            ch = map[gc];
0778:                        }
0779:                        if (ch != CharToGlyphMapper.INVISIBLE_GLYPH_ID) {
0780:                            chars[i] = ch;
0781:                        } else {
0782:                            return false;
0783:                        }
0784:                    }
0785:                } else {
0786:                    for (int i = 0; i < numGlyphs; i++) {
0787:                        int gc = glyphCodes[i];
0788:                        char ch;
0789:                        if (gc == CharToGlyphMapper.INVISIBLE_GLYPH_ID) {
0790:                            ch = '\n';
0791:                        } else if (gc < 0 || gc >= glyphToCharMap.length) {
0792:                            return false;
0793:                        } else {
0794:                            ch = glyphToCharMap[gc];
0795:                        }
0796:                        if (ch != CharToGlyphMapper.INVISIBLE_GLYPH_ID) {
0797:                            chars[i] = ch;
0798:                        } else {
0799:                            return false;
0800:                        }
0801:                    }
0802:                }
0803:
0804:                FontRenderContext gvFrc = g.getFontRenderContext();
0805:                GlyphVector gv2 = font.createGlyphVector(gvFrc, chars);
0806:                if (gv2.getNumGlyphs() != numGlyphs) {
0807:                    return printGlyphVector(g, x, y);
0808:                }
0809:                int[] glyphCodes2 = gv2.getGlyphCodes(0, numGlyphs, null);
0810:                /*  
0811:                 * Needed to double-check remapping of X11 symbol & dingbats.
0812:                 */
0813:                for (int i = 0; i < numGlyphs; i++) {
0814:                    if (glyphCodes[i] != glyphCodes2[i]) {
0815:                        return printGlyphVector(g, x, y);
0816:                    }
0817:                }
0818:
0819:                FontRenderContext g2dFrc = getFontRenderContext();
0820:                boolean compatibleFRC = gvFrc.equals(g2dFrc);
0821:                /* If differ only in specifying A-A or a translation, these are
0822:                 * also compatible FRC's, and we can do one drawString call.
0823:                 */
0824:                if (!compatibleFRC
0825:                        && gvFrc.usesFractionalMetrics() == g2dFrc
0826:                                .usesFractionalMetrics()) {
0827:                    AffineTransform gvAT = gvFrc.getTransform();
0828:                    AffineTransform g2dAT = getTransform();
0829:                    double[] gvMatrix = new double[4];
0830:                    double[] g2dMatrix = new double[4];
0831:                    gvAT.getMatrix(gvMatrix);
0832:                    g2dAT.getMatrix(g2dMatrix);
0833:                    compatibleFRC = true;
0834:                    for (int i = 0; i < 4; i++) {
0835:                        if (gvMatrix[i] != g2dMatrix[i]) {
0836:                            compatibleFRC = false;
0837:                            break;
0838:                        }
0839:                    }
0840:                }
0841:
0842:                String str = new String(chars, 0, numGlyphs);
0843:                int numFonts = platformFontCount(font, str);
0844:                if (numFonts == 0) {
0845:                    return false;
0846:                }
0847:
0848:                float[] positions = g.getGlyphPositions(0, numGlyphs, null);
0849:                boolean noPositionAdjustments = ((flags & GlyphVector.FLAG_HAS_POSITION_ADJUSTMENTS) == 0)
0850:                        || samePositions(gv2, glyphCodes2, glyphCodes,
0851:                                positions);
0852:
0853:                /* We have to consider that the application may be directly
0854:                 * creating a GlyphVector, rather than one being created by
0855:                 * TextLayout or indirectly from drawString. In such a case, if the
0856:                 * font has layout attributes, the text may measure differently
0857:                 * when we reconstitute it into a String and ask for the length that
0858:                 * drawString would use. For example, KERNING will be applied in such
0859:                 * a case but that Font attribute is not applied when the application
0860:                 * directly created a GlyphVector. So in this case we need to verify
0861:                 * that the text measures the same in both cases - ie that the
0862:                 * layout attribute has no effect. If it does we can't always
0863:                 * use the drawString call unless we can coerce the drawString call
0864:                 * into measuring and displaying the string to the same length.
0865:                 * That is the case where there is only one font used and we can
0866:                 * specify the overall advance of the string. (See below).
0867:                 */
0868:
0869:                Point2D gvAdvancePt = g.getGlyphPosition(numGlyphs);
0870:                float gvAdvanceX = (float) gvAdvancePt.getX();
0871:                boolean layoutAffectsAdvance = false;
0872:                if (font.hasLayoutAttributes() && printingGlyphVector
0873:                        && noPositionAdjustments) {
0874:
0875:                    /* If TRACKING is in use then the glyph vector will report
0876:                     * position adjustments, then that ought to be sufficient to
0877:                     * tell us we can't just ask native to do "drawString". But layout
0878:                     * always sets the position adjustment flag, so we don't believe
0879:                     * it and verify the positions are really different than
0880:                     * createGlyphVector() (with no layout) would create. However
0881:                     * inconsistently, TRACKING is applied when creating a GlyphVector,
0882:                     * since it doesn't actually require "layout" (even though its
0883:                     * considered a layout attribute), it just requires a fractional
0884:                     * tweak to the[default]advances. So we need to specifically
0885:                     * check for tracking until such time as as we can trust
0886:                     * the GlyphVector.FLAG_HAS_POSITION_ADJUSTMENTS bit.
0887:                     */
0888:                    Map<TextAttribute, ?> map = font.getAttributes();
0889:                    Object o = map.get(TextAttribute.TRACKING);
0890:                    boolean tracking = o != null && (o instanceof  Number)
0891:                            && (((Number) o).floatValue() != 0f);
0892:
0893:                    if (tracking) {
0894:                        noPositionAdjustments = false;
0895:                    } else {
0896:                        Rectangle2D bounds = font.getStringBounds(str, gvFrc);
0897:                        float strAdvanceX = (float) bounds.getWidth();
0898:                        if (Math.abs(strAdvanceX - gvAdvanceX) > 0.00001) {
0899:                            layoutAffectsAdvance = true;
0900:                        }
0901:                    }
0902:                }
0903:
0904:                if (compatibleFRC && noPositionAdjustments
0905:                        && !layoutAffectsAdvance) {
0906:                    drawString(str, x, y, font, gvFrc, 0f);
0907:                    return true;
0908:                }
0909:
0910:                /* If positions have not been explicitly assigned, we can
0911:                 * ask the string to be drawn adjusted to this width.
0912:                 * This call is supported only in the PS generator.
0913:                 * GDI has API to specify the advance for each glyph in a
0914:                 * string which could be used here too, but that is not yet
0915:                 * implemented, and we'd need to update the signature of the
0916:                 * drawString method to take the advances (ie relative positions)
0917:                 * and use that instead of the width.
0918:                 */
0919:                if (numFonts == 1 && canDrawStringToWidth()
0920:                        && noPositionAdjustments) {
0921:                    drawString(str, x, y, font, gvFrc, gvAdvanceX);
0922:                    return true;
0923:                }
0924:
0925:                /* In some scripts chars drawn individually do not have the
0926:                 * same representation (glyphs) as when combined with other chars.
0927:                 * The logic here is erring on the side of caution, in particular
0928:                 * in including supplementary characters. 
0929:                 */
0930:                if (FontManager.isComplexText(chars, 0, chars.length)) {
0931:                    return printGlyphVector(g, x, y);
0932:                }
0933:
0934:                /* If we reach here we have mapped all the glyphs back
0935:                 * one-to-one to simple unicode chars that we know are in the font.
0936:                 * We can call "drawChars" on each one of them in turn, setting
0937:                 * the position based on the glyph positions.
0938:                 * There's typically overhead in this. If numGlyphs is 'large',
0939:                 * it may even be better to try printGlyphVector() in this case.
0940:                 * This may be less recoverable for apps, but sophisticated apps
0941:                 * should be able to recover the text from simple glyph vectors
0942:                 * and we can avoid penalising the more common case - although
0943:                 * this is already a minority case.
0944:                 */
0945:                if (numGlyphs > 10 && printGlyphVector(g, x, y)) {
0946:                    return true;
0947:                }
0948:
0949:                for (int i = 0; i < numGlyphs; i++) {
0950:                    String s = new String(chars, i, 1);
0951:                    drawString(s, x + positions[i * 2], y
0952:                            + positions[i * 2 + 1], font, gvFrc, 0f);
0953:                }
0954:                return true;
0955:            }
0956:
0957:            /* The same codes must be in the same positions for this to return true.
0958:             * This would look cleaner if it took the original GV as a parameter but
0959:             * we already have the codes and will need to get the positions array
0960:             * too in most cases anyway. So its cheaper to pass them in.
0961:             * This call wouldn't be necessary if layout didn't always set the
0962:             * FLAG_HAS_POSITION_ADJUSTMENTS even if the default advances are used
0963:             * and there was no re-ordering (this should be fixed some day).
0964:             */
0965:            private boolean samePositions(GlyphVector gv, int[] gvcodes,
0966:                    int[] origCodes, float[] origPositions) {
0967:
0968:                int numGlyphs = gv.getNumGlyphs();
0969:                float[] gvpos = gv.getGlyphPositions(0, numGlyphs, null);
0970:
0971:                /* this shouldn't happen here, but just in case */
0972:                if (numGlyphs != gvcodes.length || /* real paranoia here */
0973:                origCodes.length != gvcodes.length
0974:                        || origPositions.length != gvpos.length) {
0975:                    return false;
0976:                }
0977:
0978:                for (int i = 0; i < numGlyphs; i++) {
0979:                    if (gvcodes[i] != origCodes[i]
0980:                            || gvpos[i] != origPositions[i]) {
0981:                        return false;
0982:                    }
0983:                }
0984:                return true;
0985:            }
0986:
0987:            protected boolean canDrawStringToWidth() {
0988:                return false;
0989:            }
0990:
0991:            /* return an array which can map glyphs back to char codes.
0992:             * Glyphs which aren't mapped from a simple unicode code point
0993:             * will have no mapping in this array, and will be assumed to be
0994:             * because of some substitution that we can't handle.
0995:             */
0996:            private static char[] getGlyphToCharMapForFont(Font2D font2D) {
0997:                /* NB Composites report the number of glyphs in slot 0.
0998:                 * So if a string uses a char from a later slot, or a fallback slot,
0999:                 * it will not be able to use this faster path.
1000:                 */
1001:                int numGlyphs = font2D.getNumGlyphs();
1002:                int missingGlyph = font2D.getMissingGlyphCode();
1003:                char[] glyphToCharMap = new char[numGlyphs];
1004:                int glyph;
1005:
1006:                for (int i = 0; i < numGlyphs; i++) {
1007:                    glyphToCharMap[i] = CharToGlyphMapper.INVISIBLE_GLYPH_ID;
1008:                }
1009:
1010:                /* Consider refining the ranges to try to map by asking the font
1011:                 * what ranges it supports.
1012:                 * Since a glyph may be mapped by multiple code points, and this
1013:                 * code can't handle that, we always prefer the earlier code point.
1014:                 */
1015:                for (char c = 0; c < 0xFFFF; c++) {
1016:                    if (c >= CharToGlyphMapper.HI_SURROGATE_START
1017:                            && c <= CharToGlyphMapper.LO_SURROGATE_END) {
1018:                        continue;
1019:                    }
1020:                    glyph = font2D.charToGlyph(c);
1021:                    if (glyph != missingGlyph
1022:                            && glyph < numGlyphs
1023:                            && (glyphToCharMap[glyph] == CharToGlyphMapper.INVISIBLE_GLYPH_ID)) {
1024:                        glyphToCharMap[glyph] = c;
1025:                    }
1026:                }
1027:                return glyphToCharMap;
1028:            }
1029:
1030:            /**
1031:             * Strokes the outline of a Shape using the settings of the current
1032:             * graphics state.  The rendering attributes applied include the
1033:             * clip, transform, paint or color, composite and stroke attributes.
1034:             * @param s The shape to be drawn.
1035:             * @see #setStroke
1036:             * @see #setPaint
1037:             * @see java.awt.Graphics#setColor
1038:             * @see #transform
1039:             * @see #setTransform
1040:             * @see #clip
1041:             * @see #setClip
1042:             * @see #setComposite
1043:             */
1044:            public void draw(Shape s) {
1045:
1046:                fill(getStroke().createStrokedShape(s));
1047:            }
1048:
1049:            /**
1050:             * Fills the interior of a Shape using the settings of the current
1051:             * graphics state. The rendering attributes applied include the
1052:             * clip, transform, paint or color, and composite.
1053:             * @see #setPaint
1054:             * @see java.awt.Graphics#setColor
1055:             * @see #transform
1056:             * @see #setTransform
1057:             * @see #setComposite
1058:             * @see #clip
1059:             * @see #setClip
1060:             */
1061:            public void fill(Shape s) {
1062:                Paint paint = getPaint();
1063:
1064:                try {
1065:                    fill(s, (Color) paint);
1066:
1067:                    /* The PathGraphics class only supports filling with
1068:                     * solid colors and so we do not expect the cast of Paint
1069:                     * to Color to fail. If it does fail then something went
1070:                     * wrong, like the app draw a page with a solid color but
1071:                     * then redrew it with a Gradient.
1072:                     */
1073:                } catch (ClassCastException e) {
1074:                    throw new IllegalArgumentException(
1075:                            "Expected a Color instance");
1076:                }
1077:            }
1078:
1079:            public void fill(Shape s, Color color) {
1080:                AffineTransform deviceTransform = getTransform();
1081:
1082:                if (getClip() != null) {
1083:                    deviceClip(getClip().getPathIterator(deviceTransform));
1084:                }
1085:                deviceFill(s.getPathIterator(deviceTransform), color);
1086:            }
1087:
1088:            /**
1089:             * Fill the path defined by <code>pathIter</code>
1090:             * with the specified color.
1091:             * The path is provided in device coordinates.
1092:             */
1093:            protected abstract void deviceFill(PathIterator pathIter,
1094:                    Color color);
1095:
1096:            /*
1097:             * Set the clipping path to that defined by
1098:             * the passed in <code>PathIterator</code>.
1099:             */
1100:            protected abstract void deviceClip(PathIterator pathIter);
1101:
1102:            /*
1103:             * Draw the outline of the rectangle without using path
1104:             * if supported by platform.
1105:             */
1106:            protected abstract void deviceFrameRect(int x, int y, int width,
1107:                    int height, Color color);
1108:
1109:            /*
1110:             * Draw a line without using path if supported by platform.
1111:             */
1112:            protected abstract void deviceDrawLine(int xBegin, int yBegin,
1113:                    int xEnd, int yEnd, Color color);
1114:
1115:            /*
1116:             * Fill a rectangle using specified color.
1117:             */
1118:            protected abstract void deviceFillRect(int x, int y, int width,
1119:                    int height, Color color);
1120:
1121:            /* Obtain a BI from known implementations of java.awt.Image
1122:             */
1123:            protected BufferedImage getBufferedImage(Image img) {
1124:                if (img instanceof  BufferedImage) {
1125:                    // Otherwise we expect a BufferedImage to behave as a standard BI
1126:                    return (BufferedImage) img;
1127:                } else if (img instanceof  ToolkitImage) {
1128:                    // This can be null if the image isn't loaded yet.
1129:                    // This is fine as in that case our caller will return
1130:                    // as it will only draw a fully loaded image
1131:                    return ((ToolkitImage) img).getBufferedImage();
1132:                } else if (img instanceof  VolatileImage) {
1133:                    // VI needs to make a new BI: this is unavoidable but
1134:                    // I don't expect VI's to be "huge" in any case.
1135:                    return ((VolatileImage) img).getSnapshot();
1136:                } else {
1137:                    // may be null or may be some non-standard Image which
1138:                    // shouldn't happen as Image is implemented by the platform
1139:                    // not by applications
1140:                    // If you add a new Image implementation to the platform you
1141:                    // will need to support it here similarly to VI.
1142:                    return null;
1143:                }
1144:            }
1145:
1146:            /**
1147:             * Return true if the BufferedImage argument has non-opaque
1148:             * bits in it and therefore can not be directly rendered by
1149:             * GDI. Return false if the image is opaque. If this function
1150:             * can not tell for sure whether the image has transparent
1151:             * pixels then it assumes that it does.
1152:             */
1153:            protected boolean hasTransparentPixels(BufferedImage bufferedImage) {
1154:                ColorModel colorModel = bufferedImage.getColorModel();
1155:                boolean hasTransparency = colorModel == null ? true
1156:                        : colorModel.getTransparency() != ColorModel.OPAQUE;
1157:
1158:                /*
1159:                 * For the default INT ARGB check the image to see if any pixels are
1160:                 * really transparent. If there are no transparent pixels then the
1161:                 * transparency of the color model can be ignored.
1162:                 * We assume that IndexColorModel images have already been
1163:                 * checked for transparency and will be OPAQUE unless they actually
1164:                 * have transparent pixels present.
1165:                 */
1166:                if (hasTransparency && bufferedImage != null) {
1167:                    if (bufferedImage.getType() == BufferedImage.TYPE_INT_ARGB
1168:                            || bufferedImage.getType() == BufferedImage.TYPE_INT_ARGB_PRE) {
1169:                        DataBuffer db = bufferedImage.getRaster()
1170:                                .getDataBuffer();
1171:                        SampleModel sm = bufferedImage.getRaster()
1172:                                .getSampleModel();
1173:                        if (db instanceof  DataBufferInt
1174:                                && sm instanceof  SinglePixelPackedSampleModel) {
1175:                            SinglePixelPackedSampleModel psm = (SinglePixelPackedSampleModel) sm;
1176:                            // Stealing the data array for reading only...
1177:                            int[] int_data = SunWritableRaster.stealData(
1178:                                    (DataBufferInt) db, 0);
1179:                            int x = bufferedImage.getMinX();
1180:                            int y = bufferedImage.getMinY();
1181:                            int w = bufferedImage.getWidth();
1182:                            int h = bufferedImage.getHeight();
1183:                            int stride = psm.getScanlineStride();
1184:                            boolean hastranspixel = false;
1185:                            for (int j = y; j < y + h; j++) {
1186:                                int yoff = j * stride;
1187:                                for (int i = x; i < x + w; i++) {
1188:                                    if ((int_data[yoff + i] & 0xff000000) != 0xff000000) {
1189:                                        hastranspixel = true;
1190:                                        break;
1191:                                    }
1192:                                }
1193:                                if (hastranspixel) {
1194:                                    break;
1195:                                }
1196:                            }
1197:                            if (hastranspixel == false) {
1198:                                hasTransparency = false;
1199:                            }
1200:                        }
1201:                    }
1202:                }
1203:
1204:                return hasTransparency;
1205:            }
1206:
1207:            protected boolean isBitmaskTransparency(BufferedImage bufferedImage) {
1208:                ColorModel colorModel = bufferedImage.getColorModel();
1209:                return (colorModel != null && colorModel.getTransparency() == ColorModel.BITMASK);
1210:            }
1211:
1212:            /* An optimisation for the special case of ICM images which have
1213:             * bitmask transparency.
1214:             */
1215:            protected boolean drawBitmaskImage(BufferedImage bufferedImage,
1216:                    AffineTransform xform, Color bgcolor, int srcX, int srcY,
1217:                    int srcWidth, int srcHeight) {
1218:
1219:                ColorModel colorModel = bufferedImage.getColorModel();
1220:                IndexColorModel icm;
1221:                int[] pixels;
1222:
1223:                if (!(colorModel instanceof  IndexColorModel)) {
1224:                    return false;
1225:                } else {
1226:                    icm = (IndexColorModel) colorModel;
1227:                }
1228:
1229:                if (colorModel.getTransparency() != ColorModel.BITMASK) {
1230:                    return false;
1231:                }
1232:
1233:                // to be compatible with 1.1 printing which treated b/g colors
1234:                // with alpha 128 as opaque
1235:                if (bgcolor != null && bgcolor.getAlpha() < 128) {
1236:                    return false;
1237:                }
1238:
1239:                if ((xform.getType() & ~(AffineTransform.TYPE_UNIFORM_SCALE
1240:                        | AffineTransform.TYPE_TRANSLATION | AffineTransform.TYPE_QUADRANT_ROTATION)) != 0) {
1241:                    return false;
1242:                }
1243:
1244:                if ((getTransform().getType() & ~(AffineTransform.TYPE_UNIFORM_SCALE
1245:                        | AffineTransform.TYPE_TRANSLATION | AffineTransform.TYPE_QUADRANT_ROTATION)) != 0) {
1246:                    return false;
1247:                }
1248:
1249:                BufferedImage subImage = null;
1250:                Raster raster = bufferedImage.getRaster();
1251:                int transpixel = icm.getTransparentPixel();
1252:                byte[] alphas = new byte[icm.getMapSize()];
1253:                icm.getAlphas(alphas);
1254:                if (transpixel >= 0) {
1255:                    alphas[transpixel] = 0;
1256:                }
1257:
1258:                /* don't just use srcWidth & srcHeight from application - they
1259:                 * may exceed the extent of the image - may need to clip.
1260:                 * The image xform will ensure that points are still mapped properly.
1261:                 */
1262:                int rw = raster.getWidth();
1263:                int rh = raster.getHeight();
1264:                if (srcX > rw || srcY > rh) {
1265:                    return false;
1266:                }
1267:                int right, bottom, wid, hgt;
1268:                if (srcX + srcWidth > rw) {
1269:                    right = rw;
1270:                    wid = right - srcX;
1271:                } else {
1272:                    right = srcX + srcWidth;
1273:                    wid = srcWidth;
1274:                }
1275:                if (srcY + srcHeight > rh) {
1276:                    bottom = rh;
1277:                    hgt = bottom - srcY;
1278:                } else {
1279:                    bottom = srcY + srcHeight;
1280:                    hgt = srcHeight;
1281:                }
1282:                pixels = new int[wid];
1283:                for (int j = srcY; j < bottom; j++) {
1284:                    int startx = -1;
1285:                    raster.getPixels(srcX, j, wid, 1, pixels);
1286:                    for (int i = srcX; i < right; i++) {
1287:                        if (alphas[pixels[i - srcX]] == 0) {
1288:                            if (startx >= 0) {
1289:                                subImage = bufferedImage.getSubimage(startx, j,
1290:                                        i - startx, 1);
1291:                                xform.translate(startx, j);
1292:                                drawImageToPlatform(subImage, xform, bgcolor,
1293:                                        0, 0, i - startx, 1, true);
1294:                                xform.translate(-startx, -j);
1295:                                startx = -1;
1296:                            }
1297:                        } else if (startx < 0) {
1298:                            startx = i;
1299:                        }
1300:                    }
1301:                    if (startx >= 0) {
1302:                        subImage = bufferedImage.getSubimage(startx, j, right
1303:                                - startx, 1);
1304:                        xform.translate(startx, j);
1305:                        drawImageToPlatform(subImage, xform, bgcolor, 0, 0,
1306:                                right - startx, 1, true);
1307:                        xform.translate(-startx, -j);
1308:                    }
1309:                }
1310:                return true;
1311:            }
1312:
1313:            /**
1314:             * The various <code>drawImage()</code> methods for
1315:             * <code>PathGraphics</code> are all decomposed
1316:             * into an invocation of <code>drawImageToPlatform</code>.
1317:             * The portion of the passed in image defined by
1318:             * <code>srcX, srcY, srcWidth, and srcHeight</code>
1319:             * is transformed by the supplied AffineTransform and
1320:             * drawn using PS to the printer context.
1321:             * 
1322:             * @param	img	The image to be drawn.
1323:             *                  This method does nothing if <code>img</code> is null.
1324:             * @param	xform	Used to tranform the image before drawing.
1325:             *			This can be null.
1326:             * @param	bgcolor	This color is drawn where the image has transparent
1327:             *			pixels. If this parameter is null then the
1328:             *			pixels already in the destination should show
1329:             *			through.
1330:             * @param	srcX	With srcY this defines the upper-left corner
1331:             *			of the portion of the image to be drawn.
1332:             *
1333:             * @param	srcY	With srcX this defines the upper-left corner
1334:             *			of the portion of the image to be drawn.
1335:             * @param	srcWidth    The width of the portion of the image to
1336:             *			    be drawn.
1337:             * @param	srcHeight   The height of the portion of the image to
1338:             *			    be drawn.
1339:             * @param   handlingTransparency if being recursively called to
1340:             *                    print opaque region of transparent image
1341:             */
1342:            protected abstract boolean drawImageToPlatform(Image img,
1343:                    AffineTransform xform, Color bgcolor, int srcX, int srcY,
1344:                    int srcWidth, int srcHeight, boolean handlingTransparency);
1345:
1346:            /** 
1347:             * Draws as much of the specified image as is currently available.
1348:             * The image is drawn with its top-left corner at 
1349:             * (<i>x</i>,&nbsp;<i>y</i>) in this graphics context's coordinate 
1350:             * space. Transparent pixels in the image do not affect whatever 
1351:             * pixels are already there. 
1352:             * <p>
1353:             * This method returns immediately in all cases, even if the
1354:             * complete image has not yet been loaded, and it has not been dithered 
1355:             * and converted for the current output device.
1356:             * <p>
1357:             * If the image has not yet been completely loaded, then
1358:             * <code>drawImage</code> returns <code>false</code>. As more of
1359:             * the image becomes available, the process that draws the image notifies 
1360:             * the specified image observer.
1361:             * @param    img the specified image to be drawn.
1362:             * @param    x   the <i>x</i> coordinate.
1363:             * @param    y   the <i>y</i> coordinate.
1364:             * @param    observer    object to be notified as more of 
1365:             *                          the image is converted.
1366:             * @see      java.awt.Image
1367:             * @see      java.awt.image.ImageObserver
1368:             * @see      java.awt.image.ImageObserver#imageUpdate(java.awt.Image, int, int, int, int, int)
1369:             * @since    JDK1.0
1370:             */
1371:            public boolean drawImage(Image img, int x, int y,
1372:                    ImageObserver observer) {
1373:
1374:                return drawImage(img, x, y, null, observer);
1375:            }
1376:
1377:            /**
1378:             * Draws as much of the specified image as has already been scaled
1379:             * to fit inside the specified rectangle.
1380:             * <p>
1381:             * The image is drawn inside the specified rectangle of this 
1382:             * graphics context's coordinate space, and is scaled if 
1383:             * necessary. Transparent pixels do not affect whatever pixels
1384:             * are already there. 
1385:             * <p>
1386:             * This method returns immediately in all cases, even if the
1387:             * entire image has not yet been scaled, dithered, and converted
1388:             * for the current output device.
1389:             * If the current output representation is not yet complete, then
1390:             * <code>drawImage</code> returns <code>false</code>. As more of
1391:             * the image becomes available, the process that draws the image notifies 
1392:             * the image observer by calling its <code>imageUpdate</code> method.
1393:             * <p>
1394:             * A scaled version of an image will not necessarily be
1395:             * available immediately just because an unscaled version of the
1396:             * image has been constructed for this output device.  Each size of
1397:             * the image may be cached separately and generated from the original
1398:             * data in a separate image production sequence.
1399:             * @param    img    the specified image to be drawn.
1400:             * @param    x      the <i>x</i> coordinate.
1401:             * @param    y      the <i>y</i> coordinate.
1402:             * @param    width  the width of the rectangle.
1403:             * @param    height the height of the rectangle.
1404:             * @param    observer    object to be notified as more of 
1405:             *                          the image is converted.
1406:             * @see      java.awt.Image
1407:             * @see      java.awt.image.ImageObserver
1408:             * @see      java.awt.image.ImageObserver#imageUpdate(java.awt.Image, int, int, int, int, int)
1409:             * @since    JDK1.0
1410:             */
1411:            public boolean drawImage(Image img, int x, int y, int width,
1412:                    int height, ImageObserver observer) {
1413:
1414:                return drawImage(img, x, y, width, height, null, observer);
1415:
1416:            }
1417:
1418:            /*
1419:             * Draws as much of the specified image as is currently available.
1420:             * The image is drawn with its top-left corner at 
1421:             * (<i>x</i>,&nbsp;<i>y</i>) in this graphics context's coordinate 
1422:             * space.  Transparent pixels are drawn in the specified
1423:             * background color.
1424:             * <p> 
1425:             * This operation is equivalent to filling a rectangle of the
1426:             * width and height of the specified image with the given color and then
1427:             * drawing the image on top of it, but possibly more efficient.
1428:             * <p>
1429:             * This method returns immediately in all cases, even if the
1430:             * complete image has not yet been loaded, and it has not been dithered 
1431:             * and converted for the current output device.
1432:             * <p>
1433:             * If the image has not yet been completely loaded, then
1434:             * <code>drawImage</code> returns <code>false</code>. As more of
1435:             * the image becomes available, the process that draws the image notifies 
1436:             * the specified image observer.
1437:             * @param    img    the specified image to be drawn.
1438:             *                  This method does nothing if <code>img</code> is null.
1439:             * @param    x      the <i>x</i> coordinate.
1440:             * @param    y      the <i>y</i> coordinate.
1441:             * @param    bgcolor the background color to paint under the
1442:             *                   non-opaque portions of the image.
1443:             *			 In this WPathGraphics implementation,
1444:             *			 this parameter can be null in which
1445:             *			 case that background is made a transparent
1446:             *			 white.
1447:             * @param    observer    object to be notified as more of 
1448:             *                          the image is converted.
1449:             * @see      java.awt.Image
1450:             * @see      java.awt.image.ImageObserver
1451:             * @see      java.awt.image.ImageObserver#imageUpdate(java.awt.Image, int, int, int, int, int)
1452:             * @since    JDK1.0
1453:             */
1454:            public boolean drawImage(Image img, int x, int y, Color bgcolor,
1455:                    ImageObserver observer) {
1456:
1457:                if (img == null) {
1458:                    return true;
1459:                }
1460:
1461:                boolean result;
1462:                int srcWidth = img.getWidth(null);
1463:                int srcHeight = img.getHeight(null);
1464:
1465:                if (srcWidth < 0 || srcHeight < 0) {
1466:                    result = false;
1467:                } else {
1468:                    result = drawImage(img, x, y, srcWidth, srcHeight, bgcolor,
1469:                            observer);
1470:                }
1471:
1472:                return result;
1473:            }
1474:
1475:            /**
1476:             * Draws as much of the specified image as has already been scaled
1477:             * to fit inside the specified rectangle.
1478:             * <p>
1479:             * The image is drawn inside the specified rectangle of this 
1480:             * graphics context's coordinate space, and is scaled if 
1481:             * necessary. Transparent pixels are drawn in the specified
1482:             * background color. 
1483:             * This operation is equivalent to filling a rectangle of the
1484:             * width and height of the specified image with the given color and then
1485:             * drawing the image on top of it, but possibly more efficient.
1486:             * <p>
1487:             * This method returns immediately in all cases, even if the
1488:             * entire image has not yet been scaled, dithered, and converted
1489:             * for the current output device.
1490:             * If the current output representation is not yet complete then
1491:             * <code>drawImage</code> returns <code>false</code>. As more of
1492:             * the image becomes available, the process that draws the image notifies 
1493:             * the specified image observer.
1494:             * <p>
1495:             * A scaled version of an image will not necessarily be
1496:             * available immediately just because an unscaled version of the
1497:             * image has been constructed for this output device.  Each size of
1498:             * the image may be cached separately and generated from the original
1499:             * data in a separate image production sequence.
1500:             * @param    img       the specified image to be drawn.
1501:             *                     This method does nothing if <code>img</code> is null.
1502:             * @param    x         the <i>x</i> coordinate.
1503:             * @param    y         the <i>y</i> coordinate.
1504:             * @param    width     the width of the rectangle.
1505:             * @param    height    the height of the rectangle.
1506:             * @param    bgcolor   the background color to paint under the
1507:             *                         non-opaque portions of the image.
1508:             * @param    observer    object to be notified as more of 
1509:             *                          the image is converted.
1510:             * @see      java.awt.Image
1511:             * @see      java.awt.image.ImageObserver
1512:             * @see      java.awt.image.ImageObserver#imageUpdate(java.awt.Image, int, int, int, int, int)
1513:             * @since    JDK1.0
1514:             */
1515:            public boolean drawImage(Image img, int x, int y, int width,
1516:                    int height, Color bgcolor, ImageObserver observer) {
1517:
1518:                if (img == null) {
1519:                    return true;
1520:                }
1521:
1522:                boolean result;
1523:                int srcWidth = img.getWidth(null);
1524:                int srcHeight = img.getHeight(null);
1525:
1526:                if (srcWidth < 0 || srcHeight < 0) {
1527:                    result = false;
1528:                } else {
1529:                    result = drawImage(img, x, y, x + width, y + height, 0, 0,
1530:                            srcWidth, srcHeight, observer);
1531:                }
1532:
1533:                return result;
1534:            }
1535:
1536:            /**
1537:             * Draws as much of the specified area of the specified image as is
1538:             * currently available, scaling it on the fly to fit inside the
1539:             * specified area of the destination drawable surface. Transparent pixels 
1540:             * do not affect whatever pixels are already there.
1541:             * <p>
1542:             * This method returns immediately in all cases, even if the
1543:             * image area to be drawn has not yet been scaled, dithered, and converted
1544:             * for the current output device.
1545:             * If the current output representation is not yet complete then
1546:             * <code>drawImage</code> returns <code>false</code>. As more of
1547:             * the image becomes available, the process that draws the image notifies 
1548:             * the specified image observer.
1549:             * <p>
1550:             * This method always uses the unscaled version of the image
1551:             * to render the scaled rectangle and performs the required
1552:             * scaling on the fly. It does not use a cached, scaled version
1553:             * of the image for this operation. Scaling of the image from source
1554:             * to destination is performed such that the first coordinate
1555:             * of the source rectangle is mapped to the first coordinate of
1556:             * the destination rectangle, and the second source coordinate is
1557:             * mapped to the second destination coordinate. The subimage is
1558:             * scaled and flipped as needed to preserve those mappings.
1559:             * @param       img the specified image to be drawn
1560:             * @param       dx1 the <i>x</i> coordinate of the first corner of the
1561:             *                    destination rectangle.
1562:             * @param       dy1 the <i>y</i> coordinate of the first corner of the
1563:             *                    destination rectangle.
1564:             * @param       dx2 the <i>x</i> coordinate of the second corner of the
1565:             *                    destination rectangle.
1566:             * @param       dy2 the <i>y</i> coordinate of the second corner of the
1567:             *                    destination rectangle.
1568:             * @param       sx1 the <i>x</i> coordinate of the first corner of the
1569:             *                    source rectangle.
1570:             * @param       sy1 the <i>y</i> coordinate of the first corner of the
1571:             *                    source rectangle.
1572:             * @param       sx2 the <i>x</i> coordinate of the second corner of the
1573:             *                    source rectangle.
1574:             * @param       sy2 the <i>y</i> coordinate of the second corner of the
1575:             *                    source rectangle.
1576:             * @param       observer object to be notified as more of the image is
1577:             *                    scaled and converted.
1578:             * @see         java.awt.Image
1579:             * @see         java.awt.image.ImageObserver
1580:             * @see         java.awt.image.ImageObserver#imageUpdate(java.awt.Image, int, int, int, int, int)
1581:             * @since       JDK1.1
1582:             */
1583:            public boolean drawImage(Image img, int dx1, int dy1, int dx2,
1584:                    int dy2, int sx1, int sy1, int sx2, int sy2,
1585:                    ImageObserver observer) {
1586:
1587:                return drawImage(img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2,
1588:                        null, observer);
1589:            }
1590:
1591:            /**
1592:             * Draws as much of the specified area of the specified image as is
1593:             * currently available, scaling it on the fly to fit inside the
1594:             * specified area of the destination drawable surface. 
1595:             * <p>
1596:             * Transparent pixels are drawn in the specified background color. 
1597:             * This operation is equivalent to filling a rectangle of the
1598:             * width and height of the specified image with the given color and then
1599:             * drawing the image on top of it, but possibly more efficient.
1600:             * <p>
1601:             * This method returns immediately in all cases, even if the
1602:             * image area to be drawn has not yet been scaled, dithered, and converted
1603:             * for the current output device.
1604:             * If the current output representation is not yet complete then
1605:             * <code>drawImage</code> returns <code>false</code>. As more of
1606:             * the image becomes available, the process that draws the image notifies 
1607:             * the specified image observer.
1608:             * <p>
1609:             * This method always uses the unscaled version of the image
1610:             * to render the scaled rectangle and performs the required
1611:             * scaling on the fly. It does not use a cached, scaled version
1612:             * of the image for this operation. Scaling of the image from source
1613:             * to destination is performed such that the first coordinate
1614:             * of the source rectangle is mapped to the first coordinate of
1615:             * the destination rectangle, and the second source coordinate is
1616:             * mapped to the second destination coordinate. The subimage is
1617:             * scaled and flipped as needed to preserve those mappings.
1618:             * @param       img the specified image to be drawn
1619:             *                  This method does nothing if <code>img</code> is null.
1620:             * @param       dx1 the <i>x</i> coordinate of the first corner of the
1621:             *                    destination rectangle.
1622:             * @param       dy1 the <i>y</i> coordinate of the first corner of the
1623:             *                    destination rectangle.
1624:             * @param       dx2 the <i>x</i> coordinate of the second corner of the
1625:             *                    destination rectangle.
1626:             * @param       dy2 the <i>y</i> coordinate of the second corner of the
1627:             *                    destination rectangle.
1628:             * @param       sx1 the <i>x</i> coordinate of the first corner of the
1629:             *                    source rectangle.
1630:             * @param       sy1 the <i>y</i> coordinate of the first corner of the
1631:             *                    source rectangle.
1632:             * @param       sx2 the <i>x</i> coordinate of the second corner of the
1633:             *                    source rectangle.
1634:             * @param       sy2 the <i>y</i> coordinate of the second corner of the
1635:             *                    source rectangle.
1636:             * @param       bgcolor the background color to paint under the
1637:             *                    non-opaque portions of the image.
1638:             * @param       observer object to be notified as more of the image is
1639:             *                    scaled and converted.
1640:             * @see         java.awt.Image
1641:             * @see         java.awt.image.ImageObserver
1642:             * @see         java.awt.image.ImageObserver#imageUpdate(java.awt.Image, int, int, int, int, int)
1643:             * @since       JDK1.1
1644:             */
1645:            public boolean drawImage(Image img, int dx1, int dy1, int dx2,
1646:                    int dy2, int sx1, int sy1, int sx2, int sy2, Color bgcolor,
1647:                    ImageObserver observer) {
1648:
1649:                if (img == null) {
1650:                    return true;
1651:                }
1652:                int imgWidth = img.getWidth(null);
1653:                int imgHeight = img.getHeight(null);
1654:
1655:                if (imgWidth < 0 || imgHeight < 0) {
1656:                    return true;
1657:                }
1658:
1659:                int srcWidth = sx2 - sx1;
1660:                int srcHeight = sy2 - sy1;
1661:
1662:                /* Create a transform which describes the changes
1663:                 * from the source coordinates to the destination
1664:                 * coordinates. The scaling is determined by the
1665:                 * ratio of the two rectangles, while the translation
1666:                 * comes from the difference of their origins.
1667:                 */
1668:                float scalex = (float) (dx2 - dx1) / srcWidth;
1669:                float scaley = (float) (dy2 - dy1) / srcHeight;
1670:                AffineTransform xForm = new AffineTransform(scalex, 0, 0,
1671:                        scaley, dx1 - (sx1 * scalex), dy1 - (sy1 * scaley));
1672:
1673:                /* drawImageToPlatform needs the top-left of the source area and
1674:                 * a positive width and height. The xform describes how to map
1675:                 * src->dest, so that information is not lost.
1676:                 */
1677:                int tmp = 0;
1678:                if (sx2 < sx1) {
1679:                    tmp = sx1;
1680:                    sx1 = sx2;
1681:                    sx2 = tmp;
1682:                }
1683:                if (sy2 < sy1) {
1684:                    tmp = sy1;
1685:                    sy1 = sy2;
1686:                    sy2 = tmp;
1687:                }
1688:
1689:                /* if src area is beyond the bounds of the image, we must clip it.
1690:                 * The transform is based on the specified area, not the clipped one.
1691:                 */
1692:                if (sx1 < 0) {
1693:                    sx1 = 0;
1694:                } else if (sx1 > imgWidth) { // empty srcArea, nothing to draw
1695:                    sx1 = imgWidth;
1696:                }
1697:                if (sx2 < 0) { // empty srcArea, nothing to draw
1698:                    sx2 = 0;
1699:                } else if (sx2 > imgWidth) {
1700:                    sx2 = imgWidth;
1701:                }
1702:                if (sy1 < 0) {
1703:                    sy1 = 0;
1704:                } else if (sy1 > imgHeight) { // empty srcArea
1705:                    sy1 = imgHeight;
1706:                }
1707:                if (sy2 < 0) { // empty srcArea
1708:                    sy2 = 0;
1709:                } else if (sy2 > imgHeight) {
1710:                    sy2 = imgHeight;
1711:                }
1712:
1713:                srcWidth = sx2 - sx1;
1714:                srcHeight = sy2 - sy1;
1715:
1716:                if (srcWidth <= 0 || srcHeight <= 0) {
1717:                    return true;
1718:                }
1719:
1720:                return drawImageToPlatform(img, xForm, bgcolor, sx1, sy1,
1721:                        srcWidth, srcHeight, false);
1722:
1723:            }
1724:
1725:            /**
1726:             * Draws an image, applying a transform from image space into user space
1727:             * before drawing.
1728:             * The transformation from user space into device space is done with
1729:             * the current transform in the Graphics2D.
1730:             * The given transformation is applied to the image before the
1731:             * transform attribute in the Graphics2D state is applied.
1732:             * The rendering attributes applied include the clip, transform,
1733:             * and composite attributes. Note that the result is
1734:             * undefined, if the given transform is noninvertible.
1735:             * @param img The image to be drawn.
1736:             *            This method does nothing if <code>img</code> is null.
1737:             * @param xform The transformation from image space into user space.
1738:             * @param obs The image observer to be notified as more of the image
1739:             * is converted.
1740:             * @see #transform
1741:             * @see #setTransform
1742:             * @see #setComposite
1743:             * @see #clip
1744:             * @see #setClip
1745:             */
1746:            public boolean drawImage(Image img, AffineTransform xform,
1747:                    ImageObserver obs) {
1748:
1749:                if (img == null) {
1750:                    return true;
1751:                }
1752:
1753:                boolean result;
1754:                int srcWidth = img.getWidth(null);
1755:                int srcHeight = img.getHeight(null);
1756:
1757:                if (srcWidth < 0 || srcHeight < 0) {
1758:                    result = false;
1759:                } else {
1760:                    result = drawImageToPlatform(img, xform, null, 0, 0,
1761:                            srcWidth, srcHeight, false);
1762:                }
1763:
1764:                return result;
1765:            }
1766:
1767:            /**
1768:             * Draws a BufferedImage that is filtered with a BufferedImageOp.
1769:             * The rendering attributes applied include the clip, transform
1770:             * and composite attributes.  This is equivalent to:
1771:             * <pre>
1772:             * img1 = op.filter(img, null);
1773:             * drawImage(img1, new AffineTransform(1f,0f,0f,1f,x,y), null);
1774:             * </pre>
1775:             * @param op The filter to be applied to the image before drawing.
1776:             * @param img The BufferedImage to be drawn.
1777:             *            This method does nothing if <code>img</code> is null.
1778:             * @param x,y The location in user space where the image should be drawn.
1779:             * @see #transform
1780:             * @see #setTransform
1781:             * @see #setComposite
1782:             * @see #clip
1783:             * @see #setClip
1784:             */
1785:            public void drawImage(BufferedImage img, BufferedImageOp op, int x,
1786:                    int y) {
1787:
1788:                if (img == null) {
1789:                    return;
1790:                }
1791:
1792:                int srcWidth = img.getWidth(null);
1793:                int srcHeight = img.getHeight(null);
1794:
1795:                if (op != null) {
1796:                    img = op.filter(img, null);
1797:                }
1798:                if (srcWidth <= 0 || srcHeight <= 0) {
1799:                    return;
1800:                } else {
1801:                    AffineTransform xform = new AffineTransform(1f, 0f, 0f, 1f,
1802:                            x, y);
1803:                    drawImageToPlatform(img, xform, null, 0, 0, srcWidth,
1804:                            srcHeight, false);
1805:                }
1806:
1807:            }
1808:
1809:            /**
1810:             * Draws an image, applying a transform from image space into user space
1811:             * before drawing.
1812:             * The transformation from user space into device space is done with
1813:             * the current transform in the Graphics2D.
1814:             * The given transformation is applied to the image before the
1815:             * transform attribute in the Graphics2D state is applied.
1816:             * The rendering attributes applied include the clip, transform,
1817:             * and composite attributes. Note that the result is
1818:             * undefined, if the given transform is noninvertible.
1819:             * @param img The image to be drawn.
1820:             *            This method does nothing if <code>img</code> is null.
1821:             * @param xform The transformation from image space into user space.
1822:             * @see #transform
1823:             * @see #setTransform
1824:             * @see #setComposite
1825:             * @see #clip
1826:             * @see #setClip
1827:             */
1828:            public void drawRenderedImage(RenderedImage img,
1829:                    AffineTransform xform) {
1830:
1831:                if (img == null) {
1832:                    return;
1833:                }
1834:
1835:                BufferedImage bufferedImage = null;
1836:                int srcWidth = img.getWidth();
1837:                int srcHeight = img.getHeight();
1838:
1839:                if (srcWidth <= 0 || srcHeight <= 0) {
1840:                    return;
1841:                }
1842:
1843:                if (img instanceof  BufferedImage) {
1844:                    bufferedImage = (BufferedImage) img;
1845:                } else {
1846:                    bufferedImage = new BufferedImage(srcWidth, srcHeight,
1847:                            BufferedImage.TYPE_INT_ARGB);
1848:                    Graphics2D imageGraphics = bufferedImage.createGraphics();
1849:                    imageGraphics.drawRenderedImage(img, xform);
1850:                }
1851:
1852:                drawImageToPlatform(bufferedImage, xform, null, 0, 0, srcWidth,
1853:                        srcHeight, false);
1854:
1855:            }
1856:
1857:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.