diff options
Diffstat (limited to 'src/java/org/apache/fop/afp')
16 files changed, 171 insertions, 304 deletions
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()); + } } } |