diff options
author | Jeremias Maerki <jeremias@apache.org> | 2008-08-14 09:13:09 +0000 |
---|---|---|
committer | Jeremias Maerki <jeremias@apache.org> | 2008-08-14 09:13:09 +0000 |
commit | 07c47a253ccfd4afd4111beafe270eb8b5ef144a (patch) | |
tree | 6198565a342e9ef182f901c924a1ef4f2551084b /src/java/org/apache/fop | |
parent | 686f92dd78dcf4b6750230a55de5c1427ab20464 (diff) | |
download | xmlgraphics-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')
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} */ |