Browse Source

new area tree and rendering stuff


git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@194519 13f79535-47bb-0310-9956-ffa450edef68
pull/30/head
Keiron Liddle 22 years ago
parent
commit
3845c31d0e
65 changed files with 1730 additions and 6005 deletions
  1. 1
    1
      src/org/apache/fop/apps/AWTStarter.java
  2. 3
    3
      src/org/apache/fop/apps/CommandLineOptions.java
  3. 4
    9
      src/org/apache/fop/apps/PrintStarter.java
  4. 6
    6
      src/org/apache/fop/apps/StreamRenderer.java
  5. 26
    0
      src/org/apache/fop/area/Area.java
  6. 98
    0
      src/org/apache/fop/area/AreaTree.java
  7. 39
    0
      src/org/apache/fop/area/BeforeFloat.java
  8. 82
    0
      src/org/apache/fop/area/Block.java
  9. 30
    0
      src/org/apache/fop/area/BodyRegion.java
  10. 25
    0
      src/org/apache/fop/area/Flow.java
  11. 33
    0
      src/org/apache/fop/area/Footnote.java
  12. 48
    0
      src/org/apache/fop/area/LineArea.java
  13. 30
    0
      src/org/apache/fop/area/MainReference.java
  14. 47
    0
      src/org/apache/fop/area/Page.java
  15. 31
    0
      src/org/apache/fop/area/PageViewport.java
  16. 40
    0
      src/org/apache/fop/area/Region.java
  17. 27
    0
      src/org/apache/fop/area/RegionViewport.java
  18. 29
    0
      src/org/apache/fop/area/Span.java
  19. 11
    0
      src/org/apache/fop/area/Title.java
  20. 15
    0
      src/org/apache/fop/area/inline/Anchor.java
  21. 28
    0
      src/org/apache/fop/area/inline/Character.java
  22. 28
    0
      src/org/apache/fop/area/inline/Container.java
  23. 21
    0
      src/org/apache/fop/area/inline/ForeignObject.java
  24. 17
    0
      src/org/apache/fop/area/inline/Image.java
  25. 33
    0
      src/org/apache/fop/area/inline/InlineArea.java
  26. 19
    0
      src/org/apache/fop/area/inline/Leader.java
  27. 17
    0
      src/org/apache/fop/area/inline/Space.java
  28. 17
    0
      src/org/apache/fop/area/inline/Stretch.java
  29. 20
    0
      src/org/apache/fop/area/inline/Unresolved.java
  30. 16
    0
      src/org/apache/fop/area/inline/UnresolvedPageNumber.java
  31. 22
    0
      src/org/apache/fop/area/inline/Viewport.java
  32. 15
    0
      src/org/apache/fop/area/inline/Word.java
  33. 37
    0
      src/org/apache/fop/fo/FOUserAgent.java
  34. 0
    4
      src/org/apache/fop/image/ImageArea.java
  35. 0
    4
      src/org/apache/fop/layout/AreaContainer.java
  36. 0
    4
      src/org/apache/fop/layout/BlockArea.java
  37. 0
    4
      src/org/apache/fop/layout/BodyAreaContainer.java
  38. 0
    1
      src/org/apache/fop/layout/Box.java
  39. 0
    4
      src/org/apache/fop/layout/ColumnArea.java
  40. 0
    4
      src/org/apache/fop/layout/DisplaySpace.java
  41. 0
    4
      src/org/apache/fop/layout/LineArea.java
  42. 0
    4
      src/org/apache/fop/layout/Page.java
  43. 0
    4
      src/org/apache/fop/layout/SpanArea.java
  44. 0
    5
      src/org/apache/fop/layout/inline/ForeignObjectArea.java
  45. 0
    4
      src/org/apache/fop/layout/inline/InlineSpace.java
  46. 0
    4
      src/org/apache/fop/layout/inline/LeaderArea.java
  47. 0
    4
      src/org/apache/fop/layout/inline/WordArea.java
  48. 90
    0
      src/org/apache/fop/pdf/PDFState.java
  49. 175
    176
      src/org/apache/fop/render/AbstractRenderer.java
  50. 6
    397
      src/org/apache/fop/render/PrintRenderer.java
  51. 38
    77
      src/org/apache/fop/render/Renderer.java
  52. 23
    746
      src/org/apache/fop/render/awt/AWTRenderer.java
  53. 3
    277
      src/org/apache/fop/render/mif/MIFRenderer.java
  54. 1
    573
      src/org/apache/fop/render/pcl/PCLRenderer.java
  55. 7
    735
      src/org/apache/fop/render/pdf/PDFRenderer.java
  56. 1
    1
      src/org/apache/fop/render/ps/PSGraphics2D.java
  57. 2
    520
      src/org/apache/fop/render/ps/PSRenderer.java
  58. 6
    520
      src/org/apache/fop/render/svg/SVGRenderer.java
  59. 0
    1573
      src/org/apache/fop/render/txt/TXTRenderer.java
  60. 103
    324
      src/org/apache/fop/render/xml/XMLRenderer.java
  61. 0
    9
      src/org/apache/fop/svg/SVGArea.java
  62. 356
    0
      src/org/apache/fop/tools/AreaTreeBuilder.java
  63. 1
    1
      src/org/apache/fop/tools/TestConverter.java
  64. 2
    2
      src/org/apache/fop/tools/anttasks/Fop.java
  65. 1
    1
      src/org/apache/fop/viewer/PreviewDialog.java

