aboutsummaryrefslogtreecommitdiffstats
path: root/src/org/apache/fop/render/pdf
diff options
context:
space:
mode:
authorKeiron Liddle <keiron@apache.org>2000-08-29 00:12:15 +0000
committerKeiron Liddle <keiron@apache.org>2000-08-29 00:12:15 +0000
commit230c9191efa128e9d7c9afb3b3bf1f1e002948f8 (patch)
tree5b59fffedf52e6c150a8810c8316f1296b2843ca /src/org/apache/fop/render/pdf
parent2758565557ea2770792504e69b5e2baca1955302 (diff)
downloadxmlgraphics-fop-230c9191efa128e9d7c9afb3b3bf1f1e002948f8.tar.gz
xmlgraphics-fop-230c9191efa128e9d7c9afb3b3bf1f1e002948f8.zip
changed to handle changes to dom, styling, transform, text etc.
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@193680 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src/org/apache/fop/render/pdf')
-rw-r--r--src/org/apache/fop/render/pdf/PDFRenderer.java1718
1 files changed, 985 insertions, 733 deletions
diff --git a/src/org/apache/fop/render/pdf/PDFRenderer.java b/src/org/apache/fop/render/pdf/PDFRenderer.java
index 261e22b9e..d012f267f 100644
--- a/src/org/apache/fop/render/pdf/PDFRenderer.java
+++ b/src/org/apache/fop/render/pdf/PDFRenderer.java
@@ -65,7 +65,9 @@ import org.apache.fop.pdf.*;
import org.apache.fop.layout.*;
import org.apache.fop.image.*;
+import org.w3c.dom.*;
import org.w3c.dom.svg.*;
+import org.w3c.dom.css.*;
import org.w3c.dom.svg.SVGLength;
import org.apache.fop.dom.svg.*;
@@ -199,6 +201,556 @@ public class PDFRenderer implements Renderer {
+ "Q\nBT\n");
}
+ /**
+ * add a 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 stroke the stroke color/gradient
+ */
+ protected void addRect(int x, int y, int w, int h,
+ PDFPathPaint stroke) {
+ currentStream.add("ET\nq\n"
+ + stroke.getColorSpaceOut(false)
+ + (x/1000f) + " " + (y/1000f) + " "
+ + (w/1000f) + " " + (h/1000f) + " re s\n"
+ + "Q\nBT\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 fill the fill color/gradient
+ * @param stroke the stroke color/gradient
+ */
+ protected void addRect(int x, int y, int w, int h,
+ PDFPathPaint stroke,
+ PDFPathPaint fill) {
+ currentStream.add("ET\nq\n"
+ + fill.getColorSpaceOut(true)
+ + stroke.getColorSpaceOut(false)
+ + (x/1000f) + " " + (y/1000f) + " "
+ + (w/1000f) + " " + (h/1000f) + " re b\n"
+ + "Q\nBT\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();
+ this.currentAreaContainerXPosition += area.getXPosition();
+ } else if (area.getPosition() == Position.STATIC) {
+ this.currentYPosition -= area.getPaddingTop() + area.borderWidthTop;
+ this.currentAreaContainerXPosition += area.getPaddingLeft() + area.borderWidthLeft;
+ }
+
+ doFrame(area);
+
+ Enumeration e = area.getChildren().elements();
+ while (e.hasMoreElements()) {
+ Box b = (Box) e.nextElement();
+ b.render(this);
+ }
+ if (area.getPosition() != Position.STATIC) {
+ this.currentYPosition = saveY;
+ this.currentAreaContainerXPosition = saveX;
+ } else
+ this.currentYPosition -= area.getHeight();
+ }
+
+ private void doFrame(Area area) {
+ int w, h;
+ int rx = this.currentAreaContainerXPosition;
+ w = area.getContentWidth();
+ if (area instanceof BlockArea)
+ 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,
+ new PDFColor(bg),
+ new PDFColor(bg));
+ }
+
+ 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,
+ new PDFColor(area.borderColorTop));
+ if (area.borderWidthLeft != 0)
+ addLine(rx, ry, rx, ry - h,
+ area.borderWidthLeft,
+ new PDFColor(area.borderColorLeft));
+ if (area.borderWidthRight != 0)
+ addLine(rx + w, ry, rx + w, ry - h,
+ area.borderWidthRight,
+ new PDFColor(area.borderColorRight));
+ if (area.borderWidthBottom != 0)
+ addLine(rx, ry - h, rx + w, ry - h,
+ area.borderWidthBottom,
+ new PDFColor(area.borderColorBottom));
+
+ }
+
+
+ /**
+ * render block area to PDF
+ *
+ * @param area the block area to render
+ */
+ public void renderBlockArea(BlockArea area) {
+ doFrame(area);
+ Enumeration e = area.getChildren().elements();
+ while (e.hasMoreElements()) {
+ Box b = (Box) e.nextElement();
+ b.render(this);
+ }
+ }
+
+ /**
+ * render display space to PDF
+ *
+ * @param space the display space to render
+ */
+ public void renderDisplaySpace(DisplaySpace space) {
+ int d = space.getSize();
+ this.currentYPosition -= d;
+ }
+
+ /**
+ * render image area to PDF
+ *
+ * @param area the image area to render
+ */
+ public void renderImageArea(ImageArea area) {
+ // adapted from contribution by BoBoGi
+ int x = this.currentAreaContainerXPosition +
+ area.getXOffset();
+ int y = this.currentYPosition;
+ int w = area.getContentWidth();
+ int h = area.getHeight();
+
+ this.currentYPosition -= h;
+
+ FopImage img = area.getImage();
+
+ int xObjectNum = this.pdfDoc.addImage(img);
+
+ currentStream.add("ET\nq\n" + (((float) w) / 1000f) + " 0 0 " +
+ (((float) h) / 1000f) + " " +
+ (((float) x) / 1000f) + " " +
+ (((float) (y - h)) / 1000f) + " cm\n" +
+ "/Im" + xObjectNum + " Do\nQ\nBT\n");
+ }
+
+ /** render a foreign object area */
+ public void renderForeignObjectArea(ForeignObjectArea area)
+ {
+ // if necessary need to scale and align the content
+ int x = this.currentAreaContainerXPosition;
+ switch(area.getAlign()) {
+ case TextAlign.START:
+ break;
+ case TextAlign.END:
+ break;
+ case TextAlign.CENTER:
+ case TextAlign.JUSTIFY:
+ break;
+ }
+ switch(area.getVerticalAlign()) {
+ case VerticalAlign.BASELINE:
+ break;
+ case VerticalAlign.MIDDLE:
+ break;
+ case VerticalAlign.SUB:
+ break;
+ case VerticalAlign.SUPER:
+ break;
+ case VerticalAlign.TEXT_TOP:
+ break;
+ case VerticalAlign.TEXT_BOTTOM:
+ break;
+ case VerticalAlign.TOP:
+ break;
+ case VerticalAlign.BOTTOM:
+ break;
+ }
+ // in general the content will not be text
+ currentStream.add("ET\n");
+ // align and scale
+ currentStream.add("q\n");
+ switch(area.scalingMethod()) {
+ case Scaling.UNIFORM:
+ break;
+ case Scaling.NON_UNIFORM:
+ break;
+ }
+ // if the overflow is auto (default), scroll or visible
+ // then the contents should not be clipped, since this
+ // is considered a printing medium.
+ switch(area.getOverflow()) {
+ case Overflow.VISIBLE:
+ case Overflow.SCROLL:
+ case Overflow.AUTO:
+ break;
+ case Overflow.HIDDEN:
+ break;
+ }
+ area.getObject().render(this);
+ currentStream.add("Q\n");
+ currentStream.add("BT\n");
+ this.currentYPosition -= area.getEffectiveHeight();
+ }
+
+ /**
+ * 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;
+ SVGSVGElement svg = area.getSVGDocument().getRootElement();
+ int w = (int)(svg.getWidth().getBaseVal().getValue() * 1000);
+ int h = (int)(svg.getHeight().getBaseVal().getValue() * 1000);
+
+ /*
+ * 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
+
+ renderSVG(area.getFontState(), svg, x, y);
+
+ currentStream.add("Q\n");
+ }
+
+ /**
+ * render inline area to PDF
+ *
+ * @param area inline area to render
+ */
+ public void renderInlineArea(InlineArea area) {
+ char ch;
+ StringBuffer pdf = new StringBuffer();
+
+ String name = area.getFontState().getFontName();
+ int size = area.getFontState().getFontSize();
+
+ PDFColor theAreaColor = new PDFColor(
+ (double)area.getRed(),
+ (double)area.getGreen(),
+ (double)area.getBlue() );
+
+ if ((!name.equals(this.currentFontName))
+ || (size != this.currentFontSize)) {
+ this.currentFontName = name;
+ this.currentFontSize = size;
+ pdf = pdf.append("/" + name + " " + (size/1000) + " Tf\n");
+ }
+
+ //if (theAreaColor.isEquivalent(this.currentFill)) {
+ this.currentFill = theAreaColor;
+
+ pdf = pdf.append(this.currentFill.getColorSpaceOut(true));
+ //}
+
+ int rx = this.currentXPosition;
+ int bl = this.currentYPosition;
+
+ pdf = pdf.append("1 0 0 1 "
+ +(rx/1000f) + " " + (bl/1000f)
+ + " Tm (");
+
+ String s;
+ if ( area.getPageNumberID()!=null ) { // this text is a page number, so resolve it
+ s = idReferences.getPageNumber(area.getPageNumberID());
+ if(s==null)
+ {
+ s="";
+ }
+ }
+ else {
+ s = area.getText();
+ }
+
+ int l = s.length();
+
+ for (int i=0; i < l; i++) {
+ ch = s.charAt(i);
+ if (ch > 127) {
+ pdf = pdf.append("\\");
+ pdf = pdf.append(Integer.toOctalString((int)ch));
+ } else {
+ switch (ch) {
+ case '(' : pdf = pdf.append("\\("); break;
+ case ')' : pdf = pdf.append("\\)"); break;
+ case '\\' : pdf = pdf.append("\\\\"); break;
+ default : pdf = pdf.append(ch); break;
+ }
+ }
+ }
+ pdf = pdf.append(") Tj\n");
+
+ currentStream.add(pdf.toString());
+
+ this.currentXPosition += area.getContentWidth();
+ }
+
+ /**
+ * render inline space to PDF
+ *
+ * @param space space to render
+ */
+ public void renderInlineSpace(InlineSpace space) {
+ this.currentXPosition += space.getSize();
+ }
+
+ /**
+ * render line area to PDF
+ *
+ * @param area area to render
+ */
+ 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;
+
+ int bl = this.currentYPosition;
+
+ Enumeration e = area.getChildren().elements();
+ while (e.hasMoreElements()) {
+ Box b = (Box) e.nextElement();
+ b.render(this);
+ }
+
+ this.currentYPosition = ry-h;
+ }
+
+ /**
+ * render page into PDF
+ *
+ * @param page page to render
+ */
+ public void renderPage(Page page) {
+ AreaContainer body, before, after;
+
+ currentStream = this.pdfDoc.makeStream();
+ body = page.getBody();
+ before = page.getBefore();
+ after = page.getAfter();
+
+ this.currentFontName = "";
+ this.currentFontSize = 0;
+
+ currentStream.add("BT\n");
+ renderAreaContainer(body);
+
+ if (before != null) {
+ renderAreaContainer(before);
+ }
+
+ if (after != null) {
+ renderAreaContainer(after);
+ }
+
+ currentStream.add("ET\n");
+
+ currentPage = this.pdfDoc.makePage(this.pdfResources, currentStream,
+ page.getWidth()/1000,
+ page.getHeight()/1000, page);
+
+ if (page.hasLinks()) {
+ currentAnnotList = this.pdfDoc.makeAnnotList();
+ currentPage.setAnnotList(currentAnnotList);
+
+ Enumeration e = page.getLinkSets().elements();
+ while (e.hasMoreElements()) {
+ LinkSet linkSet = (LinkSet) e.nextElement();
+
+ linkSet.align();
+ String dest = linkSet.getDest();
+ int linkType = linkSet.getLinkType();
+ Enumeration f = linkSet.getRects().elements();
+ while (f.hasMoreElements()) {
+ LinkedRectangle lrect = (LinkedRectangle) f.nextElement();
+ currentAnnotList.addLink(
+ this.pdfDoc.makeLink(lrect.getRectangle(), dest, linkType));
+ }
+ }
+ } else {
+ // just to be on the safe side
+ currentAnnotList = null;
+ }
+ }
+
+ /**
+ * 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();
+
+ addLine(rx, ry, rx+w, ry, th, new PDFColor(area.getRed(), area.getGreen(),area.getBlue()));
+ }
+
+ /**
+ * set up the font info
+ *
+ * @param fontInfo font info to set up
+ */
+ public void setupFontInfo(FontInfo fontInfo) {
+ FontSetup.setup(fontInfo);
+ FontSetup.addToResources(this.pdfDoc, fontInfo);
+ }
+
+ // SVG Stuff
+
+ public void renderGArea(FontState fontState, SVGGElement area, int posx, int posy)
+ {
+ NodeList nl = area.getChildNodes();
+ for(int count = 0; count < nl.getLength(); count++) {
+ Node n = nl.item(count);
+ if(n instanceof SVGElement) {
+ renderElement(fontState, (SVGElement)n, posx, posy);
+ }
+ }
+ }
+
+ void handleSwitchElement(FontState fontState, int posx, int posy, SVGSwitchElement ael)
+ {
+ SVGList relist = ael.getRequiredExtensions();
+ SVGList rflist = ael.getRequiredFeatures();
+ SVGList sllist = ael.getSystemLanguage();
+ org.w3c.dom.NodeList nl = ael.getChildNodes();
+ for(int count = 0; count < nl.getLength(); count++) {
+ org.w3c.dom.Node n = nl.item(count);
+ // only render the first child that has a valid
+ // test data
+ if(n instanceof GraphicElement) {
+ GraphicElement graphic = (GraphicElement)n;
+ SVGList grelist = graphic.getRequiredExtensions();
+ // if null it evaluates to true
+ if(grelist != null) {
+ for(int i = 0; i < grelist.getNumberOfItems(); i++) {
+ String str = (String)grelist.getItem(i);
+ if(relist == null) {
+ // use default extension set
+ // currently no extensions are supported
+// if(!(str.equals("http:// ??"))) {
+ continue;
+// }
+ } else {
+ }
+ }
+ }
+ SVGList grflist = graphic.getRequiredFeatures();
+ if(grflist != null) {
+ for(int i = 0; i < grflist.getNumberOfItems(); i++) {
+ String str = (String)grflist.getItem(i);
+ if(rflist == null) {
+ // use default feature set
+ if(!(str.equals("org.w3c.svg.static")
+ || str.equals("org.w3c.dom.svg.all"))) {
+ continue;
+ }
+ } else {
+ boolean found = false;
+ for(int j = 0; j < rflist.getNumberOfItems(); j++) {
+ if(rflist.getItem(j).equals(str)) {
+ found = true;
+ break;
+ }
+ }
+ if(!found)
+ continue;
+ }
+ }
+ }
+ SVGList gsllist = graphic.getSystemLanguage();
+ if(gsllist != null) {
+ for(int i = 0; i < gsllist.getNumberOfItems(); i++) {
+ String str = (String)gsllist.getItem(i);
+ if(sllist == null) {
+ // use default feature set
+ if(!(str.equals("en"))) {
+ continue;
+ }
+ } else {
+ boolean found = false;
+ for(int j = 0; j < sllist.getNumberOfItems(); j++) {
+ if(sllist.getItem(j).equals(str)) {
+ found = true;
+ break;
+ }
+ }
+ if(!found)
+ continue;
+ }
+ }
+ }
+ renderElement(fontState, (SVGElement)n, posx, posy);
+ // only render the first valid one
+ break;
+ }
+ }
+ }
+
/**
* add a line to the current stream
*
@@ -280,45 +832,6 @@ public class PDFRenderer implements Renderer {
doDrawing(di);
}
- /**
- * add a 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 stroke the stroke color/gradient
- */
- protected void addRect(int x, int y, int w, int h,
- PDFPathPaint stroke) {
- currentStream.add("ET\nq\n"
- + stroke.getColorSpaceOut(false)
- + (x/1000f) + " " + (y/1000f) + " "
- + (w/1000f) + " " + (h/1000f) + " re s\n"
- + "Q\nBT\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 fill the fill color/gradient
- * @param stroke the stroke color/gradient
- */
- protected void addRect(int x, int y, int w, int h,
- PDFPathPaint stroke,
- PDFPathPaint fill) {
- currentStream.add("ET\nq\n"
- + fill.getColorSpaceOut(true)
- + stroke.getColorSpaceOut(false)
- + (x/1000f) + " " + (y/1000f) + " "
- + (w/1000f) + " " + (h/1000f) + " re b\n"
- + "Q\nBT\n");
- }
-
protected void addPath(Vector points, int posx, int posy, DrawingInstruction di)
{
SVGPathSegImpl pathmoveto = null;
@@ -625,151 +1138,23 @@ public class PDFRenderer implements Renderer {
}
}
- /**
- * 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();
- this.currentAreaContainerXPosition += area.getXPosition();
- } else if (area.getPosition() == Position.STATIC) {
- this.currentYPosition -= area.getPaddingTop() + area.borderWidthTop;
- this.currentAreaContainerXPosition += area.getPaddingLeft() + area.borderWidthLeft;
- }
-
- doFrame(area);
-
- Enumeration e = area.getChildren().elements();
- while (e.hasMoreElements()) {
- Box b = (Box) e.nextElement();
- b.render(this);
- }
- if (area.getPosition() != Position.STATIC) {
- this.currentYPosition = saveY;
- this.currentAreaContainerXPosition = saveX;
- } else
- this.currentYPosition -= area.getHeight();
- }
-
- private void doFrame(Area area) {
- int w, h;
- int rx = this.currentAreaContainerXPosition;
- w = area.getContentWidth();
- if (area instanceof BlockArea)
- 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,
- new PDFColor(bg),
- new PDFColor(bg));
- }
-
- 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,
- new PDFColor(area.borderColorTop));
- if (area.borderWidthLeft != 0)
- addLine(rx, ry, rx, ry - h,
- area.borderWidthLeft,
- new PDFColor(area.borderColorLeft));
- if (area.borderWidthRight != 0)
- addLine(rx + w, ry, rx + w, ry - h,
- area.borderWidthRight,
- new PDFColor(area.borderColorRight));
- if (area.borderWidthBottom != 0)
- addLine(rx, ry - h, rx + w, ry - h,
- area.borderWidthBottom,
- new PDFColor(area.borderColorBottom));
-
- }
-
-
- /**
- * render block area to PDF
- *
- * @param area the block area to render
- */
- public void renderBlockArea(BlockArea area) {
- doFrame(area);
- Enumeration e = area.getChildren().elements();
- while (e.hasMoreElements()) {
- Box b = (Box) e.nextElement();
- b.render(this);
- }
- }
-
- /**
- * render display space to PDF
- *
- * @param space the display space to render
- */
- public void renderDisplaySpace(DisplaySpace space) {
- int d = space.getSize();
- this.currentYPosition -= d;
- }
-
- /**
- * render image area to PDF
- *
- * @param area the image area to render
- */
- public void renderImageArea(ImageArea area) {
- // adapted from contribution by BoBoGi
- int x = this.currentAreaContainerXPosition +
- area.getXOffset();
- int y = this.currentYPosition;
- int w = area.getContentWidth();
- int h = area.getHeight();
-
- this.currentYPosition -= h;
-
- FopImage img = area.getImage();
-
- int xObjectNum = this.pdfDoc.addImage(img);
-
- currentStream.add("ET\nq\n" + (((float) w) / 1000f) + " 0 0 " +
- (((float) h) / 1000f) + " " +
- (((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)
+ public void renderImage(FontState fontState, String href, float x, float y, float width, float height)
{
try {
if(href.indexOf(":") == -1) {
href = "file:" + href;
}
FopImage img = FopImageFactory.Make(href);
- if(img != null) {
+ if(img instanceof SVGImage) {
+ SVGSVGElement svg = ((SVGImage)img).getSVGDocument().getRootElement();
+ currentStream.add("q\n" + width / svg.getWidth().getBaseVal().getValue() + " 0 0 " + height / svg.getHeight().getBaseVal().getValue() + " 0 0 cm\n");
+ renderSVG(fontState, svg, (int)x * 1000, (int)y * 1000);
+ currentStream.add("Q\n");
+// renderSVG(svg);
+ } else if(img != null) {
int xObjectNum = this.pdfDoc.addImage(img);
currentStream.add("q\n1 0 0 -1 " + 0
- + " " + (y + height) + " cm\n" + width + " 0 0 " +
+ + " " + (2 * y + height) + " cm\n" + width + " 0 0 " +
height + " " +
x + " " +
y + " cm\n" +
@@ -777,111 +1162,23 @@ public class PDFRenderer implements Renderer {
// img.close();
}
} catch(Exception e) {
+e.printStackTrace();
System.err.println("could not add image to SVG: " + href);
}
}
- /** render a foreign object area */
- public void renderForeignObjectArea(ForeignObjectArea area)
- {
- // if necessary need to scale and align the content
- int x = this.currentAreaContainerXPosition;
- switch(area.getAlign()) {
- case TextAlign.START:
- break;
- case TextAlign.END:
- break;
- case TextAlign.CENTER:
- case TextAlign.JUSTIFY:
- break;
- }
- switch(area.getVerticalAlign()) {
- case VerticalAlign.BASELINE:
- break;
- case VerticalAlign.MIDDLE:
- break;
- case VerticalAlign.SUB:
- break;
- case VerticalAlign.SUPER:
- break;
- case VerticalAlign.TEXT_TOP:
- break;
- case VerticalAlign.TEXT_BOTTOM:
- break;
- case VerticalAlign.TOP:
- break;
- case VerticalAlign.BOTTOM:
- break;
- }
- // in general the content will not be text
- currentStream.add("ET\n");
- // align and scale
- currentStream.add("q\n");
- switch(area.scalingMethod()) {
- case Scaling.UNIFORM:
- break;
- case Scaling.NON_UNIFORM:
- break;
- }
- // if the overflow is auto (default), scroll or visible
- // then the contents should not be clipped, since this
- // is considered a printing medium.
- switch(area.getOverflow()) {
- case Overflow.VISIBLE:
- case Overflow.SCROLL:
- case Overflow.AUTO:
- break;
- case Overflow.HIDDEN:
- break;
- }
- area.getObject().render(this);
- currentStream.add("Q\n");
- currentStream.add("BT\n");
- this.currentYPosition -= area.getEffectiveHeight();
- }
-
- /**
- * 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();
-
- /*
- * 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);
+ void renderSVG(FontState fontState, SVGSVGElement svg, int x, int y)
+ {
+ NodeList nl = svg.getChildNodes();
+ for(int count = 0; count < nl.getLength(); count++) {
+ Node n = nl.item(count);
+ if(n instanceof SVGElement) {
+ renderElement(fontState, (SVGElement)n, x, y);
}
}
-
- currentStream.add("Q\n");
}
- void handleGradient(String sp, boolean fill, GraphicImpl area)
+ void handleGradient(String sp, boolean fill, SVGElement area)
{
// should be a url to a gradient
String url = (String)sp;
@@ -894,7 +1191,8 @@ public class PDFRenderer implements Renderer {
// local reference
if(address.startsWith("#")) {
// find the gradient element
- GraphicImpl gi = area.locateDef(address.substring(1, address.length()));
+ SVGElement gi = null;
+// 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;
@@ -925,15 +1223,15 @@ public class PDFRenderer implements Renderer {
Vector theFunctions = new Vector();
- org.w3c.dom.NodeList nl = linear.getChildNodes();
+ NodeList nl = linear.getChildNodes();
Vector someColors = new Vector();
float lastoffset = 0;
Vector lastVector = null;
SVGStopElementImpl stop;
- Hashtable table;
+ Hashtable table = null;
for(int count = 0; count < nl.getLength(); count++) {
stop = (SVGStopElementImpl)nl.item(count);
- table = stop.oldgetStyle();
+// table = stop.oldgetStyle();
ColorType sc = (ColorType)table.get("stop-color");
if(sc == null) {
// maybe using color
@@ -977,7 +1275,7 @@ public class PDFRenderer implements Renderer {
ColorSpace aColorSpace = new ColorSpace(ColorSpace.DEVICE_RGB);
org.w3c.dom.NodeList nl = radial.getChildNodes();
SVGStopElementImpl stop;
- Hashtable table;
+ Hashtable table = null;
Vector someColors = new Vector();
Vector theCoords = new Vector();
Vector theBounds = new Vector();
@@ -1038,7 +1336,7 @@ public class PDFRenderer implements Renderer {
float lastoffset = 0;
for(int count = 0; count < nl.getLength(); count++) {
stop = (SVGStopElementImpl)nl.item(count);
- table = stop.oldgetStyle();
+// table = stop.oldgetStyle();
ColorType sc = (ColorType)table.get("stop-color");
if(sc == null) {
// maybe using color
@@ -1079,14 +1377,28 @@ public class PDFRenderer implements Renderer {
int linejoin = 0; // miter
int miterwidth = 8;
}
- protected DrawingInstruction applyStyle(GraphicImpl area, Hashtable style)
+ protected DrawingInstruction applyStyle(SVGElement area, CSSStyleDeclaration style)
{
DrawingInstruction di = new DrawingInstruction();
- Object sp;
- sp = style.get("fill");
+ CSSValue sp;
+ sp = style.getPropertyCSSValue("fill");
if(sp != null) {
- di.fill = true;
- if(sp instanceof ColorType) {
+ if(sp.getValueType() == CSSValue.CSS_PRIMITIVE_VALUE) {
+ if(((CSSPrimitiveValue)sp).getPrimitiveType() == CSSPrimitiveValue.CSS_RGBCOLOR) {
+ RGBColor col = ((CSSPrimitiveValue)sp).getRGBColorValue();
+ CSSPrimitiveValue val;
+ val = col.getRed();
+ float red = val.getFloatValue(CSSPrimitiveValue.CSS_NUMBER);
+ val = col.getGreen();
+ float green = val.getFloatValue(CSSPrimitiveValue.CSS_NUMBER);
+ val = col.getBlue();
+ float blue = val.getFloatValue(CSSPrimitiveValue.CSS_NUMBER);
+ PDFColor fillColour = new PDFColor(red, green, blue);
+ currentStream.add(fillColour.getColorSpaceOut(true));
+ di.fill = true;
+ }
+ }
+/* if(sp instanceof ColorType) {
ColorType ct = (ColorType)sp;
PDFColor fillColour = new PDFColor(ct.red(), ct.green(), ct.blue());
currentStream.add(fillColour.getColorSpaceOut(true));
@@ -1096,20 +1408,38 @@ public class PDFRenderer implements Renderer {
} else {
handleGradient((String)sp, true, area);
}
- }
+ }*/
} else {
}
- sp = style.get("fill-rule");
+ sp = style.getPropertyCSSValue("fill-rule");
if(sp != null) {
- if(sp.equals("nonzero")) {
- di.nonzero = true;
- }
+ if(sp.getValueType() == CSSValue.CSS_PRIMITIVE_VALUE) {
+ if(((CSSPrimitiveValue)sp).getPrimitiveType() == CSSPrimitiveValue.CSS_STRING) {
+ if(sp.getCssText().equals("nonzero")) {
+ di.nonzero = true;
+ }
+ }
+ }
} else {
}
- sp = style.get("stroke");
+ sp = style.getPropertyCSSValue("stroke");
if(sp != null) {
- di.stroke = true;
- if(sp instanceof ColorType) {
+ if(sp.getValueType() == CSSValue.CSS_PRIMITIVE_VALUE) {
+ if(((CSSPrimitiveValue)sp).getPrimitiveType() == CSSPrimitiveValue.CSS_RGBCOLOR) {
+ RGBColor col = ((CSSPrimitiveValue)sp).getRGBColorValue();
+ CSSPrimitiveValue val;
+ val = col.getRed();
+ float red = val.getFloatValue(CSSPrimitiveValue.CSS_NUMBER);
+ val = col.getGreen();
+ float green = val.getFloatValue(CSSPrimitiveValue.CSS_NUMBER);
+ val = col.getBlue();
+ float blue = val.getFloatValue(CSSPrimitiveValue.CSS_NUMBER);
+ PDFColor fillColour = new PDFColor(red, green, blue);
+ currentStream.add(fillColour.getColorSpaceOut(false));
+ di.stroke = true;
+ }
+ }
+/* if(sp instanceof ColorType) {
ColorType ct = (ColorType)sp;
PDFColor fillColour = new PDFColor(ct.red(), ct.green(), ct.blue());
currentStream.add(fillColour.getColorSpaceOut(false));
@@ -1119,57 +1449,88 @@ public class PDFRenderer implements Renderer {
} else {
handleGradient((String)sp, false, area);
}
- }
+ }*/
} else {
}
- sp = style.get("stroke-linecap");
+ sp = style.getPropertyCSSValue("stroke-linecap");
if(sp != null) {
- // butt, round ,square
- if(sp.equals("butt")) {
- currentStream.add(0 + " J\n");
- } else if(sp.equals("round")) {
- currentStream.add(1 + " J\n");
- } else if(sp.equals("square")) {
- currentStream.add(2 + " J\n");
- }
+ if(sp.getValueType() == CSSValue.CSS_PRIMITIVE_VALUE) {
+ if(((CSSPrimitiveValue)sp).getPrimitiveType() == CSSPrimitiveValue.CSS_STRING) {
+ String str = sp.getCssText();
+ // butt, round ,square
+ if(str.equals("butt")) {
+ currentStream.add(0 + " J\n");
+ } else if(str.equals("round")) {
+ currentStream.add(1 + " J\n");
+ } else if(str.equals("square")) {
+ currentStream.add(2 + " J\n");
+ }
+ }
+ }
} else {
}
- sp = style.get("stroke-linejoin");
+ sp = style.getPropertyCSSValue("stroke-linejoin");
if(sp != null) {
- if(sp.equals("miter")) {
- currentStream.add(0 + " j\n");
- } else if(sp.equals("round")) {
- currentStream.add(1 + " j\n");
- } else if(sp.equals("bevel")) {
- currentStream.add(2 + " j\n");
- }
+ if(sp.getValueType() == CSSValue.CSS_PRIMITIVE_VALUE) {
+ if(((CSSPrimitiveValue)sp).getPrimitiveType() == CSSPrimitiveValue.CSS_STRING) {
+ String str = sp.getCssText();
+ if(str.equals("miter")) {
+ currentStream.add(0 + " j\n");
+ } else if(str.equals("round")) {
+ currentStream.add(1 + " j\n");
+ } else if(str.equals("bevel")) {
+ currentStream.add(2 + " j\n");
+ }
+ }
+ }
} else {
}
- sp = style.get("stroke-miterlimit");
+ sp = style.getPropertyCSSValue("stroke-miterlimit");
if(sp != null) {
- float width;
- width = ((SVGLengthImpl)sp).getValue();
- PDFNumber pdfNumber = new PDFNumber();
- currentStream.add(pdfNumber.doubleOut(width) + " M\n");
+ if(sp.getValueType() == CSSValue.CSS_PRIMITIVE_VALUE) {
+ float width;
+ width = ((CSSPrimitiveValue)sp).getFloatValue(CSSPrimitiveValue.CSS_PT);
+ PDFNumber pdfNumber = new PDFNumber();
+ currentStream.add(pdfNumber.doubleOut(width) + " M\n");
+ }
} else {
}
- sp = style.get("stroke-width");
+ sp = style.getPropertyCSSValue("stroke-width");
if(sp != null) {
- float width;
- width = ((SVGLengthImpl)sp).getValue();
- PDFNumber pdfNumber = new PDFNumber();
- currentStream.add(pdfNumber.doubleOut(width) + " w\n");
+ if(sp.getValueType() == CSSValue.CSS_PRIMITIVE_VALUE) {
+ float width;
+ width = ((CSSPrimitiveValue)sp).getFloatValue(CSSPrimitiveValue.CSS_PT);
+ PDFNumber pdfNumber = new PDFNumber();
+ currentStream.add(pdfNumber.doubleOut(width) + " w\n");
+ }
}
- sp = style.get("stroke-dasharray");
+ sp = style.getPropertyCSSValue("stroke-dasharray");
if(sp != null) {
- Vector list;
+ if(sp.getValueType() == CSSValue.CSS_VALUE_LIST) {
+ currentStream.add("[ ");
+ CSSValueList list = (CSSValueList)sp;
+ for(int count = 0; count < list.getLength(); count++) {
+ CSSValue val = list.item(count);
+ if(val.getValueType() == CSSValue.CSS_PRIMITIVE_VALUE) {
+ currentStream.add(((CSSPrimitiveValue)val).getFloatValue(CSSPrimitiveValue.CSS_NUMBER) + " ");
+ }
+ }
+ currentStream.add("] ");
+ sp = style.getPropertyCSSValue("stroke-offset");
+ if(sp != null && sp.getValueType() == CSSValue.CSS_PRIMITIVE_VALUE) {
+ currentStream.add(((CSSPrimitiveValue)sp).getFloatValue(CSSPrimitiveValue.CSS_NUMBER) + " d\n");
+ } else {
+ currentStream.add("0 d\n");
+ }
+ }
+/* 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");
+ sp = style.getPropertyCSSValue("stroke-offset");
if(sp != null) {
float width;
width = ((SVGLengthImpl)sp).getValue();
@@ -1177,52 +1538,65 @@ public class PDFRenderer implements Renderer {
currentStream.add("] " + pdfNumber.doubleOut(width) + " d\n");
} else {
currentStream.add("] 0 d\n");
- }
+ }*/
}
- sp = style.get("mask");
+ sp = style.getPropertyCSSValue("mask");
if(sp != null) {
String maskurl;
- maskurl = (String)sp;
+// maskurl = (String)sp;
// System.out.println("mask: " + maskurl);
- maskurl = maskurl.substring(1, maskurl.length());
+// maskurl = maskurl.substring(1, maskurl.length());
// get def of mask and set mask
- GraphicImpl graph = null;
- graph = area.locateDef(maskurl);
- if(graph != null) {
+// SVGElement graph = null;
+// graph = area.locateDef(maskurl);
+// if(graph != null) {
// System.out.println("mask: " + graph);
- GraphicImpl parent = graph.getGraphicParent();
- graph.setParent(area);
+// SVGElement parent = graph.getGraphicParent();
+// graph.setParent(area);
// renderElement(svgarea, graph, posx, posy);
- graph.setParent(parent);
- }
+// graph.setParent(parent);
+// }
}
return di;
}
// need to transform about the origin of the current object
- protected void applyTransform(Vector trans)
+ protected void applyTransform(SVGAnimatedTransformList trans, SVGRect bbox)
{
+ // need to rotate and scale about the bbox top left
PDFNumber pdfNumber = new PDFNumber();
- for(Enumeration e = trans.elements(); e.hasMoreElements(); ) {
- SVGTransform t = (SVGTransform)e.nextElement();
- SVGMatrix matrix = t.getMatrix();
+ if(bbox != null) {
+// currentStream.add("1 0 0 1 " + pdfNumber.doubleOut(bbox.getX()) + " " + pdfNumber.doubleOut(bbox.getY()) + " cm\n");
+ }
+ SVGTransformList list = trans.getBaseVal();
+ for(int count = 0; count < list.getNumberOfItems(); count++) {
+ SVGMatrix matrix = ((SVGTransform)list.getItem(count)).getMatrix();
currentStream.add(pdfNumber.doubleOut(matrix.getA()) + " " + pdfNumber.doubleOut(matrix.getB()) + " " + pdfNumber.doubleOut(matrix.getC())
+ " " + pdfNumber.doubleOut(matrix.getD()) + " " + pdfNumber.doubleOut(matrix.getE()) + " " + pdfNumber.doubleOut(matrix.getF()) + " cm\n");
}
+ if(bbox != null) {
+// currentStream.add("1 0 0 1 " + pdfNumber.doubleOut(-bbox.getX()) + " " + pdfNumber.doubleOut(-bbox.getY()) + " cm\n");
+ }
}
- public void renderElement(SVGArea svgarea, GraphicImpl area, int posx, int posy)
+ public void renderElement(FontState fontState, SVGElement area, int posx, int posy)
{
int x = posx;
int y = posy;
- Hashtable style = area.oldgetStyle();
+ CSSStyleDeclaration style = null;
+ if(area instanceof SVGStylable)
+ style = ((SVGStylable)area).getStyle();
DrawingInstruction di = null;
currentStream.add("q\n");
- Vector trans = area.oldgetTransform();
- if(trans != null) {
- applyTransform(trans);
+ if(area instanceof SVGTransformable) {
+ SVGTransformable tf = (SVGTransformable)area;
+ SVGAnimatedTransformList trans = tf.getTransform();
+ SVGRect bbox = tf.getBBox();
+ if(trans != null) {
+ applyTransform(trans, bbox);
+ }
}
if(style != null) {
@@ -1249,7 +1623,7 @@ public class PDFRenderer implements Renderer {
// currentStream.add("q\n");
// currentStream.add(1 + " " + 0 + " " + 0 + " " + 1 + " " + 0 + " " + 0 + " cm\n");
currentStream.add("BT\n");
- renderText(svgarea, (SVGTextElementImpl)area, 0, 0/*, di*/);
+ renderText(fontState, (SVGTextElementImpl)area, 0, 0/*, di*/);
currentStream.add("ET\n");
// currentStream.add("Q\n");
} else if (area instanceof SVGCircleElement) {
@@ -1272,44 +1646,38 @@ public class PDFRenderer implements Renderer {
} else if (area instanceof SVGPolygonElementImpl) {
addPolyline(((SVGPolygonElementImpl)area).points, posx, posy, di, true);
} else if (area instanceof SVGGElementImpl) {
- renderGArea(svgarea, (SVGGElementImpl)area, x, y);
+ renderGArea(fontState, (SVGGElementImpl)area, x, y);
} else if(area instanceof SVGUseElementImpl) {
SVGUseElementImpl ug = (SVGUseElementImpl)area;
String ref = ug.link;
ref = ref.substring(1, ref.length());
- GraphicImpl graph = null;
- graph = area.locateDef(ref);
+ SVGElement graph = null;
+// graph = area.locateDef(ref);
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);
+// SVGElement 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);
+ renderElement(fontState, 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) {
+ renderImage(fontState, ig.link, ig.x, ig.y, ig.width, ig.height);
+ } else if (area instanceof SVGSVGElement) {
// 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);
- }
- }
+ renderSVG(fontState, (SVGSVGElement)area, x, y);
currentStream.add("Q\n");
} else if (area instanceof SVGAElement) {
SVGAElement ael = (SVGAElement)area;
org.w3c.dom.NodeList nl = ael.getChildNodes();
for(int count = 0; count < nl.getLength(); count++) {
org.w3c.dom.Node n = nl.item(count);
- if(n instanceof GraphicImpl) {
+ if(n instanceof SVGElement) {
if(n instanceof GraphicElement) {
SVGRect rect = ((GraphicElement)n).getBBox();
if(rect != null) {
@@ -1322,28 +1690,23 @@ public class PDFRenderer implements Renderer {
currentAnnotList = null;
*/ }
}
- renderElement(svgarea, (GraphicImpl)n, posx, posy);
+ renderElement(fontState, (SVGElement)n, posx, posy);
}
}
} else if (area instanceof SVGSwitchElement) {
- handleSwitchElement(svgarea, posx, posy, (SVGSwitchElement)area);
+ handleSwitchElement(fontState, posx, posy, (SVGSwitchElement)area);
}
// 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)
+ public void renderText(FontState fontState, SVGTextElementImpl tg, float x, float y)
{
- FontState fontState = svgarea.getFontState();
- if(fontState == null) {
- return; // for now
- }
PDFNumber pdfNumber = new PDFNumber();
- Hashtable styles;
- styles = tg.oldgetStyle();
+ CSSStyleDeclaration styles;
+ styles = tg.getStyle();
applyStyle(tg, styles);
// apply transform
// text has a Tm and need to handle each element
@@ -1354,24 +1717,42 @@ public class PDFRenderer implements Renderer {
+ " " + pdfNumber.doubleOut(matrix.getC())
+ " " + pdfNumber.doubleOut(-matrix.getD()) + " ");
- String fontFamily;
- fontFamily = (String)styles.get("font-family");
+ String fontFamily = null;
+ CSSValue sp = styles.getPropertyCSSValue("font-family");
+ if(sp != null && sp.getValueType() == CSSValue.CSS_PRIMITIVE_VALUE) {
+ if(((CSSPrimitiveValue)sp).getPrimitiveType() == CSSPrimitiveValue.CSS_STRING) {
+ fontFamily = sp.getCssText();
+ }
+ }
if(fontFamily == null)
fontFamily = fontState.getFontFamily();
- String fontStyle;
- fontStyle = (String)styles.get("font-style");
+ String fontStyle = null;
+ sp = styles.getPropertyCSSValue("font-style");
+ if(sp != null && sp.getValueType() == CSSValue.CSS_PRIMITIVE_VALUE) {
+ if(((CSSPrimitiveValue)sp).getPrimitiveType() == CSSPrimitiveValue.CSS_STRING) {
+ fontStyle = sp.getCssText();
+ }
+ }
if(fontStyle == null)
fontStyle = fontState.getFontStyle();
- String fontWeight;
- fontWeight = (String)styles.get("font-weight");
+ String fontWeight = null;
+ sp = styles.getPropertyCSSValue("font-weight");
+ if(sp != null && sp.getValueType() == CSSValue.CSS_PRIMITIVE_VALUE) {
+ if(((CSSPrimitiveValue)sp).getPrimitiveType() == CSSPrimitiveValue.CSS_STRING) {
+ fontWeight = sp.getCssText();
+ }
+ }
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();
+ sp = styles.getPropertyCSSValue("font-size");
+ if(sp != null && sp.getValueType() == CSSValue.CSS_PRIMITIVE_VALUE) {
+// if(((CSSPrimitiveValue)sp).getPrimitiveType() == CSSPrimitiveValue.CSS_NUMBER) {
+ fontSize = ((CSSPrimitiveValue)sp).getFloatValue(CSSPrimitiveValue.CSS_PT);
+// }
+ } else {
+ fontSize = fontState.getFontSize() / 1000f;
+ }
FontState fs = fontState;
try {
fs = new FontState(fontState.getFontInfo(), fontFamily, fontStyle,
@@ -1385,78 +1766,102 @@ public class PDFRenderer implements Renderer {
float tx = tg.x;
float ty = tg.y;
float currentX = x + tx;
+ float currentY = y + ty;
Vector list = tg.textList;
for(Enumeration e = list.elements(); e.hasMoreElements(); ) {
Object o = e.nextElement();
+ styles = tg.getStyle();
+ applyStyle(tg, styles);
if(o instanceof String) {
String str = (String)o;
currentStream.add(transstr
+ (currentX + matrix.getE()) + " "
+ (y+ty + matrix.getF()) + " Tm "
- + "(" + str + ") Tj\n");
- for(int count = 0; count < str.length(); count++) {
- currentX += fs.width(str.charAt(count)) / 1000f;
- }
- currentX += fs.width(' ') / 1000f;
+ + "(");
+ boolean spacing = "preserve".equals(tg.getXMLspace());
+ currentX = addSVGStr(fs, currentX, str, spacing);
+ currentStream.add(") Tj\n");
+// for(int count = 0; count < str.length(); count++) {
+// }
+// currentX += fs.width(' ') / 1000f;
} else if(o instanceof SVGTextPathElementImpl) {
SVGTextPathElementImpl tpg = (SVGTextPathElementImpl)o;
String ref = tpg.str;
- GraphicImpl graph = null;
- graph = tpg.locateDef(ref);
+ SVGElement graph = null;
+// graph = tpg.locateDef(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);
+// GraphicImpl parent = graph.getGraphicParent();
+// graph.setParent(tpg);
// set text path??
// how should this work
- graph.setParent(parent);
+// graph.setParent(parent);
}
} else if(o instanceof SVGTRefElementImpl) {
SVGTRefElementImpl trg = (SVGTRefElementImpl)o;
String ref = trg.ref;
ref = ref.substring(1, ref.length());
- GraphicImpl graph = null;
- graph = trg.locateDef(ref);
+ SVGElement graph = null;
+// graph = trg.locateDef(ref);
if(graph != null && graph instanceof SVGTextElementImpl) {
- GraphicImpl parent = graph.getGraphicParent();
- graph.setParent(trg);
+// GraphicImpl parent = graph.getGraphicParent();
+// graph.setParent(trg);
SVGTextElementImpl te = (SVGTextElementImpl)graph;
- renderText(svgarea, te, (int)(x + tx), (int)(y + ty));
- graph.setParent(parent);
+ renderText(fs, 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.oldgetStyle();
+ styles = tsg.getStyle();
applyStyle(tsg, styles);
boolean changed = false;
- String newprop;
- newprop = (String)styles.get("font-family");
+ String newprop = null;
+ sp = styles.getPropertyCSSValue("font-family");
+ if(sp != null && sp.getValueType() == CSSValue.CSS_PRIMITIVE_VALUE) {
+ if(((CSSPrimitiveValue)sp).getPrimitiveType() == CSSPrimitiveValue.CSS_STRING) {
+ newprop = sp.getCssText();
+ }
+ }
if(newprop != null && !newprop.equals(fontFamily)) {
fontFamily = newprop;
changed = true;
}
- newprop = (String)styles.get("font-style");
+ sp = styles.getPropertyCSSValue("font-style");
+ if(sp != null && sp.getValueType() == CSSValue.CSS_PRIMITIVE_VALUE) {
+ if(((CSSPrimitiveValue)sp).getPrimitiveType() == CSSPrimitiveValue.CSS_STRING) {
+ newprop = sp.getCssText();
+ }
+ }
if(newprop != null && !newprop.equals(fontStyle)) {
fontStyle = newprop;
changed = true;
}
- newprop = (String)styles.get("font-weight");
+ sp = styles.getPropertyCSSValue("font-weight");
+ if(sp != null && sp.getValueType() == CSSValue.CSS_PRIMITIVE_VALUE) {
+ if(((CSSPrimitiveValue)sp).getPrimitiveType() == CSSPrimitiveValue.CSS_STRING) {
+ newprop = sp.getCssText();
+ }
+ }
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;
- }
+ float newSize = fontSize;
+ sp = styles.getPropertyCSSValue("font-size");
+ if(sp != null && sp.getValueType() == CSSValue.CSS_PRIMITIVE_VALUE) {
+// if(((CSSPrimitiveValue)sp).getPrimitiveType() == CSSPrimitiveValue.CSS_NUMBER) {
+ newSize = ((CSSPrimitiveValue)sp).getFloatValue(CSSPrimitiveValue.CSS_PT);
+// }
+ }
+ if(fontSize != newSize) {
+ fontSize = newSize;
+ changed = true;
}
+ FontState oldfs = null;
if(changed) {
+ oldfs = fs;
try {
fs = new FontState(fontState.getFontInfo(), fontFamily, fontStyle,
fontWeight, (int)(fontSize * 1000));
@@ -1466,343 +1871,190 @@ public class PDFRenderer implements Renderer {
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()) + " "
- + (y + ty + tsg.dy + matrix.getF()) + " Tm "
- + "(" + tsg.str.charAt(count) + ") Tj\n");
- currentX = x + pos + fs.width(tsg.str.charAt(count)) / 1000f;
- count++;
+ float baseX;
+ float baseY;
+
+ StringBuffer pdf = new StringBuffer();
+ boolean spacing = "preserve".equals(tsg.getXMLspace());
+ boolean inbetween = false;
+ boolean addedspace = false;
+ int charPos = 0;
+ float xpos = currentX;
+ float ypos = currentY;
+ for (int i=0; i < tsg.str.length(); i++) {
+ char ch = tsg.str.charAt(i);
+ xpos = currentX;
+ ypos = currentY;
+ if(tsg.ylist.size() > charPos) {
+ ypos = y + ty + ((Float)tsg.ylist.elementAt(charPos)).floatValue();
}
- if(enum.hasMoreElements()) {
- // do nothing
- } else if(count < tsg.str.length()) {
- currentStream.add(transstr
- + (currentX + matrix.getE()) + " "
- + (y + ty + tsg.dy + matrix.getF()) + " Tm "
- + "(" + tsg.str.substring(count, tsg.str.length()) + ") Tj\n");
+ if(tsg.dylist.size() > charPos) {
+ ypos = ypos + ((Float)tsg.dylist.elementAt(charPos)).floatValue();
}
- } 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()) + " "
- + (y + ty + tsg.dy + matrix.getF()) + " Tm "
- + "(" + tsg.str.charAt(count) + ") Tj\n");
- currentX += pos + fs.width(tsg.str.charAt(count)) / 1000f;
- count++;
+ if(tsg.xlist.size() > charPos) {
+ xpos = x + tx + ((Float)tsg.xlist.elementAt(charPos)).floatValue();
}
- if(enum.hasMoreElements()) {
- // do nothing
- } else if(count < tsg.str.length()) {
- currentStream.add(transstr
- + (currentX + matrix.getE()) + " "
- + (y + ty + tsg.dy + matrix.getF()) + " Tm "
- + "(" + tsg.str.substring(count, tsg.str.length()) + ") Tj\n");
+ if(tsg.dxlist.size() > charPos) {
+ xpos = xpos + ((Float)tsg.dxlist.elementAt(charPos)).floatValue();
+ }
+ if (ch > 127) {
+ pdf = pdf.append(transstr
+ + (xpos + matrix.getE()) + " "
+ + (ypos + matrix.getF()) + " Tm "
+ + "(" + "\\" + Integer.toOctalString((int)ch) + ") Tj\n");
+ currentX = xpos + fs.width(ch) / 1000f;
+ currentY = ypos;
+ charPos++;
+ inbetween = true;
+ addedspace = false;
+ } else {
+ switch (ch) {
+ case '(' :
+ pdf = pdf.append(transstr
+ + (xpos + matrix.getE()) + " "
+ + (ypos + matrix.getF()) + " Tm "
+ + "(" + "\\(" + ") Tj\n");
+ currentX = xpos + fs.width(ch) / 1000f;
+ currentY = ypos;
+ charPos++;
+ inbetween = true;
+ addedspace = false;
+ break;
+ case ')' :
+ pdf = pdf.append(transstr
+ + (xpos + matrix.getE()) + " "
+ + (ypos + matrix.getF()) + " Tm "
+ + "(" + "\\)" + ") Tj\n");
+ currentX = xpos + fs.width(ch) / 1000f;
+ currentY = ypos;
+ charPos++;
+ inbetween = true;
+ addedspace = false;
+ break;
+ case '\\' :
+ pdf = pdf.append(transstr
+ + (xpos + matrix.getE()) + " "
+ + (ypos + matrix.getF()) + " Tm "
+ + "(" + "\\\\" + ") Tj\n");
+ currentX = xpos + fs.width(ch) / 1000f;
+ currentY = ypos;
+ charPos++;
+ inbetween = true;
+ addedspace = false;
+ break;
+ case ' ':
+ case ' ':
+ if(spacing) {
+ currentX = xpos + fs.width(' ') / 1000f;
+ currentY = ypos;
+ charPos++;
+ } else {
+ if(inbetween && !addedspace) {
+ addedspace = true;
+ currentX = xpos + fs.width(' ') / 1000f;
+ currentY = ypos;
+ charPos++;
+ }
+ }
+ break;
+ case '\n':
+ case '\r':
+ if(spacing) {
+ currentX = xpos + fs.width(' ') / 1000f;
+ currentY = ypos;
+ charPos++;
+ }
+ break;
+ default:
+ addedspace = false;
+ pdf = pdf.append(transstr
+ + (xpos + matrix.getE()) + " "
+ + (ypos + matrix.getF()) + " Tm "
+ + "(" + ch + ") Tj\n");
+ currentX = xpos + fs.width(ch) / 1000f;
+ currentY = ypos;
+ charPos++;
+ inbetween = true;
+ break;
}
- } 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;
+ currentStream.add(pdf.toString());
+ }
+// currentX += fs.width(' ') / 1000f;
+ if(changed) {
+ fs = oldfs;
+ currentStream.add("/" + fs.getFontName() + " " + fs.getFontSize() / 1000f + " Tf\n");
+ }
} 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);
- }
- }
- }
-
- void handleSwitchElement(SVGArea svgarea, int posx, int posy, SVGSwitchElement ael)
+ protected float addSVGStr(FontState fs, float currentX, String str, boolean spacing)
{
- SVGList relist = ael.getRequiredExtensions();
- SVGList rflist = ael.getRequiredFeatures();
- SVGList sllist = ael.getSystemLanguage();
- org.w3c.dom.NodeList nl = ael.getChildNodes();
- for(int count = 0; count < nl.getLength(); count++) {
- org.w3c.dom.Node n = nl.item(count);
- // only render the first child that has a valid
- // test data
- if(n instanceof GraphicElement) {
- GraphicElement graphic = (GraphicElement)n;
- SVGList grelist = graphic.getRequiredExtensions();
- // if null it evaluates to true
- if(grelist != null) {
- for(int i = 0; i < grelist.getNumberOfItems(); i++) {
- String str = (String)grelist.getItem(i);
- if(relist == null) {
- // use default extension set
- // currently no extensions are supported
-// if(!(str.equals("http:// ??"))) {
- continue;
-// }
- } else {
- }
- }
- }
- SVGList grflist = graphic.getRequiredFeatures();
- if(grflist != null) {
- for(int i = 0; i < grflist.getNumberOfItems(); i++) {
- String str = (String)grflist.getItem(i);
- if(rflist == null) {
- // use default feature set
- if(!(str.equals("org.w3c.svg.static")
- || str.equals("org.w3c.dom.svg.all"))) {
- continue;
- }
- } else {
- boolean found = false;
- for(int j = 0; j < rflist.getNumberOfItems(); j++) {
- if(rflist.getItem(j).equals(str)) {
- found = true;
- break;
- }
- }
- if(!found)
- continue;
- }
- }
- }
- SVGList gsllist = graphic.getSystemLanguage();
- if(gsllist != null) {
- for(int i = 0; i < gsllist.getNumberOfItems(); i++) {
- String str = (String)gsllist.getItem(i);
- if(sllist == null) {
- // use default feature set
- if(!(str.equals("en"))) {
- continue;
- }
- } else {
- boolean found = false;
- for(int j = 0; j < sllist.getNumberOfItems(); j++) {
- if(sllist.getItem(j).equals(str)) {
- found = true;
- break;
- }
- }
- if(!found)
- continue;
- }
- }
- }
- renderElement(svgarea, (GraphicImpl)n, posx, posy);
- // only render the first valid one
+ boolean inbetween = false;
+ boolean addedspace = false;
+ StringBuffer pdf = new StringBuffer();
+ for (int i=0; i < str.length(); i++) {
+ char ch = str.charAt(i);
+ if (ch > 127) {
+ pdf = pdf.append("\\");
+ pdf = pdf.append(Integer.toOctalString((int)ch));
+ currentX += fs.width(ch) / 1000f;
+ inbetween = true;
+ addedspace = false;
+ } else {
+ switch (ch) {
+ case '(' :
+ pdf = pdf.append("\\(");
+ currentX += fs.width(ch) / 1000f;
+ inbetween = true;
+ addedspace = false;
+ break;
+ case ')' :
+ pdf = pdf.append("\\)");
+ currentX += fs.width(ch) / 1000f;
+ inbetween = true;
+ addedspace = false;
+ break;
+ case '\\' :
+ pdf = pdf.append("\\\\");
+ currentX += fs.width(ch) / 1000f;
+ inbetween = true;
+ addedspace = false;
break;
+ case ' ':
+ case ' ':
+ if(spacing) {
+ pdf = pdf.append(' ');
+ currentX += fs.width(' ') / 1000f;
+ } else {
+ if(inbetween && !addedspace) {
+ addedspace = true;
+ pdf = pdf.append(' ');
+ currentX += fs.width(' ') / 1000f;
+ }
+ }
+ break;
+ case '\n':
+ case '\r':
+ if(spacing) {
+ pdf = pdf.append(' ');
+ currentX += fs.width(' ') / 1000f;
+ }
+ break;
+ default:
+ addedspace = false;
+ pdf = pdf.append(ch);
+ currentX += fs.width(ch) / 1000f;
+ inbetween = true;
+ break;
+ }
}
}
+ currentStream.add(pdf.toString());
+ return currentX;
}
- /**
- * render inline area to PDF
- *
- * @param area inline area to render
- */
- public void renderInlineArea(InlineArea area) {
- char ch;
- StringBuffer pdf = new StringBuffer();
-
- String name = area.getFontState().getFontName();
- int size = area.getFontState().getFontSize();
-
- PDFColor theAreaColor = new PDFColor(
- (double)area.getRed(),
- (double)area.getGreen(),
- (double)area.getBlue() );
-
- if ((!name.equals(this.currentFontName))
- || (size != this.currentFontSize)) {
- this.currentFontName = name;
- this.currentFontSize = size;
- pdf = pdf.append("/" + name + " " + (size/1000) + " Tf\n");
- }
-
- //if (theAreaColor.isEquivalent(this.currentFill)) {
- this.currentFill = theAreaColor;
-
- pdf = pdf.append(this.currentFill.getColorSpaceOut(true));
- //}
-
- int rx = this.currentXPosition;
- int bl = this.currentYPosition;
-
- pdf = pdf.append("1 0 0 1 "
- +(rx/1000f) + " " + (bl/1000f)
- + " Tm (");
-
- String s;
- if ( area.getPageNumberID()!=null ) { // this text is a page number, so resolve it
- s = idReferences.getPageNumber(area.getPageNumberID());
- if(s==null)
- {
- s="";
- }
- }
- else {
- s = area.getText();
- }
-
- int l = s.length();
-
- for (int i=0; i < l; i++) {
- ch = s.charAt(i);
- if (ch > 127) {
- pdf = pdf.append("\\");
- pdf = pdf.append(Integer.toOctalString((int)ch));
- } else {
- switch (ch) {
- case '(' : pdf = pdf.append("\\("); break;
- case ')' : pdf = pdf.append("\\)"); break;
- case '\\' : pdf = pdf.append("\\\\"); break;
- default : pdf = pdf.append(ch); break;
- }
- }
- }
- pdf = pdf.append(") Tj\n");
-
- currentStream.add(pdf.toString());
-
- this.currentXPosition += area.getContentWidth();
- }
-
- /**
- * render inline space to PDF
- *
- * @param space space to render
- */
- public void renderInlineSpace(InlineSpace space) {
- this.currentXPosition += space.getSize();
- }
-
- /**
- * render line area to PDF
- *
- * @param area area to render
- */
- 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;
-
- int bl = this.currentYPosition;
-
- Enumeration e = area.getChildren().elements();
- while (e.hasMoreElements()) {
- Box b = (Box) e.nextElement();
- b.render(this);
- }
-
- this.currentYPosition = ry-h;
- }
-
- /**
- * render page into PDF
- *
- * @param page page to render
- */
- public void renderPage(Page page) {
- AreaContainer body, before, after;
-
- currentStream = this.pdfDoc.makeStream();
- body = page.getBody();
- before = page.getBefore();
- after = page.getAfter();
-
- this.currentFontName = "";
- this.currentFontSize = 0;
-
- currentStream.add("BT\n");
- renderAreaContainer(body);
-
- if (before != null) {
- renderAreaContainer(before);
- }
-
- if (after != null) {
- renderAreaContainer(after);
- }
-
- currentStream.add("ET\n");
-
- currentPage = this.pdfDoc.makePage(this.pdfResources, currentStream,
- page.getWidth()/1000,
- page.getHeight()/1000, page);
-
- if (page.hasLinks()) {
- currentAnnotList = this.pdfDoc.makeAnnotList();
- currentPage.setAnnotList(currentAnnotList);
-
- Enumeration e = page.getLinkSets().elements();
- while (e.hasMoreElements()) {
- LinkSet linkSet = (LinkSet) e.nextElement();
-
- linkSet.align();
- String dest = linkSet.getDest();
- int linkType = linkSet.getLinkType();
- Enumeration f = linkSet.getRects().elements();
- while (f.hasMoreElements()) {
- LinkedRectangle lrect = (LinkedRectangle) f.nextElement();
- currentAnnotList.addLink(
- this.pdfDoc.makeLink(lrect.getRectangle(), dest, linkType));
- }
- }
- } else {
- // just to be on the safe side
- currentAnnotList = null;
- }
- }
-
- /**
- * 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();
-
- addLine(rx, ry, rx+w, ry, th, new PDFColor(area.getRed(), area.getGreen(),area.getBlue()));
- }
-
- /**
- * set up the font info
- *
- * @param fontInfo font info to set up
- */
- public void setupFontInfo(FontInfo fontInfo) {
- FontSetup.setup(fontInfo);
- FontSetup.addToResources(this.pdfDoc, fontInfo);
- }
}