aboutsummaryrefslogtreecommitdiffstats
path: root/src/java/org
diff options
context:
space:
mode:
Diffstat (limited to 'src/java/org')
-rw-r--r--src/java/org/apache/fop/apps/FopFactory.java10
-rw-r--r--src/java/org/apache/fop/cli/InputHandler.java8
-rw-r--r--src/java/org/apache/fop/fo/ElementMapping.java6
-rw-r--r--src/java/org/apache/fop/fo/FOPropertyMapping.java6
-rw-r--r--src/java/org/apache/fop/fo/FOTreeBuilder.java104
-rw-r--r--src/java/org/apache/fop/fo/flow/table/EmptyGridUnit.java7
-rw-r--r--src/java/org/apache/fop/fo/flow/table/GridUnit.java9
-rw-r--r--src/java/org/apache/fop/fo/flow/table/PrimaryGridUnit.java26
-rw-r--r--src/java/org/apache/fop/fo/properties/CommonHyphenation.java5
-rw-r--r--src/java/org/apache/fop/fo/properties/XMLLangShorthandParser.java2
-rw-r--r--src/java/org/apache/fop/fonts/AbstractCodePointMapping.java23
-rw-r--r--src/java/org/apache/fop/fonts/Base14Font.java (renamed from src/java/org/apache/fop/image/EmfImage.java)32
-rw-r--r--src/java/org/apache/fop/fonts/CIDFont.java33
-rw-r--r--src/java/org/apache/fop/fonts/CIDSubset.java177
-rw-r--r--src/java/org/apache/fop/fonts/Font.java2
-rw-r--r--src/java/org/apache/fop/fonts/LazyFont.java24
-rw-r--r--src/java/org/apache/fop/fonts/MultiByteFont.java156
-rw-r--r--src/java/org/apache/fop/fonts/NamedCharacter.java142
-rw-r--r--src/java/org/apache/fop/fonts/SimpleSingleByteEncoding.java145
-rw-r--r--src/java/org/apache/fop/fonts/SingleByteEncoding.java (renamed from src/java/org/apache/fop/image/RegisterableImageProvider.java)41
-rw-r--r--src/java/org/apache/fop/fonts/SingleByteFont.java214
-rw-r--r--src/java/org/apache/fop/fonts/Typeface.java7
-rw-r--r--src/java/org/apache/fop/fonts/truetype/TTFSubSetFile.java19
-rw-r--r--src/java/org/apache/fop/fonts/type1/AFMCharMetrics.java46
-rw-r--r--src/java/org/apache/fop/fonts/type1/AFMFile.java12
-rw-r--r--src/java/org/apache/fop/fonts/type1/AFMParser.java17
-rw-r--r--src/java/org/apache/fop/fonts/type1/Type1FontLoader.java33
-rw-r--r--src/java/org/apache/fop/image/AbstractFopImage.java376
-rw-r--r--src/java/org/apache/fop/image/BmpImage.java220
-rw-r--r--src/java/org/apache/fop/image/EPSImage.java122
-rw-r--r--src/java/org/apache/fop/image/FopImage.java207
-rw-r--r--src/java/org/apache/fop/image/FopImageConsumer.java211
-rw-r--r--src/java/org/apache/fop/image/GifImage.java218
-rw-r--r--src/java/org/apache/fop/image/ImageCache.java72
-rw-r--r--src/java/org/apache/fop/image/ImageFactory.java708
-rw-r--r--src/java/org/apache/fop/image/ImageLoader.java64
-rw-r--r--src/java/org/apache/fop/image/JAIImage.java194
-rw-r--r--src/java/org/apache/fop/image/JimiImage.java186
-rw-r--r--src/java/org/apache/fop/image/JpegImage.java239
-rw-r--r--src/java/org/apache/fop/image/PNGImage.java87
-rw-r--r--src/java/org/apache/fop/image/TIFFImage.java207
-rw-r--r--src/java/org/apache/fop/image/XMLImage.java78
-rw-r--r--src/java/org/apache/fop/image/XmlGraphicsCommonsImage.java239
-rw-r--r--src/java/org/apache/fop/image/analyser/BMPReader.java134
-rw-r--r--src/java/org/apache/fop/image/analyser/EMFReader.java162
-rw-r--r--src/java/org/apache/fop/image/analyser/EPSReader.java253
-rw-r--r--src/java/org/apache/fop/image/analyser/GIFReader.java104
-rw-r--r--src/java/org/apache/fop/image/analyser/ImageReader.java56
-rw-r--r--src/java/org/apache/fop/image/analyser/ImageReaderFactory.java108
-rw-r--r--src/java/org/apache/fop/image/analyser/JPEGReader.java264
-rw-r--r--src/java/org/apache/fop/image/analyser/PNGReader.java115
-rw-r--r--src/java/org/apache/fop/image/analyser/SVGReader.java188
-rw-r--r--src/java/org/apache/fop/image/analyser/TIFFReader.java117
-rw-r--r--src/java/org/apache/fop/image/analyser/XMLReader.java167
-rw-r--r--src/java/org/apache/fop/image/analyser/package.html23
-rw-r--r--src/java/org/apache/fop/image/package.html2
-rw-r--r--src/java/org/apache/fop/layoutmgr/AbstractBreaker.java4
-rw-r--r--src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java16
-rw-r--r--src/java/org/apache/fop/layoutmgr/AreaAdditionUtil.java2
-rw-r--r--src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java54
-rw-r--r--src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java11
-rw-r--r--src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java21
-rw-r--r--src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java2
-rw-r--r--src/java/org/apache/fop/layoutmgr/LayoutContext.java108
-rw-r--r--src/java/org/apache/fop/layoutmgr/MinOptMaxUtil.java13
-rw-r--r--src/java/org/apache/fop/layoutmgr/PageBreaker.java2
-rw-r--r--src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java8
-rw-r--r--src/java/org/apache/fop/layoutmgr/StaticContentLayoutManager.java8
-rw-r--r--src/java/org/apache/fop/layoutmgr/TraitSetter.java87
-rw-r--r--src/java/org/apache/fop/layoutmgr/inline/AbstractGraphicsLayoutManager.java7
-rw-r--r--src/java/org/apache/fop/layoutmgr/inline/AbstractPageNumberCitationLayoutManager.java17
-rw-r--r--src/java/org/apache/fop/layoutmgr/inline/CharacterLayoutManager.java23
-rw-r--r--src/java/org/apache/fop/layoutmgr/inline/ContentLayoutManager.java24
-rw-r--r--src/java/org/apache/fop/layoutmgr/inline/ICLayoutManager.java5
-rwxr-xr-xsrc/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java18
-rw-r--r--src/java/org/apache/fop/layoutmgr/inline/InlineStackingLayoutManager.java26
-rw-r--r--src/java/org/apache/fop/layoutmgr/inline/LeaderLayoutManager.java5
-rw-r--r--src/java/org/apache/fop/layoutmgr/inline/LeafNodeLayoutManager.java10
-rw-r--r--src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java14
-rw-r--r--src/java/org/apache/fop/layoutmgr/inline/PageNumberLayoutManager.java6
-rw-r--r--src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java36
-rw-r--r--src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java30
-rw-r--r--src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java58
-rw-r--r--src/java/org/apache/fop/layoutmgr/table/ActiveCell.java144
-rw-r--r--src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java220
-rw-r--r--src/java/org/apache/fop/layoutmgr/table/RowPainter.java116
-rw-r--r--src/java/org/apache/fop/layoutmgr/table/TableAndCaptionLayoutManager.java7
-rw-r--r--src/java/org/apache/fop/layoutmgr/table/TableCaptionLayoutManager.java5
-rw-r--r--src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java123
-rw-r--r--src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java164
-rw-r--r--src/java/org/apache/fop/layoutmgr/table/TableContentPosition.java7
-rw-r--r--src/java/org/apache/fop/layoutmgr/table/TableHFPenaltyPosition.java5
-rw-r--r--src/java/org/apache/fop/layoutmgr/table/TableHeaderFooterPosition.java5
-rw-r--r--src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java75
-rw-r--r--src/java/org/apache/fop/pdf/PDFCMap.java5
-rw-r--r--src/java/org/apache/fop/pdf/PDFEncoding.java8
-rw-r--r--src/java/org/apache/fop/pdf/PDFFactory.java133
-rw-r--r--src/java/org/apache/fop/pdf/PDFResources.java2
-rw-r--r--src/java/org/apache/fop/pdf/PDFStream.java38
-rw-r--r--src/java/org/apache/fop/pdf/PDFTTFStream.java2
-rw-r--r--src/java/org/apache/fop/pdf/PDFTextUtil.java295
-rw-r--r--src/java/org/apache/fop/render/AbstractGenericSVGHandler.java2
-rw-r--r--src/java/org/apache/fop/render/afp/AFPRenderer.java22
-rw-r--r--src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java3
-rw-r--r--src/java/org/apache/fop/render/afp/AFPSVGHandler.java10
-rwxr-xr-xsrc/java/org/apache/fop/render/afp/extensions/AFPElement.java7
-rwxr-xr-xsrc/java/org/apache/fop/render/afp/extensions/AFPElementMapping.java18
-rw-r--r--src/java/org/apache/fop/render/afp/extensions/AFPExtensionHandler.java2
-rw-r--r--src/java/org/apache/fop/render/afp/fonts/OutlineFont.java7
-rw-r--r--src/java/org/apache/fop/render/afp/fonts/RasterFont.java7
-rw-r--r--src/java/org/apache/fop/render/afp/modca/AbstractAFPObject.java10
-rw-r--r--src/java/org/apache/fop/render/afp/modca/AbstractDescriptor.java14
-rw-r--r--src/java/org/apache/fop/render/afp/modca/AbstractNamedAFPObject.java23
-rw-r--r--src/java/org/apache/fop/render/afp/modca/AbstractPageObject.java2
-rw-r--r--src/java/org/apache/fop/render/afp/modca/ImageContent.java98
-rw-r--r--src/java/org/apache/fop/render/afp/modca/ImageDataDescriptor.java81
-rw-r--r--src/java/org/apache/fop/render/afp/modca/ImageSegment.java2
-rw-r--r--src/java/org/apache/fop/render/afp/modca/ObjectAreaDescriptor.java21
-rw-r--r--src/java/org/apache/fop/render/afp/modca/PageDescriptor.java12
-rw-r--r--src/java/org/apache/fop/render/afp/modca/PageObject.java8
-rw-r--r--src/java/org/apache/fop/render/afp/modca/PresentationTextData.java122
-rw-r--r--src/java/org/apache/fop/render/afp/modca/PresentationTextDescriptor.java13
-rw-r--r--src/java/org/apache/fop/render/afp/modca/PresentationTextObject.java3
-rw-r--r--src/java/org/apache/fop/render/afp/modca/TagLogicalElementBean.java4
-rw-r--r--src/java/org/apache/fop/render/java2d/CustomFontMetricsMapper.java2
-rw-r--r--src/java/org/apache/fop/render/java2d/Java2DRenderer.java2
-rw-r--r--src/java/org/apache/fop/render/java2d/SystemFontMetricsMapper.java2
-rw-r--r--src/java/org/apache/fop/render/pdf/AbstractImageAdapter.java10
-rw-r--r--src/java/org/apache/fop/render/pdf/ImageRawJPEGAdapter.java101
-rw-r--r--src/java/org/apache/fop/render/pdf/PDFGraphics2DAdapter.java4
-rw-r--r--src/java/org/apache/fop/render/pdf/PDFRenderer.java258
-rw-r--r--src/java/org/apache/fop/render/ps/PSFontUtils.java128
-rw-r--r--src/java/org/apache/fop/render/ps/PSImageUtils.java73
-rw-r--r--src/java/org/apache/fop/render/ps/PSRenderer.java91
-rw-r--r--src/java/org/apache/fop/render/rtf/SVGConverter.java70
-rw-r--r--src/java/org/apache/fop/svg/GraphicsConfiguration.java (renamed from src/java/org/apache/fop/image/analyser/SVGZReader.java)42
-rw-r--r--src/java/org/apache/fop/svg/PDFGraphics2D.java11
-rw-r--r--src/java/org/apache/fop/svg/PDFTextPainter.java11
-rw-r--r--src/java/org/apache/fop/svg/PDFTextUtil.java231
139 files changed, 2920 insertions, 7003 deletions
diff --git a/src/java/org/apache/fop/apps/FopFactory.java b/src/java/org/apache/fop/apps/FopFactory.java
index e6ac70d67..ce77d9040 100644
--- a/src/java/org/apache/fop/apps/FopFactory.java
+++ b/src/java/org/apache/fop/apps/FopFactory.java
@@ -46,7 +46,6 @@ import org.apache.fop.fo.ElementMapping;
import org.apache.fop.fo.ElementMappingRegistry;
import org.apache.fop.fonts.FontCache;
import org.apache.fop.hyphenation.HyphenationTreeResolver;
-import org.apache.fop.image.ImageFactory;
import org.apache.fop.layoutmgr.LayoutManagerMaker;
import org.apache.fop.render.RendererFactory;
import org.apache.fop.render.XMLHandlerRegistry;
@@ -82,9 +81,6 @@ public class FopFactory implements ImageContext {
private ColorSpaceCache colorSpaceCache = null;
- /** Image factory for creating fop image objects */
- private ImageFactory imageFactory;
-
/** Image manager for loading and caching image objects */
private ImageManager imageManager;
@@ -155,7 +151,6 @@ public class FopFactory implements ImageContext {
this.elementMappingRegistry = new ElementMappingRegistry(this);
this.foURIResolver = new FOURIResolver(validateUserConfigStrictly());
this.colorSpaceCache = new ColorSpaceCache(foURIResolver);
- this.imageFactory = new ImageFactory();
this.imageManager = new ImageManager(this);
this.rendererFactory = new RendererFactory();
this.xmlHandlers = new XMLHandlerRegistry();
@@ -290,11 +285,6 @@ public class FopFactory implements ImageContext {
return this.contentHandlerFactoryRegistry;
}
- /** @return the image factory */
- public ImageFactory getImageFactory() {
- return this.imageFactory;
- }
-
/**
* Returns the image manager.
* @return the image manager
diff --git a/src/java/org/apache/fop/cli/InputHandler.java b/src/java/org/apache/fop/cli/InputHandler.java
index 68af6ae51..4c38fa5c7 100644
--- a/src/java/org/apache/fop/cli/InputHandler.java
+++ b/src/java/org/apache/fop/cli/InputHandler.java
@@ -39,8 +39,13 @@ import javax.xml.transform.sax.SAXSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
+
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+
import org.apache.fop.apps.FOPException;
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.apps.Fop;
@@ -150,6 +155,7 @@ public class InputHandler implements ErrorListener, Renderable {
try {
InputSource is = new InputSource(new FileInputStream(
this.sourcefile));
+ is.setSystemId(this.sourcefile.toURI().toASCIIString());
SAXParserFactory spf = SAXParserFactory.newInstance();
spf.setFeature("http://xml.org/sax/features/namespaces", true);
spf.setFeature("http://apache.org/xml/features/xinclude", true);
@@ -221,7 +227,7 @@ public class InputHandler implements ErrorListener, Renderable {
* {@inheritDoc}
*/
public void warning(TransformerException exc) {
- log.warn(exc.toString());
+ log.warn(exc.getLocalizedMessage());
}
/**
diff --git a/src/java/org/apache/fop/fo/ElementMapping.java b/src/java/org/apache/fop/fo/ElementMapping.java
index 0f436ae28..495983750 100644
--- a/src/java/org/apache/fop/fo/ElementMapping.java
+++ b/src/java/org/apache/fop/fo/ElementMapping.java
@@ -19,7 +19,7 @@
package org.apache.fop.fo;
-import java.util.HashMap;
+import java.util.Map;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
@@ -37,7 +37,7 @@ public abstract class ElementMapping {
public static final String DEFAULT = "<default>";
/** The HashMap table of formatting objects defined by the ElementMapping */
- protected HashMap foObjs = null;
+ protected Map foObjs = null;
/** The namespace for the ElementMapping */
protected String namespaceURI = null;
@@ -47,7 +47,7 @@ public abstract class ElementMapping {
*
* @return Table of Maker objects for this ElementMapping
*/
- public HashMap getTable() {
+ public Map getTable() {
if (foObjs == null) {
initialize();
}
diff --git a/src/java/org/apache/fop/fo/FOPropertyMapping.java b/src/java/org/apache/fop/fo/FOPropertyMapping.java
index 9910f1ce7..539648f5a 100644
--- a/src/java/org/apache/fop/fo/FOPropertyMapping.java
+++ b/src/java/org/apache/fop/fo/FOPropertyMapping.java
@@ -412,6 +412,7 @@ public final class FOPropertyMapping implements Constants {
l.setInherited(false);
l.addEnum("auto", getEnumProperty(EN_AUTO, "AUTO"));
l.setDefault("auto");
+ l.setPercentBase(LengthBase.CONTAINING_BLOCK_HEIGHT);
addPropertyMaker("top", l);
// right
@@ -419,6 +420,7 @@ public final class FOPropertyMapping implements Constants {
l.setInherited(false);
l.addEnum("auto", getEnumProperty(EN_AUTO, "AUTO"));
l.setDefault("auto");
+ l.setPercentBase(LengthBase.CONTAINING_BLOCK_WIDTH);
addPropertyMaker("right", l);
// bottom
@@ -426,6 +428,7 @@ public final class FOPropertyMapping implements Constants {
l.setInherited(false);
l.addEnum("auto", getEnumProperty(EN_AUTO, "AUTO"));
l.setDefault("auto");
+ l.setPercentBase(LengthBase.CONTAINING_BLOCK_HEIGHT);
addPropertyMaker("bottom", l);
// left
@@ -433,6 +436,7 @@ public final class FOPropertyMapping implements Constants {
l.setInherited(false);
l.addEnum("auto", getEnumProperty(EN_AUTO, "AUTO"));
l.setDefault("auto");
+ l.setPercentBase(LengthBase.CONTAINING_BLOCK_WIDTH);
addPropertyMaker("left", l);
}
@@ -1161,6 +1165,7 @@ public final class FOPropertyMapping implements Constants {
m = new LengthProperty.Maker(PR_START_INDENT);
m.setInherited(true);
m.setDefault("0pt");
+ m.setPercentBase(LengthBase.CONTAINING_REFAREA_WIDTH);
IndentPropertyMaker sCorr = new IndentPropertyMaker(m);
sCorr.setCorresponding(PR_MARGIN_LEFT, PR_MARGIN_RIGHT, PR_MARGIN_TOP);
sCorr.setUseParent(false);
@@ -1177,6 +1182,7 @@ public final class FOPropertyMapping implements Constants {
m = new LengthProperty.Maker(PR_END_INDENT);
m.setInherited(true);
m.setDefault("0pt");
+ m.setPercentBase(LengthBase.CONTAINING_REFAREA_WIDTH);
IndentPropertyMaker eCorr = new IndentPropertyMaker(m);
eCorr.setCorresponding(PR_MARGIN_RIGHT, PR_MARGIN_LEFT, PR_MARGIN_BOTTOM);
eCorr.setUseParent(false);
diff --git a/src/java/org/apache/fop/fo/FOTreeBuilder.java b/src/java/org/apache/fop/fo/FOTreeBuilder.java
index 63fc5cb5b..d02a058fe 100644
--- a/src/java/org/apache/fop/fo/FOTreeBuilder.java
+++ b/src/java/org/apache/fop/fo/FOTreeBuilder.java
@@ -38,7 +38,6 @@ import org.apache.fop.area.AreaTreeHandler;
import org.apache.fop.fo.ElementMapping.Maker;
import org.apache.fop.fo.extensions.ExtensionElementMapping;
import org.apache.fop.fo.pagination.Root;
-import org.apache.fop.image.ImageFactory;
import org.apache.fop.util.ContentHandlerFactory;
import org.apache.fop.util.ContentHandlerFactory.ObjectBuiltListener;
import org.apache.fop.util.ContentHandlerFactory.ObjectSource;
@@ -57,9 +56,7 @@ public class FOTreeBuilder extends DefaultHandler {
/** The registry for ElementMapping instances */
protected ElementMappingRegistry elementMappingRegistry;
- /**
- * The root of the formatting object tree
- */
+ /** The root of the formatting object tree */
protected Root rootFObj = null;
/** Main DefaultHandler that handles the FO namespace. */
@@ -68,10 +65,7 @@ public class FOTreeBuilder extends DefaultHandler {
/** Current delegate ContentHandler to receive the SAX events */
protected ContentHandler delegate;
- /**
- * The class that handles formatting and rendering to a stream
- * (mark-fop@inomial.com)
- */
+ /** The object that handles formatting and rendering to a stream */
private FOEventHandler foEventHandler;
/** The SAX locator object managing the line and column counters */
@@ -86,14 +80,18 @@ public class FOTreeBuilder extends DefaultHandler {
private int depth;
/**
- * FOTreeBuilder constructor
+ * <code>FOTreeBuilder</code> constructor
+ *
* @param outputFormat the MIME type of the output format to use (ex. "application/pdf").
- * @param foUserAgent in effect for this process
- * @param stream OutputStream to direct results
- * @throws FOPException if the FOTreeBuilder cannot be properly created
+ * @param foUserAgent the {@link FOUserAgent} in effect for this process
+ * @param stream the <code>OutputStream</code> to direct the results to
+ * @throws FOPException if the <code>FOTreeBuilder</code> cannot be properly created
*/
- public FOTreeBuilder(String outputFormat, FOUserAgent foUserAgent,
- OutputStream stream) throws FOPException {
+ public FOTreeBuilder(
+ String outputFormat,
+ FOUserAgent foUserAgent,
+ OutputStream stream)
+ throws FOPException {
this.userAgent = foUserAgent;
this.elementMappingRegistry = userAgent.getFactory().getElementMappingRegistry();
@@ -108,40 +106,25 @@ public class FOTreeBuilder extends DefaultHandler {
});
}
- /**
- * This method enables to reduce memory consumption of the FO tree slightly. When it returns
- * true no Locator is passed to the FO tree nodes which would copy the information into
- * a SAX LocatorImpl instance.
- * @return true if no context information should be stored on each node in the FO tree.
- * @deprecated Use FOUserAgent.isLocatorEnabled() instead.
- */
- protected boolean isLocatorDisabled() {
- return !userAgent.isLocatorEnabled();
- }
-
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
public void setDocumentLocator(Locator locator) {
this.locator = locator;
}
- /** @return a Locator instance if it is available and not disabled */
+ /**
+ * @return a {@link Locator} instance if it is available and not disabled
+ */
protected Locator getEffectiveLocator() {
return (userAgent.isLocatorEnabled() ? this.locator : null);
}
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
public void characters(char[] data, int start, int length)
throws SAXException {
delegate.characters(data, start, length);
}
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
public void startDocument() throws SAXException {
if (used) {
throw new IllegalStateException("FOTreeBuilder (and the Fop class) cannot be reused."
@@ -159,9 +142,7 @@ public class FOTreeBuilder extends DefaultHandler {
this.delegate = this.mainFOHandler;
}
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
public void endDocument() throws SAXException {
this.delegate.endDocument();
if (this.rootFObj == null && empty) {
@@ -173,24 +154,16 @@ public class FOTreeBuilder extends DefaultHandler {
log.debug("Parsing of document complete");
}
foEventHandler.endDocument();
-
- //Notify the image factory that this user agent has expired.
- ImageFactory imageFactory = userAgent.getFactory().getImageFactory();
- imageFactory.removeContext(this.userAgent);
}
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
public void startElement(String namespaceURI, String localName, String rawName,
Attributes attlist) throws SAXException {
this.depth++;
delegate.startElement(namespaceURI, localName, rawName, attlist);
}
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
public void endElement(String uri, String localName, String rawName)
throws SAXException {
this.delegate.endElement(uri, localName, rawName);
@@ -206,7 +179,8 @@ public class FOTreeBuilder extends DefaultHandler {
}
/**
- * Finds the Maker used to create node objects of a particular type
+ * Finds the {@link Maker} used to create {@link FONode} objects of a particular type
+ *
* @param namespaceURI URI for the namespace of the element
* @param localName name of the Element
* @return the ElementMapping.Maker that can create an FO object for this element
@@ -218,7 +192,7 @@ public class FOTreeBuilder extends DefaultHandler {
/** {@inheritDoc} */
public void warning(SAXParseException e) {
- log.warn(e.toString());
+ log.warn(e.getLocalizedMessage());
}
/** {@inheritDoc} */
@@ -233,7 +207,8 @@ public class FOTreeBuilder extends DefaultHandler {
}
/**
- * Provides access to the underlying FOEventHandler object.
+ * Provides access to the underlying {@link FOEventHandler} object.
+ *
* @return the FOEventHandler object
*/
public FOEventHandler getEventHandler() {
@@ -244,6 +219,7 @@ public class FOTreeBuilder extends DefaultHandler {
* Returns the results of the rendering process. Information includes
* the total number of pages generated and the number of pages per
* page-sequence.
+ *
* @return the results of the rendering process.
*/
public FormattingResults getResults() {
@@ -257,23 +233,17 @@ public class FOTreeBuilder extends DefaultHandler {
}
/**
- * Main DefaultHandler implementation which builds the FO tree.
+ * Main <code>DefaultHandler</code> implementation which builds the FO tree.
*/
private class MainFOHandler extends DefaultHandler {
- /**
- * Current formatting object being handled
- */
+ /** Current formatting object being handled */
protected FONode currentFObj = null;
- /**
- * Current propertyList for the node being handled.
- */
+ /** Current propertyList for the node being handled */
protected PropertyList currentPropertyList;
- /**
- * Current marker nesting-depth
- */
+ /** Current marker nesting-depth */
private int nestedMarkerDepth = 0;
/** {@inheritDoc} */
@@ -298,11 +268,7 @@ public class FOTreeBuilder extends DefaultHandler {
} else { // check that incoming node is valid for currentFObj
if (namespaceURI.equals(FOElementMapping.URI)
|| namespaceURI.equals(ExtensionElementMapping.URI)) {
- try {
- currentFObj.validateChildNode(locator, namespaceURI, localName);
- } catch (ValidationException e) {
- throw e;
- }
+ currentFObj.validateChildNode(locator, namespaceURI, localName);
}
}
@@ -391,12 +357,11 @@ public class FOTreeBuilder extends DefaultHandler {
if (currentFObj.getParent() == null) {
log.debug("endElement for top-level " + currentFObj.getName());
}
+
currentFObj = currentFObj.getParent();
}
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
public void characters(char[] data, int start, int length)
throws FOPException {
if (currentFObj != null) {
@@ -405,6 +370,7 @@ public class FOTreeBuilder extends DefaultHandler {
}
}
+ /** {@inheritDoc} */
public void endDocument() throws SAXException {
currentFObj = null;
}
diff --git a/src/java/org/apache/fop/fo/flow/table/EmptyGridUnit.java b/src/java/org/apache/fop/fo/flow/table/EmptyGridUnit.java
index 201029ff1..2c910d3f8 100644
--- a/src/java/org/apache/fop/fo/flow/table/EmptyGridUnit.java
+++ b/src/java/org/apache/fop/fo/flow/table/EmptyGridUnit.java
@@ -25,8 +25,6 @@ package org.apache.fop.fo.flow.table;
*/
public class EmptyGridUnit extends GridUnit {
- private TableBody body;
-
/**
* @param table the containing table
* @param row the table-row element this grid unit belongs to (if any)
@@ -57,11 +55,6 @@ public class EmptyGridUnit extends GridUnit {
}
/** {@inheritDoc} */
- public TableBody getBody() {
- return this.body;
- }
-
- /** {@inheritDoc} */
public boolean isLastGridUnitColSpan() {
return true;
}
diff --git a/src/java/org/apache/fop/fo/flow/table/GridUnit.java b/src/java/org/apache/fop/fo/flow/table/GridUnit.java
index 23d1cc001..b9394ff31 100644
--- a/src/java/org/apache/fop/fo/flow/table/GridUnit.java
+++ b/src/java/org/apache/fop/fo/flow/table/GridUnit.java
@@ -19,7 +19,6 @@
package org.apache.fop.fo.flow.table;
-import org.apache.fop.fo.FONode;
import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
import org.apache.fop.fo.properties.CommonBorderPaddingBackground.BorderInfo;
import org.apache.fop.layoutmgr.table.CollapsingBorderModel;
@@ -165,14 +164,6 @@ public class GridUnit {
this.row = row;
}
- public TableBody getBody() {
- FONode node = getCell();
- while (node != null && !(node instanceof TableBody)) {
- node = node.getParent();
- }
- return (TableBody) node;
- }
-
/**
* Returns the before-start grid unit of the cell containing this grid unit.
*
diff --git a/src/java/org/apache/fop/fo/flow/table/PrimaryGridUnit.java b/src/java/org/apache/fop/fo/flow/table/PrimaryGridUnit.java
index 1a47a7dcf..8af896fa2 100644
--- a/src/java/org/apache/fop/fo/flow/table/PrimaryGridUnit.java
+++ b/src/java/org/apache/fop/fo/flow/table/PrimaryGridUnit.java
@@ -23,6 +23,7 @@ import java.util.LinkedList;
import java.util.List;
import org.apache.fop.fo.Constants;
+import org.apache.fop.fo.FONode;
import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
import org.apache.fop.layoutmgr.ElementListUtils;
import org.apache.fop.layoutmgr.table.TableCellLayoutManager;
@@ -71,6 +72,19 @@ public class PrimaryGridUnit extends GridUnit {
.getValue() / 2; // TODO
}
+ /**
+ * Returns the fo:table-header/footer/body element containing this cell.
+ *
+ * @return the enclosing table part
+ */
+ public TableBody getTableBody() {
+ FONode node = cell.getParent();
+ if (node instanceof TableRow) {
+ node = node.getParent();
+ }
+ return (TableBody) node;
+ }
+
public TableCellLayoutManager getCellLM() {
assert cellLM != null;
return cellLM;
@@ -224,18 +238,6 @@ public class PrimaryGridUnit extends GridUnit {
return contentLength;
}
- /** @return true if cell/row has an explicit BPD/height */
- public boolean hasBPD() {
- if (!getCell().getBlockProgressionDimension().getOptimum(null).isAuto()) {
- return true;
- }
- if (getRow() != null
- && !getRow().getBlockProgressionDimension().getOptimum(null).isAuto()) {
- return true;
- }
- return false;
- }
-
/**
* Returns the grid units belonging to the same span as this one.
*
diff --git a/src/java/org/apache/fop/fo/properties/CommonHyphenation.java b/src/java/org/apache/fop/fo/properties/CommonHyphenation.java
index 26747c24d..f47ddbe0c 100644
--- a/src/java/org/apache/fop/fo/properties/CommonHyphenation.java
+++ b/src/java/org/apache/fop/fo/properties/CommonHyphenation.java
@@ -21,6 +21,7 @@ package org.apache.fop.fo.properties;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+
import org.apache.fop.fo.Constants;
import org.apache.fop.fo.PropertyList;
import org.apache.fop.fo.expr.PropertyException;
@@ -142,7 +143,7 @@ public final class CommonHyphenation {
FontMetrics metrics = font.getFontMetrics();
if (metrics instanceof Typeface) {
Typeface typeface = (Typeface)metrics;
- if ("SymbolEncoding".equals(typeface.getEncoding())) {
+ if ("SymbolEncoding".equals(typeface.getEncodingName())) {
//SymbolEncoding doesn't have HYPHEN_MINUS, so replace by MINUS_SIGN
} else {
//only warn if the encoding is not SymbolEncoding
@@ -154,7 +155,7 @@ public final class CommonHyphenation {
FontMetrics metrics = font.getFontMetrics();
if (metrics instanceof Typeface) {
Typeface typeface = (Typeface)metrics;
- if ("ZapfDingbatsEncoding".equals(typeface.getEncoding())) {
+ if ("ZapfDingbatsEncoding".equals(typeface.getEncodingName())) {
//ZapfDingbatsEncoding doesn't have HYPHEN_MINUS, so replace by ' '
} else {
//only warn if the encoding is not ZapfDingbatsEncoding
diff --git a/src/java/org/apache/fop/fo/properties/XMLLangShorthandParser.java b/src/java/org/apache/fop/fo/properties/XMLLangShorthandParser.java
index 69ca372e5..5a5cf95c5 100644
--- a/src/java/org/apache/fop/fo/properties/XMLLangShorthandParser.java
+++ b/src/java/org/apache/fop/fo/properties/XMLLangShorthandParser.java
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
-/* $Id:$ */
+/* $Id$ */
package org.apache.fop.fo.properties;
diff --git a/src/java/org/apache/fop/fonts/AbstractCodePointMapping.java b/src/java/org/apache/fop/fonts/AbstractCodePointMapping.java
index 91d13da85..3a2ac5022 100644
--- a/src/java/org/apache/fop/fonts/AbstractCodePointMapping.java
+++ b/src/java/org/apache/fop/fonts/AbstractCodePointMapping.java
@@ -29,7 +29,7 @@ import org.apache.fop.util.CharUtilities;
/**
* Abstract base class for code point mapping classes (1-byte character encodings).
*/
-public class AbstractCodePointMapping {
+public class AbstractCodePointMapping implements SingleByteEncoding {
private String name;
private char[] latin1Map;
@@ -114,19 +114,12 @@ public class AbstractCodePointMapping {
}
}
- /**
- * Returns the encoding's name.
- * @return the name of the encoding
- */
+ /** {@inheritDoc} */
public String getName() {
return this.name;
}
- /**
- * Maps a Unicode character to a code point in the encoding.
- * @param c the Unicode character to map
- * @return the coid point in the encoding or 0 (=.notdef) if not found
- */
+ /** {@inheritDoc} */
public final char mapChar(char c) {
if (c < 256) {
char latin1 = latin1Map[c];
@@ -172,8 +165,8 @@ public class AbstractCodePointMapping {
}
}
- putFallbackCharacter(c, '\0');
- return 0;
+ putFallbackCharacter(c, NOT_FOUND_CODE_POINT);
+ return NOT_FOUND_CODE_POINT;
}
private void putFallbackCharacter(char c, char mapTo) {
@@ -227,11 +220,7 @@ public class AbstractCodePointMapping {
return -1;
}
- /**
- * Returns the array of character names for this encoding.
- * @return the array of character names
- * (unmapped code points are represented by a ".notdef" value)
- */
+ /** {@inheritDoc} */
public String[] getCharNameMap() {
if (this.charNameMap != null) {
String[] copy = new String[this.charNameMap.length];
diff --git a/src/java/org/apache/fop/image/EmfImage.java b/src/java/org/apache/fop/fonts/Base14Font.java
index 73bbad232..26c11e72b 100644
--- a/src/java/org/apache/fop/image/EmfImage.java
+++ b/src/java/org/apache/fop/fonts/Base14Font.java
@@ -16,36 +16,12 @@
*/
/* $Id$ */
-
-package org.apache.fop.image;
+
+package org.apache.fop.fonts;
/**
- * Enhanced metafile image.
- * This supports loading a EMF image.
- *
- * @see AbstractFopImage
- * @see FopImage
+ * Base class for all Base 14 fonts.
*/
-public class EmfImage extends AbstractFopImage {
-
- /**
- * Create a bitmap image with the image data.
- *
- * @param imgInfo the image information
- */
- public EmfImage(FopImage.ImageInfo imgInfo) {
- super(imgInfo);
- }
+public abstract class Base14Font extends Typeface {
- /**
- * Load the original EMF data.
- * This loads the original EMF data and reads the color space,
- * and icc profile if any.
- *
- * @return true if loaded false for any error
- */
- protected boolean loadOriginalData() {
- return loadDefaultOriginalData();
- }
}
-
diff --git a/src/java/org/apache/fop/fonts/CIDFont.java b/src/java/org/apache/fop/fonts/CIDFont.java
index c554d2165..7216c8f15 100644
--- a/src/java/org/apache/fop/fonts/CIDFont.java
+++ b/src/java/org/apache/fop/fonts/CIDFont.java
@@ -20,31 +20,14 @@
package org.apache.fop.fonts;
//Java
-import java.util.Map;
/**
* Abstract base class for CID fonts.
*/
public abstract class CIDFont extends CustomFont {
- /**
- * usedGlyphs contains orginal, new glyph index
- */
- public Map usedGlyphs = new java.util.HashMap();
-
- /**
- * usedGlyphsIndex contains new glyph, original index
- */
- public Map usedGlyphsIndex = new java.util.HashMap();
- public int usedGlyphsCount = 0;
-
- /**
- * usedCharsIndex contains new glyph, original char
- */
- public Map usedCharsIndex = new java.util.HashMap();
-
- //private PDFWArray warray = new PDFWArray();
- public int width[] = null;
+ /** Contains the character widths for all characters in the font */
+ protected int[] width = null;
// ---- Required ----
/**
@@ -73,6 +56,11 @@ public abstract class CIDFont extends CustomFont {
*/
public abstract int getSupplement();
+ /**
+ * Returns the subset information for this font.
+ * @return the subset information
+ */
+ public abstract CIDSubset getCIDSubset();
// ---- Optional ----
/**
@@ -88,9 +76,4 @@ public abstract class CIDFont extends CustomFont {
return true;
}
- /**
- * Returns a char array containing all Unicode characters that have been accessed.
- * @return a char array with all used Unicode characters
- */
- public abstract char[] getCharsUsed();
-} \ No newline at end of file
+}
diff --git a/src/java/org/apache/fop/fonts/CIDSubset.java b/src/java/org/apache/fop/fonts/CIDSubset.java
new file mode 100644
index 000000000..6bcfc0b71
--- /dev/null
+++ b/src/java/org/apache/fop/fonts/CIDSubset.java
@@ -0,0 +1,177 @@
+/*
+ * 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.fonts;
+
+import java.util.BitSet;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.apache.fop.util.CharUtilities;
+
+//Naming:
+//glyph index: original index of the glyph in the non-subset font (!= unicode index)
+//character selector: index into a set of glyphs. For subset CID fonts, this starts at 0. For
+// non-subset fonts, this is the same as the glyph index.
+//Unicode index: The Unicode codepoint of a character.
+//Glyph name: the Adobe glyph name (as found in Glyphs.java)
+
+/**
+ * Keeps track of the glyphs used in a document. This information is later used to build
+ * a subset of a font.
+ */
+public class CIDSubset {
+
+ /**
+ * usedGlyphs contains orginal, new glyph index (glyph index -> char selector)
+ */
+ private Map/*<Integer, Integer>*/ usedGlyphs = new java.util.HashMap();
+
+ /**
+ * usedGlyphsIndex contains new glyph, original index (char selector -> glyph index)
+ */
+ private Map/*<Integer, Integer>*/ usedGlyphsIndex = new java.util.HashMap();
+ private int usedGlyphsCount = 0;
+
+ /**
+ * usedCharsIndex contains new glyph, original char (char selector -> Unicode)
+ */
+ private Map/*<Integer, Character>*/ usedCharsIndex = new java.util.HashMap();
+
+ public CIDSubset() {
+ }
+
+ /**
+ * Adds the initial 3 glyphs which are the same for all CID subsets.
+ */
+ public void setupFirstThreeGlyphs() {
+ // Make sure that the 3 first glyphs are included
+ usedGlyphs.put(new Integer(0), new Integer(0));
+ usedGlyphsIndex.put(new Integer(0), new Integer(0));
+ usedGlyphsCount++;
+ usedGlyphs.put(new Integer(1), new Integer(1));
+ usedGlyphsIndex.put(new Integer(1), new Integer(1));
+ usedGlyphsCount++;
+ usedGlyphs.put(new Integer(2), new Integer(2));
+ usedGlyphsIndex.put(new Integer(2), new Integer(2));
+ usedGlyphsCount++;
+ }
+
+ /**
+ * Returns the original index of the glyph inside the (non-subset) font's glyph list. This
+ * index can be used to access the character width information, for example.
+ * @param subsetIndex the subset index (character selector) to access the glyph
+ * @return the original index (or -1 if no glyph index is available for the subset index)
+ */
+ public int getGlyphIndexForSubsetIndex(int subsetIndex) {
+ Integer glyphIndex = (Integer)usedGlyphsIndex.get(new Integer(subsetIndex));
+ if (glyphIndex != null) {
+ return glyphIndex.intValue();
+ } else {
+ return -1;
+ }
+ }
+
+ /**
+ * Returns the Unicode value for a subset index (character selector). If there's no such
+ * Unicode value, the "NOT A CHARACTER" (0xFFFF) is returned.
+ * @param subsetIndex the subset index (character selector)
+ * @return the Unicode value or "NOT A CHARACTER" (0xFFFF)
+ */
+ public char getUnicodeForSubsetIndex(int subsetIndex) {
+ Character mapValue = (Character)usedCharsIndex.get(new Integer(subsetIndex));
+ if (mapValue != null) {
+ return mapValue.charValue();
+ } else {
+ return CharUtilities.NOT_A_CHARACTER;
+ }
+ }
+
+ /**
+ * Maps a character to a character selector for a font subset. If the character isn't in the
+ * subset, yet, it is added and a new character selector returned. Otherwise, the already
+ * allocated character selector is returned from the existing map/subset.
+ * @param glyphIndex the glyph index of the character
+ * @param unicode the Unicode index of the character
+ * @return the subset index
+ */
+ public int mapSubsetChar(int glyphIndex, char unicode) {
+ // Reencode to a new subset font or get the reencoded value
+ // IOW, accumulate the accessed characters and build a character map for them
+ Integer subsetCharSelector = (Integer)usedGlyphs.get(new Integer(glyphIndex));
+ if (subsetCharSelector == null) {
+ int selector = usedGlyphsCount;
+ usedGlyphs.put(new Integer(glyphIndex),
+ new Integer(selector));
+ usedGlyphsIndex.put(new Integer(selector),
+ new Integer(glyphIndex));
+ usedCharsIndex.put(new Integer(selector),
+ new Character(unicode));
+ usedGlyphsCount++;
+ return selector;
+ } else {
+ return subsetCharSelector.intValue();
+ }
+ }
+
+ /**
+ * Returns an unmodifiable Map of the font subset. It maps from glyph index to
+ * character selector (i.e. the subset index in this case).
+ * @return Map Map&lt;Integer, Integer&gt; of the font subset
+ */
+ public Map/*<Integer, Integer>*/ getSubsetGlyphs() {
+ return Collections.unmodifiableMap(this.usedGlyphs);
+ }
+
+ /**
+ * Returns a char array containing all Unicode characters that are in the subset.
+ * @return a char array with all used Unicode characters
+ */
+ public char[] getSubsetChars() {
+ char[] charArray = new char[usedGlyphsCount];
+ for (int i = 0; i < usedGlyphsCount; i++) {
+ charArray[i] = getUnicodeForSubsetIndex(i);
+ }
+ return charArray;
+ }
+
+ /**
+ * Returns the number of glyphs in the subset.
+ * @return the number of glyphs in the subset
+ */
+ public int getSubsetSize() {
+ return this.usedGlyphsCount;
+ }
+
+ /**
+ * Returns a BitSet with bits set for each available glyph index.
+ * @return a BitSet indicating available glyph indices
+ */
+ public BitSet getGlyphIndexBitSet() {
+ BitSet bitset = new BitSet();
+ Iterator iter = usedGlyphs.keySet().iterator();
+ while (iter.hasNext()) {
+ Integer cid = (Integer)iter.next();
+ bitset.set(cid.intValue());
+ }
+ return bitset;
+ }
+
+}
diff --git a/src/java/org/apache/fop/fonts/Font.java b/src/java/org/apache/fop/fonts/Font.java
index e123513c2..ff71434c6 100644
--- a/src/java/org/apache/fop/fonts/Font.java
+++ b/src/java/org/apache/fop/fonts/Font.java
@@ -199,7 +199,7 @@ public class Font {
// Use default CodePointMapping
char d = CodePointMapping.getMapping("WinAnsiEncoding").mapChar(c);
- if (d != 0) {
+ if (d != SingleByteEncoding.NOT_FOUND_CODE_POINT) {
c = d;
} else {
log.warn("Glyph " + (int) c + " not available in font " + fontName);
diff --git a/src/java/org/apache/fop/fonts/LazyFont.java b/src/java/org/apache/fop/fonts/LazyFont.java
index e6ed7e881..8997069d4 100644
--- a/src/java/org/apache/fop/fonts/LazyFont.java
+++ b/src/java/org/apache/fop/fonts/LazyFont.java
@@ -64,11 +64,10 @@ public class LazyFont extends Typeface implements FontDescriptor {
this.resolver = resolver;
}
- /**
- * String representation of LazyFont
- */
+ /** {@inheritDoc} */
public String toString() {
- return ( "metrics-url=" + metricsFileName + ", embed-url=" + fontEmbedPath + ", kerning=" + useKerning );
+ return ( "metrics-url=" + metricsFileName + ", embed-url=" + fontEmbedPath
+ + ", kerning=" + useKerning );
}
private void load(boolean fail) {
@@ -80,8 +79,9 @@ public class LazyFont extends Typeface implements FontDescriptor {
if (resolver != null) {
Source source = resolver.resolve(metricsFileName);
if (source == null) {
- String err = "Cannot load font: failed to create Source from metrics file "
- + metricsFileName;
+ String err
+ = "Cannot load font: failed to create Source from metrics file "
+ + metricsFileName;
if (fail) {
throw new RuntimeException(err);
} else {
@@ -112,8 +112,8 @@ public class LazyFont extends Typeface implements FontDescriptor {
src.setSystemId(source.getSystemId());
reader = new FontReader(src);
} else {
- reader
- = new FontReader(new InputSource(new URL(metricsFileName).openStream()));
+ reader = new FontReader(new InputSource(
+ new URL(metricsFileName).openStream()));
}
reader.setKerningEnabled(useKerning);
reader.setFontEmbedPath(fontEmbedPath);
@@ -153,12 +153,10 @@ public class LazyFont extends Typeface implements FontDescriptor {
}
// ---- Font ----
- /**
- * {@inheritDoc}
- */
- public String getEncoding() {
+ /** {@inheritDoc} */
+ public String getEncodingName() {
load(true);
- return realFont.getEncoding();
+ return realFont.getEncodingName();
}
/**
diff --git a/src/java/org/apache/fop/fonts/MultiByteFont.java b/src/java/org/apache/fop/fonts/MultiByteFont.java
index e40c40985..5849379bd 100644
--- a/src/java/org/apache/fop/fonts/MultiByteFont.java
+++ b/src/java/org/apache/fop/fonts/MultiByteFont.java
@@ -39,6 +39,9 @@ public class MultiByteFont extends CIDFont {
private String namePrefix = null; // Quasi unique prefix
+ private CIDSubset subset = new CIDSubset();
+
+ /** A map from Unicode indices to glyph indices */
private BFEntry[] bfentries = null;
/**
@@ -46,15 +49,7 @@ public class MultiByteFont extends CIDFont {
*/
public MultiByteFont() {
// Make sure that the 3 first glyphs are included
- usedGlyphs.put(new Integer(0), new Integer(0));
- usedGlyphsIndex.put(new Integer(0), new Integer(0));
- usedGlyphsCount++;
- usedGlyphs.put(new Integer(1), new Integer(1));
- usedGlyphsIndex.put(new Integer(1), new Integer(1));
- usedGlyphsCount++;
- usedGlyphs.put(new Integer(2), new Integer(2));
- usedGlyphsIndex.put(new Integer(2), new Integer(2));
- usedGlyphsCount++;
+ subset.setupFirstThreeGlyphs();
// Create a quasiunique prefix for fontname
synchronized (this.getClass()) {
@@ -77,37 +72,27 @@ public class MultiByteFont extends CIDFont {
setFontType(FontType.TYPE0);
}
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
public int getDefaultWidth() {
return defaultWidth;
}
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
public String getRegistry() {
return "Adobe";
}
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
public String getOrdering() {
return "UCS";
}
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
public int getSupplement() {
return 0;
}
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
public CIDFontType getCIDType() {
return cidType;
}
@@ -133,68 +118,47 @@ public class MultiByteFont extends CIDFont {
}
}
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
public boolean isEmbeddable() {
return !(getEmbedFileName() == null && getEmbedResourceName() == null);
}
- /**
- * {@inheritDoc}
- */
- public String getEncoding() {
+ /** {@inheritDoc} */
+ public CIDSubset getCIDSubset() {
+ return this.subset;
+ }
+
+ /** {@inheritDoc} */
+ public String getEncodingName() {
return encoding;
}
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
public int getWidth(int i, int size) {
if (isEmbeddable()) {
- Integer idx = (Integer)usedGlyphsIndex.get(new Integer(i));
- return size * width[idx.intValue()];
+ int glyphIndex = subset.getGlyphIndexForSubsetIndex(i);
+ return size * width[glyphIndex];
} else {
return size * width[i];
}
}
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
public int[] getWidths() {
int[] arr = new int[width.length];
System.arraycopy(width, 0, arr, 0, width.length - 1);
- /*
- for (int i = 0; i < arr.length; i++)
- arr[i] *= size;
- */
return arr;
}
/**
- * Remaps a codepoint based.
- * @param i codepoint to remap
- * @return new codepoint
+ * Returns the glyph index for a Unicode character. The method returns 0 if there's no
+ * such glyph in the character map.
+ * @param c the Unicode character index
+ * @return the glyph index (or 0 if the glyph is not available)
*/
-/* unused
- public Integer reMap(Integer i) {
- if (isEmbeddable()) {
- Integer ret = (Integer)usedGlyphsIndex.get(i);
- if (ret == null) {
- ret = i;
- }
- return ret;
- } else {
- return i;
- }
-
- }
-*/
-
private int findGlyphIndex(char c) {
int idx = (int)c;
- int retIdx = 0;
+ int retIdx = 0; //.notdef
for (int i = 0; (i < bfentries.length) && retIdx == 0; i++) {
if (bfentries[i].getUnicodeStart() <= idx
@@ -208,48 +172,30 @@ public class MultiByteFont extends CIDFont {
return retIdx;
}
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
public char mapChar(char c) {
notifyMapOperation();
- int retIdx = findGlyphIndex(c);
+ int glyphIndex = findGlyphIndex(c);
if (isEmbeddable()) {
- // Reencode to a new subset font or get
- // the reencoded value
- Integer newIdx = (Integer)usedGlyphs.get(new Integer(retIdx));
- if (newIdx == null) {
- usedGlyphs.put(new Integer(retIdx),
- new Integer(usedGlyphsCount));
- usedGlyphsIndex.put(new Integer(usedGlyphsCount),
- new Integer(retIdx));
- usedCharsIndex.put(new Integer(usedGlyphsCount),
- new Integer((int) c));
- retIdx = usedGlyphsCount;
- usedGlyphsCount++;
- } else {
- retIdx = newIdx.intValue();
- }
+ glyphIndex = subset.mapSubsetChar(glyphIndex, c);
}
- return (char)retIdx;
+ return (char)glyphIndex;
}
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
public boolean hasChar(char c) {
return (findGlyphIndex(c) > 0);
}
-
/**
- * Sets the bfentries.
- * @param bfentries The bfentries to set
+ * Sets the array of BFEntry instances which constitutes the Unicode to glyph index map for
+ * a font. ("BF" means "base font")
+ * @param entries the Unicode to glyph index map
*/
- public void setBFEntries(BFEntry[] bfentries) {
- this.bfentries = bfentries;
+ public void setBFEntries(BFEntry[] entries) {
+ this.bfentries = entries;
}
/**
@@ -277,17 +223,6 @@ public class MultiByteFont extends CIDFont {
}
/**
- * Adds a new CID width entry to the font.
- * @param cidWidthIndex index
- * @param wds array of widths
- */
- /*
- public void addCIDWidthEntry(int cidWidthIndex, int[] wds) {
- this.warray.addEntry(cidWidthIndex, wds);
- }*/
-
-
- /**
* Sets the width array.
* @param wds array of widths.
*/
@@ -300,30 +235,15 @@ public class MultiByteFont extends CIDFont {
* @return Map Map of used Glyphs
*/
public Map getUsedGlyphs() {
- return usedGlyphs;
+ return subset.getSubsetGlyphs();
}
- /** The invalid Unicode character, suitable as a return value in methods
- * that need to return an invalid character. */
- public static final char INVALID_UNICODE_CHAR = 0xFFFF;
-
/** {@inheritDoc} */
public char[] getCharsUsed() {
if (!isEmbeddable()) {
return null;
}
- char[] charArray = new char[usedGlyphsCount];
- for (int i = 0; i < usedGlyphsCount; i++) {
- Integer mapValue = (Integer)usedCharsIndex.get(new Integer(i));
- if (mapValue != null) {
- char arrayItem = (char) mapValue.intValue();
- charArray[i] = arrayItem;
- }
- else {
- charArray[i] = INVALID_UNICODE_CHAR;
- }
- }
- return charArray;
+ return subset.getSubsetChars();
}
}
diff --git a/src/java/org/apache/fop/fonts/NamedCharacter.java b/src/java/org/apache/fop/fonts/NamedCharacter.java
new file mode 100644
index 000000000..2c8007ba1
--- /dev/null
+++ b/src/java/org/apache/fop/fonts/NamedCharacter.java
@@ -0,0 +1,142 @@
+/*
+ * 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.fonts;
+
+import org.apache.xmlgraphics.fonts.Glyphs;
+
+import org.apache.fop.util.CharUtilities;
+
+/**
+ * Represents an named character with character name (from the Adobe glyph list) and a Unicode
+ * sequence that this character represents.
+ */
+public class NamedCharacter {
+
+ private String charName;
+ private String unicodeSequence;
+
+ /**
+ * Main constructor.
+ * @param charName the character name
+ * @param unicodeSequence the Unicode sequence associated with this character
+ */
+ public NamedCharacter(String charName, String unicodeSequence) {
+ if (charName == null) {
+ throw new NullPointerException("charName must not be null");
+ }
+ this.charName = charName;
+ if (unicodeSequence != null) {
+ this.unicodeSequence = unicodeSequence;
+ } else {
+ this.unicodeSequence = Glyphs.getUnicodeSequenceForGlyphName(charName);
+ }
+ }
+
+ /**
+ * Simple constructor.
+ * @param charName the character name
+ */
+ public NamedCharacter(String charName) {
+ this(charName, null);
+ }
+
+ /** {@inheritDoc} */
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((charName == null) ? 0 : charName.hashCode());
+ return result;
+ }
+
+ /** {@inheritDoc} */
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final NamedCharacter other = (NamedCharacter)obj;
+ return charName.equals(other.charName);
+ }
+
+ /**
+ * Returns the character name (as defined by the Adobe glyph list).
+ * @return the character name
+ */
+ public String getName() {
+ return this.charName;
+ }
+
+ /**
+ * Returns the Unicode sequence associated with this character.
+ * @return the Unicode sequence (or null if no Unicode sequence is associated)
+ */
+ public String getUnicodeSequence() {
+ return this.unicodeSequence;
+ }
+
+ /**
+ * Indicates whether a single Unicode value is associated with this character.
+ * @return true if exactly one Unicode value is associated with this character, false otherwise
+ */
+ public boolean hasSingleUnicodeValue() {
+ return (this.unicodeSequence != null && this.unicodeSequence.length() == 1);
+ }
+
+ /**
+ * Returns the single Unicode value associated with this named character. Check
+ * {@link #hasSingleUnicodeValue()} before you call this method because an
+ * IllegalStateException is thrown is a Unicode sequence with more than one character is
+ * associated with this character.
+ * @return the single Unicode value (or FFFF ("NOT A CHARACTER") if no Unicode value is
+ * available)
+ * @throws IllegalStateException if a Unicode sequence with more than one value is associated
+ * with the named character
+ */
+ public char getSingleUnicodeValue() throws IllegalStateException {
+ if (this.unicodeSequence == null) {
+ return CharUtilities.NOT_A_CHARACTER;
+ }
+ if (this.unicodeSequence.length() > 1) {
+ throw new IllegalStateException("getSingleUnicodeValue() may not be called for a"
+ + " named character that has more than one Unicode value (a sequence)"
+ + " associated with the named character!");
+ }
+ return this.unicodeSequence.charAt(0);
+ }
+
+ /** {@inheritDoc} */
+ public String toString() {
+ StringBuffer sb = new StringBuffer(this.unicodeSequence);
+ sb.append(" (");
+ if (this.unicodeSequence != null) {
+ for (int i = 0, c = this.unicodeSequence.length(); i < c; i++) {
+ sb.append("0x").append(Integer.toHexString(this.unicodeSequence.charAt(0)));
+ }
+ sb.append(", ");
+ }
+ sb.append(getName()).append(')');
+ return sb.toString();
+ }
+} \ No newline at end of file
diff --git a/src/java/org/apache/fop/fonts/SimpleSingleByteEncoding.java b/src/java/org/apache/fop/fonts/SimpleSingleByteEncoding.java
new file mode 100644
index 000000000..a5ba1a33b
--- /dev/null
+++ b/src/java/org/apache/fop/fonts/SimpleSingleByteEncoding.java
@@ -0,0 +1,145 @@
+/*
+ * 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.fonts;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.xmlgraphics.fonts.Glyphs;
+
+/**
+ * A simple implementation of the OneByteEncoding mostly used for encodings that are constructed
+ * on-the-fly.
+ */
+public class SimpleSingleByteEncoding implements SingleByteEncoding {
+
+ private String name;
+ private List mapping = new java.util.ArrayList();
+ //List<NamedCharacter>
+ private Map charMap = new java.util.HashMap();
+ //Map<Character(Unicode), Character(code point)>
+
+ /**
+ * Main constructor.
+ * @param name the encoding's name
+ */
+ public SimpleSingleByteEncoding(String name) {
+ this.name = name;
+ }
+
+ /** {@inheritDoc} */
+ public String getName() {
+ return this.name;
+ }
+
+ /** {@inheritDoc} */
+ public char mapChar(char c) {
+ Character nc = (Character)charMap.get(new Character(c));
+ if (nc != null) {
+ return nc.charValue();
+ }
+ return NOT_FOUND_CODE_POINT;
+ }
+
+ /** {@inheritDoc} */
+ public String[] getCharNameMap() {
+ String[] map = new String[getSize()];
+ Arrays.fill(map, Glyphs.NOTDEF);
+ for (int i = getFirstChar(); i <= getLastChar(); i++) {
+ NamedCharacter ch = (NamedCharacter)this.mapping.get(i - 1);
+ map[i] = ch.getName();
+ }
+ return map;
+ }
+
+ /**
+ * Returns the index of the first defined character.
+ * @return the index of the first defined character (always 1 for this class)
+ */
+ public int getFirstChar() {
+ return 1;
+ }
+
+ /**
+ * Returns the index of the last defined character.
+ * @return the index of the last defined character
+ */
+ public int getLastChar() {
+ return this.mapping.size();
+ }
+
+ /**
+ * Returns the number of characters defined by this encoding.
+ * @return the number of characters
+ */
+ public int getSize() {
+ return this.mapping.size() + 1;
+ }
+
+ /**
+ * Indicates whether the encoding is full (with 256 code points).
+ * @return true if the encoding is full
+ */
+ public boolean isFull() {
+ return (getSize() == 256);
+ }
+
+ /**
+ * Adds a new character to the encoding.
+ * @param ch the named character
+ * @return the code point assigned to the character
+ */
+ public char addCharacter(NamedCharacter ch) {
+ if (!ch.hasSingleUnicodeValue()) {
+ throw new IllegalArgumentException("Only NamedCharacters with a single Unicode value"
+ + " are currently supported!");
+ }
+ if (isFull()) {
+ throw new IllegalStateException("Encoding is full!");
+ }
+ char newSlot = (char)(getLastChar() + 1);
+ this.mapping.add(ch);
+ this.charMap.put(new Character(ch.getSingleUnicodeValue()), new Character(newSlot));
+ return newSlot;
+ }
+
+ /**
+ * Returns the named character at a given code point in the encoding.
+ * @param codePoint the code point of the character
+ * @return the NamedCharacter (or null if no character is at this position)
+ */
+ public NamedCharacter getCharacterForIndex(int codePoint) {
+ if (codePoint < 0 || codePoint > 255) {
+ throw new IllegalArgumentException("codePoint must be between 0 and 255");
+ }
+ if (codePoint <= getLastChar()) {
+ return (NamedCharacter)this.mapping.get(codePoint - 1);
+ } else {
+ return null;
+ }
+ }
+
+ /** {@inheritDoc} */
+ public String toString() {
+ return getName() + " (" + getSize() + " chars)";
+ }
+
+}
diff --git a/src/java/org/apache/fop/image/RegisterableImageProvider.java b/src/java/org/apache/fop/fonts/SingleByteEncoding.java
index fd79ebd91..ac7241e24 100644
--- a/src/java/org/apache/fop/image/RegisterableImageProvider.java
+++ b/src/java/org/apache/fop/fonts/SingleByteEncoding.java
@@ -16,34 +16,35 @@
*/
/* $Id$ */
-
-package org.apache.fop.image;
+
+package org.apache.fop.fonts;
/**
- * This interface is used to dynamically register FopImage implementations.
- * <p>
- * NOTE: Please don't rely on this interface too much. It is a temporary measure
- * until the whole image package can be redesigned. The redesign will likely
- * provide a different mechanism to dynamically register new implementations.
+ * The interface defines a 1-byte character encoding (with 256 characters).
*/
-public interface RegisterableImageProvider {
+public interface SingleByteEncoding {
+
+ /** Code point that is used if no code point for a specific character has been found. */
+ char NOT_FOUND_CODE_POINT = '\0';
/**
- * Returns the MIME type the implementation supports.
- * @return the MIME type
- */
- String getSupportedMimeType();
-
- /**
- * Returns the name of the implementation.
- * @return the name
+ * Returns the encoding's name.
+ * @return the name of the encoding
*/
String getName();
-
+
/**
- * Returns the fully qualified class name for the implementing class.
- * @return the class name
+ * Maps a Unicode character to a code point in the encoding.
+ * @param c the Unicode character to map
+ * @return the code point in the encoding or 0 (=.notdef) if not found
*/
- String getClassName();
+ char mapChar(char c);
+ /**
+ * Returns the array of character names for this encoding.
+ * @return the array of character names
+ * (unmapped code points are represented by a ".notdef" value)
+ */
+ String[] getCharNameMap();
+
}
diff --git a/src/java/org/apache/fop/fonts/SingleByteFont.java b/src/java/org/apache/fop/fonts/SingleByteFont.java
index 814d05a2c..ac12b7615 100644
--- a/src/java/org/apache/fop/fonts/SingleByteFont.java
+++ b/src/java/org/apache/fop/fonts/SingleByteFont.java
@@ -19,6 +19,8 @@
package org.apache.fop.fonts;
+import java.util.List;
+import java.util.Map;
import java.util.Set;
import org.apache.commons.logging.Log;
@@ -31,14 +33,21 @@ import org.apache.xmlgraphics.fonts.Glyphs;
*/
public class SingleByteFont extends CustomFont {
+ /** Code point that is used if no code point for a specific character has been found. */
+ public static final char NOT_FOUND = '#';
+
/** logger */
private static Log log = LogFactory.getLog(SingleByteFont.class);
- private CodePointMapping mapping;
+ private SingleByteEncoding mapping;
private int[] width = null;
private Set warnedChars;
+
+ private Map unencodedCharacters;
+ //Map<Character, UnencodedCharacter>
+ private List additionalEncodings;
/**
* Main constructor.
@@ -54,7 +63,7 @@ public class SingleByteFont extends CustomFont {
}
/** {@inheritDoc} */
- public String getEncoding() {
+ public String getEncodingName() {
return this.mapping.getName();
}
@@ -62,18 +71,28 @@ public class SingleByteFont extends CustomFont {
* Returns the code point mapping (encoding) of this font.
* @return the code point mapping
*/
- public CodePointMapping getCodePointMapping() {
+ public SingleByteEncoding getEncoding() {
return this.mapping;
}
/** {@inheritDoc} */
public int getWidth(int i, int size) {
- int idx = i - getFirstChar();
- if (idx >= 0 && idx < width.length) {
- return size * width[i - getFirstChar()];
- } else {
- return 0;
+ if (i < 256) {
+ int idx = i - getFirstChar();
+ if (idx >= 0 && idx < width.length) {
+ return size * width[i - getFirstChar()];
+ }
+ } else if (this.additionalEncodings != null) {
+ int encodingIndex = (i / 256) - 1;
+ SimpleSingleByteEncoding encoding = getAdditionalEncoding(encodingIndex);
+ int codePoint = i % 256;
+ NamedCharacter nc = encoding.getCharacterForIndex(codePoint);
+ UnencodedCharacter uc
+ = (UnencodedCharacter)this.unencodedCharacters.get(
+ new Character(nc.getSingleUnicodeValue()));
+ return size * uc.getWidth();
}
+ return 0;
}
/** {@inheritDoc} */
@@ -87,30 +106,80 @@ public class SingleByteFont extends CustomFont {
public char mapChar(char c) {
notifyMapOperation();
char d = mapping.mapChar(c);
- if (d != 0) {
+ if (d != SingleByteEncoding.NOT_FOUND_CODE_POINT) {
return d;
- } else {
- Character ch = new Character(c);
- if (warnedChars == null) {
- warnedChars = new java.util.HashSet();
+ }
+
+ //Check unencoded characters which are available in the font by character name
+ d = mapUnencodedChar(c);
+ if (d != SingleByteEncoding.NOT_FOUND_CODE_POINT) {
+ return d;
+ }
+
+ //Give up, character is not available
+ Character ch = new Character(c);
+ if (warnedChars == null) {
+ warnedChars = new java.util.HashSet();
+ }
+ if (warnedChars.size() < 8 && !warnedChars.contains(ch)) {
+ warnedChars.add(ch);
+ if (warnedChars.size() == 8) {
+ log.warn("Many requested glyphs are not available in font " + getFontName());
+ } else {
+ log.warn("Glyph " + (int)c + " (0x" + Integer.toHexString(c)
+ + ", " + Glyphs.charToGlyphName(c)
+ + ") not available in font " + getFontName());
}
- if (warnedChars.size() < 8 && !warnedChars.contains(ch)) {
- warnedChars.add(ch);
- if (warnedChars.size() == 8) {
- log.warn("Many requested glyphs are not available in font " + getFontName());
- } else {
- log.warn("Glyph " + (int)c + " (0x" + Integer.toHexString(c)
- + ", " + Glyphs.charToGlyphName(c)
- + ") not available in font " + getFontName());
+ }
+ return NOT_FOUND;
+ }
+
+ private char mapUnencodedChar(char ch) {
+ if (this.unencodedCharacters != null) {
+ UnencodedCharacter unencoded
+ = (UnencodedCharacter)this.unencodedCharacters.get(new Character(ch));
+ if (unencoded != null) {
+ if (this.additionalEncodings == null) {
+ this.additionalEncodings = new java.util.ArrayList();
+ }
+ SimpleSingleByteEncoding encoding = null;
+ char mappedStart = 0;
+ int additionalsCount = this.additionalEncodings.size();
+ for (int i = 0; i < additionalsCount; i++) {
+ mappedStart += 256;
+ encoding = getAdditionalEncoding(i);
+ char alt = encoding.mapChar(ch);
+ if (alt != 0) {
+ return (char)(mappedStart + alt);
+ }
+ }
+ if (encoding != null && encoding.isFull()) {
+ encoding = null;
}
+ if (encoding == null) {
+ encoding = new SimpleSingleByteEncoding(
+ getFontName() + "EncodingSupp" + (additionalsCount + 1));
+ this.additionalEncodings.add(encoding);
+ mappedStart += 256;
+ }
+ return (char)(mappedStart + encoding.addCharacter(unencoded.getCharacter()));
}
- return '#';
}
+ return 0;
}
/** {@inheritDoc} */
public boolean hasChar(char c) {
- return (mapping.mapChar(c) > 0);
+ char d = mapping.mapChar(c);
+ if (d != SingleByteEncoding.NOT_FOUND_CODE_POINT) {
+ return true;
+ }
+ //Check unencoded characters which are available in the font by character name
+ d = mapUnencodedChar(c);
+ if (d != SingleByteEncoding.NOT_FOUND_CODE_POINT) {
+ return true;
+ }
+ return false;
}
/* ---- single byte font specific setters --- */
@@ -146,13 +215,106 @@ public class SingleByteFont extends CustomFont {
/**
* Sets a width for a character.
* @param index index of the character
- * @param width the width of the character
+ * @param w the width of the character
*/
- public void setWidth(int index, int width) {
+ public void setWidth(int index, int w) {
if (this.width == null) {
this.width = new int[getLastChar() - getFirstChar() + 1];
}
- this.width[index - getFirstChar()] = width;
+ this.width[index - getFirstChar()] = w;
+ }
+
+ /**
+ * Adds an unencoded character (one that is not supported by the primary encoding).
+ * @param ch the named character
+ * @param width the width of the character
+ */
+ public void addUnencodedCharacter(NamedCharacter ch, int width) {
+ if (this.unencodedCharacters == null) {
+ this.unencodedCharacters = new java.util.HashMap();
+ }
+ if (ch.hasSingleUnicodeValue()) {
+ UnencodedCharacter uc = new UnencodedCharacter(ch, width);
+ this.unencodedCharacters.put(new Character(ch.getSingleUnicodeValue()), uc);
+ } else {
+ //Cannot deal with unicode sequences, so ignore this character
+ }
+ }
+
+ /**
+ * Indicates whether the encoding has additional encodings besides the primary encoding.
+ * @return true if there are additional encodings.
+ */
+ public boolean hasAdditionalEncodings() {
+ return (this.additionalEncodings != null) && (this.additionalEncodings.size() > 0);
+ }
+
+ /**
+ * Returns the number of additional encodings this single-byte font maintains.
+ * @return the number of additional encodings
+ */
+ public int getAdditionalEncodingCount() {
+ if (hasAdditionalEncodings()) {
+ return this.additionalEncodings.size();
+ } else {
+ return 0;
+ }
+ }
+
+ /**
+ * Returns an additional encoding.
+ * @param index the index of the additional encoding
+ * @return the additional encoding
+ * @throws IndexOutOfBoundsException if the index is out of bounds
+ */
+ public SimpleSingleByteEncoding getAdditionalEncoding(int index)
+ throws IndexOutOfBoundsException {
+ if (hasAdditionalEncodings()) {
+ return (SimpleSingleByteEncoding)this.additionalEncodings.get(index);
+ } else {
+ throw new IndexOutOfBoundsException("No additional encodings available");
+ }
+ }
+
+ /**
+ * Returns an array with the widths for an additional encoding.
+ * @param index the index of the additional encoding
+ * @return the width array
+ */
+ public int[] getAdditionalWidths(int index) {
+ SimpleSingleByteEncoding enc = getAdditionalEncoding(index);
+ int[] arr = new int[enc.getLastChar() - enc.getFirstChar() + 1];
+ for (int i = 0, c = arr.length; i < c; i++) {
+ NamedCharacter nc = enc.getCharacterForIndex(enc.getFirstChar() + i);
+ UnencodedCharacter uc = (UnencodedCharacter)this.unencodedCharacters.get(
+ new Character(nc.getSingleUnicodeValue()));
+ arr[i] = uc.getWidth();
+ }
+ return arr;
+ }
+
+ private static final class UnencodedCharacter {
+
+ private NamedCharacter character;
+ private int width;
+
+ public UnencodedCharacter(NamedCharacter character, int width) {
+ this.character = character;
+ this.width = width;
+ }
+
+ public NamedCharacter getCharacter() {
+ return this.character;
+ }
+
+ public int getWidth() {
+ return this.width;
+ }
+
+ /** {@inheritDoc} */
+ public String toString() {
+ return getCharacter().toString();
+ }
}
}
diff --git a/src/java/org/apache/fop/fonts/Typeface.java b/src/java/org/apache/fop/fonts/Typeface.java
index 3bc3be772..173d2e8a3 100644
--- a/src/java/org/apache/fop/fonts/Typeface.java
+++ b/src/java/org/apache/fop/fonts/Typeface.java
@@ -19,11 +19,8 @@
package org.apache.fop.fonts;
-// FOP
-
-
/**
- * Base class for PDF font classes
+ * Base class for font classes
*/
public abstract class Typeface implements FontMetrics {
@@ -37,7 +34,7 @@ public abstract class Typeface implements FontMetrics {
* Get the encoding of the font.
* @return the encoding
*/
- public abstract String getEncoding();
+ public abstract String getEncodingName();
/**
* Map a Unicode character to a code point in the font.
diff --git a/src/java/org/apache/fop/fonts/truetype/TTFSubSetFile.java b/src/java/org/apache/fop/fonts/truetype/TTFSubSetFile.java
index 99fd10315..d593c4544 100644
--- a/src/java/org/apache/fop/fonts/truetype/TTFSubSetFile.java
+++ b/src/java/org/apache/fop/fonts/truetype/TTFSubSetFile.java
@@ -592,8 +592,8 @@ public class TTFSubSetFile extends TTFFile {
+ mtxTab[origIndex.intValue()].getOffset()) < 0) {
// origIndex is a composite glyph
allComposites.put(origIndex, glyphs.get(origIndex));
- List composites =
- getIncludedGlyphs(in, (int)entry.getOffset(),
+ List composites
+ = getIncludedGlyphs(in, (int)entry.getOffset(),
origIndex);
// Iterate through all composites pointed to
@@ -651,6 +651,9 @@ public class TTFSubSetFile extends TTFFile {
if (!checkTTC(in, name)) {
throw new IOException("Failed to read font");
}
+
+ //Copy the Map as we're going to modify it
+ Map subsetGlyphs = new java.util.HashMap(glyphs);
output = new byte[in.getFileSize()];
@@ -661,14 +664,14 @@ public class TTFSubSetFile extends TTFFile {
readHorizontalMetrics(in);
readIndexToLocation(in);
- scanGlyphs(in, glyphs);
+ scanGlyphs(in, subsetGlyphs);
createDirectory(); // Create the TrueType header and directory
createHead(in);
- createHhea(in, glyphs.size()); // Create the hhea table
- createHmtx(in, glyphs); // Create hmtx table
- createMaxp(in, glyphs.size()); // copy the maxp table
+ createHhea(in, subsetGlyphs.size()); // Create the hhea table
+ createHmtx(in, subsetGlyphs); // Create hmtx table
+ createMaxp(in, subsetGlyphs.size()); // copy the maxp table
boolean optionalTableFound;
optionalTableFound = createCvt(in); // copy the cvt table
@@ -689,8 +692,8 @@ public class TTFSubSetFile extends TTFFile {
log.debug("TrueType: prep table not present. Skipped.");
}
- createLoca(glyphs.size()); // create empty loca table
- createGlyf(in, glyphs); //create glyf table and update loca table
+ createLoca(subsetGlyphs.size()); // create empty loca table
+ createGlyf(in, subsetGlyphs); //create glyf table and update loca table
pad4();
createCheckSumAdjustment();
diff --git a/src/java/org/apache/fop/fonts/type1/AFMCharMetrics.java b/src/java/org/apache/fop/fonts/type1/AFMCharMetrics.java
index 1b7f814b8..758078af4 100644
--- a/src/java/org/apache/fop/fonts/type1/AFMCharMetrics.java
+++ b/src/java/org/apache/fop/fonts/type1/AFMCharMetrics.java
@@ -21,6 +21,8 @@ package org.apache.fop.fonts.type1;
import java.awt.geom.RectangularShape;
+import org.apache.fop.fonts.NamedCharacter;
+
/**
* Holds the metrics of a single character from an AFM file.
@@ -28,8 +30,7 @@ import java.awt.geom.RectangularShape;
public class AFMCharMetrics {
private int charCode = -1;
- private String unicodeSequence;
- private String charName;
+ private NamedCharacter character;
private double widthX;
private double widthY;
private RectangularShape bBox;
@@ -59,36 +60,45 @@ public class AFMCharMetrics {
}
/**
- * Returns the Unicode sequence for this character.
- * @return the Unicode characters
- * (or null if no such Unicode sequence exists for this character)
+ * Returns the named character represented by this instance.
+ * @return the named character (or null if no named character is associated)
*/
- public String getUnicodeSequence() {
- return this.unicodeSequence;
+ public NamedCharacter getCharacter() {
+ return this.character;
+ }
+
+ /**
+ * Sets the named character represented by this instance.
+ * @param ch the named character
+ */
+ public void setCharacter(NamedCharacter ch) {
+ this.character = ch;
}
/**
- * Sets the Unicode sequence for this character.
+ * Sets the named character represented by this instance.
+ * @param charName the character name (as defined in the Adobe glyph list)
* @param unicodeSequence the Unicode sequence
*/
- public void setUnicodeSequence(String unicodeSequence) {
- this.unicodeSequence = unicodeSequence;
+ public void setCharacter(String charName, String unicodeSequence) {
+ setCharacter(new NamedCharacter(charName, unicodeSequence));
}
/**
- * Returns the PostScript character name.
- * @return the charName
+ * Returns the Unicode sequence for this character.
+ * @return the Unicode characters
+ * (or null if no such Unicode sequence exists for this character)
*/
- public String getCharName() {
- return charName;
+ public String getUnicodeSequence() {
+ return (getCharacter() != null ? getCharacter().getUnicodeSequence() : null);
}
/**
- * Sets the PostScript character name.
- * @param charName the charName to set
+ * Returns the PostScript character name.
+ * @return the charName (or null if no character name is associated)
*/
- public void setCharName(String charName) {
- this.charName = charName;
+ public String getCharName() {
+ return (getCharacter() != null ? getCharacter().getName() : null);
}
/**
diff --git a/src/java/org/apache/fop/fonts/type1/AFMFile.java b/src/java/org/apache/fop/fonts/type1/AFMFile.java
index b51485485..6a1973843 100644
--- a/src/java/org/apache/fop/fonts/type1/AFMFile.java
+++ b/src/java/org/apache/fop/fonts/type1/AFMFile.java
@@ -26,7 +26,6 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
-import org.apache.xmlgraphics.fonts.Glyphs;
import org.apache.xmlgraphics.java2d.Dimension2DDouble;
/**
@@ -315,15 +314,8 @@ public class AFMFile {
public void addCharMetrics(AFMCharMetrics metrics) {
String name = metrics.getCharName();
if (metrics.getUnicodeSequence() == null) {
- if (name != null) {
- String u = Glyphs.getUnicodeSequenceForGlyphName(metrics.getCharName());
- if (u != null) {
- metrics.setUnicodeSequence(u);
- }
- } else {
- //Ignore as no Unicode assignment is possible
- return;
- }
+ //Ignore as no Unicode assignment is possible
+ return;
}
this.charMetrics.add(metrics);
if (name != null) {
diff --git a/src/java/org/apache/fop/fonts/type1/AFMParser.java b/src/java/org/apache/fop/fonts/type1/AFMParser.java
index bb7ea3d30..2e63ea729 100644
--- a/src/java/org/apache/fop/fonts/type1/AFMParser.java
+++ b/src/java/org/apache/fop/fonts/type1/AFMParser.java
@@ -31,6 +31,8 @@ import java.util.Stack;
import org.apache.commons.io.IOUtils;
+import org.apache.fop.fonts.NamedCharacter;
+
/**
* Parses the contents of a Type 1 AFM font metrics file into an object structure ({@link AFMFile}).
*/
@@ -126,7 +128,7 @@ public class AFMParser {
VALUE_PARSERS.put(W, new NotImplementedYet(W));
VALUE_PARSERS.put(W0, new NotImplementedYet(W0));
VALUE_PARSERS.put(W1, new NotImplementedYet(W1));
- VALUE_PARSERS.put(N, new StringSetter("CharName"));
+ VALUE_PARSERS.put(N, new NamedCharacterSetter("Character"));
VALUE_PARSERS.put(B, new CharBBox());
VALUE_PARSERS.put(START_TRACK_KERN, new NotImplementedYet(START_TRACK_KERN));
VALUE_PARSERS.put(END_TRACK_KERN, new NotImplementedYet(END_TRACK_KERN));
@@ -379,6 +381,19 @@ public class AFMParser {
}
}
+ private static class NamedCharacterSetter extends BeanSetter {
+
+ public NamedCharacterSetter(String variable) {
+ super(variable);
+ }
+
+ public void parse(String line, int startpos, Stack stack) throws IOException {
+ NamedCharacter ch = new NamedCharacter(getStringValue(line, startpos));
+ Object obj = stack.peek();
+ setValue(obj, ch);
+ }
+ }
+
private static class NumberSetter extends BeanSetter {
public NumberSetter(String variable) {
super(variable);
diff --git a/src/java/org/apache/fop/fonts/type1/Type1FontLoader.java b/src/java/org/apache/fop/fonts/type1/Type1FontLoader.java
index 910ee82cc..8cf6f2371 100644
--- a/src/java/org/apache/fop/fonts/type1/Type1FontLoader.java
+++ b/src/java/org/apache/fop/fonts/type1/Type1FontLoader.java
@@ -108,6 +108,11 @@ public class Type1FontLoader extends FontLoader {
throw new java.io.FileNotFoundException(
"Neither an AFM nor a PFM file was found for " + this.fontFileURI);
}
+ if (pfm == null) {
+ //Cannot do without the PFM for now
+ throw new java.io.FileNotFoundException(
+ "No PFM file was found for " + this.fontFileURI);
+ }
buildFont(afm, pfm);
this.loaded = true;
}
@@ -122,12 +127,17 @@ public class Type1FontLoader extends FontLoader {
singleFont.setEmbedFileName(this.fontFileURI);
returnFont = singleFont;
+ handleEncoding(afm, pfm);
+ handleFontName(afm, pfm);
+ handleMetrics(afm, pfm);
+ }
+
+ private void handleEncoding(AFMFile afm, PFMFile pfm) {
//Encoding
if (afm != null) {
String encoding = afm.getEncodingScheme();
if ("AdobeStandardEncoding".equals(encoding)) {
- //Use WinAnsi in this case as it better fits the usual character set people need
- singleFont.setEncoding(CodePointMapping.WIN_ANSI_ENCODING);
+ singleFont.setEncoding(CodePointMapping.STANDARD_ENCODING);
} else {
String effEncodingName;
if ("FontSpecific".equals(encoding)) {
@@ -142,6 +152,14 @@ public class Type1FontLoader extends FontLoader {
CodePointMapping mapping = buildCustomEncoding(effEncodingName, afm);
singleFont.setEncoding(mapping);
}
+ List charMetrics = afm.getCharMetrics();
+ for (int i = 0, c = afm.getCharCount(); i < c; i++) {
+ AFMCharMetrics metrics = (AFMCharMetrics)charMetrics.get(i);
+ if (!metrics.hasCharCode() && metrics.getCharacter() != null) {
+ singleFont.addUnencodedCharacter(metrics.getCharacter(),
+ (int)Math.round(metrics.getWidthX()));
+ }
+ }
} else {
if (pfm.getCharSet() >= 0 && pfm.getCharSet() <= 2) {
singleFont.setEncoding(pfm.getCharSetName() + "Encoding");
@@ -151,7 +169,9 @@ public class Type1FontLoader extends FontLoader {
singleFont.setEncoding("WinAnsiEncoding"); //Try fallback, no guarantees!
}
}
-
+ }
+
+ private void handleFontName(AFMFile afm, PFMFile pfm) {
//Font name
if (afm != null) {
returnFont.setFontName(afm.getFontName()); //PostScript font name
@@ -168,7 +188,9 @@ public class Type1FontLoader extends FontLoader {
names.add(pfm.getWindowsName()); //emulate afm.getFamilyName()
returnFont.setFamilyNames(names);
}
-
+ }
+
+ private void handleMetrics(AFMFile afm, PFMFile pfm) {
//Basic metrics
if (afm != null) {
if (afm.getCapHeight() != null) {
@@ -268,6 +290,7 @@ public class Type1FontLoader extends FontLoader {
if (afm != null) {
//TODO returnFont.setFlags(flags);
+
returnFont.setFirstChar(afm.getFirstChar());
returnFont.setLastChar(afm.getLastChar());
Iterator iter = afm.getCharMetrics().iterator();
@@ -279,7 +302,6 @@ public class Type1FontLoader extends FontLoader {
}
returnFont.replaceKerningMap(afm.createXKerningMapEncoded());
} else {
- returnFont.setFlags(pfm.getFlags());
returnFont.setFirstChar(pfm.getFirstChar());
returnFont.setLastChar(pfm.getLastChar());
for (short i = pfm.getFirstChar(); i <= pfm.getLastChar(); i++) {
@@ -287,6 +309,7 @@ public class Type1FontLoader extends FontLoader {
}
returnFont.replaceKerningMap(pfm.getKerning());
}
+ returnFont.setFlags(pfm.getFlags());
}
private CodePointMapping buildCustomEncoding(String encodingName, AFMFile afm) {
diff --git a/src/java/org/apache/fop/image/AbstractFopImage.java b/src/java/org/apache/fop/image/AbstractFopImage.java
deleted file mode 100644
index 68949b9c9..000000000
--- a/src/java/org/apache/fop/image/AbstractFopImage.java
+++ /dev/null
@@ -1,376 +0,0 @@
-/*
- * 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.image;
-
-// Java
-import java.awt.color.ColorSpace;
-import java.awt.color.ICC_ColorSpace;
-import java.awt.color.ICC_Profile;
-import java.io.InputStream;
-import java.awt.Color;
-
-import org.apache.commons.io.IOUtils;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.fop.datatypes.Length;
-
-/**
- * Base class to implement the FopImage interface.
- *
- * @see FopImage
- */
-public abstract class AbstractFopImage implements FopImage {
-
- /**
- * logging instance
- */
- protected static Log log = LogFactory.getLog(AbstractFopImage.class);
-
- /**
- * Keeps track of what has been loaded.
- */
- protected int loaded = 0;
-
- /**
- * Image width (in pixel).
- */
- protected int width = 0;
-
- /**
- * Image height (in pixel).
- */
- protected int height = 0;
-
- /** Horizontal bitmap resolution (in dpi) */
- protected double dpiHorizontal = 72.0f;
-
- /** Vertical bitmap resolution (in dpi) */
- protected double dpiVertical = 72.0f;
-
- /**
- * Image input stream.
- */
- protected InputStream inputStream = null;
-
- /**
- * ImageReader object (to obtain image header informations).
- */
- protected FopImage.ImageInfo imageInfo = null;
-
- /**
- * Image color space (java.awt.color.ColorSpace).
- */
- protected ColorSpace colorSpace = null;
-
- /**
- * Bits per pixel.
- */
- protected int bitsPerPixel = 0;
-
- /**
- * Image data (pixels, uncompressed).
- */
- protected byte[] bitmaps = null;
-
- /**
- * Image data (undecoded, compressed, for image formats that can be embedded without decoding.
- */
- protected byte[] raw = null;
-
- /**
- * Image transparency.
- */
- protected boolean isTransparent = false;
-
- /**
- * Transparent color (java.awt.Color).
- */
- protected Color transparentColor = null;
-
- /**
- * Photoshop generated CMYK JPEGs are inverted.
- */
- protected boolean invertImage = false;
-
- /**
- * Constructor.
- * Construct a new FopImage object and initialize its default properties:
- * <UL>
- * <LI>image width
- * <LI>image height
- * </UL>
- * The image data isn't kept in memory.
- * @param info image information
- */
- public AbstractFopImage(FopImage.ImageInfo info) {
- this.inputStream = info.inputStream;
- this.imageInfo = info;
- if (this.imageInfo.width != -1) {
- width = imageInfo.width;
- height = imageInfo.height;
- dpiHorizontal = imageInfo.dpiHorizontal;
- dpiVertical = imageInfo.dpiVertical;
- loaded = loaded | DIMENSIONS;
- }
- }
-
- /**
- * Get the mime type for this image.
- *
- * @return the mime type for the image
- */
- public String getMimeType() {
- return imageInfo.mimeType;
- }
-
- /** {@inheritDoc} */
- public String getOriginalURI() {
- return this.imageInfo.originalURI;
- }
-
- /**
- * Load image data and initialize its properties.
- *
- * @param type the type of loading to do
- * @return true if the loading was successful
- */
- public synchronized boolean load(int type) {
- if ((loaded & type) != 0) {
- return true;
- }
- boolean success = true;
- if (((type & DIMENSIONS) != 0) && ((loaded & DIMENSIONS) == 0)) {
- success = success && loadDimensions();
-
- if (!success) {
- return false;
- }
- loaded = loaded | DIMENSIONS;
- }
- if (((type & BITMAP) != 0) && ((loaded & BITMAP) == 0)) {
- success = success && loadBitmap();
- if (success) {
- loaded = loaded | BITMAP;
- }
- }
- if (((type & ORIGINAL_DATA) != 0) && ((loaded & ORIGINAL_DATA) == 0)) {
- success = success && loadOriginalData();
- if (success) {
- loaded = loaded | ORIGINAL_DATA;
- }
- }
- return success;
- }
-
- /**
- * Load the dimensions of the image.
- * All implementations should override this to get and
- * return the dimensions.
- *
- * @return true if the loading was successful
- */
- protected boolean loadDimensions() {
- return false;
- }
-
- /**
- * Load a bitmap array of the image.
- * If the renderer requires a bitmap image then the
- * implementations should override this to load the bitmap.
- *
- * @return true if the loading was successful
- */
- protected boolean loadBitmap() {
- return false;
- }
-
- /**
- * Load the original image data.
- * In some cases the original data can be used by the renderer.
- * This should load the data and any other associated information.
- *
- * @return true if the loading was successful
- */
- protected boolean loadOriginalData() {
- return false;
- }
-
- /**
- * Load the original image data. This is generic code for use by any
- * subclass that wants to use this from a loadOriginalData() implementation.
- *
- * @return true if the loading was successful
- */
- protected boolean loadDefaultOriginalData() {
- if (inputStream == null) {
- throw new IllegalStateException("inputStream is already null or was never set");
- }
- try {
- this.raw = IOUtils.toByteArray(inputStream);
- } catch (java.io.IOException ex) {
- log.error("Error while reading raw image: " + ex.getMessage(), ex);
- return false;
- } finally {
- IOUtils.closeQuietly(inputStream);
- inputStream = null;
- }
- return true;
- }
-
- /**
- * @return the image width (in pixels)
- */
- public int getWidth() {
- return this.width;
- }
-
- /**
- * @return the image height (in pixels)
- */
- public int getHeight() {
- return this.height;
- }
-
- /** {@inheritDoc} */
- public int getIntrinsicWidth() {
- return (int)(getWidth() * 72000 / getHorizontalResolution());
- }
-
- /** {@inheritDoc} */
- public int getIntrinsicHeight() {
- return (int)(getHeight() * 72000 / getVerticalResolution());
- }
-
- /** {@inheritDoc} */
- public Length getIntrinsicAlignmentAdjust() {
- return this.imageInfo.alignmentAdjust;
- }
-
- /** {@inheritDoc} */
- public double getHorizontalResolution() {
- return this.dpiHorizontal;
- }
-
- /** {@inheritDoc} */
- public double getVerticalResolution() {
- return this.dpiVertical;
- }
-
- /**
- * Return the image color space.
- * @return the image color space (java.awt.color.ColorSpace)
- */
- public ColorSpace getColorSpace() {
- return this.colorSpace;
- }
-
- /**
- * Get ICC profile for this image.
- * @return the icc profile or null if not applicable
- */
- public ICC_Profile getICCProfile() {
- if (this.colorSpace != null && this.colorSpace instanceof ICC_ColorSpace) {
- return ((ICC_ColorSpace)this.colorSpace).getProfile();
- }
- return null;
- }
-
- /**
- * Return the number of bits per pixel.
- * @return number of bits per pixel
- */
- public int getBitsPerPixel() {
- return this.bitsPerPixel;
- }
-
- /**
- * Return the image transparency.
- * @return true if the image is transparent
- */
- public boolean isTransparent() {
- return this.isTransparent;
- }
-
- /**
- * Check if this image has a soft mask.
- *
- * @return true if the image also has a soft transparency mask
- */
- public boolean hasSoftMask() {
- return false;
- }
-
- /**
- * Get the soft mask.
- * The soft mask should have the same bitdepth as the image data.
- *
- * @return the data array of soft mask values
- */
- public byte[] getSoftMask() {
- return null;
- }
-
- /**
- * Return the transparent color.
- * @return the transparent color (java.awt.Color)
- */
- public Color getTransparentColor() {
- return this.transparentColor;
- }
-
- /** @return true for CMYK images generated by Adobe Photoshop */
- public boolean isInverted() {
- return this.invertImage;
- }
-
- /**
- * Return the image data (pixels, uncompressed).
- * @return the image data
- */
- public byte[] getBitmaps() {
- return this.bitmaps;
- }
-
- /**
- * Return the image data size (number of bytes taken up by the uncompressed pixels).
- * @return the image data size
- */
- public int getBitmapsSize() {
- return (bitmaps != null ? bitmaps.length : 0);
- }
-
- /**
- * Return the original image data (compressed).
- * @return the original image data
- */
- public byte[] getResourceBytes() {
- return raw;
- }
-
- /**
- * Return the original image data size (compressed).
- * @return the original image data size
- */
- public int getResourceBytesSize() {
- return (raw != null ? raw.length : 0);
- }
-
-}
-
diff --git a/src/java/org/apache/fop/image/BmpImage.java b/src/java/org/apache/fop/image/BmpImage.java
deleted file mode 100644
index 5ebf522e9..000000000
--- a/src/java/org/apache/fop/image/BmpImage.java
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
- * 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.image;
-
-// Java
-import java.io.IOException;
-import java.awt.color.ColorSpace;
-
-import org.apache.commons.io.IOUtils;
-
-/**
- * Bitmap image.
- * This supports loading a bitmap image into bitmap data.
- *
- * @see AbstractFopImage
- * @see FopImage
- */
-public class BmpImage extends AbstractFopImage {
- /**
- * Create a bitmap image with the image data.
- *
- * @param imgInfo the image information
- */
- public BmpImage(FopImage.ImageInfo imgInfo) {
- super(imgInfo);
- }
-
- /**
- * Load the bitmap.
- * This laods the bitmap data from the bitmap image.
- *
- * @return true if it was loaded successfully
- */
- protected boolean loadBitmap() {
- int wpos = 18;
- int hpos = 22; // offset positioning for w and height in bmp files
- int[] headermap = new int[54];
- int filepos = 0;
- byte[] palette = null;
- try {
- boolean eof = false;
- while ((!eof) && (filepos < 54)) {
- int input = inputStream.read();
- if (input == -1) {
- eof = true;
- } else {
- headermap[filepos++] = input;
- }
- }
-
- if (headermap[28] == 4 || headermap[28] == 8) {
- int palettesize = 1 << headermap[28];
- palette = new byte[palettesize * 3];
- int countr = 0;
- while (!eof && countr < palettesize) {
- int count2 = 2;
- while (!eof && count2 >= -1) {
- int input = inputStream.read();
- if (input == -1) {
- eof = true;
- } else if (count2 >= 0) {
- palette[countr * 3 + count2] = (byte)(input & 0xFF);
- }
- count2--;
- filepos++;
- }
- countr++;
- }
- }
- } catch (IOException ex) {
- log.error("Error while loading image (Bmp): " + ex.getMessage(), ex);
- IOUtils.closeQuietly(inputStream);
- inputStream = null;
- return false;
- }
- // gets h & w from headermap
- this.width = headermap[wpos]
- + headermap[wpos + 1] * 256
- + headermap[wpos + 2] * 256 * 256
- + headermap[wpos + 3] * 256 * 256 * 256;
- this.height = headermap[hpos]
- + headermap[hpos + 1] * 256
- + headermap[hpos + 2] * 256 * 256
- + headermap[hpos + 3] * 256 * 256 * 256;
-
- int imagestart = headermap[10]
- + headermap[11] * 256
- + headermap[12] * 256 * 256
- + headermap[13] * 256 * 256 * 256;
- this.bitsPerPixel = headermap[28];
- this.colorSpace = ColorSpace.getInstance(ColorSpace.CS_LINEAR_RGB);
- int bytes = 0;
- if (this.bitsPerPixel == 1) {
- bytes = (this.width + 7) / 8;
- } else if (this.bitsPerPixel == 24) {
- bytes = this.width * 3;
- } else if (this.bitsPerPixel == 4 || this.bitsPerPixel == 8) {
- bytes = this.width / (8 / this.bitsPerPixel);
- } else {
- log.error("Image (" + ""
- + ") has " + this.bitsPerPixel
- + " which is not a supported BMP format.");
- return false;
- }
- if ((bytes & 0x03) != 0) {
- bytes |= 0x03;
- bytes++;
- }
-
- // Should take care of the ColorSpace and bitsPerPixel
- this.bitmaps = new byte[this.width * this.height * 3];
-
- int[] temp = new int[bytes * this.height];
- try {
- int input;
- int count = 0;
- inputStream.skip((long)(imagestart - filepos));
- while ((input = inputStream.read()) != -1) {
- if (count >= temp.length) {
- log.warn("Data longer than expected while loading image");
- break;
- } else {
- temp[count++] = input;
- }
- }
- } catch (IOException ex) {
- log.error("Error while loading image (Bmp): " + ex.getMessage(), ex);
- return false;
- } finally {
- IOUtils.closeQuietly(inputStream);
- inputStream = null;
- }
-
- for (int i = 0; i < this.height; i++) {
- int x = 0;
- int j = 0;
- while (j < bytes) {
- int p = temp[(this.height - i - 1) * bytes + j];
-
- if (this.bitsPerPixel == 24 && x < this.width) {
- int countr = 2;
- do {
- this.bitmaps[3 * (i * this.width + x) + countr]
- = (byte)(temp[(this.height - i - 1) * bytes + j] & 0xFF);
- j++;
- } while (--countr >= 0)
- ;
- x++;
- } else if (this.bitsPerPixel == 1) {
- for (int countr = 0;
- countr < 8 && x < this.width; countr++) {
- if ((p & 0x80) != 0) {
- this.bitmaps[3 * (i * this.width + x)] = (byte) 0xFF;
- this.bitmaps[3 * (i * this.width + x) + 1] = (byte) 0xFF;
- this.bitmaps[3 * (i * this.width + x) + 2] = (byte) 0xFF;
- } else {
- this.bitmaps[3 * (i * this.width + x)] = (byte) 0;
- this.bitmaps[3 * (i * this.width + x) + 1] = (byte) 0;
- this.bitmaps[3 * (i * this.width + x) + 2] = (byte) 0;
- }
- p <<= 1;
- x++;
- }
- j++;
- } else if (this.bitsPerPixel == 4) {
- for (int countr = 0;
- countr < 2 && x < this.width; countr++) {
- int pal = ((p & 0xF0) >> 4) * 3;
- this.bitmaps[3 * (i * this.width + x)] = palette[pal];
- this.bitmaps[3 * (i * this.width + x) + 1] = palette[pal + 1];
- this.bitmaps[3 * (i * this.width + x) + 2] = palette[pal + 2];
- p <<= 4;
- x++;
- }
- j++;
- } else if (this.bitsPerPixel == 8) {
- if (x < this.width) {
- p *= 3;
- this.bitmaps[3 * (i * this.width + x)] = palette[p];
- this.bitmaps[3 * (i * this.width + x) + 1] = palette[p + 1];
- this.bitmaps[3 * (i * this.width + x) + 2] = palette[p + 2];
- j++;
- x++;
- } else {
- j = bytes;
- }
- } else {
- j++;
- }
- }
- }
-
- // This seems really strange to me, but I noticed that
- // JimiImage hardcodes bitsPerPixel to 8. If I do not
- // do this Acrobat is unable to read the resultant PDF,
- // so we will hardcode this...
- this.bitsPerPixel = 8;
-
- return true;
- }
-
-}
-
diff --git a/src/java/org/apache/fop/image/EPSImage.java b/src/java/org/apache/fop/image/EPSImage.java
deleted file mode 100644
index ab708f2a4..000000000
--- a/src/java/org/apache/fop/image/EPSImage.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * 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.image;
-
-
-/**
- * EPS image handler.
- * This handles the Encapulated PostScript images.
- * It gets the dimensions and original data from the analyser.
- *
- * @see AbstractFopImage
- * @see FopImage
- */
-public class EPSImage extends AbstractFopImage {
-
- private String docName;
- private int[] bbox;
-
- private EPSData epsData = null;
-
- /**
- * Create an EPS image with the image information.
- *
- * @param imgInfo the information containing the data and bounding box
- */
- public EPSImage(FopImage.ImageInfo imgInfo) {
- super(imgInfo);
- init("");
- if (imgInfo.data instanceof EPSData) {
- epsData = (EPSData) imgInfo.data;
- bbox = new int[4];
- bbox[0] = (int) epsData.bbox[0];
- bbox[1] = (int) epsData.bbox[1];
- bbox[2] = (int) epsData.bbox[2];
- bbox[3] = (int) epsData.bbox[3];
-
- loaded = loaded | ORIGINAL_DATA;
- }
- }
-
- /**
- * Initialize docName and bounding box.
- * @param name the document name
- */
- private void init(String name) {
- bbox = new int[4];
- bbox[0] = 0;
- bbox[1] = 0;
- bbox[2] = 0;
- bbox[3] = 0;
-
- docName = name;
- }
-
- /**
- * Return the name of the eps
- * @return the name of the eps
- */
- public String getDocName() {
- return docName;
- }
-
- /**
- * Return the bounding box
- * @return an int array containing the bounding box
- */
- public int[] getBBox() {
- return bbox;
- }
-
- /**
- * Get the eps image.
- *
- * @return the original eps image data
- */
- public byte[] getEPSImage() {
- if (epsData.epsFile == null) {
- //log.error("ERROR LOADING EXTERNAL EPS");
- }
- return epsData.epsFile;
- }
-
- /**
- * Data for EPS image.
- */
- public static class EPSData {
- public long[] bbox;
- public boolean isAscii; // True if plain ascii eps file
-
- // offsets if not ascii
- public long psStart = 0;
- public long psLength = 0;
- public long wmfStart = 0;
- public long wmfLength = 0;
- public long tiffStart = 0;
- public long tiffLength = 0;
-
- /** raw eps file */
- public byte[] rawEps;
- /** eps part */
- public byte[] epsFile;
- public byte[] preview = null;
- }
-
-}
diff --git a/src/java/org/apache/fop/image/FopImage.java b/src/java/org/apache/fop/image/FopImage.java
deleted file mode 100644
index abe11ef25..000000000
--- a/src/java/org/apache/fop/image/FopImage.java
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- * 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.image;
-
-import java.io.InputStream;
-import java.awt.color.ColorSpace;
-import java.awt.color.ICC_Profile;
-import java.awt.Color;
-
-import org.apache.fop.datatypes.Length;
-
-/**
- * Fop image interface for loading images.
- */
-public interface FopImage {
- /**
- * Flag for loading dimensions.
- */
- int DIMENSIONS = 1;
-
- /**
- * Flag for loading original data.
- */
- int ORIGINAL_DATA = 2;
-
- /**
- * Flag for loading bitmap data.
- */
- int BITMAP = 4;
-
- /**
- * Get the mime type of this image.
- * This is used so that when reading from the image it knows
- * what type of image it is.
- *
- * @return the mime type string
- */
- String getMimeType();
-
- /** @return the original URI used to access this image. */
- String getOriginalURI();
-
- /**
- * Load particular inforamtion for this image
- * This must be called before attempting to get
- * the information.
- *
- * @param type the type of loading required
- * @return boolean true if the information could be loaded
- */
- boolean load(int type);
-
- /**
- * Returns the image width.
- * @return the width in pixels
- */
- int getWidth();
-
- /**
- * Returns the image height.
- * @return the height in pixels
- */
- int getHeight();
-
- /**
- * @return the intrinsic image width (in millipoints)
- */
- int getIntrinsicWidth();
-
- /**
- * @return the intrinsic image width (in millipoints)
- */
- int getIntrinsicHeight();
-
- /**
- * @return the intrinsic alignment-adjust value or NULL if the image does
- * not have one.
- */
- Length getIntrinsicAlignmentAdjust();
-
- /**
- * @return the horizontal bitmap resolution (in dpi)
- */
- double getHorizontalResolution();
-
- /**
- * @return the vertical bitmap resolution (in dpi)
- */
- double getVerticalResolution();
-
- /**
- * Returns the color space of the image.
- * @return the color space
- */
- ColorSpace getColorSpace();
-
- /**
- * Returns the ICC profile.
- * @return the ICC profile, null if none is available
- */
- ICC_Profile getICCProfile();
-
- /**
- * Returns the number of bits per pixel for the image.
- * @return the number of bits per pixel
- */
- int getBitsPerPixel();
-
- /**
- * Indicates whether the image is transparent.
- * @return True if it is transparent
- */
- boolean isTransparent();
-
- /**
- * For transparent images. Returns the transparent color.
- * @return the transparent color
- */
- Color getTransparentColor();
-
- /**
- * Indicates whether the image has a Soft Mask (See section 7.5.4 in the
- * PDF specs)
- * @return True if a Soft Mask exists
- */
- boolean hasSoftMask();
-
- /**
- * For images with a Soft Mask. Returns the Soft Mask as an array.
- * @return the Soft Mask
- */
- byte[] getSoftMask();
-
- /** @return true for CMYK images generated by Adobe Photoshop */
- boolean isInverted();
-
- /**
- * Returns the decoded and uncompressed image as a array of
- * width * height * [colorspace-multiplicator] pixels.
- * @return the bitmap
- */
- byte[] getBitmaps();
- /**
- * Returns the size of the image.
- * width * (bitsPerPixel / 8) * height, no ?
- * @return the size
- */
- int getBitmapsSize();
-
- /**
- * Returns the encoded/compressed image as an array of bytes.
- * @return the raw image
- */
- byte[] getResourceBytes();
-
- /**
- * Returns the number of bytes of the raw image.
- * @return the size in bytes
- */
- int getResourceBytesSize();
-
- /**
- * Image info class.
- * Information loaded from analyser and passed to image object.
- */
- public static class ImageInfo {
- /** InputStream to load the image from */
- public InputStream inputStream;
- /** Original URI the image was accessed with */
- public String originalURI;
- /** image width (in pixels) */
- public int width;
- /** image height (in pixels) */
- public int height;
- /** horizontal bitmap resolution (in dpi) */
- public double dpiHorizontal = 72.0f;
- /** vertical bitmap resolution (in dpi) */
- public double dpiVertical = 72.0f;
- /** implementation-specific data object (ex. a SVG DOM for SVG images) */
- public Object data;
- /** MIME type of the image */
- public String mimeType;
- /** implementation-specific String (ex. the namespace for XML-based images) */
- public String str;
- /** intrinsic alignment-adjust or null if there is none */
- public Length alignmentAdjust;
- }
-
-}
-
diff --git a/src/java/org/apache/fop/image/FopImageConsumer.java b/src/java/org/apache/fop/image/FopImageConsumer.java
deleted file mode 100644
index 4e4d7be48..000000000
--- a/src/java/org/apache/fop/image/FopImageConsumer.java
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * 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.image;
-
-// Java
-import java.util.Hashtable;
-import java.awt.image.ColorModel;
-import java.awt.image.ImageConsumer;
-import java.awt.image.ImageProducer;
-import java.awt.image.PixelGrabber;
-
-/**
- * ImageConsumer implementation for FopImage classes.
- */
-public class FopImageConsumer implements ImageConsumer {
-
- /** Image width in pixels */
- protected int width = -1;
- /** Image height in pixels */
- protected int height = -1;
- /** Image status */
- protected Integer imageStatus = new Integer(-1);
- /** hints */
- protected int hints = 0;
- /** Image properties */
- protected Hashtable properties = null;
- /** Color model */
- protected ColorModel cm = null;
- /** Image producer */
- protected ImageProducer ip = null;
-
- /**
- * Main constructor
- * @param iprod ImageProducer to use
- */
- public FopImageConsumer(ImageProducer iprod) {
- this.ip = iprod;
- }
-
- /**
- * {@inheritDoc}
- */
- public void imageComplete(int status) {
- /*
- * log.error("Status ");
- * if (status == ImageConsumer.COMPLETESCANLINES) {
- * log.error("CompleteScanLines");
- * } else if (status == ImageConsumer.IMAGEABORTED) {
- * log.error("ImageAborted");
- * } else if (status == ImageConsumer.IMAGEERROR) {
- * log.error("ImageError");
- * } else if (status == ImageConsumer.RANDOMPIXELORDER) {
- * log.error("RandomPixelOrder");
- * } else if (status == ImageConsumer.SINGLEFRAME) {
- * log.error("SingleFrame");
- * } else if (status == ImageConsumer.SINGLEFRAMEDONE) {
- * log.error("SingleFrameDone");
- * } else if (status == ImageConsumer.SINGLEPASS) {
- * log.error("SinglePass");
- * } else if (status == ImageConsumer.STATICIMAGEDONE) {
- * log.error("StaticImageDone");
- * } else if (status == ImageConsumer.TOPDOWNLEFTRIGHT) {
- * log.error("TopDownLeftRight");
- * }
- */
- synchronized (this.imageStatus) {
- // Need to stop status if image done
- if (imageStatus.intValue() != ImageConsumer.STATICIMAGEDONE
- && imageStatus.intValue() != ImageConsumer.SINGLEFRAMEDONE) {
- this.imageStatus = new Integer(status);
- }
- }
- }
-
- /**
- * {@inheritDoc}
- */
- public void setColorModel(ColorModel model) {
- // log.error("setColorModel: " + model);
- this.cm = model;
- }
-
- /**
- * {@inheritDoc}
- */
- public void setDimensions(int width, int height) {
- // log.error("setDimension: w=" + width + " h=" + height);
- this.width = width;
- this.height = height;
- }
-
- /**
- * {@inheritDoc}
- */
- public void setHints(int hintflags) {
- // log.error("setHints: " + hintflags);
- this.hints = hintflags;
- }
-
- /**
- * {@inheritDoc}
- */
- public void setProperties(Hashtable props) {
- // log.error("setProperties: " + props);
- this.properties = props;
- }
-
- /**
- * {@inheritDoc}
- */
- public void setPixels(int x, int y, int w, int h, ColorModel model,
- byte[] pixels, int off, int scansize) {
- }
-
- /**
- * {@inheritDoc}
- */
- public void setPixels(int x, int y, int w, int h, ColorModel model,
- int[] pixels, int off, int scansize) {
- }
-
- /**
- * Indicates whether the image is ready.
- * @return boolean True if the image is ready, false if it's still loading
- * @throws Exception If an error happened while loading the image
- */
- public boolean isImageReady() throws Exception {
- /**@todo Use a better exception than Exception */
- synchronized (this.imageStatus) {
- if (this.imageStatus.intValue() == ImageConsumer.IMAGEABORTED) {
- throw new Exception("Image aborted");
- }
- if (this.imageStatus.intValue() == ImageConsumer.IMAGEERROR) {
- throw new Exception("Image error");
- }
-
- if (imageStatus.intValue() == ImageConsumer.STATICIMAGEDONE
- || imageStatus.intValue() == ImageConsumer.SINGLEFRAMEDONE) {
- return true;
- }
-
- return false;
- }
- }
-
- /**
- * Returns the image width
- * @return the width in pixels
- */
- public int getWidth() {
- return this.width;
- }
-
- /**
- * Returns the image height
- * @return the height in pixels
- */
- public int getHeight() {
- return this.height;
- }
-
- /**
- * Returns the color model of the image
- * @return the color model
- */
- public ColorModel getColorModel() {
- return this.cm;
- }
-
- /**
- * Returns the bitmap as an array.
- * @return the bitmap as an array.
- * @throws Exception if an error occured while generating the array
- */
- public int[] getImage() throws Exception {
- int tmpMap[] = new int[this.width * this.height];
- PixelGrabber pg = new PixelGrabber(this.ip, 0, 0, this.width,
- this.height, tmpMap, 0, this.width);
- pg.setDimensions(this.width, this.height);
- pg.setColorModel(this.cm);
- pg.setHints(this.hints);
- pg.setProperties(this.properties);
- try {
- pg.grabPixels();
- } catch (InterruptedException intex) {
- /**@todo Use a better exception than Exception */
- throw new Exception("Image grabbing interrupted : "
- + intex.getMessage());
- }
- return tmpMap;
- }
-
-}
-
diff --git a/src/java/org/apache/fop/image/GifImage.java b/src/java/org/apache/fop/image/GifImage.java
deleted file mode 100644
index 27e81c4fc..000000000
--- a/src/java/org/apache/fop/image/GifImage.java
+++ /dev/null
@@ -1,218 +0,0 @@
-/*
- * 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.image;
-
-// Java
-import java.awt.image.ImageProducer;
-import java.awt.image.ColorModel;
-import java.awt.image.IndexColorModel;
-import java.awt.color.ColorSpace;
-import java.awt.Color;
-import java.io.InputStream;
-import java.io.IOException;
-import java.net.URLConnection;
-
-import org.apache.commons.io.IOUtils;
-
-/**
- * FopImage object for GIF images, using Java native classes.
- *
- * @see AbstractFopImage
- * @see FopImage
- */
-public class GifImage extends AbstractFopImage {
-
- /**
- * Create a new gif image.
- *
- * @param imgInfo the image info for this gif image
- */
- public GifImage(FopImage.ImageInfo imgInfo) {
- super(imgInfo);
- }
-
- /**
- * Load the bitmap for this gif image.
- * This loads the data and creates a bitmap byte array
- * of the image data.
- * To decode the image a dummy URLConnection is used that
- * will do the conversion.
- *
- * @return True if the load process succeeded
- */
- protected boolean loadBitmap() {
- int[] tmpMap = null;
- try {
- URLConnection con = new DummyConnection(inputStream);
-
- ImageProducer ip = (ImageProducer) con.getContent();
- if (ip == null) {
- return false;
- }
- FopImageConsumer consumer = new FopImageConsumer(ip);
- ip.startProduction(consumer);
-
- //Load the image into memory
- while (!consumer.isImageReady()) {
- Thread.sleep(500);
- }
-
- this.height = consumer.getHeight();
- this.width = consumer.getWidth();
-
- try {
- tmpMap = consumer.getImage();
- } catch (Exception ex) {
- log.error("Image grabbing interrupted : "
- + ex.getMessage(), ex);
- return false;
- }
-
- ColorModel cm = consumer.getColorModel();
- this.bitsPerPixel = 8;
- // this.bitsPerPixel = cm.getPixelSize();
- this.colorSpace = ColorSpace.getInstance(ColorSpace.CS_LINEAR_RGB);
- if (cm.hasAlpha()) {
- // java.awt.Transparency. BITMASK or OPAQUE or TRANSLUCENT
- int transparencyType = cm.getTransparency();
-
- if (transparencyType == java.awt.Transparency.OPAQUE) {
- this.isTransparent = false;
- } else if (transparencyType == java.awt.Transparency.BITMASK) {
- if (cm instanceof IndexColorModel) {
- IndexColorModel indexcm = (IndexColorModel) cm;
- this.isTransparent = false;
- byte[] alphas = new byte[indexcm.getMapSize()];
- byte[] reds = new byte[indexcm.getMapSize()];
- byte[] greens = new byte[indexcm.getMapSize()];
- byte[] blues = new byte[indexcm.getMapSize()];
- indexcm.getAlphas(alphas);
- indexcm.getReds(reds);
- indexcm.getGreens(greens);
- indexcm.getBlues(blues);
- for (int i = 0;
- i < indexcm.getMapSize();
- i++) {
- if ((alphas[i] & 0xFF) == 0) {
- this.isTransparent = true;
- this.transparentColor = new Color(
- (int)(reds[i] & 0xFF),
- (int)(greens[i] & 0xFF),
- (int)(blues[i] & 0xFF));
- break;
- }
- }
- } else {
- // TRANSLUCENT
- /*
- * this.isTransparent = false;
- * for (int i = 0; i < this.width * this.height; i++) {
- * if (cm.getAlpha(tmpMap[i]) == 0) {
- * this.isTransparent = true;
- * this.transparentColor = new PDFColor(cm.getRed(tmpMap[i]),
- * cm.getGreen(tmpMap[i]), cm.getBlue(tmpMap[i]));
- * break;
- * }
- * }
- */
- // use special API...
- this.isTransparent = false;
- }
- } else {
- this.isTransparent = false;
- }
- } else {
- this.isTransparent = false;
- }
- } catch (Exception ex) {
- log.error("Error while loading image (Gif): " + ex.getMessage(), ex);
- return false;
- } finally {
- IOUtils.closeQuietly(inputStream);
- inputStream = null;
- }
-
- // Should take care of the ColorSpace and bitsPerPixel
- this.bitmaps = new byte[this.width * this.height * 3];
- for (int i = 0; i < this.height; i++) {
- for (int j = 0; j < this.width; j++) {
- int p = tmpMap[i * this.width + j];
- int r = (p >> 16) & 0xFF;
- int g = (p >> 8) & 0xFF;
- int b = (p) & 0xFF;
- this.bitmaps[3 * (i * this.width + j)] = (byte)(r & 0xFF);
- this.bitmaps[3 * (i * this.width + j) + 1] = (byte)(g & 0xFF);
- this.bitmaps[3 * (i * this.width + j) + 2] = (byte)(b & 0xFF);
- }
- }
- return true;
- }
-
- /** {@inheritDoc} */
- protected boolean loadOriginalData() {
- return loadDefaultOriginalData();
- }
-
- /**
- * A dummy url connection for a gif image in an input stream.
- */
- protected static class DummyConnection extends URLConnection {
- private InputStream inputStream;
-
- DummyConnection(InputStream is) {
- super(null);
- inputStream = is;
- }
-
- /**
- * {@inheritDoc}
- */
- public InputStream getInputStream() throws IOException {
- return inputStream;
- }
-
- /**
- * {@inheritDoc}
- */
- public void connect() throws IOException {
- // do nothing
- }
-
- /**
- * {@inheritDoc}
- */
- public String getContentType() {
- return "image/gif";
- }
-
- /**
- * {@inheritDoc}
- */
- public int getContentLength() {
- try {
- return inputStream.available();
- } catch (IOException e) {
- return -1;
- }
- }
-
- }
-}
-
diff --git a/src/java/org/apache/fop/image/ImageCache.java b/src/java/org/apache/fop/image/ImageCache.java
deleted file mode 100644
index 3dd639823..000000000
--- a/src/java/org/apache/fop/image/ImageCache.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * 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.image;
-
-// FOP
-import org.apache.fop.apps.FOUserAgent;
-
-/**
- * Image cache holder.
- * This interface is used for caching images.
- */
-public interface ImageCache {
-
- /**
- * Get an image from the cache.
- *
- * @param url the url and key for the image
- * @param context the user agent context
- * @return the requested image
- */
- FopImage getImage(String url, FOUserAgent context);
-
- /**
- * Release an image in the current context.
- *
- * @param url the url and key for the image
- * @param context the user agent context
- */
- void releaseImage(String url, FOUserAgent context);
-
- /**
- * Invalidate image.
- * If during loading this image is found to be invalid
- * it will be invalidated to prevent further attempts at
- * loading the image.
- *
- * @param url the url and key for the image
- * @param context the user agent context
- */
- void invalidateImage(String url, FOUserAgent context);
-
- /**
- * Remove a context and handle all images in the context.
- *
- * @param context the user agent context
- */
- void removeContext(FOUserAgent context);
-
- /**
- * Forces the cache to fully cleared.
- */
- void clearAll();
-
-}
-
diff --git a/src/java/org/apache/fop/image/ImageFactory.java b/src/java/org/apache/fop/image/ImageFactory.java
deleted file mode 100644
index 5c9f198e8..000000000
--- a/src/java/org/apache/fop/image/ImageFactory.java
+++ /dev/null
@@ -1,708 +0,0 @@
-/*
- * 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.image;
-
-// Java
-import java.io.InputStream;
-import java.lang.ref.Reference;
-import java.lang.ref.ReferenceQueue;
-import java.lang.ref.SoftReference;
-import java.lang.reflect.Constructor;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.Map.Entry;
-
-import javax.xml.transform.Source;
-import javax.xml.transform.stream.StreamSource;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.fop.apps.FOUserAgent;
-import org.apache.fop.datatypes.URISpecification;
-import org.apache.fop.image.analyser.ImageReaderFactory;
-import org.apache.xmlgraphics.util.Service;
-
-/**
- * Create FopImage objects (with a configuration file - not yet implemented).
- * @author Eric SCHAEFFER
- */
-public final class ImageFactory {
-
- /**
- * logging instance
- */
- protected static Log log = LogFactory.getLog(FopImage.class);
-
- private HashMap imageMimeTypes = new HashMap();
-
- private ImageCache cache = new ContextImageCache(true);
-
- /**
- * Main constructor for the ImageFactory.
- */
- public ImageFactory() {
- /* @todo The mappings set up below of image mime types to implementing
- * classes should be made externally configurable
- */
- ImageProvider jaiImage = new ImageProvider("JAIImage", "org.apache.fop.image.JAIImage");
- ImageProvider jimiImage = new ImageProvider("JIMIImage", "org.apache.fop.image.JimiImage");
- ImageProvider imageIoImage = new ImageProvider(
- "ImageIOImage", "org.apache.fop.image.ImageIOImage");
- ImageProvider gifImage = new ImageProvider("GIFImage", "org.apache.fop.image.GifImage");
- ImageProvider jpegImage = new ImageProvider("JPEGImage", "org.apache.fop.image.JpegImage");
- ImageProvider jpegImageIOImage = new ImageProvider(
- "JPEGImage", "org.apache.fop.image.JpegImageIOImage");
- ImageProvider bmpImage = new ImageProvider("BMPImage", "org.apache.fop.image.BmpImage");
- ImageProvider epsImage = new ImageProvider("EPSImage", "org.apache.fop.image.EPSImage");
- ImageProvider pngImage = new ImageProvider("PNGImage", "org.apache.fop.image.PNGImage");
- ImageProvider tiffImage = new ImageProvider("TIFFImage", "org.apache.fop.image.TIFFImage");
- ImageProvider xmlImage = new ImageProvider("XMLImage", "org.apache.fop.image.XMLImage");
- ImageProvider emfImage = new ImageProvider("EMFImage", "org.apache.fop.image.EmfImage");
-
- ImageMimeType imt = new ImageMimeType("image/gif");
- imageMimeTypes.put(imt.getMimeType(), imt);
- imt.addProvider(imageIoImage);
- imt.addProvider(jaiImage);
- imt.addProvider(jimiImage);
- imt.addProvider(gifImage);
-
- imt = new ImageMimeType("image/jpeg");
- imageMimeTypes.put(imt.getMimeType(), imt);
- imt.addProvider(jpegImageIOImage);
- imt.addProvider(jpegImage);
-
- imt = new ImageMimeType("image/bmp");
- imageMimeTypes.put(imt.getMimeType(), imt);
- imt.addProvider(bmpImage);
-
- imt = new ImageMimeType("image/eps");
- imageMimeTypes.put(imt.getMimeType(), imt);
- imt.addProvider(epsImage);
-
- imt = new ImageMimeType("image/png");
- imageMimeTypes.put(imt.getMimeType(), imt);
- //Image I/O is faster and more memory-efficient than own codec for PNG
- imt.addProvider(imageIoImage);
- imt.addProvider(pngImage);
-
- imt = new ImageMimeType("image/tga");
- imageMimeTypes.put(imt.getMimeType(), imt);
- imt.addProvider(jaiImage);
- imt.addProvider(imageIoImage);
- imt.addProvider(jimiImage);
-
- imt = new ImageMimeType("image/tiff");
- imageMimeTypes.put(imt.getMimeType(), imt);
- imt.addProvider(tiffImage); //Slower but supports CCITT embedding
- imt.addProvider(imageIoImage); //Fast but doesn't support CCITT embedding
- imt.addProvider(jaiImage); //Fast but doesn't support CCITT embedding
-
- imt = new ImageMimeType("image/svg+xml");
- imageMimeTypes.put(imt.getMimeType(), imt);
- imt.addProvider(xmlImage);
-
- imt = new ImageMimeType("text/xml");
- imageMimeTypes.put(imt.getMimeType(), imt);
- imt.addProvider(xmlImage);
-
- imt = new ImageMimeType("image/emf");
- imageMimeTypes.put(imt.getMimeType(), imt);
- imt.addProvider(emfImage);
-
- Iterator iter = Service.providers(RegisterableImageProvider.class, true);
- while (iter.hasNext()) {
- RegisterableImageProvider impl = (RegisterableImageProvider)iter.next();
- imt = new ImageMimeType(impl.getSupportedMimeType());
- imageMimeTypes.put(imt.getMimeType(), imt);
- imt.addProvider(new ImageProvider(impl.getName(), impl.getClassName()));
- }
- }
-
- /**
- * Get the url string from a wrapped url.
- *
- * @param href the input wrapped url
- * @return the raw url
- */
- public static String getURL(String href) {
- return URISpecification.getURL(href);
- }
-
- /**
- * Get the image from the cache or load.
- * If this returns null then the image could not be loaded
- * due to an error. Messages should be logged.
- * Before calling this the getURL(url) must be used.
- *
- * @param url the url for the image
- * @param context the user agent context
- * @return the fop image instance
- */
- public FopImage getImage(String url, FOUserAgent context) {
- return cache.getImage(url, context);
- }
-
- /**
- * Release an image from the cache.
- * This can be used if the renderer has its own cache of
- * the image.
- * The image should then be put into the weak cache.
- *
- * @param url the url for the image
- * @param context the user agent context
- */
- public void releaseImage(String url, FOUserAgent context) {
- cache.releaseImage(url, context);
- }
-
- /**
- * Release the context and all images in the context.
- *
- * @param context the context to remove
- */
- public void removeContext(FOUserAgent context) {
- cache.removeContext(context);
- }
-
- /**
- * Create an FopImage objects.
- * @param href the url for the image
- * @param ua the user agent context
- * @return the fop image instance
- */
- public FopImage loadImage(String href, FOUserAgent ua) {
-
- Source source = ua.resolveURI(href);
- if (source == null) {
- return null;
- }
-
- // Got a valid source, obtain an InputStream from it
- InputStream in = null;
- if (source instanceof StreamSource) {
- in = ((StreamSource)source).getInputStream();
- }
- if (in == null) {
- try {
- in = new java.net.URL(source.getSystemId()).openStream();
- } catch (Exception ex) {
- log.error("Unable to obtain stream from id '"
- + source.getSystemId() + "'");
- }
- }
- if (in == null) {
- return null;
- }
-
- //Make sure the InputStream is decorated with a BufferedInputStream
- if (!(in instanceof java.io.BufferedInputStream)) {
- in = new java.io.BufferedInputStream(in);
- }
-
- // Check image type
- FopImage.ImageInfo imgInfo = null;
- try {
- imgInfo = ImageReaderFactory.make(source.getSystemId(), in, ua);
- } catch (Exception e) {
- log.error("Error while recovering image information ("
- + href + ") : " + e.getMessage(), e);
- return null;
- }
- if (imgInfo == null) {
- try {
- in.close();
- in = null;
- } catch (Exception e) {
- log.debug("Error closing the InputStream for the image", e);
- }
- log.error("No ImageReader for this type of image (" + href + ")");
- return null;
- }
- // Associate mime-type to FopImage class
- String imgMimeType = imgInfo.mimeType;
- Class imageClass = getImageClass(imgMimeType);
- if (imageClass == null) {
- log.error("Unsupported image type (" + href + "): " + imgMimeType);
- return null;
- } else {
- if (log.isDebugEnabled()) {
- log.debug("Loading " + imgMimeType + " with " + imageClass.getName()
- + ": " + href);
- }
- }
-
- // load the right image class
- // return new <FopImage implementing class>
- Object imageInstance = null;
- try {
- Class[] imageConstructorParameters = new Class[1];
- imageConstructorParameters[0] = org.apache.fop.image.FopImage.ImageInfo.class;
- Constructor imageConstructor = imageClass.getDeclaredConstructor(
- imageConstructorParameters);
- Object[] initArgs = new Object[1];
- initArgs[0] = imgInfo;
- imageInstance = imageConstructor.newInstance(initArgs);
- } catch (java.lang.reflect.InvocationTargetException ex) {
- Throwable t = ex.getTargetException();
- String msg;
- if (t != null) {
- msg = t.getMessage();
- } else {
- msg = ex.getMessage();
- }
- log.error("Error creating FopImage object ("
- + href + "): " + msg, (t == null) ? ex : t);
- return null;
- } catch (InstantiationException ie) {
- log.error("Error creating FopImage object ("
- + href + "): Could not instantiate " + imageClass.getName() + " instance");
- return null;
- } catch (Exception ex) {
- log.error("Error creating FopImage object ("
- + href + "): " + ex.getMessage(), ex);
- return null;
- }
- if (!(imageInstance instanceof org.apache.fop.image.FopImage)) {
- log.error("Error creating FopImage object (" + href + "): " + "class "
- + imageClass.getName()
- + " doesn't implement org.apache.fop.image.FopImage interface");
- return null;
- }
- return (FopImage) imageInstance;
- }
-
- private Class getImageClass(String imgMimeType) {
- ImageMimeType imt = (ImageMimeType)imageMimeTypes.get(imgMimeType);
- if (imt == null) {
- return null;
- }
- return imt.getFirstImplementingClass();
- }
-
- /**
- * Forces all the image caches to be cleared. This should normally only be used in
- * testing environments. If you happen to think that you need to call this yourself
- * in a production environment, please notify the development team so we can look
- * into the issue. A call like this shouldn't be necessary anymore like it may have
- * been with FOP 0.20.5.
- */
- public void clearCaches() {
- cache.clearAll();
- }
-}
-
-/**
- * Basic image cache.
- * This keeps track of invalid images.
- */
-class BasicImageCache implements ImageCache {
-
- private Set invalid = Collections.synchronizedSet(new java.util.HashSet());
- //private Map contextStore = Collections.synchronizedMap(new java.util.HashMap());
-
- public FopImage getImage(String url, FOUserAgent context) {
- if (invalid.contains(url)) {
- return null;
- }
- //TODO Doesn't seem to be fully implemented. Do we need it at all? Not referenced.
- return null;
- }
-
- public void releaseImage(String url, FOUserAgent context) {
- // do nothing
- }
-
- public void invalidateImage(String url, FOUserAgent context) {
- // cap size of invalid list
- if (invalid.size() > 100) {
- invalid.clear();
- }
- invalid.add(url);
- }
-
- public void removeContext(FOUserAgent context) {
- // do nothing
- }
-
- /** {@inheritDoc} */
- public void clearAll() {
- invalid.clear();
- }
-
-}
-
-/**
- * This is the context image cache.
- * This caches images on the basis of the given context.
- * Common images in different contexts are currently not handled.
- * There are two possiblities, each context handles its own images
- * and renderers can cache information or images are shared and
- * all information is retained.
- * Once a context is removed then all images are placed into a
- * weak hashmap so they may be garbage collected.
- */
-class ContextImageCache implements ImageCache {
-
- // if this cache is collective then images can be shared
- // among contexts, this implies that the base directory
- // is either the same or does not effect the images being
- // loaded
- private boolean collective;
- private Map contextStore = Collections.synchronizedMap(new java.util.HashMap());
- private Set invalid = null;
- private Map refStore = null;
- private ReferenceQueue refQueue = new ReferenceQueue();
-
- public ContextImageCache(boolean col) {
- collective = col;
- if (collective) {
- refStore = Collections.synchronizedMap(new java.util.HashMap());
- invalid = Collections.synchronizedSet(new java.util.HashSet());
- }
- }
-
- // sync around lookups and puts
- // another sync around load for a particular image
- public FopImage getImage(String url, FOUserAgent context) {
- ImageLoader im = null;
- // this protects the finding or creating of a new
- // ImageLoader for multi threads
- synchronized (this) {
- if (collective && invalid.contains(url)) {
- return null;
- }
- Context con = (Context) contextStore.get(context);
- if (con == null) {
- con = new Context(context, collective);
- contextStore.put(context, con);
- } else {
- if (con.invalid(url)) {
- return null;
- }
- im = con.getImage(url);
- }
- if (im == null && collective) {
- Iterator i = contextStore.values().iterator();
- while (i.hasNext()) {
- Context c = (Context)i.next();
- if (c != con) {
- im = c.getImage(url);
- if (im != null) {
- break;
- }
- }
- }
- if (im == null) {
- Reference ref = (Reference)refStore.get(url);
- if (ref != null) {
- im = (ImageLoader) ref.get();
- if (im == null) {
- //Remove key if its value has been garbage collected
- refStore.remove(url);
- }
- }
- }
- }
-
- if (im != null) {
- con.putImage(url, im);
- } else {
- im = con.getImage(url, this);
- }
- }
-
- // the ImageLoader is synchronized so images with the
- // same url will not be loaded at the same time
- if (im != null) {
- return im.loadImage();
- }
- return null;
- }
-
- public void releaseImage(String url, FOUserAgent context) {
- Context con = (Context) contextStore.get(context);
- if (con != null) {
- if (collective) {
- ImageLoader im = con.getImage(url);
- refStore.put(url, wrapInReference(im, url));
- }
- con.releaseImage(url);
- }
- }
-
- public void invalidateImage(String url, FOUserAgent context) {
- if (collective) {
- // cap size of invalid list
- if (invalid.size() > 100) {
- invalid.clear();
- }
- invalid.add(url);
- }
- Context con = (Context) contextStore.get(context);
- if (con != null) {
- con.invalidateImage(url);
- }
- }
-
- private Reference wrapInReference(Object obj, Object key) {
- return new SoftReferenceWithKey(obj, key, refQueue);
- }
-
- private static class SoftReferenceWithKey extends SoftReference {
-
- private Object key;
-
- public SoftReferenceWithKey(Object referent, Object key, ReferenceQueue q) {
- super(referent, q);
- this.key = key;
- }
- }
-
- public void removeContext(FOUserAgent context) {
- Context con = (Context) contextStore.get(context);
- if (con != null) {
- if (collective) {
- Map images = con.getImages();
- Iterator iter = images.entrySet().iterator();
- while (iter.hasNext()) {
- Entry entry = (Entry)iter.next();
- refStore.put(entry.getKey(),
- wrapInReference(entry.getValue(), entry.getKey()));
- }
- }
- contextStore.remove(context);
- }
- //House-keeping (remove cleared references)
- checkReferenceQueue();
- }
-
- /**
- * Checks the reference queue if any references have been cleared and removes them from the
- * cache.
- */
- private void checkReferenceQueue() {
- SoftReferenceWithKey ref;
- while ((ref = (SoftReferenceWithKey)refQueue.poll()) != null) {
- refStore.remove(ref.key);
- }
- }
-
- class Context {
- private Map images = Collections.synchronizedMap(new java.util.HashMap());
- private Set invalid = null;
- private FOUserAgent userAgent;
-
- public Context(FOUserAgent ua, boolean inv) {
- userAgent = ua;
- if (inv) {
- invalid = Collections.synchronizedSet(new java.util.HashSet());
- }
- }
-
- public ImageLoader getImage(String url, ImageCache c) {
- if (images.containsKey(url)) {
- return (ImageLoader) images.get(url);
- }
- ImageLoader loader = new ImageLoader(url, c, userAgent);
- images.put(url, loader);
- return loader;
- }
-
- public void putImage(String url, ImageLoader image) {
- images.put(url, image);
- }
-
- public ImageLoader getImage(String url) {
- return (ImageLoader) images.get(url);
- }
-
- public void releaseImage(String url) {
- images.remove(url);
- }
-
- public Map getImages() {
- return images;
- }
-
- public void invalidateImage(String url) {
- invalid.add(url);
- }
-
- public boolean invalid(String url) {
- return invalid.contains(url);
- }
-
- }
-
- /** {@inheritDoc} */
- public void clearAll() {
- this.refStore.clear();
- this.invalid.clear();
- //The context-sensitive caches are not cleared so there are no negative side-effects
- //in a multi-threaded environment. Not that it's a good idea to use this method at
- //all except in testing environments. If such a calls is necessary in normal environments
- //we need to check on memory leaks!
- }
-
-}
-
-/**
- * Encapsulates a class of type FopImage by holding its class name.
- * This allows dynamic loading of the class at runtime.
- */
-class ImageProvider {
-
- private String name = null;
-
- private String className = null;
-
- private boolean checked = false;
-
- private Class clazz = null;
-
- /**
- * Creates an ImageProvider with a given name and implementing class.
- * The class name should refer to a class of type {@link FopImage}.
- * However, this is not checked on construction.
- * @param name The name of the provider
- * @param className The full class name of the class implementing this provider
- */
- public ImageProvider(String name, String className) {
- setName(name);
- setClassName(className);
- }
-
- /**
- * Returns the provider name.
- * @return The provider name
- */
- public String getName() {
- return name;
- }
-
- private void setName(String name) {
- this.name = name;
- }
-
- /**
- * Returns the implementing class name.
- * @return The implementing class name
- */
- public String getClassName() {
- return className;
- }
-
- private void setClassName(String className) {
- this.className = className;
- }
-
- /**
- * Returns the implementing class as a {@link Class} object.
- * @return The implementing class or null if it couldn't be loaded.
- */
- public Class getImplementingClass() {
- if (!checked) {
- try {
- clazz = Class.forName(getClassName());
- } catch (ClassNotFoundException cnfe) {
- //nop
- } catch (LinkageError le) {
- // This can happen if fop was build with support for a
- // particular provider (e.g. a binary fop distribution)
- // but the required support files (e.g. jai, jimi) are not
- // available in the current runtime environment.
- ImageFactory.log.debug("Image support provider " + getName()
- + " could not be loaded. If " + getName() + " should be"
- + " available please make sure all required external libraries"
- + " are on the classpath.");
- }
- checked = true;
- }
- return clazz;
- }
-}
-
-/**
- * Holds a mime type for a particular image format plus a list of
- * {@link ImageProvider} objects which support the particular image format.
- */
-class ImageMimeType {
-
- private String mimeType = null;
-
- private List providers = null;
-
- /**
- * Constructor for a particular mime type.
- * @param mimeType The mime type
- */
- public ImageMimeType(String mimeType) {
- setMimeType(mimeType);
- }
-
- /**
- * Returns the mime type.
- * @return The mime type
- */
- public String getMimeType() {
- return mimeType;
- }
-
- private void setMimeType(String mimeType) {
- this.mimeType = mimeType;
- }
-
- /**
- * Returns the class from the first available provider.
- * @return The first available class or null if none can be found
- */
- public Class getFirstImplementingClass() {
- if (providers == null) {
- return null;
- }
- for (Iterator it = providers.iterator(); it.hasNext();) {
- ImageProvider ip = (ImageProvider)it.next();
- Class clazz = ip.getImplementingClass();
- if (clazz != null) {
- return clazz;
- }
- }
- return null;
- }
-
- /**
- * Adds a new provider.
- * The provider is added to the end of the current provider list.
- * @param The new provider to add
- */
- public void addProvider(ImageProvider provider) {
- if (providers == null) {
- providers = new ArrayList(4); // Assume we only have a few providers
- }
- if (!providers.contains(provider)) {
- providers.add(provider);
- }
- }
-} \ No newline at end of file
diff --git a/src/java/org/apache/fop/image/ImageLoader.java b/src/java/org/apache/fop/image/ImageLoader.java
deleted file mode 100644
index 111ef919f..000000000
--- a/src/java/org/apache/fop/image/ImageLoader.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * 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.image;
-
-import org.apache.fop.apps.FOUserAgent;
-
-/**
- * Class to load images.
- */
-class ImageLoader {
-
- private String url;
- private ImageCache cache;
- private boolean valid = true;
- private FOUserAgent userAgent;
- private FopImage image = null;
-
- /**
- * Main constructor.
- * @param url URL to the image
- * @param cache Image cache
- * @param ua User agent
- */
- public ImageLoader(String url, ImageCache cache, FOUserAgent ua) {
- this.url = url;
- this.cache = cache;
- this.userAgent = ua;
- }
-
- /**
- * Loads the image.
- * @return the loaded image
- */
- public synchronized FopImage loadImage() {
- if (!valid || image != null) {
- return image;
- }
- ImageFactory imageFactory = userAgent.getFactory().getImageFactory();
- image = imageFactory.loadImage(url, userAgent);
- if (image == null) {
- cache.invalidateImage(url, userAgent);
- valid = false;
- }
- return image;
- }
-
-}
diff --git a/src/java/org/apache/fop/image/JAIImage.java b/src/java/org/apache/fop/image/JAIImage.java
deleted file mode 100644
index 8b3074052..000000000
--- a/src/java/org/apache/fop/image/JAIImage.java
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- * 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.image;
-
-// AWT
-import java.awt.image.ColorModel;
-import java.awt.image.IndexColorModel;
-import java.awt.image.BufferedImage;
-import java.awt.Color;
-
-// JAI
-import javax.media.jai.JAI;
-import javax.media.jai.RenderedOp;
-
-import org.apache.commons.io.IOUtils;
-// Sun codec
-import com.sun.media.jai.codec.FileCacheSeekableStream;
-
-/**
- * FopImage object using JAI.
- *
- * @see AbstractFopImage
- * @see FopImage
- */
-public class JAIImage extends AbstractFopImage {
-
- /**
- * Create a new JAI image.
- *
- * @param imgInfo the image info for this JAI image
- */
- public JAIImage(FopImage.ImageInfo imgInfo) {
- super(imgInfo);
- }
-
- /**
- * {@inheritDoc}
- */
- protected boolean loadDimensions() {
- if (this.bitmaps == null) {
- loadImage();
- }
- return this.bitmaps != null;
- }
-
- /**
- * {@inheritDoc}
- */
- protected boolean loadBitmap() {
- if (this.bitmaps == null) {
- loadImage();
- }
-
- return this.bitmaps != null;
- }
-
- /**
- * Loads the image from the inputstream
- */
- protected void loadImage() {
- com.sun.media.jai.codec.FileCacheSeekableStream seekableInput = null;
- RenderedOp imageOp = null;
- try {
- seekableInput = new FileCacheSeekableStream(inputStream);
- imageOp = JAI.create("stream", seekableInput);
-
- this.height = imageOp.getHeight();
- this.width = imageOp.getWidth();
-
- ColorModel cm = imageOp.getColorModel();
- //this.bitsPerPixel = 8;
- this.bitsPerPixel = cm.getPixelSize();
-
- // TODO: the getRGB() function converts the image into the RGB
- // colorspace. However, here we assume the image colorspace is kept.
- // It should be either one of them, but not both. Unfortunately
- // there are other hacks for images in the CMYK colorspace (e.g. in
- // the PDF output) that would need to be changed as well.
-
- //this.colorSpace = ColorSpace.getInstance(ColorSpace.CS_LINEAR_RGB);
- this.colorSpace = cm.getColorSpace();
-
- BufferedImage imageData = imageOp.getAsBufferedImage();
- int[] tmpMap = imageData.getRGB(0, 0, this.width,
- this.height, null, 0, this.width);
-
- if (cm.hasAlpha()) {
- // java.awt.Transparency. BITMASK or OPAQUE or TRANSLUCENT
- int transparencyType = cm.getTransparency();
-
- if (transparencyType == java.awt.Transparency.OPAQUE) {
- this.isTransparent = false;
- } else if (transparencyType == java.awt.Transparency.BITMASK) {
- if (cm instanceof IndexColorModel) {
- this.isTransparent = false;
- byte[] alphas = new byte[
- ((IndexColorModel) cm).getMapSize()];
- byte[] reds = new byte[
- ((IndexColorModel) cm).getMapSize()];
- byte[] greens = new byte[
- ((IndexColorModel) cm).getMapSize()];
- byte[] blues = new byte[
- ((IndexColorModel) cm).getMapSize()];
- ((IndexColorModel) cm).getAlphas(alphas);
- ((IndexColorModel) cm).getReds(reds);
- ((IndexColorModel) cm).getGreens(greens);
- ((IndexColorModel) cm).getBlues(blues);
- for (int i = 0;
- i < ((IndexColorModel) cm).getMapSize();
- i++) {
- if ((alphas[i] & 0xFF) == 0) {
- this.isTransparent = true;
- this.transparentColor = new Color(
- (int)(reds[i] & 0xFF),
- (int)(greens[i] & 0xFF),
- (int)(blues[i] & 0xFF));
- break;
- }
- }
- } else {
- // TRANSLUCENT
- /*
- * this.isTransparent = false;
- * for (int i = 0; i < this.width * this.height; i++) {
- * if (cm.getAlpha(tmpMap[i]) == 0) {
- * this.isTransparent = true;
- * this.transparentColor = new PDFColor(cm.getRed(tmpMap[i]),
- * cm.getGreen(tmpMap[i]), cm.getBlue(tmpMap[i]));
- * break;
- * }
- * }
- * // or use special API...
- */
- this.isTransparent = false;
- }
- } else {
- this.isTransparent = false;
- }
- } else {
- this.isTransparent = false;
- }
-
- // Should take care of the ColorSpace and bitsPerPixel
- this.bitmaps = new byte[this.width * this.height * 3];
- for (int i = 0; i < this.height; i++) {
- for (int j = 0; j < this.width; j++) {
- int p = tmpMap[i * this.width + j];
- int r = (p >> 16) & 0xFF;
- int g = (p >> 8) & 0xFF;
- int b = (p) & 0xFF;
- this.bitmaps[3 * (i * this.width + j)] = (byte)(r & 0xFF);
- this.bitmaps[3 * (i * this.width + j) + 1] = (byte)(g & 0xFF);
- this.bitmaps[3 * (i * this.width + j) + 2] = (byte)(b & 0xFF);
- }
- }
-
- } catch (Exception ex) {
- log.error("Error while loading image (JAI): " + ex.getMessage(), ex);
- } finally {
- IOUtils.closeQuietly(inputStream);
- inputStream = null;
- if (imageOp != null) {
- imageOp.dispose();
- }
- if (seekableInput != null) {
- IOUtils.closeQuietly(seekableInput);
- }
- }
- }
-
- /** {@inheritDoc} */
- protected boolean loadOriginalData() {
- return loadDefaultOriginalData();
- }
-
-}
-
diff --git a/src/java/org/apache/fop/image/JimiImage.java b/src/java/org/apache/fop/image/JimiImage.java
deleted file mode 100644
index 49fb0b2e0..000000000
--- a/src/java/org/apache/fop/image/JimiImage.java
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * 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.image;
-
-// Java
-import java.awt.image.ImageProducer;
-import java.awt.image.ColorModel;
-import java.awt.image.IndexColorModel;
-import java.awt.color.ColorSpace;
-import java.awt.Color;
-
-import org.apache.commons.io.IOUtils;
-
-// Jimi
-import com.sun.jimi.core.Jimi;
-
-/**
- * FopImage object for several images types, using Jimi.
- * See Jimi documentation for supported image types.
- *
- * @see AbstractFopImage
- * @see FopImage
- */
-public class JimiImage extends AbstractFopImage {
-
- /**
- * Create a new Jimi image.
- *
- * @param imgInfo the image info for this Jimi image
- */
- public JimiImage(FopImage.ImageInfo imgInfo) {
- super(imgInfo);
- }
-
- /**
- * {@inheritDoc}
- */
- protected boolean loadDimensions() {
- if (this.bitmaps == null) {
- loadImage();
- }
-
- return this.bitmaps != null;
- }
-
- /**
- * {@inheritDoc}
- */
- protected boolean loadBitmap() {
- if (this.bitmaps == null) {
- loadImage();
- }
-
- return this.bitmaps != null;
- }
-
- /**
- * Loads the image from the inputstream
- */
- protected void loadImage() {
- int[] tmpMap = null;
- try {
- ImageProducer ip = Jimi.getImageProducer(inputStream,
- Jimi.SYNCHRONOUS | Jimi.IN_MEMORY);
- FopImageConsumer consumer = new FopImageConsumer(ip);
- ip.startProduction(consumer);
-
- while (!consumer.isImageReady()) {
- Thread.sleep(500);
- }
- this.height = consumer.getHeight();
- this.width = consumer.getWidth();
-
- try {
- tmpMap = consumer.getImage();
- } catch (Exception ex) {
- log.error("Image grabbing interrupted", ex);
- return;
- }
-
- ColorModel cm = consumer.getColorModel();
- this.bitsPerPixel = 8;
- // this.bitsPerPixel = cm.getPixelSize();
- this.colorSpace = ColorSpace.getInstance(ColorSpace.CS_LINEAR_RGB);
- if (cm.hasAlpha()) {
- // java.awt.Transparency. BITMASK or OPAQUE or TRANSLUCENT
- int transparencyType = cm.getTransparency();
- if (transparencyType == java.awt.Transparency.OPAQUE) {
- this.isTransparent = false;
- } else if (transparencyType == java.awt.Transparency.BITMASK) {
- if (cm instanceof IndexColorModel) {
- this.isTransparent = false;
- byte[] alphas = new byte[
- ((IndexColorModel) cm).getMapSize()];
- byte[] reds = new byte[
- ((IndexColorModel) cm).getMapSize()];
- byte[] greens = new byte[
- ((IndexColorModel) cm).getMapSize()];
- byte[] blues = new byte[
- ((IndexColorModel) cm).getMapSize()];
- ((IndexColorModel) cm).getAlphas(alphas);
- ((IndexColorModel) cm).getReds(reds);
- ((IndexColorModel) cm).getGreens(greens);
- ((IndexColorModel) cm).getBlues(blues);
- for (int i = 0;
- i < ((IndexColorModel) cm).getMapSize();
- i++) {
- if ((alphas[i] & 0xFF) == 0) {
- this.isTransparent = true;
- this.transparentColor = new Color(
- (int)(reds[i] & 0xFF),
- (int)(greens[i] & 0xFF),
- (int)(blues[i] & 0xFF));
- break;
- }
- }
- } else {
- // TRANSLUCENT
- /*
- * this.isTransparent = false;
- * for (int i = 0; i < this.width * this.height; i++) {
- * if (cm.getAlpha(tmpMap[i]) == 0) {
- * this.isTransparent = true;
- * this.transparentColor = new PDFColor(cm.getRed(tmpMap[i]),
- * cm.getGreen(tmpMap[i]), cm.getBlue(tmpMap[i]));
- * break;
- * }
- * }
- */
- // use special API...
- this.isTransparent = false;
- }
- } else {
- this.isTransparent = false;
- }
- } else {
- this.isTransparent = false;
- }
- } catch (Throwable ex) {
- log.error("Error while loading image (Jimi): " + ex.getMessage(), ex);
- return;
- } finally {
- IOUtils.closeQuietly(inputStream);
- inputStream = null;
- }
-
-
- // Should take care of the ColorSpace and bitsPerPixel
- this.bitmaps = new byte[this.width * this.height * 3];
- for (int i = 0; i < this.height; i++) {
- for (int j = 0; j < this.width; j++) {
- int p = tmpMap[i * this.width + j];
- int r = (p >> 16) & 0xFF;
- int g = (p >> 8) & 0xFF;
- int b = (p) & 0xFF;
- this.bitmaps[3 * (i * this.width + j)] = (byte)(r & 0xFF);
- this.bitmaps[3 * (i * this.width + j) + 1] = (byte)(g & 0xFF);
- this.bitmaps[3 * (i * this.width + j) + 2] = (byte)(b & 0xFF);
- }
- }
- }
-
- /** {@inheritDoc} */
- protected boolean loadOriginalData() {
- return loadDefaultOriginalData();
- }
-
-}
-
diff --git a/src/java/org/apache/fop/image/JpegImage.java b/src/java/org/apache/fop/image/JpegImage.java
deleted file mode 100644
index 1de6b0d48..000000000
--- a/src/java/org/apache/fop/image/JpegImage.java
+++ /dev/null
@@ -1,239 +0,0 @@
-/*
- * 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.image;
-
-import java.awt.color.ColorSpace;
-import java.awt.color.ICC_Profile;
-
-import org.apache.commons.io.IOUtils;
-import org.apache.commons.io.output.ByteArrayOutputStream;
-import org.apache.fop.util.CMYKColorSpace;
-
-/**
- * FopImage object for JPEG images, Using Java native classes.
- *
- * @see AbstractFopImage
- * @see FopImage
- */
-public class JpegImage extends AbstractFopImage {
- private ICC_Profile iccProfile = null;
- private boolean foundICCProfile = false;
- private boolean hasAPPEMarker = false;
-
- /**
- * Create a jpeg image with the info.
- *
- * @param imgInfo the image info for this jpeg
- */
- public JpegImage(FopImage.ImageInfo imgInfo) {
- super(imgInfo);
- }
-
- /**
- * Load the original jpeg data.
- * This loads the original jpeg data and reads the color space,
- * and icc profile if any.
- *
- * @return true if loaded false for any error
- */
- protected boolean loadOriginalData() {
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- ByteArrayOutputStream iccStream = null;
- int index = 0;
- boolean cont = true;
-
- try {
- byte[] readBuf = new byte[4096];
- int bytesRead;
- while ((bytesRead = inputStream.read(readBuf)) != -1) {
- baos.write(readBuf, 0, bytesRead);
- }
- } catch (java.io.IOException ex) {
- log.error("Error while loading image (Jpeg): " + ex.getMessage(), ex);
- return false;
- } finally {
- IOUtils.closeQuietly(inputStream);
- inputStream = null;
- }
-
- this.raw = baos.toByteArray();
- this.bitsPerPixel = 8;
- this.isTransparent = false;
-
- //Check for SOI (Start of image) marker (FFD8)
- if (this.raw.length > (index + 2)
- && uByte(this.raw[index]) == 255 /*0xFF*/
- && uByte(this.raw[index + 1]) == 216 /*0xD8*/) {
- index += 2;
-
- while (index < this.raw.length && cont) {
- //check to be sure this is the begining of a header
- if (this.raw.length > (index + 2)
- && uByte(this.raw[index]) == 255 /*0xFF*/) {
-
- //192 or 194 are the header bytes that contain
- // the jpeg width height and color depth.
- if (uByte(this.raw[index + 1]) == 192 /*0xC0*/
- || uByte(this.raw[index + 1]) == 194 /*0xC2*/) {
-
- this.height = calcBytes(this.raw[index + 5],
- this.raw[index + 6]);
- this.width = calcBytes(this.raw[index + 7],
- this.raw[index + 8]);
-
- int numComponents = this.raw[index + 9];
- if (numComponents == 1) {
- this.colorSpace = ColorSpace.getInstance(
- ColorSpace.CS_GRAY);
- } else if (numComponents == 3) {
- this.colorSpace = ColorSpace.getInstance(
- ColorSpace.CS_LINEAR_RGB);
- } else if (numComponents == 4) {
- // howto create CMYK color space
- /*
- this.colorSpace = ColorSpace.getInstance(
- ColorSpace.CS_CIEXYZ);
- */
- this.colorSpace = CMYKColorSpace.getInstance();
- } else {
- log.error("Unknown ColorSpace for image: "
- + "");
- return false;
- }
-
- if (foundICCProfile) {
- cont = false;
- break;
- }
- index += calcBytes(this.raw[index + 2],
- this.raw[index + 3]) + 2;
-
- } else if (uByte(this.raw[index + 1]) == 226 /*0xE2*/
- && this.raw.length > (index + 60)) {
- // Check if ICC profile
- byte[] iccString = new byte[11];
- System.arraycopy(this.raw, index + 4,
- iccString, 0, 11);
-
- if ("ICC_PROFILE".equals(new String(iccString))) {
- int chunkSize = calcBytes(
- this.raw[index + 2],
- this.raw[index + 3]) + 2;
-
- if (iccStream == null) {
- iccStream = new ByteArrayOutputStream();
- }
- iccStream.write(this.raw,
- index + 18, chunkSize - 18);
-
- }
-
- index += calcBytes(this.raw[index + 2],
- this.raw[index + 3]) + 2;
- // Check for Adobe APPE Marker
- } else if ((uByte(this.raw[index]) == 0xff
- && uByte(this.raw[index + 1]) == 0xee
- && uByte(this.raw[index + 2]) == 0
- && uByte(this.raw[index + 3]) == 14
- && "Adobe".equals(new String(this.raw, index + 4, 5)))) {
- // The reason for reading the APPE marker is that Adobe Photoshop
- // generates CMYK JPEGs with inverted values. The correct thing
- // to do would be to interpret the values in the marker, but for now
- // only assume that if APPE marker is present and colorspace is CMYK,
- // the image is inverted.
- hasAPPEMarker = true;
-
- index += calcBytes(this.raw[index + 2],
- this.raw[index + 3]) + 2;
- } else {
- index += calcBytes(this.raw[index + 2],
- this.raw[index + 3]) + 2;
- }
-
- } else {
- cont = false;
- }
- }
- } else {
- log.error("Error while loading "
- + "JpegImage - Invalid JPEG Header.");
- return false;
- }
- if (iccStream != null && iccStream.size() > 0) {
- int padding = (8 - (iccStream.size() % 8)) % 8;
- if (padding != 0) {
- try {
- iccStream.write(new byte[padding]);
- } catch (Exception ex) {
- log.error("Error while aligning ICC stream: " + ex.getMessage(), ex);
- return false;
- }
- }
- try {
- iccProfile = ICC_Profile.getInstance(iccStream.toByteArray());
- } catch (IllegalArgumentException iae) {
- log.warn("An ICC profile is present but it is invalid ("
- + iae.getMessage() + "). The color profile will be ignored. ("
- + this.getOriginalURI() + ")");
- }
- if (iccProfile.getNumComponents() != this.colorSpace.getNumComponents()) {
- log.warn("The number of components of the ICC profile ("
- + iccProfile.getNumComponents()
- + ") doesn't match the image ("
- + this.colorSpace.getNumComponents()
- + "). Ignoring the ICC color profile.");
- this.iccProfile = null;
- }
- } else if (this.colorSpace == null) {
- log.error("ColorSpace not specified for JPEG image");
- return false;
- }
- if (hasAPPEMarker && this.colorSpace.getType() == ColorSpace.TYPE_CMYK) {
- if (log.isDebugEnabled()) {
- log.debug("JPEG has an Adobe APPE marker. Note: CMYK Image will be inverted. ("
- + this.getOriginalURI() + ")");
- }
- this.invertImage = true;
- }
- return true;
- }
-
- /**
- * Get the ICC profile for this Jpeg image.
- *
- * @return the icc profile or null if not found
- */
- public ICC_Profile getICCProfile() {
- return iccProfile;
- }
-
- private int calcBytes(byte bOne, byte bTwo) {
- return (uByte(bOne) * 256) + uByte(bTwo);
- }
-
- private int uByte(byte bIn) {
- if (bIn < 0) {
- return 256 + bIn;
- } else {
- return bIn;
- }
- }
-}
-
diff --git a/src/java/org/apache/fop/image/PNGImage.java b/src/java/org/apache/fop/image/PNGImage.java
deleted file mode 100644
index c83d491f0..000000000
--- a/src/java/org/apache/fop/image/PNGImage.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * 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.image;
-
-import java.io.IOException;
-
-import org.apache.xmlgraphics.image.codec.png.PNGRed;
-import org.apache.xmlgraphics.image.codec.png.PNGDecodeParam;
-import org.apache.xmlgraphics.image.codec.util.SeekableStream;
-import org.apache.xmlgraphics.image.rendered.CachableRed;
-import org.apache.commons.io.IOUtils;
-
-/**
- * FopImage object using PNG
- *
- * @see AbstractFopImage
- * @see FopImage
- */
-public class PNGImage extends XmlGraphicsCommonsImage {
-
- /**
- * Constructs a new PNGImage instance.
- * @param imgReader basic metadata for the image
- */
- public PNGImage(FopImage.ImageInfo imgReader) {
- super(imgReader);
- this.loaded = 0; //TODO The PNGReader cannot read the resolution, yet.
- }
-
- /**
- * {@inheritDoc}
- */
- protected CachableRed decodeImage(SeekableStream stream) throws IOException {
- PNGDecodeParam param = new PNGDecodeParam();
- param.setPerformGammaCorrection(true);
- param.setDisplayExponent(2.2f); // sRGB gamma
- PNGRed red = new PNGRed(stream, param);
- String unit = (String)red.getProperty("pixel_units");
- if ("Meters".equals(unit)) {
- this.dpiHorizontal = ((Integer)red.getProperty("x_pixels_per_unit")).intValue()
- * 25.4f / 1000f;
- this.dpiVertical = ((Integer)red.getProperty("y_pixels_per_unit")).intValue()
- * 25.4f / 1000f;
- }
- return red;
- }
-
- /**
- * Load the original PNG data.
- * This loads the original PNG data as is into memory.
- *
- * @return true if loaded false for any error
- */
- protected boolean loadOriginalData() {
- try {
- seekableInput.seek(0);
- this.raw = IOUtils.toByteArray(seekableInput);
-
- } catch (java.io.IOException ex) {
- log.error("Error while loading raw image: " + ex.getMessage(), ex);
- return false;
- } finally {
- IOUtils.closeQuietly(inputStream);
- inputStream = null;
- }
-
- return true;
- }
-
-}
diff --git a/src/java/org/apache/fop/image/TIFFImage.java b/src/java/org/apache/fop/image/TIFFImage.java
deleted file mode 100644
index d9a9fc022..000000000
--- a/src/java/org/apache/fop/image/TIFFImage.java
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- * 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.image;
-
-import java.awt.color.ColorSpace;
-import java.io.IOException;
-
-import org.apache.xmlgraphics.image.codec.util.SeekableStream;
-import org.apache.xmlgraphics.image.codec.tiff.TIFFDirectory;
-import org.apache.xmlgraphics.image.codec.tiff.TIFFField;
-import org.apache.xmlgraphics.image.codec.tiff.TIFFImageDecoder;
-import org.apache.xmlgraphics.image.rendered.CachableRed;
-import org.apache.commons.io.IOUtils;
-
-/**
- * TIFF implementation using the Batik codecs.
- */
-public class TIFFImage extends XmlGraphicsCommonsImage {
-
- private int compression = 0;
- private int stripCount = 0;
- private long stripOffset = 0;
- private long stripLength = 0;
- private int fillOrder = 1;
-
- /**
- * Constructs a new BatikImage instance.
- * @param imgReader basic metadata for the image
- */
- public TIFFImage(FopImage.ImageInfo imgReader) {
- super(imgReader);
- }
-
- /**
- * The compression type set in the TIFF directory
- * @return the TIFF compression type
- */
- public int getCompression() {
- return compression;
- }
-
- /**
- * The number of strips in the image
- * @return the number of strips in the image
- */
- public int getStripCount() {
- return stripCount;
- }
-
- /**
- * {@inheritDoc}
- * org.apache.xmlgraphics.image.codec.util.SeekableStream)
- */
- protected CachableRed decodeImage(SeekableStream stream) throws IOException {
- org.apache.xmlgraphics.image.codec.tiff.TIFFImage img
- = new org.apache.xmlgraphics.image.codec.tiff.TIFFImage
- (stream, null, 0);
- TIFFDirectory dir = (TIFFDirectory)img.getProperty("tiff_directory");
- TIFFField fld = dir.getField(TIFFImageDecoder.TIFF_RESOLUTION_UNIT);
- int resUnit = fld.getAsInt(0);
- fld = dir.getField(TIFFImageDecoder.TIFF_X_RESOLUTION);
- double xRes = fld.getAsDouble(0);
- fld = dir.getField(TIFFImageDecoder.TIFF_Y_RESOLUTION);
- double yRes = fld.getAsDouble(0);
- switch (resUnit) {
- case 2: //inch
- this.dpiHorizontal = xRes;
- this.dpiVertical = yRes;
- break;
- case 3: //cm
- this.dpiHorizontal = xRes * 2.54f;
- this.dpiVertical = yRes * 2.54f;
- break;
- default:
- //ignored
- log.warn("Cannot determine bitmap resolution."
- + " Unimplemented resolution unit: " + resUnit);
- }
- fld = dir.getField(TIFFImageDecoder.TIFF_COMPRESSION);
- if (fld != null) {
- compression = fld.getAsInt(0);
- }
- fld = dir.getField(TIFFImageDecoder.TIFF_BITS_PER_SAMPLE);
- if (fld != null) {
- bitsPerPixel = fld.getAsInt(0);
- }
- fld = dir.getField(TIFFImageDecoder.TIFF_ROWS_PER_STRIP);
- if (fld == null) {
- stripCount = 1;
- } else {
- stripCount = (int)(dir.getFieldAsLong(TIFFImageDecoder.TIFF_IMAGE_LENGTH)
- / fld.getAsLong(0));
- }
-
- fld = dir.getField(TIFFImageDecoder.TIFF_FILL_ORDER);
- if (fld != null) {
- fillOrder = fld.getAsInt(0);
- }
-
- stripOffset = dir.getField(TIFFImageDecoder.TIFF_STRIP_OFFSETS).getAsLong(0);
- stripLength = dir.getField(TIFFImageDecoder.TIFF_STRIP_BYTE_COUNTS).getAsLong(0);
-
- if (this.bitsPerPixel == 1) {
- this.colorSpace = ColorSpace.getInstance(ColorSpace.CS_GRAY);
- }
- return img;
- }
-
- /**
- * Load the original TIFF data.
- * This loads only strip 1 of the original TIFF data.
- *
- * @return true if loaded false for any error
- * {@inheritDoc}
- */
- protected boolean loadOriginalData() {
- if (loadDimensions()) {
- byte[] readBuf = new byte[(int)stripLength];
- int bytesRead;
-
- try {
- this.seekableInput.reset();
- this.seekableInput.skip(stripOffset);
- bytesRead = seekableInput.read(readBuf);
- if (bytesRead != stripLength) {
- log.error("Error while loading image: length mismatch on read");
- return false;
- }
-
- // need to invert bytes if fill order = 2
- if (fillOrder == 2) {
- for (int i = 0; i < (int)stripLength; i++) {
- readBuf[i] = flipTable[readBuf[i] & 0xff];
- }
- }
- this.raw = readBuf;
-
- return true;
- } catch (IOException ioe) {
- log.error("Error while loading image strip 1 (TIFF): ", ioe);
- return false;
- } finally {
- IOUtils.closeQuietly(seekableInput);
- IOUtils.closeQuietly(inputStream);
- this.seekableInput = null;
- this.inputStream = null;
- this.cr = null;
- }
- }
- return false;
- }
-
- // Table to be used when fillOrder = 2, for flipping bytes.
- // Copied from XML Graphics Commons' TIFFFaxDecoder class
- private static byte[] flipTable = {
- 0, -128, 64, -64, 32, -96, 96, -32,
- 16, -112, 80, -48, 48, -80, 112, -16,
- 8, -120, 72, -56, 40, -88, 104, -24,
- 24, -104, 88, -40, 56, -72, 120, -8,
- 4, -124, 68, -60, 36, -92, 100, -28,
- 20, -108, 84, -44, 52, -76, 116, -12,
- 12, -116, 76, -52, 44, -84, 108, -20,
- 28, -100, 92, -36, 60, -68, 124, -4,
- 2, -126, 66, -62, 34, -94, 98, -30,
- 18, -110, 82, -46, 50, -78, 114, -14,
- 10, -118, 74, -54, 42, -86, 106, -22,
- 26, -102, 90, -38, 58, -70, 122, -6,
- 6, -122, 70, -58, 38, -90, 102, -26,
- 22, -106, 86, -42, 54, -74, 118, -10,
- 14, -114, 78, -50, 46, -82, 110, -18,
- 30, -98, 94, -34, 62, -66, 126, -2,
- 1, -127, 65, -63, 33, -95, 97, -31,
- 17, -111, 81, -47, 49, -79, 113, -15,
- 9, -119, 73, -55, 41, -87, 105, -23,
- 25, -103, 89, -39, 57, -71, 121, -7,
- 5, -123, 69, -59, 37, -91, 101, -27,
- 21, -107, 85, -43, 53, -75, 117, -11,
- 13, -115, 77, -51, 45, -83, 109, -19,
- 29, -99, 93, -35, 61, -67, 125, -3,
- 3, -125, 67, -61, 35, -93, 99, -29,
- 19, -109, 83, -45, 51, -77, 115, -13,
- 11, -117, 75, -53, 43, -85, 107, -21,
- 27, -101, 91, -37, 59, -69, 123, -5,
- 7, -121, 71, -57, 39, -89, 103, -25,
- 23, -105, 87, -41, 55, -73, 119, -9,
- 15, -113, 79, -49, 47, -81, 111, -17,
- 31, -97, 95, -33, 63, -65, 127, -1,
- };
- // end
-}
diff --git a/src/java/org/apache/fop/image/XMLImage.java b/src/java/org/apache/fop/image/XMLImage.java
deleted file mode 100644
index 261dc8494..000000000
--- a/src/java/org/apache/fop/image/XMLImage.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * 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.image;
-
-// Java
-import org.w3c.dom.Document;
-import javax.xml.parsers.SAXParserFactory;
-
-/**
- * This is an implementation for XML-based images such as SVG.
- *
- * @see AbstractFopImage
- * @see FopImage
- */
-public class XMLImage extends AbstractFopImage {
-
- private Document doc;
- private String namespace = "";
-
- /**
- * @see org.apache.fop.image.AbstractFopImage#AbstractFopImage(FopImage.ImageInfo)
- */
- public XMLImage(FopImage.ImageInfo imgInfo) {
- super(imgInfo);
- if (imgInfo.data instanceof Document) {
- doc = (Document)imgInfo.data;
- loaded = loaded | ORIGINAL_DATA;
- }
- namespace = imgInfo.str;
- }
-
- /**
- * Returns the fully qualified classname of an XML parser for
- * Batik classes that apparently need it (error messages, perhaps)
- * @return an XML parser classname
- */
- public static String getParserName() {
- try {
- SAXParserFactory factory = SAXParserFactory.newInstance();
- return factory.newSAXParser().getXMLReader().getClass().getName();
- } catch (Exception e) {
- return null;
- }
- }
-
- /**
- * Returns the XML document as a DOM document.
- * @return the DOM document
- */
- public Document getDocument() {
- return this.doc;
- }
-
- /**
- * Returns the namespace of the XML document.
- * @return the namespace
- */
- public String getNameSpace() {
- return this.namespace;
- }
-}
diff --git a/src/java/org/apache/fop/image/XmlGraphicsCommonsImage.java b/src/java/org/apache/fop/image/XmlGraphicsCommonsImage.java
deleted file mode 100644
index 662673726..000000000
--- a/src/java/org/apache/fop/image/XmlGraphicsCommonsImage.java
+++ /dev/null
@@ -1,239 +0,0 @@
-/*
- * 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.image;
-
-import java.awt.Color;
-import java.awt.Transparency;
-import java.awt.image.ColorModel;
-import java.awt.image.IndexColorModel;
-import java.awt.image.RenderedImage;
-import java.awt.image.WritableRaster;
-import java.awt.image.BufferedImage;
-import java.io.IOException;
-
-import org.apache.xmlgraphics.image.GraphicsUtil;
-import org.apache.xmlgraphics.image.codec.util.SeekableStream;
-import org.apache.xmlgraphics.image.codec.util.MemoryCacheSeekableStream;
-import org.apache.xmlgraphics.image.codec.util.FileCacheSeekableStream;
-import org.apache.xmlgraphics.image.rendered.CachableRed;
-
-import org.apache.commons.io.IOUtils;
-
-/**
- * Abstract FopImage implementation which uses the internal codecs from XML Graphics Commons.
- *
- * @see AbstractFopImage
- * @see FopImage
- */
-public abstract class XmlGraphicsCommonsImage extends AbstractFopImage {
-
- private byte[] softMask = null;
-
- /**
- * The InputStream wrapped into a SeekableStream for decoding.
- */
- protected SeekableStream seekableInput = null;
-
- /**
- * The Batik representation of the image
- */
- protected CachableRed cr = null;
-
- /**
- * Constructs a new BatikImage instance.
- * @param imgReader basic metadata for the image
- */
- public XmlGraphicsCommonsImage(FopImage.ImageInfo imgReader) {
- super(imgReader);
- }
-
- /**
- * {@inheritDoc}
- */
- protected boolean loadDimensions() {
- if (seekableInput == null && inputStream != null) {
- try {
- seekableInput = new FileCacheSeekableStream(inputStream);
- } catch (IOException ioe) {
- seekableInput = new MemoryCacheSeekableStream(inputStream);
- }
- try {
- this.bitsPerPixel = 8;
- cr = decodeImage(seekableInput);
- this.height = cr.getHeight();
- this.width = cr.getWidth();
- this.isTransparent = false;
- this.softMask = null;
- ColorModel cm = cr.getColorModel();
-
- this.height = cr.getHeight();
- this.width = cr.getWidth();
- this.isTransparent = false;
- this.softMask = null;
-
- int transparencyType = cm.getTransparency();
- if (cm instanceof IndexColorModel) {
- if (transparencyType == Transparency.BITMASK) {
- // Use 'transparent color'.
- IndexColorModel icm = (IndexColorModel)cm;
- int numColor = icm.getMapSize();
- byte [] alpha = new byte[numColor];
- icm.getAlphas(alpha);
- for (int i = 0; i < numColor; i++) {
- if ((alpha[i] & 0xFF) == 0) {
- this.isTransparent = true;
- int red = (icm.getRed (i)) & 0xFF;
- int grn = (icm.getGreen(i)) & 0xFF;
- int blu = (icm.getBlue (i)) & 0xFF;
- this.transparentColor = new Color(red, grn, blu);
- break;
- }
- }
- }
- } else {
- cr = GraphicsUtil.convertTosRGB(cr);
- }
-
- // Get our current ColorModel
- cm = cr.getColorModel();
- if (this.colorSpace == null) {
- this.colorSpace = cm.getColorSpace();
- }
- } catch (IOException ioe) {
- log.error("Error while loading image (Batik): " + ioe.getMessage(), ioe);
- IOUtils.closeQuietly(seekableInput);
- IOUtils.closeQuietly(inputStream);
- seekableInput = null;
- inputStream = null;
- return false;
- }
- }
- return this.height != -1;
- }
-
- /**
- * {@inheritDoc}
- */
- protected boolean loadBitmap() {
- if (this.bitmaps == null) {
- loadImage();
- }
-
- return this.bitmaps != null;
- }
-
- /**
- * {@inheritDoc}
- */
- public boolean hasSoftMask() {
- if (this.bitmaps == null && this.raw == null) {
- loadImage();
- }
-
- return (this.softMask != null);
- }
-
- /**
- * {@inheritDoc}
- */
- public byte[] getSoftMask() {
- if (this.bitmaps == null) {
- loadImage();
- }
-
- return this.softMask;
- }
-
- /**
- * Decodes the image from the stream.
- * @param stream the stream to read the image from
- * @return the decoded image
- * @throws IOException in case an I/O problem occurs
- */
- protected abstract CachableRed decodeImage(SeekableStream stream) throws IOException;
-
- /**
- * Loads the image from the InputStream.
- */
- protected void loadImage() {
- if (loadDimensions()) {
- try {
- if (cr == null) {
- throw new IllegalStateException(
- "Can't load the bitmaps data without the CachableRed instance");
- }
-
- // Get our current ColorModel
- ColorModel cm = cr.getColorModel();
-
- // It has an alpha channel so generate a soft mask.
- if (!this.isTransparent && cm.hasAlpha()) {
- this.softMask = new byte[this.width * this.height];
- }
-
- this.bitmaps = new byte[this.width * this.height * 3];
-
- constructBitmaps(cr, this.bitmaps, this.softMask);
- } catch (Exception ex) {
- log.error("Error while loading image (Batik): " + ex.getMessage(), ex);
- } finally {
- // Make sure we clean up
- IOUtils.closeQuietly(seekableInput);
- IOUtils.closeQuietly(inputStream);
- seekableInput = null;
- inputStream = null;
- cr = null;
- }
- }
- }
-
- private static void constructBitmaps(RenderedImage red, byte[] bitmaps, byte[] softMask) {
- WritableRaster wr = (WritableRaster)red.getData();
- ColorModel cm = red.getColorModel();
- BufferedImage bi = new BufferedImage
- (cm, wr.createWritableTranslatedChild(0, 0),
- cm.isAlphaPremultiplied(), null);
- int width = red.getWidth();
- int height = red.getHeight();
- int [] tmpMap = new int[width];
- int idx = 0;
- int sfIdx = 0;
- for (int y = 0; y < height; y++) {
- tmpMap = bi.getRGB(0, y, width, 1, tmpMap, 0, width);
- if (softMask != null) {
- for (int x = 0; x < width; x++) {
- int pix = tmpMap[x];
- softMask[sfIdx++] = (byte)(pix >>> 24);
- bitmaps[idx++] = (byte)((pix >>> 16) & 0xFF);
- bitmaps[idx++] = (byte)((pix >>> 8) & 0xFF);
- bitmaps[idx++] = (byte)((pix) & 0xFF);
- }
- } else {
- for (int x = 0; x < width; x++) {
- int pix = tmpMap[x];
- bitmaps[idx++] = (byte)((pix >> 16) & 0xFF);
- bitmaps[idx++] = (byte)((pix >> 8) & 0xFF);
- bitmaps[idx++] = (byte)((pix) & 0xFF);
- }
- }
- }
- }
-
-} \ No newline at end of file
diff --git a/src/java/org/apache/fop/image/analyser/BMPReader.java b/src/java/org/apache/fop/image/analyser/BMPReader.java
deleted file mode 100644
index caca6f3dd..000000000
--- a/src/java/org/apache/fop/image/analyser/BMPReader.java
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * 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.image.analyser;
-
-// Java
-import java.io.InputStream;
-import java.io.IOException;
-
-// FOP
-import org.apache.fop.image.FopImage;
-import org.apache.fop.apps.FOUserAgent;
-
-/**
- * ImageReader object for BMP image type.
- *
- * @author Pankaj Narula
- * @version $Id$
- */
-public class BMPReader implements ImageReader {
-
- /** Length of the BMP header */
- protected static final int BMP_SIG_LENGTH = 46;
-
- /** offset to width */
- private static final int WIDTH_OFFSET = 18;
- /** offset to height */
- private static final int HEIGHT_OFFSET = 22;
- /** offset to horizontal res */
- private static final int HRES_OFFSET = 38;
- /** offset to vertical res */
- private static final int VRES_OFFSET = 42;
-
- /** {@inheritDoc} */
- public FopImage.ImageInfo verifySignature(String uri, InputStream bis,
- FOUserAgent ua) throws IOException {
- byte[] header = getDefaultHeader(bis);
- boolean supported = ((header[0] == (byte) 0x42)
- && (header[1] == (byte) 0x4d));
- if (supported) {
- FopImage.ImageInfo info = new FopImage.ImageInfo();
- info.dpiHorizontal = ua.getFactory().getSourceResolution();
- info.dpiVertical = info.dpiHorizontal;
-
- getDimension(header, info);
- info.originalURI = uri;
- info.mimeType = getMimeType();
- info.inputStream = bis;
- return info;
- } else {
- return null;
- }
- }
-
- /**
- * Returns the MIME type supported by this implementation.
- *
- * @return The MIME type
- */
- public String getMimeType() {
- return "image/bmp";
- }
-
- private void getDimension(byte[] header, FopImage.ImageInfo info) {
- // little endian notation
- int byte1 = header[WIDTH_OFFSET] & 0xff;
- int byte2 = header[WIDTH_OFFSET + 1] & 0xff;
- int byte3 = header[WIDTH_OFFSET + 2] & 0xff;
- int byte4 = header[WIDTH_OFFSET + 3] & 0xff;
- long l = (long) ((byte4 << 24) | (byte3 << 16)
- | (byte2 << 8) | byte1);
- info.width = (int) (l & 0xffffffff);
-
- byte1 = header[HEIGHT_OFFSET] & 0xff;
- byte2 = header[HEIGHT_OFFSET + 1] & 0xff;
- byte3 = header[HEIGHT_OFFSET + 2] & 0xff;
- byte4 = header[HEIGHT_OFFSET + 3] & 0xff;
- l = (long) ((byte4 << 24) | (byte3 << 16) | (byte2 << 8) | byte1);
- info.height = (int) (l & 0xffffffff);
-
- byte1 = header[HRES_OFFSET] & 0xff;
- byte2 = header[HRES_OFFSET + 1] & 0xff;
- byte3 = header[HRES_OFFSET + 2] & 0xff;
- byte4 = header[HRES_OFFSET + 3] & 0xff;
- l = (long) ((byte4 << 24) | (byte3 << 16) | (byte2 << 8) | byte1);
- if (l > 0) {
- info.dpiHorizontal = l / 39.37d;
- }
-
- byte1 = header[VRES_OFFSET] & 0xff;
- byte2 = header[VRES_OFFSET + 1] & 0xff;
- byte3 = header[VRES_OFFSET + 2] & 0xff;
- byte4 = header[VRES_OFFSET + 3] & 0xff;
- l = (long) ((byte4 << 24) | (byte3 << 16) | (byte2 << 8) | byte1);
- if (l > 0) {
- info.dpiVertical = l / 39.37d;
- }
- }
-
- private byte[] getDefaultHeader(InputStream imageStream)
- throws IOException {
- byte[] header = new byte[BMP_SIG_LENGTH];
- try {
- imageStream.mark(BMP_SIG_LENGTH + 1);
- imageStream.read(header);
- imageStream.reset();
- } catch (IOException ex) {
- try {
- imageStream.reset();
- } catch (IOException exbis) {
- // throw the original exception, not this one
- }
- throw ex;
- }
- return header;
- }
-
-}
diff --git a/src/java/org/apache/fop/image/analyser/EMFReader.java b/src/java/org/apache/fop/image/analyser/EMFReader.java
deleted file mode 100644
index d6e2f2975..000000000
--- a/src/java/org/apache/fop/image/analyser/EMFReader.java
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * 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.image.analyser;
-
-// Java
-import java.io.InputStream;
-import java.io.IOException;
-
-// FOP
-import org.apache.fop.image.FopImage;
-import org.apache.fop.apps.FOUserAgent;
-
-/**
- * ImageReader object for EMF image type.
- *
- * @author Peter Herweg
- */
-public class EMFReader implements ImageReader {
-
- /** Length of the EMF header */
- protected static final int EMF_SIG_LENGTH = 88;
-
- /** offset to signature */
- private static final int SIGNATURE_OFFSET = 40;
- /** offset to width */
- private static final int WIDTH_OFFSET = 32;
- /** offset to height */
- private static final int HEIGHT_OFFSET = 36;
- /** offset to horizontal resolution in pixel */
- private static final int HRES_PIXEL_OFFSET = 72;
- /** offset to vertical resolution in pixel */
- private static final int VRES_PIXEL_OFFSET = 76;
- /** offset to horizontal resolution in mm */
- private static final int HRES_MM_OFFSET = 80;
- /** offset to vertical resolution in mm */
- private static final int VRES_MM_OFFSET = 84;
-
- /** {@inheritDoc} */
- public FopImage.ImageInfo verifySignature(String uri, InputStream bis,
- FOUserAgent ua) throws IOException {
- byte[] header = getDefaultHeader(bis);
- boolean supported
- = ( (header[SIGNATURE_OFFSET + 0] == (byte) 0x20)
- && (header[SIGNATURE_OFFSET + 1] == (byte) 0x45)
- && (header[SIGNATURE_OFFSET + 2] == (byte) 0x4D)
- && (header[SIGNATURE_OFFSET + 3] == (byte) 0x46) );
-
- if (supported) {
- FopImage.ImageInfo info = getDimension(header);
- info.originalURI = uri;
- info.mimeType = getMimeType();
- info.inputStream = bis;
- return info;
- } else {
- return null;
- }
- }
-
- /**
- * Returns the MIME type supported by this implementation.
- *
- * @return The MIME type
- */
- public String getMimeType() {
- return "image/emf";
- }
-
- private FopImage.ImageInfo getDimension(byte[] header) {
- FopImage.ImageInfo info = new FopImage.ImageInfo();
- long value = 0;
- int byte1;
- int byte2;
- int byte3;
- int byte4;
-
- // little endian notation
-
- //resolution
- byte1 = header[HRES_MM_OFFSET] & 0xff;
- byte2 = header[HRES_MM_OFFSET + 1] & 0xff;
- byte3 = header[HRES_MM_OFFSET + 2] & 0xff;
- byte4 = header[HRES_MM_OFFSET + 3] & 0xff;
- long hresMM = (long) ((byte4 << 24) | (byte3 << 16) | (byte2 << 8) | byte1);
-
- byte1 = header[VRES_MM_OFFSET] & 0xff;
- byte2 = header[VRES_MM_OFFSET + 1] & 0xff;
- byte3 = header[VRES_MM_OFFSET + 2] & 0xff;
- byte4 = header[VRES_MM_OFFSET + 3] & 0xff;
- long vresMM = (long) ((byte4 << 24) | (byte3 << 16) | (byte2 << 8) | byte1);
-
- byte1 = header[HRES_PIXEL_OFFSET] & 0xff;
- byte2 = header[HRES_PIXEL_OFFSET + 1] & 0xff;
- byte3 = header[HRES_PIXEL_OFFSET + 2] & 0xff;
- byte4 = header[HRES_PIXEL_OFFSET + 3] & 0xff;
- long hresPixel = (long) ((byte4 << 24) | (byte3 << 16) | (byte2 << 8) | byte1);
-
- byte1 = header[VRES_PIXEL_OFFSET] & 0xff;
- byte2 = header[VRES_PIXEL_OFFSET + 1] & 0xff;
- byte3 = header[VRES_PIXEL_OFFSET + 2] & 0xff;
- byte4 = header[VRES_PIXEL_OFFSET + 3] & 0xff;
- long vresPixel = (long) ((byte4 << 24) | (byte3 << 16) | (byte2 << 8) | byte1);
-
- info.dpiHorizontal = hresPixel / (hresMM / 25.4f);
- info.dpiVertical = vresPixel / (vresMM / 25.4f);
-
- //width
- byte1 = header[WIDTH_OFFSET] & 0xff;
- byte2 = header[WIDTH_OFFSET + 1] & 0xff;
- byte3 = header[WIDTH_OFFSET + 2] & 0xff;
- byte4 = header[WIDTH_OFFSET + 3] & 0xff;
- value = (long) ((byte4 << 24) | (byte3 << 16)
- | (byte2 << 8) | byte1);
- value = Math.round(value / 100f / 25.4f * info.dpiHorizontal);
- info.width = (int) (value & 0xffffffff);
-
- //height
- byte1 = header[HEIGHT_OFFSET] & 0xff;
- byte2 = header[HEIGHT_OFFSET + 1] & 0xff;
- byte3 = header[HEIGHT_OFFSET + 2] & 0xff;
- byte4 = header[HEIGHT_OFFSET + 3] & 0xff;
- value = (long) ((byte4 << 24) | (byte3 << 16) | (byte2 << 8) | byte1);
- value = Math.round(value / 100f / 25.4f * info.dpiVertical);
- info.height = (int) (value & 0xffffffff);
-
- return info;
- }
-
- private byte[] getDefaultHeader(InputStream imageStream)
- throws IOException {
- byte[] header = new byte[EMF_SIG_LENGTH];
- try {
- imageStream.mark(EMF_SIG_LENGTH + 1);
- imageStream.read(header);
- imageStream.reset();
- } catch (IOException ex) {
- try {
- imageStream.reset();
- } catch (IOException exbis) {
- // throw the original exception, not this one
- }
- throw ex;
- }
- return header;
- }
-}
diff --git a/src/java/org/apache/fop/image/analyser/EPSReader.java b/src/java/org/apache/fop/image/analyser/EPSReader.java
deleted file mode 100644
index 92260d1ab..000000000
--- a/src/java/org/apache/fop/image/analyser/EPSReader.java
+++ /dev/null
@@ -1,253 +0,0 @@
-/*
- * 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.image.analyser;
-
-// Java
-import java.io.InputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-
-// FOP
-import org.apache.commons.io.IOUtils;
-import org.apache.fop.image.FopImage;
-import org.apache.fop.image.EPSImage;
-import org.apache.fop.apps.FOUserAgent;
-
-/**
- * ImageReader object for EPS document image type.
- *
- * @version $Id$
- */
-public class EPSReader implements ImageReader {
-
- private static final byte[] EPS_HEADER_ASCII = "%!PS".getBytes();
- private static final byte[] BOUNDINGBOX = "%%BoundingBox: ".getBytes();
- //private static final byte[] HIRESBOUNDINGBOX = "%%HiResBoundingBox: ".getBytes();
- //TODO Implement HiResBoundingBox, ImageInfo probably needs some changes for that
-
- /** {@inheritDoc} */
- public FopImage.ImageInfo verifySignature(String uri, InputStream bis,
- FOUserAgent ua) throws IOException {
-
- boolean isEPS = false;
-
- bis.mark(32);
- byte[] header = new byte[30];
- bis.read(header, 0, 30);
- bis.reset();
-
- EPSImage.EPSData data = new EPSImage.EPSData();
-
- // Check if binary header
- if (getLong(header, 0) == 0xC6D3D0C5) {
- data.isAscii = false;
- isEPS = true;
-
- data.psStart = getLong(header, 4);
- data.psLength = getLong(header, 8);
- data.wmfStart = getLong(header, 12);
- data.wmfLength = getLong(header, 16);
- data.tiffStart = getLong(header, 20);
- data.tiffLength = getLong(header, 24);
-
- } else {
- // Check if plain ascii
- byte[] epsh = "%!PS".getBytes();
- if (EPS_HEADER_ASCII[0] == header[0]
- && EPS_HEADER_ASCII[1] == header[1]
- && EPS_HEADER_ASCII[2] == header[2]
- && EPS_HEADER_ASCII[3] == header[3]) {
- data.isAscii = true;
- isEPS = true;
- }
- }
-
- if (isEPS) {
- FopImage.ImageInfo info = new FopImage.ImageInfo();
- info.originalURI = uri;
- info.mimeType = getMimeType();
- info.data = data;
- readEPSImage(bis, data);
- data.bbox = readBBox(data);
-
- if (data.bbox != null) {
- info.width = (int) (data.bbox[2] - data.bbox[0]);
- info.height = (int) (data.bbox[3] - data.bbox[1]);
-
- // image data read
- IOUtils.closeQuietly(bis);
- info.inputStream = null;
-
- return info;
- } else {
- // Ain't eps if no BoundingBox
- isEPS = false;
- }
- }
-
- return null;
- }
-
- /**
- * Returns the MIME type supported by this implementation.
- *
- * @return The MIME type
- */
- public String getMimeType() {
- return "image/eps";
- }
-
- private long getLong(byte[] buf, int idx) {
- int b1 = buf[idx] & 0xff;
- int b2 = buf[idx + 1] & 0xff;
- int b3 = buf[idx + 2] & 0xff;
- int b4 = buf[idx + 3] & 0xff;
-
- return (long) ((b4 << 24) | (b3 << 16) | (b2 << 8) | b1);
- }
-
- /**
- * Read the eps file and extract eps part.
- *
- * @param bis The InputStream
- * @param data EPSData object to write the results to
- * @exception IOException If an I/O error occurs
- */
- private void readEPSImage(InputStream bis, EPSImage.EPSData data)
- throws IOException {
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- byte[] file;
- byte[] readBuf = new byte[20480];
- int bytesRead;
- int index = 0;
- boolean cont = true;
-
- try {
- while ((bytesRead = bis.read(readBuf)) != -1) {
- baos.write(readBuf, 0, bytesRead);
- }
- } catch (java.io.IOException ex) {
- throw new IOException("Error while loading EPS image: "
- + ex.getMessage());
- }
-
- file = baos.toByteArray();
-
- if (data.isAscii) {
- data.rawEps = null;
- data.epsFile = new byte[file.length];
- System.arraycopy(file, 0, data.epsFile, 0, data.epsFile.length);
- } else {
- data.rawEps = new byte[file.length];
- data.epsFile = new byte[(int) data.psLength];
- System.arraycopy(file, 0, data.rawEps, 0, data.rawEps.length);
- System.arraycopy(data.rawEps, (int) data.psStart, data.epsFile, 0,
- (int) data.psLength);
- }
- }
-
- /**
- * Get embedded TIFF preview or null.
- *
- * @param data The EPS payload
- * @return The embedded preview
- */
- public byte[] getPreview(EPSImage.EPSData data) {
- if (data.preview == null) {
- if (data.tiffLength > 0) {
- data.preview = new byte[(int) data.tiffLength];
- System.arraycopy(data.rawEps, (int) data.tiffStart, data.preview, 0,
- (int) data.tiffLength);
- }
- }
- return data.preview;
- }
-
- /**
- * Extract bounding box from eps part.
- *
- * @param data The EPS payload
- * @return An Array of four coordinates making up the bounding box
- */
- private long[] readBBox(EPSImage.EPSData data) {
- long[] mbbox = null;
- int idx = 0;
- boolean found = false;
-
- while (!found && (data.epsFile.length > (idx + BOUNDINGBOX.length))) {
- boolean sfound = true;
- int i = idx;
- for (i = idx; sfound && (i - idx) < BOUNDINGBOX.length; i++) {
- if (BOUNDINGBOX[i - idx] != data.epsFile[i]) {
- sfound = false;
- }
- }
- if (sfound) {
- found = true;
- idx = i;
- } else {
- idx++;
- }
- }
-
- if (!found) {
- return mbbox;
- }
-
- mbbox = new long[4];
- idx += readLongString(data, mbbox, 0, idx);
- idx += readLongString(data, mbbox, 1, idx);
- idx += readLongString(data, mbbox, 2, idx);
- idx += readLongString(data, mbbox, 3, idx);
-
- return mbbox;
- }
-
- private int readLongString(EPSImage.EPSData data, long[] mbbox, int i, int idx) {
- while (idx < data.epsFile.length && (data.epsFile[idx] == 32)) {
- idx++;
- }
-
- int nidx = idx;
-
- // check also for ANSI46(".") to identify floating point values
- while (nidx < data.epsFile.length
- && ((data.epsFile[nidx] >= 48 && data.epsFile[nidx] <= 57)
- || (data.epsFile[nidx] == 45)
- || (data.epsFile[nidx] == 46))) {
- nidx++;
- }
-
- byte[] num = new byte[nidx - idx];
- System.arraycopy(data.epsFile, idx, num, 0, nidx - idx);
- String ns = new String(num);
-
- //if( ns.indexOf(".") != -1 ) {
- // do something like logging a warning
- //}
-
- // then parse the double and round off to the next math. Integer
- mbbox[i] = (long) Math.ceil(Double.parseDouble(ns));
-
- return (1 + nidx - idx);
- }
-
-}
-
diff --git a/src/java/org/apache/fop/image/analyser/GIFReader.java b/src/java/org/apache/fop/image/analyser/GIFReader.java
deleted file mode 100644
index d8da89607..000000000
--- a/src/java/org/apache/fop/image/analyser/GIFReader.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * 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.image.analyser;
-
-// Java
-import java.io.InputStream;
-import java.io.IOException;
-
-// FOP
-import org.apache.fop.image.FopImage;
-import org.apache.fop.apps.FOUserAgent;
-
-/**
- * ImageReader object for GIF image type.
- *
- * @author Pankaj Narula
- * @version $Id$
- */
-public class GIFReader implements ImageReader {
-
- private static final int GIF_SIG_LENGTH = 10;
-
- /** {@inheritDoc} */
- public FopImage.ImageInfo verifySignature(String uri, InputStream bis,
- FOUserAgent ua) throws IOException {
- byte[] header = getDefaultHeader(bis);
- boolean supported = ((header[0] == 'G')
- && (header[1] == 'I')
- && (header[2] == 'F')
- && (header[3] == '8')
- && (header[4] == '7' || header[4] == '9')
- && (header[5] == 'a'));
- if (supported) {
- FopImage.ImageInfo info = new FopImage.ImageInfo();
- info.dpiHorizontal = ua.getFactory().getSourceResolution();
- info.dpiVertical = info.dpiHorizontal;
-
- getDimension(header, info);
- info.originalURI = uri;
- info.mimeType = getMimeType();
- info.inputStream = bis;
- return info;
- } else {
- return null;
- }
- }
-
- /**
- * Returns the MIME type supported by this implementation.
- *
- * @return The MIME type
- */
- public String getMimeType() {
- return "image/gif";
- }
-
- private void getDimension(byte[] header, FopImage.ImageInfo info) {
- // little endian notation
- int byte1 = header[6] & 0xff;
- int byte2 = header[7] & 0xff;
- info.width = ((byte2 << 8) | byte1) & 0xffff;
-
- byte1 = header[8] & 0xff;
- byte2 = header[9] & 0xff;
- info.height = ((byte2 << 8) | byte1) & 0xffff;
- }
-
- private byte[] getDefaultHeader(InputStream imageStream)
- throws IOException {
- byte[] header = new byte[GIF_SIG_LENGTH];
- try {
- imageStream.mark(GIF_SIG_LENGTH + 1);
- imageStream.read(header);
- imageStream.reset();
- } catch (IOException ex) {
- try {
- imageStream.reset();
- } catch (IOException exbis) {
- // throw the original exception, not this one
- }
- throw ex;
- }
- return header;
- }
-
-}
-
diff --git a/src/java/org/apache/fop/image/analyser/ImageReader.java b/src/java/org/apache/fop/image/analyser/ImageReader.java
deleted file mode 100644
index 980d1e489..000000000
--- a/src/java/org/apache/fop/image/analyser/ImageReader.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * 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.image.analyser;
-
-// Java
-import java.io.InputStream;
-import java.io.IOException;
-
-// FOP
-import org.apache.fop.image.FopImage;
-import org.apache.fop.apps.FOUserAgent;
-
-/**
- * ImageReader objects read image headers to determine the image size.
- *
- * @author Pankaj Narula
- * @version $Id$
- */
-public interface ImageReader {
-
- /**
- * Verify image type. If the stream does not contain image data expected by
- * the reader it must reset the stream to the start. This is so that the
- * next reader can start reading from the start. The reader must not close
- * the stream unless it can handle the image and it has read the
- * information.
- *
- * @param bis Image buffered input stream
- * @param uri URI to the image
- * @param ua The user agent
- * @return <code>true</code> if image type is the handled one
- * @exception IOException if an I/O error occurs
- */
- FopImage.ImageInfo verifySignature(String uri, InputStream bis,
- FOUserAgent ua)
- throws IOException;
-
-}
-
diff --git a/src/java/org/apache/fop/image/analyser/ImageReaderFactory.java b/src/java/org/apache/fop/image/analyser/ImageReaderFactory.java
deleted file mode 100644
index c07d68d39..000000000
--- a/src/java/org/apache/fop/image/analyser/ImageReaderFactory.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * 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.image.analyser;
-
-// Java
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Iterator;
-import java.util.List;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.fop.apps.FOUserAgent;
-import org.apache.fop.image.FopImage;
-import org.apache.xmlgraphics.util.Service;
-
-/**
- * Factory for ImageReader objects.
- *
- * @author Pankaj Narula
- * @version $Id$
- */
-public class ImageReaderFactory {
-
- private static List formats = new java.util.ArrayList();
-
- /** logger */
- protected static Log log = LogFactory.getLog(ImageReaderFactory.class);
-
- static {
- registerFormat(new JPEGReader());
- registerFormat(new BMPReader());
- registerFormat(new GIFReader());
- registerFormat(new PNGReader());
- registerFormat(new TIFFReader());
- registerFormat(new EPSReader());
- registerFormat(new EMFReader());
-
- //Dynamic registration of ImageReaders
- Iterator iter = Service.providers(ImageReader.class, true);
- while (iter.hasNext()) {
- registerFormat((ImageReader)iter.next());
- }
-
- // the xml parser through batik closes the stream when finished
- // so there is a workaround in the SVGReader
- registerFormat(new SVGReader());
- registerFormat(new SVGZReader());
- registerFormat(new XMLReader());
- }
-
- /**
- * Registers a new ImageReader.
- *
- * @param reader An ImageReader instance
- */
- public static void registerFormat(ImageReader reader) {
- formats.add(reader);
- }
-
- /**
- * ImageReader maker.
- *
- * @param uri URI to the image
- * @param in image input stream
- * @param ua user agent
- * @return An ImageInfo object describing the image
- */
- public static FopImage.ImageInfo make(String uri, InputStream in,
- FOUserAgent ua) {
-
- ImageReader reader;
- try {
- for (int count = 0; count < formats.size(); count++) {
- reader = (ImageReader) formats.get(count);
- FopImage.ImageInfo info = reader.verifySignature(uri, in, ua);
- if (info != null) {
- return info;
- }
- }
- log.warn("No ImageReader found for " + uri);
- in.close();
- } catch (IOException ex) {
- log.error("Error while recovering Image Informations ("
- + uri + ")", ex);
- }
- return null;
- }
-
-}
-
diff --git a/src/java/org/apache/fop/image/analyser/JPEGReader.java b/src/java/org/apache/fop/image/analyser/JPEGReader.java
deleted file mode 100644
index c90f6b000..000000000
--- a/src/java/org/apache/fop/image/analyser/JPEGReader.java
+++ /dev/null
@@ -1,264 +0,0 @@
-/*
- * 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.image.analyser;
-
-// Java
-import java.io.InputStream;
-import java.io.IOException;
-
-// FOP
-import org.apache.fop.image.FopImage;
-import org.apache.fop.apps.FOUserAgent;
-
-/**
- * ImageReader object for JPEG image type.
- *
- * @author Pankaj Narula
- * @version $Id$
- */
-public class JPEGReader implements ImageReader {
-
- /**
- * Only SOFn and APPn markers are defined as SOFn is needed for the height and
- * width search. APPn is also defined because if the JPEG contains thumbnails
- * the dimensions of the thumnail would also be after the SOFn marker enclosed
- * inside the APPn marker. And we don't want to confuse those dimensions with
- * the image dimensions.
- */
- private static final int MARK = 0xff; // Beginning of a Marker
- private static final int NULL = 0x00; // Special case for 0xff00
- private static final int SOF1 = 0xc0; // Baseline DCT
- private static final int SOF2 = 0xc1; // Extended Sequential DCT
- private static final int SOF3 = 0xc2; // Progrssive DCT only PDF 1.3
- private static final int SOFA = 0xca; // Progressice DCT only PDF 1.3
- private static final int APP0 = 0xe0; // Application marker, JFIF
- private static final int APPF = 0xef; // Application marker
- private static final int SOS = 0xda; // Start of Scan
- private static final int SOI = 0xd8; // start of Image
- private static final int JPG_SIG_LENGTH = 2;
-
- /** {@inheritDoc} */
- public FopImage.ImageInfo verifySignature(String uri, InputStream fis,
- FOUserAgent ua) throws IOException {
- byte[] header = getDefaultHeader(fis);
- boolean supported = ((header[0] == (byte) 0xff)
- && (header[1] == (byte) 0xd8));
- if (supported) {
- FopImage.ImageInfo info = new FopImage.ImageInfo();
- info.dpiHorizontal = ua.getFactory().getSourceResolution();
- info.dpiVertical = info.dpiHorizontal;
-
- getDimension(fis, info);
- info.originalURI = uri;
- info.mimeType = getMimeType();
- info.inputStream = fis;
- return info;
- } else {
- return null;
- }
- }
-
- /**
- * Returns the MIME type supported by this implementation.
- *
- * @return The MIME type
- */
- public String getMimeType() {
- return "image/jpeg";
- }
-
- private byte[] getDefaultHeader(InputStream imageStream) throws IOException {
- byte[] header = new byte[JPG_SIG_LENGTH];
- try {
- imageStream.mark(JPG_SIG_LENGTH + 1);
- imageStream.read(header);
- imageStream.reset();
- } catch (IOException ex) {
- try {
- imageStream.reset();
- } catch (IOException exbis) {
- // throw the original exception, not this one
- }
- throw ex;
- }
- return header;
- }
-
- private void getDimension(InputStream imageStream,
- FopImage.ImageInfo info)
- throws IOException {
- try {
- int pos=0, avail = imageStream.available();
- imageStream.mark(avail);
- int marker = NULL;
- long length, skipped;
-outer:
- while (true) {
- do {
- if (avail == 0) {
- imageStream.reset();
- avail = 2*pos;
- imageStream.mark(avail);
- pos = (int)this.skip(imageStream, pos);
- avail -= pos;
- }
- //Marker first byte (FF)
- marker = imageStream.read();
- pos++; avail--;
- } while (marker != MARK);
-
- do {
- if (avail == 0) {
- imageStream.reset();
- avail = 2*pos;
- imageStream.mark(avail);
- pos = (int)this.skip(imageStream, pos);
- avail -= pos;
- }
- //Marker second byte
- marker = imageStream.read();
- pos++; avail--;
- } while (marker == MARK);
-
- switch (marker) {
- case SOI:
- break;
- case NULL:
- break;
- case APP0:
- if (avail < 14) {
- imageStream.reset();
- avail = 2 * pos;
- imageStream.mark(avail);
- pos = (int)this.skip(imageStream, pos);
- avail -= pos;
- }
- int reclen = this.read2bytes(imageStream);
- pos += 2; avail -= 2;
- this.skip(imageStream, 7);
- pos += 7; avail -= 7;
- int densityUnits = imageStream.read();
- pos++; avail--;
- int xdensity = this.read2bytes(imageStream);
- pos += 2; avail -= 2;
- int ydensity = this.read2bytes(imageStream);
- pos += 2; avail -= 2;
-
- if (densityUnits == 2) {
- info.dpiHorizontal = xdensity * 28.3464567 / 72; //dpi
- info.dpiVertical = ydensity * 28.3464567 / 72; //dpi
- } else if (densityUnits == 1) {
- info.dpiHorizontal = xdensity;
- info.dpiVertical = ydensity;
- } else {
- // Use resolution specified in
- // FOUserAgent.getFactory() (default 72dpi).
- }
-
- int restlen = reclen - 12;
- if (avail < restlen) {
- imageStream.reset();
- avail = 2 * pos;
- if (avail < pos + restlen + 10) {
- avail = (int)(pos + restlen + 10);
- }
- imageStream.mark(avail);
- pos = (int)this.skip(imageStream, pos);
- avail -= pos;
- }
- skipped = this.skip(imageStream, restlen - 2);
- pos += skipped; avail -= skipped;
- if (skipped != restlen - 2) {
- throw new IOException("Skipping Error");
- }
- break;
- case SOF1:
- case SOF2:
- case SOF3: // SOF3 and SOFA are only supported by PDF 1.3
- case SOFA:
- while (avail < 7) {
- imageStream.reset();
- avail = 2*pos;
- imageStream.mark(avail);
- pos = (int)this.skip(imageStream, pos);
- avail -= pos;
- }
- this.skip(imageStream, 3);
- pos+=3; avail-=3;
- info.height = this.read2bytes(imageStream);
- pos+=2; avail-=2;
- info.width = this.read2bytes(imageStream);
- pos+=2; avail-=2;
- break outer;
- default:
- while (avail < 2) {
- imageStream.reset();
- avail = 2*pos;
- imageStream.mark(avail);
- pos = (int)this.skip(imageStream, pos);
- avail -= pos;
- }
- length = this.read2bytes(imageStream);
- pos+=2; avail-=2;
- if (avail < length) {
- imageStream.reset();
- avail = 2*pos;
- if (avail < pos+length+10) {
- avail = (int)(pos+length+10);
- }
- imageStream.mark(avail);
- pos = (int)this.skip(imageStream, pos);
- avail -= pos;
- }
- skipped = this.skip(imageStream, length - 2);
- pos += skipped; avail -= skipped;
- if (skipped != length - 2) {
- throw new IOException("Skipping Error");
- }
- }
- }
- imageStream.reset();
- } catch (IOException ioe) {
- try {
- imageStream.reset();
- } catch (IOException exbis) {
- // throw the original exception, not this one
- }
- throw ioe;
- }
- }
-
- private int read2bytes(InputStream imageStream) throws IOException {
- int byte1 = imageStream.read();
- int byte2 = imageStream.read();
- return (int) ((byte1 << 8) | byte2);
- }
-
- private long skip(InputStream imageStream, long n) throws IOException {
- long discarded = 0;
- while (discarded != n) {
- imageStream.read();
- discarded++;
- }
- return discarded; // scope for exception
- }
-
-}
-
diff --git a/src/java/org/apache/fop/image/analyser/PNGReader.java b/src/java/org/apache/fop/image/analyser/PNGReader.java
deleted file mode 100644
index ab6c64775..000000000
--- a/src/java/org/apache/fop/image/analyser/PNGReader.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * 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.image.analyser;
-
-// Java
-import java.io.InputStream;
-import java.io.IOException;
-
-// FOP
-import org.apache.fop.image.FopImage;
-import org.apache.fop.apps.FOUserAgent;
-
-/**
- * ImageReader object for PNG image type.
- *
- * @author Pankaj Narula
- * @version $Id$
- */
-public class PNGReader implements ImageReader {
-
- private static final int PNG_SIG_LENGTH = 24;
-
- /** {@inheritDoc} */
- public FopImage.ImageInfo verifySignature(String uri, InputStream bis,
- FOUserAgent ua) throws IOException {
- byte[] header = getDefaultHeader(bis);
- boolean supported = ((header[0] == (byte) 0x89)
- && (header[1] == (byte) 0x50)
- && (header[2] == (byte) 0x4e)
- && (header[3] == (byte) 0x47)
- && (header[4] == (byte) 0x0d)
- && (header[5] == (byte) 0x0a)
- && (header[6] == (byte) 0x1a)
- && (header[7] == (byte) 0x0a));
-
- if (supported) {
- FopImage.ImageInfo info = new FopImage.ImageInfo();
- info.dpiHorizontal = ua.getFactory().getSourceResolution();
- info.dpiVertical = info.dpiHorizontal;
-
- getDimension(header, info);
- info.originalURI = uri;
- info.mimeType = getMimeType();
- info.inputStream = bis;
- return info;
- } else {
- return null;
- }
- }
-
- /**
- * Returns the MIME type supported by this implementation.
- *
- * @return The MIME type
- */
- public String getMimeType() {
- return "image/png";
- }
-
- private void getDimension(byte[] header, FopImage.ImageInfo info) {
- // png is always big endian
- int byte1 = header[16] & 0xff;
- int byte2 = header[17] & 0xff;
- int byte3 = header[18] & 0xff;
- int byte4 = header[19] & 0xff;
- long l = (long) ((byte1 << 24)
- | (byte2 << 16)
- | (byte3 << 8)
- | (byte4));
- info.width = (int) l;
-
- byte1 = header[20] & 0xff;
- byte2 = header[21] & 0xff;
- byte3 = header[22] & 0xff;
- byte4 = header[23] & 0xff;
- l = (long) ((byte1 << 24) | (byte2 << 16) | (byte3 << 8) | byte4);
- info.height = (int) l;
- }
-
- private byte[] getDefaultHeader(InputStream imageStream)
- throws IOException {
- byte[] header = new byte[PNG_SIG_LENGTH];
- try {
- imageStream.mark(PNG_SIG_LENGTH + 1);
- imageStream.read(header);
- imageStream.reset();
- } catch (IOException ex) {
- try {
- imageStream.reset();
- } catch (IOException exbis) {
- // throw the original exception, not this one
- }
- throw ex;
- }
- return header;
- }
-
-}
diff --git a/src/java/org/apache/fop/image/analyser/SVGReader.java b/src/java/org/apache/fop/image/analyser/SVGReader.java
deleted file mode 100644
index cffaa365c..000000000
--- a/src/java/org/apache/fop/image/analyser/SVGReader.java
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * 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.image.analyser;
-
-// Java
-import java.io.InputStream;
-import java.io.IOException;
-import java.awt.geom.AffineTransform;
-
-// XML
-import org.w3c.dom.Element;
-import org.w3c.dom.svg.SVGDocument;
-
-// Batik
-import org.apache.batik.dom.svg.SAXSVGDocumentFactory;
-import org.apache.batik.dom.svg.SVGOMDocument;
-import org.apache.batik.bridge.BridgeContext;
-import org.apache.batik.bridge.UnitProcessor;
-import org.apache.batik.dom.svg.SVGDOMImplementation;
-import org.apache.commons.io.IOUtils;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-// FOP
-import org.apache.fop.image.XMLImage;
-import org.apache.fop.image.FopImage;
-import org.apache.fop.apps.FOUserAgent;
-import org.apache.fop.svg.SVGUserAgent;
-import org.apache.fop.util.UnclosableInputStream;
-
-/**
- * ImageReader object for SVG document image type.
- */
-public class SVGReader implements ImageReader {
-
- /** Logger instance */
- protected static Log log = LogFactory.getLog(SVGReader.class);
-
- /** SVG's MIME type */
- public static final String SVG_MIME_TYPE = "image/svg+xml";
-
- private boolean batik = true;
-
- /** {@inheritDoc} */
- public FopImage.ImageInfo verifySignature(String uri, InputStream fis,
- FOUserAgent ua) throws IOException {
- FopImage.ImageInfo info = loadImage(uri, fis, ua);
- if (info != null) {
- IOUtils.closeQuietly(fis);
- }
- return info;
- }
-
- /**
- * Returns the MIME type supported by this implementation.
- *
- * @return The MIME type
- */
- public String getMimeType() {
- return SVG_MIME_TYPE;
- }
-
- /**
- * This means the external svg document will be loaded twice. Possibly need
- * a slightly different design for the image stuff.
- *
- * @param uri @todo Description of the Parameter
- * @param fis @todo Description of the Parameter
- * @param ua @todo Description of the Parameter
- * @return @todo Description of the Return Value
- */
- private FopImage.ImageInfo loadImage(String uri, InputStream bis,
- FOUserAgent ua) {
- if (batik) {
- try {
- Loader loader = new Loader();
- return loader.getImage(uri, bis,
- ua.getSourcePixelUnitToMillimeter());
- } catch (NoClassDefFoundError e) {
- batik = false;
- log.warn("Batik not in class path", e);
- return null;
- }
- }
- return null;
- }
-
- /**
- * This method is put in another class so that the classloader does not
- * attempt to load batik related classes when constructing the SVGReader
- * class.
- */
- class Loader {
- private FopImage.ImageInfo getImage(String uri, InputStream fis,
- float pixelUnitToMM) {
- // parse document and get the size attributes of the svg element
-
- try {
- fis = new UnclosableInputStream(fis);
-
- FopImage.ImageInfo info = new FopImage.ImageInfo();
-
- //Set the resolution to that of the FOUserAgent
- info.dpiHorizontal = 25.4f / pixelUnitToMM;
- info.dpiVertical = info.dpiHorizontal;
-
- info.originalURI = uri;
- info.mimeType = getMimeType();
- info.str = SVGDOMImplementation.SVG_NAMESPACE_URI;
-
- int length = fis.available();
- fis.mark(length + 1);
- SAXSVGDocumentFactory factory = new SAXSVGDocumentFactory(
- XMLImage.getParserName());
- SVGDocument doc = (SVGDocument) factory.createSVGDocument(uri, fis);
- info.data = doc;
-
- Element e = doc.getRootElement();
- String s;
- SVGUserAgent userAg = new SVGUserAgent(pixelUnitToMM,
- new AffineTransform());
- BridgeContext ctx = new BridgeContext(userAg);
- UnitProcessor.Context uctx = UnitProcessor.createContext(ctx, e);
-
- // 'width' attribute - default is 100%
- s = e.getAttributeNS(null,
- SVGOMDocument.SVG_WIDTH_ATTRIBUTE);
- if (s.length() == 0) {
- s = SVGOMDocument.SVG_SVG_WIDTH_DEFAULT_VALUE;
- }
- info.width = Math.round(UnitProcessor.svgHorizontalLengthToUserSpace(
- s, SVGOMDocument.SVG_WIDTH_ATTRIBUTE, uctx));
-
- // 'height' attribute - default is 100%
- s = e.getAttributeNS(null,
- SVGOMDocument.SVG_HEIGHT_ATTRIBUTE);
- if (s.length() == 0) {
- s = SVGOMDocument.SVG_SVG_HEIGHT_DEFAULT_VALUE;
- }
- info.height = Math.round(UnitProcessor.svgVerticalLengthToUserSpace(
- s, SVGOMDocument.SVG_HEIGHT_ATTRIBUTE, uctx));
-
- return info;
- } catch (NoClassDefFoundError ncdfe) {
- try {
- fis.reset();
- } catch (IOException ioe) {
- // we're more interested in the original exception
- }
- batik = false;
- log.warn("Batik not in class path", ncdfe);
- return null;
- } catch (IOException e) {
- // If the svg is invalid then it throws an IOException
- // so there is no way of knowing if it is an svg document
-
- log.debug("Error while trying to load stream as an SVG file: "
- + e.getMessage());
- // assuming any exception means this document is not svg
- // or could not be loaded for some reason
- try {
- fis.reset();
- } catch (IOException ioe) {
- // we're more interested in the original exception
- }
- return null;
- }
- }
- }
-
-}
diff --git a/src/java/org/apache/fop/image/analyser/TIFFReader.java b/src/java/org/apache/fop/image/analyser/TIFFReader.java
deleted file mode 100644
index 08d702780..000000000
--- a/src/java/org/apache/fop/image/analyser/TIFFReader.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * 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.image.analyser;
-
-// Java
-import java.io.InputStream;
-import java.io.IOException;
-
-// FOP
-import org.apache.fop.image.FopImage;
-import org.apache.fop.apps.FOUserAgent;
-
-/**
- * ImageReader object for TIFF image type.
- *
- * @author Pankaj Narula, Michael Lee
- * @version $Id$
- */
-public class TIFFReader implements ImageReader {
-
- private static final int TIFF_SIG_LENGTH = 8;
-
- /** {@inheritDoc} */
- public FopImage.ImageInfo verifySignature(String uri, InputStream bis,
- FOUserAgent ua) throws IOException {
- byte[] header = getDefaultHeader(bis);
- boolean supported = false;
-
- // first 2 bytes = II (little endian encoding)
- if (header[0] == (byte) 0x49 && header[1] == (byte) 0x49) {
-
- // look for '42' in byte 3 and '0' in byte 4
- if (header[2] == 42 && header[3] == 0) {
- supported = true;
- }
- }
-
- // first 2 bytes == MM (big endian encoding)
- if (header[0] == (byte) 0x4D && header[1] == (byte) 0x4D) {
-
- // look for '42' in byte 4 and '0' in byte 3
- if (header[2] == 0 && header[3] == 42) {
- supported = true;
- }
- }
-
- if (supported) {
- FopImage.ImageInfo info = new FopImage.ImageInfo();
- info.dpiHorizontal = ua.getFactory().getSourceResolution();
- info.dpiVertical = info.dpiHorizontal;
-
- getDimension(header, info);
- info.originalURI = uri;
- info.mimeType = getMimeType();
- info.inputStream = bis;
- return info;
- } else {
- return null;
- }
- }
-
- /**
- * Returns the MIME type supported by this implementation.
- *
- * @return The MIME type
- */
- public String getMimeType() {
- return "image/tiff";
- }
-
- private void getDimension(byte[] header, FopImage.ImageInfo info) {
- // currently not setting the width and height
- // these are set again by the Jimi image reader.
- // I suppose I'll do it one day to be complete. Or
- // someone else will.
- // Note: bytes 4,5,6,7 contain the byte offset in the stream of the first IFD block
- info.width = -1;
- info.height = -1;
- }
-
- private byte[] getDefaultHeader(InputStream imageStream)
- throws IOException {
- byte[] header = new byte[TIFF_SIG_LENGTH];
- try {
- imageStream.mark(TIFF_SIG_LENGTH + 1);
- imageStream.read(header);
- imageStream.reset();
- } catch (IOException ex) {
- try {
- imageStream.reset();
- } catch (IOException exbis) {
- // throw the original exception, not this one
- }
- throw ex;
- }
- return header;
- }
-
-}
-
diff --git a/src/java/org/apache/fop/image/analyser/XMLReader.java b/src/java/org/apache/fop/image/analyser/XMLReader.java
deleted file mode 100644
index 4d0145eed..000000000
--- a/src/java/org/apache/fop/image/analyser/XMLReader.java
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * 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.image.analyser;
-
-// Java
-import java.io.InputStream;
-import java.io.IOException;
-import java.util.Map;
-
-// XML
-import javax.xml.parsers.DocumentBuilderFactory;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-
-// FOP
-import org.apache.fop.image.FopImage;
-import org.apache.fop.util.UnclosableInputStream;
-import org.apache.fop.apps.FOUserAgent;
-
-// Commons-Logging
-import org.apache.commons.io.IOUtils;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-/** ImageReader object for XML document image type. */
-public class XMLReader implements ImageReader {
-
- /**
- * logging instance
- */
- private Log log = LogFactory.getLog(XMLReader.class);
-
- private static Map converters = new java.util.HashMap();
-
- /**
- * Registers a Converter implementation with XMLReader.
- *
- * @param ns The namespace to associate with this converter
- * @param conv The actual Converter implementation
- */
- public static void setConverter(String ns, Converter conv) {
- converters.put(ns, conv);
- }
-
- /** {@inheritDoc} */
- public FopImage.ImageInfo verifySignature(String uri, InputStream fis,
- FOUserAgent ua)
- throws IOException {
- FopImage.ImageInfo info = loadImage(uri, fis, ua);
- if (info != null) {
- info.originalURI = uri;
- IOUtils.closeQuietly(fis);
- }
- return info;
- }
-
- /**
- * Returns the MIME type supported by this implementation.
- *
- * @return The MIME type
- */
- public String getMimeType() {
- return "text/xml";
- }
-
- /**
- * Creates an ImageInfo object from an XML image read from a stream.
- *
- * (todo) This means the external svg document will be loaded twice. Possibly need
- * a slightly different design for the image stuff.
- *
- * @param uri The URI to the image
- * @param bis The InputStream
- * @param ua The user agent
- * @return An ImageInfo object describing the image
- */
- protected FopImage.ImageInfo loadImage(String uri, InputStream bis,
- FOUserAgent ua) {
- return createDocument(bis, ua);
- }
-
- /**
- * Creates an ImageInfo object from an XML image read from a stream.
- *
- * @param input The InputStream
- * @param ua The user agent
- * @return An ImageInfo object describing the image
- */
- public FopImage.ImageInfo createDocument(final InputStream input, final FOUserAgent ua) {
- Document doc = null;
- FopImage.ImageInfo info = new FopImage.ImageInfo();
- info.mimeType = getMimeType();
-
- try {
- final InputStream is = new UnclosableInputStream(input);
- int length = is.available();
- is.mark(length);
-
- DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
- doc = dbf.newDocumentBuilder().parse(is);
- info.data = doc;
-
- Element root = doc.getDocumentElement();
- log.debug("XML image namespace: " + root.getAttribute("xmlns"));
- String ns = root.getAttribute("xmlns");
- info.str = ns;
-
- Converter conv = (Converter) converters.get(ns);
- if (conv != null) {
- FopImage.ImageInfo i = conv.convert(doc);
- if (i != null) {
- info = i;
- }
- }
- } catch (Exception e) {
- log.debug("Error while constructing image from XML", e);
- try {
- input.reset();
- } catch (IOException ioe) {
- // throw the original exception, not this one
- }
- return null;
- }
- if (info != null) {
- try {
- input.close();
- } catch (IOException io) {
- // ignore
- }
- }
- return info;
- }
-
- /**
- * This interface is to be implemented for XML to image converters.
- */
- public static interface Converter {
-
- /**
- * This method is called for a DOM document to be converted into an
- * ImageInfo object.
- *
- * @param doc The DOM document to convert
- * @return An ImageInfo object describing the image
- */
- FopImage.ImageInfo convert(Document doc);
- }
-
-}
-
diff --git a/src/java/org/apache/fop/image/analyser/package.html b/src/java/org/apache/fop/image/analyser/package.html
deleted file mode 100644
index 677a625b2..000000000
--- a/src/java/org/apache/fop/image/analyser/package.html
+++ /dev/null
@@ -1,23 +0,0 @@
-<!--
- 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$ -->
-<HTML>
-<TITLE>org.apache.fop.image.analyser Package</TITLE>
-<BODY>
-<P>Image analyzers for determining the format of an image and to preload its intrinsic size.</P>
-</BODY>
-</HTML> \ No newline at end of file
diff --git a/src/java/org/apache/fop/image/package.html b/src/java/org/apache/fop/image/package.html
index 0145864b2..cbd2d7c5e 100644
--- a/src/java/org/apache/fop/image/package.html
+++ b/src/java/org/apache/fop/image/package.html
@@ -18,6 +18,6 @@
<HTML>
<TITLE>org.apache.fop.image Package</TITLE>
<BODY>
-<P>Contains image loading adapters for various image sources and the image cache.</P>
+<P>Contains image loading adapters for various image sources.</P>
</BODY>
</HTML> \ No newline at end of file
diff --git a/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java b/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java
index 54fd315b1..65d537bcd 100644
--- a/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java
+++ b/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java
@@ -272,7 +272,7 @@ public abstract class AbstractBreaker {
*/
public void doLayout(int flowBPD, boolean autoHeight) {
LayoutContext childLC = createLayoutContext();
- childLC.setStackLimit(new MinOptMax(flowBPD));
+ childLC.setStackLimitBP(new MinOptMax(flowBPD));
if (getCurrentDisplayAlign() == Constants.EN_X_FILL) {
//EN_X_FILL is non-standard (by LF)
@@ -495,7 +495,7 @@ public abstract class AbstractBreaker {
int averageLineLength = optimizeLineLength(effectiveList,
startElementIndex, endElementIndex);
if (averageLineLength != 0) {
- childLC.setStackLimit(new MinOptMax(averageLineLength));
+ childLC.setStackLimitBP(new MinOptMax(averageLineLength));
}
}
/* *** *** non-standard extension *** *** */
diff --git a/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java b/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java
index f75fffc0d..656b5e2df 100644
--- a/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/AbstractLayoutManager.java
@@ -113,7 +113,7 @@ public abstract class AbstractLayoutManager extends AbstractBaseLayoutManager
if (curChildLM != null && !curChildLM.isFinished()) {
return curChildLM;
}
- while (childLMiter.hasNext()) {
+ if (childLMiter.hasNext()) {
curChildLM = (LayoutManager) childLMiter.next();
curChildLM.initialize();
return curChildLM;
@@ -350,6 +350,10 @@ public abstract class AbstractLayoutManager extends AbstractBaseLayoutManager
/**
* Registers the FO's markers on the current PageViewport
+ *
+ * @param isStarting boolean indicating whether the markers qualify as 'starting'
+ * @param isFirst boolean indicating whether the markers qualify as 'first'
+ * @param isLast boolean indicating whether the markers qualify as 'last'
*/
protected void addMarkersToPage(boolean isStarting, boolean isFirst, boolean isLast) {
if (this.markers != null) {
@@ -361,10 +365,18 @@ public abstract class AbstractLayoutManager extends AbstractBaseLayoutManager
}
}
+ /**
+ * Registers the FO's id on the current PageViewport
+ */
+ protected void addId() {
+ if (fobj != null) {
+ getPSLM().addIDToPage(fobj.getId());
+ }
+ }
+
/** {@inheritDoc} */
public String toString() {
return (super.toString() + (fobj != null ? "[fobj=" + fobj.toString() + "]" : ""));
}
-
}
diff --git a/src/java/org/apache/fop/layoutmgr/AreaAdditionUtil.java b/src/java/org/apache/fop/layoutmgr/AreaAdditionUtil.java
index 80e0b74cc..1b0d02639 100644
--- a/src/java/org/apache/fop/layoutmgr/AreaAdditionUtil.java
+++ b/src/java/org/apache/fop/layoutmgr/AreaAdditionUtil.java
@@ -117,7 +117,7 @@ public class AreaAdditionUtil {
// set space after for each LM, in order to implement
// display-align = distribute
lc.setSpaceAfter(layoutContext.getSpaceAfter());
- lc.setStackLimit(layoutContext.getStackLimit());
+ lc.setStackLimitsFrom(layoutContext);
childLM.addAreas(childPosIter, lc);
}
diff --git a/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java
index fc60b561e..e8ca88c1c 100644
--- a/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java
@@ -38,7 +38,6 @@ import org.apache.fop.datatypes.Length;
import org.apache.fop.fo.FONode;
import org.apache.fop.fo.flow.BlockContainer;
import org.apache.fop.fo.properties.CommonAbsolutePosition;
-import org.apache.fop.layoutmgr.inline.InlineLayoutManager;
import org.apache.fop.traits.MinOptMax;
import org.apache.fop.traits.SpaceVal;
@@ -201,7 +200,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager
= (getBlockContainerFO().getReferenceOrientation() % 180 != 0);
autoHeight = false;
//boolean rotated = (getBlockContainerFO().getReferenceOrientation() % 180 != 0);
- int maxbpd = context.getStackLimit().opt;
+ int maxbpd = context.getStackLimitBP().opt;
int allocBPD;
if (height.getEnum() == EN_AUTO
|| (!height.isAbsolute() && getAncestorBlockAreaBPD() <= 0)) {
@@ -249,7 +248,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager
MinOptMax stackLimit = new MinOptMax(relDims.bpd);
- LinkedList returnedList = null;
+ LinkedList returnedList;
LinkedList contentList = new LinkedList();
LinkedList returnList = new LinkedList();
@@ -280,8 +279,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager
LayoutContext childLC = new LayoutContext(0);
childLC.copyPendingMarksFrom(context);
// curLM is a ?
- childLC.setStackLimit(MinOptMax.subtract(context
- .getStackLimit(), stackLimit));
+ childLC.setStackLimitBP(MinOptMax.subtract(context.getStackLimitBP(), stackLimit));
childLC.setRefIPD(relDims.ipd);
childLC.setWritingMode(getBlockContainerFO().getWritingMode());
@@ -388,6 +386,9 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager
}
addKnuthElementsForBorderPaddingAfter(returnList, true);
addKnuthElementsForSpaceAfter(returnList, alignment);
+
+ //All child content is processed. Only break-after can occur now, so...
+ context.clearPendingMarks();
addKnuthElementsForBreakAfter(returnList, context);
setFinished(true);
@@ -411,7 +412,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager
if (isFixed()) {
availHeight = (int)getCurrentPV().getViewArea().getHeight();
} else {
- availHeight = context.getStackLimit().opt;
+ availHeight = context.getStackLimitBP().opt;
}
allocBPD = availHeight;
allocBPD -= offset.y;
@@ -444,7 +445,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager
}
}
} else {
- int maxbpd = context.getStackLimit().opt;
+ int maxbpd = context.getStackLimitBP().opt;
allocBPD = maxbpd;
if (!switchedProgressionDirection) {
autoHeight = true;
@@ -601,11 +602,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager
}
public boolean isOverflow() {
- if (isEmpty()) {
- return false;
- } else {
- return (deferredAlg.getPageBreaks().size() > 1);
- }
+ return !isEmpty() && (deferredAlg.getPageBreaks().size() > 1);
}
protected LayoutManager getTopLevelLM() {
@@ -625,7 +622,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager
while ((curLM = getChildLM()) != null) {
LayoutContext childLC = new LayoutContext(0);
- childLC.setStackLimit(context.getStackLimit());
+ childLC.setStackLimitBP(context.getStackLimitBP());
childLC.setRefIPD(context.getRefIPD());
childLC.setWritingMode(getBlockContainerFO().getWritingMode());
@@ -707,7 +704,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager
addBlockSpacing(0.0, new MinOptMax(layoutContext.getSpaceBefore()));
}
- LayoutManager childLM = null;
+ LayoutManager childLM;
LayoutManager lastLM = null;
LayoutContext lc = new LayoutContext(0);
lc.setSpaceAdjust(layoutContext.getSpaceAdjust());
@@ -736,7 +733,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager
}
Position innerPosition = pos;
if (pos instanceof NonLeafPosition) {
- innerPosition = ((NonLeafPosition)pos).getPosition();
+ innerPosition = pos.getPosition();
}
if (pos instanceof BlockContainerPosition) {
if (bcpos != null) {
@@ -772,7 +769,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager
}
}
- getPSLM().addIDToPage(getBlockContainerFO().getId());
+ addId();
addMarkersToPage(true, isFirst(firstPos), isLast(lastPos));
@@ -854,7 +851,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager
// set last area flag
lc.setFlags(LayoutContext.LAST_AREA,
(layoutContext.isLastArea() && childLM == lastLM));
- /*LF*/lc.setStackLimit(layoutContext.getStackLimit());
+ /*LF*/lc.setStackLimitBP(layoutContext.getStackLimitBP());
// Add the line areas to Area
childLM.addAreas(childPosIter, lc);
}
@@ -873,7 +870,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager
referenceArea = null;
resetSpaces();
- getPSLM().notifyEndOfLayout(((BlockContainer)getFObj()).getId());
+ getPSLM().notifyEndOfLayout(fobj.getId());
}
/**
@@ -992,30 +989,21 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager
}
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
public boolean mustKeepTogether() {
//TODO Keeps will have to be more sophisticated sooner or later
- return (!getBlockContainerFO().getKeepTogether().getWithinPage().isAuto()
- || !getBlockContainerFO().getKeepTogether().getWithinColumn().isAuto()
- || (getParent() instanceof BlockLevelLayoutManager
- && ((BlockLevelLayoutManager) getParent()).mustKeepTogether())
- || (getParent() instanceof InlineLayoutManager
- && ((InlineLayoutManager) getParent()).mustKeepTogether()));
+ return super.mustKeepTogether()
+ || !getBlockContainerFO().getKeepTogether().getWithinPage().isAuto()
+ || !getBlockContainerFO().getKeepTogether().getWithinColumn().isAuto();
}
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
public boolean mustKeepWithPrevious() {
return !getBlockContainerFO().getKeepWithPrevious().getWithinPage().isAuto()
|| !getBlockContainerFO().getKeepWithPrevious().getWithinColumn().isAuto();
}
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
public boolean mustKeepWithNext() {
return !getBlockContainerFO().getKeepWithNext().getWithinPage().isAuto()
|| !getBlockContainerFO().getKeepWithNext().getWithinColumn().isAuto();
diff --git a/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java
index bb39def8d..f5270107c 100644
--- a/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java
@@ -25,6 +25,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.area.LineArea;
@@ -146,7 +147,7 @@ public class BlockLayoutManager extends BlockStackingLayoutManager
* @return true if there are more child lms
*/
public boolean hasNext() {
- return (curPos < listLMs.size()) ? true : createNextChildLMs(curPos);
+ return (curPos < listLMs.size()) || createNextChildLMs(curPos);
}
/**
@@ -249,7 +250,7 @@ public class BlockLayoutManager extends BlockStackingLayoutManager
addBlockSpacing(0.0, new MinOptMax(layoutContext.getSpaceBefore()));
}
- LayoutManager childLM = null;
+ LayoutManager childLM;
LayoutManager lastLM = null;
LayoutContext lc = new LayoutContext(0);
lc.setSpaceAdjust(layoutContext.getSpaceAdjust());
@@ -279,7 +280,7 @@ public class BlockLayoutManager extends BlockStackingLayoutManager
Position innerPosition = pos;
if (pos instanceof NonLeafPosition) {
//Not all elements are wrapped
- innerPosition = ((NonLeafPosition) pos).getPosition();
+ innerPosition = pos.getPosition();
}
if (innerPosition == null) {
// pos was created by this BlockLM and was inside an element
@@ -308,7 +309,7 @@ public class BlockLayoutManager extends BlockStackingLayoutManager
}
}
- getPSLM().addIDToPage(getBlockFO().getId());
+ addId();
addMarkersToPage(true, isFirst(firstPos), isLast(lastPos));
@@ -389,7 +390,7 @@ public class BlockLayoutManager extends BlockStackingLayoutManager
// set last area flag
lc.setFlags(LayoutContext.LAST_AREA,
(layoutContext.isLastArea() && childLM == lastLM));
- lc.setStackLimit(layoutContext.getStackLimit());
+ lc.setStackLimitBP(layoutContext.getStackLimitBP());
// Add the line areas to Area
childLM.addAreas(childPosIter, lc);
}
diff --git a/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java
index 5faad623c..67ed1de9f 100644
--- a/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java
@@ -274,13 +274,14 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager
if (curLM instanceof LineLayoutManager) {
// curLM is a LineLayoutManager
// set stackLimit for lines (stack limit is now i-p-direction, not b-p-direction!)
- childLC.setStackLimit(new MinOptMax(getContentAreaIPD()));
+ childLC.setStackLimitBP(context.getStackLimitBP());
+ childLC.setStackLimitIP(new MinOptMax(getContentAreaIPD()));
childLC.setRefIPD(getContentAreaIPD());
} else {
// curLM is a ?
//childLC.setStackLimit(MinOptMax.subtract(context
// .getStackLimit(), stackSize));
- childLC.setStackLimit(context.getStackLimit());
+ childLC.setStackLimitBP(context.getStackLimitBP());
childLC.setRefIPD(referenceIPD);
}
@@ -293,15 +294,22 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager
if (returnedList != null
&& returnedList.size() == 1
&& ((ListElement) returnedList.getFirst()).isForcedBreak()) {
- // a descendant of this block has break-before
- contentList.addAll(returnedList);
if (curLM.isFinished() && !hasNextChildLM()) {
- forcedBreakAfterLast = (BreakElement)contentList.removeLast();
+ // a descendant of this block has break-before
+ forcedBreakAfterLast = (BreakElement) returnedList.getFirst();
context.clearPendingMarks();
break;
}
+ if (contentList.size() == 0) {
+ // Empty fo:block, zero-length box makes sure the IDs and/or markers
+ // are registered and borders/padding are painted.
+ returnList.add(new KnuthBox(0, notifyPos(new Position(this)), false));
+ }
+ // a descendant of this block has break-before
+ contentList.addAll(returnedList);
+
/* extension: conversione di tutta la sequenza fin'ora ottenuta */
if (bpUnit > 0) {
storedList = contentList;
@@ -392,6 +400,9 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager
addKnuthElementsForBorderPaddingAfter(returnList, true);
addKnuthElementsForSpaceAfter(returnList, alignment);
+
+ //All child content is processed. Only break-after can occur now, so...
+ context.clearPendingMarks();
if (forcedBreakAfterLast == null) {
addKnuthElementsForBreakAfter(returnList, context);
}
diff --git a/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java b/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java
index a70dd0883..115532cf1 100644
--- a/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java
@@ -99,7 +99,7 @@ public class FlowLayoutManager extends BlockStackingLayoutManager
//MinOptMax bpd = context.getStackLimit();
LayoutContext childLC = new LayoutContext(0);
- childLC.setStackLimit(context.getStackLimit());
+ childLC.setStackLimitBP(context.getStackLimitBP());
childLC.setRefIPD(context.getRefIPD());
childLC.setWritingMode(getCurrentPage().getSimplePageMaster().getWritingMode());
diff --git a/src/java/org/apache/fop/layoutmgr/LayoutContext.java b/src/java/org/apache/fop/layoutmgr/LayoutContext.java
index 9eb38600b..79b5e232f 100644
--- a/src/java/org/apache/fop/layoutmgr/LayoutContext.java
+++ b/src/java/org/apache/fop/layoutmgr/LayoutContext.java
@@ -74,18 +74,29 @@ public class LayoutContext {
private int flags; // Contains some set of flags defined above
/**
* Total available stacking dimension for a "galley-level" layout
- * manager (Line or Flow). It is passed by the parent LM. For LineLM,
- * the block LM determines this based on indent properties.
+ * manager in block-progression-direction. It is passed by the
+ * parent LM.
* These LM <b>may</b> wish to pass this information down to lower
* level LM to allow them to optimize returned break possibilities.
*/
- private MinOptMax stackLimit;
+ private MinOptMax stackLimitBP;
+ /**
+ * Total available stacking dimension for a "galley-level" layout
+ * manager in inline-progression-direction. It is passed by the
+ * parent LM. For LineLM, the block LM determines this based on
+ * indent properties.
+ * These LM <b>may</b> wish to pass this information down to lower
+ * level LM to allow them to optimize returned break possibilities.
+ */
+ private MinOptMax stackLimitIP;
/** True if current element list is spanning in multi-column layout. */
private int nextSpan = Constants.NOT_SET;
/** inline-progression-dimension of nearest ancestor reference area */
private int refIPD;
+ //TODO After the split of stackLimit into stackLimitBP and stackLimitIP there's now some
+ //overlap with refIPD. Need to investigate how best to refactor that.
/** the writing mode established by the nearest ancestor reference area */
private int writingMode = Constants.EN_LR_TB;
@@ -145,7 +156,7 @@ public class LayoutContext {
this.flags = parentLC.flags;
this.refIPD = parentLC.refIPD;
this.writingMode = parentLC.writingMode;
- this.stackLimit = null; // Don't reference parent MinOptMax!
+ setStackLimitsFrom(parentLC);
this.leadingSpace = parentLC.leadingSpace; //???
this.trailingSpace = parentLC.trailingSpace; //???
this.hyphContext = parentLC.hyphContext;
@@ -166,7 +177,8 @@ public class LayoutContext {
public LayoutContext(int flags) {
this.flags = flags;
this.refIPD = 0;
- stackLimit = new MinOptMax(0);
+ stackLimitBP = new MinOptMax(0);
+ stackLimitIP = new MinOptMax(0);
leadingSpace = null;
trailingSpace = null;
}
@@ -273,12 +285,8 @@ public class LayoutContext {
* Clears all pending marks on the LayoutContext.
*/
public void clearPendingMarks() {
- if (this.pendingBeforeMarks != null) {
- this.pendingBeforeMarks.clear();
- }
- if (this.pendingAfterMarks != null) {
- this.pendingAfterMarks.clear();
- }
+ this.pendingBeforeMarks = null;
+ this.pendingAfterMarks = null;
}
/**
@@ -306,15 +314,48 @@ public class LayoutContext {
}
}
- public void setStackLimit(MinOptMax limit) {
- stackLimit = limit;
+ /**
+ * Sets the stack limit in block-progression-dimension.
+ * @param limit the stack limit
+ */
+ public void setStackLimitBP(MinOptMax limit) {
+ stackLimitBP = limit;
}
- public MinOptMax getStackLimit() {
- return stackLimit;
+ /**
+ * Returns the stack limit in block-progression-dimension.
+ * @return the stack limit
+ */
+ public MinOptMax getStackLimitBP() {
+ return stackLimitBP;
}
/**
+ * Sets the stack limit in inline-progression-dimension.
+ * @param limit the stack limit
+ */
+ public void setStackLimitIP(MinOptMax limit) {
+ stackLimitIP = limit;
+ }
+
+ /**
+ * Returns the stack limit in inline-progression-dimension.
+ * @return the stack limit
+ */
+ public MinOptMax getStackLimitIP() {
+ return stackLimitIP;
+ }
+
+ /**
+ * Sets (Copies) the stack limits in both directions from another layout context.
+ * @param context the layout context to taje the values from
+ */
+ public void setStackLimitsFrom(LayoutContext context) {
+ setStackLimitBP(context.getStackLimitBP());
+ setStackLimitIP(context.getStackLimitIP());
+ }
+
+ /**
* Sets the inline-progression-dimension of the nearest ancestor reference area.
*/
public void setRefIPD(int ipd) {
@@ -536,22 +577,27 @@ public class LayoutContext {
/** {@inheritDoc} */
public String toString() {
- return "Layout Context:" +
- "\nStack Limit: \t" + (getStackLimit() == null ? "null" : getStackLimit().toString()) +
- "\nTrailing Space: \t" + (getTrailingSpace() == null ? "null" : getTrailingSpace().toString()) +
- "\nLeading Space: \t" + (getLeadingSpace() == null ? "null" : getLeadingSpace().toString()) +
- "\nReference IPD: \t" + getRefIPD() +
- "\nSpace Adjust: \t" + getSpaceAdjust() +
- "\nIPD Adjust: \t" + getIPDAdjust() +
- "\nResolve Leading Space: \t" + resolveLeadingSpace() +
- "\nSuppress Leading Space: \t" + suppressLeadingSpace() +
- "\nIs First Area: \t" + isFirstArea() +
- "\nStarts New Area: \t" + startsNewArea() +
- "\nIs Last Area: \t" + isLastArea() +
- "\nTry Hyphenate: \t" + tryHyphenate() +
- "\nKeeps: \t[" + (isKeepWithNextPending() ? "keep-with-next" : "") + "]["
- + (isKeepWithPreviousPending() ? "keep-with-previous" : "") + "] pending" +
- "\nBreaks: \tforced [" + (breakBefore != Constants.EN_AUTO ? "break-before" : "") + "]["
+ return "Layout Context:"
+ + "\nStack Limit BPD: \t"
+ + (getStackLimitBP() == null ? "null" : getStackLimitBP().toString())
+ + "\nStack Limit IPD: \t"
+ + (getStackLimitIP() == null ? "null" : getStackLimitIP().toString())
+ + "\nTrailing Space: \t"
+ + (getTrailingSpace() == null ? "null" : getTrailingSpace().toString())
+ + "\nLeading Space: \t"
+ + (getLeadingSpace() == null ? "null" : getLeadingSpace().toString())
+ + "\nReference IPD: \t" + getRefIPD()
+ + "\nSpace Adjust: \t" + getSpaceAdjust()
+ + "\nIPD Adjust: \t" + getIPDAdjust()
+ + "\nResolve Leading Space: \t" + resolveLeadingSpace()
+ + "\nSuppress Leading Space: \t" + suppressLeadingSpace()
+ + "\nIs First Area: \t" + isFirstArea()
+ + "\nStarts New Area: \t" + startsNewArea()
+ + "\nIs Last Area: \t" + isLastArea()
+ + "\nTry Hyphenate: \t" + tryHyphenate()
+ + "\nKeeps: \t[" + (isKeepWithNextPending() ? "keep-with-next" : "") + "]["
+ + (isKeepWithPreviousPending() ? "keep-with-previous" : "") + "] pending"
+ + "\nBreaks: \tforced [" + (breakBefore != Constants.EN_AUTO ? "break-before" : "") + "]["
+ (breakAfter != Constants.EN_AUTO ? "break-after" : "") + "]";
}
diff --git a/src/java/org/apache/fop/layoutmgr/MinOptMaxUtil.java b/src/java/org/apache/fop/layoutmgr/MinOptMaxUtil.java
index ff9bdb1d9..b58af1cfe 100644
--- a/src/java/org/apache/fop/layoutmgr/MinOptMaxUtil.java
+++ b/src/java/org/apache/fop/layoutmgr/MinOptMaxUtil.java
@@ -68,19 +68,16 @@ public class MinOptMaxUtil {
}
/**
- * Extend the minimum length to the given length.
+ * Extends the minimum length to the given length if necessary, and adjusts opt and
+ * max accordingly.
+ *
* @param mom the min/opt/max trait
* @param len the new minimum length
- * @param optToLen if set adjusts the optimum length to be the smaller of the
- * minimum length and the given length
*/
- public static void extendMinimum(MinOptMax mom, int len, boolean optToLen) {
+ public static void extendMinimum(MinOptMax mom, int len) {
if (mom.min < len) {
mom.min = len;
mom.opt = Math.max(mom.min, mom.opt);
- if (optToLen) {
- mom.opt = Math.min(mom.min, len);
- }
mom.max = Math.max(mom.opt, mom.max);
}
}
@@ -111,7 +108,7 @@ public class MinOptMaxUtil {
? 0 : prop.getMinimum(context).getLength().getValue(context)),
(prop.getOptimum(context).isAuto()
? 0 : prop.getOptimum(context).getLength().getValue(context)),
- (prop.getMinimum(context).isAuto()
+ (prop.getMaximum(context).isAuto()
? Integer.MAX_VALUE
: prop.getMaximum(context).getLength().getValue(context)));
return mom;
diff --git a/src/java/org/apache/fop/layoutmgr/PageBreaker.java b/src/java/org/apache/fop/layoutmgr/PageBreaker.java
index cf830a7ec..3e100cd50 100644
--- a/src/java/org/apache/fop/layoutmgr/PageBreaker.java
+++ b/src/java/org/apache/fop/layoutmgr/PageBreaker.java
@@ -156,7 +156,7 @@ public class PageBreaker extends AbstractBreaker {
// element represents a line with footnote citations
bFootnotesPresent = true;
LayoutContext footnoteContext = new LayoutContext(context);
- footnoteContext.setStackLimit(context.getStackLimit());
+ footnoteContext.setStackLimitBP(context.getStackLimitBP());
footnoteContext.setRefIPD(pslm.getCurrentPV()
.getRegionReference(Constants.FO_REGION_BODY).getIPD());
LinkedList footnoteBodyLMs = ((KnuthBlockBox) element).getFootnoteBodyLMs();
diff --git a/src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java b/src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java
index 57fc4600e..d98d29b5c 100644
--- a/src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java
+++ b/src/java/org/apache/fop/layoutmgr/PageBreakingAlgorithm.java
@@ -364,7 +364,13 @@ class PageBreakingAlgorithm extends BreakingAlgorithm {
} else {
// there are no footnotes
}
- return getLineWidth(activeNode.line) - actualWidth;
+ int diff = getLineWidth(activeNode.line) - actualWidth;
+ if (autoHeight && diff < 0) {
+ //getLineWidth() for auto-height parts return 0 so the diff will be negative
+ return 0; //...but we don't want to shrink in this case. Stick to optimum.
+ } else {
+ return diff;
+ }
}
/** Checks whether footnotes from preceding pages may be deferred to the page after
diff --git a/src/java/org/apache/fop/layoutmgr/StaticContentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/StaticContentLayoutManager.java
index c8b89e6af..b1e414527 100644
--- a/src/java/org/apache/fop/layoutmgr/StaticContentLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/StaticContentLayoutManager.java
@@ -93,7 +93,7 @@ public class StaticContentLayoutManager extends BlockStackingLayoutManager {
//TODO Empty this method?!?
// set layout dimensions
setContentAreaIPD(context.getRefIPD());
- setContentAreaBPD(context.getStackLimit().opt);
+ setContentAreaBPD(context.getStackLimitBP().opt);
//TODO Copied from elsewhere. May be worthwhile to factor out the common parts.
// currently active LM
@@ -111,10 +111,10 @@ public class StaticContentLayoutManager extends BlockStackingLayoutManager {
}
// Set up a LayoutContext
- MinOptMax bpd = context.getStackLimit();
+ MinOptMax bpd = context.getStackLimitBP();
LayoutContext childLC = new LayoutContext(0);
- childLC.setStackLimit(MinOptMax.subtract(bpd, stackSize));
+ childLC.setStackLimitBP(MinOptMax.subtract(bpd, stackSize));
childLC.setRefIPD(context.getRefIPD());
// get elements from curLM
@@ -307,7 +307,7 @@ public class StaticContentLayoutManager extends BlockStackingLayoutManager {
while ((curLM = getChildLM()) != null) {
LayoutContext childLC = new LayoutContext(0);
- childLC.setStackLimit(context.getStackLimit());
+ childLC.setStackLimitBP(context.getStackLimitBP());
childLC.setRefIPD(context.getRefIPD());
childLC.setWritingMode(context.getWritingMode());
diff --git a/src/java/org/apache/fop/layoutmgr/TraitSetter.java b/src/java/org/apache/fop/layoutmgr/TraitSetter.java
index 841a94705..dfc8c99f2 100644
--- a/src/java/org/apache/fop/layoutmgr/TraitSetter.java
+++ b/src/java/org/apache/fop/layoutmgr/TraitSetter.java
@@ -29,6 +29,7 @@ import org.apache.fop.datatypes.SimplePercentBaseContext;
import org.apache.fop.fo.Constants;
import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
import org.apache.fop.fo.properties.CommonMarginBlock;
+import org.apache.fop.fo.properties.CommonMarginBlock;
import org.apache.fop.fo.properties.CommonTextDecoration;
import org.apache.fop.fo.properties.CommonBorderPaddingBackground.BorderInfo;
import org.apache.fop.fonts.Font;
@@ -281,6 +282,90 @@ public class TraitSetter {
}
/**
+ * Add background to an area. This method is mainly used by table-related layout
+ * managers to add background for column, body or row. Since the area corresponding to
+ * border-separation must be filled with the table's background, for every cell an
+ * additional area with the same dimensions is created to hold the background for the
+ * corresponding column/body/row. An additional shift must then be added to
+ * background-position-horizontal/vertical to ensure the background images are
+ * correctly placed. Indeed the placement of images must be made WRT the
+ * column/body/row and not the cell.
+ *
+ * <p>Note: The area's IPD and BPD must be set before calling this method.</p>
+ *
+ * <p>TODO the regular
+ * {@link #addBackground(Area, CommonBorderPaddingBackground, PercentBaseContext)}
+ * method should be used instead, and a means to retrieve the original area's
+ * dimensions must be found.</p>
+ *
+ * <p>TODO the placement of images in the x- or y-direction will be incorrect if
+ * background-repeat is set for that direction.</p>
+ *
+ * @param area the area to set the traits on
+ * @param backProps the background properties
+ * @param context Property evaluation context
+ * @param ipdShift horizontal shift to affect to the background, in addition to the
+ * value of the background-position-horizontal property
+ * @param bpdShift vertical shift to affect to the background, in addition to the
+ * value of the background-position-vertical property
+ * @param referenceIPD value to use as a reference for percentage calculation
+ * @param referenceBPD value to use as a reference for percentage calculation
+ */
+ public static void addBackground(Area area,
+ CommonBorderPaddingBackground backProps,
+ PercentBaseContext context,
+ int ipdShift, int bpdShift, int referenceIPD, int referenceBPD) {
+ if (!backProps.hasBackground()) {
+ return;
+ }
+ Trait.Background back = new Trait.Background();
+ back.setColor(backProps.backgroundColor);
+
+ if (backProps.getImageInfo() != null) {
+ back.setURL(backProps.backgroundImage);
+ back.setImageInfo(backProps.getImageInfo());
+ back.setRepeat(backProps.backgroundRepeat);
+ if (backProps.backgroundPositionHorizontal != null) {
+ if (back.getRepeat() == Constants.EN_NOREPEAT
+ || back.getRepeat() == Constants.EN_REPEATY) {
+ if (area.getIPD() > 0) {
+ PercentBaseContext refContext = new SimplePercentBaseContext(context,
+ LengthBase.IMAGE_BACKGROUND_POSITION_HORIZONTAL,
+ (referenceIPD - back.getImageInfo().getSize().getWidthMpt()));
+
+ back.setHoriz(ipdShift
+ + backProps.backgroundPositionHorizontal.getValue(refContext));
+ } else {
+ // TODO Area IPD has to be set for this to work
+ log.warn("Horizontal background image positioning ignored"
+ + " because the IPD was not set on the area."
+ + " (Yes, it's a bug in FOP)");
+ }
+ }
+ }
+ if (backProps.backgroundPositionVertical != null) {
+ if (back.getRepeat() == Constants.EN_NOREPEAT
+ || back.getRepeat() == Constants.EN_REPEATX) {
+ if (area.getBPD() > 0) {
+ PercentBaseContext refContext = new SimplePercentBaseContext(context,
+ LengthBase.IMAGE_BACKGROUND_POSITION_VERTICAL,
+ (referenceBPD - back.getImageInfo().getSize().getHeightMpt()));
+ back.setVertical(bpdShift
+ + backProps.backgroundPositionVertical.getValue(refContext));
+ } else {
+ // TODO Area BPD has to be set for this to work
+ log.warn("Vertical background image positioning ignored"
+ + " because the BPD was not set on the area."
+ + " (Yes, it's a bug in FOP)");
+ }
+ }
+ }
+ }
+
+ area.addTrait(Trait.BACKGROUND, back);
+ }
+
+ /**
* Add background to an area.
* Layout managers that create areas with a background can use this to
* add the background to the area.
@@ -312,7 +397,7 @@ public class TraitSetter {
back.setHoriz(backProps.backgroundPositionHorizontal.getValue(
new SimplePercentBaseContext(context,
LengthBase.IMAGE_BACKGROUND_POSITION_HORIZONTAL,
- (width - back.getImageInfo().getSize().getHeightMpt())
+ (width - back.getImageInfo().getSize().getWidthMpt())
)
));
} else {
diff --git a/src/java/org/apache/fop/layoutmgr/inline/AbstractGraphicsLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/AbstractGraphicsLayoutManager.java
index 6426f15db..38e0c35bc 100644
--- a/src/java/org/apache/fop/layoutmgr/inline/AbstractGraphicsLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/inline/AbstractGraphicsLayoutManager.java
@@ -124,13 +124,6 @@ public abstract class AbstractGraphicsLayoutManager extends LeafNodeLayoutManage
}
/**
- * {@inheritDoc}
- */
- protected void addId() {
- getPSLM().addIDToPage(fobj.getId());
- }
-
- /**
* Returns the image of foreign object area to be put into
* the viewport.
* @return the appropriate area
diff --git a/src/java/org/apache/fop/layoutmgr/inline/AbstractPageNumberCitationLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/AbstractPageNumberCitationLayoutManager.java
index 41d4af1c1..c92bdb6fc 100644
--- a/src/java/org/apache/fop/layoutmgr/inline/AbstractPageNumberCitationLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/inline/AbstractPageNumberCitationLayoutManager.java
@@ -51,7 +51,7 @@ public abstract class AbstractPageNumberCitationLayoutManager extends LeafNodeLa
* Constructor
*
* @param node the formatting object that creates this area
- * @todo better retrieval of font info
+ * TODO better retrieval of font info
*/
public AbstractPageNumberCitationLayoutManager(AbstractPageNumberCitation node) {
super(node);
@@ -83,7 +83,7 @@ public abstract class AbstractPageNumberCitationLayoutManager extends LeafNodeLa
/** {@inheritDoc} */
public InlineArea get(LayoutContext context) {
- curArea = getPageNumberCitationInlineArea(parentLM);
+ curArea = getPageNumberCitationInlineArea();
return curArea;
}
@@ -99,12 +99,15 @@ public abstract class AbstractPageNumberCitationLayoutManager extends LeafNodeLa
}
/**
- * if id can be resolved then simply return a word, otherwise
+ * If id can be resolved then simply return a word, otherwise
* return a resolvable area
+ *
+ * @param parentLM the parent LayoutManager
+ * @return a corresponding InlineArea
*/
- private InlineArea getPageNumberCitationInlineArea(LayoutManager parentLM) {
+ private InlineArea getPageNumberCitationInlineArea() {
PageViewport page = getPSLM().getFirstPVWithID(fobj.getRefId());
- TextArea text = null;
+ TextArea text;
if (page != null) {
String str = page.getPageNumberString();
// get page string from parent, build area
@@ -150,9 +153,5 @@ public abstract class AbstractPageNumberCitationLayoutManager extends LeafNodeLa
return width;
}
- /** {@inheritDoc} */
- protected void addId() {
- getPSLM().addIDToPage(fobj.getId());
- }
}
diff --git a/src/java/org/apache/fop/layoutmgr/inline/CharacterLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/CharacterLayoutManager.java
index 0430eef0c..b53e442d4 100644
--- a/src/java/org/apache/fop/layoutmgr/inline/CharacterLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/inline/CharacterLayoutManager.java
@@ -45,7 +45,6 @@ import org.apache.fop.util.CharUtilities;
* LayoutManager for the fo:character formatting object
*/
public class CharacterLayoutManager extends LeafNodeLayoutManager {
- private Character fobj;
private MinOptMax letterSpaceIPD;
private int hyphIPD;
private Font font;
@@ -57,13 +56,13 @@ public class CharacterLayoutManager extends LeafNodeLayoutManager {
* @param node the fo:character formatting object
*/
public CharacterLayoutManager(Character node) {
- // @todo better null checking of node
super(node);
- fobj = node;
}
/** {@inheritDoc} */
public void initialize() {
+ Character fobj = (Character)this.fobj;
+
FontInfo fi = fobj.getFOEventHandler().getFontInfo();
FontTriplet[] fontkeys = fobj.getCommonFont().getFontState(fi);
font = fi.getFontInstance(fontkeys[0], fobj.getCommonFont().fontSize.getValue(this));
@@ -90,7 +89,7 @@ public class CharacterLayoutManager extends LeafNodeLayoutManager {
text.addWord(String.valueOf(ch), 0);
}
TraitSetter.setProducerID(text, node.getId());
- TraitSetter.addTextDecoration(text, fobj.getTextDecoration());
+ TraitSetter.addTextDecoration(text, node.getTextDecoration());
return text;
}
@@ -105,6 +104,8 @@ public class CharacterLayoutManager extends LeafNodeLayoutManager {
return null;
}
+ Character fobj = (Character)this.fobj;
+
ipd = new MinOptMax(font.getCharWidth(fobj.getCharacter()));
curArea.setIPD(ipd.opt);
@@ -178,14 +179,7 @@ public class CharacterLayoutManager extends LeafNodeLayoutManager {
/** {@inheritDoc} */
public boolean applyChanges(List oldList) {
setFinished(false);
- if (isSomethingChanged) {
- // there is nothing to do,
- // possible changes have already been applied
- // in the hyphenate() method
- return true;
- } else {
- return false;
- }
+ return isSomethingChanged;
}
/** {@inheritDoc} */
@@ -238,10 +232,5 @@ public class CharacterLayoutManager extends LeafNodeLayoutManager {
return returnList;
}
- /** {@inheritDoc} */
- protected void addId() {
- getPSLM().addIDToPage(fobj.getId());
- }
-
}
diff --git a/src/java/org/apache/fop/layoutmgr/inline/ContentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/ContentLayoutManager.java
index 03e9b382a..ff7c5b3ce 100644
--- a/src/java/org/apache/fop/layoutmgr/inline/ContentLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/inline/ContentLayoutManager.java
@@ -19,9 +19,20 @@
package org.apache.fop.layoutmgr.inline;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.ListIterator;
+
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+
import org.apache.fop.apps.FOUserAgent;
+import org.apache.fop.area.Area;
+import org.apache.fop.area.Block;
+import org.apache.fop.area.LineArea;
+import org.apache.fop.area.inline.InlineArea;
import org.apache.fop.fo.Constants;
import org.apache.fop.fo.pagination.Title;
import org.apache.fop.layoutmgr.AbstractBaseLayoutManager;
@@ -34,19 +45,8 @@ import org.apache.fop.layoutmgr.PageSequenceLayoutManager;
import org.apache.fop.layoutmgr.Position;
import org.apache.fop.layoutmgr.PositionIterator;
import org.apache.fop.layoutmgr.SpaceSpecifier;
-import org.apache.fop.area.Area;
-import org.apache.fop.area.LineArea;
-import org.apache.fop.area.inline.InlineArea;
-
-import java.util.LinkedList;
-import java.util.List;
-import java.util.ListIterator;
-import java.util.ArrayList;
-import java.util.Iterator;
import org.apache.fop.traits.MinOptMax;
-import org.apache.fop.area.Block;
-
/**
* Content Layout Manager.
* For use with objects that contain inline areas such as
@@ -115,7 +115,7 @@ public class ContentLayoutManager extends AbstractBaseLayoutManager
childLC.setLeadingSpace(new SpaceSpecifier(false));
childLC.setTrailingSpace(new SpaceSpecifier(false));
// set stackLimit for lines
- childLC.setStackLimit(new MinOptMax(ipd));
+ childLC.setStackLimitIP(new MinOptMax(ipd));
childLC.setRefIPD(ipd);
int lineHeight = 14000;
diff --git a/src/java/org/apache/fop/layoutmgr/inline/ICLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/ICLayoutManager.java
index 4ffafb061..7ca9e0d5e 100644
--- a/src/java/org/apache/fop/layoutmgr/inline/ICLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/inline/ICLayoutManager.java
@@ -31,12 +31,10 @@ import org.apache.fop.fo.flow.InlineContainer;
* and id areas are maintained for later retrieval.
*/
public class ICLayoutManager extends LeafNodeLayoutManager {
- private InlineContainer fobj;
private List childrenLM;
public ICLayoutManager(InlineContainer node, List childLM) {
super(node);
- fobj = node;
childrenLM = childLM;
}
@@ -44,7 +42,4 @@ public class ICLayoutManager extends LeafNodeLayoutManager {
return null;
}
- protected void addId() {
- getPSLM().addIDToPage(fobj.getId());
- }
}
diff --git a/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java
index b449b6689..e9919e02f 100755
--- a/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java
@@ -19,12 +19,13 @@
package org.apache.fop.layoutmgr.inline;
-import java.util.ListIterator;
import java.util.LinkedList;
import java.util.List;
+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.inline.InlineArea;
import org.apache.fop.area.inline.InlineBlockParent;
@@ -47,12 +48,12 @@ import org.apache.fop.layoutmgr.InlineKnuthSequence;
import org.apache.fop.layoutmgr.KnuthBox;
import org.apache.fop.layoutmgr.KnuthSequence;
import org.apache.fop.layoutmgr.LayoutContext;
-import org.apache.fop.layoutmgr.NonLeafPosition;
-import org.apache.fop.layoutmgr.SpaceSpecifier;
-import org.apache.fop.layoutmgr.TraitSetter;
import org.apache.fop.layoutmgr.LayoutManager;
+import org.apache.fop.layoutmgr.NonLeafPosition;
import org.apache.fop.layoutmgr.Position;
import org.apache.fop.layoutmgr.PositionIterator;
+import org.apache.fop.layoutmgr.SpaceSpecifier;
+import org.apache.fop.layoutmgr.TraitSetter;
import org.apache.fop.traits.MinOptMax;
import org.apache.fop.traits.SpaceVal;
@@ -296,7 +297,7 @@ public class InlineLayoutManager extends InlineStackingLayoutManager {
);
}
- while ((curLM = (LayoutManager) getChildLM()) != null) {
+ while ((curLM = getChildLM()) != null) {
if (!(curLM instanceof InlineLevelLayoutManager)) {
// A block LM
@@ -435,7 +436,7 @@ public class InlineLayoutManager extends InlineStackingLayoutManager {
// layout context given to lastLM, but must be cleared in the
// layout context given to the other LMs.
LinkedList positionList = new LinkedList();
- NonLeafPosition pos = null;
+ NonLeafPosition pos;
LayoutManager lastLM = null;// last child LM in this iterator
Position lastPos = null;
while (parentIter.hasNext()) {
@@ -599,9 +600,4 @@ public class InlineLayoutManager extends InlineStackingLayoutManager {
return this.auxiliaryPosition;
}
- /** {@inheritDoc} */
- protected void addId() {
- getPSLM().addIDToPage(fobj.getId());
- }
-
}
diff --git a/src/java/org/apache/fop/layoutmgr/inline/InlineStackingLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/InlineStackingLayoutManager.java
index 4d0872a6d..bf1538a7c 100644
--- a/src/java/org/apache/fop/layoutmgr/inline/InlineStackingLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/inline/InlineStackingLayoutManager.java
@@ -75,15 +75,9 @@ public abstract class InlineStackingLayoutManager extends AbstractLayoutManager
private Area currentArea; // LineArea or InlineParent
- //private BreakPoss prevBP;
-
/** The child layout context */
protected LayoutContext childLC;
- private boolean bAreaCreated = false;
-
- //private LayoutManager currentLM = null;
-
/** Used to store previous content IPD for each child LM. */
private HashMap hmPrevIPD = new HashMap();
@@ -171,14 +165,6 @@ public abstract class InlineStackingLayoutManager extends AbstractLayoutManager
}
/**
- * This method is called by addAreas() so IDs can be added to a page for FOs that
- * support the 'id' property.
- */
- protected void addId() {
- // Do nothing here, overriden in subclasses that have an 'id' property.
- }
-
- /**
* Returns the current area.
* @return the current area
*/
@@ -255,7 +241,7 @@ public abstract class InlineStackingLayoutManager extends AbstractLayoutManager
// "unwrap" the Position stored in each element of oldList
while (oldListIterator.hasNext()) {
element = (KnuthElement) oldListIterator.next();
- element.setPosition(((NonLeafPosition)element.getPosition()).getPosition());
+ element.setPosition(element.getPosition().getPosition());
}
// The last element may not have a layout manager (its position == null);
@@ -288,7 +274,7 @@ public abstract class InlineStackingLayoutManager extends AbstractLayoutManager
// "unwrap" the Position stored in each element of oldList
while (oldListIterator.hasNext()) {
element = (KnuthElement) oldListIterator.next();
- element.setPosition(((NonLeafPosition)element.getPosition()).getPosition());
+ element.setPosition(element.getPosition().getPosition());
}
((InlineLevelLayoutManager)
@@ -298,14 +284,14 @@ public abstract class InlineStackingLayoutManager extends AbstractLayoutManager
/** {@inheritDoc} */
public void getWordChars(StringBuffer sbChars, Position pos) {
- Position newPos = ((NonLeafPosition) pos).getPosition();
+ Position newPos = pos.getPosition();
((InlineLevelLayoutManager)
newPos.getLM()).getWordChars(sbChars, newPos);
}
/** {@inheritDoc} */
public void hyphenate(Position pos, HyphContext hc) {
- Position newPos = ((NonLeafPosition) pos).getPosition();
+ Position newPos = pos.getPosition();
((InlineLevelLayoutManager)
newPos.getLM()).hyphenate(newPos, hc);
}
@@ -318,7 +304,7 @@ public abstract class InlineStackingLayoutManager extends AbstractLayoutManager
while (oldListIterator.hasNext()) {
oldElement = (KnuthElement) oldListIterator.next();
oldElement.setPosition
- (((NonLeafPosition) oldElement.getPosition()).getPosition());
+ (oldElement.getPosition().getPosition());
}
// reset the iterator
oldListIterator = oldList.listIterator();
@@ -385,7 +371,7 @@ public abstract class InlineStackingLayoutManager extends AbstractLayoutManager
while (oldListIterator.hasNext()) {
oldElement = (KnuthElement) oldListIterator.next();
oldElement.setPosition
- (((NonLeafPosition) oldElement.getPosition()).getPosition());
+ (oldElement.getPosition().getPosition());
}
// reset the iterator
oldListIterator = oldList.listIterator();
diff --git a/src/java/org/apache/fop/layoutmgr/inline/LeaderLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/LeaderLayoutManager.java
index 5f93ab98c..f4bcde96f 100644
--- a/src/java/org/apache/fop/layoutmgr/inline/LeaderLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/inline/LeaderLayoutManager.java
@@ -339,11 +339,6 @@ public class LeaderLayoutManager extends LeafNodeLayoutManager {
return returnList;
}
- /** {@inheritDoc} */
- protected void addId() {
- getPSLM().addIDToPage(fobj.getId());
- }
-
/**
* {@inheritDoc}
*/
diff --git a/src/java/org/apache/fop/layoutmgr/inline/LeafNodeLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/LeafNodeLayoutManager.java
index 78d126194..fb5e9ee4d 100644
--- a/src/java/org/apache/fop/layoutmgr/inline/LeafNodeLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/inline/LeafNodeLayoutManager.java
@@ -65,8 +65,6 @@ public abstract class LeafNodeLayoutManager extends AbstractLayoutManager
/** The alignment context applying to this area */
protected AlignmentContext alignmentContext = null;
- private MinOptMax ipd;
-
/** Flag to indicate if something was changed as part of the getChangeKnuthElements sequence */
protected boolean isSomethingChanged = false;
/** Our area info for the Knuth elements */
@@ -205,14 +203,6 @@ public abstract class LeafNodeLayoutManager extends AbstractLayoutManager
}
/**
- * This method is called by addAreas() so IDs can be added to a page for FOs that
- * support the 'id' property.
- */
- protected void addId() {
- // Do nothing here, overriden in subclasses that have an 'id' property.
- }
-
- /**
* Offset this area.
* Offset the inline area in the bpd direction when adding the
* inline area.
diff --git a/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java
index 6df7ac00c..9a818232c 100644
--- a/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.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.LineArea;
import org.apache.fop.area.Trait;
@@ -582,9 +583,6 @@ public class LineLayoutManager extends InlineStackingLayoutManager
// Get a break from currently active child LM
// Set up constraints for inline level managers
- // IPD remaining in line
- MinOptMax availIPD = context.getStackLimit();
-
clearPrevIPD();
//PHASE 1: Create Knuth elements
@@ -646,7 +644,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager
InlineLevelLayoutManager curLM;
LinkedList returnedList = null;
- iLineWidth = context.getStackLimit().opt;
+ iLineWidth = context.getStackLimitIP().opt;
// convert all the text in a sequence of paragraphs made
// of KnuthBox, KnuthGlue and KnuthPenalty objects
@@ -1687,7 +1685,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager
*/
if (false && textAlignment == EN_JUSTIFY) {
// re-compute space adjust ratio
- int updatedDifference = context.getStackLimit().opt
+ int updatedDifference = context.getStackLimitIP().opt
- lbp.lineWidth + lbp.difference;
double updatedRatio = 0.0;
if (updatedDifference > 0) {
@@ -1701,12 +1699,12 @@ public class LineLayoutManager extends InlineStackingLayoutManager
} else if (false && textAlignment == EN_CENTER) {
// re-compute indent
int updatedIndent = lbp.startIndent
- + (context.getStackLimit().opt - lbp.lineWidth) / 2;
+ + (context.getStackLimitIP().opt - lbp.lineWidth) / 2;
lineArea.addTrait(Trait.START_INDENT, new Integer(updatedIndent));
} else if (false && textAlignment == EN_END) {
// re-compute indent
int updatedIndent = lbp.startIndent
- + (context.getStackLimit().opt - lbp.lineWidth);
+ + (context.getStackLimitIP().opt - lbp.lineWidth);
lineArea.addTrait(Trait.START_INDENT, new Integer(updatedIndent));
}
@@ -1770,7 +1768,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager
// set last area flag
blocklc.setFlags(LayoutContext.LAST_AREA,
(context.isLastArea() && childLM == lastLM));
- blocklc.setStackLimit(context.getStackLimit());
+ blocklc.setStackLimitsFrom(context);
// Add the line areas to Area
childLM.addAreas(childPosIter, blocklc);
blocklc.setLeadingSpace(blocklc.getTrailingSpace());
diff --git a/src/java/org/apache/fop/layoutmgr/inline/PageNumberLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/PageNumberLayoutManager.java
index 88f1d283c..1aaaaf527 100644
--- a/src/java/org/apache/fop/layoutmgr/inline/PageNumberLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/inline/PageNumberLayoutManager.java
@@ -42,7 +42,7 @@ public class PageNumberLayoutManager extends LeafNodeLayoutManager {
* Constructor
*
* @param node the fo:page-number formatting object that creates the area
- * @todo better null checking of node, font
+ * TODO better null checking of node, font
*/
public PageNumberLayoutManager(PageNumber node) {
super(node);
@@ -131,9 +131,5 @@ public class PageNumberLayoutManager extends LeafNodeLayoutManager {
return width;
}
- /** {@inheritDoc} */
- protected void addId() {
- getPSLM().addIDToPage(fobj.getId());
- }
}
diff --git a/src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java b/src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java
index 470cbbe9c..c17ddc711 100644
--- a/src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java
@@ -19,29 +19,29 @@
package org.apache.fop.layoutmgr.list;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
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.ListBlock;
-import org.apache.fop.layoutmgr.BlockLevelLayoutManager;
import org.apache.fop.layoutmgr.BlockStackingLayoutManager;
import org.apache.fop.layoutmgr.ConditionalElementListener;
import org.apache.fop.layoutmgr.ElementListUtils;
-import org.apache.fop.layoutmgr.LayoutManager;
import org.apache.fop.layoutmgr.LayoutContext;
-import org.apache.fop.layoutmgr.PositionIterator;
-import org.apache.fop.layoutmgr.Position;
+import org.apache.fop.layoutmgr.LayoutManager;
import org.apache.fop.layoutmgr.NonLeafPosition;
+import org.apache.fop.layoutmgr.Position;
+import org.apache.fop.layoutmgr.PositionIterator;
import org.apache.fop.layoutmgr.RelSide;
import org.apache.fop.layoutmgr.TraitSetter;
-import org.apache.fop.area.Area;
-import org.apache.fop.area.Block;
import org.apache.fop.traits.MinOptMax;
import org.apache.fop.traits.SpaceVal;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-
/**
* LayoutManager for a list-block FO.
* A list block contains list items which are stacked within
@@ -156,11 +156,11 @@ public class ListBlockLayoutManager extends BlockStackingLayoutManager
addBlockSpacing(0.0, new MinOptMax(layoutContext.getSpaceBefore()));
}
- getPSLM().addIDToPage(getListBlockFO().getId());
+ addId();
// the list block contains areas stacked from each list item
- LayoutManager childLM = null;
+ LayoutManager childLM;
LayoutContext lc = new LayoutContext(0);
LayoutManager firstLM = null;
LayoutManager lastLM = null;
@@ -181,10 +181,10 @@ public class ListBlockLayoutManager extends BlockStackingLayoutManager
}
if (pos instanceof NonLeafPosition
&& (pos.getPosition() != null)
- && ((NonLeafPosition) pos).getPosition().getLM() != this) {
+ && pos.getPosition().getLM() != this) {
// pos was created by a child of this ListBlockLM
- positionList.add(((NonLeafPosition) pos).getPosition());
- lastLM = ((NonLeafPosition) pos).getPosition().getLM();
+ positionList.add(pos.getPosition());
+ lastLM = pos.getPosition().getLM();
if (firstLM == null) {
firstLM = lastLM;
}
@@ -200,7 +200,7 @@ public class ListBlockLayoutManager extends BlockStackingLayoutManager
lc.setSpaceAdjust(layoutContext.getSpaceAdjust());
lc.setFlags(LayoutContext.FIRST_AREA, childLM == firstLM);
lc.setFlags(LayoutContext.LAST_AREA, childLM == lastLM);
- lc.setStackLimit(layoutContext.getStackLimit());
+ lc.setStackLimitBP(layoutContext.getStackLimitBP());
childLM.addAreas(childPosIter, lc);
}
@@ -218,7 +218,7 @@ public class ListBlockLayoutManager extends BlockStackingLayoutManager
curBlockArea = null;
resetSpaces();
- getPSLM().notifyEndOfLayout(((ListBlock)getFObj()).getId());
+ getPSLM().notifyEndOfLayout(fobj.getId());
}
/**
@@ -280,7 +280,7 @@ public class ListBlockLayoutManager extends BlockStackingLayoutManager
/** {@inheritDoc} */
public boolean mustKeepTogether() {
//TODO Keeps will have to be more sophisticated sooner or later
- return ((BlockLevelLayoutManager)getParent()).mustKeepTogether()
+ return super.mustKeepTogether()
|| !getListBlockFO().getKeepTogether().getWithinPage().isAuto()
|| !getListBlockFO().getKeepTogether().getWithinColumn().isAuto();
}
diff --git a/src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java
index 853b1a128..8b0028a8f 100644
--- a/src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java
@@ -19,24 +19,24 @@
package org.apache.fop.layoutmgr.list;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.apache.fop.area.Area;
+import org.apache.fop.area.Block;
import org.apache.fop.fo.flow.AbstractListItemPart;
import org.apache.fop.fo.flow.ListItemBody;
import org.apache.fop.fo.flow.ListItemLabel;
import org.apache.fop.layoutmgr.BlockLevelLayoutManager;
import org.apache.fop.layoutmgr.BlockStackingLayoutManager;
-import org.apache.fop.layoutmgr.LayoutManager;
import org.apache.fop.layoutmgr.LayoutContext;
-import org.apache.fop.layoutmgr.PositionIterator;
-import org.apache.fop.layoutmgr.Position;
+import org.apache.fop.layoutmgr.LayoutManager;
import org.apache.fop.layoutmgr.NonLeafPosition;
+import org.apache.fop.layoutmgr.Position;
+import org.apache.fop.layoutmgr.PositionIterator;
import org.apache.fop.layoutmgr.TraitSetter;
import org.apache.fop.layoutmgr.SpaceResolver.SpaceHandlingBreakPosition;
-import org.apache.fop.area.Area;
-import org.apache.fop.area.Block;
-
-import java.util.Iterator;
-import java.util.List;
-import java.util.LinkedList;
/**
* LayoutManager for a list-item-label or list-item-body FO.
@@ -115,9 +115,9 @@ public class ListItemContentLayoutManager extends BlockStackingLayoutManager {
LayoutContext layoutContext) {
getParentArea(null);
- getPSLM().addIDToPage(getPartFO().getId());
+ addId();
- LayoutManager childLM = null;
+ LayoutManager childLM;
LayoutContext lc = new LayoutContext(0);
LayoutManager firstLM = null;
LayoutManager lastLM = null;
@@ -141,8 +141,8 @@ public class ListItemContentLayoutManager extends BlockStackingLayoutManager {
}
if (pos instanceof NonLeafPosition) {
// pos was created by a child of this ListBlockLM
- positionList.add(((NonLeafPosition) pos).getPosition());
- lastLM = ((NonLeafPosition) pos).getPosition().getLM();
+ positionList.add(pos.getPosition());
+ lastLM = pos.getPosition().getLM();
if (firstLM == null) {
firstLM = lastLM;
}
@@ -162,7 +162,7 @@ public class ListItemContentLayoutManager extends BlockStackingLayoutManager {
lc.setFlags(LayoutContext.LAST_AREA, childLM == lastLM);
// set the space adjustment ratio
lc.setSpaceAdjust(layoutContext.getSpaceAdjust());
- lc.setStackLimit(layoutContext.getStackLimit());
+ lc.setStackLimitBP(layoutContext.getStackLimitBP());
childLM.addAreas(childPosIter, lc);
}
@@ -172,7 +172,7 @@ public class ListItemContentLayoutManager extends BlockStackingLayoutManager {
curBlockArea = null;
- getPSLM().notifyEndOfLayout(((AbstractListItemPart)getFObj()).getId());
+ getPSLM().notifyEndOfLayout(fobj.getId());
}
/**
diff --git a/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java b/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java
index dc28e98e2..c6b5b8cf9 100644
--- a/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java
@@ -19,8 +19,16 @@
package org.apache.fop.layoutmgr.list;
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+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;
import org.apache.fop.fo.flow.ListItemBody;
import org.apache.fop.fo.flow.ListItemLabel;
@@ -30,28 +38,21 @@ import org.apache.fop.layoutmgr.BreakElement;
import org.apache.fop.layoutmgr.ConditionalElementListener;
import org.apache.fop.layoutmgr.ElementListObserver;
import org.apache.fop.layoutmgr.ElementListUtils;
-import org.apache.fop.layoutmgr.LayoutManager;
+import org.apache.fop.layoutmgr.KnuthBox;
+import org.apache.fop.layoutmgr.KnuthElement;
+import org.apache.fop.layoutmgr.KnuthPenalty;
+import org.apache.fop.layoutmgr.KnuthPossPosIter;
import org.apache.fop.layoutmgr.LayoutContext;
-import org.apache.fop.layoutmgr.PositionIterator;
-import org.apache.fop.layoutmgr.Position;
+import org.apache.fop.layoutmgr.LayoutManager;
import org.apache.fop.layoutmgr.NonLeafPosition;
+import org.apache.fop.layoutmgr.Position;
+import org.apache.fop.layoutmgr.PositionIterator;
import org.apache.fop.layoutmgr.RelSide;
import org.apache.fop.layoutmgr.SpaceResolver;
import org.apache.fop.layoutmgr.TraitSetter;
-import org.apache.fop.layoutmgr.KnuthElement;
-import org.apache.fop.layoutmgr.KnuthBox;
-import org.apache.fop.layoutmgr.KnuthPenalty;
-import org.apache.fop.layoutmgr.KnuthPossPosIter;
-import org.apache.fop.area.Area;
-import org.apache.fop.area.Block;
import org.apache.fop.traits.MinOptMax;
import org.apache.fop.traits.SpaceVal;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.LinkedList;
-import java.util.ListIterator;
-
/**
* LayoutManager for a list-item FO.
* The list item contains a list item label and a list item body.
@@ -72,8 +73,6 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager
private LinkedList labelList = null;
private LinkedList bodyList = null;
- private int listItemHeight;
-
private boolean discardBorderBefore;
private boolean discardBorderAfter;
private boolean discardPaddingBefore;
@@ -83,7 +82,9 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager
private boolean keepWithNextPendingOnLabel;
private boolean keepWithNextPendingOnBody;
-
+
+ private int listItemHeight;
+
private class ListItemPosition extends Position {
private int iLabelFirstIndex;
private int iLabelLastIndex;
@@ -116,6 +117,11 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager
}
/** {@inheritDoc} */
+ public boolean generatesAreas() {
+ return true;
+ }
+
+ /** {@inheritDoc} */
public String toString() {
StringBuffer sb = new StringBuffer("ListItemPosition:");
sb.append(getIndex()).append("(");
@@ -301,12 +307,12 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager
int additionalPenaltyHeight = 0;
KnuthElement endEl = (KnuthElement)elementLists[0].get(end[0]);
if (endEl instanceof KnuthPenalty) {
- additionalPenaltyHeight = ((KnuthPenalty)endEl).getW();
+ additionalPenaltyHeight = endEl.getW();
}
endEl = (KnuthElement)elementLists[1].get(end[1]);
if (endEl instanceof KnuthPenalty) {
additionalPenaltyHeight = Math.max(
- additionalPenaltyHeight, ((KnuthPenalty)endEl).getW());
+ additionalPenaltyHeight, endEl.getW());
}
int boxHeight = step - addedBoxHeight - penaltyHeight;
@@ -413,10 +419,10 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager
// body
// "unwrap" the Positions stored in the elements
ListIterator oldListIterator = oldList.listIterator();
- KnuthElement oldElement = null;
+ KnuthElement oldElement;
while (oldListIterator.hasNext()) {
oldElement = (KnuthElement)oldListIterator.next();
- Position innerPosition = ((NonLeafPosition) oldElement.getPosition()).getPosition();
+ Position innerPosition = oldElement.getPosition().getPosition();
//log.debug(" BLM> unwrapping: " + (oldElement.isBox()
// ? "box " : (oldElement.isGlue() ? "glue " : "penalty"))
// + " creato da " + oldElement.getLayoutManager().getClass().getName());
@@ -459,7 +465,7 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager
LayoutContext layoutContext) {
getParentArea(null);
- getPSLM().addIDToPage(getListItemFO().getId());
+ addId();
LayoutContext lc = new LayoutContext(0);
Position firstPos = null;
@@ -478,7 +484,7 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager
}
if (pos instanceof NonLeafPosition && pos.getPosition() != null) {
// pos contains a ListItemPosition created by this ListBlockLM
- positionList.add(((NonLeafPosition) pos).getPosition());
+ positionList.add(pos.getPosition());
}
}
@@ -510,7 +516,7 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager
// set the space adjustment ratio
lc.setSpaceAdjust(layoutContext.getSpaceAdjust());
// TO DO: use the right stack limit for the label
- lc.setStackLimit(layoutContext.getStackLimit());
+ lc.setStackLimitBP(layoutContext.getStackLimitBP());
label.addAreas(labelIter, lc);
}
@@ -531,7 +537,7 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager
// set the space adjustment ratio
lc.setSpaceAdjust(layoutContext.getSpaceAdjust());
// TO DO: use the right stack limit for the body
- lc.setStackLimit(layoutContext.getStackLimit());
+ lc.setStackLimitBP(layoutContext.getStackLimitBP());
body.addAreas(bodyIter, lc);
}
@@ -554,7 +560,7 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager
curBlockArea = null;
resetSpaces();
- getPSLM().notifyEndOfLayout(((ListItem)getFObj()).getId());
+ getPSLM().notifyEndOfLayout(fobj.getId());
}
/**
diff --git a/src/java/org/apache/fop/layoutmgr/table/ActiveCell.java b/src/java/org/apache/fop/layoutmgr/table/ActiveCell.java
index c1e4ae619..61d0f8e6f 100644
--- a/src/java/org/apache/fop/layoutmgr/table/ActiveCell.java
+++ b/src/java/org/apache/fop/layoutmgr/table/ActiveCell.java
@@ -33,6 +33,8 @@ import org.apache.fop.layoutmgr.ElementListUtils;
import org.apache.fop.layoutmgr.KnuthBox;
import org.apache.fop.layoutmgr.KnuthElement;
import org.apache.fop.layoutmgr.KnuthPenalty;
+import org.apache.fop.layoutmgr.MinOptMaxUtil;
+import org.apache.fop.traits.MinOptMax;
/**
* A cell playing in the construction of steps for a row-group.
@@ -133,6 +135,49 @@ class ActiveCell {
}
}
+ // TODO to be removed along with the RowPainter#computeContentLength method
+ /** See {@link ActiveCell#handleExplicitHeight(MinOptMax, MinOptMax)}. */
+ private static class FillerPenalty extends KnuthPenalty {
+
+ private int contentLength;
+
+ FillerPenalty(KnuthPenalty p, int length) {
+ super(length, p.getP(), p.isFlagged(), p.getBreakClass(),
+ p.getPosition(), p.isAuxiliary());
+ contentLength = p.getW();
+ }
+
+ FillerPenalty(int length) {
+ super(length, 0, false, null, true);
+ contentLength = 0;
+ }
+ }
+
+ /** See {@link ActiveCell#handleExplicitHeight(MinOptMax, MinOptMax)}. */
+ private static class FillerBox extends KnuthBox {
+ FillerBox(int length) {
+ super(length, null, true);
+ }
+ }
+
+ /**
+ * Returns the actual length of the content represented by the given element. In the
+ * case where this element is used as a filler to match a row's fixed height, the
+ * value returned by the getW() method will be higher than the actual content.
+ *
+ * @param el an element
+ * @return the actual content length corresponding to the element
+ */
+ static int getElementContentLength(KnuthElement el) {
+ if (el instanceof FillerPenalty) {
+ return ((FillerPenalty) el).contentLength;
+ } else if (el instanceof FillerBox) {
+ return 0;
+ } else {
+ return el.getW();
+ }
+ }
+
ActiveCell(PrimaryGridUnit pgu, EffRow row, int rowIndex, int previousRowsLength,
TableLayoutManager tableLM) {
this.pgu = pgu;
@@ -149,23 +194,10 @@ class ActiveCell {
+ pgu.getBeforeBorderWidth(0, ConditionalBorder.REST);
bpAfterNormal = paddingAfterNormal + pgu.getAfterBorderWidth(ConditionalBorder.NORMAL);
bpAfterTrailing = paddingAfterTrailing + pgu.getAfterBorderWidth(0, ConditionalBorder.REST);
- boolean makeBoxForWholeRow = false;
- if (row.getExplicitHeight().min > 0) {
- boolean contentsSmaller = ElementListUtils.removeLegalBreaks(
- pgu.getElements(), row.getExplicitHeight());
- if (contentsSmaller) {
- makeBoxForWholeRow = true;
- }
- }
- if (makeBoxForWholeRow) {
- elementList = new java.util.ArrayList(1);
- int height = row.getHeight().opt;
- height -= 2 * tableLM.getHalfBorderSeparationBPD();
- height -= bpBeforeNormal + bpAfterNormal;
- elementList.add(new KnuthBoxCellWithBPD(height));
- } else {
- elementList = pgu.getElements();
- }
+ elementList = pgu.getElements();
+ handleExplicitHeight(
+ MinOptMaxUtil.toMinOptMax(pgu.getCell().getBlockProgressionDimension(), tableLM),
+ row.getExplicitHeight());
knuthIter = elementList.listIterator();
includedLength = -1; // Avoid troubles with cells having content of zero length
totalLength = previousRowsLength + ElementListUtils.calcContentLength(elementList);
@@ -182,6 +214,46 @@ class ActiveCell {
}
}
+ /**
+ * Modifies the cell's element list by putting filler elements, so that the cell's or
+ * row's explicit height is always reached.
+ *
+ * TODO this will work properly only for the first break. Then the limitation
+ * explained on http://wiki.apache.org/xmlgraphics-fop/TableLayout/KnownProblems
+ * occurs. The list of elements needs to be re-adjusted after each break.
+ */
+ private void handleExplicitHeight(MinOptMax cellBPD, MinOptMax rowBPD) {
+ int minBPD = Math.max(cellBPD.min, rowBPD.min);
+ if (minBPD > 0) {
+ ListIterator iter = elementList.listIterator();
+ int cumulateLength = 0;
+ boolean prevIsBox = false;
+ while (iter.hasNext() && cumulateLength < minBPD) {
+ KnuthElement el = (KnuthElement) iter.next();
+ if (el.isBox()) {
+ prevIsBox = true;
+ cumulateLength += el.getW();
+ } else if (el.isGlue()) {
+ if (prevIsBox) {
+ elementList.add(iter.nextIndex() - 1,
+ new FillerPenalty(minBPD - cumulateLength));
+ }
+ prevIsBox = false;
+ cumulateLength += el.getW();
+ } else {
+ prevIsBox = false;
+ if (cumulateLength + el.getW() < minBPD) {
+ iter.set(new FillerPenalty((KnuthPenalty) el, minBPD - cumulateLength));
+ }
+ }
+ }
+ }
+ int optBPD = Math.max(minBPD, Math.max(cellBPD.opt, rowBPD.opt));
+ if (pgu.getContentLength() < optBPD) {
+ elementList.add(new FillerBox(optBPD - pgu.getContentLength()));
+ }
+ }
+
PrimaryGridUnit getPrimaryGridUnit() {
return pgu;
}
@@ -265,14 +337,22 @@ class ActiveCell {
}
/**
- * Returns the last step for this cell.
+ * Returns the last step for this cell. This includes the normal border- and
+ * padding-before, the whole content, the normal padding-after, and the
+ * <em>trailing</em> after border. Indeed, if the normal border is taken instead,
+ * and appears to be smaller than the trailing one, the last step may be smaller than
+ * the current step (see TableStepper#considerRowLastStep). This will produce a wrong
+ * infinite penalty, plus the cell's content won't be taken into account since the
+ * final step will be smaller than the current one (see {@link #signalNextStep(int)}).
+ * This actually means that the content will be swallowed.
*
- * @return the step including all of the cell's content plus the normal borders and paddings
+ * @return the length of last step
*/
int getLastStep() {
assert nextStep.end == elementList.size() - 1;
assert nextStep.contentLength == totalLength && nextStep.penaltyLength == 0;
- int lastStep = bpBeforeNormal + totalLength + bpAfterNormal;
+ int lastStep = bpBeforeNormal + totalLength + paddingAfterNormal
+ + pgu.getAfterBorderWidth(ConditionalBorder.LEADING_TRAILING);
log.debug(this + ": last step = " + lastStep);
return lastStep;
}
@@ -394,8 +474,12 @@ class ActiveCell {
*/
void endRow(int rowIndex) {
if (endsOnRow(rowIndex)) {
+ // Subtract the old value of bpAfterTrailing...
+ nextStep.totalLength -= bpAfterTrailing;
bpAfterTrailing = paddingAfterNormal
+ pgu.getAfterBorderWidth(ConditionalBorder.LEADING_TRAILING);
+ // ... and add the new one
+ nextStep.totalLength += bpAfterTrailing;
lastCellPart = true;
} else {
bpBeforeLeading = paddingBeforeLeading
@@ -445,13 +529,6 @@ class ActiveCell {
return new CellPart(pgu, nextStep.start, previousStep.end, lastCellPart,
0, 0, previousStep.penaltyLength,
bpBeforeNormal, bpBeforeFirst, bpAfterNormal, bpAfterTrailing);
- } else if (nextStep.start == 0 && nextStep.end == 0
- && elementList.size() == 1
- && elementList.get(0) instanceof KnuthBoxCellWithBPD) {
- //Special case: Cell with fixed BPD
- return new CellPart(pgu, 0, pgu.getElements().size() - 1, lastCellPart,
- nextStep.condBeforeContentLength, length, nextStep.penaltyLength,
- bpBeforeNormal, bpBeforeFirst, bpAfterNormal, bpAfterTrailing);
} else {
return new CellPart(pgu, nextStep.start, nextStep.end, lastCellPart,
nextStep.condBeforeContentLength, length, nextStep.penaltyLength,
@@ -463,20 +540,9 @@ class ActiveCell {
return keepWithNextSignal;
}
-
+
/** {@inheritDoc} */
public String toString() {
return "Cell " + (pgu.getRowIndex() + 1) + "." + (pgu.getColIndex() + 1);
}
-
-
- /**
- * Marker class denoting table cells fitting in just one box (no legal break inside).
- */
- private static class KnuthBoxCellWithBPD extends KnuthBox {
-
- public KnuthBoxCellWithBPD(int w) {
- super(w, null, true);
- }
- }
}
diff --git a/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java
index c2e26e18d..9c97ca827 100644
--- a/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java
@@ -19,16 +19,16 @@
package org.apache.fop.layoutmgr.table;
+import java.util.Iterator;
import java.util.LinkedList;
-import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.fop.fo.Constants;
-import org.apache.fop.fo.FONode;
import org.apache.fop.fo.flow.table.EffRow;
import org.apache.fop.fo.flow.table.GridUnit;
import org.apache.fop.fo.flow.table.PrimaryGridUnit;
+import org.apache.fop.fo.flow.table.TableColumn;
import org.apache.fop.fo.flow.table.TableRow;
import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
import org.apache.fop.fo.properties.LengthRangeProperty;
@@ -94,137 +94,119 @@ class RowGroupLayoutManager {
private void createElementsForRowGroup(LayoutContext context, int alignment,
int bodyType, LinkedList returnList) {
log.debug("Handling row group with " + rowGroup.length + " rows...");
+ EffRow row;
+ for (int rgi = 0; rgi < rowGroup.length; rgi++) {
+ row = rowGroup[rgi];
+ for (Iterator iter = row.getGridUnits().iterator(); iter.hasNext();) {
+ GridUnit gu = (GridUnit) iter.next();
+ if (gu.isPrimary()) {
+ PrimaryGridUnit primary = gu.getPrimary();
+ // TODO a new LM must be created for every new static-content
+ primary.createCellLM();
+ primary.getCellLM().setParent(tableLM);
+ //Calculate width of cell
+ int spanWidth = 0;
+ Iterator colIter = tableLM.getTable().getColumns().listIterator(
+ primary.getColIndex());
+ for (int i = 0, c = primary.getCell().getNumberColumnsSpanned(); i < c; i++) {
+ spanWidth += ((TableColumn) colIter.next()).getColumnWidth().getValue(
+ tableLM);
+ }
+ LayoutContext childLC = new LayoutContext(0);
+ childLC.setStackLimitBP(context.getStackLimitBP()); //necessary?
+ childLC.setRefIPD(spanWidth);
+
+ //Get the element list for the cell contents
+ LinkedList elems = primary.getCellLM().getNextKnuthElements(
+ childLC, alignment);
+ ElementListObserver.observe(elems, "table-cell", primary.getCell().getId());
+ primary.setElements(elems);
+ }
+ }
+ }
+ computeRowHeights();
+ LinkedList elements = tableStepper.getCombinedKnuthElementsForRowGroup(context,
+ rowGroup, bodyType);
+ returnList.addAll(elements);
+ }
+
+ /**
+ * Calculate the heights of the rows in the row group, see CSS21, 17.5.3 Table height
+ * algorithms.
+ *
+ * TODO this method will need to be adapted once clarification has been made by the
+ * W3C regarding whether borders or border-separation must be included or not
+ */
+ private void computeRowHeights() {
+ log.debug("rowGroup:");
MinOptMax[] rowHeights = new MinOptMax[rowGroup.length];
- MinOptMax[] explicitRowHeights = new MinOptMax[rowGroup.length];
EffRow row;
- List pgus = new java.util.ArrayList(); //holds a list of a row's primary grid units
for (int rgi = 0; rgi < rowGroup.length; rgi++) {
row = rowGroup[rgi];
- rowHeights[rgi] = new MinOptMax(0, 0, Integer.MAX_VALUE);
- explicitRowHeights[rgi] = new MinOptMax(0, 0, Integer.MAX_VALUE);
-
- pgus.clear();
- TableRow tableRow = null;
- // The row's minimum content height; 0 if the row's height is auto, otherwise
- // the .minimum component of the explicitly specified value
- int minRowBPD = 0;
// The BPD of the biggest cell in the row
- int maxCellBPD = 0;
- for (int j = 0; j < row.getGridUnits().size(); j++) {
- GridUnit gu = row.getGridUnit(j);
- if ((gu.isPrimary() || (gu.getColSpanIndex() == 0 && gu.isLastGridUnitRowSpan()))
- && !gu.isEmpty()) {
+// int maxCellBPD = 0;
+ MinOptMax explicitRowHeight;
+ TableRow tableRowFO = rowGroup[rgi].getTableRow();
+ if (tableRowFO == null) {
+ rowHeights[rgi] = new MinOptMax(0, 0, Integer.MAX_VALUE);
+ explicitRowHeight = new MinOptMax(0, 0, Integer.MAX_VALUE);
+ } else {
+ LengthRangeProperty rowBPD = tableRowFO.getBlockProgressionDimension();
+ rowHeights[rgi] = MinOptMaxUtil.toMinOptMax(rowBPD, tableLM);
+ explicitRowHeight = MinOptMaxUtil.toMinOptMax(rowBPD, tableLM);
+ }
+ for (Iterator iter = row.getGridUnits().iterator(); iter.hasNext();) {
+ GridUnit gu = (GridUnit) iter.next();
+ if (!gu.isEmpty() && gu.getColSpanIndex() == 0 && gu.isLastGridUnitRowSpan()) {
PrimaryGridUnit primary = gu.getPrimary();
-
- if (gu.isPrimary()) {
- // TODO a new LM must be created for every new static-content
- primary.createCellLM();
- primary.getCellLM().setParent(tableLM);
-
- //Determine the table-row if any
- if (tableRow == null && primary.getRow() != null) {
- tableRow = primary.getRow();
-
- //Check for bpd on row, see CSS21, 17.5.3 Table height algorithms
- LengthRangeProperty rowBPD = tableRow.getBlockProgressionDimension();
- if (!rowBPD.getMinimum(tableLM).isAuto()) {
- minRowBPD = Math.max(minRowBPD,
- rowBPD.getMinimum(tableLM).getLength().getValue(tableLM));
- }
- MinOptMaxUtil.restrict(explicitRowHeights[rgi], rowBPD, tableLM);
-
- }
-
- //Calculate width of cell
- int spanWidth = 0;
- for (int i = primary.getColIndex();
- i < primary.getColIndex()
- + primary.getCell().getNumberColumnsSpanned();
- i++) {
- if (tableLM.getColumns().getColumn(i + 1) != null) {
- spanWidth += tableLM.getColumns().getColumn(i + 1)
- .getColumnWidth().getValue(tableLM);
- }
- }
- LayoutContext childLC = new LayoutContext(0);
- childLC.setStackLimit(context.getStackLimit()); //necessary?
- childLC.setRefIPD(spanWidth);
-
- //Get the element list for the cell contents
- LinkedList elems = primary.getCellLM().getNextKnuthElements(
- childLC, alignment);
- ElementListObserver.observe(elems, "table-cell", primary.getCell().getId());
- primary.setElements(elems);
+ int effectiveCellBPD = 0;
+ LengthRangeProperty cellBPD = primary.getCell().getBlockProgressionDimension();
+ if (!cellBPD.getMinimum(tableLM).isAuto()) {
+ effectiveCellBPD = cellBPD.getMinimum(tableLM).getLength()
+ .getValue(tableLM);
}
-
- //Calculate height of row, see CSS21, 17.5.3 Table height algorithms
- if (gu.isLastGridUnitRowSpan()) {
- // The effective cell's bpd, after taking into account bpd
- // (possibly explicitly) set on the row or on the cell, and the
- // cell's content length
- int effectiveCellBPD = minRowBPD;
- LengthRangeProperty cellBPD = primary.getCell()
- .getBlockProgressionDimension();
- if (!cellBPD.getMinimum(tableLM).isAuto()) {
- effectiveCellBPD = Math.max(effectiveCellBPD,
- cellBPD.getMinimum(tableLM).getLength().getValue(tableLM));
- }
- if (!cellBPD.getOptimum(tableLM).isAuto()) {
- effectiveCellBPD = Math.max(effectiveCellBPD,
- cellBPD.getOptimum(tableLM).getLength().getValue(tableLM));
- }
- if (gu.getRowSpanIndex() == 0) {
- //TODO ATM only non-row-spanned cells are taken for this
- MinOptMaxUtil.restrict(explicitRowHeights[rgi], cellBPD, tableLM);
- }
- effectiveCellBPD = Math.max(effectiveCellBPD,
- primary.getContentLength());
-
- int borderWidths = primary.getBeforeAfterBorderWidth();
- int padding = 0;
- maxCellBPD = Math.max(maxCellBPD, effectiveCellBPD);
- CommonBorderPaddingBackground cbpb
- = primary.getCell().getCommonBorderPaddingBackground();
- padding += cbpb.getPaddingBefore(false, primary.getCellLM());
- padding += cbpb.getPaddingAfter(false, primary.getCellLM());
- int effRowHeight = effectiveCellBPD
- + padding + borderWidths;
- for (int previous = 0; previous < gu.getRowSpanIndex(); previous++) {
- effRowHeight -= rowHeights[rgi - previous - 1].opt;
- }
- if (effRowHeight > rowHeights[rgi].min) {
- //This is the new height of the (grid) row
- MinOptMaxUtil.extendMinimum(rowHeights[rgi], effRowHeight, false);
- }
+ if (!cellBPD.getOptimum(tableLM).isAuto()) {
+ effectiveCellBPD = cellBPD.getOptimum(tableLM).getLength()
+ .getValue(tableLM);
}
-
- if (gu.isPrimary()) {
- pgus.add(primary);
+ if (gu.getRowSpanIndex() == 0) {
+ effectiveCellBPD = Math.max(effectiveCellBPD, explicitRowHeight.opt);
+ }
+ effectiveCellBPD = Math.max(effectiveCellBPD, primary.getContentLength());
+ int borderWidths = primary.getBeforeAfterBorderWidth();
+ int padding = 0;
+ CommonBorderPaddingBackground cbpb = primary.getCell()
+ .getCommonBorderPaddingBackground();
+ padding += cbpb.getPaddingBefore(false, primary.getCellLM());
+ padding += cbpb.getPaddingAfter(false, primary.getCellLM());
+ int effRowHeight = effectiveCellBPD + padding + borderWidths;
+ for (int prev = rgi - 1; prev >= rgi - gu.getRowSpanIndex(); prev--) {
+ effRowHeight -= rowHeights[prev].opt;
+ }
+ if (effRowHeight > rowHeights[rgi].min) {
+ // This is the new height of the (grid) row
+ MinOptMaxUtil.extendMinimum(rowHeights[rgi], effRowHeight);
}
}
}
row.setHeight(rowHeights[rgi]);
- row.setExplicitHeight(explicitRowHeights[rgi]);
- if (maxCellBPD > row.getExplicitHeight().max) {
- log.warn(FONode.decorateWithContextInfo(
- "The contents of row " + (row.getIndex() + 1)
- + " are taller than they should be (there is a"
- + " block-progression-dimension or height constraint on the indicated row)."
- + " Due to its contents the row grows"
- + " to " + maxCellBPD + " millipoints, but the row shouldn't get"
- + " any taller than " + row.getExplicitHeight() + " millipoints.",
- row.getTableRow()));
- }
- }
- if (log.isDebugEnabled()) {
- log.debug("rowGroup:");
- for (int i = 0; i < rowHeights.length; i++) {
- log.debug(" height=" + rowHeights[i] + " explicit=" + explicitRowHeights[i]);
+ row.setExplicitHeight(explicitRowHeight);
+ // TODO re-enable and improve after clarification
+// if (maxCellBPD > row.getExplicitHeight().max) {
+// log.warn(FONode.decorateWithContextInfo(
+// "The contents of row " + (row.getIndex() + 1)
+// + " are taller than they should be (there is a"
+// + " block-progression-dimension or height constraint
+// + " on the indicated row)."
+// + " Due to its contents the row grows"
+// + " to " + maxCellBPD + " millipoints, but the row shouldn't get"
+// + " any taller than " + row.getExplicitHeight() + " millipoints.",
+// row.getTableRow()));
+// }
+ if (log.isDebugEnabled()) {
+ log.debug(" height=" + rowHeights[rgi] + " explicit=" + explicitRowHeight);
}
}
- LinkedList elements = tableStepper.getCombinedKnuthElementsForRowGroup(context,
- rowGroup, bodyType);
- returnList.addAll(elements);
}
}
diff --git a/src/java/org/apache/fop/layoutmgr/table/RowPainter.java b/src/java/org/apache/fop/layoutmgr/table/RowPainter.java
index 022ff0589..bed9c53ae 100644
--- a/src/java/org/apache/fop/layoutmgr/table/RowPainter.java
+++ b/src/java/org/apache/fop/layoutmgr/table/RowPainter.java
@@ -23,25 +23,27 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
+import java.util.ListIterator;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.apache.fop.area.Block;
import org.apache.fop.fo.flow.table.ConditionalBorder;
import org.apache.fop.fo.flow.table.EffRow;
import org.apache.fop.fo.flow.table.GridUnit;
import org.apache.fop.fo.flow.table.PrimaryGridUnit;
-import org.apache.fop.fo.flow.table.TableRow;
+import org.apache.fop.fo.flow.table.TableBody;
+import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
import org.apache.fop.layoutmgr.ElementListUtils;
import org.apache.fop.layoutmgr.KnuthElement;
import org.apache.fop.layoutmgr.KnuthPossPosIter;
import org.apache.fop.layoutmgr.LayoutContext;
import org.apache.fop.layoutmgr.SpaceResolver;
+import org.apache.fop.layoutmgr.TraitSetter;
import org.apache.fop.traits.BorderProps;
class RowPainter {
private static Log log = LogFactory.getLog(RowPainter.class);
- /** The fo:table-row containing the currently handled grid rows. */
- private TableRow rowFO = null;
private int colCount;
private int currentRowOffset = 0;
/** Currently handled row (= last encountered row). */
@@ -71,6 +73,13 @@ class RowPainter {
private CellPart[] firstCellParts;
private CellPart[] lastCellParts;
+ /** y-offset of the current table part. */
+ private int tablePartOffset = 0;
+ /** See {@link RowPainter#registerPartBackgroundArea(Block)}. */
+ private CommonBorderPaddingBackground tablePartBackground;
+ /** See {@link RowPainter#registerPartBackgroundArea(Block)}. */
+ private List tablePartBackgroundAreas;
+
private TableContentLayoutManager tclm;
RowPainter(TableContentLayoutManager tclm, LayoutContext layoutContext) {
@@ -85,6 +94,44 @@ class RowPainter {
this.firstRowOnPageIndex = -1;
}
+ void startTablePart(TableBody tablePart) {
+ CommonBorderPaddingBackground background = tablePart.getCommonBorderPaddingBackground();
+ if (background.hasBackground()) {
+ tablePartBackground = background;
+ if (tablePartBackgroundAreas == null) {
+ tablePartBackgroundAreas = new ArrayList();
+ }
+ }
+ tablePartOffset = currentRowOffset;
+ }
+
+ /**
+ * Signals that the end of the current table part is reached.
+ *
+ * @param lastInBody true if the part is the last table-body element to be displayed
+ * on the current page. In which case all the cells must be flushed even if they
+ * aren't finished, plus the proper collapsed borders must be selected (trailing
+ * instead of normal, or rest if the cell is unfinished)
+ * @param lastOnPage true if the part is the last to be displayed on the current page.
+ * In which case collapsed after borders for the cells on the last row must be drawn
+ * in the outer mode
+ */
+ void endTablePart(boolean lastInBody, boolean lastOnPage) {
+ addAreasAndFlushRow(lastInBody, lastOnPage);
+
+ if (tablePartBackground != null) {
+ TableLayoutManager tableLM = tclm.getTableLM();
+ for (Iterator iter = tablePartBackgroundAreas.iterator(); iter.hasNext();) {
+ Block backgroundArea = (Block) iter.next();
+ TraitSetter.addBackground(backgroundArea, tablePartBackground, tableLM,
+ -backgroundArea.getXOffset(), tablePartOffset - backgroundArea.getYOffset(),
+ tableLM.getContentAreaIPD(), currentRowOffset - tablePartOffset);
+ }
+ tablePartBackground = null;
+ tablePartBackgroundAreas.clear();
+ }
+ }
+
int getAccumulatedBPD() {
return currentRowOffset;
}
@@ -108,7 +155,6 @@ class RowPainter {
currentRow = row;
}
}
- rowFO = currentRow.getTableRow();
if (firstRowIndex < 0) {
firstRowIndex = currentRow.getIndex();
if (firstRowOnPageIndex < 0) {
@@ -148,7 +194,7 @@ class RowPainter {
* displayed on the current page. In which case collapsed after borders must be drawn
* in the outer mode
*/
- void addAreasAndFlushRow(boolean lastInPart, boolean lastOnPage) {
+ private void addAreasAndFlushRow(boolean lastInPart, boolean lastOnPage) {
if (log.isDebugEnabled()) {
log.debug("Remembering yoffset for row " + currentRow.getIndex() + ": "
+ currentRowOffset);
@@ -182,8 +228,6 @@ class RowPainter {
}
// Then add areas for cells finishing on the current row
- tclm.addRowBackgroundArea(rowFO, actualRowHeight, layoutContext.getRefIPD(),
- currentRowOffset);
for (int i = 0; i < colCount; i++) {
GridUnit currentGU = currentRow.getGridUnit(i);
if (!currentGU.isEmpty() && currentGU.getColSpanIndex() == 0
@@ -255,18 +299,22 @@ class RowPainter {
// cell, in most cases)
return 0;
} else {
- int actualStart = startIndex;
+ ListIterator iter = pgu.getElements().listIterator(startIndex);
// Skip from the content length calculation glues and penalties occurring at the
// beginning of the page
- while (actualStart <= endIndex
- && !((KnuthElement) pgu.getElements().get(actualStart)).isBox()) {
- actualStart++;
+ boolean nextIsBox = false;
+ while (iter.nextIndex() <= endIndex && !nextIsBox) {
+ nextIsBox = ((KnuthElement) iter.next()).isBox();
}
- int len = ElementListUtils.calcContentLength(
- pgu.getElements(), actualStart, endIndex);
- KnuthElement el = (KnuthElement)pgu.getElements().get(endIndex);
- if (el.isPenalty()) {
- len += el.getW();
+ int len = 0;
+ if (((KnuthElement) iter.previous()).isBox()) {
+ while (iter.nextIndex() < endIndex) {
+ KnuthElement el = (KnuthElement) iter.next();
+ if (el.isBox() || el.isGlue()) {
+ len += el.getW();
+ }
+ }
+ len += ActiveCell.getElementContentLength((KnuthElement) iter.next());
}
return len;
}
@@ -278,8 +326,20 @@ class RowPainter {
* Determine the index of the first row of this cell that will be displayed on the
* current page.
*/
- int startRowIndex = Math.max(pgu.getRowIndex(), firstRowIndex);
int currentRowIndex = currentRow.getIndex();
+ int startRowIndex;
+ int firstRowHeight;
+ if (pgu.getRowIndex() >= firstRowIndex) {
+ startRowIndex = pgu.getRowIndex();
+ if (startRowIndex < currentRowIndex) {
+ firstRowHeight = getRowOffset(startRowIndex + 1) - getRowOffset(startRowIndex);
+ } else {
+ firstRowHeight = rowHeight;
+ }
+ } else {
+ startRowIndex = firstRowIndex;
+ firstRowHeight = 0;
+ }
/*
* In collapsing-border model, if the cell spans over several columns/rows then
@@ -319,7 +379,25 @@ class RowPainter {
cellLM.addAreas(new KnuthPossPosIter(pgu.getElements(), startPos, endPos + 1),
layoutContext, spannedGridRowHeights, startRowIndex - pgu.getRowIndex(),
currentRowIndex - pgu.getRowIndex(), borderBeforeWhich, borderAfterWhich,
- startRowIndex == firstRowOnPageIndex, lastOnPage);
+ startRowIndex == firstRowOnPageIndex, lastOnPage, this, firstRowHeight);
+ }
+
+
+ /**
+ * Registers the given area, that will be used to render the part of
+ * table-header/footer/body background covered by a table-cell. If percentages are
+ * used to place the background image, the final bpd of the (fraction of) table part
+ * that will be rendered on the current page must be known. The traits can't then be
+ * set when the areas for the cell are created since at that moment this bpd is yet
+ * unknown. So they will instead be set in
+ * {@link #addAreasAndFlushRow(boolean, boolean)}.
+ *
+ * @param backgroundArea the block of the cell's dimensions that will hold the part
+ * background
+ */
+ void registerPartBackgroundArea(Block backgroundArea) {
+ tclm.getTableLM().addBackgroundArea(backgroundArea);
+ tablePartBackgroundAreas.add(backgroundArea);
}
/**
@@ -357,11 +435,13 @@ class RowPainter {
}
// TODO get rid of that
+ /** Signals that the first table-body instance has started. */
void startBody() {
Arrays.fill(firstCellOnPage, true);
}
// TODO get rid of that
+ /** Signals that the last table-body instance has ended. */
void endBody() {
Arrays.fill(firstCellOnPage, false);
}
diff --git a/src/java/org/apache/fop/layoutmgr/table/TableAndCaptionLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableAndCaptionLayoutManager.java
index 6d2e49e96..2e5bbdf1f 100644
--- a/src/java/org/apache/fop/layoutmgr/table/TableAndCaptionLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/table/TableAndCaptionLayoutManager.java
@@ -23,7 +23,6 @@ import org.apache.fop.fo.flow.table.TableAndCaption;
import org.apache.fop.layoutmgr.BlockStackingLayoutManager;
import org.apache.fop.layoutmgr.LayoutContext;
import org.apache.fop.layoutmgr.PositionIterator;
-import org.apache.fop.layoutmgr.Position;
import org.apache.fop.area.Area;
import org.apache.fop.area.Block;
@@ -36,8 +35,7 @@ import org.apache.fop.area.Block;
* @todo Implement getNextKnuthElements()
*/
public class TableAndCaptionLayoutManager extends BlockStackingLayoutManager {
- private TableAndCaption fobj;
-
+
private Block curBlockArea;
//private List childBreaks = new java.util.ArrayList();
@@ -48,7 +46,6 @@ public class TableAndCaptionLayoutManager extends BlockStackingLayoutManager {
*/
public TableAndCaptionLayoutManager(TableAndCaption node) {
super(node);
- fobj = node;
}
/**
@@ -134,7 +131,7 @@ public class TableAndCaptionLayoutManager extends BlockStackingLayoutManager {
public void addAreas(PositionIterator parentIter,
LayoutContext layoutContext) {
getParentArea(null);
- getPSLM().addIDToPage(fobj.getId());
+ addId();
/* TODO: Reimplement using Knuth approach
LayoutManager childLM;
diff --git a/src/java/org/apache/fop/layoutmgr/table/TableCaptionLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableCaptionLayoutManager.java
index 4c21df937..674fd9a90 100644
--- a/src/java/org/apache/fop/layoutmgr/table/TableCaptionLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/table/TableCaptionLayoutManager.java
@@ -23,7 +23,6 @@ import org.apache.fop.fo.flow.table.TableCaption;
import org.apache.fop.layoutmgr.BlockStackingLayoutManager;
import org.apache.fop.layoutmgr.LayoutContext;
import org.apache.fop.layoutmgr.PositionIterator;
-import org.apache.fop.layoutmgr.Position;
import org.apache.fop.area.Area;
import org.apache.fop.area.Block;
@@ -34,7 +33,6 @@ import org.apache.fop.area.Block;
* @todo Implement getNextKnuthElements()
*/
public class TableCaptionLayoutManager extends BlockStackingLayoutManager {
- private TableCaption fobj;
private Block curBlockArea;
@@ -46,7 +44,6 @@ public class TableCaptionLayoutManager extends BlockStackingLayoutManager {
*/
public TableCaptionLayoutManager(TableCaption node) {
super(node);
- fobj = node;
}
/**
@@ -133,7 +130,7 @@ public class TableCaptionLayoutManager extends BlockStackingLayoutManager {
public void addAreas(PositionIterator parentIter,
LayoutContext layoutContext) {
getParentArea(null);
- getPSLM().addIDToPage(fobj.getId());
+ addId();
/* TODO: Reimplement using Knuth approach
LayoutManager childLM;
diff --git a/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java
index 289785d68..8acfebca0 100644
--- a/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java
@@ -23,16 +23,19 @@ import java.util.LinkedList;
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.area.Trait;
import org.apache.fop.datatypes.PercentBaseContext;
-import org.apache.fop.fo.FONode;
import org.apache.fop.fo.flow.table.ConditionalBorder;
import org.apache.fop.fo.flow.table.GridUnit;
import org.apache.fop.fo.flow.table.PrimaryGridUnit;
import org.apache.fop.fo.flow.table.Table;
+import org.apache.fop.fo.flow.table.TableBody;
import org.apache.fop.fo.flow.table.TableCell;
+import org.apache.fop.fo.flow.table.TableColumn;
+import org.apache.fop.fo.flow.table.TableRow;
import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
import org.apache.fop.fo.properties.CommonBorderPaddingBackground.BorderInfo;
import org.apache.fop.layoutmgr.AreaAdditionUtil;
@@ -71,9 +74,8 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager
private int xoffset;
private int yoffset;
private int cellIPD;
- private int rowHeight;
+ private int totalHeight;
private int usedBPD;
- private int borderAndPaddingBPD;
private boolean emptyCell = true;
/**
@@ -96,31 +98,11 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager
return getTable().isSeparateBorderModel();
}
- /** {@inheritDoc} */
- public void initialize() {
- borderAndPaddingBPD = 0;
- borderAndPaddingBPD += getTableCell()
- .getCommonBorderPaddingBackground().getBorderBeforeWidth(false);
- borderAndPaddingBPD += getTableCell()
- .getCommonBorderPaddingBackground().getBorderAfterWidth(false);
- if (!isSeparateBorderModel()) {
- borderAndPaddingBPD /= 2;
- }
- borderAndPaddingBPD += getTableCell().getCommonBorderPaddingBackground()
- .getPaddingBefore(false, this);
- borderAndPaddingBPD += getTableCell().getCommonBorderPaddingBackground()
- .getPaddingAfter(false, this);
- }
-
/**
* @return the table owning this cell
*/
public Table getTable() {
- FONode node = fobj.getParent();
- while (!(node instanceof Table)) {
- node = node.getParent();
- }
- return (Table)node;
+ return getTableCell().getTable();
}
@@ -148,13 +130,13 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager
* {@inheritDoc}
*/
public LinkedList getNextKnuthElements(LayoutContext context, int alignment) {
- MinOptMax stackLimit = new MinOptMax(context.getStackLimit());
+ MinOptMax stackLimit = new MinOptMax(context.getStackLimitBP());
referenceIPD = context.getRefIPD();
cellIPD = referenceIPD;
cellIPD -= getIPIndents();
- LinkedList returnedList = null;
+ LinkedList returnedList;
LinkedList contentList = new LinkedList();
LinkedList returnList = new LinkedList();
@@ -163,8 +145,8 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager
while ((curLM = (BlockLevelLayoutManager) getChildLM()) != null) {
LayoutContext childLC = new LayoutContext(0);
// curLM is a ?
- childLC.setStackLimit(MinOptMax.subtract(context
- .getStackLimit(), stackLimit));
+ childLC.setStackLimitBP(MinOptMax.subtract(context
+ .getStackLimitBP(), stackLimit));
childLC.setRefIPD(cellIPD);
// get elements from curLM
@@ -260,7 +242,7 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager
p.setP(0);
}
- getPSLM().notifyEndOfLayout(((TableCell)getFObj()).getId());
+ getPSLM().notifyEndOfLayout(fobj.getId());
setFinished(true);
return returnList;
@@ -303,7 +285,7 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager
* @param h the height of cell
*/
public void setTotalHeight(int h) {
- rowHeight = h;
+ totalHeight = h;
}
/**
@@ -330,6 +312,10 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager
* which case collapsed before borders must be drawn in the outer mode
* @param lastOnPage true if the cell will be the very last one on the page, in which
* case collapsed after borders must be drawn in the outer mode
+ * @param painter painter
+ * @param firstRowHeight height of the first row spanned by this cell (may be zero if
+ * this row is placed on a previous page). Used to calculate the placement of the
+ * row's background image if any
*/
public void addAreas(PositionIterator parentIter,
LayoutContext layoutContext,
@@ -339,13 +325,25 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager
int borderBeforeWhich,
int borderAfterWhich,
boolean firstOnPage,
- boolean lastOnPage) {
+ boolean lastOnPage,
+ RowPainter painter,
+ int firstRowHeight) {
getParentArea(null);
- getPSLM().addIDToPage(getTableCell().getId());
+ addId();
int borderBeforeWidth = primaryGridUnit.getBeforeBorderWidth(startRow, borderBeforeWhich);
int borderAfterWidth = primaryGridUnit.getAfterBorderWidth(endRow, borderAfterWhich);
+
+ CommonBorderPaddingBackground padding = primaryGridUnit.getCell()
+ .getCommonBorderPaddingBackground();
+ int paddingRectBPD = totalHeight - borderBeforeWidth - borderAfterWidth;
+ int cellBPD = paddingRectBPD;
+ cellBPD -= padding.getPaddingBefore(borderBeforeWhich == ConditionalBorder.REST, this);
+ cellBPD -= padding.getPaddingAfter(borderAfterWhich == ConditionalBorder.REST, this);
+
+ addBackgroundAreas(painter, firstRowHeight, borderBeforeWidth, paddingRectBPD);
+
if (isSeparateBorderModel()) {
if (!emptyCell || getTableCell().showEmptyCells()) {
if (borderBeforeWidth > 0) {
@@ -421,7 +419,7 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager
int dx = xoffset;
for (int x = 0; x < gridUnits.length; x++) {
int ipd = getTable().getColumn(primaryGridUnit.getColIndex() + x)
- .getColumnWidth().getValue((PercentBaseContext) getParent());
+ .getColumnWidth().getValue(getParent());
if (blocks[y][x] != null) {
Block block = blocks[y][x];
adjustYOffset(block, dy);
@@ -437,18 +435,12 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager
}
}
- CommonBorderPaddingBackground padding = primaryGridUnit.getCell()
- .getCommonBorderPaddingBackground();
TraitSetter.addPadding(curBlockArea,
padding,
borderBeforeWhich == ConditionalBorder.REST,
borderAfterWhich == ConditionalBorder.REST,
false, false, this);
- int cellBPD = rowHeight - borderBeforeWidth - borderAfterWidth;
- cellBPD -= padding.getPaddingBefore(borderBeforeWhich == ConditionalBorder.REST, this);
- cellBPD -= padding.getPaddingAfter(borderAfterWhich == ConditionalBorder.REST, this);
-
//Handle display-align
if (usedBPD < cellBPD) {
if (getTableCell().getDisplayAlign() == EN_CENTER) {
@@ -468,16 +460,9 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager
curBlockArea.setBPD(cellBPD);
// Add background after we know the BPD
- if (isSeparateBorderModel()) {
- if (!emptyCell || getTableCell().showEmptyCells()) {
- TraitSetter.addBackground(curBlockArea,
- getTableCell().getCommonBorderPaddingBackground(),
- this);
- }
- } else {
+ if (!isSeparateBorderModel() || !emptyCell || getTableCell().showEmptyCells()) {
TraitSetter.addBackground(curBlockArea,
- getTableCell().getCommonBorderPaddingBackground(),
- this);
+ getTableCell().getCommonBorderPaddingBackground(), this);
}
flush();
@@ -485,6 +470,33 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager
curBlockArea = null;
}
+ /** Adds background areas for the column, body and row, if any. */
+ private void addBackgroundAreas(RowPainter painter, int firstRowHeight, int borderBeforeWidth,
+ int paddingRectBPD) {
+ TableColumn column = getTable().getColumn(primaryGridUnit.getColIndex());
+ if (column.getCommonBorderPaddingBackground().hasBackground()) {
+ Block colBackgroundArea = getBackgroundArea(paddingRectBPD, borderBeforeWidth);
+ ((TableLayoutManager) parentLM).registerColumnBackgroundArea(column, colBackgroundArea,
+ -startIndent);
+ }
+
+ TableBody body = primaryGridUnit.getTableBody();
+ if (body.getCommonBorderPaddingBackground().hasBackground()) {
+ painter.registerPartBackgroundArea(
+ getBackgroundArea(paddingRectBPD, borderBeforeWidth));
+ }
+
+ TableRow row = primaryGridUnit.getRow();
+ if (row != null && row.getCommonBorderPaddingBackground().hasBackground()) {
+ Block rowBackgroundArea = getBackgroundArea(paddingRectBPD, borderBeforeWidth);
+ ((TableLayoutManager) parentLM).addBackgroundArea(rowBackgroundArea);
+ TraitSetter.addBackground(rowBackgroundArea, row.getCommonBorderPaddingBackground(),
+ parentLM,
+ -xoffset - startIndent, -borderBeforeWidth,
+ parentLM.getContentAreaIPD(), firstRowHeight);
+ }
+ }
+
private void addBorder(Block[][] blocks, int i, int j, Integer side, BorderInfo border,
boolean outer) {
if (blocks[i][j] == null) {
@@ -513,6 +525,21 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager
block.setBPD(block.getBPD() + amount);
}
+ private Block getBackgroundArea(int bpd, int borderBeforeWidth) {
+ CommonBorderPaddingBackground padding = getTableCell().getCommonBorderPaddingBackground();
+ int paddingStart = padding.getPaddingStart(false, this);
+ int paddingEnd = padding.getPaddingEnd(false, this);
+
+ Block block = new Block();
+ TraitSetter.setProducerID(block, getTable().getId());
+ block.setPositioning(Block.ABSOLUTE);
+ block.setIPD(cellIPD + paddingStart + paddingEnd);
+ block.setBPD(bpd);
+ block.setXOffset(xoffset + startIndent - paddingStart);
+ block.setYOffset(yoffset + borderBeforeWidth);
+ return block;
+ }
+
/**
* Return an Area which can contain the passed childArea. The childArea
* may not yet have any content, but it has essential traits set.
diff --git a/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java
index b9a118e28..7cdeb79d5 100644
--- a/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java
@@ -27,8 +27,6 @@ import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.apache.fop.area.Block;
-import org.apache.fop.area.Trait;
import org.apache.fop.datatypes.PercentBaseContext;
import org.apache.fop.fo.Constants;
import org.apache.fop.fo.FObj;
@@ -36,7 +34,6 @@ import org.apache.fop.fo.flow.table.EffRow;
import org.apache.fop.fo.flow.table.PrimaryGridUnit;
import org.apache.fop.fo.flow.table.Table;
import org.apache.fop.fo.flow.table.TableBody;
-import org.apache.fop.fo.flow.table.TableRow;
import org.apache.fop.layoutmgr.BreakElement;
import org.apache.fop.layoutmgr.ElementListUtils;
import org.apache.fop.layoutmgr.KnuthBox;
@@ -46,7 +43,6 @@ import org.apache.fop.layoutmgr.LayoutContext;
import org.apache.fop.layoutmgr.ListElement;
import org.apache.fop.layoutmgr.Position;
import org.apache.fop.layoutmgr.PositionIterator;
-import org.apache.fop.layoutmgr.TraitSetter;
import org.apache.fop.layoutmgr.SpaceResolver.SpaceHandlingBreakPosition;
import org.apache.fop.util.BreakUtil;
@@ -293,7 +289,7 @@ public class TableContentLayoutManager implements PercentBaseContext {
this.usedBPD = 0;
RowPainter painter = new RowPainter(this, layoutContext);
- List positions = new java.util.ArrayList();
+ List tablePositions = new ArrayList();
List headerElements = null;
List footerElements = null;
Position firstPos = null;
@@ -330,7 +326,7 @@ public class TableContentLayoutManager implements PercentBaseContext {
//ignore for now, see special handling below if break is at a penalty
//Only if the last position in this part/page us such a position it will be used
} else if (pos instanceof TableContentPosition) {
- positions.add(pos);
+ tablePositions.add(pos);
} else {
if (log.isDebugEnabled()) {
log.debug("Ignoring position: " + pos);
@@ -359,21 +355,23 @@ public class TableContentLayoutManager implements PercentBaseContext {
if (headerElements != null) {
//header positions for the last part are the second-to-last element and need to
//be handled first before all other TableContentPositions
- PositionIterator nestedIter = new KnuthPossPosIter(headerElements);
- iterateAndPaintPositions(nestedIter, painter, false);
+ addHeaderFooterAreas(headerElements, tableLM.getTable().getTableHeader(), painter,
+ false);
}
- //Iterate over all steps
- Iterator posIter = positions.iterator();
- painter.startBody();
- // Here we are sure that posIter iterates only over TableContentPosition instances
- iterateAndPaintPositions(posIter, painter, footerElements == null);
- painter.endBody();
+ if (tablePositions.isEmpty()) {
+ // TODO make sure this actually never happens
+ log.error("tablePositions empty."
+ + " Please send your FO file to fop-users@xmlgraphics.apache.org");
+ } else {
+ // Here we are sure that posIter iterates only over TableContentPosition instances
+ addBodyAreas(tablePositions.iterator(), painter, footerElements == null);
+ }
if (footerElements != null) {
//Positions for footers are simply added at the end
- PositionIterator nestedIter = new KnuthPossPosIter(footerElements);
- iterateAndPaintPositions(nestedIter, painter, true);
+ addHeaderFooterAreas(footerElements, tableLM.getTable().getTableFooter(), painter,
+ true);
}
this.usedBPD += painter.getAccumulatedBPD();
@@ -384,106 +382,74 @@ public class TableContentLayoutManager implements PercentBaseContext {
}
}
+ private void addHeaderFooterAreas(List elements, TableBody part, RowPainter painter,
+ boolean lastOnPage) {
+ List lst = new ArrayList(elements.size());
+ for (Iterator iter = new KnuthPossPosIter(elements); iter.hasNext();) {
+ Position pos = (Position) iter.next();
+ /*
+ * Unlike for the body the Positions associated to the glues generated by
+ * TableStepper haven't been removed yet.
+ */
+ if (pos instanceof TableContentPosition) {
+ lst.add((TableContentPosition) pos);
+ }
+ }
+ addTablePartAreas(lst, painter, part, true, true, true, lastOnPage);
+ }
+
/**
- * Iterates over a part of the table (header, footer, body) and paints the related
- * elements.
+ * Iterates over the positions corresponding to the table's body (which may contain
+ * several table-body elements!) and adds the corresponding areas.
*
- * @param iterator iterator over Position elements. Those positions correspond to the
- * elements of the table present on the current page
+ * @param iterator iterator over TableContentPosition elements. Those positions
+ * correspond to the elements of the body present on the current page
* @param painter
- * @param lastOnPage true if the corresponding part will be the last on the page
- * (either body or footer, obviously)
+ * @param lastOnPage true if the table has no footer (then the last line of the table
+ * that will be present on the page belongs to the body)
*/
- private void iterateAndPaintPositions(Iterator iterator, RowPainter painter,
+ private void addBodyAreas(Iterator iterator, RowPainter painter,
boolean lastOnPage) {
+ painter.startBody();
List lst = new ArrayList();
- boolean firstPos = false;
- TableBody body = null;
+ TableContentPosition pos = (TableContentPosition) iterator.next();
+ boolean isFirstPos = pos.getFlag(TableContentPosition.FIRST_IN_ROWGROUP)
+ && pos.getRow().getFlag(EffRow.FIRST_IN_PART);
+ TableBody body = pos.getTableBody();
+ lst.add(pos);
while (iterator.hasNext()) {
- Position pos = (Position)iterator.next();
- if (pos instanceof TableContentPosition) {
- TableContentPosition tcpos = (TableContentPosition)pos;
- lst.add(tcpos);
- CellPart part = (CellPart)tcpos.cellParts.get(0);
- if (body == null) {
- body = part.pgu.getBody();
- }
- if (tcpos.getFlag(TableContentPosition.FIRST_IN_ROWGROUP)
- && tcpos.getRow().getFlag(EffRow.FIRST_IN_PART)) {
- firstPos = true;
-
- }
- if (tcpos.getFlag(TableContentPosition.LAST_IN_ROWGROUP)
- && tcpos.getRow().getFlag(EffRow.LAST_IN_PART)) {
- log.trace("LAST_IN_ROWGROUP + LAST_IN_PART");
- handleMarkersAndPositions(lst, body, firstPos, true, painter);
- //reset
- firstPos = false;
- body = null;
- lst.clear();
- }
+ pos = (TableContentPosition) iterator.next();
+ if (pos.getTableBody() != body) {
+ addTablePartAreas(lst, painter, body, isFirstPos, true, false, false);
+ isFirstPos = true;
+ lst.clear();
+ body = pos.getTableBody();
}
+ lst.add(pos);
}
- if (body != null) {
- // Entering this block means that the end of the current table-part hasn't
- // been reached (otherwise it would have been caught by the test above). So
- // lastPos is necessarily false
- handleMarkersAndPositions(lst, body, firstPos, false, painter);
- }
- painter.addAreasAndFlushRow(true, lastOnPage);
- }
-
- private void handleMarkersAndPositions(List positions, TableBody body, boolean firstPos,
- boolean lastPos, RowPainter painter) {
- getTableLM().getCurrentPV().addMarkers(body.getMarkers(),
- true, firstPos, lastPos);
- int size = positions.size();
- for (int i = 0; i < size; i++) {
- painter.handleTableContentPosition((TableContentPosition)positions.get(i));
- }
- getTableLM().getCurrentPV().addMarkers(body.getMarkers(),
- false, firstPos, lastPos);
+ boolean isLastPos = pos.getFlag(TableContentPosition.LAST_IN_ROWGROUP)
+ && pos.getRow().getFlag(EffRow.LAST_IN_PART);
+ addTablePartAreas(lst, painter, body, isFirstPos, isLastPos, true, lastOnPage);
+ painter.endBody();
}
/**
- * Get the area for a row for background.
- * @param row the table-row object or null
- * @return the row area or null if there's no background to paint
+ * Adds the areas corresponding to a single fo:table-header/footer/body element.
*/
- Block getRowArea(TableRow row) {
- if (row == null || !row.getCommonBorderPaddingBackground().hasBackground()) {
- return null;
- } else {
- Block block = new Block();
- block.addTrait(Trait.IS_REFERENCE_AREA, Boolean.TRUE);
- block.setPositioning(Block.ABSOLUTE);
- return block;
+ private void addTablePartAreas(List positions, RowPainter painter, TableBody body,
+ boolean isFirstPos, boolean isLastPos, boolean lastInBody, boolean lastOnPage) {
+ getTableLM().getCurrentPV().addMarkers(body.getMarkers(),
+ true, isFirstPos, isLastPos);
+ painter.startTablePart(body);
+ for (Iterator iter = positions.iterator(); iter.hasNext();) {
+ painter.handleTableContentPosition((TableContentPosition) iter.next());
}
+ getTableLM().getCurrentPV().addMarkers(body.getMarkers(),
+ false, isFirstPos, isLastPos);
+ painter.endTablePart(lastInBody, lastOnPage);
}
/**
- * Adds the area for the row background if any.
- * @param row row for which to generate the background
- * @param bpd block-progression-dimension of the row
- * @param ipd inline-progression-dimension of the row
- * @param yoffset Y offset at which to paint
- */
- void addRowBackgroundArea(TableRow row, int bpd, int ipd, int yoffset) {
- //Add row background if any
- Block rowBackground = getRowArea(row);
- if (rowBackground != null) {
- rowBackground.setBPD(bpd);
- rowBackground.setIPD(ipd);
- rowBackground.setXOffset(this.startXOffset);
- rowBackground.setYOffset(yoffset);
- getTableLM().addChildArea(rowBackground);
- TraitSetter.addBackground(rowBackground,
- row.getCommonBorderPaddingBackground(), getTableLM());
- }
- }
-
-
- /**
* Sets the overall starting x-offset. Used for proper placement of cells.
* @param startXOffset starting x-offset (table's start-indent)
*/
diff --git a/src/java/org/apache/fop/layoutmgr/table/TableContentPosition.java b/src/java/org/apache/fop/layoutmgr/table/TableContentPosition.java
index e702c58a9..260b8cfdf 100644
--- a/src/java/org/apache/fop/layoutmgr/table/TableContentPosition.java
+++ b/src/java/org/apache/fop/layoutmgr/table/TableContentPosition.java
@@ -22,6 +22,7 @@ package org.apache.fop.layoutmgr.table;
import java.util.List;
import org.apache.fop.fo.flow.table.EffRow;
+import org.apache.fop.fo.flow.table.TableBody;
import org.apache.fop.layoutmgr.LayoutManager;
import org.apache.fop.layoutmgr.Position;
@@ -79,6 +80,10 @@ class TableContentPosition extends Position {
return row;
}
+ TableBody getTableBody() {
+ return ((CellPart) cellParts.get(0)).pgu.getTableBody();
+ }
+
/**
* Returns a flag for this GridUnit.
* @param which the requested flag
@@ -101,10 +106,12 @@ class TableContentPosition extends Position {
}
}
+ /** {@inheritDoc} */
public boolean generatesAreas() {
return true;
}
+ /** {@inheritDoc} */
public String toString() {
StringBuffer sb = new StringBuffer("TableContentPosition:");
sb.append(getIndex());
diff --git a/src/java/org/apache/fop/layoutmgr/table/TableHFPenaltyPosition.java b/src/java/org/apache/fop/layoutmgr/table/TableHFPenaltyPosition.java
index afa166985..3e504a45c 100644
--- a/src/java/org/apache/fop/layoutmgr/table/TableHFPenaltyPosition.java
+++ b/src/java/org/apache/fop/layoutmgr/table/TableHFPenaltyPosition.java
@@ -43,6 +43,11 @@ class TableHFPenaltyPosition extends Position {
super(lm);
}
+ /** {@inheritDoc} */
+ public boolean generatesAreas() {
+ return true;
+ }
+
public String toString() {
StringBuffer sb = new StringBuffer("TableHFPenaltyPosition:");
sb.append(getIndex()).append("(");
diff --git a/src/java/org/apache/fop/layoutmgr/table/TableHeaderFooterPosition.java b/src/java/org/apache/fop/layoutmgr/table/TableHeaderFooterPosition.java
index c3ae72c74..8d3b993b2 100644
--- a/src/java/org/apache/fop/layoutmgr/table/TableHeaderFooterPosition.java
+++ b/src/java/org/apache/fop/layoutmgr/table/TableHeaderFooterPosition.java
@@ -48,6 +48,11 @@ class TableHeaderFooterPosition extends Position {
this.nestedElements = nestedElements;
}
+ /** {@inheritDoc} */
+ public boolean generatesAreas() {
+ return true;
+ }
+
public String toString() {
StringBuffer sb = new StringBuffer("Table");
sb.append(header ? "Header" : "Footer");
diff --git a/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java
index 1cbc3e50a..d6bba5cb5 100644
--- a/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java
+++ b/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java
@@ -19,8 +19,10 @@
package org.apache.fop.layoutmgr.table;
+import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
+import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -79,7 +81,27 @@ public class TableLayoutManager extends BlockStackingLayoutManager
private int halfBorderSeparationBPD;
private int halfBorderSeparationIPD;
-
+
+ /** See {@link TableLayoutManager#registerColumnBackgroundArea(TableColumn, Block, int)}. */
+ private List columnBackgroundAreas;
+
+ /**
+ * Temporary holder of column background informations for a table-cell's area.
+ *
+ * @see TableLayoutManager#registerColumnBackgroundArea(TableColumn, Block, int)
+ */
+ private static final class ColumnBackgroundInfo {
+ private TableColumn column;
+ private Block backgroundArea;
+ private int xShift;
+
+ private ColumnBackgroundInfo(TableColumn column, Block backgroundArea, int xShift) {
+ this.column = column;
+ this.backgroundArea = backgroundArea;
+ this.xShift = xShift;
+ }
+ }
+
/**
* Create a new table layout manager.
* @param node the table FO
@@ -211,7 +233,7 @@ public class TableLayoutManager extends BlockStackingLayoutManager
// Elements for the table-header/footer/body
- LinkedList contentKnuthElements = null;
+ LinkedList contentKnuthElements;
contentLM = new TableContentLayoutManager(this);
LayoutContext childLC = new LayoutContext(0);
/*
@@ -263,7 +285,30 @@ public class TableLayoutManager extends BlockStackingLayoutManager
resetSpaces();
return returnList;
}
-
+
+ /**
+ * Registers the given area, that will be used to render the part of column background
+ * covered by a table-cell. If percentages are used to place the background image, the
+ * final bpd of the (fraction of) table that will be rendered on the current page must
+ * be known. The traits can't then be set when the areas for the cell are created
+ * since at that moment this bpd is yet unknown. So they will instead be set in
+ * TableLM's {@link #addAreas(PositionIterator, LayoutContext)} method.
+ *
+ * @param column the table-column element from which the cell gets background
+ * informations
+ * @param backgroundArea the block of the cell's dimensions that will hold the column
+ * background
+ * @param xShift additional amount by which the image must be shifted to be correctly
+ * placed (to counterbalance the cell's start border)
+ */
+ void registerColumnBackgroundArea(TableColumn column, Block backgroundArea, int xShift) {
+ addBackgroundArea(backgroundArea);
+ if (columnBackgroundAreas == null) {
+ columnBackgroundAreas = new ArrayList();
+ }
+ columnBackgroundAreas.add(new ColumnBackgroundInfo(column, backgroundArea, xShift));
+ }
+
/**
* The table area is a reference area that contains areas for
* columns, bodies, rows and the contents are in cells.
@@ -274,7 +319,7 @@ public class TableLayoutManager extends BlockStackingLayoutManager
public void addAreas(PositionIterator parentIter,
LayoutContext layoutContext) {
getParentArea(null);
- getPSLM().addIDToPage(getTable().getId());
+ addId();
// add space before, in order to implement display-align = "center" or "after"
if (layoutContext.getSpaceBefore() != 0) {
@@ -298,6 +343,17 @@ public class TableLayoutManager extends BlockStackingLayoutManager
curBlockArea.setBPD(tableHeight);
+ if (columnBackgroundAreas != null) {
+ for (Iterator iter = columnBackgroundAreas.iterator(); iter.hasNext();) {
+ ColumnBackgroundInfo b = (ColumnBackgroundInfo) iter.next();
+ TraitSetter.addBackground(b.backgroundArea,
+ b.column.getCommonBorderPaddingBackground(), this,
+ b.xShift, -b.backgroundArea.getYOffset(),
+ b.column.getColumnWidth().getValue(this), tableHeight);
+ }
+ columnBackgroundAreas.clear();
+ }
+
if (getTable().isSeparateBorderModel()) {
TraitSetter.addBorders(curBlockArea,
getTable().getCommonBorderPaddingBackground(),
@@ -323,7 +379,7 @@ public class TableLayoutManager extends BlockStackingLayoutManager
resetSpaces();
curBlockArea = null;
- getPSLM().notifyEndOfLayout(((Table)getFObj()).getId());
+ getPSLM().notifyEndOfLayout(fobj.getId());
}
/**
@@ -366,6 +422,15 @@ public class TableLayoutManager extends BlockStackingLayoutManager
}
}
+ /**
+ * Adds the given area to this layout manager's area, without updating the used bpd.
+ *
+ * @param background an area
+ */
+ void addBackgroundArea(Block background) {
+ curBlockArea.addChildArea(background);
+ }
+
/** {@inheritDoc} */
public int negotiateBPDAdjustment(int adj, KnuthElement lastElement) {
// TODO Auto-generated method stub
diff --git a/src/java/org/apache/fop/pdf/PDFCMap.java b/src/java/org/apache/fop/pdf/PDFCMap.java
index bdf8108c2..1be5e9dc4 100644
--- a/src/java/org/apache/fop/pdf/PDFCMap.java
+++ b/src/java/org/apache/fop/pdf/PDFCMap.java
@@ -21,7 +21,6 @@ package org.apache.fop.pdf;
import java.io.IOException;
import java.io.OutputStream;
-import java.io.StringWriter;
import java.io.Writer;
/**
@@ -425,10 +424,8 @@ public class PDFCMap extends PDFStream {
/** {@inheritDoc} */
protected int output(OutputStream stream) throws IOException {
- StringWriter writer = new StringWriter();
- CMapBuilder builder = createCMapBuilder(writer);
+ CMapBuilder builder = createCMapBuilder(getBufferWriter());
builder.writeCMap();
- add(writer.getBuffer().toString()); //TODO Could be optimized by not buffering
return super.output(stream);
}
}
diff --git a/src/java/org/apache/fop/pdf/PDFEncoding.java b/src/java/org/apache/fop/pdf/PDFEncoding.java
index b2fba6e53..6dc448b40 100644
--- a/src/java/org/apache/fop/pdf/PDFEncoding.java
+++ b/src/java/org/apache/fop/pdf/PDFEncoding.java
@@ -132,6 +132,14 @@ public class PDFEncoding extends PDFDictionary {
}
/**
+ * Indicates whether any differences have been recorded.
+ * @return true if there are differences.
+ */
+ public boolean hasDifferences() {
+ return (this.differences.length() > 0);
+ }
+
+ /**
* Creates and returns the PDFArray representing the Differences entry.
* @return the Differences entry
*/
diff --git a/src/java/org/apache/fop/pdf/PDFFactory.java b/src/java/org/apache/fop/pdf/PDFFactory.java
index 687b32016..f4474331f 100644
--- a/src/java/org/apache/fop/pdf/PDFFactory.java
+++ b/src/java/org/apache/fop/pdf/PDFFactory.java
@@ -43,6 +43,7 @@ import org.apache.commons.logging.LogFactory;
import org.apache.xmlgraphics.xmp.Metadata;
import org.apache.fop.fonts.CIDFont;
+import org.apache.fop.fonts.CIDSubset;
import org.apache.fop.fonts.CodePointMapping;
import org.apache.fop.fonts.CustomFont;
import org.apache.fop.fonts.FontDescriptor;
@@ -50,6 +51,8 @@ import org.apache.fop.fonts.FontMetrics;
import org.apache.fop.fonts.FontType;
import org.apache.fop.fonts.LazyFont;
import org.apache.fop.fonts.MultiByteFont;
+import org.apache.fop.fonts.SimpleSingleByteEncoding;
+import org.apache.fop.fonts.SingleByteEncoding;
import org.apache.fop.fonts.SingleByteFont;
import org.apache.fop.fonts.Typeface;
import org.apache.fop.fonts.truetype.FontFileReader;
@@ -1166,7 +1169,7 @@ public class PDFFactory {
}
/**
- * make a Type1 /Font object
+ * Make a Type1 /Font object.
*
* @param fontname internal name to use for this font (eg "F1")
* @param basefont name of the base font (eg "Helvetica")
@@ -1217,10 +1220,12 @@ public class PDFFactory {
(PDFCIDFontDescriptor)pdfdesc);
getDocument().registerObject(cidFont);
- PDFCMap cmap = new PDFToUnicodeCMap(cidMetrics.getCharsUsed(), "fop-ucs-H",
- new PDFCIDSystemInfo("Adobe",
- "Identity",
- 0));
+ PDFCMap cmap = new PDFToUnicodeCMap(
+ cidMetrics.getCIDSubset().getSubsetChars(),
+ "fop-ucs-H",
+ new PDFCIDSystemInfo("Adobe",
+ "Identity",
+ 0));
getDocument().registerObject(cmap);
((PDFFontType0)font).setCMAP(cmap);
((PDFFontType0)font).setDescendantFonts(cidFont);
@@ -1238,35 +1243,20 @@ public class PDFFactory {
int lastChar = singleByteFont.getLastChar();
nonBase14.setWidthMetrics(firstChar,
lastChar,
- makeArray(metrics.getWidths()));
+ new PDFArray(null, metrics.getWidths()));
//Handle encoding
- CodePointMapping mapping = singleByteFont.getCodePointMapping();
+ SingleByteEncoding mapping = singleByteFont.getEncoding();
if (PDFEncoding.isPredefinedEncoding(mapping.getName())) {
font.setEncoding(mapping.getName());
} else {
- CodePointMapping winansi = CodePointMapping.getMapping(
- CodePointMapping.WIN_ANSI_ENCODING);
- PDFEncoding pdfEncoding = new PDFEncoding(winansi.getName());
- PDFEncoding.DifferencesBuilder builder
- = pdfEncoding.createDifferencesBuilder();
- int start = -1;
- String[] winansiNames = winansi.getCharNameMap();
- String[] charNameMap = mapping.getCharNameMap();
- for (int i = 0; i < 256; i++) {
- String wac = winansiNames[i];
- String c = charNameMap[i];
- if (!wac.equals(c)) {
- if (start != i) {
- builder.addDifference(i);
- start = i;
- }
- builder.addName(c);
- start++;
- }
+ Object pdfEncoding = createPDFEncoding(mapping,
+ singleByteFont.getFontName());
+ if (pdfEncoding instanceof PDFEncoding) {
+ font.setEncoding((PDFEncoding)pdfEncoding);
+ } else {
+ font.setEncoding((String)pdfEncoding);
}
- pdfEncoding.setDifferences(builder.toPDFArray());
- font.setEncoding(pdfEncoding);
/* JM: What I thought would be a necessity with custom encodings turned out to
* be a bug in Adobe Acrobat 8. The following section just demonstrates how
@@ -1278,21 +1268,88 @@ public class PDFFactory {
nonBase14.setToUnicode(cmap);
*/
}
+
+ //Handle additional encodings (characters outside the primary encoding)
+ if (singleByteFont.hasAdditionalEncodings()) {
+ for (int i = 0, c = singleByteFont.getAdditionalEncodingCount(); i < c; i++) {
+ SimpleSingleByteEncoding addEncoding
+ = singleByteFont.getAdditionalEncoding(i);
+ String name = fontname + "_" + (i + 1);
+ Object pdfenc = createPDFEncoding(addEncoding,
+ singleByteFont.getFontName());
+ PDFFontNonBase14 addFont = (PDFFontNonBase14)PDFFont.createFont(
+ name, fonttype,
+ basefont, pdfenc);
+ addFont.setDescriptor(pdfdesc);
+ addFont.setWidthMetrics(
+ addEncoding.getFirstChar(),
+ addEncoding.getLastChar(),
+ new PDFArray(null, singleByteFont.getAdditionalWidths(i)));
+ getDocument().registerObject(addFont);
+ getDocument().getResources().addFont(addFont);
+ }
+ }
}
return font;
}
}
+ /**
+ * Creates a PDFEncoding instance from a CodePointMapping instance.
+ * @param encoding the code point mapping (encoding)
+ * @return the PDF Encoding dictionary (or a String with the predefined encoding)
+ */
+ public Object createPDFEncoding(SingleByteEncoding encoding, String fontNameHint) {
+ SingleByteEncoding baseEncoding;
+ if (fontNameHint.indexOf("Symbol") >= 0) {
+ baseEncoding = CodePointMapping.getMapping(
+ CodePointMapping.SYMBOL_ENCODING);
+ } else {
+ baseEncoding = CodePointMapping.getMapping(
+ CodePointMapping.STANDARD_ENCODING);
+ }
+ PDFEncoding pdfEncoding = new PDFEncoding(baseEncoding.getName());
+ PDFEncoding.DifferencesBuilder builder
+ = pdfEncoding.createDifferencesBuilder();
+ int start = -1;
+ String[] baseNames = baseEncoding.getCharNameMap();
+ String[] charNameMap = encoding.getCharNameMap();
+ for (int i = 0, ci = charNameMap.length; i < ci; i++) {
+ String basec = baseNames[i];
+ String c = charNameMap[i];
+ if (!basec.equals(c)) {
+ if (start != i) {
+ builder.addDifference(i);
+ start = i;
+ }
+ builder.addName(c);
+ start++;
+ }
+ }
+ if (builder.hasDifferences()) {
+ pdfEncoding.setDifferences(builder.toPDFArray());
+ return pdfEncoding;
+ } else {
+ return baseEncoding.getName();
+ }
+ }
+
+ /**
+ * Creates and returns a width array with the widths of all the characters in the subset.
+ * @param cidFont the font
+ * @return the width array
+ */
public PDFWArray getSubsetWidths(CIDFont cidFont) {
// Create widths for reencoded chars
PDFWArray warray = new PDFWArray();
- int[] tmpWidth = new int[cidFont.usedGlyphsCount];
+ int[] widths = cidFont.getWidths();
+ CIDSubset subset = cidFont.getCIDSubset();
+ int[] tmpWidth = new int[subset.getSubsetSize()];
- for (int i = 0; i < cidFont.usedGlyphsCount; i++) {
- Integer nw = (Integer)cidFont.usedGlyphsIndex.get(new Integer(i));
- int nwx = (nw == null) ? 0 : nw.intValue();
- tmpWidth[i] = cidFont.width[nwx];
+ for (int i = 0, c = subset.getSubsetSize(); i < c; i++) {
+ int nwx = Math.max(0, subset.getGlyphIndexForSubsetIndex(i));
+ tmpWidth[i] = widths[nwx];
}
warray.addEntry(0, tmpWidth);
return warray;
@@ -1345,12 +1402,7 @@ public class PDFFactory {
}
private void buildCIDSet(PDFFontDescriptor descriptor, CIDFont cidFont) {
- BitSet cidSubset = new BitSet();
- Iterator iter = cidFont.usedGlyphs.keySet().iterator();
- while (iter.hasNext()) {
- Integer cid = (Integer)iter.next();
- cidSubset.set(cid.intValue());
- }
+ BitSet cidSubset = cidFont.getCIDSubset().getGlyphIndexBitSet();
PDFStream cidSet = makeStream(null, true);
ByteArrayOutputStream baout = new ByteArrayOutputStream(cidSubset.length() / 8 + 1);
int value = 0;
@@ -1548,14 +1600,13 @@ public class PDFFactory {
}
/**
- * make an Array object (ex. Widths array for a font)
+ * Make an Array object (ex. Widths array for a font).
*
* @param values the int array values
* @return the PDF Array with the int values
*/
public PDFArray makeArray(int[] values) {
PDFArray array = new PDFArray(null, values);
-
getDocument().registerObject(array);
return array;
}
diff --git a/src/java/org/apache/fop/pdf/PDFResources.java b/src/java/org/apache/fop/pdf/PDFResources.java
index 66ccdc78b..b0c0128e1 100644
--- a/src/java/org/apache/fop/pdf/PDFResources.java
+++ b/src/java/org/apache/fop/pdf/PDFResources.java
@@ -110,7 +110,7 @@ public class PDFResources extends PDFObject {
desc = (FontDescriptor)font;
}
addFont(doc.getFactory().makeFont(
- f, font.getEmbedFontName(), font.getEncoding(), font, desc));
+ f, font.getEmbedFontName(), font.getEncodingName(), font, desc));
}
}
}
diff --git a/src/java/org/apache/fop/pdf/PDFStream.java b/src/java/org/apache/fop/pdf/PDFStream.java
index 59a8336c5..a213340e3 100644
--- a/src/java/org/apache/fop/pdf/PDFStream.java
+++ b/src/java/org/apache/fop/pdf/PDFStream.java
@@ -19,8 +19,9 @@
package org.apache.fop.pdf;
-import java.io.OutputStream;
import java.io.IOException;
+import java.io.OutputStream;
+import java.io.Writer;
/**
* Class representing a PDF stream.
@@ -37,6 +38,8 @@ public class PDFStream extends AbstractPDFStream {
*/
protected StreamCache data;
+ private transient Writer streamWriter;
+
/**
* Create an empty stream object
*/
@@ -44,6 +47,10 @@ public class PDFStream extends AbstractPDFStream {
super();
try {
data = StreamCacheFactory.getInstance().createStreamCache();
+ this.streamWriter = new java.io.OutputStreamWriter(
+ getBufferOutputStream(), PDFDocument.ENCODING);
+ //Buffer to minimize calls to the converter
+ this.streamWriter = new java.io.BufferedWriter(this.streamWriter);
} catch (IOException ex) {
//TODO throw the exception and catch it elsewhere
ex.printStackTrace();
@@ -57,21 +64,35 @@ public class PDFStream extends AbstractPDFStream {
*/
public void add(String s) {
try {
- data.getOutputStream().write(PDFDocument.encode(s));
+ this.streamWriter.write(s);
} catch (IOException ex) {
//TODO throw the exception and catch it elsewhere
ex.printStackTrace();
}
-
+ }
+
+ private void flush() throws IOException {
+ this.streamWriter.flush();
}
/**
+ * Returns a Writer that writes to the OutputStream of the buffer.
+ * @return the Writer
+ */
+ public Writer getBufferWriter() {
+ return this.streamWriter;
+ }
+
+ /**
* Returns an OutputStream that can be used to write to the buffer which is used
* to build up the PDF stream.
* @return the OutputStream
* @throws IOException In case of an I/O problem
*/
public OutputStream getBufferOutputStream() throws IOException {
+ if (this.streamWriter != null) {
+ flush(); //Just to be sure
+ }
return this.data.getOutputStream();
}
@@ -91,6 +112,7 @@ public class PDFStream extends AbstractPDFStream {
*/
public int getDataLength() {
try {
+ flush();
return data.getSize();
} catch (Exception e) {
//TODO throw the exception and catch it elsewhere
@@ -99,17 +121,15 @@ public class PDFStream extends AbstractPDFStream {
}
}
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
protected int getSizeHint() throws IOException {
+ flush();
return data.getSize();
}
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
protected void outputRawStreamData(OutputStream out) throws IOException {
+ flush();
data.outputContents(out);
}
diff --git a/src/java/org/apache/fop/pdf/PDFTTFStream.java b/src/java/org/apache/fop/pdf/PDFTTFStream.java
index b3488f6a1..5570c62f3 100644
--- a/src/java/org/apache/fop/pdf/PDFTTFStream.java
+++ b/src/java/org/apache/fop/pdf/PDFTTFStream.java
@@ -67,7 +67,7 @@ public class PDFTTFStream extends PDFStream {
*/
public void setData(byte[] data, int size) throws IOException {
this.data.clear();
- this.data.getOutputStream().write(data, 0, size);
+ getBufferOutputStream().write(data, 0, size);
}
}
diff --git a/src/java/org/apache/fop/pdf/PDFTextUtil.java b/src/java/org/apache/fop/pdf/PDFTextUtil.java
new file mode 100644
index 000000000..224bb6a1d
--- /dev/null
+++ b/src/java/org/apache/fop/pdf/PDFTextUtil.java
@@ -0,0 +1,295 @@
+/*
+ * 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;
+
+import java.awt.geom.AffineTransform;
+
+/**
+ * Utility class for generating PDF text objects. It needs to be subclassed to add writing
+ * functionality (see {@link #write(String)}).
+ */
+public abstract class PDFTextUtil {
+
+ /** The number of decimal places. */
+ private static final int DEC = 8;
+
+ /** PDF text rendering mode: Fill text */
+ public static final int TR_FILL = 0;
+ /** PDF text rendering mode: Stroke text */
+ public static final int TR_STROKE = 1;
+ /** PDF text rendering mode: Fill, then stroke text */
+ public static final int TR_FILL_STROKE = 2;
+ /** PDF text rendering mode: Neither fill nor stroke text (invisible) */
+ public static final int TR_INVISIBLE = 3;
+ /** PDF text rendering mode: Fill text and add to path for clipping */
+ public static final int TR_FILL_CLIP = 4;
+ /** PDF text rendering mode: Stroke text and add to path for clipping */
+ public static final int TR_STROKE_CLIP = 5;
+ /** PDF text rendering mode: Fill, then stroke text and add to path for clipping */
+ public static final int TR_FILL_STROKE_CLIP = 6;
+ /** PDF text rendering mode: Add text to path for clipping */
+ public static final int TR_CLIP = 7;
+
+ private boolean inTextObject = false;
+ private String startText;
+ private String endText;
+ private boolean useMultiByte;
+ private StringBuffer bufTJ;
+ private int textRenderingMode = TR_FILL;
+
+ private String currentFontName;
+ private double currentFontSize;
+
+ /**
+ * Main constructor.
+ */
+ public PDFTextUtil() {
+ //nop
+ }
+
+ /**
+ * Writes PDF code.
+ * @param code the PDF code to write
+ */
+ protected abstract void write(String code);
+
+ private void writeAffineTransform(AffineTransform at, StringBuffer sb) {
+ double[] lt = new double[6];
+ at.getMatrix(lt);
+ sb.append(PDFNumber.doubleOut(lt[0], DEC)).append(" ");
+ sb.append(PDFNumber.doubleOut(lt[1], DEC)).append(" ");
+ sb.append(PDFNumber.doubleOut(lt[2], DEC)).append(" ");
+ sb.append(PDFNumber.doubleOut(lt[3], DEC)).append(" ");
+ sb.append(PDFNumber.doubleOut(lt[4], DEC)).append(" ");
+ sb.append(PDFNumber.doubleOut(lt[5], DEC));
+ }
+
+ private void writeChar(char ch, StringBuffer sb) {
+ if (!useMultiByte) {
+ if (ch < 32 || ch > 127) {
+ sb.append("\\").append(Integer.toOctalString((int)ch));
+ } else {
+ switch (ch) {
+ case '(':
+ case ')':
+ case '\\':
+ sb.append("\\");
+ break;
+ default:
+ }
+ sb.append(ch);
+ }
+ } else {
+ sb.append(PDFText.toUnicodeHex(ch));
+ }
+ }
+
+ private void checkInTextObject() {
+ if (!inTextObject) {
+ throw new IllegalStateException("Not in text object");
+ }
+ }
+
+ /**
+ * Indicates whether we are in a text object or not.
+ * @return true if we are in a text object
+ */
+ public boolean isInTextObject() {
+ return inTextObject;
+ }
+
+ /**
+ * Called when a new text object should be started. Be sure to call setFont() before
+ * issuing any text painting commands.
+ */
+ public void beginTextObject() {
+ if (inTextObject) {
+ throw new IllegalStateException("Already in text object");
+ }
+ write("BT\n");
+ this.inTextObject = true;
+ }
+
+ /**
+ * Called when a text object should be ended.
+ */
+ public void endTextObject() {
+ checkInTextObject();
+ write("ET\n");
+ this.inTextObject = false;
+ initValues();
+ }
+
+ /**
+ * Resets the state fields.
+ */
+ protected void initValues() {
+ this.currentFontName = null;
+ this.currentFontSize = 0.0;
+ this.textRenderingMode = TR_FILL;
+ }
+
+ /**
+ * Creates a "q" command, pushing a copy of the entire graphics state onto the stack.
+ */
+ public void saveGraphicsState() {
+ write("q\n");
+ }
+
+ /**
+ * Creates a "Q" command, restoring the entire graphics state to its former value by popping
+ * it from the stack.
+ */
+ public void restoreGraphicsState() {
+ write("Q\n");
+ }
+
+ /**
+ * Creates a "cm" command.
+ * @param at the transformation matrix
+ */
+ public void concatMatrix(AffineTransform at) {
+ if (!at.isIdentity()) {
+ writeTJ();
+ StringBuffer sb = new StringBuffer();
+ writeAffineTransform(at, sb);
+ sb.append(" cm\n");
+ write(sb.toString());
+ }
+ }
+
+ /**
+ * Writes a "Tf" command, setting a new current font.
+ * @param fontName the name of the font to select
+ * @param fontSize the font size (in points)
+ */
+ public void writeTf(String fontName, double fontSize) {
+ checkInTextObject();
+ write("/" + fontName + " " + PDFNumber.doubleOut(fontSize) + " Tf\n");
+
+ this.startText = useMultiByte ? "<" : "(";
+ this.endText = useMultiByte ? ">" : ")";
+ }
+
+ /**
+ * Updates the current font. This method only writes a "Tf" if the current font changes.
+ * @param fontName the name of the font to select
+ * @param fontSize the font size (in points)
+ * @param multiByte true indicates the font is a multi-byte font, false means single-byte
+ */
+ public void updateTf(String fontName, double fontSize, boolean multiByte) {
+ checkInTextObject();
+ if (!fontName.equals(this.currentFontName) || (fontSize != this.currentFontSize)) {
+ writeTJ();
+ this.currentFontName = fontName;
+ this.currentFontSize = fontSize;
+ this.useMultiByte = multiByte;
+ writeTf(fontName, fontSize);
+ }
+ }
+
+ /**
+ * Sets the text rendering mode.
+ * @param mode the rendering mode (value 0 to 7, see PDF Spec, constants: TR_*)
+ */
+ public void setTextRenderingMode(int mode) {
+ if (mode < 0 || mode > 7) {
+ throw new IllegalArgumentException(
+ "Illegal value for text rendering mode. Expected: 0-7");
+ }
+ if (mode != this.textRenderingMode) {
+ writeTJ();
+ this.textRenderingMode = mode;
+ write(this.textRenderingMode + " Tr\n");
+ }
+ }
+
+ /**
+ * Sets the text rendering mode.
+ * @param fill true if the text should be filled
+ * @param stroke true if the text should be stroked
+ * @param addToClip true if the path should be added for clipping
+ */
+ public void setTextRenderingMode(boolean fill, boolean stroke, boolean addToClip) {
+ int mode;
+ if (fill) {
+ mode = (stroke ? 2 : 0);
+ } else {
+ mode = (stroke ? 1 : 3);
+ }
+ if (addToClip) {
+ mode += 4;
+ }
+ setTextRenderingMode(mode);
+ }
+
+ /**
+ * Writes a "Tm" command, setting a new text transformation matrix.
+ * @param localTransform the new text transformation matrix
+ */
+ public void writeTextMatrix(AffineTransform localTransform) {
+ StringBuffer sb = new StringBuffer();
+ writeAffineTransform(localTransform, sb);
+ sb.append(" Tm ");
+ write(sb.toString());
+ }
+
+ /**
+ * Writes a char to the "TJ-Buffer".
+ * @param codepoint the mapped character (code point/character code)
+ */
+ public void writeTJMappedChar(char codepoint) {
+ if (bufTJ == null) {
+ bufTJ = new StringBuffer();
+ }
+ if (bufTJ.length() == 0) {
+ bufTJ.append("[").append(startText);
+ }
+ writeChar(codepoint, bufTJ);
+ }
+
+ /**
+ * Writes a glyph adjust value to the "TJ-Buffer".
+ * @param adjust the glyph adjust value in thousands of text unit space.
+ */
+ public void adjustGlyphTJ(double adjust) {
+ bufTJ.append(endText).append(" ");
+ bufTJ.append(PDFNumber.doubleOut(adjust, DEC - 4));
+ bufTJ.append(" ");
+ bufTJ.append(startText);
+ }
+
+ /**
+ * Writes a "TJ" command, writing out the accumulated buffer with the characters and glyph
+ * positioning values. The buffer is reset afterwards.
+ */
+ public void writeTJ() {
+ if (isInString()) {
+ bufTJ.append(endText).append("] TJ\n");
+ write(bufTJ.toString());
+ bufTJ.setLength(0);
+ }
+ }
+
+ private boolean isInString() {
+ return bufTJ != null && bufTJ.length() > 0;
+ }
+
+}
diff --git a/src/java/org/apache/fop/render/AbstractGenericSVGHandler.java b/src/java/org/apache/fop/render/AbstractGenericSVGHandler.java
index f74699fd5..c0c9ce88c 100644
--- a/src/java/org/apache/fop/render/AbstractGenericSVGHandler.java
+++ b/src/java/org/apache/fop/render/AbstractGenericSVGHandler.java
@@ -47,7 +47,7 @@ import org.apache.fop.svg.SVGUserAgent;
public abstract class AbstractGenericSVGHandler implements XMLHandler, RendererContextConstants {
/** logging instance */
- private static Log log = LogFactory.getLog(AbstractGenericSVGHandler.class);
+ protected static Log log = LogFactory.getLog(AbstractGenericSVGHandler.class);
/** {@inheritDoc} */
public void handleXML(RendererContext context,
diff --git a/src/java/org/apache/fop/render/afp/AFPRenderer.java b/src/java/org/apache/fop/render/afp/AFPRenderer.java
index b10f4b30f..cb3d3a433 100644
--- a/src/java/org/apache/fop/render/afp/AFPRenderer.java
+++ b/src/java/org/apache/fop/render/afp/AFPRenderer.java
@@ -940,10 +940,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer {
int x = origin.x + posInt.x;
int y = origin.y + posInt.y;
- String name = null;
- if (pageSegmentsMap != null) {
- name = (String) pageSegmentsMap.get(uri);
- }
+ String name = (String)getPageSegments().get(uri);
if (name != null) {
afpDataStream.createIncludePageSegment(name, mpts2units(x), mpts2units(y));
} else {
@@ -1543,6 +1540,13 @@ public class AFPRenderer extends AbstractPathOrientedRenderer {
return MimeConstants.MIME_AFP;
}
+ private Map getPageSegments() {
+ if (pageSegmentsMap == null) {
+ pageSegmentsMap = new java.util.HashMap();
+ }
+ return pageSegmentsMap;
+ }
+
/**
* Method to render the page extension.
* <p>
@@ -1571,17 +1575,11 @@ public class AFPRenderer extends AbstractPathOrientedRenderer {
.equals(element)) {
String name = aps.getName();
String source = aps.getValue();
- if (pageSegmentsMap == null) {
- pageSegmentsMap = new java.util.HashMap();
- }
- pageSegmentsMap.put(source, name);
+ getPageSegments().put(source, name);
} else if (AFPElementMapping.TAG_LOGICAL_ELEMENT
.equals(element)) {
String name = aps.getName();
String value = aps.getValue();
- if (pageSegmentsMap == null) {
- pageSegmentsMap = new java.util.HashMap();
- }
afpDataStream.createTagLogicalElement(name, value);
} else if (AFPElementMapping.NO_OPERATION.equals(element)) {
String content = aps.getContent();
@@ -1589,7 +1587,7 @@ public class AFPRenderer extends AbstractPathOrientedRenderer {
afpDataStream.createNoOperation(content);
}
} else if (AFPElementMapping.RESOURCE.equals(element)) {
- System.out.println("resource: " + attachment);
+ log.info("resource: " + attachment);
}
}
}
diff --git a/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java b/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java
index 4c8a3dc9f..cde464ba5 100644
--- a/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java
+++ b/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java
@@ -234,8 +234,7 @@ public class AFPRendererConfigurator extends PrintRendererConfigurator {
Configuration rendererResolutionCfg = cfg.getChild("renderer-resolution", false);
if (rendererResolutionCfg != null) {
- afpRenderer.setResolution(rendererResolutionCfg.getValueAsInteger(
- AFPRenderer.DPI_240_RESOLUTION));
+ afpRenderer.setResolution(rendererResolutionCfg.getValueAsInteger(240));
}
Configuration gocaSupportCfg = cfg.getChild("goca-enabled", false);
diff --git a/src/java/org/apache/fop/render/afp/AFPSVGHandler.java b/src/java/org/apache/fop/render/afp/AFPSVGHandler.java
index 2641e6fbe..1d469ea94 100644
--- a/src/java/org/apache/fop/render/afp/AFPSVGHandler.java
+++ b/src/java/org/apache/fop/render/afp/AFPSVGHandler.java
@@ -49,9 +49,6 @@ import org.w3c.dom.Document;
*/
public class AFPSVGHandler extends AbstractGenericSVGHandler {
- /** logging instance */
- private static Log log = LogFactory.getLog(AFPSVGHandler.class);
-
/** {@inheritDoc} */
public void handleXML(RendererContext context,
Document doc, String ns) throws Exception {
@@ -196,7 +193,10 @@ public class AFPSVGHandler extends AbstractGenericSVGHandler {
}
/** {@inheritDoc} */
- public String getNamespace() {
- return SVGDOMImplementation.SVG_NAMESPACE_URI;
+ protected void updateRendererContext(RendererContext context) {
+ //Work around a problem in Batik: Gradients cannot be done in ColorSpace.CS_GRAY
+ context.setProperty(AFPRendererContextConstants.AFP_GRAYSCALE,
+ Boolean.FALSE);
}
+
}
diff --git a/src/java/org/apache/fop/render/afp/extensions/AFPElement.java b/src/java/org/apache/fop/render/afp/extensions/AFPElement.java
index 808cd88f1..659c79a8e 100755
--- a/src/java/org/apache/fop/render/afp/extensions/AFPElement.java
+++ b/src/java/org/apache/fop/render/afp/extensions/AFPElement.java
@@ -55,7 +55,8 @@ public class AFPElement extends AbstractAFPExtensionObject {
}
}
- protected ExtensionAttachment instantiateExtensionAttachment() {
- return null;
- }
+ protected ExtensionAttachment instantiateExtensionAttachment() {
+ return new AFPPageSetup(getName());
+ }
+
}
diff --git a/src/java/org/apache/fop/render/afp/extensions/AFPElementMapping.java b/src/java/org/apache/fop/render/afp/extensions/AFPElementMapping.java
index 8d4b0ae5e..ad80399e3 100755
--- a/src/java/org/apache/fop/render/afp/extensions/AFPElementMapping.java
+++ b/src/java/org/apache/fop/render/afp/extensions/AFPElementMapping.java
@@ -19,8 +19,6 @@
package org.apache.fop.render.afp.extensions;
-import java.util.HashMap;
-
import org.apache.fop.fo.ElementMapping;
import org.apache.fop.fo.FONode;
@@ -39,7 +37,7 @@ public class AFPElementMapping extends ElementMapping {
public static final String PAGE = "page";
/** page group element */
- public static final String PAGE_GROUP = "page-group";
+// public static final String PAGE_GROUP = "page-group";
/** tag logical element */
public static final String TAG_LOGICAL_ELEMENT = "tag-logical-element";
@@ -78,9 +76,12 @@ public class AFPElementMapping extends ElementMapping {
protected void initialize() {
if (foObjs == null) {
- foObjs = new HashMap();
+ super.foObjs = new java.util.HashMap();
foObjs.put(PAGE, new AFPPageSetupMaker());
- // foObjs.put(PAGE_GROUP, new AFPMaker());
+// foObjs.put(
+// PAGE_GROUP,
+// new AFPPageGroupMaker()
+// );
foObjs.put(
TAG_LOGICAL_ELEMENT,
new AFPTagLogicalElementMaker());
@@ -94,7 +95,6 @@ public class AFPElementMapping extends ElementMapping {
NO_OPERATION,
new AFPNoOperationMaker());
}
-
}
static class AFPPageSetupMaker extends ElementMapping.Maker {
@@ -126,4 +126,10 @@ public class AFPElementMapping extends ElementMapping {
return new AFPElement(parent, NO_OPERATION);
}
}
+
+// static class AFPPageGroupMaker extends ElementMapping.Maker {
+// public FONode make(FONode parent) {
+// return new AFPElement(parent, PAGE_GROUP);
+// }
+// }
}
diff --git a/src/java/org/apache/fop/render/afp/extensions/AFPExtensionHandler.java b/src/java/org/apache/fop/render/afp/extensions/AFPExtensionHandler.java
index 7fdf7cd11..fca486279 100644
--- a/src/java/org/apache/fop/render/afp/extensions/AFPExtensionHandler.java
+++ b/src/java/org/apache/fop/render/afp/extensions/AFPExtensionHandler.java
@@ -54,7 +54,7 @@ public class AFPExtensionHandler extends DefaultHandler
|| localName.equals(AFPElementMapping.INCLUDE_PAGE_OVERLAY)
|| localName.equals(AFPElementMapping.INCLUDE_PAGE_SEGMENT)
|| localName.equals(AFPElementMapping.PAGE)
- || localName.equals(AFPElementMapping.PAGE_GROUP)) {
+ /*|| localName.equals(AFPElementMapping.PAGE_GROUP)*/) {
//handled in endElement
} else {
handled = false;
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 57886f89c..f8dd9a1ed 100644
--- a/src/java/org/apache/fop/render/afp/fonts/OutlineFont.java
+++ b/src/java/org/apache/fop/render/afp/fonts/OutlineFont.java
@@ -174,11 +174,8 @@ public class OutlineFont extends AFPFont {
return charSet.mapChar(c);
}
- /**
- * Get the encoding of the font.
- * @return the encoding
- */
- public String getEncoding() {
+ /** {@inheritDoc} */
+ public String getEncodingName() {
return charSet.getEncoding();
}
} \ No newline at end of file
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 a61f97ab5..44dcd0e9f 100644
--- a/src/java/org/apache/fop/render/afp/fonts/RasterFont.java
+++ b/src/java/org/apache/fop/render/afp/fonts/RasterFont.java
@@ -229,11 +229,8 @@ public class RasterFont extends AFPFont {
return charSet.mapChar(c);
}
- /**
- * Get the encoding of the font.
- * @return the encoding
- */
- public String getEncoding() {
+ /** {@inheritDoc} */
+ public String getEncodingName() {
return charSet.getEncoding();
}
diff --git a/src/java/org/apache/fop/render/afp/modca/AbstractAFPObject.java b/src/java/org/apache/fop/render/afp/modca/AbstractAFPObject.java
index 26d42b2d4..106454ad6 100644
--- a/src/java/org/apache/fop/render/afp/modca/AbstractAFPObject.java
+++ b/src/java/org/apache/fop/render/afp/modca/AbstractAFPObject.java
@@ -44,7 +44,7 @@ public abstract class AbstractAFPObject {
* DataStream objects must implement the writeDataStream()
* method to write its data to the given OutputStream
* @param os The outputsteam stream
- * @throws java.io.IOException in the event that an I/O exception occurred
+ * @throws java.io.IOException
*/
public abstract void writeDataStream(OutputStream os) throws IOException;
@@ -52,10 +52,10 @@ public abstract class AbstractAFPObject {
* Help method to write a set of AFPObjects to the AFP datastream.
* @param objects a list of AFPObjects
* @param os The stream to write to
- * @throws java.io.IOException in the event that an I/O exception occurred
+ * @throws java.io.IOException
*/
protected void writeObjects(Collection/*<AbstractAFPObject>*/ objects, OutputStream os)
- throws IOException {
+ throws IOException {
if (objects != null) {
for (Iterator it = objects.iterator(); it.hasNext();) {
Object obj1 = it.next();
@@ -63,5 +63,7 @@ public abstract class AbstractAFPObject {
obj.writeDataStream(os);
}
}
+
}
-} \ No newline at end of file
+}
+
diff --git a/src/java/org/apache/fop/render/afp/modca/AbstractDescriptor.java b/src/java/org/apache/fop/render/afp/modca/AbstractDescriptor.java
index 29c619d32..6d827766e 100644
--- a/src/java/org/apache/fop/render/afp/modca/AbstractDescriptor.java
+++ b/src/java/org/apache/fop/render/afp/modca/AbstractDescriptor.java
@@ -28,22 +28,22 @@ public abstract class AbstractDescriptor extends AbstractAFPObject {
/** height of this descriptor */
protected int height = 0;
/** width resolution of this descriptor */
- protected int widthRes = 0;
+ protected int widthResolution = 0;
/** height resolution of this descriptor */
- protected int heightRes = 0;
+ protected int heightResolution = 0;
/**
* Constructor a PresentationTextDescriptor for the specified
* width and height.
* @param width The width of the page.
* @param height The height of the page.
- * @param widthRes The width resolution of the page.
- * @param heightRes The height resolution of the page.
+ * @param widthResolution The width resolution of the page.
+ * @param heightResolution The height resolution of the page.
*/
- public AbstractDescriptor(int width, int height, int widthRes, int heightRes) {
+ public AbstractDescriptor(int width, int height, int widthResolution, int heightResolution) {
this.width = width;
this.height = height;
- this.widthRes = widthRes;
- this.heightRes = heightRes;
+ this.widthResolution = widthResolution;
+ this.heightResolution = heightResolution;
}
}
diff --git a/src/java/org/apache/fop/render/afp/modca/AbstractNamedAFPObject.java b/src/java/org/apache/fop/render/afp/modca/AbstractNamedAFPObject.java
index 393cff84b..09fa33f8f 100644
--- a/src/java/org/apache/fop/render/afp/modca/AbstractNamedAFPObject.java
+++ b/src/java/org/apache/fop/render/afp/modca/AbstractNamedAFPObject.java
@@ -38,7 +38,7 @@ public abstract class AbstractNamedAFPObject extends AbstractStructuredAFPObject
* The name of the object in EBCIDIC bytes
*/
protected byte[] nameBytes;
-
+
/**
* Default constructor
*/
@@ -51,19 +51,17 @@ public abstract class AbstractNamedAFPObject extends AbstractStructuredAFPObject
* @param name the object name
*/
protected AbstractNamedAFPObject(String name) {
- int nameLen = getNameLength();
- if (name.length() < nameLen) {
- this.name = (name + " ").substring(0, nameLen);
- } else if (name.length() > nameLen) {
- log.warn("Constructor:: name truncated to " + nameLen + " chars: " + name);
- this.name = name.substring(0, nameLen);
- } else {
- this.name = name;
+ this.name = name;
+ if (name.length() < 8) {
+ name = (name + " ").substring(0, 8);
+ } else if (name.length() > 8) {
+ log.warn("Constructor:: name truncated to 8 chars" + name);
+ name = name.substring(0, 8);
}
try {
- this.nameBytes = name.getBytes(AFPConstants.EBCIDIC_ENCODING);
+ nameBytes = name.getBytes(AFPConstants.EBCIDIC_ENCODING);
} catch (UnsupportedEncodingException usee) {
- this.nameBytes = name.getBytes();
+ nameBytes = name.getBytes();
log.warn(
"Constructor:: UnsupportedEncodingException translating the name "
+ name);
@@ -82,5 +80,6 @@ public abstract class AbstractNamedAFPObject extends AbstractStructuredAFPObject
*/
public String getName() {
return name;
- }
+ }
+
}
diff --git a/src/java/org/apache/fop/render/afp/modca/AbstractPageObject.java b/src/java/org/apache/fop/render/afp/modca/AbstractPageObject.java
index f373b5bf7..984aa44c9 100644
--- a/src/java/org/apache/fop/render/afp/modca/AbstractPageObject.java
+++ b/src/java/org/apache/fop/render/afp/modca/AbstractPageObject.java
@@ -310,7 +310,7 @@ public abstract class AbstractPageObject extends AbstractResourceGroupContainer
private PresentationTextObject getPresentationTextObject() {
if (presentationTextObject == null) {
this.presentationTextObject = new PresentationTextObject();
- addObject(this.presentationTextObject);
+ super.addObject(this.presentationTextObject);
}
return presentationTextObject;
}
diff --git a/src/java/org/apache/fop/render/afp/modca/ImageContent.java b/src/java/org/apache/fop/render/afp/modca/ImageContent.java
index 4aea02901..726c58762 100644
--- a/src/java/org/apache/fop/render/afp/modca/ImageContent.java
+++ b/src/java/org/apache/fop/render/afp/modca/ImageContent.java
@@ -18,13 +18,11 @@
/* $Id$ */
package org.apache.fop.render.afp.modca;
-
import java.io.IOException;
import java.io.OutputStream;
import org.apache.fop.render.afp.tools.BinaryUtils;
/**
- * Image content IOCA object
*/
public class ImageContent extends AbstractStructuredAFPObject {
@@ -55,27 +53,27 @@ public class ImageContent extends AbstractStructuredAFPObject {
/**
* The image size parameter
*/
- private ImageSizeParameter imageSizeParam = null;
+ private ImageSizeParameter _imageSizeParameter = null;
/**
* The image encoding
*/
- private byte encoding = 0x03;
+ private byte _encoding = 0x03;
/**
* The image ide size
*/
- private byte size = 1;
+ private byte _size = 1;
/**
* The image compression
*/
- private byte compression = (byte)0xC0;
+ private byte _compression = (byte)0xC0;
/**
* The image color model
*/
- private byte colorModel = 0x01;
+ private byte _colorModel = 0x01;
/**
* The image data
@@ -97,39 +95,39 @@ public class ImageContent extends AbstractStructuredAFPObject {
* @param vsize The vertival size of the image.
*/
public void setImageSize(int hresol, int vresol, int hsize, int vsize) {
- this.imageSizeParam = new ImageSizeParameter(hresol, vresol, hsize, vsize);
+ _imageSizeParameter = new ImageSizeParameter(hresol, vresol, hsize, vsize);
}
/**
* Sets the image encoding.
- * @param enc The image encoding.
+ * @param encoding The image encoding.
*/
- public void setImageEncoding(byte enc) {
- this.encoding = enc;
+ public void setImageEncoding(byte encoding) {
+ _encoding = encoding;
}
/**
* Sets the image compression.
- * @param comp The image compression.
+ * @param compression The image compression.
*/
- public void setImageCompression(byte comp) {
- this.compression = comp;
+ public void setImageCompression(byte compression) {
+ _compression = compression;
}
/**
* Sets the image IDE size.
- * @param siz The IDE size.
+ * @param size The IDE size.
*/
- public void setImageIDESize(byte siz) {
- this.size = siz;
+ public void setImageIDESize(byte size) {
+ _size = size;
}
/**
* Sets the image IDE color model.
- * @param model the IDE color model.
+ * @param colorModel the IDE color model.
*/
- public void setImageIDEColorModel(byte model) {
- this.colorModel = model;
+ public void setImageIDEColorModel(byte colorModel) {
+ _colorModel = colorModel;
}
/**
@@ -144,8 +142,8 @@ public class ImageContent extends AbstractStructuredAFPObject {
* {@inheritDoc}
*/
protected void writeContent(OutputStream os) throws IOException {
- if (imageSizeParam != null) {
- imageSizeParam.writeDataStream(os);
+ if (_imageSizeParameter != null) {
+ _imageSizeParameter.writeDataStream(os);
}
os.write(getImageEncodingParameter());
os.write(getImageIDESizeParameter());
@@ -190,16 +188,21 @@ public class ImageContent extends AbstractStructuredAFPObject {
* @return byte[] The data stream.
*/
private byte[] getImageDataStart(int len) {
- byte[] imageDataStartData = new byte[] {
+
+ byte[] data = new byte[] {
(byte)0xFE, // ID
(byte)0x92, // ID
0x00, // Length
0x00, // Length
};
+
byte[] l = BinaryUtils.convert(len, 2);
- imageDataStartData[2] = l[0];
- imageDataStartData[3] = l[1];
- return imageDataStartData;
+ data[2] = l[0];
+ data[3] = l[1];
+
+
+ return data;
+
}
/**
@@ -207,13 +210,16 @@ public class ImageContent extends AbstractStructuredAFPObject {
* @return byte[] The data stream.
*/
private byte[] getImageEncodingParameter() {
- byte[] imageEncParamData = new byte[] {
+
+ byte[] data = new byte[] {
(byte)0x95, // ID
0x02, // Length
- encoding,
+ _encoding,
0x01, // RECID
};
- return imageEncParamData;
+
+ return data;
+
}
/**
@@ -221,8 +227,9 @@ public class ImageContent extends AbstractStructuredAFPObject {
* @return byte[] The data stream.
*/
private byte[] getExternalAlgorithmParameter() {
- if (encoding == (byte)0x83 && compression != 0) {
- byte[] extAlgParamData = new byte[] {
+
+ if (_encoding == (byte)0x83 && _compression != 0) {
+ byte[] data = new byte[] {
(byte)0x95, // ID
0x00, // Length
0x10, // ALGTYPE = Compression Algorithm
@@ -231,13 +238,13 @@ public class ImageContent extends AbstractStructuredAFPObject {
0x00, // Reserved
0x00, // Reserved
0x00, // Reserved
- compression, // MARKER
+ _compression, // MARKER
0x00, // Reserved
0x00, // Reserved
0x00, // Reserved
};
- extAlgParamData[1] = (byte)(extAlgParamData.length - 2);
- return extAlgParamData;
+ data[1] = (byte)(data.length - 2);
+ return data;
}
return new byte[0];
}
@@ -247,12 +254,15 @@ public class ImageContent extends AbstractStructuredAFPObject {
* @return byte[] The data stream.
*/
private byte[] getImageIDESizeParameter() {
- byte[] imageIDESizeParamData = new byte[] {
+
+ byte[] data = new byte[] {
(byte)0x96, // ID
0x01, // Length
- size,
+ _size,
};
- return imageIDESizeParamData;
+
+ return data;
+
}
/**
@@ -260,14 +270,15 @@ public class ImageContent extends AbstractStructuredAFPObject {
* @return byte[] The data stream.
*/
private byte[] getIDEStructureParameter() {
- if (colorModel != 0 && size == 24) {
- byte bits = (byte)(size / 3);
- byte[] ideStructParamData = new byte[] {
+
+ if (_colorModel != 0 && _size == 24) {
+ byte bits = (byte)(_size / 3);
+ byte[] data = new byte[] {
(byte)0x9B, // ID
0x00, // Length
0x00, // FLAGS
0x00, // Reserved
- colorModel, // COLOR MODEL
+ _colorModel, // COLOR MODEL
0x00, // Reserved
0x00, // Reserved
0x00, // Reserved
@@ -275,9 +286,10 @@ public class ImageContent extends AbstractStructuredAFPObject {
bits,
bits,
};
- ideStructParamData[1] = (byte)(ideStructParamData.length - 2);
- return ideStructParamData;
+ data[1] = (byte)(data.length - 2);
+ return data;
}
return new byte[0];
}
+
}
diff --git a/src/java/org/apache/fop/render/afp/modca/ImageDataDescriptor.java b/src/java/org/apache/fop/render/afp/modca/ImageDataDescriptor.java
index d1c2c11c7..9250f0c7f 100644
--- a/src/java/org/apache/fop/render/afp/modca/ImageDataDescriptor.java
+++ b/src/java/org/apache/fop/render/afp/modca/ImageDataDescriptor.java
@@ -27,17 +27,10 @@ import org.apache.fop.render.afp.tools.BinaryUtils;
*/
public class ImageDataDescriptor extends AbstractAFPObject {
- /** x resolution */
- private int xresol = 0;
-
- /** y resolution */
- private int yresol = 0;
-
- /** width */
- private int width = 0;
-
- /** height */
- private int height = 0;
+ private int _xresol = 0;
+ private int _yresol = 0;
+ private int _width = 0;
+ private int _height = 0;
/**
* Constructor for a ImageDataDescriptor for the specified
@@ -48,25 +41,26 @@ public class ImageDataDescriptor extends AbstractAFPObject {
* @param height The height of the height.
*/
public ImageDataDescriptor(int xresol, int yresol, int width, int height) {
- this.xresol = xresol;
- this.yresol = yresol;
- this.width = width;
- this.height = height;
+
+ _xresol = xresol;
+ _yresol = yresol;
+ _width = width;
+ _height = height;
+
}
/**
- * {@inheritDoc}
+ * Accessor method to write the AFP datastream for the Image Data Descriptor
+ * @param os The stream to write to
+ * @throws java.io.IOException
*/
- public void writeDataStream(OutputStream os) throws IOException {
- byte[] len = BinaryUtils.convert(21, 2);
- byte[] xres = BinaryUtils.convert(xresol, 2);
- byte[] yres = BinaryUtils.convert(yresol, 2);
- byte[] w = BinaryUtils.convert(width, 2);
- byte[] h = BinaryUtils.convert(height, 2);
+ public void writeDataStream(OutputStream os)
+ throws IOException {
+
byte[] data = new byte[] {
0x5A,
- len[0],
- len[1],
+ 0x00,
+ 0x20,
(byte) 0xD3,
(byte) 0xA6,
(byte) 0xFB,
@@ -74,19 +68,42 @@ public class ImageDataDescriptor extends AbstractAFPObject {
0x00, // Reserved
0x00, // Reserved
0x00, // Unit base - 10 Inches
- xres[0], // XRESOL
- xres[1], //
- yres[0], // YRESOL
- yres[1], //
- w[0], // XSIZE
- w[1], //
- h[0], // YSIZE
- h[1], //
+ 0x00, // XRESOL
+ 0x00, //
+ 0x00, // YRESOL
+ 0x00, //
+ 0x00, // XSIZE
+ 0x00, //
+ 0x00, // YSIZE
+ 0x00, //
(byte)0xF7, // ID = Set IOCA Function Set
0x02, // Length
0x01, // Category = Function set identifier
0x0B, // FCNSET = IOCA FS 11
};
+
+ byte[] l = BinaryUtils.convert(data.length - 1, 2);
+ data[1] = l[0];
+ data[2] = l[1];
+
+ byte[] x = BinaryUtils.convert(_xresol, 2);
+ data[10] = x[0];
+ data[11] = x[1];
+
+ byte[] y = BinaryUtils.convert(_yresol, 2);
+ data[12] = y[0];
+ data[13] = y[1];
+
+ byte[] w = BinaryUtils.convert(_width, 2);
+ data[14] = w[0];
+ data[15] = w[1];
+
+ byte[] h = BinaryUtils.convert(_height, 2);
+ data[16] = h[0];
+ data[17] = h[1];
+
os.write(data);
+
}
+
}
diff --git a/src/java/org/apache/fop/render/afp/modca/ImageSegment.java b/src/java/org/apache/fop/render/afp/modca/ImageSegment.java
index 2876e8348..ea8eb334b 100644
--- a/src/java/org/apache/fop/render/afp/modca/ImageSegment.java
+++ b/src/java/org/apache/fop/render/afp/modca/ImageSegment.java
@@ -18,7 +18,6 @@
/* $Id$ */
package org.apache.fop.render.afp.modca;
-
import java.io.IOException;
import java.io.OutputStream;
@@ -165,6 +164,7 @@ public class ImageSegment extends AbstractNamedAFPObject {
* {@inheritDoc}
*/
protected void writeEnd(OutputStream os) throws IOException {
+
byte[] data = new byte[] {
0x71, // ID
0x00, // Length
diff --git a/src/java/org/apache/fop/render/afp/modca/ObjectAreaDescriptor.java b/src/java/org/apache/fop/render/afp/modca/ObjectAreaDescriptor.java
index aa35db10e..7c940148b 100644
--- a/src/java/org/apache/fop/render/afp/modca/ObjectAreaDescriptor.java
+++ b/src/java/org/apache/fop/render/afp/modca/ObjectAreaDescriptor.java
@@ -35,11 +35,11 @@ public class ObjectAreaDescriptor extends AbstractDescriptor {
* and object height.
* @param width The page width.
* @param height The page height.
- * @param widthRes The page width resolution.
- * @param heightRes The page height resolution.
+ * @param widthResolution The page width resolution.
+ * @param heightResolution The page height resolution.
*/
- public ObjectAreaDescriptor(int width, int height, int widthRes, int heightRes) {
- super(width, height, widthRes, heightRes);
+ public ObjectAreaDescriptor(int width, int height, int widthResolution, int heightResolution) {
+ super(width, height, widthResolution, heightResolution);
}
/**
@@ -47,7 +47,8 @@ public class ObjectAreaDescriptor extends AbstractDescriptor {
* @param os The stream to write to
* @throws java.io.IOException thrown if an I/O exception of some sort has occurred
*/
- public void writeDataStream(OutputStream os) throws IOException {
+ public void writeDataStream(OutputStream os)
+ throws IOException {
byte[] data = new byte[29];
data[0] = 0x5A;
@@ -71,12 +72,12 @@ public class ObjectAreaDescriptor extends AbstractDescriptor {
data[15] = 0x00; // YaoBase = 10 inches
// XaoUnits
- byte[] xdpi = BinaryUtils.convert(this.widthRes * 10, 2);
+ byte[] xdpi = BinaryUtils.convert(widthResolution * 10, 2);
data[16] = xdpi[0];
data[17] = xdpi[1];
// YaoUnits
- byte[] ydpi = BinaryUtils.convert(this.heightRes * 10, 2);
+ byte[] ydpi = BinaryUtils.convert(heightResolution * 10, 2);
data[18] = ydpi[0];
data[19] = ydpi[1];
@@ -84,16 +85,18 @@ public class ObjectAreaDescriptor extends AbstractDescriptor {
data[21] = 0x4C; // tid = Object Area Size
data[22] = 0x02; // Size Type
- byte[] x = BinaryUtils.convert(this.width, 3);
+ byte[] x = BinaryUtils.convert(width, 3);
data[23] = x[0];
data[24] = x[1];
data[25] = x[2];
- byte[] y = BinaryUtils.convert(this.height, 3);
+ byte[] y = BinaryUtils.convert(height, 3);
data[26] = y[0];
data[27] = y[1];
data[28] = y[2];
os.write(data);
+
}
+
} \ No newline at end of file
diff --git a/src/java/org/apache/fop/render/afp/modca/PageDescriptor.java b/src/java/org/apache/fop/render/afp/modca/PageDescriptor.java
index ffa5f3c85..1cdec7616 100644
--- a/src/java/org/apache/fop/render/afp/modca/PageDescriptor.java
+++ b/src/java/org/apache/fop/render/afp/modca/PageDescriptor.java
@@ -35,11 +35,11 @@ public class PageDescriptor extends AbstractDescriptor {
* and page height.
* @param width The page width.
* @param height The page height.
- * @param widthRes The page width resolution
- * @param heightRes The page height resolution
+ * @param widthResolution The page width resolution
+ * @param heightResolution The page height resolution
*/
- public PageDescriptor(int width, int height, int widthRes, int heightRes) {
- super(width, height, widthRes, heightRes);
+ public PageDescriptor(int width, int height, int widthResolution, int heightResolution) {
+ super(width, height, widthResolution, heightResolution);
}
/**
@@ -68,12 +68,12 @@ public class PageDescriptor extends AbstractDescriptor {
data[10] = 0x00; // YpgBase = 10 inches
// XpgUnits
- byte[] xdpi = BinaryUtils.convert(widthRes * 10, 2);
+ byte[] xdpi = BinaryUtils.convert(widthResolution * 10, 2);
data[11] = xdpi[0];
data[12] = xdpi[1];
// YpgUnits
- byte[] ydpi = BinaryUtils.convert(heightRes * 10, 2);
+ byte[] ydpi = BinaryUtils.convert(heightResolution * 10, 2);
data[13] = ydpi[0];
data[14] = ydpi[1];
diff --git a/src/java/org/apache/fop/render/afp/modca/PageObject.java b/src/java/org/apache/fop/render/afp/modca/PageObject.java
index bad80bcc1..9a8646ba0 100644
--- a/src/java/org/apache/fop/render/afp/modca/PageObject.java
+++ b/src/java/org/apache/fop/render/afp/modca/PageObject.java
@@ -56,14 +56,14 @@ public class PageObject extends AbstractPageObject {
* the height of the page.
* @param rotation
* the rotation of the page.
- * @param widthRes
+ * @param widthResolution
* the width resolution of the page.
- * @param heightRes
+ * @param heightResolution
* the height resolution of the page.
*/
public PageObject(String name, int width, int height, int rotation,
- int widthRes, int heightRes) {
- super(name, width, height, rotation, widthRes, heightRes);
+ int widthResolution, int heightResolution) {
+ super(name, width, height, rotation, widthResolution, heightResolution);
}
/**
diff --git a/src/java/org/apache/fop/render/afp/modca/PresentationTextData.java b/src/java/org/apache/fop/render/afp/modca/PresentationTextData.java
index 30a78d6c9..98beb96f7 100644
--- a/src/java/org/apache/fop/render/afp/modca/PresentationTextData.java
+++ b/src/java/org/apache/fop/render/afp/modca/PresentationTextData.java
@@ -56,42 +56,42 @@ public class PresentationTextData extends AbstractAFPObject {
/**
* The afp data relating to this presentaion text data.
*/
- private ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
+ private ByteArrayOutputStream _baos = new ByteArrayOutputStream(1024);
/**
* The current x coordinate.
*/
- private int currentXCoordinate = -1;
+ private int _currentXCoordinate = -1;
/**
* The current y cooridnate
*/
- private int currentYCoordinate = -1;
+ private int _currentYCoordinate = -1;
/**
* The current font
*/
- private String currentFont = "";
+ private String _currentFont = "";
/**
* The current orientation
*/
- private int currentOrientation = 0;
+ private int _currentOrientation = 0;
/**
* The current color
*/
- private Color currentColor = new Color(0, 0, 0);
+ private Color _currentColor = new Color(0, 0, 0);
/**
* The current variable space increment
*/
- private int currentVariableSpaceCharacterIncrement = 0;
+ private int _currentVariableSpaceCharacterIncrement = 0;
/**
* The current inter character adjustment
*/
- private int currentInterCharacterAdjustment = 0;
+ private int _currentInterCharacterAdjustment = 0;
/**
* Default constructor for the PresentationTextData.
@@ -112,7 +112,7 @@ public class PresentationTextData extends AbstractAFPObject {
*/
public PresentationTextData(boolean controlInd) {
- baos.write(new byte[] {0x5A, // Structured field identifier
+ _baos.write(new byte[] { 0x5A, // Structured field identifier
0x00, // Record length byte 1
0x00, // Record length byte 2
(byte) 0xD3, // PresentationTextData identifier byte 1
@@ -124,7 +124,7 @@ public class PresentationTextData extends AbstractAFPObject {
}, 0, 9);
if (controlInd) {
- baos.write(new byte[] {0x2B, (byte) 0xD3}, 0, 2);
+ _baos.write(new byte[] { 0x2B, (byte) 0xD3 }, 0, 2);
}
}
@@ -142,13 +142,13 @@ public class PresentationTextData extends AbstractAFPObject {
private void setCodedFont(byte font, ByteArrayOutputStream afpdata) {
// Avoid unnecessary specification of the font
- if (String.valueOf(font).equals(currentFont)) {
+ if (String.valueOf(font).equals(_currentFont)) {
return;
} else {
- currentFont = String.valueOf(font);
+ _currentFont = String.valueOf(font);
}
- afpdata.write(new byte[] {0x03, (byte) 0xF1, font}, 0, 3);
+ afpdata.write(new byte[] { 0x03, (byte) 0xF1, font, }, 0, 3);
}
@@ -167,9 +167,9 @@ public class PresentationTextData extends AbstractAFPObject {
byte[] b = BinaryUtils.convert(coordinate, 2);
- afpdata.write(new byte[] {0x04, (byte) 0xC7, b[0], b[1]}, 0, 4);
+ afpdata.write(new byte[] { 0x04, (byte) 0xC7, b[0], b[1], }, 0, 4);
- currentXCoordinate = coordinate;
+ _currentXCoordinate = coordinate;
}
@@ -188,9 +188,9 @@ public class PresentationTextData extends AbstractAFPObject {
byte[] b = BinaryUtils.convert(coordinate, 2);
- afpdata.write(new byte[] {0x04, (byte) 0xD3, b[0], b[1]}, 0, 4);
+ afpdata.write(new byte[] { 0x04, (byte) 0xD3, b[0], b[1], }, 0, 4);
- currentYCoordinate = coordinate;
+ _currentYCoordinate = coordinate;
}
@@ -214,7 +214,7 @@ public class PresentationTextData extends AbstractAFPObject {
"Transparent data is longer than 253 bytes: " + data);
}
- afpdata.write(new byte[] {BinaryUtils.convert(l)[0], (byte) 0xDB},
+ afpdata.write(new byte[] { BinaryUtils.convert(l)[0], (byte) 0xDB, },
0, 2);
afpdata.write(data, 0, data.length);
@@ -236,7 +236,7 @@ public class PresentationTextData extends AbstractAFPObject {
private void drawBaxisRule(int length, int width,
ByteArrayOutputStream afpdata) {
- afpdata.write(new byte[] {0x07, // Length
+ afpdata.write(new byte[] { 0x07, // Length
(byte) 0xE7, // Type
}, 0, 2);
@@ -266,7 +266,7 @@ public class PresentationTextData extends AbstractAFPObject {
private void drawIaxisRule(int length, int width,
ByteArrayOutputStream afpdata) {
- afpdata.write(new byte[] {0x07, // Length
+ afpdata.write(new byte[] { 0x07, // Length
(byte) 0xE5, // Type
}, 0, 2);
@@ -284,7 +284,7 @@ public class PresentationTextData extends AbstractAFPObject {
/**
* Create the presentation text data for the byte array of data.
*
- * @param fontReference
+ * @param fontNumber
* The font resource identifier.
* @param x
* The x coordinate for the text data.
@@ -300,64 +300,64 @@ public class PresentationTextData extends AbstractAFPObject {
* The inter character adjustment.
* @param data
* The text data to be created.
- * @throws MaximumSizeExceededException if the maximum size is exceeded
+ * @throws MaximumSizeExceededException
*/
- public void createTextData(int fontReference, int x, int y, int orientation,
+ public void createTextData(int fontNumber, int x, int y, int orientation,
Color col, int vsci, int ica, byte[] data)
throws MaximumSizeExceededException {
ByteArrayOutputStream afpdata = new ByteArrayOutputStream();
- if (currentOrientation != orientation) {
+ if (_currentOrientation != orientation) {
setTextOrientation(orientation, afpdata);
- currentOrientation = orientation;
- currentXCoordinate = -1;
- currentYCoordinate = -1;
+ _currentOrientation = orientation;
+ _currentXCoordinate = -1;
+ _currentYCoordinate = -1;
}
// Avoid unnecessary specification of the Y co-ordinate
- if (y != currentYCoordinate) {
+ if (y != _currentYCoordinate) {
absoluteMoveBaseline(y, afpdata);
- currentXCoordinate = -1;
+ _currentXCoordinate = -1;
}
// Avoid unnecessary specification of the X co-ordinate
- if (x != currentXCoordinate) {
+ if (x != _currentXCoordinate) {
absoluteMoveInline(x, afpdata);
}
// Avoid unnecessary specification of the variable space increment
- if (vsci != currentVariableSpaceCharacterIncrement) {
+ if (vsci != _currentVariableSpaceCharacterIncrement) {
setVariableSpaceCharacterIncrement(vsci, afpdata);
- currentVariableSpaceCharacterIncrement = vsci;
+ _currentVariableSpaceCharacterIncrement = vsci;
}
// Avoid unnecessary specification of the inter character adjustment
- if (ica != currentInterCharacterAdjustment) {
+ if (ica != _currentInterCharacterAdjustment) {
setInterCharacterAdjustment(ica, afpdata);
- currentInterCharacterAdjustment = ica;
+ _currentInterCharacterAdjustment = ica;
}
// Avoid unnecessary specification of the text color
- if (!col.equals(currentColor)) {
+ if (!col.equals(_currentColor)) {
setExtendedTextColor(col, afpdata);
- currentColor = col;
+ _currentColor = col;
}
- setCodedFont(BinaryUtils.convert(fontReference)[0], afpdata);
+ setCodedFont(BinaryUtils.convert(fontNumber)[0], afpdata);
addTransparentData(data, afpdata);
- currentXCoordinate = -1;
+ _currentXCoordinate = -1;
int s = afpdata.size();
- if (baos.size() + s > MAX_SIZE) {
- currentXCoordinate = -1;
- currentYCoordinate = -1;
+ if (_baos.size() + s > MAX_SIZE) {
+ _currentXCoordinate = -1;
+ _currentYCoordinate = -1;
throw new MaximumSizeExceededException();
}
byte[] outputdata = afpdata.toByteArray();
- baos.write(outputdata, 0, outputdata.length);
+ _baos.write(outputdata, 0, outputdata.length);
}
@@ -379,31 +379,30 @@ public class PresentationTextData extends AbstractAFPObject {
* The orientation of the text data.
* @param col
* The text color.
- * @throws MaximumSizeExceededException if the maximum size is exceeded
*/
public void createLineData(int x1, int y1, int x2, int y2, int thickness,
int orientation, Color col) throws MaximumSizeExceededException {
ByteArrayOutputStream afpdata = new ByteArrayOutputStream();
- if (currentOrientation != orientation) {
+ if (_currentOrientation != orientation) {
setTextOrientation(orientation, afpdata);
- currentOrientation = orientation;
+ _currentOrientation = orientation;
}
// Avoid unnecessary specification of the Y coordinate
- if (y1 != currentYCoordinate) {
+ if (y1 != _currentYCoordinate) {
absoluteMoveBaseline(y1, afpdata);
}
// Avoid unnecessary specification of the X coordinate
- if (x1 != currentXCoordinate) {
+ if (x1 != _currentXCoordinate) {
absoluteMoveInline(x1, afpdata);
}
- if (!col.equals(currentColor)) {
+ if (!col.equals(_currentColor)) {
setExtendedTextColor(col, afpdata);
- currentColor = col;
+ _currentColor = col;
}
if (y1 == y2) {
@@ -416,14 +415,14 @@ public class PresentationTextData extends AbstractAFPObject {
int s = afpdata.size();
- if (baos.size() + s > MAX_SIZE) {
- currentXCoordinate = -1;
- currentYCoordinate = -1;
+ if (_baos.size() + s > MAX_SIZE) {
+ _currentXCoordinate = -1;
+ _currentYCoordinate = -1;
throw new MaximumSizeExceededException();
}
byte[] outputdata = afpdata.toByteArray();
- baos.write(outputdata, 0, outputdata.length);
+ _baos.write(outputdata, 0, outputdata.length);
}
@@ -444,7 +443,7 @@ public class PresentationTextData extends AbstractAFPObject {
private void setTextOrientation(int orientation,
ByteArrayOutputStream afpdata) {
- afpdata.write(new byte[] {0x06, (byte) 0xF7}, 0, 2);
+ afpdata.write(new byte[] { 0x06, (byte) 0xF7, }, 0, 2);
switch (orientation) {
case 90:
@@ -560,11 +559,12 @@ public class PresentationTextData extends AbstractAFPObject {
* Accessor method to write the AFP datastream for
* the text data.
* @param os The stream to write to
- * @throws java.io.IOException if an I/O exception occurred
+ * @throws java.io.IOException
*/
- public void writeDataStream(OutputStream os) throws IOException {
+ public void writeDataStream(OutputStream os)
+ throws IOException {
- byte[] data = baos.toByteArray();
+ byte[] data = _baos.toByteArray();
byte[] size = BinaryUtils.convert(data.length - 1, 2);
data[1] = size[0];
data[2] = size[1];
@@ -580,7 +580,7 @@ public class PresentationTextData extends AbstractAFPObject {
* presentation text data objects, but must eventually be terminated. This
* method terminates the control sequence.
*
- * @throws MaximumSizeExceededException if the maximum size is exceeded
+ * @throws MaximumSizeExceededException
*/
public void endControlSequence() throws MaximumSizeExceededException {
@@ -588,10 +588,12 @@ public class PresentationTextData extends AbstractAFPObject {
data[0] = 0x02;
data[1] = (byte) 0xF8;
- if (data.length + baos.size() > MAX_SIZE) {
+ if (data.length + _baos.size() > MAX_SIZE) {
throw new MaximumSizeExceededException();
}
- baos.write(data, 0, data.length);
+
+ _baos.write(data, 0, data.length);
+
}
} \ No newline at end of file
diff --git a/src/java/org/apache/fop/render/afp/modca/PresentationTextDescriptor.java b/src/java/org/apache/fop/render/afp/modca/PresentationTextDescriptor.java
index 27b3de5ca..3858f4169 100644
--- a/src/java/org/apache/fop/render/afp/modca/PresentationTextDescriptor.java
+++ b/src/java/org/apache/fop/render/afp/modca/PresentationTextDescriptor.java
@@ -52,11 +52,12 @@ public class PresentationTextDescriptor extends AbstractDescriptor {
* width and height.
* @param width The width of the page.
* @param height The height of the page.
- * @param widthRes The width resolution of the page.
- * @param heightRes The height resolution of the page.
+ * @param widthResolution The width resolution of the page.
+ * @param heightResolution The height resolution of the page.
*/
- public PresentationTextDescriptor(int width, int height, int widthRes, int heightRes) {
- super(width, height, widthRes, heightRes);
+ public PresentationTextDescriptor(int width, int height,
+ int widthResolution, int heightResolution) {
+ super(width, height, widthResolution, heightResolution);
}
/**
@@ -80,11 +81,11 @@ public class PresentationTextDescriptor extends AbstractDescriptor {
data[9] = 0x00;
data[10] = 0x00;
- byte[] xdpi = BinaryUtils.convert(widthRes * 10, 2);
+ byte[] xdpi = BinaryUtils.convert(widthResolution * 10, 2);
data[11] = xdpi[0]; // xdpi
data[12] = xdpi[1];
- byte[] ydpi = BinaryUtils.convert(heightRes * 10, 2);
+ byte[] ydpi = BinaryUtils.convert(heightResolution * 10, 2);
data[13] = ydpi[0]; // ydpi
data[14] = ydpi[1];
diff --git a/src/java/org/apache/fop/render/afp/modca/PresentationTextObject.java b/src/java/org/apache/fop/render/afp/modca/PresentationTextObject.java
index 49f7c81a8..5df9fdb4c 100644
--- a/src/java/org/apache/fop/render/afp/modca/PresentationTextObject.java
+++ b/src/java/org/apache/fop/render/afp/modca/PresentationTextObject.java
@@ -117,7 +117,6 @@ public class PresentationTextObject extends AbstractNamedAFPObject {
startPresentationTextData();
}
try {
-
currentPresentationTextData.createTextData(fontRef, x, y,
orientation, col, vsci, ica, data);
} catch (MaximumSizeExceededException msee) {
@@ -279,4 +278,4 @@ public class PresentationTextObject extends AbstractNamedAFPObject {
endControlSequence();
}
}
-} \ No newline at end of file
+}
diff --git a/src/java/org/apache/fop/render/afp/modca/TagLogicalElementBean.java b/src/java/org/apache/fop/render/afp/modca/TagLogicalElementBean.java
index 99f31ba14..29ac9eb5d 100644
--- a/src/java/org/apache/fop/render/afp/modca/TagLogicalElementBean.java
+++ b/src/java/org/apache/fop/render/afp/modca/TagLogicalElementBean.java
@@ -47,7 +47,7 @@ public class TagLogicalElementBean {
* @return the key
*/
public String getKey() {
- return this.key;
+ return key;
}
/**
@@ -55,7 +55,7 @@ public class TagLogicalElementBean {
* @return the value
*/
public String getValue() {
- return this.value;
+ return value;
}
}
diff --git a/src/java/org/apache/fop/render/java2d/CustomFontMetricsMapper.java b/src/java/org/apache/fop/render/java2d/CustomFontMetricsMapper.java
index 208bc303a..3a773a2db 100644
--- a/src/java/org/apache/fop/render/java2d/CustomFontMetricsMapper.java
+++ b/src/java/org/apache/fop/render/java2d/CustomFontMetricsMapper.java
@@ -112,7 +112,7 @@ public class CustomFontMetricsMapper extends Typeface implements FontMetricsMapp
}
/** {@inheritDoc} */
- public final String getEncoding() {
+ public final String getEncodingName() {
return null; //Not applicable to Java2D rendering
}
diff --git a/src/java/org/apache/fop/render/java2d/Java2DRenderer.java b/src/java/org/apache/fop/render/java2d/Java2DRenderer.java
index 8442af229..583d2ad2f 100644
--- a/src/java/org/apache/fop/render/java2d/Java2DRenderer.java
+++ b/src/java/org/apache/fop/render/java2d/Java2DRenderer.java
@@ -312,6 +312,8 @@ public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implem
graphics.setRenderingHint(RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_QUALITY);
}
+ graphics.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL,
+ RenderingHints.VALUE_STROKE_PURE);
// transform page based on scale factor supplied
AffineTransform at = graphics.getTransform();
diff --git a/src/java/org/apache/fop/render/java2d/SystemFontMetricsMapper.java b/src/java/org/apache/fop/render/java2d/SystemFontMetricsMapper.java
index ed7391383..19e9a4d1d 100644
--- a/src/java/org/apache/fop/render/java2d/SystemFontMetricsMapper.java
+++ b/src/java/org/apache/fop/render/java2d/SystemFontMetricsMapper.java
@@ -172,7 +172,7 @@ public class SystemFontMetricsMapper extends Typeface implements FontMetricsMapp
}
/** {@inheritDoc} */
- public String getEncoding() {
+ public String getEncodingName() {
return null; //Not applicable to Java2D rendering
}
diff --git a/src/java/org/apache/fop/render/pdf/AbstractImageAdapter.java b/src/java/org/apache/fop/render/pdf/AbstractImageAdapter.java
index b676ad6d5..caf8928ac 100644
--- a/src/java/org/apache/fop/render/pdf/AbstractImageAdapter.java
+++ b/src/java/org/apache/fop/render/pdf/AbstractImageAdapter.java
@@ -81,7 +81,7 @@ public abstract class AbstractImageAdapter implements PDFImage {
/** {@inheritDoc} */
public void setup(PDFDocument doc) {
- ICC_Profile prof = image.getICCProfile();
+ ICC_Profile prof = getEffectiveICCProfile();
PDFDeviceColorSpace pdfCS = toPDFColorSpace(getImageColorSpace());
if (prof != null) {
pdfICCStream = setupColorProfile(doc, prof, pdfCS);
@@ -100,6 +100,14 @@ public abstract class AbstractImageAdapter implements PDFImage {
}
}
+ /**
+ * Returns the effective ICC profile for the image.
+ * @return an ICC profile or null
+ */
+ protected ICC_Profile getEffectiveICCProfile() {
+ return image.getICCProfile();
+ }
+
private static PDFICCStream setupColorProfile(PDFDocument doc,
ICC_Profile prof, PDFDeviceColorSpace pdfCS) {
boolean defaultsRGB = ColorProfileUtil.isDefaultsRGB(prof);
diff --git a/src/java/org/apache/fop/render/pdf/ImageRawJPEGAdapter.java b/src/java/org/apache/fop/render/pdf/ImageRawJPEGAdapter.java
index 4b0ce4a85..1c8fceb50 100644
--- a/src/java/org/apache/fop/render/pdf/ImageRawJPEGAdapter.java
+++ b/src/java/org/apache/fop/render/pdf/ImageRawJPEGAdapter.java
@@ -18,19 +18,33 @@
/* $Id$ */
package org.apache.fop.render.pdf;
+import java.awt.color.ICC_Profile;
+import java.io.DataInput;
import java.io.IOException;
+import java.io.InputStream;
import java.io.OutputStream;
+import org.apache.commons.io.IOUtils;
+
import org.apache.xmlgraphics.image.loader.impl.ImageRawJPEG;
+import org.apache.xmlgraphics.image.loader.impl.JPEGConstants;
+import org.apache.xmlgraphics.image.loader.impl.JPEGFile;
+import org.apache.xmlgraphics.image.loader.util.ImageUtil;
import org.apache.fop.pdf.DCTFilter;
import org.apache.fop.pdf.PDFDeviceColorSpace;
import org.apache.fop.pdf.PDFDocument;
import org.apache.fop.pdf.PDFFilter;
import org.apache.fop.pdf.PDFFilterList;
+import org.apache.fop.util.ColorProfileUtil;
/**
* PDFImage implementation for the PDF renderer which handles raw JPEG images.
+ * <p>
+ * The JPEG is copied to the XObject's stream as-is but some elements (marker segments) are
+ * filtered. For example, an embedded color profile is filtered since it is already added as
+ * a PDF object and associated with the XObject. This way, the PDF file size is kept as small
+ * as possible.
*/
public class ImageRawJPEGAdapter extends AbstractImageAdapter {
@@ -68,6 +82,21 @@ public class ImageRawJPEGAdapter extends AbstractImageAdapter {
}
/** {@inheritDoc} */
+ protected ICC_Profile getEffectiveICCProfile() {
+ ICC_Profile profile = super.getEffectiveICCProfile();
+ if (profile != null
+ && profile.getNumComponents() == 3
+ && !ColorProfileUtil.isDefaultsRGB(profile)) {
+ //RGB profiles which are not sRGB don't seem to work.
+ //Without this override, the image drifts into yellow for an unknown reason.
+ //TODO Find out why this happens.
+ //Test using a JPEG images with, for example, "Adobe RGB 1998" color profile.
+ profile = null;
+ }
+ return profile;
+ }
+
+ /** {@inheritDoc} */
public int getBitsPerComponent() {
return 8;
}
@@ -84,7 +113,77 @@ public class ImageRawJPEGAdapter extends AbstractImageAdapter {
/** {@inheritDoc} */
public void outputContents(OutputStream out) throws IOException {
- getImage().writeTo(out);
+ InputStream in = getImage().createInputStream();
+ in = ImageUtil.decorateMarkSupported(in);
+ try {
+ JPEGFile jpeg = new JPEGFile(in);
+ DataInput din = jpeg.getDataInput();
+
+ //Copy the whole JPEG file except:
+ // - the ICC profile
+ //TODO Thumbnails could safely be skipped, too.
+ //TODO Metadata (XMP, IPTC, EXIF) could safely be skipped, too.
+ while (true) {
+ int reclen;
+ int segID = jpeg.readMarkerSegment();
+ switch (segID) {
+ case JPEGConstants.SOI:
+ out.write(0xFF);
+ out.write(segID);
+ break;
+ case JPEGConstants.EOI:
+ case JPEGConstants.SOS:
+ out.write(0xFF);
+ out.write(segID);
+ IOUtils.copy(in, out); //Just copy the rest!
+ return;
+ /*
+ case JPEGConstants.APP1: //Metadata
+ case JPEGConstants.APPD:
+ jpeg.skipCurrentMarkerSegment();
+ break;*/
+ case JPEGConstants.APP2: //ICC (see ICC1V42.pdf)
+ boolean skipICCProfile = false;
+ in.mark(16);
+ try {
+ reclen = jpeg.readSegmentLength();
+ // Check for ICC profile
+ byte[] iccString = new byte[11];
+ din.readFully(iccString);
+ din.skipBytes(1); //string terminator (null byte)
+
+ if ("ICC_PROFILE".equals(new String(iccString, "US-ASCII"))) {
+ skipICCProfile = (this.image.getICCProfile() != null);
+ }
+ } finally {
+ in.reset();
+ }
+ if (skipICCProfile) {
+ //ICC profile is skipped as it is already embedded as a PDF object
+ jpeg.skipCurrentMarkerSegment();
+ break;
+ }
+ default:
+ out.write(0xFF);
+ out.write(segID);
+
+ reclen = jpeg.readSegmentLength();
+ //write short
+ out.write((reclen >>> 8) & 0xFF);
+ out.write((reclen >>> 0) & 0xFF);
+ int left = reclen - 2;
+ byte[] buf = new byte[2048];
+ while (left > 0) {
+ int part = Math.min(buf.length, left);
+ din.readFully(buf, 0, part);
+ out.write(buf, 0, part);
+ left -= part;
+ }
+ }
+ }
+ } finally {
+ IOUtils.closeQuietly(in);
+ }
}
/** {@inheritDoc} */
diff --git a/src/java/org/apache/fop/render/pdf/PDFGraphics2DAdapter.java b/src/java/org/apache/fop/render/pdf/PDFGraphics2DAdapter.java
index 1a121e294..c47b944d0 100644
--- a/src/java/org/apache/fop/render/pdf/PDFGraphics2DAdapter.java
+++ b/src/java/org/apache/fop/render/pdf/PDFGraphics2DAdapter.java
@@ -89,8 +89,8 @@ public class PDFGraphics2DAdapter extends AbstractGraphics2DAdapter {
PDFGraphics2D graphics = new PDFGraphics2D(textAsShapes,
pdfInfo.fi, pdfInfo.pdfDoc,
pdfInfo.pdfContext, pdfInfo.pdfPage.referencePDF(),
- renderer.currentFontName,
- renderer.currentFontSize);
+ pdfInfo.currentFontName,
+ pdfInfo.currentFontSize);
graphics.setGraphicContext(new org.apache.xmlgraphics.java2d.GraphicContext());
AffineTransform transform = new AffineTransform();
diff --git a/src/java/org/apache/fop/render/pdf/PDFRenderer.java b/src/java/org/apache/fop/render/pdf/PDFRenderer.java
index 19f274902..55524534e 100644
--- a/src/java/org/apache/fop/render/pdf/PDFRenderer.java
+++ b/src/java/org/apache/fop/render/pdf/PDFRenderer.java
@@ -63,7 +63,6 @@ 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;
@@ -78,6 +77,8 @@ import org.apache.fop.fo.Constants;
import org.apache.fop.fo.extensions.ExtensionAttachment;
import org.apache.fop.fo.extensions.xmp.XMPMetadata;
import org.apache.fop.fonts.Font;
+import org.apache.fop.fonts.LazyFont;
+import org.apache.fop.fonts.SingleByteFont;
import org.apache.fop.fonts.Typeface;
import org.apache.fop.pdf.PDFAMode;
import org.apache.fop.pdf.PDFAction;
@@ -106,7 +107,7 @@ import org.apache.fop.pdf.PDFResourceContext;
import org.apache.fop.pdf.PDFResources;
import org.apache.fop.pdf.PDFState;
import org.apache.fop.pdf.PDFStream;
-import org.apache.fop.pdf.PDFText;
+import org.apache.fop.pdf.PDFTextUtil;
import org.apache.fop.pdf.PDFXMode;
import org.apache.fop.pdf.PDFXObject;
import org.apache.fop.render.AbstractPathOrientedRenderer;
@@ -250,21 +251,14 @@ public class PDFRenderer extends AbstractPathOrientedRenderer {
/** drawing state */
protected PDFState currentState = null;
- /** Name of currently selected font */
- protected String currentFontName = "";
- /** Size of currently selected font */
- protected int currentFontSize = 0;
+ /** Text generation utility holding the current font status */
+ protected PDFTextUtil textutil;
/** page height */
protected int pageHeight;
/** Registry of PDF filters */
protected Map filterMap;
- /**
- * true if a BT command has been written.
- */
- protected boolean inTextMode = false;
-
/** Image handler registry */
private PDFImageHandlerRegistry imageHandlerRegistry = new PDFImageHandlerRegistry();
@@ -527,7 +521,7 @@ public class PDFRenderer extends AbstractPathOrientedRenderer {
currentContext = null;
currentPage = null;
currentState = null;
- currentFontName = "";
+ this.textutil = null;
idPositions.clear();
idGoTos.clear();
@@ -665,19 +659,15 @@ public class PDFRenderer extends AbstractPathOrientedRenderer {
/** Indicates the beginning of a text object. */
protected void beginTextObject() {
- if (!inTextMode) {
- currentStream.add("BT\n");
- currentFontName = "";
- inTextMode = true;
+ if (!textutil.isInTextObject()) {
+ textutil.beginTextObject();
}
}
/** Indicates the end of a text object. */
protected void endTextObject() {
- closeText();
- if (inTextMode) {
- currentStream.add("ET\n");
- inTextMode = false;
+ if (textutil.isInTextObject()) {
+ textutil.endTextObject();
}
}
@@ -787,6 +777,11 @@ public class PDFRenderer extends AbstractPathOrientedRenderer {
currentStream = this.pdfDoc.getFactory()
.makeStream(PDFFilterList.CONTENT_FILTER, false);
+ this.textutil = new PDFTextUtil() {
+ protected void write(String code) {
+ currentStream.add(code);
+ }
+ };
currentState = new PDFState();
// Transform the PDF's default coordinate system (0,0 at lower left) to the PDFRenderer's
@@ -795,9 +790,6 @@ public class PDFRenderer extends AbstractPathOrientedRenderer {
currentState.concatenate(basicPageTransform);
currentStream.add(CTMHelper.toPDFString(basicPageTransform, false) + " cm\n");
-
- currentFontName = "";
-
super.renderPage(page);
this.pdfDoc.registerObject(currentStream);
@@ -808,6 +800,7 @@ public class PDFRenderer extends AbstractPathOrientedRenderer {
}
this.pdfDoc.addObject(currentPage);
this.pdfDoc.output(ostream);
+ this.textutil = null;
}
/** {@inheritDoc} */
@@ -841,17 +834,6 @@ public class PDFRenderer extends AbstractPathOrientedRenderer {
}
/**
- * Handle the traits for a region
- * This is used to draw the traits for the given page region.
- * (See Sect. 6.4.1.2 of XSL-FO spec.)
- * @param region the RegionViewport whose region is to be drawn
- */
- protected void handleRegionTraits(RegionViewport region) {
- currentFontName = "";
- super.handleRegionTraits(region);
- }
-
- /**
* Formats a float value (normally coordinates) as Strings.
* @param value the value
* @return the formatted value
@@ -866,7 +848,8 @@ public class PDFRenderer extends AbstractPathOrientedRenderer {
float w = x2 - x1;
float h = y2 - y1;
if ((w < 0) || (h < 0)) {
- log.error("Negative extent received (w=" + w + ", h=" + h + "). Border won't be painted.");
+ log.error("Negative extent received (w=" + w + ", h=" + h
+ + "). Border won't be painted.");
return;
}
switch (style) {
@@ -1329,12 +1312,9 @@ public class PDFRenderer extends AbstractPathOrientedRenderer {
super.renderBlock(block);
}
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
protected void renderLineArea(LineArea line) {
super.renderLineArea(line);
- closeText();
}
/**
@@ -1423,11 +1403,20 @@ public class PDFRenderer extends AbstractPathOrientedRenderer {
}
}
- /**
- * {@inheritDoc}
- */
+ private Typeface getTypeface(String fontName) {
+ Typeface tf = (Typeface) fontInfo.getFonts().get(fontName);
+ if (tf instanceof LazyFont) {
+ tf = ((LazyFont)tf).getRealFont();
+ }
+ return tf;
+ }
+
+ /** {@inheritDoc} */
public void renderText(TextArea text) {
renderInlineAreaBackAndBorders(text);
+ Color ct = (Color) text.getTrait(Trait.COLOR);
+ updateColor(ct, true);
+
beginTextObject();
StringBuffer pdf = new StringBuffer();
@@ -1435,12 +1424,10 @@ public class PDFRenderer extends AbstractPathOrientedRenderer {
int size = ((Integer) text.getTrait(Trait.FONT_SIZE)).intValue();
// This assumes that *all* CIDFonts use a /ToUnicode mapping
- Typeface tf = (Typeface) fontInfo.getFonts().get(fontName);
- boolean useMultiByte = tf.isMultiByte();
+ Typeface tf = getTypeface(fontName);
+
+ textutil.updateTf(fontName, size / 1000f, tf.isMultiByte());
- updateFont(fontName, size, pdf);
- Color ct = (Color) text.getTrait(Trait.COLOR);
- updateColor(ct, true, pdf);
// word.getOffset() = only height of text itself
// currentBlockIPPosition: 0 for beginning of line; nonzero
@@ -1448,66 +1435,46 @@ public class PDFRenderer extends AbstractPathOrientedRenderer {
int rx = currentIPPosition + text.getBorderAndPaddingWidthStart();
int bl = currentBPPosition + text.getOffset() + text.getBaselineOffset();
- pdf.append("1 0 0 -1 " + format(rx / 1000f) + " " + format(bl / 1000f) + " Tm "
- /*+ format(text.getTextLetterSpaceAdjust() / 1000f) + " Tc\n"*/
- /*+ format(text.getTextWordSpaceAdjust() / 1000f) + " Tw ["*/);
+ textutil.writeTextMatrix(new AffineTransform(1, 0, 0, -1, rx / 1000f, bl / 1000f));
- pdf.append("[");
currentStream.add(pdf.toString());
super.renderText(text);
- currentStream.add("] TJ\n");
+ textutil.writeTJ();
renderTextDecoration(tf, size, text, bl, rx);
}
-
- /**
- * {@inheritDoc}
- */
+
+ /** {@inheritDoc} */
public void renderWord(WordArea word) {
Font font = getFontFromArea(word.getParentArea());
- Typeface tf = (Typeface) fontInfo.getFonts().get(font.getFontName());
- boolean useMultiByte = tf.isMultiByte();
-
- StringBuffer pdf = new StringBuffer();
-
String s = word.getWord();
- escapeText(s, word.getLetterAdjustArray(),
- font, (AbstractTextArea)word.getParentArea(), useMultiByte, pdf);
- currentStream.add(pdf.toString());
+ escapeText(s, word.getLetterAdjustArray(),
+ font, (AbstractTextArea)word.getParentArea());
super.renderWord(word);
}
- /**
- * {@inheritDoc}
- */
+ /** {@inheritDoc} */
public void renderSpace(SpaceArea space) {
Font font = getFontFromArea(space.getParentArea());
- Typeface tf = (Typeface) fontInfo.getFonts().get(font.getFontName());
- boolean useMultiByte = tf.isMultiByte();
-
String s = space.getSpace();
- StringBuffer pdf = new StringBuffer();
-
AbstractTextArea textArea = (AbstractTextArea)space.getParentArea();
- escapeText(s, null, font, textArea, useMultiByte, pdf);
+ escapeText(s, null, font, textArea);
if (space.isAdjustable()) {
int tws = -((TextArea) space.getParentArea()).getTextWordSpaceAdjust()
- 2 * textArea.getTextLetterSpaceAdjust();
if (tws != 0) {
- pdf.append(format(tws / (font.getFontSize() / 1000f)));
- pdf.append(" ");
+ float adjust = tws / (font.getFontSize() / 1000f);
+ textutil.adjustGlyphTJ(adjust);
}
}
- currentStream.add(pdf.toString());
-
super.renderSpace(space);
}
@@ -1515,101 +1482,77 @@ public class PDFRenderer extends AbstractPathOrientedRenderer {
* Escapes text according to PDF rules.
* @param s Text to escape
* @param letterAdjust an array of widths for letter adjustment (may be null)
- * @param fs Font state
+ * @param font to font in use
+ * @param parentArea the parent text area to retrieve certain traits from
+ */
+ protected void escapeText(String s,
+ int[] letterAdjust,
+ Font font, AbstractTextArea parentArea) {
+ escapeText(s, 0, s.length(), letterAdjust, font, parentArea);
+ }
+
+ /**
+ * Escapes text according to PDF rules.
+ * @param s Text to escape
+ * @param start the start position in the text
+ * @param end the end position in the text
+ * @param letterAdjust an array of widths for letter adjustment (may be null)
+ * @param font to font in use
* @param parentArea the parent text area to retrieve certain traits from
- * @param useMultiByte Indicates the use of multi byte convention
- * @param pdf target buffer for the escaped text
*/
- public void escapeText(String s, int[] letterAdjust,
- Font fs, AbstractTextArea parentArea,
- boolean useMultiByte, StringBuffer pdf) {
- String startText = useMultiByte ? "<" : "(";
- String endText = useMultiByte ? "> " : ") ";
-
- /*
- boolean kerningAvailable = false;
- Map kerning = fs.getKerning();
- if (kerning != null && !kerning.isEmpty()) {
- //kerningAvailable = true;
- //TODO Reenable me when the layout engine supports kerning, too
- log.warn("Kerning support is disabled until it is supported by the layout engine!");
- }
- */
+ protected void escapeText(String s, int start, int end,
+ int[] letterAdjust,
+ Font font, AbstractTextArea parentArea) {
+ String fontName = font.getFontName();
+ float fontSize = font.getFontSize() / 1000f;
+ Typeface tf = getTypeface(fontName);
+ SingleByteFont singleByteFont = null;
+ if (tf instanceof SingleByteFont) {
+ singleByteFont = (SingleByteFont)tf;
+ }
int l = s.length();
-
- float fontSize = fs.getFontSize() / 1000f;
- boolean startPending = true;
- for (int i = 0; i < l; i++) {
+
+ for (int i = start; i < end; i++) {
char orgChar = s.charAt(i);
char ch;
float glyphAdjust = 0;
- if (fs.hasChar(orgChar)) {
- ch = fs.mapChar(orgChar);
+ if (font.hasChar(orgChar)) {
+ ch = font.mapChar(orgChar);
+ if (singleByteFont != null && singleByteFont.hasAdditionalEncodings()) {
+ int encoding = ch / 256;
+ if (encoding == 0) {
+ textutil.updateTf(fontName, fontSize, tf.isMultiByte());
+ } else {
+ textutil.updateTf(fontName + "_" + Integer.toString(encoding),
+ fontSize, tf.isMultiByte());
+ ch = (char)(ch % 256);
+ }
+ }
int tls = (i < l - 1 ? parentArea.getTextLetterSpaceAdjust() : 0);
glyphAdjust -= tls;
} else {
if (CharUtilities.isFixedWidthSpace(orgChar)) {
//Fixed width space are rendered as spaces so copy/paste works in a reader
- ch = fs.mapChar(CharUtilities.SPACE);
- glyphAdjust = fs.getCharWidth(ch) - fs.getCharWidth(orgChar);
+ ch = font.mapChar(CharUtilities.SPACE);
+ glyphAdjust = font.getCharWidth(ch) - font.getCharWidth(orgChar);
} else {
- ch = fs.mapChar(orgChar);
+ ch = font.mapChar(orgChar);
}
}
if (letterAdjust != null && i < l - 1) {
glyphAdjust -= letterAdjust[i + 1];
}
- if (startPending) {
- pdf.append(startText);
- startPending = false;
- }
- if (!useMultiByte) {
- if (ch < 32 || ch > 127) {
- pdf.append("\\");
- pdf.append(Integer.toOctalString((int) ch));
- } else {
- switch (ch) {
- case '(':
- case ')':
- case '\\':
- pdf.append("\\");
- break;
- default:
- }
- pdf.append(ch);
- }
- } else {
- pdf.append(PDFText.toUnicodeHex(ch));
- }
+ textutil.writeTJMappedChar(ch);
float adjust = glyphAdjust / fontSize;
if (adjust != 0) {
- pdf.append(endText).append(format(adjust)).append(' ');
- startPending = true;
+ textutil.adjustGlyphTJ(adjust);
}
}
- if (!startPending) {
- pdf.append(endText);
- }
- }
-
- /**
- * Checks to see if we have some text rendering commands open
- * still and writes out the TJ command to the stream if we do
- */
- protected void closeText() {
- /*
- if (textOpen) {
- currentStream.add("] TJ\n");
- textOpen = false;
- prevWordX = 0;
- prevWordY = 0;
- currentFontName = "";
- }*/
}
/**
@@ -1623,8 +1566,6 @@ public class PDFRenderer extends AbstractPathOrientedRenderer {
protected void setColor(Color col, boolean fill, StringBuffer pdf) {
PDFColor color = new PDFColor(this.pdfDoc, col);
- closeText();
-
if (pdf != null) {
pdf.append(color.getColorSpaceOut(fill));
} else {
@@ -1656,22 +1597,10 @@ public class PDFRenderer extends AbstractPathOrientedRenderer {
}
/** {@inheritDoc} */
- protected void updateColor(Color col, boolean fill) {
+ protected void updateColor(Color col, boolean fill) {
updateColor(col, fill, null);
}
- private void updateFont(String name, int size, StringBuffer pdf) {
- if ((!name.equals(this.currentFontName))
- || (size != this.currentFontSize)) {
- closeText();
-
- this.currentFontName = name;
- this.currentFontSize = size;
- pdf = pdf.append("/" + name + " " + format((float) size / 1000f)
- + " Tf\n");
- }
- }
-
/** {@inheritDoc} */
public void renderImage(Image image, Rectangle2D pos) {
endTextObject();
@@ -1727,8 +1656,6 @@ public class PDFRenderer extends AbstractPathOrientedRenderer {
ImageSessionContext sessionContext = getUserAgent().getImageSessionContext();
info = manager.getImageInfo(uri, sessionContext);
-
-
Map hints = ImageUtil.getDefaultHints(sessionContext);
org.apache.xmlgraphics.image.loader.Image img = manager.getImage(
info, imageHandlerRegistry.getSupportedFlavors(), hints, sessionContext);
@@ -1803,9 +1730,8 @@ public class PDFRenderer extends AbstractPathOrientedRenderer {
context.setProperty(PDFRendererContextConstants.PDF_CONTEXT, currentContext);
context.setProperty(PDFRendererContextConstants.PDF_STREAM, currentStream);
context.setProperty(PDFRendererContextConstants.PDF_FONT_INFO, fontInfo);
- context.setProperty(PDFRendererContextConstants.PDF_FONT_NAME, currentFontName);
- context.setProperty(PDFRendererContextConstants.PDF_FONT_SIZE,
- new Integer(currentFontSize));
+ context.setProperty(PDFRendererContextConstants.PDF_FONT_NAME, "");
+ context.setProperty(PDFRendererContextConstants.PDF_FONT_SIZE, new Integer(0));
return context;
}
diff --git a/src/java/org/apache/fop/render/ps/PSFontUtils.java b/src/java/org/apache/fop/render/ps/PSFontUtils.java
index bbc811b4e..1566ef799 100644
--- a/src/java/org/apache/fop/render/ps/PSFontUtils.java
+++ b/src/java/org/apache/fop/render/ps/PSFontUtils.java
@@ -32,16 +32,20 @@ import javax.xml.transform.stream.StreamSource;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.apache.xmlgraphics.fonts.Glyphs;
import org.apache.xmlgraphics.ps.DSCConstants;
import org.apache.xmlgraphics.ps.PSGenerator;
import org.apache.xmlgraphics.ps.PSResource;
import org.apache.xmlgraphics.ps.dsc.ResourceTracker;
+import org.apache.fop.fonts.Base14Font;
import org.apache.fop.fonts.CustomFont;
import org.apache.fop.fonts.Font;
import org.apache.fop.fonts.FontInfo;
import org.apache.fop.fonts.FontType;
import org.apache.fop.fonts.LazyFont;
+import org.apache.fop.fonts.SingleByteEncoding;
+import org.apache.fop.fonts.SingleByteFont;
import org.apache.fop.fonts.Typeface;
/**
@@ -81,9 +85,21 @@ public class PSFontUtils extends org.apache.xmlgraphics.ps.PSFontUtils {
while (iter.hasNext()) {
String key = (String)iter.next();
Typeface tf = getTypeFace(fontInfo, fonts, key);
- PSResource fontRes = new PSResource("font", tf.getFontName());
+ PSResource fontRes = new PSResource(PSResource.TYPE_FONT, tf.getFontName());
fontResources.put(key, fontRes);
embedFont(gen, tf, fontRes);
+
+ if (tf instanceof SingleByteFont) {
+ SingleByteFont sbf = (SingleByteFont)tf;
+ for (int i = 0, c = sbf.getAdditionalEncodingCount(); i < c; i++) {
+ SingleByteEncoding encoding = sbf.getAdditionalEncoding(i);
+ defineEncoding(gen, encoding);
+ String postFix = "_" + (i + 1);
+ PSResource derivedFontRes = defineDerivedFont(gen, tf.getFontName(),
+ tf.getFontName() + postFix, encoding.getName());
+ fontResources.put(key + postFix, derivedFontRes);
+ }
+ }
}
gen.commentln("%FOPEndFontDict");
reencodeFonts(gen, fonts);
@@ -91,29 +107,35 @@ public class PSFontUtils extends org.apache.xmlgraphics.ps.PSFontUtils {
}
private static void reencodeFonts(PSGenerator gen, Map fonts) throws IOException {
+ ResourceTracker tracker = gen.getResourceTracker();
+
+ if (!tracker.isResourceSupplied(WINANSI_ENCODING_RESOURCE)) {
+ defineWinAnsiEncoding(gen);
+ }
gen.commentln("%FOPBeginFontReencode");
- defineWinAnsiEncoding(gen);
//Rewrite font encodings
Iterator iter = fonts.keySet().iterator();
while (iter.hasNext()) {
String key = (String)iter.next();
- Typeface fm = (Typeface)fonts.get(key);
- if (fm instanceof LazyFont && ((LazyFont)fm).getRealFont() == null) {
- continue;
- } else if (null == fm.getEncoding()) {
+ Typeface tf = (Typeface)fonts.get(key);
+ if (tf instanceof LazyFont) {
+ tf = ((LazyFont)tf).getRealFont();
+ if (tf == null) {
+ continue;
+ }
+ }
+ if (null == tf.getEncodingName()) {
//ignore (ZapfDingbats and Symbol used to run through here, kept for safety reasons)
- } else if ("SymbolEncoding".equals(fm.getEncoding())) {
+ } else if ("SymbolEncoding".equals(tf.getEncodingName())) {
//ignore (no encoding redefinition)
- } else if ("ZapfDingbatsEncoding".equals(fm.getEncoding())) {
+ } else if ("ZapfDingbatsEncoding".equals(tf.getEncodingName())) {
//ignore (no encoding redefinition)
- } else if ("WinAnsiEncoding".equals(fm.getEncoding())) {
- redefineFontEncoding(gen, fm.getFontName(), fm.getEncoding());
} else {
- /* Don't complain anymore, just use the font's default encoding.
- gen.commentln("%WARNING: Only WinAnsiEncoding is supported. Font '"
- + fm.getFontName() + "' asks for: " + fm.getEncoding());
- */
+ if (tf instanceof Base14Font) {
+ //Our Base 14 fonts don't use the default encoding
+ redefineFontEncoding(gen, tf.getFontName(), tf.getEncodingName());
+ }
}
}
gen.commentln("%FOPEndFontReencode");
@@ -233,10 +255,88 @@ public class PSFontUtils extends org.apache.xmlgraphics.ps.PSFontUtils {
if (isEmbeddable(cf)) {
resTracker.registerSuppliedResource(fontRes);
}
+ if (tf instanceof SingleByteFont) {
+ SingleByteFont sbf = (SingleByteFont)tf;
+ for (int i = 0, c = sbf.getAdditionalEncodingCount(); i < c; i++) {
+ SingleByteEncoding encoding = sbf.getAdditionalEncoding(i);
+ PSResource encodingRes = new PSResource(
+ PSResource.TYPE_ENCODING, encoding.getName());
+ resTracker.registerSuppliedResource(encodingRes);
+ PSResource derivedFontRes = new PSResource(
+ PSResource.TYPE_FONT, tf.getFontName() + "_" + (i + 1));
+ resTracker.registerSuppliedResource(derivedFontRes);
+ }
+ }
}
}
}
return fontResources;
}
+ /**
+ * Defines the single-byte encoding for use in PostScript files.
+ * @param gen the PostScript generator
+ * @param encoding the single-byte encoding
+ * @return the PSResource instance that represents the encoding
+ * @throws IOException In case of an I/O problem
+ */
+ public static PSResource defineEncoding(PSGenerator gen, SingleByteEncoding encoding)
+ throws IOException {
+ PSResource res = new PSResource(PSResource.TYPE_ENCODING, encoding.getName());
+ gen.writeDSCComment(DSCConstants.BEGIN_RESOURCE, res);
+ gen.writeln("/" + encoding.getName() + " [");
+ String[] charNames = encoding.getCharNameMap();
+ for (int i = 0; i < 256; i++) {
+ if (i > 0) {
+ if ((i % 5) == 0) {
+ gen.newLine();
+ } else {
+ gen.write(" ");
+ }
+ }
+ String glyphname = null;
+ if (i < charNames.length) {
+ glyphname = charNames[i];
+ }
+ if (glyphname == null || "".equals(glyphname)) {
+ glyphname = Glyphs.NOTDEF;
+ }
+ gen.write("/");
+ gen.write(glyphname);
+ }
+ gen.newLine();
+ gen.writeln("] def");
+ gen.writeDSCComment(DSCConstants.END_RESOURCE);
+ gen.getResourceTracker().registerSuppliedResource(res);
+ return res;
+ }
+
+ /**
+ * Derives a new font based on an existing font with a given encoding. The encoding must
+ * have been registered before.
+ * @param gen the PostScript generator
+ * @param baseFontName the font name of the font to derive from
+ * @param fontName the font name of the new font to be define
+ * @param encoding the new encoding (must be predefined in the PS file)
+ * @return the PSResource representing the derived font
+ * @throws IOException In case of an I/O problem
+ */
+ public static PSResource defineDerivedFont(PSGenerator gen, String baseFontName, String fontName,
+ String encoding) throws IOException {
+ PSResource res = new PSResource(PSResource.TYPE_FONT, fontName);
+ gen.writeDSCComment(DSCConstants.BEGIN_RESOURCE, res);
+ gen.commentln("%XGCDependencies: font " + baseFontName);
+ gen.commentln("%XGC+ encoding " + encoding);
+ gen.writeln("/" + baseFontName + " findfont");
+ gen.writeln("dup length dict begin");
+ gen.writeln(" {1 index /FID ne {def} {pop pop} ifelse} forall");
+ gen.writeln(" /Encoding " + encoding + " def");
+ gen.writeln(" currentdict");
+ gen.writeln("end");
+ gen.writeln("/" + fontName + " exch definefont pop");
+ gen.writeDSCComment(DSCConstants.END_RESOURCE);
+ gen.getResourceTracker().registerSuppliedResource(res);
+ return res;
+ }
+
}
diff --git a/src/java/org/apache/fop/render/ps/PSImageUtils.java b/src/java/org/apache/fop/render/ps/PSImageUtils.java
deleted file mode 100644
index 004d5a22a..000000000
--- a/src/java/org/apache/fop/render/ps/PSImageUtils.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * 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.ps;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.xmlgraphics.ps.PSGenerator;
-
-import org.apache.fop.image.EPSImage;
-import org.apache.fop.image.FopImage;
-
-/**
- * Utility code for rendering images in PostScript.
- */
-public class PSImageUtils extends org.apache.xmlgraphics.ps.PSImageUtils {
-
- /** logging instance */
- protected static Log log = LogFactory.getLog(PSImageUtils.class);
-
- /**
- * Renders an EPS image to PostScript.
- * @param img EPS image to render
- * @param x x position
- * @param y y position
- * @param w width
- * @param h height
- * @param gen PS generator
- * @deprecated Use {@link #renderEPS(java.io.InputStream, String, java.awt.geom.Rectangle2D,
- * java.awt.geom.Rectangle2D, PSGenerator)} instead
- */
- public static void renderEPS(EPSImage img,
- float x, float y, float w, float h,
- PSGenerator gen) {
- try {
- if (!img.load(FopImage.ORIGINAL_DATA)) {
- gen.commentln("%EPS image could not be processed: " + img);
- return;
- }
- int[] bbox = img.getBBox();
- int bboxw = bbox[2] - bbox[0];
- int bboxh = bbox[3] - bbox[1];
- String name = img.getDocName();
- if (name == null || name.length() == 0) {
- name = img.getOriginalURI();
- }
- renderEPS(img.getEPSImage(), name,
- x, y, w, h,
- bbox[0], bbox[1], bboxw, bboxh, gen);
-
- } catch (Exception e) {
- log.error("PSRenderer.renderImageArea(): Error rendering bitmap ("
- + e.getMessage() + ")", e);
- }
- }
-
-}
diff --git a/src/java/org/apache/fop/render/ps/PSRenderer.java b/src/java/org/apache/fop/render/ps/PSRenderer.java
index ecd403749..7e32977e6 100644
--- a/src/java/org/apache/fop/render/ps/PSRenderer.java
+++ b/src/java/org/apache/fop/render/ps/PSRenderer.java
@@ -89,6 +89,7 @@ import org.apache.fop.fo.Constants;
import org.apache.fop.fo.extensions.ExtensionAttachment;
import org.apache.fop.fonts.Font;
import org.apache.fop.fonts.LazyFont;
+import org.apache.fop.fonts.SingleByteFont;
import org.apache.fop.fonts.Typeface;
import org.apache.fop.render.AbstractPathOrientedRenderer;
import org.apache.fop.render.Graphics2DAdapter;
@@ -660,6 +661,12 @@ public class PSRenderer extends AbstractPathOrientedRenderer
}
private String getPostScriptNameForFontKey(String key) {
+ int pos = key.indexOf('_');
+ String postFix = null;
+ if (pos > 0) {
+ postFix = key.substring(pos);
+ key = key.substring(0, pos);
+ }
Map fonts = fontInfo.getFonts();
Typeface tf = (Typeface)fonts.get(key);
if (tf instanceof LazyFont) {
@@ -668,7 +675,11 @@ public class PSRenderer extends AbstractPathOrientedRenderer
if (tf == null) {
throw new IllegalStateException("Font not available: " + key);
}
- return tf.getFontName();
+ if (postFix == null) {
+ return tf.getFontName();
+ } else {
+ return tf.getFontName() + postFix;
+ }
}
/**
@@ -698,7 +709,6 @@ public class PSRenderer extends AbstractPathOrientedRenderer
protected void useFont(String key, int size) {
try {
PSResource res = getPSResourceForFontKey(key);
- //gen.useFont(key, size / 1000f);
gen.useFont("/" + res.getName(), size / 1000f);
gen.getResourceTracker().notifyResourceUsageOnPage(res);
} catch (IOException ioe) {
@@ -951,7 +961,7 @@ public class PSRenderer extends AbstractPathOrientedRenderer
if (!isOptimizeResources()) {
this.fontResources = PSFontUtils.writeFontDict(gen, fontInfo);
} else {
- gen.commentln("%FOPFontSetup");
+ gen.commentln("%FOPFontSetup"); //Place-holder, will be replaced in the second pass
}
gen.writeDSCComment(DSCConstants.END_SETUP);
}
@@ -1292,17 +1302,16 @@ public class PSRenderer extends AbstractPathOrientedRenderer
*/
public void renderText(TextArea area) {
renderInlineAreaBackAndBorders(area);
- String fontname = getInternalFontNameForArea(area);
+ String fontkey = getInternalFontNameForArea(area);
int fontsize = area.getTraitAsInteger(Trait.FONT_SIZE);
// This assumes that *all* CIDFonts use a /ToUnicode mapping
- Typeface tf = (Typeface) fontInfo.getFonts().get(fontname);
+ Typeface tf = (Typeface) fontInfo.getFonts().get(fontkey);
//Determine position
int rx = currentIPPosition + area.getBorderAndPaddingWidthStart();
int bl = currentBPPosition + area.getOffset() + area.getBaselineOffset();
- useFont(fontname, fontsize);
Color ct = (Color)area.getTrait(Trait.COLOR);
if (ct != null) {
try {
@@ -1347,30 +1356,75 @@ public class PSRenderer extends AbstractPathOrientedRenderer
super.renderSpace(space);
}
+ private Typeface getTypeface(String fontName) {
+ Typeface tf = (Typeface)fontInfo.getFonts().get(fontName);
+ if (tf instanceof LazyFont) {
+ tf = ((LazyFont)tf).getRealFont();
+ }
+ return tf;
+ }
+
private void renderText(AbstractTextArea area, String text, int[] letterAdjust) {
+ String fontkey = getInternalFontNameForArea(area);
+ int fontSize = area.getTraitAsInteger(Trait.FONT_SIZE);
Font font = getFontFromArea(area);
- Typeface tf = (Typeface) fontInfo.getFonts().get(font.getFontName());
+ Typeface tf = getTypeface(font.getFontName());
+ SingleByteFont singleByteFont = null;
+ if (tf instanceof SingleByteFont) {
+ singleByteFont = (SingleByteFont)tf;
+ }
+ int textLen = text.length();
+ if (singleByteFont != null && singleByteFont.hasAdditionalEncodings()) {
+ int start = 0;
+ int currentEncoding = -1;
+ for (int i = 0; i < textLen; i++) {
+ char c = text.charAt(i);
+ char mapped = tf.mapChar(c);
+ int encoding = mapped / 256;
+ if (currentEncoding != encoding) {
+ if (i > 0) {
+ writeText(area, text, start, i - start, letterAdjust, fontSize, tf);
+ }
+ if (encoding == 0) {
+ useFont(fontkey, fontSize);
+ } else {
+ useFont(fontkey + "_" + Integer.toString(encoding), fontSize);
+ }
+ currentEncoding = encoding;
+ start = i;
+ }
+ }
+ writeText(area, text, start, textLen - start, letterAdjust, fontSize, tf);
+ } else {
+ useFont(fontkey, fontSize);
+ writeText(area, text, 0, textLen, letterAdjust, fontSize, tf);
+ }
+ }
+
+ private void writeText(AbstractTextArea area, String text, int start, int len,
+ int[] letterAdjust, int fontsize, Typeface tf) {
+ int end = start + len;
int initialSize = text.length();
initialSize += initialSize / 2;
StringBuffer sb = new StringBuffer(initialSize);
- int textLen = text.length();
if (letterAdjust == null
&& area.getTextLetterSpaceAdjust() == 0
&& area.getTextWordSpaceAdjust() == 0) {
sb.append("(");
- for (int i = 0; i < textLen; i++) {
+ for (int i = start; i < end; i++) {
final char c = text.charAt(i);
- final char mapped = tf.mapChar(c);
+ final char mapped = (char)(tf.mapChar(c) % 256);
PSGenerator.escapeChar(mapped, sb);
}
sb.append(") t");
} else {
sb.append("(");
- int[] offsets = new int[textLen];
- for (int i = 0; i < textLen; i++) {
+ int[] offsets = new int[len];
+ for (int i = start; i < end; i++) {
final char c = text.charAt(i);
final char mapped = tf.mapChar(c);
+ char codepoint = (char)(mapped % 256);
int wordSpace;
if (CharUtilities.isAdjustableSpace(mapped)) {
@@ -1378,14 +1432,14 @@ public class PSRenderer extends AbstractPathOrientedRenderer
} else {
wordSpace = 0;
}
- int cw = tf.getWidth(mapped, font.getFontSize()) / 1000;
- int ladj = (letterAdjust != null && i < textLen - 1 ? letterAdjust[i + 1] : 0);
- int tls = (i < textLen - 1 ? area.getTextLetterSpaceAdjust() : 0);
- offsets[i] = cw + ladj + tls + wordSpace;
- PSGenerator.escapeChar(mapped, sb);
+ int cw = tf.getWidth(mapped, fontsize) / 1000;
+ int ladj = (letterAdjust != null && i < end - 1 ? letterAdjust[i + 1] : 0);
+ int tls = (i < end - 1 ? area.getTextLetterSpaceAdjust() : 0);
+ offsets[i - start] = cw + ladj + tls + wordSpace;
+ PSGenerator.escapeChar(codepoint, sb);
}
sb.append(")" + PSGenerator.LF + "[");
- for (int i = 0; i < textLen; i++) {
+ for (int i = 0; i < len; i++) {
if (i > 0) {
if (i % 8 == 0) {
sb.append(PSGenerator.LF);
@@ -1398,7 +1452,6 @@ public class PSRenderer extends AbstractPathOrientedRenderer
sb.append("]" + PSGenerator.LF + "xshow");
}
writeln(sb.toString());
-
}
/** {@inheritDoc} */
diff --git a/src/java/org/apache/fop/render/rtf/SVGConverter.java b/src/java/org/apache/fop/render/rtf/SVGConverter.java
deleted file mode 100644
index 11ba8dc82..000000000
--- a/src/java/org/apache/fop/render/rtf/SVGConverter.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * 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.rtf;
-
-import org.apache.batik.transcoder.TranscoderException;
-import org.apache.batik.transcoder.TranscoderInput;
-import org.apache.batik.transcoder.TranscoderOutput;
-import org.apache.batik.transcoder.image.JPEGTranscoder;
-import org.apache.commons.io.output.ByteArrayOutputStream;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.fop.image.XMLImage;
-
-/**
- * Helper class for converting SVG to bitmap images.
- */
-public final class SVGConverter {
-
- /** logger instance */
- private static Log log = LogFactory.getLog(SVGConverter.class);
-
- /**
- * Constructor is private, because it's just a utility class.
- */
- private SVGConverter() {
- }
-
- /**
- * Converts a SVG image to a JPEG bitmap.
- * @param image the SVG image
- * @return a byte array containing the JPEG image
- */
- public static byte[] convertToJPEG(XMLImage image) {
- JPEGTranscoder transcoder = new JPEGTranscoder();
- /* TODO Disabled to avoid side-effect due to the mixing of source and target resolutions
- * This should be reenabled when it has been determined how exactly to handle this
- transcoder.addTranscodingHint(ImageTranscoder.KEY_PIXEL_UNIT_TO_MILLIMETER,
- new Float(25.4f / 300)); //300dpi should be enough for now.
- */
- transcoder.addTranscodingHint(JPEGTranscoder.KEY_QUALITY, new Float(0.9f));
- TranscoderInput input = new TranscoderInput(image.getDocument());
- ByteArrayOutputStream baout = new ByteArrayOutputStream(16384);
- TranscoderOutput output = new TranscoderOutput(baout);
- try {
- transcoder.transcode(input, output);
- return baout.toByteArray();
- } catch (TranscoderException e) {
- log.error(e);
- return null;
- }
- }
-
-}
diff --git a/src/java/org/apache/fop/image/analyser/SVGZReader.java b/src/java/org/apache/fop/svg/GraphicsConfiguration.java
index 14fde1cb6..a92baed27 100644
--- a/src/java/org/apache/fop/image/analyser/SVGZReader.java
+++ b/src/java/org/apache/fop/svg/GraphicsConfiguration.java
@@ -16,38 +16,36 @@
*/
/* $Id$ */
+
-package org.apache.fop.image.analyser;
+package org.apache.fop.svg;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.zip.GZIPInputStream;
-
-import org.apache.fop.apps.FOUserAgent;
-import org.apache.fop.image.FopImage;
+import java.awt.image.VolatileImage;
/**
- * Implements a reader for gzipped XMLFiles.
+ * Adapter to allow subclassing java.awt.GraphicsConfiguration without
+ * compilation errors.
+ * The version for JDK 1.4 needs to add an override for the abstract
+ * createCompatibleVolatileImage() method. It can't be overidden
+ * for JDK 1.3 because there is no VolatileImage there.
*
- * <p>
- * The current implementation is limited to SVG files only.
*/
-public class SVGZReader extends XMLReader {
+abstract public class GraphicsConfiguration extends java.awt.GraphicsConfiguration {
+
/**
- * Default constructor.
+ * @see java.awt.GraphicsConfiguration#createCompatibleVolatileImage(int, int)
+ * @since JDK 1.4
*/
- public SVGZReader() {
+ public VolatileImage createCompatibleVolatileImage(int width, int height) {
+ return null;
}
- /** {@inheritDoc} */
- protected FopImage.ImageInfo loadImage(final String uri,
- final InputStream bis, final FOUserAgent ua) {
- try {
- return new SVGReader().verifySignature(uri,
- new GZIPInputStream(bis), ua);
- } catch (final IOException e) {
- // ignore
- }
+ /**
+ * @see java.awt.GraphicsConfiguration#createCompatibleVolatileImage(int, int, int)
+ * @since JDK 1.5
+ */
+ public VolatileImage createCompatibleVolatileImage(int width, int height, int transparency) {
return null;
}
+
}
diff --git a/src/java/org/apache/fop/svg/PDFGraphics2D.java b/src/java/org/apache/fop/svg/PDFGraphics2D.java
index 864809ebe..f6a7cbc3b 100644
--- a/src/java/org/apache/fop/svg/PDFGraphics2D.java
+++ b/src/java/org/apache/fop/svg/PDFGraphics2D.java
@@ -70,12 +70,10 @@ import org.apache.xmlgraphics.image.loader.impl.ImageRendered;
import org.apache.xmlgraphics.java2d.AbstractGraphics2D;
import org.apache.xmlgraphics.java2d.GraphicContext;
-import org.apache.fop.fonts.CIDFont;
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.fop.fonts.LazyFont;
import org.apache.fop.pdf.BitmapImage;
import org.apache.fop.pdf.PDFAnnotList;
import org.apache.fop.pdf.PDFColor;
@@ -1473,14 +1471,7 @@ public class PDFGraphics2D extends AbstractGraphics2D {
// This assumes that *all* CIDFonts use a /ToUnicode mapping
org.apache.fop.fonts.Typeface f
= (org.apache.fop.fonts.Typeface)fontInfo.getFonts().get(name);
- if (f instanceof LazyFont) {
- if (((LazyFont) f).getRealFont() instanceof CIDFont) {
- return true;
- }
- } else if (f instanceof CIDFont) {
- return true;
- }
- return false;
+ return f.isMultiByte();
}
private void addKerning(StringWriter buf, Integer ch1, Integer ch2,
diff --git a/src/java/org/apache/fop/svg/PDFTextPainter.java b/src/java/org/apache/fop/svg/PDFTextPainter.java
index 7154c68a9..754b0794b 100644
--- a/src/java/org/apache/fop/svg/PDFTextPainter.java
+++ b/src/java/org/apache/fop/svg/PDFTextPainter.java
@@ -43,6 +43,7 @@ import org.apache.batik.gvt.renderer.StrokingTextPainter;
import org.apache.batik.gvt.text.GVTAttributedCharacterIterator;
import org.apache.batik.gvt.text.TextPaintInfo;
import org.apache.batik.gvt.text.TextSpanLayout;
+
import org.apache.fop.fonts.Font;
import org.apache.fop.fonts.FontInfo;
import org.apache.fop.fonts.FontTriplet;
@@ -83,8 +84,12 @@ public class PDFTextPainter extends StrokingTextPainter {
super.paintTextRuns(textRuns, g2d);
return;
}
- PDFGraphics2D pdf = (PDFGraphics2D)g2d;
- PDFTextUtil textUtil = new PDFTextUtil(pdf);
+ final PDFGraphics2D pdf = (PDFGraphics2D)g2d;
+ PDFTextUtil textUtil = new PDFTextUtil(pdf.fontInfo) {
+ protected void write(String code) {
+ pdf.currentStream.write(code);
+ }
+ };
for (int i = 0; i < textRuns.size(); i++) {
TextRun textRun = (TextRun)textRuns.get(i);
AttributedCharacterIterator runaci = textRun.getACI();
@@ -134,7 +139,7 @@ public class PDFTextPainter extends StrokingTextPainter {
}
textUtil.saveGraphicsState();
- textUtil.concatMatrixCurrentTransform();
+ textUtil.concatMatrix(g2d.getTransform());
Shape imclip = g2d.getClip();
pdf.writeClip(imclip);
diff --git a/src/java/org/apache/fop/svg/PDFTextUtil.java b/src/java/org/apache/fop/svg/PDFTextUtil.java
index 0fb552026..f3c7f31a2 100644
--- a/src/java/org/apache/fop/svg/PDFTextUtil.java
+++ b/src/java/org/apache/fop/svg/PDFTextUtil.java
@@ -19,145 +19,33 @@
package org.apache.fop.svg;
-import java.awt.geom.AffineTransform;
-
import org.apache.fop.fonts.Font;
-import org.apache.fop.pdf.PDFNumber;
-import org.apache.fop.pdf.PDFText;
+import org.apache.fop.fonts.FontInfo;
+import org.apache.fop.fonts.Typeface;
/**
- * Utility class for generating PDF text objects.
+ * Utility class for generating PDF text objects. It needs to be subclassed to add writing
+ * functionality (see {@link #write(String)}).
*/
-public class PDFTextUtil {
+public abstract class PDFTextUtil extends org.apache.fop.pdf.PDFTextUtil {
- /** The number of decimal places. */
- private static final int DEC = 8;
-
- /** PDF text rendering mode: Fill text */
- public static final int TR_FILL = 0;
- /** PDF text rendering mode: Stroke text */
- public static final int TR_STROKE = 1;
- /** PDF text rendering mode: Fill, then stroke text */
- public static final int TR_FILL_STROKE = 2;
- /** PDF text rendering mode: Neither fill nor stroke text (invisible) */
- public static final int TR_INVISIBLE = 3;
- /** PDF text rendering mode: Fill text and add to path for clipping */
- public static final int TR_FILL_CLIP = 4;
- /** PDF text rendering mode: Stroke text and add to path for clipping */
- public static final int TR_STROKE_CLIP = 5;
- /** PDF text rendering mode: Fill, then stroke text and add to path for clipping */
- public static final int TR_FILL_STROKE_CLIP = 6;
- /** PDF text rendering mode: Add text to path for clipping */
- public static final int TR_CLIP = 7;
-
-
- private PDFGraphics2D g2d;
- private boolean inTextObject = false;
+ private FontInfo fontInfo;
private Font[] fonts;
private Font font;
- private String startText;
- private String endText;
- private boolean useMultiByte;
- private StringBuffer bufTJ;
- private int textRenderingMode = 0;
/**
* Main constructor.
- * @param g2d the PDFGraphics2D instance to work with
+ * @param fontInfo the font catalog
*/
- public PDFTextUtil(PDFGraphics2D g2d) {
- this.g2d = g2d;
+ public PDFTextUtil(FontInfo fontInfo) {
+ super();
+ this.fontInfo = fontInfo;
}
- private void writeAffineTransform(AffineTransform at, StringBuffer sb) {
- double[] lt = new double[6];
- at.getMatrix(lt);
- sb.append(PDFNumber.doubleOut(lt[0], DEC)).append(" ");
- sb.append(PDFNumber.doubleOut(lt[1], DEC)).append(" ");
- sb.append(PDFNumber.doubleOut(lt[2], DEC)).append(" ");
- sb.append(PDFNumber.doubleOut(lt[3], DEC)).append(" ");
- sb.append(PDFNumber.doubleOut(lt[4], DEC)).append(" ");
- sb.append(PDFNumber.doubleOut(lt[5], DEC));
- }
-
- private void writeChar(char ch, StringBuffer sb) {
- if (!useMultiByte) {
- if (ch > 127) {
- sb.append("\\").append(Integer.toOctalString((int)ch));
- } else {
- switch (ch) {
- case '(':
- case ')':
- case '\\':
- sb.append("\\");
- break;
- default:
- }
- sb.append(ch);
- }
- } else {
- sb.append(PDFText.toUnicodeHex(ch));
- }
- }
-
- private void checkInTextObject() {
- if (!inTextObject) {
- throw new IllegalStateException("Not in text object");
- }
- }
-
- /**
- * Called when a new text object should be started. Be sure to call setFont() before
- * issuing any text painting commands.
- */
- public void beginTextObject() {
- if (inTextObject) {
- throw new IllegalStateException("Already in text object");
- }
- g2d.currentStream.write("BT\n");
- this.inTextObject = true;
- }
-
- /**
- * Called when a text object should be ended.
- */
- public void endTextObject() {
- checkInTextObject();
- g2d.currentStream.write("ET\n");
- this.inTextObject = false;
- initValues();
- }
-
- private void initValues() {
+ /** {@inheritDoc} */
+ protected void initValues() {
+ super.initValues();
this.font = null;
- this.textRenderingMode = TR_FILL;
- }
-
- /**
- * Creates a "q" command, pushing a copy of the entire graphics state onto the stack.
- */
- public void saveGraphicsState() {
- g2d.currentStream.write("q\n");
- }
-
- /**
- * Creates a "Q" command, restoring the entire graphics state to its former value by popping
- * it from the stack.
- */
- public void restoreGraphicsState() {
- g2d.currentStream.write("Q\n");
- }
-
- /**
- * Creates a "cm" command using the current transformation as the matrix.
- */
- public void concatMatrixCurrentTransform() {
- StringBuffer sb = new StringBuffer();
- if (!g2d.getTransform().isIdentity()) {
- writeAffineTransform(g2d.getTransform(), sb);
- sb.append(" cm\n");
- }
- g2d.currentStream.write(sb.toString());
}
/**
@@ -194,63 +82,23 @@ public class PDFTextUtil {
}
/**
+ * Determines whether the font with the given name is a multi-byte font.
+ * @param name the name of the font
+ * @return true if it's a multi-byte font
+ */
+ protected boolean isMultiByteFont(String name) {
+ Typeface f = (Typeface)fontInfo.getFonts().get(name);
+ return f.isMultiByte();
+ }
+
+ /**
* Writes a "Tf" command, setting a new current font.
* @param f the font to select
*/
public void writeTf(Font f) {
- checkInTextObject();
String fontName = f.getFontName();
float fontSize = (float)f.getFontSize() / 1000f;
- g2d.currentStream.write("/" + fontName + " " + PDFNumber.doubleOut(fontSize) + " Tf\n");
-
- this.useMultiByte = g2d.isMultiByteFont(fontName);
- this.startText = useMultiByte ? "<" : "(";
- this.endText = useMultiByte ? ">" : ")";
- }
-
- /**
- * Sets the text rendering mode.
- * @param mode the rendering mode (value 0 to 7, see PDF Spec, constants: TR_*)
- */
- public void setTextRenderingMode(int mode) {
- if (mode < 0 || mode > 7) {
- throw new IllegalArgumentException(
- "Illegal value for text rendering mode. Expected: 0-7");
- }
- if (mode != this.textRenderingMode) {
- this.textRenderingMode = mode;
- g2d.currentStream.write(this.textRenderingMode + " Tr\n");
- }
- }
-
- /**
- * Sets the text rendering mode.
- * @param fill true if the text should be filled
- * @param stroke true if the text should be stroked
- * @param addToClip true if the path should be added for clipping
- */
- public void setTextRenderingMode(boolean fill, boolean stroke, boolean addToClip) {
- int mode;
- if (fill) {
- mode = (stroke ? 2 : 0);
- } else {
- mode = (stroke ? 1 : 3);
- }
- if (addToClip) {
- mode += 4;
- }
- setTextRenderingMode(mode);
- }
-
- /**
- * Writes a "Tm" command, setting a new text transformation matrix.
- * @param localTransform the new text transformation matrix
- */
- public void writeTextMatrix(AffineTransform localTransform) {
- StringBuffer sb = new StringBuffer();
- writeAffineTransform(localTransform, sb);
- sb.append(" Tm\n");
- g2d.currentStream.write(sb.toString());
+ updateTf(fontName, fontSize, isMultiByteFont(fontName));
}
/**
@@ -272,37 +120,8 @@ public class PDFTextUtil {
* @param ch the unmapped character
*/
public void writeTJChar(char ch) {
- if (bufTJ == null) {
- bufTJ = new StringBuffer();
- }
- if (bufTJ.length() == 0) {
- bufTJ.append("[").append(startText);
- }
char mappedChar = font.mapChar(ch);
- writeChar(mappedChar, bufTJ);
- }
-
- /**
- * Writes a glyph adjust value to the "TJ-Buffer".
- * @param adjust the glyph adjust value in thousands of text unit space.
- */
- public void adjustGlyphTJ(double adjust) {
- bufTJ.append(endText).append(" ");
- bufTJ.append(PDFNumber.doubleOut(adjust, DEC - 4));
- bufTJ.append(" ");
- bufTJ.append(startText);
- }
-
- /**
- * Writes a "TJ" command, writing out the accumulated buffer with the characters and glyph
- * positioning values. The buffer is reset afterwards.
- */
- public void writeTJ() {
- if (bufTJ != null && bufTJ.length() > 0) {
- bufTJ.append(endText).append("] TJ\n");
- g2d.currentStream.write(bufTJ.toString());
- bufTJ.setLength(0);
- }
+ writeTJMappedChar(mappedChar);
}
}