+ 1
- 1
src/org/apache/fop/apps/AWTStarter.java View File

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


+ 3
- 3
src/org/apache/fop/apps/CommandLineOptions.java View File

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


+ 4
- 9
src/org/apache/fop/apps/PrintStarter.java View File

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




+ 6
- 6
src/org/apache/fop/apps/StreamRenderer.java View File

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

+ 26
- 0
src/org/apache/fop/area/Area.java View File

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

}

+ 98
- 0
src/org/apache/fop/area/AreaTree.java View File

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

+ 39
- 0
src/org/apache/fop/area/BeforeFloat.java View File

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

+ 82
- 0
src/org/apache/fop/area/Block.java View File

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

+ 30
- 0
src/org/apache/fop/area/BodyRegion.java View File

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

+ 25
- 0
src/org/apache/fop/area/Flow.java View File

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

}

+ 33
- 0
src/org/apache/fop/area/Footnote.java View File

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

+ 48
- 0
src/org/apache/fop/area/LineArea.java View File

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

+ 30
- 0
src/org/apache/fop/area/MainReference.java View File

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

+ 47
- 0
src/org/apache/fop/area/Page.java View File

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

}

+ 31
- 0
src/org/apache/fop/area/PageViewport.java View File

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

+ 40
- 0
src/org/apache/fop/area/Region.java View File

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

}

+ 27
- 0
src/org/apache/fop/area/RegionViewport.java View File

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

}

+ 29
- 0
src/org/apache/fop/area/Span.java View File

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

+ 11
- 0
src/org/apache/fop/area/Title.java View File

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

+ 15
- 0
src/org/apache/fop/area/inline/Anchor.java View File

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

}

+ 28
- 0
src/org/apache/fop/area/inline/Character.java View File

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

}

+ 28
- 0
src/org/apache/fop/area/inline/Container.java View File

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

}

+ 21
- 0
src/org/apache/fop/area/inline/ForeignObject.java View File

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

}

+ 17
- 0
src/org/apache/fop/area/inline/Image.java View File

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

}

+ 33
- 0
src/org/apache/fop/area/inline/InlineArea.java View File

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

+ 19
- 0
src/org/apache/fop/area/inline/Leader.java View File

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

}

+ 17
- 0
src/org/apache/fop/area/inline/Space.java View File

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

+ 17
- 0
src/org/apache/fop/area/inline/Stretch.java View File

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

}

+ 20
- 0
src/org/apache/fop/area/inline/Unresolved.java View File

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

}
}

+ 16
- 0
src/org/apache/fop/area/inline/UnresolvedPageNumber.java View File

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

}

+ 22
- 0
src/org/apache/fop/area/inline/Viewport.java View File

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

}

+ 15
- 0
src/org/apache/fop/area/inline/Word.java View File

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

}

