diff options
author | Keiron Liddle <keiron@apache.org> | 2000-07-11 05:26:54 +0000 |
---|---|---|
committer | Keiron Liddle <keiron@apache.org> | 2000-07-11 05:26:54 +0000 |
commit | 544bbe5aa3eb04f27e78c83785f9447265c57614 (patch) | |
tree | 875d7af790d2daf22654a6fd0594cf7a8568865f /src/org/apache/fop | |
parent | f01eae085e174ef0c9f3f5d9600b0cea08e85439 (diff) | |
download | xmlgraphics-fop-544bbe5aa3eb04f27e78c83785f9447265c57614.tar.gz xmlgraphics-fop-544bbe5aa3eb04f27e78c83785f9447265c57614.zip |
changed to render svg area, in a different package
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@193482 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src/org/apache/fop')
-rw-r--r-- | src/org/apache/fop/render/Renderer.java | 2 | ||||
-rw-r--r-- | src/org/apache/fop/render/awt/AWTRenderer.java | 716 | ||||
-rw-r--r-- | src/org/apache/fop/render/pdf/PDFRenderer.java | 1004 | ||||
-rw-r--r-- | src/org/apache/fop/render/xml/XMLRenderer.java | 2 |
4 files changed, 1286 insertions, 438 deletions
diff --git a/src/org/apache/fop/render/Renderer.java b/src/org/apache/fop/render/Renderer.java index c0bdcbced..ee4569733 100644 --- a/src/org/apache/fop/render/Renderer.java +++ b/src/org/apache/fop/render/Renderer.java @@ -51,7 +51,7 @@ package org.apache.fop.render; // FOP -import org.apache.fop.svg.SVGArea; +import org.apache.fop.dom.svg.SVGArea; import org.apache.fop.image.ImageArea; import org.apache.fop.apps.FOPException; import org.apache.fop.layout.*; diff --git a/src/org/apache/fop/render/awt/AWTRenderer.java b/src/org/apache/fop/render/awt/AWTRenderer.java index 1318049a6..1d0f8a52f 100644 --- a/src/org/apache/fop/render/awt/AWTRenderer.java +++ b/src/org/apache/fop/render/awt/AWTRenderer.java @@ -14,12 +14,16 @@ import org.apache.fop.messaging.MessageHandler; import org.apache.fop.datatypes.*; import org.apache.fop.image.*; import org.apache.fop.svg.*; +import org.apache.fop.dom.svg.*; +import org.apache.fop.dom.svg.SVGArea; import org.apache.fop.render.pdf.*; import org.apache.fop.viewer.*; import org.apache.fop.apps.*; -import org.apache.fop.render.Renderer; + +import org.w3c.dom.svg.*; import java.awt.*; +import java.awt.Image; import java.awt.image.*; import java.awt.geom.*; import java.awt.font.*; @@ -30,23 +34,24 @@ import javax.swing.*; import java.awt.print.*; import java.awt.image.BufferedImage; +import org.apache.fop.render.Renderer; public class AWTRenderer implements Renderer, Printable, Pageable { - protected int pageWidth = 0; - protected int pageHeight = 0; - protected double scaleFactor = 100.0; - protected int pageNumber = 0; - protected AreaTree tree; - protected ProgressListener progressListener = null; - protected Translator res = null; - - protected Hashtable fontNames = new Hashtable(); - protected Hashtable fontStyles = new Hashtable(); - protected Color saveColor; + protected int pageWidth = 0; + protected int pageHeight = 0; + protected double scaleFactor = 100.0; + protected int pageNumber = 0; + protected AreaTree tree; + protected ProgressListener progressListener = null; + protected Translator res = null; - // Key - Font name, Value - java Font name. - protected static Hashtable JAVA_FONT_NAMES; + protected Hashtable fontNames = new Hashtable(); + protected Hashtable fontStyles = new Hashtable(); + protected Color saveColor; + + // Key - Font name, Value - java Font name. + protected static Hashtable JAVA_FONT_NAMES; /** * Image Object and Graphics Object. The Graphics Object is the Graphics @@ -58,64 +63,64 @@ public class AWTRenderer implements Renderer, Printable, Pageable { /** * The current (internal) font name */ - protected String currentFontName; + protected String currentFontName; /** * The current font size in millipoints */ - protected int currentFontSize; + protected int currentFontSize; /** * The current colour's red, green and blue component */ - protected float currentRed = 0; - protected float currentGreen = 0; - protected float currentBlue = 0; + protected float currentRed = 0; + protected float currentGreen = 0; + protected float currentBlue = 0; /** * The current vertical position in millipoints from bottom */ - protected int currentYPosition = 0; + protected int currentYPosition = 0; /** * The current horizontal position in millipoints from left */ - protected int currentXPosition = 0; + protected int currentXPosition = 0; /** * The horizontal position of the current area container */ - private int currentAreaContainerXPosition = 0; - - static { - JAVA_FONT_NAMES = new Hashtable(); - JAVA_FONT_NAMES.put("Times", "serif"); - JAVA_FONT_NAMES.put("Times-Roman", "serif"); - JAVA_FONT_NAMES.put("Courier", "monospaced"); - JAVA_FONT_NAMES.put("Helvetica", "sansserif"); - // JAVA_FONT_NAMES.put("Serif", "sansserif"); - } + private int currentAreaContainerXPosition = 0; - public AWTRenderer(Translator aRes) { - res = aRes; - } + static { + JAVA_FONT_NAMES = new Hashtable(); + JAVA_FONT_NAMES.put("Times", "serif"); + JAVA_FONT_NAMES.put("Times-Roman", "serif"); + JAVA_FONT_NAMES.put("Courier", "monospaced"); + JAVA_FONT_NAMES.put("Helvetica", "sansserif"); + // JAVA_FONT_NAMES.put("Serif", "sansserif"); + } - public int getPageNumber() { - return pageNumber; - } + public AWTRenderer(Translator aRes) { + res = aRes; + } - public void setPageNumber(int aValue) { - pageNumber = aValue; - } + public int getPageNumber() { + return pageNumber; + } - public void setScaleFactor(double newScaleFactor) { - scaleFactor = newScaleFactor; - } + public void setPageNumber(int aValue) { + pageNumber = aValue; + } - public double getScaleFactor() { - return scaleFactor; + public void setScaleFactor(double newScaleFactor) { + scaleFactor = newScaleFactor; } + public double getScaleFactor() { + return scaleFactor; + } + public BufferedImage getLastRenderedPage() { return pageImage; } @@ -133,8 +138,8 @@ public class AWTRenderer implements Renderer, Printable, Pageable { * @param b the blue component */ protected void addLine(int x1, int y1, int x2, int y2, int th, - float r, float g, float b) { - graphics.setColor(new Color (r,g,b)); + float r, float g, float b) { + graphics.setColor(new Color (r,g,b)); graphics.drawLine((int)(x1/1000f), pageHeight - (int)(y1/1000f), (int)(x2/1000f), pageHeight - (int)(y2/1000f)); } @@ -173,42 +178,42 @@ public class AWTRenderer implements Renderer, Printable, Pageable { * @param fb the blue component of the fill */ protected void addRect(int x, int y, int w, int h, - float r, float g, float b, - float fr, float fg, float fb) { - graphics.setColor(new Color (r,g,b)); + float r, float g, float b, + float fr, float fg, float fb) { + graphics.setColor(new Color (r,g,b)); graphics.fill3DRect((int) (x/1000f), pageHeight - (int) (y/1000f), (int) (w/1000f), -(int) (h/1000f),true); } - /** - * Vor dem Druck einzustellen: - * - * Seite/Seiten wählen - * Zoomfaktor - * Seitenformat / Quer- oder Hoch - **/ - public void transform(Graphics2D g2d, double zoomPercent, double angle) { - AffineTransform at = g2d.getTransform(); - at.rotate(angle); - at.scale(zoomPercent/100.0, zoomPercent/100.0); - g2d.setTransform(at); - } - - protected void drawFrame() { - - int width = pageWidth; - int height = pageHeight; - - graphics.setColor(Color.white); - graphics.fillRect(0, 0, width, height); - graphics.setColor(Color.black); - graphics.drawRect(-1, -1, width+2, height+2); - graphics.drawLine(width+2, 0, width+2, height+2); - graphics.drawLine(width+3, 1, width+3, height+3); - - graphics.drawLine(0, height+2, width+2, height+2); - graphics.drawLine(1, height+3, width+3, height+3); - } + /** + * Vor dem Druck einzustellen: + * + * Seite/Seiten wählen + * Zoomfaktor + * Seitenformat / Quer- oder Hoch + **/ + public void transform(Graphics2D g2d, double zoomPercent, double angle) { + AffineTransform at = g2d.getTransform(); + at.rotate(angle); + at.scale(zoomPercent/100.0, zoomPercent/100.0); + g2d.setTransform(at); + } + + protected void drawFrame() { + + int width = pageWidth; + int height = pageHeight; + + graphics.setColor(Color.white); + graphics.fillRect(0, 0, width, height); + graphics.setColor(Color.black); + graphics.drawRect(-1, -1, width+2, height+2); + graphics.drawLine(width+2, 0, width+2, height+2); + graphics.drawLine(width+3, 1, width+3, height+3); + + graphics.drawLine(0, height+2, width+2, height+2); + graphics.drawLine(1, height+3, width+3, height+3); + } /** * Retrieve the number of pages in this document. @@ -243,11 +248,11 @@ public class AWTRenderer implements Renderer, Printable, Pageable { public void render(AreaTree areaTree, int aPageNumber) throws IOException { - tree = areaTree; - Page page = (Page)areaTree.getPages().elementAt(aPageNumber); - - pageWidth = (int)((float)page.getWidth() / 1000f); - pageHeight = (int)((float)page.getHeight() / 1000f); + tree = areaTree; + Page page = (Page)areaTree.getPages().elementAt(aPageNumber); + + pageWidth = (int)((float)page.getWidth() / 1000f); + pageHeight = (int)((float)page.getHeight() / 1000f); pageImage = new BufferedImage((int)((pageWidth * (int)scaleFactor)/100), @@ -256,38 +261,38 @@ public class AWTRenderer implements Renderer, Printable, Pageable { graphics = pageImage.createGraphics(); - transform(graphics, scaleFactor, 0); - drawFrame(); + transform(graphics, scaleFactor, 0); + drawFrame(); - renderPage(page); - } + renderPage(page); + } - public void renderPage(Page page) { - AreaContainer body, before, after; + public void renderPage(Page page) { + AreaContainer body, before, after; - body = page.getBody(); - before = page.getBefore(); - after = page.getAfter(); + body = page.getBody(); + before = page.getBefore(); + after = page.getAfter(); - this.currentFontName = ""; - this.currentFontSize = 0; + this.currentFontName = ""; + this.currentFontSize = 0; - renderAreaContainer(body); + renderAreaContainer(body); - if (before != null) { - renderAreaContainer(before); - } + if (before != null) { + renderAreaContainer(before); + } - if (after != null) { - renderAreaContainer(after); - } + if (after != null) { + renderAreaContainer(after); } + } - public void renderAreaContainer(AreaContainer area) { + public void renderAreaContainer(AreaContainer area) { + + int saveY = this.currentYPosition; + int saveX = this.currentAreaContainerXPosition; - int saveY = this.currentYPosition; - int saveX = this.currentAreaContainerXPosition; - if (area.getPosition() == org.apache.fop.fo.properties.Position.ABSOLUTE) { // Y position is computed assuming positive Y axis, adjust @@ -295,14 +300,14 @@ public class AWTRenderer implements Renderer, Printable, Pageable { this.currentYPosition = area.getYPosition() - 2 * area.getPaddingTop() - 2 * area.borderWidthTop; - this.currentAreaContainerXPosition = area.getXPosition(); + this.currentAreaContainerXPosition = area.getXPosition(); } else if (area.getPosition() == org.apache.fop.fo.properties.Position.RELATIVE) { - this.currentYPosition -= area.getYPosition(); - this.currentAreaContainerXPosition += area.getXPosition(); + this.currentYPosition -= area.getYPosition(); + this.currentAreaContainerXPosition += area.getXPosition(); } else if (area.getPosition() == org.apache.fop.fo.properties.Position.STATIC) { - this.currentYPosition -= area.getPaddingTop() + area.borderWidthTop; + this.currentYPosition -= area.getPaddingTop() + area.borderWidthTop; this.currentAreaContainerXPosition += area.getPaddingLeft() + area.borderWidthLeft; } @@ -318,280 +323,280 @@ public class AWTRenderer implements Renderer, Printable, Pageable { if (area.getPosition() != org.apache.fop.fo.properties.Position.STATIC) { - this.currentYPosition = saveY; - this.currentAreaContainerXPosition = saveX; - } else { - this.currentYPosition -= area.getHeight(); - } + this.currentYPosition = saveY; + this.currentAreaContainerXPosition = saveX; + } else { + this.currentYPosition -= area.getHeight(); } + } - private void doFrame(org.apache.fop.layout.Area area) { - int w, h; - int rx = this.currentAreaContainerXPosition; - w = area.getContentWidth(); + private void doFrame(org.apache.fop.layout.Area area) { + int w, h; + int rx = this.currentAreaContainerXPosition; + w = area.getContentWidth(); if (area instanceof BlockArea) { - rx += ((BlockArea)area).getStartIndent(); + rx += ((BlockArea)area).getStartIndent(); } - h = area.getContentHeight(); - int ry = this.currentYPosition; - ColorType bg = area.getBackgroundColor(); - - rx = rx - area.getPaddingLeft(); - ry = ry + area.getPaddingTop(); - w = w + area.getPaddingLeft() + area.getPaddingRight(); - h = h + area.getPaddingTop() + area.getPaddingBottom(); - - // I'm not sure I should have to check for bg being null - // but I do - if ((bg != null) && (bg.alpha() == 0)) { - this.addRect(rx, ry, w, -h, - bg.red(), bg.green(), bg.blue(), - bg.red(), bg.green(), bg.blue()); - } + h = area.getContentHeight(); + int ry = this.currentYPosition; + ColorType bg = area.getBackgroundColor(); + + rx = rx - area.getPaddingLeft(); + ry = ry + area.getPaddingTop(); + w = w + area.getPaddingLeft() + area.getPaddingRight(); + h = h + area.getPaddingTop() + area.getPaddingBottom(); + + // I'm not sure I should have to check for bg being null + // but I do + if ((bg != null) && (bg.alpha() == 0)) { + this.addRect(rx, ry, w, -h, + bg.red(), bg.green(), bg.blue(), + bg.red(), bg.green(), bg.blue()); + } - rx = rx - area.borderWidthLeft; - ry = ry + area.borderWidthTop; - w = w + area.borderWidthLeft + area.borderWidthRight; - h = h + area.borderWidthTop + area.borderWidthBottom; + rx = rx - area.borderWidthLeft; + ry = ry + area.borderWidthTop; + w = w + area.borderWidthLeft + area.borderWidthRight; + h = h + area.borderWidthTop + area.borderWidthBottom; if (area.borderWidthTop != 0) { - addLine(rx, ry, rx + w, ry, - area.borderWidthTop, + addLine(rx, ry, rx + w, ry, + area.borderWidthTop, area.borderColorTop.red(), area.borderColorTop.green(), area.borderColorTop.blue()); } if (area.borderWidthLeft != 0) { - addLine(rx, ry, rx, ry - h, - area.borderWidthLeft, + addLine(rx, ry, rx, ry - h, + area.borderWidthLeft, area.borderColorLeft.red(), area.borderColorLeft.green(), area.borderColorLeft.blue()); } if (area.borderWidthRight != 0) { - addLine(rx + w, ry, rx + w, ry - h, - area.borderWidthRight, + addLine(rx + w, ry, rx + w, ry - h, + area.borderWidthRight, area.borderColorRight.red(), area.borderColorRight.green(), area.borderColorRight.blue()); } if (area.borderWidthBottom != 0) { - addLine(rx, ry - h, rx + w, ry - h, - area.borderWidthBottom, + addLine(rx, ry - h, rx + w, ry - h, + area.borderWidthBottom, area.borderColorBottom.red(), area.borderColorBottom.green(), area.borderColorBottom.blue()); } - } + } - protected Rectangle2D getBounds(org.apache.fop.layout.Area a) { - return new Rectangle2D.Double(currentAreaContainerXPosition, - currentYPosition, - a.getAllocationWidth(), - a.getHeight()); - } + protected Rectangle2D getBounds(org.apache.fop.layout.Area a) { + return new Rectangle2D.Double(currentAreaContainerXPosition, + currentYPosition, + a.getAllocationWidth(), + a.getHeight()); + } - public void renderBlockArea(BlockArea area) { - doFrame(area); - Enumeration e = area.getChildren().elements(); - while (e.hasMoreElements()) { + public void renderBlockArea(BlockArea area) { + doFrame(area); + Enumeration e = area.getChildren().elements(); + while (e.hasMoreElements()) { org.apache.fop.layout.Box b = (org.apache.fop.layout.Box) e.nextElement(); - b.render(this); - } + b.render(this); } + } - public void setupFontInfo(FontInfo fontInfo) { - FontSetup.setup(fontInfo); - Hashtable hash = fontInfo.getFonts(); - org.apache.fop.render.pdf.Font f; - String name; - Object key; - int fontStyle; - - for (Enumeration e = hash.keys(); e.hasMoreElements();) { - fontStyle = java.awt.Font.PLAIN; - key = e.nextElement(); - f = (org.apache.fop.render.pdf.Font)hash.get(key); - name = f.fontName(); - - if (name.toUpperCase().indexOf("BOLD") > 0) { - fontStyle += java.awt.Font.BOLD; - } - if (name.toUpperCase().indexOf("ITALIC") > 0 || - name.toUpperCase().indexOf("OBLIQUE") > 0) { - fontStyle += java.awt.Font.ITALIC; - } - - int hyphenIndex = name.indexOf("-"); - - hyphenIndex = (hyphenIndex < 0) ? name.length() : hyphenIndex; - fontNames.put(key, name.substring(0, hyphenIndex)); - fontStyles.put(key, new Integer(fontStyle)); - } - - } - - public void renderDisplaySpace(DisplaySpace space) { - int d = space.getSize(); - this.currentYPosition -= d; + public void setupFontInfo(FontInfo fontInfo) { + FontSetup.setup(fontInfo); + Hashtable hash = fontInfo.getFonts(); + org.apache.fop.render.pdf.Font f; + String name; + Object key; + int fontStyle; + + for (Enumeration e = hash.keys(); e.hasMoreElements();) { + fontStyle = java.awt.Font.PLAIN; + key = e.nextElement(); + f = (org.apache.fop.render.pdf.Font)hash.get(key); + name = f.fontName(); + + if (name.toUpperCase().indexOf("BOLD") > 0) { + fontStyle += java.awt.Font.BOLD; + } + if (name.toUpperCase().indexOf("ITALIC") > 0 || + name.toUpperCase().indexOf("OBLIQUE") > 0) { + fontStyle += java.awt.Font.ITALIC; + } + + int hyphenIndex = name.indexOf("-"); + + hyphenIndex = (hyphenIndex < 0) ? name.length() : hyphenIndex; + fontNames.put(key, name.substring(0, hyphenIndex)); + fontStyles.put(key, new Integer(fontStyle)); } - - - public void renderImageArea(ImageArea area) { - int x = this.currentAreaContainerXPosition + - area.getXOffset(); - int y = this.currentYPosition; - int w = area.getContentWidth(); - int h = area.getHeight(); - - FopImage img = area.getImage(); - - if (img == null) { + + } + + public void renderDisplaySpace(DisplaySpace space) { + int d = space.getSize(); + this.currentYPosition -= d; + } + + + public void renderImageArea(ImageArea area) { + int x = this.currentAreaContainerXPosition + + area.getXOffset(); + int y = this.currentYPosition; + int w = area.getContentWidth(); + int h = area.getHeight(); + + FopImage img = area.getImage(); + + if (img == null) { MessageHandler.logln("area.getImage() is null"); - } - + } + try { byte[] map = img.getBitmaps(); String path = img.getURL(); - ImageIcon icon = new ImageIcon(path); - Image imgage = icon.getImage(); - - graphics.drawImage(imgage, currentXPosition / 1000, - pageHeight - y / 1000, - img.getWidth() / 1000, - img.getHeight() / 1000, - null); - - currentYPosition -= h; + ImageIcon icon = new ImageIcon(path); + Image imgage = icon.getImage(); + + graphics.drawImage(imgage, currentXPosition / 1000, + pageHeight - y / 1000, + img.getWidth() / 1000, + img.getHeight() / 1000, + null); + + currentYPosition -= h; } catch (FopImageException imgex) { // ? MessageHandler.logln("Error while loading image : " + imgex.getMessage()); } } - public void renderInlineArea(InlineArea area) { - char ch; - StringBuffer pdf = new StringBuffer(); - - String name = area.getFontState().getFontName(); - int size = area.getFontState().getFontSize(); - - float red = area.getRed(); - float green = area.getGreen(); - float blue = area.getBlue(); - - if ((!name.equals(this.currentFontName)) - || (size != this.currentFontSize)) { - this.currentFontName = name; - this.currentFontSize = size; - } - - if ((red != this.currentRed) - || (green != this.currentGreen) - || (blue != this.currentBlue)) { - this.currentRed = red; - this.currentGreen = green; - this.currentBlue = blue; - } + public void renderInlineArea(InlineArea area) { + char ch; + StringBuffer pdf = new StringBuffer(); + + String name = area.getFontState().getFontName(); + int size = area.getFontState().getFontSize(); + + float red = area.getRed(); + float green = area.getGreen(); + float blue = area.getBlue(); - int rx = this.currentXPosition; - int bl = this.currentYPosition; + if ((!name.equals(this.currentFontName)) + || (size != this.currentFontSize)) { + this.currentFontName = name; + this.currentFontSize = size; + } + + if ((red != this.currentRed) + || (green != this.currentGreen) + || (blue != this.currentBlue)) { + this.currentRed = red; + this.currentGreen = green; + this.currentBlue = blue; + } + + int rx = this.currentXPosition; + int bl = this.currentYPosition; - String s = area.getText(); - Color oldColor = graphics.getColor(); - java.awt.Font oldFont = graphics.getFont(); - String aFontName = fontNames.get(name).toString(); + String s = area.getText(); + Color oldColor = graphics.getColor(); + java.awt.Font oldFont = graphics.getFont(); + String aFontName = fontNames.get(name).toString(); - aFontName = getJavaFontName(aFontName); + aFontName = getJavaFontName(aFontName); java.awt.Font f = new java.awt.Font(aFontName, - ((Integer)fontStyles.get(name)).intValue(), - (int)(size / 1000f)); + ((Integer)fontStyles.get(name)).intValue(), + (int)(size / 1000f)); - graphics.setColor(new Color(red, green, blue)); - - /* - Die KLasse TextLayout nimmt für die Ausgabe eigenen Schriftsatz, - der i.R. breiter ist. Deshalb wird bis diese Tatsache sich geklärt/ - geregelt hat weniger schöne Ausgabe über Graphics benutzt. - */ + graphics.setColor(new Color(red, green, blue)); + + /* + Die KLasse TextLayout nimmt für die Ausgabe eigenen Schriftsatz, + der i.R. breiter ist. Deshalb wird bis diese Tatsache sich geklärt/ + geregelt hat weniger schöne Ausgabe über Graphics benutzt. + */ // Fonts in bold still have trouble displaying! FontRenderContext newContext = new FontRenderContext(null, true, true); - TextLayout layout = new TextLayout(s, f, newContext); + TextLayout layout = new TextLayout(s, f, newContext); graphics.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); - layout.draw(graphics, rx / 1000f, (int)(pageHeight - bl / 1000f)); + layout.draw(graphics, rx / 1000f, (int)(pageHeight - bl / 1000f)); graphics.setColor(oldColor); - this.currentXPosition += area.getContentWidth(); - } + this.currentXPosition += area.getContentWidth(); + } - public void renderInlineSpace(InlineSpace space) { - this.currentXPosition += space.getSize(); - } + public void renderInlineSpace(InlineSpace space) { + this.currentXPosition += space.getSize(); + } - public void renderLineArea(LineArea area) { - int rx = this.currentAreaContainerXPosition - + area.getStartIndent(); - int ry = this.currentYPosition; - int w = area.getContentWidth(); - int h = area.getHeight(); + public void renderLineArea(LineArea area) { + int rx = this.currentAreaContainerXPosition + + area.getStartIndent(); + int ry = this.currentYPosition; + int w = area.getContentWidth(); + int h = area.getHeight(); - this.currentYPosition -= area.getPlacementOffset(); - this.currentXPosition = rx; + this.currentYPosition -= area.getPlacementOffset(); + this.currentXPosition = rx; - int bl = this.currentYPosition; + int bl = this.currentYPosition; - Enumeration e = area.getChildren().elements(); - while (e.hasMoreElements()) { + Enumeration e = area.getChildren().elements(); + while (e.hasMoreElements()) { org.apache.fop.layout.Box b = (org.apache.fop.layout.Box) e.nextElement(); - b.render(this); - } - - this.currentYPosition = ry-h; - } - - /** - * render rule area into PDF - * - * @param area area to render - */ - public void renderRuleArea(RuleArea area) { - int rx = this.currentAreaContainerXPosition - + area.getStartIndent(); - int ry = this.currentYPosition; - int w = area.getContentWidth(); - int h = area.getHeight(); - int th = area.getRuleThickness(); - float r = area.getRed(); - float g = area.getGreen(); - float b = area.getBlue(); - Color oldColor = graphics.getColor(); - - graphics.setColor(new Color(r, g, b)); - - graphics.fillRect((int)(rx / 1000f), (int)(pageHeight - ry / 1000f), - (int)(w / 1000f), (int)(th / 1000f)); - graphics.setColor(oldColor); - - } - - public void renderSVGArea(SVGArea area) { - int x = this.currentAreaContainerXPosition; - int y = this.currentYPosition; - int w = area.getContentWidth(); - int h = area.getHeight(); - this.currentYPosition -= h; + b.render(this); + } + + this.currentYPosition = ry-h; + } + + /** + * render rule area into PDF + * + * @param area area to render + */ + public void renderRuleArea(RuleArea area) { + int rx = this.currentAreaContainerXPosition + + area.getStartIndent(); + int ry = this.currentYPosition; + int w = area.getContentWidth(); + int h = area.getHeight(); + int th = area.getRuleThickness(); + float r = area.getRed(); + float g = area.getGreen(); + float b = area.getBlue(); + Color oldColor = graphics.getColor(); + + graphics.setColor(new Color(r, g, b)); + + graphics.fillRect((int)(rx / 1000f), (int)(pageHeight - ry / 1000f), + (int)(w / 1000f), (int)(th / 1000f)); + graphics.setColor(oldColor); + + } + + public void renderSVGArea(SVGArea area) { + int x = this.currentAreaContainerXPosition; + int y = this.currentYPosition; + int w = area.getContentWidth(); + int h = area.getHeight(); + this.currentYPosition -= h; // Enumeration e = area.getChildren().elements(); // while (e.hasMoreElements()) { @@ -620,70 +625,71 @@ public class AWTRenderer implements Renderer, Printable, Pageable { // } } - protected String getJavaFontName(String aName) { - if (aName == null) - return null; + protected String getJavaFontName(String aName) { + if (aName == null) + return null; - Object o = JAVA_FONT_NAMES.get(aName); + Object o = JAVA_FONT_NAMES.get(aName); - return (o == null) ? aName : o.toString(); - } + return (o == null) ? aName : o.toString(); + } - public void setProducer(String producer) { + public void setProducer(String producer) { // defined in Renderer Interface } public int print(Graphics g, PageFormat pageFormat, int pageIndex) throws PrinterException { - if (pageIndex >= tree.getPages().size()) - return NO_SUCH_PAGE; + if (pageIndex >= tree.getPages().size()) + return NO_SUCH_PAGE; - Graphics2D oldGraphics = graphics; - int oldPageNumber = pageNumber; + Graphics2D oldGraphics = graphics; + int oldPageNumber = pageNumber; - graphics = (Graphics2D)g; - Page aPage = (Page)tree.getPages().elementAt(pageIndex); - renderPage(aPage); - graphics = oldGraphics; + graphics = (Graphics2D)g; + Page aPage = (Page)tree.getPages().elementAt(pageIndex); + renderPage(aPage); + graphics = oldGraphics; - return PAGE_EXISTS; - } + return PAGE_EXISTS; + } - public int getNumberOfPages() { - return tree.getPages().size(); - } + public int getNumberOfPages() { + return tree.getPages().size(); + } public PageFormat getPageFormat(int pageIndex) throws IndexOutOfBoundsException { - if (pageIndex >= tree.getPages().size()) - return null; - - Page page = (Page)tree.getPages().elementAt(pageIndex); - PageFormat pageFormat = new PageFormat(); - Paper paper = new Paper(); + if (pageIndex >= tree.getPages().size()) + return null; + + Page page = (Page)tree.getPages().elementAt(pageIndex); + PageFormat pageFormat = new PageFormat(); + Paper paper = new Paper(); paper.setImageableArea(0, 0, page.getWidth() / 1000d, page.getHeight() / 1000d); - paper.setSize(page.getWidth() / 1000d, page.getHeight() / 1000d); - pageFormat.setPaper(paper); - - return pageFormat; - } + paper.setSize(page.getWidth() / 1000d, page.getHeight() / 1000d); + pageFormat.setPaper(paper); + + return pageFormat; + } public Printable getPrintable(int pageIndex) throws IndexOutOfBoundsException { - return this; - } + return this; + } - public void setProgressListener(ProgressListener l) { - progressListener = l; - } + public void setProgressListener(ProgressListener l) { + progressListener = l; + } - public static Color colorType2Color(ColorType ct) { - if (ct == null) { - return null; - } - return new Color(ct.red(), ct.green(), ct.blue()); + public static Color colorType2Color(ColorType ct) { + if (ct == null) { + return null; } + return new Color(ct.red(), ct.green(), ct.blue()); + } } + diff --git a/src/org/apache/fop/render/pdf/PDFRenderer.java b/src/org/apache/fop/render/pdf/PDFRenderer.java index 0fe1609a7..757c1e125 100644 --- a/src/org/apache/fop/render/pdf/PDFRenderer.java +++ b/src/org/apache/fop/render/pdf/PDFRenderer.java @@ -60,8 +60,19 @@ import org.apache.fop.apps.FOPException; import org.apache.fop.fo.properties.*; import org.apache.fop.layout.*; import org.apache.fop.datatypes.*; -import org.apache.fop.svg.*; +import org.apache.fop.svg.PathPoint; import org.apache.fop.pdf.*; +import org.apache.fop.layout.*; +import org.apache.fop.image.*; + +import org.w3c.dom.svg.*; +import org.w3c.dom.svg.SVGLength; + +import org.apache.fop.dom.svg.*; +import org.apache.fop.dom.svg.SVGRectElementImpl; +import org.apache.fop.dom.svg.SVGTextElementImpl; +import org.apache.fop.dom.svg.SVGLineElementImpl; +import org.apache.fop.dom.svg.SVGArea; // Java import java.io.IOException; @@ -69,6 +80,7 @@ import java.io.PrintWriter; import java.util.Enumeration; import java.awt.Rectangle; import java.util.Vector; +import java.util.Hashtable; /** * Renderer that renders areas to PDF @@ -144,47 +156,117 @@ public class PDFRenderer implements Renderer { * * @param areaTree the laid-out area tree * @param writer the PrintWriter to write the PDF with - */ - public void render(AreaTree areaTree, PrintWriter writer) + */ + public void render(AreaTree areaTree, PrintWriter writer) throws IOException, FOPException { MessageHandler.logln("rendering areas to PDF"); idReferences=areaTree.getIDReferences(); this.pdfResources = this.pdfDoc.getResources(); this.pdfDoc.setIDReferences(idReferences); - Enumeration e = areaTree.getPages().elements(); + Enumeration e = areaTree.getPages().elements(); while ( e.hasMoreElements() ) { - this.renderPage((Page) e.nextElement()); - } + this.renderPage((Page) e.nextElement()); + } if ( !idReferences.isEveryIdValid() ) { throw new FOPException("The id \""+idReferences.getNextInvalidId()+"\" was referenced but does not exist\n"); } MessageHandler.logln("writing out PDF"); - this.pdfDoc.output(writer); - } + this.pdfDoc.output(writer); + } + /** + * add a line to the current stream + * + * @param x1 the start x location in millipoints + * @param y1 the start y location in millipoints + * @param x2 the end x location in millipoints + * @param y2 the end y location in millipoints + * @param th the thickness in millipoints + * @param r the red component + * @param g the green component + * @param b the blue component + */ + protected void addLine(int x1, int y1, int x2, int y2, int th, PDFPathPaint stroke) + { + currentStream.add(stroke.getColorSpaceOut(false)); + currentStream.add(th / 1000f + " w\n"); + addLine(x1/1000f, y1/1000f, x2/1000f, y2/1000f, false); + currentStream.add("0 G\n"); + } + /** + * add a line to the current stream + * + * @param x1 the start x location in millipoints + * @param y1 the start y location in millipoints + * @param x2 the end x location in millipoints + * @param y2 the end y location in millipoints + * @param th the thickness in millipoints + * @param r the red component + * @param g the green component + * @param b the blue component + */ + protected void addLine(float x1, float y1, float x2, float y2, boolean fill) + { + String str; + str = "" + x1 + " " + y1 + " m " + + x2 + " " + y2 + " l"; + if(fill) + currentStream.add(str + " f\n"); + currentStream.add(str + " S\n"); + } - /** - * add a line to the current stream - * - * @param x1 the start x location in millipoints - * @param y1 the start y location in millipoints - * @param x2 the end x location in millipoints - * @param y2 the end y location in millipoints - * @param th the thickness in millipoints - * @param stroke the stroke color/gradient - */ - protected void addLine(int x1, int y1, int x2, int y2, int th, - PDFPathPaint stroke) { - - currentStream.add(stroke.getColorSpaceOut(false) - + (x1/1000f) + " " + (y1/1000f) + " m " - + (x2/1000f) + " " + (y2/1000f) + " l " - + (th/1000f) + " w S\n" - + "0 0 0 RG\n"); - } + protected void addCircle(float cx, float cy, float r, boolean fill) + { + String str; + str = "" + cx + " " + (cy - r) + " m\n" + + "" + (cx + 21 * r / 40f) + " " + (cy - r) + " " + (cx + r) + " " + (cy - 21 * r / 40f) + " " + (cx + r) + " " + cy + " c\n" + + "" + (cx + r) + " " + (cy + 21 * r / 40f) + " " + (cx + 21 * r / 40f) + " " + (cy + r) + " " + cx + " " + (cy + r) + " c\n" + + "" + (cx - 21 * r / 40f) + " " + (cy + r) + " " + (cx - r) + " " + (cy + 21 * r / 40f) + " " + (cx - r) + " " + cy + " c\n" + + "" + (cx - r) + " " + (cy - 21 * r / 40f) + " " + (cx - 21 * r / 40f) + " " + (cy - r) + " " + cx + " " + (cy - r) + " c\n"; + + if(fill) + currentStream.add(str + "f\n"); + currentStream.add(str + "S\n"); + } + + protected void addEllipse(float cx, float cy, float rx, float ry, boolean fill) + { + String str; + str = "" + cx + " " + (cy - ry) + " m\n" + + "" + (cx + 21 * rx / 40f) + " " + (cy - ry) + " " + (cx + rx) + " " + (cy - 21 * ry / 40f) + " " + (cx + rx) + " " + cy + " c\n" + + "" + (cx + rx) + " " + (cy + 21 * ry / 40f) + " " + (cx + 21 * rx / 40f) + " " + (cy + ry) + " " + cx + " " + (cy + ry) + " c\n" + + "" + (cx - 21 * rx / 40f) + " " + (cy + ry) + " " + (cx - rx) + " " + (cy + 21 * ry / 40f) + " " + (cx - rx) + " " + cy + " c\n" + + "" + (cx - rx) + " " + (cy - 21 * ry / 40f) + " " + (cx - 21 * rx / 40f) + " " + (cy - ry) + " " + cx + " " + (cy - ry) + " c\n"; + if(fill) + currentStream.add(str + "f\n"); + currentStream.add(str + "S\n"); + } + + /** + * add a filled rectangle to the current stream + * + * @param x the x position of left edge in millipoints + * @param y the y position of top edge in millipoints + * @param w the width in millipoints + * @param h the height in millipoints + * @param r the red component of edges + * @param g the green component of edges + * @param b the blue component of edges + * @param fr the red component of the fill + * @param fg the green component of the fill + * @param fb the blue component of the fill + */ + protected void addRect(float x, float y, float w, float h, boolean fill) + { + String str = "" + x + " " + y + " " + + w + " " + h + " re"; + if(fill) + currentStream.add(str + " f\n"); + currentStream.add(str + " S\n"); + } /** * add a rectangle to the current stream @@ -200,7 +282,7 @@ public class PDFRenderer implements Renderer { currentStream.add(stroke.getColorSpaceOut(false) + (x/1000f) + " " + (y/1000f) + " " + (w/1000f) + " " + (h/1000f) + " re S\n" - + "0 0 0 RG\n"); + + "0 G\n"); } /** @@ -222,22 +304,190 @@ public class PDFRenderer implements Renderer { + (w/1000f) + " " + (h/1000f) + " re S\n" + (x/1000f) + " " + (y/1000f) + " " + (w/1000f) + " " + (h/1000f) + " re f\n" - + "0 0 0 RG 0 0 0 rg\n"); - } + + "0 g\n"); + } - /** - * render area container to PDF - * - * @param area the area container to render - */ - public void renderAreaContainer(AreaContainer area) { - - int saveY = this.currentYPosition; - int saveX = this.currentAreaContainerXPosition; - - if (area.getPosition() == Position.ABSOLUTE) { - // Y position is computed assuming positive Y axis, adjust for negative postscript one - this.currentYPosition = area.getYPosition() - 2 * area.getPaddingTop() - 2 * area.borderWidthTop; + protected void addPath(Vector points, int posx, int posy, boolean fill) + { + SVGPathSegImpl pathmoveto = null; + float lastx = 0; + float lasty = 0; + for(Enumeration e = points.elements(); e.hasMoreElements(); ) { + SVGPathSegImpl pc = (SVGPathSegImpl)e.nextElement(); + float[] vals = pc.getValues(); + float lastcx = 0; + float lastcy = 0; + switch(pc.getPathSegType()) { + case SVGPathSeg.SVG_PATHSEG_MOVETO_ABS: + pathmoveto = pc; + lastx = vals[0]; + lasty = vals[1]; + currentStream.add(lastx + " " + lasty + " m\n"); + break; + case SVGPathSeg.SVG_PATHSEG_MOVETO_REL: + if(pathmoveto == null) { + lastx = vals[0]; + lasty = vals[1]; + pathmoveto = pc; + currentStream.add(lastx + " " + lasty + " m\n"); + } else { + lastx += vals[0]; + lasty += vals[1]; + currentStream.add(lastx + " " + lasty + " l\n"); + } + break; + case SVGPathSeg.SVG_PATHSEG_LINETO_ABS: + lastx = vals[0]; + lasty = vals[1]; + currentStream.add(lastx + " " + lasty + " l\n"); + break; + case SVGPathSeg.SVG_PATHSEG_LINETO_REL: + lastx += vals[0]; + lasty += vals[1]; + currentStream.add(lastx + " " + lasty + " l\n"); + break; + case SVGPathSeg.SVG_PATHSEG_LINETO_VERTICAL_ABS: + lasty = vals[0]; + currentStream.add(lastx + " " + lasty + " l\n"); + break; + case SVGPathSeg.SVG_PATHSEG_LINETO_VERTICAL_REL: + lasty += vals[0]; + currentStream.add(lastx + " " + lasty + " l\n"); + break; + case SVGPathSeg.SVG_PATHSEG_LINETO_HORIZONTAL_ABS: + lastx = vals[0]; + currentStream.add(lastx + " " + lasty + " l\n"); + break; + case SVGPathSeg.SVG_PATHSEG_LINETO_HORIZONTAL_REL: + lastx += vals[0]; + currentStream.add(lastx + " " + lasty + " l\n"); + break; + case SVGPathSeg.SVG_PATHSEG_CURVETO_CUBIC_ABS: + lastx = vals[4]; + lasty = vals[5]; + lastcx = vals[2]; + lastcy = vals[3]; + currentStream.add((vals[0]) + " " + (vals[1]) + " " + + (vals[2]) + " " + (vals[3]) + " " + + lastx + " " + lasty + + " c\n"); + break; + case SVGPathSeg.SVG_PATHSEG_CURVETO_CUBIC_REL: + currentStream.add((vals[0] + lastx) + " " + (vals[1] + lasty) + " " + + (vals[2] + lastx) + " " + (vals[3] + lasty) + " " + + (vals[4] + lastx) + " " + (vals[5] + lasty) + + " c\n"); + lastcx = vals[2] + lastx; + lastcy = vals[3] + lasty; + lastx += vals[4]; + lasty += vals[5]; + break; + case SVGPathSeg.SVG_PATHSEG_CURVETO_CUBIC_SMOOTH_ABS: + if(lastcx == 0) { + lastcx = lastx; + } + if(lastcy == 0) { + lastcy = lasty; + } + lastx = vals[2]; + lasty = vals[3]; + currentStream.add(lastcx + " " + lastcy + " " + + (vals[0]) + " " + (vals[1]) + " " + + lastx + " " + lasty + + " c\n"); + break; + case SVGPathSeg.SVG_PATHSEG_CURVETO_CUBIC_SMOOTH_REL: + if(lastcx == 0) { + lastcx = lastx; + } + if(lastcy == 0) { + lastcy = lasty; + } + currentStream.add(lastcx + " " + lastcy + " " + + (vals[0] + lastx) + " " + (vals[1] + lasty) + " " + + (vals[2] + lastx) + " " + (vals[3] + lasty) + + " c\n"); + lastx += vals[2]; + lasty += vals[3]; + break; + case SVGPathSeg.SVG_PATHSEG_CURVETO_QUADRATIC_ABS: + if(lastcx == 0) { + lastcx = lastx; + } + if(lastcy == 0) { + lastcy = lasty; + } + lastx = vals[0]; + lasty = vals[1]; + lastcx = 0; + lastcy = 0; + currentStream.add(lastcx + " " + lastcy + " " + + lastx + " " + lasty + + " y\n"); + break; + case SVGPathSeg.SVG_PATHSEG_CURVETO_QUADRATIC_REL: + if(lastcx == 0) { + lastcx = lastx; + } + if(lastcy == 0) { + lastcy = lasty; + } + currentStream.add(lastcx + " " + lastcy + " " + + (vals[0] + lastx) + " " + (vals[1] + lasty) + + " y\n"); + lastcx = 0; + lastcy = 0; + lastx += vals[0]; + lasty += vals[1]; + break; + case SVGPathSeg.SVG_PATHSEG_CLOSEPATH: + currentStream.add("h\n"); + break; + } + } + if(fill) + currentStream.add("B\n"); + currentStream.add("S\n"); + } + + protected void addPolyline(Vector points, int posx, int posy, boolean fill, boolean close) + { + PathPoint pc; + float lastx = 0; + float lasty = 0; + Enumeration e = points.elements(); + if(e.hasMoreElements()) { + pc = (PathPoint)e.nextElement(); + lastx = pc.x; + lasty = pc.y; + currentStream.add(lastx + " " + lasty + " m\n"); + } + while(e.hasMoreElements()) { + pc = (PathPoint)e.nextElement(); + lastx = pc.x; + lasty = pc.y; + currentStream.add(lastx + " " + lasty + " l\n"); + } + if(close) + currentStream.add("h\n"); + if(fill) + currentStream.add("b\n"); + currentStream.add("S\n"); + } + + /** + * render area container to PDF + * + * @param area the area container to render + */ + public void renderAreaContainer(AreaContainer area) { + + int saveY = this.currentYPosition; + int saveX = this.currentAreaContainerXPosition; + + if (area.getPosition() == Position.ABSOLUTE) { + // Y position is computed assuming positive Y axis, adjust for negative postscript one + this.currentYPosition = area.getYPosition() - 2 * area.getPaddingTop() - 2 * area.borderWidthTop; this.currentAreaContainerXPosition = area.getXPosition(); } else if (area.getPosition() == Position.RELATIVE) { this.currentYPosition -= area.getYPosition(); @@ -357,52 +607,643 @@ public class PDFRenderer implements Renderer { (((float) x) / 1000f) + " " + (((float) (y - h)) / 1000f) + " cm\n" + "/Im" + xObjectNum + " Do\nQ\nBT\n"); + } + + public void renderImage(String href, float x, float y, float width, float height) + { + try { + FopImage img = FopImageFactory.Make(href); + if(img != null) { + int xObjectNum = this.pdfDoc.addImage(img); + currentStream.add("q\n" + width + " 0 0 " + + height + " " + + x + " " + + y + " cm\n" + + "/Im" + xObjectNum + " Do\nQ\n"); +// img.close(); + } + } catch(Exception e) { + System.err.println("could not add image to SVG: " + href); + } } - - /** - * render SVG area to PDF - * - * @param area the SVG area to render - */ + + /** + * render SVG area to PDF + * + * @param area the SVG area to render + */ public void renderSVGArea(SVGArea area) { - int x = this.currentAreaContainerXPosition; - int y = this.currentYPosition; - int w = area.getContentWidth(); - int h = area.getHeight(); - this.currentYPosition -= h; - Enumeration e = area.getChildren().elements(); - while (e.hasMoreElements()) { - Object o = e.nextElement(); - if (o instanceof RectGraphic) { - int rx = ((RectGraphic)o).x; - int ry = ((RectGraphic)o).y; - int rw = ((RectGraphic)o).width; - int rh = ((RectGraphic)o).height; - addRect(x+rx,y-ry,rw,-rh,new PDFColor(0,0,0)); - } else if (o instanceof LineGraphic) { - int x1 = ((LineGraphic)o).x1; - int y1 = ((LineGraphic)o).y1; - int x2 = ((LineGraphic)o).x2; - int y2 = ((LineGraphic)o).y2; - addLine(x+x1,y-y1,x+x2,y-y2,0,new PDFColor(0,0,0)); - } else if (o instanceof TextGraphic) { - int tx = ((TextGraphic)o).x; - int ty = ((TextGraphic)o).y; - String s = ((TextGraphic)o).s; - currentStream.add("1 0 0 1 " - + ((x+tx)/1000f) + " " - + ((y-ty)/1000f) + " Tm " - + "(" + s + ") Tj\n"); + int x = this.currentAreaContainerXPosition; + int y = this.currentYPosition; + int w = area.getContentWidth(); + int h = area.getHeight(); + this.currentYPosition -= h; + + currentStream.add("ET\n"); + /* + * Clip to the svg area. + * Note: To have the svg overlay (under) a text area then use + * an fo:block-container + */ + currentStream.add("q\n"); + currentStream.add(x / 1000f + " " + y / 1000f + " m\n"); + currentStream.add((x + w) / 1000f + " " + y / 1000f + " l\n"); + currentStream.add((x + w) / 1000f + " " + (y - h) / 1000f + " l\n"); + currentStream.add(x / 1000f + " " + (y - h) / 1000f + " l\n"); + currentStream.add("h\n"); + currentStream.add("W\n"); + currentStream.add("n\n"); + // transform so that the coordinates (0,0) is from the top left + // and positive is down and to the right + currentStream.add(1 + " " + 0 + " " + 0 + " " + (-1) + " " + x / 1000f + " " + y / 1000f + " cm\n"); + + // TODO - translate and clip to viewbox + + Enumeration e = area.getChildren().elements(); + while (e.hasMoreElements()) { + Object o = e.nextElement(); + if(o instanceof GraphicImpl) { + renderElement(area, (GraphicImpl)o, x, y); + } } + + currentStream.add("Q\n"); + currentStream.add("BT\n"); } + + void handleGradient(String sp, boolean fill, GraphicImpl area) + { + // should be a url to a gradient + String url = (String)sp; + if(url.startsWith("url(")) { + String address; + int b1 = url.indexOf("("); + int b2 = url.indexOf(")"); + address = url.substring(b1 + 1, b2); + address = address.trim(); + // local reference + if(address.startsWith("#")) { + // find the gradient element + GraphicImpl gi = area.locateDef(address.substring(1, address.length())); +// System.out.println(gi + ":" + address.substring(1, address.length())); + if(gi instanceof SVGLinearGradientElement) { + SVGLinearGradientElement linear = (SVGLinearGradientElement)gi; + + Vector theCoords = new Vector(); + theCoords.addElement(new Double(linear.getX1().getValue())); + theCoords.addElement(new Double(linear.getY1().getValue())); + theCoords.addElement(new Double(linear.getX2().getValue())); + theCoords.addElement(new Double(linear.getY2().getValue())); + + Vector theExtend = new Vector(); + theExtend.addElement(new Boolean(true)); + theExtend.addElement(new Boolean(true)); + + Vector theDomain = new Vector(); + theDomain.addElement(new Double(0)); + theDomain.addElement(new Double(1)); + + Vector theEncode = new Vector(); + theEncode.addElement(new Double(0)); + theEncode.addElement(new Double(1)); + theEncode.addElement(new Double(0)); + theEncode.addElement(new Double(1)); + + Vector theBounds = new Vector(); + theBounds.addElement(new Double(0)); + theBounds.addElement(new Double(1)); + + Vector theFunctions = new Vector(); + + org.w3c.dom.NodeList nl = linear.getChildNodes(); + Vector someColors = new Vector(); + float lastoffset = 0; + Vector lastVector = null; + SVGStopElementImpl stop; + Hashtable table; + for(int count = 0; count < nl.getLength(); count++) { + stop = (SVGStopElementImpl)nl.item(count); + table = stop.getStyle(); + ColorType sc = (ColorType)table.get("stop-color"); + if(sc == null) { + // maybe using color + sc = (ColorType)table.get("color"); + } + if(sc == null) { + // problems + System.err.println("no stop-color or color in stop element"); + continue; + } + float offset = stop.getOffset(); + PDFColor color = new PDFColor(sc.red(), sc.green(), sc.blue()); + Vector colVector = color.getVector(); + // create bounds from last to offset + if(lastVector != null) { + Vector theCzero = lastVector; + Vector theCone = colVector; + PDFFunction myfunc = this.pdfDoc.makeFunction(2, theDomain, null, + theCzero, theCone, 1.0); + theFunctions.addElement(myfunc); + } + lastoffset = offset; + lastVector = colVector; + someColors.addElement(color); + } + ColorSpace aColorSpace = new ColorSpace(ColorSpace.DEVICE_RGB); +/* PDFFunction myfunky = this.pdfDoc.makeFunction(3, + theDomain, null, + theFunctions, null, + theEncode); + PDFShading myShad = null; + myShad = this.pdfDoc.makeShading( + 2, aColorSpace, + null, null, false, + theCoords, null, myfunky,theExtend); + PDFPattern myPat = this.pdfDoc.makePattern(2, myShad, null, null, null);*/ + PDFPattern myPat = this.pdfDoc.createGradient(false, aColorSpace, someColors,null,theCoords); + currentStream.add(myPat.getColorSpaceOut(fill)); + } else if(gi instanceof SVGRadialGradientElement) { + SVGRadialGradientElement radial = (SVGRadialGradientElement)gi; + ColorSpace aColorSpace = new ColorSpace(ColorSpace.DEVICE_RGB); + org.w3c.dom.NodeList nl = radial.getChildNodes(); + SVGStopElementImpl stop; + Hashtable table; + Vector someColors = new Vector(); + Vector theCoords = new Vector(); + Vector theBounds = new Vector(); + // todo handle gradient units + SVGRect bbox = null; + if(area instanceof SVGRectElement) { + bbox = ((SVGRectElement)area).getBBox(); + } + short units = radial.getGradientUnits(); + switch(units) { + case SVGUnitTypes.SVG_UNIT_TYPE_OBJECTBOUNDINGBOX: + break; + case SVGUnitTypes.SVG_UNIT_TYPE_UNKNOWN: + default: + } + // check value types, eg. % + if(bbox != null) { + theCoords.addElement(new Double(bbox.getX().getValue() + + radial.getCx().getValue() * bbox.getWidth().getValue())); + theCoords.addElement(new Double(bbox.getY().getValue() + + radial.getCy().getValue() * bbox.getHeight().getValue())); + theCoords.addElement(new Double(radial.getR().getValue() * + bbox.getHeight().getValue())); + theCoords.addElement(new Double(bbox.getX().getValue() + + radial.getFx().getValue() * bbox.getWidth().getValue())); + theCoords.addElement(new Double(bbox.getY().getValue() + + radial.getFy().getValue() * bbox.getHeight().getValue())); + theCoords.addElement(new Double(radial.getR().getValue())); + } else { + theCoords.addElement(new Double(radial.getCx().getValue())); + theCoords.addElement(new Double(radial.getCy().getValue())); + theCoords.addElement(new Double(radial.getR().getValue())); + theCoords.addElement(new Double(radial.getFx().getValue())); // Fx + theCoords.addElement(new Double(radial.getFy().getValue())); // Fy + theCoords.addElement(new Double(radial.getR().getValue())); + } + float lastoffset = 0; + for(int count = 0; count < nl.getLength(); count++) { + stop = (SVGStopElementImpl)nl.item(count); + table = stop.getStyle(); + ColorType sc = (ColorType)table.get("stop-color"); + if(sc == null) { + // maybe using color + sc = (ColorType)table.get("color"); + } + if(sc == null) { + // problems + System.err.println("no stop-color or color in stop element"); + continue; + } + float offset = stop.getOffset(); + PDFColor color = new PDFColor(sc.red(), sc.green(), sc.blue()); + // create bounds from last to offset + lastoffset = offset; + someColors.addElement(color); + } + PDFPattern myPat = this.pdfDoc.createGradient(true, aColorSpace, someColors,null,theCoords); + + currentStream.add(myPat.getColorSpaceOut(fill)); + } else { + System.err.println("WARNING Invalid fill reference :" + gi + ":" + address); + } + } + } } - /** - * render inline area to PDF + /* + * This sets up the style for drawing objects. + * Should only set style for elements that have changes. * - * @param area inline area to render */ - public void renderInlineArea(InlineArea area) { + protected boolean applyStyle(GraphicImpl area, Hashtable style) + { + boolean fill = false; + Object sp; + sp = style.get("fill"); + if(sp != null) { + if(sp instanceof ColorType) { + ColorType ct = (ColorType)sp; + PDFColor fillColour = new PDFColor(ct.red(), ct.green(), ct.blue()); + currentStream.add(fillColour.getColorSpaceOut(true)); + } else if (sp instanceof String) { + handleGradient((String)sp, true, area); + } + fill = true; + } else { + } + sp = style.get("stroke"); + if(sp != null) { + if(sp instanceof ColorType) { + ColorType ct = (ColorType)sp; + PDFColor fillColour = new PDFColor(ct.red(), ct.green(), ct.blue()); + currentStream.add(fillColour.getColorSpaceOut(false)); + } else if(sp instanceof String) { + handleGradient((String)sp, false, area); + } + } else { + } + sp = style.get("stroke-width"); + if(sp != null) { + float width; + width = ((SVGLengthImpl)sp).getValue(); + PDFNumber pdfNumber = new PDFNumber(); + currentStream.add(pdfNumber.doubleOut(width) + " w\n"); + } + sp = style.get("stroke-dasharray"); + if(sp != null) { + Vector list; + list = (Vector)sp; + currentStream.add("[ "); + for(Enumeration e = list.elements(); e.hasMoreElements(); ) { + Integer val = (Integer)e.nextElement(); + currentStream.add(val.intValue() + " "); + } + sp = style.get("stroke-offset"); + if(sp != null) { + float width; + width = ((SVGLengthImpl)sp).getValue(); + PDFNumber pdfNumber = new PDFNumber(); + currentStream.add("] " + pdfNumber.doubleOut(width) + " d\n"); + } else { + currentStream.add("] 0 d\n"); + } + + } + sp = style.get("mask"); + if(sp != null) { + String maskurl; + maskurl = (String)sp; + maskurl = maskurl.substring(1, maskurl.length()); + // get def of mask and set mask +// Hashtable defs; + GraphicImpl graph = null; + graph = area.locateDef(maskurl); +// defs = area.getDefs(); +// if(defs != null) +// graph = (GraphicImpl)defs.get(maskurl); + if(graph != null) { + GraphicImpl parent = graph.getGraphicParent(); + graph.setParent(area); +// renderElement(svgarea, graph, posx, posy); + graph.setParent(parent); + } + } + return fill; + } + + protected void applyTransform(Vector trans) + { + PDFNumber pdfNumber = new PDFNumber(); + for(Enumeration e = trans.elements(); e.hasMoreElements(); ) { + SVGTransform t = (SVGTransform)e.nextElement(); + SVGMatrix matrix = t.getMatrix(); + currentStream.add(pdfNumber.doubleOut(matrix.getA()) + " " + pdfNumber.doubleOut(matrix.getB()) + " " + pdfNumber.doubleOut(matrix.getC()) + + " " + pdfNumber.doubleOut(matrix.getD()) + " " + pdfNumber.doubleOut(matrix.getE().getValue()) + " " + pdfNumber.doubleOut(matrix.getF().getValue()) + " cm\n"); + } + } + + public void renderElement(SVGArea svgarea, GraphicImpl area, int posx, int posy) + { + int x = posx; + int y = posy; + Hashtable style = area.getStyle(); + boolean fill = false; + + currentStream.add("q\n"); + Vector trans = area.oldgetTransform(); + if(trans != null) { + applyTransform(trans); + } + + if(style != null) { + fill = applyStyle(area, style); + } + + if (area instanceof SVGRectElement) { + SVGRectElement rg = (SVGRectElement)area; + float rx = rg.getX().getValue(); + float ry = rg.getY().getValue(); + float rw = rg.getWidth().getValue(); + float rh = rg.getHeight().getValue(); + addRect(rx, ry, rw, rh, fill); + } else if (area instanceof SVGLineElement) { + SVGLineElement lg = (SVGLineElement)area; + float x1 = lg.getX1().getValue(); + float y1 = lg.getY1().getValue(); + float x2 = lg.getX2().getValue(); + float y2 = lg.getY2().getValue(); + addLine(x1,y1,x2,y2, fill); + } else if (area instanceof SVGTextElementImpl) { +// currentStream.add("q\n"); +// currentStream.add(1 + " " + 0 + " " + 0 + " " + 1 + " " + 0 + " " + 0 + " cm\n"); + currentStream.add("BT\n"); + renderText(svgarea, (SVGTextElementImpl)area, 0, 0); + currentStream.add("ET\n"); +// currentStream.add("Q\n"); + } else if (area instanceof SVGCircleElement) { + SVGCircleElement cg = (SVGCircleElement)area; + float cx = cg.getCx().getValue(); + float cy = cg.getCy().getValue(); + float r = cg.getR().getValue(); + addCircle(cx,cy,r, fill); + } else if (area instanceof SVGEllipseElement) { + SVGEllipseElement cg = (SVGEllipseElement)area; + float cx = cg.getCx().getValue(); + float cy = cg.getCy().getValue(); + float rx = cg.getRx().getValue(); + float ry = cg.getRy().getValue(); + addEllipse(cx,cy,rx,ry, fill); + } else if (area instanceof SVGPathElementImpl) { + addPath(((SVGPathElementImpl)area).pathElements, posx, posy, fill); + } else if (area instanceof SVGPolylineElementImpl) { + addPolyline(((SVGPolylineElementImpl)area).points, posx, posy, fill, false); + } else if (area instanceof SVGPolygonElementImpl) { + addPolyline(((SVGPolygonElementImpl)area).points, posx, posy, fill, true); + } else if (area instanceof SVGGElementImpl) { + renderGArea(svgarea, (SVGGElementImpl)area, x, y); + } else if(area instanceof SVGUseElementImpl) { + SVGUseElementImpl ug = (SVGUseElementImpl)area; + String ref = ug.link; + ref = ref.substring(1, ref.length()); +// Hashtable defs; + GraphicImpl graph = null; + graph = area.locateDef(ref); +// defs = ug.getDefs(); +// if(defs != null) +// graph = (GraphicImpl)defs.get(ref); +// if(graph == null) { + // find element inside parent. +// } + if(graph != null) { + // probably not the best way to do this, should be able + // to render without the style being set. + GraphicImpl parent = graph.getGraphicParent(); + graph.setParent(area); + // need to clip (if necessary) to the use area + // the style of the linked element is as if is was + // a direct descendant of the use element. + renderElement(svgarea, graph, posx, posy); + graph.setParent(parent); + } + } else if (area instanceof SVGImageElementImpl) { + SVGImageElementImpl ig = (SVGImageElementImpl)area; + renderImage(ig.link, ig.x, ig.y, ig.width, ig.height); + } else if (area instanceof SVGArea) { + // the x and y pos will be wrong! + Enumeration e = ((SVGArea)area).getChildren().elements(); + currentStream.add("q\n"); + while (e.hasMoreElements()) { + Object o = e.nextElement(); + if(o instanceof GraphicImpl) { + renderElement((SVGArea)area, (GraphicImpl)o, x, y); + } + } + currentStream.add("Q\n"); + } + // should be done with some cleanup code, so only + // required values are reset. + currentStream.add("Q\n"); + } + +// need to escape certain chars + public void renderText(SVGArea svgarea, SVGTextElementImpl tg, float x, float y) + { + FontState fontState = svgarea.getFontState(); + PDFNumber pdfNumber = new PDFNumber(); + + Hashtable styles; + styles = tg.getStyle(); + applyStyle(tg, styles); + // apply transform + // text has a Tm and need to handle each element + SVGTransformList trans = tg.getTransform(); + SVGMatrix matrix = trans.consolidate().getMatrix(); + String transstr = (pdfNumber.doubleOut(matrix.getA()) + + " " + pdfNumber.doubleOut(matrix.getB()) + + " " + pdfNumber.doubleOut(matrix.getC()) + + " " + pdfNumber.doubleOut(-matrix.getD()) + " "); + + String fontFamily; + fontFamily = (String)styles.get("font-family"); + if(fontFamily == null) + fontFamily = fontState.getFontFamily(); + String fontStyle; + fontStyle = (String)styles.get("font-style"); + if(fontStyle == null) + fontStyle = fontState.getFontStyle(); + String fontWeight; + fontWeight = (String)styles.get("font-weight"); + if(fontWeight == null) + fontWeight = fontState.getFontWeight(); + SVGLength len; + len = (SVGLength)styles.get("font-size"); + float fontSize; + fontSize = fontState.getFontSize() / 1000f; + if(len != null) + fontSize = len.getValue(); + FontState fs = fontState; + try { + fs = new FontState(fontState.getFontInfo(), fontFamily, fontStyle, + fontWeight, (int)(fontSize * 1000)); + } catch(Exception fope) { +// fope.printStackTrace(); + } + + currentStream.add("/" + fs.getFontName() + " " + fontSize + " Tf\n"); + + float tx = tg.x; + float ty = tg.y; + float currentX = x + tx; + Vector list = tg.textList; + for(Enumeration e = list.elements(); e.hasMoreElements(); ) { + Object o = e.nextElement(); + if(o instanceof String) { + String str = (String)o; + currentStream.add(transstr + + (currentX + matrix.getE().getValue()) + " " + + (y+ty + matrix.getF().getValue()) + " Tm " + + "(" + str + ") Tj\n"); + for(int count = 0; count < str.length(); count++) { + currentX += fs.width(str.charAt(count)) / 1000f; + } + currentX += fs.width(' ') / 1000f; + } else if(o instanceof SVGTextPathElementImpl) { + SVGTextPathElementImpl tpg = (SVGTextPathElementImpl)o; + String ref = tpg.str; +// Hashtable defs; + GraphicImpl graph = null; + graph = tpg.locateDef(ref); +// defs = tpg.getDefs(); +// if(defs != null) +// graph = (GraphicImpl)defs.get(ref); + if(graph != null && graph instanceof SVGPathElementImpl) { + // probably not the best way to do this, should be able + // to render without the style being set. + GraphicImpl parent = graph.getGraphicParent(); + graph.setParent(tpg); + // set text path?? + // how should this work + graph.setParent(parent); + } + } else if(o instanceof SVGTRefElementImpl) { + SVGTRefElementImpl trg = (SVGTRefElementImpl)o; + String ref = trg.ref; + ref = ref.substring(1, ref.length()); +// Hashtable defs; + GraphicImpl graph = null; + graph = trg.locateDef(ref); +// defs = trg.getDefs(); +// if(defs != null) +// graph = (GraphicImpl)defs.get(ref); + if(graph != null && graph instanceof SVGTextElementImpl) { + GraphicImpl parent = graph.getGraphicParent(); + graph.setParent(trg); + SVGTextElementImpl te = (SVGTextElementImpl)graph; + renderText(svgarea, te, (int)(x + tx), (int)(y + ty)); + graph.setParent(parent); + } + } else if(o instanceof SVGTSpanElementImpl) { + // TODO handle dy properly + SVGTSpanElementImpl tsg = (SVGTSpanElementImpl)o; + styles = tsg.getStyle(); + applyStyle(tsg, styles); + boolean changed = false; + + String newprop; + newprop = (String)styles.get("font-family"); + if(newprop != null && !newprop.equals(fontFamily)) { + fontFamily = newprop; + changed = true; + } + newprop = (String)styles.get("font-style"); + if(newprop != null && !newprop.equals(fontStyle)) { + fontStyle = newprop; + changed = true; + } + newprop = (String)styles.get("font-weight"); + if(newprop != null && !newprop.equals(fontWeight)) { + fontWeight = newprop; + changed = true; + } + len = (SVGLengthImpl)styles.get("font-size"); + if(len != null) { + float newSize = len.getValue(); + if(fontSize != newSize) { + fontSize = newSize; + changed = true; + } + } + if(changed) { + try { + fs = new FontState(fontState.getFontInfo(), fontFamily, fontStyle, + fontWeight, (int)(fontSize * 1000)); + } catch(Exception fope) { + } + + currentStream.add("/" + fs.getFontName() + " " + fontSize + " Tf\n"); + } + + if(tsg.ylist != null) { + ty = ((Float)tsg.ylist.elementAt(0)).floatValue(); + } + if(tsg.xlist != null) { + Enumeration enum = tsg.xlist.elements(); + int count = 0; + while(enum.hasMoreElements() && count < tsg.str.length()) { + float pos = ((Float)enum.nextElement()).floatValue(); + currentStream.add(transstr + + (x + pos + matrix.getE().getValue()) + " " + + (y + ty + tsg.dy + matrix.getF().getValue()) + " Tm " + + "(" + tsg.str.charAt(count) + ") Tj\n"); + currentX = x + pos + fs.width(tsg.str.charAt(count)) / 1000f; + count++; + } + if(enum.hasMoreElements()) { + // do nothing + } else if(count < tsg.str.length()) { + currentStream.add(transstr + + (currentX + matrix.getE().getValue()) + " " + + (y + ty + tsg.dy + matrix.getF().getValue()) + " Tm " + + "(" + tsg.str.substring(count, tsg.str.length()) + ") Tj\n"); + } + } else if(tsg.dxlist != null) { + Enumeration enum = tsg.dxlist.elements(); + int count = 0; + while(enum.hasMoreElements() && count < tsg.str.length()) { + float pos = ((Float)enum.nextElement()).floatValue(); + currentStream.add(transstr + + (currentX + pos + matrix.getE().getValue()) + " " + + (y + ty + tsg.dy + matrix.getF().getValue()) + " Tm " + + "(" + tsg.str.charAt(count) + ") Tj\n"); + currentX += pos + fs.width(tsg.str.charAt(count)) / 1000f; + count++; + } + if(enum.hasMoreElements()) { + // do nothing + } else if(count < tsg.str.length()) { + currentStream.add(transstr + + (currentX + matrix.getE().getValue()) + " " + + (y + ty + tsg.dy + matrix.getF().getValue()) + " Tm " + + "(" + tsg.str.substring(count, tsg.str.length()) + ") Tj\n"); + } + } else { +/* currentStream.add(transstr + + (((tsg.x == 0) ? (currentX) : (x))/1000f + tsg.x) + " " + + (y / 1000f - ((tsg.y == 0) ? (ty + tsg.dy) : tsg.y)) + " Tm " + + "(" + tsg.str + ") Tj\n"); + currentX = (tsg.x == 0) ? (currentX + tsg.dx) : (x + tsg.x); + for(int count = 0; count < tsg.str.length(); count++) { + currentX += fs.width(tsg.str.charAt(count)); + }*/ + } + currentX += fs.width(' ') / 1000f; + } else { + System.err.println("Error: unknown text element " + o); + } + } + } + + public void renderGArea(SVGArea svgarea, SVGGElementImpl area, int posx, int posy) + { + Enumeration e = area.getChildren().elements(); + while (e.hasMoreElements()) { + Object o = e.nextElement(); + if(o instanceof GraphicImpl) { + renderElement(svgarea, (GraphicImpl)o, posx, posy); + } + } + } + + /** + * render inline area to PDF + * + * @param area inline area to render + */ + public void renderInlineArea(InlineArea area) { char ch; StringBuffer pdf = new StringBuffer(); @@ -583,4 +1424,3 @@ public class PDFRenderer implements Renderer { FontSetup.addToResources(this.pdfDoc, fontInfo); } } - diff --git a/src/org/apache/fop/render/xml/XMLRenderer.java b/src/org/apache/fop/render/xml/XMLRenderer.java index 77a40bd69..672c58e75 100644 --- a/src/org/apache/fop/render/xml/XMLRenderer.java +++ b/src/org/apache/fop/render/xml/XMLRenderer.java @@ -53,6 +53,8 @@ package org.apache.fop.render.xml; // FOP import org.apache.fop.svg.*; import org.apache.fop.messaging.MessageHandler; +import org.apache.fop.dom.svg.*; +import org.apache.fop.dom.svg.SVGArea; import org.apache.fop.render.Renderer; import org.apache.fop.image.ImageArea; import org.apache.fop.layout.*; |