ASF Bugzilla – Attachment 14372 Details for
Bug 33760
[Patch] current AWTRenderer
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
[PATCH] implementation of the AWTRenderer (2)
PatchAWTRenderer2.txt (text/plain), 94.42 KB, created by
renaud richardet
on 2005-02-28 03:16:00 UTC
(
hide
)
Description:
[PATCH] implementation of the AWTRenderer (2)
Filename:
MIME Type:
Creator:
renaud richardet
Created:
2005-02-28 03:16:00 UTC
Size:
94.42 KB
patch
obsolete
>Index: src/java/org/apache/fop/area/CTM.java >=================================================================== >RCS file: /home/cvspublic/xml-fop/src/java/org/apache/fop/area/CTM.java,v >retrieving revision 1.9 >diff -u -r1.9 CTM.java >--- src/java/org/apache/fop/area/CTM.java 24 Nov 2004 21:07:28 -0000 1.9 >+++ src/java/org/apache/fop/area/CTM.java 28 Feb 2005 02:06:52 -0000 >@@ -1,12 +1,12 @@ > /* > * Copyright 1999-2004 The Apache Software Foundation. >- * >+ * > * Licensed under the Apache License, Version 2.0 (the "License"); > * you may not use this file except in compliance with the License. > * You may obtain a copy of the License at >- * >+ * > * http://www.apache.org/licenses/LICENSE-2.0 >- * >+ * > * Unless required by applicable law or agreed to in writing, software > * distributed under the License is distributed on an "AS IS" BASIS, > * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. >@@ -248,6 +248,8 @@ > > /** > * Construct a coordinate transformation matrix (CTM). >+ * @param absRefOrient absolute reference orientation >+ * @param writingMode > * @param absVPrect absolute viewpoint rectangle > * @param reldims relative dimensions > * @return CTM the coordinate transformation matrix (CTM) >@@ -311,4 +313,18 @@ > return ctm.multiply(CTM.getWMctm(writingMode, reldims.ipd, reldims.bpd)); > } > >+ >+ /**gets the x shift of this CTM >+ * @return the x shift as a double >+ */ >+ public double getXShift( ) { >+ return this.e; >+ } >+ >+ /**gets the y shift of this CTM >+ * @return the y shift as a double >+ */ >+ public double getYShift( ) { >+ return this.f; >+ } > } >Index: src/java/org/apache/fop/render/AbstractRenderer.java >=================================================================== >RCS file: /home/cvspublic/xml-fop/src/java/org/apache/fop/render/AbstractRenderer.java,v >retrieving revision 1.42 >diff -u -r1.42 AbstractRenderer.java >--- src/java/org/apache/fop/render/AbstractRenderer.java 7 Feb 2005 11:00:19 -0000 1.42 >+++ src/java/org/apache/fop/render/AbstractRenderer.java 28 Feb 2005 02:06:57 -0000 >@@ -1,12 +1,12 @@ > /* > * Copyright 1999-2005 The Apache Software Foundation. >- * >+ * > * Licensed under the Apache License, Version 2.0 (the "License"); > * you may not use this file except in compliance with the License. > * You may obtain a copy of the License at >- * >+ * > * http://www.apache.org/licenses/LICENSE-2.0 >- * >+ * > * Unless required by applicable law or agreed to in writing, software > * distributed under the License is distributed on an "AS IS" BASIS, > * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. >@@ -59,7 +59,9 @@ > import org.apache.fop.area.inline.TextArea; > import org.apache.fop.area.inline.Character; > import org.apache.fop.apps.FOUserAgent; >+import org.apache.fop.datatypes.ColorType; > import org.apache.fop.fo.Constants; >+import org.apache.fop.fonts.Font; > import org.apache.fop.fonts.FontInfo; > import org.apache.commons.logging.Log; > import org.apache.commons.logging.LogFactory; >@@ -74,7 +76,7 @@ > * top level processing of the area tree and adds some abstract methods to > * handle viewports. This keeps track of the current block and inline position. > */ >-public abstract class AbstractRenderer >+public abstract class AbstractRenderer > implements Renderer, Configurable, Constants { > > /** >@@ -86,7 +88,7 @@ > * logging instance > */ > protected static Log logger = LogFactory.getLog("org.apache.fop.render"); >- >+ > /** > * block progression position > */ >@@ -109,6 +111,9 @@ > */ > protected int containingIPPosition = 0; > >+ /** Name of currently selected font */ >+ protected String currentFontName = ""; >+ > /** > * @see org.apache.avalon.framework.configuration.Configurable#configure(Configuration) > */ >@@ -256,8 +261,9 @@ > // The CTM will transform coordinates relative to > // this region-reference area into page coords, so > // set origin for the region to 0,0. >- currentBPPosition = 0; >- currentIPPosition = 0; >+ //currentBPPosition = 0; >+ //currentIPPosition = 0; >+ //FIXME containingXXXPosition is reseted in startVParea(); > > RegionReference region = port.getRegion(); > handleRegionTraits(port); >@@ -275,26 +281,53 @@ > } > > /** >- * (todo) Description of the Method >+ * The CTM will transform coordinates relative to this >+ * region-reference area into page coords > * >- * @param ctm The coordinate transformation matrix to use >+ * @param ctm The coordinate transformation matrix to use > */ > protected void startVParea(CTM ctm) { } > > /** >+ * (todo) Description of the Method >+ */ >+ protected void endVParea() { } >+ >+ /** > * Handle the traits for a region > * This is used to draw the traits for the given page region. > * (See Sect. 6.4.1.2 of XSL-FO spec.) >- * @param rv the RegionViewport whose region is to be drawn >+ * @param region the RegionViewport whose region is to be drawn > */ >- protected void handleRegionTraits(RegionViewport rv) { >- // draw border and background >+ protected void handleRegionTraits(RegionViewport region) { >+ >+ currentFontName = ""; // TODO why here? >+ Rectangle2D viewArea = region.getViewArea(); >+ float startx = (float) (viewArea.getX() / 1000f); >+ float starty = (float) (viewArea.getY() / 1000f); >+ float width = (float) (viewArea.getWidth() / 1000f); >+ float height = (float) (viewArea.getHeight() / 1000f); >+ >+ if (region.getRegion().getRegionClass() == FO_REGION_BODY) { >+ currentBPPosition = region.getBorderAndPaddingWidthBefore(); >+ currentIPPosition = region.getBorderAndPaddingWidthStart(); >+ } >+ drawBackAndBorders(region, startx, starty, width, height); > } > > /** >- * (todo) Description of the Method >+ * Draw the background and borders. This draws the background and border >+ * traits for an area given the position. >+ * >+ * @param region the area to get the traits from >+ * @param startx the start x position >+ * @param starty the start y position >+ * @param width the width of the area >+ * @param height the height of the area > */ >- protected void endVParea() { } >+ protected void drawBackAndBorders(RegionViewport region, float startx, >+ float starty, float width, float height) { >+ } > > /** > * Renders a region reference area. >@@ -429,8 +462,8 @@ > int saveBP = currentBPPosition; > > CTM ctm = bv.getCTM(); >- currentIPPosition = 0; >- currentBPPosition = 0; >+ //currentIPPosition = 0; >+ //currentBPPosition = 0; > > startVParea(ctm); > handleBlockTraits(bv); >@@ -458,7 +491,7 @@ > * Renders a list of block areas. > * > * @param parent the parent block if the parent is a block, otherwise >- * a null value. >+ * a null value. > * @param blocks The block areas > */ > protected void renderBlocks(Block parent, List blocks) { >@@ -475,7 +508,7 @@ > currentIPPosition += spaceStart.intValue(); > }*/ > } >- >+ > // the position of the containing block is used for > // absolutely positioned areas > int contBP = currentBPPosition; >@@ -496,8 +529,8 @@ > // a line area is rendered from the top left position > // of the line, each inline object is offset from there > LineArea line = (LineArea) obj; >- currentIPPosition = contIP >- + parent.getStartIndent() >+ currentIPPosition = contIP >+ + parent.getStartIndent() > + line.getStartIndent(); > renderLineArea(line); > currentBPPosition += line.getAllocBPD(); >@@ -556,11 +589,88 @@ > } > } > >+ /** Renders the text decorations of an inline area >+ * @param area the inline area >+ */ > protected void renderTextDecoration(InlineArea area) { >- //getLogger().debug("renderTextDecoration for " + area + " -> " + area.getTrait(Trait.UNDERLINE)); >+ //getLogger().debug("renderTextDecoration for " + >+ //area + " -> " + area.getTrait(Trait.UNDERLINE)); > } > > /** >+ * Paints the text decoration marks. >+ * @param fs Current font >+ * @param inline inline area to paint the marks for >+ * @param baseline position of the baseline >+ * @param startx start IPD >+ */ >+ protected void renderTextDecoration(Font fs, InlineArea inline, >+ int baseline, int startx) { >+ boolean hasTextDeco = inline.hasUnderline() >+ || inline.hasOverline() >+ || inline.hasLineThrough(); >+ if (hasTextDeco) { >+ endTextObject(); >+ updateLineStyle(Constants.EN_SOLID); >+ updateLineWidth(fs.getDescender() / -8 / 1000f); >+ float endx = (startx + inline.getIPD()) / 1000f; >+ if (inline.hasUnderline()) { >+ ColorType ct = (ColorType) inline.getTrait(Trait.UNDERLINE_COLOR); >+ updateColor(ct, false, null); >+ float y = baseline - fs.getDescender() / 2; >+ drawLine(startx / 1000f, y / 1000f, endx, y / 1000f); >+ } >+ if (inline.hasOverline()) { >+ ColorType ct = (ColorType) inline.getTrait(Trait.OVERLINE_COLOR); >+ updateColor(ct, false, null); >+ float y = (float)(baseline - (1.1 * fs.getCapHeight())); >+ drawLine(startx / 1000f, y / 1000f, endx, y / 1000f); >+ } >+ if (inline.hasLineThrough()) { >+ ColorType ct = (ColorType) inline.getTrait(Trait.LINETHROUGH_COLOR); >+ updateColor(ct, false, null); >+ float y = (float)(baseline - (0.45 * fs.getCapHeight())); >+ drawLine(startx / 1000f, y / 1000f, endx, y / 1000f); >+ } >+ } >+ } >+ >+ /** >+ * Sets the current line style. The line width should be >+ * set with updateLineWidth() before calling this method >+ * @param style the constant for the style of the line as an int >+ */ >+ protected void updateLineStyle(int style) { } >+ >+ /** Indicates the end of a text object. */ >+ protected void endTextObject() { } >+ >+ /** >+ * Sets the current line width in points. >+ * @param width line width in points >+ */ >+ protected void updateLineWidth(float width) { } >+ >+ /** >+ * Draw a line. >+ * >+ * @param startx the start x position >+ * @param starty the start y position >+ * @param endx the x end position >+ * @param endy the y end position >+ */ >+ protected void drawLine(float startx, float starty, float endx, float endy) { } >+ >+ /** >+ * Establishes a new foreground or fill color. >+ * @param col the color to apply (null skips this operation) >+ * @param fill true to set the fill color, false for the foreground color >+ * @param pdf StringBuffer to write the PDF code to, if null, the code is >+ * written to the current stream. >+ */ >+ protected void updateColor(ColorType col, boolean fill, StringBuffer pdf) { } >+ >+ /** > * Renders a line area. <p> > * > * A line area may have grouped styling for its children such as underline, >@@ -624,12 +734,12 @@ > int saveIP = currentIPPosition; > Iterator iter = ip.getChildAreas().iterator(); > while (iter.hasNext()) { >- renderInlineArea((InlineArea) iter.next()); >+ renderInlineArea((InlineArea) iter.next()); > } > currentIPPosition = saveIP + ip.getAllocIPD(); > } > >- /** @see org.apache.fop.render.Renderer */ >+ /** @see org.apache.fop.render.Renderer */ //TODO nothing to see there > protected void renderViewport(Viewport viewport) { > Area content = viewport.getContent(); > int saveBP = currentBPPosition; >@@ -677,7 +787,7 @@ > * > * @param fo The foreign object area > * @param pos The target position of the foreign object >- * (todo) Make renderForeignObject() protected >+ * TODO Make renderForeignObject() protected > */ > public void renderForeignObject(ForeignObject fo, Rectangle2D pos) { > // Default: do nothing. >@@ -686,6 +796,7 @@ > > /** > * Set the default xml handler for the given mime type. >+ * @param foua the user agent > * @param mime MIME type > * @param handler XMLHandler to use > */ >@@ -696,6 +807,7 @@ > > /** > * Add an xml handler for the given mime type and xml namespace. >+ * @param foua the user agent > * @param mime MIME type > * @param ns Namespace URI > * @param handler XMLHandler to use >@@ -714,6 +826,7 @@ > * Render the xml document with the given xml namespace. > * The Render Context is by the handle to render into the current > * rendering target. >+ * @param foua the user agent > * @param ctx rendering context > * @param doc DOM Document containing the source document > * @param namespace Namespace URI of the document >@@ -746,7 +859,7 @@ > > /** > * Get the MIME type of the renderer. >- * >+ * > * @return The MIME type of the renderer > */ > public String getMimeType() { >Index: src/java/org/apache/fop/render/awt/AWTRenderer.java >=================================================================== >RCS file: /home/cvspublic/xml-fop/src/java/org/apache/fop/render/awt/AWTRenderer.java,v >retrieving revision 1.33 >diff -u -r1.33 AWTRenderer.java >--- src/java/org/apache/fop/render/awt/AWTRenderer.java 24 Nov 2004 21:07:30 -0000 1.33 >+++ src/java/org/apache/fop/render/awt/AWTRenderer.java 28 Feb 2005 02:07:01 -0000 >@@ -1,12 +1,12 @@ > /* > * Copyright 1999-2004 The Apache Software Foundation. >- * >+ * > * Licensed under the Apache License, Version 2.0 (the "License"); > * you may not use this file except in compliance with the License. > * You may obtain a copy of the License at >- * >+ * > * http://www.apache.org/licenses/LICENSE-2.0 >- * >+ * > * Unless required by applicable law or agreed to in writing, software > * distributed under the License is distributed on an "AS IS" BASIS, > * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. >@@ -26,6 +26,7 @@ > */ > > // Java >+import java.awt.BasicStroke; > import java.awt.Color; > import java.awt.Dimension; > import java.awt.Graphics; >@@ -35,6 +36,8 @@ > import java.awt.event.WindowAdapter; > import java.awt.event.WindowEvent; > import java.awt.geom.AffineTransform; >+import java.awt.geom.Line2D; >+import java.awt.geom.NoninvertibleTransformException; > import java.awt.geom.Rectangle2D; > import java.awt.image.BufferedImage; > import java.awt.print.PageFormat; >@@ -45,41 +48,103 @@ > import java.util.Map; > import java.util.Vector; > >-import org.apache.fop.fonts.FontInfo; >+import org.apache.batik.bridge.BridgeContext; >+import org.apache.batik.bridge.GVTBuilder; >+import org.apache.batik.bridge.ViewBox; >+import org.apache.batik.gvt.GraphicsNode; > import org.apache.fop.apps.FOPException; > import org.apache.fop.apps.FOUserAgent; > import org.apache.fop.area.Area; >+import org.apache.fop.area.Block; >+import org.apache.fop.area.CTM; > import org.apache.fop.area.Page; > import org.apache.fop.area.PageViewport; >-import org.apache.fop.area.RegionViewport; > import org.apache.fop.area.Trait; >+import org.apache.fop.area.inline.Character; >+import org.apache.fop.area.inline.ForeignObject; >+import org.apache.fop.area.inline.Image; >+import org.apache.fop.area.inline.Leader; > import org.apache.fop.area.inline.TextArea; > import org.apache.fop.datatypes.ColorType; >+import org.apache.fop.fonts.Font; >+import org.apache.fop.fonts.FontInfo; >+import org.apache.fop.fonts.FontMetrics; > import org.apache.fop.image.FopImage; > import org.apache.fop.image.ImageFactory; >+import org.apache.fop.image.XMLImage; > import org.apache.fop.render.AbstractRenderer; >-import org.apache.fop.traits.BorderProps; >-import org.apache.fop.render.awt.FontMetricsMapper; >+import org.apache.fop.render.RendererContext; > import org.apache.fop.render.awt.viewer.PreviewDialog; > import org.apache.fop.render.awt.viewer.Translator; >+import org.apache.fop.svg.SVGUserAgent; >+import org.apache.fop.traits.BorderProps; >+import org.w3c.dom.Document; >+import org.w3c.dom.svg.SVGDocument; >+import org.w3c.dom.svg.SVGSVGElement; > > /** >- * This is FOP's AWT renderer. >+ * Java2DRenderer provides the abstract technical foundation for all rendering >+ * with the Java2D API. Renderers like AWTRenderer subclass it and provide the >+ * concrete output paths. >+ * >+ * A lot of the logic is performed by AbstractRenderer. The class-variables >+ * currentIPPosition and currentBPPosition hold the position of the currently >+ * rendered area. >+ * >+ * The rendering process is basically always the same: void renderXXXXX(Area >+ * area){ get the currentPosition updateColor(area); updateFont(area); String s = >+ * area.getTextArea(); graphics.draw(new Shape(args)); } >+ * > */ >-public class AWTRenderer extends AbstractRenderer implements Printable, Pageable { >+public class AWTRenderer extends AbstractRenderer implements Printable, >+ Pageable { > >- /** The MIME type for PostScript */ >+ /** The MIME type for AWT-Rendering */ > public static final String MIME_TYPE = "application/awt"; > > protected double scaleFactor = 100.0; >+ > protected int pageNumber = 0; >+ > private int pageWidth = 0; >+ > private int pageHeight = 0; >+ > private Vector pageViewportList = new java.util.Vector(); >+ > private Vector pageList = new java.util.Vector(); >+ > private Vector bufferedImageList = new java.util.Vector(); >- private BufferedImage currentPageImage = null; >- >+ >+ protected BufferedImage currentPageImage = null; >+ >+ /** the graphic used to draw on the BufferedImage */ >+ protected Graphics2D graphics = null; >+ >+ /** the stroke used for graphics */ >+ protected BasicStroke stroke = new BasicStroke(); >+ >+ /** a basic stroke to reset the stroke */ >+ protected final BasicStroke basicStroke = new BasicStroke(); >+ >+ private boolean debug = true; >+ >+ protected boolean antialiasing = true; >+ >+ protected boolean qualityRendering = true; >+ >+ /** Size of currently selected font */ >+ protected int currentFontSize = 0; >+ >+ /** Currently selected Color */ >+ protected Color currentColor = null; >+ >+ /** Width of current line */ >+ protected float currentLineWidth = 0; >+ >+ /** Style of current line */ >+ protected int currentLineStyle = 0; >+ > /** Font configuration */ > protected FontInfo fontInfo; > >@@ -89,13 +154,14 @@ > protected Translator translator = null; > > private Map fontNames = new java.util.Hashtable(); >+ > private Map fontStyles = new java.util.Hashtable(); >+ > private Color saveColor = null; > > /** >- * The preview dialog frame used for display of the documents. >- * Also used as the AWT Component for FontSetup in generating >- * valid font measures. >+ * The preview dialog frame used for display of the documents. Also used as >+ * the AWT Component for FontSetup in generating valid font measures. > */ > protected PreviewDialog frame; > >@@ -127,9 +193,10 @@ > public void setupFontInfo(FontInfo inFontInfo) { > // create a temp Image to test font metrics on > fontInfo = inFontInfo; >- BufferedImage fontImage = >- new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB); >+ BufferedImage fontImage = new BufferedImage(100, 100, >+ BufferedImage.TYPE_INT_RGB); > FontSetup.setup(fontInfo, fontImage.createGraphics()); >+ // FIXME is this implemented correctly? > } > > public int getPageNumber() { >@@ -148,17 +215,16 @@ > return scaleFactor; > } > >- public void startRenderer(OutputStream out) >- throws IOException { >+ public void startRenderer(OutputStream out) throws IOException { > // empty pageViewportList, in case of a reload from PreviewDialog > pageViewportList.removeAllElements(); > pageList.removeAllElements(); > bufferedImageList.removeAllElements(); >- System.out.println("\nRegion Types: 0-Before/Top, 1-Start/Left, 2-Body, 3-End/Right, 4-After/Bottom"); >+ System.out.println("\nRegion Types: 0-Before/Top, 1-Start/Left," >+ + " 2-Body, 3-End/Right, 4-After/Bottom"); > } > >- public void stopRenderer() >- throws IOException { >+ public void stopRenderer() throws IOException { > frame.setStatus(translator.getString("Status.Show")); > frame.showPage(); > } >@@ -188,7 +254,7 @@ > } > }); > >- //Centers the window >+ // Centers the window > Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); > Dimension frameSize = frame.getSize(); > if (frameSize.height > screenSize.height) { >@@ -198,18 +264,22 @@ > frameSize.width = screenSize.width; > } > frame.setLocation((screenSize.width - frameSize.width) / 2, >- (screenSize.height - frameSize.height) / 2); >+ (screenSize.height - frameSize.height) / 2); > frame.setVisible(true); > frame.setStatus(translator.getString("Status.Build.FO.tree")); > return frame; > } > >- /** This method override only stores the PageViewport in a vector. >- * No actual rendering performed -- this is done by getPageImage(pageNum) instead. >- * @param pageViewport the <code>PageViewport</code> object supplied by the Area Tree >- * @see org.apache.fop.render.Renderer >- */ >- public void renderPage(PageViewport pageViewport) throws IOException, FOPException { >+ /** >+ * This method override only stores the PageViewport in a vector. No actual >+ * rendering performed -- this is done by getPageImage(pageNum) instead. >+ * >+ * @param pageViewport the <code>PageViewport</code> object supplied by >+ * the Area Tree >+ * @see org.apache.fop.render.Renderer >+ */ >+ public void renderPage(PageViewport pageViewport) throws IOException, >+ FOPException { > pageViewportList.add(pageViewport); > pageList.add(pageViewport.getPage().clone()); > bufferedImageList.add(getPageImage(pageViewport)); >@@ -219,31 +289,43 @@ > return (BufferedImage) bufferedImageList.get(pageNum); > } > >- /** Generates a desired page from the renderer's page viewport vector. >+ /** >+ * Generates a desired page from the renderer's page viewport vector. >+ * > * @param pageNum the 0-based page number to generate >- * @return the <code>java.awt.image.BufferedImage</code> corresponding to the page >- * @throws FOPException in case of an out-of-range page number requested >- */ >- public BufferedImage getPageImage(PageViewport pageViewport) throws FOPException { >+ * @return the <code>java.awt.image.BufferedImage</code> corresponding to >+ * the page >+ * @throws FOPException in case of an out-of-range page number requested >+ */ >+ public BufferedImage getPageImage(PageViewport pageViewport) >+ throws FOPException { > Page page = pageViewport.getPage(); > > Rectangle2D bounds = pageViewport.getViewArea(); >- pageWidth = (int) Math.round(bounds.getWidth() / 1000f ); >- pageHeight = (int) Math.round(bounds.getHeight() / 1000f ); >-/* >- System.out.println("(Page) X, Y, Width, Height: " + bounds.getX() >- + " " + bounds.getY() >- + " " + bounds.getWidth() >- + " " + bounds.getHeight()); >-*/ >- currentPageImage = >- new BufferedImage((int)((pageWidth * (int)scaleFactor) / 100), >- (int)((pageHeight * (int)scaleFactor) / 100), >- BufferedImage.TYPE_INT_RGB); >- >- Graphics2D graphics = currentPageImage.createGraphics(); >- graphics.setRenderingHint (RenderingHints.KEY_FRACTIONALMETRICS, >- RenderingHints.VALUE_FRACTIONALMETRICS_ON); >+ pageWidth = (int) Math.round(bounds.getWidth() / 1000f); >+ pageHeight = (int) Math.round(bounds.getHeight() / 1000f); >+ >+ System.out.println("(Page) X, Y, Width, Height: " + bounds.getX() + " " >+ + bounds.getY() + " " + bounds.getWidth() + " " >+ + bounds.getHeight() + ", pageWidth " + pageWidth >+ + ", pageHeight " + pageHeight); >+ >+ currentPageImage = new BufferedImage( >+ (int) ((pageWidth * (int) scaleFactor) / 100), >+ (int) ((pageHeight * (int) scaleFactor) / 100), >+ BufferedImage.TYPE_INT_RGB); >+ >+ graphics = currentPageImage.createGraphics(); >+ graphics.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, >+ RenderingHints.VALUE_FRACTIONALMETRICS_ON); >+ if (antialiasing) { >+ graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, >+ RenderingHints.VALUE_TEXT_ANTIALIAS_ON); >+ } >+ if (qualityRendering) { >+ graphics.setRenderingHint(RenderingHints.KEY_RENDERING, >+ RenderingHints.VALUE_RENDER_QUALITY); >+ } > > // transform page based on scale factor supplied > AffineTransform at = graphics.getTransform(); >@@ -254,47 +336,64 @@ > graphics.setColor(Color.white); > graphics.fillRect(0, 0, pageWidth, pageHeight); > graphics.setColor(Color.black); >+ // TODO Why draw those silly lines? > graphics.drawRect(-1, -1, pageWidth + 2, pageHeight + 2); > graphics.drawLine(pageWidth + 2, 0, pageWidth + 2, pageHeight + 2); > graphics.drawLine(pageWidth + 3, 1, pageWidth + 3, pageHeight + 3); > graphics.drawLine(0, pageHeight + 2, pageWidth + 2, pageHeight + 2); > graphics.drawLine(1, pageHeight + 3, pageWidth + 3, pageHeight + 3); > >+ // reset the current Positions >+ currentBPPosition = 0; >+ currentIPPosition = 0; >+ >+ // this toggles the rendering of all areas > renderPageAreas(page); > return currentPageImage; > } > >- /** Generates a desired page from the renderer's page viewport vector. >+ /** >+ * TODO refactor with getPageImage(PageViewport) Generates a desired page >+ * from the renderer's page viewport vector. >+ * > * @param pageNum the 0-based page number to generate >- * @return the <code>java.awt.image.BufferedImage</code> corresponding to the page >- * @throws FOPException in case of an out-of-range page number requested >- */ >+ * @return the <code>java.awt.image.BufferedImage</code> corresponding to >+ * the page >+ * @throws FOPException in case of an out-of-range page number requested >+ */ > public BufferedImage getPageImage(int pageNum) throws FOPException { > if (pageNum < 0 || pageNum >= pageViewportList.size()) { > throw new FOPException("out-of-range page number (" + pageNum >- + ") requested; only " + pageViewportList.size() >- + " page(s) available."); >+ + ") requested; only " + pageViewportList.size() >+ + " page(s) available."); > } >- PageViewport pageViewport = (PageViewport) pageViewportList.get(pageNum); >+ PageViewport pageViewport = (PageViewport) pageViewportList >+ .get(pageNum); > Page page = (Page) pageList.get(pageNum); > > Rectangle2D bounds = pageViewport.getViewArea(); >- pageWidth = (int) Math.round(bounds.getWidth() / 1000f ); >- pageHeight = (int) Math.round(bounds.getHeight() / 1000f ); >-/* >- System.out.println("(Page) X, Y, Width, Height: " + bounds.getX() >- + " " + bounds.getY() >- + " " + bounds.getWidth() >- + " " + bounds.getHeight()); >-*/ >- currentPageImage = >- new BufferedImage((int)((pageWidth * (int)scaleFactor) / 100), >- (int)((pageHeight * (int)scaleFactor) / 100), >- BufferedImage.TYPE_INT_RGB); >- >- Graphics2D graphics = currentPageImage.createGraphics(); >- graphics.setRenderingHint (RenderingHints.KEY_FRACTIONALMETRICS, >- RenderingHints.VALUE_FRACTIONALMETRICS_ON); >+ pageWidth = (int) Math.round(bounds.getWidth() / 1000f); >+ pageHeight = (int) Math.round(bounds.getHeight() / 1000f); >+ /* >+ * System.out.println("(Page) X, Y, Width, Height: " + bounds.getX() + " " + >+ * bounds.getY() + " " + bounds.getWidth() + " " + bounds.getHeight()); >+ */ >+ currentPageImage = new BufferedImage( >+ (int) ((pageWidth * (int) scaleFactor) / 100), >+ (int) ((pageHeight * (int) scaleFactor) / 100), >+ BufferedImage.TYPE_INT_RGB); >+ >+ graphics = currentPageImage.createGraphics(); >+ graphics.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, >+ RenderingHints.VALUE_FRACTIONALMETRICS_ON); >+ if (antialiasing) { >+ graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, >+ RenderingHints.VALUE_TEXT_ANTIALIAS_ON); >+ } >+ if (qualityRendering) { >+ graphics.setRenderingHint(RenderingHints.KEY_RENDERING, >+ RenderingHints.VALUE_RENDER_QUALITY); >+ } > > // transform page based on scale factor supplied > AffineTransform at = graphics.getTransform(); >@@ -311,47 +410,29 @@ > graphics.drawLine(0, pageHeight + 2, pageWidth + 2, pageHeight + 2); > graphics.drawLine(1, pageHeight + 3, pageWidth + 3, pageHeight + 3); > >+ // reset the current Positions >+ currentBPPosition = 0; >+ currentIPPosition = 0; >+ > renderPageAreas(page); > return currentPageImage; > } > > /** >- * Handle the traits for a region >- * This is used to draw the traits for the given page region. >- * (See Sect. 6.4.1.2 of XSL-FO spec.) >- * @param region the RegionViewport whose region is to be drawn >- */ >- protected void handleRegionTraits(RegionViewport region) { >- Rectangle2D viewArea = region.getViewArea(); >- >- int startX = (int) Math.round((viewArea.getX() / 1000f) >- * (scaleFactor / 100f)); >- int startY = (int) Math.round((viewArea.getY() / 1000f) >- * (scaleFactor / 100f)); >- // for rounding to work correctly, need to take into account >- // fractional portion of X and Y. >- int width = (int) Math.round(((viewArea.getX() + viewArea.getWidth()) / 1000f) >- * (scaleFactor / 100f)) - startX; >- int height = (int) Math.round(((viewArea.getY() + viewArea.getHeight()) / 1000f) >- * (scaleFactor / 100f)) - startY; >- >- if (region.getRegion() != null) { >- System.out.print("\nRegion type = " + region.getRegion().getRegionClass()); >- } >- >- System.out.println(" X, Width, Y, Height: " + startX >- + " " + width >- + " " + startY >- + " " + height >- ); >- >- drawBackAndBorders(region, startX, startY, width, height); >+ * @see org.apache.fop.render.AbstractRenderer#startVParea(CTM) >+ */ >+ protected void startVParea(CTM ctm) { >+ >+ // Uses the x shift (param e) and y shift (param f) >+ // of the CTM to update the current Positions >+ currentIPPosition += (int) ctm.getXShift(); >+ currentBPPosition += (int) ctm.getYShift(); >+ // TODO is this supporting other writing modes? > } > > /** >- * Draw the background and borders. >- * This draws the background and border traits for an area given >- * the position. >+ * Draw the background and borders. This draws the background and border >+ * traits for an area given the position. > * > * @param block the area to get the traits from > * @param startx the start x position >@@ -359,107 +440,233 @@ > * @param width the width of the area > * @param height the height of the area > */ >- protected void drawBackAndBorders(Area block, >- int startx, int starty, >- int width, int height) { >+ protected void drawBackAndBorders(Area area, float startx, float starty, >+ float width, float height) { >+ // TODO put in AbstractRenderer and call drawBackground() >+ // and drawBorders() >+ >+ BorderProps bpsBefore = (BorderProps) area >+ .getTrait(Trait.BORDER_BEFORE); >+ BorderProps bpsAfter = (BorderProps) area.getTrait(Trait.BORDER_AFTER); >+ BorderProps bpsStart = (BorderProps) area.getTrait(Trait.BORDER_START); >+ BorderProps bpsEnd = (BorderProps) area.getTrait(Trait.BORDER_END); > >- // draw background then border >- Graphics2D graphics = currentPageImage.createGraphics(); >+ // draw background > Trait.Background back; >- back = (Trait.Background) block.getTrait(Trait.BACKGROUND); >+ back = (Trait.Background) area.getTrait(Trait.BACKGROUND); > if (back != null) { > >+ // Calculate padding rectangle >+ float sx = startx; >+ float sy = starty; >+ float paddRectWidth = width; >+ float paddRectHeight = height; >+ >+ if (bpsStart != null) { >+ sx += bpsStart.width / 1000f; >+ paddRectWidth -= bpsStart.width / 1000f; >+ } >+ if (bpsBefore != null) { >+ sy += bpsBefore.width / 1000f; >+ paddRectHeight -= bpsBefore.width / 1000f; >+ } >+ if (bpsEnd != null) { >+ paddRectWidth -= bpsEnd.width / 1000f; >+ } >+ if (bpsAfter != null) { >+ paddRectHeight -= bpsAfter.width / 1000f; >+ } >+ > if (back.getColor() != null) { >- graphics.setColor(back.getColor().getAWTColor()); >- graphics.fillRect(startx, starty, width, height); >+ drawBackground(back, sx, sy, paddRectWidth, paddRectHeight); > } >- if (back.getURL() != null) { // TODO: implement >- ImageFactory fact = ImageFactory.getInstance(); >- FopImage fopimage = fact.getImage(back.getURL(), userAgent); >+ >+ // background image >+ if (back.getFopImage() != null) { >+ FopImage fopimage = back.getFopImage(); > if (fopimage != null && fopimage.load(FopImage.DIMENSIONS)) { >- if (back.getRepeat() == EN_REPEAT) { >- // create a pattern for the image >- } else { >- // place once >- Rectangle2D pos; >- pos = new Rectangle2D.Float((startx + back.getHoriz()) * 1000, >- (starty + back.getVertical()) * 1000, >- fopimage.getWidth() * 1000, >- fopimage.getHeight() * 1000); >-// putImage(back.getURL(), pos); >+ // TODO clip(sx, sy, paddRectWidth, paddRectHeight); >+ int horzCount = (int) ((paddRectWidth * 1000 / fopimage >+ .getIntrinsicWidth()) + 1.0f); >+ int vertCount = (int) ((paddRectHeight * 1000 / fopimage >+ .getIntrinsicHeight()) + 1.0f); >+ if (back.getRepeat() == EN_NOREPEAT) { >+ horzCount = 1; >+ vertCount = 1; >+ } else if (back.getRepeat() == EN_REPEATX) { >+ vertCount = 1; >+ } else if (back.getRepeat() == EN_REPEATY) { >+ horzCount = 1; >+ } >+ // change from points to millipoints >+ sx *= 1000; >+ sy *= 1000; >+ if (horzCount == 1) { >+ sx += back.getHoriz(); >+ } >+ if (vertCount == 1) { >+ sy += back.getVertical(); > } >+ for (int x = 0; x < horzCount; x++) { >+ for (int y = 0; y < vertCount; y++) { >+ // place once >+ Rectangle2D pos; >+ pos = new Rectangle2D.Float(sx >+ + (x * fopimage.getIntrinsicWidth()), sy >+ + (y * fopimage.getIntrinsicHeight()), >+ fopimage.getIntrinsicWidth(), fopimage >+ .getIntrinsicHeight()); >+ putImage(back.getURL(), pos); //TODO test >+ } >+ } >+ >+ } else { >+ getLogger().warn( >+ "Can't find background image: " + back.getURL()); > } > } > } > >- BorderProps bps = (BorderProps) block.getTrait(Trait.BORDER_BEFORE); >+ // draw border //TODO not touched, maybe better implemented in pdf? >+ // -->to be tested >+ BorderProps bps = (BorderProps) area.getTrait(Trait.BORDER_BEFORE); > if (bps != null) { >- int borderWidth = (int) Math.round((bps.width / 1000f) * (scaleFactor / 100f)); >+ int borderWidth = (int) Math.round((bps.width / 1000f) >+ * (scaleFactor / 100f)); > graphics.setColor(bps.color.getAWTColor()); >- graphics.fillRect(startx, starty, width, borderWidth); >+ graphics.fillRect((int) startx, (int) starty, (int) width, >+ borderWidth); > } >- bps = (BorderProps) block.getTrait(Trait.BORDER_AFTER); >+ bps = (BorderProps) area.getTrait(Trait.BORDER_AFTER); > if (bps != null) { >- int borderWidth = (int) Math.round((bps.width / 1000f) * (scaleFactor / 100f)); >- int sy = starty + height; >+ int borderWidth = (int) Math.round((bps.width / 1000f) >+ * (scaleFactor / 100f)); >+ float sy = starty + height; > graphics.setColor(bps.color.getAWTColor()); >- graphics.fillRect(startx, starty + height - borderWidth, >- width, borderWidth); >+ graphics.fillRect((int) startx, >+ (int) (starty + height - borderWidth), (int) width, >+ borderWidth); > } >- bps = (BorderProps) block.getTrait(Trait.BORDER_START); >+ bps = (BorderProps) area.getTrait(Trait.BORDER_START); > if (bps != null) { >- int borderWidth = (int) Math.round((bps.width / 1000f) * (scaleFactor / 100f)); >+ int borderWidth = (int) Math.round((bps.width / 1000f) >+ * (scaleFactor / 100f)); > graphics.setColor(bps.color.getAWTColor()); >- graphics.fillRect(startx, starty, borderWidth, height); >+ graphics.fillRect((int) startx, (int) starty, borderWidth, >+ (int) height); > } >- bps = (BorderProps) block.getTrait(Trait.BORDER_END); >+ bps = (BorderProps) area.getTrait(Trait.BORDER_END); > if (bps != null) { >- int borderWidth = (int) Math.round((bps.width / 1000f) * (scaleFactor / 100f)); >- int sx = startx + width; >+ int borderWidth = (int) Math.round((bps.width / 1000f) >+ * (scaleFactor / 100f)); >+ float sx = startx + width; > graphics.setColor(bps.color.getAWTColor()); >- graphics.fillRect(startx + width - borderWidth, starty, >- borderWidth, height); >+ graphics.fillRect((int) (startx + width - borderWidth), >+ (int) starty, borderWidth, (int) height); > } >- >+ > } >- >+ >+ /** >+ * Draw the Background Rectangle of a given area. >+ * >+ * @param back the Trait.Background >+ * @param sx x coordinate of the rectangle to be filled. >+ * @param sy y the y coordinate of the rectangle to be filled. >+ * @param paddRectWidth the width of the rectangle to be filled. >+ * @param paddRectHeight the height of the rectangle to be filled. >+ */ >+ protected void drawBackground(Trait.Background back, float sx, float sy, >+ float paddRectWidth, float paddRectHeight) { >+ >+ graphics.setColor(back.getColor().getAWTColor()); >+ graphics.fillRect((int) sx, (int) sy, (int) paddRectWidth, >+ (int) paddRectHeight); >+ } >+ >+ /** >+ * Handle block traits. The block could be any sort of block with any >+ * positioning so this should render the traits such as border and >+ * background in its position. >+ * >+ * @param block the block to render the traits >+ */ >+ protected void handleBlockTraits(Block block) { >+ // TODO only copied from pdf >+ // TODO check and try to put in AbstractRenderer >+ int borderPaddingStart = block.getBorderAndPaddingWidthStart(); >+ int borderPaddingBefore = block.getBorderAndPaddingWidthBefore(); >+ >+ float startx = currentIPPosition / 1000f; >+ float starty = currentBPPosition / 1000f; >+ float width = block.getIPD() / 1000f; >+ float height = block.getBPD() / 1000f; >+ >+ startx += block.getStartIndent() / 1000f; >+ startx -= block.getBorderAndPaddingWidthStart() / 1000f; >+ width += borderPaddingStart / 1000f; >+ width += block.getBorderAndPaddingWidthEnd() / 1000f; >+ height += borderPaddingBefore / 1000f; >+ height += block.getBorderAndPaddingWidthAfter() / 1000f; >+ >+ drawBackAndBorders(block, startx, starty, width, height); >+ } >+ > /** > * @see org.apache.fop.render.Renderer#renderText(TextArea) > */ > public void renderText(TextArea text) { >- System.out.println("In render text: " + text.getTextArea()); > >- Graphics2D graphics = currentPageImage.createGraphics(); >+ float x = currentIPPosition / 1000f; >+ float y = (currentBPPosition + text.getOffset()) / 1000f; // baseline >+ >+ updateColor(text); >+ updateFont(text); >+ String s = text.getTextArea(); >+ graphics.drawString(s, x, y); >+ >+ getLogger().debug( >+ s + " cX " + currentIPPosition + "curY" + currentBPPosition >+ + " x " + x + " y " + y); >+ >+ // rendering text decorations //TODO refactorize > String fontName = (String) text.getTrait(Trait.FONT_NAME); > int size = ((Integer) text.getTrait(Trait.FONT_SIZE)).intValue(); >-// Typeface f = (Typeface) fontInfo.getFonts().get(fontName); >- ColorType ct = (ColorType) text.getTrait(Trait.COLOR); >+ FontMetrics metrics = fontInfo.getMetricsFor(fontName); >+ Font fs = new Font(fontName, metrics, size); >+ super.renderTextDecoration(fs, text, (currentBPPosition + text >+ .getOffset()), currentIPPosition); >+ renderTextDecoration(fs, text, (int) y, (int) x); > >- FontMetricsMapper mapper = (FontMetricsMapper) >- fontInfo.getMetricsFor(fontName); >- if (mapper == null) { >- mapper = new FontMetricsMapper("MonoSpaced", java.awt.Font.PLAIN, >- graphics); >- } >- >-// graphics.setColor(ct.getAWTColor()); >-// graphics.setFont(mapper.getFont(size)); >- graphics.setColor(java.awt.Color.black); >- graphics.setFont(new java.awt.Font("monospaced", java.awt.Font.PLAIN, >- 10)); >- >- int rx = currentIPPosition; >- int bl = currentBPPosition + text.getOffset(); >- >- int newx = (int) (rx + 500) / 1000; >- int newy = (int) (pageHeight - (bl + 500) / 1000); >- >- String s = text.getTextArea(); >-// graphics.drawString(s, newx, newy); >- graphics.drawString(s, 220, 200); >+ super.renderText(text); >+ } > >- // TODO: render text decorations >- currentIPPosition += text.getAllocIPD(); >+ /** >+ * @see org.apache.fop.render.Renderer#renderCharacter(Character) >+ */ >+ public void renderCharacter(Character ch) { >+ >+ float x = currentIPPosition / 1000f; >+ float y = (currentBPPosition + ch.getOffset()) / 1000f; // baseline >+ >+ updateColor(ch); >+ updateFont(ch); >+ String s = ch.getChar(); >+ graphics.drawString(s, x, y); >+ >+ getLogger().debug( >+ s + " cX " + currentIPPosition + "curY" + currentBPPosition); >+ >+ // rendering text decorations //TODO refactorize >+ String fontName = (String) ch.getTrait(Trait.FONT_NAME); >+ int size = ((Integer) ch.getTrait(Trait.FONT_SIZE)).intValue(); >+ FontMetrics metrics = fontInfo.getMetricsFor(fontName); >+ Font fs = new Font(fontName, metrics, size); >+ super.renderTextDecoration(fs, ch, >+ (currentBPPosition + ch.getOffset()), currentIPPosition); >+ renderTextDecoration(fs, ch, (int) y, (int) x); >+ >+ super.renderCharacter(ch); > } > > /** @see org.apache.fop.render.AbstractRenderer */ >@@ -467,4 +674,398 @@ > return MIME_TYPE; > } > >+ /** >+ * Render leader area. This renders a leader area which is an area with a >+ * rule. >+ * >+ * @param area the leader area to render >+ */ >+ public void renderLeader(Leader area) { >+ >+ // TODO leader-length: 25%, 50%, 75%, 100% not working yet >+ >+ float startx = ((float) currentIPPosition) / 1000f; >+ float starty = ((currentBPPosition + area.getOffset()) / 1000f); >+ float endx = (currentIPPosition + area.getIPD()) / 1000f; >+ >+ updateColor(area); >+ >+ Line2D.Float leader = new Line2D.Float(startx, starty, endx, starty); >+ float thickness = area.getRuleThickness() / 1000f; >+ >+ int style = area.getRuleStyle(); >+ switch (style) { >+ case EN_SOLID: >+ case EN_DOTTED: >+ case EN_DASHED: >+ updateLineWidth(thickness); >+ updateLineStyle(style); >+ graphics.draw(leader); >+ break; >+ case EN_DOUBLE: >+ updateLineWidth(thickness / 3f); // only a third >+ updateLineStyle(EN_SOLID); >+ >+ Line2D.Float upperLeader = new Line2D.Float(startx, starty, endx, >+ starty); >+ graphics.draw(upperLeader); >+ Line2D.Float lowerLeader = new Line2D.Float(startx, starty + 2 >+ * thickness, endx, starty + 2 * thickness); >+ graphics.draw(lowerLeader); >+ break; >+ case EN_GROOVE: >+ // The rule looks as though it were carved into the canvas. >+ // (Top/left half of the rule's thickness is the >+ // color specified; the other half is white.) >+ >+ updateLineWidth(thickness / 2f); // only the half >+ updateLineStyle(EN_SOLID); >+ >+ Line2D.Float upperLeader2 = new Line2D.Float(startx, starty, endx, >+ starty); >+ graphics.draw(upperLeader2); >+ Line2D.Float lowerLeader2 = new Line2D.Float(startx, starty >+ + thickness, endx, starty + thickness); >+ graphics.setColor(Color.WHITE); >+ graphics.draw(lowerLeader2); >+ // TODO the implementation could be nicer, f.eg. with triangles at >+ // the tip of the lines. See also RenderX's implementation (looks >+ // like a button) >+ break; >+ case EN_RIDGE: >+ // The opposite of "groove", the rule looks as though it were >+ // coming out of the canvas. (Bottom/right half of the rule's >+ // thickness is the color specified; the other half is white.) >+ >+ updateLineWidth(thickness / 2f); // only the half >+ updateLineStyle(EN_SOLID); >+ >+ Line2D.Float lowerLeader3 = new Line2D.Float(startx, starty >+ + thickness, endx, starty + thickness); >+ graphics.draw(lowerLeader3); >+ Line2D.Float upperLeader3 = new Line2D.Float(startx, starty, endx, >+ starty); >+ graphics.setColor(Color.WHITE); >+ graphics.draw(upperLeader3); >+ // TODO the implementation could be nicer, f.eg. with triangles at >+ // the tip of the lines. See also RenderX's implementation (looks >+ // like a button) >+ break; >+ case EN_NONE: >+ // No rule is drawn >+ break; >+ >+ } // end switch >+ >+ graphics.setStroke(basicStroke); // reset the stroke >+ >+ super.renderLeader(area); >+ } >+ >+ // TODO abstractize? >+ /** >+ * Converts a ColorType to a java.awt.Color (sRGB). >+ * >+ * @param col the color >+ * @return the converted color >+ */ >+ protected Color toColor(ColorType col) { >+ return new Color(col.getRed(), col.getGreen(), col.getBlue()); >+ } >+ >+ /** >+ * Establishes a new foreground or fill color. >+ * >+ * @param col the color to apply (null skips this operation) >+ * @param fill true to set the fill color, false for the foreground color >+ * @param pdf StringBuffer to write the PDF code to, if null, the code is >+ * written to the current stream. >+ */ >+ protected void updateColor(ColorType col, boolean fill, StringBuffer pdf) { >+ if (col == null) { >+ return; >+ } >+ Color newCol = toColor(col); >+ graphics.setColor(newCol); >+ } >+ >+ protected void updateColor(Area area) { >+ ColorType ct = (ColorType) area.getTrait(Trait.COLOR); >+ try { // FIXME there must be another way (that always works) >+ currentColor = ct.getAWTColor(); >+ } catch (Exception e) { >+ getLogger() >+ .warn( >+ "Can't find color: " + ct >+ + "color set by default to black"); >+ currentColor = java.awt.Color.black; >+ } >+ graphics.setColor(currentColor); >+ } >+ >+ protected void updateFont(String name, int size, StringBuffer pdf) { >+ if ((!name.equals(this.currentFontName)) >+ || (size != this.currentFontSize)) { >+ >+ // graphics.setFont(xxxx); //TODO >+ // this.currentFontName = name; >+ // this.currentFontSize = size; >+ } >+ } >+ >+ protected void updateFont(Area area) { >+ >+ // FIXME Fonts are not working properly yet >+ >+ String fontName = (String) area.getTrait(Trait.FONT_NAME); >+ int size = ((Integer) area.getTrait(Trait.FONT_SIZE)).intValue(); >+ >+ FontMetricsMapper mapper = (FontMetricsMapper) fontInfo >+ .getMetricsFor(fontName); >+ java.awt.Font font = mapper.getFont(size); >+ >+ // graphics.setFont(new java.awt.Font("SansSerif", java.awt.Font.PLAIN, >+ // (int)(size/1000f))); >+ graphics.setFont(font); >+ >+ } >+ >+ /** >+ * Sets the current line width in points. >+ * >+ * @param width line width in points >+ */ >+ protected void updateLineWidth(float width) { >+ this.currentLineWidth = width; >+ } >+ >+ /** >+ * Sets the current line style. The line width should be set with >+ * updateLineWidth() before calling this method >+ * >+ * @param style the constant for the style of the line as an int >+ */ >+ protected void updateLineStyle(int style) { >+ switch (style) { >+ case EN_DOTTED: >+ stroke = new BasicStroke(currentLineWidth, BasicStroke.CAP_BUTT, >+ BasicStroke.JOIN_BEVEL, 0f, new float[] { 2f }, 0f); >+ graphics.setStroke(stroke); >+ break; >+ case EN_DASHED: >+ stroke = new BasicStroke(currentLineWidth, BasicStroke.CAP_BUTT, >+ BasicStroke.JOIN_BEVEL, 0f, new float[] { 8f, 2f }, 0f); >+ graphics.setStroke(stroke); >+ break; >+ default: // EN_SOLID: >+ stroke = new BasicStroke(currentLineWidth); >+ graphics.setStroke(stroke); >+ break; >+ } >+ } >+ >+ /** >+ * Draw a line. >+ * >+ * @param startx the start x position >+ * @param starty the start y position >+ * @param endx the x end position >+ * @param endy the y end position >+ */ >+ protected void drawLine(float startx, float starty, float endx, float endy) { >+ graphics.draw(new Line2D.Float(startx, starty, endx, endy)); >+ } >+ >+ // TODO abstractize, or refactorize with putImage >+ /** >+ * @see org.apache.fop.render.AbstractRenderer#renderImage(Image, >+ * Rectangle2D) >+ */ >+ public void renderImage(Image image, Rectangle2D pos) { >+ endTextObject(); >+ String url = image.getURL(); >+ putImage(url, pos); >+ } >+ >+ /** >+ * Adds a PDF XObject (a bitmap) to the PDF that will later be referenced. >+ * >+ * @param url URL of the bitmap >+ * @param pos Position of the bitmap >+ */ >+ protected void putImage(String pUrl, Rectangle2D pos) { >+ >+ int x = currentIPPosition; // TODO + area.getXOffset(); >+ int y = currentBPPosition; >+ String url = ImageFactory.getURL(pUrl); >+ >+ ImageFactory fact = ImageFactory.getInstance(); >+ FopImage fopimage = fact.getImage(url, userAgent); >+ >+ if (fopimage == null) { >+ return; >+ } >+ if (!fopimage.load(FopImage.DIMENSIONS)) { >+ return; >+ } >+ int w = fopimage.getWidth(); >+ int h = fopimage.getHeight(); >+ String mime = fopimage.getMimeType(); >+ if ("text/xml".equals(mime)) { >+ if (!fopimage.load(FopImage.ORIGINAL_DATA)) { >+ return; >+ } >+ Document doc = ((XMLImage) fopimage).getDocument(); >+ String ns = ((XMLImage) fopimage).getNameSpace(); >+ renderDocument(doc, ns, pos); >+ >+ } else if ("image/svg+xml".equals(mime)) { >+ if (!fopimage.load(FopImage.ORIGINAL_DATA)) { >+ return; >+ } >+ Document doc = ((XMLImage) fopimage).getDocument(); >+ renderSVGDocument(doc, pos); // TODO check if ok. >+ >+ } else if (("image/eps".equals(mime)) || ("image/jpeg".equals(mime))) { >+ if (!fopimage.load(FopImage.ORIGINAL_DATA)) { >+ return; >+ } >+ java.awt.Image awtImage = new javax.swing.ImageIcon(url).getImage(); >+ graphics.drawImage(awtImage, (int) (x / 1000f), (int) (y / 1000f), >+ (int) w, h, null); >+ currentBPPosition += (h * 1000); // TODO doesn't work! >+ >+ } else if ("image/bmp".equals(mime)) { >+ if (!fopimage.load(FopImage.BITMAP)) { >+ return; >+ } >+ try { >+ java.awt.Image awtImage = new BMPReader().loadbitmap(url); >+ graphics.drawImage(awtImage, (int) (x / 1000f), >+ (int) (y / 1000f), (int) w, h, null); >+ } catch (Exception e) { >+ getLogger().warn(e); >+ } >+ currentBPPosition += (h * 1000); // TODO doesn't work! >+ >+ } else { >+ if (!fopimage.load(FopImage.BITMAP)) { >+ return; >+ } >+ java.awt.Image awtImage = new javax.swing.ImageIcon(url).getImage(); >+ graphics.drawImage(awtImage, (int) (x / 1000f), (int) (y / 1000f), >+ (int) w, h, null); >+ currentBPPosition += (h * 1000); // TODO doesn't work! >+ } >+ } >+ >+ /** >+ * @see org.apache.fop.render.AbstractRenderer#renderForeignObject(ForeignObject, >+ * Rectangle2D) >+ */ >+ public void renderForeignObject(ForeignObject fo, Rectangle2D pos) { >+ endTextObject(); >+ Document doc = fo.getDocument(); >+ String ns = fo.getNameSpace(); >+ if (ns.equals("http://www.w3.org/2000/svg")) { >+ // FIXME ren: is this the right way to do it? >+ renderSVGDocument(doc, pos); >+ } else { >+ renderDocument(doc, ns, pos); >+ } >+ // this.currentXPosition += area.getContentWidth(); TODO >+ } >+ >+ /** >+ * Renders an XML document (SVG for example). >+ * >+ * @param doc DOM document representing the XML document >+ * @param ns Namespace for the document >+ * @param pos Position on the page >+ */ >+ public void renderDocument(Document doc, String ns, Rectangle2D pos) { >+ RendererContext context; >+ context = new RendererContext(MIME_TYPE); >+ context.setUserAgent(userAgent); >+ // TODO implement >+ /* >+ * context.setProperty(PDFXMLHandler.PDF_DOCUMENT, pdfDoc); >+ * context.setProperty(PDFXMLHandler.OUTPUT_STREAM, ostream); >+ * context.setProperty(PDFXMLHandler.PDF_STATE, currentState); >+ * context.setProperty(PDFXMLHandler.PDF_PAGE, currentPage); >+ * context.setProperty(PDFXMLHandler.PDF_CONTEXT, currentContext == null ? >+ * currentPage : currentContext); >+ * context.setProperty(PDFXMLHandler.PDF_CONTEXT, currentContext); >+ * context.setProperty(PDFXMLHandler.PDF_STREAM, currentStream); >+ * context.setProperty(PDFXMLHandler.PDF_XPOS, new >+ * Integer(currentIPPosition + (int) pos.getX())); >+ * context.setProperty(PDFXMLHandler.PDF_YPOS, new >+ * Integer(currentBPPosition + (int) pos.getY())); >+ * context.setProperty(PDFXMLHandler.PDF_FONT_INFO, fontInfo); >+ * context.setProperty(PDFXMLHandler.PDF_FONT_NAME, currentFontName); >+ * context.setProperty(PDFXMLHandler.PDF_FONT_SIZE, new >+ * Integer(currentFontSize)); >+ * context.setProperty(PDFXMLHandler.PDF_WIDTH, new Integer((int) >+ * pos.getWidth())); context.setProperty(PDFXMLHandler.PDF_HEIGHT, new >+ * Integer((int) pos.getHeight())); renderXML(userAgent, context, doc, >+ * ns); >+ */ >+ } >+ >+ protected void renderSVGDocument(Document doc, Rectangle2D pos) { >+ >+ int x = currentIPPosition; // TODO + area.getXOffset(); >+ int y = currentBPPosition; >+ >+ RendererContext context; >+ context = new RendererContext(MIME_TYPE); >+ context.setUserAgent(userAgent); >+ >+ SVGUserAgent ua = new SVGUserAgent(context.getUserAgent() >+ .getPixelUnitToMillimeter(), new AffineTransform()); >+ >+ GVTBuilder builder = new GVTBuilder(); >+ BridgeContext ctx = new BridgeContext(ua); >+ >+ GraphicsNode root; >+ try { >+ root = builder.build(ctx, doc); >+ } catch (Exception e) { >+ getLogger().error( >+ "svg graphic could not be built: " + e.getMessage(), e); >+ return; >+ } >+ float w = (float) ctx.getDocumentSize().getWidth() * 1000f; >+ float h = (float) ctx.getDocumentSize().getHeight() * 1000f; >+ >+ // correct integer roundoff TODO ren: needed? >+ graphics.translate(x / 1000, y / 1000); >+ >+ SVGSVGElement svg = ((SVGDocument) doc).getRootElement(); >+ // TODO ren: do we need the whole at-stuff? >+ AffineTransform at = ViewBox.getPreserveAspectRatioTransform(svg, >+ w / 1000f, h / 1000f); >+ AffineTransform inverse = null; >+ try { >+ inverse = at.createInverse(); >+ } catch (NoninvertibleTransformException e) { >+ getLogger().warn(e); >+ } >+ if (!at.isIdentity()) { >+ graphics.transform(at); >+ } >+ >+ try { >+ root.paint(graphics); >+ } catch (Exception e) { >+ e.printStackTrace(); >+ } >+ >+ if (inverse != null && !inverse.isIdentity()) { >+ graphics.transform(inverse); >+ } >+ // correct integer roundoff TODO ren: needed? >+ // graphics.translate(-x / 1000f, y / 1000f - pageHeight); >+ graphics.translate(-(x + 500) / 1000, (y + 500) / 1000 - pageHeight); >+ } > } >Index: src/java/org/apache/fop/render/pdf/PDFRenderer.java >=================================================================== >RCS file: /home/cvspublic/xml-fop/src/java/org/apache/fop/render/pdf/PDFRenderer.java,v >retrieving revision 1.81 >diff -u -r1.81 PDFRenderer.java >--- src/java/org/apache/fop/render/pdf/PDFRenderer.java 16 Feb 2005 10:15:45 -0000 1.81 >+++ src/java/org/apache/fop/render/pdf/PDFRenderer.java 28 Feb 2005 02:07:06 -0000 >@@ -19,49 +19,42 @@ > package org.apache.fop.render.pdf; > > // Java >-import java.io.IOException; >-import java.io.OutputStream; > import java.awt.Color; >-import java.awt.geom.Rectangle2D; > import java.awt.geom.AffineTransform; >+import java.awt.geom.Rectangle2D; >+import java.io.IOException; >+import java.io.OutputStream; > import java.util.Iterator; >-import java.util.Map; > import java.util.List; >+import java.util.Map; > >-// XML >-import org.w3c.dom.Document; >- >-// Avalon > import org.apache.avalon.framework.configuration.Configuration; > import org.apache.avalon.framework.configuration.ConfigurationException; >- >-// FOP > import org.apache.fop.apps.FOPException; > import org.apache.fop.apps.FOUserAgent; > import org.apache.fop.area.Area; > import org.apache.fop.area.Block; > import org.apache.fop.area.BlockViewport; >+import org.apache.fop.area.BookmarkData; > import org.apache.fop.area.CTM; > import org.apache.fop.area.LineArea; >+import org.apache.fop.area.OffDocumentItem; > import org.apache.fop.area.Page; > import org.apache.fop.area.PageViewport; >-import org.apache.fop.area.RegionViewport; > import org.apache.fop.area.Trait; >-import org.apache.fop.area.OffDocumentItem; >-import org.apache.fop.area.BookmarkData; > import org.apache.fop.area.inline.Character; >-import org.apache.fop.area.inline.InlineArea; >-import org.apache.fop.area.inline.TextArea; >-import org.apache.fop.area.inline.Viewport; > import org.apache.fop.area.inline.ForeignObject; > import org.apache.fop.area.inline.Image; >-import org.apache.fop.area.inline.Leader; > import org.apache.fop.area.inline.InlineParent; >+import org.apache.fop.area.inline.Leader; >+import org.apache.fop.area.inline.TextArea; >+import org.apache.fop.area.inline.Viewport; > import org.apache.fop.datatypes.ColorType; >-import org.apache.fop.fonts.Typeface; >+import org.apache.fop.fo.Constants; > import org.apache.fop.fonts.Font; >-import org.apache.fop.fonts.FontSetup; > import org.apache.fop.fonts.FontMetrics; >+import org.apache.fop.fonts.FontSetup; >+import org.apache.fop.fonts.Typeface; > import org.apache.fop.image.FopImage; > import org.apache.fop.image.ImageFactory; > import org.apache.fop.image.XMLImage; >@@ -83,7 +76,7 @@ > import org.apache.fop.render.PrintRenderer; > import org.apache.fop.render.RendererContext; > import org.apache.fop.traits.BorderProps; >-import org.apache.fop.fo.Constants; >+import org.w3c.dom.Document; > > > /* >@@ -103,7 +96,7 @@ > * > */ > public class PDFRenderer extends PrintRenderer { >- >+ > /** > * The mime type for pdf > */ >@@ -111,7 +104,7 @@ > > /** Controls whether comments are written to the PDF stream. */ > protected static final boolean WRITE_COMMENTS = true; >- >+ > /** > * the PDF Document being created > */ >@@ -162,8 +155,6 @@ > /** drawing state */ > protected PDFState currentState = null; > >- /** Name of currently selected font */ >- protected String currentFontName = ""; > /** Size of currently selected font */ > protected int currentFontSize = 0; > /** page height */ >@@ -178,7 +169,7 @@ > protected boolean textOpen = false; > > /** >- * true if a BT command has been written. >+ * true if a BT command has been written. > */ > protected boolean inTextMode = false; > >@@ -313,7 +304,7 @@ > } > } > >- private void renderBookmarkItem(BookmarkData bookmarkItem, >+ private void renderBookmarkItem(BookmarkData bookmarkItem, > PDFOutline parentBookmarkItem) { > PDFOutline pdfOutline = null; > PageViewport pv = bookmarkItem.getPageViewport(); >@@ -325,13 +316,13 @@ > if (parentBookmarkItem == null) { > PDFOutline outlineRoot = pdfDoc.getOutlineRoot(); > pdfOutline = pdfDoc.getFactory().makeOutline(outlineRoot, >- bookmarkItem.getBookmarkTitle(), >+ bookmarkItem.getBookmarkTitle(), > intDest, yoffset, > bookmarkItem.showChildItems()); > } else { > pdfOutline = pdfDoc.getFactory().makeOutline(parentBookmarkItem, >- bookmarkItem.getBookmarkTitle(), >- intDest, yoffset, >+ bookmarkItem.getBookmarkTitle(), >+ intDest, yoffset, > bookmarkItem.showChildItems()); > } > } >@@ -340,8 +331,8 @@ > renderBookmarkItem(bookmarkItem.getSubData(i), pdfOutline); > } > } >- >- /** >+ >+ /** > * writes out a comment. > * @param text text for the comment > */ >@@ -463,8 +454,8 @@ > // Transform origin at top left to origin at bottom left > currentStream.add("1 0 0 -1 0 " > + (int) Math.round(pageHeight / 1000) + " cm\n"); >- >- >+ >+ > currentFontName = ""; > > Page p = page.getPage(); >@@ -484,6 +475,12 @@ > * @see org.apache.fop.render.AbstractRenderer#startVParea(CTM) > */ > protected void startVParea(CTM ctm) { >+ // The CTM will transform coordinates relative to >+ // this region-reference area into page coords, so >+ // set origin for the region to 0,0. >+ currentIPPosition = 0; >+ currentBPPosition = 0; >+ > // Set the given CTM in the graphics state > currentState.push(); > currentState.setTransform( >@@ -503,26 +500,6 @@ > currentState.pop(); > } > >- /** >- * Handle the traits for a region >- * This is used to draw the traits for the given page region. >- * (See Sect. 6.4.1.2 of XSL-FO spec.) >- * @param region the RegionViewport whose region is to be drawn >- */ >- protected void handleRegionTraits(RegionViewport region) { >- currentFontName = ""; >- Rectangle2D viewArea = region.getViewArea(); >- float startx = (float)(viewArea.getX() / 1000f); >- float starty = (float)(viewArea.getY() / 1000f); >- float width = (float)(viewArea.getWidth() / 1000f); >- float height = (float)(viewArea.getHeight() / 1000f); >- >- if (region.getRegion().getRegionClass() == FO_REGION_BODY) { >- currentBPPosition = region.getBorderAndPaddingWidthBefore(); >- currentIPPosition = region.getBorderAndPaddingWidthStart(); >- } >- drawBackAndBorders(region, startx, starty, width, height); >- } > > /** > * Handle block traits. >@@ -535,7 +512,7 @@ > protected void handleBlockTraits(Block block) { > int borderPaddingStart = block.getBorderAndPaddingWidthStart(); > int borderPaddingBefore = block.getBorderAndPaddingWidthBefore(); >- >+ > float startx = currentIPPosition / 1000f; > float starty = currentBPPosition / 1000f; > float width = block.getIPD() / 1000f; >@@ -615,10 +592,10 @@ > if (fopimage != null && fopimage.load(FopImage.DIMENSIONS)) { > saveGraphicsState(); > clip(sx, sy, paddRectWidth, paddRectHeight); >- int horzCount = (int)((paddRectWidth >- * 1000 / fopimage.getIntrinsicWidth()) + 1.0f); >- int vertCount = (int)((paddRectHeight >- * 1000 / fopimage.getIntrinsicHeight()) + 1.0f); >+ int horzCount = (int)((paddRectWidth >+ * 1000 / fopimage.getIntrinsicWidth()) + 1.0f); >+ int vertCount = (int)((paddRectHeight >+ * 1000 / fopimage.getIntrinsicHeight()) + 1.0f); > if (back.getRepeat() == EN_NOREPEAT) { > horzCount = 1; > vertCount = 1; >@@ -647,7 +624,7 @@ > putImage(back.getURL(), pos); > } > } >- >+ > restoreGraphicsState(); > } else { > getLogger().warn("Can't find background image: " + back.getURL()); >@@ -656,7 +633,7 @@ > } > > boolean b[] = new boolean[] { >- (bpsBefore != null), (bpsEnd != null), >+ (bpsBefore != null), (bpsEnd != null), > (bpsAfter != null), (bpsStart != null)}; > if (!b[0] && !b[1] && !b[2] && !b[3]) { > return; >@@ -667,9 +644,9 @@ > (b[2] ? bpsAfter.width / 1000f : 0.0f), > (b[3] ? bpsStart.width / 1000f : 0.0f)}; > float clipw[] = new float[] { >- BorderProps.getClippedWidth(bpsBefore) / 1000f, >- BorderProps.getClippedWidth(bpsEnd) / 1000f, >- BorderProps.getClippedWidth(bpsAfter) / 1000f, >+ BorderProps.getClippedWidth(bpsBefore) / 1000f, >+ BorderProps.getClippedWidth(bpsEnd) / 1000f, >+ BorderProps.getClippedWidth(bpsAfter) / 1000f, > BorderProps.getClippedWidth(bpsStart) / 1000f}; > starty += clipw[0]; > height -= clipw[0]; >@@ -677,7 +654,7 @@ > startx += clipw[3]; > width -= clipw[3]; > width -= clipw[1]; >- >+ > boolean slant[] = new boolean[] { > (b[3] && b[0]), (b[0] && b[1]), (b[1] && b[2]), (b[2] && b[3])}; > if (bpsBefore != null) { >@@ -723,7 +700,7 @@ > float outerx = startx + width + clipw[1]; > float clipx = outerx - clipw[1]; > float innerx = outerx - bw[1]; >- >+ > saveGraphicsState(); > moveTo(clipx, sy1); > float sy1a = sy1; >@@ -785,7 +762,7 @@ > float sy1 = starty; > float sy2 = (slant[0] ? sy1 + bw[0] - clipw[0] : sy1); > float ey1 = sy1 + height; >- float ey2 = (slant[3] ? ey1 - bw[2] + clipw[2]: ey1); >+ float ey2 = (slant[3] ? ey1 - bw[2] + clipw[2] : ey1); > float outerx = startx - clipw[3]; > float clipx = outerx + clipw[3]; > float innerx = outerx + bw[3]; >@@ -813,7 +790,7 @@ > restoreGraphicsState(); > } > } >- >+ > private Color lightenColor(Color col, float factor) { > float[] cols = new float[3]; > cols = col.getColorComponents(cols); >@@ -829,7 +806,7 @@ > return new Color(cols[0], cols[1], cols[2]); > } > >- private void drawBorderLine(float x1, float y1, float x2, float y2, >+ private void drawBorderLine(float x1, float y1, float x2, float y2, > boolean horz, boolean startOrBefore, int style, ColorType col) { > float w = x2 - x1; > float h = y2 - y1; >@@ -838,7 +815,7 @@ > return; > } > switch (style) { >- case Constants.EN_DASHED: >+ case Constants.EN_DASHED: > setColor(toColor(col), false, null); > if (horz) { > float unit = Math.abs(2 * h); >@@ -980,19 +957,22 @@ > } > } > } >- >+ > /** > * Sets the current line width in points. > * @param width line width in points > */ >- private void updateLineWidth(float width) { >+ protected void updateLineWidth(float width) { > if (currentState.setLineWidth(width)) { > //Only write if value has changed WRT the current line width > currentStream.add(width + " w\n"); > } > } >- >- private void updateLineStyle(int style) { >+ >+ /** >+ * @see org.apache.fop.render.AbstractRenderer#updateLineStyle(int) >+ */ >+ protected void updateLineStyle(int style) { > switch (style) { > case Constants.EN_DASHED: > currentStream.add("[3] 0 d\n"); >@@ -1008,32 +988,32 @@ > } > > /** >- * Moves the current point to (x, y), omitting any connecting line segment. >+ * Moves the current point to (x, y), omitting any connecting line segment. > * @param x x coordinate > * @param y y coordinate > */ > private void moveTo(float x, float y) { > currentStream.add(x + " " + y + " m "); > } >- >+ > /** >- * Appends a straight line segment from the current point to (x, y). The >- * new current point is (x, y). >+ * Appends a straight line segment from the current point to (x, y). The >+ * new current point is (x, y). > * @param x x coordinate > * @param y y coordinate > */ > private void lineTo(float x, float y) { > currentStream.add(x + " " + y + " l "); > } >- >+ > /** >- * Closes the current subpath by appending a straight line segment from >+ * Closes the current subpath by appending a straight line segment from > * the current point to the starting point of the subpath. > */ > private void closePath() { > currentStream.add("h "); > } >- >+ > /** > * Draw a line. > * >@@ -1042,7 +1022,7 @@ > * @param endx the x end position > * @param endy the y end position > */ >- private void drawLine(float startx, float starty, float endx, float endy) { >+ protected void drawLine(float startx, float starty, float endx, float endy) { > currentStream.add(startx + " " + starty + " m "); > currentStream.add(endx + " " + endy + " l S\n"); > } >@@ -1089,14 +1069,14 @@ > restoreGraphicsState(); > } > } >- >+ > CTM tempctm = new CTM(containingIPPosition, containingBPPosition); > ctm = tempctm.multiply(ctm); > > //This is the content-rect > float width = (float)bv.getIPD() / 1000f; > float height = (float)bv.getBPD() / 1000f; >- >+ > //Adjust for spaces (from margin or indirectly by start-indent etc. > Integer spaceStart = (Integer) bv.getTrait(Trait.SPACE_START); > if (spaceStart != null) { >@@ -1115,7 +1095,7 @@ > //Now adjust for border/padding > x += borderPaddingStart / 1000f; > y += borderPaddingBefore / 1000f; >- >+ > if (bv.getClip()) { > saveGraphicsState(); > clip(x, y, width, height); >@@ -1123,9 +1103,6 @@ > > startVParea(ctm); > >- currentIPPosition = 0; >- currentBPPosition = 0; >- > renderBlocks(bv, children); > endVParea(); > >@@ -1151,7 +1128,7 @@ > currentState.setTransform(at); > double[] matrix = new double[6]; > at.getMatrix(matrix); >- tempctm = new CTM(matrix[0], matrix[1], matrix[2], matrix[3], >+ tempctm = new CTM(matrix[0], matrix[1], matrix[2], matrix[3], > matrix[4] * 1000, matrix[5] * 1000); > currentStream.add(CTMHelper.toPDFString(tempctm) + " cm\n"); > } >@@ -1162,7 +1139,7 @@ > } > comment("------ done."); > } >- >+ > currentIPPosition = saveIP; > currentBPPosition = saveBP; > } else { >@@ -1177,7 +1154,7 @@ > > CTM tempctm = new CTM(containingIPPosition, currentBPPosition + containingBPPosition); > ctm = tempctm.multiply(ctm); >- >+ > //Now adjust for border/padding > x += borderPaddingStart / 1000f; > y += borderPaddingBefore / 1000f; >@@ -1192,8 +1169,6 @@ > > if (ctm != null) { > startVParea(ctm); >- currentIPPosition = 0; >- currentBPPosition = 0; > } > renderBlocks(bv, children); > if (ctm != null) { >@@ -1206,7 +1181,7 @@ > > currentIPPosition = saveIP; > currentBPPosition = saveBP; >- >+ > //Adjust BP position (alloc BPD + spaces) > if (spaceBefore != null) { > currentBPPosition += spaceBefore.intValue(); >@@ -1367,7 +1342,7 @@ > currentStream.add(pdf.toString()); > > renderTextDecoration(fs, ch, bl, rx); >- >+ > super.renderCharacter(ch); > } > >@@ -1380,7 +1355,7 @@ > > String name = (String) text.getTrait(Trait.FONT_NAME); > int size = ((Integer) text.getTrait(Trait.FONT_SIZE)).intValue(); >- >+ > // This assumes that *all* CIDFonts use a /ToUnicode mapping > Typeface f = (Typeface) fontInfo.getFonts().get(name); > boolean useMultiByte = f.isMultiByte(); >@@ -1429,7 +1404,7 @@ > prevWordX = rx; > > String s = text.getTextArea(); >- >+ System.out.println(s + " currXPos " + rx + " currYPos " + bl); > FontMetrics metrics = fontInfo.getMetricsFor(name); > Font fs = new Font(name, metrics, size); > escapeText(s, fs, useMultiByte, pdf); >@@ -1438,47 +1413,9 @@ > currentStream.add(pdf.toString()); > > renderTextDecoration(fs, text, bl, rx); >- >+ > super.renderText(text); > } >- >- /** >- * Paints the text decoration marks. >- * @param fs Current font >- * @param inline inline area to paint the marks for >- * @param baseline position of the baseline >- * @param startx start IPD >- */ >- protected void renderTextDecoration(Font fs, InlineArea inline, >- int baseline, int startx) { >- boolean hasTextDeco = inline.hasUnderline() >- || inline.hasOverline() >- || inline.hasLineThrough(); >- if (hasTextDeco) { >- endTextObject(); >- updateLineStyle(Constants.EN_SOLID); >- updateLineWidth(fs.getDescender() / -8 / 1000f); >- float endx = (startx + inline.getIPD()) / 1000f; >- if (inline.hasUnderline()) { >- ColorType ct = (ColorType) inline.getTrait(Trait.UNDERLINE_COLOR); >- updateColor(ct, false, null); >- float y = baseline - fs.getDescender() / 2; >- drawLine(startx / 1000f, y / 1000f, endx, y / 1000f); >- } >- if (inline.hasOverline()) { >- ColorType ct = (ColorType) inline.getTrait(Trait.OVERLINE_COLOR); >- updateColor(ct, false, null); >- float y = (float)(baseline - (1.1 * fs.getCapHeight())); >- drawLine(startx / 1000f, y / 1000f, endx, y / 1000f); >- } >- if (inline.hasLineThrough()) { >- ColorType ct = (ColorType) inline.getTrait(Trait.LINETHROUGH_COLOR); >- updateColor(ct, false, null); >- float y = (float)(baseline - (0.45 * fs.getCapHeight())); >- drawLine(startx / 1000f, y / 1000f, endx, y / 1000f); >- } >- } >- } > > /** > * Escapes text according to PDF rules. >@@ -1559,7 +1496,7 @@ > /** > * Establishes a new foreground or fill color. In contrast to updateColor > * this method does not check the PDFState for optimization possibilities. >- * @param col the color to apply >+ * @param col the color to apply > * @param fill true to set the fill color, false for the foreground color > * @param pdf StringBuffer to write the PDF code to, if null, the code is > * written to the current stream. >@@ -1568,14 +1505,14 @@ > PDFColor color = new PDFColor(col); > > closeText(); >- >+ > if (pdf != null) { > pdf.append(color.getColorSpaceOut(fill)); > } else { > currentStream.add(color.getColorSpaceOut(fill)); > } > } >- >+ > /** > * Converts a ColorType to a java.awt.Color (sRGB). > * @param col the color >@@ -1584,7 +1521,7 @@ > private Color toColor(ColorType col) { > return new Color(col.getRed(), col.getGreen(), col.getBlue()); > } >- >+ > /** > * Establishes a new foreground or fill color. > * @param col the color to apply (null skips this operation) >@@ -1592,7 +1529,7 @@ > * @param pdf StringBuffer to write the PDF code to, if null, the code is > * written to the current stream. > */ >- private void updateColor(ColorType col, boolean fill, StringBuffer pdf) { >+ protected void updateColor(ColorType col, boolean fill, StringBuffer pdf) { > if (col == null) { > return; > } >@@ -1725,7 +1662,7 @@ > currentStream.add(w + " 0 0 " > + -h + " " > + (currentIPPosition / 1000f + x) + " " >- + (currentBPPosition / 1000f + h + y) >+ + (currentBPPosition / 1000f + h + y) > + " cm\n" + "/Im" + xobj + " Do\n"); > restoreGraphicsState(); > } >@@ -1786,7 +1723,7 @@ > float y = (currentBPPosition + viewport.getOffset()) / 1000f; > float width = viewport.getIPD() / 1000f; > float height = viewport.getBPD() / 1000f; >- // TODO: Calculate the border rect correctly. >+ // TODO Calculate the border rect correctly. > drawBackAndBorders(viewport, x, y, width, height); > > if (viewport.getClip()) { >Index: src/java/org/apache/fop/render/ps/PSRenderer.java >=================================================================== >RCS file: /home/cvspublic/xml-fop/src/java/org/apache/fop/render/ps/PSRenderer.java,v >retrieving revision 1.36 >diff -u -r1.36 PSRenderer.java >--- src/java/org/apache/fop/render/ps/PSRenderer.java 6 Feb 2005 20:48:48 -0000 1.36 >+++ src/java/org/apache/fop/render/ps/PSRenderer.java 28 Feb 2005 02:07:09 -0000 >@@ -24,12 +24,11 @@ > import java.io.OutputStream; > import java.util.List; > >-// FOP > import org.apache.avalon.framework.configuration.Configuration; > import org.apache.avalon.framework.configuration.ConfigurationException; >-import org.apache.fop.area.Area; >-import org.apache.fop.area.RegionViewport; > import org.apache.fop.apps.FOPException; >+import org.apache.fop.apps.FOUserAgent; >+import org.apache.fop.area.Area; > import org.apache.fop.area.Block; > import org.apache.fop.area.BlockViewport; > import org.apache.fop.area.CTM; >@@ -38,16 +37,13 @@ > import org.apache.fop.area.inline.ForeignObject; > import org.apache.fop.area.inline.TextArea; > import org.apache.fop.datatypes.ColorType; >-import org.apache.fop.apps.FOUserAgent; > import org.apache.fop.fonts.FontSetup; > import org.apache.fop.fonts.Typeface; >-import org.apache.fop.render.PrintRenderer; >-import org.apache.fop.render.RendererContext; >- > import org.apache.fop.image.FopImage; > import org.apache.fop.image.ImageFactory; >+import org.apache.fop.render.PrintRenderer; >+import org.apache.fop.render.RendererContext; > import org.apache.fop.traits.BorderProps; >- > import org.w3c.dom.Document; > > /** >@@ -507,9 +503,6 @@ > > if (bv.getPositioning() == Block.ABSOLUTE) { > >- currentIPPosition = 0; >- currentBPPosition = 0; >- > //closeText(); > endTextObject(); > >@@ -603,6 +596,12 @@ > * @see org.apache.fop.render.AbstractRenderer#startVParea(CTM) > */ > protected void startVParea(CTM ctm) { >+ // The CTM will transform coordinates relative to >+ // this region-reference area into page coords, so >+ // set origin for the region to 0,0. >+ currentIPPosition = 0; >+ currentBPPosition = 0; >+ > // Set the given CTM in the graphics state > //currentState.push(); > //currentState.setTransform(new AffineTransform(CTMHelper.toPDFArray(ctm))); >@@ -625,27 +624,7 @@ > restoreGraphicsState(); > //currentState.pop(); > } >- >- /** >- * Handle the traits for a region >- * This is used to draw the traits for the given page region. >- * (See Sect. 6.4.1.2 of XSL-FO spec.) >- * @param region the RegionViewport whose region is to be drawn >- */ >- protected void handleRegionTraits(RegionViewport region) { >- currentFontName = ""; >- float startx = 0; >- float starty = 0; >- Rectangle2D viewArea = region.getViewArea(); >- float width = (float)(viewArea.getWidth()); >- float height = (float)(viewArea.getHeight()); >- /* >- Trait.Background back; >- back = (Trait.Background)region.getTrait(Trait.BACKGROUND); >- */ >- drawBackAndBorders(region, startx, starty, width, height); >- } >- >+ > /** > * Handle block traits. > * The block could be any sort of block with any positioning >@@ -793,7 +772,7 @@ > * @param endx the x end position > * @param endy the y end position > */ >- private void drawLine(float startx, float starty, float endx, float endy) { >+ protected void drawLine(float startx, float starty, float endx, float endy) { > writeln(startx + " " + starty + " M "); > writeln(endx + " " + endy + " lineto"); > } >Index: src/java/org/apache/fop/render/awt/BMPReader.java >=================================================================== >RCS file: src/java/org/apache/fop/render/awt/BMPReader.java >diff -N src/java/org/apache/fop/render/awt/BMPReader.java >--- /dev/null 1 Jan 1970 00:00:00 -0000 >+++ src/java/org/apache/fop/render/awt/BMPReader.java 1 Jan 1970 00:00:00 -0000 >@@ -0,0 +1,187 @@ >+package org.apache.fop.render.awt; >+ >+import java.awt.Component; >+import java.awt.Container; >+import java.awt.Image; >+import java.awt.image.MemoryImageSource; >+import java.io.BufferedInputStream; >+import java.io.FileInputStream; >+import java.io.IOException; >+ >+import org.apache.commons.logging.Log; >+import org.apache.commons.logging.LogFactory; >+import org.apache.fop.apps.FOPException; >+ >+/** >+ * Class used to load windows bitmap images (.bmp) >+ * >+ * see http://www.javaworld.com/javaworld/javatips/jw-javatip43.html >+ * >+ */ >+public class BMPReader { >+ >+ /** logging instance */ >+ protected static Log logger = LogFactory.getLog("org.apache.fop.render"); >+ >+ private Image image; >+ >+ private BufferedInputStream bs; >+ >+ /** >+ * Loads a Bitmap from an url pointing to a .bmp-file. Reads only >+ * uncompressed 24- and 8-bit images. >+ * >+ * @param url >+ * the url of the bitmap >+ * @return Image the bitmap as an awt.Image >+ * @throws IOException >+ * if the url cannot be read >+ * @throws FOPException >+ * if the image is not a 24- or 8-bit image or if it is >+ * compressed >+ */ >+ public Image loadbitmap(String url) throws IOException, FOPException { >+ >+ bs = new BufferedInputStream(new FileInputStream(url)); >+ int bflen = 14; // 14 byte BITMAPFILEHEADER >+ byte bf[] = new byte[bflen]; >+ bs.read(bf, 0, bflen); >+ int bilen = 40; // 40-byte BITMAPINFOHEADER >+ byte bi[] = new byte[bilen]; >+ bs.read(bi, 0, bilen); >+ >+ // Interperet data. >+ int nsize = (((int) bf[5] & 0xff) << 24) | (((int) bf[4] & 0xff) << 16) >+ | (((int) bf[3] & 0xff) << 8) | (int) bf[2] & 0xff; >+ int nbisize = (((int) bi[3] & 0xff) << 24) >+ | (((int) bi[2] & 0xff) << 16) | (((int) bi[1] & 0xff) << 8) >+ | (int) bi[0] & 0xff; >+ int nwidth = (((int) bi[7] & 0xff) << 24) >+ | (((int) bi[6] & 0xff) << 16) | (((int) bi[5] & 0xff) << 8) >+ | (int) bi[4] & 0xff; >+ int nheight = (((int) bi[11] & 0xff) << 24) >+ | (((int) bi[10] & 0xff) << 16) | (((int) bi[9] & 0xff) << 8) >+ | (int) bi[8] & 0xff; >+ int nplanes = (((int) bi[13] & 0xff) << 8) | (int) bi[12] & 0xff; >+ int nbitcount = (((int) bi[15] & 0xff) << 8) | (int) bi[14] & 0xff; >+ >+ // Look for non-zero values to indicate compression >+ int ncompression = (((int) bi[19]) << 24) | (((int) bi[18]) << 16) >+ | (((int) bi[17]) << 8) | (int) bi[16]; >+ if (ncompression != 0) { >+ bs.close(); >+ throw new FOPException("Bitmap" + url + "could not be rendered. " >+ + "FOP only supports non-compressed Windows Bitmap"); >+ } >+ int nsizeimage = (((int) bi[23] & 0xff) << 24) >+ | (((int) bi[22] & 0xff) << 16) | (((int) bi[21] & 0xff) << 8) >+ | (int) bi[20] & 0xff; >+ int nxpm = (((int) bi[27] & 0xff) << 24) >+ | (((int) bi[26] & 0xff) << 16) | (((int) bi[25] & 0xff) << 8) >+ | (int) bi[24] & 0xff; >+ int nypm = (((int) bi[31] & 0xff) << 24) >+ | (((int) bi[30] & 0xff) << 16) | (((int) bi[29] & 0xff) << 8) >+ | (int) bi[28] & 0xff; >+ int nclrused = (((int) bi[35] & 0xff) << 24) >+ | (((int) bi[34] & 0xff) << 16) | (((int) bi[33] & 0xff) << 8) >+ | (int) bi[32] & 0xff; >+ int nclrimp = (((int) bi[39] & 0xff) << 24) >+ | (((int) bi[38] & 0xff) << 16) | (((int) bi[37] & 0xff) << 8) >+ | (int) bi[36] & 0xff; >+ >+ logger.debug("Rendering Bitmap" + url + "Colors important are :" >+ + nclrimp + "File type is :" + (char) bf[0] + (char) bf[1] >+ + "Size of file is :" + nsize + "Size of bitmapinfoheader is :" >+ + nbisize + "Width is :" + nwidth + "Height is :" + nheight >+ + "Planes is :" + nplanes + "BitCount is :" + nbitcount >+ + "Compression is :" + ncompression + "SizeImage is :" >+ + nsizeimage + "X-Pixels per meter is :" + nxpm >+ + "Y-Pixels per meter is :" + nypm + "Colors used are :" >+ + nclrused); >+ >+ if (nbitcount == 24) { >+ // No Palatte data for 24-bit format but scan lines are >+ // padded out to even 4-byte boundaries. >+ int npad = (nsizeimage / nheight) - nwidth * 3; >+ if (npad == 4){ >+ npad = 0; // corrected >+ } >+ int ndata[] = new int[nheight * nwidth]; >+ byte brgb[] = new byte[(nwidth + npad) * 3 * nheight]; >+ bs.read(brgb, 0, (nwidth + npad) * 3 * nheight); >+ int nindex = 0; >+ for (int j = 0; j < nheight; j++) { >+ for (int i = 0; i < nwidth; i++) { >+ ndata[nwidth * (nheight - j - 1) + i] = (255 & 0xff) << 24 >+ | (((int) brgb[nindex + 2] & 0xff) << 16) >+ | (((int) brgb[nindex + 1] & 0xff) << 8) >+ | (int) brgb[nindex] & 0xff; >+ >+ nindex += 3; >+ } >+ nindex += npad; >+ } >+ >+ Component c = new Container(); >+ image = c.createImage(new MemoryImageSource(nwidth, nheight, ndata, >+ 0, nwidth)); >+ } else if (nbitcount == 8) { >+ // Have to determine the number of colors, the clrsused >+ // parameter is dominant if it is greater than zero. If >+ // zero, calculate colors based on bitsperpixel. >+ int nNumColors = 0; >+ if (nclrused > 0) { >+ nNumColors = nclrused; >+ } else { >+ nNumColors = (1 & 0xff) << nbitcount; >+ } >+ >+ // Some bitmaps do not have the sizeimage field calculated >+ // Ferret out these cases and fix 'em. >+ if (nsizeimage == 0) { >+ nsizeimage = ((((nwidth * nbitcount) + 31) & ~31) >> 3); >+ nsizeimage *= nheight; >+ } >+ >+ // Read the palatte colors. >+ int npalette[] = new int[nNumColors]; >+ byte bpalette[] = new byte[nNumColors * 4]; >+ bs.read(bpalette, 0, nNumColors * 4); >+ int nindex8 = 0; >+ for (int n = 0; n < nNumColors; n++) { >+ npalette[n] = (255 & 0xff) << 24 >+ | (((int) bpalette[nindex8 + 2] & 0xff) << 16) >+ | (((int) bpalette[nindex8 + 1] & 0xff) << 8) >+ | (int) bpalette[nindex8] & 0xff; >+ } >+ >+ // Read the image data (actually indices into the palette) >+ // Scan lines are still padded out to even 4-byte >+ // boundaries. >+ int npad8 = (nsizeimage / nheight) - nwidth; >+ int ndata8[] = new int[nwidth * nheight]; >+ byte bdata[] = new byte[(nwidth + npad8) * nheight]; >+ bs.read(bdata, 0, (nwidth + npad8) * nheight); >+ nindex8 = 0; >+ for (int j8 = 0; j8 < nheight; j8++) { >+ for (int i8 = 0; i8 < nwidth; i8++) { >+ ndata8[nwidth * (nheight - j8 - 1) + i8] = >+ npalette[((int) bdata[nindex8] & 0xff)]; >+ nindex8++; >+ } >+ nindex8 += npad8; >+ } >+ >+ Component c = new Container(); >+ image = c.createImage(new MemoryImageSource(nwidth, nheight, >+ ndata8, 0, nwidth)); >+ } else { >+ throw new FOPException("Bitmap" + url + "could not be rendered. " >+ + "FOP only supports 24-bit or 8-bit Windows Bitmap"); >+ } >+ >+ bs.close(); >+ return image; >+ >+ } >+}
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 33760
:
14371
|
14372
|
14426
|
14520
|
15340