diff options
Diffstat (limited to 'src/java/org/apache/fop')
87 files changed, 1166 insertions, 930 deletions
diff --git a/src/java/org/apache/fop/accessibility/fo/StructureTreeEventTrigger.java b/src/java/org/apache/fop/accessibility/fo/StructureTreeEventTrigger.java index 51f7f2bed..7e3ed0591 100644 --- a/src/java/org/apache/fop/accessibility/fo/StructureTreeEventTrigger.java +++ b/src/java/org/apache/fop/accessibility/fo/StructureTreeEventTrigger.java @@ -221,14 +221,17 @@ class StructureTreeEventTrigger extends FOEventHandler { @Override public void startCell(TableCell tc) { AttributesImpl attributes = new AttributesImpl(); - int colSpan = tc.getNumberColumnsSpanned(); - if (colSpan > 1) { - addNoNamespaceAttribute(attributes, "number-columns-spanned", - Integer.toString(colSpan)); - } + addSpanAttribute(attributes, "number-columns-spanned", tc.getNumberColumnsSpanned()); + addSpanAttribute(attributes, "number-rows-spanned", tc.getNumberRowsSpanned()); startElement(tc, attributes); } + private void addSpanAttribute(AttributesImpl attributes, String attributeName, int span) { + if (span > 1) { + addNoNamespaceAttribute(attributes, attributeName, Integer.toString(span)); + } + } + @Override public void endCell(TableCell tc) { endElement(tc); diff --git a/src/java/org/apache/fop/afp/AFPEventProducer.java b/src/java/org/apache/fop/afp/AFPEventProducer.java index 93eb9c042..01d5c4ad7 100644 --- a/src/java/org/apache/fop/afp/AFPEventProducer.java +++ b/src/java/org/apache/fop/afp/AFPEventProducer.java @@ -113,4 +113,13 @@ public interface AFPEventProducer extends EventProducer { * @event.severity ERROR */ void invalidConfiguration(Object source, Exception e); + + /** + * The characterset is missing metric information for the specified character + * @param source the event source + * @param character the character with missing metric information. + * @param charSet the character set containing missing metric information + * @event.severity WARN + */ + void charactersetMissingMetrics(Object source, char character, String charSet); } diff --git a/src/java/org/apache/fop/afp/AFPEventProducer.xml b/src/java/org/apache/fop/afp/AFPEventProducer.xml index 042eb5ed8..e17a4ea40 100644 --- a/src/java/org/apache/fop/afp/AFPEventProducer.xml +++ b/src/java/org/apache/fop/afp/AFPEventProducer.xml @@ -8,4 +8,5 @@ <message key="fontConfigMissing">The mandatory configuation node: '{missingConfig}' was not found at {location}.</message> <message key="characterSetNameInvalid">The character set given has an invalid name. [ Reason: {msg} ]</message> <message key="codePageNotFound">The code page for an AFP font cannot be found.[ Reason: {e}]</message> + <message key="charactersetMissingMetrics">Metric information is missing for the glyph `{character}` in the characterset `{charSet}`. Using space increment width.</message> </catalogue> diff --git a/src/java/org/apache/fop/afp/AFPGraphics2D.java b/src/java/org/apache/fop/afp/AFPGraphics2D.java index 7172b0ee3..937cf68b0 100644 --- a/src/java/org/apache/fop/afp/AFPGraphics2D.java +++ b/src/java/org/apache/fop/afp/AFPGraphics2D.java @@ -52,13 +52,13 @@ import org.apache.xmlgraphics.image.loader.ImageSize; import org.apache.xmlgraphics.image.loader.impl.ImageRendered; import org.apache.xmlgraphics.java2d.AbstractGraphics2D; import org.apache.xmlgraphics.java2d.GraphicContext; +import org.apache.xmlgraphics.java2d.GraphicsConfigurationWithTransparency; import org.apache.xmlgraphics.java2d.StrokingTextHandler; import org.apache.xmlgraphics.java2d.TextHandler; import org.apache.xmlgraphics.util.UnitConv; import org.apache.fop.afp.goca.GraphicsSetLineType; import org.apache.fop.afp.modca.GraphicsObject; -import org.apache.fop.afp.svg.AFPGraphicsConfiguration; import org.apache.fop.afp.util.CubicBezierApproximator; import org.apache.fop.fonts.FontInfo; import org.apache.fop.render.afp.AFPImageHandlerRenderedImage; @@ -111,7 +111,7 @@ public class AFPGraphics2D extends AbstractGraphics2D implements NativeImageHand private AFPPaintingState paintingState = null; /** AFP graphics configuration */ - private final AFPGraphicsConfiguration graphicsConfig = new AFPGraphicsConfiguration(); + private final GraphicsConfigurationWithTransparency graphicsConfig = new GraphicsConfigurationWithTransparency(); /** The AFP FontInfo */ private FontInfo fontInfo; diff --git a/src/java/org/apache/fop/afp/AFPResourceLevel.java b/src/java/org/apache/fop/afp/AFPResourceLevel.java index 860ca3d26..d56763050 100644 --- a/src/java/org/apache/fop/afp/AFPResourceLevel.java +++ b/src/java/org/apache/fop/afp/AFPResourceLevel.java @@ -66,9 +66,8 @@ public class AFPResourceLevel { } } - /** the external resource group file path */ private URI extUri = null; - private ResourceType resourceType; + private final ResourceType resourceType; /** * Sets the resource placement level within the AFP output @@ -84,7 +83,7 @@ public class AFPResourceLevel { /** * Main constructor * - * @param level the resource level + * @param resourceType the resource type */ public AFPResourceLevel(ResourceType resourceType) { this.resourceType = resourceType; @@ -156,7 +155,7 @@ public class AFPResourceLevel { /** * Sets the URI of the external resource group. * - * @param filePath the URI of the external resource group + * @param uri the URI of the external resource group */ public void setExternalUri(URI uri) { this.extUri = uri; diff --git a/src/java/org/apache/fop/afp/AFPResourceManager.java b/src/java/org/apache/fop/afp/AFPResourceManager.java index 885e13e5b..e9c8eda67 100644 --- a/src/java/org/apache/fop/afp/AFPResourceManager.java +++ b/src/java/org/apache/fop/afp/AFPResourceManager.java @@ -115,9 +115,9 @@ public class AFPResourceManager { } /** - * Sets the default resource group file path + * Sets the default resource group URI. * - * @param filePath the default resource group file path + * @param uri the default resource group URI */ public void setDefaultResourceGroupUri(URI uri) { diff --git a/src/java/org/apache/fop/afp/AFPStreamer.java b/src/java/org/apache/fop/afp/AFPStreamer.java index 072dc1796..fb2b282f6 100644 --- a/src/java/org/apache/fop/afp/AFPStreamer.java +++ b/src/java/org/apache/fop/afp/AFPStreamer.java @@ -99,9 +99,9 @@ public class AFPStreamer implements Streamable { } /** - * Sets the default resource group file path + * Sets the default resource group URI. * - * @param filePath the default resource group file path + * @param uri the default resource group URI */ public void setDefaultResourceGroupUri(URI uri) { this.defaultResourceGroupUri = uri; diff --git a/src/java/org/apache/fop/afp/fonts/AbstractOutlineFont.java b/src/java/org/apache/fop/afp/fonts/AbstractOutlineFont.java index 1a2611d8d..7b57a2b8c 100644 --- a/src/java/org/apache/fop/afp/fonts/AbstractOutlineFont.java +++ b/src/java/org/apache/fop/afp/fonts/AbstractOutlineFont.java @@ -19,6 +19,8 @@ package org.apache.fop.afp.fonts; +import org.apache.fop.afp.AFPEventProducer; + /** * A font defined as a set of lines and curves as opposed to a bitmap font. An * outline font can be scaled to any size and otherwise transformed more easily @@ -29,16 +31,25 @@ public abstract class AbstractOutlineFont extends AFPFont { /** The character set for this font */ protected CharacterSet charSet = null; + private final AFPEventProducer eventProducer; + /** * Constructor for an outline font. * * @param name the name of the font * @param embeddable sets whether or not this font is to be embedded * @param charSet the chracter set + * @param eventProducer The object to handle any events which occur from the object. */ - public AbstractOutlineFont(String name, boolean embeddable, CharacterSet charSet) { + public AbstractOutlineFont(String name, boolean embeddable, CharacterSet charSet, + AFPEventProducer eventProducer) { super(name, embeddable); this.charSet = charSet; + this.eventProducer = eventProducer; + } + + AFPEventProducer getAFPEventProducer() { + return eventProducer; } /** diff --git a/src/java/org/apache/fop/afp/fonts/CharacterSet.java b/src/java/org/apache/fop/afp/fonts/CharacterSet.java index 49e7f99ba..d54d478bc 100644 --- a/src/java/org/apache/fop/afp/fonts/CharacterSet.java +++ b/src/java/org/apache/fop/afp/fonts/CharacterSet.java @@ -363,4 +363,12 @@ public class CharacterSet { return getCharacterSetOrientation().getEmSpaceIncrement(); } + /** + * Returns the nominal character increment. + * @return the nominal character increment + */ + public int getNominalCharIncrement() { + return getCharacterSetOrientation().getNominalCharIncrement(); + } + } diff --git a/src/java/org/apache/fop/afp/fonts/CharacterSetBuilder.java b/src/java/org/apache/fop/afp/fonts/CharacterSetBuilder.java index 7331178f5..2565942b5 100644 --- a/src/java/org/apache/fop/afp/fonts/CharacterSetBuilder.java +++ b/src/java/org/apache/fop/afp/fonts/CharacterSetBuilder.java @@ -236,9 +236,9 @@ public abstract class CharacterSetBuilder { CharacterSetType charsetType, AFPResourceAccessor accessor, AFPEventProducer eventProducer) throws IOException { // check for cached version of the characterset - String descriptor = characterSetName + "_" + encoding + "_" + codePageName; - CharacterSet characterSet = (CharacterSet) characterSetsCache.get(descriptor); - + URI charSetURI = accessor.resolveURI(characterSetName); + String cacheKey = charSetURI.toASCIIString() + "_" + characterSetName + "_" + codePageName; + CharacterSet characterSet = (CharacterSet) characterSetsCache.get(cacheKey); if (characterSet != null) { return characterSet; } @@ -257,6 +257,8 @@ public abstract class CharacterSetBuilder { * chracter global identifier. */ Map<String, String> codePage; + // TODO: This could have performance implications if several threads want to use the + // codePagesCache to retrieve different codepages. synchronized (codePagesCache) { codePage = codePagesCache.get(codePageName); @@ -308,7 +310,7 @@ public abstract class CharacterSetBuilder { } finally { closeInputStream(inputStream); } - characterSetsCache.put(descriptor, characterSet); + characterSetsCache.put(cacheKey, characterSet); return characterSet; } @@ -446,20 +448,15 @@ public abstract class CharacterSetBuilder { position++; if (position == 26) { - position = 0; int orientation = determineOrientation(fnoData[2]); - // Space Increment - int space = ((fnoData[8] & 0xFF ) << 8) + (fnoData[9] & 0xFF); - // Em-Space Increment - int em = ((fnoData[14] & 0xFF ) << 8) + (fnoData[15] & 0xFF); - - CharacterSetOrientation cso = new CharacterSetOrientation(orientation); - cso.setSpaceIncrement(space); - cso.setEmSpaceIncrement(em); - orientations.add(cso); + int spaceIncrement = getUBIN(fnoData, 8); + int emIncrement = getUBIN(fnoData, 14); + int nominalCharacterIncrement = getUBIN(fnoData, 20); + orientations.add(new CharacterSetOrientation(orientation, spaceIncrement, + emIncrement, nominalCharacterIncrement)); } } return orientations.toArray(EMPTY_CSO_ARRAY); diff --git a/src/java/org/apache/fop/afp/fonts/CharacterSetOrientation.java b/src/java/org/apache/fop/afp/fonts/CharacterSetOrientation.java index 7ac8ae96b..a730525d2 100644 --- a/src/java/org/apache/fop/afp/fonts/CharacterSetOrientation.java +++ b/src/java/org/apache/fop/afp/fonts/CharacterSetOrientation.java @@ -60,7 +60,7 @@ public class CharacterSetOrientation { /** * The character widths in the character set (indexed using Unicode codepoints) */ - private int[] charsWidths = null; + private int[] charsWidths; /** * The height of lowercase letters @@ -77,25 +77,26 @@ public class CharacterSetOrientation { */ private char lastChar; - - /** - * The character set orientation - */ - private int orientation = 0; - + /** The character set orientation */ + private final int orientation; /** space increment */ - private int spaceIncrement; + private final int spaceIncrement; /** em space increment */ - private int emSpaceIncrement = -1; - + private final int emSpaceIncrement; + /** Nominal Character Increment */ + private final int nomCharIncrement; /** * Constructor for the CharacterSetOrientation, the orientation is * expressed as the degrees rotation (i.e 0, 90, 180, 270) * @param orientation the character set orientation */ - public CharacterSetOrientation(int orientation) { + public CharacterSetOrientation(int orientation, int spaceIncrement, int emSpaceIncrement, + int nomCharIncrement) { this.orientation = orientation; + this.spaceIncrement = spaceIncrement; + this.emSpaceIncrement = emSpaceIncrement; + this.nomCharIncrement = nomCharIncrement; charsWidths = new int[256]; Arrays.fill(charsWidths, -1); } @@ -284,14 +285,6 @@ public class CharacterSetOrientation { } /** - * Sets the space increment. - * @param value the space increment - */ - public void setSpaceIncrement(int value) { - this.spaceIncrement = value; - } - - /** * Returns the em space increment. * @return the em space increment */ @@ -300,11 +293,10 @@ public class CharacterSetOrientation { } /** - * Sets the em space increment. - * @param value the em space increment + * Returns the nominal character increment. + * @return the nominal character increment */ - public void setEmSpaceIncrement(int value) { - this.emSpaceIncrement = value; + public int getNominalCharIncrement() { + return this.nomCharIncrement; } - } diff --git a/src/java/org/apache/fop/afp/fonts/DoubleByteFont.java b/src/java/org/apache/fop/afp/fonts/DoubleByteFont.java index a81805bc5..78da6ea82 100644 --- a/src/java/org/apache/fop/afp/fonts/DoubleByteFont.java +++ b/src/java/org/apache/fop/afp/fonts/DoubleByteFont.java @@ -23,6 +23,11 @@ import java.lang.Character.UnicodeBlock; import java.util.HashSet; import java.util.Set; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.apache.fop.afp.AFPEventProducer; + /** * Implementation of AbstractOutlineFont that supports double-byte fonts (CID Keyed font (Type 0)). * The width of characters that are not prescribed a width metrics in the font resource use @@ -31,7 +36,9 @@ import java.util.Set; */ public class DoubleByteFont extends AbstractOutlineFont { - //private static final Log LOG = LogFactory.getLog(DoubleByteFont.class); + private static final Log log = LogFactory.getLog(DoubleByteFont.class); + + private final Set<Integer> charsProcessed; //See also http://unicode.org/reports/tr11/ which we've not closely looked at, yet //TODO the Unicode block listed here is probably not complete (ex. Hiragana, Katakana etc.) @@ -49,9 +56,12 @@ public class DoubleByteFont extends AbstractOutlineFont { * @param name the name of the font * @param embeddable whether or not this font is embeddable * @param charSet the character set + * @param eventProducer Handles any AFP related events */ - public DoubleByteFont(String name, boolean embeddable, CharacterSet charSet) { - super(name, embeddable, charSet); + public DoubleByteFont(String name, boolean embeddable, CharacterSet charSet, + AFPEventProducer eventProducer) { + super(name, embeddable, charSet, eventProducer); + charsProcessed = new HashSet<Integer>(); } /** {@inheritDoc} */ @@ -60,16 +70,30 @@ public class DoubleByteFont extends AbstractOutlineFont { try { charWidth = charSet.getWidth(toUnicodeCodepoint(character)); } catch (IllegalArgumentException e) { + if (!charsProcessed.contains(character)) { + charsProcessed.add(character); + getAFPEventProducer().charactersetMissingMetrics(this, (char)character, + charSet.getName().trim()); + } // We shall try and handle characters that have no mapped width metric in font resource charWidth = -1; } if (charWidth == -1) { - charWidth = inferCharWidth(character); + charWidth = getDefaultCharacterWidth(character); } return charWidth * size; } + private int getDefaultCharacterWidth(int character) { + int nominalCharIncrement = charSet.getNominalCharIncrement(); + if (nominalCharIncrement > 0) { + return nominalCharIncrement; + } else { + return inferCharWidth(character); + } + } + private int inferCharWidth(int character) { //Is this character an ideograph? diff --git a/src/java/org/apache/fop/afp/fonts/OutlineFont.java b/src/java/org/apache/fop/afp/fonts/OutlineFont.java index 103d96eca..e9cdf5ba4 100644 --- a/src/java/org/apache/fop/afp/fonts/OutlineFont.java +++ b/src/java/org/apache/fop/afp/fonts/OutlineFont.java @@ -19,6 +19,8 @@ package org.apache.fop.afp.fonts; +import org.apache.fop.afp.AFPEventProducer; + /** * Default implementation of AbstractOutlineFont. */ @@ -29,9 +31,11 @@ public class OutlineFont extends AbstractOutlineFont { * @param name font's name * @param embeddable whether or not this font is embeddable * @param charSet font's character set + * @param eventProducer Handles any AFP related events */ - public OutlineFont(String name, boolean embeddable, CharacterSet charSet) { - super(name, embeddable, charSet); + public OutlineFont(String name, boolean embeddable, CharacterSet charSet, + AFPEventProducer eventProducer) { + super(name, embeddable, charSet, eventProducer); } } diff --git a/src/java/org/apache/fop/afp/modca/IncludedResourceObject.java b/src/java/org/apache/fop/afp/modca/IncludedResourceObject.java index 9ab84a640..8bfcf4624 100644 --- a/src/java/org/apache/fop/afp/modca/IncludedResourceObject.java +++ b/src/java/org/apache/fop/afp/modca/IncludedResourceObject.java @@ -34,7 +34,7 @@ import org.apache.fop.afp.util.AFPResourceUtil; */ public class IncludedResourceObject extends AbstractNamedAFPObject { - private AFPResourceAccessor resourceAccessor; + private final AFPResourceAccessor resourceAccessor; private URI uri; /** diff --git a/src/java/org/apache/fop/afp/svg/AFPGraphicsConfiguration.java b/src/java/org/apache/fop/afp/svg/AFPGraphicsConfiguration.java deleted file mode 100644 index 0a051e675..000000000 --- a/src/java/org/apache/fop/afp/svg/AFPGraphicsConfiguration.java +++ /dev/null @@ -1,152 +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.afp.svg; - -import java.awt.GraphicsDevice; -import java.awt.Rectangle; -import java.awt.Transparency; -import java.awt.geom.AffineTransform; -import java.awt.image.BufferedImage; -import java.awt.image.ColorModel; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import org.apache.fop.svg.GraphicsConfiguration; - -/** - * Our implementation of the class that returns information about - * roughly what we can handle and want to see (alpha for example). - */ -public class AFPGraphicsConfiguration extends GraphicsConfiguration { - // We use this to get a good colormodel.. - private static final BufferedImage BI_WITH_ALPHA - = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB); - // We use this to get a good colormodel.. - private static final BufferedImage BI_WITHOUT_ALPHA - = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB); - - /** - * Construct a buffered image with an alpha channel, unless - * transparencty is OPAQUE (no alpha at all). - * - * @param width the width of the image - * @param height the height of the image - * @param transparency the alpha value of the image - * @return the new buffered image - */ - public BufferedImage createCompatibleImage(int width, int height, - int transparency) { - if (transparency == Transparency.OPAQUE) { - return new BufferedImage(width, height, - BufferedImage.TYPE_INT_RGB); - } else { - return new BufferedImage(width, height, - BufferedImage.TYPE_INT_ARGB); - } - } - - /** - * Construct a buffered image with an alpha channel. - * - * @param width the width of the image - * @param height the height of the image - * @return the new buffered image - */ - public BufferedImage createCompatibleImage(int width, int height) { - return new BufferedImage(width, height, - BufferedImage.TYPE_INT_ARGB); - } - - /** - * TODO: This should return the page bounds in Pts, - * I couldn't figure out how to get this for the current - * page (this still works for now, - * but it should be fixed...). - * - * @return the bounds of the page - */ - public Rectangle getBounds() { - return null; - } - - /** - * Return a good default color model for this 'device'. - * @return the colour model for the configuration - */ - public ColorModel getColorModel() { - return BI_WITH_ALPHA.getColorModel(); - } - - /** - * Return a good color model given <code>transparency</code> - * - * @param transparency the alpha value for the colour model - * @return the colour model for the configuration - */ - public ColorModel getColorModel(int transparency) { - if (transparency == Transparency.OPAQUE) { - return BI_WITHOUT_ALPHA.getColorModel(); - } else { - return BI_WITH_ALPHA.getColorModel(); - } - } - - private static final Log LOG - = LogFactory.getLog(AFPGraphicsConfiguration.class); - - private AffineTransform defaultTransform = null; - private AffineTransform normalizingTransform = null; - private final GraphicsDevice graphicsDevice = new AFPGraphicsDevice(this);; - - /** - * The default transform (1:1). - * - * @return the default transform for the configuration - */ - public AffineTransform getDefaultTransform() { - LOG.debug("getDefaultTransform()"); - if (defaultTransform == null) { - defaultTransform = new AffineTransform(); - } - return defaultTransform; - } - - /** - * The normalizing transform (1:1) (since we currently - * render images at 72dpi, which we might want to change - * in the future). - * - * @return the normalizing transform for the configuration - */ - public AffineTransform getNormalizingTransform() { - LOG.debug("getNormalizingTransform()"); - if (normalizingTransform == null) { - normalizingTransform = new AffineTransform(2, 0, 0, 2, 0, 0); - } - return normalizingTransform; - } - - /** {@inheritDoc} */ - public GraphicsDevice getDevice() { - LOG.debug("getDevice()"); - return graphicsDevice; - } -} diff --git a/src/java/org/apache/fop/afp/svg/AFPGraphicsDevice.java b/src/java/org/apache/fop/afp/svg/AFPGraphicsDevice.java deleted file mode 100644 index daa25aaa0..000000000 --- a/src/java/org/apache/fop/afp/svg/AFPGraphicsDevice.java +++ /dev/null @@ -1,80 +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.afp.svg; - -import java.awt.GraphicsConfiguration; -import java.awt.GraphicsDevice; - -/** - * This implements the GraphicsDevice interface as appropriate for - * an AFPGraphics2D. - */ -public class AFPGraphicsDevice extends GraphicsDevice { - - /** - * The Graphics Config that created us... - */ - protected GraphicsConfiguration gc; - - /** - * Create a new AF{ graphics device. - * - * @param gc The graphics configuration we should reference - */ - public AFPGraphicsDevice(AFPGraphicsConfiguration gc) { - this.gc = gc; - } - - /** - * Return an array of our one GraphicsConfig - * - * @return an array containing the one graphics configuration - */ - public GraphicsConfiguration[] getConfigurations() { - return new GraphicsConfiguration[] {gc}; - } - - /** - * Return out sole GraphicsConfig. - * - * @return the graphics configuration that created this object - */ - public GraphicsConfiguration getDefaultConfiguration() { - return this.gc; - } - - /** - * Generate an IdString.. - * - * @return the ID string for this device, uses toString - */ - public String getIDstring() { - return toString(); - } - - /** - * Let the caller know that we are "a printer" - * - * @return the type which is always printer - */ - public int getType() { - return GraphicsDevice.TYPE_PRINTER; - } -} diff --git a/src/java/org/apache/fop/afp/util/AFPResourceAccessor.java b/src/java/org/apache/fop/afp/util/AFPResourceAccessor.java index 02691527e..46b09be21 100644 --- a/src/java/org/apache/fop/afp/util/AFPResourceAccessor.java +++ b/src/java/org/apache/fop/afp/util/AFPResourceAccessor.java @@ -24,6 +24,9 @@ import java.io.InputStream; import java.net.URI; import java.net.URISyntaxException; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + import org.apache.fop.apps.io.InternalResourceResolver; /** @@ -31,46 +34,97 @@ import org.apache.fop.apps.io.InternalResourceResolver; */ public final class AFPResourceAccessor { + private static final Log log = LogFactory.getLog(AFPResourceAccessor.class); + private final InternalResourceResolver resourceResolver; - private final String baseURI; + private final URI baseURI; + private final URIResolver uriResolver; /** * Constructor for resource to be accessed via the {@link org.apache.fop.apps.FOUserAgent}. This * contructor takes a base URI for resolving font resource URIs. So, if fonts need to be - * accessed, you can set the {@link FontManager}'s base URI instead of the one on the - * {@link org.apache.fop.apps.FopFactory}. + * accessed, you can set the {@link org.apache.fop.fonts.FontManager}'s base URI instead of the + * one on the {@link org.apache.fop.apps.FopFactory}. * - * @param InternalResourceResolver resource resolver + * @param resourceResolver the resolver of resources * @param baseURI the custom base URI to resolve relative URIs against (may be null) */ public AFPResourceAccessor(InternalResourceResolver resourceResolver, String baseURI) { this.resourceResolver = resourceResolver; - this.baseURI = baseURI; + URI actualBaseURI = null; + URIResolver uriResolver; + if (baseURI == null) { + actualBaseURI = null; + uriResolver = new NullBaseURIResolver(); + } else { + try { + actualBaseURI = InternalResourceResolver.getBaseURI(baseURI); + uriResolver = new BaseURIResolver(); + } catch (URISyntaxException use) { + log.error("The URI given \"" + baseURI + "\" is invalid: " + use.getMessage()); + actualBaseURI = null; + uriResolver = new NullBaseURIResolver(); + } + } + this.baseURI = actualBaseURI; + this.uriResolver = uriResolver; } /** * Constructor for resource to be accessed via the {@link org.apache.fop.apps.FOUserAgent}. * - * @param InternalResourceResolver resource resolver + * @param resourceResolver the resolver of resources */ public AFPResourceAccessor(InternalResourceResolver resourceResolver) { this(resourceResolver, null); } - private URI getResourceURI(URI uri) { - if (baseURI == null) { + /** + * Creates an {@link InputStream} given a URI. + * + * @param uri the URI of the InputStream + * @return an InputStream + * @throws IOException if an I/O error occurs while creating the InputStream. + */ + public InputStream createInputStream(URI uri) throws IOException { + return resourceResolver.getResource(uriResolver.resolveURI(uri)); + } + + /** + * Returns the resolved URI, given the URI of a resource. + * + * @param uri the resource URI + * @return the resolved URI + */ + public URI resolveURI(String uri) { + return uriResolver.resolveURI(uri); + } + + private interface URIResolver { + URI resolveURI(URI uri); + + URI resolveURI(String uri); + } + + private final class NullBaseURIResolver implements URIResolver { + + public URI resolveURI(URI uri) { return uri; } - try { - URI baseURI = InternalResourceResolver.getBaseURI(this.baseURI); - return baseURI.resolve(uri); - } catch (URISyntaxException use) { - return uri; + + public URI resolveURI(String uri) { + return URI.create("./" + uri.trim()); } } - /** {@inheritDoc} */ - public InputStream createInputStream(URI uri) throws IOException { - return resourceResolver.getResource(getResourceURI(uri)); + private final class BaseURIResolver implements URIResolver { + + public URI resolveURI(URI uri) { + return baseURI.resolve(uri); + } + + public URI resolveURI(String uri) { + return baseURI.resolve(uri.trim()); + } } } diff --git a/src/java/org/apache/fop/apps/FOUserAgent.java b/src/java/org/apache/fop/apps/FOUserAgent.java index b4c69c6e3..0ed5b7228 100644 --- a/src/java/org/apache/fop/apps/FOUserAgent.java +++ b/src/java/org/apache/fop/apps/FOUserAgent.java @@ -166,7 +166,7 @@ public class FOUserAgent { * requires an output stream and you want to configure this very rendering run, * i.e. if you want to set some metadata like the title and author of the document * you want to render. In that case, create a new {@link FOUserAgent} instance - * using {@link #newFOUserAgent()}. + * using {@link org.apache.fop.apps.FopFactory#newFOUserAgent() newFOUserAgent()}. * <p> * MIME types are used to select the output format (ex. "application/pdf" for PDF). You can * use the constants defined in {@link MimeConstants}. @@ -184,7 +184,7 @@ public class FOUserAgent { * Returns a new {@link Fop} instance. Use this factory method if you want to configure this * very rendering run, i.e. if you want to set some metadata like the title and author of the * document you want to render. In that case, create a new {@link FOUserAgent} - * instance using {@link #newFOUserAgent()}. + * instance using {@link org.apache.fop.apps.FopFactory#newFOUserAgent() newFOUserAgent()}. * <p> * MIME types are used to select the output format (ex. "application/pdf" for PDF). You can * use the constants defined in {@link MimeConstants}. @@ -791,9 +791,8 @@ public class FOUserAgent { return factory.getColorSpaceCache(); } - /** @see {@link FopFactory#getHyphenationPatternNames()} */ + /** @see FopFactory#getHyphenationPatternNames() */ public Map<String, String> getHyphenationPatternNames() { return factory.getHyphenationPatternNames(); } } - diff --git a/src/java/org/apache/fop/apps/Fop.java b/src/java/org/apache/fop/apps/Fop.java index fc82ac1cb..5e3261221 100644 --- a/src/java/org/apache/fop/apps/Fop.java +++ b/src/java/org/apache/fop/apps/Fop.java @@ -52,7 +52,7 @@ public class Fop { private OutputStream stream = null; // FOUserAgent object to set processing options - private FOUserAgent foUserAgent = null; + private final FOUserAgent foUserAgent; // FOTreeBuilder object to maintain reference for access to results private FOTreeBuilder foTreeBuilder = null; @@ -81,6 +81,10 @@ public class Fop { /** * Get the FOUserAgent instance associated with the rendering run represented by this instance. * @return the user agent + * + * @deprecated this getter doesn't need to exist. By virtue of the fact that the client has + * an instance of this object, it means they also have the {@link FOUserAgent} since this's + * constructor is only used in {@link FOUserAgent} */ public FOUserAgent getUserAgent() { return foUserAgent; diff --git a/src/java/org/apache/fop/apps/FopConfParser.java b/src/java/org/apache/fop/apps/FopConfParser.java index bf39a53f0..c6e3dbd19 100644 --- a/src/java/org/apache/fop/apps/FopConfParser.java +++ b/src/java/org/apache/fop/apps/FopConfParser.java @@ -142,12 +142,20 @@ public class FopConfParser { log.debug("Initializing FopFactory Configuration"); } - // TODO: This makes this variable both strict FO and user-config validation, is that right? - boolean strict = false; // strict fo validation if (cfg.getChild("strict-validation", false) != null) { try { - strict = cfg.getChild("strict-validation").getValueAsBoolean(); + boolean strict = cfg.getChild("strict-validation").getValueAsBoolean(); + fopFactoryBuilder.setStrictFOValidation(strict); + } catch (ConfigurationException e) { + LogUtil.handleException(log, e, false); + } + } + + boolean strict = false; + if (cfg.getChild("strict-configuration", false) != null) { + try { + strict = cfg.getChild("strict-configuration").getValueAsBoolean(); fopFactoryBuilder.setStrictUserConfigValidation(strict); } catch (ConfigurationException e) { LogUtil.handleException(log, e, false); diff --git a/src/java/org/apache/fop/apps/FopFactory.java b/src/java/org/apache/fop/apps/FopFactory.java index 4508ea7fa..80c957f9f 100644 --- a/src/java/org/apache/fop/apps/FopFactory.java +++ b/src/java/org/apache/fop/apps/FopFactory.java @@ -295,7 +295,7 @@ public final class FopFactory implements ImageContext { * @return the config object * @throws FOPException when an error occurs while creating the configuration object */ - public RendererConfig getRendererConfig(FOUserAgent userAgent, Configuration cfg, + synchronized RendererConfig getRendererConfig(FOUserAgent userAgent, Configuration cfg, RendererConfigParser configCreator) throws FOPException { RendererConfig config = rendererConfig.get(configCreator.getMimeType()); if (config == null) { @@ -325,48 +325,41 @@ public final class FopFactory implements ImageContext { return config.isAccessibilityEnabled(); } - /** - * Returns the image manager. - * @return the image manager - */ + /** @see FopFactoryConfig#getImageManager() */ public ImageManager getImageManager() { return config.getImageManager(); } - /** - * Returns the overriding LayoutManagerMaker instance, if any. - * @return the overriding LayoutManagerMaker or null - */ + /** @see FopFactoryConfig#getLayoutManagerMakerOverride() */ public LayoutManagerMaker getLayoutManagerMakerOverride() { return config.getLayoutManagerMakerOverride(); } - /** @return the hyphenation pattern names */ + /** @see FopFactoryConfig#getHyphenationPatternNames() */ public Map<String, String> getHyphenationPatternNames() { return config.getHyphenationPatternNames(); } - /** - * Returns whether FOP is strictly validating input XSL - * @return true of strict validation turned on, false otherwise - */ + /** @see FopFactoryConfig#validateStrictly() */ public boolean validateStrictly() { return config.validateStrictly(); } - /** - * @return true if the indent inheritance should be broken when crossing reference area - * boundaries (for more info, see the javadoc for the relative member variable) - */ + /** @see FopFactoryConfig#isBreakIndentInheritanceOnReferenceAreaBoundary() */ public boolean isBreakIndentInheritanceOnReferenceAreaBoundary() { return config.isBreakIndentInheritanceOnReferenceAreaBoundary(); } - /** @return the resolution for resolution-dependent input */ + /** @see FopFactoryConfig#getSourceResolution() */ public float getSourceResolution() { return config.getSourceResolution(); } + /** @see FopFactoryConfig#getTargetResolution() */ + public float getTargetResolution() { + return config.getTargetResolution(); + } + /** * Returns the conversion factor from pixel units to millimeters. This * depends on the desired source resolution. @@ -377,11 +370,6 @@ public final class FopFactory implements ImageContext { return UnitConv.IN2MM / getSourceResolution(); } - /** @return the resolution for resolution-dependant output */ - public float getTargetResolution() { - return config.getTargetResolution(); - } - /** * Returns the conversion factor from pixel units to millimeters. This * depends on the desired target resolution. @@ -392,42 +380,26 @@ public final class FopFactory implements ImageContext { return 25.4f / getTargetResolution(); } - /** - * Gets the default page-height to use as fallback, - * in case page-height="auto" - * - * @return the page-height, as a String - */ + /** @see FopFactoryConfig#getPageHeight() */ public String getPageHeight() { return config.getPageHeight(); } - /** - * Gets the default page-width to use as fallback, - * in case page-width="auto" - * - * @return the page-width, as a String - */ + /** @see FopFactoryConfig#getPageWidth() */ public String getPageWidth() { return config.getPageWidth(); } - /** - * Indicates whether a namespace URI is on the ignored list. - * @param namespaceURI the namespace URI - * @return true if the namespace is ignored by FOP - */ + /** @see FopFactoryConfig#isNamespaceIgnored(String) */ public boolean isNamespaceIgnored(String namespaceURI) { return config.isNamespaceIgnored(namespaceURI); } - /** @return the set of namespaces that are ignored by FOP */ + /** @see FopFactoryConfig#getIgnoredNamespaces() */ public Set<String> getIgnoredNamespace() { return config.getIgnoredNamespaces(); } - //------------------------------------------- Configuration stuff - /** * Get the user configuration. * @return the user configuration @@ -436,20 +408,12 @@ public final class FopFactory implements ImageContext { return config.getUserConfig(); } - /** - * Is the user configuration to be validated? - * @return if the user configuration should be validated - */ + /** @see FopFactoryConfig#validateUserConfigStrictly() */ public boolean validateUserConfigStrictly() { return config.validateUserConfigStrictly(); } - //------------------------------------------- Font related stuff - - /** - * Returns the font manager. - * @return the font manager - */ + /** @see FopFactoryConfig#getFontManager() */ public FontManager getFontManager() { return config.getFontManager(); } diff --git a/src/java/org/apache/fop/apps/FopFactoryBuilder.java b/src/java/org/apache/fop/apps/FopFactoryBuilder.java index 6c3da57f3..cfc47496c 100644 --- a/src/java/org/apache/fop/apps/FopFactoryBuilder.java +++ b/src/java/org/apache/fop/apps/FopFactoryBuilder.java @@ -61,7 +61,7 @@ public final class FopFactoryBuilder { /** * A builder class for {@link FopFactory} which can be used for setting configuration. This is * a helper constructor that uses the default URI resolver implementation that FOP packages - * provide ({@link DefaultResourceResolver}). + * provide ({@link org.apache.fop.apps.io.ResourceResolverFactory.DefaultResourceResolver}). * * @param defaultBaseURI the default base URI for resolving URIs against */ @@ -97,6 +97,17 @@ public final class FopFactoryBuilder { * @deprecated Exposing the {@link FopFactoryConfig} is only to maintain backwards compatibility */ public FopFactoryConfig buildConfig() { + return buildConfiguration(); + } + + /** + * Builds the configuration object used by the FopFactory. + * + * @return the config for the {@link FopFactory} + */ + // The {@link FopFactoryConfig} doesn't need to be exposed in the "public" API, this method + // should remain package private. + FopFactoryConfig buildConfiguration() { fopFactoryConfigBuilder = CompletedFopFactoryConfigBuilder.INSTANCE; return config; } @@ -107,7 +118,7 @@ public final class FopFactoryBuilder { * @return the FopFactory instance */ public FopFactory build() { - return FopFactory.newInstance(buildConfig()); + return FopFactory.newInstance(buildConfiguration()); } /** @@ -150,13 +161,12 @@ public final class FopFactoryBuilder { /** * Sets the {@link LayoutManagerMaker} so that users can configure how FOP creates - * {@link LayoutManager}s. + * {@link org.apache.fop.layoutmgr.LayoutManager}s. * * @param lmMaker he layout manager maker * @return <code>this</code> */ - public FopFactoryBuilder setLayoutManagerMakerOverride( - LayoutManagerMaker lmMaker) { + public FopFactoryBuilder setLayoutManagerMakerOverride(LayoutManagerMaker lmMaker) { fopFactoryConfigBuilder.setLayoutManagerMakerOverride(lmMaker); return this; } @@ -285,11 +295,10 @@ public final class FopFactoryBuilder { } /** - * Sets whether to chose a {@link Renderer} in preference to an + * Sets whether to chose a {@link org.apache.fop.render.Renderer} in preference to an * {@link org.apache.fop.render.intermediate.IFDocumentHandler}. * - * @see {@link RendererFactory} - * @param preferRenderer true to prefer {@link Renderer} + * @param preferRenderer true to prefer {@link org.apache.fop.render.Renderer} * @return <code>this</code> */ public FopFactoryBuilder setPreferRenderer(boolean preferRenderer) { diff --git a/src/java/org/apache/fop/apps/FopFactoryConfig.java b/src/java/org/apache/fop/apps/FopFactoryConfig.java index 2545eea5e..60e8d98e7 100644 --- a/src/java/org/apache/fop/apps/FopFactoryConfig.java +++ b/src/java/org/apache/fop/apps/FopFactoryConfig.java @@ -34,6 +34,9 @@ import org.apache.fop.layoutmgr.LayoutManagerMaker; /** * The configuration data for a {@link FopFactory} instance. */ +// TODO: Make this interface and any implementations of this interface package private. Though +// they are used by classes that are considered the public API, this object doesn't need to be a +// part of the API. Why would a user care how the internal objects are passed around? They shouldn't. public interface FopFactoryConfig { /** Defines if FOP should use an alternative rule to determine text indents */ @@ -64,7 +67,10 @@ public interface FopFactoryConfig { */ boolean isAccessibilityEnabled(); - /** @see {@link FopFactory#getLayoutManagerMakerOverride()} */ + /** + * Returns the overriding LayoutManagerMaker instance, if any. + * @return the overriding LayoutManagerMaker or null + */ LayoutManagerMaker getLayoutManagerMakerOverride(); /** @@ -81,31 +87,54 @@ public interface FopFactoryConfig { */ URI getBaseURI(); - /** @see {@link FopFactory#validateStrictly()} */ + /** + * Returns whether FOP is strictly validating input XSL + * @return true of strict validation turned on, false otherwise + */ boolean validateStrictly(); - /** @see {@link FopFactory#validateUserConfigStrictly()} */ + /** + * Is the user configuration to be validated? + * @return if the user configuration should be validated + */ boolean validateUserConfigStrictly(); - /** @see {@link FopFactory#isBreakIndentInheritanceOnReferenceAreaBoundary()} */ + /** + * @return true if the indent inheritance should be broken when crossing reference area + * boundaries (for more info, see the javadoc for the relative member variable) + */ boolean isBreakIndentInheritanceOnReferenceAreaBoundary(); - /** @see {@link FopFactory#getSourceResolution()} */ + /** @return the resolution for resolution-dependent input */ float getSourceResolution(); - /** @see {@link FopFactory#getTargetResolution()} */ + /** @return the resolution for resolution-dependent output */ float getTargetResolution(); - /** @see {@link FopFactory#getPageHeight()} */ + /** + * Gets the default page-height to use as fallback, + * in case page-height="auto" + * + * @return the page-height, as a String + */ String getPageHeight(); - /** @see {@link FopFactory#getPageWidth()} */ + /** + * Gets the default page-width to use as fallback, + * in case page-width="auto" + * + * @return the page-width, as a String + */ String getPageWidth(); - /** @see {@link FopFactory#getIgnoredNamespace()} */ + /** @return the set of namespaces that are ignored by FOP */ Set<String> getIgnoredNamespaces(); - /** @see {@link FopFactory#isNamespaceIgnored(String)} */ + /** + * Indicates whether a namespace URI is on the ignored list. + * @param namespace the namespace URI + * @return true if the namespace is ignored by FOP + */ boolean isNamespaceIgnored(String namespace); /** @@ -115,17 +144,23 @@ public interface FopFactoryConfig { */ Configuration getUserConfig(); - /** @see {@link org.apache.fop.render.RendererFactory#isRendererPreferred()} */ + /** @see org.apache.fop.render.RendererFactory#isRendererPreferred() */ boolean preferRenderer(); - /** @see {@link FopFactory#getFontManager()} */ + /** + * Returns the font manager. + * @return the font manager + */ FontManager getFontManager(); - /** @see {@link FopFactory#getImageManager()} */ + /** + * Returns the image manager. + * @return the image manager + */ ImageManager getImageManager(); boolean isComplexScriptFeaturesEnabled(); - /** @see {@link FopFactory#getHyphenationPatternNames()} */ + /** @return the hyphenation pattern names */ Map<String, String> getHyphenationPatternNames(); } diff --git a/src/java/org/apache/fop/apps/io/ResourceResolverFactory.java b/src/java/org/apache/fop/apps/io/ResourceResolverFactory.java index 2c8300fb9..72eac456d 100644 --- a/src/java/org/apache/fop/apps/io/ResourceResolverFactory.java +++ b/src/java/org/apache/fop/apps/io/ResourceResolverFactory.java @@ -83,6 +83,15 @@ public final class ResourceResolverFactory { return new TempAwareResourceResolver(tempResourceResolver, defaultResourceResolver); } + /** + * This creates the builder class for binding URI schemas to implementations of + * {@link ResourceResolver}. This allows users to define their own URI schemas such that they + * have finer control over the acquisition of resources. + * + * @param defaultResolver the default resource resolver that should be used in the event that + * none of the other registered resolvers match the schema + * @return the schema aware {@link ResourceResolver} builder + */ public static SchemaAwareResourceResolverBuilder createSchemaAwareResourceResolverBuilder( ResourceResolver defaultResolver) { return new SchemaAwareResourceResolverBuilderImpl(defaultResolver); @@ -99,10 +108,12 @@ public final class ResourceResolverFactory { new NormalResourceResolver()); } + /** {@inheritDoc} */ public Resource getResource(URI uri) throws IOException { return delegate.getResource(uri); } + /** {@inheritDoc} */ public OutputStream getOutputStream(URI uri) throws IOException { return delegate.getOutputStream(uri); } @@ -125,6 +136,7 @@ public final class ResourceResolverFactory { return TempResourceURIGenerator.isTempUri(uri); } + /** {@inheritDoc} */ public Resource getResource(URI uri) throws IOException { if (isTempUri(uri)) { return tempResourceResolver.getResource(uri.getPath()); @@ -133,6 +145,7 @@ public final class ResourceResolverFactory { } } + /** {@inheritDoc} */ public OutputStream getOutputStream(URI uri) throws IOException { if (isTempUri(uri)) { return tempResourceResolver.getOutputStream(uri.getPath()); @@ -140,7 +153,6 @@ public final class ResourceResolverFactory { return defaultResourceResolver.getOutputStream(uri); } } - } private static class DefaultTempResourceResolver implements TempResourceResolver { @@ -150,10 +162,12 @@ public final class ResourceResolverFactory { return file; } + /** {@inheritDoc} */ public Resource getResource(String id) throws IOException { return new Resource(getTempFile(id).toURI().toURL().openStream()); } + /** {@inheritDoc} */ public OutputStream getOutputStream(String id) throws IOException { File file = getTempFile(id); if (file.createNewFile()) { @@ -196,19 +210,52 @@ public final class ResourceResolverFactory { } } + /** {@inheritDoc} */ public Resource getResource(URI uri) throws IOException { return getResourceResolverForSchema(uri).getResource(uri); } + /** {@inheritDoc} */ public OutputStream getOutputStream(URI uri) throws IOException { return getResourceResolverForSchema(uri).getOutputStream(uri); } } + /** + * Implementations of this interface will be builders for {@link ResourceResolver}, they bind + * URI schemas to their respective resolver. This gives users more control over the mechanisms + * by which URIs are resolved. + * <p> + * Here is an example of how this could be used: + * </p> + * <p><code> + * SchemaAwareResourceResolverBuilder builder + * = ResourceResolverFactory.createSchemaAwareResourceResolverBuilder(defaultResolver); + * builder.registerResourceResolverForSchema("test", testResolver); + * builder.registerResourceResolverForSchema("anotherTest", test2Resolver); + * ResourceResolver resolver = builder.build(); + * </code></p> + * This will result in all URIs for the form "test:///..." will be resolved using the + * <code>testResolver</code> object; URIs of the form "anotherTest:///..." will be resolved + * using <code>test2Resolver</code>; all other URIs will be resolved from the defaultResolver. + */ public interface SchemaAwareResourceResolverBuilder { + /** + * Register a schema with its respective {@link ResourceResolver}. This resolver will be + * used as the only resolver for the specified schema. + * + * @param schema the schema to be used with the given resolver + * @param resourceResolver the resource resolver + */ void registerResourceResolverForSchema(String schema, ResourceResolver resourceResolver); + /** + * Builds a {@link ResourceResolver} that will delegate to the respective resource resolver + * when a registered URI schema is given + * + * @return a resolver that delegates to the appropriate schema resolver + */ ResourceResolver build(); } @@ -218,10 +265,12 @@ public final class ResourceResolverFactory { private static final SchemaAwareResourceResolverBuilder INSTANCE = new CompletedSchemaAwareResourceResolverBuilder(); + /** {@inheritDoc} */ public ResourceResolver build() { throw new IllegalStateException("Resource resolver already built"); } + /** {@inheritDoc} */ public void registerResourceResolverForSchema(String schema, ResourceResolver resourceResolver) { throw new IllegalStateException("Resource resolver already built"); @@ -240,11 +289,13 @@ public final class ResourceResolverFactory { this.defaultResolver = defaultResolver; } + /** {@inheritDoc} */ public void registerResourceResolverForSchema(String schema, ResourceResolver resourceResolver) { schemaHandlingResourceResolvers.put(schema, resourceResolver); } + /** {@inheritDoc} */ public ResourceResolver build() { return new SchemaAwareResourceResolver( Collections.unmodifiableMap(schemaHandlingResourceResolvers), defaultResolver); @@ -261,11 +312,13 @@ public final class ResourceResolverFactory { this.delegate = new ActiveSchemaAwareResourceResolverBuilder(defaultResolver); } + /** {@inheritDoc} */ public void registerResourceResolverForSchema(String schema, ResourceResolver resourceResolver) { delegate.registerResourceResolverForSchema(schema, resourceResolver); } + /** {@inheritDoc} */ public ResourceResolver build() { ResourceResolver resourceResolver = delegate.build(); delegate = CompletedSchemaAwareResourceResolverBuilder.INSTANCE; diff --git a/src/java/org/apache/fop/apps/io/TempResourceResolver.java b/src/java/org/apache/fop/apps/io/TempResourceResolver.java index b17630a1d..cf307fab6 100644 --- a/src/java/org/apache/fop/apps/io/TempResourceResolver.java +++ b/src/java/org/apache/fop/apps/io/TempResourceResolver.java @@ -35,7 +35,7 @@ public interface TempResourceResolver { * @return the resource * @throws IOException if an I/O error occured during resource acquisition */ - Resource getResource(String id) throws IOException; + Resource getResource(String uri) throws IOException; /** * Gets an temporary-output stream of a given URI. @@ -44,5 +44,5 @@ public interface TempResourceResolver { * @return the output stream * @throws IOException if an I/O error occured while creating an output stream */ - OutputStream getOutputStream(String id) throws IOException; + OutputStream getOutputStream(String uri) throws IOException; } diff --git a/src/java/org/apache/fop/cli/CommandLineOptions.java b/src/java/org/apache/fop/cli/CommandLineOptions.java index aa402aa6a..886e27527 100644 --- a/src/java/org/apache/fop/cli/CommandLineOptions.java +++ b/src/java/org/apache/fop/cli/CommandLineOptions.java @@ -24,6 +24,7 @@ import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.PrintStream; +import java.net.URI; import java.util.Locale; import java.util.Map; import java.util.Vector; @@ -42,6 +43,7 @@ import org.apache.fop.apps.FOUserAgent; import org.apache.fop.apps.FopConfParser; import org.apache.fop.apps.FopFactory; import org.apache.fop.apps.FopFactoryBuilder; +import org.apache.fop.apps.FopFactoryConfig; import org.apache.fop.apps.MimeConstants; import org.apache.fop.pdf.PDFAMode; import org.apache.fop.pdf.PDFEncryptionManager; @@ -116,7 +118,7 @@ public class CommandLineOptions { /* rendering options (for the user agent) */ private Map renderingOptions = new java.util.HashMap(); /* target resolution (for the user agent) */ - private int targetResolution = 0; + private float targetResolution = FopFactoryConfig.DEFAULT_TARGET_RESOLUTION; private boolean strictValidation = true; /* control memory-conservation policy */ @@ -137,6 +139,8 @@ public class CommandLineOptions { private boolean flushCache = false; + private URI baseURI = new File(".").getAbsoluteFile().toURI(); + /** * Construct a command line option object. */ @@ -465,6 +469,7 @@ public class CommandLineOptions { this.useStdIn = true; } else { fofile = new File(filename); + baseURI = getBaseURI(fofile); } return 1; } @@ -494,11 +499,16 @@ public class CommandLineOptions { this.useStdIn = true; } else { xmlfile = new File(filename); + baseURI = getBaseURI(xmlfile); } return 1; } } + private URI getBaseURI(File file) { + return file.getAbsoluteFile().getParentFile().toURI(); + } + private int parseAWTOutputOption(String[] args, int i) throws FOPException { setOutputMode(MimeConstants.MIME_FOP_AWT_PREVIEW); return 0; @@ -725,6 +735,7 @@ public class CommandLineOptions { this.useStdIn = true; } else { fofile = new File(filename); + baseURI = getBaseURI(fofile); } } else if (outputmode == null) { outputmode = MimeConstants.MIME_PDF; @@ -783,6 +794,7 @@ public class CommandLineOptions { this.useStdIn = true; } else { areatreefile = new File(filename); + baseURI = getBaseURI(areatreefile); } return 1; } @@ -799,6 +811,7 @@ public class CommandLineOptions { this.useStdIn = true; } else { iffile = new File(filename); + baseURI = getBaseURI(iffile); } return 1; } @@ -815,6 +828,7 @@ public class CommandLineOptions { this.useStdIn = true; } else { imagefile = new File(filename); + baseURI = getBaseURI(imagefile); } return 1; } @@ -1030,15 +1044,22 @@ public class CommandLineOptions { private void setUserConfig() throws FOPException, IOException { FopFactoryBuilder fopFactoryBuilder; if (userConfigFile == null) { - fopFactoryBuilder = new FopFactoryBuilder(new File(".").toURI()); + fopFactoryBuilder = new FopFactoryBuilder(baseURI); + fopFactoryBuilder.setStrictFOValidation(strictValidation); + fopFactoryBuilder.setTargetResolution(targetResolution); + fopFactoryBuilder.setComplexScriptFeatures(useComplexScriptFeatures); } else { try { fopFactoryBuilder = new FopConfParser(userConfigFile).getFopFactoryBuilder(); } catch (SAXException e) { throw new FOPException(e); } - fopFactoryBuilder.setStrictFOValidation(strictValidation); - fopFactoryBuilder.setComplexScriptFeatures(useComplexScriptFeatures); + if (!strictValidation) { + fopFactoryBuilder.setStrictFOValidation(strictValidation); + } + if (useComplexScriptFeatures) { + fopFactoryBuilder.setComplexScriptFeatures(useComplexScriptFeatures); + } } factory = fopFactoryBuilder.build(); } diff --git a/src/java/org/apache/fop/fonts/DefaultFontConfig.java b/src/java/org/apache/fop/fonts/DefaultFontConfig.java index 6c5cebb42..375db34df 100644 --- a/src/java/org/apache/fop/fonts/DefaultFontConfig.java +++ b/src/java/org/apache/fop/fonts/DefaultFontConfig.java @@ -89,7 +89,7 @@ public final class DefaultFontConfig implements FontConfig { } else { this.strict = strict; this.fontInfoCfg = cfg.getChild("fonts", false); - instance = new DefaultFontConfig(cfg.getChild("auto-detect", false) != null); + instance = new DefaultFontConfig(fontInfoCfg.getChild("auto-detect", false) != null); parse(); } } diff --git a/src/java/org/apache/fop/fonts/DefaultFontConfigurator.java b/src/java/org/apache/fop/fonts/DefaultFontConfigurator.java index 2c60cf4bf..9534ef8ad 100644 --- a/src/java/org/apache/fop/fonts/DefaultFontConfigurator.java +++ b/src/java/org/apache/fop/fonts/DefaultFontConfigurator.java @@ -52,7 +52,6 @@ public class DefaultFontConfigurator implements FontConfigurator<EmbedFontInfo> /** * Main constructor - * @param fontInfoConfig the configuration object * @param fontManager the font manager * @param listener the font event listener * @param strict true if an Exception should be thrown if an error is found. diff --git a/src/java/org/apache/fop/fonts/FontCache.java b/src/java/org/apache/fop/fonts/FontCache.java index 35997f3d7..52db98ff3 100644 --- a/src/java/org/apache/fop/fonts/FontCache.java +++ b/src/java/org/apache/fop/fonts/FontCache.java @@ -53,7 +53,7 @@ public final class FontCache implements Serializable { * Serialization Version UID. Change this value if you want to make sure the * user's cache file is purged after an update. */ - private static final long serialVersionUID = 605232520271754719L; + private static final long serialVersionUID = 9129238336422194339L; /** logging instance */ private static Log log = LogFactory.getLog(FontCache.class); @@ -65,7 +65,7 @@ public final class FontCache implements Serializable { private static final String DEFAULT_CACHE_FILENAME = "fop-fonts.cache"; /** has this cache been changed since it was last read? */ - private transient boolean changed = false; + private transient boolean changed; /** change lock */ private final boolean[] changeLock = new boolean[1]; @@ -73,12 +73,14 @@ public final class FontCache implements Serializable { /** * master mapping of font url -> font info. This needs to be a list, since a * TTC file may contain more than 1 font. + * @serial */ private Map<String, CachedFontFile> fontfileMap = null; /** * mapping of font url -> file modified date (for all fonts that have failed * to load) + * @serial */ private Map<String, Long> failedFontMap = null; @@ -139,6 +141,7 @@ public final class FontCache implements Serializable { * * @return the font cache deserialized from the file (or null if no cache * file exists or if it could not be read) + * @deprecated use {@link #loadFrom(File)} instead */ public static FontCache load() { return loadFrom(getDefaultCacheFile(false)); @@ -190,8 +193,8 @@ public final class FontCache implements Serializable { /** * Writes the font cache to disk. * - * @throws FOPException - * fop exception + * @throws FOPException fop exception + * @deprecated use {@link #saveTo(File)} instead */ public void save() throws FOPException { saveTo(getDefaultCacheFile(true)); @@ -462,10 +465,9 @@ public final class FontCache implements Serializable { } /** - * Retrieve the last modified date/time of a URL. + * Retrieve the last modified date/time of a URI. * - * @param url - * the URL + * @param uri the URI * @return the last modified date/time */ public static long getLastModified(URI uri) { diff --git a/src/java/org/apache/fop/fonts/FontManager.java b/src/java/org/apache/fop/fonts/FontManager.java index e9b021978..bff001f73 100644 --- a/src/java/org/apache/fop/fonts/FontManager.java +++ b/src/java/org/apache/fop/fonts/FontManager.java @@ -138,7 +138,6 @@ public class FontManager { /** * Whether or not to cache results of font triplet detection/auto-config - * @param useCache use cache or not */ public void disableFontCache() { fontCacheManager = FontCacheManagerFactory.createDisabled(); @@ -163,8 +162,7 @@ public class FontManager { /** * Deletes the current FontCache file - * @return Returns true if the font cache file was successfully deleted. - * @throws FOPException - + * @throws FOPException if an error was thrown while deleting the cache */ public void deleteCache() throws FOPException { fontCacheManager.delete(getCacheFile(true)); diff --git a/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java b/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java index 5fa411101..9f94b4f49 100644 --- a/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java +++ b/src/java/org/apache/fop/layoutmgr/AbstractBreaker.java @@ -329,7 +329,7 @@ public abstract class AbstractBreaker { * @return the top-level LayoutContext */ protected LayoutContext createLayoutContext() { - return new LayoutContext(0); + return LayoutContext.newInstance(); } /** @@ -481,6 +481,11 @@ public abstract class AbstractBreaker { addAreas(alg, 0, partCount, originalList, effectiveList); } + protected void addAreas(PageBreakingAlgorithm alg, int startPart, int partCount, + BlockSequence originalList, BlockSequence effectiveList) { + addAreas(alg, startPart, partCount, originalList, effectiveList, LayoutContext.newInstance()); + } + /** * Phase 3 of Knuth algorithm: Adds the areas * @param alg PageBreakingAlgorithm instance which determined the breaks @@ -490,9 +495,7 @@ public abstract class AbstractBreaker { * @param effectiveList effective Knuth element list (after adjustments) */ protected void addAreas(PageBreakingAlgorithm alg, int startPart, int partCount, - BlockSequence originalList, BlockSequence effectiveList) { - LayoutContext childLC; - // add areas + BlockSequence originalList, BlockSequence effectiveList, final LayoutContext childLC) { int startElementIndex = 0; int endElementIndex = 0; int lastBreak = -1; @@ -507,7 +510,17 @@ public abstract class AbstractBreaker { ListElement lastBreakElement = effectiveList.getElement(endElementIndex); if (lastBreakElement.isPenalty()) { KnuthPenalty pen = (KnuthPenalty)lastBreakElement; - lastBreakClass = pen.getBreakClass(); + if (pen.getPenalty() == KnuthPenalty.INFINITE) { + /** + * That means that there was a keep.within-page="always", but that + * it's OK to break at a column. TODO The break class is being + * abused to implement keep.within-column and keep.within-page. + * This is very misleading and must be revised. + */ + lastBreakClass = Constants.EN_COLUMN; + } else { + lastBreakClass = pen.getBreakClass(); + } } else { lastBreakClass = Constants.EN_COLUMN; } @@ -550,19 +563,13 @@ public abstract class AbstractBreaker { // ignore KnuthGlue and KnuthPenalty objects // at the beginning of the line - ListIterator<KnuthElement> effectiveListIterator - = effectiveList.listIterator(startElementIndex); - while (effectiveListIterator.hasNext() - && !(effectiveListIterator.next()).isBox()) { - startElementIndex++; - } + startElementIndex = alg.par.getFirstBoxIndex(startElementIndex); if (startElementIndex <= endElementIndex) { if (log.isDebugEnabled()) { log.debug(" addAreas from " + startElementIndex + " to " + endElementIndex); } - childLC = new LayoutContext(0); // set the space adjustment ratio childLC.setSpaceAdjust(pbp.bpdAdjust); // add space before if display-align is center or bottom @@ -576,7 +583,9 @@ public abstract class AbstractBreaker { && p < (partCount - 1)) { // count the boxes whose width is not 0 int boxCount = 0; - effectiveListIterator = effectiveList.listIterator(startElementIndex); + @SuppressWarnings("unchecked") + ListIterator<KnuthElement> effectiveListIterator = effectiveList + .listIterator(startElementIndex); while (effectiveListIterator.nextIndex() <= endElementIndex) { KnuthElement tempEl = effectiveListIterator.next(); if (tempEl.isBox() && tempEl.getWidth() > 0) { diff --git a/src/java/org/apache/fop/layoutmgr/AreaAdditionUtil.java b/src/java/org/apache/fop/layoutmgr/AreaAdditionUtil.java index 97484aaab..c80982cce 100644 --- a/src/java/org/apache/fop/layoutmgr/AreaAdditionUtil.java +++ b/src/java/org/apache/fop/layoutmgr/AreaAdditionUtil.java @@ -40,7 +40,7 @@ public final class AreaAdditionUtil { public static void addAreas(BlockStackingLayoutManager bslm, PositionIterator parentIter, LayoutContext layoutContext) { LayoutManager childLM; - LayoutContext lc = new LayoutContext(0); + LayoutContext lc = LayoutContext.offspringOf(layoutContext); LayoutManager firstLM = null; LayoutManager lastLM = null; Position firstPos = null; diff --git a/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java index adce89ac0..920589657 100644 --- a/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/BlockContainerLayoutManager.java @@ -193,7 +193,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager impl */ @Override protected LayoutContext makeChildLayoutContext(LayoutContext context) { - LayoutContext childLC = new LayoutContext(0); + LayoutContext childLC = LayoutContext.newInstance(); childLC.setStackLimitBP( context.getStackLimitBP().minus(MinOptMax.getInstance(relDims.bpd))); childLC.setRefIPD(relDims.ipd); @@ -707,7 +707,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager impl return curChildLM; } - public void addContainedAreas() { + public void addContainedAreas(LayoutContext layoutContext) { if (isEmpty()) { return; } @@ -715,8 +715,10 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager impl //overflow should be visible. this.deferredAlg.removeAllPageBreaks(); this.addAreas(this.deferredAlg, + 0, this.deferredAlg.getPageBreaks().size(), - this.deferredOriginalList, this.deferredEffectiveList); + this.deferredOriginalList, this.deferredEffectiveList, + LayoutContext.offspringOf(layoutContext)); } } @@ -754,7 +756,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager impl LayoutManager childLM; LayoutManager lastLM = null; - LayoutContext lc = new LayoutContext(0); + LayoutContext lc = LayoutContext.offspringOf(layoutContext); lc.setSpaceAdjust(layoutContext.getSpaceAdjust()); // set space after in the LayoutContext for children if (layoutContext.getSpaceAfter() > 0) { @@ -821,7 +823,7 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager impl } } else { //Add child areas inside the reference area - bcpos.getBreaker().addContainedAreas(); + bcpos.getBreaker().addContainedAreas(layoutContext); } addMarkersToPage(false, isFirst(firstPos), isLast(lastPos)); @@ -1044,10 +1046,6 @@ public class BlockContainerLayoutManager extends BlockStackingLayoutManager impl return true; } - public int getBreakBefore() { - return BreakOpportunityHelper.getBreakBefore(this); - } - } diff --git a/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java index 03b2d380c..a99b45620 100644 --- a/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/BlockLayoutManager.java @@ -272,7 +272,7 @@ public class BlockLayoutManager extends BlockStackingLayoutManager implements Co LayoutManager childLM; LayoutManager lastLM = null; - LayoutContext lc = new LayoutContext(0); + LayoutContext lc = LayoutContext.offspringOf(layoutContext); lc.setSpaceAdjust(layoutContext.getSpaceAdjust()); // set space after in the LayoutContext for children if (layoutContext.getSpaceAfter() > 0) { @@ -504,8 +504,4 @@ public class BlockLayoutManager extends BlockStackingLayoutManager implements Co return true; } - public int getBreakBefore() { - return BreakOpportunityHelper.getBreakBefore(this); - } - } diff --git a/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java b/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java index 78ab6711a..d11f062cb 100644 --- a/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/BlockStackingLayoutManager.java @@ -383,7 +383,7 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager * @return a new child layout context */ protected LayoutContext makeChildLayoutContext(LayoutContext context) { - LayoutContext childLC = new LayoutContext(0); + LayoutContext childLC = LayoutContext.newInstance(); childLC.copyPendingMarksFrom(context); childLC.setStackLimitBP(context.getStackLimitBP()); childLC.setRefIPD(referenceIPD); @@ -1035,7 +1035,7 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager * @return true if an element has been added due to a break-before. */ protected boolean addKnuthElementsForBreakBefore(List returnList, LayoutContext context) { - int breakBefore = BreakOpportunityHelper.getBreakBefore(this); + int breakBefore = getBreakBefore(); if (breakBefore == EN_PAGE || breakBefore == EN_COLUMN || breakBefore == EN_EVEN_PAGE @@ -1050,6 +1050,17 @@ public abstract class BlockStackingLayoutManager extends AbstractLayoutManager } /** + * Returns the highest priority break-before value on this layout manager or its + * relevant descendants. + * + * @return the break-before value (Constants.EN_*) + * @see BreakOpportunity#getBreakBefore() + */ + public int getBreakBefore() { + return BreakOpportunityHelper.getBreakBefore(this); + } + + /** * Creates Knuth elements for break-after and adds them to the return list. * @param returnList return list to add the additional elements to * @param context the layout context diff --git a/src/java/org/apache/fop/layoutmgr/BreakingAlgorithm.java b/src/java/org/apache/fop/layoutmgr/BreakingAlgorithm.java index 7e55c31f6..3830878fe 100644 --- a/src/java/org/apache/fop/layoutmgr/BreakingAlgorithm.java +++ b/src/java/org/apache/fop/layoutmgr/BreakingAlgorithm.java @@ -532,14 +532,15 @@ public abstract class BreakingAlgorithm { // index of the first KnuthBox in the sequence, in case of non-centered // alignment. For centered alignment, we need to take into account preceding // penalties+glues used for the filler spaces - int firstBoxIndex = startIndex; + int previousPosition = startIndex; if (alignment != Constants.EN_CENTER) { - firstBoxIndex = par.getFirstBoxIndex(startIndex); + int firstBoxIndex = par.getFirstBoxIndex(startIndex); + previousPosition = (firstBoxIndex >= par.size()) ? startIndex : firstBoxIndex - 1; } - firstBoxIndex = (firstBoxIndex < 0) ? 0 : firstBoxIndex; + previousPosition = (previousPosition < 0) ? 0 : previousPosition; // create an active node representing the starting point - addNode(0, createNode(firstBoxIndex, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, null)); + addNode(0, createNode(previousPosition, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, null)); KnuthNode lastForced = getNode(0); if (log.isTraceEnabled()) { diff --git a/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java b/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java index 1ea3c84d4..0260046e1 100644 --- a/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/FlowLayoutManager.java @@ -200,7 +200,7 @@ public class FlowLayoutManager extends BlockStackingLayoutManager */ @Override protected LayoutContext makeChildLayoutContext(LayoutContext context) { - LayoutContext childLC = new LayoutContext(0); + LayoutContext childLC = LayoutContext.newInstance(); childLC.setStackLimitBP(context.getStackLimitBP()); childLC.setRefIPD(context.getRefIPD()); childLC.setWritingMode(getCurrentPage().getSimplePageMaster().getWritingMode()); diff --git a/src/java/org/apache/fop/layoutmgr/FootnoteBodyLayoutManager.java b/src/java/org/apache/fop/layoutmgr/FootnoteBodyLayoutManager.java index 078b7c451..432493a71 100644 --- a/src/java/org/apache/fop/layoutmgr/FootnoteBodyLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/FootnoteBodyLayoutManager.java @@ -42,7 +42,7 @@ public class FootnoteBodyLayoutManager extends BlockStackingLayoutManager { public void addAreas(PositionIterator parentIter, LayoutContext layoutContext) { LayoutManager childLM; LayoutManager lastLM = null; - LayoutContext lc = new LayoutContext(0); + LayoutContext lc = LayoutContext.newInstance(); // "unwrap" the NonLeafPositions stored in parentIter // and put them in a new list; diff --git a/src/java/org/apache/fop/layoutmgr/KnuthSequence.java b/src/java/org/apache/fop/layoutmgr/KnuthSequence.java index d568da45e..8d5e77ae0 100644 --- a/src/java/org/apache/fop/layoutmgr/KnuthSequence.java +++ b/src/java/org/apache/fop/layoutmgr/KnuthSequence.java @@ -20,6 +20,7 @@ package org.apache.fop.layoutmgr; import java.util.ArrayList; +import java.util.Iterator; import java.util.List; import java.util.ListIterator; @@ -159,46 +160,26 @@ public abstract class KnuthSequence extends ArrayList { : (ListElement) get(index); } - /** @return the position index of the first box in this sequence */ - protected int getFirstBoxIndex() { - if (isEmpty()) { - return -1; - } else { - return getFirstBoxIndex(0); - } - } - /** - * Get the position index of the first box in this sequence, - * starting at the given index. If there is no box after the - * passed {@code startIndex}, the starting index itself is returned. - * @param startIndex the starting index for the lookup - * @return the absolute position index of the next box element + * Returns the position index of the first box in this sequence, starting at the given + * index. If {@code startIndex} is outside the bounds of this sequence, it is + * returned. + * + * @param startIndex the index from which to start the lookup + * @return the index of the next box element, {@link #size()} if there is no such + * element, {@code startIndex} if {@code (startIndex < 0 || startIndex >= size())} */ protected int getFirstBoxIndex(int startIndex) { - if (isEmpty() || startIndex < 0 || startIndex >= size()) { - return -1; + if (startIndex < 0 || startIndex >= size()) { + return startIndex; } else { - ListElement element = null; - int posIndex = startIndex; - int lastIndex = size(); - while ( posIndex < lastIndex ) { - element = getElement(posIndex); - if ( !element.isBox() ) { - posIndex++; - } else { - break; - } - } - if ( posIndex != startIndex ) { - if ( ( element != null ) && element.isBox() ) { - return posIndex - 1; - } else { - return startIndex; - } - } else { - return startIndex; + int boxIndex = startIndex; + @SuppressWarnings("unchecked") + Iterator<ListElement> iter = listIterator(startIndex); + while (iter.hasNext() && !iter.next().isBox()) { + boxIndex++; } + return boxIndex; } } diff --git a/src/java/org/apache/fop/layoutmgr/LayoutContext.java b/src/java/org/apache/fop/layoutmgr/LayoutContext.java index a2512c50b..21983c20f 100644 --- a/src/java/org/apache/fop/layoutmgr/LayoutContext.java +++ b/src/java/org/apache/fop/layoutmgr/LayoutContext.java @@ -33,47 +33,27 @@ import org.apache.fop.traits.WritingMode; * This class is used to pass information to the getNextKnuthElements() * method. It is set up by higher level LM and used by lower level LM. */ -public class LayoutContext { +public final class LayoutContext { - /** linebreak at line feed only flag */ - public static final int LINEBREAK_AT_LF_ONLY = 0x01; /** Generated break possibility is first in a new area */ - public static final int NEW_AREA = 0x02; - /** ipd unknown flag */ - public static final int IPD_UNKNOWN = 0x04; - /** Signal to a Line LM that a higher level LM may provoke a change - * in the reference area, thus ref area IPD. The LineLM should return - * without looking for a line break. - */ - public static final int CHECK_REF_AREA = 0x08; + public static final int NEW_AREA = 0x01; /** * If this flag is set, it indicates that any break-before values other than "auto" should * not cause a mandatory break as this break was already handled by a parent layout manager. */ - public static final int SUPPRESS_BREAK_BEFORE = 0x10; - /** first area flag */ - public static final int FIRST_AREA = 0x20; - /** try hypenate flag */ - public static final int TRY_HYPHENATE = 0x40; - /** last area flag */ - public static final int LAST_AREA = 0x80; - /** resolve leading space flag */ - public static final int RESOLVE_LEADING_SPACE = 0x100; + public static final int SUPPRESS_BREAK_BEFORE = 0x02; - /** - * This flag indicates that there's a keep-with-next that hasn't - * been processed, yet. - */ - //public static final int KEEP_WITH_NEXT_PENDING = 0x200; - /** - * This flag indicates that there's a keep-with-previous that hasn't - * been processed, yet. - */ - //public static final int KEEP_WITH_PREVIOUS_PENDING = 0x400; + public static final int FIRST_AREA = 0x04; + + public static final int LAST_AREA = 0x08; + public static final int RESOLVE_LEADING_SPACE = 0x10; + + private static final int TREAT_AS_ARTIFACT = 0x20; private int flags; // Contains some set of flags defined above + /** * Total available stacking dimension for a "galley-level" layout * manager in block-progression-direction. It is passed by the @@ -145,11 +125,27 @@ public class LayoutContext { private int disableColumnBalancing; + public static LayoutContext newInstance() { + return new LayoutContext(0); + } + + public static LayoutContext copyOf(LayoutContext copy) { + return new LayoutContext(copy); + } + /** - * Copy constructor for creating child layout contexts. - * @param parentLC the parent layout context to copy from + * Returns a descendant of the given layout context. The new context is the same as + * what would have been created by {@link #newInstance()}, except for inheritable + * properties that are passed on by the parent. At the moment, the only inheritable + * property is the value returned by {@link #treatAsArtifact()}. */ - public LayoutContext(LayoutContext parentLC) { + public static LayoutContext offspringOf(LayoutContext parent) { + LayoutContext offspring = new LayoutContext(0); + offspring.setTreatAsArtifact(parent.treatAsArtifact()); + return offspring; + } + + private LayoutContext(LayoutContext parentLC) { this.flags = parentLC.flags; this.refIPD = parentLC.refIPD; this.writingMode = parentLC.writingMode; @@ -170,11 +166,7 @@ public class LayoutContext { this.disableColumnBalancing = parentLC.disableColumnBalancing; } - /** - * Main constructor. - * @param flags the initial flags - */ - public LayoutContext(int flags) { + private LayoutContext(int flags) { this.flags = flags; this.refIPD = 0; stackLimitBP = MinOptMax.ZERO; @@ -435,11 +427,6 @@ public class LayoutContext { return hyphContext; } - /** @return true if try hyphenate is set */ - public boolean tryHyphenate() { - return ((this.flags & TRY_HYPHENATE) != 0); - } - /** * Sets the currently applicable alignment in BP direction. * @param alignment one of EN_START, EN_JUSTIFY etc. @@ -673,7 +660,6 @@ public class LayoutContext { + "\nIs First Area: \t" + isFirstArea() + "\nStarts New Area: \t" + startsNewArea() + "\nIs Last Area: \t" + isLastArea() - + "\nTry Hyphenate: \t" + tryHyphenate() + "\nKeeps: \t[keep-with-next=" + getKeepWithNextPending() + "][keep-with-previous=" + getKeepWithPreviousPending() + "] pending" + "\nBreaks: \tforced [" + (breakBefore != Constants.EN_AUTO ? "break-before" : "") + "][" @@ -698,5 +684,13 @@ public class LayoutContext { public void setDisableColumnBalancing(int disableColumnBalancing) { this.disableColumnBalancing = disableColumnBalancing; } + + public boolean treatAsArtifact() { + return (flags & TREAT_AS_ARTIFACT) != 0; + } + + public void setTreatAsArtifact(boolean treatAsArtifact) { + setFlags(TREAT_AS_ARTIFACT, treatAsArtifact); + } } diff --git a/src/java/org/apache/fop/layoutmgr/PageBreaker.java b/src/java/org/apache/fop/layoutmgr/PageBreaker.java index 8fd131a73..309f4e32f 100644 --- a/src/java/org/apache/fop/layoutmgr/PageBreaker.java +++ b/src/java/org/apache/fop/layoutmgr/PageBreaker.java @@ -95,8 +95,7 @@ public class PageBreaker extends AbstractBreaker { return new PageBreakingLayoutListener() { public void notifyOverflow(int part, int amount, FObj obj) { - Page p = pageProvider.getPage( - false, part, PageProvider.RELTO_CURRENT_ELEMENT_LIST); + Page p = pageProvider.getPageFromColumnIndex(part); RegionBody body = (RegionBody)p.getSimplePageMaster().getRegion( Region.FO_REGION_BODY); BlockLevelEventProducer eventProducer = BlockLevelEventProducer.Provider.get( @@ -167,7 +166,7 @@ public class PageBreaker extends AbstractBreaker { && ((KnuthBlockBox) element).hasAnchors()) { // element represents a line with footnote citations containsFootnotes = true; - LayoutContext footnoteContext = new LayoutContext(context); + LayoutContext footnoteContext = LayoutContext.copyOf(context); footnoteContext.setStackLimitBP(context.getStackLimitBP()); footnoteContext.setRefIPD(pslm.getCurrentPV() .getRegionReference(Constants.FO_REGION_BODY).getIPD()); @@ -330,7 +329,7 @@ public class PageBreaker extends AbstractBreaker { //Get page break from which we restart PageBreakPosition pbp = (PageBreakPosition) alg.getPageBreaks().get(restartPoint - 1); - newStartPos = pbp.getLeafPos() + 1; + newStartPos = alg.par.getFirstBoxIndex(pbp.getLeafPos() + 1); //Handle page break right here to avoid any side-effects if (newStartPos > 0) { handleBreakTrait(Constants.EN_PAGE); @@ -473,7 +472,7 @@ public class PageBreaker extends AbstractBreaker { SpaceResolver.performConditionalsNotification(elementList, firstIndex, lastIndex, -1); - LayoutContext childLC = new LayoutContext(0); + LayoutContext childLC = LayoutContext.newInstance(); AreaAdditionUtil.addAreas(null, new KnuthPossPosIter(elementList, firstIndex, lastIndex + 1), childLC); @@ -521,7 +520,6 @@ public class PageBreaker extends AbstractBreaker { return; case Constants.EN_COLUMN: case Constants.EN_AUTO: - case Constants.EN_PAGE: case -1: PageViewport pv = curPage.getPageViewport(); @@ -545,6 +543,7 @@ public class PageBreaker extends AbstractBreaker { /*curPage = */pslm.makeNewPage(false); } return; + case Constants.EN_PAGE: default: log.debug("handling break-before after page " + pslm.getCurrentPageNum() + " breakVal=" + getBreakClassName(breakVal)); @@ -560,7 +559,7 @@ public class PageBreaker extends AbstractBreaker { } /** - * Check if a blank page is needed to accomodate + * Check if a blank page is needed to accommodate * desired even or odd page number. * @param breakVal - value of break-before or break-after trait. */ diff --git a/src/java/org/apache/fop/layoutmgr/PageProvider.java b/src/java/org/apache/fop/layoutmgr/PageProvider.java index 0ad990899..8117d547d 100644 --- a/src/java/org/apache/fop/layoutmgr/PageProvider.java +++ b/src/java/org/apache/fop/layoutmgr/PageProvider.java @@ -151,18 +151,37 @@ public class PageProvider implements Constants { return this.lastReportedBPD; } - // Wish there were a more elegant way to do this in Java - private int[] getColIndexAndColCount(int index) { + private static class Column { + + final Page page; + + final int pageIndex; + + final int colIndex; + + final int columnCount; + + Column(Page page, int pageIndex, int colIndex, int columnCount) { + this.page = page; + this.pageIndex = pageIndex; + this.colIndex = colIndex; + this.columnCount = columnCount; + } + + } + + private Column getColumn(int index) { int columnCount = 0; int colIndex = startColumnOfCurrentElementList + index; int pageIndex = -1; + Page page; do { colIndex -= columnCount; pageIndex++; - Page page = getPage(false, pageIndex, RELTO_CURRENT_ELEMENT_LIST); + page = getPage(false, pageIndex, RELTO_CURRENT_ELEMENT_LIST); columnCount = page.getPageViewport().getCurrentSpan().getColumnCount(); } while (colIndex >= columnCount); - return new int[] {colIndex, columnCount}; + return new Column(page, pageIndex, colIndex, columnCount); } /** @@ -173,22 +192,13 @@ public class PageProvider implements Constants { * than, equal to or greater than the IPD of the following part */ public int compareIPDs(int index) { - int columnCount = 0; - int colIndex = startColumnOfCurrentElementList + index; - int pageIndex = -1; - Page page; - do { - colIndex -= columnCount; - pageIndex++; - page = getPage(false, pageIndex, RELTO_CURRENT_ELEMENT_LIST); - columnCount = page.getPageViewport().getCurrentSpan().getColumnCount(); - } while (colIndex >= columnCount); - if (colIndex + 1 < columnCount) { + Column column = getColumn(index); + if (column.colIndex + 1 < column.columnCount) { // Next part is a column on same page => same IPD return 0; } else { - Page nextPage = getPage(false, pageIndex + 1, RELTO_CURRENT_ELEMENT_LIST); - return page.getPageViewport().getBodyRegion().getIPD() + Page nextPage = getPage(false, column.pageIndex + 1, RELTO_CURRENT_ELEMENT_LIST); + return column.page.getPageViewport().getBodyRegion().getIPD() - nextPage.getPageViewport().getBodyRegion().getIPD(); } } @@ -199,7 +209,7 @@ public class PageProvider implements Constants { * @return {@code true} if the break starts a new page */ boolean startPage(int index) { - return getColIndexAndColCount(index)[0] == 0; + return getColumn(index).colIndex == 0; } /** @@ -208,8 +218,8 @@ public class PageProvider implements Constants { * @return {@code true} if the break ends a page */ boolean endPage(int index) { - int[] colIndexAndColCount = getColIndexAndColCount(index); - return colIndexAndColCount[0] == colIndexAndColCount[1] - 1; + Column column = getColumn(index); + return column.colIndex == column.columnCount - 1; } /** @@ -219,7 +229,7 @@ public class PageProvider implements Constants { * @return the number of columns */ int getColumnCount(int index) { - return getColIndexAndColCount(index)[1]; + return getColumn(index).columnCount; } /** @@ -229,24 +239,12 @@ public class PageProvider implements Constants { * @return the requested part index */ public int getStartingPartIndexForLastPage(int partCount) { - int result = 0; - int idx = 0; - int pageIndex = 0; - int colIndex = startColumnOfCurrentElementList; - Page page = getPage( - false, pageIndex, RELTO_CURRENT_ELEMENT_LIST); - while (idx < partCount) { - if ((colIndex >= page.getPageViewport().getCurrentSpan().getColumnCount())) { - colIndex = 0; - pageIndex++; - page = getPage( - false, pageIndex, RELTO_CURRENT_ELEMENT_LIST); - result = idx; - } - colIndex++; - idx++; - } - return result; + int lastPartIndex = partCount - 1; + return lastPartIndex - getColumn(lastPartIndex).colIndex; + } + + Page getPageFromColumnIndex(int columnIndex) { + return getColumn(columnIndex).page; } /** @@ -291,7 +289,9 @@ public class PageProvider implements Constants { log.trace("last page requested: " + index); } } - while (intIndex >= cachedPages.size()) { + if (intIndex > cachedPages.size()) { + throw new UnsupportedOperationException("Cannot handle holes in page cache"); + } else if (intIndex == cachedPages.size()) { if (log.isTraceEnabled()) { log.trace("Caching " + index); } diff --git a/src/java/org/apache/fop/layoutmgr/StaticContentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/StaticContentLayoutManager.java index d5949f4a2..403daceb3 100644 --- a/src/java/org/apache/fop/layoutmgr/StaticContentLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/StaticContentLayoutManager.java @@ -232,7 +232,7 @@ public class StaticContentLayoutManager extends BlockStackingLayoutManager { List returnList = new LinkedList(); while ((curLM = getChildLM()) != null) { - LayoutContext childLC = new LayoutContext(0); + LayoutContext childLC = LayoutContext.newInstance(); childLC.setStackLimitBP(context.getStackLimitBP()); childLC.setRefIPD(context.getRefIPD()); childLC.setWritingMode(context.getWritingMode()); diff --git a/src/java/org/apache/fop/layoutmgr/inline/AbstractGraphicsLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/AbstractGraphicsLayoutManager.java index a7bc78be8..c3026e5e7 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/AbstractGraphicsLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/AbstractGraphicsLayoutManager.java @@ -24,6 +24,7 @@ import java.awt.Rectangle; import java.util.List; import org.apache.fop.area.Area; +import org.apache.fop.area.inline.InlineArea; import org.apache.fop.area.inline.InlineViewport; import org.apache.fop.datatypes.LengthBase; import org.apache.fop.fo.FObj; @@ -92,7 +93,6 @@ public abstract class AbstractGraphicsLayoutManager extends LeafNodeLayoutManage transferForeignAttributes(viewportArea); InlineViewport vp = new InlineViewport(viewportArea, bidiLevel); - TraitSetter.addStructureTreeElement(vp, fobj.getStructureTreeElement()); TraitSetter.setProducerID(vp, fobj.getId()); vp.setIPD(imageLayout.getViewportSize().width); vp.setBPD(imageLayout.getViewportSize().height); @@ -118,6 +118,21 @@ public abstract class AbstractGraphicsLayoutManager extends LeafNodeLayoutManage return super.getNextKnuthElements(context, alignment); } + @Override + protected InlineArea getEffectiveArea(LayoutContext layoutContext) { + /* + * If an image is in a repeated table heading, then it must be treated as real + * content the first time and then as artifact. Therefore we cannot re-use the + * area, as we have to account for the likely different values of treatAsArtifact. + */ + InlineArea area = curArea != null ? curArea : getInlineArea(); + curArea = null; + if (!layoutContext.treatAsArtifact()) { + TraitSetter.addStructureTreeElement(area, ((AbstractGraphics) fobj).getStructureTreeElement()); + } + return area; + } + /** {@inheritDoc} */ protected AlignmentContext makeAlignmentContext(LayoutContext context) { final AbstractGraphics fobj = (AbstractGraphics)this.fobj; diff --git a/src/java/org/apache/fop/layoutmgr/inline/AbstractPageNumberCitationLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/AbstractPageNumberCitationLayoutManager.java index b9110de9e..cad6fd3cf 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/AbstractPageNumberCitationLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/AbstractPageNumberCitationLayoutManager.java @@ -19,17 +19,18 @@ package org.apache.fop.layoutmgr.inline; -import org.apache.fop.area.Resolvable; +import org.apache.fop.area.PageViewport; import org.apache.fop.area.Trait; import org.apache.fop.area.inline.InlineArea; import org.apache.fop.area.inline.TextArea; +import org.apache.fop.area.inline.UnresolvedPageNumber; import org.apache.fop.fo.flow.AbstractPageNumberCitation; import org.apache.fop.fonts.Font; import org.apache.fop.fonts.FontInfo; import org.apache.fop.fonts.FontTriplet; import org.apache.fop.layoutmgr.LayoutContext; -import org.apache.fop.layoutmgr.PositionIterator; import org.apache.fop.layoutmgr.TraitSetter; +import org.apache.fop.traits.MinOptMax; /** * LayoutManager for the fo:page-number-citation(-last) formatting object @@ -42,7 +43,9 @@ public abstract class AbstractPageNumberCitationLayoutManager extends LeafNodeLa protected Font font; /** Indicates whether the page referred to by the citation has been resolved yet */ - protected boolean resolved = false; + private boolean resolved; + + private String citationString; /** * Constructor @@ -78,47 +81,79 @@ public abstract class AbstractPageNumberCitationLayoutManager extends LeafNodeLa ); } - /** {@inheritDoc} */ - public abstract InlineArea get(LayoutContext context); + @Override + protected MinOptMax getAllocationIPD(int refIPD) { + determineCitationString(); + int ipd = getStringWidth(citationString); + return MinOptMax.getInstance(ipd); + } - /** - * {@inheritDoc} - * , LayoutContext) - */ - public void addAreas(PositionIterator posIter, LayoutContext context) { - super.addAreas(posIter, context); - if (!resolved) { - getPSLM().addUnresolvedArea(fobj.getRefId(), (Resolvable) curArea); + private void determineCitationString() { + assert citationString == null; + PageViewport page = getCitedPage(); + if (page != null) { + resolved = true; + citationString = page.getPageNumberString(); + } else { + resolved = false; + citationString = "MMM"; // Use a place holder + } + } + + private int getStringWidth(String str) { + int width = 0; + for (int count = 0; count < str.length(); count++) { + width += font.getCharWidth(str.charAt(count)); + } + return width; + } + + protected abstract PageViewport getCitedPage(); + + @Override + protected InlineArea getEffectiveArea(LayoutContext layoutContext) { + InlineArea area = getPageNumberCitationArea(); + if (!layoutContext.treatAsArtifact()) { + TraitSetter.addStructureTreeElement(area, fobj.getStructureTreeElement()); + } + return area; + } + + private InlineArea getPageNumberCitationArea() { + TextArea text; + if (resolved) { + text = new TextArea(); + text.addWord(citationString, 0); + } else { + UnresolvedPageNumber unresolved = new UnresolvedPageNumber(fobj.getRefId(), font, + getReferenceType()); + getPSLM().addUnresolvedArea(fobj.getRefId(), unresolved); + text = unresolved; } + setTraits(text); + return text; } /** - * Updates the traits for the generated text area. - * @param text the text area + * @return {@link org.apache.fop.area.inline.UnresolvedPageNumber#FIRST} or + * {@link org.apache.fop.area.inline.UnresolvedPageNumber#LAST} */ - protected void updateTextAreaTraits(TextArea text) { + protected abstract boolean getReferenceType(); + + private void setTraits(TextArea text) { TraitSetter.setProducerID(text, fobj.getId()); + int bidiLevel = getBidiLevel(); + text.setBidiLevel(bidiLevel); + int width = getStringWidth(citationString); // TODO: [GA] !I18N! + text.setIPD(width); // TODO: [GA] !I18N! text.setBPD(font.getAscender() - font.getDescender()); text.setBaselineOffset(font.getAscender()); TraitSetter.addFontTraits(text, font); text.addTrait(Trait.COLOR, fobj.getColor()); - TraitSetter.addStructureTreeElement(text, fobj.getStructureTreeElement()); TraitSetter.addTextDecoration(text, fobj.getTextDecoration()); } /** - * @param str string to be measured - * @return width (in millipoints ??) of the string - */ - protected int getStringWidth(String str) { - int width = 0; - for (int count = 0; count < str.length(); count++) { - width += font.getCharWidth(str.charAt(count)); - } - return width; - } - - /** * @return bidi level governing abstract page number citation */ protected int getBidiLevel() { diff --git a/src/java/org/apache/fop/layoutmgr/inline/CharacterLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/CharacterLayoutManager.java index 32d4d1004..212170eae 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/CharacterLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/CharacterLayoutManager.java @@ -23,6 +23,7 @@ import java.util.LinkedList; import java.util.List; import org.apache.fop.area.Trait; +import org.apache.fop.area.inline.InlineArea; import org.apache.fop.area.inline.TextArea; import org.apache.fop.fo.flow.Character; import org.apache.fop.fo.properties.CommonBorderPaddingBackground; @@ -69,17 +70,15 @@ public class CharacterLayoutManager extends LeafNodeLayoutManager { hyphIPD = fobj.getCommonHyphenation().getHyphIPD(font); borderProps = fobj.getCommonBorderPaddingBackground(); setCommonBorderPaddingBackground(borderProps); - TextArea chArea = getCharacterInlineArea(fobj); - chArea.setBaselineOffset(font.getAscender()); - setCurrentArea(chArea); } - private TextArea getCharacterInlineArea(Character node) { + private TextArea createCharacterArea() { + Character fobj = (Character) this.fobj; TextArea text = new TextArea(); - char ch = node.getCharacter(); + char ch = fobj.getCharacter(); int ipd = font.getCharWidth(ch); int blockProgressionOffset = 0; - int level = node.getBidiLevel(); + int level = fobj.getBidiLevel(); if (CharUtilities.isAnySpace(ch)) { // add space unless it's zero-width: if (!CharUtilities.isZeroWidthSpace(ch)) { @@ -90,32 +89,29 @@ public class CharacterLayoutManager extends LeafNodeLayoutManager { int[] levels = ( level >= 0 ) ? new int[] {level} : null; text.addWord(String.valueOf(ch), ipd, null, levels, null, blockProgressionOffset); } - TraitSetter.setProducerID(text, node.getId()); - TraitSetter.addTextDecoration(text, node.getTextDecoration()); - TraitSetter.addStructureTreeElement(text, node.getStructureTreeElement()); + + TraitSetter.setProducerID(text, fobj.getId()); + TraitSetter.addTextDecoration(text, fobj.getTextDecoration()); + text.setIPD(font.getCharWidth(fobj.getCharacter())); + text.setBPD(font.getAscender() - font.getDescender()); + text.setBaselineOffset(font.getAscender()); + TraitSetter.addFontTraits(text, font); + text.addTrait(Trait.COLOR, fobj.getColor()); return text; } - /** {@inheritDoc} */ @Override - public List getNextKnuthElements(LayoutContext context, int alignment) { - MinOptMax ipd; - curArea = get(context); - KnuthSequence seq = new InlineKnuthSequence(); - - if (curArea == null) { - setFinished(true); - return null; + protected InlineArea getEffectiveArea(LayoutContext layoutContext) { + InlineArea area = createCharacterArea(); + if (!layoutContext.treatAsArtifact()) { + TraitSetter.addStructureTreeElement(area, ((Character) fobj).getStructureTreeElement()); } + return area; + } - Character fobj = (Character)this.fobj; - - ipd = MinOptMax.getInstance(curArea.getIPD()); - - curArea.setBPD(font.getAscender() - font.getDescender()); - - TraitSetter.addFontTraits(curArea, font); - curArea.addTrait(Trait.COLOR, fobj.getColor()); + /** {@inheritDoc} */ + public List getNextKnuthElements(LayoutContext context, int alignment) { + Character fobj = (Character) this.fobj; // TODO: may need some special handling for fo:character alignmentContext = new AlignmentContext(font @@ -126,9 +122,11 @@ public class CharacterLayoutManager extends LeafNodeLayoutManager { , fobj.getDominantBaseline() , context.getAlignmentContext()); + KnuthSequence seq = new InlineKnuthSequence(); addKnuthElementsForBorderPaddingStart(seq); // create the AreaInfo object to store the computed values + MinOptMax ipd = MinOptMax.getInstance(font.getCharWidth(fobj.getCharacter())); areaInfo = new AreaInfo((short) 0, ipd, false, alignmentContext); // node is a fo:Character @@ -162,7 +160,7 @@ public class CharacterLayoutManager extends LeafNodeLayoutManager { /** {@inheritDoc} */ @Override public String getWordChars(Position pos) { - return ((TextArea) curArea).getText(); + return String.valueOf(((Character) fobj).getCharacter()); } /** {@inheritDoc} */ diff --git a/src/java/org/apache/fop/layoutmgr/inline/ContentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/ContentLayoutManager.java index c7eaa1820..b3c768987 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/ContentLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/ContentLayoutManager.java @@ -110,7 +110,8 @@ public class ContentLayoutManager extends AbstractBaseLayoutManager int ipd = 1000000; - LayoutContext childLC = new LayoutContext(LayoutContext.NEW_AREA); + LayoutContext childLC = LayoutContext.newInstance(); + childLC.setFlags(LayoutContext.NEW_AREA); childLC.setLeadingSpace(new SpaceSpecifier(false)); childLC.setTrailingSpace(new SpaceSpecifier(false)); childLC.setRefIPD(ipd); @@ -143,7 +144,7 @@ public class ContentLayoutManager extends AbstractBaseLayoutManager middlefollow = maxtb - lineLead; } - LayoutContext lc = new LayoutContext(0); + LayoutContext lc = LayoutContext.newInstance(); lc.setFlags(LayoutContext.RESOLVE_LEADING_SPACE, true); lc.setLeadingSpace(new SpaceSpecifier(false)); @@ -160,7 +161,7 @@ public class ContentLayoutManager extends AbstractBaseLayoutManager int savedIPD = ((InlineArea)holder).getIPD(); // set to zero the ipd adjustment ratio, to avoid spaces in the pattern // to be modified - LayoutContext childContext = new LayoutContext(context); + LayoutContext childContext = LayoutContext.copyOf(context); childContext.setIPDAdjust(0.0); childLM.addAreas(posIter, childContext); ((InlineArea)holder).setIPD(savedIPD); diff --git a/src/java/org/apache/fop/layoutmgr/inline/FootnoteLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/FootnoteLayoutManager.java index 68a240ff1..50b88b5b9 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/FootnoteLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/FootnoteLayoutManager.java @@ -151,7 +151,7 @@ public class FootnoteLayoutManager extends InlineStackingLayoutManager { citationLM.setParent(getParent()); // make the citationLM add its areas - LayoutContext childContext = new LayoutContext(context); + LayoutContext childContext = LayoutContext.copyOf(context); PositionIterator childPosIter = new PositionIterator(positionList.listIterator()); LayoutManager childLM; while ((childLM = childPosIter.getNextChildLM()) != null) { diff --git a/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java index e87b29b2d..77ac8c4d6 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/InlineLayoutManager.java @@ -283,7 +283,7 @@ public class InlineLayoutManager extends InlineStackingLayoutManager { , context.getAlignmentContext()); } - childLC = new LayoutContext(context); + childLC = LayoutContext.copyOf(context); childLC.setAlignmentContext(alignmentContext); if (context.startsNewArea()) { @@ -439,7 +439,7 @@ public class InlineLayoutManager extends InlineStackingLayoutManager { addId(); - setChildContext(new LayoutContext(context)); // Store current value + setChildContext(LayoutContext.copyOf(context)); // Store current value // "Unwrap" the NonLeafPositions stored in parentIter and put // them in a new list. Set lastLM to be the LayoutManager diff --git a/src/java/org/apache/fop/layoutmgr/inline/LeaderLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/LeaderLayoutManager.java index b3d3218ab..aa2f79759 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/LeaderLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/LeaderLayoutManager.java @@ -191,7 +191,7 @@ public class LeaderLayoutManager extends LeafNodeLayoutManager { clm.addChildLM(lm); lm.initialize(); - LayoutContext childContext = new LayoutContext(0); + LayoutContext childContext = LayoutContext.newInstance(); childContext.setAlignmentContext(context.getAlignmentContext()); contentList = clm.getNextKnuthElements(childContext, 0); int width = clm.getStackingSize(); diff --git a/src/java/org/apache/fop/layoutmgr/inline/LeafNodeLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/LeafNodeLayoutManager.java index 203c7a7fc..001fde817 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/LeafNodeLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/LeafNodeLayoutManager.java @@ -188,7 +188,7 @@ public abstract class LeafNodeLayoutManager extends AbstractLayoutManager public void addAreas(PositionIterator posIter, LayoutContext context) { addId(); - InlineArea area = getEffectiveArea(); + InlineArea area = getEffectiveArea(context); if (area.getAllocIPD() > 0 || area.getAllocBPD() > 0) { offsetArea(area, context); widthAdjustArea(area, context); @@ -211,7 +211,7 @@ public abstract class LeafNodeLayoutManager extends AbstractLayoutManager * @return the effective area to be added to the area tree. Normally, this is simply "curArea" * but in the case of page-number(-citation) curArea is cloned, updated and returned. */ - protected InlineArea getEffectiveArea() { + protected InlineArea getEffectiveArea(LayoutContext layoutContext) { return curArea; } @@ -264,11 +264,6 @@ public abstract class LeafNodeLayoutManager extends AbstractLayoutManager public List getNextKnuthElements(LayoutContext context, int alignment) { curArea = get(context); - if (curArea == null) { - setFinished(true); - return null; - } - alignmentContext = makeAlignmentContext(context); MinOptMax ipd = getAllocationIPD(context.getRefIPD()); diff --git a/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java index 5b8145432..00cd427d9 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java @@ -674,7 +674,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager * @param context the LayoutContext */ private void collectInlineKnuthElements(LayoutContext context) { - LayoutContext inlineLC = new LayoutContext(context); + LayoutContext inlineLC = LayoutContext.copyOf(context); // convert all the text in a sequence of paragraphs made // of KnuthBox, KnuthGlue and KnuthPenalty objects @@ -1522,7 +1522,7 @@ public class LineLayoutManager extends InlineStackingLayoutManager PositionIterator inlinePosIter = new KnuthPossPosIter(seq, startElementIndex, endElementIndex + 1); - LayoutContext lc = new LayoutContext(0); + LayoutContext lc = LayoutContext.offspringOf(context); lc.setAlignmentContext(alignmentContext); lc.setSpaceAdjust(lbp.dAdjust); lc.setIPDAdjust(lbp.ipdAdjust); @@ -1577,12 +1577,12 @@ public class LineLayoutManager extends InlineStackingLayoutManager LineArea lineArea = new LineArea(); setCurrentArea(lineArea); - LayoutContext lc = new LayoutContext(0); + LayoutContext lc = LayoutContext.newInstance(); lc.setAlignmentContext(alignmentContext); setChildContext(lc); PositionIterator childPosIter = new PositionIterator(positionList.listIterator()); - LayoutContext blocklc = new LayoutContext(0); + LayoutContext blocklc = LayoutContext.offspringOf(context); blocklc.setLeadingSpace(new SpaceSpecifier(true)); blocklc.setTrailingSpace(new SpaceSpecifier(false)); blocklc.setFlags(LayoutContext.RESOLVE_LEADING_SPACE, true); diff --git a/src/java/org/apache/fop/layoutmgr/inline/PageNumberCitationLastLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/PageNumberCitationLastLayoutManager.java index b1ba38565..81846615f 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/PageNumberCitationLastLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/PageNumberCitationLastLayoutManager.java @@ -20,65 +20,36 @@ package org.apache.fop.layoutmgr.inline; import org.apache.fop.area.PageViewport; -import org.apache.fop.area.Resolvable; -import org.apache.fop.area.inline.InlineArea; -import org.apache.fop.area.inline.TextArea; import org.apache.fop.area.inline.UnresolvedPageNumber; import org.apache.fop.fo.flow.PageNumberCitationLast; -import org.apache.fop.layoutmgr.LayoutContext; -import org.apache.fop.layoutmgr.LayoutManager; /** - * LayoutManager for the fo:page-number-citation-last formatting object + * LayoutManager for the fo:page-number-citation-last formatting object. */ public class PageNumberCitationLastLayoutManager extends AbstractPageNumberCitationLayoutManager { /** - * Constructor + * Constructor. * * @param node the formatting object that creates this area * TODO better retrieval of font info */ public PageNumberCitationLastLayoutManager(PageNumberCitationLast node) { super(node); - fobj = node; } - /** {@inheritDoc} */ - public InlineArea get(LayoutContext context) { - curArea = getPageNumberCitationLastInlineArea(parentLayoutManager); - return curArea; - } - - /** - * if id can be resolved then simply return a word, otherwise - * return a resolvable area - */ - private InlineArea getPageNumberCitationLastInlineArea(LayoutManager parentLM) { - TextArea text = null; - int level = getBidiLevel(); - if (!getPSLM().associateLayoutManagerID(fobj.getRefId())) { - text = new UnresolvedPageNumber(fobj.getRefId(), font, UnresolvedPageNumber.LAST); - getPSLM().addUnresolvedArea(fobj.getRefId(), (Resolvable)text); - String str = "MMM"; // reserve three spaces for page number - int width = getStringWidth(str); - text.setBidiLevel(level); - text.setIPD(width); - resolved = false; + @Override + protected PageViewport getCitedPage() { + if (getPSLM().associateLayoutManagerID(fobj.getRefId())) { + return getPSLM().getLastPVWithID(fobj.getRefId()); } else { - PageViewport page = getPSLM().getLastPVWithID(fobj.getRefId()); - String str = page.getPageNumberString(); - // get page string from parent, build area - text = new TextArea(); - int width = getStringWidth(str); - text.setBidiLevel(level); - text.addWord(str, 0, level); - text.setIPD(width); - resolved = true; + return null; } + } - updateTextAreaTraits(text); - - return text; + @Override + protected boolean getReferenceType() { + return UnresolvedPageNumber.LAST; } + } diff --git a/src/java/org/apache/fop/layoutmgr/inline/PageNumberCitationLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/PageNumberCitationLayoutManager.java index 16ce09ec5..a4976f833 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/PageNumberCitationLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/PageNumberCitationLayoutManager.java @@ -20,19 +20,16 @@ package org.apache.fop.layoutmgr.inline; import org.apache.fop.area.PageViewport; -import org.apache.fop.area.inline.InlineArea; -import org.apache.fop.area.inline.TextArea; import org.apache.fop.area.inline.UnresolvedPageNumber; import org.apache.fop.fo.flow.PageNumberCitation; -import org.apache.fop.layoutmgr.LayoutContext; /** - * LayoutManager for the fo:page-number-citation formatting object + * LayoutManager for the fo:page-number-citation formatting object. */ public class PageNumberCitationLayoutManager extends AbstractPageNumberCitationLayoutManager { /** - * Constructor + * Constructor. * * @param node the formatting object that creates this area * TODO better retrieval of font info @@ -41,42 +38,14 @@ public class PageNumberCitationLayoutManager extends AbstractPageNumberCitationL super(node); } - /** {@inheritDoc} */ - public InlineArea get(LayoutContext context) { - curArea = getPageNumberCitationInlineArea(); - return curArea; + @Override + protected PageViewport getCitedPage() { + return getPSLM().getFirstPVWithID(fobj.getRefId()); } - /** - * if id can be resolved then simply return a word, otherwise - * return a resolvable area - * - * TODO: [GA] May need to run bidi algorithm and script processor - * on resolved page number. - */ - private InlineArea getPageNumberCitationInlineArea() { - PageViewport page = getPSLM().getFirstPVWithID(fobj.getRefId()); - TextArea text = null; - int level = getBidiLevel(); - if (page != null) { - String str = page.getPageNumberString(); - // get page string from parent, build area - text = new TextArea(); - int width = getStringWidth(str); // TODO: [GA] !I18N! - text.setBidiLevel(level); - text.addWord(str, 0, level); - text.setIPD(width); // TODO: [GA] !I18N! - resolved = true; - } else { - text = new UnresolvedPageNumber(fobj.getRefId(), font); - String str = "MMM"; // reserve three spaces for page number - int width = getStringWidth(str); // TODO: [GA] !I18N! - text.setBidiLevel(level); - text.setIPD(width); // TODO: [GA] !I18N! - resolved = false; - } - updateTextAreaTraits(text); - return text; + @Override + protected boolean getReferenceType() { + return UnresolvedPageNumber.FIRST; } } diff --git a/src/java/org/apache/fop/layoutmgr/inline/PageNumberLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/PageNumberLayoutManager.java index c3ee5af32..82e53666c 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/PageNumberLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/PageNumberLayoutManager.java @@ -85,14 +85,13 @@ public class PageNumberLayoutManager extends LeafNodeLayoutManager { text.setBaselineOffset(font.getAscender()); TraitSetter.addFontTraits(text, font); text.addTrait(Trait.COLOR, fobj.getColor()); - TraitSetter.addStructureTreeElement(text, fobj.getStructureTreeElement()); TraitSetter.addTextDecoration(text, fobj.getTextDecoration()); return text; } /** {@inheritDoc} */ - protected InlineArea getEffectiveArea() { + protected InlineArea getEffectiveArea(LayoutContext layoutContext) { TextArea baseArea = (TextArea)curArea; //TODO Maybe replace that with a clone() call or better, a copy constructor //TODO or even better: delay area creation until addAreas() stage @@ -105,6 +104,9 @@ public class PageNumberLayoutManager extends LeafNodeLayoutManager { ta.setBaselineOffset(baseArea.getBaselineOffset()); ta.addTrait(Trait.COLOR, fobj.getColor()); //only to initialize the trait map ta.getTraits().putAll(baseArea.getTraits()); + if (!layoutContext.treatAsArtifact()) { + TraitSetter.addStructureTreeElement(ta, fobj.getStructureTreeElement()); + } updateContent(ta); return ta; } diff --git a/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java index 645a78527..c2f69cf98 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/TextLayoutManager.java @@ -469,7 +469,9 @@ public class TextLayoutManager extends LeafNodeLayoutManager { TraitSetter.addFontTraits(textArea, font); textArea.addTrait(Trait.COLOR, foText.getColor()); TraitSetter.addTextDecoration(textArea, foText.getTextDecoration()); - TraitSetter.addStructureTreeElement(textArea, foText.getStructureTreeElement()); + if (!context.treatAsArtifact()) { + TraitSetter.addStructureTreeElement(textArea, foText.getStructureTreeElement()); + } return textArea; } diff --git a/src/java/org/apache/fop/layoutmgr/inline/WrapperLayoutManager.java b/src/java/org/apache/fop/layoutmgr/inline/WrapperLayoutManager.java index ca5179399..9b37e2405 100644 --- a/src/java/org/apache/fop/layoutmgr/inline/WrapperLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/inline/WrapperLayoutManager.java @@ -71,7 +71,7 @@ public class WrapperLayoutManager extends LeafNodeLayoutManager { TraitSetter.setProducerID(helperBlock, fobj.getId()); parentLayoutManager.addChildArea(helperBlock); } else { - InlineArea area = getEffectiveArea(); + InlineArea area = getEffectiveArea(context); parentLayoutManager.addChildArea(area); } } diff --git a/src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java b/src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java index 5bd451ffb..480934bf3 100644 --- a/src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/list/ListBlockLayoutManager.java @@ -141,7 +141,7 @@ public class ListBlockLayoutManager extends BlockStackingLayoutManager // the list block contains areas stacked from each list item LayoutManager childLM; - LayoutContext lc = new LayoutContext(0); + LayoutContext lc = LayoutContext.offspringOf(layoutContext); LayoutManager firstLM = null; LayoutManager lastLM = null; Position firstPos = null; diff --git a/src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java index a84069082..3204a867e 100644 --- a/src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/list/ListItemContentLayoutManager.java @@ -20,6 +20,7 @@ package org.apache.fop.layoutmgr.list; import java.util.LinkedList; +import java.util.List; import org.apache.fop.area.Area; import org.apache.fop.area.Block; @@ -28,9 +29,11 @@ import org.apache.fop.fo.flow.ListItemBody; import org.apache.fop.fo.flow.ListItemLabel; import org.apache.fop.fo.properties.KeepProperty; import org.apache.fop.layoutmgr.BlockStackingLayoutManager; +import org.apache.fop.layoutmgr.BreakOpportunity; import org.apache.fop.layoutmgr.Keep; import org.apache.fop.layoutmgr.LayoutContext; import org.apache.fop.layoutmgr.LayoutManager; +import org.apache.fop.layoutmgr.ListElement; import org.apache.fop.layoutmgr.NonLeafPosition; import org.apache.fop.layoutmgr.Position; import org.apache.fop.layoutmgr.PositionIterator; @@ -40,7 +43,7 @@ import org.apache.fop.layoutmgr.TraitSetter; /** * LayoutManager for a list-item-label or list-item-body FO. */ -public class ListItemContentLayoutManager extends BlockStackingLayoutManager { +public class ListItemContentLayoutManager extends BlockStackingLayoutManager implements BreakOpportunity { private Block curBlockArea; @@ -98,7 +101,7 @@ public class ListItemContentLayoutManager extends BlockStackingLayoutManager { addId(); LayoutManager childLM; - LayoutContext lc = new LayoutContext(0); + LayoutContext lc = LayoutContext.offspringOf(layoutContext); LayoutManager firstLM = null; LayoutManager lastLM = null; Position firstPos = null; @@ -220,5 +223,16 @@ public class ListItemContentLayoutManager extends BlockStackingLayoutManager { public Keep getKeepWithPrevious() { return Keep.KEEP_AUTO; } + + @SuppressWarnings("unchecked") + @Override + public List<ListElement> getNextKnuthElements(LayoutContext context, int alignment) { + List<ListElement> elements = new LinkedList<ListElement>(); + do { + elements.addAll(super.getNextKnuthElements(context, alignment)); + } while (!isFinished()); + return elements; + } + } diff --git a/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java b/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java index bc7daa24f..32aa4c674 100644 --- a/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/list/ListItemLayoutManager.java @@ -35,6 +35,8 @@ import org.apache.fop.fo.flow.ListItemLabel; import org.apache.fop.fo.properties.KeepProperty; import org.apache.fop.layoutmgr.BlockStackingLayoutManager; import org.apache.fop.layoutmgr.BreakElement; +import org.apache.fop.layoutmgr.BreakOpportunity; +import org.apache.fop.layoutmgr.BreakOpportunityHelper; import org.apache.fop.layoutmgr.ConditionalElementListener; import org.apache.fop.layoutmgr.ElementListObserver; import org.apache.fop.layoutmgr.ElementListUtils; @@ -56,13 +58,14 @@ import org.apache.fop.layoutmgr.SpaceResolver; import org.apache.fop.layoutmgr.TraitSetter; import org.apache.fop.traits.MinOptMax; import org.apache.fop.traits.SpaceVal; +import org.apache.fop.util.BreakUtil; /** * LayoutManager for a list-item FO. * The list item contains a list item label and a list item body. */ -public class ListItemLayoutManager extends BlockStackingLayoutManager - implements ConditionalElementListener { +public class ListItemLayoutManager extends BlockStackingLayoutManager implements ConditionalElementListener, + BreakOpportunity { /** logging instance */ private static Log log = LogFactory.getLog(ListItemLayoutManager.class); @@ -204,6 +207,7 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager // label childLC = makeChildLayoutContext(context); + childLC.setFlags(LayoutContext.SUPPRESS_BREAK_BEFORE); label.initialize(); labelList = label.getNextKnuthElements(childLC, alignment); @@ -217,6 +221,7 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager // body childLC = makeChildLayoutContext(context); + childLC.setFlags(LayoutContext.SUPPRESS_BREAK_BEFORE); body.initialize(); bodyList = body.getNextKnuthElements(childLC, alignment); @@ -296,16 +301,23 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager //Additional penalty height from penalties in the source lists int additionalPenaltyHeight = 0; int stepPenalty = 0; + int breakClass = EN_AUTO; KnuthElement endEl = (KnuthElement)elementLists[0].get(end[0]); if (endEl instanceof KnuthPenalty) { additionalPenaltyHeight = endEl.getWidth(); - stepPenalty = Math.max(stepPenalty, endEl.getPenalty()); + stepPenalty = endEl.getPenalty() == -KnuthElement.INFINITE ? -KnuthElement.INFINITE : Math + .max(stepPenalty, endEl.getPenalty()); + breakClass = BreakUtil.compareBreakClasses(breakClass, + ((KnuthPenalty) endEl).getBreakClass()); } endEl = (KnuthElement)elementLists[1].get(end[1]); if (endEl instanceof KnuthPenalty) { additionalPenaltyHeight = Math.max( additionalPenaltyHeight, endEl.getWidth()); - stepPenalty = Math.max(stepPenalty, endEl.getPenalty()); + stepPenalty = endEl.getPenalty() == -KnuthElement.INFINITE ? -KnuthElement.INFINITE : Math + .max(stepPenalty, endEl.getPenalty()); + breakClass = BreakUtil.compareBreakClasses(breakClass, + ((KnuthPenalty) endEl).getBreakClass()); } int boxHeight = step - addedBoxHeight - penaltyHeight; @@ -343,9 +355,9 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager int p = stepPenalty; if (p > -KnuthElement.INFINITE) { p = Math.max(p, keep.getPenalty()); + breakClass = keep.getContext(); } - returnList.add(new BreakElement(stepPosition, penaltyHeight, p, keep.getContext(), - context)); + returnList.add(new BreakElement(stepPosition, penaltyHeight, p, breakClass, context)); } } @@ -476,7 +488,7 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager addId(); - LayoutContext lc = new LayoutContext(0); + LayoutContext lc = LayoutContext.offspringOf(layoutContext); Position firstPos = null; Position lastPos = null; @@ -693,6 +705,13 @@ public class ListItemLayoutManager extends BlockStackingLayoutManager body.reset(); } + @Override + public int getBreakBefore() { + int breakBefore = BreakOpportunityHelper.getBreakBefore(this); + breakBefore = BreakUtil.compareBreakClasses(breakBefore, label.getBreakBefore()); + breakBefore = BreakUtil.compareBreakClasses(breakBefore, body.getBreakBefore()); + return breakBefore; + } } diff --git a/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java index f41f77ea4..ed46d2199 100644 --- a/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/RowGroupLayoutManager.java @@ -112,7 +112,7 @@ class RowGroupLayoutManager { spanWidth += ((TableColumn) colIter.next()).getColumnWidth().getValue( tableLM); } - LayoutContext childLC = new LayoutContext(0); + LayoutContext childLC = LayoutContext.newInstance(); childLC.setStackLimitBP(context.getStackLimitBP()); //necessary? childLC.setRefIPD(spanWidth); diff --git a/src/java/org/apache/fop/layoutmgr/table/TableAndCaptionLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableAndCaptionLayoutManager.java index fc35a8069..0582a0283 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableAndCaptionLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableAndCaptionLayoutManager.java @@ -81,7 +81,7 @@ public class TableAndCaptionLayoutManager extends BlockStackingLayoutManager { int ipd = context.getRefIPD(); BreakPoss bp; - LayoutContext childLC = new LayoutContext(0); + LayoutContext childLC = LayoutContext.newInstance(); // if line layout manager then set stack limit to ipd // line LM actually generates a LineArea which is a block childLC.setStackLimit( @@ -145,7 +145,7 @@ public class TableAndCaptionLayoutManager extends BlockStackingLayoutManager { /* TODO: Reimplement using Knuth approach LayoutManager childLM; int iStartPos = 0; - LayoutContext lc = new LayoutContext(0); + LayoutContext lc = LayoutContext.newInstance(); while (parentIter.hasNext()) { LeafPosition lfp = (LeafPosition) parentIter.next(); // Add the block areas to Area diff --git a/src/java/org/apache/fop/layoutmgr/table/TableCaptionLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableCaptionLayoutManager.java index 7ba0b5970..66f7ad9f2 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableCaptionLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableCaptionLayoutManager.java @@ -76,7 +76,7 @@ public class TableCaptionLayoutManager extends BlockStackingLayoutManager { int ipd = context.getRefIPD(); BreakPoss bp; - LayoutContext childLC = new LayoutContext(0); + LayoutContext childLC = LayoutContext.newInstance(); // if line layout manager then set stack limit to ipd // line LM actually generates a LineArea which is a block childLC.setStackLimit( @@ -141,7 +141,7 @@ public class TableCaptionLayoutManager extends BlockStackingLayoutManager { /* TODO: Reimplement using Knuth approach LayoutManager childLM; int iStartPos = 0; - LayoutContext lc = new LayoutContext(0); + LayoutContext lc = LayoutContext.newInstance(); while (parentIter.hasNext()) { LeafPosition lfp = (LeafPosition) parentIter.next(); // Add the block areas to Area diff --git a/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java index d5f259b38..2ca5a26d1 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableCellLayoutManager.java @@ -144,7 +144,7 @@ public class TableCellLayoutManager extends BlockStackingLayoutManager LayoutManager curLM; // currently active LM LayoutManager prevLM = null; // previously active LM while ((curLM = getChildLM()) != null) { - LayoutContext childLC = new LayoutContext(0); + LayoutContext childLC = LayoutContext.newInstance(); // curLM is a ? childLC.setStackLimitBP(context.getStackLimitBP().minus(stackLimit)); childLC.setRefIPD(cellIPD); diff --git a/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java index f5e7500e2..ea8774716 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableContentLayoutManager.java @@ -71,6 +71,8 @@ public class TableContentLayoutManager implements PercentBaseContext { private TableStepper stepper; + private boolean headerIsBeingRepeated; + /** * Main constructor * @param parent Parent layout manager @@ -383,6 +385,7 @@ public class TableContentLayoutManager implements PercentBaseContext { } } } + boolean treatFooterAsArtifact = layoutContext.treatAsArtifact(); if (lastPos instanceof TableHFPenaltyPosition) { TableHFPenaltyPosition penaltyPos = (TableHFPenaltyPosition)lastPos; LOG.debug("Break at penalty!"); @@ -393,6 +396,7 @@ public class TableContentLayoutManager implements PercentBaseContext { } if (penaltyPos.footerElements != null) { footerElements = penaltyPos.footerElements; + treatFooterAsArtifact = true; } } @@ -403,10 +407,18 @@ public class TableContentLayoutManager implements PercentBaseContext { } if (headerElements != null) { + boolean ancestorTreatAsArtifact = layoutContext.treatAsArtifact(); + if (headerIsBeingRepeated) { + layoutContext.setTreatAsArtifact(true); + } //header positions for the last part are the second-to-last element and need to //be handled first before all other TableContentPositions addHeaderFooterAreas(headerElements, tableLM.getTable().getTableHeader(), painter, false); + if (!ancestorTreatAsArtifact) { + headerIsBeingRepeated = true; + } + layoutContext.setTreatAsArtifact(ancestorTreatAsArtifact); } if (tablePositions.isEmpty()) { @@ -419,9 +431,12 @@ public class TableContentLayoutManager implements PercentBaseContext { } if (footerElements != null) { + boolean ancestorTreatAsArtifact = layoutContext.treatAsArtifact(); + layoutContext.setTreatAsArtifact(treatFooterAsArtifact); //Positions for footers are simply added at the end addHeaderFooterAreas(footerElements, tableLM.getTable().getTableFooter(), painter, true); + layoutContext.setTreatAsArtifact(ancestorTreatAsArtifact); } this.usedBPD += painter.getAccumulatedBPD(); diff --git a/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java b/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java index 7e343697a..5a4152c69 100644 --- a/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java +++ b/src/java/org/apache/fop/layoutmgr/table/TableLayoutManager.java @@ -242,7 +242,7 @@ public class TableLayoutManager extends BlockStackingLayoutManager // Elements for the table-header/footer/body List contentKnuthElements; contentLM = new TableContentLayoutManager(this); - LayoutContext childLC = new LayoutContext(0); + LayoutContext childLC = LayoutContext.newInstance(); /* childLC.setStackLimit( MinOptMax.subtract(context.getStackLimit(), @@ -355,7 +355,7 @@ public class TableLayoutManager extends BlockStackingLayoutManager // BPD of the table, i.e., height of its content; table's borders and paddings not counted int tableHeight = 0; //Body childLM; - LayoutContext lc = new LayoutContext(0); + LayoutContext lc = LayoutContext.offspringOf(layoutContext); lc.setRefIPD(getContentAreaIPD()); diff --git a/src/java/org/apache/fop/pdf/PDFArray.java b/src/java/org/apache/fop/pdf/PDFArray.java index 131830328..78f5d080b 100644 --- a/src/java/org/apache/fop/pdf/PDFArray.java +++ b/src/java/org/apache/fop/pdf/PDFArray.java @@ -100,6 +100,15 @@ public class PDFArray extends PDFObject { } /** + * Creates an array object made of the given elements. + * + * @param elements the array content + */ + public PDFArray(List<?> elements) { + this(null, elements); + } + + /** * Create the array object * @param parent the array's parent if any * @param values the actual array wrapped by this object diff --git a/src/java/org/apache/fop/pdf/PDFDocument.java b/src/java/org/apache/fop/pdf/PDFDocument.java index dad404d11..e46a22c4a 100644 --- a/src/java/org/apache/fop/pdf/PDFDocument.java +++ b/src/java/org/apache/fop/pdf/PDFDocument.java @@ -37,6 +37,7 @@ import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.apache.fop.pdf.StandardStructureAttributes.Table.Scope; import org.apache.fop.pdf.xref.CrossReferenceStream; import org.apache.fop.pdf.xref.CrossReferenceTable; import org.apache.fop.pdf.xref.TrailerDictionary; @@ -362,7 +363,7 @@ public class PDFDocument { * hierarchy * @return a dictionary of type StructElem */ - public PDFStructElem makeStructureElement(PDFName structureType, PDFObject parent) { + public PDFStructElem makeStructureElement(StructureType structureType, PDFObject parent) { PDFStructElem structElem = new PDFStructElem(parent, structureType); assignObjectNumber(structElem); structureTreeElements.add(structElem); @@ -370,6 +371,23 @@ public class PDFDocument { } /** + * Creates and returns a structure element. + * + * @param structureType the structure type of the new element (value for the + * S entry) + * @param parent the parent of the new structure element in the structure + * hierarchy + * @param scope the scope of the given table header element + * @return a dictionary of type StructElem + */ + public PDFStructElem makeStructureElement(StructureType structureType, PDFObject parent, + Scope scope) { + PDFStructElem structElem = makeStructureElement(structureType, parent); + versionController.addTableHeaderScopeAttribute(structElem, scope); + return structElem; + } + + /** * Get the {@link PDFInfo} object for this document. * * @return the {@link PDFInfo} object diff --git a/src/java/org/apache/fop/pdf/PDFProfile.java b/src/java/org/apache/fop/pdf/PDFProfile.java index 580a9a791..98005e469 100644 --- a/src/java/org/apache/fop/pdf/PDFProfile.java +++ b/src/java/org/apache/fop/pdf/PDFProfile.java @@ -202,7 +202,8 @@ public class PDFProfile { PDFDictionary markInfo = getDocument().getRoot().getMarkInfo(); if (markInfo == null) { throw new PDFConformanceException(format( - "{0} requires the MarkInfo dictionary to be present", getPDFAMode())); + "{0} requires that the accessibility option in the configuration file be enabled", + getPDFAMode())); } if (!Boolean.TRUE.equals(markInfo.get("Marked"))) { throw new PDFConformanceException(format(err, diff --git a/src/java/org/apache/fop/pdf/PDFStructElem.java b/src/java/org/apache/fop/pdf/PDFStructElem.java index a77111170..28cebb3ee 100644 --- a/src/java/org/apache/fop/pdf/PDFStructElem.java +++ b/src/java/org/apache/fop/pdf/PDFStructElem.java @@ -26,6 +26,7 @@ import java.util.List; import java.util.Locale; import org.apache.fop.accessibility.StructureTreeElement; +import org.apache.fop.pdf.StandardStructureAttributes.Table; import org.apache.fop.util.LanguageTags; /** @@ -33,6 +34,8 @@ import org.apache.fop.util.LanguageTags; */ public class PDFStructElem extends PDFDictionary implements StructureTreeElement, CompressedObject { + private StructureType structureType; + private PDFStructElem parentElement; /** @@ -40,18 +43,25 @@ public class PDFStructElem extends PDFDictionary implements StructureTreeElement */ protected List<PDFObject> kids; + private List<PDFDictionary> attributes; + /** * Creates a new structure element. * * @param parent parent of this element * @param structureType the structure type of this element */ - PDFStructElem(PDFObject parent, PDFName structureType) { + PDFStructElem(PDFObject parent, StructureType structureType) { + this(parent); + this.structureType = structureType; + put("S", structureType.getName()); + setParent(parent); + } + + private PDFStructElem(PDFObject parent) { if (parent instanceof PDFStructElem) { parentElement = (PDFStructElem) parent; } - put("S", structureType); - setParent(parent); } /** @@ -72,9 +82,7 @@ public class PDFStructElem extends PDFDictionary implements StructureTreeElement } /** - * Add a kid to this structure element. This element will then add itself to - * its parent structure element if it has not already, and so will the - * parent, and so on. + * Adds a kid to this structure element. * * @param kid element to be added */ @@ -111,8 +119,8 @@ public class PDFStructElem extends PDFDictionary implements StructureTreeElement * * @return the value of the S entry */ - public PDFName getStructureType() { - return (PDFName) get("S"); + public StructureType getStructureType() { + return structureType; } /** @@ -145,9 +153,21 @@ public class PDFStructElem extends PDFDictionary implements StructureTreeElement @Override protected void writeDictionary(OutputStream out, StringBuilder textBuffer) throws IOException { attachKids(); + attachAttributes(); super.writeDictionary(out, textBuffer); } + private void attachAttributes() { + if (attributes != null) { + if (attributes.size() == 1) { + put("A", attributes.get(0)); + } else { + PDFArray array = new PDFArray(attributes); + put("A", array); + } + } + } + /** * Attaches all valid kids to the kids array. * @@ -177,6 +197,24 @@ public class PDFStructElem extends PDFDictionary implements StructureTreeElement return kidsAttached; } + public void setTableAttributeColSpan(int colSpan) { + setTableAttributeRowColumnSpan("ColSpan", colSpan); + } + + public void setTableAttributeRowSpan(int rowSpan) { + setTableAttributeRowColumnSpan("RowSpan", rowSpan); + } + + private void setTableAttributeRowColumnSpan(String typeSpan, int span) { + PDFDictionary attribute = new PDFDictionary(); + attribute.put("O", Table.NAME); + attribute.put(typeSpan, span); + if (attributes == null) { + attributes = new ArrayList<PDFDictionary>(2); + } + attributes.add(attribute); + } + /** * Class representing a placeholder for a PDF Structure Element. */ @@ -196,13 +234,8 @@ public class PDFStructElem extends PDFDictionary implements StructureTreeElement } } - /** - * Constructor - * @param parent - - * @param name - - */ - public Placeholder(PDFObject parent, String name) { - super(parent, new PDFName(name)); + public Placeholder(PDFObject parent) { + super(parent); } } diff --git a/src/java/org/apache/fop/pdf/StandardStructureAttributes.java b/src/java/org/apache/fop/pdf/StandardStructureAttributes.java new file mode 100644 index 000000000..0a93d46bb --- /dev/null +++ b/src/java/org/apache/fop/pdf/StandardStructureAttributes.java @@ -0,0 +1,69 @@ +/* + * 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; + +/** + * Standard attributes, as defined in section 10.7.5 of the PDF Reference, Fourth edition (PDF 1.5). + */ +public final class StandardStructureAttributes { + + public static final class Table { + + /** + * The name to use as an attribute owner. This is the value of the 'O' entry in + * the attribute's dictionary. + */ + public static final PDFName NAME = new PDFName("Table"); + + public static enum Scope { + ROW("Row"), + COLUMN("Column"), + BOTH("Both"); + + private final PDFName name; + + private Scope(String name) { + this.name = new PDFName(name); + } + + /** + * Returns the name of this attribute. + * + * @return a name suitable for use as a value in the attribute's dictionary + */ + public PDFName getName() { + return name; + } + + /** + * Sets the given scope on the given table header element. + */ + static void addScopeAttribute(PDFStructElem th, Scope scope) { + PDFDictionary scopeAttribute = new PDFDictionary(); + scopeAttribute.put("O", Table.NAME); + scopeAttribute.put("Scope", scope.getName()); + th.put("A", scopeAttribute); + } + } + } + + private StandardStructureAttributes() { } + +} diff --git a/src/java/org/apache/fop/pdf/StandardStructureTypes.java b/src/java/org/apache/fop/pdf/StandardStructureTypes.java new file mode 100644 index 000000000..dc045e180 --- /dev/null +++ b/src/java/org/apache/fop/pdf/StandardStructureTypes.java @@ -0,0 +1,132 @@ +/* + * 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.util.HashMap; +import java.util.Map; + +/** + * Standard structure types, as defined in section 10.7.4 of the PDF Reference, Fourth Edition (PDF 1.5). + */ +public final class StandardStructureTypes { + + public static final class Grouping { + + public static final StructureType DOCUMENT = new StructureTypeImpl("Document"); + public static final StructureType PART = new StructureTypeImpl("Part"); + public static final StructureType ART = new StructureTypeImpl("Art"); + public static final StructureType SECT = new StructureTypeImpl("Sect"); + public static final StructureType DIV = new StructureTypeImpl("Div"); + public static final StructureType BLOCK_QUOTE = new StructureTypeImpl("BlockQuote"); + public static final StructureType CAPTION = new StructureTypeImpl("Caption"); + public static final StructureType TOC = new StructureTypeImpl("TOC"); + public static final StructureType TOCI = new StructureTypeImpl("TOCI"); + public static final StructureType INDEX = new StructureTypeImpl("Index"); + public static final StructureType NON_STRUCT = new StructureTypeImpl("NonStruct"); + public static final StructureType PRIVATE = new StructureTypeImpl("Private"); + } + + public static final class Paragraphlike { + public static final StructureType H = new StructureTypeImpl("H"); + public static final StructureType H1 = new StructureTypeImpl("H1"); + public static final StructureType H2 = new StructureTypeImpl("H2"); + public static final StructureType H3 = new StructureTypeImpl("H3"); + public static final StructureType H4 = new StructureTypeImpl("H4"); + public static final StructureType H5 = new StructureTypeImpl("H5"); + public static final StructureType H6 = new StructureTypeImpl("H6"); + public static final StructureType P = new StructureTypeImpl("P"); + } + + public static final class List { + public static final StructureType L = new StructureTypeImpl("L"); + public static final StructureType LI = new StructureTypeImpl("LI"); + public static final StructureType LBL = new StructureTypeImpl("Lbl"); + public static final StructureType LBODY = new StructureTypeImpl("LBody"); + } + + public static final class Table { + public static final StructureType TABLE = new StructureTypeImpl("Table"); + public static final StructureType TR = new StructureTypeImpl("TR"); + public static final StructureType TH = new StructureTypeImpl("TH"); + public static final StructureType TD = new StructureTypeImpl("TD"); + public static final StructureType THEAD = new StructureTypeImpl("THead"); + public static final StructureType TBODY = new StructureTypeImpl("TBody"); + public static final StructureType TFOOT = new StructureTypeImpl("TFoot"); + } + + public static final class InlineLevelStructure { + public static final StructureType SPAN = new StructureTypeImpl("Span"); + public static final StructureType QUOTE = new StructureTypeImpl("Quote"); + public static final StructureType NOTE = new StructureTypeImpl("Note"); + public static final StructureType REFERENCE = new StructureTypeImpl("Reference"); + public static final StructureType BIB_ENTRY = new StructureTypeImpl("BibEntry"); + public static final StructureType CODE = new StructureTypeImpl("Code"); + public static final StructureType LINK = new StructureTypeImpl("Link"); + public static final StructureType ANNOT = new StructureTypeImpl("Annot"); + } + + public static final class RubyOrWarichu { + public static final StructureType RUBY = new StructureTypeImpl("Ruby"); + public static final StructureType RB = new StructureTypeImpl("RB"); + public static final StructureType RT = new StructureTypeImpl("RT"); + public static final StructureType RP = new StructureTypeImpl("RP"); + public static final StructureType WARICHU = new StructureTypeImpl("Warichu"); + public static final StructureType WT = new StructureTypeImpl("WT"); + public static final StructureType WP = new StructureTypeImpl("WP"); + } + + public static final class Illustration { + public static final StructureType FIGURE = new StructureTypeImpl("Figure"); + public static final StructureType FORMULA = new StructureTypeImpl("Formula"); + public static final StructureType FORM = new StructureTypeImpl("Form"); + } + + private static class StructureTypeImpl implements StructureType { + + private final PDFName name; + + protected StructureTypeImpl(String name) { + this.name = new PDFName(name); + StandardStructureTypes.STRUCTURE_TYPES.put(name, this); + } + + public PDFName getName() { + return name; + } + + } + + private static final Map<String, StructureType> STRUCTURE_TYPES = new HashMap<String, StructureType>(); + + private StandardStructureTypes() { } + + /** + * Returns the standard structure type of the given name. + * + * @param name the name of a structure type, case sensitive. For example, Document, + * Sect, H1, etc. + * @return the corresponding {@code StructureType} instance, or {@code null} if the given + * name does not correspond to a standard structure type + */ + public static StructureType get(String name) { + return STRUCTURE_TYPES.get(name); + } + +} diff --git a/src/java/org/apache/fop/pdf/StreamCacheFactory.java b/src/java/org/apache/fop/pdf/StreamCacheFactory.java index aa4d665da..e81edf62a 100644 --- a/src/java/org/apache/fop/pdf/StreamCacheFactory.java +++ b/src/java/org/apache/fop/pdf/StreamCacheFactory.java @@ -30,7 +30,6 @@ public final class StreamCacheFactory { /** * Returns an instance of a StreamCacheFactory with the requested features. - * @param cacheToFile True if file shall be cached using a temporary file * @return StreamCacheFactory the requested factory */ public static StreamCacheFactory getInstance() { diff --git a/src/java/org/apache/fop/pdf/StructureType.java b/src/java/org/apache/fop/pdf/StructureType.java new file mode 100644 index 000000000..7b9b4c169 --- /dev/null +++ b/src/java/org/apache/fop/pdf/StructureType.java @@ -0,0 +1,34 @@ +/* + * 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; + +/** + * A structure type, as defined in Section 10.6.2 of the PDF Reference, fourth edition (PDF 1.5). + */ +public interface StructureType { + + /** + * Returns the name of this structure type. + * + * @return the name object identifying this structure type + */ + PDFName getName(); + +} diff --git a/src/java/org/apache/fop/pdf/VersionController.java b/src/java/org/apache/fop/pdf/VersionController.java index 4a92f4994..bd5e4d20f 100644 --- a/src/java/org/apache/fop/pdf/VersionController.java +++ b/src/java/org/apache/fop/pdf/VersionController.java @@ -19,6 +19,8 @@ package org.apache.fop.pdf; +import org.apache.fop.pdf.StandardStructureAttributes.Table.Scope; + /** * An abstraction that controls the mutability of the PDF version for a document. */ @@ -47,6 +49,8 @@ public abstract class VersionController { */ public abstract void setPDFVersion(Version version); + abstract void addTableHeaderScopeAttribute(PDFStructElem th, Scope scope); + @Override public String toString() { return version.toString(); @@ -67,6 +71,13 @@ public abstract class VersionController { public void setPDFVersion(Version version) { throw new IllegalStateException("Cannot change the version of this PDF document."); } + + @Override + void addTableHeaderScopeAttribute(PDFStructElem th, Scope scope) { + if (super.version.compareTo(Version.V1_4) > 0) { + Scope.addScopeAttribute(th, scope); + } + } } /** @@ -91,6 +102,12 @@ public abstract class VersionController { doc.getRoot().setVersion(version); } } + + @Override + void addTableHeaderScopeAttribute(PDFStructElem th, Scope scope) { + setPDFVersion(Version.V1_5); + Scope.addScopeAttribute(th, scope); + } } /** diff --git a/src/java/org/apache/fop/render/AbstractRendererMaker.java b/src/java/org/apache/fop/render/AbstractRendererMaker.java index b4a281efa..505a60a1c 100644 --- a/src/java/org/apache/fop/render/AbstractRendererMaker.java +++ b/src/java/org/apache/fop/render/AbstractRendererMaker.java @@ -46,10 +46,10 @@ public abstract class AbstractRendererMaker { public abstract String[] getSupportedMimeTypes(); /** - * Returns a renderer config object that can be used to - * configure the renderer. + * Configures a given renderer using the appropriate configurator. + * * @param userAgent user agent - * @return a config object that can be used to configure the renderer + * @param renderer the renderer that is to be configured */ public abstract void configureRenderer(FOUserAgent userAgent, Renderer renderer) throws FOPException; diff --git a/src/java/org/apache/fop/render/PrintRendererConfigurator.java b/src/java/org/apache/fop/render/PrintRendererConfigurator.java index 8de2d1a92..96da591c1 100644 --- a/src/java/org/apache/fop/render/PrintRendererConfigurator.java +++ b/src/java/org/apache/fop/render/PrintRendererConfigurator.java @@ -36,6 +36,7 @@ import org.apache.fop.fonts.FontManager; import org.apache.fop.render.RendererConfig.RendererConfigParser; import org.apache.fop.render.intermediate.IFDocumentHandler; import org.apache.fop.render.intermediate.IFDocumentHandlerConfigurator; +import org.apache.fop.render.pdf.PDFRendererConfig.PDFRendererConfigParser; /** * Base Print renderer configurator (mostly handles font configuration) @@ -166,7 +167,9 @@ public abstract class PrintRendererConfigurator extends AbstractRendererConfigur } public static PrintRendererConfigurator createDefaultInstance(FOUserAgent userAgent) { - return new PrintRendererConfigurator(userAgent, null) { + // Since PDF is the default output is PDF, it makes sense for the default config parser + // to also be the PDF flavour + return new PrintRendererConfigurator(userAgent, new PDFRendererConfigParser()) { @Override protected List<FontCollection> getDefaultFontCollection() { throw new UnsupportedOperationException(); diff --git a/src/java/org/apache/fop/render/afp/AFPFontConfig.java b/src/java/org/apache/fop/render/afp/AFPFontConfig.java index eca76078f..aef0b666c 100644 --- a/src/java/org/apache/fop/render/afp/AFPFontConfig.java +++ b/src/java/org/apache/fop/render/afp/AFPFontConfig.java @@ -329,8 +329,8 @@ public final class AFPFontConfig implements FontConfig { AFPResourceAccessor accessor = getAccessor(resourceResolver); CharacterSet characterSet = CharacterSetBuilder.getDoubleByteInstance().buildDBCS( characterset, super.codePage, super.encoding, charsetType, accessor, eventProducer); - return getFontInfo(new DoubleByteFont(super.codePage, super.embeddable, characterSet), - this); + return getFontInfo(new DoubleByteFont(super.codePage, super.embeddable, characterSet, + eventProducer), this); } } @@ -365,7 +365,8 @@ public final class AFPFontConfig implements FontConfig { characterSet = CharacterSetBuilder.getSingleByteInstance().buildSBCS( characterset, super.codePage, super.encoding, accessor, eventProducer); } - return getFontInfo(new OutlineFont(super.name, super.embeddable, characterSet), this); + return getFontInfo(new OutlineFont(super.name, super.embeddable, characterSet, + eventProducer), this); } } diff --git a/src/java/org/apache/fop/render/intermediate/IFDocumentHandlerConfigurator.java b/src/java/org/apache/fop/render/intermediate/IFDocumentHandlerConfigurator.java index c00ebe29e..a55f42e9d 100644 --- a/src/java/org/apache/fop/render/intermediate/IFDocumentHandlerConfigurator.java +++ b/src/java/org/apache/fop/render/intermediate/IFDocumentHandlerConfigurator.java @@ -29,6 +29,7 @@ public interface IFDocumentHandlerConfigurator { /** * Configures a intermediate format document handler. + * * @param documentHandler the document handler instance * @throws FOPException if an error occurs while configuring the object */ @@ -36,10 +37,10 @@ public interface IFDocumentHandlerConfigurator { /** * Sets up the {@link FontInfo} object for the IFDocumentHandler. - * @param documentHandler the document handler instance + * + * @param mimeType the MIME type of the document handler * @param fontInfo the font info object to set up * @throws FOPException if an error occurs while configuring the object */ void setupFontInfo(String mimeType, FontInfo fontInfo) throws FOPException; - } diff --git a/src/java/org/apache/fop/render/pcl/PCLGraphics2D.java b/src/java/org/apache/fop/render/pcl/PCLGraphics2D.java index 3fc988110..0fbf86c2c 100644 --- a/src/java/org/apache/fop/render/pcl/PCLGraphics2D.java +++ b/src/java/org/apache/fop/render/pcl/PCLGraphics2D.java @@ -25,7 +25,6 @@ import java.awt.Dimension; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.GraphicsConfiguration; -import java.awt.GraphicsEnvironment; import java.awt.Image; import java.awt.Paint; import java.awt.Shape; @@ -44,6 +43,7 @@ import java.text.AttributedCharacterIterator; import org.apache.xmlgraphics.java2d.AbstractGraphics2D; import org.apache.xmlgraphics.java2d.GraphicContext; +import org.apache.xmlgraphics.java2d.GraphicsConfigurationWithTransparency; import org.apache.xmlgraphics.util.UnitConv; /** @@ -127,8 +127,7 @@ public class PCLGraphics2D extends AbstractGraphics2D { /** {@inheritDoc} */ public GraphicsConfiguration getDeviceConfiguration() { - return GraphicsEnvironment.getLocalGraphicsEnvironment() - .getDefaultScreenDevice().getDefaultConfiguration(); + return new GraphicsConfigurationWithTransparency(); } /** diff --git a/src/java/org/apache/fop/render/pdf/FOToPDFRoleMap.java b/src/java/org/apache/fop/render/pdf/FOToPDFRoleMap.java index 0f752e886..68bfd8686 100644 --- a/src/java/org/apache/fop/render/pdf/FOToPDFRoleMap.java +++ b/src/java/org/apache/fop/render/pdf/FOToPDFRoleMap.java @@ -19,145 +19,66 @@ package org.apache.fop.render.pdf; -import java.util.HashMap; import java.util.Map; import org.apache.fop.events.EventBroadcaster; -import org.apache.fop.pdf.PDFName; import org.apache.fop.pdf.PDFObject; import org.apache.fop.pdf.PDFStructElem; +import org.apache.fop.pdf.StandardStructureTypes; +import org.apache.fop.pdf.StructureType; /** * This class provides the standard mappings from Formatting Objects to PDF structure types. */ final class FOToPDFRoleMap { - /** - * Standard structure types defined by the PDF Reference, Fourth Edition (PDF 1.5). - */ - private static final Map<String, PDFName> STANDARD_STRUCTURE_TYPES - = new HashMap<String, PDFName>(); - - private static final Map<String, Mapper> DEFAULT_MAPPINGS - = new java.util.HashMap<String, Mapper>(); - - private static final PDFName THEAD; - private static final PDFName NON_STRUCT; + private static final Map<String, Mapper> DEFAULT_MAPPINGS = new java.util.HashMap<String, Mapper>(); static { - // Create PDFNames for the standard structure types - // Table 10.18: Grouping elements - addStructureType("Document"); - addStructureType("Part"); - addStructureType("Art"); - addStructureType("Sect"); - addStructureType("Div"); - addStructureType("BlockQuote"); - addStructureType("Caption"); - addStructureType("TOC"); - addStructureType("TOCI"); - addStructureType("Index"); - addStructureType("NonStruct"); - addStructureType("Private"); - // Table 10.20: Paragraphlike elements - addStructureType("H"); - addStructureType("H1"); - addStructureType("H2"); - addStructureType("H3"); - addStructureType("H4"); - addStructureType("H5"); - addStructureType("H6"); - addStructureType("P"); - // Table 10.21: List elements - addStructureType("L"); - addStructureType("LI"); - addStructureType("Lbl"); - addStructureType("LBody"); - // Table 10.22: Table elements - addStructureType("Table"); - addStructureType("TR"); - addStructureType("TH"); - addStructureType("TD"); - addStructureType("THead"); - addStructureType("TBody"); - addStructureType("TFoot"); - // Table 10.23: Inline-level structure elements - addStructureType("Span"); - addStructureType("Quote"); - addStructureType("Note"); - addStructureType("Reference"); - addStructureType("BibEntry"); - addStructureType("Code"); - addStructureType("Link"); - addStructureType("Annot"); - // Table 10.24: Ruby and Warichu elements - addStructureType("Ruby"); - addStructureType("RB"); - addStructureType("RT"); - addStructureType("RP"); - addStructureType("Warichu"); - addStructureType("WT"); - addStructureType("WP"); - // Table 10.25: Illustration elements - addStructureType("Figure"); - addStructureType("Formula"); - addStructureType("Form"); - - NON_STRUCT = STANDARD_STRUCTURE_TYPES.get("NonStruct"); - assert NON_STRUCT != null; - THEAD = STANDARD_STRUCTURE_TYPES.get("THead"); - assert THEAD != null; - // Create the standard mappings // Declarations and Pagination and Layout Formatting Objects - addMapping("root", "Document"); - addMapping("page-sequence", "Part"); - addMapping("flow", "Sect"); - addMapping("static-content", "Sect"); + addMapping("root", StandardStructureTypes.Grouping.DOCUMENT); + addMapping("page-sequence", StandardStructureTypes.Grouping.PART); + addMapping("flow", StandardStructureTypes.Grouping.SECT); + addMapping("static-content", StandardStructureTypes.Grouping.SECT); // Block-level Formatting Objects - addMapping("block", "P"); - addMapping("block-container", "Div"); + addMapping("block", StandardStructureTypes.Paragraphlike.P); + addMapping("block-container", StandardStructureTypes.Grouping.DIV); // Inline-level Formatting Objects - addMapping("character", "Span"); - addMapping("external-graphic", "Figure"); - addMapping("instream-foreign-object", "Figure"); - addMapping("inline", "Span"); - addMapping("inline-container", "Div"); - addMapping("page-number", "Quote"); - addMapping("page-number-citation", "Quote"); - addMapping("page-number-citation-last", "Quote"); + addMapping("character", StandardStructureTypes.InlineLevelStructure.SPAN); + addMapping("external-graphic", StandardStructureTypes.Illustration.FIGURE); + addMapping("instream-foreign-object", StandardStructureTypes.Illustration.FIGURE); + addMapping("inline", StandardStructureTypes.InlineLevelStructure.SPAN); + addMapping("inline-container", StandardStructureTypes.Grouping.DIV); + addMapping("page-number", StandardStructureTypes.InlineLevelStructure.QUOTE); + addMapping("page-number-citation", StandardStructureTypes.InlineLevelStructure.QUOTE); + addMapping("page-number-citation-last", StandardStructureTypes.InlineLevelStructure.QUOTE); // Formatting Objects for Tables - addMapping("table-and-caption", "Div"); - addMapping("table", "Table"); - addMapping("table-caption", "Caption"); - addMapping("table-header", "THead"); - addMapping("table-footer", "TFoot"); - addMapping("table-body", "TBody"); - addMapping("table-row", "TR"); + addMapping("table-and-caption", StandardStructureTypes.Grouping.DIV); + addMapping("table", StandardStructureTypes.Table.TABLE); + addMapping("table-caption", StandardStructureTypes.Grouping.CAPTION); + addMapping("table-header", StandardStructureTypes.Table.THEAD); + addMapping("table-footer", StandardStructureTypes.Table.TFOOT); + addMapping("table-body", StandardStructureTypes.Table.TBODY); + addMapping("table-row", StandardStructureTypes.Table.TR); addMapping("table-cell", new TableCellMapper()); // Formatting Objects for Lists - addMapping("list-block", "L"); - addMapping("list-item", "LI"); - addMapping("list-item-body", "LBody"); - addMapping("list-item-label", "Lbl"); + addMapping("list-block", StandardStructureTypes.List.L); + addMapping("list-item", StandardStructureTypes.List.LI); + addMapping("list-item-body", StandardStructureTypes.List.LBODY); + addMapping("list-item-label", StandardStructureTypes.List.LBL); // Dynamic Effects: Link and Multi Formatting Objects - addMapping("basic-link", "Link"); + addMapping("basic-link", StandardStructureTypes.InlineLevelStructure.LINK); // Out-of-Line Formatting Objects - addMapping("float", "Div"); - addMapping("footnote", "Note"); - addMapping("footnote-body", "Sect"); - addMapping("wrapper", "Span"); - addMapping("marker", "Private"); - } - - private static void addStructureType(String structureType) { - STANDARD_STRUCTURE_TYPES.put(structureType, new PDFName(structureType)); + addMapping("float", StandardStructureTypes.Grouping.DIV); + addMapping("footnote", StandardStructureTypes.InlineLevelStructure.NOTE); + addMapping("footnote-body", StandardStructureTypes.Grouping.SECT); + addMapping("wrapper", StandardStructureTypes.InlineLevelStructure.SPAN); + addMapping("marker", StandardStructureTypes.Grouping.PRIVATE); } - private static void addMapping(String fo, String structureType) { - PDFName type = STANDARD_STRUCTURE_TYPES.get(structureType); - assert type != null; - addMapping(fo, new SimpleMapper(type)); + private static void addMapping(String fo, StructureType structureType) { + addMapping(fo, new SimpleMapper(structureType)); } private static void addMapping(String fo, Mapper mapper) { @@ -173,13 +94,13 @@ final class FOToPDFRoleMap { * @param eventBroadcaster the event broadcaster * @return the structure type or null if no match could be found */ - public static PDFName mapFormattingObject(String fo, String role, + public static StructureType mapFormattingObject(String fo, String role, PDFObject parent, EventBroadcaster eventBroadcaster) { - PDFName type = null; + StructureType type = null; if (role == null) { type = getDefaultMappingFor(fo, parent); } else { - type = STANDARD_STRUCTURE_TYPES.get(role); + type = StandardStructureTypes.get(role); if (type == null) { type = getDefaultMappingFor(fo, parent); PDFEventProducer.Provider.get(eventBroadcaster).nonStandardStructureType(fo, @@ -196,28 +117,28 @@ final class FOToPDFRoleMap { * @param parent the parent of the structure element to be mapped * @return the structure type or NonStruct if no match could be found */ - private static PDFName getDefaultMappingFor(String fo, PDFObject parent) { + private static StructureType getDefaultMappingFor(String fo, PDFObject parent) { Mapper mapper = DEFAULT_MAPPINGS.get(fo); if (mapper != null) { return mapper.getStructureType(parent); } else { - return NON_STRUCT; + return StandardStructureTypes.Grouping.NON_STRUCT; } } private interface Mapper { - PDFName getStructureType(PDFObject parent); + StructureType getStructureType(PDFObject parent); } private static class SimpleMapper implements Mapper { - private PDFName structureType; + private StructureType structureType; - public SimpleMapper(PDFName structureType) { + public SimpleMapper(StructureType structureType) { this.structureType = structureType; } - public PDFName getStructureType(PDFObject parent) { + public StructureType getStructureType(PDFObject parent) { return structureType; } @@ -225,17 +146,14 @@ final class FOToPDFRoleMap { private static class TableCellMapper implements Mapper { - public PDFName getStructureType(PDFObject parent) { + public StructureType getStructureType(PDFObject parent) { PDFStructElem grandParent = ((PDFStructElem) parent).getParentStructElem(); //TODO What to do with cells from table-footer? Currently they are mapped on TD. - PDFName type; - if (THEAD.equals(grandParent.getStructureType())) { - type = STANDARD_STRUCTURE_TYPES.get("TH"); + if (grandParent.getStructureType() == StandardStructureTypes.Table.THEAD) { + return StandardStructureTypes.Table.TH; } else { - type = STANDARD_STRUCTURE_TYPES.get("TD"); + return StandardStructureTypes.Table.TD; } - assert type != null; - return type; } } diff --git a/src/java/org/apache/fop/render/pdf/PDFLogicalStructureHandler.java b/src/java/org/apache/fop/render/pdf/PDFLogicalStructureHandler.java index 6559e8d56..ee00d2401 100644 --- a/src/java/org/apache/fop/render/pdf/PDFLogicalStructureHandler.java +++ b/src/java/org/apache/fop/render/pdf/PDFLogicalStructureHandler.java @@ -132,7 +132,7 @@ class PDFLogicalStructureHandler { ? structureTreeElement.getParentStructElem() : structureTreeElement; pageParentTreeArray.add(parent); - String type = parent.getStructureType().toString(); + String type = parent.getStructureType().getName().toString(); int mcid = pageParentTreeArray.length() - 1; return new MarkedContentInfo(type, mcid, structureTreeElement); } diff --git a/src/java/org/apache/fop/render/pdf/PDFRendererConfig.java b/src/java/org/apache/fop/render/pdf/PDFRendererConfig.java index 049345609..0de7443bf 100644 --- a/src/java/org/apache/fop/render/pdf/PDFRendererConfig.java +++ b/src/java/org/apache/fop/render/pdf/PDFRendererConfig.java @@ -185,7 +185,7 @@ public final class PDFRendererConfig implements RendererConfig { } debug.append(filterList.get(j)); } - LogUtil.handleError(LOG, debug.toString(), true); + LOG.debug(debug.toString()); } if (filterMap.get(type) != null) { diff --git a/src/java/org/apache/fop/render/pdf/PDFStructureTreeBuilder.java b/src/java/org/apache/fop/render/pdf/PDFStructureTreeBuilder.java index 3839d47bc..1377bbfce 100644 --- a/src/java/org/apache/fop/render/pdf/PDFStructureTreeBuilder.java +++ b/src/java/org/apache/fop/render/pdf/PDFStructureTreeBuilder.java @@ -29,18 +29,18 @@ import org.apache.fop.accessibility.StructureTreeEventHandler; import org.apache.fop.events.EventBroadcaster; import org.apache.fop.fo.extensions.ExtensionElementMapping; import org.apache.fop.pdf.PDFFactory; -import org.apache.fop.pdf.PDFName; import org.apache.fop.pdf.PDFObject; import org.apache.fop.pdf.PDFParentTree; import org.apache.fop.pdf.PDFStructElem; import org.apache.fop.pdf.PDFStructTreeRoot; +import org.apache.fop.pdf.StandardStructureAttributes.Table.Scope; +import org.apache.fop.pdf.StandardStructureTypes.Table; +import org.apache.fop.pdf.StructureType; class PDFStructureTreeBuilder implements StructureTreeEventHandler { private PDFFactory pdfFactory; - private PDFLogicalStructureHandler logicalStructureHandler; - private EventBroadcaster eventBroadcaster; private LinkedList<PDFStructElem> ancestors = new LinkedList<PDFStructElem>(); @@ -52,11 +52,10 @@ class PDFStructureTreeBuilder implements StructureTreeEventHandler { } void setLogicalStructureHandler(PDFLogicalStructureHandler logicalStructureHandler) { - this.logicalStructureHandler = logicalStructureHandler; - createRootStructureElement(); + createRootStructureElement(logicalStructureHandler); } - private void createRootStructureElement() { + private void createRootStructureElement(PDFLogicalStructureHandler logicalStructureHandler) { assert rootStructureElement == null; PDFParentTree parentTree = logicalStructureHandler.getParentTree(); PDFStructTreeRoot structTreeRoot = pdfFactory.getDocument().makeStructTreeRoot(parentTree); @@ -79,8 +78,13 @@ class PDFStructureTreeBuilder implements StructureTreeEventHandler { } private PDFStructElem createStructureElement(String name, PDFObject parent, String role) { - PDFName structureType = FOToPDFRoleMap.mapFormattingObject(name, role, parent, eventBroadcaster); - return pdfFactory.getDocument().makeStructureElement(structureType, parent); + StructureType structureType = FOToPDFRoleMap.mapFormattingObject(name, role, parent, + eventBroadcaster); + if (structureType == Table.TH) { + return pdfFactory.getDocument().makeStructureElement(structureType, parent, Scope.COLUMN); + } else { + return pdfFactory.getDocument().makeStructureElement(structureType, parent); + } } public void endPageSequence() { @@ -90,11 +94,23 @@ class PDFStructureTreeBuilder implements StructureTreeEventHandler { PDFStructElem parent = ancestors.getFirst(); String role = attributes.getValue("role"); PDFStructElem structElem = createStructureElement(name, parent, role); + setSpanAttributes(structElem, attributes); parent.addKid(structElem); ancestors.addFirst(structElem); return structElem; } + private void setSpanAttributes(PDFStructElem structElem, Attributes attributes) { + String columnSpan = attributes.getValue("number-columns-spanned"); + if (columnSpan != null) { + structElem.setTableAttributeColSpan(Integer.parseInt(columnSpan)); + } + String rowSpan = attributes.getValue("number-rows-spanned"); + if (rowSpan != null) { + structElem.setTableAttributeRowSpan(Integer.parseInt(rowSpan)); + } + } + public void endNode(String name) { removeFirstAncestor(); } @@ -123,7 +139,7 @@ class PDFStructureTreeBuilder implements StructureTreeEventHandler { String role = attributes.getValue("role"); PDFStructElem structElem; if ("#PCDATA".equals(name)) { - structElem = new PDFStructElem.Placeholder(parent, name); + structElem = new PDFStructElem.Placeholder(parent); } else { structElem = createStructureElement(name, parent, role); } diff --git a/src/java/org/apache/fop/render/ps/PSRendererOption.java b/src/java/org/apache/fop/render/ps/PSRendererOption.java index 4c3396921..992ca1959 100644 --- a/src/java/org/apache/fop/render/ps/PSRendererOption.java +++ b/src/java/org/apache/fop/render/ps/PSRendererOption.java @@ -29,7 +29,7 @@ import org.apache.fop.render.RendererConfigOption; public enum PSRendererOption implements RendererConfigOption { /** Indicates whether landscape pages should be rotated, default: false */ AUTO_ROTATE_LANDSCAPE("auto-rotate-landscape", false), - /** Sets the PostScript language leven, default: {@see PSGenerator#DEFAULT_LANGUAGE_LEVEL}*/ + /** Sets the PostScript language level, default: {@link PSGenerator#DEFAULT_LANGUAGE_LEVEL} */ LANGUAGE_LEVEL("language-level", PSGenerator.DEFAULT_LANGUAGE_LEVEL), /** Whether resources should be optimized in a post-processing run, default: false */ OPTIMIZE_RESOURCES("optimize-resources", false), diff --git a/src/java/org/apache/fop/svg/PDFGraphics2D.java b/src/java/org/apache/fop/svg/PDFGraphics2D.java index 87c12d869..7517babf2 100644 --- a/src/java/org/apache/fop/svg/PDFGraphics2D.java +++ b/src/java/org/apache/fop/svg/PDFGraphics2D.java @@ -68,6 +68,7 @@ import org.apache.xmlgraphics.image.loader.impl.ImageRawJPEG; import org.apache.xmlgraphics.image.loader.impl.ImageRendered; import org.apache.xmlgraphics.java2d.AbstractGraphics2D; import org.apache.xmlgraphics.java2d.GraphicContext; +import org.apache.xmlgraphics.java2d.GraphicsConfigurationWithTransparency; import org.apache.fop.fonts.Font; import org.apache.fop.fonts.FontInfo; @@ -1765,7 +1766,7 @@ public class PDFGraphics2D extends AbstractGraphics2D implements NativeImageHand */ @Override public GraphicsConfiguration getDeviceConfiguration() { - return new PDFGraphicsConfiguration(); + return new GraphicsConfigurationWithTransparency(); } /** diff --git a/src/java/org/apache/fop/util/ColorSpaceCache.java b/src/java/org/apache/fop/util/ColorSpaceCache.java index a249fe47b..acb83cdef 100644 --- a/src/java/org/apache/fop/util/ColorSpaceCache.java +++ b/src/java/org/apache/fop/util/ColorSpaceCache.java @@ -62,13 +62,11 @@ public class ColorSpaceCache { * If that fails null is returned. * * @param profileName the profile name - * @param base a base URI to resolve relative URIs - * @param iccProfileSrc ICC Profile source to return a ColorSpace for + * @param iccProfileSrc ICC Profile source to return a ColorSpace * @param renderingIntent overriding rendering intent * @return ICC ColorSpace object or null if ColorSpace could not be created */ - public ColorSpace get(String profileName, String iccProfileSrc, - RenderingIntent renderingIntent) { + public ColorSpace get(String profileName, String iccProfileSrc, RenderingIntent renderingIntent) { String key = profileName + ":" + iccProfileSrc; // TODO: This stuff needs some TLC, fix it!! ColorSpace colorSpace = null; |