diff options
author | Jeremias Maerki <jeremias@apache.org> | 2008-11-21 18:17:47 +0000 |
---|---|---|
committer | Jeremias Maerki <jeremias@apache.org> | 2008-11-21 18:17:47 +0000 |
commit | 9d339f0968314f0cfcc4a720628fed1845292ce1 (patch) | |
tree | ee0ff6bd4f29d79bc6f5f55aa4c6d67b10a37c2d /src/java | |
parent | be4dc692db093ec6b8039d7e61804e28f1709db4 (diff) | |
parent | 0d4aac57ebb98f2a40dce9ccd24027d8ab268782 (diff) | |
download | xmlgraphics-fop-9d339f0968314f0cfcc4a720628fed1845292ce1.tar.gz xmlgraphics-fop-9d339f0968314f0cfcc4a720628fed1845292ce1.zip |
Merged from Trunk revisions 706551 to 719661.
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_AreaTreeNewDesign@719664 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src/java')
26 files changed, 651 insertions, 394 deletions
diff --git a/src/java/org/apache/fop/area/Block.java b/src/java/org/apache/fop/area/Block.java index 7a2465859..5faec9f7a 100644 --- a/src/java/org/apache/fop/area/Block.java +++ b/src/java/org/apache/fop/area/Block.java @@ -79,7 +79,7 @@ public class Block extends BlockParent { * @param autoHeight increase the height of the block. */ public void addBlock(Block block, boolean autoHeight) { - if (autoHeight && allowBPDUpdate) { + if (autoHeight && allowBPDUpdate && block.isStacked()) { bpd += block.getAllocBPD(); } addChildArea(block); diff --git a/src/java/org/apache/fop/fo/XMLObj.java b/src/java/org/apache/fop/fo/XMLObj.java index 256700aa7..a73eda2e9 100644 --- a/src/java/org/apache/fop/fo/XMLObj.java +++ b/src/java/org/apache/fop/fo/XMLObj.java @@ -217,6 +217,7 @@ public abstract class XMLObj extends FONode implements ObjectBuiltListener { /** {@inheritDoc} */ public void notifyObjectBuilt(Object obj) { this.doc = (Document)obj; + this.element = this.doc.getDocumentElement(); } } diff --git a/src/java/org/apache/fop/fo/extensions/svg/SVGDOMContentHandlerFactory.java b/src/java/org/apache/fop/fo/extensions/svg/SVGDOMContentHandlerFactory.java new file mode 100644 index 000000000..6556c7251 --- /dev/null +++ b/src/java/org/apache/fop/fo/extensions/svg/SVGDOMContentHandlerFactory.java @@ -0,0 +1,151 @@ +/* + * 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.fo.extensions.svg; + +import javax.xml.transform.TransformerConfigurationException; +import javax.xml.transform.dom.DOMResult; +import javax.xml.transform.sax.SAXTransformerFactory; +import javax.xml.transform.sax.TransformerHandler; + +import org.w3c.dom.DOMImplementation; +import org.w3c.dom.Document; + +import org.xml.sax.Attributes; +import org.xml.sax.ContentHandler; +import org.xml.sax.SAXException; + +import org.apache.batik.dom.svg.SVGDOMImplementation; + +import org.apache.fop.util.ContentHandlerFactory; +import org.apache.fop.util.DelegatingContentHandler; + +/** + * ContentHandlerFactory which constructs ContentHandlers that build SVG DOM + * Documents. + */ +public class SVGDOMContentHandlerFactory implements ContentHandlerFactory { + + private static SAXTransformerFactory tFactory + = (SAXTransformerFactory)SAXTransformerFactory.newInstance(); + + /** + * Default Constructor. + */ + public SVGDOMContentHandlerFactory() { + // nop + } + + /** {@inheritDoc} */ + public String[] getSupportedNamespaces() { + return new String[] {SVGDOMImplementation.SVG_NAMESPACE_URI}; + } + + /** {@inheritDoc} */ + public ContentHandler createContentHandler() throws SAXException { + return new Handler(); + } + + private static class Handler extends DelegatingContentHandler implements + ContentHandlerFactory.ObjectSource { + + private Document doc; + private ObjectBuiltListener obListener; + + public Handler() throws SAXException { + super(); + } + + public Document getDocument() { + return this.doc; + } + + /** {@inheritDoc} */ + public Object getObject() { + return getDocument(); + } + + /** {@inheritDoc} */ + public void setObjectBuiltListener(ObjectBuiltListener listener) { + this.obListener = listener; + } + + /** {@inheritDoc} */ + public void startDocument() throws SAXException { + // Suppress startDocument() call if doc has not been set, yet. It + // will be done later. + if (doc != null) { + super.startDocument(); + } + } + + private DOMImplementation getDOMImplementation(String ver) { + //TODO It would be great if Batik provided this method as static helper method. + if (ver == null || ver.length() == 0 + || ver.equals("1.0") || ver.equals("1.1")) { + return SVGDOMImplementation.getDOMImplementation(); + } else if (ver.equals("1.2")) { + try { + Class clazz = Class.forName( + "org.apache.batik.dom.svg12.SVG12DOMImplementation"); + return (DOMImplementation)clazz.getMethod( + "getDOMImplementation", null).invoke(null, null); + } catch (Exception e) { + return SVGDOMImplementation.getDOMImplementation(); + } + } + throw new RuntimeException("Unsupport SVG version '" + ver + "'"); + } + + /** {@inheritDoc} */ + public void startElement(String uri, String localName, String qName, Attributes atts) + throws SAXException { + if (doc == null) { + TransformerHandler handler; + try { + handler = tFactory.newTransformerHandler(); + } catch (TransformerConfigurationException e) { + throw new SAXException("Error creating a new TransformerHandler", e); + } + String version = atts.getValue("version"); + DOMImplementation domImplementation = getDOMImplementation(version); + doc = domImplementation.createDocument(uri, qName, null); + // It's easier to work with an empty document, so remove the + // root element + doc.removeChild(doc.getDocumentElement()); + handler.setResult(new DOMResult(doc)); + setDelegateContentHandler(handler); + setDelegateLexicalHandler(handler); + setDelegateDTDHandler(handler); + handler.startDocument(); + } + super.startElement(uri, localName, qName, atts); + } + + /** {@inheritDoc} */ + public void endDocument() throws SAXException { + super.endDocument(); + if (obListener != null) { + obListener.notifyObjectBuilt(getObject()); + } + } + + } + +} diff --git a/src/java/org/apache/fop/fo/extensions/svg/SVGElement.java b/src/java/org/apache/fop/fo/extensions/svg/SVGElement.java index a40b80190..72cf19bc7 100644 --- a/src/java/org/apache/fop/fo/extensions/svg/SVGElement.java +++ b/src/java/org/apache/fop/fo/extensions/svg/SVGElement.java @@ -20,35 +20,27 @@ package org.apache.fop.fo.extensions.svg; // FOP -import org.apache.fop.apps.FOPException; -import org.apache.fop.fo.FONode; -import org.apache.fop.fo.PropertyList; -import org.apache.fop.util.ContentHandlerFactory; -import org.apache.fop.util.DOMBuilderContentHandlerFactory; +import java.awt.geom.AffineTransform; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.net.URL; + +import org.w3c.dom.Element; +import org.apache.batik.bridge.UnitProcessor; +import org.apache.batik.dom.svg.SVGContext; +import org.apache.batik.dom.svg.SVGDOMImplementation; import org.apache.batik.dom.svg.SVGOMDocument; import org.apache.batik.dom.svg.SVGOMElement; -import org.apache.batik.dom.svg.SVGContext; import org.apache.batik.dom.util.XMLSupport; -import org.w3c.dom.Element; -import org.w3c.dom.svg.SVGDocument; -import org.xml.sax.Attributes; -import org.xml.sax.Locator; -import org.apache.batik.bridge.UnitProcessor; import org.apache.batik.util.SVGConstants; -import org.w3c.dom.DOMImplementation; - -import org.apache.batik.dom.svg.SVGDOMImplementation; - -import java.net.URL; -import java.awt.geom.AffineTransform; -import java.awt.geom.Point2D; -import java.awt.geom.Rectangle2D; +import org.apache.fop.fo.FONode; +import org.apache.fop.util.ContentHandlerFactory; /** - * class representing the SVG root element - * for constructing an svg document. + * Class representing the SVG root element + * for constructing an SVG document. */ public class SVGElement extends SVGObj { @@ -61,21 +53,9 @@ public class SVGElement extends SVGObj { super(parent); } - /** - * {@inheritDoc} - */ + /** {@inheritDoc} */ public ContentHandlerFactory getContentHandlerFactory() { - return new DOMBuilderContentHandlerFactory(getNamespaceURI(), - SVGDOMImplementation.getDOMImplementation()); - } - - /** - * {@inheritDoc} - */ - public void processNode(String elementName, Locator locator, - Attributes attlist, PropertyList propertyList) throws FOPException { - super.processNode(elementName, locator, attlist, propertyList); - init(); + return new SVGDOMContentHandlerFactory(); } /** @@ -104,7 +84,6 @@ public class SVGElement extends SVGObj { log.error("Could not set base URL for svg", e); } - Element e = ((SVGDocument)doc).getRootElement(); final float ptmm = getUserAgent().getSourcePixelUnitToMillimeter(); // temporary svg context SVGContext dc = new SVGContext() { @@ -157,7 +136,8 @@ public class SVGElement extends SVGObj { public void deselectAll() { } }; - ((SVGOMElement)e).setSVGContext(dc); + SVGOMElement e = (SVGOMElement)svgRoot; + e.setSVGContext(dc); //if (!e.hasAttributeNS(XMLSupport.XMLNS_NAMESPACE_URI, "xmlns")) { e.setAttributeNS(XMLSupport.XMLNS_NAMESPACE_URI, "xmlns", @@ -165,21 +145,11 @@ public class SVGElement extends SVGObj { //} int fontSize = 12; Point2D p2d = getSize(fontSize, svgRoot, getUserAgent().getSourcePixelUnitToMillimeter()); - ((SVGOMElement)e).setSVGContext(null); + e.setSVGContext(null); return p2d; } - private void init() { - DOMImplementation impl = SVGDOMImplementation.getDOMImplementation(); - String svgNS = SVGDOMImplementation.SVG_NAMESPACE_URI; - doc = impl.createDocument(svgNS, "svg", null); - - element = doc.getDocumentElement(); - - buildTopLevel(doc, element); - } - /** * Get the size of the SVG root element. * @param size the font size diff --git a/src/java/org/apache/fop/fonts/Font.java b/src/java/org/apache/fop/fonts/Font.java index de6904d9b..ebd45457d 100644 --- a/src/java/org/apache/fop/fonts/Font.java +++ b/src/java/org/apache/fop/fonts/Font.java @@ -64,16 +64,16 @@ public class Font { /** logger */ private static Log log = LogFactory.getLog(Font.class); - private String fontName; - private FontTriplet triplet; - private int fontSize; + private final String fontName; + private final FontTriplet triplet; + private final int fontSize; /** * normal or small-caps font */ //private int fontVariant; - private FontMetrics metric; + private final FontMetrics metric; /** * Main constructor @@ -268,7 +268,8 @@ public class Font { width = getCharWidth(' '); } else { if (hasChar(c)) { - width = getWidth(mapChar(c)); + int mappedChar = mapChar(c); + width = getWidth(mappedChar); } else { width = -1; } diff --git a/src/java/org/apache/fop/fonts/FontCache.java b/src/java/org/apache/fop/fonts/FontCache.java index 2528989bb..fceeacb7b 100644 --- a/src/java/org/apache/fop/fonts/FontCache.java +++ b/src/java/org/apache/fop/fonts/FontCache.java @@ -48,7 +48,7 @@ public final class FontCache implements Serializable { * Serialization Version UID. Change this value if you want to make sure the user's cache * file is purged after an update. */ - private static final long serialVersionUID = 605232520271754718L; + private static final long serialVersionUID = 605232520271754719L; /** logging instance */ private static Log log = LogFactory.getLog(FontCache.class); @@ -64,7 +64,7 @@ public final class FontCache implements Serializable { private transient boolean changed = false; /** change lock */ - private transient Object changeLock = new Object(); + private final boolean[] changeLock = new boolean[1]; /** master mapping of font url -> font info. This needs to be * a list, since a TTC file may contain more than 1 font. */ @@ -80,12 +80,6 @@ public final class FontCache implements Serializable { //nop } - private void readObject(java.io.ObjectInputStream in) - throws IOException, ClassNotFoundException { - in.defaultReadObject(); - this.changeLock = new Object(); //Initialize transient field - } - private static File getUserHome() { String s = System.getProperty("user.home"); if (s != null) { @@ -226,10 +220,8 @@ public final class FontCache implements Serializable { * @return boolean */ public boolean containsFont(String embedUrl) { - if (embedUrl != null) { - return getFontFileMap().containsKey(embedUrl); - } - return false; + return (embedUrl != null + && getFontFileMap().containsKey(embedUrl)); } /** @@ -238,10 +230,8 @@ public final class FontCache implements Serializable { * @return font */ public boolean containsFont(EmbedFontInfo fontInfo) { - if (fontInfo != null) { - return getFontFileMap().containsKey(getCacheKey(fontInfo)); - } - return false; + return (fontInfo != null + && getFontFileMap().containsKey(getCacheKey(fontInfo))); } /** @@ -316,10 +306,7 @@ public final class FontCache implements Serializable { * @return CachedFontFile object */ public CachedFontFile getFontFile(String embedUrl) { - if (containsFont(embedUrl)) { - return (CachedFontFile)getFontFileMap().get(embedUrl); - } - return null; + return containsFont(embedUrl) ? (CachedFontFile) getFontFileMap().get(embedUrl) : null; } /** @@ -362,8 +349,8 @@ public final class FontCache implements Serializable { * @return whether this is a failed font */ public boolean isFailedFont(String embedUrl, long lastModified) { - if (getFailedFontMap().containsKey(embedUrl)) { - synchronized (changeLock) { + synchronized (changeLock) { + if (getFailedFontMap().containsKey(embedUrl)) { long failedLastModified = ((Long)getFailedFontMap().get(embedUrl)).longValue(); if (lastModified != failedLastModified) { // this font has been changed so lets remove it @@ -371,10 +358,11 @@ public final class FontCache implements Serializable { getFailedFontMap().remove(embedUrl); changed = true; } + return true; + } else { + return false; } - return true; } - return false; } /** @@ -457,10 +445,8 @@ public final class FontCache implements Serializable { } public boolean containsFont(EmbedFontInfo efi) { - if (efi.getPostScriptName() != null) { - return getFileFontsMap().containsKey(efi.getPostScriptName()); - } - return false; + return efi.getPostScriptName() != null + && getFileFontsMap().containsKey(efi.getPostScriptName()); } public EmbedFontInfo[] getEmbedFontInfos() { diff --git a/src/java/org/apache/fop/fonts/FontSetup.java b/src/java/org/apache/fop/fonts/FontSetup.java index eea04a580..f7ad6fc65 100644 --- a/src/java/org/apache/fop/fonts/FontSetup.java +++ b/src/java/org/apache/fop/fonts/FontSetup.java @@ -27,7 +27,6 @@ import javax.xml.transform.stream.StreamSource; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; - import org.apache.fop.fonts.base14.Courier; import org.apache.fop.fonts.base14.CourierBold; import org.apache.fop.fonts.base14.CourierBoldOblique; @@ -202,7 +201,7 @@ public class FontSetup { if (resolver == null) { //Ensure that we have minimal font resolution capabilities - resolver = createMinimalFontResolver1(); + resolver = createMinimalFontResolver(); } String internalName = null; @@ -225,7 +224,7 @@ public class FontSetup { } /** @return a new FontResolver to be used by the font subsystem */ - public static FontResolver createMinimalFontResolver1() { + public static FontResolver createMinimalFontResolver() { return new FontResolver() { /** {@inheritDoc} */ diff --git a/src/java/org/apache/fop/fonts/truetype/TTFFile.java b/src/java/org/apache/fop/fonts/truetype/TTFFile.java index 409b3908b..7198888f1 100644 --- a/src/java/org/apache/fop/fonts/truetype/TTFFile.java +++ b/src/java/org/apache/fop/fonts/truetype/TTFFile.java @@ -1248,10 +1248,11 @@ public class TTFFile { } } - log.debug("Font box height: " + (ascender - descender)); - if (ascender - descender > upem) { - log.warn("Ascender and descender together are larger than the em box." - + " This could lead to a wrong baseline placement in Apache FOP."); + if (log.isDebugEnabled()) { + log.debug("Font box height: " + (ascender - descender)); + if (ascender - descender > upem) { + log.debug("Ascender and descender together are larger than the em box."); + } } } @@ -1259,7 +1260,7 @@ public class TTFFile { // Approximate capHeight from height of "H" // It's most unlikely that a font misses the PCLT table // This also assumes that postscriptnames exists ("H") - // Should look it up int the cmap (that wouldn't help + // Should look it up in the cmap (that wouldn't help // for charsets without H anyway...) // Same for xHeight with the letter "x" int localCapHeight = 0; @@ -1294,10 +1295,12 @@ public class TTFFile { } } } - log.debug("Ascender from glyph 'd': " + localAscender - + " " + convertTTFUnit2PDFUnit(localAscender)); - log.debug("Descender from glyph 'p': " + localDescender - + " " + convertTTFUnit2PDFUnit(localDescender)); + if (log.isDebugEnabled()) { + log.debug("Ascender from glyph 'd': " + localAscender + + " " + convertTTFUnit2PDFUnit(localAscender)); + log.debug("Descender from glyph 'p': " + localDescender + + " " + convertTTFUnit2PDFUnit(localDescender)); + } if (ascender - descender > upem) { log.debug("Replacing specified ascender/descender with derived values to get values" + " which fit in the em box."); @@ -1305,10 +1308,12 @@ public class TTFFile { descender = localDescender; } - log.debug("xHeight from glyph 'x': " + localXHeight - + " " + convertTTFUnit2PDFUnit(localXHeight)); - log.debug("CapHeight from glyph 'H': " + localCapHeight - + " " + convertTTFUnit2PDFUnit(localCapHeight)); + if (log.isDebugEnabled()) { + log.debug("xHeight from glyph 'x': " + localXHeight + + " " + convertTTFUnit2PDFUnit(localXHeight)); + log.debug("CapHeight from glyph 'H': " + localCapHeight + + " " + convertTTFUnit2PDFUnit(localCapHeight)); + } if (capHeight == 0) { capHeight = localCapHeight; if (capHeight == 0) { diff --git a/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java b/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java index 293d6dbe0..42f08a42d 100644 --- a/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java @@ -50,8 +50,6 @@ public class FlowLayoutManager extends BlockStackingLayoutManager /** Array of areas currently being filled stored by area class */ private BlockParent[] currentAreas = new BlockParent[Area.CLASS_MAX]; - private int currentSpan = EN_NONE; - /** * This is the top level layout manager. * It is created by the PageSequence FO. @@ -89,10 +87,11 @@ public class FlowLayoutManager extends BlockStackingLayoutManager } else if (curLM instanceof BlockContainerLayoutManager) { span = ((BlockContainerLayoutManager)curLM).getBlockContainerFO().getSpan(); } + + int currentSpan = context.getCurrentSpan(); if (currentSpan != span) { log.debug("span change from " + currentSpan + " to " + span); context.signalSpanChange(span); - currentSpan = span; SpaceResolver.resolveElementList(returnList); return returnList; } @@ -228,7 +227,7 @@ public class FlowLayoutManager extends BlockStackingLayoutManager oldElement = (KnuthElement)oldListIterator.next(); if (oldElement.getPosition() instanceof NonLeafPosition) { // oldElement was created by a descendant of this FlowLM - oldElement.setPosition(((NonLeafPosition)oldElement.getPosition()).getPosition()); + oldElement.setPosition((oldElement.getPosition()).getPosition()); } else { // thisElement was created by this FlowLM, remove it oldListIterator.remove(); @@ -344,7 +343,7 @@ public class FlowLayoutManager extends BlockStackingLayoutManager * @return the BPD of the content area */ public int getContentAreaBPD() { - return (int) getCurrentPV().getBodyRegion().getBPD(); + return getCurrentPV().getBodyRegion().getBPD(); } } diff --git a/src/java/org/apache/fop/layoutmgr/LayoutContext.java b/src/java/org/apache/fop/layoutmgr/LayoutContext.java index 8b716dfde..3526ed239 100644 --- a/src/java/org/apache/fop/layoutmgr/LayoutContext.java +++ b/src/java/org/apache/fop/layoutmgr/LayoutContext.java @@ -88,7 +88,8 @@ public class LayoutContext { */ private MinOptMax stackLimitIP; - /** True if current element list is spanning in multi-column layout. */ + /** to keep track of spanning in multi-column layout */ + private int currentSpan = Constants.NOT_SET; private int nextSpan = Constants.NOT_SET; /** inline-progression-dimension of nearest ancestor reference area */ @@ -522,22 +523,37 @@ public class LayoutContext { } /** - * @return true if the current element list ends early because of a span change - * in multi-column layout. + * @return one of: {@link Constants#NOT_SET}, {@link Constants#EN_NONE} + * {@link Constants#EN_ALL} */ public int getNextSpan() { return nextSpan; } /** + * @return one of: {@link Constants#NOT_SET}, {@link Constants#EN_NONE} + * {@link Constants#EN_ALL} + */ + public int getCurrentSpan() { + return (currentSpan == Constants.NOT_SET) + ? Constants.EN_NONE : currentSpan; + } + + /** * Used to signal the PSLM that the element list ends early because of a span change in * multi-column layout. * @param span the new span value (legal values: NOT_SET, EN_NONE, EN_ALL) */ public void signalSpanChange(int span) { - if (span == Constants.NOT_SET || span == Constants.EN_NONE || span == Constants.EN_ALL) { + switch (span) { + case Constants.NOT_SET: + case Constants.EN_NONE: + case Constants.EN_ALL: + this.currentSpan = this.nextSpan; this.nextSpan = span; - } else { + break; + default: + assert false; throw new IllegalArgumentException("Illegal value on signalSpanChange() for span: " + span); } diff --git a/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java index 459bce0e8..27ed38b53 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java @@ -910,7 +910,7 @@ public class TextLayoutManager extends LeafNodeLayoutManager { } startIndex = stopIndex; } - this.hasChanged = !nothingChanged; + this.hasChanged = (this.hasChanged || !nothingChanged); } /** {@inheritDoc} */ diff --git a/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java b/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java index d83cca642..a4e8982f7 100644 --- a/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java @@ -26,6 +26,7 @@ import java.util.ListIterator; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.apache.fop.area.Area; import org.apache.fop.area.Block; import org.apache.fop.fo.flow.ListItem; @@ -537,14 +538,6 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager label.addAreas(labelIter, lc); } - // reset the area bpd after adding the label areas and before adding the body areas - int savedBPD = 0; - if (labelFirstIndex <= labelLastIndex - && bodyFirstIndex <= bodyLastIndex) { - savedBPD = curBlockArea.getBPD(); - curBlockArea.setBPD(0); - } - // add body areas if (bodyFirstIndex <= bodyLastIndex) { KnuthPossPosIter bodyIter = new KnuthPossPosIter(bodyList, @@ -559,9 +552,13 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager } // after adding body areas, set the maximum area bpd - if (curBlockArea.getBPD() < savedBPD) { - curBlockArea.setBPD(savedBPD); + int childCount = curBlockArea.getChildAreas().size(); + assert childCount >= 1 && childCount <= 2; + int itemBPD = ((Block)curBlockArea.getChildAreas().get(0)).getAllocBPD(); + if (childCount == 2) { + itemBPD = Math.max(itemBPD, ((Block)curBlockArea.getChildAreas().get(1)).getAllocBPD()); } + curBlockArea.setBPD(itemBPD); addMarkersToPage(false, isFirst(firstPos), isLast(lastPos)); diff --git a/src/java/org/apache/fop/pdf/PDFDocument.java b/src/java/org/apache/fop/pdf/PDFDocument.java index 16ec81049..598fd433e 100644 --- a/src/java/org/apache/fop/pdf/PDFDocument.java +++ b/src/java/org/apache/fop/pdf/PDFDocument.java @@ -224,6 +224,11 @@ public class PDFDocument { protected List gotos = new java.util.ArrayList(); /** + * List of PDFLaunch objects. + */ + protected List launches = new java.util.ArrayList(); + + /** * The PDFDests object for the name dictionary. * Note: This object is not a list. */ @@ -486,6 +491,9 @@ public class PDFDocument { if (obj instanceof PDFPage) { this.pages.notifyKidRegistered((PDFPage)obj); } + if (obj instanceof PDFLaunch) { + this.launches.add(obj); + } if (obj instanceof PDFLink) { this.links.add(obj); } @@ -657,6 +665,15 @@ public class PDFDocument { } /** + * Finds a launch. + * @param compare reference object to use as search template + * @return the launch if found, null otherwise + */ + protected PDFLaunch findLaunch(PDFLaunch compare) { + return (PDFLaunch) findPDFObject(launches, compare); + } + + /** * Looks for an existing GState to use * @param wanted requested features * @param current currently active features @@ -703,7 +720,6 @@ public class PDFDocument { */ public void setColorSpace(int theColorspace) { this.colorspace.setColorSpace(theColorspace); - return; } /** @@ -1019,12 +1035,6 @@ public class PDFDocument { by the table's length */ this.position += outputXref(stream); - // Determine existance of encryption dictionary - String encryptEntry = ""; - if (this.encryption != null) { - encryptEntry = this.encryption.getTrailerEntry(); - } - /* construct the trailer */ String pdf = "trailer\n" @@ -1037,10 +1047,13 @@ public class PDFDocument { + "\n" + "/Info " + this.info.referencePDF() - + "\n" - + getIDEntry() - + "\n" - + encryptEntry + + "\n"; + if (this.encryption != null) { + pdf += this.encryption.getTrailerEntry(); + } else { + pdf += getIDEntry(); + } + pdf += "\n" + ">>\n" + "startxref\n" + this.xref diff --git a/src/java/org/apache/fop/pdf/PDFFactory.java b/src/java/org/apache/fop/pdf/PDFFactory.java index fc6e6b9fa..a5beb4ec7 100644 --- a/src/java/org/apache/fop/pdf/PDFFactory.java +++ b/src/java/org/apache/fop/pdf/PDFFactory.java @@ -1011,6 +1011,10 @@ public class PDFFactory { // HTTP URL? if (targetLo.startsWith("http://")) { return new PDFUri(target); + // Non PDF files. Try to /Launch them. + } else if (targetLo.startsWith("file://")) { + target = target.substring("file://".length()); + return getLaunchAction(target); // Bare PDF file name? } else if (targetLo.endsWith(".pdf")) { return getGoToPDFAction(target, null, -1, newWindow); @@ -1105,6 +1109,37 @@ public class PDFFactory { } /** + * Creates and returns a launch pdf document action using + * <code>file</code> to create a file spcifiaciton for + * the document/file to be opened with an external application. + * + * @param file the pdf file name + * @return the pdf launch object + */ + private PDFLaunch getLaunchAction(String file) { + getDocument().getProfile().verifyActionAllowed(); + + PDFFileSpec fileSpec = new PDFFileSpec(file); + PDFFileSpec oldSpec = getDocument().findFileSpec(fileSpec); + + if (oldSpec == null) { + getDocument().registerObject(fileSpec); + } else { + fileSpec = oldSpec; + } + PDFLaunch launch = new PDFLaunch(fileSpec); + PDFLaunch oldLaunch = getDocument().findLaunch(launch); + + if (oldLaunch == null) { + getDocument().registerObject(launch); + } else { + launch = oldLaunch; + } + + return launch; + } + + /** * Make an outline object and add it to the given parent * * @param parent the parent PDFOutline object (may be null) diff --git a/src/java/org/apache/fop/pdf/PDFLaunch.java b/src/java/org/apache/fop/pdf/PDFLaunch.java new file mode 100644 index 000000000..d87fa2523 --- /dev/null +++ b/src/java/org/apache/fop/pdf/PDFLaunch.java @@ -0,0 +1,68 @@ +/* + * 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.pdf; + +/** + * This class represents the /Launch action. + */ +public class PDFLaunch extends PDFAction { + + private PDFFileSpec externalFileSpec; + + public PDFLaunch(PDFFileSpec fileSpec) { + this.externalFileSpec = fileSpec; + } + + public String getAction() { + return this.referencePDF(); + } + + public String toPDFString() { + StringBuffer sb = new StringBuffer(64); + sb.append(getObjectID()); + sb.append("<<\n/S /Launch\n/F "); + sb.append(externalFileSpec.referencePDF()); + sb.append(" \n>>\nendobj\n"); + + return sb.toString(); + } + + /** + * Check if this equals another object. + * + * @param obj the object to compare + * @return true if this equals other object + */ + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + + if (obj == null || !(obj instanceof PDFLaunch)) { + return false; + } + + PDFLaunch launch = (PDFLaunch) obj; + + if (!launch.externalFileSpec.referencePDF().equals(externalFileSpec.referencePDF())) { + return false; + } + + return true; + } +} diff --git a/src/java/org/apache/fop/render/afp/fonts/AFPFontReader.java b/src/java/org/apache/fop/render/afp/fonts/AFPFontReader.java index 7951be26c..0c190738c 100644 --- a/src/java/org/apache/fop/render/afp/fonts/AFPFontReader.java +++ b/src/java/org/apache/fop/render/afp/fonts/AFPFontReader.java @@ -26,12 +26,11 @@ import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; -import java.util.ArrayList; -import java.util.HashMap; +import java.util.List; +import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.apache.fop.render.afp.exceptions.FontRuntimeException; import org.apache.fop.render.afp.modca.AFPConstants; import org.apache.fop.render.afp.tools.StructuredFieldReader; @@ -111,143 +110,19 @@ public final class AFPFontReader { /** * The collection of code pages */ - private HashMap codePages = new HashMap(); + private final Map/*<String, Map<String, String>>*/ codePages + = new java.util.HashMap/*<String, Map<String, String>>*/(); /** - * Load the font details and metrics into the CharacterSetMetric object, - * this will use the actual afp code page and character set files to load - * the object with the necessary metrics. + * Returns an InputStream to a given file path and filename * - * @param characterSet the CharacterSetMetric object to populate - */ - public void loadCharacterSetMetric(CharacterSet characterSet) { - - InputStream inputStream = null; - - try { - - /** - * Get the code page which contains the character mapping - * information to map the unicode character id to the graphic - * chracter global identifier. - */ - String cp = new String(characterSet.getCodePage()); - String path = characterSet.getPath(); - - HashMap codepage = (HashMap) codePages.get(cp); - - if (codepage == null) { - codepage = loadCodePage(cp, characterSet.getEncoding(), path); - codePages.put(cp, codepage); - } - - /** - * Load the character set metric information, no need to cache this - * information as it should be cached by the objects that wish to - * load character set metric information. - */ - final String characterset = characterSet.getName(); - - ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - if (classLoader == null) { - classLoader = AFPFontReader.class.getClassLoader(); - } - - URL url = classLoader.getResource(path); - if (url == null) { - try { - File file = new File(path); - url = file.toURI().toURL(); - if (url == null) { - String msg = "CharacterSet file not found for " - + characterset + " in classpath: " + path; - log.error(msg); - throw new FileNotFoundException(msg); - } - } catch (MalformedURLException ex) { - String msg = "CharacterSet file not found for " - + characterset + " in classpath: " + path; - log.error(msg); - throw new FileNotFoundException(msg); - } - - } - - File directory = new File(url.getPath()); - - final String filterpattern = characterset.trim(); - FilenameFilter filter = new FilenameFilter() { - public boolean accept(File dir, String name) { - return name.startsWith(filterpattern); - } - }; - - File[] csfont = directory.listFiles(filter); - if (csfont.length < 1) { - String msg = "CharacterSet file search for " + characterset - + " located " + csfont.length + " files"; - log.error(msg); - throw new FileNotFoundException(msg); - } else if (csfont.length > 1) { - String msg = "CharacterSet file search for " + characterset - + " located " + csfont.length + " files"; - log.warn(msg); - } - - inputStream = csfont[0].toURI().toURL().openStream(); - if (inputStream == null) { - String msg = "Failed to open character set resource " - + characterset; - log.error(msg); - throw new FileNotFoundException(msg); - } - - StructuredFieldReader sfr = new StructuredFieldReader(inputStream); - - // Process D3A789 Font Control - FontControl fnc = processFontControl(sfr); - - //process D3AE89 Font Orientation - CharacterSetOrientation[] csoArray = processFontOrientation(sfr); - - //process D3AC89 Font Position - processFontPosition(sfr, csoArray, fnc.getDpi()); - - //process D38C89 Font Index (per orientation) - for (int i = 0; i < csoArray.length; i++) { - processFontIndex(sfr, csoArray[i], codepage, fnc.getDpi()); - characterSet.addCharacterSetOrientation(csoArray[i]); - } - - } catch (Exception ex) { - throw new FontRuntimeException( - "Failed to load the character set metrics for code page " - + characterSet.getCodePage(), ex); - } finally { - try { - inputStream.close(); - } catch (Exception ex) { - // Ignore - } - } - - } - - /** - * Load the code page information from the appropriate file. The file name - * to load is determined by the code page name and the file extension 'CDP'. + * @param path the file path + * @param filename the file name + * @return an inputStream * - * @param codePage - * the code page identifier - * @param encoding - * the encoding to use for the character decoding + * @throws IOException in the event that an I/O exception of some sort has occurred */ - private static HashMap loadCodePage(String codePage, String encoding, - String path) throws IOException { - - // Create the HashMap to store code page information - HashMap codepages = new HashMap(); - + private InputStream openInputStream(String path, String filename) throws IOException { ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); if (classLoader == null) { classLoader = AFPFontReader.class.getClassLoader(); @@ -260,14 +135,12 @@ public final class AFPFontReader { File file = new File(path); url = file.toURI().toURL(); if (url == null) { - String msg = "CodePage file not found for " + codePage - + " in classpath: " + path; + String msg = "file not found " + filename + " in classpath: " + path; log.error(msg); throw new FileNotFoundException(msg); } } catch (MalformedURLException ex) { - String msg = "CodePage file not found for " + codePage - + " in classpath: " + path; + String msg = "file not found " + filename + " in classpath: " + path; log.error(msg); throw new FileNotFoundException(msg); } @@ -280,115 +153,220 @@ public final class AFPFontReader { throw new FileNotFoundException(msg); } - final String filterpattern = codePage.trim(); + final String filterpattern = filename.trim(); FilenameFilter filter = new FilenameFilter() { public boolean accept(File dir, String name) { return name.startsWith(filterpattern); } }; - File[] codepage = directory.listFiles(filter); + File[] files = directory.listFiles(filter); - if (codepage.length < 1) { - String msg = "CodePage file search for " + codePage + " located " - + codepage.length + " files"; + if (files.length < 1) { + String msg = "file search for " + filename + " located " + + files.length + " files"; log.error(msg); throw new FileNotFoundException(msg); - } else if (codepage.length > 1) { - String msg = "CodePage file search for " + codePage + " located " - + codepage.length + " files"; + } else if (files.length > 1) { + String msg = "file search for " + filename + " located " + + files.length + " files"; log.warn(msg); } - InputStream is = codepage[0].toURI().toURL().openStream(); + InputStream inputStream = files[0].toURI().toURL().openStream(); - if (is == null) { - String msg = "AFPFontReader:: loadCodePage(String):: code page file not found for " - + codePage; + if (inputStream == null) { + String msg = "AFPFontReader:: getInputStream():: file not found for " + filename; log.error(msg); throw new FileNotFoundException(msg); } - StructuredFieldReader sfr = new StructuredFieldReader(is); - byte[] data = sfr.getNext(CHARACTER_TABLE_SF); + return inputStream; + } - int position = 0; - byte[] gcgiBytes = new byte[8]; - byte[] charBytes = new byte[1]; + /** + * Closes the inputstream + * + * @param inputStream the inputstream to close + */ + private void closeInputStream(InputStream inputStream) { + try { + if (inputStream != null) { + inputStream.close(); + } + } catch (Exception ex) { + // Lets log at least! + log.error(ex.getMessage()); + } + } - // Read data, ignoring bytes 0 - 2 - for (int index = 3; index < data.length; index++) { - if (position < 8) { - // Build the graphic character global identifier key - gcgiBytes[position] = data[index]; - position++; - } else if (position == 9) { - position = 0; - // Set the character - charBytes[0] = data[index]; - String gcgiString = new String(gcgiBytes, - AFPConstants.EBCIDIC_ENCODING); - String charString = new String(charBytes, encoding); -// int value = charString.charAt(0); - codepages.put(gcgiString, charString); + /** + * Load the font details and metrics into the CharacterSetMetric object, + * this will use the actual afp code page and character set files to load + * the object with the necessary metrics. + * + * @param characterSet the CharacterSetMetric object to populate + * @throws IOException if an I/O exception of some sort has occurred. + */ + public void loadCharacterSetMetric(CharacterSet characterSet) throws IOException { + + InputStream inputStream = null; + + try { + + /** + * Get the code page which contains the character mapping + * information to map the unicode character id to the graphic + * chracter global identifier. + */ + String codePageId = new String(characterSet.getCodePage()); + String path = characterSet.getPath(); + + Map/*<String,String>*/ codePage = (Map/*<String,String>*/)codePages.get(codePageId); + + if (codePage == null) { + codePage = loadCodePage(codePageId, characterSet.getEncoding(), path); + codePages.put(codePageId, codePage); + } + + /** + * Load the character set metric information, no need to cache this + * information as it should be cached by the objects that wish to + * load character set metric information. + */ + final String characterSetName = characterSet.getName(); + + inputStream = openInputStream(path, characterSetName); + + StructuredFieldReader structuredFieldReader = new StructuredFieldReader(inputStream); + + // Process D3A789 Font Control + FontControl fontControl = processFontControl(structuredFieldReader); + + if (fontControl != null) { + //process D3AE89 Font Orientation + CharacterSetOrientation[] characterSetOrientations + = processFontOrientation(structuredFieldReader); + + int dpi = fontControl.getDpi(); + + //process D3AC89 Font Position + processFontPosition(structuredFieldReader, characterSetOrientations, dpi); + + //process D38C89 Font Index (per orientation) + for (int i = 0; i < characterSetOrientations.length; i++) { + processFontIndex(structuredFieldReader, + characterSetOrientations[i], codePage, dpi); + characterSet.addCharacterSetOrientation(characterSetOrientations[i]); + } } else { - position++; + throw new IOException( + "Failed to read font control structured field in character set " + + characterSetName); } + + } finally { + closeInputStream(inputStream); } + } + + /** + * Load the code page information from the appropriate file. The file name + * to load is determined by the code page name and the file extension 'CDP'. + * + * @param codePage + * the code page identifier + * @param encoding + * the encoding to use for the character decoding + * @returns a code page mapping + */ + private Map/*<String,String>*/ loadCodePage(String codePage, String encoding, + String path) throws IOException { + + // Create the HashMap to store code page information + Map/*<String,String>*/ codePages = new java.util.HashMap/*<String,String>*/(); + + InputStream inputStream = null; try { - is.close(); - } catch (Exception ex) { - // Ignore + inputStream = openInputStream(path, codePage.trim()); + + StructuredFieldReader structuredFieldReader = new StructuredFieldReader(inputStream); + byte[] data = structuredFieldReader.getNext(CHARACTER_TABLE_SF); + + int position = 0; + byte[] gcgiBytes = new byte[8]; + byte[] charBytes = new byte[1]; + + // Read data, ignoring bytes 0 - 2 + for (int index = 3; index < data.length; index++) { + if (position < 8) { + // Build the graphic character global identifier key + gcgiBytes[position] = data[index]; + position++; + } else if (position == 9) { + position = 0; + // Set the character + charBytes[0] = data[index]; + String gcgiString = new String(gcgiBytes, + AFPConstants.EBCIDIC_ENCODING); + String charString = new String(charBytes, encoding); +// int value = charString.charAt(0); + codePages.put(gcgiString, charString); + } else { + position++; + } + } + } finally { + closeInputStream(inputStream); } - return codepages; - + return codePages; } /** * Process the font control details using the structured field reader. * - * @param sfr + * @param structuredFieldReader * the structured field reader */ - private static FontControl processFontControl(StructuredFieldReader sfr) + private FontControl processFontControl(StructuredFieldReader structuredFieldReader) throws IOException { - byte[] fncData = sfr.getNext(FONT_CONTROL_SF); + byte[] fncData = structuredFieldReader.getNext(FONT_CONTROL_SF); // int position = 0; + FontControl fontControl = null; + if (fncData != null) { + fontControl = new FontControl(); - FontControl fontControl = new AFPFontReader().new FontControl(); - - if (fncData[7] == (byte) 0x02) { - fontControl.setRelative(true); - } - - int dpi = (((fncData[9] & 0xFF) << 8) + (fncData[10] & 0xFF)) / 10; + if (fncData[7] == (byte) 0x02) { + fontControl.setRelative(true); + } - fontControl.setDpi(dpi); + int dpi = (((fncData[9] & 0xFF) << 8) + (fncData[10] & 0xFF)) / 10; + fontControl.setDpi(dpi); + } return fontControl; - } /** * Process the font orientation details from using the structured field * reader. * - * @param sfr + * @param structuredFieldReader * the structured field reader */ - private static CharacterSetOrientation[] processFontOrientation( - StructuredFieldReader sfr) throws IOException { + private CharacterSetOrientation[] processFontOrientation( + StructuredFieldReader structuredFieldReader) throws IOException { - byte[] data = sfr.getNext(FONT_ORIENTATION_SF); + byte[] data = structuredFieldReader.getNext(FONT_ORIENTATION_SF); int position = 0; byte[] fnoData = new byte[26]; - ArrayList orientations = new ArrayList(); + List orientations = new java.util.ArrayList(); // Read data, ignoring bytes 0 - 2 for (int index = 3; index < data.length; index++) { @@ -434,20 +412,20 @@ public final class AFPFontReader { * Populate the CharacterSetOrientation object in the suplied array with the * font position details using the supplied structured field reader. * - * @param sfr + * @param structuredFieldReader * the structured field reader - * @param csoArray + * @param characterSetOrientations * the array of CharacterSetOrientation objects */ - private static void processFontPosition(StructuredFieldReader sfr, - CharacterSetOrientation[] csoArray, int dpi) throws IOException { + private void processFontPosition(StructuredFieldReader structuredFieldReader, + CharacterSetOrientation[] characterSetOrientations, int dpi) throws IOException { - byte[] data = sfr.getNext(FONT_POSITION_SF); + byte[] data = structuredFieldReader.getNext(FONT_POSITION_SF); int position = 0; byte[] fpData = new byte[26]; - int csoIndex = 0; + int characterSetOrientationIndex = 0; int fopFactor = 0; switch (dpi) { @@ -475,7 +453,8 @@ public final class AFPFontReader { position = 0; - CharacterSetOrientation cso = csoArray[csoIndex]; + CharacterSetOrientation characterSetOrientation + = characterSetOrientations[characterSetOrientationIndex]; int xHeight = ((fpData[2] & 0xFF) << 8) + (fpData[3] & 0xFF); int capHeight = ((fpData[4] & 0xFF) << 8) + (fpData[5] & 0xFF); @@ -484,12 +463,12 @@ public final class AFPFontReader { dscHeight = dscHeight * -1; - cso.setXHeight(xHeight * fopFactor); - cso.setCapHeight(capHeight * fopFactor); - cso.setAscender(ascHeight * fopFactor); - cso.setDescender(dscHeight * fopFactor); + characterSetOrientation.setXHeight(xHeight * fopFactor); + characterSetOrientation.setCapHeight(capHeight * fopFactor); + characterSetOrientation.setAscender(ascHeight * fopFactor); + characterSetOrientation.setDescender(dscHeight * fopFactor); - csoIndex++; + characterSetOrientationIndex++; fpData[position] = data[index]; @@ -503,18 +482,18 @@ public final class AFPFontReader { /** * Process the font index details for the character set orientation. * - * @param sfr + * @param structuredFieldReader * the structured field reader * @param cso * the CharacterSetOrientation object to populate * @param codepage * the map of code pages */ - private static void processFontIndex(StructuredFieldReader sfr, - CharacterSetOrientation cso, HashMap codepage, int dpi) + private void processFontIndex(StructuredFieldReader structuredFieldReader, + CharacterSetOrientation cso, Map/*<String,String>*/ codepage, int dpi) throws IOException { - byte[] data = sfr.getNext(FONT_INDEX_SF); + byte[] data = structuredFieldReader.getNext(FONT_INDEX_SF); int fopFactor = 0; @@ -545,14 +524,14 @@ public final class AFPFontReader { // Read data, ignoring bytes 0 - 2 for (int index = 3; index < data.length; index++) { if (position < 8) { - gcgid[position] = (byte) data[index]; + gcgid[position] = data[index]; position++; } else if (position < 27) { - fiData[position - 8] = (byte) data[index]; + fiData[position - 8] = data[index]; position++; } else if (position == 27) { - fiData[position - 8] = (byte) data[index]; + fiData[position - 8] = data[index]; position = 0; diff --git a/src/java/org/apache/fop/render/afp/fonts/CharacterSet.java b/src/java/org/apache/fop/render/afp/fonts/CharacterSet.java index 434f541a4..f7680b15c 100644 --- a/src/java/org/apache/fop/render/afp/fonts/CharacterSet.java +++ b/src/java/org/apache/fop/render/afp/fonts/CharacterSet.java @@ -19,6 +19,7 @@ package org.apache.fop.render.afp.fonts; +import java.io.IOException; import java.io.UnsupportedEncodingException; import java.util.Map; @@ -49,6 +50,15 @@ public class CharacterSet { /** Static logging instance */ protected static final Log log = LogFactory.getLog(CharacterSet.class.getName()); + /** default codepage */ + protected static final String DEFAULT_CODEPAGE = "T1V10500"; + + /** default encoding */ + protected static final String DEFAULT_ENCODING = "Cp500"; + + private static final int MAX_NAME_LEN = 8; + + /** The code page to which the character set relates */ protected String codePage; @@ -64,8 +74,8 @@ public class CharacterSet { /** Indicator as to whether to metrics have been loaded */ private boolean isMetricsLoaded = false; - /** The current orientation (currently only 0 is suppoted by FOP) */ - private String currentOrientation = "0"; + /** The current orientation (currently only 0 is supported by FOP) */ + private final String currentOrientation = "0"; /** The collection of objects for each orientation */ private Map characterSetOrientations = null; @@ -79,27 +89,23 @@ public class CharacterSet { * @param name the character set name * @param path the path to the installed afp fonts */ - public CharacterSet( - String codePage, - String encoding, - String name, - String path) { - - if (name.length() > 8) { - String msg = "Character set name must be a maximum of 8 characters " + name; + public CharacterSet(String codePage, String encoding, String name, String path) { + if (name.length() > MAX_NAME_LEN) { + String msg = "Character set name '" + name + "' must be a maximum of " + + MAX_NAME_LEN + " characters"; log.error("Constructor:: " + msg); throw new IllegalArgumentException(msg); } - if (name.length() < 8) { - this.name = StringUtils.rpad(name, ' ', 8); + if (name.length() < MAX_NAME_LEN) { + this.name = StringUtils.rpad(name, ' ', MAX_NAME_LEN); } else { this.name = name; } - this.codePage = codePage; this.encoding = encoding; this.path = path; + this.characterSetOrientations = new java.util.HashMap(4); } @@ -121,7 +127,7 @@ public class CharacterSet { * a character rotation other than 0, ascender height loses its * meaning when the character is lying on its side or is upside down * with respect to normal viewing orientation. For the general case, - * Ascender Height is the character�s most positive y-axis value. + * Ascender Height is the characters most positive y-axis value. * For bounded character boxes, for a given character having an * ascender, ascender height and baseline offset are equal. * @@ -157,9 +163,9 @@ public class CharacterSet { } /** - * The first character in the character set + * Returns the first character in the character set * - * @return the first character + * @return the first character in the character set */ public int getFirstChar() { load(); @@ -169,7 +175,7 @@ public class CharacterSet { /** * Returns the last character in the character set * - * @return the last character + * @return the last character in the character set */ public int getLastChar() { load(); @@ -197,6 +203,7 @@ public class CharacterSet { /** * XHeight refers to the height of the lower case letters above the baseline. + * * @return the typical height of characters */ public int getXHeight() { @@ -211,9 +218,9 @@ public class CharacterSet { * @param character the character from which the width will be calculated * @return the width of the character */ - public int width(int character) { + public int getWidth(int character) { load(); - return getCharacterSetOrientation().width(character); + return getCharacterSetOrientation().getWidth(character); } /** @@ -223,24 +230,30 @@ public class CharacterSet { private void load() { if (!isMetricsLoaded) { AFPFontReader afpFontReader = new AFPFontReader(); - afpFontReader.loadCharacterSetMetric(this); - isMetricsLoaded = true; + try { + afpFontReader.loadCharacterSetMetric(this); + isMetricsLoaded = true; + } catch (IOException e) { + String msg = "Failed to load the character set metrics for code page " + codePage; + log.error(msg); + throw new RuntimeException(e.getMessage()); + } } } /** * Returns the AFP character set identifier * - * @return String + * @return the AFP character set identifier */ public String getName() { return name; } /** - * Returns the AFP character set identifier + * Returns the AFP character set identifier as a byte array * - * @return the AFP character set identifier + * @return the AFP character set identifier as a byte array */ public byte[] getNameBytes() { byte[] nameBytes = null; @@ -249,8 +262,7 @@ public class CharacterSet { } catch (UnsupportedEncodingException usee) { nameBytes = name.getBytes(); log.warn( - "UnsupportedEncodingException translating the name " - + name); + "UnsupportedEncodingException translating the name " + name); } return nameBytes; } @@ -281,16 +293,14 @@ public class CharacterSet { * implementation (whenever FOP implement the mechanism). This is also * the case for landscape prints which use an orientation of 270 degrees, * in 99.9% of cases the font metrics will be the same as the 0 degrees - * therefore the implementation currely will always use 0 degrees. + * therefore the implementation currently will always use 0 degrees. * * @return characterSetOrentation The current orientation metrics. */ private CharacterSetOrientation getCharacterSetOrientation() { - CharacterSetOrientation c = (CharacterSetOrientation) characterSetOrientations.get(currentOrientation); return c; - } /** diff --git a/src/java/org/apache/fop/render/afp/fonts/CharacterSetOrientation.java b/src/java/org/apache/fop/render/afp/fonts/CharacterSetOrientation.java index be6dbf6ea..e13029717 100644 --- a/src/java/org/apache/fop/render/afp/fonts/CharacterSetOrientation.java +++ b/src/java/org/apache/fop/render/afp/fonts/CharacterSetOrientation.java @@ -183,11 +183,15 @@ public class CharacterSetOrientation { /** * Get the width (in 1/1000ths of a point size) of the character * identified by the parameter passed. - * @param character the character to evaluate + * @param characterIndex the character to evaluate * @return the widths of the character */ - public int width(int character) { - return chars[character]; + public int getWidth(int characterIndex) { + if (characterIndex >= chars.length) { + throw new IllegalArgumentException("Invalid character index: " + + characterIndex + ", maximum is " + (chars.length - 1)); + } + return chars[characterIndex]; } /** diff --git a/src/java/org/apache/fop/render/afp/fonts/FopCharacterSet.java b/src/java/org/apache/fop/render/afp/fonts/FopCharacterSet.java index f6864d73f..d5beb5a33 100644 --- a/src/java/org/apache/fop/render/afp/fonts/FopCharacterSet.java +++ b/src/java/org/apache/fop/render/afp/fonts/FopCharacterSet.java @@ -125,7 +125,7 @@ public class FopCharacterSet extends CharacterSet { * @param character the character from which the width will be calculated * @return the width of the character */ - public int width(int character) { + public int getWidth(int character) { return charSet.getWidth(character, size); } diff --git a/src/java/org/apache/fop/render/afp/fonts/OutlineFont.java b/src/java/org/apache/fop/render/afp/fonts/OutlineFont.java index f8dd9a1ed..71c5dfb6f 100644 --- a/src/java/org/apache/fop/render/afp/fonts/OutlineFont.java +++ b/src/java/org/apache/fop/render/afp/fonts/OutlineFont.java @@ -136,7 +136,7 @@ public class OutlineFont extends AFPFont { * @return the width of the character for the specified point size */ public int getWidth(int character, int size) { - return charSet.width(character) / 1000 * size; + return charSet.getWidth(character) / 1000 * size; } /** diff --git a/src/java/org/apache/fop/render/afp/fonts/RasterFont.java b/src/java/org/apache/fop/render/afp/fonts/RasterFont.java index 8312dca72..5c1696aa4 100644 --- a/src/java/org/apache/fop/render/afp/fonts/RasterFont.java +++ b/src/java/org/apache/fop/render/afp/fonts/RasterFont.java @@ -196,7 +196,7 @@ public class RasterFont extends AFPFont { * @return the width for the given point size */ public int getWidth(int character, int size) { - return getCharacterSet(size).width(character); + return getCharacterSet(size).getWidth(character); } /** diff --git a/src/java/org/apache/fop/render/afp/tools/StructuredFieldReader.java b/src/java/org/apache/fop/render/afp/tools/StructuredFieldReader.java index 1939d2dda..48beff023 100644 --- a/src/java/org/apache/fop/render/afp/tools/StructuredFieldReader.java +++ b/src/java/org/apache/fop/render/afp/tools/StructuredFieldReader.java @@ -58,14 +58,14 @@ public class StructuredFieldReader { * parameter (this must be a valid MO:DCA structured field. * @param identifier the three byte identifier * @throws IOException if an I/O exception occurred - * @return the next structured field + * @return the next structured field or null when there are no more */ public byte[] getNext(byte[] identifier) throws IOException { int bufferPointer = 0; byte[] bufferData = new byte[identifier.length + 2]; for (int x = 0; x < identifier.length; x++) { - bufferData[x] = (byte) 0; + bufferData[x] = 0x00; } int c; @@ -128,7 +128,6 @@ public class StructuredFieldReader { } - return new byte[] { - }; + return null; } } diff --git a/src/java/org/apache/fop/render/ps/AbstractPSTranscoder.java b/src/java/org/apache/fop/render/ps/AbstractPSTranscoder.java index b8ff8ef3f..705515311 100644 --- a/src/java/org/apache/fop/render/ps/AbstractPSTranscoder.java +++ b/src/java/org/apache/fop/render/ps/AbstractPSTranscoder.java @@ -34,8 +34,10 @@ import org.apache.batik.bridge.UnitProcessor; import org.apache.batik.transcoder.TranscoderException; import org.apache.batik.transcoder.TranscoderOutput; import org.apache.batik.transcoder.image.ImageTranscoder; -import org.apache.xmlgraphics.java2d.ps.AbstractPSDocumentGraphics2D; + import org.apache.xmlgraphics.java2d.TextHandler; +import org.apache.xmlgraphics.java2d.ps.AbstractPSDocumentGraphics2D; +import org.apache.xmlgraphics.ps.PSGenerator; import org.apache.fop.fonts.FontInfo; import org.apache.fop.fonts.FontSetup; @@ -70,7 +72,7 @@ import org.apache.fop.svg.AbstractFOPTranscoder; */ public abstract class AbstractPSTranscoder extends AbstractFOPTranscoder { - private Configuration cfg = null; + private final Configuration cfg = null; protected AbstractPSDocumentGraphics2D graphics = null; /** @@ -99,6 +101,7 @@ public abstract class AbstractPSTranscoder extends AbstractFOPTranscoder { FontInfo fontInfo = new FontInfo(); //TODO Do custom font configuration here somewhere/somehow FontSetup.setup(fontInfo); + PSGenerator generator = graphics.getPSGenerator(); graphics.setCustomTextHandler(new NativeTextHandler(graphics, fontInfo)); } diff --git a/src/java/org/apache/fop/render/ps/NativeTextHandler.java b/src/java/org/apache/fop/render/ps/NativeTextHandler.java index 9f62097e9..7cf59d519 100644 --- a/src/java/org/apache/fop/render/ps/NativeTextHandler.java +++ b/src/java/org/apache/fop/render/ps/NativeTextHandler.java @@ -19,17 +19,19 @@ package org.apache.fop.render.ps; +import java.awt.Graphics2D; import java.awt.Shape; import java.awt.geom.AffineTransform; import java.io.IOException; +import org.apache.xmlgraphics.java2d.ps.PSGraphics2D; +import org.apache.xmlgraphics.java2d.ps.PSTextHandler; +import org.apache.xmlgraphics.ps.PSGenerator; + import org.apache.fop.fonts.Font; import org.apache.fop.fonts.FontInfo; import org.apache.fop.fonts.FontSetup; import org.apache.fop.fonts.FontTriplet; -import org.apache.xmlgraphics.java2d.ps.PSGraphics2D; -import org.apache.xmlgraphics.java2d.ps.PSTextHandler; -import org.apache.xmlgraphics.ps.PSGenerator; /** * Specialized TextHandler implementation that the PSGraphics2D class delegates to to paint text @@ -37,7 +39,7 @@ import org.apache.xmlgraphics.ps.PSGenerator; */ public class NativeTextHandler implements PSTextHandler { - private PSGraphics2D g2d; + private PSGraphics2D rootG2D; /** FontInfo containing all available fonts */ protected FontInfo fontInfo; @@ -60,7 +62,7 @@ public class NativeTextHandler implements PSTextHandler { * @param fontInfo the FontInfo object with all available fonts */ public NativeTextHandler(PSGraphics2D g2d, FontInfo fontInfo) { - this.g2d = g2d; + this.rootG2D = g2d; if (fontInfo != null) { this.fontInfo = fontInfo; } else { @@ -83,7 +85,7 @@ public class NativeTextHandler implements PSTextHandler { } private PSGenerator getPSGenerator() { - return this.g2d.getPSGenerator(); + return this.rootG2D.getPSGenerator(); } /** {@inheritDoc} */ @@ -98,12 +100,19 @@ public class NativeTextHandler implements PSTextHandler { //nop } + /** {@inheritDoc} */ + public void drawString(String text, float x, float y) throws IOException { + // TODO Remove me after removing the deprecated method in TextHandler. + throw new UnsupportedOperationException("Deprecated method!"); + } + /** * Draw a string to the PostScript document. The text is painted using * text operations. * {@inheritDoc} */ - public void drawString(String s, float x, float y) throws IOException { + public void drawString(Graphics2D g, String s, float x, float y) throws IOException { + PSGraphics2D g2d = (PSGraphics2D)g; g2d.preparePainting(); if (this.overrideFont == null) { java.awt.Font awtFont = g2d.getFont(); diff --git a/src/java/org/apache/fop/render/ps/PSSVGHandler.java b/src/java/org/apache/fop/render/ps/PSSVGHandler.java index d4a478fa4..1e65dfb98 100644 --- a/src/java/org/apache/fop/render/ps/PSSVGHandler.java +++ b/src/java/org/apache/fop/render/ps/PSSVGHandler.java @@ -262,7 +262,8 @@ public class PSSVGHandler extends AbstractGenericSVGHandler NativeTextHandler nativeTextHandler = null; BridgeContext ctx = new BridgeContext(ua); if (!strokeText) { - nativeTextHandler = new NativeTextHandler(graphics, psInfo.getFontInfo()); + FontInfo fontInfo = psInfo.getFontInfo(); + nativeTextHandler = new NativeTextHandler(graphics, fontInfo); graphics.setCustomTextHandler(nativeTextHandler); PSTextPainter textPainter = new PSTextPainter(nativeTextHandler); ctx.setTextPainter(textPainter); @@ -283,8 +284,8 @@ public class PSSVGHandler extends AbstractGenericSVGHandler float w = (float)ctx.getDocumentSize().getWidth() * 1000f; float h = (float)ctx.getDocumentSize().getHeight() * 1000f; - float sx = psInfo.getWidth() / (float)w; - float sy = psInfo.getHeight() / (float)h; + float sx = psInfo.getWidth() / w; + float sy = psInfo.getHeight() / h; ctx = null; builder = null; diff --git a/src/java/org/apache/fop/svg/FOPSAXSVGDocumentFactory.java b/src/java/org/apache/fop/svg/FOPSAXSVGDocumentFactory.java index 720795cb2..fce6ed2b6 100644 --- a/src/java/org/apache/fop/svg/FOPSAXSVGDocumentFactory.java +++ b/src/java/org/apache/fop/svg/FOPSAXSVGDocumentFactory.java @@ -21,6 +21,8 @@ package org.apache.fop.svg; import java.io.IOException; +import org.w3c.dom.Document; + import org.xml.sax.EntityResolver; import org.xml.sax.InputSource; import org.xml.sax.SAXException; @@ -71,4 +73,13 @@ public class FOPSAXSVGDocumentFactory extends SAXSVGDocumentFactory { return super.resolveEntity(publicId, systemId); } + /** + * Returns the document built up by handling the incoming SAX events. This method will not + * return any instance for the first SAX events have been received. + * @return the DOM document + */ + public Document getDocument() { + return this.document; + } + } |