diff options
author | Keiron Liddle <keiron@apache.org> | 2002-07-04 14:08:20 +0000 |
---|---|---|
committer | Keiron Liddle <keiron@apache.org> | 2002-07-04 14:08:20 +0000 |
commit | 072a9d2808472eec30aa1c272ee4cb50e596a3c9 (patch) | |
tree | f82cc18789323e776b399f063b0c0ec85301bb28 | |
parent | 15e5fd84a05a9ebd8f26096bcbe2bc9e36fb8345 (diff) | |
download | xmlgraphics-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.java | 16 | ||||
-rw-r--r-- | src/org/apache/fop/fo/flow/ExternalGraphic.java | 171 | ||||
-rw-r--r-- | src/org/apache/fop/pdf/PDFDocument.java | 52 | ||||
-rw-r--r-- | src/org/apache/fop/pdf/PDFGState.java | 76 | ||||
-rw-r--r-- | src/org/apache/fop/pdf/PDFResources.java | 20 | ||||
-rw-r--r-- | src/org/apache/fop/pdf/PDFState.java | 37 | ||||
-rw-r--r-- | src/org/apache/fop/render/AbstractRenderer.java | 9 | ||||
-rw-r--r-- | src/org/apache/fop/render/pdf/FopPDFImage.java | 6 | ||||
-rw-r--r-- | src/org/apache/fop/render/pdf/PDFRenderer.java | 75 | ||||
-rw-r--r-- | src/org/apache/fop/svg/PDFGraphics2D.java | 89 | ||||
-rw-r--r-- | src/org/apache/fop/svg/PDFTextPainter.java | 5 |
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); } } |