Browse Source

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
tags/fop-1_0
Jeremias Maerki 15 years ago
parent
commit
07c47a253c

+ 2
- 0
src/java/org/apache/fop/render/intermediate/AbstractIFPainter.java View File

@@ -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.

+ 214
- 0
src/java/org/apache/fop/render/intermediate/BorderPainter.java View File

@@ -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();

}

+ 4
- 0
src/java/org/apache/fop/render/intermediate/IFConstants.java View File

@@ -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";
}

+ 15
- 0
src/java/org/apache/fop/render/intermediate/IFPainter.java View File

@@ -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.

+ 32
- 7
src/java/org/apache/fop/render/intermediate/IFParser.java View File

@@ -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 {

+ 28
- 3
src/java/org/apache/fop/render/intermediate/IFRenderer.java View File

@@ -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} */

+ 37
- 6
src/java/org/apache/fop/render/intermediate/IFSerializer.java View File

@@ -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);
}

+ 263
- 0
src/java/org/apache/fop/render/pdf/PDFBorderPainter.java View File

@@ -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");
}

}

+ 1
- 1
src/java/org/apache/fop/render/pdf/PDFContentGenerator.java View File

@@ -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);
}


+ 12
- 0
src/java/org/apache/fop/render/pdf/PDFPainter.java View File

@@ -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");

+ 1
- 167
src/java/org/apache/fop/render/pdf/PDFRenderer.java View File

@@ -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} */

+ 7
- 0
src/sandbox/org/apache/fop/render/svg/AbstractSVGPainter.java View File

@@ -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 {

+ 12
- 0
test/test.xconf View File

@@ -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"/>

Loading…
Cancel
Save