git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_AreaTreeNewDesign@685827 13f79535-47bb-0310-9956-ffa450edef68tags/fop-1_0
@@ -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. |
@@ -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(); | |||
} |
@@ -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"; | |||
} |
@@ -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. | |||
@@ -276,6 +277,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. |
@@ -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 { |
@@ -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); | |||
@@ -963,18 +969,37 @@ public class IFRenderer extends AbstractPathOrientedRenderer { | |||
log.warn("closePath() NYI"); | |||
} | |||
/** {@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} */ |
@@ -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,14 +364,44 @@ 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 { | |||
@@ -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); | |||
} |
@@ -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"); | |||
} | |||
} |
@@ -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); | |||
} | |||
@@ -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"); |
@@ -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} */ |
@@ -51,6 +51,7 @@ import org.apache.fop.render.intermediate.AbstractXMLWritingIFPainter; | |||
import org.apache.fop.render.intermediate.IFConstants; | |||
import org.apache.fop.render.intermediate.IFException; | |||
import org.apache.fop.render.intermediate.IFState; | |||
import org.apache.fop.traits.BorderProps; | |||
import org.apache.fop.util.ColorUtil; | |||
/** | |||
@@ -300,6 +301,12 @@ public abstract class AbstractSVGPainter extends AbstractXMLWritingIFPainter | |||
} | |||
} | |||
/** {@inheritDoc} */ | |||
public void drawBorderRect(Rectangle rect, BorderProps before, BorderProps after, | |||
BorderProps start, BorderProps end) throws IFException { | |||
// TODO Auto-generated method stub | |||
} | |||
/** {@inheritDoc} */ | |||
public void drawText(int x, int y, int[] dx, int[] dy, String text) throws IFException { | |||
try { |
@@ -6,6 +6,18 @@ | |||
<renderers> | |||
<renderer mime="application/pdf"> | |||
<filterList type="tiff"> | |||
<value>ascii-85</value> | |||
</filterList> | |||
<filterList type="default"> | |||
<value>null</value> | |||
</filterList> | |||
<filterList type="image"> | |||
<value>null</value> | |||
</filterList> | |||
<filterList type="content"> | |||
<value>null</value> | |||
</filterList> | |||
<fonts> | |||
<font metrics-url="test/resources/fonts/glb12.ttf.xml" embed-url="test/resources/fonts/glb12.ttf"> | |||
<font-triplet name="Gladiator" style="normal" weight="normal"/> |