Source Code Cross Referenced for PDFGraphics.java in  » PDF » gnujpdf » gnu » jpdf » 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 » PDF » gnujpdf » gnu.jpdf 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * $Id: PDFGraphics.java,v 1.2 2001/11/16 15:26:04 ezb Exp $ 
0003:         *
0004:         * $Date: 2001/11/16 15:26:04 $
0005:         *
0006:         * 
0007:         * This library is free software; you can redistribute it and/or
0008:         * modify it under the terms of the GNU Lesser General Public 
0009:         * License as published by the Free Software Foundation; either 
0010:         * version 2.1 of the License, or (at your option) any later version. 
0011:         * 
0012:         * This library is distributed in the hope that it will be useful, 
0013:         * but WITHOUT ANY WARRANTY; without even the implied warranty of 
0014:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
0015:         * Lesser General Public License for more details. 
0016:         * 
0017:         * You should have received a copy of the GNU Lesser General Public 
0018:         * License along with this library; if not, write to the Free Software 
0019:         * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
0020:         */
0021:        package gnu.jpdf;
0022:
0023:        import java.awt.*;
0024:        import java.awt.image.*;
0025:        import java.io.*;
0026:        import java.util.*;
0027:
0028:        /**
0029:         * This class is our implementation of AWT's Graphics class. It provides a
0030:         * Java standard way of rendering into a PDF Document's Page.
0031:         *
0032:         * @author Peter T Mount, http://www.retep.org.uk/pdf/
0033:         * @author Eric Z. Beard, ericzbeard@hotmail.com
0034:         * @author $Author: ezb $
0035:         * @version $Revision: 1.2 $, $Date: 2001/11/16 15:26:04 $
0036:         * @see gnu.jpdf.PDFGraphics
0037:         */
0038:        public class PDFGraphics extends Graphics implements  Serializable {
0039:
0040:            /*
0041:             * NOTE: The original class is the work of Peter T. Mount, who released it 
0042:             * in the uk.org.retep.pdf package.  It was modified by Eric Z. Beard as 
0043:             * follows: 
0044:             * The package name was changed to gnu.pdf.  
0045:             * The formatting was changed a little bit.
0046:             * This used to subclass an abstract class in a different package with 
0047:             *   the same name (confusing). Now it's one concrete class.
0048:             * drawImage() was implemented 
0049:             * It is still licensed under the LGPL.
0050:             */
0051:
0052:            // Implementation notes:
0053:            //
0054:            // Pages 333-335 of the PDF Reference Manual
0055:            //
0056:            // Unless absolutely required, use the moveto, lineto and rectangle
0057:            // operators to perform those actions. 
0058:            // They contain some extra optimisations
0059:            // which will reduce the output size by up to half in some cases.
0060:            //
0061:            // About fill operators: For correct operation, any fill operation should
0062:            // start with closeBlock(), which will ensure any previous path is completed,
0063:            // otherwise you may find the fill will include previous items
0064:            /**
0065:             * This is the media we are working with
0066:             */
0067:            protected Rectangle media;
0068:
0069:            /**
0070:             * The media's rotation, either 0,90,180 or 270.
0071:             */
0072:            private int mediaRot;
0073:
0074:            /**
0075:             * This is used to translate coordinates
0076:             */
0077:            protected int trax;
0078:
0079:            /**
0080:             * This is used to translate coordinates
0081:             */
0082:            protected int tray;
0083:
0084:            /**
0085:             * Part of the optimiser:
0086:             * This is written to the stream when the newPath() is called. np then clears
0087:             * this value.
0088:             */
0089:            private String pre_np;
0090:
0091:            /**
0092:             * Part of the optimiser:
0093:             * When true, we are drawing a path.
0094:             */
0095:            private boolean inStroke;
0096:
0097:            /**
0098:             * Part of the optimiser:
0099:             * The last known moveto/lineto x coordinate
0100:             * @see #moveto
0101:             * @see #lineto
0102:             */
0103:            private int lx; // last known moveto/lineto coords
0104:
0105:            /**
0106:             * Part of the optimiser:
0107:             * The last known moveto/lineto y coordinate
0108:             * @see #moveto
0109:             * @see #lineto
0110:             */
0111:            private int ly; // last known moveto/lineto coords
0112:
0113:            /**
0114:             * Part of the optimiser:
0115:             * When true, we are within a Text Block.
0116:             */
0117:            private boolean inText; // true if within a Text Block - see newTextBlock()
0118:
0119:            /**
0120:             * Part of the optimiser:
0121:             * When true, the font has changed.
0122:             */
0123:            private boolean newFont; // true if the font changes - see newTextBlock()
0124:
0125:            /**
0126:             * Part of the optimiser:
0127:             * The last x coordinate when rendering text
0128:             */
0129:            private int tx; // the last coordinate for text rendering
0130:
0131:            /**
0132:             * Part of the optimiser:
0133:             * The last y coordinate when rendering text
0134:             */
0135:            private int ty; // the last coordinate for text rendering
0136:
0137:            /**
0138:             * This is the current pen/fill color
0139:             */
0140:            private Color color;
0141:
0142:            /**
0143:             * This is the current font (in PDF format)
0144:             */
0145:            private PDFFont pdffont;
0146:
0147:            /**
0148:             * This is the current font (in Java format)
0149:             */
0150:            private Font font;
0151:
0152:            /**
0153:             * This is the PrintWriter used to write PDF drawing commands to the Stream
0154:             */
0155:            private PrintWriter pw;
0156:
0157:            /**
0158:             * This is a reference to the PDFPage we are rendering to.
0159:             */
0160:            private PDFPage page;
0161:
0162:            /**
0163:             * This is true for any Graphics instance that didn't create the stream.
0164:             * @see #create
0165:             */
0166:            private boolean child;
0167:
0168:            /**
0169:             * This method creates a new instance of the class based on the page 
0170:             * and a print writer. 
0171:             *
0172:             * @param page the page to attach to
0173:             * @param pw the <code>PrintWriter</code> to attach to.
0174:             */
0175:            protected PDFGraphics createGraphic(PDFPage page, PrintWriter pw) {
0176:                PDFGraphics g = new PDFGraphics();
0177:                g.init(page, pw);
0178:                return g;
0179:            }
0180:
0181:            /**
0182:             * This is called by PDFPage when creating a Graphcis instance.
0183:             * @param page The PDFPage to draw onto.
0184:             */
0185:            protected void init(PDFPage page) {
0186:                this .page = page;
0187:
0188:                // We are the parent instance
0189:                child = false;
0190:
0191:                // Now create a stream to store the graphics in
0192:                PDFStream stream = new PDFStream();
0193:                page.getPDFDocument().add(stream);
0194:                page.add(stream);
0195:                pw = stream.getWriter();
0196:
0197:                // initially, we are limited to the page size
0198:                clipRectangle = new Rectangle(page.getMedia());
0199:
0200:                // finally initialise the stream
0201:                init();
0202:            }
0203:
0204:            /**
0205:             * This method is used internally by create() and by the PDFJob class
0206:             * @param page PDFPage to draw into
0207:             * @param pw PrintWriter to use
0208:             */
0209:            protected void init(PDFPage page, PrintWriter pw) {
0210:                this .page = page;
0211:                this .pw = pw;
0212:
0213:                // In this case, we didn't create the stream (our parent did)
0214:                // so child is true (see dispose)
0215:                child = true;
0216:
0217:                // finally initialise the stream
0218:                init();
0219:            }
0220:
0221:            /**
0222:             * This initialises the stream by saving the current graphics state, and
0223:             * setting up the default line width (for us).
0224:             *
0225:             * It also sets up the instance ready for graphic operations and any
0226:             * optimisations.
0227:             *
0228:             * <p>For child instances, the stream is already open, so this should keep
0229:             * things happy.
0230:             */
0231:            private void init() {
0232:                // save graphics state (restored by dispose)
0233:                if (child) {
0234:                    pw.print("q ");
0235:                }
0236:
0237:                // Set the line width
0238:                setDefaultLineWidth();
0239:
0240:                // now initialise the instance
0241:                //setColor(Color.black);
0242:                color = Color.black;
0243:                // possible: if parent.color is not black, then force black?
0244:                // must check to see what AWT does?
0245:
0246:                // get the page dimensions (needed to get the orientation correct)
0247:                media = page.getMedia();
0248:                mediaRot = page.getOrientation();
0249:
0250:                // Finally set the page Orientation
0251:                if (!child) {
0252:                    setOrientation();
0253:                }
0254:            }
0255:
0256:            /**
0257:             * Returns the PrintWriter handling the underlying stream
0258:             * @return the PrintWriter handling the underlying stream
0259:             */
0260:            public PrintWriter getWriter() {
0261:                return pw;
0262:            }
0263:
0264:            /**
0265:             * Returns the associated PDFPage for this graphic
0266:             * @return the associated PDFPage for this graphic
0267:             */
0268:            public PDFPage getPage() {
0269:                return page;
0270:            }
0271:
0272:            /**
0273:             * <p>This returns a child instance of this Graphics object. As with AWT, the
0274:             * affects of using the parent instance while the child exists, is not
0275:             * determined.</p>
0276:             *
0277:             * <p>Once complete, the child should be released with it's dispose()
0278:             * method which will restore the graphics state to it's parent.</p>
0279:             *
0280:             * @return Graphics object to render onto the page
0281:             */
0282:            public Graphics create() {
0283:                closeBlock();
0284:
0285:                PDFGraphics g = createGraphic(page, pw);
0286:
0287:                // The new instance inherits a few items
0288:                g.media = new Rectangle(media);
0289:                g.trax = trax;
0290:                g.tray = tray;
0291:                g.clipRectangle = new Rectangle(clipRectangle);
0292:
0293:                return (Graphics) g;
0294:            } // end create()
0295:
0296:            /**
0297:             * <p>This releases any resources used by this Graphics object. You must use
0298:             * this method once finished with it. Leaving it open will leave the PDF
0299:             * stream in an inconsistent state, and will produce errors.</p>
0300:             *
0301:             * <p>If this was created with Graphics.create() then the parent instance
0302:             * can be used again. If not, then this closes the graphics operations for
0303:             * this page when used with PDFJob.</p>
0304:             *
0305:             * <p>When using PDFPage, you can create another fresh Graphics instance,
0306:             * which will draw over this one.</p>
0307:             *
0308:             */
0309:            public void dispose() {
0310:                closeBlock();
0311:                if (child) {
0312:                    pw.println("Q"); // restore graphics context
0313:                } else {
0314:                    pw.close(); // close the stream if were the parent
0315:                }
0316:            }
0317:
0318:            // *********************************************
0319:            // **** Implementation of java.awt.Graphics ****
0320:            // *********************************************
0321:
0322:            //============ Rectangle operations =======================
0323:
0324:            /**
0325:             * This simply draws a White Rectangle to clear the area
0326:             * @param x coord
0327:             * @param y coord
0328:             * @param w width
0329:             * @param h height
0330:             */
0331:            public void clearRect(int x, int y, int w, int h) {
0332:                closeBlock();
0333:                pw.print("q 1 1 1 RG ");// save state, set colour to White
0334:                drawRect(x, y, w, h);
0335:                closeBlock("B Q"); // close fill & stroke, then restore state
0336:            }
0337:
0338:            /**
0339:             * We override Graphics.drawRect as it doesn't join the 4 lines.
0340:             * Also, PDF provides us with a Rectangle operator, so we will use that.
0341:             * @param x coord
0342:             * @param y coord
0343:             * @param w width
0344:             * @param h height
0345:             */
0346:            public void drawRect(int x, int y, int w, int h) {
0347:                newPath();
0348:                pw.print(cxy(x, y) + cwh(w, h) + "re "); // rectangle
0349:                lx = x; // I don't know if this is correct, but lets see if PDF ends
0350:                ly = y; // the rectangle at it's start.
0351:                // stroke (optimised)
0352:            }
0353:
0354:            /**
0355:             * <p>Not implemented</p>
0356:             *
0357:             * <p>Draws a 3-D highlighted outline of the specified rectangle. 
0358:             * The edges of the rectangle are highlighted so that they appear 
0359:             * to be beveled and lit from the upper left corner. 
0360:             * The colors used for the highlighting effect are determined based on 
0361:             * the current color. The resulting rectangle covers an area that 
0362:             * is width + 1 pixels wide by height + 1 pixels tall.
0363:             *</p>
0364:             *
0365:             * @param x an <code>int</code> value
0366:             * @param y an <code>int</code> value
0367:             * @param width an <code>int</code> value
0368:             * @param height an <code>int</code> value
0369:             * @param raised a <code>boolean</code> value
0370:             */
0371:            public void draw3DRect(int x, int y, int width, int height,
0372:                    boolean raised) {
0373:                // Not implemented
0374:            }
0375:
0376:            /**
0377:             * <p>Not implemented</p>
0378:             *
0379:             * @param x an <code>int</code> value
0380:             * @param y an <code>int</code> value
0381:             * @param width an <code>int</code> value
0382:             * @param height an <code>int</code> value
0383:             * @param raised a <code>boolean</code> value
0384:             */
0385:            public void fill3DRect(int x, int y, int width, int height,
0386:                    boolean raised) {
0387:                // Not implemented
0388:            }
0389:
0390:            /**
0391:             * Fills a rectangle with the current colour
0392:             *
0393:             * @param x coord
0394:             * @param y coord
0395:             * @param w width
0396:             * @param h height
0397:             */
0398:            public void fillRect(int x, int y, int w, int h) {
0399:                // end any path & stroke. This ensures the fill is on this
0400:                // rectangle, and not on any previous graphics
0401:                closeBlock();
0402:                drawRect(x, y, w, h);
0403:                closeBlock("B"); // rectangle, fill stroke
0404:            }
0405:
0406:            //============ Round Rectangle operations =======================
0407:
0408:            /**
0409:             * This is not yet implemented
0410:             *
0411:             * @param x coord
0412:             * @param y coord
0413:             * @param w width
0414:             * @param h height
0415:             * @param aw a-width
0416:             * @param ah a-height
0417:             */
0418:            public void fillRoundRect(int x, int y, int w, int h, int aw, int ah) {
0419:            }
0420:
0421:            /**
0422:             * This is not yet implemented
0423:             *
0424:             * @param x coord
0425:             * @param y coord
0426:             * @param w width
0427:             * @param h height
0428:             * @param aw a-width
0429:             * @param ah a-height
0430:             */
0431:            public void drawRoundRect(int x, int y, int w, int h, int aw, int ah) {
0432:            }
0433:
0434:            //============ Oval operations =======================
0435:
0436:            /**
0437:             * <p>Draws an oval</p>
0438:             *
0439:             * @param x coord
0440:             * @param y coord
0441:             * @param w width
0442:             * @param h height
0443:             */
0444:            public void drawOval(int x, int y, int w, int h) {
0445:                drawArc(x, y, w, h, 0, 360);
0446:            }
0447:
0448:            /**
0449:             * <p>Draws a filled oval</p>
0450:             *
0451:             * @param x coord
0452:             * @param y coord
0453:             * @param w width
0454:             * @param h height
0455:             */
0456:            public void fillOval(int x, int y, int w, int h) {
0457:                fillArc(x, y, w, h, 0, 360);
0458:            }
0459:
0460:            //============ Polygon operations =======================
0461:
0462:            /**
0463:             * Draws a polygon, linking the first and last coordinates.
0464:             * @param xp Array of x coordinates
0465:             * @param yp Array of y coordinates
0466:             * @param np number of points in polygon
0467:             */
0468:            public void drawPolygon(int[] xp, int[] yp, int np) {
0469:                polygon(xp, yp, np);
0470:                closeBlock("s"); // closepath and stroke
0471:            }
0472:
0473:            /**
0474:             * Draws a polyline. The first and last coordinates are not linked.
0475:             * @param xp Array of x coordinates
0476:             * @param yp Array of y coordinates
0477:             * @param np number of points in polyline
0478:             */
0479:            public void drawPolyline(int[] xp, int[] yp, int np) {
0480:                polygon(xp, yp, np);
0481:                // no stroke, as we keep the optimiser in stroke state
0482:            }
0483:
0484:            /**
0485:             * Fills a polygon.
0486:             * @param xp Array of x coordinates
0487:             * @param yp Array of y coordinates
0488:             * @param np number of points in polygon
0489:             */
0490:            public void fillPolygon(int[] xp, int[] yp, int np) {
0491:                closeBlock(); // finish off any previous paths
0492:                polygon(xp, yp, np);
0493:                closeBlock("b"); // closepath, fill and stroke
0494:            }
0495:
0496:            //============ Image operations =======================
0497:
0498:            /**
0499:             * Draw's an image onto the page
0500:             * @param img The java.awt.Image
0501:             * @param x coordinate on page
0502:             * @param y coordinate on page
0503:             * @param obs ImageObserver
0504:             * @return true if drawn
0505:             */
0506:            public boolean drawImage(Image img, int x, int y, ImageObserver obs) {
0507:                return drawImage(img, x, y, img.getWidth(obs), img
0508:                        .getHeight(obs), obs);
0509:            }
0510:
0511:            /**
0512:             * <p>Draws an image onto the page.</p>
0513:             *
0514:             * <p>This method is implemented with ASCIIbase85 encoding and the 
0515:             * zip stream deflater.  It results in a stream that is anywhere 
0516:             * from 3 to 10 times as big as the image.  This obviusly needs some 
0517:             * improvement, but it works well for small images</p>
0518:             *
0519:             * @param img The java.awt.Image
0520:             * @param x coordinate on page
0521:             * @param y coordinate on page
0522:             * @param w Width on page
0523:             * @param h height on page
0524:             * @param obs ImageObserver
0525:             * @return true if drawn
0526:             */
0527:            public boolean drawImage(Image img, int x, int y, int w, int h,
0528:                    ImageObserver obs) {
0529:                closeBlock();
0530:                PDFImage image = new PDFImage(img, x, y, w, h, obs);
0531:                // The image needs to be registered in several places
0532:                page.getPDFDocument().setImageName(image);
0533:                page.getPDFDocument().add(image);
0534:                page.addToProcset("/ImageC");
0535:                page.addResource("/XObject << " + image.getName() + " "
0536:                        + image.getSerialID() + " 0 R >>");
0537:                // q w 0 0 h x y cm % the coordinate matrix
0538:                pw.print("q "
0539:                        + image.getWidth()
0540:                        + " 0 0 "
0541:                        + image.getHeight()
0542:                        + " "
0543:                        + x
0544:                        + " "
0545:                        + ((int) page.getDimension().getHeight() - y - image
0546:                                .getHeight()) + " cm \n" + image.getName()
0547:                        + " Do\nQ\n");
0548:                return false;
0549:            }
0550:
0551:            /**
0552:             * <p>Draw's an image onto the page, with a backing colour.</p>
0553:             *
0554:             * @param img The java.awt.Image
0555:             * @param x coordinate on page
0556:             * @param y coordinate on page
0557:             * @param bgcolor Background colour
0558:             * @param obs ImageObserver
0559:             * @return true if drawn
0560:             */
0561:            public boolean drawImage(Image img, int x, int y, Color bgcolor,
0562:                    ImageObserver obs) {
0563:                return drawImage(img, x, y, img.getWidth(obs), img
0564:                        .getHeight(obs), bgcolor, obs);
0565:            }
0566:
0567:            /**
0568:             * <p>Draw's an image onto the page, with a backing colour.</p>
0569:             *
0570:             * @param img The java.awt.Image
0571:             * @param x coordinate on page
0572:             * @param y coordinate on page
0573:             * @param w Width on page
0574:             * @param h height on page
0575:             * @param bgcolor Background colour
0576:             * @param obs ImageObserver
0577:             * @return true if drawn
0578:             */
0579:            public boolean drawImage(Image img, int x, int y, int w, int h,
0580:                    Color bgcolor, ImageObserver obs) {
0581:                closeBlock();
0582:                pw.print("q "); // save state
0583:                Color c = color; // save current colour
0584:                setColor(bgcolor); // change the colour
0585:                drawRect(x, y, w, h);
0586:                closeBlock("B Q"); // fill stroke, restore state
0587:                color = c; // restore original colour
0588:                return drawImage(img, x, y, img.getWidth(obs), img
0589:                        .getHeight(obs), obs);
0590:            }
0591:
0592:            /**
0593:             * Draw's an image onto the page, with scaling
0594:             * <p>This is not yet supported.
0595:             *
0596:             * @param img The java.awt.Image
0597:             * @param dx1 coordinate on page
0598:             * @param dy1 coordinate on page
0599:             * @param dx2 coordinate on page
0600:             * @param dy2 coordinate on page
0601:             * @param sx1 coordinate on image
0602:             * @param sy1 coordinate on image
0603:             * @param sx2 coordinate on image
0604:             * @param sy2 coordinate on image
0605:             * @param obs ImageObserver
0606:             * @return true if drawn
0607:             */
0608:            public boolean drawImage(Image img, int dx1, int dy1, int dx2,
0609:                    int dy2, int sx1, int sy1, int sx2, int sy2,
0610:                    ImageObserver obs) {
0611:                // This shouldn't be too bad, just change the coordinate matrix
0612:                return false;
0613:            }
0614:
0615:            /**
0616:             * Draw's an image onto the page, with scaling
0617:             * <p>This is not yet supported.
0618:             *
0619:             * @param img The java.awt.Image
0620:             * @param dx1 coordinate on page
0621:             * @param dy1 coordinate on page
0622:             * @param dx2 coordinate on page
0623:             * @param dy2 coordinate on page
0624:             * @param sx1 coordinate on image
0625:             * @param sy1 coordinate on image
0626:             * @param sx2 coordinate on image
0627:             * @param sy2 coordinate on image
0628:             * @param bgcolor Background colour
0629:             * @param obs ImageObserver
0630:             * @return true if drawn
0631:             */
0632:            public boolean drawImage(Image img, int dx1, int dy1, int dx2,
0633:                    int dy2, int sx1, int sy1, int sx2, int sy2, Color bgcolor,
0634:                    ImageObserver obs) {
0635:                return false;
0636:            }
0637:
0638:            //============ Clipping operations =======================
0639:
0640:            /**
0641:             * This holds the current clipRectangle
0642:             */
0643:            protected Rectangle clipRectangle;
0644:
0645:            /**
0646:             * Clips to a set of coordinates
0647:             * @param x coord
0648:             * @param y coord
0649:             * @param w width
0650:             * @param h height
0651:             */
0652:            public void clipRect(int x, int y, int w, int h) {
0653:                setClip(x, y, w, h);
0654:            }
0655:
0656:            /**
0657:             * Clips to a set of coordinates
0658:             * @param x coord
0659:             * @param y coord
0660:             * @param w width
0661:             * @param h height
0662:             */
0663:            public void setClip(int x, int y, int w, int h) {
0664:                clipRectangle = new Rectangle(x, y, w, h);
0665:                closeBlock(); // finish off any existing paths
0666:                drawRect(x, y, w, h);
0667:                closeBlock("W n"); // clip to current path
0668:            }
0669:
0670:            /**
0671:             * As my JDK docs say, this may break with Java 2D.
0672:             * <p>Sets the clipping region to that of a Shape.
0673:             * @param s Shape to clip to.
0674:             */
0675:            public void setClip(Shape s) {
0676:                Rectangle r = s.getBounds();
0677:                setClip(r.x, r.y, r.width, r.height);
0678:            }
0679:
0680:            /**
0681:             * This extra method allows PDF users to clip to a Polygon.
0682:             *
0683:             * <p>In theory you could use setClip(), except that java.awt.Graphics
0684:             * only supports Rectangle with that method, so we will have an extra
0685:             * method.
0686:             * @param p Polygon to clip to
0687:             */
0688:            public void clipPolygon(Polygon p) {
0689:                closeBlock(); // finish off any existing path
0690:                polygon(p.xpoints, p.ypoints, p.npoints);
0691:                closeBlock("W"); // clip to current path
0692:                clipRectangle = p.getBounds();
0693:            }
0694:
0695:            /**
0696:             * Returns the Rectangle that fits the current clipping region
0697:             * @return the Rectangle that fits the current clipping region
0698:             */
0699:            public Rectangle getClipBounds() {
0700:                return clipRectangle;
0701:            }
0702:
0703:            //============ Colour operations =======================
0704:
0705:            /**
0706:             * Returns the current pen Colour
0707:             * @return the current pen Colour
0708:             */
0709:            public Color getColor() {
0710:                return color;
0711:            }
0712:
0713:            /**
0714:             * Sets the colour for drawing
0715:             * @param c Color to use
0716:             */
0717:            public void setColor(Color c) {
0718:                color = c;
0719:                double r = ((double) c.getRed()) / 255.0;
0720:                double g = ((double) c.getGreen()) / 255.0;
0721:                double b = ((double) c.getBlue()) / 255.0;
0722:                closeBlock(); // This ensures any paths are drawn in the previous colours
0723:                pw.println("" + r + " " + g + " " + b + " rg " + r + " " + g
0724:                        + " " + b + " RG");
0725:            }
0726:
0727:            /**
0728:             * Not implemented, as this is not supported in the PDF specification.
0729:             */
0730:            public void setPaintMode() {
0731:            }
0732:
0733:            /**
0734:             * Not implemented, as this is not supported in the PDF specification.
0735:             * @param c1 Color to xor with
0736:             */
0737:            public void setXORMode(Color c1) {
0738:            }
0739:
0740:            //============ Text operations =======================
0741:
0742:            /**
0743:             * Returns the FontMetrics for a font.
0744:             * <p>This doesn't work correctly. Perhaps having some way of mapping
0745:             * the base 14 fonts to our own FontMetrics implementation?
0746:             * @param font The java.awt.Font to return the metrics for
0747:             * @return FontMetrics for a font
0748:             */
0749:            public FontMetrics getFontMetrics(Font font) {
0750:                Frame dummy = new Frame();
0751:                dummy.addNotify();
0752:                Image image = dummy.createImage(100, 100);
0753:                if (image == null) {
0754:                    System.err.println("getFontMetrics: image is null");
0755:                }
0756:                Graphics graphics = image.getGraphics();
0757:                return graphics.getFontMetrics(font);
0758:
0759:            }
0760:
0761:            /**
0762:             * Return's the current font.
0763:             * @return the current font.
0764:             */
0765:            public Font getFont() {
0766:                if (font == null)
0767:                    setFont(new Font("SansSerif", Font.PLAIN, 12));
0768:                return font;
0769:            }
0770:
0771:            /**
0772:             * This sets the font.
0773:             * @param f java.awt.Font to set to.
0774:             */
0775:            public void setFont(Font f) {
0776:                // Optimise: Save some space if the font is already the current one.
0777:                if (font != f) {
0778:                    font = f;
0779:                    pdffont = page.getFont("/Type1", f.getName(), f.getStyle());
0780:
0781:                    // mark the font as changed
0782:                    newFont = true;
0783:                }
0784:            }
0785:
0786:            /**
0787:             * This draws a string.
0788:             * 
0789:             * @oaran s String to draw
0790:             * @param x coord
0791:             * @param y coord
0792:             */
0793:            public void drawString(String s, int x, int y) {
0794:                newTextBlock(x, y);
0795:                pw.println(PDFStringHelper.makePDFString(s) + " Tj");
0796:            }
0797:
0798:            /**
0799:             * <p>Not implemented</p>
0800:             *
0801:             * @param data a <code>byte[]</code> value
0802:             * @param offset an <code>int</code> value
0803:             * @param length an <code>int</code> value
0804:             * @param x an <code>int</code> value
0805:             * @param y an <code>int</code> value
0806:             */
0807:            public void drawBytes(byte[] data, int offset, int length, int x,
0808:                    int y) {
0809:
0810:            }
0811:
0812:            //============ Optimizers =======================
0813:
0814:            /**
0815:             * All functions should call this to close any existing optimised blocks.
0816:             */
0817:            void closeBlock() {
0818:                closeBlock("S");
0819:            }
0820:
0821:            /**
0822:             * <p>This is used by code that use the path in any way other than Stroke
0823:             * (like Fill, close path & Stroke etc). Usually this is used internally.</p>
0824:             *
0825:             * @param code PDF operators that will close the path
0826:             */
0827:            void closeBlock(String code) {
0828:                if (inText) {
0829:                    pw.println("ET Q");
0830:                    setOrientation(); // fixes Orientation matrix
0831:                }
0832:
0833:                if (inStroke) {
0834:                    pw.println(code);
0835:                }
0836:
0837:                inStroke = inText = false;
0838:            }
0839:
0840:            /**
0841:             * Functions that draw lines should start by calling this. It starts a
0842:             * new path unless inStroke is set, in that case it uses the existing path
0843:             */
0844:            void newPath() {
0845:                if (inText) {
0846:                    closeBlock();
0847:                }
0848:                if (!inStroke) {
0849:                    if (pre_np != null) {
0850:                        pw.print(pre_np); // this is the prefix set by setOrientation()
0851:                        pre_np = null;
0852:                    }
0853:                    pw.print("n ");
0854:                }
0855:
0856:                inText = false;
0857:                inStroke = true;
0858:
0859:                // an unlikely coordinate to fool the moveto() optimizer
0860:                lx = ly = -9999;
0861:            }
0862:
0863:            /**
0864:             * <p>Functions that draw text should start by calling this. It starts a text
0865:             * block (accounting for media orientation) unless we are already in a Text
0866:             * block.</p>
0867:             *
0868:             * <p>It also handles if the font has been changed since the current text
0869:             * block was started, so your function will be current.</p>
0870:             *
0871:             * @param x x coord in java space
0872:             * @param y y coord in java space
0873:             */
0874:            void newTextBlock(int x, int y) {
0875:                // close the current path if there is one
0876:                if (inStroke) {
0877:                    closeBlock();
0878:                }
0879:                // create the text block if one is not current. If we are, the newFont
0880:                // condition at the end catches font changes
0881:                if (!inText) {
0882:                    // This ensures that there is a font available
0883:                    getFont();
0884:
0885:                    pw.print("q BT ");
0886:                    tx = ty = 0;
0887:
0888:                    // produce the text matrix for the media
0889:                    switch (mediaRot) {
0890:                    case 0: // Portrait
0891:                        //pw.println("1 0 0 1 0 0 Tm");
0892:                        break;
0893:
0894:                    case 90: // Landscape
0895:                        pw.println("0 1 -1 0 0 0 Tm"); // rotate
0896:                        break;
0897:
0898:                    case 180: // Inverted Portrait
0899:                        pw.println("1 0 0 -1 0 0 Tm");
0900:                        break;
0901:
0902:                    case 270: // Seascape
0903:                        pw.println("0 -1 1 0 0 0 Tm"); // rotate
0904:                        break;
0905:                    }
0906:
0907:                    // move the text cursor by an absolute amount
0908:                    pw.print(txy(x, y) + "Td ");
0909:
0910:                } else {
0911:                    // move the text cursor by a relative amount
0912:                    //int ox=x-tx, oy=ty-y;
0913:                    //pw.print(""+ox+" "+oy+" Td ");
0914:                    //pw.print(cwh(x-tx,y-ty)+"Td ");
0915:                    pw.print(twh(x, y, tx, ty) + "Td ");
0916:                }
0917:
0918:                // preserve the coordinates for the next time
0919:                tx = x;
0920:                ty = y;
0921:
0922:                if (newFont || !inText)
0923:                    pw.print(pdffont.getName() + " " + font.getSize() + " Tf ");
0924:
0925:                // later add colour changes here (if required)
0926:
0927:                inStroke = newFont = false;
0928:                inText = true;
0929:            }
0930:
0931:            /**
0932:             * This is unsupported - how do you do this with Vector graphics?
0933:             * @param x coord
0934:             * @param y coord
0935:             * @param w width
0936:             * @param h height
0937:             * @param dx coord
0938:             * @param dy coord
0939:             */
0940:            public void copyArea(int x, int y, int w, int h, int dx, int dy) {
0941:                // Hmm...   Probably need to keep track of everything 
0942:                // that has been drawn so far to get the contents of an area
0943:            }
0944:
0945:            //============ Line operations =======================
0946:
0947:            /**
0948:             * Draws a line between two coordinates.
0949:             *
0950:             * If the first coordinate is the same as the last one drawn
0951:             * (ie a previous drawLine, moveto, etc) it is ignored.
0952:             * @param x1 coord
0953:             * @param y1 coord
0954:             * @param x2 coord
0955:             * @param y2 coord
0956:             */
0957:            public void drawLine(int x1, int y1, int x2, int y2) {
0958:                moveto(x1, y1);
0959:                lineto(x2, y2);
0960:            }
0961:
0962:            /**
0963:             * Translate the origin.
0964:             * @param x coord offset
0965:             * @param y coord offset
0966:             */
0967:            public void translate(int x, int y) {
0968:                trax += x;
0969:                tray += y;
0970:                //closeBlock();
0971:                //// we use cw & ch here as the coordinates are relative not absolute
0972:                //pw.println("1 0 0 1 "+cwh(x,y)+" cm");
0973:            }
0974:
0975:            //============ Arcs operations ==============================
0976:            // These are the standard Graphics operators. They use the
0977:            // arc extension operators to achieve the affect.
0978:
0979:            /**
0980:             * Draws an arc
0981:             * @param x coord
0982:             * @param y coord
0983:             * @param w width
0984:             * @param h height
0985:             * @param sa Start angle
0986:             * @param aa End angle
0987:             */
0988:            public void drawArc(int x, int y, int w, int h, int sa, int aa) {
0989:                w = w >> 1;
0990:                h = h >> 1;
0991:                x += w;
0992:                y += h;
0993:
0994:                arc((double) x, (double) y, (double) w, (double) h,
0995:                        (double) -sa, (double) (-sa - aa), false);
0996:            }
0997:
0998:            /**
0999:             * Fills an arc, joining the start and end coordinates
1000:             * @param x coord
1001:             * @param y coord
1002:             * @param w width
1003:             * @param h height
1004:             * @param sa Start angle
1005:             * @param aa End angle
1006:             */
1007:            public void fillArc(int x, int y, int w, int h, int sa, int aa) {
1008:                // here we fool the optimizer. We force any open path to be closed,
1009:                // then draw the arc. Finally, as the optimizer hasn't stroke'd the
1010:                // path, we close and fill it, and mark the Stroke as closed.
1011:                //
1012:                // Note: The lineto to the centre of the object is required, because
1013:                //       the fill only fills the arc. Skipping this includes an extra
1014:                //       chord, which isn't correct. Peter May 31 2000
1015:                closeBlock();
1016:                drawArc(x, y, w, h, sa, aa);
1017:                lineto(x + (w >> 1), y + (h >> 1));
1018:                closeBlock("b"); // closepath and fill
1019:            }
1020:
1021:            //============ Extension operations ==============================
1022:            // These are extensions, and provide access to PDF Specific
1023:            // operators.
1024:
1025:            /**
1026:             * This moves the current drawing point.
1027:             * @param x coord
1028:             * @param y coord
1029:             */
1030:            public void moveto(int x, int y) {
1031:                newPath();
1032:                if (lx != x && ly != y)
1033:                    pw.print(cxy(x, y) + "m ");
1034:                lx = x;
1035:                ly = y;
1036:            }
1037:
1038:            /**
1039:             * This moves the current drawing point.
1040:             * @param x coord
1041:             * @param y coord
1042:             */
1043:            public void moveto(double x, double y) {
1044:                newPath();
1045:                // no optimisation here as it may introduce errors on decimal coords.
1046:                pw.print(cxy(x, y) + "m ");
1047:                lx = (int) x;
1048:                ly = (int) y;
1049:            }
1050:
1051:            /**
1052:             * This adds a line segment to the current path
1053:             * @param x coord
1054:             * @param y coord
1055:             */
1056:            public void lineto(int x, int y) {
1057:                newPath();
1058:                if (lx != x && ly != y)
1059:                    pw.print(cxy(x, y) + "l ");
1060:                lx = x;
1061:                ly = y;
1062:            }
1063:
1064:            /**
1065:             * This adds a line segment to the current path
1066:             * @param x coord
1067:             * @param y coord
1068:             */
1069:            public void lineto(double x, double y) {
1070:                newPath();
1071:                // no optimisation here as it may introduce errors on decimal coords.
1072:                pw.print(cxy(x, y) + "l ");
1073:                lx = (int) x;
1074:                ly = (int) y;
1075:            }
1076:
1077:            /**
1078:             * This extension allows the width of the drawn line to be set
1079:             * @param w Line width in mm
1080:             */
1081:            public void setLineWidth(double w) {
1082:                closeBlock(); // draw any path before we change the line width
1083:                pw.println("" + w + " w");
1084:            }
1085:
1086:            /**
1087:             * This extension sets the line width to the default of 1mm which is what
1088:             * Java uses when drawing to a PrintJob.
1089:             */
1090:            public void setDefaultLineWidth() {
1091:                closeBlock(); // draw any path before we change the line width
1092:                pw.println("1 w");
1093:            }
1094:
1095:            /**
1096:             * This is used to add a polygon to the current path.
1097:             * Used by drawPolygon(), drawPolyline() and fillPolygon() etal
1098:             * @param xp Array of x coordinates
1099:             * @param yp Array of y coordinates
1100:             * @param np number of points in polygon
1101:             * @see #drawPolygon
1102:             * @see #drawPolyline
1103:             * @see #fillPolygon
1104:             */
1105:            public void polygon(int[] xp, int[] yp, int np) {
1106:                // newPath() not needed here as moveto does it ;-)
1107:                moveto(xp[0], yp[0]);
1108:                for (int i = 1; i < np; i++)
1109:                    lineto(xp[i], yp[i]);
1110:            }
1111:
1112:            /**
1113:             * This extension appends a Bezier curve to the path. The curve
1114:             * extends from the current point to (x3,y3) using (x1,y1) and
1115:             * (x2,y2) as the Bezier control points.
1116:             * <p>The new current point is (x3,y3)
1117:             *
1118:             * @param x1 First control point
1119:             * @param y1 First control point
1120:             * @param x2 Second control point
1121:             * @param y2 Second control point
1122:             * @param x3 Destination point
1123:             * @param y3 Destination point
1124:             */
1125:            public void curveto(int x1, int y1, int x2, int y2, int x3, int y3) {
1126:                newPath();
1127:                pw.println(cxy(x1, y1) + cxy(x2, y2) + cxy(x3, y3) + "c");
1128:                lx = x3;
1129:                ly = y3;
1130:            }
1131:
1132:            /**
1133:             * This extension appends a Bezier curve to the path. The curve
1134:             * extends from the current point to (x3,y3) using (x1,y1) and
1135:             * (x2,y2) as the Bezier control points.
1136:             * <p>The new current point is (x3,y3)
1137:             *
1138:             * @param x1 First control point
1139:             * @param y1 First control point
1140:             * @param x2 Second control point
1141:             * @param y2 Second control point
1142:             * @param x3 Destination point
1143:             * @param y3 Destination point
1144:             */
1145:            public void curveto(double x1, double y1, double x2, double y2,
1146:                    double x3, double y3) {
1147:                newPath();
1148:                pw.println(cxy(x1, y1) + cxy(x2, y2) + cxy(x3, y3) + "c");
1149:                lx = (int) x3;
1150:                ly = (int) y3;
1151:            }
1152:
1153:            /**
1154:             * This extension appends a Bezier curve to the path. The curve
1155:             * extends from the current point to (x2,y2) using the current
1156:             * point and (x1,y1) as the Bezier control points.
1157:             * <p>The new current point is (x2,y2)
1158:             *
1159:             * @param x1 Second control point
1160:             * @param y1 Second control point
1161:             * @param x2 Destination point
1162:             * @param y2 Destination point
1163:             */
1164:            public void curveto(int x1, int y1, int x2, int y2) {
1165:                newPath();
1166:                pw.println(cxy(x1, y1) + cxy(x2, y2) + "v");
1167:                lx = x2;
1168:                ly = y2;
1169:            }
1170:
1171:            /**
1172:             * This extension appends a Bezier curve to the path. The curve
1173:             * extends from the current point to (x2,y2) using the current
1174:             * point and (x1,y1) as the Bezier control points.
1175:             * <p>The new current point is (x2,y2)
1176:             *
1177:             * @param x1 Second control point
1178:             * @param y1 Second control point
1179:             * @param x2 Destination point
1180:             * @param y2 Destination point
1181:             */
1182:            public void curveto(double x1, double y1, double x2, double y2) {
1183:                newPath();
1184:                pw.println(cxy(x1, y1) + cxy(x2, y2) + "v");
1185:                lx = (int) x2;
1186:                ly = (int) y2;
1187:            }
1188:
1189:            /**
1190:             * This extension appends a Bezier curve to the path. The curve
1191:             * extends from the current point to (x2,y2) using (x1,y1) and
1192:             * the end point as the Bezier control points.
1193:             * <p>The new current point is (x2,y2)
1194:             *
1195:             * @param x1 Second control point
1196:             * @param y1 Second control point
1197:             * @param x2 Destination point
1198:             * @param y2 Destination point
1199:             */
1200:            public void curveto2(int x1, int y1, int x2, int y2) {
1201:                newPath();
1202:                pw.println(cxy(x1, y1) + cxy(x2, y2) + "y");
1203:                lx = x2;
1204:                ly = y2;
1205:            }
1206:
1207:            /**
1208:             * This extension appends a Bezier curve to the path. The curve
1209:             * extends from the current point to (x2,y2) using (x1,y1) and
1210:             * the end point as the Bezier control points.
1211:             * <p>The new current point is (x2,y2)
1212:             *
1213:             * @param x1 Second control point
1214:             * @param y1 Second control point
1215:             * @param x2 Destination point
1216:             * @param y2 Destination point
1217:             */
1218:            public void curveto2(double x1, double y1, double x2, double y2) {
1219:                newPath();
1220:                pw.println(cxy(x1, y1) + cxy(x2, y2) + "y");
1221:                lx = (int) x2;
1222:                ly = (int) y2;
1223:            }
1224:
1225:            // Arcs are horrible and complex. They are at the end of the
1226:            // file, because they are the largest. This is because, unlike
1227:            // Postscript, PDF doesn't have any arc operators, so we must
1228:            // implement them by converting into one or more Bezier curves
1229:            // (which is how Postscript does them internally).
1230:
1231:            /**
1232:             * One degree in radians
1233:             */
1234:            private static final double degrees_to_radians = Math.PI / 180.0;
1235:
1236:            /**
1237:             * This produces an arc by breaking it down into one or more Bezier curves.
1238:             * It is used internally to implement the drawArc and fillArc methods.
1239:             *
1240:             * @param axc X coordinate of arc centre
1241:             * @param ayc Y coordinate of arc centre
1242:             * @param width of bounding rectangle
1243:             * @param height of bounding rectangle
1244:             * @param ang1 Start angle
1245:             * @param ang2 End angle
1246:             * @param clockwise true to draw clockwise, false anti-clockwise
1247:             */
1248:            public void arc(double axc, double ayc, double width,
1249:                    double height, double ang1, double ang2, boolean clockwise) {
1250:
1251:                double adiff;
1252:                double x0, y0;
1253:                double x3r, y3r;
1254:                boolean first = true;
1255:
1256:                // may not need this
1257:                //if( ar < 0 ) {
1258:                //ang1 += fixed_180;
1259:                //ang2 += fixed_180;
1260:                //ar = - ar;
1261:                //}
1262:
1263:                double ang1r = (ang1 % 360.0) * degrees_to_radians;
1264:
1265:                double sin0 = Math.sin(ang1r);
1266:                double cos0 = Math.cos(ang1r);
1267:
1268:                x0 = axc + width * cos0;
1269:                y0 = ayc + height * sin0;
1270:
1271:                // NB: !clockwise here as Java Space is inverted to User Space
1272:                if (!clockwise) {
1273:                    // Quadrant reduction
1274:                    while (ang1 < ang2)
1275:                        ang2 -= 360.0;
1276:                    while ((adiff = ang2 - ang1) < -90.0) {
1277:                        double w = sin0;
1278:                        sin0 = -cos0;
1279:                        cos0 = w;
1280:                        x3r = axc + width * cos0;
1281:                        y3r = ayc + height * sin0;
1282:                        arc_add(first, width, height, x0, y0, x3r, y3r,
1283:                                (x0 + width * cos0), (y0 + height * sin0));
1284:
1285:                        x0 = x3r;
1286:                        y0 = y3r;
1287:                        ang1 -= 90.0;
1288:                        first = false;
1289:                    }
1290:                } else {
1291:                    // Quadrant reduction
1292:                    while (ang2 < ang1)
1293:                        ang2 += 360.0;
1294:                    while ((adiff = ang2 - ang1) > 90.0) {
1295:                        double w = cos0;
1296:                        cos0 = -sin0;
1297:                        sin0 = w;
1298:                        x3r = axc + width * cos0;
1299:                        y3r = ayc + height * sin0;
1300:                        arc_add(first, width, height, x0, y0, x3r, y3r,
1301:                                (x0 + width * cos0), (y0 + height * sin0));
1302:
1303:                        x0 = x3r;
1304:                        y0 = y3r;
1305:                        ang1 += 90.0;
1306:                        first = false;
1307:                    }
1308:                }
1309:
1310:                // Compute the intersection of the tangents.
1311:                // We know that -fixed_90 <= adiff <= fixed_90.
1312:                double trad = Math.tan(adiff * (degrees_to_radians / 2));
1313:                double ang2r = ang2 * degrees_to_radians;
1314:                double xt = x0 - trad * width * sin0;
1315:                double yt = y0 + trad * height * cos0;
1316:                arc_add(first, width, height, x0, y0, (axc + width
1317:                        * Math.cos(ang2r)), (ayc + height * Math.sin(ang2r)),
1318:                        xt, yt);
1319:            }
1320:
1321:            /**
1322:             * Used by the arc method to actually add an arc to the path
1323:             * Important: We write directly to the stream here, because this method
1324:             * operates in User space, rather than Java space.
1325:             * @param first true if the first arc
1326:             * @param w width
1327:             * @param h height
1328:             * @param x0 coord
1329:             * @param y0 coord
1330:             * @param x3 coord
1331:             * @param y3 coord
1332:             * @param xt coord
1333:             * @param yt coord
1334:             */
1335:            private void arc_add(boolean first, double w, double h, double x0,
1336:                    double y0, double x3, double y3, double xt, double yt) {
1337:                double dx = xt - x0, dy = yt - y0;
1338:                double dist = dx * dx + dy * dy;
1339:                double w2 = w * w, h2 = h * h;
1340:                double r2 = w2 + h2;
1341:
1342:                double fw = 0.0, fh = 0.0;
1343:                if (dist < (r2 * 1.0e8)) {
1344:                    fw = (4.0 / 3.0) / (1 + Math.sqrt(1 + dist / w2));
1345:                    fh = (4.0 / 3.0) / (1 + Math.sqrt(1 + dist / h2));
1346:                }
1347:
1348:                // The path must have a starting point
1349:                if (first)
1350:                    moveto(x0, y0);
1351:
1352:                double x = x0 + ((xt - x0) * fw);
1353:                double y = y0 + ((yt - y0) * fh);
1354:                x0 = x3 + ((xt - x3) * fw);
1355:                y0 = y3 + ((yt - y3) * fh);
1356:
1357:                // Finally the actual curve.
1358:                curveto(x, y, x0, y0, x3, y3);
1359:            }
1360:
1361:            /**
1362:             * This sets the media Orientation (0=Portrait, 90=Landscape,
1363:             * 180=Inverse, 270=Seascape).
1364:             *
1365:             * <p>Normally, this is called when the Graphics instance is created, but
1366:             * if the media is changed, then this must be called, especially when using
1367:             * the PDFJob class to create the file.
1368:             *
1369:             */
1370:            public void setOrientation() {
1371:                mediaRot = page.getOrientation();
1372:                switch (mediaRot) {
1373:                case 0: // Portrait
1374:                    //pre_np = "1 0 0 1 0 "+media.height+" cm 1 0 0 -1 0 0 cm ";
1375:                    break;
1376:
1377:                case 90: // Landscape
1378:                    //pw.println("0.7071067 0.7071067 -0.7071067 0.7071067 0 0 Tm");
1379:                    //pw.println("1 0 0 1 0 -"+page.getMedia().height+" Tm");
1380:                    //pre_np = "1 0 0 1 "+page.getMedia().width+" 0 cm 0 1 -1 0 0 0 cm ";
1381:                    break;
1382:
1383:                case 180: // Inverted Portrait
1384:                    //pre_np = "1 0 0 1 "+media.width+" 0 cm -1 0 0 1 0 0 cm ";
1385:                    break;
1386:
1387:                case 270: // Seascape
1388:                    // check this
1389:                    //pre_np = "1 0 0 1 -"+page.getMedia().width+" 0 cm 0 -1 1 0 0 0 cm ";
1390:                    break;
1391:                }
1392:            }
1393:
1394:            /**
1395:             * Converts the Java space coordinates into pdf.
1396:             * @param x coord
1397:             * @param y coord
1398:             * @return String containing the coordinates in PDF space
1399:             */
1400:            private String cxy(int x, int y) {
1401:                return cxy((double) x, (double) y);
1402:            }
1403:
1404:            /**
1405:             * Converts the Java space coordinates into pdf.
1406:             * @param x coord
1407:             * @param y coord
1408:             * @return String containing the coordinates in PDF space
1409:             */
1410:            private String cxy(double x, double y) {
1411:                double nx = x, ny = y; // scratch
1412:                double mw = (double) (media.width);
1413:                double mh = (double) (media.height);
1414:
1415:                // handle any translations
1416:                x -= trax;
1417:                y -= tray;
1418:
1419:                switch (mediaRot) {
1420:                case 0:
1421:                    // Portrait
1422:                    //nx = x;
1423:                    ny = mh - y;
1424:                    break;
1425:
1426:                case 90:
1427:                    // Landscape
1428:                    nx = y;
1429:                    ny = x;
1430:                    break;
1431:
1432:                case 180:
1433:                    // Inverse Portrait
1434:                    nx = mw - x;
1435:                    //ny = y;
1436:                    break;
1437:
1438:                case 270:
1439:                    // Seascape
1440:                    nx = mw - y;
1441:                    ny = mh - x;
1442:                    break;
1443:                }
1444:
1445:                return "" + nx + " " + ny + " ";
1446:            }
1447:
1448:            /**
1449:             * Converts the Java space dimension into pdf.
1450:             * @param w width
1451:             * @param h height
1452:             * @return String containing the coordinates in PDF space
1453:             */
1454:            private String cwh(int w, int h) {
1455:                return cwh((double) w, (double) h);
1456:            }
1457:
1458:            /**
1459:             * Converts the Java space dimension into pdf.
1460:             * @param w width
1461:             * @param h height
1462:             * @return String containing the coordinates in PDF space
1463:             */
1464:            private String cwh(double w, double h) {
1465:                double nw = w, nh = h; // scratch
1466:
1467:                switch (mediaRot) {
1468:                case 0:
1469:                    // Portrait
1470:                    //nw = w;
1471:                    nh = -h;
1472:                    break;
1473:
1474:                case 90:
1475:                    // Landscape
1476:                    nw = h;
1477:                    nh = w;
1478:                    break;
1479:
1480:                case 180:
1481:                    // Inverse Portrait
1482:                    nw = -w;
1483:                    //nh = h;
1484:                    break;
1485:
1486:                case 270:
1487:                    // Seascape
1488:                    nw = -h;
1489:                    nh = -w;
1490:                    break;
1491:                }
1492:
1493:                return "" + nw + " " + nh + " ";
1494:            }
1495:
1496:            /**
1497:             * Converts the Java space coordinates into pdf text space.
1498:             * @param x coord
1499:             * @param y coord
1500:             * @return String containing the coordinates in PDF text space
1501:             */
1502:            private String txy(int x, int y) {
1503:                int nx = x, ny = y;
1504:                int mw = media.width;
1505:                int mh = media.height;
1506:
1507:                // handle any translations
1508:                x += trax;
1509:                y += tray;
1510:
1511:                switch (mediaRot) {
1512:                case 0:
1513:                    // Portrait
1514:                    //nx = x;
1515:                    ny = mh - y;
1516:                    break;
1517:
1518:                case 90:
1519:                    // Landscape
1520:                    //nx = y;
1521:                    //ny = x;
1522:                    nx = x;
1523:                    ny = -y;
1524:                    break;
1525:
1526:                case 180:
1527:                    // Inverse Portrait
1528:                    // to be completed
1529:                    nx = mw - x;
1530:                    //ny = y;
1531:                    break;
1532:
1533:                case 270:
1534:                    // Seascape
1535:                    // to be completed
1536:                    nx = mw - y;
1537:                    ny = mh - x;
1538:                    break;
1539:                }
1540:
1541:                return "" + nx + " " + ny + " ";
1542:            }
1543:
1544:            /**
1545:             * Converts the Java space coordinates into pdf text space.
1546:             * @param x coord
1547:             * @param y coord
1548:             * @param tx coord
1549:             * @param ty coord
1550:             * @return String containing the coordinates in PDF text space
1551:             */
1552:            private String twh(int x, int y, int tx, int ty) {
1553:                int nx = x, ny = y;
1554:                int ntx = tx, nty = ty;
1555:                int mw = media.width;
1556:                int mh = media.height;
1557:                int sx = 1, sy = 1;
1558:                switch (mediaRot) {
1559:                case 0:
1560:                    // Portrait
1561:                    //nx = x;
1562:                    ny = mh - y;
1563:                    nty = mh - ty;
1564:                    break;
1565:
1566:                case 90:
1567:                    // Landscape
1568:                    //nx = y;
1569:                    //ny = x;
1570:                    //ntx = ty;
1571:                    //nty = tx;
1572:                    //sy=-1;
1573:                    nx = x;
1574:                    ny = -y;
1575:                    ntx = tx;
1576:                    nty = -ty;
1577:                    //sy=-1;
1578:                    break;
1579:
1580:                case 180:
1581:                    // Inverse Portrait
1582:                    // to be completed
1583:                    nx = mw - x;
1584:                    //ny = y;
1585:                    break;
1586:
1587:                case 270:
1588:                    // Seascape
1589:                    // to be completed
1590:                    nx = mw - y;
1591:                    ny = mh - x;
1592:                    break;
1593:                }
1594:
1595:                nx = sx * (nx - ntx);
1596:                ny = sy * (ny - nty);
1597:                return "" + nx + " " + ny + " ";
1598:            }
1599:
1600:            /**
1601:             * Returns the Shape of the clipping region
1602:             * As my JDK docs say, this may break with Java 2D.
1603:             * @return Shape of the clipping region
1604:             */
1605:            public Shape getClip() {
1606:                return null;
1607:            }
1608:
1609:            /**
1610:             * Draws a string using a AttributedCharacterIterator.
1611:             * <p>This is not supported yet, as I have no idea what an
1612:             * AttributedCharacterIterator is.
1613:             * <p>This method is new to the Java2 API.
1614:             */
1615:            public void drawString(java.text.AttributedCharacterIterator aci,
1616:                    int x, int y) {
1617:            }
1618:
1619:        } // end class PDFGraphics
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.