|
|
@@ -0,0 +1,506 @@ |
|
|
|
// PrintRenderer is an abstract base class for renderers that produce printed type output. |
|
|
|
// Subclasses would be PDFRenderer, PCLRenderer and similar renderers. |
|
|
|
|
|
|
|
package org.apache.fop.render; |
|
|
|
|
|
|
|
// FOP |
|
|
|
import org.apache.fop.pdf.PDFPathPaint; |
|
|
|
import org.apache.fop.pdf.PDFColor; |
|
|
|
//import org.apache.fop.render.Renderer; |
|
|
|
//import org.apache.fop.messaging.MessageHandler; |
|
|
|
import org.apache.fop.image.ImageArea; |
|
|
|
//import org.apache.fop.image.FopImage; |
|
|
|
import org.apache.fop.apps.FOPException; |
|
|
|
import org.apache.fop.fo.properties.*; |
|
|
|
import org.apache.fop.layout.*; |
|
|
|
import org.apache.fop.layout.inline.*; |
|
|
|
import org.apache.fop.datatypes.*; |
|
|
|
//import org.apache.fop.configuration.Configuration; |
|
|
|
//import org.apache.fop.extensions.*; |
|
|
|
//import org.apache.fop.datatypes.IDReferences; |
|
|
|
import org.apache.fop.render.pdf.FontSetup; |
|
|
|
|
|
|
|
import org.apache.fop.dom.svg.*; |
|
|
|
|
|
|
|
// Java |
|
|
|
import java.io.IOException; |
|
|
|
import java.io.OutputStream; |
|
|
|
import java.util.Enumeration; |
|
|
|
|
|
|
|
/** |
|
|
|
* Abstract base class of "Print" type renderers. |
|
|
|
*/ |
|
|
|
public abstract class PrintRenderer implements Renderer |
|
|
|
{ |
|
|
|
// vvv These are not currently referenced by the PrintRenderer, but are common to PCL and PDF renderers - so declare here. |
|
|
|
/** the current (internal) font name */ |
|
|
|
protected String currentFontName; |
|
|
|
/** the current font size in millipoints */ |
|
|
|
protected int currentFontSize; |
|
|
|
/** the current color/gradient for borders, letters, etc. */ |
|
|
|
protected PDFPathPaint currentStroke = null; |
|
|
|
/** the current color/gradient to fill shapes with */ |
|
|
|
protected PDFPathPaint currentFill = null; |
|
|
|
/** the current colour's red component */ |
|
|
|
//protected float currentRed = 0; |
|
|
|
/** the current colour's green component */ |
|
|
|
//protected float currentGreen = 0; |
|
|
|
/** the current colour's blue component */ |
|
|
|
//protected float currentBlue = 0; |
|
|
|
// ^^^ |
|
|
|
|
|
|
|
/** the current vertical position in millipoints from bottom */ |
|
|
|
protected int currentYPosition = 0; |
|
|
|
|
|
|
|
/** the current horizontal position in millipoints from left */ |
|
|
|
protected int currentXPosition = 0; |
|
|
|
|
|
|
|
/** the horizontal position of the current area container */ |
|
|
|
protected int currentAreaContainerXPosition = 0; |
|
|
|
|
|
|
|
// previous values used for text-decoration drawing |
|
|
|
protected int prevUnderlineXEndPos; |
|
|
|
protected int prevUnderlineYEndPos; |
|
|
|
protected int prevUnderlineSize; |
|
|
|
protected PDFColor prevUnderlineColor; |
|
|
|
protected int prevOverlineXEndPos; |
|
|
|
protected int prevOverlineYEndPos; |
|
|
|
protected int prevOverlineSize; |
|
|
|
protected PDFColor prevOverlineColor; |
|
|
|
protected int prevLineThroughXEndPos; |
|
|
|
protected int prevLineThroughYEndPos; |
|
|
|
protected int prevLineThroughSize; |
|
|
|
protected PDFColor prevLineThroughColor; |
|
|
|
|
|
|
|
protected FontInfo fontInfo; |
|
|
|
|
|
|
|
/** the IDReferences for this document */ |
|
|
|
protected IDReferences idReferences; |
|
|
|
|
|
|
|
/** |
|
|
|
* set the document's producer |
|
|
|
* |
|
|
|
* @param producer string indicating application producing PDF |
|
|
|
*/ |
|
|
|
public abstract void setProducer(String producer); |
|
|
|
|
|
|
|
/** |
|
|
|
* render the areas |
|
|
|
* |
|
|
|
* @param areaTree the laid-out area tree |
|
|
|
* @param stream the OutputStream to write to |
|
|
|
*/ |
|
|
|
public abstract void render(AreaTree areaTree, |
|
|
|
OutputStream stream) throws IOException, FOPException; |
|
|
|
|
|
|
|
/** |
|
|
|
* add a line to the current stream |
|
|
|
* |
|
|
|
* @param x1 the start x location in millipoints |
|
|
|
* @param y1 the start y location in millipoints |
|
|
|
* @param x2 the end x location in millipoints |
|
|
|
* @param y2 the end y location in millipoints |
|
|
|
* @param th the thickness in millipoints |
|
|
|
* @param r the red component |
|
|
|
* @param g the green component |
|
|
|
* @param b the blue component |
|
|
|
*/ |
|
|
|
protected abstract void addLine(int x1, int y1, int x2, int y2, int th, |
|
|
|
PDFPathPaint stroke); |
|
|
|
|
|
|
|
/** |
|
|
|
* add a line to the current stream |
|
|
|
* |
|
|
|
* @param x1 the start x location in millipoints |
|
|
|
* @param y1 the start y location in millipoints |
|
|
|
* @param x2 the end x location in millipoints |
|
|
|
* @param y2 the end y location in millipoints |
|
|
|
* @param th the thickness in millipoints |
|
|
|
* @param rs the rule style |
|
|
|
* @param r the red component |
|
|
|
* @param g the green component |
|
|
|
* @param b the blue component |
|
|
|
*/ |
|
|
|
protected abstract void addLine(int x1, int y1, int x2, int y2, int th, |
|
|
|
int rs, PDFPathPaint stroke); |
|
|
|
/** |
|
|
|
* add a rectangle to the current stream |
|
|
|
* |
|
|
|
* @param x the x position of left edge in millipoints |
|
|
|
* @param y the y position of top edge in millipoints |
|
|
|
* @param w the width in millipoints |
|
|
|
* @param h the height in millipoints |
|
|
|
* @param stroke the stroke color/gradient |
|
|
|
*/ |
|
|
|
protected abstract void addRect(int x, int y, int w, int h, |
|
|
|
PDFPathPaint stroke); |
|
|
|
|
|
|
|
/** |
|
|
|
* add a filled rectangle to the current stream |
|
|
|
* |
|
|
|
* @param x the x position of left edge in millipoints |
|
|
|
* @param y the y position of top edge in millipoints |
|
|
|
* @param w the width in millipoints |
|
|
|
* @param h the height in millipoints |
|
|
|
* @param fill the fill color/gradient |
|
|
|
* @param stroke the stroke color/gradient |
|
|
|
*/ |
|
|
|
protected abstract void addRect(int x, int y, int w, int h, |
|
|
|
PDFPathPaint stroke, PDFPathPaint fill); |
|
|
|
|
|
|
|
/** |
|
|
|
* render area container |
|
|
|
* |
|
|
|
* @param area the area container to render |
|
|
|
*/ |
|
|
|
public void renderAreaContainer(AreaContainer area) { |
|
|
|
|
|
|
|
int saveY = this.currentYPosition; |
|
|
|
int saveX = this.currentAreaContainerXPosition; |
|
|
|
|
|
|
|
if (area.getPosition() == Position.ABSOLUTE) { |
|
|
|
// Y position is computed assuming positive Y axis, adjust for negative postscript one |
|
|
|
this.currentYPosition = |
|
|
|
area.getYPosition() - 2 * area.getPaddingTop() - |
|
|
|
2 * area.getBorderTopWidth(); |
|
|
|
this.currentAreaContainerXPosition = area.getXPosition(); |
|
|
|
} else if (area.getPosition() == Position.RELATIVE) { |
|
|
|
this.currentYPosition -= area.getYPosition(); |
|
|
|
this.currentAreaContainerXPosition += area.getXPosition(); |
|
|
|
} else if (area.getPosition() == Position.STATIC) { |
|
|
|
this.currentYPosition -= |
|
|
|
area.getPaddingTop() + area.getBorderTopWidth(); |
|
|
|
this.currentAreaContainerXPosition += |
|
|
|
area.getPaddingLeft() + area.getBorderLeftWidth(); |
|
|
|
} |
|
|
|
|
|
|
|
this.currentXPosition = this.currentAreaContainerXPosition; |
|
|
|
doFrame(area); |
|
|
|
|
|
|
|
Enumeration e = area.getChildren().elements(); |
|
|
|
while (e.hasMoreElements()) { |
|
|
|
Box b = (Box) e.nextElement(); |
|
|
|
b.render(this); |
|
|
|
} |
|
|
|
if (area.getPosition() != Position.STATIC) { |
|
|
|
this.currentYPosition = saveY; |
|
|
|
this.currentAreaContainerXPosition = saveX; |
|
|
|
} else |
|
|
|
this.currentYPosition -= area.getHeight(); |
|
|
|
} |
|
|
|
|
|
|
|
public void renderBodyAreaContainer(BodyAreaContainer area) { |
|
|
|
int saveY = this.currentYPosition; |
|
|
|
int saveX = this.currentAreaContainerXPosition; |
|
|
|
|
|
|
|
if (area.getPosition() == Position.ABSOLUTE) { |
|
|
|
// Y position is computed assuming positive Y axis, adjust for negative postscript one |
|
|
|
this.currentYPosition = area.getYPosition(); |
|
|
|
this.currentAreaContainerXPosition = area.getXPosition(); |
|
|
|
} else if (area.getPosition() == Position.RELATIVE) { |
|
|
|
this.currentYPosition -= area.getYPosition(); |
|
|
|
this.currentAreaContainerXPosition += area.getXPosition(); |
|
|
|
} |
|
|
|
|
|
|
|
this.currentXPosition = this.currentAreaContainerXPosition; |
|
|
|
int w, h; |
|
|
|
int rx = this.currentAreaContainerXPosition; |
|
|
|
w = area.getContentWidth(); |
|
|
|
h = area.getContentHeight(); |
|
|
|
int ry = this.currentYPosition; |
|
|
|
ColorType bg = area.getBackgroundColor(); |
|
|
|
|
|
|
|
// I'm not sure I should have to check for bg being null |
|
|
|
// but I do |
|
|
|
if ((bg != null) && (bg.alpha() == 0)) { |
|
|
|
this.addRect(rx, ry, w, -h, new PDFColor(bg), new PDFColor(bg)); |
|
|
|
} |
|
|
|
|
|
|
|
// floats & footnotes stuff |
|
|
|
renderAreaContainer(area.getBeforeFloatReferenceArea()); |
|
|
|
renderAreaContainer(area.getFootnoteReferenceArea()); |
|
|
|
|
|
|
|
// main reference area |
|
|
|
Enumeration e = area.getMainReferenceArea().getChildren().elements(); |
|
|
|
while (e.hasMoreElements()) { |
|
|
|
Box b = (Box) e.nextElement(); |
|
|
|
b.render(this); // span areas |
|
|
|
} |
|
|
|
|
|
|
|
if (area.getPosition() != Position.STATIC) { |
|
|
|
this.currentYPosition = saveY; |
|
|
|
this.currentAreaContainerXPosition = saveX; |
|
|
|
} else |
|
|
|
this.currentYPosition -= area.getHeight(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
public void renderSpanArea(SpanArea area) { |
|
|
|
Enumeration e = area.getChildren().elements(); |
|
|
|
while (e.hasMoreElements()) { |
|
|
|
Box b = (Box) e.nextElement(); |
|
|
|
b.render(this); // column areas |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
private void doFrame(Area area) { |
|
|
|
int w, h; |
|
|
|
int rx = this.currentAreaContainerXPosition; |
|
|
|
w = area.getContentWidth(); |
|
|
|
if (area instanceof BlockArea) |
|
|
|
rx += ((BlockArea) area).getStartIndent(); |
|
|
|
h = area.getContentHeight(); |
|
|
|
int ry = this.currentYPosition; |
|
|
|
ColorType bg = area.getBackgroundColor(); |
|
|
|
|
|
|
|
rx = rx - area.getPaddingLeft(); |
|
|
|
ry = ry + area.getPaddingTop(); |
|
|
|
w = w + area.getPaddingLeft() + area.getPaddingRight(); |
|
|
|
h = h + area.getPaddingTop() + area.getPaddingBottom(); |
|
|
|
|
|
|
|
// I'm not sure I should have to check for bg being null |
|
|
|
// but I do |
|
|
|
if ((bg != null) && (bg.alpha() == 0)) { |
|
|
|
this.addRect(rx, ry, w, -h, new PDFColor(bg), new PDFColor(bg)); |
|
|
|
} |
|
|
|
|
|
|
|
rx = rx - area.getBorderLeftWidth(); |
|
|
|
ry = ry + area.getBorderTopWidth(); |
|
|
|
w = w + area.getBorderLeftWidth() + area.getBorderRightWidth(); |
|
|
|
h = h + area.getBorderTopWidth() + area.getBorderBottomWidth(); |
|
|
|
|
|
|
|
// Handle line style |
|
|
|
// Offset for haft the line width! |
|
|
|
BorderAndPadding bp = area.getBorderAndPadding(); |
|
|
|
if (area.getBorderTopWidth() != 0) |
|
|
|
addLine(rx, ry, rx + w, ry, area.getBorderTopWidth(), |
|
|
|
new PDFColor(bp.getBorderColor(BorderAndPadding.TOP))); |
|
|
|
if (area.getBorderLeftWidth() != 0) |
|
|
|
addLine(rx, ry, rx, ry - h, area.getBorderLeftWidth(), |
|
|
|
new PDFColor(bp.getBorderColor(BorderAndPadding.LEFT))); |
|
|
|
if (area.getBorderRightWidth() != 0) |
|
|
|
addLine(rx + w, ry, rx + w, ry - h, area.getBorderRightWidth(), |
|
|
|
new PDFColor(bp.getBorderColor(BorderAndPadding.RIGHT))); |
|
|
|
if (area.getBorderBottomWidth() != 0) |
|
|
|
addLine(rx, ry - h, rx + w, ry - h, area.getBorderBottomWidth(), |
|
|
|
new PDFColor(bp.getBorderColor(BorderAndPadding.BOTTOM))); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* render block area |
|
|
|
* |
|
|
|
* @param area the block area to render |
|
|
|
*/ |
|
|
|
public void renderBlockArea(BlockArea area) { |
|
|
|
// KLease: Temporary test to fix block positioning |
|
|
|
// Offset ypos by padding and border widths |
|
|
|
this.currentYPosition -= (area.getPaddingTop() + area.getBorderTopWidth()); |
|
|
|
doFrame(area); |
|
|
|
Enumeration e = area.getChildren().elements(); |
|
|
|
while (e.hasMoreElements()) { |
|
|
|
Box b = (Box) e.nextElement(); |
|
|
|
b.render(this); |
|
|
|
} |
|
|
|
this.currentYPosition -= (area.getPaddingBottom() + area.getBorderBottomWidth()); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* render display space |
|
|
|
* |
|
|
|
* @param space the display space to render |
|
|
|
*/ |
|
|
|
public void renderDisplaySpace(DisplaySpace space) { |
|
|
|
int d = space.getSize(); |
|
|
|
this.currentYPosition -= d; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* render image area |
|
|
|
* |
|
|
|
* @param area the image area to render |
|
|
|
*/ |
|
|
|
public abstract void renderImageArea(ImageArea area); |
|
|
|
|
|
|
|
/** render a foreign object area */ |
|
|
|
public abstract void renderForeignObjectArea(ForeignObjectArea area); |
|
|
|
|
|
|
|
/** |
|
|
|
* render SVG area |
|
|
|
* |
|
|
|
* @param area the SVG area to render |
|
|
|
*/ |
|
|
|
public abstract void renderSVGArea(SVGArea area); |
|
|
|
|
|
|
|
/** |
|
|
|
* render inline area |
|
|
|
* |
|
|
|
* @param area inline area to render |
|
|
|
*/ |
|
|
|
public abstract void renderWordArea(WordArea area); |
|
|
|
|
|
|
|
protected void addWordLines(WordArea area, int rx, int bl, int size, PDFColor theAreaColor) |
|
|
|
{ |
|
|
|
if (area.getUnderlined()) { |
|
|
|
int yPos = bl - size/10; |
|
|
|
addLine(rx, yPos, rx + area.getContentWidth(), |
|
|
|
yPos, size/14, theAreaColor); |
|
|
|
// save position for underlining a following InlineSpace |
|
|
|
prevUnderlineXEndPos = rx + area.getContentWidth(); |
|
|
|
prevUnderlineYEndPos = yPos; |
|
|
|
prevUnderlineSize = size/14; |
|
|
|
prevUnderlineColor = theAreaColor; |
|
|
|
} |
|
|
|
|
|
|
|
if (area.getOverlined()) { |
|
|
|
int yPos = bl + area.getFontState().getAscender() + size/10; |
|
|
|
addLine(rx, yPos, rx + area.getContentWidth(), |
|
|
|
yPos, size/14, theAreaColor); |
|
|
|
prevOverlineXEndPos = rx + area.getContentWidth(); |
|
|
|
prevOverlineYEndPos = yPos; |
|
|
|
prevOverlineSize = size/14; |
|
|
|
prevOverlineColor = theAreaColor; |
|
|
|
} |
|
|
|
|
|
|
|
if (area.getLineThrough()) { |
|
|
|
int yPos = bl + area.getFontState().getAscender() * 3/8; |
|
|
|
addLine(rx, yPos, rx + area.getContentWidth(), |
|
|
|
yPos, size/14, theAreaColor); |
|
|
|
prevLineThroughXEndPos = rx + area.getContentWidth(); |
|
|
|
prevLineThroughYEndPos = yPos; |
|
|
|
prevLineThroughSize = size/14; |
|
|
|
prevLineThroughColor = theAreaColor; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* render inline space |
|
|
|
* |
|
|
|
* @param space space to render |
|
|
|
*/ |
|
|
|
public void renderInlineSpace(InlineSpace space) { |
|
|
|
this.currentXPosition += space.getSize(); |
|
|
|
if (space.getUnderlined()) { |
|
|
|
if (prevUnderlineColor != null) { |
|
|
|
addLine(prevUnderlineXEndPos, prevUnderlineYEndPos, |
|
|
|
prevUnderlineXEndPos + space.getSize(), |
|
|
|
prevUnderlineYEndPos, prevUnderlineSize, prevUnderlineColor); |
|
|
|
} |
|
|
|
} |
|
|
|
if (space.getOverlined()) { |
|
|
|
if (prevOverlineColor != null) { |
|
|
|
addLine(prevOverlineXEndPos, prevOverlineYEndPos, |
|
|
|
prevOverlineXEndPos + space.getSize(), |
|
|
|
prevOverlineYEndPos, prevOverlineSize, prevOverlineColor); |
|
|
|
} |
|
|
|
} |
|
|
|
if (space.getLineThrough()) { |
|
|
|
if (prevLineThroughColor != null) { |
|
|
|
addLine(prevLineThroughXEndPos, prevLineThroughYEndPos, |
|
|
|
prevLineThroughXEndPos + space.getSize(), |
|
|
|
prevLineThroughYEndPos, prevLineThroughSize, prevLineThroughColor); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* render line area |
|
|
|
* |
|
|
|
* @param area area to render |
|
|
|
*/ |
|
|
|
public void renderLineArea(LineArea area) { |
|
|
|
int rx = this.currentAreaContainerXPosition + area.getStartIndent(); |
|
|
|
int ry = this.currentYPosition; |
|
|
|
int w = area.getContentWidth(); |
|
|
|
int h = area.getHeight(); |
|
|
|
|
|
|
|
this.currentYPosition -= area.getPlacementOffset(); |
|
|
|
this.currentXPosition = rx; |
|
|
|
|
|
|
|
int bl = this.currentYPosition; |
|
|
|
|
|
|
|
Enumeration e = area.getChildren().elements(); |
|
|
|
while (e.hasMoreElements()) { |
|
|
|
Box b = (Box) e.nextElement(); |
|
|
|
if(b instanceof InlineArea) { |
|
|
|
InlineArea ia = (InlineArea)b; |
|
|
|
this.currentYPosition = ry - ia.getYOffset(); |
|
|
|
} else { |
|
|
|
this.currentYPosition = ry - area.getPlacementOffset(); |
|
|
|
} |
|
|
|
b.render(this); |
|
|
|
} |
|
|
|
|
|
|
|
this.currentYPosition = ry - h; |
|
|
|
this.currentXPosition = rx; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* render page |
|
|
|
* |
|
|
|
* @param page page to render |
|
|
|
*/ |
|
|
|
public abstract void renderPage(Page page); |
|
|
|
|
|
|
|
/** |
|
|
|
* render leader area |
|
|
|
* |
|
|
|
* @param area area to render |
|
|
|
*/ |
|
|
|
public void renderLeaderArea(LeaderArea area) { |
|
|
|
int rx = this.currentXPosition; |
|
|
|
int ry = this.currentYPosition; |
|
|
|
int w = area.getContentWidth(); |
|
|
|
int h = area.getHeight(); |
|
|
|
int th = area.getRuleThickness(); |
|
|
|
int st = area.getRuleStyle(); |
|
|
|
|
|
|
|
//checks whether thickness is = 0, because of bug in pdf (or where?), |
|
|
|
//a line with thickness 0 is still displayed |
|
|
|
if (th != 0) { |
|
|
|
switch (st) { |
|
|
|
case org.apache.fop.fo.properties.RuleStyle.DOUBLE: |
|
|
|
addLine(rx, ry, rx + w, ry, th / 3, st, |
|
|
|
new PDFColor(area.getRed(), |
|
|
|
area.getGreen(), area.getBlue())); |
|
|
|
addLine(rx, ry + (2 * th / 3), rx + w, |
|
|
|
ry + (2 * th / 3), th / 3, st, |
|
|
|
new PDFColor(area.getRed(), |
|
|
|
area.getGreen(), area.getBlue())); |
|
|
|
break; |
|
|
|
case org.apache.fop.fo.properties.RuleStyle.GROOVE: |
|
|
|
addLine(rx, ry, rx + w, ry, th / 2, st, |
|
|
|
new PDFColor(area.getRed(), |
|
|
|
area.getGreen(), area.getBlue())); |
|
|
|
addLine(rx, ry + (th / 2), rx + w, ry + (th / 2), |
|
|
|
th / 2, st, new PDFColor(255, 255, 255)); |
|
|
|
break; |
|
|
|
case org.apache.fop.fo.properties.RuleStyle.RIDGE: |
|
|
|
addLine(rx, ry, rx + w, ry, th / 2, st, |
|
|
|
new PDFColor(255, 255, 255)); |
|
|
|
addLine(rx, ry + (th / 2), rx + w, ry + (th / 2), |
|
|
|
th / 2, st, |
|
|
|
new PDFColor(area.getRed(), |
|
|
|
area.getGreen(), area.getBlue())); |
|
|
|
break; |
|
|
|
default: |
|
|
|
addLine(rx, ry, rx + w, ry, th, st, |
|
|
|
new PDFColor(area.getRed(), |
|
|
|
area.getGreen(), area.getBlue())); |
|
|
|
} |
|
|
|
this.currentXPosition += area.getContentWidth(); |
|
|
|
this.currentYPosition += th; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* set up the font info |
|
|
|
* |
|
|
|
* @param fontInfo font info to set up |
|
|
|
*/ |
|
|
|
public void setupFontInfo(FontInfo fontInfo) { |
|
|
|
this.fontInfo = fontInfo; |
|
|
|
FontSetup.setup(fontInfo); |
|
|
|
} |
|
|
|
} |