aboutsummaryrefslogtreecommitdiffstats
path: root/src/java/org/apache/fop
diff options
context:
space:
mode:
authorJeremias Maerki <jeremias@apache.org>2008-08-14 09:13:09 +0000
committerJeremias Maerki <jeremias@apache.org>2008-08-14 09:13:09 +0000
commit07c47a253ccfd4afd4111beafe270eb8b5ef144a (patch)
tree6198565a342e9ef182f901c924a1ef4f2551084b /src/java/org/apache/fop
parent686f92dd78dcf4b6750230a55de5c1427ab20464 (diff)
downloadxmlgraphics-fop-07c47a253ccfd4afd4111beafe270eb8b5ef144a.tar.gz
xmlgraphics-fop-07c47a253ccfd4afd4111beafe270eb8b5ef144a.zip
Initial implementation for border painting for the new IF (including support for PDF, but not SVG, yet)
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_AreaTreeNewDesign@685827 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src/java/org/apache/fop')
-rw-r--r--src/java/org/apache/fop/render/intermediate/AbstractIFPainter.java2
-rw-r--r--src/java/org/apache/fop/render/intermediate/BorderPainter.java214
-rw-r--r--src/java/org/apache/fop/render/intermediate/IFConstants.java4
-rw-r--r--src/java/org/apache/fop/render/intermediate/IFPainter.java15
-rw-r--r--src/java/org/apache/fop/render/intermediate/IFParser.java39
-rw-r--r--src/java/org/apache/fop/render/intermediate/IFRenderer.java31
-rw-r--r--src/java/org/apache/fop/render/intermediate/IFSerializer.java43
-rw-r--r--src/java/org/apache/fop/render/pdf/PDFBorderPainter.java263
-rw-r--r--src/java/org/apache/fop/render/pdf/PDFContentGenerator.java2
-rw-r--r--src/java/org/apache/fop/render/pdf/PDFPainter.java12
-rw-r--r--src/java/org/apache/fop/render/pdf/PDFRenderer.java168
11 files changed, 609 insertions, 184 deletions
diff --git a/src/java/org/apache/fop/render/intermediate/AbstractIFPainter.java b/src/java/org/apache/fop/render/intermediate/AbstractIFPainter.java
index 5f904858f..90876b18c 100644
--- a/src/java/org/apache/fop/render/intermediate/AbstractIFPainter.java
+++ b/src/java/org/apache/fop/render/intermediate/AbstractIFPainter.java
@@ -60,6 +60,8 @@ public abstract class AbstractIFPainter implements IFPainter {
/** Image handler registry */
protected ImageHandlerRegistry imageHandlerRegistry = new ImageHandlerRegistry();
+ //TODO Move reference to FOPFactory to the user has a chance to add his own implementations
+ //and so the lookup process isn't redone for each painter instance.
/**
* Default constructor.
diff --git a/src/java/org/apache/fop/render/intermediate/BorderPainter.java b/src/java/org/apache/fop/render/intermediate/BorderPainter.java
new file mode 100644
index 000000000..fdde321a9
--- /dev/null
+++ b/src/java/org/apache/fop/render/intermediate/BorderPainter.java
@@ -0,0 +1,214 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.render.intermediate;
+
+import java.awt.Color;
+import java.awt.Rectangle;
+
+import org.apache.fop.traits.BorderProps;
+
+/**
+ * This is an abstract base class for handling border painting.
+ */
+public abstract class BorderPainter {
+
+ /**
+ * Draws borders.
+ * @param borderRect the border rectangle
+ * @param bpsBefore the border specification on the before side
+ * @param bpsAfter the border specification on the after side
+ * @param bpsStart the border specification on the start side
+ * @param bpsEnd the border specification on the end side
+ */
+ public void drawBorders(Rectangle borderRect,
+ BorderProps bpsBefore, BorderProps bpsAfter,
+ BorderProps bpsStart, BorderProps bpsEnd) {
+ int startx = borderRect.x;
+ int starty = borderRect.y;
+ int width = borderRect.width;
+ int height = borderRect.height;
+ boolean[] b = new boolean[] {
+ (bpsBefore != null), (bpsEnd != null),
+ (bpsAfter != null), (bpsStart != null)};
+ if (!b[0] && !b[1] && !b[2] && !b[3]) {
+ return;
+ }
+ int[] bw = new int[] {
+ (b[0] ? bpsBefore.width : 0),
+ (b[1] ? bpsEnd.width : 0),
+ (b[2] ? bpsAfter.width : 0),
+ (b[3] ? bpsStart.width : 0)};
+ int[] clipw = new int[] {
+ BorderProps.getClippedWidth(bpsBefore),
+ BorderProps.getClippedWidth(bpsEnd),
+ BorderProps.getClippedWidth(bpsAfter),
+ BorderProps.getClippedWidth(bpsStart)};
+ starty += clipw[0];
+ height -= clipw[0];
+ height -= clipw[2];
+ startx += clipw[3];
+ width -= clipw[3];
+ width -= clipw[1];
+
+ boolean[] slant = new boolean[] {
+ (b[3] && b[0]), (b[0] && b[1]), (b[1] && b[2]), (b[2] && b[3])};
+ if (bpsBefore != null) {
+ int sx1 = startx;
+ int sx2 = (slant[0] ? sx1 + bw[3] - clipw[3] : sx1);
+ int ex1 = startx + width;
+ int ex2 = (slant[1] ? ex1 - bw[1] + clipw[1] : ex1);
+ int outery = starty - clipw[0];
+ int clipy = outery + clipw[0];
+ int innery = outery + bw[0];
+
+ saveGraphicsState();
+ moveTo(sx1, clipy);
+ int sx1a = sx1;
+ int ex1a = ex1;
+ if (bpsBefore.mode == BorderProps.COLLAPSE_OUTER) {
+ if (bpsStart != null && bpsStart.mode == BorderProps.COLLAPSE_OUTER) {
+ sx1a -= clipw[3];
+ }
+ if (bpsEnd != null && bpsEnd.mode == BorderProps.COLLAPSE_OUTER) {
+ ex1a += clipw[1];
+ }
+ lineTo(sx1a, outery);
+ lineTo(ex1a, outery);
+ }
+ lineTo(ex1, clipy);
+ lineTo(ex2, innery);
+ lineTo(sx2, innery);
+ closePath();
+ clip();
+ drawBorderLine(sx1a, outery, ex1a, innery, true, true,
+ bpsBefore.style, bpsBefore.color);
+ restoreGraphicsState();
+ }
+ if (bpsEnd != null) {
+ int sy1 = starty;
+ int sy2 = (slant[1] ? sy1 + bw[0] - clipw[0] : sy1);
+ int ey1 = starty + height;
+ int ey2 = (slant[2] ? ey1 - bw[2] + clipw[2] : ey1);
+ int outerx = startx + width + clipw[1];
+ int clipx = outerx - clipw[1];
+ int innerx = outerx - bw[1];
+
+ saveGraphicsState();
+ moveTo(clipx, sy1);
+ int sy1a = sy1;
+ int ey1a = ey1;
+ if (bpsEnd.mode == BorderProps.COLLAPSE_OUTER) {
+ if (bpsBefore != null && bpsBefore.mode == BorderProps.COLLAPSE_OUTER) {
+ sy1a -= clipw[0];
+ }
+ if (bpsAfter != null && bpsAfter.mode == BorderProps.COLLAPSE_OUTER) {
+ ey1a += clipw[2];
+ }
+ lineTo(outerx, sy1a);
+ lineTo(outerx, ey1a);
+ }
+ lineTo(clipx, ey1);
+ lineTo(innerx, ey2);
+ lineTo(innerx, sy2);
+ closePath();
+ clip();
+ drawBorderLine(innerx, sy1a, outerx, ey1a, false, false, bpsEnd.style, bpsEnd.color);
+ restoreGraphicsState();
+ }
+ if (bpsAfter != null) {
+ int sx1 = startx;
+ int sx2 = (slant[3] ? sx1 + bw[3] - clipw[3] : sx1);
+ int ex1 = startx + width;
+ int ex2 = (slant[2] ? ex1 - bw[1] + clipw[1] : ex1);
+ int outery = starty + height + clipw[2];
+ int clipy = outery - clipw[2];
+ int innery = outery - bw[2];
+
+ saveGraphicsState();
+ moveTo(ex1, clipy);
+ int sx1a = sx1;
+ int ex1a = ex1;
+ if (bpsAfter.mode == BorderProps.COLLAPSE_OUTER) {
+ if (bpsStart != null && bpsStart.mode == BorderProps.COLLAPSE_OUTER) {
+ sx1a -= clipw[3];
+ }
+ if (bpsEnd != null && bpsEnd.mode == BorderProps.COLLAPSE_OUTER) {
+ ex1a += clipw[1];
+ }
+ lineTo(ex1a, outery);
+ lineTo(sx1a, outery);
+ }
+ lineTo(sx1, clipy);
+ lineTo(sx2, innery);
+ lineTo(ex2, innery);
+ closePath();
+ clip();
+ drawBorderLine(sx1a, innery, ex1a, outery, true, false, bpsAfter.style, bpsAfter.color);
+ restoreGraphicsState();
+ }
+ if (bpsStart != null) {
+ int sy1 = starty;
+ int sy2 = (slant[0] ? sy1 + bw[0] - clipw[0] : sy1);
+ int ey1 = sy1 + height;
+ int ey2 = (slant[3] ? ey1 - bw[2] + clipw[2] : ey1);
+ int outerx = startx - clipw[3];
+ int clipx = outerx + clipw[3];
+ int innerx = outerx + bw[3];
+
+ saveGraphicsState();
+ moveTo(clipx, ey1);
+ int sy1a = sy1;
+ int ey1a = ey1;
+ if (bpsStart.mode == BorderProps.COLLAPSE_OUTER) {
+ if (bpsBefore != null && bpsBefore.mode == BorderProps.COLLAPSE_OUTER) {
+ sy1a -= clipw[0];
+ }
+ if (bpsAfter != null && bpsAfter.mode == BorderProps.COLLAPSE_OUTER) {
+ ey1a += clipw[2];
+ }
+ lineTo(outerx, ey1a);
+ lineTo(outerx, sy1a);
+ }
+ lineTo(clipx, sy1);
+ lineTo(innerx, sy2);
+ lineTo(innerx, ey2);
+ closePath();
+ clip();
+ drawBorderLine(outerx, sy1a, innerx, ey1a, false, true, bpsStart.style, bpsStart.color);
+ restoreGraphicsState();
+ }
+ }
+
+
+ protected abstract void drawBorderLine(int x1, int y1, int x2, int y2,
+ boolean horz, boolean startOrBefore, int style, Color col);
+
+ protected abstract void moveTo(int x, int y);
+
+ protected abstract void lineTo(int x, int y);
+
+ protected abstract void closePath();
+
+ protected abstract void clip();
+
+ protected abstract void saveGraphicsState();
+ protected abstract void restoreGraphicsState();
+
+}
diff --git a/src/java/org/apache/fop/render/intermediate/IFConstants.java b/src/java/org/apache/fop/render/intermediate/IFConstants.java
index 2ea97a231..8fe094604 100644
--- a/src/java/org/apache/fop/render/intermediate/IFConstants.java
+++ b/src/java/org/apache/fop/render/intermediate/IFConstants.java
@@ -44,4 +44,8 @@ public interface IFConstants extends XMLConstants {
String EL_VIEWPORT = "viewport";
String EL_GROUP = "g";
String EL_IMAGE = "image";
+ String EL_RECT = "rect";
+ String EL_BORDER_RECT = "border-rect";
+ String EL_FONT = "font";
+ String EL_TEXT = "text";
}
diff --git a/src/java/org/apache/fop/render/intermediate/IFPainter.java b/src/java/org/apache/fop/render/intermediate/IFPainter.java
index 026f43a8e..6042ed816 100644
--- a/src/java/org/apache/fop/render/intermediate/IFPainter.java
+++ b/src/java/org/apache/fop/render/intermediate/IFPainter.java
@@ -32,6 +32,7 @@ import org.w3c.dom.Document;
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.fonts.FontInfo;
+import org.apache.fop.traits.BorderProps;
/**
* Interface used to paint whole documents layouted by Apache FOP.
@@ -277,6 +278,20 @@ public interface IFPainter {
void drawRect(Rectangle rect, Paint fill, Color stroke) throws IFException;
/**
+ * Draws a border rectangle. The border segments are specified through {@code BorderProps}
+ * instances.
+ * @param rect the rectangle's coordinates and extent
+ * @param before the border segment on the before-side (top)
+ * @param after the border segment on the after-side (bottom)
+ * @param start the border segment on the start-side (left)
+ * @param end the border segment on the end-side (right)
+ * @throws IFException if an error occurs while handling this event
+ */
+ void drawBorderRect(Rectangle rect,
+ BorderProps before, BorderProps after,
+ BorderProps start, BorderProps end) throws IFException;
+
+ /**
* Draws an image identified by a URI inside a given rectangle. This is the equivalent to
* an fo:external-graphic in XSL-FO.
* @param uri the image's URI
diff --git a/src/java/org/apache/fop/render/intermediate/IFParser.java b/src/java/org/apache/fop/render/intermediate/IFParser.java
index 9c615427f..e365bb519 100644
--- a/src/java/org/apache/fop/render/intermediate/IFParser.java
+++ b/src/java/org/apache/fop/render/intermediate/IFParser.java
@@ -49,6 +49,7 @@ import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.fo.ElementMapping;
import org.apache.fop.fo.ElementMappingRegistry;
import org.apache.fop.fo.expr.PropertyException;
+import org.apache.fop.traits.BorderProps;
import org.apache.fop.util.ColorUtil;
import org.apache.fop.util.ContentHandlerFactory;
import org.apache.fop.util.ContentHandlerFactoryRegistry;
@@ -133,9 +134,10 @@ public class IFParser implements IFConstants {
//Page content
elementHandlers.put(EL_VIEWPORT, new ViewportHandler());
elementHandlers.put(EL_GROUP, new GroupHandler());
- elementHandlers.put("font", new FontHandler());
- elementHandlers.put("text", new TextHandler());
- elementHandlers.put("rect", new RectHandler());
+ elementHandlers.put(EL_FONT, new FontHandler());
+ elementHandlers.put(EL_TEXT, new TextHandler());
+ elementHandlers.put(EL_RECT, new RectHandler());
+ elementHandlers.put(EL_BORDER_RECT, new BorderRectHandler());
elementHandlers.put(EL_IMAGE, new ImageHandler());
}
@@ -442,10 +444,10 @@ public class IFParser implements IFConstants {
private class RectHandler extends AbstractElementHandler {
public void startElement(Attributes attributes) throws IFException {
- int x = Integer.parseInt(lastAttributes.getValue("x"));
- int y = Integer.parseInt(lastAttributes.getValue("y"));
- int width = Integer.parseInt(lastAttributes.getValue("width"));
- int height = Integer.parseInt(lastAttributes.getValue("height"));
+ int x = Integer.parseInt(attributes.getValue("x"));
+ int y = Integer.parseInt(attributes.getValue("y"));
+ int width = Integer.parseInt(attributes.getValue("width"));
+ int height = Integer.parseInt(attributes.getValue("height"));
Color fillColor;
try {
fillColor = getAttributeAsColor(attributes, "fill");
@@ -463,6 +465,29 @@ public class IFParser implements IFConstants {
}
+ private static final String[] SIDES = new String[] {"before", "after", "start", "end"};
+
+ private class BorderRectHandler extends AbstractElementHandler {
+
+ public void startElement(Attributes attributes) throws IFException {
+ int x = Integer.parseInt(attributes.getValue("x"));
+ int y = Integer.parseInt(attributes.getValue("y"));
+ int width = Integer.parseInt(attributes.getValue("width"));
+ int height = Integer.parseInt(attributes.getValue("height"));
+ BorderProps[] borders = new BorderProps[4];
+ for (int i = 0; i < 4; i++) {
+ String b = attributes.getValue(SIDES[i]);
+ if (b != null) {
+ borders[i] = BorderProps.valueOf(userAgent, b);
+ }
+ }
+
+ painter.drawBorderRect(new Rectangle(x, y, width, height),
+ borders[0], borders[1], borders[2], borders[3]);
+ }
+
+ }
+
private class ImageHandler extends AbstractElementHandler {
public void startElement(Attributes attributes) throws IFException {
diff --git a/src/java/org/apache/fop/render/intermediate/IFRenderer.java b/src/java/org/apache/fop/render/intermediate/IFRenderer.java
index e5dcccf62..529aee4d0 100644
--- a/src/java/org/apache/fop/render/intermediate/IFRenderer.java
+++ b/src/java/org/apache/fop/render/intermediate/IFRenderer.java
@@ -85,6 +85,7 @@ import org.apache.fop.render.intermediate.extensions.BookmarkTree;
import org.apache.fop.render.intermediate.extensions.GoToXYAction;
import org.apache.fop.render.intermediate.extensions.NamedDestination;
import org.apache.fop.render.pdf.PDFEventProducer;
+import org.apache.fop.traits.BorderProps;
/**
* This renderer implementation is an adapter to the {@code IFPainter} interface. It is used
@@ -92,6 +93,11 @@ import org.apache.fop.render.pdf.PDFEventProducer;
*/
public class IFRenderer extends AbstractPathOrientedRenderer {
+ //TODO Many parts of the Renderer infrastructure are using floats (coordinates in points)
+ //instead of ints (in millipoints). A lot of conversion to and from is performed.
+ //When the new IF is established, the Renderer infrastructure should be revisited so check
+ //if optimizations can be done to avoid int->float->int conversions.
+
/** logging instance */
protected static Log log = LogFactory.getLog(IFRenderer.class);
@@ -964,17 +970,36 @@ public class IFRenderer extends AbstractPathOrientedRenderer {
}
/** {@inheritDoc} */
+ protected void drawBorders(float startx, float starty,
+ float width, float height,
+ BorderProps bpsBefore, BorderProps bpsAfter,
+ BorderProps bpsStart, BorderProps bpsEnd) {
+ Rectangle rect = toMillipointRectangle(startx, starty, width, height);
+ try {
+ painter.drawBorderRect(rect, bpsBefore, bpsAfter, bpsStart, bpsEnd);
+ } catch (IFException ife) {
+ handleIFException(ife);
+ }
+ }
+
+ /** {@inheritDoc} */
protected void drawBorderLine(float x1, float y1, float x2, float y2, boolean horz,
boolean startOrBefore, int style, Color col) {
- // TODO Auto-generated method stub
- //log.warn("drawBorderLine() NYI");
+ log.warn("drawBorderLine() not properly implemented, yet");
updateColor(col, true);
fillRect(x1, y1, x2 - x1, y2 - y1);
}
+ private int toMillipoints(float coordinate) {
+ return (int)(coordinate * 1000);
+ }
+
private Rectangle toMillipointRectangle(float x, float y, float width, float height) {
return new Rectangle(
- (int)(x * 1000), (int)(y * 1000), (int)(width * 1000), (int)(height * 1000));
+ toMillipoints(x),
+ toMillipoints(y),
+ toMillipoints(width),
+ toMillipoints(height));
}
/** {@inheritDoc} */
diff --git a/src/java/org/apache/fop/render/intermediate/IFSerializer.java b/src/java/org/apache/fop/render/intermediate/IFSerializer.java
index 9ca242fb9..40cd9a25b 100644
--- a/src/java/org/apache/fop/render/intermediate/IFSerializer.java
+++ b/src/java/org/apache/fop/render/intermediate/IFSerializer.java
@@ -36,6 +36,7 @@ import org.apache.xmlgraphics.util.QName;
import org.apache.xmlgraphics.util.XMLizable;
import org.apache.fop.render.RenderingContext;
+import org.apache.fop.traits.BorderProps;
import org.apache.fop.util.ColorUtil;
import org.apache.fop.util.DOM2SAX;
import org.apache.fop.util.XMLUtil;
@@ -242,7 +243,7 @@ public class IFSerializer extends AbstractXMLWritingIFPainter implements IFConst
try {
AttributesImpl atts = new AttributesImpl();
if (transform != null && transform.length() > 0) {
- addAttribute(atts,"transform", transform);
+ addAttribute(atts, "transform", transform);
}
addAttribute(atts, "width", Integer.toString(size.width));
addAttribute(atts, "height", Integer.toString(size.height));
@@ -363,15 +364,45 @@ public class IFSerializer extends AbstractXMLWritingIFPainter implements IFConst
addAttribute(atts, "fill", toString(fill));
}
if (stroke != null) {
- addAttribute(atts, "sroke", toString(stroke));
+ addAttribute(atts, "stroke", toString(stroke));
}
- element("rect", atts);
+ element(EL_RECT, atts);
} catch (SAXException e) {
throw new IFException("SAX error in drawRect()", e);
}
}
/** {@inheritDoc} */
+ public void drawBorderRect(Rectangle rect, BorderProps before, BorderProps after,
+ BorderProps start, BorderProps end) throws IFException {
+ if (before == null && after == null && start == null && end == null) {
+ return;
+ }
+ try {
+ AttributesImpl atts = new AttributesImpl();
+ addAttribute(atts, "x", Integer.toString(rect.x));
+ addAttribute(atts, "y", Integer.toString(rect.y));
+ addAttribute(atts, "width", Integer.toString(rect.width));
+ addAttribute(atts, "height", Integer.toString(rect.height));
+ if (before != null) {
+ addAttribute(atts, "before", before.toString());
+ }
+ if (after != null) {
+ addAttribute(atts, "after", after.toString());
+ }
+ if (start != null) {
+ addAttribute(atts, "start", start.toString());
+ }
+ if (end != null) {
+ addAttribute(atts, "end", end.toString());
+ }
+ element(EL_BORDER_RECT, atts);
+ } catch (SAXException e) {
+ throw new IFException("SAX error in drawBorderRect()", e);
+ }
+ }
+
+ /** {@inheritDoc} */
public void drawText(int x, int y, int[] dx, int[] dy, String text) throws IFException {
try {
AttributesImpl atts = new AttributesImpl();
@@ -383,10 +414,10 @@ public class IFSerializer extends AbstractXMLWritingIFPainter implements IFConst
if (dy != null) {
addAttribute(atts, "dy", toString(dy));
}
- startElement("text", atts);
+ startElement(EL_TEXT, atts);
char[] chars = text.toCharArray();
handler.characters(chars, 0, chars.length);
- endElement("text");
+ endElement(EL_TEXT);
} catch (SAXException e) {
throw new IFException("SAX error in setFont()", e);
}
@@ -415,7 +446,7 @@ public class IFSerializer extends AbstractXMLWritingIFPainter implements IFConst
if (color != null) {
addAttribute(atts, "color", toString(color));
}
- element("font", atts);
+ element(EL_FONT, atts);
} catch (SAXException e) {
throw new IFException("SAX error in setFont()", e);
}
diff --git a/src/java/org/apache/fop/render/pdf/PDFBorderPainter.java b/src/java/org/apache/fop/render/pdf/PDFBorderPainter.java
new file mode 100644
index 000000000..ab34e36c9
--- /dev/null
+++ b/src/java/org/apache/fop/render/pdf/PDFBorderPainter.java
@@ -0,0 +1,263 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.render.pdf;
+
+import java.awt.Color;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.apache.fop.fo.Constants;
+import org.apache.fop.render.PrintRenderer;
+import org.apache.fop.render.intermediate.BorderPainter;
+
+/**
+ * PDF-specific implementation of the {@code BorderPainter}.
+ */
+public class PDFBorderPainter extends BorderPainter {
+
+ /** logging instance */
+ private static Log log = LogFactory.getLog(PDFBorderPainter.class);
+
+ private PDFContentGenerator generator;
+
+ public PDFBorderPainter(PDFContentGenerator generator) {
+ this.generator = generator;
+ }
+
+ /** {@inheritDoc} */
+ protected void drawBorderLine(int x1, int y1, int x2, int y2, boolean horz,
+ boolean startOrBefore, int style, Color col) {
+ drawBorderLine(generator, x1 / 1000f, y1 / 1000f, x2 / 1000f, y2 / 1000f,
+ horz, startOrBefore, style, col);
+ }
+
+ /** {@inheritDoc} */
+ public static void drawBorderLine(PDFContentGenerator generator,
+ float x1, float y1, float x2, float y2, boolean horz,
+ boolean startOrBefore, int style, Color col) {
+ float w = x2 - x1;
+ float h = y2 - y1;
+ if ((w < 0) || (h < 0)) {
+ log.error("Negative extent received (w=" + w + ", h=" + h
+ + "). Border won't be painted.");
+ return;
+ }
+ switch (style) {
+ case Constants.EN_DASHED:
+ generator.setColor(col, false);
+ if (horz) {
+ float unit = Math.abs(2 * h);
+ int rep = (int)(w / unit);
+ if (rep % 2 == 0) {
+ rep++;
+ }
+ unit = w / rep;
+ generator.add("[" + format(unit) + "] 0 d ");
+ generator.add(format(h) + " w\n");
+ float ym = y1 + (h / 2);
+ generator.add(format(x1) + " " + format(ym) + " m "
+ + format(x2) + " " + format(ym) + " l S\n");
+ } else {
+ float unit = Math.abs(2 * w);
+ int rep = (int)(h / unit);
+ if (rep % 2 == 0) {
+ rep++;
+ }
+ unit = h / rep;
+ generator.add("[" + format(unit) + "] 0 d ");
+ generator.add(format(w) + " w\n");
+ float xm = x1 + (w / 2);
+ generator.add(format(xm) + " " + format(y1) + " m "
+ + format(xm) + " " + format(y2) + " l S\n");
+ }
+ break;
+ case Constants.EN_DOTTED:
+ generator.setColor(col, false);
+ generator.add("1 J ");
+ if (horz) {
+ float unit = Math.abs(2 * h);
+ int rep = (int)(w / unit);
+ if (rep % 2 == 0) {
+ rep++;
+ }
+ unit = w / rep;
+ generator.add("[0 " + format(unit) + "] 0 d ");
+ generator.add(format(h) + " w\n");
+ float ym = y1 + (h / 2);
+ generator.add(format(x1) + " " + format(ym) + " m "
+ + format(x2) + " " + format(ym) + " l S\n");
+ } else {
+ float unit = Math.abs(2 * w);
+ int rep = (int)(h / unit);
+ if (rep % 2 == 0) {
+ rep++;
+ }
+ unit = h / rep;
+ generator.add("[0 " + format(unit) + " ] 0 d ");
+ generator.add(format(w) + " w\n");
+ float xm = x1 + (w / 2);
+ generator.add(format(xm) + " " + format(y1) + " m "
+ + format(xm) + " " + format(y2) + " l S\n");
+ }
+ break;
+ case Constants.EN_DOUBLE:
+ generator.setColor(col, false);
+ generator.add("[] 0 d ");
+ if (horz) {
+ float h3 = h / 3;
+ generator.add(format(h3) + " w\n");
+ float ym1 = y1 + (h3 / 2);
+ float ym2 = ym1 + h3 + h3;
+ generator.add(format(x1) + " " + format(ym1) + " m "
+ + format(x2) + " " + format(ym1) + " l S\n");
+ generator.add(format(x1) + " " + format(ym2) + " m "
+ + format(x2) + " " + format(ym2) + " l S\n");
+ } else {
+ float w3 = w / 3;
+ generator.add(format(w3) + " w\n");
+ float xm1 = x1 + (w3 / 2);
+ float xm2 = xm1 + w3 + w3;
+ generator.add(format(xm1) + " " + format(y1) + " m "
+ + format(xm1) + " " + format(y2) + " l S\n");
+ generator.add(format(xm2) + " " + format(y1) + " m "
+ + format(xm2) + " " + format(y2) + " l S\n");
+ }
+ break;
+ case Constants.EN_GROOVE:
+ case Constants.EN_RIDGE:
+ {
+ float colFactor = (style == Constants.EN_GROOVE ? 0.4f : -0.4f);
+ generator.add("[] 0 d ");
+ if (horz) {
+ Color uppercol = PrintRenderer.lightenColor(col, -colFactor);
+ Color lowercol = PrintRenderer.lightenColor(col, colFactor);
+ float h3 = h / 3;
+ generator.add(format(h3) + " w\n");
+ float ym1 = y1 + (h3 / 2);
+ generator.setColor(uppercol, false);
+ generator.add(format(x1) + " " + format(ym1) + " m "
+ + format(x2) + " " + format(ym1) + " l S\n");
+ generator.setColor(col, false);
+ generator.add(format(x1) + " " + format(ym1 + h3) + " m "
+ + format(x2) + " " + format(ym1 + h3) + " l S\n");
+ generator.setColor(lowercol, false);
+ generator.add(format(x1) + " " + format(ym1 + h3 + h3) + " m "
+ + format(x2) + " " + format(ym1 + h3 + h3) + " l S\n");
+ } else {
+ Color leftcol = PrintRenderer.lightenColor(col, -colFactor);
+ Color rightcol = PrintRenderer.lightenColor(col, colFactor);
+ float w3 = w / 3;
+ generator.add(format(w3) + " w\n");
+ float xm1 = x1 + (w3 / 2);
+ generator.setColor(leftcol, false);
+ generator.add(format(xm1) + " " + format(y1) + " m "
+ + format(xm1) + " " + format(y2) + " l S\n");
+ generator.setColor(col, false);
+ generator.add(format(xm1 + w3) + " " + format(y1) + " m "
+ + format(xm1 + w3) + " " + format(y2) + " l S\n");
+ generator.setColor(rightcol, false);
+ generator.add(format(xm1 + w3 + w3) + " " + format(y1) + " m "
+ + format(xm1 + w3 + w3) + " " + format(y2) + " l S\n");
+ }
+ break;
+ }
+ case Constants.EN_INSET:
+ case Constants.EN_OUTSET:
+ {
+ float colFactor = (style == Constants.EN_OUTSET ? 0.4f : -0.4f);
+ generator.add("[] 0 d ");
+ Color c = col;
+ if (horz) {
+ c = PrintRenderer.lightenColor(c, (startOrBefore ? 1 : -1) * colFactor);
+ generator.add(format(h) + " w\n");
+ float ym1 = y1 + (h / 2);
+ generator.setColor(c, false);
+ generator.add(format(x1) + " " + format(ym1) + " m "
+ + format(x2) + " " + format(ym1) + " l S\n");
+ } else {
+ c = PrintRenderer.lightenColor(c, (startOrBefore ? 1 : -1) * colFactor);
+ generator.add(format(w) + " w\n");
+ float xm1 = x1 + (w / 2);
+ generator.setColor(c, false);
+ generator.add(format(xm1) + " " + format(y1) + " m "
+ + format(xm1) + " " + format(y2) + " l S\n");
+ }
+ break;
+ }
+ case Constants.EN_HIDDEN:
+ break;
+ default:
+ generator.setColor(col, false);
+ generator.add("[] 0 d ");
+ if (horz) {
+ generator.add(format(h) + " w\n");
+ float ym = y1 + (h / 2);
+ generator.add(format(x1) + " " + format(ym) + " m "
+ + format(x2) + " " + format(ym) + " l S\n");
+ } else {
+ generator.add(format(w) + " w\n");
+ float xm = x1 + (w / 2);
+ generator.add(format(xm) + " " + format(y1) + " m "
+ + format(xm) + " " + format(y2) + " l S\n");
+ }
+ }
+ }
+
+
+ static final String format(int coordinate) {
+ return format(coordinate / 1000f);
+ }
+
+ static final String format(float coordinate) {
+ return PDFContentGenerator.format(coordinate);
+ }
+
+ /** {@inheritDoc} */
+ protected void moveTo(int x, int y) {
+ generator.add(format(x) + " " + format(y) + " m ");
+ }
+
+ /** {@inheritDoc} */
+ protected void lineTo(int x, int y) {
+ generator.add(format(x) + " " + format(y) + " l ");
+ }
+
+ /** {@inheritDoc} */
+ protected void closePath() {
+ generator.add("h ");
+ }
+
+ /** {@inheritDoc} */
+ protected void clip() {
+ generator.add("W\n" + "n\n");
+ }
+
+ /** {@inheritDoc} */
+ protected void saveGraphicsState() {
+ generator.add("q\n");
+ }
+
+ /** {@inheritDoc} */
+ protected void restoreGraphicsState() {
+ generator.add("Q\n");
+ }
+
+}
diff --git a/src/java/org/apache/fop/render/pdf/PDFContentGenerator.java b/src/java/org/apache/fop/render/pdf/PDFContentGenerator.java
index 8d5b4ccb0..da1bf728e 100644
--- a/src/java/org/apache/fop/render/pdf/PDFContentGenerator.java
+++ b/src/java/org/apache/fop/render/pdf/PDFContentGenerator.java
@@ -222,7 +222,7 @@ public class PDFContentGenerator {
* @param value the value
* @return the formatted value
*/
- protected static String format(float value) {
+ public static final String format(float value) {
return PDFNumber.doubleOut(value);
}
diff --git a/src/java/org/apache/fop/render/pdf/PDFPainter.java b/src/java/org/apache/fop/render/pdf/PDFPainter.java
index 5e57946fb..cfbc21d35 100644
--- a/src/java/org/apache/fop/render/pdf/PDFPainter.java
+++ b/src/java/org/apache/fop/render/pdf/PDFPainter.java
@@ -64,6 +64,7 @@ import org.apache.fop.render.intermediate.extensions.Bookmark;
import org.apache.fop.render.intermediate.extensions.BookmarkTree;
import org.apache.fop.render.intermediate.extensions.GoToXYAction;
import org.apache.fop.render.intermediate.extensions.NamedDestination;
+import org.apache.fop.traits.BorderProps;
import org.apache.fop.util.CharUtilities;
/**
@@ -92,6 +93,8 @@ public class PDFPainter extends AbstractBinaryWritingIFPainter {
/** The current content generator */
protected PDFContentGenerator generator;
+ private PDFBorderPainter borderPainter;
+
/** the current annotation list to add annotations to */
protected PDFResourceContext currentContext;
@@ -201,6 +204,8 @@ public class PDFPainter extends AbstractBinaryWritingIFPainter {
AffineTransform basicPageTransform = new AffineTransform(1, 0, 0, -1, 0,
size.height / 1000f);
generator.concatenate(basicPageTransform);
+
+ this.borderPainter = new PDFBorderPainter(this.generator);
}
/** {@inheritDoc} */
@@ -357,6 +362,13 @@ public class PDFPainter extends AbstractBinaryWritingIFPainter {
}
}
+ /** {@inheritDoc} */
+ public void drawBorderRect(Rectangle rect, BorderProps before, BorderProps after,
+ BorderProps start, BorderProps end) throws IFException {
+ this.borderPainter.drawBorders(rect, before, after, start, end);
+
+ }
+
private Typeface getTypeface(String fontName) {
if (fontName == null) {
throw new NullPointerException("fontName must not be null");
diff --git a/src/java/org/apache/fop/render/pdf/PDFRenderer.java b/src/java/org/apache/fop/render/pdf/PDFRenderer.java
index fbcf892a0..591cca96b 100644
--- a/src/java/org/apache/fop/render/pdf/PDFRenderer.java
+++ b/src/java/org/apache/fop/render/pdf/PDFRenderer.java
@@ -64,7 +64,6 @@ import org.apache.fop.area.inline.TextArea;
import org.apache.fop.area.inline.WordArea;
import org.apache.fop.datatypes.URISpecification;
import org.apache.fop.events.ResourceEventProducer;
-import org.apache.fop.fo.Constants;
import org.apache.fop.fo.extensions.ExtensionAttachment;
import org.apache.fop.fo.extensions.xmp.XMPMetadata;
import org.apache.fop.fonts.Font;
@@ -541,172 +540,7 @@ public class PDFRenderer extends AbstractPathOrientedRenderer implements PDFConf
/** {@inheritDoc} */
protected void drawBorderLine(float x1, float y1, float x2, float y2,
boolean horz, boolean startOrBefore, int style, Color col) {
- float w = x2 - x1;
- float h = y2 - y1;
- if ((w < 0) || (h < 0)) {
- log.error("Negative extent received (w=" + w + ", h=" + h
- + "). Border won't be painted.");
- return;
- }
- switch (style) {
- case Constants.EN_DASHED:
- generator.setColor(col, false);
- if (horz) {
- float unit = Math.abs(2 * h);
- int rep = (int)(w / unit);
- if (rep % 2 == 0) {
- rep++;
- }
- unit = w / rep;
- generator.add("[" + format(unit) + "] 0 d ");
- generator.add(format(h) + " w\n");
- float ym = y1 + (h / 2);
- generator.add(format(x1) + " " + format(ym) + " m "
- + format(x2) + " " + format(ym) + " l S\n");
- } else {
- float unit = Math.abs(2 * w);
- int rep = (int)(h / unit);
- if (rep % 2 == 0) {
- rep++;
- }
- unit = h / rep;
- generator.add("[" + format(unit) + "] 0 d ");
- generator.add(format(w) + " w\n");
- float xm = x1 + (w / 2);
- generator.add(format(xm) + " " + format(y1) + " m "
- + format(xm) + " " + format(y2) + " l S\n");
- }
- break;
- case Constants.EN_DOTTED:
- generator.setColor(col, false);
- generator.add("1 J ");
- if (horz) {
- float unit = Math.abs(2 * h);
- int rep = (int)(w / unit);
- if (rep % 2 == 0) {
- rep++;
- }
- unit = w / rep;
- generator.add("[0 " + format(unit) + "] 0 d ");
- generator.add(format(h) + " w\n");
- float ym = y1 + (h / 2);
- generator.add(format(x1) + " " + format(ym) + " m "
- + format(x2) + " " + format(ym) + " l S\n");
- } else {
- float unit = Math.abs(2 * w);
- int rep = (int)(h / unit);
- if (rep % 2 == 0) {
- rep++;
- }
- unit = h / rep;
- generator.add("[0 " + format(unit) + " ] 0 d ");
- generator.add(format(w) + " w\n");
- float xm = x1 + (w / 2);
- generator.add(format(xm) + " " + format(y1) + " m "
- + format(xm) + " " + format(y2) + " l S\n");
- }
- break;
- case Constants.EN_DOUBLE:
- generator.setColor(col, false);
- generator.add("[] 0 d ");
- if (horz) {
- float h3 = h / 3;
- generator.add(format(h3) + " w\n");
- float ym1 = y1 + (h3 / 2);
- float ym2 = ym1 + h3 + h3;
- generator.add(format(x1) + " " + format(ym1) + " m "
- + format(x2) + " " + format(ym1) + " l S\n");
- generator.add(format(x1) + " " + format(ym2) + " m "
- + format(x2) + " " + format(ym2) + " l S\n");
- } else {
- float w3 = w / 3;
- generator.add(format(w3) + " w\n");
- float xm1 = x1 + (w3 / 2);
- float xm2 = xm1 + w3 + w3;
- generator.add(format(xm1) + " " + format(y1) + " m "
- + format(xm1) + " " + format(y2) + " l S\n");
- generator.add(format(xm2) + " " + format(y1) + " m "
- + format(xm2) + " " + format(y2) + " l S\n");
- }
- break;
- case Constants.EN_GROOVE:
- case Constants.EN_RIDGE:
- {
- float colFactor = (style == EN_GROOVE ? 0.4f : -0.4f);
- generator.add("[] 0 d ");
- if (horz) {
- Color uppercol = lightenColor(col, -colFactor);
- Color lowercol = lightenColor(col, colFactor);
- float h3 = h / 3;
- generator.add(format(h3) + " w\n");
- float ym1 = y1 + (h3 / 2);
- generator.setColor(uppercol, false);
- generator.add(format(x1) + " " + format(ym1) + " m "
- + format(x2) + " " + format(ym1) + " l S\n");
- generator.setColor(col, false);
- generator.add(format(x1) + " " + format(ym1 + h3) + " m "
- + format(x2) + " " + format(ym1 + h3) + " l S\n");
- generator.setColor(lowercol, false);
- generator.add(format(x1) + " " + format(ym1 + h3 + h3) + " m "
- + format(x2) + " " + format(ym1 + h3 + h3) + " l S\n");
- } else {
- Color leftcol = lightenColor(col, -colFactor);
- Color rightcol = lightenColor(col, colFactor);
- float w3 = w / 3;
- generator.add(format(w3) + " w\n");
- float xm1 = x1 + (w3 / 2);
- generator.setColor(leftcol, false);
- generator.add(format(xm1) + " " + format(y1) + " m "
- + format(xm1) + " " + format(y2) + " l S\n");
- generator.setColor(col, false);
- generator.add(format(xm1 + w3) + " " + format(y1) + " m "
- + format(xm1 + w3) + " " + format(y2) + " l S\n");
- generator.setColor(rightcol, false);
- generator.add(format(xm1 + w3 + w3) + " " + format(y1) + " m "
- + format(xm1 + w3 + w3) + " " + format(y2) + " l S\n");
- }
- break;
- }
- case Constants.EN_INSET:
- case Constants.EN_OUTSET:
- {
- float colFactor = (style == EN_OUTSET ? 0.4f : -0.4f);
- generator.add("[] 0 d ");
- Color c = col;
- if (horz) {
- c = lightenColor(c, (startOrBefore ? 1 : -1) * colFactor);
- generator.add(format(h) + " w\n");
- float ym1 = y1 + (h / 2);
- generator.setColor(c, false);
- generator.add(format(x1) + " " + format(ym1) + " m "
- + format(x2) + " " + format(ym1) + " l S\n");
- } else {
- c = lightenColor(c, (startOrBefore ? 1 : -1) * colFactor);
- generator.add(format(w) + " w\n");
- float xm1 = x1 + (w / 2);
- generator.setColor(c, false);
- generator.add(format(xm1) + " " + format(y1) + " m "
- + format(xm1) + " " + format(y2) + " l S\n");
- }
- break;
- }
- case Constants.EN_HIDDEN:
- break;
- default:
- generator.setColor(col, false);
- generator.add("[] 0 d ");
- if (horz) {
- generator.add(format(h) + " w\n");
- float ym = y1 + (h / 2);
- generator.add(format(x1) + " " + format(ym) + " m "
- + format(x2) + " " + format(ym) + " l S\n");
- } else {
- generator.add(format(w) + " w\n");
- float xm = x1 + (w / 2);
- generator.add(format(xm) + " " + format(y1) + " m "
- + format(xm) + " " + format(y2) + " l S\n");
- }
- }
+ PDFBorderPainter.drawBorderLine(generator, x1, y1, x2, y2, horz, startOrBefore, style, col);
}
/** {@inheritDoc} */