git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@194519 13f79535-47bb-0310-9956-ffa450edef68pull/30/head
@@ -86,7 +86,7 @@ public class AWTStarter extends CommandLineStarter { | |||
resource.setMissingEmphasized(false); | |||
renderer = new AWTRenderer(resource); | |||
frame = createPreviewDialog(renderer, resource); | |||
renderer.setProgressListener(frame); | |||
//renderer.setProgressListener(frame); | |||
renderer.setComponent(frame); | |||
} | |||
@@ -86,7 +86,7 @@ public class CommandLineOptions { | |||
/* language for user information */ | |||
String language = null; | |||
private java.util.Hashtable rendererOptions; | |||
private java.util.HashMap rendererOptions; | |||
private Logger log; | |||
@@ -113,7 +113,7 @@ public class CommandLineOptions { | |||
log.setPriority(Priority.INFO); | |||
boolean optionsParsed = true; | |||
rendererOptions = new java.util.Hashtable(); | |||
rendererOptions = new java.util.HashMap(); | |||
try { | |||
optionsParsed = parseOptions(args); | |||
if (optionsParsed) { | |||
@@ -410,7 +410,7 @@ public class CommandLineOptions { | |||
} | |||
} | |||
public java.util.Hashtable getRendererOptions() { | |||
public java.util.HashMap getRendererOptions() { | |||
return rendererOptions; | |||
} | |||
@@ -134,18 +134,17 @@ public class PrintStarter extends CommandLineStarter { | |||
} | |||
public void stopRenderer(OutputStream outputStream) | |||
throws IOException { | |||
super.stopRenderer(outputStream); | |||
super.stopRenderer(); | |||
if(endNumber == -1) | |||
endNumber = getPageCount(); | |||
Vector numbers = getInvalidPageNumbers(); | |||
for (int i = numbers.size() - 1; i > -1; i--) | |||
removePage(Integer.parseInt((String)numbers.elementAt(i))); | |||
for (int i = numbers.size() - 1; i > -1; i--) { | |||
//removePage(Integer.parseInt((String)numbers.elementAt(i))); | |||
} | |||
try { | |||
printerJob.print(); | |||
@@ -160,10 +159,8 @@ public class PrintStarter extends CommandLineStarter { | |||
public void renderPage(Page page) { | |||
pageWidth = (int)((float)page.getWidth() / 1000f); | |||
pageHeight = (int)((float)page.getHeight() / 1000f); | |||
super.renderPage(page); | |||
} | |||
private Vector getInvalidPageNumbers() { | |||
Vector vec = new Vector(); | |||
@@ -200,5 +197,3 @@ public class PrintStarter extends CommandLineStarter { | |||
} // class PrintRenderer | |||
} // class PrintCommandLine | |||
@@ -132,7 +132,7 @@ public class StreamRenderer { | |||
*/ | |||
try { | |||
processQueue(true); | |||
renderer.stopRenderer(outputStream); | |||
renderer.stopRenderer(); | |||
} catch (FOPException e) { | |||
throw new SAXException(e); | |||
} | |||
@@ -202,11 +202,11 @@ public class StreamRenderer { | |||
valid on the current pages. This short-cuts the | |||
pipeline and renders the area immediately. | |||
*/ | |||
if ((renderQueue.size() == 0) && idReferences.isEveryIdValid()) | |||
renderer.render(page, outputStream); | |||
else | |||
if ((renderQueue.size() == 0) && idReferences.isEveryIdValid()) { | |||
//renderer.render(page, outputStream); | |||
} else { | |||
addToRenderQueue(page); | |||
} | |||
pageCount++; | |||
} | |||
@@ -235,7 +235,7 @@ public class StreamRenderer { | |||
if ((!force) && (!entry.isResolved())) | |||
break; | |||
renderer.render(entry.getPage(), outputStream); | |||
//renderer.render(entry.getPage(), outputStream); | |||
/* TODO | |||
Enumeration rootEnumeration = |
@@ -0,0 +1,26 @@ | |||
/* | |||
* $Id$ | |||
* Copyright (C) 2001 The Apache Software Foundation. All rights reserved. | |||
* For details on use and redistribution please refer to the | |||
* LICENSE file included with these sources. | |||
*/ | |||
package org.apache.fop.area; | |||
/** | |||
* base object for all areas | |||
*/ | |||
public class Area { | |||
// stacking directions | |||
public static final int LR = 0; | |||
public static final int RL = 1; | |||
public static final int TB = 2; | |||
public static final int BT = 3; | |||
// orientations for reference areas | |||
public static final int ORIENT_0 = 0; | |||
public static final int ORIENT_90 = 1; | |||
public static final int ORIENT_180 = 2; | |||
public static final int ORIENT_270 = 3; | |||
} |
@@ -0,0 +1,98 @@ | |||
/* | |||
* $Id$ | |||
* Copyright (C) 2001 The Apache Software Foundation. All rights reserved. | |||
* For details on use and redistribution please refer to the | |||
* LICENSE file included with these sources. | |||
*/ | |||
package org.apache.fop.area; | |||
import java.util.ArrayList; | |||
public class AreaTree { | |||
// allows for different models to deal with adding/rendering | |||
// in different situations | |||
AreaTreeModel model; | |||
public void createRenderPageModel(PageRenderListener listener) { | |||
} | |||
public static StorePagesModel createStorePagesModel() { | |||
return new StorePagesModel(); | |||
} | |||
public void setTreeModel(AreaTreeModel m) { | |||
model = m; | |||
} | |||
public void startPageSequence(Area title) { | |||
model.startPageSequence(title); | |||
} | |||
public void addPage(PageViewport page) { | |||
model.addPage(page); | |||
} | |||
// this is the model for the area tree object | |||
public static abstract class AreaTreeModel { | |||
public abstract void startPageSequence(Area title); | |||
public abstract void addPage(PageViewport page); | |||
} | |||
// this queues pages and will call the render listener | |||
// when the page is ready to be rendered | |||
// if the render supports out of order rendering | |||
// then a ready page is rendered immediately | |||
public static class RenderPagesModel extends AreaTreeModel { | |||
public void startPageSequence(Area title) {} | |||
public void addPage(PageViewport page) {} | |||
} | |||
// this class stores all the pages in the document | |||
// for interactive agents | |||
public static class StorePagesModel extends AreaTreeModel { | |||
ArrayList pageSequence = null; | |||
ArrayList titles = new ArrayList(); | |||
ArrayList currSequence; | |||
public StorePagesModel() {} | |||
public void startPageSequence(Area title) { | |||
titles.add(title); | |||
if (pageSequence == null) { | |||
pageSequence = new ArrayList(); | |||
} | |||
currSequence = new ArrayList(); | |||
pageSequence.add(currSequence); | |||
} | |||
public void addPage(PageViewport page) { | |||
currSequence.add(page); | |||
} | |||
public int getPageSequenceCount() { | |||
return pageSequence.size(); | |||
} | |||
public Title getTitle(int count) { | |||
return (Title) titles.get(count); | |||
} | |||
public int getPageCount(int seq) { | |||
ArrayList sequence = (ArrayList) pageSequence.get(seq); | |||
return sequence.size(); | |||
} | |||
public PageViewport getPage(int seq, int count) { | |||
ArrayList sequence = (ArrayList) pageSequence.get(seq); | |||
return (PageViewport) sequence.get(count); | |||
} | |||
} | |||
} | |||
abstract class PageRenderListener { | |||
public abstract void startPageSequence(Area title); | |||
public abstract void preparePage(PageViewport page); | |||
public abstract void renderPage(PageViewport page); | |||
} |
@@ -0,0 +1,39 @@ | |||
/* | |||
* $Id$ | |||
* Copyright (C) 2001 The Apache Software Foundation. All rights reserved. | |||
* For details on use and redistribution please refer to the | |||
* LICENSE file included with these sources. | |||
*/ | |||
package org.apache.fop.area; | |||
import java.util.List; | |||
import java.util.ArrayList; | |||
public class BeforeFloat extends Area { | |||
// this is an optional block area that will be rendered | |||
// as the separator only if there are float areas | |||
Block separator = null; | |||
// before float area | |||
// has an optional separator | |||
// and a list of sub block areas | |||
ArrayList blocks = null; | |||
public List getBlocks() { | |||
return blocks; | |||
} | |||
public Block getSeparator() { | |||
return separator; | |||
} | |||
public int getHeight() { | |||
if (blocks == null) { | |||
return 0; | |||
} | |||
int h = 0; | |||
return h; | |||
} | |||
} |
@@ -0,0 +1,82 @@ | |||
/* | |||
* $Id$ | |||
* Copyright (C) 2001 The Apache Software Foundation. All rights reserved. | |||
* For details on use and redistribution please refer to the | |||
* LICENSE file included with these sources. | |||
*/ | |||
package org.apache.fop.area; | |||
import java.util.ArrayList; | |||
import java.util.List; | |||
import java.awt.geom.Rectangle2D; | |||
// block areas hold either more block areas or line | |||
// areas can also be used as a block spacer | |||
// a block area may have children positioned by stacking | |||
// or by relative to the parent for floats, tables and lists | |||
// cacheable object | |||
// has id information | |||
public class Block extends Area { | |||
// normally stacked with other blocks | |||
public static final int STACK = 0; | |||
// placed relative to the parent area | |||
public static final int RELATIVE = 1; | |||
// placed relative to the page or viewport | |||
public static final int ABSOLUTE = 2; | |||
// this position is used for absolute position | |||
// or as an indent | |||
// this has the size in the block progression dimension | |||
Rectangle2D bounds = null; | |||
int stacking = TB; | |||
// list of marker fo objects that are associated with this area | |||
// if a retrieve marker resolves this area it will format the | |||
// available markers, markers are discarded once page complete | |||
private ArrayList markers = null; | |||
ArrayList children = null; | |||
boolean blocks = false; | |||
// a block with may contain the dominant styling info in | |||
// terms of most lines or blocks with info | |||
int positioning = STACK; | |||
// orientation if reference area | |||
int orientation = ORIENT_0; | |||
public void addBlock(Block block) { | |||
if (children == null) { | |||
children = new ArrayList(); | |||
} else if (!blocks) { | |||
// error | |||
} | |||
blocks = true; | |||
children.add(block); | |||
} | |||
public void addLineArea(LineArea line) { | |||
if (children == null) { | |||
children = new ArrayList(); | |||
} else if (blocks) { | |||
// error | |||
} | |||
children.add(line); | |||
} | |||
public boolean isChildrenBlocks() { | |||
return blocks; | |||
} | |||
public List getChildAreas() { | |||
return children; | |||
} | |||
public int getPositioning() { | |||
return positioning; | |||
} | |||
} |
@@ -0,0 +1,30 @@ | |||
/* | |||
* $Id$ | |||
* Copyright (C) 2001 The Apache Software Foundation. All rights reserved. | |||
* For details on use and redistribution please refer to the | |||
* LICENSE file included with these sources. | |||
*/ | |||
package org.apache.fop.area; | |||
public class BodyRegion extends Region { | |||
BeforeFloat beforeFloat; | |||
MainReference mainReference; | |||
Footnote footnote; | |||
public BodyRegion() { | |||
super(BODY); | |||
} | |||
public BeforeFloat getBeforeFloat() { | |||
return beforeFloat; | |||
} | |||
public MainReference getMainReference() { | |||
return mainReference; | |||
} | |||
public Footnote getFootnote() { | |||
return footnote; | |||
} | |||
} |
@@ -0,0 +1,25 @@ | |||
/* | |||
* $Id$ | |||
* Copyright (C) 2001 The Apache Software Foundation. All rights reserved. | |||
* For details on use and redistribution please refer to the | |||
* LICENSE file included with these sources. | |||
*/ | |||
package org.apache.fop.area; | |||
import java.util.ArrayList; | |||
import java.util.List; | |||
// this is a normal flow reference area | |||
// it containts a list of block areas from the flow | |||
public class Flow extends Area { | |||
// the list of blocks created from the flow | |||
ArrayList blocks = new ArrayList(); | |||
int stacking = TB; | |||
int width; | |||
public List getBlocks() { | |||
return blocks; | |||
} | |||
} |
@@ -0,0 +1,33 @@ | |||
/* | |||
* $Id$ | |||
* Copyright (C) 2001 The Apache Software Foundation. All rights reserved. | |||
* For details on use and redistribution please refer to the | |||
* LICENSE file included with these sources. | |||
*/ | |||
package org.apache.fop.area; | |||
import java.util.List; | |||
import java.util.ArrayList; | |||
// may combine with before float into a conditional area | |||
public class Footnote { | |||
Block separator = null; | |||
// footnote has an optional separator | |||
// and a list of sub block areas that can be added/removed | |||
// this is the relative position of the footnote inside | |||
// the body region | |||
int top; | |||
ArrayList blocks = null; | |||
public Block getSeparator() { | |||
return separator; | |||
} | |||
public List getBlocks() { | |||
return blocks; | |||
} | |||
} |
@@ -0,0 +1,48 @@ | |||
/* | |||
* $Id$ | |||
* Copyright (C) 2001 The Apache Software Foundation. All rights reserved. | |||
* For details on use and redistribution please refer to the | |||
* LICENSE file included with these sources. | |||
*/ | |||
package org.apache.fop.area; | |||
import org.apache.fop.area.inline.InlineArea; | |||
import java.util.ArrayList; | |||
import java.util.List; | |||
// a line area can contain information in ranges of child inline | |||
// areas that have properties such as | |||
// links, background, underline, bold, id areas | |||
public class LineArea extends Area { | |||
int stacking = LR; | |||
// contains inline areas | |||
// has start indent and length, dominant baseline, height | |||
int startIndent; | |||
int length; | |||
int lineHeight; | |||
// this is the offset for the dominant baseline | |||
int baseLine; | |||
// this class can contain the dominant char styling info | |||
// this means that many renderers can optimise a bit | |||
ArrayList inlineAreas = new ArrayList(); | |||
public void addInlineArea(InlineArea area) { | |||
inlineAreas.add(area); | |||
} | |||
public List getInlineAreas() { | |||
return inlineAreas; | |||
} | |||
} | |||
/* | |||
class LineProperty { | |||
int propType; | |||
int[] range; | |||
Object data; | |||
} | |||
*/ |
@@ -0,0 +1,30 @@ | |||
/* | |||
* $Id$ | |||
* Copyright (C) 2001 The Apache Software Foundation. All rights reserved. | |||
* For details on use and redistribution please refer to the | |||
* LICENSE file included with these sources. | |||
*/ | |||
package org.apache.fop.area; | |||
import java.util.ArrayList; | |||
import java.util.List; | |||
// the area that contains the flow via the span areas | |||
public class MainReference { | |||
List spanAreas = new ArrayList(); | |||
int columnGap; | |||
int width; | |||
public List getSpans() { | |||
return spanAreas; | |||
} | |||
public int getColumnGap() { | |||
return columnGap; | |||
} | |||
public int getWidth() { | |||
return width; | |||
} | |||
} |
@@ -0,0 +1,47 @@ | |||
/* | |||
* $Id$ | |||
* Copyright (C) 2001 The Apache Software Foundation. All rights reserved. | |||
* For details on use and redistribution please refer to the | |||
* LICENSE file included with these sources. | |||
*/ | |||
package org.apache.fop.area; | |||
public class Page { | |||
// contains before, start, body, end and after regions | |||
RegionViewport regionBefore = null; | |||
RegionViewport regionStart = null; | |||
RegionViewport regionBody = null; | |||
RegionViewport regionEnd = null; | |||
RegionViewport regionAfter = null; | |||
public void setRegion(int areaclass, RegionViewport port) { | |||
if (areaclass == Region.BEFORE) { | |||
regionBefore = port; | |||
} else if (areaclass == Region.START) { | |||
regionStart = port; | |||
} else if (areaclass == Region.BODY) { | |||
regionBody = port; | |||
} else if (areaclass == Region.END) { | |||
regionEnd = port; | |||
} else if (areaclass == Region.AFTER) { | |||
regionAfter = port; | |||
} | |||
} | |||
public RegionViewport getRegion(int areaclass) { | |||
if (areaclass == Region.BEFORE) { | |||
return regionBefore; | |||
} else if (areaclass == Region.START) { | |||
return regionStart; | |||
} else if (areaclass == Region.BODY) { | |||
return regionBody; | |||
} else if (areaclass == Region.END) { | |||
return regionEnd; | |||
} else if (areaclass == Region.AFTER) { | |||
return regionAfter; | |||
} | |||
return null; | |||
} | |||
} |
@@ -0,0 +1,31 @@ | |||
/* | |||
* $Id$ | |||
* Copyright (C) 2001 The Apache Software Foundation. All rights reserved. | |||
* For details on use and redistribution please refer to the | |||
* LICENSE file included with these sources. | |||
*/ | |||
package org.apache.fop.area; | |||
import java.awt.geom.Rectangle2D; | |||
import java.util.ArrayList; | |||
// this is the level that creates the page | |||
// the page (reference area) is then rendered inside the page object | |||
public class PageViewport { | |||
Page page; | |||
Rectangle2D viewArea; | |||
public PageViewport(Page p) { | |||
page = p; | |||
} | |||
// this list is only used when the page is discarded | |||
// the information is kept for future reference | |||
ArrayList idReferences = null; | |||
// a viewport area for page and reference areas | |||
public Page getPage() { | |||
return page; | |||
} | |||
} |
@@ -0,0 +1,40 @@ | |||
/* | |||
* $Id$ | |||
* Copyright (C) 2001 The Apache Software Foundation. All rights reserved. | |||
* For details on use and redistribution please refer to the | |||
* LICENSE file included with these sources. | |||
*/ | |||
package org.apache.fop.area; | |||
import java.util.ArrayList; | |||
import java.util.List; | |||
public class Region { | |||
public static final int BEFORE = 0; | |||
public static final int START = 1; | |||
public static final int BODY = 2; | |||
public static final int END = 3; | |||
public static final int AFTER = 4; | |||
int regionClass = BEFORE; | |||
public Region(int type) { | |||
regionClass = type; | |||
} | |||
// the list of block areas from the static flow | |||
ArrayList blocks = new ArrayList(); | |||
public List getBlocks() { | |||
return blocks; | |||
} | |||
public int getRegionClass() { | |||
return regionClass; | |||
} | |||
public void addBlock(Block block) { | |||
blocks.add(block); | |||
} | |||
} |
@@ -0,0 +1,27 @@ | |||
/* | |||
* $Id$ | |||
* Copyright (C) 2001 The Apache Software Foundation. All rights reserved. | |||
* For details on use and redistribution please refer to the | |||
* LICENSE file included with these sources. | |||
*/ | |||
package org.apache.fop.area; | |||
import java.awt.geom.Rectangle2D; | |||
public class RegionViewport { | |||
// this rectangle is relative to the page | |||
Rectangle2D regionArea; | |||
boolean clip; | |||
Region region; | |||
public void setRegion(Region reg) { | |||
region = reg; | |||
} | |||
public Region getRegion() { | |||
return region; | |||
} | |||
} |
@@ -0,0 +1,29 @@ | |||
/* | |||
* $Id$ | |||
* Copyright (C) 2001 The Apache Software Foundation. All rights reserved. | |||
* For details on use and redistribution please refer to the | |||
* LICENSE file included with these sources. | |||
*/ | |||
package org.apache.fop.area; | |||
import java.util.ArrayList; | |||
// this is a reference area block area with 0 border and padding | |||
public class Span extends Area { | |||
// the list of flow reference areas in this span area | |||
ArrayList flowAreas = new ArrayList(); | |||
int height; | |||
public int getColumnCount() { | |||
return flowAreas.size(); | |||
} | |||
public int getHeight() { | |||
return height; | |||
} | |||
public Flow getFlow(int count) { | |||
return (Flow) flowAreas.get(count); | |||
} | |||
} |
@@ -0,0 +1,11 @@ | |||
/* | |||
* $Id$ | |||
* Copyright (C) 2001 The Apache Software Foundation. All rights reserved. | |||
* For details on use and redistribution please refer to the | |||
* LICENSE file included with these sources. | |||
*/ | |||
package org.apache.fop.area; | |||
public class Title extends LineArea { | |||
} |
@@ -0,0 +1,15 @@ | |||
/* | |||
* $Id$ | |||
* Copyright (C) 2001 The Apache Software Foundation. All rights reserved. | |||
* For details on use and redistribution please refer to the | |||
* LICENSE file included with these sources. | |||
*/ | |||
package org.apache.fop.area.inline; | |||
public class Anchor extends InlineArea { | |||
// has a keep with adjacent area | |||
// has reference to associated footnote or float out-of-line area | |||
} |
@@ -0,0 +1,28 @@ | |||
/* | |||
* $Id$ | |||
* Copyright (C) 2001 The Apache Software Foundation. All rights reserved. | |||
* For details on use and redistribution please refer to the | |||
* LICENSE file included with these sources. | |||
*/ | |||
package org.apache.fop.area.inline; | |||
import org.apache.fop.render.Renderer; | |||
public class Character extends InlineArea { | |||
char character; | |||
public Character(char ch) { | |||
character = ch; | |||
} | |||
// character info: font, char spacing, colour, baseline | |||
public void render(Renderer renderer) { | |||
renderer.renderCharacter(this); | |||
} | |||
public char getChar() { | |||
return character; | |||
} | |||
} |
@@ -0,0 +1,28 @@ | |||
/* | |||
* $Id$ | |||
* Copyright (C) 2001 The Apache Software Foundation. All rights reserved. | |||
* For details on use and redistribution please refer to the | |||
* LICENSE file included with these sources. | |||
*/ | |||
package org.apache.fop.area.inline; | |||
import org.apache.fop.render.Renderer; | |||
import java.util.List; | |||
import java.util.ArrayList; | |||
public class Container extends InlineArea { | |||
ArrayList blocks = new ArrayList(); | |||
// this is an inline area that can have blocks as children | |||
public void render(Renderer renderer) { | |||
renderer.renderContainer(this); | |||
} | |||
public List getBlocks() { | |||
return blocks; | |||
} | |||
} |
@@ -0,0 +1,21 @@ | |||
/* | |||
* $Id$ | |||
* Copyright (C) 2001 The Apache Software Foundation. All rights reserved. | |||
* For details on use and redistribution please refer to the | |||
* LICENSE file included with these sources. | |||
*/ | |||
package org.apache.fop.area.inline; | |||
import org.apache.fop.area.Area; | |||
import org.w3c.dom.Document; | |||
// cacheable object | |||
public class ForeignObject extends Area { | |||
Document doc; | |||
String namespace; | |||
// dom object | |||
// height, width | |||
} |
@@ -0,0 +1,17 @@ | |||
/* | |||
* $Id$ | |||
* Copyright (C) 2001 The Apache Software Foundation. All rights reserved. | |||
* For details on use and redistribution please refer to the | |||
* LICENSE file included with these sources. | |||
*/ | |||
package org.apache.fop.area.inline; | |||
import org.apache.fop.area.Area; | |||
// cacheable object | |||
public class Image extends Area { | |||
// image object, mime type, url | |||
} |
@@ -0,0 +1,33 @@ | |||
/* | |||
* $Id$ | |||
* Copyright (C) 2001 The Apache Software Foundation. All rights reserved. | |||
* For details on use and redistribution please refer to the | |||
* LICENSE file included with these sources. | |||
*/ | |||
package org.apache.fop.area.inline; | |||
import org.apache.fop.area.Area; | |||
import org.apache.fop.render.Renderer; | |||
public class InlineArea extends Area { | |||
int width; | |||
int height; | |||
// position within the line area, either top or baseline | |||
int verticalPosition; | |||
// width, height, vertical alignment | |||
// inline areas are expected to implement this method | |||
// to render themselves | |||
public void render(Renderer renderer) { | |||
} | |||
public void setWidth(int w) { | |||
width = w; | |||
} | |||
public int getWidth() { | |||
return width; | |||
} | |||
} |
@@ -0,0 +1,19 @@ | |||
/* | |||
* $Id$ | |||
* Copyright (C) 2001 The Apache Software Foundation. All rights reserved. | |||
* For details on use and redistribution please refer to the | |||
* LICENSE file included with these sources. | |||
*/ | |||
package org.apache.fop.area.inline; | |||
public class Leader extends Stretch { | |||
// pattern, length min opt max | |||
// in the case of use content or dots this is replaced | |||
// with the set of inline areas | |||
// if space replaced with a space | |||
// otherwise this is a holder for a line | |||
} |
@@ -0,0 +1,17 @@ | |||
/* | |||
* $Id$ | |||
* Copyright (C) 2001 The Apache Software Foundation. All rights reserved. | |||
* For details on use and redistribution please refer to the | |||
* LICENSE file included with these sources. | |||
*/ | |||
package org.apache.fop.area.inline; | |||
import org.apache.fop.render.Renderer; | |||
public class Space extends Stretch { | |||
public void render(Renderer renderer) { | |||
renderer.renderInlineSpace(this); | |||
} | |||
} |
@@ -0,0 +1,17 @@ | |||
/* | |||
* $Id$ | |||
* Copyright (C) 2001 The Apache Software Foundation. All rights reserved. | |||
* For details on use and redistribution please refer to the | |||
* LICENSE file included with these sources. | |||
*/ | |||
package org.apache.fop.area.inline; | |||
public class Stretch extends InlineArea { | |||
// min size | |||
// set size | |||
// get size | |||
// height 0 | |||
} |
@@ -0,0 +1,20 @@ | |||
/* | |||
* $Id$ | |||
* Copyright (C) 2001 The Apache Software Foundation. All rights reserved. | |||
* For details on use and redistribution please refer to the | |||
* LICENSE file included with these sources. | |||
*/ | |||
package org.apache.fop.area.inline; | |||
public class Unresolved extends InlineArea { | |||
boolean resolved = false; | |||
// id ref | |||
// resolve | |||
// resolve without area | |||
public void resolve() { | |||
} | |||
} |
@@ -0,0 +1,16 @@ | |||
/* | |||
* $Id$ | |||
* Copyright (C) 2001 The Apache Software Foundation. All rights reserved. | |||
* For details on use and redistribution please refer to the | |||
* LICENSE file included with these sources. | |||
*/ | |||
package org.apache.fop.area.inline; | |||
public class UnresolvedPageNumber extends Unresolved { | |||
// id ref | |||
// resolve | |||
// resolve without area | |||
} |
@@ -0,0 +1,22 @@ | |||
/* | |||
* $Id$ | |||
* Copyright (C) 2001 The Apache Software Foundation. All rights reserved. | |||
* For details on use and redistribution please refer to the | |||
* LICENSE file included with these sources. | |||
*/ | |||
package org.apache.fop.area.inline; | |||
import org.apache.fop.area.Area; | |||
import java.awt.geom.Rectangle2D; | |||
public class Viewport extends InlineArea { | |||
// contents could be foreign object or image | |||
Area content; | |||
// an inline-level viewport area for graphic and instream foreign object | |||
boolean clip = false; | |||
// position relative to this area | |||
Rectangle2D contentPosition; | |||
} |
@@ -0,0 +1,15 @@ | |||
/* | |||
* $Id$ | |||
* Copyright (C) 2001 The Apache Software Foundation. All rights reserved. | |||
* For details on use and redistribution please refer to the | |||
* LICENSE file included with these sources. | |||
*/ | |||
package org.apache.fop.area.inline; | |||
public class Word extends InlineArea { | |||
// character info: font, char spacing, colour, baseline | |||
String word; | |||
} |
@@ -0,0 +1,37 @@ | |||
/* | |||
* $Id$ | |||
* Copyright (C) 2001 The Apache Software Foundation. All rights reserved. | |||
* For details on use and redistribution please refer to the | |||
* LICENSE file included with these sources. | |||
*/ | |||
package org.apache.fop.fo; | |||
import org.w3c.dom.*; | |||
/** | |||
* The User Agent for fo. | |||
* This user agent is used by the processing to obtain user configurable | |||
* options. | |||
* | |||
* Renderer specific extensions (that do not produce normal areas on | |||
* the output) will be done like so: | |||
* The extension will create an area, custom if necessary | |||
* this area will be added to the user agent with a key | |||
* the renderer will know keys for particular extensions | |||
* eg. bookmarks will be held in a special hierarchical area representing | |||
* the title and bookmark structure | |||
* These areas may contain resolveable areas that will be processed | |||
* with other resolveable areas | |||
*/ | |||
public interface FOUserAgent { | |||
public void renderXML(RendererContext ctx, Document doc, String namespace); | |||
} | |||
class RendererContext { | |||
String getMimeType() { | |||
return null; | |||
} | |||
} | |||
@@ -64,10 +64,6 @@ public class ImageArea extends InlineArea { | |||
return this.image; | |||
} | |||
public void render(Renderer renderer) { | |||
renderer.renderImageArea(this); | |||
} | |||
public int getImageHeight() { | |||
return currentHeight; | |||
} |
@@ -34,10 +34,6 @@ public class AreaContainer extends Area { | |||
// setIsReferenceArea(true); // Should always be true! | |||
} | |||
public void render(Renderer renderer) { | |||
renderer.renderAreaContainer(this); | |||
} | |||
public int getPosition() { | |||
return position; | |||
} |
@@ -78,10 +78,6 @@ public class BlockArea extends Area { | |||
this.halfLeading = (lineHeight - fontState.getFontSize()) / 2; | |||
} | |||
public void render(Renderer renderer) { | |||
renderer.renderBlockArea(this); | |||
} | |||
/** | |||
* Add a Line Area to this block area. | |||
* Used internally to add a completed line area to this block area |
@@ -95,10 +95,6 @@ public class BodyAreaContainer extends Area { | |||
// setBorderWidth(0, 0, 0, 0); | |||
} | |||
public void render(Renderer renderer) { | |||
renderer.renderBodyAreaContainer(this); | |||
} | |||
public int getPosition() { | |||
return position; | |||
} |
@@ -12,5 +12,4 @@ import org.apache.fop.render.Renderer; | |||
abstract public class Box { | |||
protected Area parent; | |||
protected AreaTree areaTree; | |||
abstract public void render(Renderer renderer); | |||
} |
@@ -29,10 +29,6 @@ public class ColumnArea extends AreaContainer { | |||
this.setAreaName("normal-flow-ref.-area"); | |||
} | |||
public void render(Renderer renderer) { | |||
renderer.renderAreaContainer(this); | |||
} | |||
public void end() {} | |||
public void start() {} |
@@ -20,8 +20,4 @@ public class DisplaySpace extends Space { | |||
return size; | |||
} | |||
public void render(Renderer renderer) { | |||
renderer.renderDisplaySpace(this); | |||
} | |||
} |
@@ -158,10 +158,6 @@ public class LineArea extends Area { | |||
} | |||
} | |||
public void render(Renderer renderer) { | |||
renderer.renderLineArea(this); | |||
} | |||
public int addPageNumberCitation(String refid, LinkSet ls) { | |||
/* |
@@ -124,10 +124,6 @@ public class Page { | |||
area.setPage(this); | |||
} | |||
public void render(Renderer renderer) { | |||
renderer.renderPage(this); | |||
} | |||
public AreaContainer getAfter() { | |||
return this.after; | |||
} |
@@ -49,10 +49,6 @@ public class SpanArea extends AreaContainer { | |||
} | |||
} | |||
public void render(Renderer renderer) { | |||
renderer.renderSpanArea(this); | |||
} | |||
public void end() {} | |||
public void start() {} |
@@ -45,11 +45,6 @@ public class ForeignObjectArea extends InlineArea { | |||
super(fontState, width, 0, 0, 0); | |||
} | |||
public void render(Renderer renderer) { | |||
if (foreignObject != null) | |||
renderer.renderForeignObjectArea(this); | |||
} | |||
/** | |||
* This is NOT the content width of the instream-foreign-object. | |||
* This is the content width for a Box. |
@@ -87,8 +87,4 @@ public class InlineSpace extends Space { | |||
return eatable; | |||
} | |||
public void render(Renderer renderer) { | |||
renderer.renderInlineSpace(this); | |||
} | |||
} |
@@ -38,10 +38,6 @@ public class LeaderArea extends InlineArea { | |||
this.ruleThickness = ruleThickness; | |||
} | |||
public void render(Renderer renderer) { | |||
renderer.renderLeaderArea(this); | |||
} | |||
public int getRuleThickness() { | |||
return this.ruleThickness; | |||
} |
@@ -27,10 +27,6 @@ public class WordArea extends InlineArea { | |||
this.contentRectangleWidth = width; | |||
} | |||
public void render(Renderer renderer) { | |||
renderer.renderWordArea(this); | |||
} | |||
public String getText() { | |||
return this.text; | |||
} |
@@ -0,0 +1,90 @@ | |||
/* | |||
* $Id$ | |||
* Copyright (C) 2001 The Apache Software Foundation. All rights reserved. | |||
* For details on use and redistribution please refer to the | |||
* LICENSE file included with these sources. | |||
*/ | |||
package org.apache.fop.pdf; | |||
import java.awt.Shape; | |||
import java.util.ArrayList; | |||
import java.util.HashMap; | |||
/** | |||
* This keeps information about the current state when writing to pdf. | |||
* It allows for creating new graphics states with the q operator. | |||
* | |||
* When setting the state for pdf there are three possible ways of | |||
* handling the situation. | |||
* The values can be set to override previous or default values. | |||
* A new state can be added and then the values set. | |||
* The current state can be popped and values will return to a | |||
* previous state then the necessary values can be overridden. | |||
* The current transform behaves differently to other values as the | |||
* matrix is combined with the current resolved value. | |||
* It is impossible to optimise the result without analysing the all | |||
* the possible combinations after completing. | |||
*/ | |||
public class PDFState { | |||
private final static String COLOR = "color"; | |||
private final static String BACKCOLOR = "backcolor"; | |||
private final static String PATTERN = "pattern"; | |||
private final static String BACKPATTERN = "backpattern"; | |||
private final static String LINECAP = "lineCap"; | |||
private final static String LINEJOIN = "lineJoin"; | |||
private final static String LINEWIDTH = "lineWidth"; | |||
private final static String MITERLIMIT = "miterLimit"; | |||
private final static String TEXT = "text"; | |||
private final static String DASHOFFSET = "dashOffset"; | |||
private final static String DASHARRAY = "dashArray"; | |||
private final static String TRANSFORM = "transform"; | |||
private final static String FONTSIZE = "fontSize"; | |||
private final static String FONTNAME = "fontName"; | |||
private final static String CLIP = "clip"; | |||
PDFColor color = new PDFColor(0, 0, 0); | |||
PDFColor backcolor = new PDFColor(255, 255, 255); | |||
PDFPattern pattern = null; | |||
PDFPattern backPattern = null; | |||
int lineCap = 0; | |||
int lineJoin = 0; | |||
float lineWidth = 1; | |||
float miterLimit = 0; | |||
boolean text = false; | |||
int dashOffset = 0; | |||
int[] dashArray = new int[0]; | |||
double[] transform = new double[]{1, 0, 0, 1, 0, 0}; | |||
float fontSize = 0; | |||
String fontName = ""; | |||
Shape clip = null; | |||
ArrayList stateStack = new ArrayList(); | |||
public PDFState() { | |||
} | |||
// this call should be used when the q operator is used | |||
// so that the state is known when popped | |||
public void push() { | |||
HashMap changedMap = new HashMap(); | |||
} | |||
public void pop() { | |||
if (getStackLevel() > 0) { | |||
stateStack.remove(stateStack.size() - 1); | |||
} | |||
} | |||
public int getStackLevel() { | |||
return stateStack.size(); | |||
} | |||
public boolean setLineDash(int[] array, int offset) { | |||
return false; | |||
} | |||
} | |||
@@ -8,222 +8,221 @@ | |||
package org.apache.fop.render; | |||
// FOP | |||
import org.apache.fop.pdf.PDFPathPaint; | |||
import org.apache.fop.pdf.PDFColor; | |||
import org.apache.fop.image.ImageArea; | |||
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.render.pdf.FontSetup; | |||
import org.apache.fop.area.*; | |||
import org.apache.fop.area.Span; | |||
import org.apache.fop.area.inline.*; | |||
import org.apache.fop.area.inline.Space; | |||
import org.apache.fop.fo.FOUserAgent; | |||
import org.apache.log.Logger; | |||
// Java | |||
import java.io.IOException; | |||
import java.io.OutputStream; | |||
import java.util.Enumeration; | |||
import java.util.HashMap; | |||
import java.util.List; | |||
/** | |||
* Abstract base class for all renderers. | |||
* | |||
* The Abstract renderer does all the top level processing | |||
* of the area tree and adds some abstract methods to handle | |||
* viewports. | |||
*/ | |||
public abstract class AbstractRenderer implements Renderer { | |||
protected Logger log; | |||
protected FOUserAgent userAgent; | |||
protected HashMap options; | |||
/** | |||
* the current vertical position in millipoints from bottom | |||
*/ | |||
protected int currentYPosition = 0; | |||
// block progression position | |||
protected int currentBPPosition = 0; | |||
/** | |||
* the current horizontal position in millipoints from left | |||
*/ | |||
protected int currentXPosition = 0; | |||
// inline progression position | |||
protected int currentIPPosition = 0; | |||
/** | |||
* the horizontal position of the current area container | |||
*/ | |||
protected int currentAreaContainerXPosition = 0; | |||
protected int currentBlockIPPosition = 0; | |||
public void setLogger(Logger logger) { | |||
log = logger; | |||
} | |||
public void renderSpanArea(SpanArea area) { | |||
Enumeration e = area.getChildren().elements(); | |||
while (e.hasMoreElements()) { | |||
Box b = (Box)e.nextElement(); | |||
b.render(this); // column areas | |||
} | |||
public void setUserAgent(FOUserAgent agent) { | |||
userAgent = agent; | |||
} | |||
public void setOptions(HashMap opt) { | |||
options = opt; | |||
} | |||
protected abstract void doFrame(Area area); | |||
/** | |||
* Add a filled rectangle to the current stream | |||
* This default implementation calls addRect | |||
* using the same color for fill and border. | |||
* | |||
* @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 | |||
*/ | |||
protected abstract void addFilledRect(int x, int y, int w, int h, | |||
ColorType col); | |||
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(); | |||
} | |||
public void startPageSequence(Title seqTitle) { | |||
} | |||
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)) { | |||
addFilledRect(rx, ry, w, -h, bg); | |||
} | |||
// normally this would be overriden to create a page in the | |||
// output | |||
public void renderPage(PageViewport page) throws IOException, | |||
FOPException { | |||
// floats & footnotes stuff | |||
renderAreaContainer(area.getBeforeFloatReferenceArea()); | |||
renderAreaContainer(area.getFootnoteReferenceArea()); | |||
Page p = page.getPage(); | |||
renderPageAreas(p); | |||
} | |||
// main reference area | |||
Enumeration e = area.getMainReferenceArea().getChildren().elements(); | |||
while (e.hasMoreElements()) { | |||
Box b = (Box)e.nextElement(); | |||
b.render(this); // span areas | |||
} | |||
protected void renderPageAreas(Page page) { | |||
RegionViewport viewport; | |||
viewport = page.getRegion(Region.BEFORE); | |||
renderRegionViewport(viewport); | |||
viewport = page.getRegion(Region.START); | |||
renderRegionViewport(viewport); | |||
viewport = page.getRegion(Region.BODY); | |||
renderRegionViewport(viewport); | |||
viewport = page.getRegion(Region.END); | |||
renderRegionViewport(viewport); | |||
viewport = page.getRegion(Region.AFTER); | |||
renderRegionViewport(viewport); | |||
} | |||
if (area.getPosition() != Position.STATIC) { | |||
this.currentYPosition = saveY; | |||
this.currentAreaContainerXPosition = saveX; | |||
} else | |||
this.currentYPosition -= area.getHeight(); | |||
} | |||
/** | |||
* 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) { | |||
// XPosition and YPosition give the content rectangle position | |||
this.currentYPosition = area.getYPosition(); | |||
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(); | |||
*/ | |||
// the region may clip the area and it establishes | |||
// a position from where the region is placed | |||
protected void renderRegionViewport(RegionViewport port) { | |||
if(port != null) { | |||
Region region = port.getRegion(); | |||
if (region.getRegionClass() == Region.BODY) { | |||
renderBodyRegion((BodyRegion) region); | |||
} else { | |||
renderRegion(region); | |||
} | |||
} | |||
} | |||
protected void renderRegion(Region region) { | |||
List blocks = region.getBlocks(); | |||
this.currentXPosition = this.currentAreaContainerXPosition; | |||
doFrame(area); | |||
renderBlocks(blocks); | |||
Enumeration e = area.getChildren().elements(); | |||
while (e.hasMoreElements()) { | |||
Box b = (Box)e.nextElement(); | |||
b.render(this); | |||
} | |||
protected void renderBodyRegion(BodyRegion region) { | |||
BeforeFloat bf = region.getBeforeFloat(); | |||
if(bf != null) { | |||
renderBeforeFloat(bf); | |||
} | |||
MainReference mr = region.getMainReference(); | |||
if(mr != null) { | |||
renderMainReference(mr); | |||
} | |||
Footnote foot = region.getFootnote(); | |||
if(foot != null) { | |||
renderFootnote(foot); | |||
} | |||
} | |||
protected void renderBeforeFloat(BeforeFloat bf) { | |||
List blocks = bf.getBlocks(); | |||
if (blocks != null) { | |||
renderBlocks(blocks); | |||
Block sep = bf.getSeparator(); | |||
if (sep != null) { | |||
renderBlock(sep); | |||
} | |||
} | |||
// Restore previous origin | |||
this.currentYPosition = saveY; | |||
this.currentAreaContainerXPosition = saveX; | |||
if (area.getPosition() == Position.STATIC) { | |||
this.currentYPosition -= area.getHeight(); | |||
} | |||
protected void renderFootnote(Footnote footnote) { | |||
List blocks = footnote.getBlocks(); | |||
if (blocks != null) { | |||
Block sep = footnote.getSeparator(); | |||
if (sep != null) { | |||
renderBlock(sep); | |||
} | |||
renderBlocks(blocks); | |||
} | |||
} | |||
/** | |||
* ** | |||
* if (area.getPosition() != Position.STATIC) { | |||
* this.currentYPosition = saveY; | |||
* this.currentAreaContainerXPosition = saveX; | |||
* } else | |||
* this.currentYPosition -= area.getHeight(); | |||
* ** | |||
*/ | |||
} | |||
/** | |||
* 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); | |||
// the main reference area contains a list of spans that are | |||
// stacked on the page | |||
// the spans contain a list of normal flow reference areas | |||
// that are positioned into columns. | |||
protected void renderMainReference(MainReference mr) { | |||
int saveIPPos = currentIPPosition; | |||
Span span = null; | |||
List spans = mr.getSpans(); | |||
for (int count = 0; count < spans.size(); count++) { | |||
span = (Span) spans.get(count); | |||
int offset = (mr.getWidth() - | |||
(span.getColumnCount() - 1) * mr.getColumnGap()) / | |||
span.getColumnCount() + mr.getColumnGap(); | |||
for (int c = 0; c < span.getColumnCount(); c++) { | |||
Flow flow = (Flow) span.getFlow(c); | |||
renderFlow(flow); | |||
currentIPPosition += offset; | |||
} | |||
currentIPPosition = saveIPPos; | |||
currentBPPosition += span.getHeight(); | |||
} | |||
this.currentYPosition -= (area.getPaddingBottom() | |||
+ area.getBorderBottomWidth()); | |||
} | |||
/** | |||
* 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(); | |||
} | |||
// the normal flow reference area contains stacked blocks | |||
protected void renderFlow(Flow flow) { | |||
List blocks = flow.getBlocks(); | |||
renderBlocks(blocks); | |||
} | |||
protected void renderBlock(Block block) { | |||
boolean childrenblocks = block.isChildrenBlocks(); | |||
List children = block.getChildAreas(); | |||
if (childrenblocks) { | |||
renderBlocks(children); | |||
} else { | |||
if (children == null) { | |||
// simply move position | |||
} else { | |||
this.currentYPosition = ry - area.getPlacementOffset(); | |||
for (int count = 0; count < children.size(); count++) { | |||
LineArea line = (LineArea) children.get(count); | |||
renderLineArea(line); | |||
} | |||
} | |||
b.render(this); | |||
} | |||
} | |||
// a line area may have grouped styling for its children | |||
// such as underline, background | |||
protected void renderLineArea(LineArea line) { | |||
List children = line.getInlineAreas(); | |||
for (int count = 0; count < children.size(); count++) { | |||
InlineArea inline = (InlineArea) children.get(count); | |||
inline.render(this); | |||
} | |||
} | |||
public void renderContainer(Container cont) { | |||
List blocks = cont.getBlocks(); | |||
renderBlocks(blocks); | |||
} | |||
this.currentYPosition = ry - h; | |||
this.currentXPosition = rx; | |||
public void renderCharacter(org.apache.fop.area.inline.Character ch) { | |||
currentBlockIPPosition += ch.getWidth(); | |||
} | |||
// an inline space moves the inline progression position | |||
// for the current block by the width or height of the space | |||
// it may also have styling (only on this object) that needs | |||
// handling | |||
public void renderInlineSpace(Space space) { | |||
currentBlockIPPosition += space.getWidth(); | |||
} | |||
protected void renderBlocks(List blocks) { | |||
for (int count = 0; count < blocks.size(); count++) { | |||
Block block = (Block) blocks.get(count); | |||
renderBlock(block); | |||
} | |||
} | |||
} |
@@ -5,9 +5,6 @@ | |||
* LICENSE file included with these sources." | |||
*/ | |||
// 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 | |||
@@ -16,12 +13,9 @@ import org.apache.fop.pdf.PDFColor; | |||
import org.apache.fop.image.ImageArea; | |||
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.render.pdf.FontSetup; | |||
import org.apache.fop.svg.SVGArea; | |||
import org.apache.fop.layout.FontInfo; | |||
// Java | |||
import java.io.IOException; | |||
@@ -31,384 +25,10 @@ import java.util.Enumeration; | |||
/** | |||
* Abstract base class of "Print" type renderers. | |||
* | |||
* Modified by Mark Lillywhite mark-fop@inomial.com. Removed | |||
* the render(AreaTree, OutputStream) method, and added | |||
* no-op concrete implementation of startRenderer() and | |||
* stopRenderer(). The method render(Page, OutputStream) | |||
* is not mentioned in this class but it is inherited from | |||
* the Renderer interface. | |||
*/ | |||
public abstract class PrintRenderer extends AbstractRenderer { | |||
// 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; | |||
// ^^^ | |||
// 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); | |||
/** | |||
* 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 and stroked 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); | |||
/** | |||
* Add a filled rectangle to the current stream | |||
* This default implementation calls addRect | |||
* using the same color for fill and border. | |||
* | |||
* @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 | |||
*/ | |||
protected void addFilledRect(int x, int y, int w, int h, | |||
PDFPathPaint fill) { | |||
addRect(x, y, w, h, fill, fill); | |||
} | |||
protected void addFilledRect(int x, int y, int w, int h, | |||
ColorType col) { | |||
PDFColor pdfcol = new PDFColor(col); | |||
addRect(x, y, w, h, pdfcol, pdfcol); | |||
} | |||
protected 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.addFilledRect(rx, ry, w, -h, 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(); | |||
// int left = rx - area.getBorderLeftWidth() / 2; | |||
// int right = rx + w + area.getBorderRightWidth() / 2; | |||
// int top = ry + area.getBorderTopWidth() / 2; | |||
// int bottom = ry - h - area.getBorderBottomWidth() / 2; | |||
// if (area.getBorderTopWidth() != 0) | |||
// addLine(left, top, right, top, area.getBorderTopWidth(), | |||
// new PDFColor(bp.getBorderColor(BorderAndPadding.TOP))); | |||
// if (area.getBorderLeftWidth() != 0) | |||
// addLine(left, ry + area.getBorderTopWidth(), left, bottom, area.getBorderLeftWidth(), | |||
// new PDFColor(bp.getBorderColor(BorderAndPadding.LEFT))); | |||
// if (area.getBorderRightWidth() != 0) | |||
// addLine(right, ry + area.getBorderTopWidth(), right, bottom, area.getBorderRightWidth(), | |||
// new PDFColor(bp.getBorderColor(BorderAndPadding.RIGHT))); | |||
// if (area.getBorderBottomWidth() != 0) | |||
// addLine(rx - area.getBorderLeftWidth(), bottom, rx + w + area.getBorderRightWidth(), bottom, area.getBorderBottomWidth(), | |||
// new PDFColor(bp.getBorderColor(BorderAndPadding.BOTTOM))); | |||
// Try using rectangles instead of lines. Line style will be a | |||
// problem though? | |||
int left = area.getBorderLeftWidth(); | |||
int right = area.getBorderRightWidth(); | |||
int top = area.getBorderTopWidth(); | |||
int bottom = area.getBorderBottomWidth(); | |||
// If style is solid, use filled rectangles | |||
if (top != 0) | |||
addFilledRect(rx, ry, w, top, | |||
new PDFColor(bp.getBorderColor(BorderAndPadding.TOP))); | |||
if (left != 0) | |||
addFilledRect(rx - left, ry - h - bottom, left, h + top + bottom, | |||
new PDFColor(bp.getBorderColor(BorderAndPadding.LEFT))); | |||
if (right != 0) | |||
addFilledRect(rx + w, ry - h - bottom, right, h + top + bottom, | |||
new PDFColor(bp.getBorderColor(BorderAndPadding.RIGHT))); | |||
if (bottom != 0) | |||
addFilledRect(rx, ry - h - bottom, w, bottom, | |||
new PDFColor(bp.getBorderColor(BorderAndPadding.BOTTOM))); | |||
} | |||
/** | |||
* 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 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 | |||
* | |||
@@ -420,28 +40,17 @@ public abstract class PrintRenderer extends AbstractRenderer { | |||
} | |||
/** | |||
Default start renderer method. This would | |||
normally be overridden. (mark-fop@inomial.com). | |||
*/ | |||
* | |||
*/ | |||
public void startRenderer(OutputStream outputStream) | |||
throws IOException {} | |||
/** | |||
Default stop renderer method. This would | |||
normally be overridden. (mark-fop@inomial.com). | |||
*/ | |||
public void stopRenderer(OutputStream outputStream) | |||
* | |||
*/ | |||
public void stopRenderer() | |||
throws IOException | |||
{ | |||
this.idReferences = null; | |||
currentFontName = ""; | |||
currentStroke = null; | |||
currentFill = null; | |||
prevUnderlineColor = null; | |||
prevOverlineColor = null; | |||
prevLineThroughColor = null; | |||
fontInfo = null; | |||
this.idReferences = null; | |||
} | |||
} |
@@ -7,31 +7,47 @@ | |||
package org.apache.fop.render; | |||
// FOP | |||
import org.apache.fop.svg.SVGArea; | |||
import org.apache.fop.image.ImageArea; | |||
import org.apache.fop.apps.FOPException; | |||
import org.apache.fop.layout.*; | |||
import org.apache.fop.layout.inline.*; | |||
import org.apache.fop.area.*; | |||
import org.apache.fop.area.inline.*; | |||
import org.apache.fop.layout.FontInfo; | |||
import org.apache.fop.fo.FOUserAgent; | |||
import org.apache.log.Logger; | |||
// Java | |||
import java.io.OutputStream; | |||
import java.io.IOException; | |||
import java.util.HashMap; | |||
/** | |||
* interface implement by all renderers. | |||
* | |||
* Interface implemented by all renderers. | |||
* This interface is used to control the rendering of pages | |||
* and to let block and inline level areas call the appropriate | |||
* method to render themselves | |||
* | |||
* a Renderer implementation takes areas/spaces and produces output in | |||
* some format. | |||
*/ | |||
public interface Renderer { | |||
public void startRenderer(OutputStream outputStream) | |||
throws IOException; | |||
public void stopRenderer() | |||
throws IOException; | |||
/** | |||
* Set the logger | |||
*/ | |||
public void setLogger(Logger logger); | |||
/** | |||
* Set the User Agent | |||
*/ | |||
public void setUserAgent(FOUserAgent agent); | |||
/** | |||
* set up the given FontInfo | |||
*/ | |||
@@ -40,89 +56,34 @@ public interface Renderer { | |||
/** | |||
* set up renderer options | |||
*/ | |||
public void setOptions(java.util.Hashtable options); | |||
public void setOptions(HashMap options); | |||
/** | |||
* set the producer of the rendering | |||
*/ | |||
public void setProducer(String producer); | |||
/** | |||
* render the given area tree to the given stream | |||
*/ | |||
//public void render(AreaTree areaTree, OutputStream stream) throws IOException, FOPException; | |||
public void render(Page page, OutputStream stream) | |||
throws IOException, FOPException; | |||
/** | |||
* render the given area container | |||
*/ | |||
public void renderAreaContainer(AreaContainer area); | |||
public void startPageSequence(Title seqTitle); | |||
/** | |||
* render the given area container | |||
*/ | |||
public void renderBodyAreaContainer(BodyAreaContainer area); | |||
/** | |||
* render the given span area | |||
*/ | |||
public void renderSpanArea(SpanArea area); | |||
/** | |||
* render the given block area | |||
*/ | |||
public void renderBlockArea(BlockArea area); | |||
/** | |||
* render the given display space | |||
*/ | |||
public void renderDisplaySpace(DisplaySpace space); | |||
/** | |||
* render the given SVG area | |||
*/ | |||
public void renderSVGArea(SVGArea area); | |||
/** | |||
* render a foreign object area | |||
*/ | |||
public void renderForeignObjectArea(ForeignObjectArea area); | |||
/** | |||
* render the given image area | |||
*/ | |||
public void renderImageArea(ImageArea area); | |||
/** | |||
* render the given inline area | |||
*/ | |||
public void renderWordArea(WordArea area); | |||
/** | |||
* render the given inline space | |||
*/ | |||
public void renderInlineSpace(InlineSpace space); | |||
public void renderPage(PageViewport page) | |||
throws IOException, FOPException; | |||
/** | |||
* render the given line area | |||
*/ | |||
public void renderLineArea(LineArea area); | |||
/** | |||
* render the given page | |||
*/ | |||
public void renderPage(Page page); | |||
public void renderContainer(Container cont); | |||
/* | |||
public void renderInlineViewport(org.apache.fop.area.inline.Viewport view); | |||
/** | |||
* render the given leader area | |||
*/ | |||
public void renderLeaderArea(LeaderArea area); | |||
public void renderWord(Word area); | |||
*/ | |||
public void renderCharacter(org.apache.fop.area.inline.Character ch); | |||
public void startRenderer(OutputStream outputStream) | |||
throws IOException; | |||
public void renderInlineSpace(Space space); | |||
/* | |||
public void renderForeignObject(ForeignObject area); | |||
public void stopRenderer(OutputStream outputStream) | |||
throws IOException; | |||
public void renderImage(Image area); | |||
public void renderLeader(Leader area); | |||
*/ | |||
} | |||
@@ -53,10 +53,6 @@ import java.text.*; | |||
import org.apache.fop.render.AbstractRenderer; | |||
/** | |||
Modified by Mark Lillywhite mark-fop@inomial.com. Did lots of | |||
cleaning up and made the class implement the new Renderer | |||
interface. This class could also do with a general audit, | |||
and I suspect it's not swing-thread-safe either. | |||
*/ | |||
public class AWTRenderer extends AbstractRenderer implements Printable, Pageable { | |||
@@ -105,20 +101,22 @@ public class AWTRenderer extends AbstractRenderer implements Printable, Pageable | |||
*/ | |||
protected Component parent; | |||
/** | |||
* options | |||
*/ | |||
protected Hashtable options; | |||
public AWTRenderer(Translator aRes) { | |||
res = aRes; | |||
} | |||
/** | |||
* set up renderer options | |||
*/ | |||
public void setOptions(Hashtable options) { | |||
this.options = options; | |||
public void setProducer(String producer) { | |||
} | |||
public AWTRenderer(Translator aRes) { | |||
res = aRes; | |||
public int getPageCount() { | |||
return 0; | |||
} | |||
public void setupFontInfo(FontInfo fontInfo) { | |||
// create a temp Image to test font metrics on | |||
BufferedImage fontImage = | |||
new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB); | |||
FontSetup.setup(fontInfo, fontImage.createGraphics()); | |||
} | |||
/** | |||
@@ -151,749 +149,28 @@ public class AWTRenderer extends AbstractRenderer implements Printable, Pageable | |||
return pageImage; | |||
} | |||
/** | |||
* 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 | |||
*/ | |||
// corrected 7/13/01 aml,rlc to properly handle thickness | |||
// | |||
protected void addLine(int x1, int y1, int x2, int y2, int th, float r, | |||
float g, float b) { | |||
graphics.setColor(new Color(r, g, b)); | |||
int x = x1; | |||
int y = y1; | |||
int height, width; | |||
if (x1 == x2) // vertical line | |||
{ | |||
height = y2 - y1; | |||
if (height > 0) // y coordinates are reversed between fo and AWT | |||
{ | |||
height = -height; | |||
y = y2; | |||
} | |||
width = th; | |||
if (width < 0) { | |||
width = -width; | |||
x -= width; | |||
} | |||
} else // horizontal line | |||
{ | |||
width = x2 - x1; | |||
if (width < 0) { | |||
width = -width; | |||
x = x2; | |||
} | |||
height = th; | |||
if (height > 0) // y coordinates are reversed between fo and AWT | |||
{ | |||
height = -height; | |||
y -= height; | |||
} | |||
} | |||
addRect(x, y, width, height, false); | |||
// // graphics.setColor(Color.red); | |||
// graphics.drawLine((int)(x1 / 1000f), | |||
// pageHeight - (int)(y1 / 1000f), (int)(x2 / 1000f), | |||
// pageHeight - (int)(y2 / 1000f)); | |||
} | |||
/** | |||
* draw a rectangle | |||
* | |||
* @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 r the red component | |||
* @param g the green component | |||
* @param b the blue component | |||
*/ | |||
// changed by aml/rlc to use helper function that | |||
// corrects for integer roundoff, and to remove 3D effect | |||
protected void addRect(int x, int y, int w, int h, float r, float g, | |||
float b) { | |||
graphics.setColor(new Color(r, g, b)); | |||
// graphics.setColor(Color.green); | |||
addRect(x, y, w, h, true); | |||
} | |||
/** | |||
* draw a filled rectangle | |||
* | |||
* @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 r the red component of edges | |||
* @param g the green component of edges | |||
* @param b the blue component of edges | |||
* @param fr the red component of the fill | |||
* @param fg the green component of the fill | |||
* @param fb the blue component of the fill | |||
*/ | |||
// changed by aml/rlc to use helper function that | |||
// corrects for integer roundoff | |||
protected void addRect(int x, int y, int w, int h, float r, float g, | |||
float b, float fr, float fg, float fb) { | |||
graphics.setColor(new Color(r, g, b)); | |||
addRect(x, y, w, h, true); | |||
graphics.setColor(new Color(fr, fg, fb)); | |||
addRect(x, y, w, h, false); | |||
} | |||
/** | |||
* draw a filled rectangle in the current color | |||
* | |||
* @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 drawAsOutline true for draw, false for fill | |||
*/ | |||
// helper function by aml/rlc to correct integer roundoff problems | |||
// | |||
protected void addRect(int x, int y, int w, int h, | |||
boolean drawAsOutline) { | |||
int startx = (x + 500) / 1000; | |||
int starty = pageHeight - ((y + 500) / 1000); | |||
int endx = (x + w + 500) / 1000; | |||
int endy = pageHeight - ((y + h + 500) / 1000); | |||
if (drawAsOutline) | |||
graphics.drawRect(startx, starty, endx - startx, endy - starty); | |||
else | |||
graphics.fillRect(startx, starty, endx - startx, endy - starty); | |||
} | |||
protected void addFilledRect(int x, int y, int w, int h, | |||
ColorType col) { | |||
float r = col.red(); | |||
float g = col.green(); | |||
float b = col.blue(); | |||
addRect(x, y, w, h, r, g, b, r, g, b); | |||
} | |||
/** | |||
* To configure before print. | |||
* | |||
* Choose pages | |||
* Zoom factor | |||
* Page format / Landscape or Portrait | |||
*/ | |||
public void transform(Graphics2D g2d, double zoomPercent, double angle) { | |||
AffineTransform at = g2d.getTransform(); | |||
at.rotate(angle); | |||
at.scale(zoomPercent / 100.0, zoomPercent / 100.0); | |||
g2d.setTransform(at); | |||
} | |||
protected void drawFrame() { | |||
int width = pageWidth; | |||
int height = pageHeight; | |||
graphics.setColor(Color.white); | |||
graphics.fillRect(0, 0, width, height); | |||
graphics.setColor(Color.black); | |||
graphics.drawRect(-1, -1, width + 2, height + 2); | |||
graphics.drawLine(width + 2, 0, width + 2, height + 2); | |||
graphics.drawLine(width + 3, 1, width + 3, height + 3); | |||
graphics.drawLine(0, height + 2, width + 2, height + 2); | |||
graphics.drawLine(1, height + 3, width + 3, height + 3); | |||
} | |||
/** | |||
* Retrieve the number of pages in this document. | |||
* | |||
* @return the number of pages | |||
*/ | |||
public int getPageCount() { | |||
return pageList.size(); | |||
} | |||
public void removePage(int page) { | |||
pageList.removeElementAt(page); | |||
} | |||
public void render(int aPageNumber) { | |||
if(aPageNumber >= pageList.size()) | |||
return; | |||
try { | |||
render((Page) pageList.elementAt(aPageNumber)); | |||
} catch(IOException e) { | |||
e.printStackTrace(); | |||
// This exception can't occur because we are not dealing with | |||
// any files | |||
} | |||
} | |||
public void render(Page page, OutputStream stream) | |||
public void startRenderer(OutputStream out) | |||
throws IOException { | |||
pageList.addElement(page); | |||
} | |||
public void render(Page page) | |||
public void stopRenderer() | |||
throws IOException { | |||
idReferences = page.getIDReferences(); | |||
pageWidth = (int)((float)page.getWidth() / 1000f + .5); | |||
pageHeight = (int)((float)page.getHeight() / 1000f + .5); | |||
pageImage = | |||
new BufferedImage((int)((pageWidth * (int)scaleFactor) / 100), | |||
(int)((pageHeight * (int)scaleFactor) / 100), | |||
BufferedImage.TYPE_INT_RGB); | |||
graphics = pageImage.createGraphics(); | |||
transform(graphics, scaleFactor, 0); | |||
drawFrame(); | |||
renderPage(page); | |||
} | |||
public void renderPage(Page page) { | |||
BodyAreaContainer body; | |||
AreaContainer before, after; | |||
body = page.getBody(); | |||
before = page.getBefore(); | |||
after = page.getAfter(); | |||
this.currentFontName = ""; | |||
this.currentFontSize = 0; | |||
renderBodyAreaContainer(body); | |||
if (before != null) { | |||
renderAreaContainer(before); | |||
} | |||
if (after != null) { | |||
renderAreaContainer(after); | |||
} | |||
// SG: Wollen wir Links abbilden? | |||
/* | |||
* if (page.hasLinks()) { | |||
* .... | |||
* } | |||
*/ | |||
} | |||
protected void doFrame(org.apache.fop.layout.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, bg.red(), bg.green(), bg.blue(), | |||
bg.red(), bg.green(), bg.blue()); | |||
} | |||
rx = rx - area.getBorderLeftWidth(); | |||
ry = ry + area.getBorderTopWidth(); | |||
w = w + area.getBorderLeftWidth() + area.getBorderRightWidth(); | |||
h = h + area.getBorderTopWidth() + area.getBorderBottomWidth(); | |||
BorderAndPadding bp = area.getBorderAndPadding(); | |||
ColorType borderColor; | |||
if (area.getBorderTopWidth() != 0) { | |||
borderColor = bp.getBorderColor(BorderAndPadding.TOP); | |||
// addLine(rx, ry, rx + w, ry, area.getBorderTopWidth(), // corrected aml/rlc | |||
addLine(rx, ry, rx + w, ry, -area.getBorderTopWidth(), | |||
borderColor.red(), borderColor.green(), | |||
borderColor.blue()); | |||
} | |||
if (area.getBorderLeftWidth() != 0) { | |||
borderColor = bp.getBorderColor(BorderAndPadding.LEFT); | |||
addLine(rx, ry, rx, ry - h, area.getBorderLeftWidth(), | |||
borderColor.red(), borderColor.green(), | |||
borderColor.blue()); | |||
} | |||
if (area.getBorderRightWidth() != 0) { | |||
borderColor = bp.getBorderColor(BorderAndPadding.RIGHT); | |||
addLine(rx + w, ry, rx + w, ry - h, | |||
// area.getBorderRightWidth(), borderColor.red(), // corrected aml/rlc | |||
-area.getBorderRightWidth(), borderColor.red(), | |||
borderColor.green(), | |||
borderColor.blue()); | |||
} | |||
if (area.getBorderBottomWidth() != 0) { | |||
borderColor = bp.getBorderColor(BorderAndPadding.BOTTOM); | |||
addLine(rx, ry - h, rx + w, ry - h, area.getBorderBottomWidth(), | |||
borderColor.red(), borderColor.green(), | |||
borderColor.blue()); | |||
} | |||
} | |||
protected Rectangle2D getBounds(org.apache.fop.layout.Area a) { | |||
return new Rectangle2D.Double(currentAreaContainerXPosition, | |||
currentYPosition, | |||
a.getAllocationWidth(), a.getHeight()); | |||
} | |||
public void setupFontInfo(FontInfo fontInfo) { | |||
// create a temp Image to test font metrics on | |||
BufferedImage fontImage = | |||
new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB); | |||
FontSetup.setup(fontInfo, fontImage.createGraphics()); | |||
} | |||
public void renderDisplaySpace(DisplaySpace space) { | |||
int d = space.getSize(); | |||
this.currentYPosition -= d; | |||
// Printable Interface | |||
public PageFormat getPageFormat(int pos) { | |||
return null; | |||
} | |||
// correct integer roundoff (aml/rlc) | |||
public void renderImageArea(ImageArea area) { | |||
int x = currentXPosition + area.getXOffset(); | |||
int y = currentYPosition; | |||
int w = area.getContentWidth(); | |||
int h = area.getHeight(); | |||
this.currentYPosition -= h; | |||
FopImage img = area.getImage(); | |||
if (img == null) { | |||
log.error("Error while loading image : area.getImage() is null"); | |||
// correct integer roundoff | |||
// graphics.drawRect(x / 1000, pageHeight - y / 1000, | |||
// w / 1000, h / 1000); | |||
addRect(x, y, w, h, true); // use helper function | |||
java.awt.Font f = graphics.getFont(); | |||
java.awt.Font smallFont = new java.awt.Font(f.getFontName(), | |||
f.getStyle(), 8); | |||
graphics.setFont(smallFont); | |||
// correct integer roundoff // aml/rlc | |||
// graphics.drawString("area.getImage() is null", x / 1000, | |||
// pageHeight - y / 1000); | |||
graphics.drawString("area.getImage() is null", (x + 500) / 1000, | |||
pageHeight - (y + 500) / 1000); | |||
graphics.setFont(f); | |||
} else { | |||
if (img instanceof SVGImage) { | |||
try { | |||
SVGDocument svg = ((SVGImage)img).getSVGDocument(); | |||
renderSVGDocument(svg, (int)x, (int)y); | |||
} catch (FopImageException e) {} | |||
} else { | |||
String urlString = img.getURL(); | |||
try { | |||
URL url = new URL(urlString); | |||
ImageIcon icon = new ImageIcon(url); | |||
Image image = icon.getImage(); | |||
// correct integer roundoff aml/rlc | |||
// graphics.drawImage(image, x / 1000, | |||
// pageHeight - y / 1000, w / 1000, h / 1000, | |||
// null); | |||
int startx = (x + 500) / 1000; | |||
int starty = pageHeight - ((y + 500) / 1000); | |||
int endx = (x + w + 500) / 1000; | |||
int endy = pageHeight - ((y + h + 500) / 1000); | |||
// reverse start and end y because h is positive | |||
graphics.drawImage(image, startx, starty, endx - startx, | |||
starty - endy, null); | |||
} catch (MalformedURLException mue) { | |||
// cannot normally occur because, if URL is wrong, constructing FopImage | |||
// will already have failed earlier on | |||
} | |||
} | |||
} | |||
this.currentXPosition += area.getContentWidth(); | |||
} | |||
public void renderWordArea(WordArea area) { | |||
char ch; | |||
StringBuffer pdf = new StringBuffer(); | |||
String name = area.getFontState().getFontName(); | |||
int size = area.getFontState().getFontSize(); | |||
boolean underlined = area.getUnderlined(); | |||
float red = area.getRed(); | |||
float green = area.getGreen(); | |||
float blue = area.getBlue(); | |||
FontMetricsMapper mapper; | |||
try { | |||
mapper = | |||
(FontMetricsMapper)area.getFontState().getFontInfo().getMetricsFor(name); | |||
} catch (FOPException iox) { | |||
mapper = new FontMetricsMapper("MonoSpaced", java.awt.Font.PLAIN, | |||
graphics); | |||
} | |||
if ((!name.equals(this.currentFontName)) | |||
|| (size != this.currentFontSize)) { | |||
this.currentFontName = name; | |||
this.currentFontSize = size; | |||
} | |||
if ((red != this.currentRed) || (green != this.currentGreen) | |||
|| (blue != this.currentBlue)) { | |||
this.currentRed = red; | |||
this.currentGreen = green; | |||
this.currentBlue = blue; | |||
} | |||
int rx = this.currentXPosition; | |||
int bl = this.currentYPosition; | |||
String s; // = area.getText(); | |||
if (area.getPageNumberID() | |||
!= null) { // this text is a page number, so resolve it | |||
s = idReferences.getPageNumber(area.getPageNumberID()); | |||
if (s == null) { | |||
s = ""; | |||
} | |||
} else { | |||
s = area.getText(); | |||
} | |||
Color oldColor = graphics.getColor(); | |||
java.awt.Font oldFont = graphics.getFont(); | |||
java.awt.Font f = mapper.getFont(size); | |||
if (saveColor != null) { | |||
if (saveColor.getRed() != red || saveColor.getGreen() != green | |||
|| saveColor.getBlue() != blue) { | |||
saveColor = new Color(red, green, blue); | |||
} | |||
} else { | |||
saveColor = new Color(red, green, blue); | |||
} | |||
graphics.setColor(saveColor); | |||
AttributedString ats = new AttributedString(s); | |||
ats.addAttribute(TextAttribute.FONT, f); | |||
if (underlined) { | |||
ats.addAttribute(TextAttribute.UNDERLINE, | |||
TextAttribute.UNDERLINE_ON); | |||
} | |||
AttributedCharacterIterator iter = ats.getIterator(); | |||
// correct integer roundoff | |||
// graphics.drawString(iter, rx / 1000f, | |||
// (int)(pageHeight - bl / 1000f)); | |||
graphics.drawString(iter, (rx + 500) / 1000, | |||
(int)(pageHeight - (bl + 500) / 1000)); | |||
graphics.setColor(oldColor); | |||
this.currentXPosition += area.getContentWidth(); | |||
} | |||
public void renderInlineSpace(InlineSpace space) { | |||
this.currentXPosition += space.getSize(); | |||
} | |||
/** | |||
* render leader area into AWT | |||
* | |||
* @param area area to render | |||
*/ | |||
// call to addRect corrected by aml/rlc | |||
public void renderLeaderArea(LeaderArea area) { | |||
int rx = this.currentXPosition; | |||
int ry = this.currentYPosition; | |||
int w = area.getLeaderLength(); | |||
int h = area.getHeight(); | |||
int th = area.getRuleThickness(); | |||
int st = area.getRuleStyle(); // not used at the moment | |||
float r = area.getRed(); | |||
float g = area.getGreen(); | |||
float b = area.getBlue(); | |||
Color oldColor = graphics.getColor(); | |||
graphics.setColor(new Color(r, g, b)); | |||
// use helper function to correct integer roundoff - aml/rlc | |||
// graphics.fillRect((int)(rx / 1000f), | |||
// (int)(pageHeight - ry / 1000f), (int)(w / 1000f), | |||
// (int)(th / 1000f)); | |||
addRect(rx, ry, w, -th, false); // NB addRect expects negative height | |||
graphics.setColor(oldColor); | |||
this.currentXPosition += area.getContentWidth(); | |||
} | |||
public void renderSVGArea(SVGArea area) { | |||
int x = this.currentXPosition; | |||
int y = this.currentYPosition; | |||
int w = area.getContentWidth(); | |||
int h = area.getHeight(); | |||
Document doc = area.getSVGDocument(); | |||
renderSVGDocument(doc, x, y); | |||
this.currentXPosition += area.getContentWidth(); | |||
} | |||
protected void renderSVGDocument(Document doc, int x, int y) { | |||
MUserAgent userAgent = new MUserAgent(new AffineTransform()); | |||
userAgent.setLogger(log); | |||
GVTBuilder builder = new GVTBuilder(); | |||
BridgeContext ctx = new BridgeContext(userAgent); | |||
GraphicsNode root; | |||
try { | |||
root = builder.build(ctx, doc); | |||
} catch (Exception e) { | |||
log.error("svg graphic could not be built: " | |||
+ e.getMessage(), e); | |||
return; | |||
} | |||
float w = (float)ctx.getDocumentSize().getWidth() * 1000f; | |||
float h = (float)ctx.getDocumentSize().getHeight() * 1000f; | |||
// correct integer roundoff aml/rlc | |||
// graphics.translate(x / 1000f, pageHeight - y / 1000f); | |||
graphics.translate((x + 500) / 1000, pageHeight - (y + 500) / 1000); | |||
SVGSVGElement svg = ((SVGDocument)doc).getRootElement(); | |||
AffineTransform at = ViewBox.getPreserveAspectRatioTransform(svg, w / 1000f, h / 1000f); | |||
AffineTransform inverse = null; | |||
try { | |||
inverse = at.createInverse(); | |||
} catch(NoninvertibleTransformException e) { | |||
} | |||
if(!at.isIdentity()) { | |||
graphics.transform(at); | |||
} | |||
try { | |||
root.paint(graphics); | |||
} catch (Exception e) { | |||
e.printStackTrace(); | |||
} | |||
if(inverse != null && !inverse.isIdentity()) { | |||
graphics.transform(inverse); | |||
} | |||
// correct integer roundoff aml/rlc | |||
// graphics.translate(-x / 1000f, y / 1000f - pageHeight); | |||
graphics.translate(-(x + 500) / 1000, (y + 500) / 1000 - pageHeight); | |||
} | |||
public void setProducer(String producer) { | |||
// defined in Renderer Interface | |||
} | |||
public int print(Graphics g, PageFormat pageFormat, | |||
int pageIndex) throws PrinterException { | |||
if (pageIndex >= pageList.size()) | |||
return NO_SUCH_PAGE; | |||
Graphics2D oldGraphics = graphics; | |||
int oldPageNumber = pageNumber; | |||
graphics = (Graphics2D)g; | |||
Page aPage = (Page)pageList.elementAt(pageIndex); | |||
renderPage(aPage); | |||
graphics = oldGraphics; | |||
return PAGE_EXISTS; | |||
public Printable getPrintable(int pos) { | |||
return null; | |||
} | |||
public int getNumberOfPages() { | |||
return pageList.size(); | |||
} | |||
public PageFormat getPageFormat(int pageIndex) | |||
throws IndexOutOfBoundsException { | |||
if (pageIndex >= pageList.size()) | |||
return null; | |||
Page page = (Page)pageList.elementAt(pageIndex); | |||
PageFormat pageFormat = new PageFormat(); | |||
Paper paper = new Paper(); | |||
double width = page.getWidth(); | |||
double height = page.getHeight(); | |||
// if the width is greater than the height assume lanscape mode | |||
// and swap the width and height values in the paper format | |||
if (width > height) { | |||
paper.setImageableArea(0, 0, height / 1000d, width / 1000d); | |||
paper.setSize(height / 1000d, width / 1000d); | |||
pageFormat.setOrientation(PageFormat.LANDSCAPE); | |||
} else { | |||
paper.setImageableArea(0, 0, width / 1000d, height / 1000d); | |||
paper.setSize(width / 1000d, height / 1000d); | |||
pageFormat.setOrientation(PageFormat.PORTRAIT); | |||
} | |||
pageFormat.setPaper(paper); | |||
return pageFormat; | |||
} | |||
public Printable getPrintable(int pageIndex) | |||
throws IndexOutOfBoundsException { | |||
return this; | |||
} | |||
public void setProgressListener(ProgressListener l) { | |||
progressListener = l; | |||
} | |||
public static Color colorType2Color(ColorType ct) { | |||
if (ct == null) { | |||
return null; | |||
} | |||
return new Color(ct.red(), ct.green(), ct.blue()); | |||
} | |||
/** | |||
* Draws an image. | |||
* TODO: protect other image formats (JIMI) | |||
*/ | |||
/* | |||
* public void renderImage(String href, float x, float y, float width, | |||
* float height, Vector transform) { | |||
* // What is with transformations? | |||
* try { | |||
* URL url = new URL(href); | |||
* ImageIcon imageIcon = new ImageIcon(url); | |||
* AffineTransform fullTransform = new AffineTransform(); | |||
* AffineTransform aTransform; | |||
* transform = (transform == null) ? new Vector() : transform; | |||
* for (int i = 0; i < transform.size(); i++) { | |||
* org.w3c.dom.svg.SVGTransform t = | |||
* (org.w3c.dom.svg.SVGTransform) | |||
* transform.elementAt(i); | |||
* SVGMatrix matrix = t.getMatrix(); | |||
* aTransform = new AffineTransform(matrix.getA(), | |||
* matrix.getB(), matrix.getC(), matrix.getD(), | |||
* matrix.getE(), matrix.getF()); | |||
* fullTransform.concatenate(aTransform); | |||
* } | |||
* BufferedImage bi = new BufferedImage((int) width, (int) height, | |||
* BufferedImage.TYPE_INT_RGB); | |||
* Graphics2D g2d = bi.createGraphics(); | |||
* BufferedImageOp bop = new AffineTransformOp(fullTransform, | |||
* AffineTransformOp.TYPE_NEAREST_NEIGHBOR); | |||
* g2d.drawImage(imageIcon.getImage(), 0, 0, (int) width, | |||
* (int) height, imageIcon.getImageObserver()); | |||
* graphics.drawImage(bi, bop, (int) x, (int) y); | |||
* } catch (Exception ex) { | |||
* log.error("AWTRenderer: renderImage(): " + | |||
* ex.getMessage(), ex); | |||
* } | |||
* } | |||
*/ | |||
public void renderForeignObjectArea(ForeignObjectArea area) { | |||
area.getObject().render(this); | |||
return 0; | |||
} | |||
protected class MUserAgent extends org.apache.fop.svg.SVGUserAgent { | |||
/** | |||
* Creates a new SVGUserAgent. | |||
*/ | |||
protected MUserAgent(AffineTransform at) { | |||
super(at); | |||
} | |||
/** | |||
* Opens a link in a new component. | |||
* @param doc The current document. | |||
* @param uri The document URI. | |||
*/ | |||
public void openLink(SVGAElement elt) { | |||
// application.openLink(uri); | |||
} | |||
public Point getClientAreaLocationOnScreen() { | |||
return new Point(0, 0); | |||
} | |||
public void setSVGCursor(java.awt.Cursor cursor) {} | |||
public Dimension2D getViewportSize() { | |||
return new Dimension(100, 100); | |||
} | |||
public EventDispatcher getEventDispatcher() { | |||
return null; | |||
} | |||
} | |||
public void startRenderer(OutputStream outputStream) | |||
throws IOException {} | |||
public void stopRenderer(OutputStream outputStream) | |||
throws IOException { | |||
render(0); | |||
public int print(Graphics g, PageFormat format, int pos) { | |||
return 0; | |||
} | |||
} |
@@ -41,11 +41,6 @@ import java.util.Hashtable; | |||
/** | |||
* Renderer that renders areas to MIF | |||
* | |||
* Modified by Mark Lillywhite mark-fop@inomial.com. Updated to | |||
* collect all the Pages and print them out at the end. This means | |||
* that the MIF renderer does not stream, but on the other hand | |||
* it should still work. I don't have an MIF view to test it with, | |||
* you see. | |||
*/ | |||
public class MIFRenderer extends AbstractRenderer { | |||
@@ -79,11 +74,6 @@ public class MIFRenderer extends AbstractRenderer { | |||
/* is a table currently open? */ | |||
private boolean inTable = false; | |||
/** | |||
* options | |||
*/ | |||
protected Hashtable options; | |||
/** | |||
* create the MIF renderer | |||
*/ | |||
@@ -91,12 +81,8 @@ public class MIFRenderer extends AbstractRenderer { | |||
this.mifDoc = new MIFDocument(); | |||
} | |||
/** | |||
* set up renderer options | |||
*/ | |||
public void setOptions(Hashtable options) { | |||
this.options = options; | |||
} | |||
public void startRenderer(OutputStream outputStream) | |||
throws IOException {} | |||
/** | |||
* set up the given FontInfo | |||
@@ -114,272 +100,12 @@ public class MIFRenderer extends AbstractRenderer { | |||
public void setProducer(String producer) {} | |||
public void renderAreaContainer(AreaContainer area) { | |||
if (area.foCreator != null | |||
&& area.foCreator.getName() == "fo:table") { | |||
this.mifDoc.createTable(); | |||
this.inTable = true; | |||
} else if (area.foCreator != null | |||
&& area.foCreator.getName() == "fo:table-body") { | |||
this.mifDoc.setCurrent("fo:table-body"); | |||
} else if (area.foCreator != null | |||
&& area.foCreator.getName() == "fo:table-column") { | |||
int colWidth = | |||
((org.apache.fop.fo.flow.TableColumn)area.foCreator).getColumnWidth(); | |||
this.mifDoc.setColumnProp(colWidth); | |||
} else if (area.foCreator != null | |||
&& area.foCreator.getName() == "fo:table-row") { | |||
this.mifDoc.startRow(); | |||
} else if (area.foCreator != null | |||
&& area.foCreator.getName() == "fo:table-cell") { | |||
int rowSpan = | |||
((org.apache.fop.fo.flow.TableCell)area.foCreator).getNumRowsSpanned(); | |||
int colSpan = | |||
((org.apache.fop.fo.flow.TableCell)area.foCreator).getNumColumnsSpanned(); | |||
this.mifDoc.startCell(rowSpan, colSpan); | |||
} else if (inTable) { | |||
inTable = false; | |||
this.mifDoc.endTable(); | |||
} | |||
super.renderAreaContainer(area); | |||
} | |||
protected void addFilledRect(int x, int y, int w, int h, | |||
ColorType col) { | |||
} | |||
protected 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(); | |||
// Create a textrect with these dimensions. | |||
// The y co-ordinate is measured +ve downwards so subtract page-height | |||
this.mifDoc.setTextRectProp(rx, pageHeight - ry, w, h); | |||
/* | |||
* 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))); | |||
*/ | |||
} | |||
public void renderSpanArea(SpanArea area) { | |||
// A span maps to a textframe | |||
this.mifDoc.createTextRect(area.getColumnCount()); | |||
super.renderSpanArea(area); | |||
} | |||
/** | |||
* render the given block area | |||
*/ | |||
public void renderBlockArea(BlockArea area) { | |||
this.mifDoc.setBlockProp(area.getStartIndent(), area.getEndIndent()); | |||
super.renderBlockArea(area); | |||
} | |||
/** | |||
* render the given display space | |||
*/ | |||
public void renderDisplaySpace(DisplaySpace space) { | |||
int d = space.getSize(); | |||
this.currentYPosition -= d; | |||
} | |||
/** | |||
* render the given SVG area | |||
*/ | |||
public void renderSVGArea(SVGArea area) {} | |||
/** | |||
* render a foreign object area | |||
*/ | |||
public void renderForeignObjectArea(ForeignObjectArea area) {} | |||
public void renderWordArea(WordArea area) { | |||
String s; | |||
s = area.getText(); | |||
this.mifDoc.addToStream(s); | |||
this.currentXPosition += area.getContentWidth(); | |||
} | |||
/** | |||
* render the given image area | |||
*/ | |||
public void renderImageArea(ImageArea area) { | |||
int x = this.currentAreaContainerXPosition + area.getXOffset(); | |||
int y = this.currentYPosition; | |||
int w = area.getContentWidth(); | |||
int h = area.getHeight(); | |||
this.currentYPosition -= h; | |||
FopImage img = area.getImage(); | |||
if (img instanceof SVGImage) { | |||
/* | |||
* try { | |||
* SVGSVGElement svg = | |||
* ((SVGImage) img).getSVGDocument().getRootElement(); | |||
* currentStream.add("ET\nq\n" + (((float) w) / 1000f) + | |||
* " 0 0 " + (((float) h) / 1000f) + " " + | |||
* (((float) x) / 1000f) + " " + | |||
* (((float)(y - h)) / 1000f) + " cm\n"); | |||
* // renderSVG(svg, (int) x, (int) y); | |||
* currentStream.add("Q\nBT\n"); | |||
* } catch (FopImageException e) { | |||
* } | |||
*/ | |||
log.warn("SVG images not supported in this version"); | |||
} else { | |||
String url = img.getURL(); | |||
this.mifDoc.addImage(url, x, pageHeight - y, w, h); | |||
} | |||
} | |||
/** | |||
* render the given inline area | |||
*/ | |||
public void renderInlineArea(InlineArea area) {} | |||
/** | |||
* render the given inline space | |||
*/ | |||
public void renderInlineSpace(InlineSpace space) { | |||
// I dont need the size of space! I just need to | |||
// leave a blank space each time | |||
String s = " "; | |||
this.mifDoc.addToStream(s); // cool! | |||
this.currentXPosition += space.getSize(); | |||
} | |||
/** | |||
* render the given line area | |||
*/ | |||
public void renderLineArea(LineArea area) { | |||
// The start of a new linearea corresponds to a new para in FM | |||
this.mifDoc.startLine(); | |||
super.renderLineArea(area); | |||
} | |||
/** | |||
* render the given page | |||
*/ | |||
public void renderPage(Page page) { | |||
AreaContainer before, after; | |||
BodyAreaContainer body; | |||
body = page.getBody(); | |||
before = page.getBefore(); | |||
after = page.getAfter(); | |||
this.currentFontName = ""; | |||
this.currentFontSize = "0"; | |||
pageHeight = page.getHeight(); | |||
pageWidth = page.getWidth(); | |||
this.mifDoc.setDocumentHeightWidth(pageHeight, pageWidth); | |||
this.mifDoc.createPage(); | |||
renderBodyAreaContainer(body); | |||
// If the area is an instance of anything other than body, it goes into the | |||
// corresponding master page. | |||
if (before != null) { | |||
this.mifDoc.createTextRect(1); // Create a rect with one col | |||
renderAreaContainer(before); | |||
} | |||
if (after != null) { | |||
this.mifDoc.createTextRect(1); // Create a rect with one col | |||
renderAreaContainer(after); | |||
} | |||
} | |||
/** | |||
* render the given leader area | |||
*/ | |||
public void renderLeaderArea(LeaderArea area) {} | |||
/** | |||
Default start renderer method. This would | |||
normally be overridden. (mark-fop@inomial.com). | |||
*/ | |||
public void startRenderer(OutputStream outputStream) | |||
throws IOException { | |||
log.info("rendering areas to MIF"); | |||
} | |||
/** | |||
Default stop renderer method. This would | |||
normally be overridden. (mark-fop@inomial.com) | |||
*/ | |||
public void stopRenderer(OutputStream outputStream) | |||
public void stopRenderer() | |||
throws IOException { | |||
log.info("writing out MIF"); | |||
this.mifDoc.output(outputStream); | |||
outputStream.flush(); | |||
} | |||
public void render(Page page, OutputStream outputStream) { | |||
this.renderPage(page); | |||
} | |||
} | |||
@@ -34,8 +34,6 @@ import java.util.Enumeration; | |||
* Renderer that renders areas to PCL | |||
* Created by Arthur E Welch III while at M&I EastPoint Technology | |||
* Donated by EastPoint to the Apache FOP project March 2, 2001. | |||
* Modified by Mark Lillywhite mark-fop@inomial.com to use the | |||
* new Renderer interface. | |||
*/ | |||
public class PCLRenderer extends PrintRenderer { | |||
@@ -67,13 +65,6 @@ public class PCLRenderer extends PrintRenderer { | |||
*/ | |||
public PCLRenderer() {} | |||
/** | |||
* set up renderer options | |||
*/ | |||
public void setOptions(java.util.Hashtable options) { | |||
this.options = options; | |||
} | |||
/** | |||
* set the PCL document's producer | |||
* | |||
@@ -81,407 +72,6 @@ public class PCLRenderer extends PrintRenderer { | |||
*/ | |||
public void setProducer(String producer) {} | |||
/** | |||
* 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 stroke the line color | |||
*/ | |||
protected void addLine(int x1, int y1, int x2, int y2, int th, | |||
PDFPathPaint stroke) { | |||
if (x1 == x2) | |||
addRect(x1 - (th / 2), y1, th, y2 - y1 + 1, stroke, stroke); | |||
else if (y1 == y2) | |||
addRect(x1, y1 + (th / 2), x2 - x1 + 1, th, stroke, 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 stroke the line color | |||
*/ | |||
protected void addLine(int x1, int y1, int x2, int y2, int th, int rs, | |||
PDFPathPaint stroke) { | |||
int dashon = 0; | |||
int dashoff = 0; | |||
// if ( rs != null && rs.length() > 5 && rs.charAt(0) == '[' && rs.charAt(1) != ']' && rs.charAt(4) == ']' ) | |||
// { | |||
// dashon = rs.charAt(1) - '0'; | |||
// dashoff = rs.charAt(3) - '0'; | |||
// } | |||
switch (rs) { | |||
case org.apache.fop.fo.properties.RuleStyle.DASHED: | |||
dashon = 3; | |||
dashoff = 3; | |||
break; | |||
case org.apache.fop.fo.properties.RuleStyle.DOTTED: | |||
dashon = 1; | |||
dashoff = 3; | |||
break; | |||
} | |||
if (x1 == x2) { | |||
if (dashon > 0 && dashoff > 0) { | |||
int start = y1; | |||
int len = th * dashon; | |||
while (start < y2) { | |||
if (start + len > y2) | |||
len = y2 - start; | |||
addRect(x1 - (th / 2), start, th, len, stroke, stroke); | |||
start += (len + dashoff * th); | |||
} | |||
} else | |||
addRect(x1 - (th / 2), y1, th, y2 - y1 + 1, stroke, stroke); | |||
} else if (y1 == y2) { | |||
if (dashon > 0 && dashoff > 0) { | |||
int start = x1; | |||
int len = th * dashon; | |||
while (start < x2) { | |||
if (start + len > x2) | |||
len = x2 - start; | |||
addRect(start, y1 + (th / 2), len, th, stroke, stroke); | |||
start += (len + dashoff * th); | |||
} | |||
} else | |||
addRect(x1, y1 + (th / 2), x2 - x1 + 1, th, stroke, 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 void addRect(int x, int y, int w, int h, PDFPathPaint stroke) { | |||
//if (h < 0) | |||
// h *= -1; | |||
if ((h >= 0 && h < 720) || (h < 0 && h > -720) || w < 720) { | |||
if (w < 720) | |||
w = 720; | |||
if (h > 0 && h < 720) | |||
h = 720; | |||
else if (h < 0 && h > -720) | |||
h = -720; | |||
addRect(x, y, w, h, stroke, stroke); | |||
} else { | |||
addRect(x, y, w, 720, stroke, stroke); | |||
addRect(x, y, 720, h, stroke, stroke); | |||
addRect(x + w - 720, y, 720, h, stroke, stroke); | |||
addRect(x, y - h + 720, w, 720, stroke, 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 void addRect(int x, int y, int w, int h, PDFPathPaint stroke, | |||
PDFPathPaint fill) { | |||
if ((w == 0) || (h == 0)) | |||
return; | |||
if (h < 0) | |||
h *= -1; | |||
else | |||
y += h; | |||
PDFColor sc = (PDFColor)stroke; | |||
PDFColor fc = (PDFColor)fill; | |||
sc.setColorSpace(ColorSpace.DEVICE_RGB); | |||
fc.setColorSpace(ColorSpace.DEVICE_RGB); | |||
int lineshade = | |||
(int)(100 | |||
- ((0.3f * sc.red() + 0.59f * sc.green() + 0.11f * sc.blue()) | |||
* 100f)); | |||
int fillshade = | |||
(int)(100 | |||
- ((0.3f * fc.red() + 0.59f * fc.green() + 0.11f * fc.blue()) | |||
* 100f)); | |||
int xpos = xoffset + (x / 100); | |||
if (xpos < 0) { | |||
xpos = 0; | |||
log.warn("Horizontal position out of bounds."); | |||
} | |||
currentStream.add("\033*v1O\033&a" + xpos + "h" | |||
+ (pageHeight - (y / 100)) + "V" + "\033*c" | |||
+ (w / 100) + "h" + (h / 100) + "V" + "\033*c" | |||
+ lineshade + "G" + "\033*c2P"); | |||
if (fillshade != lineshade && (w >= 720 || h >= 720)) { | |||
xpos = xoffset + ((x + 240) / 100); | |||
if (xpos < 0) { | |||
xpos = 0; | |||
log.warn("Horizontal position out of bounds."); | |||
} | |||
currentStream.add("\033&a" + xpos + "h" | |||
+ (pageHeight - ((y + 240)) / 100) + "V" | |||
+ "\033*c" + ((w - 480) / 100) + "h" | |||
+ ((h - 480) / 100) + "V" + "\033*c" | |||
+ fillshade + "G" + "\033*c2P"); | |||
} | |||
// Reset pattern transparency mode. | |||
currentStream.add("\033*v0O"); | |||
} | |||
boolean printBMP(FopImage img, int x, int y, int w, | |||
int h) throws FopImageException { | |||
// Print the passed image file in PCL. | |||
byte imgmap[] = img.getBitmaps(); | |||
int ix = 0; | |||
int iy = 0; | |||
int indx = 0; | |||
int iw = img.getWidth(); | |||
int ih = img.getHeight(); | |||
int bytewidth = (iw / 8); | |||
if ((iw % 8) != 0) | |||
bytewidth++; | |||
byte ib; | |||
char ic[] = new char[bytewidth * 2]; | |||
char icu[] = new char[bytewidth]; | |||
int lastcount = -1; | |||
byte lastbyte = 0; | |||
int icwidth = 0; | |||
int cr = 0; | |||
int cg = 0; | |||
int cb = 0; | |||
int grey = 0; | |||
boolean iscolor = img.getColorSpace().getColorSpace() | |||
!= ColorSpace.DEVICE_GRAY; | |||
int dcount = 0; | |||
int xres = (iw * 72000) / w; | |||
int yres = (ih * 72000) / h; | |||
int resolution = xres; | |||
if (yres > xres) | |||
resolution = yres; | |||
if (resolution > 300) | |||
resolution = 600; | |||
else if (resolution > 150) | |||
resolution = 300; | |||
else if (resolution > 100) | |||
resolution = 150; | |||
else if (resolution > 75) | |||
resolution = 100; | |||
else | |||
resolution = 75; | |||
if (debug) | |||
System.out.println("PCLRenderer.printBMP() iscolor = " + iscolor); | |||
// Setup for graphics | |||
currentStream.add("\033*t" + resolution + "R\033*r0F\033*r1A"); | |||
// Transfer graphics data | |||
for (iy = 0; iy < ih; iy++) { | |||
ib = 0; | |||
// int padding = iw % 8; | |||
// if ( padding != 0 ) | |||
// padding = 8 - padding; | |||
// padding = 0; | |||
// indx = (ih - iy - 1 + padding) * iw; | |||
indx = iy * iw; | |||
if (iscolor) | |||
indx *= 3; | |||
// currentStream.add("\033*b" + bytewidth + "W"); | |||
for (ix = 0; ix < iw; ix++) { | |||
if (iscolor) { | |||
cr = imgmap[indx++] & 0xFF; | |||
cg = imgmap[indx++] & 0xFF; | |||
cb = imgmap[indx++] & 0xFF; | |||
grey = (cr * 30 + cg * 59 + cb * 11) / 100; | |||
} else | |||
grey = imgmap[indx++] & 0xFF; | |||
if (grey < 128) | |||
ib |= (1 << (7 - (ix % 8))); | |||
if ((ix % 8) == 7 || ((ix + 1) == iw)) { | |||
if (icwidth < bytewidth) { | |||
if (lastcount >= 0) { | |||
if (ib == lastbyte) | |||
lastcount++; | |||
else { | |||
ic[icwidth++] = (char)(lastcount & 0xFF); | |||
ic[icwidth++] = (char)lastbyte; | |||
lastbyte = ib; | |||
lastcount = 0; | |||
} | |||
} else { | |||
lastbyte = ib; | |||
lastcount = 0; | |||
} | |||
if (lastcount == 255 || ((ix + 1) == iw)) { | |||
ic[icwidth++] = (char)(lastcount & 0xFF); | |||
ic[icwidth++] = (char)lastbyte; | |||
lastbyte = 0; | |||
lastcount = -1; | |||
} | |||
} | |||
icu[ix / 8] = (char)ib; | |||
ib = 0; | |||
} | |||
} | |||
if (icwidth < bytewidth) { | |||
currentStream.add("\033*b1m" + icwidth + "W"); | |||
currentStream.add(new String(ic, 0, icwidth)); | |||
} else { | |||
currentStream.add("\033*b0m" + bytewidth + "W"); | |||
currentStream.add(new String(icu)); | |||
} | |||
lastcount = -1; | |||
icwidth = 0; | |||
} | |||
// End graphics | |||
currentStream.add("\033*rB"); | |||
return (true); | |||
} | |||
/** | |||
* render image area to PCL | |||
* | |||
* @param area the image area to render | |||
*/ | |||
public void renderImageArea(ImageArea area) { | |||
int x = this.currentAreaContainerXPosition + area.getXOffset(); | |||
int y = this.currentYPosition; | |||
int w = area.getContentWidth(); | |||
int h = area.getHeight(); | |||
this.currentYPosition -= h; | |||
FopImage img = area.getImage(); | |||
int xpos = xoffset + (x / 100); | |||
if (xpos < 0) { | |||
xpos = 0; | |||
log.warn("Horizontal position out of bounds."); | |||
} | |||
currentStream.add("\033&a" + xpos + "h" + (pageHeight - (y / 100)) | |||
+ "V"); | |||
try { | |||
printBMP(img, x, y, w, h); | |||
} catch (FopImageException e) { | |||
// e.printStackTrace(System.out); | |||
log.error("PCLRenderer.renderImageArea() Error printing BMP (" | |||
+ e.toString() + ")"); | |||
} | |||
} | |||
/** | |||
* render a foreign object area | |||
*/ | |||
public void renderForeignObjectArea(ForeignObjectArea area) { | |||
// if necessary need to scale and align the content | |||
this.currentXPosition = this.currentXPosition + area.getXOffset(); | |||
this.currentYPosition = this.currentYPosition; | |||
switch (area.getAlign()) { | |||
case TextAlign.START: | |||
break; | |||
case TextAlign.END: | |||
break; | |||
case TextAlign.CENTER: | |||
case TextAlign.JUSTIFY: | |||
break; | |||
} | |||
switch (area.getVerticalAlign()) { | |||
case VerticalAlign.BASELINE: | |||
break; | |||
case VerticalAlign.MIDDLE: | |||
break; | |||
case VerticalAlign.SUB: | |||
break; | |||
case VerticalAlign.SUPER: | |||
break; | |||
case VerticalAlign.TEXT_TOP: | |||
break; | |||
case VerticalAlign.TEXT_BOTTOM: | |||
break; | |||
case VerticalAlign.TOP: | |||
break; | |||
case VerticalAlign.BOTTOM: | |||
break; | |||
} | |||
// in general the content will not be text | |||
// align and scale | |||
switch (area.scalingMethod()) { | |||
case Scaling.UNIFORM: | |||
break; | |||
case Scaling.NON_UNIFORM: | |||
break; | |||
} | |||
// if the overflow is auto (default), scroll or visible | |||
// then the contents should not be clipped, since this | |||
// is considered a printing medium. | |||
switch (area.getOverflow()) { | |||
case Overflow.VISIBLE: | |||
case Overflow.SCROLL: | |||
case Overflow.AUTO: | |||
break; | |||
case Overflow.HIDDEN: | |||
break; | |||
} | |||
area.getObject().render(this); | |||
this.currentXPosition += area.getEffectiveWidth(); | |||
// this.currentYPosition -= area.getEffectiveHeight(); | |||
} | |||
/** | |||
* render SVG area to PCL | |||
* | |||
* @param area the SVG area to render | |||
*/ | |||
public void renderSVGArea(SVGArea area) { | |||
if (debug) | |||
System.out.println("PCLRenderer.renderSVGArea(" + area + ")"); | |||
int x = this.currentXPosition; | |||
int y = this.currentYPosition; | |||
SVGSVGElement svg = | |||
((SVGDocument)area.getSVGDocument()).getRootElement(); | |||
int w = (int)(svg.getWidth().getBaseVal().getValue() * 1000); | |||
int h = (int)(svg.getHeight().getBaseVal().getValue() * 1000); | |||
/* | |||
* Clip to the svg area. | |||
* Note: To have the svg overlay (under) a text area then use | |||
* an fo:block-container | |||
*/ | |||
// TODO - translate and clip to viewbox | |||
// currentStream.add(svgRenderer.getString()); | |||
// currentStream.add("Q\n"); | |||
} | |||
public void setFont(String name, float size) { | |||
int fontcode = 0; | |||
if (name.length() > 1 && name.charAt(0) == 'F') { | |||
@@ -573,160 +163,6 @@ public class PCLRenderer extends PrintRenderer { | |||
} | |||
} | |||
/** | |||
* render inline area to PCL | |||
* | |||
* @param area inline area to render | |||
*/ | |||
public void renderWordArea(WordArea area) { | |||
String name = area.getFontState().getFontName(); | |||
int size = area.getFontState().getFontSize(); | |||
float red = area.getRed(); | |||
float green = area.getGreen(); | |||
float blue = area.getBlue(); | |||
PDFColor theAreaColor = new PDFColor((double)area.getRed(), | |||
(double)area.getGreen(), | |||
(double)area.getBlue()); | |||
// currentStream.add("\033*c" + (int)(100 - ((0.3f * red + 0.59f * green + 0.11f * blue) * 100f)) + "G\033*v2T"); | |||
currentStream.add("\033*v1O\033*c" | |||
+ (int)(100 - ((0.3f * red + 0.59f * green + 0.11f * blue) * 100f)) | |||
+ "G\033*v2T"); | |||
if ((!name.equals(this.currentFontName)) | |||
|| (size != this.currentFontSize)) { | |||
this.currentFontName = name; | |||
this.currentFontSize = size; | |||
setFont(name, size); | |||
} | |||
this.currentFill = theAreaColor; | |||
int rx = this.currentXPosition; | |||
int bl = this.currentYPosition; | |||
String s; | |||
if (area.getPageNumberID() != null) { | |||
// this text is a page number, so resolve it | |||
s = idReferences.getPageNumber(area.getPageNumberID()); | |||
if (s == null) | |||
s = ""; | |||
} else { | |||
s = area.getText(); | |||
} | |||
addWordLines(area, rx, bl, size, theAreaColor); | |||
int xpos = xoffset + (rx / 100); | |||
if (xpos < 0) { | |||
xpos = 0; | |||
log.warn("Horizontal position out of bounds."); | |||
} | |||
currentStream.add("\033&a" + xpos + "h" + (pageHeight - (bl / 100)) | |||
+ "V" + s); | |||
this.currentXPosition += area.getContentWidth(); | |||
} | |||
/** | |||
* render page into PCL | |||
* | |||
* @param page page to render | |||
*/ | |||
public void renderPage(Page page) { | |||
if (debug) | |||
System.out.println("PCLRenderer.renderPage() page.Height() = " | |||
+ page.getHeight()); | |||
BodyAreaContainer body; | |||
AreaContainer before, after, start, end; | |||
if (paperheight > 0 && divisions == -1) | |||
divisions = paperheight / (page.getHeight() / 100); | |||
if (debug) | |||
System.out.println("PCLRenderer.renderPage() paperheight=" | |||
+ paperheight + " divisions=" + divisions); | |||
// Set top margin. | |||
// float fullmargin = 0; | |||
if (divisions > 0) | |||
fullmargin = paperheight * curdiv / divisions; | |||
if (topmargin > 0) | |||
fullmargin += topmargin; | |||
if (debug) | |||
System.out.println("PCLRenderer.renderPage() curdiv=" + curdiv | |||
+ " fullmargin=" + fullmargin); | |||
// if ( fullmargin > 0 ) | |||
// currentStream.add("\033&l" + (fullmargin / 15f) + "c1e8C"); | |||
// this.currentYPosition = fullmargin * 100; | |||
if (paperheight > 0) | |||
pageHeight = (paperheight / divisions) + fullmargin; | |||
else | |||
pageHeight = page.getHeight() / 100; | |||
if (debug) | |||
System.out.println("PCLRenderer.renderPage() Set currentYPosition=" | |||
+ this.currentYPosition); | |||
if (leftmargin > 0 && curdiv == 0) | |||
currentStream.add("\033&k" + (leftmargin / 6f) | |||
+ "H\033&a1L\033&k12H"); | |||
body = page.getBody(); | |||
before = page.getBefore(); | |||
after = page.getAfter(); | |||
start = page.getStart(); | |||
end = page.getEnd(); | |||
this.currentFontName = ""; | |||
this.currentFontSize = 0; | |||
renderBodyAreaContainer(body); | |||
if (before != null) | |||
renderAreaContainer(before); | |||
if (after != null) | |||
renderAreaContainer(after); | |||
if (start != null) | |||
renderAreaContainer(start); | |||
if (end != null) | |||
renderAreaContainer(end); | |||
// End page. | |||
if (++curdiv == divisions || divisions == -1) { | |||
curdiv = 0; | |||
currentStream.add("\f"); | |||
} | |||
// Links, etc not implemented... | |||
/* | |||
* currentPage = this.pdfDoc.makePage(this.pdfResources, currentStream, | |||
* page.getWidth()/1000, page.getHeight()/1000, page); | |||
* if (page.hasLinks()) { | |||
* currentAnnotList = this.pdfDoc.makeAnnotList(); | |||
* currentPage.setAnnotList(currentAnnotList); | |||
* Enumeration e = page.getLinkSets().elements(); | |||
* while (e.hasMoreElements()) { | |||
* LinkSet linkSet = (LinkSet) e.nextElement(); | |||
* linkSet.align(); | |||
* String dest = linkSet.getDest(); | |||
* int linkType = linkSet.getLinkType(); | |||
* Enumeration f = linkSet.getRects().elements(); | |||
* while (f.hasMoreElements()) { | |||
* LinkedRectangle lrect = (LinkedRectangle) f.nextElement(); | |||
* currentAnnotList.addLink( | |||
* this.pdfDoc.makeLink(lrect.getRectangle(), dest, linkType)); | |||
* } | |||
* } | |||
* } else { | |||
* // just to be on the safe side | |||
* currentAnnotList = null; | |||
* } | |||
*/ | |||
} | |||
public void startRenderer(OutputStream outputStream) | |||
throws IOException { | |||
log.info("rendering areas to PCL"); | |||
@@ -746,16 +182,8 @@ public class PCLRenderer extends PrintRenderer { | |||
currentStream.add("\033" + "9\033&l0E"); | |||
} | |||
public void stopRenderer(OutputStream outputStream) | |||
throws IOException { | |||
log.info("writing out PCL"); | |||
outputStream.flush(); | |||
} | |||
public void render(Page page, OutputStream outputStream) | |||
public void stopRenderer() | |||
throws IOException { | |||
idReferences = page.getIDReferences(); | |||
this.renderPage(page); | |||
} | |||
} |
@@ -13,52 +13,25 @@ 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.inline.*; | |||
import org.apache.fop.datatypes.*; | |||
import org.apache.fop.svg.*; | |||
import org.apache.fop.pdf.*; | |||
import org.apache.fop.layout.*; | |||
import org.apache.fop.image.*; | |||
import org.apache.fop.extensions.*; | |||
import org.apache.fop.datatypes.IDReferences; | |||
import org.apache.fop.render.pdf.fonts.LazyFont; | |||
import org.apache.batik.bridge.*; | |||
import org.apache.batik.swing.svg.*; | |||
import org.apache.batik.swing.gvt.*; | |||
import org.apache.batik.gvt.*; | |||
import org.apache.batik.gvt.renderer.*; | |||
import org.apache.batik.gvt.filter.*; | |||
import org.apache.batik.gvt.event.*; | |||
import org.apache.fop.area.*; | |||
import org.apache.fop.area.inline.*; | |||
import org.w3c.dom.*; | |||
import org.w3c.dom.svg.*; | |||
import org.w3c.dom.css.*; | |||
import org.w3c.dom.svg.SVGLength; | |||
import org.w3c.dom.Document; | |||
// Java | |||
import java.io.IOException; | |||
import java.io.OutputStream; | |||
import java.util.Enumeration; | |||
import java.util.Vector; | |||
import java.util.Hashtable; | |||
import java.awt.geom.AffineTransform; | |||
import java.awt.geom.Dimension2D; | |||
import java.awt.Point; | |||
import java.awt.RenderingHints; | |||
import java.awt.Dimension; | |||
/** | |||
* Renderer that renders areas to PDF | |||
* | |||
* Modified by Mark Lillywhite, mark-fop@inomial.com to use the | |||
* new Renderer interface. The PDF renderer is by far the trickiest | |||
* renderer and the best supported by FOP. It also required some | |||
* reworking in the way that Pages, Catalogs and the Root object | |||
* were written to the stream. The output document should now still | |||
* be a 100% compatible PDF document, but hte order of the document | |||
* writing is significantly different. See also the changes | |||
* to PDFPage, PDFPages and PDFRoot. | |||
*/ | |||
public class PDFRenderer extends PrintRenderer { | |||
@@ -116,13 +89,6 @@ public class PDFRenderer extends PrintRenderer { | |||
*/ | |||
private StringBuffer _wordAreaPDF = new StringBuffer(); | |||
/** | |||
* options | |||
*/ | |||
protected Hashtable options; | |||
protected Vector extensions = null; | |||
/** | |||
* create the PDF renderer | |||
*/ | |||
@@ -130,13 +96,6 @@ public class PDFRenderer extends PrintRenderer { | |||
this.pdfDoc = new PDFDocument(); | |||
} | |||
/** | |||
* set up renderer options | |||
*/ | |||
public void setOptions(Hashtable options) { | |||
this.options = options; | |||
} | |||
/** | |||
* set the PDF document's producer | |||
* | |||
@@ -151,703 +110,16 @@ public class PDFRenderer extends PrintRenderer { | |||
pdfDoc.outputHeader(stream); | |||
} | |||
public void stopRenderer(OutputStream stream) | |||
public void stopRenderer() | |||
throws IOException { | |||
renderRootExtensions(extensions); | |||
FontSetup.addToResources(this.pdfDoc, fontInfo); | |||
pdfDoc.outputTrailer(stream); | |||
// this frees up memory and makes the renderer reusable | |||
this.pdfDoc = new PDFDocument(); | |||
this.pdfResources = null; | |||
extensions = null; | |||
currentStream = null; | |||
currentAnnotList = null; | |||
currentPage = null; | |||
currentColor = null; | |||
super.stopRenderer(stream); | |||
} | |||
/** | |||
* 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 void addLine(int x1, int y1, int x2, int y2, int th, | |||
PDFPathPaint stroke) { | |||
closeText(); | |||
currentStream.add("ET\nq\n" + stroke.getColorSpaceOut(false) | |||
+ (x1 / 1000f) + " " + (y1 / 1000f) + " m " | |||
+ (x2 / 1000f) + " " + (y2 / 1000f) + " l " | |||
+ (th / 1000f) + " w S\n" + "Q\nBT\n"); | |||
} | |||
/** | |||
* 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 void addLine(int x1, int y1, int x2, int y2, int th, int rs, | |||
PDFPathPaint stroke) { | |||
closeText(); | |||
currentStream.add("ET\nq\n" + stroke.getColorSpaceOut(false) | |||
+ setRuleStylePattern(rs) + (x1 / 1000f) + " " | |||
+ (y1 / 1000f) + " m " + (x2 / 1000f) + " " | |||
+ (y2 / 1000f) + " l " + (th / 1000f) + " w S\n" | |||
+ "Q\nBT\n"); | |||
} | |||
/** | |||
* 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 void addRect(int x, int y, int w, int h, PDFPathPaint stroke) { | |||
closeText(); | |||
currentStream.add("ET\nq\n" + stroke.getColorSpaceOut(false) | |||
+ (x / 1000f) + " " + (y / 1000f) + " " | |||
+ (w / 1000f) + " " + (h / 1000f) + " re s\n" | |||
+ "Q\nBT\n"); | |||
} | |||
/** | |||
* 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 void addRect(int x, int y, int w, int h, PDFPathPaint stroke, | |||
PDFPathPaint fill) { | |||
closeText(); | |||
currentStream.add("ET\nq\n" + fill.getColorSpaceOut(true) | |||
+ stroke.getColorSpaceOut(false) + (x / 1000f) | |||
+ " " + (y / 1000f) + " " + (w / 1000f) + " " | |||
+ (h / 1000f) + " re b\n" + "Q\nBT\n"); | |||
} | |||
/** | |||
* 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 | |||
*/ | |||
protected void addFilledRect(int x, int y, int w, int h, | |||
PDFPathPaint fill) { | |||
closeText(); | |||
currentStream.add("ET\nq\n" + fill.getColorSpaceOut(true) | |||
+ (x / 1000f) + " " + (y / 1000f) + " " | |||
+ (w / 1000f) + " " + (h / 1000f) + " re f\n" | |||
+ "Q\nBT\n"); | |||
} | |||
/** | |||
* render image area to PDF | |||
* | |||
* @param area the image area to render | |||
*/ | |||
public void renderImageArea(ImageArea area) { | |||
// adapted from contribution by BoBoGi | |||
int x = this.currentXPosition + area.getXOffset(); | |||
int y = this.currentYPosition; | |||
int w = area.getContentWidth(); | |||
int h = area.getHeight(); | |||
this.currentYPosition -= h; | |||
FopImage img = area.getImage(); | |||
if (img instanceof SVGImage) { | |||
try { | |||
closeText(); | |||
SVGDocument svg = ((SVGImage)img).getSVGDocument(); | |||
currentStream.add("ET\nq\n"); | |||
renderSVGDocument(svg, (int)x, (int)y, area.getFontState()); | |||
currentStream.add("Q\nBT\n"); | |||
} catch (FopImageException e) {} | |||
} else { | |||
int xObjectNum = this.pdfDoc.addImage(img); | |||
closeText(); | |||
currentStream.add("ET\nq\n" + (((float)w) / 1000f) + " 0 0 " | |||
+ (((float)h) / 1000f) + " " | |||
+ (((float)x) / 1000f) + " " | |||
+ (((float)(y - h)) / 1000f) + " cm\n" + "/Im" | |||
+ xObjectNum + " Do\nQ\nBT\n"); | |||
} | |||
this.currentXPosition += area.getContentWidth(); | |||
} | |||
/** | |||
* render a foreign object area | |||
*/ | |||
public void renderForeignObjectArea(ForeignObjectArea area) { | |||
// if necessary need to scale and align the content | |||
this.currentXPosition = this.currentXPosition + area.getXOffset(); | |||
this.currentYPosition = this.currentYPosition; | |||
switch (area.getAlign()) { | |||
case TextAlign.START: | |||
break; | |||
case TextAlign.END: | |||
break; | |||
case TextAlign.CENTER: | |||
case TextAlign.JUSTIFY: | |||
break; | |||
} | |||
switch (area.getVerticalAlign()) { | |||
case VerticalAlign.BASELINE: | |||
break; | |||
case VerticalAlign.MIDDLE: | |||
break; | |||
case VerticalAlign.SUB: | |||
break; | |||
case VerticalAlign.SUPER: | |||
break; | |||
case VerticalAlign.TEXT_TOP: | |||
break; | |||
case VerticalAlign.TEXT_BOTTOM: | |||
break; | |||
case VerticalAlign.TOP: | |||
break; | |||
case VerticalAlign.BOTTOM: | |||
break; | |||
} | |||
closeText(); | |||
// in general the content will not be text | |||
currentStream.add("ET\n"); | |||
// align and scale | |||
currentStream.add("q\n"); | |||
switch (area.scalingMethod()) { | |||
case Scaling.UNIFORM: | |||
break; | |||
case Scaling.NON_UNIFORM: | |||
break; | |||
} | |||
// if the overflow is auto (default), scroll or visible | |||
// then the contents should not be clipped, since this | |||
// is considered a printing medium. | |||
switch (area.getOverflow()) { | |||
case Overflow.VISIBLE: | |||
case Overflow.SCROLL: | |||
case Overflow.AUTO: | |||
break; | |||
case Overflow.HIDDEN: | |||
break; | |||
} | |||
area.getObject().render(this); | |||
currentStream.add("Q\n"); | |||
currentStream.add("BT\n"); | |||
this.currentXPosition += area.getEffectiveWidth(); | |||
// this.currentYPosition -= area.getEffectiveHeight(); | |||
} | |||
/** | |||
* render SVG area to PDF | |||
* | |||
* @param area the SVG area to render | |||
*/ | |||
public void renderSVGArea(SVGArea area) { | |||
// place at the current instream offset | |||
int x = this.currentXPosition; | |||
int y = this.currentYPosition; | |||
renderSVGDocument(area.getSVGDocument(), x, y, area.getFontState()); | |||
} | |||
protected void renderSVGDocument(Document doc, int x, int y, | |||
FontState fs) { | |||
float sx = 1, sy = -1; | |||
int xOffset = x, yOffset = y; | |||
org.apache.fop.svg.SVGUserAgent userAgent | |||
= new org.apache.fop.svg.SVGUserAgent(new AffineTransform()); | |||
userAgent.setLogger(log); | |||
GVTBuilder builder = new GVTBuilder(); | |||
BridgeContext ctx = new BridgeContext(userAgent); | |||
TextPainter textPainter = null; | |||
Boolean bl = | |||
org.apache.fop.configuration.Configuration.getBooleanValue("strokeSVGText"); | |||
if (bl == null || bl.booleanValue()) { | |||
textPainter = new StrokingTextPainter(); | |||
} else { | |||
textPainter = new PDFTextPainter(fs); | |||
} | |||
ctx.setTextPainter(textPainter); | |||
PDFAElementBridge aBridge = new PDFAElementBridge(); | |||
aBridge.setCurrentTransform(new AffineTransform(sx, 0, 0, sy, xOffset / 1000f, yOffset / 1000f)); | |||
ctx.putBridge(aBridge); | |||
GraphicsNode root; | |||
try { | |||
root = builder.build(ctx, doc); | |||
} catch (Exception e) { | |||
log.error("svg graphic could not be built: " | |||
+ e.getMessage(), e); | |||
return; | |||
} | |||
// get the 'width' and 'height' attributes of the SVG document | |||
float w = (float)ctx.getDocumentSize().getWidth() * 1000f; | |||
float h = (float)ctx.getDocumentSize().getHeight() * 1000f; | |||
ctx = null; | |||
builder = null; | |||
/* | |||
* Clip to the svg area. | |||
* Note: To have the svg overlay (under) a text area then use | |||
* an fo:block-container | |||
*/ | |||
currentStream.add("q\n"); | |||
if (w != 0 && h != 0) { | |||
currentStream.add(x / 1000f + " " + y / 1000f + " m\n"); | |||
currentStream.add((x + w) / 1000f + " " + y / 1000f + " l\n"); | |||
currentStream.add((x + w) / 1000f + " " + (y - h) / 1000f | |||
+ " l\n"); | |||
currentStream.add(x / 1000f + " " + (y - h) / 1000f + " l\n"); | |||
currentStream.add("h\n"); | |||
currentStream.add("W\n"); | |||
currentStream.add("n\n"); | |||
} | |||
// transform so that the coordinates (0,0) is from the top left | |||
// and positive is down and to the right. (0,0) is where the | |||
// viewBox puts it. | |||
currentStream.add(sx + " 0 0 " + sy + " " + xOffset / 1000f + " " | |||
+ yOffset / 1000f + " cm\n"); | |||
SVGSVGElement svg = ((SVGDocument)doc).getRootElement(); | |||
AffineTransform at = ViewBox.getPreserveAspectRatioTransform(svg, w / 1000f, h / 1000f); | |||
if(!at.isIdentity()) { | |||
double[] vals = new double[6]; | |||
at.getMatrix(vals); | |||
currentStream.add(PDFNumber.doubleOut(vals[0]) + " " | |||
+ PDFNumber.doubleOut(vals[1]) + " " | |||
+ PDFNumber.doubleOut(vals[2]) + " " | |||
+ PDFNumber.doubleOut(vals[3]) + " " | |||
+ PDFNumber.doubleOut(vals[4]) + " " | |||
+ PDFNumber.doubleOut(vals[5]) + " cm\n"); | |||
} | |||
PDFGraphics2D graphics = new PDFGraphics2D(true, fs, pdfDoc, | |||
currentFontName, | |||
currentFontSize, | |||
currentXPosition, | |||
currentYPosition); | |||
graphics.setGraphicContext(new org.apache.batik.ext.awt.g2d.GraphicContext()); | |||
try { | |||
root.paint(graphics); | |||
currentStream.add(graphics.getString()); | |||
} catch (Exception e) { | |||
log.error("svg graphic could not be rendered: " | |||
+ e.getMessage(), e); | |||
} | |||
currentAnnotList = graphics.getAnnotList(); | |||
currentStream.add("Q\n"); | |||
} | |||
/** | |||
* render inline area to PDF | |||
* | |||
* @param area inline area to render | |||
*/ | |||
public void renderWordArea(WordArea area) { | |||
synchronized (_wordAreaPDF) { | |||
StringBuffer pdf = _wordAreaPDF; | |||
pdf.setLength(0); | |||
Hashtable kerning = null; | |||
boolean kerningAvailable = false; | |||
kerning = area.getFontState().getKerning(); | |||
if (kerning != null &&!kerning.isEmpty()) { | |||
kerningAvailable = true; | |||
} | |||
String name = area.getFontState().getFontName(); | |||
int size = area.getFontState().getFontSize(); | |||
// This assumes that *all* CIDFonts use a /ToUnicode mapping | |||
boolean useMultiByte = false; | |||
Font f = | |||
(Font)area.getFontState().getFontInfo().getFonts().get(name); | |||
if (f instanceof LazyFont){ | |||
if(((LazyFont) f).getRealFont() instanceof CIDFont){ | |||
useMultiByte = true; | |||
} | |||
}else if (f instanceof CIDFont){ | |||
useMultiByte = true; | |||
} | |||
// String startText = useMultiByte ? "<FEFF" : "("; | |||
String startText = useMultiByte ? "<" : "("; | |||
String endText = useMultiByte ? "> " : ") "; | |||
if ((!name.equals(this.currentFontName)) | |||
|| (size != this.currentFontSize)) { | |||
closeText(); | |||
this.currentFontName = name; | |||
this.currentFontSize = size; | |||
pdf = pdf.append("/" + name + " " + (size / 1000) + " Tf\n"); | |||
} | |||
PDFColor areaColor = null; | |||
if (this.currentFill instanceof PDFColor) { | |||
areaColor = (PDFColor)this.currentFill; | |||
} | |||
if (areaColor == null || areaColor.red() != (double)area.getRed() | |||
|| areaColor.green() != (double)area.getGreen() | |||
|| areaColor.blue() != (double)area.getBlue()) { | |||
areaColor = new PDFColor((double)area.getRed(), | |||
(double)area.getGreen(), | |||
(double)area.getBlue()); | |||
closeText(); | |||
this.currentFill = areaColor; | |||
pdf.append(this.currentFill.getColorSpaceOut(true)); | |||
} | |||
int rx = this.currentXPosition; | |||
int bl = this.currentYPosition; | |||
addWordLines(area, rx, bl, size, areaColor); | |||
if (!textOpen || bl != prevWordY) { | |||
closeText(); | |||
pdf.append("1 0 0 1 " + (rx / 1000f) + " " + (bl / 1000f) | |||
+ " Tm [" + startText); | |||
prevWordY = bl; | |||
textOpen = true; | |||
} else { | |||
// express the space between words in thousandths of an em | |||
int space = prevWordX - rx + prevWordWidth; | |||
float emDiff = (float)space / (float)currentFontSize * 1000f; | |||
// this prevents a problem in Acrobat Reader where large | |||
// numbers cause text to disappear or default to a limit | |||
if (emDiff < -33000) { | |||
closeText(); | |||
pdf.append("1 0 0 1 " + (rx / 1000f) + " " + (bl / 1000f) | |||
+ " Tm [" + startText); | |||
textOpen = true; | |||
} else { | |||
pdf.append(Float.toString(emDiff)); | |||
pdf.append(" "); | |||
pdf.append(startText); | |||
} | |||
} | |||
prevWordWidth = area.getContentWidth(); | |||
prevWordX = rx; | |||
String s; | |||
if (area.getPageNumberID() | |||
!= null) { // this text is a page number, so resolve it | |||
s = idReferences.getPageNumber(area.getPageNumberID()); | |||
if (s == null) { | |||
s = ""; | |||
} | |||
} else { | |||
s = area.getText(); | |||
} | |||
int l = s.length(); | |||
for (int i = 0; i < l; i++) { | |||
char ch = area.getFontState().mapChar(s.charAt(i)); | |||
if (!useMultiByte) { | |||
if (ch > 127) { | |||
pdf.append("\\"); | |||
pdf.append(Integer.toOctalString((int)ch)); | |||
} else { | |||
switch (ch) { | |||
case '(': | |||
case ')': | |||
case '\\': | |||
pdf.append("\\"); | |||
break; | |||
} | |||
pdf.append(ch); | |||
} | |||
} else { | |||
pdf.append(getUnicodeString(ch)); | |||
} | |||
if (kerningAvailable && (i + 1) < l) { | |||
addKerning(pdf, (new Integer((int)ch)), | |||
(new Integer((int)area.getFontState().mapChar(s.charAt(i + 1)))), | |||
kerning, startText, endText); | |||
} | |||
} | |||
pdf.append(endText); | |||
currentStream.add(pdf.toString()); | |||
this.currentXPosition += area.getContentWidth(); | |||
} | |||
} | |||
/** | |||
* Convert a char to a multibyte hex representation | |||
*/ | |||
private String getUnicodeString(char c) { | |||
StringBuffer buf = new StringBuffer(4); | |||
byte[] uniBytes = null; | |||
try { | |||
char[] a = { | |||
c | |||
}; | |||
uniBytes = new String(a).getBytes("UnicodeBigUnmarked"); | |||
} catch (Exception e) { | |||
// This should never fail | |||
} | |||
public void renderPage(PageViewport page) throws IOException, FOPException { | |||
for (int i = 0; i < uniBytes.length; i++) { | |||
int b = (uniBytes[i] < 0) ? (int)(256 + uniBytes[i]) | |||
: (int)uniBytes[i]; | |||
String hexString = Integer.toHexString(b); | |||
if (hexString.length() == 1) | |||
buf = buf.append("0" + hexString); | |||
else | |||
buf = buf.append(hexString); | |||
} | |||
return buf.toString(); | |||
Page p = page.getPage(); | |||
renderPageAreas(p); | |||
} | |||
/** | |||
* Checks to see if we have some text rendering commands open | |||
* still and writes out the TJ command to the stream if we do | |||
*/ | |||
private void closeText() { | |||
if (textOpen) { | |||
currentStream.add("] TJ\n"); | |||
textOpen = false; | |||
prevWordX = 0; | |||
prevWordY = 0; | |||
} | |||
} | |||
private void addKerning(StringBuffer buf, Integer ch1, Integer ch2, | |||
Hashtable kerning, String startText, | |||
String endText) { | |||
Hashtable kernPair = (Hashtable)kerning.get(ch1); | |||
if (kernPair != null) { | |||
Integer width = (Integer)kernPair.get(ch2); | |||
if (width != null) { | |||
buf.append(endText).append(-(width.intValue())).append(' ').append(startText); | |||
} | |||
} | |||
} | |||
public void render(Page page, OutputStream outputStream) | |||
throws FOPException, IOException { | |||
// log.debug("rendering single page to PDF"); | |||
this.idReferences = page.getIDReferences(); | |||
this.pdfResources = this.pdfDoc.getResources(); | |||
this.pdfDoc.setIDReferences(idReferences); | |||
this.renderPage(page); | |||
Vector exts = page.getExtensions(); | |||
if(exts != null) { | |||
extensions = exts; | |||
} | |||
// log.debug("writing out PDF"); | |||
this.pdfDoc.output(outputStream); | |||
} | |||
/** | |||
* render page into PDF | |||
* | |||
* @param page page to render | |||
*/ | |||
public void renderPage(Page page) { | |||
BodyAreaContainer body; | |||
AreaContainer before, after, start, end; | |||
currentStream = this.pdfDoc.makeStream(); | |||
body = page.getBody(); | |||
before = page.getBefore(); | |||
after = page.getAfter(); | |||
start = page.getStart(); | |||
end = page.getEnd(); | |||
this.currentFontName = ""; | |||
this.currentFontSize = 0; | |||
currentStream.add("BT\n"); | |||
renderBodyAreaContainer(body); | |||
if (before != null) { | |||
renderAreaContainer(before); | |||
} | |||
if (after != null) { | |||
renderAreaContainer(after); | |||
} | |||
if (start != null) { | |||
renderAreaContainer(start); | |||
} | |||
if (end != null) { | |||
renderAreaContainer(end); | |||
} | |||
closeText(); | |||
float w = page.getWidth(); | |||
float h = page.getHeight(); | |||
currentStream.add("ET\n"); | |||
currentPage = this.pdfDoc.makePage(this.pdfResources, currentStream, | |||
Math.round(w / 1000), | |||
Math.round(h / 1000), page); | |||
if (page.hasLinks() || currentAnnotList != null) { | |||
if(currentAnnotList == null) { | |||
currentAnnotList = this.pdfDoc.makeAnnotList(); | |||
} | |||
currentPage.setAnnotList(currentAnnotList); | |||
Enumeration e = page.getLinkSets().elements(); | |||
while (e.hasMoreElements()) { | |||
LinkSet linkSet = (LinkSet)e.nextElement(); | |||
linkSet.align(); | |||
String dest = linkSet.getDest(); | |||
int linkType = linkSet.getLinkType(); | |||
Enumeration f = linkSet.getRects().elements(); | |||
while (f.hasMoreElements()) { | |||
LinkedRectangle lrect = (LinkedRectangle)f.nextElement(); | |||
currentAnnotList.addLink(this.pdfDoc.makeLink(lrect.getRectangle(), | |||
dest, linkType)); | |||
} | |||
} | |||
currentAnnotList = null; | |||
} else { | |||
// just to be on the safe side | |||
currentAnnotList = null; | |||
} | |||
// ensures that color is properly reset for blocks that carry over pages | |||
this.currentFill = null; | |||
} | |||
/** | |||
* defines a string containing dashArray and dashPhase for the rule style | |||
*/ | |||
private String setRuleStylePattern(int style) { | |||
String rs = ""; | |||
switch (style) { | |||
case org.apache.fop.fo.properties.RuleStyle.SOLID: | |||
rs = "[] 0 d "; | |||
break; | |||
case org.apache.fop.fo.properties.RuleStyle.DASHED: | |||
rs = "[3 3] 0 d "; | |||
break; | |||
case org.apache.fop.fo.properties.RuleStyle.DOTTED: | |||
rs = "[1 3] 0 d "; | |||
break; | |||
case org.apache.fop.fo.properties.RuleStyle.DOUBLE: | |||
rs = "[] 0 d "; | |||
break; | |||
default: | |||
rs = "[] 0 d "; | |||
} | |||
return rs; | |||
} | |||
protected void renderRootExtensions(Vector exts) { | |||
if (exts != null) { | |||
Enumeration e = exts.elements(); | |||
while (e.hasMoreElements()) { | |||
ExtensionObj ext = (ExtensionObj)e.nextElement(); | |||
if (ext instanceof Outline) { | |||
renderOutline((Outline)ext); | |||
} | |||
} | |||
} | |||
} | |||
private void renderOutline(Outline outline) { | |||
PDFOutline outlineRoot = pdfDoc.getOutlineRoot(); | |||
PDFOutline pdfOutline = null; | |||
Outline parent = outline.getParentOutline(); | |||
if (parent == null) { | |||
pdfOutline = | |||
this.pdfDoc.makeOutline(outlineRoot, | |||
outline.getLabel().toString(), | |||
outline.getInternalDestination()); | |||
} else { | |||
PDFOutline pdfParentOutline = | |||
(PDFOutline)parent.getRendererObject(); | |||
if (pdfParentOutline == null) { | |||
log.error("pdfParentOutline is null"); | |||
} else { | |||
pdfOutline = | |||
this.pdfDoc.makeOutline(pdfParentOutline, | |||
outline.getLabel().toString(), | |||
outline.getInternalDestination()); | |||
} | |||
} | |||
outline.setRendererObject(pdfOutline); | |||
// handle sub outlines | |||
Vector v = outline.getOutlines(); | |||
Enumeration e = v.elements(); | |||
while (e.hasMoreElements()) { | |||
renderOutline((Outline)e.nextElement()); | |||
} | |||
} | |||
} |
@@ -211,7 +211,7 @@ public class PSGraphics2D extends AbstractGraphics2D { | |||
// psRenderer.write("" + matrix[0] + " " + matrix[1] + | |||
// " " + matrix[2] + " " + matrix[3] + " " + | |||
// matrix[4] + " " + matrix[5] + " cm\n"); | |||
psRenderer.renderBitmap(fopimg, x, y, width, height); | |||
//psRenderer.renderBitmap(fopimg, x, y, width, height); | |||
psRenderer.write("grestore"); | |||
} catch (Exception e) { | |||
e.printStackTrace(); |
@@ -106,9 +106,6 @@ public class PSRenderer extends AbstractRenderer { | |||
protected IDReferences idReferences; | |||
protected Hashtable options; | |||
/** | |||
* set the document's producer | |||
* | |||
@@ -118,14 +115,6 @@ public class PSRenderer extends AbstractRenderer { | |||
this.producer = producer; | |||
} | |||
/** | |||
* set up renderer options | |||
*/ | |||
public void setOptions(Hashtable options) { | |||
this.options = options; | |||
} | |||
/** | |||
* write out a command | |||
*/ | |||
@@ -239,7 +228,7 @@ public class PSRenderer extends AbstractRenderer { | |||
} | |||
protected void movetoCurrPosition() { | |||
write(this.currentXPosition + " " + this.currentYPosition + " M"); | |||
write(this.currentIPPosition + " " + this.currentBPPosition + " M"); | |||
} | |||
/** | |||
@@ -266,190 +255,6 @@ public class PSRenderer extends AbstractRenderer { | |||
write("fill"); | |||
} | |||
/** | |||
* render a display space to PostScript | |||
* | |||
* @param space the space to render | |||
*/ | |||
public void renderDisplaySpace(DisplaySpace space) { | |||
// write("% --- DisplaySpace size="+space.getSize()); | |||
this.currentYPosition -= space.getSize(); | |||
movetoCurrPosition(); | |||
} | |||
/** | |||
* render a foreign object area | |||
*/ | |||
public void renderForeignObjectArea(ForeignObjectArea area) { | |||
// if necessary need to scale and align the content | |||
area.getObject().render(this); | |||
} | |||
/** | |||
* render an SVG area to PostScript | |||
* | |||
* @param area the area to render | |||
*/ | |||
public void renderSVGArea(SVGArea area) { | |||
int x = this.currentXPosition; | |||
int y = this.currentYPosition; | |||
Document doc = area.getSVGDocument(); | |||
org.apache.fop.svg.SVGUserAgent userAgent | |||
= new org.apache.fop.svg.SVGUserAgent(new AffineTransform()); | |||
userAgent.setLogger(log); | |||
GVTBuilder builder = new GVTBuilder(); | |||
BridgeContext ctx = new BridgeContext(userAgent); | |||
GraphicsNode root; | |||
try { | |||
root = builder.build(ctx, doc); | |||
} catch (Exception e) { | |||
log.error("svg graphic could not be built: " | |||
+ e.getMessage(), e); | |||
return; | |||
} | |||
// get the 'width' and 'height' attributes of the SVG document | |||
float w = (float)ctx.getDocumentSize().getWidth() * 1000f; | |||
float h = (float)ctx.getDocumentSize().getHeight() * 1000f; | |||
ctx = null; | |||
builder = null; | |||
float sx = 1, sy = -1; | |||
int xOffset = x, yOffset = y; | |||
comment("% --- SVG Area"); | |||
write("gsave"); | |||
if (w != 0 && h != 0) { | |||
write("newpath"); | |||
write(x + " " + y + " M"); | |||
write((x + w) + " " + y + " rlineto"); | |||
write((x + w) + " " + (y - h) + " rlineto"); | |||
write(x + " " + (y - h) + " rlineto"); | |||
write("closepath"); | |||
write("clippath"); | |||
} | |||
// transform so that the coordinates (0,0) is from the top left | |||
// and positive is down and to the right. (0,0) is where the | |||
// viewBox puts it. | |||
write(xOffset + " " + yOffset + " translate"); | |||
write(sx + " " + sy + " scale"); | |||
PSGraphics2D graphics = new PSGraphics2D(false, area.getFontState(), | |||
this, currentFontName, | |||
currentFontSize, | |||
currentXPosition, | |||
currentYPosition); | |||
graphics.setGraphicContext(new org.apache.batik.ext.awt.g2d.GraphicContext()); | |||
try { | |||
root.paint(graphics); | |||
} catch (Exception e) { | |||
log.error("svg graphic could not be rendered: " | |||
+ e.getMessage(), e); | |||
} | |||
write("grestore"); | |||
comment("% --- SVG Area end"); | |||
movetoCurrPosition(); | |||
} | |||
public void renderBitmap(FopImage img, int x, int y, int w, int h) { | |||
try { | |||
boolean iscolor = img.getColorSpace().getColorSpace() | |||
!= ColorSpace.DEVICE_GRAY; | |||
byte[] imgmap = img.getBitmaps(); | |||
write("gsave"); | |||
write("/DeviceRGB setcolorspace"); | |||
write(x + " " + (y - h) + " translate"); | |||
write(w + " " + h + " scale"); | |||
write("<<"); | |||
write(" /ImageType 1"); | |||
write(" /Width " + img.getWidth()); | |||
write(" /Height " + img.getHeight()); | |||
write(" /BitsPerComponent 8"); | |||
if (iscolor) { | |||
write(" /Decode [0 1 0 1 0 1]"); | |||
} else { | |||
write(" /Decode [0 1]"); | |||
} | |||
// Setup scanning for left-to-right and top-to-bottom | |||
write(" /ImageMatrix [" + img.getWidth() + " 0 0 -" | |||
+ img.getHeight() + " 0 " + img.getHeight() + "]"); | |||
write(" /DataSource currentfile /ASCII85Decode filter /FlateDecode filter"); | |||
// write(" /DataSource currentfile /ASCIIHexDecode filter /FlateDecode filter"); | |||
// write(" /DataSource currentfile /ASCII85Decode filter /RunLengthDecode filter"); | |||
// write(" /DataSource currentfile /ASCIIHexDecode filter /RunLengthDecode filter"); | |||
// write(" /DataSource currentfile /ASCIIHexDecode filter"); | |||
// write(" /DataSource currentfile /ASCII85Decode filter"); | |||
// write(" /DataSource currentfile /RunLengthDecode filter"); | |||
write(">>"); | |||
write("image"); | |||
/* | |||
* for (int y=0; y<img.getHeight(); y++) { | |||
* int indx = y * img.getWidth(); | |||
* if (iscolor) indx*= 3; | |||
* for (int x=0; x<img.getWidth(); x++) { | |||
* if (iscolor) { | |||
* writeASCIIHex(imgmap[indx++] & 0xFF); | |||
* writeASCIIHex(imgmap[indx++] & 0xFF); | |||
* writeASCIIHex(imgmap[indx++] & 0xFF); | |||
* } else { | |||
* writeASCIIHex(imgmap[indx++] & 0xFF); | |||
* } | |||
* } | |||
* } | |||
*/ | |||
try { | |||
// imgmap[0] = 1; | |||
InputStream bain = new ByteArrayInputStream(imgmap); | |||
InputStream in; | |||
in = bain; | |||
in = FlateEncodeFilter.filter(in); | |||
// in = RunLengthEncodeFilter.filter(in); | |||
// in = ASCIIHexEncodeFilter.filter(in); | |||
in = ASCII85EncodeFilter.filter(in); | |||
copyStream(in, this.out); | |||
} catch (IOException e) { | |||
if (!ioTrouble) | |||
e.printStackTrace(); | |||
ioTrouble = true; | |||
} | |||
write(""); | |||
write("grestore"); | |||
} catch (FopImageException e) { | |||
log.error("PSRenderer.renderImageArea(): Error rendering bitmap (" | |||
+ e.getMessage() + ")", e); | |||
} | |||
} | |||
/** | |||
* render an image area to PostScript | |||
* | |||
* @param area the area to render | |||
*/ | |||
public void renderImageArea(ImageArea area) { | |||
int x = this.currentAreaContainerXPosition + area.getXOffset(); | |||
int y = this.currentYPosition; | |||
int w = area.getContentWidth(); | |||
int h = area.getHeight(); | |||
this.currentYPosition -= area.getHeight(); | |||
imagecount++; | |||
// if (imagecount!=4) return; | |||
comment("% --- ImageArea"); | |||
if (area.getImage() instanceof SVGImage) {} | |||
else { | |||
renderBitmap(area.getImage(), x, y, w, h); | |||
} | |||
comment("% --- ImageArea end"); | |||
} | |||
private long copyStream(InputStream in, OutputStream out, | |||
int bufferSize) throws IOException { | |||
long bytes_total = 0; | |||
@@ -468,58 +273,6 @@ public class PSRenderer extends AbstractRenderer { | |||
return copyStream(in, out, 4096); | |||
} | |||
/** | |||
* render an inline area to PostScript | |||
* | |||
* @param area the area to render | |||
*/ | |||
public void renderWordArea(WordArea area) { | |||
FontState fs = area.getFontState(); | |||
String fontWeight = fs.getFontWeight(); | |||
StringBuffer sb = new StringBuffer(); | |||
String s; | |||
if (area.getPageNumberID() | |||
!= null) { // this text is a page number, so resolve it | |||
s = idReferences.getPageNumber(area.getPageNumberID()); | |||
if (s == null) { | |||
s = ""; | |||
} | |||
} else { | |||
s = area.getText(); | |||
} | |||
int l = s.length(); | |||
for (int i = 0; i < l; i++) { | |||
char ch = s.charAt(i); | |||
char mch = fs.mapChar(ch); | |||
if (mch > 127) { | |||
sb = sb.append("\\" + Integer.toOctalString(mch)); | |||
} else { | |||
String escape = "\\()[]{}"; | |||
if (escape.indexOf(mch) >= 0) { | |||
sb.append("\\"); | |||
} | |||
sb = sb.append(mch); | |||
} | |||
} | |||
// System.out.println("["+s+"] --> ["+sb.toString()+"]"); | |||
// comment("% --- InlineArea font-weight="+fontWeight+": " + sb.toString()); | |||
useFont(fs.getFontName(), fs.getFontSize()); | |||
useColor(area.getRed(), area.getGreen(), area.getBlue()); | |||
if (area.getUnderlined() || area.getLineThrough() | |||
|| area.getOverlined()) | |||
write("ULS"); | |||
write("(" + sb.toString() + ") t"); | |||
if (area.getUnderlined()) | |||
write("ULE"); | |||
if (area.getLineThrough()) | |||
write("SOE"); | |||
if (area.getOverlined()) | |||
write("OLE"); | |||
this.currentXPosition += area.getContentWidth(); | |||
} | |||
public void useFont(String name, int size) { | |||
if ((currentFontName != name) || (currentFontSize != size)) { | |||
write(name + " " + size + " F"); | |||
@@ -528,269 +281,6 @@ public class PSRenderer extends AbstractRenderer { | |||
} | |||
} | |||
/** | |||
* render an inline space to PostScript | |||
* | |||
* @param space the space to render | |||
*/ | |||
public void renderInlineSpace(InlineSpace space) { | |||
// write("% --- InlineSpace size="+space.getSize()); | |||
this.currentXPosition += space.getSize(); | |||
if (space.getUnderlined() || space.getLineThrough() | |||
|| space.getOverlined()) | |||
write("ULS"); | |||
write(space.getSize() + " 0 RM"); | |||
if (space.getUnderlined()) | |||
write("ULE"); | |||
if (space.getLineThrough()) | |||
write("SOE"); | |||
if (space.getOverlined()) | |||
write("OLE"); | |||
} | |||
/** | |||
* render a line area to PostScript | |||
* | |||
* @param area the 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; | |||
// method is identical to super method except next line | |||
movetoCurrPosition(); | |||
String fontWeight = area.getFontState().getFontWeight(); | |||
// comment("% --- LineArea begin font-weight="+fontWeight); | |||
Enumeration e = area.getChildren().elements(); | |||
while (e.hasMoreElements()) { | |||
Box b = (Box)e.nextElement(); | |||
this.currentYPosition = ry - area.getPlacementOffset(); | |||
b.render(this); | |||
} | |||
// comment("% --- LineArea end"); | |||
this.currentYPosition = ry - h; | |||
this.currentXPosition = rx; | |||
} | |||
/** | |||
* render a page to PostScript | |||
* | |||
* @param page the page to render | |||
*/ | |||
public void renderPage(Page page) { | |||
this.idReferences = page.getIDReferences(); | |||
BodyAreaContainer body; | |||
AreaContainer before, after; | |||
write("%%Page: " + page.getNumber() + " " + page.getNumber()); | |||
write("%%BeginPageSetup"); | |||
write("FOPFonts begin"); | |||
write("0.001 0.001 scale"); | |||
write("%%EndPageSetup"); | |||
body = page.getBody(); | |||
before = page.getBefore(); | |||
after = page.getAfter(); | |||
if (before != null) { | |||
renderAreaContainer(before); | |||
} | |||
renderBodyAreaContainer(body); | |||
if (after != null) { | |||
renderAreaContainer(after); | |||
} | |||
write("showpage"); | |||
write("%%PageTrailer"); | |||
write("%%EndPage"); | |||
} | |||
/** | |||
* render a leader area to PostScript | |||
* | |||
* @param area the area to render | |||
*/ | |||
public void renderLeaderArea(LeaderArea area) { | |||
int rx = this.currentXPosition; | |||
int ry = this.currentYPosition; | |||
int w = area.getContentWidth(); | |||
int th = area.getRuleThickness(); | |||
int th2 = th / 2; | |||
int th3 = th / 3; | |||
int th4 = th / 4; | |||
switch (area.getLeaderPattern()) { | |||
case LeaderPattern.SPACE: | |||
// NOP | |||
break; | |||
case LeaderPattern.RULE: | |||
if (area.getRuleStyle() == RuleStyle.NONE) | |||
break; | |||
useColor(area.getRed(), area.getGreen(), area.getBlue()); | |||
write("gsave"); | |||
write("0 setlinecap"); | |||
switch (area.getRuleStyle()) { | |||
case RuleStyle.DOTTED: | |||
write("newpath"); | |||
write("[1000 3000] 0 setdash"); | |||
write(th + " setlinewidth"); | |||
write(rx + " " + ry + " M"); | |||
write(w + " 0 rlineto"); | |||
useColor(area.getRed(), area.getGreen(), area.getBlue()); | |||
write("stroke"); | |||
break; | |||
case RuleStyle.DASHED: | |||
write("newpath"); | |||
write("[3000 3000] 0 setdash"); | |||
write(th + " setlinewidth"); | |||
write(rx + " " + ry + " M"); | |||
write(w + " 0 rlineto"); | |||
useColor(area.getRed(), area.getGreen(), area.getBlue()); | |||
write("stroke"); | |||
break; | |||
case RuleStyle.SOLID: | |||
write("newpath"); | |||
write(th + " setlinewidth"); | |||
write(rx + " " + ry + " M"); | |||
write(w + " 0 rlineto"); | |||
useColor(area.getRed(), area.getGreen(), area.getBlue()); | |||
write("stroke"); | |||
break; | |||
case RuleStyle.DOUBLE: | |||
write("newpath"); | |||
write(th3 + " setlinewidth"); | |||
write(rx + " " + (ry - th3) + " M"); | |||
write(w + " 0 rlineto"); | |||
write(rx + " " + (ry + th3) + " M"); | |||
write(w + " 0 rlineto"); | |||
useColor(area.getRed(), area.getGreen(), area.getBlue()); | |||
write("stroke"); | |||
break; | |||
case RuleStyle.GROOVE: | |||
write(th2 + " setlinewidth"); | |||
write("newpath"); | |||
write(rx + " " + (ry - th4) + " M"); | |||
write(w + " 0 rlineto"); | |||
useColor(area.getRed(), area.getGreen(), area.getBlue()); | |||
write("stroke"); | |||
write("newpath"); | |||
write(rx + " " + (ry + th4) + " M"); | |||
write(w + " 0 rlineto"); | |||
useColor(1, 1, 1); // white | |||
write("stroke"); | |||
break; | |||
case RuleStyle.RIDGE: | |||
write(th2 + " setlinewidth"); | |||
write("newpath"); | |||
write(rx + " " + (ry - th4) + " M"); | |||
write(w + " 0 rlineto"); | |||
useColor(1, 1, 1); // white | |||
write("stroke"); | |||
write("newpath"); | |||
write(rx + " " + (ry + th4) + " M"); | |||
write(w + " 0 rlineto"); | |||
useColor(area.getRed(), area.getGreen(), area.getBlue()); | |||
write("stroke"); | |||
break; | |||
} | |||
write("grestore"); | |||
break; | |||
case LeaderPattern.DOTS: | |||
comment("% --- Leader dots NYI"); | |||
log.error("Leader dots: Not yet implemented"); | |||
break; | |||
case LeaderPattern.USECONTENT: | |||
comment("% --- Leader use-content NYI"); | |||
log.error("Leader use-content: Not yet implemented"); | |||
break; | |||
} | |||
this.currentXPosition += area.getContentWidth(); | |||
write(area.getContentWidth() + " 0 RM"); | |||
} | |||
protected void doFrame(Area area) { | |||
int w, h; | |||
int rx = this.currentAreaContainerXPosition; | |||
w = area.getContentWidth(); | |||
BorderAndPadding bap = area.getBorderAndPadding(); | |||
if (area instanceof BlockArea) | |||
rx += ((BlockArea)area).getStartIndent(); | |||
h = area.getContentHeight(); | |||
int ry = this.currentYPosition; | |||
rx = rx - area.getPaddingLeft(); | |||
ry = ry + area.getPaddingTop(); | |||
w = w + area.getPaddingLeft() + area.getPaddingRight(); | |||
h = h + area.getPaddingTop() + area.getPaddingBottom(); | |||
rx = rx - area.getBorderLeftWidth(); | |||
ry = ry + area.getBorderTopWidth(); | |||
w = w + area.getBorderLeftWidth() + area.getBorderRightWidth(); | |||
h = h + area.getBorderTopWidth() + area.getBorderBottomWidth(); | |||
// Create a textrect with these dimensions. | |||
// The y co-ordinate is measured +ve downwards so subtract page-height | |||
ColorType bg = area.getBackgroundColor(); | |||
if ((bg != null) && (bg.alpha() == 0)) { | |||
write("newpath"); | |||
write(rx + " " + ry + " M"); | |||
write(w + " 0 rlineto"); | |||
write("0 " + (-h) + " rlineto"); | |||
write((-w) + " 0 rlineto"); | |||
write("0 " + h + " rlineto"); | |||
write("closepath"); | |||
useColor(bg); | |||
write("fill"); | |||
} | |||
if (area.getBorderTopWidth() != 0) { | |||
write("newpath"); | |||
write(rx + " " + ry + " M"); | |||
write(w + " 0 rlineto"); | |||
write(area.getBorderTopWidth() + " setlinewidth"); | |||
write("0 setlinecap"); | |||
useColor(bap.getBorderColor(BorderAndPadding.TOP)); | |||
write("stroke"); | |||
} | |||
if (area.getBorderLeftWidth() != 0) { | |||
write("newpath"); | |||
write(rx + " " + ry + " M"); | |||
write("0 " + (-h) + " rlineto"); | |||
write(area.getBorderLeftWidth() + " setlinewidth"); | |||
write("0 setlinecap"); | |||
useColor(bap.getBorderColor(BorderAndPadding.LEFT)); | |||
write("stroke"); | |||
} | |||
if (area.getBorderRightWidth() != 0) { | |||
write("newpath"); | |||
write((rx + w) + " " + ry + " M"); | |||
write("0 " + (-h) + " rlineto"); | |||
write(area.getBorderRightWidth() + " setlinewidth"); | |||
write("0 setlinecap"); | |||
useColor(bap.getBorderColor(BorderAndPadding.RIGHT)); | |||
write("stroke"); | |||
} | |||
if (area.getBorderBottomWidth() != 0) { | |||
write("newpath"); | |||
write(rx + " " + (ry - h) + " M"); | |||
write(w + " 0 rlineto"); | |||
write(area.getBorderBottomWidth() + " setlinewidth"); | |||
write("0 setlinecap"); | |||
useColor(bap.getBorderColor(BorderAndPadding.BOTTOM)); | |||
write("stroke"); | |||
} | |||
} | |||
private void useColor(ColorType col) { | |||
useColor(col.red(), col.green(), col.blue()); | |||
} | |||
@@ -805,8 +295,6 @@ public class PSRenderer extends AbstractRenderer { | |||
} | |||
/** | |||
Default start renderer method. This would | |||
normally be overridden. (mark-fop@inomial.com). | |||
*/ | |||
public void startRenderer(OutputStream outputStream) | |||
throws IOException { | |||
@@ -829,18 +317,12 @@ public class PSRenderer extends AbstractRenderer { | |||
} | |||
/** | |||
Default stop renderer method. This would | |||
normally be overridden. (mark-fop@inomial.com). | |||
*/ | |||
public void stopRenderer(OutputStream outputStream) | |||
public void stopRenderer() | |||
throws IOException { | |||
write("%%Trailer"); | |||
write("%%EOF"); | |||
this.out.flush(); | |||
log.debug("written out PostScript"); | |||
} | |||
public void render(Page page, OutputStream outputStream) { | |||
this.renderPage(page); | |||
} | |||
} |
@@ -82,274 +82,9 @@ public class SVGRenderer extends AbstractRenderer { | |||
protected float currentGreen = 0; | |||
protected float currentBlue = 0; | |||
/** | |||
* options | |||
*/ | |||
protected Hashtable options; | |||
/** | |||
* set up renderer options | |||
*/ | |||
public void setOptions(Hashtable options) { | |||
this.options = options; | |||
} | |||
public SVGRenderer() { | |||
} | |||
/** | |||
* 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 void addLine(int x1, int y1, int x2, int y2, int th, float r, | |||
float g, float b) { | |||
Element line = SVGUtilities.createLine(svgDocument, x1 / 1000f, pageHeight - (y1 / 1000f), x2 / 1000f, pageHeight - (y2 / 1000f)); | |||
line.setAttributeNS(null, "style", "stroke-width:" + (Math.abs(th) / 1000f) | |||
+ ";stroke:rgb(" + ((int)(255 * r)) + "," + ((int)(255 * g)) + "," + ((int)(255 * b)) + ")"); | |||
currentPageG.appendChild(line); | |||
} | |||
/** | |||
* draw a rectangle | |||
* | |||
* @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 r the red component | |||
* @param g the green component | |||
* @param b the blue component | |||
*/ | |||
protected void addRect(int x, int y, int w, int h, float r, float g, | |||
float b) { | |||
Element rect = SVGUtilities.createRect(svgDocument, x / 1000f, pageHeight - (y / 1000f), w / 1000f, h / 1000f); | |||
rect.setAttributeNS(null, "style", "stroke:rgb(" + ((int)(255 * r)) + "," + ((int)(255 * g)) + "," + ((int)(255 * b)) + ")"); | |||
currentPageG.appendChild(rect); | |||
} | |||
/** | |||
* draw a filled rectangle | |||
* | |||
* @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 r the red component of edges | |||
* @param g the green component of edges | |||
* @param b the blue component of edges | |||
* @param fr the red component of the fill | |||
* @param fg the green component of the fill | |||
* @param fb the blue component of the fill | |||
*/ | |||
protected void addRect(int x, int y, int w, int h, float r, float g, | |||
float b, float fr, float fg, float fb) { | |||
Element rect = SVGUtilities.createRect(svgDocument, x / 1000f, pageHeight - (y / 1000f), w / 1000f, h / 1000f); | |||
rect.setAttributeNS(null, "style", "stroke:rgb(" + ((int)(255 * r)) + "," + ((int)(255 * g)) + "," + ((int)(255 * b)) + ");fill:rgb(" + ((int)(255 * fr)) + "," + ((int)(255 * fg)) + "," + ((int)(255 * fb)) + ")"); | |||
currentPageG.appendChild(rect); | |||
} | |||
/** | |||
* draw a filled rectangle in the current color | |||
* | |||
* @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 drawAsOutline true for draw, false for fill | |||
*/ | |||
protected void addRect(int x, int y, int w, int h, | |||
boolean drawAsOutline) { | |||
int startx = (x + 500) / 1000; | |||
int starty = pageHeight - ((y + 500) / 1000); | |||
int endx = (x + w + 500) / 1000; | |||
int endy = pageHeight - ((y + h + 500) / 1000); | |||
if (drawAsOutline) { | |||
Element rect = SVGUtilities.createRect(svgDocument, startx, starty, endx - startx, endy - starty); | |||
rect.setAttributeNS(null, "style", "fill:none"); | |||
currentPageG.appendChild(rect); | |||
} else { | |||
Element rect = SVGUtilities.createRect(svgDocument, startx, starty, endx - startx, starty - endy); | |||
rect.setAttributeNS(null, "style", "stroke:none"); | |||
currentPageG.appendChild(rect); | |||
} | |||
} | |||
protected void addFilledRect(int x, int y, int w, int h, | |||
ColorType col) { | |||
float r = col.red(); | |||
float g = col.green(); | |||
float b = col.blue(); | |||
addRect(x, y, w, h, r, g, b, r, g, b); | |||
} | |||
protected void drawFrame() { | |||
int width = pageWidth; | |||
int height = pageHeight; | |||
Element rect = SVGUtilities.createRect(svgDocument, 0, 0, width, height); | |||
rect.setAttributeNS(null, "style", "fill:none;stroke:black"); | |||
currentPageG.appendChild(rect); | |||
} | |||
public void render(Page page, OutputStream stream) | |||
throws IOException { | |||
pageNumber++; | |||
this.render(page); | |||
} | |||
public void render(Page page) | |||
throws IOException { | |||
idReferences = page.getIDReferences(); | |||
int lastWidth = pageWidth; | |||
int lastHeight = pageHeight; | |||
pageWidth = (int)((float)page.getWidth() / 1000f + .5); | |||
pageHeight = (int)((float)page.getHeight() / 1000f + .5); | |||
if(lastLink != null && currentPageG != null) { | |||
lastLink.setAttributeNS(null, "xlink:href", "#svgView(viewBox(0, "+ (totalHeight) + ", " + pageWidth + ", " + pageHeight + "))"); | |||
currentPageG.appendChild(lastLink); | |||
} | |||
totalHeight += pageHeight; | |||
if(totalWidth < pageWidth) { | |||
totalWidth = pageWidth; | |||
} | |||
currentPageG = SVGUtilities.createG(svgDocument); | |||
currentPageG.setAttributeNS(null, "id", /*title + */"Page-" + pageNumber); | |||
currentPageG.setAttributeNS(null, "style", "font-family:sanserif;font-size:12"); | |||
svgRoot.appendChild(currentPageG); | |||
drawFrame(); | |||
renderPage(page); | |||
currentPageG.setAttributeNS(null, "transform", "translate(0," + (totalHeight - pageHeight) + ")"); | |||
Element lastPageLink = svgDocument.createElementNS(svgNS, "a"); | |||
if(lastLink != null) { | |||
lastPageLink.setAttributeNS(null, "xlink:href", "#svgView(viewBox(0, " + (totalHeight - pageHeight - lastHeight) + ", " + lastWidth + ", " + lastHeight + "))"); | |||
} else { | |||
lastPageLink.setAttributeNS(null, "xlink:href", "#svgView(viewBox(0, " + (totalHeight - pageHeight) + ", " + pageWidth + ", " + pageHeight + "))"); | |||
} | |||
currentPageG.appendChild(lastPageLink); | |||
Element rect = SVGUtilities.createRect(svgDocument, 0, 0, pageWidth / 2, pageHeight); | |||
rect.setAttributeNS(null, "style", "fill:blue;visibility:hidden"); | |||
lastPageLink.appendChild(rect); | |||
lastLink = svgDocument.createElementNS(svgNS, "a"); | |||
rect = SVGUtilities.createRect(svgDocument, pageWidth / 2, 0, pageWidth / 2, pageHeight); | |||
rect.setAttributeNS(null, "style", "fill:blue;visibility:hidden"); | |||
lastLink.appendChild(rect); | |||
/* | |||
* if (page.hasLinks()) { | |||
* .... | |||
* } | |||
*/ | |||
} | |||
public void renderPage(Page page) { | |||
BodyAreaContainer body; | |||
AreaContainer before, after; | |||
body = page.getBody(); | |||
before = page.getBefore(); | |||
after = page.getAfter(); | |||
this.currentFontName = ""; | |||
this.currentFontSize = 0; | |||
renderBodyAreaContainer(body); | |||
if (before != null) { | |||
renderAreaContainer(before); | |||
} | |||
if (after != null) { | |||
renderAreaContainer(after); | |||
} | |||
} | |||
protected void doFrame(org.apache.fop.layout.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, bg.red(), bg.green(), bg.blue(), | |||
bg.red(), bg.green(), bg.blue()); | |||
} | |||
rx = rx - area.getBorderLeftWidth(); | |||
ry = ry + area.getBorderTopWidth(); | |||
w = w + area.getBorderLeftWidth() + area.getBorderRightWidth(); | |||
h = h + area.getBorderTopWidth() + area.getBorderBottomWidth(); | |||
BorderAndPadding bp = area.getBorderAndPadding(); | |||
ColorType borderColor; | |||
if (area.getBorderTopWidth() != 0) { | |||
borderColor = bp.getBorderColor(BorderAndPadding.TOP); | |||
addLine(rx, ry, rx + w, ry, area.getBorderTopWidth(), | |||
borderColor.red(), borderColor.green(), | |||
borderColor.blue()); | |||
} | |||
if (area.getBorderLeftWidth() != 0) { | |||
borderColor = bp.getBorderColor(BorderAndPadding.LEFT); | |||
addLine(rx, ry, rx, ry - h, area.getBorderLeftWidth(), | |||
borderColor.red(), borderColor.green(), | |||
borderColor.blue()); | |||
} | |||
if (area.getBorderRightWidth() != 0) { | |||
borderColor = bp.getBorderColor(BorderAndPadding.RIGHT); | |||
addLine(rx + w, ry, rx + w, ry - h, | |||
area.getBorderRightWidth(), borderColor.red(), | |||
borderColor.green(), | |||
borderColor.blue()); | |||
} | |||
if (area.getBorderBottomWidth() != 0) { | |||
borderColor = bp.getBorderColor(BorderAndPadding.BOTTOM); | |||
addLine(rx, ry - h, rx + w, ry - h, area.getBorderBottomWidth(), | |||
borderColor.red(), borderColor.green(), | |||
borderColor.blue()); | |||
} | |||
} | |||
protected Rectangle2D getBounds(org.apache.fop.layout.Area a) { | |||
return new Rectangle2D.Double(currentAreaContainerXPosition, | |||
currentYPosition, | |||
a.getAllocationWidth(), a.getHeight()); | |||
} | |||
public void setupFontInfo(FontInfo fontInfo) { | |||
// create a temp Image to test font metrics on | |||
BufferedImage fontImage = | |||
@@ -357,266 +92,17 @@ public class SVGRenderer extends AbstractRenderer { | |||
org.apache.fop.render.awt.FontSetup.setup(fontInfo, fontImage.createGraphics()); | |||
} | |||
public void renderDisplaySpace(DisplaySpace space) { | |||
int d = space.getSize(); | |||
this.currentYPosition -= d; | |||
} | |||
public void renderImageArea(ImageArea area) { | |||
int x = currentXPosition + area.getXOffset(); | |||
int y = currentYPosition; | |||
int w = area.getContentWidth(); | |||
int h = area.getHeight(); | |||
this.currentYPosition -= h; | |||
FopImage img = area.getImage(); | |||
if (img == null) { | |||
log.error("Error while loading image : area.getImage() is null"); | |||
addRect(x, y, w, h, true); // use helper function | |||
} else { | |||
if (img instanceof SVGImage) { | |||
try { | |||
SVGDocument svg = ((SVGImage)img).getSVGDocument(); | |||
renderSVGDocument(svg, x / 1000f, pageHeight - y / 1000f); | |||
} catch (FopImageException e) {} | |||
} else { | |||
String urlString = img.getURL(); | |||
try { | |||
URL url = new URL(urlString); | |||
ImageIcon icon = new ImageIcon(url); | |||
Image image = icon.getImage(); | |||
int startx = (x + 500) / 1000; | |||
int starty = pageHeight - ((y + 500) / 1000); | |||
int endx = (x + w + 500) / 1000; | |||
int endy = pageHeight - ((y + h + 500) / 1000); | |||
// reverse start and end y because h is positive | |||
//graphics.drawImage(image, startx, starty, endx - startx, | |||
// starty - endy, null); | |||
} catch (MalformedURLException mue) { | |||
// cannot normally occur because, if URL is wrong, constructing FopImage | |||
// will already have failed earlier on | |||
} | |||
} | |||
} | |||
this.currentXPosition += area.getContentWidth(); | |||
} | |||
public void renderWordArea(WordArea area) { | |||
char ch; | |||
StringBuffer pdf = new StringBuffer(); | |||
String name = area.getFontState().getFontFamily(); | |||
int size = area.getFontState().getFontSize(); | |||
boolean underlined = area.getUnderlined(); | |||
float red = area.getRed(); | |||
float green = area.getGreen(); | |||
float blue = area.getBlue(); | |||
if ((!name.equals(this.currentFontName)) | |||
|| (size != this.currentFontSize)) { | |||
this.currentFontName = name; | |||
this.currentFontSize = size; | |||
} | |||
if ((red != this.currentRed) || (green != this.currentGreen) | |||
|| (blue != this.currentBlue)) { | |||
this.currentRed = red; | |||
this.currentGreen = green; | |||
this.currentBlue = blue; | |||
} | |||
int rx = this.currentXPosition; | |||
int bl = this.currentYPosition; | |||
String s; // = area.getText(); | |||
if (area.getPageNumberID() | |||
!= null) { // this text is a page number, so resolve it | |||
s = idReferences.getPageNumber(area.getPageNumberID()); | |||
if (s == null) { | |||
s = ""; | |||
} | |||
} else { | |||
s = area.getText(); | |||
} | |||
if (saveColor != null) { | |||
if (saveColor.getRed() != red || saveColor.getGreen() != green | |||
|| saveColor.getBlue() != blue) { | |||
saveColor = new Color(red, green, blue); | |||
} | |||
} else { | |||
saveColor = new Color(red, green, blue); | |||
} | |||
Element text = SVGUtilities.createText(svgDocument, rx / 1000f, pageHeight - bl / 1000f, s); | |||
String st = null; | |||
if(!"sans-serif".equals(this.currentFontName)) { | |||
st = "font-family:" + this.currentFontName; | |||
} | |||
if(this.currentFontSize != 12000) { | |||
if(st == null) { | |||
st = ""; | |||
} else { | |||
st += ";"; | |||
} | |||
st += "font-size:" + (this.currentFontSize / 1000f); | |||
} | |||
if(red != 0 || green != 0 || blue != 0) { | |||
if(st == null) { | |||
st = ""; | |||
} else { | |||
st += ";"; | |||
} | |||
st += "fill:rgb(" + ((int)(255 * red)) + "," + ((int)(255 * green)) + "," + ((int)(255 * blue)) + ")"; | |||
} | |||
String fweight = area.getFontState().getFontWeight(); | |||
if(!"normal".equals(fweight)) { | |||
if(st == null) { | |||
st = ""; | |||
} else { | |||
st += ";"; | |||
} | |||
st += "font-weight:" + fweight; | |||
} | |||
String fstyle = area.getFontState().getFontStyle(); | |||
if(!"normal".equals(fstyle)) { | |||
if(st == null) { | |||
st = ""; | |||
} else { | |||
st += ";"; | |||
} | |||
st += "font-style:" + fstyle; | |||
} | |||
if(st != null) { | |||
text.setAttributeNS(null, "style", st); | |||
} | |||
currentPageG.appendChild(text); | |||
this.currentXPosition += area.getContentWidth(); | |||
public void setProducer(String producer) { | |||
} | |||
public void renderInlineSpace(InlineSpace space) { | |||
this.currentXPosition += space.getSize(); | |||
} | |||
public void startRenderer(OutputStream outputStream) | |||
throws IOException {} | |||
/** | |||
* | |||
* @param area area to render | |||
*/ | |||
public void renderLeaderArea(LeaderArea area) { | |||
int rx = this.currentXPosition; | |||
int ry = this.currentYPosition; | |||
int w = area.getLeaderLength(); | |||
int h = area.getHeight(); | |||
int th = area.getRuleThickness(); | |||
int st = area.getRuleStyle(); // not used at the moment | |||
float r = area.getRed(); | |||
float g = area.getGreen(); | |||
float b = area.getBlue(); | |||
//graphics.setColor(new Color(r, g, b)); | |||
addRect(rx, ry, w, th, false); | |||
this.currentXPosition += area.getContentWidth(); | |||
} | |||
public void renderSVGArea(SVGArea area) { | |||
float x = this.currentXPosition / 1000f; | |||
float y = pageHeight - this.currentYPosition / 1000f; | |||
int w = area.getContentWidth(); | |||
int h = area.getHeight(); | |||
Document doc = area.getSVGDocument(); | |||
renderSVGDocument(doc, x, y); | |||
this.currentXPosition += area.getContentWidth(); | |||
} | |||
protected void renderSVGDocument(Document doc, float x, float y) { | |||
SVGSVGElement svg = ((SVGDocument)doc).getRootElement(); | |||
Element view = svgDocument.createElementNS(svgNS, "svg"); | |||
Node newsvg = svgDocument.importNode(svg, true); | |||
//view.setAttributeNS(null, "viewBox", "0 0 "); | |||
view.setAttributeNS(null, "x", "" + x); | |||
view.setAttributeNS(null, "y", "" + y); | |||
// this fixes a problem where the xmlns is repeated sometimes | |||
Element ele = (Element)newsvg; | |||
ele.setAttributeNS(XMLSupport.XMLNS_NAMESPACE_URI, "xmlns", svgNS); | |||
if(ele.hasAttributeNS(null, "xmlns")) { | |||
ele.removeAttributeNS(null, "xmlns"); | |||
} | |||
view.appendChild(newsvg); | |||
currentPageG.appendChild(view); | |||
public void stopRenderer() | |||
throws IOException | |||
{ | |||
} | |||
public void setProducer(String producer) { | |||
// defined in Renderer Interface | |||
} | |||
public static Color colorType2Color(ColorType ct) { | |||
if (ct == null) { | |||
return null; | |||
} | |||
return new Color(ct.red(), ct.green(), ct.blue()); | |||
} | |||
public void renderForeignObjectArea(ForeignObjectArea area) { | |||
area.getObject().render(this); | |||
} | |||
public void startRenderer(OutputStream outputStream) | |||
throws IOException { | |||
DOMImplementation impl = SVGDOMImplementation.getDOMImplementation(); | |||
svgDocument = impl.createDocument(svgNS, "svg", null); | |||
ProcessingInstruction pi = | |||
svgDocument.createProcessingInstruction( | |||
"xml", | |||
" version=\"1.0\" encoding=\"ISO-8859-1\""); | |||
svgRoot = svgDocument.getDocumentElement(); | |||
svgDocument.insertBefore(pi, svgRoot); | |||
} | |||
public void stopRenderer(OutputStream outputStream) | |||
throws IOException { | |||
svgRoot.setAttributeNS(null, "width", "" + totalWidth); | |||
svgRoot.setAttributeNS(null, "height", "" + totalHeight); | |||
//svgRoot.setAttributeNS(null, "viewBox", "0 0 " + pageWidth + " " + pageHeight); | |||
SVGTranscoder svgT = new SVGTranscoder(); | |||
TranscoderInput input = new TranscoderInput(svgDocument); | |||
TranscoderOutput output = new TranscoderOutput(new OutputStreamWriter(outputStream)); | |||
try { | |||
svgT.transcode(input, output); | |||
} catch(TranscoderException e) { | |||
log.error("could not write svg file :" + e.getMessage(), e); | |||
} | |||
outputStream.flush(); | |||
svgDocument = null; | |||
svgRoot = null; | |||
currentPageG = null; | |||
lastLink = null; | |||
totalWidth = 0; | |||
totalHeight = 0; | |||
pageNumber = 0; | |||
} | |||
} |
@@ -12,10 +12,12 @@ import org.apache.fop.svg.*; | |||
import org.apache.fop.render.Renderer; | |||
import org.apache.fop.render.AbstractRenderer; | |||
import org.apache.fop.image.ImageArea; | |||
import org.apache.fop.layout.*; | |||
import org.apache.fop.layout.inline.*; | |||
import org.apache.fop.area.*; | |||
import org.apache.fop.area.inline.*; | |||
import org.apache.fop.pdf.*; | |||
import org.apache.fop.fo.properties.LeaderPattern; | |||
import org.apache.fop.layout.FontInfo; | |||
import org.apache.fop.apps.FOPException; | |||
import org.apache.log.Logger; | |||
@@ -24,20 +26,16 @@ import java.io.IOException; | |||
import java.io.PrintWriter; | |||
import java.io.OutputStream; | |||
import java.util.Enumeration; | |||
import java.util.Hashtable; | |||
import java.util.HashMap; | |||
import java.util.List; | |||
/** | |||
* Renderer that renders areas to XML for debugging purposes. | |||
* | |||
* Modified by Mark Lillywhite mark-fop@inomial.com to use the | |||
* new renderer interface. Not 100% certain that this is correct. | |||
*/ | |||
public class XMLRenderer implements Renderer { | |||
public class XMLRenderer extends AbstractRenderer { | |||
boolean startedSequence = false; | |||
protected Logger log; | |||
public void setLogger(Logger logger) { | |||
log = logger; | |||
public void setProducer(String producer) { | |||
} | |||
/** | |||
@@ -58,37 +56,10 @@ public class XMLRenderer implements Renderer { | |||
/** | |||
* options | |||
*/ | |||
protected Hashtable options; | |||
private boolean consistentOutput = false; | |||
public XMLRenderer() {} | |||
/** | |||
* set up renderer options | |||
*/ | |||
public void setOptions(Hashtable options) { | |||
this.options = options; | |||
Boolean con = (Boolean)options.get("consistentOutput"); | |||
if(con != null) { | |||
consistentOutput = con.booleanValue(); | |||
} | |||
} | |||
/** | |||
* set the document's producer | |||
* | |||
* @param producer string indicating application producing the XML | |||
*/ | |||
public void setProducer(String producer) { | |||
this.producer = producer; | |||
} | |||
public void render(Page page, OutputStream outputStream) | |||
throws IOException { | |||
this.renderPage(page); | |||
} | |||
/** | |||
* write out spaces to make indent | |||
*/ | |||
@@ -153,318 +124,126 @@ public class XMLRenderer implements Renderer { | |||
org.apache.fop.render.pdf.FontSetup.setup(fontInfo); | |||
} | |||
/** | |||
* render an area container to XML | |||
* | |||
* @param area the area container to render | |||
*/ | |||
public void renderAreaContainer(AreaContainer area) { | |||
writeStartTag("<AreaContainer name=\"" + area.getAreaName() + "\">"); | |||
Enumeration e = area.getChildren().elements(); | |||
while (e.hasMoreElements()) { | |||
Box b = (Box)e.nextElement(); | |||
b.render(this); | |||
} | |||
writeEndTag("</AreaContainer>"); | |||
private boolean isCoarseXml() { | |||
return ((Boolean)options.get("fineDetail")).booleanValue(); | |||
} | |||
/** | |||
* render a body area container to XML | |||
* | |||
* @param area the body area container to render | |||
*/ | |||
public void renderBodyAreaContainer(BodyAreaContainer area) { | |||
writeStartTag("<BodyAreaContainer>"); | |||
Enumeration e = area.getChildren().elements(); | |||
while (e.hasMoreElements()) { | |||
Box b = (Box)e.nextElement(); | |||
b.render(this); | |||
} | |||
writeEndTag("</BodyAreaContainer>"); | |||
*/ | |||
public void startRenderer(OutputStream outputStream) | |||
throws IOException { | |||
log.debug("rendering areas to XML"); | |||
this.writer = new PrintWriter(outputStream); | |||
this.writer.write( "<?xml version=\"1.0\"?>\n<!-- produced by " + | |||
this.producer + " -->\n"); | |||
writeStartTag("<areaTree>"); | |||
} | |||
/** | |||
* render a span area to XML | |||
* | |||
* @param area the span area to render | |||
*/ | |||
public void renderSpanArea(SpanArea area) { | |||
writeStartTag("<SpanArea>"); | |||
Enumeration e = area.getChildren().elements(); | |||
while (e.hasMoreElements()) { | |||
Box b = (Box)e.nextElement(); | |||
b.render(this); | |||
} | |||
writeEndTag("</SpanArea>"); | |||
*/ | |||
public void stopRenderer() | |||
throws IOException { | |||
writeEndTag("</pageSequence>"); | |||
writeEndTag("</areaTree>"); | |||
this.writer.flush(); | |||
log.debug("written out XML"); | |||
} | |||
/** | |||
* render a block area to XML | |||
* | |||
* @param area the block area to render | |||
*/ | |||
public void renderBlockArea(BlockArea area) { | |||
StringBuffer baText = new StringBuffer(); | |||
baText.append("<BlockArea start-indent=\"" + area.getStartIndent() | |||
+ "\""); | |||
baText.append(" end-indent=\"" + area.getEndIndent() + "\""); | |||
baText.append("\nis-first=\"" + area.isFirst() + "\""); | |||
baText.append(" is-last=\"" + area.isLast() + "\""); | |||
if (null != area.getGeneratedBy()) | |||
baText.append(" generated-by=\"" | |||
+ area.getGeneratedBy().getName() + "//"); | |||
if(consistentOutput) { | |||
baText.append(area.getGeneratedBy().getClass() + "\""); | |||
} else { | |||
baText.append(area.getGeneratedBy() + "\""); | |||
} | |||
baText.append(">"); | |||
writeStartTag(baText.toString()); | |||
// write out marker info | |||
java.util.Vector markers = area.getMarkers(); | |||
if (!markers.isEmpty()) { | |||
writeStartTag("<Markers>"); | |||
for (int m = 0; m < markers.size(); m++) { | |||
org.apache.fop.fo.flow.Marker marker = | |||
(org.apache.fop.fo.flow.Marker)markers.elementAt(m); | |||
StringBuffer maText = new StringBuffer(); | |||
maText.append("<Marker marker-class-name=\"" | |||
+ marker.getMarkerClassName() + "\""); | |||
maText.append(" RegisteredArea=\"" + marker.getRegistryArea() | |||
+ "\""); | |||
maText.append("/>"); | |||
writeEmptyElementTag(maText.toString()); | |||
} | |||
writeEndTag("</Markers>"); | |||
} | |||
Enumeration e = area.getChildren().elements(); | |||
while (e.hasMoreElements()) { | |||
Box b = (Box)e.nextElement(); | |||
b.render(this); | |||
} | |||
writeEndTag("</BlockArea>"); | |||
public void renderPage(PageViewport page) | |||
throws IOException, FOPException { | |||
writeStartTag("<pageViewport>"); | |||
writeStartTag("<page>"); | |||
super.renderPage(page); | |||
writeEndTag("</page>"); | |||
writeEndTag("</pageViewport>"); | |||
} | |||
public void renderInlineArea(InlineArea area) { | |||
StringBuffer iaText = new StringBuffer(); | |||
iaText.append("<InlineArea"); | |||
iaText.append("\nis-first=\"" + area.isFirst() + "\""); | |||
iaText.append(" is-last=\"" + area.isLast() + "\""); | |||
if (null != area.getGeneratedBy()) | |||
iaText.append(" generated-by=\"" | |||
+ area.getGeneratedBy().getName() + "//" | |||
+ area.getGeneratedBy() + "\""); | |||
iaText.append(">"); | |||
writeStartTag(iaText.toString()); | |||
// write out marker info | |||
java.util.Vector markers = area.getMarkers(); | |||
if (!markers.isEmpty()) { | |||
writeStartTag("<Markers>"); | |||
for (int m = 0; m < markers.size(); m++) { | |||
org.apache.fop.fo.flow.Marker marker = | |||
(org.apache.fop.fo.flow.Marker)markers.elementAt(m); | |||
StringBuffer maText = new StringBuffer(); | |||
maText.append("<Marker marker-class-name=\"" | |||
+ marker.getMarkerClassName() + "\""); | |||
maText.append(" RegisteredArea=\"" + marker.getRegistryArea() | |||
+ "\""); | |||
maText.append("/>"); | |||
writeEmptyElementTag(maText.toString()); | |||
} | |||
writeEndTag("</Markers>"); | |||
} | |||
public void startPageSequence(Title seqTitle) { | |||
if(startedSequence) { | |||
writeEndTag("</pageSequence>"); | |||
} | |||
startedSequence = true; | |||
writeStartTag("<pageSequence>"); | |||
if(seqTitle != null) { | |||
writeStartTag("<title>"); | |||
List children = seqTitle.getInlineAreas(); | |||
Enumeration e = area.getChildren().elements(); | |||
while (e.hasMoreElements()) { | |||
Box b = (Box)e.nextElement(); | |||
b.render(this); | |||
for (int count = 0; count < children.size(); count++) { | |||
InlineArea inline = (InlineArea) children.get(count); | |||
inline.render(this); | |||
} | |||
writeEndTag("</InlineArea>"); | |||
} | |||
/** | |||
* render a display space to XML | |||
* | |||
* @param space the space to render | |||
*/ | |||
public void renderDisplaySpace(DisplaySpace space) { | |||
if (!isCoarseXml()) | |||
writeEmptyElementTag("<DisplaySpace size=\"" + space.getSize() | |||
+ "\"/>"); | |||
writeEndTag("</title>"); | |||
} | |||
} | |||
/** | |||
* render a foreign object area | |||
*/ | |||
public void renderForeignObjectArea(ForeignObjectArea area) { | |||
// if necessary need to scale and align the content | |||
area.getObject().render(this); | |||
} | |||
protected void renderRegionViewport(RegionViewport port) { | |||
if(port != null) { | |||
writeStartTag("<regionViewport>"); | |||
Region region = port.getRegion(); | |||
if (region.getRegionClass() == Region.BEFORE) { | |||
writeStartTag("<regionBefore>"); | |||
renderRegion(region); | |||
writeEndTag("</regionBefore>"); | |||
} else if (region.getRegionClass() == Region.START) { | |||
writeStartTag("<regionStart>"); | |||
renderRegion(region); | |||
writeEndTag("</regionStart>"); | |||
} else if (region.getRegionClass() == Region.BODY) { | |||
writeStartTag("<regionBody>"); | |||
renderBodyRegion((BodyRegion)region); | |||
writeEndTag("</regionBody>"); | |||
} else if (region.getRegionClass() == Region.END) { | |||
writeStartTag("<regionEnd>"); | |||
renderRegion(region); | |||
writeEndTag("</regionEnd>"); | |||
} else if (region.getRegionClass() == Region.AFTER) { | |||
writeStartTag("<regionAfter>"); | |||
renderRegion(region); | |||
writeEndTag("</regionAfter>"); | |||
} | |||
writeEndTag("</regionViewport>"); | |||
} | |||
/** | |||
* render an SVG area to XML | |||
* | |||
* @param area the area to render | |||
*/ | |||
public void renderSVGArea(SVGArea area) { | |||
writeEmptyElementTag("<SVG/>"); | |||
} | |||
/** | |||
* render an image area to XML | |||
* | |||
* @param area the area to render | |||
*/ | |||
public void renderImageArea(ImageArea area) { | |||
writeEmptyElementTag("<ImageArea/>"); | |||
} | |||
} | |||
/** | |||
* render an inline area to XML | |||
* | |||
* @param area the area to render | |||
*/ | |||
public void renderWordArea(WordArea area) { | |||
String fontWeight = area.getFontState().getFontWeight(); | |||
StringBuffer sb = new StringBuffer(); | |||
String s = area.getText(); | |||
int l = s.length(); | |||
for (int i = 0; i < l; i++) { | |||
char ch = s.charAt(i); | |||
if (ch > 127) | |||
sb = sb.append("&#" + (int)ch + ";"); | |||
else | |||
sb = sb.append(ch); | |||
} | |||
if (!isCoarseXml()) { | |||
writeElement("<WordArea font-weight=\"" + fontWeight | |||
+ "\" red=\"" + area.getRed() + "\" green=\"" | |||
+ area.getGreen() + "\" blue=\"" + area.getBlue() | |||
+ "\" width=\"" + area.getContentWidth() + "\">" | |||
+ sb.toString() + "</WordArea>"); | |||
} else { | |||
this.writer.write(sb.toString()); | |||
} | |||
} | |||
protected void renderBeforeFloat(BeforeFloat bf) { | |||
writeStartTag("<beforeFloat>"); | |||
super.renderBeforeFloat(bf); | |||
writeEndTag("</beforeFloat>"); | |||
} | |||
/** | |||
* render an inline space to XML | |||
* | |||
* @param space the space to render | |||
*/ | |||
public void renderInlineSpace(InlineSpace space) { | |||
if (!isCoarseXml()) | |||
writeEmptyElementTag("<InlineSpace size=\"" + space.getSize() | |||
+ "\"/>"); | |||
else | |||
this.writer.write(" "); | |||
} | |||
protected void renderFootnote(Footnote footnote) { | |||
writeStartTag("<footnote>"); | |||
super.renderFootnote(footnote); | |||
writeEndTag("</footnote>"); | |||
} | |||
/** | |||
* render a line area to XML | |||
* | |||
* @param area the area to render | |||
*/ | |||
public void renderLineArea(LineArea area) { | |||
if (!isCoarseXml()) { | |||
String fontWeight = area.getFontState().getFontWeight(); | |||
writeStartTag("<LineArea font-weight=\"" + fontWeight + "\">"); | |||
} | |||
Enumeration e = area.getChildren().elements(); | |||
while (e.hasMoreElements()) { | |||
Box b = (Box)e.nextElement(); | |||
b.render(this); | |||
} | |||
if (!isCoarseXml()) | |||
writeEndTag("</LineArea>"); | |||
else | |||
this.writer.write("\n"); | |||
} | |||
protected void renderMainReference(MainReference mr) { | |||
writeStartTag("<mainReference>"); | |||
super.renderMainReference(mr); | |||
writeEndTag("</mainReference>"); | |||
} | |||
/** | |||
* render a page to XML | |||
* | |||
* @param page the page to render | |||
*/ | |||
public void renderPage(Page page) { | |||
BodyAreaContainer body; | |||
AreaContainer before, after; | |||
writeStartTag("<Page number=\"" + page.getFormattedNumber() + "\">"); | |||
body = page.getBody(); | |||
before = page.getBefore(); | |||
after = page.getAfter(); | |||
if (before != null) { | |||
renderAreaContainer(before); | |||
} | |||
renderBodyAreaContainer(body); | |||
if (after != null) { | |||
renderAreaContainer(after); | |||
} | |||
writeEndTag("</Page>"); | |||
protected void renderBlock(Block block) { | |||
writeStartTag("<block>"); | |||
super.renderBlock(block); | |||
writeEndTag("</block>"); | |||
} | |||
/** | |||
* render a leader area to XML | |||
* | |||
* @param area the area to render | |||
*/ | |||
public void renderLeaderArea(LeaderArea area) { | |||
if (isCoarseXml()) | |||
return; | |||
String leaderPattern = ""; | |||
switch (area.getLeaderPattern()) { | |||
case LeaderPattern.SPACE: | |||
leaderPattern = "space"; | |||
break; | |||
case LeaderPattern.RULE: | |||
leaderPattern = "rule"; | |||
break; | |||
case LeaderPattern.DOTS: | |||
leaderPattern = "dots"; | |||
break; | |||
case LeaderPattern.USECONTENT: | |||
leaderPattern = "use-content"; | |||
break; | |||
} | |||
writeEmptyElementTag("<Leader leader-pattern=\"" + leaderPattern | |||
+ " leader-length=\"" + area.getLeaderLength() | |||
+ "\" rule-thickness=\"" | |||
+ area.getRuleThickness() + "\" rule-style=\"" | |||
+ area.getRuleStyle() + "\" red=\"" | |||
+ area.getRed() + "\" green=\"" | |||
+ area.getGreen() + "\" blue=\"" | |||
+ area.getBlue() + "\"/>"); | |||
protected void renderLineArea(LineArea line) { | |||
writeStartTag("<lineArea>"); | |||
super.renderLineArea(line); | |||
writeEndTag("</lineArea>"); | |||
} | |||
private boolean isCoarseXml() { | |||
return ((Boolean)options.get("fineDetail")).booleanValue(); | |||
} | |||
public void renderCharacter(org.apache.fop.area.inline.Character ch) { | |||
writeElement("<char>" + ch.getChar() + "</char>"); | |||
} | |||
/** | |||
Default start renderer method. This would | |||
normally be overridden. (mark-fop@inomial.com). | |||
*/ | |||
public void startRenderer(OutputStream outputStream) | |||
throws IOException { | |||
log.debug("rendering areas to XML"); | |||
this.writer = new PrintWriter(outputStream); | |||
this.writer.write( "<?xml version=\"1.0\"?>\n<!-- produced by " + | |||
this.producer + " -->\n"); | |||
writeStartTag("<AreaTree>"); | |||
public void renderInlineSpace(Space space) { | |||
writeElement("<space width=\"" + space.getWidth() + "\"/>"); | |||
} | |||
/** | |||
Default stop renderer method. This would | |||
normally be overridden. (mark-fop@inomial.com). | |||
*/ | |||
public void stopRenderer(OutputStream outputStream) | |||
throws IOException { | |||
writeEndTag("</AreaTree>"); | |||
this.writer.flush(); | |||
log.debug("written out XML"); | |||
} | |||
} |
@@ -49,13 +49,4 @@ public class SVGArea extends Area { | |||
return contentRectangleWidth; | |||
} | |||
/** | |||
* render the SVG. | |||
* | |||
* @param renderer the Renderer to use | |||
*/ | |||
public void render(Renderer renderer) { | |||
renderer.renderSVGArea(this); | |||
} | |||
} |
@@ -0,0 +1,356 @@ | |||
/* | |||
* $Id$ | |||
* Copyright (C) 2001 The Apache Software Foundation. All rights reserved. | |||
* For details on use and redistribution please refer to the | |||
* LICENSE file included with these sources. | |||
*/ | |||
package org.apache.fop.tools; | |||
import org.apache.fop.apps.*; | |||
import org.apache.fop.configuration.*; | |||
import org.apache.fop.area.*; | |||
import org.apache.fop.area.inline.*; | |||
import org.apache.fop.area.inline.Character; | |||
import org.apache.fop.render.*; | |||
import org.apache.fop.render.pdf.*; | |||
import org.apache.fop.render.svg.*; | |||
import org.apache.fop.render.xml.*; | |||
import org.apache.log.*; | |||
import org.apache.log.format.*; | |||
import org.apache.log.output.io.*; | |||
import org.apache.log.output.*; | |||
import java.io.*; | |||
import java.util.*; | |||
import org.w3c.dom.*; | |||
/** | |||
* Area tree tester. | |||
* The purpose of this class is to create and render an area tree | |||
* for the purpose of testing the area tree and rendering. | |||
* This covers the set of possible properties that can be set | |||
* on the area tree for rendering. | |||
* Tests: different renderers, saving and loading pages with serialization | |||
* out of order rendering | |||
*/ | |||
public class AreaTreeBuilder { | |||
private Logger log; | |||
String baseName = "temp"; | |||
/** | |||
*/ | |||
public static void main(String[] args) { | |||
AreaTreeBuilder atb = new AreaTreeBuilder(); | |||
atb.runTests(); | |||
} | |||
public AreaTreeBuilder() { | |||
setupLogging(); | |||
} | |||
private void setupLogging() { | |||
Hierarchy hierarchy = Hierarchy.getDefaultHierarchy(); | |||
PatternFormatter formatter = new PatternFormatter("[%{priority}]: %{message}\n%{throwable}"); | |||
LogTarget target = null; | |||
target = new StreamTarget(System.out, formatter); | |||
hierarchy.setDefaultLogTarget(target); | |||
log = hierarchy.getLoggerFor("test"); | |||
log.setPriority(Priority.DEBUG); | |||
} | |||
/** | |||
* | |||
*/ | |||
protected void runTests() { | |||
log.debug("Starting tests"); | |||
runTest(); | |||
log.debug("Finished"); | |||
} | |||
/** | |||
*/ | |||
protected void runTest() { | |||
AreaTree.StorePagesModel sm = AreaTree.createStorePagesModel(); | |||
TreeLoader tl = new TreeLoader(); | |||
tl.setTreeModel(sm); | |||
try { | |||
InputStream is = | |||
new BufferedInputStream(new FileInputStream("doc.xml")); | |||
tl.buildAreaTree(is); | |||
renderAreaTree(sm); | |||
} catch (IOException e) { | |||
log.error("error reading file" + e.getMessage(), e); | |||
} | |||
} | |||
protected void renderAreaTree(AreaTree.StorePagesModel sm) { | |||
try { | |||
OutputStream os = new BufferedOutputStream( | |||
new FileOutputStream(baseName + ".xml")); | |||
Renderer rend = new XMLRenderer(); | |||
//Renderer rend = new PDFRenderer(); | |||
rend.setLogger(log); | |||
rend.startRenderer(os); | |||
int count = 0; | |||
int seqc = sm.getPageSequenceCount(); | |||
while (count < seqc) { | |||
Title title = sm.getTitle(count); | |||
rend.startPageSequence(title); | |||
int pagec = sm.getPageCount(count); | |||
int c = 0; | |||
while (c < pagec) { | |||
PageViewport page = sm.getPage(count, c); | |||
c++; | |||
rend.renderPage(page); | |||
} | |||
count++; | |||
} | |||
rend.stopRenderer(); | |||
os.close(); | |||
} catch (Exception e) { | |||
log.error("error rendering output", e); | |||
} | |||
} | |||
} | |||
// this loads an area tree from an xml file | |||
// the xml format is the same as the xml renderer output | |||
class TreeLoader { | |||
AreaTree areaTree; | |||
AreaTree.AreaTreeModel model; | |||
TreeLoader() { | |||
} | |||
public void setTreeModel(AreaTree.AreaTreeModel mo) { | |||
model = mo; | |||
} | |||
public void buildAreaTree(InputStream is) { | |||
Document doc = null; | |||
try { | |||
doc = javax.xml.parsers.DocumentBuilderFactory.newInstance(). | |||
newDocumentBuilder().parse(is); | |||
} catch (Exception e) { | |||
e.printStackTrace(); | |||
} | |||
Element root = null; | |||
root = doc.getDocumentElement(); | |||
areaTree = new AreaTree(); | |||
areaTree.setTreeModel(model); | |||
readAreaTree(root); | |||
} | |||
public void readAreaTree(Element root) { | |||
NodeList childs = root.getChildNodes(); | |||
for (int i = 0; i < childs.getLength(); i++) { | |||
Node obj = childs.item(i); | |||
if (obj.getNodeName().equals("pageSequence")) { | |||
readPageSequence((Element) obj); | |||
} | |||
} | |||
} | |||
public void readPageSequence(Element root) { | |||
Title title = null; | |||
boolean started = false; | |||
NodeList childs = root.getChildNodes(); | |||
for (int i = 0; i < childs.getLength(); i++) { | |||
Node obj = childs.item(i); | |||
if (obj.getNodeName().equals("title")) { | |||
if (started) { | |||
// problem | |||
} else { | |||
title = readTitle((Element) obj); | |||
model.startPageSequence(title); | |||
started = true; | |||
} | |||
} else if (obj.getNodeName().equals("pageViewport")) { | |||
if (!started) { | |||
model.startPageSequence(null); | |||
started = true; | |||
} | |||
PageViewport viewport = readPageViewport((Element) obj); | |||
areaTree.addPage(viewport); | |||
} | |||
} | |||
} | |||
public Title readTitle(Element root) { | |||
Title title = new Title(); | |||
List childs = getInlineAreas(root); | |||
for (int i = 0; i < childs.size(); i++) { | |||
InlineArea obj = (InlineArea) childs.get(i); | |||
title.addInlineArea(obj); | |||
} | |||
return title; | |||
} | |||
public PageViewport readPageViewport(Element root) { | |||
String bounds = root.getAttribute("bounds"); | |||
PageViewport viewport = null; | |||
NodeList childs = root.getChildNodes(); | |||
for (int i = 0; i < childs.getLength(); i++) { | |||
Node obj = childs.item(i); | |||
if (obj.getNodeName().equals("page")) { | |||
Page page = readPage((Element) obj); | |||
viewport = new PageViewport(page); | |||
} | |||
} | |||
return viewport; | |||
} | |||
public Page readPage(Element root) { | |||
String bounds = root.getAttribute("bounds"); | |||
Page page = new Page(); | |||
NodeList childs = root.getChildNodes(); | |||
for (int i = 0; i < childs.getLength(); i++) { | |||
Node obj = childs.item(i); | |||
if (obj.getNodeName().equals("regionViewport")) { | |||
readRegionViewport(page, (Element) obj); | |||
} | |||
} | |||
return page; | |||
} | |||
public RegionViewport readRegionViewport(Page page, Element root) { | |||
RegionViewport reg = new RegionViewport(); | |||
NodeList childs = root.getChildNodes(); | |||
for (int i = 0; i < childs.getLength(); i++) { | |||
Node obj = childs.item(i); | |||
if (obj.getNodeName().equals("regionBefore")) { | |||
reg.setRegion(readRegion((Element) obj, Region.BEFORE)); | |||
page.setRegion(Region.BEFORE, reg); | |||
} else if (obj.getNodeName().equals("regionStart")) { | |||
reg.setRegion(readRegion((Element) obj, Region.START)); | |||
page.setRegion(Region.START, reg); | |||
} else if (obj.getNodeName().equals("regionBody")) { | |||
reg.setRegion(readRegion((Element) obj, Region.BODY)); | |||
page.setRegion(Region.BODY, reg); | |||
} else if (obj.getNodeName().equals("regionEnd")) { | |||
reg.setRegion(readRegion((Element) obj, Region.END)); | |||
page.setRegion(Region.END, reg); | |||
} else if (obj.getNodeName().equals("regionAfter")) { | |||
reg.setRegion(readRegion((Element) obj, Region.AFTER)); | |||
page.setRegion(Region.AFTER, reg); | |||
} | |||
} | |||
return reg; | |||
} | |||
public Region readRegion(Element root, int type) { | |||
Region reg; | |||
if (type == Region.BODY) { | |||
reg = new BodyRegion(); | |||
} else { | |||
reg = new Region(type); | |||
} | |||
List blocks = getBlocks(root); | |||
for (int i = 0; i < blocks.size(); i++) { | |||
Block obj = (Block) blocks.get(i); | |||
reg.addBlock(obj); | |||
} | |||
return reg; | |||
} | |||
List getBlocks(Element root) { | |||
ArrayList list = new ArrayList(); | |||
NodeList childs = root.getChildNodes(); | |||
for (int i = 0; i < childs.getLength(); i++) { | |||
Node obj = childs.item(i); | |||
if (obj.getNodeName().equals("block")) { | |||
Block block = new Block(); | |||
addBlockChildren(block, (Element) obj); | |||
list.add(block); | |||
} | |||
} | |||
return list; | |||
} | |||
protected void addBlockChildren(Block block, Element root) { | |||
NodeList childs = root.getChildNodes(); | |||
int type = -1; | |||
for (int i = 0; i < childs.getLength(); i++) { | |||
Node obj = childs.item(i); | |||
if (obj.getNodeName().equals("block")) { | |||
if (type == 2) { | |||
// error | |||
} | |||
Block b = new Block(); | |||
addBlockChildren(b, (Element) obj); | |||
block.addBlock(b); | |||
type = 1; | |||
} else if (obj.getNodeName().equals("lineArea")) { | |||
if (type == 1) { | |||
// error | |||
} | |||
LineArea line = new LineArea(); | |||
List inlines = getInlineAreas((Element)obj); | |||
for (int j = 0; j < inlines.size(); j++) { | |||
InlineArea inline = (InlineArea) inlines.get(j); | |||
line.addInlineArea(inline); | |||
} | |||
block.addLineArea(line); | |||
type = 2; | |||
} | |||
} | |||
} | |||
// children of element are inline areas | |||
List getInlineAreas(Element root) { | |||
ArrayList list = new ArrayList(); | |||
NodeList childs = root.getChildNodes(); | |||
for (int i = 0; i < childs.getLength(); i++) { | |||
Node obj = childs.item(i); | |||
if (obj.getNodeName().equals("char")) { | |||
Character ch = | |||
new Character(getString((Element) obj).charAt(0)); | |||
list.add(ch); | |||
} else if (obj.getNodeName().equals("space")) { | |||
Space space = new Space(); | |||
String width = ((Element) obj).getAttribute("width"); | |||
int w = Integer.parseInt(width); | |||
space.setWidth(w); | |||
list.add(space); | |||
} else if (obj.getNodeName().equals("container")) { | |||
} else if (obj.getNodeName().equals("viewport")) { | |||
} else if (obj.getNodeName().equals("leader")) { | |||
} else { | |||
} | |||
} | |||
return list; | |||
} | |||
public String getString(Element ele) { | |||
String str = ""; | |||
NodeList childs = ele.getChildNodes(); | |||
if (childs.getLength() == 0) { | |||
return null; | |||
} | |||
for (int i = 0; i < childs.getLength(); i++) { | |||
Node obj = childs.item(i); | |||
str = str + obj.getNodeValue(); | |||
} | |||
return str; | |||
} | |||
} | |||
@@ -246,7 +246,7 @@ public class TestConverter { | |||
driver.setRenderer(Driver.RENDER_XML); | |||
} | |||
Hashtable rendererOptions = new Hashtable(); | |||
HashMap rendererOptions = new HashMap(); | |||
rendererOptions.put("fineDetail", new Boolean(false)); | |||
rendererOptions.put("consistentOutput", new Boolean(true)); | |||
driver.getRenderer().setOptions(rendererOptions); |
@@ -227,7 +227,7 @@ class FOPTaskStarter extends Starter { | |||
} else if (format.equalsIgnoreCase("application/vnd.mif") || | |||
format.equalsIgnoreCase("mif")) { | |||
return Driver.RENDER_MIF; | |||
} else if (format.equalsIgnoreCase("application/vnd.gp-PCL") || | |||
} else if (format.equalsIgnoreCase("application/vnd.hp-PCL") || | |||
format.equalsIgnoreCase("pcl")) { | |||
return Driver.RENDER_PCL; | |||
} else if (format.equalsIgnoreCase("text/plain") || | |||
@@ -368,7 +368,7 @@ class FOPTaskStarter extends Starter { | |||
driver.setLogger(log); | |||
driver.setRenderer(renderer); | |||
if (renderer == Driver.RENDER_XML) { | |||
Hashtable rendererOptions = new Hashtable(); | |||
HashMap rendererOptions = new HashMap(); | |||
rendererOptions.put("fineDetail", new Boolean(true)); | |||
driver.getRenderer().setOptions(rendererOptions); | |||
} |
@@ -532,7 +532,7 @@ public class PreviewDialog extends JFrame implements ProgressListener, | |||
BufferedImage pageImage = null; | |||
Graphics graphics = null; | |||
renderer.render(currentPage); | |||
//renderer.render(currentPage); | |||
pageImage = renderer.getLastRenderedPage(); | |||
if (pageImage == null) | |||
return; |