"viewport" and "group" are implemented in IFSerializer, SVG and PDF. Some minor problems remain. Fixed a few minor bugs (like NPEs) found while testing. git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_AreaTreeNewDesign@680266 13f79535-47bb-0310-9956-ffa450edef68tags/fop-1_0
@@ -592,6 +592,7 @@ RetroWeaver will be added here --> | |||
<include name="org/apache/fop/render/pdf/**"/> | |||
<exclude name="org/apache/fop/render/pdf/PDFRenderer.class"/> | |||
<exclude name="org/apache/fop/render/pdf/PDFXMLHandler*"/> | |||
<include name="org/apache/fop/render/intermediate/IFPainterConfigurator.class"/> | |||
<include name="org/apache/fop/render/*RendererConfigurator**"/> | |||
<include name="org/apache/fop/pdf/**"/> | |||
</patternset> |
@@ -270,7 +270,12 @@ public abstract class PDFTextUtil { | |||
* @param adjust the glyph adjust value in thousands of text unit space. | |||
*/ | |||
public void adjustGlyphTJ(double adjust) { | |||
bufTJ.append(endText).append(" "); | |||
if (bufTJ == null) { | |||
bufTJ = new StringBuffer(); | |||
} | |||
if (bufTJ.length() > 0) { | |||
bufTJ.append(endText).append(" "); | |||
} | |||
bufTJ.append(PDFNumber.doubleOut(adjust, DEC - 4)); | |||
bufTJ.append(" "); | |||
bufTJ.append(startText); |
@@ -19,6 +19,10 @@ | |||
package org.apache.fop.render.intermediate; | |||
import java.awt.Dimension; | |||
import java.awt.Rectangle; | |||
import java.awt.geom.AffineTransform; | |||
import org.apache.fop.apps.FOUserAgent; | |||
/** | |||
@@ -47,4 +51,23 @@ public abstract class AbstractIFPainter implements IFPainter { | |||
return this.userAgent; | |||
} | |||
private AffineTransform combine(AffineTransform[] transforms) { | |||
AffineTransform at = new AffineTransform(); | |||
for (int i = 0, c = transforms.length; i < c; i++) { | |||
at.concatenate(transforms[i]); | |||
} | |||
return at; | |||
} | |||
/** {@inheritDoc} */ | |||
public void startViewport(AffineTransform[] transforms, Dimension size, Rectangle clipRect) | |||
throws IFException { | |||
startViewport(combine(transforms), size, clipRect); | |||
} | |||
/** {@inheritDoc} */ | |||
public void startGroup(AffineTransform[] transforms) throws IFException { | |||
startGroup(combine(transforms)); | |||
} | |||
} |
@@ -19,6 +19,7 @@ | |||
package org.apache.fop.render.intermediate; | |||
import java.awt.Rectangle; | |||
import java.awt.geom.AffineTransform; | |||
import java.text.DecimalFormat; | |||
import java.text.DecimalFormatSymbols; | |||
@@ -131,6 +132,9 @@ public abstract class AbstractXMLWritingIFPainter extends AbstractIFPainter { | |||
* @return the StringBuffer passed to this method | |||
*/ | |||
protected StringBuffer toString(AffineTransform transform, StringBuffer sb) { | |||
if (transform.isIdentity()) { | |||
return sb; | |||
} | |||
double[] matrix = new double[6]; | |||
transform.getMatrix(matrix); | |||
if (matrix[0] == 1 && matrix[3] == 1 && matrix[1] == 0 && matrix[2] == 0) { | |||
@@ -210,4 +214,20 @@ public abstract class AbstractXMLWritingIFPainter extends AbstractIFPainter { | |||
} | |||
return sb.toString(); | |||
} | |||
/** | |||
* Converts a rectangle into a space-separated string. | |||
* @param rect the rectangle | |||
* @return the space-separated array of coordinates | |||
*/ | |||
protected String toString(Rectangle rect) { | |||
if (rect == null) { | |||
return ""; | |||
} | |||
StringBuffer sb = new StringBuffer(); | |||
sb.append(rect.x).append(' ').append(rect.y).append(' '); | |||
sb.append(rect.width).append(' ').append(rect.height); | |||
return sb.toString(); | |||
} | |||
} |
@@ -33,6 +33,8 @@ import org.apache.batik.parser.TransformListParser; | |||
*/ | |||
public class AffineTransformArrayParser implements TransformListHandler { | |||
private static final AffineTransform[] EMPTY_ARRAY = new AffineTransform[0]; | |||
private List transforms; | |||
/** | |||
@@ -60,6 +62,9 @@ public class AffineTransformArrayParser implements TransformListHandler { | |||
*/ | |||
public static AffineTransform[] createAffineTransform(String s) | |||
throws ParseException { | |||
if (s == null) { | |||
return EMPTY_ARRAY; | |||
} | |||
TransformListParser p = new TransformListParser(); | |||
AffineTransformArrayParser th = new AffineTransformArrayParser(); | |||
@@ -47,5 +47,6 @@ public interface IFConstants { | |||
String EL_PAGE_HEADER = "page-header"; | |||
String EL_PAGE_TRAILER = "page-trailer"; | |||
String EL_PAGE_CONTENT = "content"; | |||
String EL_BOX = "box"; | |||
String EL_VIEWPORT = "viewport"; | |||
String EL_GROUP = "g"; | |||
} |
@@ -0,0 +1,60 @@ | |||
/* | |||
* Licensed to the Apache Software Foundation (ASF) under one or more | |||
* contributor license agreements. See the NOTICE file distributed with | |||
* this work for additional information regarding copyright ownership. | |||
* The ASF licenses this file to You under the Apache License, Version 2.0 | |||
* (the "License"); you may not use this file except in compliance with | |||
* the License. You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
*/ | |||
/* $Id$ */ | |||
package org.apache.fop.render.intermediate; | |||
import org.apache.xmlgraphics.java2d.GraphicContext; | |||
public class IFGraphicContext extends GraphicContext { | |||
private int groupDepth; | |||
/** | |||
* Default constructor. | |||
*/ | |||
public IFGraphicContext() { | |||
super(); | |||
} | |||
/** | |||
* Copy constructor. | |||
* @param graphicContext the graphic context to make a copy of | |||
*/ | |||
protected IFGraphicContext(IFGraphicContext graphicContext) { | |||
super(graphicContext); | |||
//We don't clone groupDepth! | |||
} | |||
/** {@inheritDoc} */ | |||
public Object clone() { | |||
return new IFGraphicContext(this); | |||
} | |||
public void startGroup() { | |||
this.groupDepth++; | |||
} | |||
public void endGroup() { | |||
this.groupDepth--; | |||
} | |||
public int getGroupDepth() { | |||
return this.groupDepth; | |||
} | |||
} |
@@ -214,10 +214,14 @@ public interface IFPainter { | |||
*/ | |||
void endPageTrailer() throws IFException; | |||
void startBox(AffineTransform transform, Dimension size, boolean clip) throws IFException; | |||
void startBox(AffineTransform[] transforms, Dimension size, boolean clip) throws IFException; | |||
void startViewport(AffineTransform transform, Dimension size, Rectangle clipRect) throws IFException; | |||
void startViewport(AffineTransform[] transforms, Dimension size, Rectangle clipRect) throws IFException; | |||
//For transform, Batik's org.apache.batik.parser.TransformListHandler/Parser can be used | |||
void endBox() throws IFException; | |||
void endViewport() throws IFException; | |||
void startGroup(AffineTransform[] transforms) throws IFException; | |||
void startGroup(AffineTransform transform) throws IFException; | |||
void endGroup() throws IFException; | |||
/** | |||
* Updates the current font. |
@@ -122,15 +122,16 @@ public class IFParser implements IFConstants { | |||
this.painter = painter; | |||
this.userAgent = userAgent; | |||
this.elementMappingRegistry = elementMappingRegistry; | |||
elementHandlers.put("document", new DocumentHandler()); | |||
elementHandlers.put("header", new DocumentHeaderHandler()); | |||
elementHandlers.put("page-sequence", new PageSequenceHandler()); | |||
elementHandlers.put("page", new PageHandler()); | |||
elementHandlers.put("page-header", new PageHeaderHandler()); | |||
elementHandlers.put("content", new PageContentHandler()); | |||
elementHandlers.put("page-trailer", new PageTrailerHandler()); | |||
elementHandlers.put(EL_DOCUMENT, new DocumentHandler()); | |||
elementHandlers.put(EL_HEADER, new DocumentHeaderHandler()); | |||
elementHandlers.put(EL_PAGE_SEQUENCE, new PageSequenceHandler()); | |||
elementHandlers.put(EL_PAGE, new PageHandler()); | |||
elementHandlers.put(EL_PAGE_HEADER, new PageHeaderHandler()); | |||
elementHandlers.put(EL_PAGE_CONTENT, new PageContentHandler()); | |||
elementHandlers.put(EL_PAGE_TRAILER, new PageTrailerHandler()); | |||
//Page content | |||
elementHandlers.put("box", new BoxHandler()); | |||
elementHandlers.put(EL_VIEWPORT, new ViewportHandler()); | |||
elementHandlers.put(EL_GROUP, new GroupHandler()); | |||
elementHandlers.put("font", new FontHandler()); | |||
elementHandlers.put("text", new TextHandler()); | |||
elementHandlers.put("rect", new RectHandler()); | |||
@@ -366,18 +367,35 @@ public class IFParser implements IFConstants { | |||
} | |||
private class BoxHandler extends AbstractElementHandler { | |||
private class ViewportHandler extends AbstractElementHandler { | |||
public void startElement(Attributes attributes) throws IFException { | |||
String transform = attributes.getValue("transform"); | |||
AffineTransform[] transforms | |||
= AffineTransformArrayParser.createAffineTransform(transform); | |||
//TODO Incomplete implementation | |||
painter.startBox(transforms, null, false); | |||
int width = Integer.parseInt(attributes.getValue("width")); | |||
int height = Integer.parseInt(attributes.getValue("height")); | |||
Rectangle clipRect = getAttributeAsRectangle(attributes, "clip-rect"); | |||
painter.startViewport(transforms, new Dimension(width, height), clipRect); | |||
} | |||
public void endElement() throws IFException { | |||
painter.endBox(); | |||
painter.endViewport(); | |||
} | |||
} | |||
private class GroupHandler extends AbstractElementHandler { | |||
public void startElement(Attributes attributes) throws IFException { | |||
String transform = attributes.getValue("transform"); | |||
AffineTransform[] transforms | |||
= AffineTransformArrayParser.createAffineTransform(transform); | |||
painter.startGroup(transforms); | |||
} | |||
public void endElement() throws IFException { | |||
painter.endGroup(); | |||
} | |||
} | |||
@@ -515,8 +533,11 @@ public class IFParser implements IFConstants { | |||
} | |||
private static Rectangle getAttributeAsRectangle(Attributes attributes, String name) { | |||
String s = attributes.getValue(name).trim(); | |||
int[] values = ConversionUtils.toIntArray(s, "\\s"); | |||
String s = attributes.getValue(name); | |||
if (s == null) { | |||
return null; | |||
} | |||
int[] values = ConversionUtils.toIntArray(s.trim(), "\\s"); | |||
if (values.length != 4) { | |||
throw new IllegalArgumentException("Rectangle must consist of 4 int values!"); | |||
} |
@@ -37,7 +37,6 @@ import org.xml.sax.SAXException; | |||
import org.apache.commons.logging.Log; | |||
import org.apache.commons.logging.LogFactory; | |||
import org.apache.xmlgraphics.java2d.GraphicContext; | |||
import org.apache.xmlgraphics.xmp.Metadata; | |||
import org.apache.xmlgraphics.xmp.schemas.DublinCoreAdapter; | |||
import org.apache.xmlgraphics.xmp.schemas.DublinCoreSchema; | |||
@@ -48,16 +47,19 @@ import org.apache.fop.Version; | |||
import org.apache.fop.apps.FOPException; | |||
import org.apache.fop.apps.MimeConstants; | |||
import org.apache.fop.area.Block; | |||
import org.apache.fop.area.BlockViewport; | |||
import org.apache.fop.area.CTM; | |||
import org.apache.fop.area.OffDocumentExtensionAttachment; | |||
import org.apache.fop.area.OffDocumentItem; | |||
import org.apache.fop.area.PageSequence; | |||
import org.apache.fop.area.PageViewport; | |||
import org.apache.fop.area.RegionViewport; | |||
import org.apache.fop.area.Trait; | |||
import org.apache.fop.area.inline.AbstractTextArea; | |||
import org.apache.fop.area.inline.Image; | |||
import org.apache.fop.area.inline.SpaceArea; | |||
import org.apache.fop.area.inline.TextArea; | |||
import org.apache.fop.area.inline.Viewport; | |||
import org.apache.fop.area.inline.WordArea; | |||
import org.apache.fop.fo.extensions.ExtensionAttachment; | |||
import org.apache.fop.fo.extensions.xmp.XMPMetadata; | |||
@@ -85,7 +87,8 @@ public class IFRenderer extends AbstractPathOrientedRenderer { | |||
private boolean inPageSequence = false; | |||
private Stack graphicContextStack = new Stack(); | |||
private GraphicContext graphicContext = new GraphicContext(); | |||
private Stack viewportDimensionStack = new Stack(); | |||
private IFGraphicContext graphicContext = new IFGraphicContext(); | |||
private Metadata documentMetadata; | |||
@@ -285,12 +288,20 @@ public class IFRenderer extends AbstractPathOrientedRenderer { | |||
/** {@inheritDoc} */ | |||
protected void saveGraphicsState() { | |||
graphicContextStack.push(graphicContext); | |||
graphicContext = (GraphicContext)graphicContext.clone(); | |||
graphicContext = (IFGraphicContext)graphicContext.clone(); | |||
} | |||
/** {@inheritDoc} */ | |||
protected void restoreGraphicsState() { | |||
graphicContext = (GraphicContext)graphicContextStack.pop(); | |||
while (graphicContext.getGroupDepth() > 0) { | |||
try { | |||
painter.endGroup(); | |||
} catch (IFException e) { | |||
handleIFException(e); | |||
} | |||
graphicContext.endGroup(); | |||
} | |||
graphicContext = (IFGraphicContext)graphicContextStack.pop(); | |||
} | |||
/** {@inheritDoc} */ | |||
@@ -309,39 +320,78 @@ public class IFRenderer extends AbstractPathOrientedRenderer { | |||
log.debug("Block.FIXED --> restoring context after break-out"); | |||
for (int i = 0, c = breakOutList.size(); i < c; i++) { | |||
saveGraphicsState(); | |||
this.graphicContext = (GraphicContext)breakOutList.get(i); | |||
this.graphicContext = (IFGraphicContext)breakOutList.get(i); | |||
} | |||
} | |||
/** {@inheritDoc} */ | |||
protected void concatenateTransformationMatrix(AffineTransform at) { | |||
if (!at.isIdentity()) { | |||
graphicContext.transform(ptToMpt(at)); | |||
if (log.isDebugEnabled()) { | |||
log.debug("-----concatenateTransformationMatrix: " + at); | |||
} | |||
AffineTransform atmpt = ptToMpt(at); | |||
graphicContext.transform(atmpt); | |||
graphicContext.startGroup(); | |||
try { | |||
painter.startGroup(atmpt); | |||
} catch (IFException e) { | |||
handleIFException(e); | |||
} | |||
} | |||
} | |||
/** {@inheritDoc} */ | |||
protected void beginTextObject() { | |||
// TODO Auto-generated method stub | |||
//nop - Ignore, handled by painter internally | |||
} | |||
/** {@inheritDoc} */ | |||
protected void endTextObject() { | |||
// TODO Auto-generated method stub | |||
//nop - Ignore, handled by painter internally | |||
} | |||
/** {@inheritDoc} */ | |||
protected void renderRegionViewport(RegionViewport viewport) { | |||
Dimension dim = new Dimension(viewport.getIPD(), viewport.getBPD()); | |||
viewportDimensionStack.push(dim); | |||
super.renderRegionViewport(viewport); | |||
viewportDimensionStack.pop(); | |||
} | |||
/** {@inheritDoc} */ | |||
protected void renderBlockViewport(BlockViewport bv, List children) { | |||
Dimension dim = new Dimension(bv.getIPD(), bv.getBPD()); | |||
viewportDimensionStack.push(dim); | |||
super.renderBlockViewport(bv, children); | |||
viewportDimensionStack.pop(); | |||
} | |||
/** {@inheritDoc} */ | |||
public void renderViewport(Viewport viewport) { | |||
Dimension dim = new Dimension(viewport.getIPD(), viewport.getBPD()); | |||
viewportDimensionStack.push(dim); | |||
super.renderViewport(viewport); | |||
viewportDimensionStack.pop(); | |||
} | |||
/** {@inheritDoc} */ | |||
protected void startVParea(CTM ctm, Rectangle2D clippingRect) { | |||
if (log.isDebugEnabled()) { | |||
log.debug("startVParea() ctm=" + ctm + ", rect=" + clippingRect); | |||
log.debug("startVParea() ctm=" + ctm + ", clippingRect=" + clippingRect); | |||
} | |||
saveGraphicsState(); | |||
AffineTransform at = new AffineTransform(ctm.toArray()); | |||
graphicContext.transform(at); | |||
try { | |||
painter.startBox(at, null, false); | |||
Rectangle clipRect = null; | |||
if (clippingRect != null) { | |||
clipRect = new Rectangle( | |||
(int)clippingRect.getMinX() - currentIPPosition, | |||
(int)clippingRect.getMinY() - currentBPPosition, | |||
(int)clippingRect.getWidth(), (int)clippingRect.getHeight()); | |||
} | |||
painter.startViewport(at, (Dimension)viewportDimensionStack.peek(), clipRect); | |||
} catch (IFException e) { | |||
handleIFException(e); | |||
} | |||
@@ -354,7 +404,7 @@ public class IFRenderer extends AbstractPathOrientedRenderer { | |||
protected void endVParea() { | |||
log.debug("endVParea()"); | |||
try { | |||
painter.endBox(); | |||
painter.endViewport(); | |||
} catch (IFException e) { | |||
handleIFException(e); | |||
} | |||
@@ -364,9 +414,10 @@ public class IFRenderer extends AbstractPathOrientedRenderer { | |||
} | |||
} | |||
/* | |||
protected void renderReferenceArea(Block block) { | |||
// TODO Auto-generated method stub | |||
} | |||
}*/ | |||
/** {@inheritDoc} */ | |||
protected void renderBlock(Block block) { | |||
@@ -502,28 +553,30 @@ public class IFRenderer extends AbstractPathOrientedRenderer { | |||
protected void drawImage(String url, Rectangle2D pos, Map foreignAttributes) { | |||
// TODO Auto-generated method stub | |||
log.warn("drawImage() NYI"); | |||
} | |||
protected void clip() { | |||
// TODO Auto-generated method stub | |||
log.warn("clip() NYI"); | |||
} | |||
protected void clipRect(float x, float y, float width, float height) { | |||
// TODO Auto-generated method stub | |||
log.warn("clipRect() NYI"); | |||
} | |||
protected void closePath() { | |||
// TODO Auto-generated method stub | |||
log.warn("closePath() NYI"); | |||
} | |||
protected void drawBorderLine(float x1, float y1, float x2, float y2, boolean horz, | |||
boolean startOrBefore, int style, Color col) { | |||
// TODO Auto-generated method stub | |||
//log.warn("drawBorderLine() NYI"); | |||
updateColor(col, true); | |||
fillRect(x1, y1, x2 - x1, y2 - y1); | |||
} | |||
private Rectangle toMillipointRectangle(float x, float y, float width, float height) { | |||
@@ -545,13 +598,13 @@ public class IFRenderer extends AbstractPathOrientedRenderer { | |||
/** {@inheritDoc} */ | |||
protected void moveTo(float x, float y) { | |||
// TODO Auto-generated method stub | |||
log.warn("moveTo() NYI"); | |||
} | |||
/** {@inheritDoc} */ | |||
protected void lineTo(float x, float y) { | |||
// TODO Auto-generated method stub | |||
log.warn("lineTo() NYI"); | |||
} | |||
/** {@inheritDoc} */ |
@@ -200,15 +200,15 @@ public class IFSerializer extends AbstractXMLWritingIFPainter implements IFConst | |||
} | |||
/** {@inheritDoc} */ | |||
public void startBox(AffineTransform transform, Dimension size, boolean clip) | |||
public void startViewport(AffineTransform transform, Dimension size, Rectangle clipRect) | |||
throws IFException { | |||
StringBuffer sb = new StringBuffer(); | |||
toString(transform, sb); | |||
startBox(sb.toString(), size, clip); | |||
startViewport(sb.toString(), size, clipRect); | |||
} | |||
/** {@inheritDoc} */ | |||
public void startBox(AffineTransform[] transforms, Dimension size, boolean clip) | |||
public void startViewport(AffineTransform[] transforms, Dimension size, Rectangle clipRect) | |||
throws IFException { | |||
StringBuffer sb = new StringBuffer(); | |||
for (int i = 0, c = transforms.length; i < c; i++) { | |||
@@ -217,32 +217,72 @@ public class IFSerializer extends AbstractXMLWritingIFPainter implements IFConst | |||
} | |||
toString(transforms[i], sb); | |||
} | |||
startBox(sb.toString(), size, clip); | |||
startViewport(sb.toString(), size, clipRect); | |||
} | |||
private void startBox(String transform, Dimension size, boolean clip) throws IFException { | |||
private void startViewport(String transform, Dimension size, Rectangle clipRect) throws IFException { | |||
try { | |||
AttributesImpl atts = new AttributesImpl(); | |||
atts.addAttribute("", "transform", "transform", CDATA, transform); | |||
if (size != null) { | |||
atts.addAttribute("", "width", "width", CDATA, Integer.toString(size.width)); | |||
atts.addAttribute("", "height", "height", CDATA, Integer.toString(size.height)); | |||
if (transform != null && transform.length() > 0) { | |||
atts.addAttribute("", "transform", "transform", CDATA, transform); | |||
} | |||
atts.addAttribute("", "width", "width", CDATA, Integer.toString(size.width)); | |||
atts.addAttribute("", "height", "height", CDATA, Integer.toString(size.height)); | |||
if (clipRect != null) { | |||
atts.addAttribute("", "clip-rect", "clip-rect", CDATA, toString(clipRect)); | |||
} | |||
if (clip) { | |||
atts.addAttribute("", "clip", "clip", CDATA, "true"); | |||
startElement(EL_VIEWPORT, atts); | |||
} catch (SAXException e) { | |||
throw new IFException("SAX error in startViewport()", e); | |||
} | |||
} | |||
/** {@inheritDoc} */ | |||
public void endViewport() throws IFException { | |||
try { | |||
endElement(EL_VIEWPORT); | |||
} catch (SAXException e) { | |||
throw new IFException("SAX error in endViewport()", e); | |||
} | |||
} | |||
/** {@inheritDoc} */ | |||
public void startGroup(AffineTransform[] transforms) throws IFException { | |||
StringBuffer sb = new StringBuffer(); | |||
for (int i = 0, c = transforms.length; i < c; i++) { | |||
if (i > 0) { | |||
sb.append(' '); | |||
} | |||
toString(transforms[i], sb); | |||
} | |||
startGroup(sb.toString()); | |||
} | |||
/** {@inheritDoc} */ | |||
public void startGroup(AffineTransform transform) throws IFException { | |||
StringBuffer sb = new StringBuffer(); | |||
toString(transform, sb); | |||
startGroup(sb.toString()); | |||
} | |||
private void startGroup(String transform) throws IFException { | |||
try { | |||
AttributesImpl atts = new AttributesImpl(); | |||
if (transform != null && transform.length() > 0) { | |||
atts.addAttribute("", "transform", "transform", CDATA, transform); | |||
} | |||
startElement(EL_BOX, atts); | |||
startElement(EL_GROUP, atts); | |||
} catch (SAXException e) { | |||
throw new IFException("SAX error in startBox()", e); | |||
throw new IFException("SAX error in startGroup()", e); | |||
} | |||
} | |||
/** {@inheritDoc} */ | |||
public void endBox() throws IFException { | |||
public void endGroup() throws IFException { | |||
try { | |||
endElement(EL_BOX); | |||
endElement(EL_GROUP); | |||
} catch (SAXException e) { | |||
throw new IFException("SAX error in endBox()", e); | |||
throw new IFException("SAX error in endGroup()", e); | |||
} | |||
} | |||
@@ -294,24 +294,33 @@ public class PDFPainter extends AbstractBinaryWritingIFPainter { | |||
} | |||
/** {@inheritDoc} */ | |||
public void startBox(AffineTransform transform, Dimension size, boolean clip) | |||
public void startViewport(AffineTransform transform, Dimension size, Rectangle clipRect) | |||
throws IFException { | |||
saveGraphicsState(); | |||
currentStream.add(CTMHelper.toPDFString(transform, true) + " cm\n"); | |||
if (clipRect != null) { | |||
StringBuffer sb = new StringBuffer(); | |||
sb.append(format(clipRect.x)).append(' '); | |||
sb.append(format(clipRect.y)).append(' '); | |||
sb.append(format(clipRect.width)).append(' '); | |||
sb.append(format(clipRect.height)).append(" re W n\n"); | |||
currentStream.add(sb.toString()); | |||
} | |||
} | |||
/** {@inheritDoc} */ | |||
public void startBox(AffineTransform[] transforms, Dimension size, boolean clip) | |||
throws IFException { | |||
AffineTransform at = new AffineTransform(); | |||
for (int i = 0, c = transforms.length; i < c; i++) { | |||
at.concatenate(transforms[i]); | |||
} | |||
startBox(at, size, clip); | |||
public void startGroup(AffineTransform transform) throws IFException { | |||
saveGraphicsState(); | |||
currentStream.add(CTMHelper.toPDFString(transform, true) + " cm\n"); | |||
} | |||
/** {@inheritDoc} */ | |||
public void endGroup() throws IFException { | |||
restoreGraphicsState(); | |||
} | |||
/** {@inheritDoc} */ | |||
public void endBox() throws IFException { | |||
public void endViewport() throws IFException { | |||
restoreGraphicsState(); | |||
} | |||
@@ -348,7 +357,7 @@ public class PDFPainter extends AbstractBinaryWritingIFPainter { | |||
} | |||
/** | |||
* Formats a int value (normally coordinates in millipoints) as Strings. | |||
* Formats a integer value (normally coordinates in millipoints) to a String. | |||
* @param value the value (in millipoints) | |||
* @return the formatted value | |||
*/ | |||
@@ -494,7 +503,7 @@ public class PDFPainter extends AbstractBinaryWritingIFPainter { | |||
} | |||
textutil.writeTJMappedChar(ch); | |||
if (dx != null && i < dxl) { | |||
if (dx != null && i < dxl - 1) { | |||
glyphAdjust += dx[i + 1]; | |||
} | |||
@@ -83,16 +83,14 @@ public abstract class AbstractSVGPainter extends AbstractXMLWritingIFPainter | |||
} | |||
/** {@inheritDoc} */ | |||
public void startBox(AffineTransform transform, Dimension size, boolean clip) | |||
public void startViewport(AffineTransform transform, Dimension size, Rectangle clipRect) | |||
throws IFException { | |||
StringBuffer sb = new StringBuffer(); | |||
toString(transform, sb); | |||
startBox(sb.toString(), size, clip); | |||
startViewport(sb.toString(), size, clipRect); | |||
} | |||
/** {@inheritDoc} */ | |||
public void startBox(AffineTransform[] transforms, Dimension size, boolean clip) | |||
throws IFException { | |||
private String toString(AffineTransform[] transforms) { | |||
StringBuffer sb = new StringBuffer(); | |||
for (int i = 0, c = transforms.length; i < c; i++) { | |||
if (i > 0) { | |||
@@ -100,38 +98,100 @@ public abstract class AbstractSVGPainter extends AbstractXMLWritingIFPainter | |||
} | |||
toString(transforms[i], sb); | |||
} | |||
startBox(sb.toString(), size, clip); | |||
return sb.toString(); | |||
} | |||
/** {@inheritDoc} */ | |||
public void startViewport(AffineTransform[] transforms, Dimension size, Rectangle clipRect) | |||
throws IFException { | |||
startViewport(toString(transforms), size, clipRect); | |||
} | |||
private void startBox(String transform, Dimension size, boolean clip) throws IFException { | |||
private void startViewport(String transform, Dimension size, Rectangle clipRect) | |||
throws IFException { | |||
try { | |||
establish(MODE_NORMAL); | |||
AttributesImpl atts = new AttributesImpl(); | |||
atts.addAttribute("", "transform", "transform", CDATA, transform); | |||
/* | |||
if (size != null) { | |||
atts.addAttribute("", "width", "width", CDATA, Integer.toString(size.width)); | |||
atts.addAttribute("", "height", "height", CDATA, Integer.toString(size.height)); | |||
if (transform != null && transform.length() > 0) { | |||
atts.addAttribute("", "transform", "transform", CDATA, transform); | |||
} | |||
if (clip) { | |||
atts.addAttribute("", "clip", "clip", CDATA, "true"); | |||
}*/ | |||
startElement("g", atts); | |||
atts.clear(); | |||
atts.addAttribute("", "width", "width", CDATA, Integer.toString(size.width)); | |||
atts.addAttribute("", "height", "height", CDATA, Integer.toString(size.height)); | |||
if (clipRect != null) { | |||
int[] v = new int[] { | |||
clipRect.y, | |||
-clipRect.x + size.width - clipRect.width, | |||
-clipRect.y + size.height - clipRect.height, | |||
clipRect.x}; | |||
int sum = 0; | |||
for (int i = 0; i < 4; i++) { | |||
sum += Math.abs(v[i]); | |||
} | |||
if (sum != 0) { | |||
StringBuffer sb = new StringBuffer("rect("); | |||
sb.append(v[0]).append(','); | |||
sb.append(v[1]).append(','); | |||
sb.append(v[2]).append(','); | |||
sb.append(v[3]).append(')'); | |||
atts.addAttribute("", "clip", "clip", CDATA, sb.toString()); | |||
} | |||
atts.addAttribute("", "overflow", "overflow", CDATA, "hidden"); | |||
} else { | |||
atts.addAttribute("", "overflow", "overflow", CDATA, "visible"); | |||
} | |||
startElement("svg", atts); | |||
} catch (SAXException e) { | |||
throw new IFException("SAX error in startBox()", e); | |||
} | |||
} | |||
/** {@inheritDoc} */ | |||
public void endBox() throws IFException { | |||
public void endViewport() throws IFException { | |||
try { | |||
establish(MODE_NORMAL); | |||
endElement("svg"); | |||
endElement("g"); | |||
} catch (SAXException e) { | |||
throw new IFException("SAX error in endBox()", e); | |||
} | |||
} | |||
/** {@inheritDoc} */ | |||
public void startGroup(AffineTransform[] transforms) throws IFException { | |||
startGroup(toString(transforms)); | |||
} | |||
/** {@inheritDoc} */ | |||
public void startGroup(AffineTransform transform) throws IFException { | |||
StringBuffer sb = new StringBuffer(); | |||
toString(transform, sb); | |||
startGroup(sb.toString()); | |||
} | |||
private void startGroup(String transform) throws IFException { | |||
try { | |||
AttributesImpl atts = new AttributesImpl(); | |||
if (transform != null && transform.length() > 0) { | |||
atts.addAttribute("", "transform", "transform", CDATA, transform); | |||
} | |||
startElement("g", atts); | |||
} catch (SAXException e) { | |||
throw new IFException("SAX error in startGroup()", e); | |||
} | |||
} | |||
/** {@inheritDoc} */ | |||
public void endGroup() throws IFException { | |||
try { | |||
endElement("g"); | |||
} catch (SAXException e) { | |||
throw new IFException("SAX error in endGroup()", e); | |||
} | |||
} | |||
/** {@inheritDoc} */ | |||
public void startImage(Rectangle rect) throws IFException { | |||
//establish(MODE_NORMAL); |
@@ -133,7 +133,16 @@ public class SVGPainter extends AbstractSVGPainter { | |||
public void startPage(int index, String name, Dimension size) throws IFException { | |||
OutputStream out; | |||
try { | |||
out = this.multiFileUtil.createOutputStream(index); | |||
if (index == 0) { | |||
out = null; | |||
} else { | |||
out = this.multiFileUtil.createOutputStream(index); | |||
if (out == null) { | |||
//TODO Convert to event | |||
throw new IFException( | |||
"No filename information available. Stopping after first page.", null); | |||
} | |||
} | |||
} catch (IOException ioe) { | |||
throw new IFException("I/O exception while setting up output file", ioe); | |||
} |