+ 37
- 0
src/org/apache/fop/fo/FOUserAgent.java View File

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


+ 0
- 4
src/org/apache/fop/image/ImageArea.java View File

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

+ 0
- 4
src/org/apache/fop/layout/AreaContainer.java View File

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

+ 0
- 4
src/org/apache/fop/layout/BlockArea.java View File

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

+ 0
- 4
src/org/apache/fop/layout/BodyAreaContainer.java View File

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

+ 0
- 1
src/org/apache/fop/layout/Box.java View File

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

+ 0
- 4
src/org/apache/fop/layout/ColumnArea.java View File

@@ -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() {}

+ 0
- 4
src/org/apache/fop/layout/DisplaySpace.java View File

@@ -20,8 +20,4 @@ public class DisplaySpace extends Space {
return size;
}

public void render(Renderer renderer) {
renderer.renderDisplaySpace(this);
}

}

+ 0
- 4
src/org/apache/fop/layout/LineArea.java View File

@@ -158,10 +158,6 @@ public class LineArea extends Area {
}
}

public void render(Renderer renderer) {
renderer.renderLineArea(this);
}

public int addPageNumberCitation(String refid, LinkSet ls) {

/*

+ 0
- 4
src/org/apache/fop/layout/Page.java View File

@@ -124,10 +124,6 @@ public class Page {
area.setPage(this);
}

public void render(Renderer renderer) {
renderer.renderPage(this);
}

public AreaContainer getAfter() {
return this.after;
}

+ 0
- 4
src/org/apache/fop/layout/SpanArea.java View File

@@ -49,10 +49,6 @@ public class SpanArea extends AreaContainer {
}
}

public void render(Renderer renderer) {
renderer.renderSpanArea(this);
}

public void end() {}

public void start() {}

+ 0
- 5
src/org/apache/fop/layout/inline/ForeignObjectArea.java View File

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

+ 0
- 4
src/org/apache/fop/layout/inline/InlineSpace.java View File

@@ -87,8 +87,4 @@ public class InlineSpace extends Space {
return eatable;
}

public void render(Renderer renderer) {
renderer.renderInlineSpace(this);
}

}

+ 0
- 4
src/org/apache/fop/layout/inline/LeaderArea.java View File

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

+ 0
- 4
src/org/apache/fop/layout/inline/WordArea.java View File

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

+ 90
- 0
src/org/apache/fop/pdf/PDFState.java View File

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

}


+ 175
- 176
src/org/apache/fop/render/AbstractRenderer.java View File

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

+ 6
- 397
src/org/apache/fop/render/PrintRenderer.java View File

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

}

+ 38
- 77
src/org/apache/fop/render/Renderer.java View File

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


+ 23
- 746
src/org/apache/fop/render/awt/AWTRenderer.java View File

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

}

+ 3
- 277
src/org/apache/fop/render/mif/MIFRenderer.java View File

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


+ 1
- 573
src/org/apache/fop/render/pcl/PCLRenderer.java View File

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

}

+ 7
- 735
src/org/apache/fop/render/pdf/PDFRenderer.java View File

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

}

+ 1
- 1
src/org/apache/fop/render/ps/PSGraphics2D.java View File

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

+ 2
- 520
src/org/apache/fop/render/ps/PSRenderer.java View File

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

+ 6
- 520
src/org/apache/fop/render/svg/SVGRenderer.java View File

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

}

+ 0
- 1573
src/org/apache/fop/render/txt/TXTRenderer.java
File diff suppressed because it is too large
View File


+ 103
- 324
src/org/apache/fop/render/xml/XMLRenderer.java View File

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

+ 0
- 9
src/org/apache/fop/svg/SVGArea.java View File

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

}

+ 356
- 0
src/org/apache/fop/tools/AreaTreeBuilder.java View File

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


}


+ 1
- 1
src/org/apache/fop/tools/TestConverter.java View File

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

+ 2
- 2
src/org/apache/fop/tools/anttasks/Fop.java View File

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

+ 1
- 1
src/org/apache/fop/viewer/PreviewDialog.java View File

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

Loading…
Cancel
Save