Source Code Cross Referenced for PCLRenderer.java in  » Graphic-Library » fop » org » apache » fop » render » pcl » 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 » Graphic Library » fop » org.apache.fop.render.pcl 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Licensed to the Apache Software Foundation (ASF) under one or more
0003:         * contributor license agreements.  See the NOTICE file distributed with
0004:         * this work for additional information regarding copyright ownership.
0005:         * The ASF licenses this file to You under the Apache License, Version 2.0
0006:         * (the "License"); you may not use this file except in compliance with
0007:         * the License.  You may obtain a copy of the License at
0008:         * 
0009:         *      http://www.apache.org/licenses/LICENSE-2.0
0010:         * 
0011:         * Unless required by applicable law or agreed to in writing, software
0012:         * distributed under the License is distributed on an "AS IS" BASIS,
0013:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014:         * See the License for the specific language governing permissions and
0015:         * limitations under the License.
0016:         */
0017:
0018:        /* $Id: PCLRenderer.java 542237 2007-05-28 14:31:24Z jeremias $ */
0019:
0020:        package org.apache.fop.render.pcl;
0021:
0022:        //Java
0023:        import java.awt.BasicStroke;
0024:        import java.awt.Color;
0025:        import java.awt.Dimension;
0026:        import java.awt.Graphics2D;
0027:        import java.awt.Rectangle;
0028:        import java.awt.RenderingHints;
0029:        import java.awt.color.ColorSpace;
0030:        import java.awt.geom.AffineTransform;
0031:        import java.awt.geom.GeneralPath;
0032:        import java.awt.geom.Line2D;
0033:        import java.awt.geom.Point2D;
0034:        import java.awt.geom.Rectangle2D;
0035:        import java.awt.image.BufferedImage;
0036:        import java.awt.image.ColorModel;
0037:        import java.awt.image.ComponentColorModel;
0038:        import java.awt.image.DataBuffer;
0039:        import java.awt.image.DataBufferByte;
0040:        import java.awt.image.PixelInterleavedSampleModel;
0041:        import java.awt.image.Raster;
0042:        import java.awt.image.RenderedImage;
0043:        import java.awt.image.SampleModel;
0044:        import java.awt.image.WritableRaster;
0045:        import java.io.IOException;
0046:        import java.io.OutputStream;
0047:        import java.util.List;
0048:        import java.util.Map;
0049:        import java.util.Stack;
0050:
0051:        import org.w3c.dom.Document;
0052:
0053:        import org.apache.xmlgraphics.java2d.GraphicContext;
0054:
0055:        // FOP
0056:        import org.apache.commons.logging.Log;
0057:        import org.apache.commons.logging.LogFactory;
0058:        import org.apache.fop.apps.FOPException;
0059:        import org.apache.fop.apps.MimeConstants;
0060:        import org.apache.fop.area.Area;
0061:        import org.apache.fop.area.Block;
0062:        import org.apache.fop.area.BlockViewport;
0063:        import org.apache.fop.area.CTM;
0064:        import org.apache.fop.area.PageViewport;
0065:        import org.apache.fop.area.Trait;
0066:        import org.apache.fop.area.inline.AbstractTextArea;
0067:        import org.apache.fop.area.inline.ForeignObject;
0068:        import org.apache.fop.area.inline.Image;
0069:        import org.apache.fop.area.inline.InlineArea;
0070:        import org.apache.fop.area.inline.SpaceArea;
0071:        import org.apache.fop.area.inline.TextArea;
0072:        import org.apache.fop.area.inline.Viewport;
0073:        import org.apache.fop.area.inline.WordArea;
0074:        import org.apache.fop.fo.extensions.ExtensionElementMapping;
0075:        import org.apache.fop.fonts.Font;
0076:        import org.apache.fop.fonts.FontInfo;
0077:        import org.apache.fop.fonts.FontMetrics;
0078:        import org.apache.fop.image.EPSImage;
0079:        import org.apache.fop.image.FopImage;
0080:        import org.apache.fop.image.ImageFactory;
0081:        import org.apache.fop.image.XMLImage;
0082:        import org.apache.fop.render.Graphics2DAdapter;
0083:        import org.apache.fop.render.Graphics2DImagePainter;
0084:        import org.apache.fop.render.PrintRenderer;
0085:        import org.apache.fop.render.RendererContext;
0086:        import org.apache.fop.render.RendererContextConstants;
0087:        import org.apache.fop.render.java2d.FontMetricsMapper;
0088:        import org.apache.fop.render.java2d.FontSetup;
0089:        import org.apache.fop.render.java2d.Java2DRenderer;
0090:        import org.apache.fop.render.pcl.extensions.PCLElementMapping;
0091:        import org.apache.fop.traits.BorderProps;
0092:        import org.apache.fop.util.QName;
0093:        import org.apache.fop.util.UnitConv;
0094:
0095:        /**
0096:         * Renderer for the PCL 5 printer language. It also uses HP GL/2 for certain graphic elements.
0097:         */
0098:        public class PCLRenderer extends PrintRenderer {
0099:
0100:            /** logging instance */
0101:            private static Log log = LogFactory.getLog(PCLRenderer.class);
0102:
0103:            /** The MIME type for PCL */
0104:            public static final String MIME_TYPE = MimeConstants.MIME_PCL_ALT;
0105:
0106:            private static final QName CONV_MODE = new QName(
0107:                    ExtensionElementMapping.URI, null, "conversion-mode");
0108:            private static final QName SRC_TRANSPARENCY = new QName(
0109:                    ExtensionElementMapping.URI, null, "source-transparency");
0110:
0111:            /** The OutputStream to write the PCL stream to */
0112:            protected OutputStream out;
0113:
0114:            /** The PCL generator */
0115:            protected PCLGenerator gen;
0116:            private boolean ioTrouble = false;
0117:
0118:            private Stack graphicContextStack = new Stack();
0119:            private GraphicContext graphicContext = new GraphicContext();
0120:
0121:            private PCLPageDefinition currentPageDefinition;
0122:            private int currentPrintDirection = 0;
0123:            private GeneralPath currentPath = null;
0124:            private java.awt.Color currentFillColor = null;
0125:
0126:            /**
0127:             * Controls whether appearance is more important than speed. False can cause some FO feature
0128:             * to be ignored (like the advanced borders). 
0129:             */
0130:            private boolean qualityBeforeSpeed = false;
0131:
0132:            /**
0133:             * Controls whether all text should be painted as text. This is a fallback setting in case
0134:             * the mixture of native and bitmapped text does not provide the necessary quality.
0135:             */
0136:            private boolean allTextAsBitmaps = false;
0137:
0138:            /**
0139:             * Create the PCL renderer
0140:             */
0141:            public PCLRenderer() {
0142:            }
0143:
0144:            public void setQualityBeforeSpeed(boolean qualityBeforeSpeed) {
0145:                this .qualityBeforeSpeed = qualityBeforeSpeed;
0146:            }
0147:
0148:            /**
0149:             * @see org.apache.fop.render.Renderer#setupFontInfo(org.apache.fop.fonts.FontInfo)
0150:             */
0151:            public void setupFontInfo(FontInfo inFontInfo) {
0152:                //Don't call super.setupFontInfo() here!
0153:                //The PCLRenderer uses the Java2D FontSetup which needs a special font setup
0154:                //create a temp Image to test font metrics on
0155:                fontInfo = inFontInfo;
0156:                BufferedImage fontImage = new BufferedImage(100, 100,
0157:                        BufferedImage.TYPE_INT_RGB);
0158:                Graphics2D g = fontImage.createGraphics();
0159:                //The next line is important to get accurate font metrics!
0160:                g.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS,
0161:                        RenderingHints.VALUE_FRACTIONALMETRICS_ON);
0162:                FontSetup.setup(fontInfo, g);
0163:            }
0164:
0165:            /**
0166:             * Central exception handler for I/O exceptions.
0167:             * @param ioe IOException to handle
0168:             */
0169:            protected void handleIOTrouble(IOException ioe) {
0170:                if (!ioTrouble) {
0171:                    log.error("Error while writing to target file", ioe);
0172:                    ioTrouble = true;
0173:                }
0174:            }
0175:
0176:            /** @see org.apache.fop.render.Renderer#getGraphics2DAdapter() */
0177:            public Graphics2DAdapter getGraphics2DAdapter() {
0178:                return new PCLGraphics2DAdapter();
0179:            }
0180:
0181:            /** @return the GraphicContext used to track coordinate system transformations */
0182:            public GraphicContext getGraphicContext() {
0183:                return this .graphicContext;
0184:            }
0185:
0186:            /** @return the target resolution */
0187:            protected int getResolution() {
0188:                int resolution = (int) Math.round(userAgent
0189:                        .getTargetResolution());
0190:                if (resolution <= 300) {
0191:                    return 300;
0192:                } else {
0193:                    return 600;
0194:                }
0195:            }
0196:
0197:            /**
0198:             * Sets the current font (NOTE: Hard-coded font mappings ATM!)
0199:             * @param name the font name (internal F* names for now)
0200:             * @param size the font size
0201:             * @param text the text to be rendered (used to determine if there are non-printable chars)
0202:             * @return true if the font can be mapped to PCL
0203:             * @throws IOException if an I/O problem occurs
0204:             */
0205:            public boolean setFont(String name, float size, String text)
0206:                    throws IOException {
0207:                byte[] encoded = text.getBytes("ISO-8859-1");
0208:                for (int i = 0, c = encoded.length; i < c; i++) {
0209:                    if (encoded[i] == 0x3F && text.charAt(i) != '?') {
0210:                        return false;
0211:                    }
0212:                }
0213:                int fontcode = 0;
0214:                if (name.length() > 1 && name.charAt(0) == 'F') {
0215:                    try {
0216:                        fontcode = Integer.parseInt(name.substring(1));
0217:                    } catch (Exception e) {
0218:                        log.error(e);
0219:                    }
0220:                }
0221:                //Note "(ON" selects ISO 8859-1 symbol set as used by PCLGenerator
0222:                String formattedSize = gen.formatDouble2(size / 1000);
0223:                switch (fontcode) {
0224:                case 1: // F1 = Helvetica
0225:                    // gen.writeCommand("(8U");
0226:                    // gen.writeCommand("(s1p" + formattedSize + "v0s0b24580T");
0227:                    // Arial is more common among PCL5 printers than Helvetica - so use Arial
0228:
0229:                    gen.writeCommand("(0N");
0230:                    gen.writeCommand("(s1p" + formattedSize + "v0s0b16602T");
0231:                    break;
0232:                case 2: // F2 = Helvetica Oblique
0233:
0234:                    gen.writeCommand("(0N");
0235:                    gen.writeCommand("(s1p" + formattedSize + "v1s0b16602T");
0236:                    break;
0237:                case 3: // F3 = Helvetica Bold
0238:
0239:                    gen.writeCommand("(0N");
0240:                    gen.writeCommand("(s1p" + formattedSize + "v0s3b16602T");
0241:                    break;
0242:                case 4: // F4 = Helvetica Bold Oblique
0243:
0244:                    gen.writeCommand("(0N");
0245:                    gen.writeCommand("(s1p" + formattedSize + "v1s3b16602T");
0246:                    break;
0247:                case 5: // F5 = Times Roman
0248:                    // gen.writeCommand("(8U");
0249:                    // gen.writeCommand("(s1p" + formattedSize + "v0s0b25093T");
0250:                    // Times New is more common among PCL5 printers than Times - so use Times New
0251:
0252:                    gen.writeCommand("(0N");
0253:                    gen.writeCommand("(s1p" + formattedSize + "v0s0b16901T");
0254:                    break;
0255:                case 6: // F6 = Times Italic
0256:
0257:                    gen.writeCommand("(0N");
0258:                    gen.writeCommand("(s1p" + formattedSize + "v1s0b16901T");
0259:                    break;
0260:                case 7: // F7 = Times Bold
0261:
0262:                    gen.writeCommand("(0N");
0263:                    gen.writeCommand("(s1p" + formattedSize + "v0s3b16901T");
0264:                    break;
0265:                case 8: // F8 = Times Bold Italic
0266:
0267:                    gen.writeCommand("(0N");
0268:                    gen.writeCommand("(s1p" + formattedSize + "v1s3b16901T");
0269:                    break;
0270:                case 9: // F9 = Courier
0271:
0272:                    gen.writeCommand("(0N");
0273:                    gen.writeCommand("(s0p"
0274:                            + gen.formatDouble2(120.01f / (size / 1000.00f))
0275:                            + "h0s0b4099T");
0276:                    break;
0277:                case 10: // F10 = Courier Oblique
0278:
0279:                    gen.writeCommand("(0N");
0280:                    gen.writeCommand("(s0p"
0281:                            + gen.formatDouble2(120.01f / (size / 1000.00f))
0282:                            + "h1s0b4099T");
0283:                    break;
0284:                case 11: // F11 = Courier Bold
0285:
0286:                    gen.writeCommand("(0N");
0287:                    gen.writeCommand("(s0p"
0288:                            + gen.formatDouble2(120.01f / (size / 1000.00f))
0289:                            + "h0s3b4099T");
0290:                    break;
0291:                case 12: // F12 = Courier Bold Oblique
0292:
0293:                    gen.writeCommand("(0N");
0294:                    gen.writeCommand("(s0p"
0295:                            + gen.formatDouble2(120.01f / (size / 1000.00f))
0296:                            + "h1s3b4099T");
0297:                    break;
0298:                case 13: // F13 = Symbol
0299:
0300:                    return false;
0301:                    //gen.writeCommand("(19M");
0302:                    //gen.writeCommand("(s1p" + formattedSize + "v0s0b16686T");
0303:                    // ECMA Latin 1 Symbol Set in Times Roman???
0304:                    // gen.writeCommand("(9U");
0305:                    // gen.writeCommand("(s1p" + formattedSize + "v0s0b25093T");
0306:                    //break;
0307:                case 14: // F14 = Zapf Dingbats
0308:
0309:                    return false;
0310:                    //gen.writeCommand("(14L");
0311:                    //gen.writeCommand("(s1p" + formattedSize + "v0s0b45101T");
0312:                    //break;
0313:                default:
0314:                    //gen.writeCommand("(0N");
0315:                    //gen.writeCommand("(s" + formattedSize + "V");
0316:                    return false;
0317:                }
0318:                return true;
0319:            }
0320:
0321:            /** @see org.apache.fop.render.Renderer#startRenderer(java.io.OutputStream) */
0322:            public void startRenderer(OutputStream outputStream)
0323:                    throws IOException {
0324:                log.debug("Rendering areas to PCL...");
0325:                this .out = outputStream;
0326:                this .gen = new PCLGenerator(out, getResolution());
0327:
0328:                gen.universalEndOfLanguage();
0329:                gen.writeText("@PJL COMMENT Produced by "
0330:                        + userAgent.getProducer() + "\n");
0331:                if (userAgent.getTitle() != null) {
0332:                    gen.writeText("@PJL JOB NAME = \"" + userAgent.getTitle()
0333:                            + "\"\n");
0334:                }
0335:                gen
0336:                        .writeText("@PJL SET RESOLUTION = " + getResolution()
0337:                                + "\n");
0338:                gen.writeText("@PJL ENTER LANGUAGE = PCL\n");
0339:                gen.resetPrinter();
0340:                gen.setUnitOfMeasure(getResolution());
0341:                gen.setRasterGraphicsResolution(getResolution());
0342:            }
0343:
0344:            /** @see org.apache.fop.render.Renderer#stopRenderer() */
0345:            public void stopRenderer() throws IOException {
0346:                gen.separateJobs();
0347:                gen.resetPrinter();
0348:                gen.universalEndOfLanguage();
0349:            }
0350:
0351:            /** @see org.apache.fop.render.AbstractRenderer */
0352:            public String getMimeType() {
0353:                return MIME_TYPE;
0354:            }
0355:
0356:            /**
0357:             * @see org.apache.fop.render.AbstractRenderer#renderPage(org.apache.fop.area.PageViewport)
0358:             */
0359:            public void renderPage(PageViewport page) throws IOException,
0360:                    FOPException {
0361:                saveGraphicsState();
0362:
0363:                //Paper source
0364:                String paperSource = page.getForeignAttributeValue(new QName(
0365:                        PCLElementMapping.NAMESPACE, null, "paper-source"));
0366:                if (paperSource != null) {
0367:                    gen.selectPaperSource(Integer.parseInt(paperSource));
0368:                }
0369:
0370:                //Page size
0371:                final long pagewidth = Math
0372:                        .round(page.getViewArea().getWidth());
0373:                final long pageheight = Math.round(page.getViewArea()
0374:                        .getHeight());
0375:                selectPageFormat(pagewidth, pageheight);
0376:
0377:                super .renderPage(page);
0378:
0379:                //Eject page
0380:                gen.formFeed();
0381:                restoreGraphicsState();
0382:            }
0383:
0384:            private void selectPageFormat(long pagewidth, long pageheight)
0385:                    throws IOException {
0386:                this .currentPageDefinition = PCLPageDefinition
0387:                        .getPageDefinition(pagewidth, pageheight, 1000);
0388:
0389:                if (this .currentPageDefinition == null) {
0390:                    this .currentPageDefinition = PCLPageDefinition
0391:                            .getDefaultPageDefinition();
0392:                    log
0393:                            .warn("Paper type could not be determined. Falling back to: "
0394:                                    + this .currentPageDefinition.getName());
0395:                }
0396:                log.debug("page size: "
0397:                        + currentPageDefinition.getPhysicalPageSize());
0398:                log.debug("logical page: "
0399:                        + currentPageDefinition.getLogicalPageRect());
0400:                if (this .currentPageDefinition.isLandscapeFormat()) {
0401:                    gen.writeCommand("&l1O"); //Orientation
0402:                } else {
0403:                    gen.writeCommand("&l0O"); //Orientation
0404:                }
0405:                gen.selectPageSize(this .currentPageDefinition.getSelector());
0406:
0407:                gen.clearHorizontalMargins();
0408:                gen.setTopMargin(0);
0409:            }
0410:
0411:            /** Saves the current graphics state on the stack. */
0412:            protected void saveGraphicsState() {
0413:                graphicContextStack.push(graphicContext);
0414:                graphicContext = (GraphicContext) graphicContext.clone();
0415:            }
0416:
0417:            /** Restores the last graphics state from the stack. */
0418:            protected void restoreGraphicsState() {
0419:                graphicContext = (GraphicContext) graphicContextStack.pop();
0420:            }
0421:
0422:            /**
0423:             * Clip an area. write a clipping operation given coordinates in the current
0424:             * transform. Coordinates are in points.
0425:             *
0426:             * @param x the x coordinate
0427:             * @param y the y coordinate
0428:             * @param width the width of the area
0429:             * @param height the height of the area
0430:             */
0431:            protected void clipRect(float x, float y, float width, float height) {
0432:                //PCL cannot clip (only HP GL/2 can)
0433:            }
0434:
0435:            private Point2D transformedPoint(float x, float y) {
0436:                return transformedPoint(Math.round(x), Math.round(y));
0437:            }
0438:
0439:            private Point2D transformedPoint(int x, int y) {
0440:                AffineTransform at = graphicContext.getTransform();
0441:                if (log.isTraceEnabled()) {
0442:                    log.trace("Current transform: " + at);
0443:                }
0444:                Point2D.Float orgPoint = new Point2D.Float(x, y);
0445:                Point2D.Float transPoint = new Point2D.Float();
0446:                at.transform(orgPoint, transPoint);
0447:                //At this point we have the absolute position in FOP's coordinate system
0448:
0449:                //Now get PCL coordinates taking the current print direction and the logical page
0450:                //into account.
0451:                Dimension pageSize = currentPageDefinition
0452:                        .getPhysicalPageSize();
0453:                Rectangle logRect = currentPageDefinition.getLogicalPageRect();
0454:                switch (currentPrintDirection) {
0455:                case 0:
0456:                    transPoint.x -= logRect.x;
0457:                    transPoint.y -= logRect.y;
0458:                    break;
0459:                case 90:
0460:                    float ty = transPoint.x;
0461:                    transPoint.x = pageSize.height - transPoint.y;
0462:                    transPoint.y = ty;
0463:                    transPoint.x -= logRect.y;
0464:                    transPoint.y -= logRect.x;
0465:                    break;
0466:                case 180:
0467:                    transPoint.x = pageSize.width - transPoint.x;
0468:                    transPoint.y = pageSize.height - transPoint.y;
0469:                    transPoint.x -= pageSize.width - logRect.x - logRect.width;
0470:                    transPoint.y -= pageSize.height - logRect.y
0471:                            - logRect.height;
0472:                    //The next line is odd and is probably necessary due to the default value of the
0473:                    //Text Length command: "1/2 inch less than maximum text length"
0474:                    //I wonder why this isn't necessary for the 90 degree rotation. *shrug*
0475:                    transPoint.y -= UnitConv.in2mpt(0.5);
0476:                    break;
0477:                case 270:
0478:                    float tx = transPoint.y;
0479:                    transPoint.y = pageSize.width - transPoint.x;
0480:                    transPoint.x = tx;
0481:                    transPoint.x -= pageSize.height - logRect.y
0482:                            - logRect.height;
0483:                    transPoint.y -= pageSize.width - logRect.x - logRect.width;
0484:                    break;
0485:                default:
0486:                    throw new IllegalStateException("Illegal print direction: "
0487:                            + currentPrintDirection);
0488:                }
0489:                return transPoint;
0490:            }
0491:
0492:            private void changePrintDirection() {
0493:                AffineTransform at = graphicContext.getTransform();
0494:                int newDir;
0495:                try {
0496:                    if (at.getScaleX() == 0 && at.getScaleY() == 0
0497:                            && at.getShearX() == 1 && at.getShearY() == -1) {
0498:                        newDir = 90;
0499:                    } else if (at.getScaleX() == -1 && at.getScaleY() == -1
0500:                            && at.getShearX() == 0 && at.getShearY() == 0) {
0501:                        newDir = 180;
0502:                    } else if (at.getScaleX() == 0 && at.getScaleY() == 0
0503:                            && at.getShearX() == -1 && at.getShearY() == 1) {
0504:                        newDir = 270;
0505:                    } else {
0506:                        newDir = 0;
0507:                    }
0508:                    if (newDir != this .currentPrintDirection) {
0509:                        this .currentPrintDirection = newDir;
0510:                        gen.changePrintDirection(this .currentPrintDirection);
0511:                    }
0512:                } catch (IOException ioe) {
0513:                    handleIOTrouble(ioe);
0514:                }
0515:            }
0516:
0517:            /**
0518:             * @see org.apache.fop.render.AbstractRenderer#startVParea(CTM, Rectangle2D)
0519:             */
0520:            protected void startVParea(CTM ctm, Rectangle2D clippingRect) {
0521:                saveGraphicsState();
0522:                AffineTransform at = new AffineTransform(ctm.toArray());
0523:                graphicContext.transform(at);
0524:                changePrintDirection();
0525:                if (log.isDebugEnabled()) {
0526:                    log.debug("startVPArea: " + at + " --> "
0527:                            + graphicContext.getTransform());
0528:                }
0529:            }
0530:
0531:            /**
0532:             * @see org.apache.fop.render.AbstractRenderer#endVParea()
0533:             */
0534:            protected void endVParea() {
0535:                restoreGraphicsState();
0536:                changePrintDirection();
0537:                if (log.isDebugEnabled()) {
0538:                    log.debug("endVPArea() --> "
0539:                            + graphicContext.getTransform());
0540:                }
0541:            }
0542:
0543:            /**
0544:             * Handle block traits.
0545:             * The block could be any sort of block with any positioning
0546:             * so this should render the traits such as border and background
0547:             * in its position.
0548:             *
0549:             * @param block the block to render the traits
0550:             */
0551:            protected void handleBlockTraits(Block block) {
0552:                int borderPaddingStart = block.getBorderAndPaddingWidthStart();
0553:                int borderPaddingBefore = block
0554:                        .getBorderAndPaddingWidthBefore();
0555:
0556:                float startx = currentIPPosition / 1000f;
0557:                float starty = currentBPPosition / 1000f;
0558:                float width = block.getIPD() / 1000f;
0559:                float height = block.getBPD() / 1000f;
0560:
0561:                startx += block.getStartIndent() / 1000f;
0562:                startx -= block.getBorderAndPaddingWidthStart() / 1000f;
0563:
0564:                width += borderPaddingStart / 1000f;
0565:                width += block.getBorderAndPaddingWidthEnd() / 1000f;
0566:                height += borderPaddingBefore / 1000f;
0567:                height += block.getBorderAndPaddingWidthAfter() / 1000f;
0568:
0569:                drawBackAndBorders(block, startx, starty, width, height);
0570:            }
0571:
0572:            /**
0573:             * @see org.apache.fop.render.AbstractRenderer#renderText(TextArea)
0574:             */
0575:            protected void renderText(final TextArea text) {
0576:                renderInlineAreaBackAndBorders(text);
0577:
0578:                String fontname = getInternalFontNameForArea(text);
0579:                final int fontsize = text.getTraitAsInteger(Trait.FONT_SIZE);
0580:
0581:                //Determine position
0582:                int saveIP = currentIPPosition;
0583:                final int rx = currentIPPosition
0584:                        + text.getBorderAndPaddingWidthStart();
0585:                int bl = currentBPPosition + text.getOffset()
0586:                        + text.getBaselineOffset();
0587:
0588:                try {
0589:
0590:                    final Color col = (Color) text.getTrait(Trait.COLOR);
0591:                    boolean pclFont = allTextAsBitmaps ? false : setFont(
0592:                            fontname, fontsize, text.getText());
0593:                    if (pclFont) {
0594:                        //this.currentFill = col;
0595:                        if (col != null) {
0596:                            //useColor(ct);
0597:                            gen.setTransparencyMode(true, false);
0598:                            gen.selectGrayscale(col);
0599:                        }
0600:
0601:                        saveGraphicsState();
0602:                        graphicContext.translate(rx, bl);
0603:                        setCursorPos(0, 0);
0604:                        gen.setTransparencyMode(true, true);
0605:                        if (text.hasUnderline()) {
0606:                            gen.writeCommand("&d0D");
0607:                        }
0608:                        super .renderText(text); //Updates IPD and renders words and spaces
0609:                        if (text.hasUnderline()) {
0610:                            gen.writeCommand("&d@");
0611:                        }
0612:                        restoreGraphicsState();
0613:                    } else {
0614:                        //Use Java2D to paint different fonts via bitmap
0615:                        final Font font = getFontFromArea(text);
0616:                        final int baseline = text.getBaselineOffset();
0617:
0618:                        //for cursive fonts, so the text isn't clipped
0619:                        int extraWidth = font.getFontSize() / 3;
0620:                        final FontMetricsMapper mapper = (FontMetricsMapper) fontInfo
0621:                                .getMetricsFor(font.getFontName());
0622:                        int maxAscent = mapper.getMaxAscent(font.getFontSize()) / 1000;
0623:                        final int additionalBPD = maxAscent - baseline;
0624:
0625:                        Graphics2DAdapter g2a = getGraphics2DAdapter();
0626:                        final Rectangle paintRect = new Rectangle(rx,
0627:                                currentBPPosition + text.getOffset()
0628:                                        - additionalBPD, text.getIPD()
0629:                                        + extraWidth, text.getBPD()
0630:                                        + additionalBPD);
0631:                        RendererContext rc = createRendererContext(paintRect.x,
0632:                                paintRect.y, paintRect.width, paintRect.height,
0633:                                null);
0634:                        Map atts = new java.util.HashMap();
0635:                        atts.put(CONV_MODE, "bitmap");
0636:                        atts.put(SRC_TRANSPARENCY, "true");
0637:                        rc.setProperty(
0638:                                RendererContextConstants.FOREIGN_ATTRIBUTES,
0639:                                atts);
0640:
0641:                        Graphics2DImagePainter painter = new Graphics2DImagePainter() {
0642:
0643:                            public void paint(Graphics2D g2d, Rectangle2D area) {
0644:                                g2d.setFont(mapper.getFont(font.getFontSize()));
0645:                                g2d.translate(0, baseline + additionalBPD);
0646:                                g2d.scale(1000, 1000);
0647:                                g2d.setColor(col);
0648:                                Java2DRenderer.renderText(text, g2d, font);
0649:                                renderTextDecoration(g2d, mapper, fontsize,
0650:                                        text, 0, 0);
0651:                            }
0652:
0653:                            public Dimension getImageSize() {
0654:                                return paintRect.getSize();
0655:                            }
0656:
0657:                        };
0658:                        g2a.paintImage(painter, rc, paintRect.x, paintRect.y,
0659:                                paintRect.width, paintRect.height);
0660:                        currentIPPosition = saveIP + text.getAllocIPD();
0661:                    }
0662:
0663:                } catch (IOException ioe) {
0664:                    handleIOTrouble(ioe);
0665:                }
0666:            }
0667:
0668:            /**
0669:             * Paints the text decoration marks.
0670:             * @param g2d Graphics2D instance to paint to
0671:             * @param fm Current typeface
0672:             * @param fontsize Current font size
0673:             * @param inline inline area to paint the marks for
0674:             * @param baseline position of the baseline
0675:             * @param startx start IPD
0676:             */
0677:            private static void renderTextDecoration(Graphics2D g2d,
0678:                    FontMetrics fm, int fontsize, InlineArea inline,
0679:                    int baseline, int startx) {
0680:                boolean hasTextDeco = inline.hasUnderline()
0681:                        || inline.hasOverline() || inline.hasLineThrough();
0682:                if (hasTextDeco) {
0683:                    float descender = fm.getDescender(fontsize) / 1000f;
0684:                    float capHeight = fm.getCapHeight(fontsize) / 1000f;
0685:                    float lineWidth = (descender / -4f) / 1000f;
0686:                    float endx = (startx + inline.getIPD()) / 1000f;
0687:                    if (inline.hasUnderline()) {
0688:                        Color ct = (Color) inline
0689:                                .getTrait(Trait.UNDERLINE_COLOR);
0690:                        g2d.setColor(ct);
0691:                        float y = baseline - descender / 2f;
0692:                        g2d.setStroke(new BasicStroke(lineWidth));
0693:                        g2d.draw(new Line2D.Float(startx / 1000f, y / 1000f,
0694:                                endx, y / 1000f));
0695:                    }
0696:                    if (inline.hasOverline()) {
0697:                        Color ct = (Color) inline
0698:                                .getTrait(Trait.OVERLINE_COLOR);
0699:                        g2d.setColor(ct);
0700:                        float y = (float) (baseline - (1.1 * capHeight));
0701:                        g2d.setStroke(new BasicStroke(lineWidth));
0702:                        g2d.draw(new Line2D.Float(startx / 1000f, y / 1000f,
0703:                                endx, y / 1000f));
0704:                    }
0705:                    if (inline.hasLineThrough()) {
0706:                        Color ct = (Color) inline
0707:                                .getTrait(Trait.LINETHROUGH_COLOR);
0708:                        g2d.setColor(ct);
0709:                        float y = (float) (baseline - (0.45 * capHeight));
0710:                        g2d.setStroke(new BasicStroke(lineWidth));
0711:                        g2d.draw(new Line2D.Float(startx / 1000f, y / 1000f,
0712:                                endx, y / 1000f));
0713:                    }
0714:                }
0715:            }
0716:
0717:            /**
0718:             * Sets the current cursor position. The coordinates are transformed to the absolute position
0719:             * on the logical PCL page and then passed on to the PCLGenerator.
0720:             * @param x the x coordinate (in millipoints)
0721:             * @param y the y coordinate (in millipoints)
0722:             */
0723:            void setCursorPos(float x, float y) {
0724:                try {
0725:                    Point2D transPoint = transformedPoint(x, y);
0726:                    gen.setCursorPos(transPoint.getX(), transPoint.getY());
0727:                } catch (IOException ioe) {
0728:                    handleIOTrouble(ioe);
0729:                }
0730:            }
0731:
0732:            /**
0733:             * @see org.apache.fop.render.AbstractPathOrientedRenderer#clip()
0734:             */
0735:            protected void clip() {
0736:                if (currentPath == null) {
0737:                    throw new IllegalStateException(
0738:                            "No current path available!");
0739:                }
0740:                //TODO Find a good way to do clipping. PCL itself cannot clip.
0741:                currentPath = null;
0742:            }
0743:
0744:            /**
0745:             * @see org.apache.fop.render.AbstractPathOrientedRenderer#closePath()
0746:             */
0747:            protected void closePath() {
0748:                currentPath.closePath();
0749:            }
0750:
0751:            /**
0752:             * @see org.apache.fop.render.AbstractPathOrientedRenderer#lineTo(float, float)
0753:             */
0754:            protected void lineTo(float x, float y) {
0755:                if (currentPath == null) {
0756:                    currentPath = new GeneralPath();
0757:                }
0758:                currentPath.lineTo(x, y);
0759:            }
0760:
0761:            /**
0762:             * @see org.apache.fop.render.AbstractPathOrientedRenderer#moveTo(float, float)
0763:             */
0764:            protected void moveTo(float x, float y) {
0765:                if (currentPath == null) {
0766:                    currentPath = new GeneralPath();
0767:                }
0768:                currentPath.moveTo(x, y);
0769:            }
0770:
0771:            /**
0772:             * Fill a rectangular area.
0773:             * @param x the x coordinate (in pt)
0774:             * @param y the y coordinate (in pt)
0775:             * @param width the width of the rectangle
0776:             * @param height the height of the rectangle
0777:             */
0778:            protected void fillRect(float x, float y, float width, float height) {
0779:                try {
0780:                    setCursorPos(x * 1000, y * 1000);
0781:                    gen.fillRect((int) (width * 1000), (int) (height * 1000),
0782:                            this .currentFillColor);
0783:                } catch (IOException ioe) {
0784:                    handleIOTrouble(ioe);
0785:                }
0786:            }
0787:
0788:            /**
0789:             * Sets the new current fill color.
0790:             * @param color the color
0791:             */
0792:            protected void updateFillColor(java.awt.Color color) {
0793:                this .currentFillColor = color;
0794:            }
0795:
0796:            /**
0797:             * @see org.apache.fop.render.AbstractRenderer#renderWord(org.apache.fop.area.inline.WordArea)
0798:             */
0799:            protected void renderWord(WordArea word) {
0800:                //Font font = getFontFromArea(word.getParentArea());
0801:
0802:                String s = word.getWord();
0803:
0804:                try {
0805:                    gen.writeText(s);
0806:                } catch (IOException ioe) {
0807:                    handleIOTrouble(ioe);
0808:                }
0809:
0810:                super .renderWord(word);
0811:            }
0812:
0813:            /**
0814:             * @see org.apache.fop.render.AbstractRenderer#renderSpace(org.apache.fop.area.inline.SpaceArea)
0815:             */
0816:            protected void renderSpace(SpaceArea space) {
0817:                AbstractTextArea textArea = (AbstractTextArea) space
0818:                        .getParentArea();
0819:                String s = space.getSpace();
0820:                char sp = s.charAt(0);
0821:                Font font = getFontFromArea(textArea);
0822:
0823:                int tws = (space.isAdjustable() ? textArea
0824:                        .getTextWordSpaceAdjust()
0825:                        + 2 * textArea.getTextLetterSpaceAdjust() : 0);
0826:
0827:                double dx = (font.getCharWidth(sp) + tws) / 100f;
0828:                try {
0829:                    gen.writeCommand("&a+" + gen.formatDouble2(dx) + "H");
0830:                } catch (IOException ioe) {
0831:                    handleIOTrouble(ioe);
0832:                }
0833:                super .renderSpace(space);
0834:            }
0835:
0836:            /**
0837:             * Render an inline viewport.
0838:             * This renders an inline viewport by clipping if necessary.
0839:             * @param viewport the viewport to handle
0840:             * @todo Copied from AbstractPathOrientedRenderer
0841:             */
0842:            public void renderViewport(Viewport viewport) {
0843:
0844:                float x = currentIPPosition / 1000f;
0845:                float y = (currentBPPosition + viewport.getOffset()) / 1000f;
0846:                float width = viewport.getIPD() / 1000f;
0847:                float height = viewport.getBPD() / 1000f;
0848:                // TODO: Calculate the border rect correctly. 
0849:                float borderPaddingStart = viewport
0850:                        .getBorderAndPaddingWidthStart() / 1000f;
0851:                float borderPaddingBefore = viewport
0852:                        .getBorderAndPaddingWidthBefore() / 1000f;
0853:                float bpwidth = borderPaddingStart
0854:                        + (viewport.getBorderAndPaddingWidthEnd() / 1000f);
0855:                float bpheight = borderPaddingBefore
0856:                        + (viewport.getBorderAndPaddingWidthAfter() / 1000f);
0857:
0858:                drawBackAndBorders(viewport, x, y, width + bpwidth, height
0859:                        + bpheight);
0860:
0861:                if (viewport.getClip()) {
0862:                    saveGraphicsState();
0863:
0864:                    clipRect(x + borderPaddingStart, y + borderPaddingBefore,
0865:                            width, height);
0866:                }
0867:                super .renderViewport(viewport);
0868:
0869:                if (viewport.getClip()) {
0870:                    restoreGraphicsState();
0871:                }
0872:            }
0873:
0874:            /**
0875:             * @see org.apache.fop.render.AbstractRenderer#renderBlockViewport(BlockViewport, List)
0876:             */
0877:            protected void renderBlockViewport(BlockViewport bv, List children) {
0878:                // clip and position viewport if necessary
0879:
0880:                // save positions
0881:                int saveIP = currentIPPosition;
0882:                int saveBP = currentBPPosition;
0883:                //String saveFontName = currentFontName;
0884:
0885:                CTM ctm = bv.getCTM();
0886:                int borderPaddingStart = bv.getBorderAndPaddingWidthStart();
0887:                int borderPaddingBefore = bv.getBorderAndPaddingWidthBefore();
0888:                float x, y;
0889:                x = (float) (bv.getXOffset() + containingIPPosition) / 1000f;
0890:                y = (float) (bv.getYOffset() + containingBPPosition) / 1000f;
0891:                //This is the content-rect
0892:                float width = (float) bv.getIPD() / 1000f;
0893:                float height = (float) bv.getBPD() / 1000f;
0894:
0895:                if (bv.getPositioning() == Block.ABSOLUTE
0896:                        || bv.getPositioning() == Block.FIXED) {
0897:
0898:                    currentIPPosition = bv.getXOffset();
0899:                    currentBPPosition = bv.getYOffset();
0900:
0901:                    //For FIXED, we need to break out of the current viewports to the
0902:                    //one established by the page. We save the state stack for restoration
0903:                    //after the block-container has been painted. See below.
0904:                    List breakOutList = null;
0905:                    if (bv.getPositioning() == Block.FIXED) {
0906:                        breakOutList = breakOutOfStateStack();
0907:                    }
0908:
0909:                    CTM tempctm = new CTM(containingIPPosition,
0910:                            containingBPPosition);
0911:                    ctm = tempctm.multiply(ctm);
0912:
0913:                    //Adjust for spaces (from margin or indirectly by start-indent etc.
0914:                    x += bv.getSpaceStart() / 1000f;
0915:                    currentIPPosition += bv.getSpaceStart();
0916:
0917:                    y += bv.getSpaceBefore() / 1000f;
0918:                    currentBPPosition += bv.getSpaceBefore();
0919:
0920:                    float bpwidth = (borderPaddingStart + bv
0921:                            .getBorderAndPaddingWidthEnd()) / 1000f;
0922:                    float bpheight = (borderPaddingBefore + bv
0923:                            .getBorderAndPaddingWidthAfter()) / 1000f;
0924:
0925:                    drawBackAndBorders(bv, x, y, width + bpwidth, height
0926:                            + bpheight);
0927:
0928:                    //Now adjust for border/padding
0929:                    currentIPPosition += borderPaddingStart;
0930:                    currentBPPosition += borderPaddingBefore;
0931:
0932:                    Rectangle2D clippingRect = null;
0933:                    if (bv.getClip()) {
0934:                        clippingRect = new Rectangle(currentIPPosition,
0935:                                currentBPPosition, bv.getIPD(), bv.getBPD());
0936:                    }
0937:
0938:                    startVParea(ctm, clippingRect);
0939:                    currentIPPosition = 0;
0940:                    currentBPPosition = 0;
0941:                    renderBlocks(bv, children);
0942:                    endVParea();
0943:
0944:                    if (breakOutList != null) {
0945:                        restoreStateStackAfterBreakOut(breakOutList);
0946:                    }
0947:
0948:                    currentIPPosition = saveIP;
0949:                    currentBPPosition = saveBP;
0950:                } else {
0951:
0952:                    currentBPPosition += bv.getSpaceBefore();
0953:
0954:                    //borders and background in the old coordinate system
0955:                    handleBlockTraits(bv);
0956:
0957:                    //Advance to start of content area
0958:                    currentIPPosition += bv.getStartIndent();
0959:
0960:                    CTM tempctm = new CTM(containingIPPosition,
0961:                            currentBPPosition);
0962:                    ctm = tempctm.multiply(ctm);
0963:
0964:                    //Now adjust for border/padding
0965:                    currentBPPosition += borderPaddingBefore;
0966:
0967:                    Rectangle2D clippingRect = null;
0968:                    if (bv.getClip()) {
0969:                        clippingRect = new Rectangle(currentIPPosition,
0970:                                currentBPPosition, bv.getIPD(), bv.getBPD());
0971:                    }
0972:
0973:                    startVParea(ctm, clippingRect);
0974:                    currentIPPosition = 0;
0975:                    currentBPPosition = 0;
0976:                    renderBlocks(bv, children);
0977:                    endVParea();
0978:
0979:                    currentIPPosition = saveIP;
0980:                    currentBPPosition = saveBP;
0981:
0982:                    currentBPPosition += (int) (bv.getAllocBPD());
0983:                }
0984:                //currentFontName = saveFontName;
0985:            }
0986:
0987:            private List breakOutOfStateStack() {
0988:                log.debug("Block.FIXED --> break out");
0989:                List breakOutList = new java.util.ArrayList();
0990:                while (!this .graphicContextStack.empty()) {
0991:                    breakOutList.add(0, this .graphicContext);
0992:                    restoreGraphicsState();
0993:                }
0994:                return breakOutList;
0995:            }
0996:
0997:            private void restoreStateStackAfterBreakOut(List breakOutList) {
0998:                log.debug("Block.FIXED --> restoring context after break-out");
0999:                for (int i = 0, c = breakOutList.size(); i < c; i++) {
1000:                    saveGraphicsState();
1001:                    this .graphicContext = (GraphicContext) breakOutList.get(i);
1002:                }
1003:            }
1004:
1005:            /**
1006:             * @see org.apache.fop.render.AbstractRenderer#renderImage(Image, Rectangle2D)
1007:             */
1008:            public void renderImage(Image image, Rectangle2D pos) {
1009:                drawImage(image.getURL(), pos, image.getForeignAttributes());
1010:            }
1011:
1012:            /**
1013:             * Draw an image at the indicated location.
1014:             * @param url the URI/URL of the image
1015:             * @param pos the position of the image
1016:             * @param foreignAttributes an optional Map with foreign attributes, may be null
1017:             */
1018:            protected void drawImage(String url, Rectangle2D pos,
1019:                    Map foreignAttributes) {
1020:                url = ImageFactory.getURL(url);
1021:                ImageFactory fact = userAgent.getFactory().getImageFactory();
1022:                FopImage fopimage = fact.getImage(url, userAgent);
1023:                if (fopimage == null) {
1024:                    return;
1025:                }
1026:                if (!fopimage.load(FopImage.DIMENSIONS)) {
1027:                    return;
1028:                }
1029:                String mime = fopimage.getMimeType();
1030:                if ("text/xml".equals(mime)) {
1031:                    if (!fopimage.load(FopImage.ORIGINAL_DATA)) {
1032:                        return;
1033:                    }
1034:                    Document doc = ((XMLImage) fopimage).getDocument();
1035:                    String ns = ((XMLImage) fopimage).getNameSpace();
1036:
1037:                    renderDocument(doc, ns, pos, foreignAttributes);
1038:                } else if ("image/svg+xml".equals(mime)) {
1039:                    if (!fopimage.load(FopImage.ORIGINAL_DATA)) {
1040:                        return;
1041:                    }
1042:                    Document doc = ((XMLImage) fopimage).getDocument();
1043:                    String ns = ((XMLImage) fopimage).getNameSpace();
1044:
1045:                    renderDocument(doc, ns, pos, foreignAttributes);
1046:                } else if (fopimage instanceof  EPSImage) {
1047:                    log.warn("EPS images are not supported by this renderer");
1048:                } else {
1049:                    if (!fopimage.load(FopImage.BITMAP)) {
1050:                        log.error("Bitmap image could not be processed: "
1051:                                + fopimage);
1052:                        return;
1053:                    }
1054:                    byte[] imgmap = fopimage.getBitmaps();
1055:
1056:                    ColorModel cm = new ComponentColorModel(ColorSpace
1057:                            .getInstance(ColorSpace.CS_LINEAR_RGB), new int[] {
1058:                            8, 8, 8 }, false, false, ColorModel.OPAQUE,
1059:                            DataBuffer.TYPE_BYTE);
1060:                    int imgw = fopimage.getWidth();
1061:                    int imgh = fopimage.getHeight();
1062:                    SampleModel sampleModel = new PixelInterleavedSampleModel(
1063:                            DataBuffer.TYPE_BYTE, imgw, imgh, 3, imgw * 3,
1064:                            new int[] { 0, 1, 2 });
1065:                    DataBuffer dbuf = new DataBufferByte(imgmap, imgw * imgh
1066:                            * 3);
1067:
1068:                    WritableRaster raster = Raster.createWritableRaster(
1069:                            sampleModel, dbuf, null);
1070:
1071:                    // Combine the color model and raster into a buffered image
1072:                    RenderedImage img = new BufferedImage(cm, raster, false,
1073:                            null);
1074:
1075:                    try {
1076:                        setCursorPos(this .currentIPPosition + (int) pos.getX(),
1077:                                this .currentBPPosition + (int) pos.getY());
1078:                        gen.paintBitmap(img, new Dimension(
1079:                                (int) pos.getWidth(), (int) pos.getHeight()),
1080:                                false);
1081:                    } catch (IOException ioe) {
1082:                        handleIOTrouble(ioe);
1083:                    }
1084:                }
1085:            }
1086:
1087:            /**
1088:             * @see org.apache.fop.render.AbstractRenderer#renderForeignObject(ForeignObject, Rectangle2D)
1089:             */
1090:            public void renderForeignObject(ForeignObject fo, Rectangle2D pos) {
1091:                Document doc = fo.getDocument();
1092:                String ns = fo.getNameSpace();
1093:                renderDocument(doc, ns, pos, fo.getForeignAttributes());
1094:            }
1095:
1096:            /** 
1097:             * Common method to render the background and borders for any inline area.
1098:             * The all borders and padding are drawn outside the specified area.
1099:             * @param area the inline area for which the background, border and padding is to be
1100:             * rendered
1101:             * @todo Copied from AbstractPathOrientedRenderer
1102:             */
1103:            protected void renderInlineAreaBackAndBorders(InlineArea area) {
1104:                float x = currentIPPosition / 1000f;
1105:                float y = (currentBPPosition + area.getOffset()) / 1000f;
1106:                float width = area.getIPD() / 1000f;
1107:                float height = area.getBPD() / 1000f;
1108:                float borderPaddingStart = area.getBorderAndPaddingWidthStart() / 1000f;
1109:                float borderPaddingBefore = area
1110:                        .getBorderAndPaddingWidthBefore() / 1000f;
1111:                float bpwidth = borderPaddingStart
1112:                        + (area.getBorderAndPaddingWidthEnd() / 1000f);
1113:                float bpheight = borderPaddingBefore
1114:                        + (area.getBorderAndPaddingWidthAfter() / 1000f);
1115:
1116:                if (height != 0.0f || bpheight != 0.0f && bpwidth != 0.0f) {
1117:                    drawBackAndBorders(area, x, y - borderPaddingBefore, width
1118:                            + bpwidth, height + bpheight);
1119:                }
1120:            }
1121:
1122:            /**
1123:             * Draw the background and borders. This draws the background and border
1124:             * traits for an area given the position.
1125:             *
1126:             * @param area the area whose traits are used
1127:             * @param startx the start x position
1128:             * @param starty the start y position
1129:             * @param width the width of the area
1130:             * @param height the height of the area
1131:             */
1132:            protected void drawBackAndBorders(Area area, float startx,
1133:                    float starty, float width, float height) {
1134:                BorderProps bpsBefore = (BorderProps) area
1135:                        .getTrait(Trait.BORDER_BEFORE);
1136:                BorderProps bpsAfter = (BorderProps) area
1137:                        .getTrait(Trait.BORDER_AFTER);
1138:                BorderProps bpsStart = (BorderProps) area
1139:                        .getTrait(Trait.BORDER_START);
1140:                BorderProps bpsEnd = (BorderProps) area
1141:                        .getTrait(Trait.BORDER_END);
1142:
1143:                // draw background
1144:                Trait.Background back;
1145:                back = (Trait.Background) area.getTrait(Trait.BACKGROUND);
1146:                if (back != null) {
1147:
1148:                    // Calculate padding rectangle
1149:                    float sx = startx;
1150:                    float sy = starty;
1151:                    float paddRectWidth = width;
1152:                    float paddRectHeight = height;
1153:
1154:                    if (bpsStart != null) {
1155:                        sx += bpsStart.width / 1000f;
1156:                        paddRectWidth -= bpsStart.width / 1000f;
1157:                    }
1158:                    if (bpsBefore != null) {
1159:                        sy += bpsBefore.width / 1000f;
1160:                        paddRectHeight -= bpsBefore.width / 1000f;
1161:                    }
1162:                    if (bpsEnd != null) {
1163:                        paddRectWidth -= bpsEnd.width / 1000f;
1164:                    }
1165:                    if (bpsAfter != null) {
1166:                        paddRectHeight -= bpsAfter.width / 1000f;
1167:                    }
1168:
1169:                    if (back.getColor() != null) {
1170:                        updateFillColor(back.getColor());
1171:                        fillRect(sx, sy, paddRectWidth, paddRectHeight);
1172:                    }
1173:
1174:                    // background image
1175:                    if (back.getFopImage() != null) {
1176:                        FopImage fopimage = back.getFopImage();
1177:                        if (fopimage != null
1178:                                && fopimage.load(FopImage.DIMENSIONS)) {
1179:                            saveGraphicsState();
1180:                            clipRect(sx, sy, paddRectWidth, paddRectHeight);
1181:                            int horzCount = (int) ((paddRectWidth * 1000 / fopimage
1182:                                    .getIntrinsicWidth()) + 1.0f);
1183:                            int vertCount = (int) ((paddRectHeight * 1000 / fopimage
1184:                                    .getIntrinsicHeight()) + 1.0f);
1185:                            if (back.getRepeat() == EN_NOREPEAT) {
1186:                                horzCount = 1;
1187:                                vertCount = 1;
1188:                            } else if (back.getRepeat() == EN_REPEATX) {
1189:                                vertCount = 1;
1190:                            } else if (back.getRepeat() == EN_REPEATY) {
1191:                                horzCount = 1;
1192:                            }
1193:                            // change from points to millipoints
1194:                            sx *= 1000;
1195:                            sy *= 1000;
1196:                            if (horzCount == 1) {
1197:                                sx += back.getHoriz();
1198:                            }
1199:                            if (vertCount == 1) {
1200:                                sy += back.getVertical();
1201:                            }
1202:                            for (int x = 0; x < horzCount; x++) {
1203:                                for (int y = 0; y < vertCount; y++) {
1204:                                    // place once
1205:                                    Rectangle2D pos;
1206:                                    // Image positions are relative to the currentIP/BP
1207:                                    pos = new Rectangle2D.Float(
1208:                                            sx
1209:                                                    - currentIPPosition
1210:                                                    + (x * fopimage
1211:                                                            .getIntrinsicWidth()),
1212:                                            sy
1213:                                                    - currentBPPosition
1214:                                                    + (y * fopimage
1215:                                                            .getIntrinsicHeight()),
1216:                                            fopimage.getIntrinsicWidth(),
1217:                                            fopimage.getIntrinsicHeight());
1218:                                    drawImage(back.getURL(), pos, null);
1219:                                }
1220:                            }
1221:                            restoreGraphicsState();
1222:                        } else {
1223:                            log.warn("Can't find background image: "
1224:                                    + back.getURL());
1225:                        }
1226:                    }
1227:                }
1228:
1229:                Rectangle2D.Float borderRect = new Rectangle2D.Float(startx,
1230:                        starty, width, height);
1231:                drawBorders(borderRect, bpsBefore, bpsAfter, bpsStart, bpsEnd);
1232:            }
1233:
1234:            /**
1235:             * Draws borders.
1236:             * @param borderRect the border rectangle
1237:             * @param bpsBefore the border specification on the before side
1238:             * @param bpsAfter the border specification on the after side
1239:             * @param bpsStart the border specification on the start side
1240:             * @param bpsEnd the border specification on the end side
1241:             */
1242:            protected void drawBorders(Rectangle2D.Float borderRect,
1243:                    final BorderProps bpsBefore, final BorderProps bpsAfter,
1244:                    final BorderProps bpsStart, final BorderProps bpsEnd) {
1245:                if (bpsBefore == null && bpsAfter == null && bpsStart == null
1246:                        && bpsEnd == null) {
1247:                    return; //no borders to paint
1248:                }
1249:                if (qualityBeforeSpeed) {
1250:                    drawQualityBorders(borderRect, bpsBefore, bpsAfter,
1251:                            bpsStart, bpsEnd);
1252:                } else {
1253:                    drawFastBorders(borderRect, bpsBefore, bpsAfter, bpsStart,
1254:                            bpsEnd);
1255:                }
1256:            }
1257:
1258:            /**
1259:             * Draws borders. Borders are drawn as shaded rectangles with no clipping.
1260:             * @param borderRect the border rectangle
1261:             * @param bpsBefore the border specification on the before side
1262:             * @param bpsAfter the border specification on the after side
1263:             * @param bpsStart the border specification on the start side
1264:             * @param bpsEnd the border specification on the end side
1265:             */
1266:            protected void drawFastBorders(Rectangle2D.Float borderRect,
1267:                    final BorderProps bpsBefore, final BorderProps bpsAfter,
1268:                    final BorderProps bpsStart, final BorderProps bpsEnd) {
1269:                float startx = borderRect.x;
1270:                float starty = borderRect.y;
1271:                float width = borderRect.width;
1272:                float height = borderRect.height;
1273:                if (bpsBefore != null) {
1274:                    float borderWidth = bpsBefore.width / 1000f;
1275:                    updateFillColor(bpsBefore.color);
1276:                    fillRect(startx, starty, width, borderWidth);
1277:                }
1278:                if (bpsAfter != null) {
1279:                    float borderWidth = bpsAfter.width / 1000f;
1280:                    updateFillColor(bpsAfter.color);
1281:                    fillRect(startx, (starty + height - borderWidth), width,
1282:                            borderWidth);
1283:                }
1284:                if (bpsStart != null) {
1285:                    float borderWidth = bpsStart.width / 1000f;
1286:                    updateFillColor(bpsStart.color);
1287:                    fillRect(startx, starty, borderWidth, height);
1288:                }
1289:                if (bpsEnd != null) {
1290:                    float borderWidth = bpsEnd.width / 1000f;
1291:                    updateFillColor(bpsEnd.color);
1292:                    fillRect((startx + width - borderWidth), starty,
1293:                            borderWidth, height);
1294:                }
1295:            }
1296:
1297:            /**
1298:             * Draws borders. Borders are drawn in-memory and painted as a bitmap.
1299:             * @param borderRect the border rectangle
1300:             * @param bpsBefore the border specification on the before side
1301:             * @param bpsAfter the border specification on the after side
1302:             * @param bpsStart the border specification on the start side
1303:             * @param bpsEnd the border specification on the end side
1304:             */
1305:            protected void drawQualityBorders(Rectangle2D.Float borderRect,
1306:                    final BorderProps bpsBefore, final BorderProps bpsAfter,
1307:                    final BorderProps bpsStart, final BorderProps bpsEnd) {
1308:                Graphics2DAdapter g2a = getGraphics2DAdapter();
1309:                final Rectangle.Float effBorderRect = new Rectangle2D.Float(
1310:                        borderRect.x - (currentIPPosition / 1000f),
1311:                        borderRect.y - (currentBPPosition / 1000f),
1312:                        borderRect.width, borderRect.height);
1313:                final Rectangle paintRect = new Rectangle((int) Math
1314:                        .round(borderRect.x * 1000f), (int) Math
1315:                        .round(borderRect.y * 1000f), (int) Math
1316:                        .floor(borderRect.width * 1000f) + 1, (int) Math
1317:                        .floor(borderRect.height * 1000f) + 1);
1318:                //Add one pixel wide safety margin around the paint area
1319:                int pixelWidth = (int) Math.round(UnitConv.in2mpt(1)
1320:                        / userAgent.getTargetResolution());
1321:                final int xoffset = (int) Math.round(-effBorderRect.x * 1000f)
1322:                        + pixelWidth;
1323:                final int yoffset = pixelWidth;
1324:                paintRect.x += xoffset;
1325:                paintRect.y += yoffset;
1326:                paintRect.width += 2 * pixelWidth;
1327:                paintRect.height += 2 * pixelWidth;
1328:
1329:                RendererContext rc = createRendererContext(paintRect.x,
1330:                        paintRect.y, paintRect.width, paintRect.height, null);
1331:                Map atts = new java.util.HashMap();
1332:                atts.put(CONV_MODE, "bitmap");
1333:                atts.put(SRC_TRANSPARENCY, "true");
1334:                rc.setProperty(RendererContextConstants.FOREIGN_ATTRIBUTES,
1335:                        atts);
1336:
1337:                Graphics2DImagePainter painter = new Graphics2DImagePainter() {
1338:
1339:                    public void paint(Graphics2D g2d, Rectangle2D area) {
1340:                        g2d.translate(xoffset, yoffset);
1341:                        g2d.scale(1000, 1000);
1342:                        float startx = effBorderRect.x;
1343:                        float starty = effBorderRect.y;
1344:                        float width = effBorderRect.width;
1345:                        float height = effBorderRect.height;
1346:                        boolean[] b = new boolean[] { (bpsBefore != null),
1347:                                (bpsEnd != null), (bpsAfter != null),
1348:                                (bpsStart != null) };
1349:                        if (!b[0] && !b[1] && !b[2] && !b[3]) {
1350:                            return;
1351:                        }
1352:                        float[] bw = new float[] {
1353:                                (b[0] ? bpsBefore.width / 1000f : 0.0f),
1354:                                (b[1] ? bpsEnd.width / 1000f : 0.0f),
1355:                                (b[2] ? bpsAfter.width / 1000f : 0.0f),
1356:                                (b[3] ? bpsStart.width / 1000f : 0.0f) };
1357:                        float[] clipw = new float[] {
1358:                                BorderProps.getClippedWidth(bpsBefore) / 1000f,
1359:                                BorderProps.getClippedWidth(bpsEnd) / 1000f,
1360:                                BorderProps.getClippedWidth(bpsAfter) / 1000f,
1361:                                BorderProps.getClippedWidth(bpsStart) / 1000f };
1362:                        starty += clipw[0];
1363:                        height -= clipw[0];
1364:                        height -= clipw[2];
1365:                        startx += clipw[3];
1366:                        width -= clipw[3];
1367:                        width -= clipw[1];
1368:
1369:                        boolean[] slant = new boolean[] { (b[3] && b[0]),
1370:                                (b[0] && b[1]), (b[1] && b[2]), (b[2] && b[3]) };
1371:                        if (bpsBefore != null) {
1372:                            //endTextObject();
1373:
1374:                            float sx1 = startx;
1375:                            float sx2 = (slant[0] ? sx1 + bw[3] - clipw[3]
1376:                                    : sx1);
1377:                            float ex1 = startx + width;
1378:                            float ex2 = (slant[1] ? ex1 - bw[1] + clipw[1]
1379:                                    : ex1);
1380:                            float outery = starty - clipw[0];
1381:                            float clipy = outery + clipw[0];
1382:                            float innery = outery + bw[0];
1383:
1384:                            //saveGraphicsState();
1385:                            Graphics2D g = (Graphics2D) g2d.create();
1386:                            moveTo(sx1, clipy);
1387:                            float sx1a = sx1;
1388:                            float ex1a = ex1;
1389:                            if (bpsBefore.mode == BorderProps.COLLAPSE_OUTER) {
1390:                                if (bpsStart != null
1391:                                        && bpsStart.mode == BorderProps.COLLAPSE_OUTER) {
1392:                                    sx1a -= clipw[3];
1393:                                }
1394:                                if (bpsEnd != null
1395:                                        && bpsEnd.mode == BorderProps.COLLAPSE_OUTER) {
1396:                                    ex1a += clipw[1];
1397:                                }
1398:                                lineTo(sx1a, outery);
1399:                                lineTo(ex1a, outery);
1400:                            }
1401:                            lineTo(ex1, clipy);
1402:                            lineTo(ex2, innery);
1403:                            lineTo(sx2, innery);
1404:                            closePath();
1405:                            //clip();
1406:                            g.clip(currentPath);
1407:                            currentPath = null;
1408:                            Rectangle2D.Float lineRect = new Rectangle2D.Float(
1409:                                    sx1a, outery, ex1a - sx1a, innery - outery);
1410:                            Java2DRenderer.drawBorderLine(lineRect, true, true,
1411:                                    bpsBefore.style, bpsBefore.color, g);
1412:                            //restoreGraphicsState();
1413:                        }
1414:                        if (bpsEnd != null) {
1415:                            //endTextObject();
1416:
1417:                            float sy1 = starty;
1418:                            float sy2 = (slant[1] ? sy1 + bw[0] - clipw[0]
1419:                                    : sy1);
1420:                            float ey1 = starty + height;
1421:                            float ey2 = (slant[2] ? ey1 - bw[2] + clipw[2]
1422:                                    : ey1);
1423:                            float outerx = startx + width + clipw[1];
1424:                            float clipx = outerx - clipw[1];
1425:                            float innerx = outerx - bw[1];
1426:
1427:                            //saveGraphicsState();
1428:                            Graphics2D g = (Graphics2D) g2d.create();
1429:                            moveTo(clipx, sy1);
1430:                            float sy1a = sy1;
1431:                            float ey1a = ey1;
1432:                            if (bpsEnd.mode == BorderProps.COLLAPSE_OUTER) {
1433:                                if (bpsBefore != null
1434:                                        && bpsBefore.mode == BorderProps.COLLAPSE_OUTER) {
1435:                                    sy1a -= clipw[0];
1436:                                }
1437:                                if (bpsAfter != null
1438:                                        && bpsAfter.mode == BorderProps.COLLAPSE_OUTER) {
1439:                                    ey1a += clipw[2];
1440:                                }
1441:                                lineTo(outerx, sy1a);
1442:                                lineTo(outerx, ey1a);
1443:                            }
1444:                            lineTo(clipx, ey1);
1445:                            lineTo(innerx, ey2);
1446:                            lineTo(innerx, sy2);
1447:                            closePath();
1448:                            //clip();
1449:                            g.setClip(currentPath);
1450:                            currentPath = null;
1451:                            Rectangle2D.Float lineRect = new Rectangle2D.Float(
1452:                                    innerx, sy1a, outerx - innerx, ey1a - sy1a);
1453:                            Java2DRenderer.drawBorderLine(lineRect, false,
1454:                                    false, bpsEnd.style, bpsEnd.color, g);
1455:                            //restoreGraphicsState();
1456:                        }
1457:                        if (bpsAfter != null) {
1458:                            //endTextObject();
1459:
1460:                            float sx1 = startx;
1461:                            float sx2 = (slant[3] ? sx1 + bw[3] - clipw[3]
1462:                                    : sx1);
1463:                            float ex1 = startx + width;
1464:                            float ex2 = (slant[2] ? ex1 - bw[1] + clipw[1]
1465:                                    : ex1);
1466:                            float outery = starty + height + clipw[2];
1467:                            float clipy = outery - clipw[2];
1468:                            float innery = outery - bw[2];
1469:
1470:                            //saveGraphicsState();
1471:                            Graphics2D g = (Graphics2D) g2d.create();
1472:                            moveTo(ex1, clipy);
1473:                            float sx1a = sx1;
1474:                            float ex1a = ex1;
1475:                            if (bpsAfter.mode == BorderProps.COLLAPSE_OUTER) {
1476:                                if (bpsStart != null
1477:                                        && bpsStart.mode == BorderProps.COLLAPSE_OUTER) {
1478:                                    sx1a -= clipw[3];
1479:                                }
1480:                                if (bpsEnd != null
1481:                                        && bpsEnd.mode == BorderProps.COLLAPSE_OUTER) {
1482:                                    ex1a += clipw[1];
1483:                                }
1484:                                lineTo(ex1a, outery);
1485:                                lineTo(sx1a, outery);
1486:                            }
1487:                            lineTo(sx1, clipy);
1488:                            lineTo(sx2, innery);
1489:                            lineTo(ex2, innery);
1490:                            closePath();
1491:                            //clip();
1492:                            g.setClip(currentPath);
1493:                            currentPath = null;
1494:                            Rectangle2D.Float lineRect = new Rectangle2D.Float(
1495:                                    sx1a, innery, ex1a - sx1a, outery - innery);
1496:                            Java2DRenderer.drawBorderLine(lineRect, true,
1497:                                    false, bpsAfter.style, bpsAfter.color, g);
1498:                            //restoreGraphicsState();
1499:                        }
1500:                        if (bpsStart != null) {
1501:                            //endTextObject();
1502:
1503:                            float sy1 = starty;
1504:                            float sy2 = (slant[0] ? sy1 + bw[0] - clipw[0]
1505:                                    : sy1);
1506:                            float ey1 = sy1 + height;
1507:                            float ey2 = (slant[3] ? ey1 - bw[2] + clipw[2]
1508:                                    : ey1);
1509:                            float outerx = startx - clipw[3];
1510:                            float clipx = outerx + clipw[3];
1511:                            float innerx = outerx + bw[3];
1512:
1513:                            //saveGraphicsState();
1514:                            Graphics2D g = (Graphics2D) g2d.create();
1515:                            moveTo(clipx, ey1);
1516:                            float sy1a = sy1;
1517:                            float ey1a = ey1;
1518:                            if (bpsStart.mode == BorderProps.COLLAPSE_OUTER) {
1519:                                if (bpsBefore != null
1520:                                        && bpsBefore.mode == BorderProps.COLLAPSE_OUTER) {
1521:                                    sy1a -= clipw[0];
1522:                                }
1523:                                if (bpsAfter != null
1524:                                        && bpsAfter.mode == BorderProps.COLLAPSE_OUTER) {
1525:                                    ey1a += clipw[2];
1526:                                }
1527:                                lineTo(outerx, ey1a);
1528:                                lineTo(outerx, sy1a);
1529:                            }
1530:                            lineTo(clipx, sy1);
1531:                            lineTo(innerx, sy2);
1532:                            lineTo(innerx, ey2);
1533:                            closePath();
1534:                            //clip();
1535:                            g.setClip(currentPath);
1536:                            currentPath = null;
1537:                            Rectangle2D.Float lineRect = new Rectangle2D.Float(
1538:                                    outerx, sy1a, innerx - outerx, ey1a - sy1a);
1539:                            Java2DRenderer.drawBorderLine(lineRect, false,
1540:                                    false, bpsStart.style, bpsStart.color, g);
1541:                            //restoreGraphicsState();
1542:                        }
1543:                    }
1544:
1545:                    public Dimension getImageSize() {
1546:                        return paintRect.getSize();
1547:                    }
1548:
1549:                };
1550:                try {
1551:                    g2a.paintImage(painter, rc, paintRect.x - xoffset,
1552:                            paintRect.y, paintRect.width, paintRect.height);
1553:                } catch (IOException ioe) {
1554:                    handleIOTrouble(ioe);
1555:                }
1556:            }
1557:
1558:            public void setAllTextAsBitmaps(boolean allTextAsBitmaps) {
1559:                this.allTextAsBitmaps = allTextAsBitmaps;
1560:            }
1561:
1562:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.