aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKeiron Liddle <keiron@apache.org>2002-07-04 14:08:20 +0000
committerKeiron Liddle <keiron@apache.org>2002-07-04 14:08:20 +0000
commit072a9d2808472eec30aa1c272ee4cb50e596a3c9 (patch)
treef82cc18789323e776b399f063b0c0ec85301bb28
parent15e5fd84a05a9ebd8f26096bcbe2bc9e36fb8345 (diff)
downloadxmlgraphics-fop-072a9d2808472eec30aa1c272ee4cb50e596a3c9.tar.gz
xmlgraphics-fop-072a9d2808472eec30aa1c272ee4cb50e596a3c9.zip
improved gstate usage
now get get image if in pdf without using cache implemented some image parameters: size,clipping... git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@194961 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--src/org/apache/fop/area/inline/Viewport.java16
-rw-r--r--src/org/apache/fop/fo/flow/ExternalGraphic.java171
-rw-r--r--src/org/apache/fop/pdf/PDFDocument.java52
-rw-r--r--src/org/apache/fop/pdf/PDFGState.java76
-rw-r--r--src/org/apache/fop/pdf/PDFResources.java20
-rw-r--r--src/org/apache/fop/pdf/PDFState.java37
-rw-r--r--src/org/apache/fop/render/AbstractRenderer.java9
-rw-r--r--src/org/apache/fop/render/pdf/FopPDFImage.java6
-rw-r--r--src/org/apache/fop/render/pdf/PDFRenderer.java75
-rw-r--r--src/org/apache/fop/svg/PDFGraphics2D.java89
-rw-r--r--src/org/apache/fop/svg/PDFTextPainter.java5
11 files changed, 416 insertions, 140 deletions
diff --git a/src/org/apache/fop/area/inline/Viewport.java b/src/org/apache/fop/area/inline/Viewport.java
index 5e1ce23d0..6f48d7d22 100644
--- a/src/org/apache/fop/area/inline/Viewport.java
+++ b/src/org/apache/fop/area/inline/Viewport.java
@@ -25,6 +25,22 @@ public class Viewport extends InlineArea {
content = child;
}
+ public void setClip(boolean c) {
+ clip = c;
+ }
+
+ public boolean getClip() {
+ return clip;
+ }
+
+ public void setContentPosition(Rectangle2D cp) {
+ contentPosition = cp;
+ }
+
+ public Rectangle2D getContentPosition() {
+ return contentPosition;
+ }
+
public Area getContent() {
return content;
}
diff --git a/src/org/apache/fop/fo/flow/ExternalGraphic.java b/src/org/apache/fop/fo/flow/ExternalGraphic.java
index 7ba5e05d6..37f896677 100644
--- a/src/org/apache/fop/fo/flow/ExternalGraphic.java
+++ b/src/org/apache/fop/fo/flow/ExternalGraphic.java
@@ -19,11 +19,13 @@ import org.apache.fop.layoutmgr.LeafNodeLayoutManager;
import org.apache.fop.layoutmgr.LayoutInfo;
import org.apache.fop.area.inline.Image;
import org.apache.fop.area.inline.Viewport;
+import org.apache.fop.datatypes.*;
// Java
import java.net.URL;
import java.net.MalformedURLException;
import java.util.List;
+import java.awt.geom.Rectangle2D;
public class ExternalGraphic extends FObj {
String url;
@@ -34,9 +36,10 @@ public class ExternalGraphic extends FObj {
int endIndent;
int spaceBefore;
int spaceAfter;
- String src;
- int height;
- int width;
+ int viewWidth = -1;
+ int viewHeight = -1;
+ boolean clip = false;
+ Rectangle2D placement = null;
public ExternalGraphic(FONode parent) {
super(parent);
@@ -53,23 +56,12 @@ public class ExternalGraphic extends FObj {
if(url == null) {
return null;
}
- url = ImageFactory.getURL(url);
- // if we need to load this image to get its size
- ImageFactory fact = ImageFactory.getInstance();
- FopImage fopimage = fact.getImage(url, userAgent);
- if(fopimage == null) {
- // error
- return null;
- }
- // load dimensions
- if(!fopimage.load(FopImage.DIMENSIONS, userAgent)) {
- // error
- return null;
- }
Image imArea = new Image(url);
Viewport vp = new Viewport(imArea);
- vp.setWidth((int)fopimage.getWidth() * 1000);
- vp.setHeight((int)fopimage.getHeight() * 1000);
+ vp.setWidth(viewWidth);
+ vp.setHeight(viewHeight);
+ vp.setClip(clip);
+ vp.setContentPosition(placement);
vp.setOffset(0);
vp.info = new LayoutInfo();
vp.info.alignment = properties.get("vertical-align").getEnum();
@@ -79,6 +71,138 @@ public class ExternalGraphic extends FObj {
}
public void setup() {
+ url = this.properties.get("src").getString();
+ if(url == null) {
+ return;
+ }
+ url = ImageFactory.getURL(url);
+
+ // assume lr-tb for now
+ Length ipd = properties.get("inline-progression-dimension.optimum").getLength();
+ if(!ipd.isAuto()) {
+ viewWidth = ipd.mvalue();
+ } else {
+ ipd = properties.get("width").getLength();
+ if(!ipd.isAuto()) {
+ viewWidth = ipd.mvalue();
+ }
+ }
+ Length bpd = properties.get("block-progression-dimension.optimum").getLength();
+ if(!bpd.isAuto()) {
+ viewHeight = bpd.mvalue();
+ } else {
+ bpd = properties.get("height").getLength();
+ if(!bpd.isAuto()) {
+ viewHeight = bpd.mvalue();
+ }
+ }
+
+ // if we need to load this image to get its size
+ FopImage fopimage = null;
+
+ int cwidth = -1;
+ int cheight = -1;
+ Length ch = properties.get("content-height").getLength();
+ if(!ch.isAuto()) {
+ /*if(ch.scaleToFit()) {
+ if(viewHeight != -1) {
+ cheight = viewHeight;
+ }
+ } else {*/
+ cheight = ch.mvalue();
+ }
+ Length cw = properties.get("content-width").getLength();
+ if(!cw.isAuto()) {
+ /*if(cw.scaleToFit()) {
+ if(viewWidth != -1) {
+ cwidth = viewWidth;
+ }
+ } else {*/
+ cwidth = cw.mvalue();
+ }
+
+ int scaling = properties.get("scaling").getEnum();
+ if((scaling == Scaling.UNIFORM) || (cwidth == -1) || cheight == -1) {
+ ImageFactory fact = ImageFactory.getInstance();
+ fopimage = fact.getImage(url, userAgent);
+ if(fopimage == null) {
+ // error
+ url = null;
+ return;
+ }
+ // load dimensions
+ if(!fopimage.load(FopImage.DIMENSIONS, userAgent)) {
+ // error
+ url = null;
+ return;
+ }
+ if(cwidth == -1) {
+ cwidth = (int)(fopimage.getWidth() * 1000);
+ }
+ if(cheight == -1) {
+ cheight = (int)(fopimage.getHeight() * 1000);
+ }
+ if(scaling == Scaling.UNIFORM) {
+ // adjust the larger
+ double rat1 = cwidth / (fopimage.getWidth() * 1000f);
+ double rat2 = cheight / (fopimage.getHeight() * 1000f);
+ if(rat1 > rat2) {
+ // reduce cheight
+ cheight = (int)(rat1 * fopimage.getHeight() * 1000);
+ } else {
+ cwidth = (int)(rat2 * fopimage.getWidth() * 1000);
+ }
+ }
+ }
+
+ if(viewWidth == -1) {
+ viewWidth = cwidth;
+ }
+ if(viewHeight == -1) {
+ viewHeight = cheight;
+ }
+
+ int overflow = properties.get("overflow").getEnum();
+ if(overflow == Overflow.HIDDEN) {
+ clip = true;
+ }
+ if(overflow == Overflow.ERROR_IF_OVERFLOW && (cwidth > viewWidth || cheight > viewHeight)) {
+ log.error("Image: " + url + " overflows the viewport");
+ clip = true;
+ }
+
+ int xoffset = 0;
+ int yoffset = 0;
+ int da = properties.get("display-align").getEnum();
+ switch(da) {
+ case DisplayAlign.BEFORE:
+ break;
+ case DisplayAlign.AFTER:
+ yoffset = viewHeight - cheight;
+ break;
+ case DisplayAlign.CENTER:
+ yoffset = (viewHeight - cheight) / 2;
+ break;
+ case DisplayAlign.AUTO:
+ default:
+ break;
+ }
+
+ int ta = properties.get("text-align").getEnum();
+ switch(ta) {
+ case TextAlign.CENTER:
+ xoffset = (viewWidth - cwidth) / 2;
+ break;
+ case TextAlign.END:
+ xoffset = viewWidth - cwidth;
+ break;
+ case TextAlign.START:
+ break;
+ case TextAlign.JUSTIFY:
+ default:
+ break;
+ }
+ placement = new Rectangle2D.Float(xoffset, yoffset, cwidth, cheight);
// Common Accessibility Properties
AccessibilityProps mAccProps = propMgr.getAccessibilityProps();
@@ -99,25 +223,14 @@ public class ExternalGraphic extends FObj {
// this.properties.get("alignment-adjust");
// this.properties.get("alignment-baseline");
// this.properties.get("baseline-shift");
- // this.properties.get("block-progression-dimension");
- // this.properties.get("content-height");
// this.properties.get("content-type");
- // this.properties.get("content-width");
- // this.properties.get("display-align");
// this.properties.get("dominant-baseline");
- // this.properties.get("height");
setupID();
- // this.properties.get("inline-progression-dimension");
// this.properties.get("keep-with-next");
// this.properties.get("keep-with-previous");
// this.properties.get("line-height");
// this.properties.get("line-height-shift-adjustment");
- // this.properties.get("overflow");
- // this.properties.get("scaling");
// this.properties.get("scaling-method");
- url = this.properties.get("src").getString();
- // this.properties.get("text-align");
- // this.properties.get("width");
}
}
diff --git a/src/org/apache/fop/pdf/PDFDocument.java b/src/org/apache/fop/pdf/PDFDocument.java
index da23546fd..259ec8d69 100644
--- a/src/org/apache/fop/pdf/PDFDocument.java
+++ b/src/org/apache/fop/pdf/PDFDocument.java
@@ -125,11 +125,6 @@ public class PDFDocument {
protected int xObjectCount = 0;
/**
- * the XObjects
- */
- protected ArrayList xObjects = new ArrayList();
-
- /**
* the XObjects Map.
* Should be modified (works only for image subtype)
*/
@@ -142,6 +137,8 @@ public class PDFDocument {
protected HashMap filterMap = new HashMap();
+ protected ArrayList gstates = new ArrayList();
+
/**
* creates an empty PDF document <p>
*
@@ -953,23 +950,49 @@ public class PDFDocument {
/**
* make an ExtGState for extra graphics options
*/
- public PDFGState makeGState() {
+ public PDFGState makeGState(HashMap settings, PDFGState current) {
+
+ // try to locate a gstate that has all the settings
+ // or will inherit from the current gstate
+ // compare "DEFAULT + settings" with "current + each gstate"
+
+ PDFGState wanted = new PDFGState(0);
+ wanted.addValues(PDFGState.DEFAULT);
+ wanted.addValues(settings);
+
+ PDFGState poss;
+ for(Iterator iter = gstates.iterator(); iter.hasNext(); ) {
+ PDFGState avail = (PDFGState)iter.next();
+ poss = new PDFGState(0);
+ poss.addValues(current);
+ poss.addValues(avail);
+ if(poss.equals(wanted)) {
+ return avail;
+ }
+ }
PDFGState gstate = new PDFGState(++this.objectcount);
+ gstate.addValues(settings);
this.objects.add(gstate);
+ gstates.add(gstate);
return gstate;
}
- public PDFXObject addImage(PDFResourceContext res, PDFImage img) {
- if(res != null) {
- res.getPDFResources().setXObjects(xObjects);
- }
+ public PDFXObject getImage(String key) {
+ PDFXObject xObject = (PDFXObject)xObjectsMap.get(key);
+ return xObject;
+ }
+ public PDFXObject addImage(PDFResourceContext res, PDFImage img) {
// check if already created
String key = img.getKey();
PDFXObject xObject = (PDFXObject)xObjectsMap.get(key);
- if (xObject != null)
+ if (xObject != null) {
+ if(res != null) {
+ res.getPDFResources().addXObject(xObject);
+ }
return xObject;
+ }
// setup image
img.setup(this);
@@ -977,7 +1000,10 @@ public class PDFDocument {
xObject = new PDFXObject(++this.objectcount, ++this.xObjectCount,
img);
this.objects.add(xObject);
- this.xObjects.add(xObject);
+ this.resources.addXObject(xObject);
+ if(res != null) {
+ res.getPDFResources().addXObject(xObject);
+ }
this.xObjectsMap.put(key, xObject);
return xObject;
}
@@ -1242,8 +1268,6 @@ public class PDFDocument {
};
stream.write(bin);
this.position += bin.length;
-
- this.resources.setXObjects(xObjects);
}
/**
diff --git a/src/org/apache/fop/pdf/PDFGState.java b/src/org/apache/fop/pdf/PDFGState.java
index 99c21f85e..e535fcdfe 100644
--- a/src/org/apache/fop/pdf/PDFGState.java
+++ b/src/org/apache/fop/pdf/PDFGState.java
@@ -7,6 +7,9 @@
package org.apache.fop.pdf;
+import java.util.HashMap;
+import java.util.Iterator;
+
/**
* class representing a /ExtGState object.
*
@@ -39,8 +42,26 @@ public class PDFGState extends PDFObject {
public static final String AIS = "ais";
public static final String TK = "tk";
- float alphaFill = 1;
- float alphaStroke = 1;
+ public static final PDFGState DEFAULT;
+
+ static {
+ DEFAULT = new PDFGState(0);
+ HashMap vals = DEFAULT.values;
+ /*vals.put(LW, new Float(1.0));
+ vals.put(LC, new Integer(0));
+ vals.put(LJ, new Integer(0));
+ vals.put(ML, new Float(10.0));
+ vals.put(D, "0 []");
+ vals.put(RI, "RelativeColorimetric");
+ vals.put(OP, Boolean.FALSE);
+ vals.put(op, Boolean.FALSE);
+ vals.put(OPM, new Integer(1));
+ vals.put(Font, "");*/
+ vals.put(CA, new Float(1.0));
+ vals.put(ca, new Float(1.0));
+ }
+
+ HashMap values = new HashMap();
/**
* create a /ExtGState object.
@@ -61,12 +82,20 @@ public class PDFGState extends PDFObject {
public void setAlpha(float val, boolean fill) {
if(fill) {
- alphaFill = val;
+ values.put(ca, new Float(val));
} else {
- alphaStroke = val;
+ values.put(CA, new Float(val));
}
}
+ public void addValues(PDFGState state) {
+ values.putAll(state.values);
+ }
+
+ public void addValues(HashMap vals) {
+ values.putAll(vals);
+ }
+
/**
* represent the object in PDF
*
@@ -75,16 +104,20 @@ public class PDFGState extends PDFObject {
public byte[] toPDF() {
StringBuffer sb = new StringBuffer(this.number + " " + this.generation
+ " obj\n<<\n/Type /ExtGState\n");
- if(alphaFill != 1) {
- sb.append("/ca " + alphaFill + "\n");
- }
- if(alphaStroke != 1) {
- sb.append("/CA " + alphaStroke + "\n");
- }
+ appendVal(sb, ca);
+ appendVal(sb, CA);
+
sb.append(">>\nendobj\n");
return sb.toString().getBytes();
}
+ private void appendVal(StringBuffer sb, String name) {
+ Object val = values.get(name);
+ if(val != null) {
+ sb.append("/" + name + " " + val + "\n");
+ }
+ }
+
/*
* example
* 29 0 obj
@@ -94,4 +127,27 @@ public class PDFGState extends PDFObject {
* >>
* endobj
*/
+
+ public boolean equals(Object obj) {
+ if(obj == this) {
+ return true;
+ }
+ if(!(obj instanceof PDFGState)) {
+ return false;
+ }
+ HashMap vals1 = values;
+ HashMap vals2 = ((PDFGState)obj).values;
+ if(vals1.size() != vals2.size()) {
+ return false;
+ }
+ for(Iterator iter = vals1.keySet().iterator(); iter.hasNext(); ) {
+ Object str = iter.next();
+ Object obj1 = vals1.get(str);
+ if(!obj1.equals(vals2.get(str))) {
+ return false;
+ }
+ }
+ return true;
+ }
}
+
diff --git a/src/org/apache/fop/pdf/PDFResources.java b/src/org/apache/fop/pdf/PDFResources.java
index 778f05e4c..312d37d3f 100644
--- a/src/org/apache/fop/pdf/PDFResources.java
+++ b/src/org/apache/fop/pdf/PDFResources.java
@@ -12,6 +12,7 @@ import java.io.PrintWriter;
import java.util.Iterator;
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.HashSet;
/**
* class representing a /Resources object.
@@ -26,10 +27,10 @@ public class PDFResources extends PDFObject {
*/
protected HashMap fonts = new HashMap();
- protected ArrayList xObjects = null;
+ protected HashSet xObjects = new HashSet();
protected ArrayList patterns = new ArrayList();
protected ArrayList shadings = new ArrayList();
- protected ArrayList gstates = new ArrayList();
+ protected HashSet gstates = new HashSet();
/**
* create a /Resources object.
@@ -62,8 +63,8 @@ public class PDFResources extends PDFObject {
this.patterns.add(thePattern);
}
- public void setXObjects(ArrayList xObjects) {
- this.xObjects = xObjects;
+ public void addXObject(PDFXObject xObject) {
+ this.xObjects.add(xObject);
}
/**
@@ -131,9 +132,10 @@ public class PDFResources extends PDFObject {
if (this.xObjects != null && !this.xObjects.isEmpty()) {
p = p.append("/XObject <<");
- for (int i = 1; i <= this.xObjects.size(); i++) {
- p = p.append("/Im" + i + " "
- + ((PDFXObject)this.xObjects.get(i - 1)).referencePDF()
+ for (Iterator iter = xObjects.iterator(); iter.hasNext(); ) {
+ PDFXObject xobj = (PDFXObject)iter.next();
+ p = p.append("/Im" + xobj.getXNumber() + " "
+ + xobj.referencePDF()
+ "\n");
}
p = p.append(" >>\n");
@@ -141,8 +143,8 @@ public class PDFResources extends PDFObject {
if (!this.gstates.isEmpty()) {
p = p.append("/ExtGState <<");
- for (int i = 0; i < this.gstates.size(); i++) {
- PDFGState gs = (PDFGState)this.gstates.get(i);
+ for (Iterator iter = gstates.iterator(); iter.hasNext(); ) {
+ PDFGState gs = (PDFGState)iter.next();
p = p.append("/" + gs.getName() + " "
+ gs.referencePDF()
+ " ");
diff --git a/src/org/apache/fop/pdf/PDFState.java b/src/org/apache/fop/pdf/PDFState.java
index 036a00fed..ef5e73885 100644
--- a/src/org/apache/fop/pdf/PDFState.java
+++ b/src/org/apache/fop/pdf/PDFState.java
@@ -177,10 +177,20 @@ public class PDFState {
return !tf.equals(transform);
}
+ /**
+ * Set a new transform.
+ * This transform is appended to the transform of
+ * the current graphic state.
+ */
public void setTransform(AffineTransform tf) {
transform.concatenate(tf);
}
+ /**
+ * Get the current transform.
+ * This gets the combination of all transforms in the
+ * current state.
+ */
public AffineTransform getTransform() {
AffineTransform tf;
AffineTransform at = new AffineTransform();
@@ -193,5 +203,32 @@ public class PDFState {
return at;
}
+
+ /**
+ * Get the grapics state.
+ * This gets the combination of all graphic states for
+ * the current context.
+ * This is the graphic state set with the gs operator not
+ * the other graphic state changes.
+ */
+ public PDFGState getGState() {
+ PDFGState defaultState = PDFGState.DEFAULT;
+
+ PDFGState state;
+ PDFGState newstate = new PDFGState(0);
+ newstate.addValues(defaultState);
+ for(Iterator iter = stateStack.iterator(); iter.hasNext(); ) {
+ HashMap map = (HashMap)iter.next();
+ state = (PDFGState)map.get(GSTATE);
+ if(state != null) {
+ newstate.addValues(state);
+ }
+ }
+ if(gstate != null) {
+ newstate.addValues(gstate);
+ }
+
+ return newstate;
+ }
}
diff --git a/src/org/apache/fop/render/AbstractRenderer.java b/src/org/apache/fop/render/AbstractRenderer.java
index 404dbb77e..9b0712d43 100644
--- a/src/org/apache/fop/render/AbstractRenderer.java
+++ b/src/org/apache/fop/render/AbstractRenderer.java
@@ -256,18 +256,19 @@ public abstract class AbstractRenderer implements Renderer {
Area content = viewport.getContent();
int saveBP = currentBPPosition;
currentBPPosition += viewport.getOffset();
+ Rectangle2D contpos = viewport.getContentPosition();
if (content instanceof Image) {
- renderImage((Image) content);
+ renderImage((Image) content, contpos);
} else if (content instanceof Container) {
renderContainer((Container) content);
} else if (content instanceof ForeignObject) {
- renderForeignObject((ForeignObject) content);
+ renderForeignObject((ForeignObject) content, contpos);
}
currentBlockIPPosition += viewport.getWidth();
currentBPPosition = saveBP;
}
- public void renderImage(Image image) {
+ public void renderImage(Image image, Rectangle2D pos) {
}
public void renderContainer(Container cont) {
@@ -283,7 +284,7 @@ public abstract class AbstractRenderer implements Renderer {
currentBPPosition = saveBP;
}
- public void renderForeignObject(ForeignObject fo) {
+ public void renderForeignObject(ForeignObject fo, Rectangle2D pos) {
}
diff --git a/src/org/apache/fop/render/pdf/FopPDFImage.java b/src/org/apache/fop/render/pdf/FopPDFImage.java
index fac035be0..bbfb83f6c 100644
--- a/src/org/apache/fop/render/pdf/FopPDFImage.java
+++ b/src/org/apache/fop/render/pdf/FopPDFImage.java
@@ -34,15 +34,17 @@ public class FopPDFImage implements PDFImage {
String softMaskRef;
boolean isPS = false;
HashMap filters;
+ String key;
- public FopPDFImage(FopImage im) {
+ public FopPDFImage(FopImage im, String k) {
fopImage = im;
+ key = k;
isPS = (fopImage instanceof EPSImage);
}
// key to look up XObject
public String getKey() {
- return fopImage.getURL();
+ return key;
}
public void setup(PDFDocument doc) {
diff --git a/src/org/apache/fop/render/pdf/PDFRenderer.java b/src/org/apache/fop/render/pdf/PDFRenderer.java
index c287adf43..12bf786be 100644
--- a/src/org/apache/fop/render/pdf/PDFRenderer.java
+++ b/src/org/apache/fop/render/pdf/PDFRenderer.java
@@ -465,8 +465,17 @@ public class PDFRenderer extends PrintRenderer {
}
}
- public void renderImage(Image image) {
+ public void renderImage(Image image, Rectangle2D pos) {
String url = image.getURL();
+
+ PDFXObject xobject = pdfDoc.getImage(url);
+ if(xobject != null) {
+ int w = (int)pos.getWidth() / 1000;
+ int h = (int)pos.getHeight() / 1000;
+ placeImage((int)pos.getX() / 1000, (int)pos.getY() / 1000, w, h, xobject.getXNumber());
+ return;
+ }
+
ImageFactory fact = ImageFactory.getInstance();
FopImage fopimage = fact.getImage(url, userAgent);
if(fopimage == null) {
@@ -484,7 +493,6 @@ public class PDFRenderer extends PrintRenderer {
String ns = ((XMLImage)fopimage).getNameSpace();
renderDocument(doc, ns);
-
} else if("image/svg+xml".equals(mime)) {
if(!fopimage.load(FopImage.ORIGINAL_DATA, userAgent)) {
return;
@@ -493,38 +501,35 @@ public class PDFRenderer extends PrintRenderer {
String ns = ((XMLImage)fopimage).getNameSpace();
renderDocument(doc, ns);
-
} else if("image/eps".equals(mime)) {
if(!fopimage.load(FopImage.ORIGINAL_DATA, userAgent)) {
return;
}
- FopPDFImage pdfimage = new FopPDFImage(fopimage);
+ FopPDFImage pdfimage = new FopPDFImage(fopimage, url);
int xobj = pdfDoc.addImage(null, pdfimage).getXNumber();
fact.releaseImage(url, userAgent);
} else if("image/jpg".equals(mime)) {
if(!fopimage.load(FopImage.ORIGINAL_DATA, userAgent)) {
return;
}
- FopPDFImage pdfimage = new FopPDFImage(fopimage);
+ FopPDFImage pdfimage = new FopPDFImage(fopimage, url);
int xobj = pdfDoc.addImage(null, pdfimage).getXNumber();
fact.releaseImage(url, userAgent);
+
+ int w = (int)pos.getWidth() / 1000;
+ int h = (int)pos.getHeight() / 1000;
+ placeImage((int)pos.getX() / 1000, (int)pos.getY() / 1000, w, h, xobj);
} else {
if(!fopimage.load(FopImage.BITMAP, userAgent)) {
return;
}
- FopPDFImage pdfimage = new FopPDFImage(fopimage);
+ FopPDFImage pdfimage = new FopPDFImage(fopimage, url);
int xobj = pdfDoc.addImage(null, pdfimage).getXNumber();
fact.releaseImage(url, userAgent);
- closeText();
- int w = fopimage.getWidth();
- int h = fopimage.getHeight();
-
- currentStream.add("ET\nq\n" + ((float)w) + " 0 0 "
- + ((float)-h) + " "
- + (((float)currentBlockIPPosition) / 1000f) + " "
- + (((float)(currentBPPosition + 1000 * h)) / 1000f) + " cm\n" + "/Im"
- + xobj + " Do\nQ\nBT\n");
+ int w = (int)pos.getWidth() / 1000;
+ int h = (int)pos.getHeight() / 1000;
+ placeImage((int)pos.getX() / 1000, (int)pos.getY() / 1000, w, h, xobj);
}
// output new data
@@ -535,7 +540,16 @@ public class PDFRenderer extends PrintRenderer {
}
}
- public void renderForeignObject(ForeignObject fo) {
+ protected void placeImage(int x, int y, int w, int h, int xobj) {
+ currentStream.add("q\n" + ((float)w) + " 0 0 "
+ + ((float)-h) + " "
+ + (((float)currentBlockIPPosition) / 1000f + x) + " "
+ + (((float)(currentBPPosition + 1000 * h)) / 1000f + y) + " cm\n" + "/Im"
+ + xobj + " Do\nQ\n");
+
+ }
+
+ public void renderForeignObject(ForeignObject fo, Rectangle2D pos) {
Document doc = fo.getDocument();
String ns = fo.getNameSpace();
renderDocument(doc, ns);
@@ -566,25 +580,34 @@ public class PDFRenderer extends PrintRenderer {
context.setProperty(PDFXMLHandler.PDF_FONT_SIZE, new Integer(currentFontSize));
context.setProperty(PDFXMLHandler.PDF_XPOS, new Integer(currentBlockIPPosition));
context.setProperty(PDFXMLHandler.PDF_YPOS, new Integer(currentBPPosition));
- closeText();
- currentStream.add("ET\n");
userAgent.renderXML(context, doc, ns);
- currentStream.add("BT\n");
}
public void renderViewport(Viewport viewport) {
- /*if (clip && 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");
+ closeText();
+ currentStream.add("ET\n");
+ if (viewport.getClip()) {
+ currentStream.add("q\n");
+
+ float x = currentBlockIPPosition / 1000f;
+ float y = (currentBPPosition + viewport.getOffset()) / 1000f;
+ float width = viewport.getWidth() / 1000f;
+ float height = viewport.getHeight() / 1000f;
+ currentStream.add(x + " " + y + " m\n");
+ currentStream.add((x + width) + " " + y + " l\n");
+ currentStream.add((x + width) + " " + (y + height) + " l\n");
+ currentStream.add(x + " " + (y + height) + " l\n");
currentStream.add("h\n");
currentStream.add("W\n");
currentStream.add("n\n");
- }*/
+ }
super.renderViewport(viewport);
+
+ if (viewport.getClip()) {
+ currentStream.add("Q\n");
+ }
+ currentStream.add("BT\n");
}
public void renderLeader(Leader area) {
diff --git a/src/org/apache/fop/svg/PDFGraphics2D.java b/src/org/apache/fop/svg/PDFGraphics2D.java
index 37c9c9573..72686fb68 100644
--- a/src/org/apache/fop/svg/PDFGraphics2D.java
+++ b/src/org/apache/fop/svg/PDFGraphics2D.java
@@ -103,20 +103,6 @@ public class PDFGraphics2D extends AbstractGraphics2D {
protected OutputStream outputStream = null;
/**
- * A registry of images that have already been drawn. They are mapped to
- * a structure with the PDF xObjectNum, width and height. This
- * prevents multiple copies from being stored, which can greatly
- * reduce the size of a PDF graphic that uses the same image over and over
- * (e.g. graphic bullets, map icons, etc.).
- */
- private HashMap imageInfos = new HashMap();
- private static class ImageInfo {
- public int width;
- public int height;
- public int xObjectNum;
- }
-
- /**
* Create a new PDFGraphics2D with the given pdf document info.
* This is used to create a Graphics object for use inside an already
* existing document.
@@ -197,7 +183,7 @@ public class PDFGraphics2D extends AbstractGraphics2D {
}
public void addJpegImage(JpegImage jpeg, float x, float y, float width, float height) {
- FopPDFImage fopimage = new FopPDFImage(jpeg);
+ FopPDFImage fopimage = new FopPDFImage(jpeg, jpeg.getURL());
int xObjectNum = this.pdfDoc.addImage(resourceContext, fopimage).getXNumber();
AffineTransform at = getTransform();
@@ -220,6 +206,7 @@ public class PDFGraphics2D extends AbstractGraphics2D {
try {
this.pdfDoc.output(outputStream);
} catch(IOException ioe) {
+ // ignore exception, will be thrown again later
}
}
}
@@ -252,36 +239,39 @@ public class PDFGraphics2D extends AbstractGraphics2D {
ImageObserver observer) {
// System.err.println("drawImage:x, y");
+ int width = img.getWidth(observer);
+ int height = img.getHeight(observer);
+
+ if (width == -1 || height == -1) {
+ return false;
+ }
+
// first we look to see if we've already added this image to
// the pdf document. If so, we just reuse the reference;
// otherwise we have to build a FopImage and add it to the pdf
// document
- ImageInfo imageInfo = (ImageInfo)imageInfos.get(img);
+ PDFXObject imageInfo = pdfDoc.getImage("TempImage:" + img.toString());
if (imageInfo == null) {
// OK, have to build and add a PDF image
- imageInfo = new ImageInfo();
- imageInfo.width = img.getWidth(observer);
- imageInfo.height = img.getHeight(observer);
-
- if (imageInfo.width == -1 || imageInfo.height == -1) {
- return false;
- }
-
- Dimension size = new Dimension(imageInfo.width * 3, imageInfo.height * 3);
+
+ // scale factor
+ final int scaleFactor = 3;
+
+ Dimension size = new Dimension(width * scaleFactor, height * scaleFactor);
BufferedImage buf = buildBufferedImage(size);
-
+
java.awt.Graphics2D g = buf.createGraphics();
g.setComposite(AlphaComposite.SrcOver);
g.setBackground(new Color(1, 1, 1, 0));
g.setPaint(new Color(1, 1, 1, 0));
- g.fillRect(0, 0, imageInfo.width * 3, imageInfo.height * 3);
+ g.fillRect(0, 0, width * scaleFactor, height * scaleFactor);
g.clip(new Rectangle(0, 0, buf.getWidth(), buf.getHeight()));
-
+
if (!g.drawImage(img, 0, 0, buf.getWidth(), buf.getHeight(), observer)) {
return false;
}
g.dispose();
-
+
final byte[] result = new byte[buf.getWidth() * buf.getHeight() * 3];
byte[] mask = new byte[buf.getWidth() * buf.getHeight()];
boolean hasMask = false;
@@ -289,13 +279,13 @@ public class PDFGraphics2D extends AbstractGraphics2D {
Raster raster = buf.getData();
DataBuffer bd = raster.getDataBuffer();
-
+
int count = 0;
int maskpos = 0;
int[] iarray;
int i, j, val, alpha, add, mult;
switch (bd.getDataType()) {
- case DataBuffer.TYPE_INT:
+ case DataBuffer.TYPE_INT:
int[][] idata = ((DataBufferInt)bd).getBankData();
for (i = 0; i < idata.length; i++) {
iarray = idata[i];
@@ -328,10 +318,10 @@ public class PDFGraphics2D extends AbstractGraphics2D {
}
}
break;
- default:
+ default:
// error
break;
- }
+ }
String ref = null;
if(hasMask) {
// if the mask is binary then we could convert it into a bitmask
@@ -344,6 +334,7 @@ public class PDFGraphics2D extends AbstractGraphics2D {
try {
this.pdfDoc.output(outputStream);
} catch(IOException ioe) {
+ // ignore exception, will be thrown again later
}
}
} else {
@@ -352,15 +343,18 @@ public class PDFGraphics2D extends AbstractGraphics2D {
BitmapImage fopimg = new BitmapImage("TempImage:" + img.toString(), buf.getWidth(), buf.getHeight(), result, ref);
fopimg.setTransparent(new PDFColor(255, 255, 255));
- imageInfo.xObjectNum = pdfDoc.addImage(resourceContext, fopimg).getXNumber();
- imageInfos.put(img, imageInfo);
+ imageInfo = pdfDoc.addImage(resourceContext, fopimg);
+ int xObjectNum = imageInfo.getXNumber();
if(outputStream != null) {
try {
this.pdfDoc.output(outputStream);
} catch(IOException ioe) {
+ // ignore exception, will be thrown again later
}
}
+ } else {
+ resourceContext.getPDFResources().addXObject(imageInfo);
}
// now do any transformation required and add the actual image
@@ -374,9 +368,9 @@ public class PDFGraphics2D extends AbstractGraphics2D {
currentStream.write("" + matrix[0] + " " + matrix[1] + " "
+ matrix[2] + " " + matrix[3] + " "
+ matrix[4] + " " + matrix[5] + " cm\n");
- currentStream.write("" + imageInfo.width + " 0 0 " + (-imageInfo.height) + " " + x
- + " " + (y + imageInfo.height) + " cm\n" + "/Im"
- + imageInfo.xObjectNum + " Do\nQ\n");
+ currentStream.write("" + width + " 0 0 " + (-height) + " " + x
+ + " " + (y + height) + " cm\n" + "/Im"
+ + imageInfo.getXNumber() + " Do\nQ\n");
return true;
}
@@ -509,8 +503,10 @@ public class PDFGraphics2D extends AbstractGraphics2D {
}
if(c.getAlpha() != 255) {
- PDFGState gstate = pdfDoc.makeGState();
- gstate.setAlpha(c.getAlpha() / 255f, false);
+ HashMap vals = new HashMap();
+ vals.put(PDFGState.CA, new Float(c.getAlpha() / 255f));
+ PDFGState gstate = pdfDoc.makeGState(vals, graphicsState.getGState());
+ //gstate.setAlpha(c.getAlpha() / 255f, false);
resourceContext.addGState(gstate);
currentStream.write("/" + gstate.getName() + " gs\n");
}
@@ -793,6 +789,7 @@ public class PDFGraphics2D extends AbstractGraphics2D {
try {
this.pdfDoc.output(outputStream);
} catch(IOException ioe) {
+ // ignore exception, will be thrown again later
}
}
@@ -982,9 +979,10 @@ public class PDFGraphics2D extends AbstractGraphics2D {
c = getBackground();
applyColor(c, false);
if(salpha != 255/* || c.getAlpha() != 255*/) {
- PDFGState gstate = pdfDoc.makeGState();
- gstate.setAlpha(salpha / 255f, true);
- //gstate.setAlpha(c.getAlpha() / 255f, false);
+ HashMap vals = new HashMap();
+ vals.put(PDFGState.ca, new Float(salpha / 255f));
+ //vals.put(PDFGState.CA, new Float(c.getAlpha() / 255f));
+ PDFGState gstate = pdfDoc.makeGState(vals, graphicsState.getGState());
resourceContext.addGState(gstate);
currentStream.write("/" + gstate.getName() + " gs\n");
}
@@ -1213,8 +1211,9 @@ public class PDFGraphics2D extends AbstractGraphics2D {
}
if(c.getAlpha() != 255) {
- PDFGState gstate = pdfDoc.makeGState();
- gstate.setAlpha(c.getAlpha() / 255f, true);
+ HashMap vals = new HashMap();
+ vals.put(PDFGState.ca, new Float(c.getAlpha() / 255f));
+ PDFGState gstate = pdfDoc.makeGState(vals, graphicsState.getGState());
resourceContext.addGState(gstate);
currentStream.write("/" + gstate.getName() + " gs\n");
}
diff --git a/src/org/apache/fop/svg/PDFTextPainter.java b/src/org/apache/fop/svg/PDFTextPainter.java
index 6476d85d9..61173a569 100644
--- a/src/org/apache/fop/svg/PDFTextPainter.java
+++ b/src/org/apache/fop/svg/PDFTextPainter.java
@@ -32,6 +32,8 @@ import org.apache.batik.gvt.font.*;
import org.apache.fop.layout.*;
+// TODO properly calculate bounds for links etc.
+
/**
* Renders the attributed character iterator of a <tt>TextNode</tt>.
*
@@ -250,7 +252,8 @@ public class PDFTextPainter implements TextPainter {
public Rectangle2D getPaintedBounds(TextNode node) {
// System.out.println("PDFText getPaintedBounds");
- return null;
+ Point2D loc = node.getLocation();
+ return new Rectangle2D.Double(loc.getX(), loc.getY(), 100, 12);
}
}