From a11874283eb80e4ce5759196bb1a751e3c93e5ac Mon Sep 17 00:00:00 2001
From: Jeremias Maerki
Date: Mon, 27 Jul 2009 16:33:01 +0000
Subject: [PATCH] Added support for AFP font embedding. Note: this changes the
default behaviour. Like with PDF and PS, all fonts are embedded by default
unless matched in the "referenced-fonts" section in the configuration. Added
support for embedding external AFP form maps (form defs) using the
afp:include-form-map extension. Fixed a small problem with AFP-related
events. DefaultFOPResourceAccessor got a fallback to the user agent's base
URI if no category base URI is specified.
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@798207 13f79535-47bb-0310-9956-ffa450edef68
---
build.xml | 3 +-
.../content/xdocs/trunk/output.xml | 34 +++++++
.../org/apache/fop/afp/AFPEventProducer.java | 10 ++
.../org/apache/fop/afp/AFPEventProducer.xml | 1 +
.../apache/fop/afp/AFPResourceManager.java | 54 +++++++++--
.../afp/fonts/AFPBase12FontCollection.java | 30 +++---
.../org/apache/fop/afp/fonts/AFPFont.java | 12 ++-
.../afp/util/DefaultFOPResourceAccessor.java | 6 +-
.../org/apache/fop/events/EventFormatter.xml | 3 -
.../fop/render/afp/AFPDocumentHandler.java | 19 +++-
.../org/apache/fop/render/afp/AFPPainter.java | 14 +--
.../apache/fop/render/afp/AFPRenderer.java | 42 ++++++++-
.../render/afp/AFPRendererConfigurator.java | 17 +++-
.../afp/extensions/AFPElementMapping.java | 12 +++
.../afp/extensions/AFPExtensionHandler.java | 60 +++++++-----
.../afp/extensions/AFPIncludeFormMap.java | 87 +++++++++++++++++
.../extensions/AFPIncludeFormMapElement.java | 89 ++++++++++++++++++
.../afp/extensions/AFPPageSetupElement.java | 11 ++-
status.xml | 9 ++
.../standard-testcases/afp-extension_1.xml | 17 +++-
test/resources/afp/F1SAMPLE.afp | Bin 0 -> 834 bytes
21 files changed, 454 insertions(+), 76 deletions(-)
create mode 100644 src/java/org/apache/fop/render/afp/extensions/AFPIncludeFormMap.java
create mode 100644 src/java/org/apache/fop/render/afp/extensions/AFPIncludeFormMapElement.java
create mode 100644 test/resources/afp/F1SAMPLE.afp
diff --git a/build.xml b/build.xml
index e9cc16a21..06e641005 100644
--- a/build.xml
+++ b/build.xml
@@ -355,12 +355,13 @@ list of possible build targets.
+
-
+
diff --git a/src/documentation/content/xdocs/trunk/output.xml b/src/documentation/content/xdocs/trunk/output.xml
index 135d56516..bae54d8b3 100644
--- a/src/documentation/content/xdocs/trunk/output.xml
+++ b/src/documentation/content/xdocs/trunk/output.xml
@@ -651,6 +651,11 @@ out = proc.getOutputStream();]]>
]]>
+
+ By default, all manually configured fonts are embedded, unless they are matched in the
+ referenced-fonts
section of the configuration file.
+ However, the default fonts shown above will not be embedded.
+
Output Resolution
@@ -836,6 +841,35 @@ out = proc.getOutputStream();]]>
available on the target platform.
+
Foreign Attributes
diff --git a/src/java/org/apache/fop/afp/AFPEventProducer.java b/src/java/org/apache/fop/afp/AFPEventProducer.java
index 49792183f..b56250fc2 100644
--- a/src/java/org/apache/fop/afp/AFPEventProducer.java
+++ b/src/java/org/apache/fop/afp/AFPEventProducer.java
@@ -80,4 +80,14 @@ public interface AFPEventProducer extends EventProducer {
* @event.severity ERROR
*/
void characterSetEncodingError(Object source, String charSetName, String encoding);
+
+ /**
+ * Triggered when an external resource fails to be embedded.
+ *
+ * @param source the event source
+ * @param resourceName the name of the resource where the error occurred
+ * @param e the original exception
+ * @event.severity ERROR
+ */
+ void resourceEmbeddingError(Object source, String resourceName, Exception e);
}
diff --git a/src/java/org/apache/fop/afp/AFPEventProducer.xml b/src/java/org/apache/fop/afp/AFPEventProducer.xml
index 8e6bb5429..364cd92ff 100644
--- a/src/java/org/apache/fop/afp/AFPEventProducer.xml
+++ b/src/java/org/apache/fop/afp/AFPEventProducer.xml
@@ -3,4 +3,5 @@
No AFP fonts configured. Using default setup.
No AFP default "any", {style}, {weight} font configured.
An error occurred when attempting to encode character set {charSetName} with encoding scheme {encoding}.
+ An error occurs while embedding the resource named "{resourceName}".[ Reason: {e}]
diff --git a/src/java/org/apache/fop/afp/AFPResourceManager.java b/src/java/org/apache/fop/afp/AFPResourceManager.java
index 09ebde296..b7e1abc01 100644
--- a/src/java/org/apache/fop/afp/AFPResourceManager.java
+++ b/src/java/org/apache/fop/afp/AFPResourceManager.java
@@ -28,6 +28,8 @@ import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.apache.fop.afp.fonts.AFPFont;
+import org.apache.fop.afp.fonts.CharacterSet;
import org.apache.fop.afp.modca.AbstractNamedAFPObject;
import org.apache.fop.afp.modca.AbstractPageObject;
import org.apache.fop.afp.modca.IncludeObject;
@@ -169,7 +171,7 @@ public class AFPResourceManager {
useInclude &= resourceGroup != null;
if (useInclude) {
boolean usePageSegment = dataObjectInfo.isCreatePageSegment();
-
+
// if it is to reside within a resource group at print-file or external level
if (resourceLevel.isPrintFile() || resourceLevel.isExternal()) {
if (usePageSegment) {
@@ -179,14 +181,14 @@ public class AFPResourceManager {
seg.addObject(namedObj);
namedObj = seg;
}
-
+
// wrap newly created data object in a resource object
namedObj = dataObjectFactory.createResource(namedObj, resourceInfo, objectType);
}
-
+
// add data object into its resource group destination
resourceGroup.addObject(namedObj);
-
+
// create the include object
objectName = namedObj.getName();
if (usePageSegment) {
@@ -217,10 +219,32 @@ public class AFPResourceManager {
private void includeObject(AFPDataObjectInfo dataObjectInfo,
String objectName) {
- IncludeObject includeObject
- = dataObjectFactory.createInclude(objectName, dataObjectInfo);
- dataStream.getCurrentPage().addObject(includeObject);
+ IncludeObject includeObject
+ = dataObjectFactory.createInclude(objectName, dataObjectInfo);
+ dataStream.getCurrentPage().addObject(includeObject);
+ }
+
+ /**
+ * Handles font embedding. If a font is embeddable and has not already been embedded it will be.
+ * @param afpFont the AFP font to be checked for embedding
+ * @param charSet the associated character set
+ * @throws IOException if there's a problem while embedding the external resources
+ */
+ public void embedFont(AFPFont afpFont, CharacterSet charSet)
+ throws IOException {
+ if (afpFont.isEmbeddable()) {
+ //Embed fonts (char sets and code pages)
+ if (charSet.getResourceAccessor() != null) {
+ ResourceAccessor accessor = charSet.getResourceAccessor();
+ createIncludedResource(
+ charSet.getName(), accessor,
+ ResourceObject.TYPE_FONT_CHARACTER_SET);
+ createIncludedResource(
+ charSet.getCodePage(), accessor,
+ ResourceObject.TYPE_CODE_PAGE);
+ }
}
+ }
private void includePageSegment(AFPDataObjectInfo dataObjectInfo,
String pageSegmentName) {
@@ -240,7 +264,6 @@ public class AFPResourceManager {
*/
public void createIncludedResource(String resourceName, ResourceAccessor accessor,
byte resourceObjectType) throws IOException {
- AFPResourceLevel resourceLevel = new AFPResourceLevel(AFPResourceLevel.PRINT_FILE);
URI uri;
try {
uri = new URI(resourceName.trim());
@@ -249,6 +272,21 @@ public class AFPResourceManager {
+ " (" + e.getMessage() + ")");
}
+ createIncludedResource(resourceName, uri, accessor, resourceObjectType);
+ }
+
+ /**
+ * Creates an included resource object by loading the contained object from a file.
+ * @param resourceName the name of the resource
+ * @param uri the URI for the resource
+ * @param accessor resource accessor to access the resource with
+ * @param resourceObjectType the resource object type ({@link ResourceObject}.*)
+ * @throws IOException if an I/O error occurs while loading the resource
+ */
+ public void createIncludedResource(String resourceName, URI uri, ResourceAccessor accessor,
+ byte resourceObjectType) throws IOException {
+ AFPResourceLevel resourceLevel = new AFPResourceLevel(AFPResourceLevel.PRINT_FILE);
+
AFPResourceInfo resourceInfo = new AFPResourceInfo();
resourceInfo.setLevel(resourceLevel);
resourceInfo.setName(resourceName);
diff --git a/src/java/org/apache/fop/afp/fonts/AFPBase12FontCollection.java b/src/java/org/apache/fop/afp/fonts/AFPBase12FontCollection.java
index fd9b05304..417250df1 100644
--- a/src/java/org/apache/fop/afp/fonts/AFPBase12FontCollection.java
+++ b/src/java/org/apache/fop/afp/fonts/AFPBase12FontCollection.java
@@ -80,22 +80,22 @@ public class AFPBase12FontCollection implements FontCollection {
/** standard font family reference names for Helvetica font */
final String[] helveticaNames = {"Helvetica", "Arial", "sans-serif"};
- font = new RasterFont("Helvetica");
+ font = createReferencedRasterFont("Helvetica");
addCharacterSet(font, "C0H200", new Helvetica());
num = addFontProperties(fontInfo, font, helveticaNames,
Font.STYLE_NORMAL, Font.WEIGHT_NORMAL, num);
- font = new RasterFont("Helvetica Italic");
+ font = createReferencedRasterFont("Helvetica Italic");
addCharacterSet(font, "C0H300", new HelveticaOblique());
num = addFontProperties(fontInfo, font, helveticaNames,
Font.STYLE_ITALIC, Font.WEIGHT_NORMAL, num);
- font = new RasterFont("Helvetica (Semi) Bold");
+ font = createReferencedRasterFont("Helvetica (Semi) Bold");
addCharacterSet(font, "C0H400", new HelveticaBold());
num = addFontProperties(fontInfo, font, helveticaNames,
Font.STYLE_NORMAL, Font.WEIGHT_BOLD, num);
- font = new RasterFont("Helvetica Italic (Semi) Bold");
+ font = createReferencedRasterFont("Helvetica Italic (Semi) Bold");
addCharacterSet(font, "C0H500", new HelveticaOblique());
num = addFontProperties(fontInfo, font, helveticaNames,
Font.STYLE_ITALIC, Font.WEIGHT_BOLD, num);
@@ -107,22 +107,22 @@ public class AFPBase12FontCollection implements FontCollection {
final String[] timesNames = {"Times", "TimesRoman", "Times Roman", "Times-Roman",
"Times New Roman", "TimesNewRoman", "serif", "any"};
- font = new RasterFont("Times Roman");
+ font = createReferencedRasterFont("Times Roman");
addCharacterSet(font, "CON200", new TimesRoman());
num = addFontProperties(fontInfo, font, timesNames,
Font.STYLE_NORMAL, Font.WEIGHT_NORMAL, num);
- font = new RasterFont("Times Roman Italic");
+ font = createReferencedRasterFont("Times Roman Italic");
addCharacterSet(font, "CON300", new TimesItalic());
num = addFontProperties(fontInfo, font, timesNames,
Font.STYLE_ITALIC, Font.WEIGHT_NORMAL, num);
- font = new RasterFont("Times Roman Bold");
+ font = createReferencedRasterFont("Times Roman Bold");
addCharacterSet(font, "CON400", new TimesBold());
num = addFontProperties(fontInfo, font, timesNames,
Font.STYLE_NORMAL, Font.WEIGHT_BOLD, num);
- font = new RasterFont("Times Roman Italic Bold");
+ font = createReferencedRasterFont("Times Roman Italic Bold");
addCharacterSet(font, "CON500", new TimesBoldItalic());
num = addFontProperties(fontInfo, font, timesNames,
Font.STYLE_ITALIC, Font.WEIGHT_BOLD, num);
@@ -131,22 +131,22 @@ public class AFPBase12FontCollection implements FontCollection {
/** standard font family reference names for Courier font */
final String[] courierNames = {"Courier", "monospace"};
- font = new RasterFont("Courier");
+ font = createReferencedRasterFont("Courier");
addCharacterSet(font, "C04200", new Courier());
num = addFontProperties(fontInfo, font, courierNames,
Font.STYLE_NORMAL, Font.WEIGHT_NORMAL, num);
- font = new RasterFont("Courier Italic");
+ font = createReferencedRasterFont("Courier Italic");
addCharacterSet(font, "C04300", new CourierOblique());
num = addFontProperties(fontInfo, font, courierNames,
Font.STYLE_ITALIC, Font.WEIGHT_NORMAL, num);
- font = new RasterFont("Courier Bold");
+ font = createReferencedRasterFont("Courier Bold");
addCharacterSet(font, "C04400", new CourierBold());
num = addFontProperties(fontInfo, font, courierNames,
Font.STYLE_NORMAL, Font.WEIGHT_BOLD, num);
- font = new RasterFont("Courier Italic Bold");
+ font = createReferencedRasterFont("Courier Italic Bold");
addCharacterSet(font, "C04500", new CourierBoldOblique());
num = addFontProperties(fontInfo, font, courierNames,
Font.STYLE_ITALIC, Font.WEIGHT_BOLD, num);
@@ -154,4 +154,10 @@ public class AFPBase12FontCollection implements FontCollection {
return num;
}
+ private RasterFont createReferencedRasterFont(String fontFamily) {
+ RasterFont font = new RasterFont(fontFamily);
+ font.setEmbeddable(false); //Font is assumed to be available on the target platform
+ return font;
+ }
+
}
diff --git a/src/java/org/apache/fop/afp/fonts/AFPFont.java b/src/java/org/apache/fop/afp/fonts/AFPFont.java
index f56611087..a1c257d3e 100644
--- a/src/java/org/apache/fop/afp/fonts/AFPFont.java
+++ b/src/java/org/apache/fop/afp/fonts/AFPFont.java
@@ -36,6 +36,8 @@ public abstract class AFPFont extends Typeface {
/** The font name */
protected String name;
+ private boolean embeddable = true;
+
/**
* Constructor for the base font requires the name.
* @param name the name of the font
@@ -97,12 +99,20 @@ public abstract class AFPFont extends Typeface {
*/
public abstract CharacterSet getCharacterSet(int size);
+ /**
+ * Controls whether this font is embeddable or not.
+ * @param value true to enable embedding, false otherwise.
+ */
+ public void setEmbeddable(boolean value) {
+ this.embeddable = value;
+ }
+
/**
* Indicates if this font may be embedded.
* @return True, if embedding is possible/permitted
*/
public boolean isEmbeddable() {
- return false; //TODO Complete AFP font embedding
+ return this.embeddable;
}
/** {@inheritDoc} */
diff --git a/src/java/org/apache/fop/afp/util/DefaultFOPResourceAccessor.java b/src/java/org/apache/fop/afp/util/DefaultFOPResourceAccessor.java
index 97646542b..053db01af 100644
--- a/src/java/org/apache/fop/afp/util/DefaultFOPResourceAccessor.java
+++ b/src/java/org/apache/fop/afp/util/DefaultFOPResourceAccessor.java
@@ -63,8 +63,10 @@ public class DefaultFOPResourceAccessor extends SimpleResourceAccessor {
URI resolved = resolveAgainstBase(uri);
//Step 2: resolve against the user agent --> stream
- Source src;
- src = userAgent.resolveURI(resolved.toASCIIString(), this.categoryBaseURI);
+ String base = (this.categoryBaseURI != null
+ ? this.categoryBaseURI
+ : this.userAgent.getBaseURL());
+ Source src = userAgent.resolveURI(resolved.toASCIIString(), base);
if (src == null) {
throw new FileNotFoundException("Resource not found: " + uri.toASCIIString());
diff --git a/src/java/org/apache/fop/events/EventFormatter.xml b/src/java/org/apache/fop/events/EventFormatter.xml
index 07ac2111e..147744a0d 100644
--- a/src/java/org/apache/fop/events/EventFormatter.xml
+++ b/src/java/org/apache/fop/events/EventFormatter.xml
@@ -105,7 +105,4 @@ Any reference to it will be considered a reference to the first occurrence in th
Font "{requested}" not found. Substituting with "{effective}".
Unable to load font file: {fontURL}.[ Reason: {e}]
Glyph "{ch}" (0x{ch,hex}[, {ch,glyph-name}]) not available in font "{fontName}".
-
-
-
diff --git a/src/java/org/apache/fop/render/afp/AFPDocumentHandler.java b/src/java/org/apache/fop/render/afp/AFPDocumentHandler.java
index febfb9672..d8a2d04e9 100644
--- a/src/java/org/apache/fop/render/afp/AFPDocumentHandler.java
+++ b/src/java/org/apache/fop/render/afp/AFPDocumentHandler.java
@@ -35,12 +35,16 @@ import org.apache.fop.afp.AbstractAFPPainter;
import org.apache.fop.afp.DataStream;
import org.apache.fop.afp.fonts.AFPFontCollection;
import org.apache.fop.afp.fonts.AFPPageFonts;
+import org.apache.fop.afp.modca.ResourceObject;
+import org.apache.fop.afp.util.DefaultFOPResourceAccessor;
+import org.apache.fop.afp.util.ResourceAccessor;
import org.apache.fop.apps.MimeConstants;
import org.apache.fop.fonts.FontCollection;
import org.apache.fop.fonts.FontEventAdapter;
import org.apache.fop.fonts.FontInfo;
import org.apache.fop.fonts.FontManager;
import org.apache.fop.render.afp.extensions.AFPElementMapping;
+import org.apache.fop.render.afp.extensions.AFPIncludeFormMap;
import org.apache.fop.render.afp.extensions.AFPInvokeMediumMap;
import org.apache.fop.render.afp.extensions.AFPPageSetup;
import org.apache.fop.render.intermediate.AbstractBinaryWritingIFDocumentHandler;
@@ -275,7 +279,8 @@ public class AFPDocumentHandler extends AbstractBinaryWritingIFDocumentHandler
} else {
if (this.location != LOC_IN_PAGE_HEADER) {
throw new IFException(
- "AFP page setup extension encountered outside the page header: " + aps, null);
+ "AFP page setup extension encountered outside the page header: " + aps,
+ null);
}
if (AFPElementMapping.INCLUDE_PAGE_OVERLAY.equals(element)) {
String overlay = aps.getName();
@@ -304,6 +309,18 @@ public class AFPDocumentHandler extends AbstractBinaryWritingIFDocumentHandler
if (mediumMap != null) {
dataStream.createInvokeMediumMap(mediumMap);
}
+ } else if (extension instanceof AFPIncludeFormMap) {
+ AFPIncludeFormMap formMap = (AFPIncludeFormMap)extension;
+ ResourceAccessor accessor = new DefaultFOPResourceAccessor(
+ getUserAgent(), null, null);
+ try {
+ getResourceManager().createIncludedResource(formMap.getName(),
+ formMap.getSrc(), accessor,
+ ResourceObject.TYPE_FORMDEF);
+ } catch (IOException ioe) {
+ throw new IFException(
+ "I/O error while embedding form map resource: " + formMap.getName(), ioe);
+ }
}
}
diff --git a/src/java/org/apache/fop/render/afp/AFPPainter.java b/src/java/org/apache/fop/render/afp/AFPPainter.java
index e591812f9..7fcd0b3d1 100644
--- a/src/java/org/apache/fop/render/afp/AFPPainter.java
+++ b/src/java/org/apache/fop/render/afp/AFPPainter.java
@@ -46,10 +46,8 @@ import org.apache.fop.afp.fonts.AFPPageFonts;
import org.apache.fop.afp.fonts.CharacterSet;
import org.apache.fop.afp.modca.AbstractPageObject;
import org.apache.fop.afp.modca.PresentationTextObject;
-import org.apache.fop.afp.modca.ResourceObject;
import org.apache.fop.afp.ptoca.PtocaBuilder;
import org.apache.fop.afp.ptoca.PtocaProducer;
-import org.apache.fop.afp.util.ResourceAccessor;
import org.apache.fop.fonts.Font;
import org.apache.fop.fonts.FontInfo;
import org.apache.fop.fonts.FontTriplet;
@@ -345,17 +343,7 @@ public class AFPPainter extends AbstractIFPainter {
if (afpFont.isEmbeddable()) {
try {
- //Embed fonts (char sets and code pages)
- //TODO This should be moved to a place where it has less performance impact
- if (charSet.getResourceAccessor() != null) {
- ResourceAccessor accessor = charSet.getResourceAccessor();
- documentHandler.getResourceManager().createIncludedResource(
- charSet.getName(), accessor,
- ResourceObject.TYPE_FONT_CHARACTER_SET);
- documentHandler.getResourceManager().createIncludedResource(
- charSet.getCodePage(), accessor,
- ResourceObject.TYPE_CODE_PAGE);
- }
+ documentHandler.getResourceManager().embedFont(afpFont, charSet);
} catch (IOException ioe) {
throw new IFException("Error while embedding font resources", ioe);
}
diff --git a/src/java/org/apache/fop/render/afp/AFPRenderer.java b/src/java/org/apache/fop/render/afp/AFPRenderer.java
index b9eb345b7..e23cf7825 100644
--- a/src/java/org/apache/fop/render/afp/AFPRenderer.java
+++ b/src/java/org/apache/fop/render/afp/AFPRenderer.java
@@ -61,10 +61,14 @@ import org.apache.fop.afp.fonts.AFPFontCollection;
import org.apache.fop.afp.fonts.AFPPageFonts;
import org.apache.fop.afp.fonts.CharacterSet;
import org.apache.fop.afp.modca.PageObject;
+import org.apache.fop.afp.modca.ResourceObject;
+import org.apache.fop.afp.util.DefaultFOPResourceAccessor;
+import org.apache.fop.afp.util.ResourceAccessor;
import org.apache.fop.apps.FOPException;
import org.apache.fop.apps.FOUserAgent;
import org.apache.fop.apps.MimeConstants;
import org.apache.fop.area.CTM;
+import org.apache.fop.area.OffDocumentExtensionAttachment;
import org.apache.fop.area.OffDocumentItem;
import org.apache.fop.area.PageSequence;
import org.apache.fop.area.PageViewport;
@@ -83,6 +87,8 @@ import org.apache.fop.render.AbstractPathOrientedRenderer;
import org.apache.fop.render.Graphics2DAdapter;
import org.apache.fop.render.RendererContext;
import org.apache.fop.render.afp.extensions.AFPElementMapping;
+import org.apache.fop.render.afp.extensions.AFPExtensionAttachment;
+import org.apache.fop.render.afp.extensions.AFPIncludeFormMap;
import org.apache.fop.render.afp.extensions.AFPInvokeMediumMap;
import org.apache.fop.render.afp.extensions.AFPPageSetup;
@@ -279,8 +285,30 @@ public class AFPRenderer extends AbstractPathOrientedRenderer implements AFPCust
/** {@inheritDoc} */
public void processOffDocumentItem(OffDocumentItem odi) {
- // TODO
- log.debug("NYI processOffDocumentItem(" + odi + ")");
+ if (odi instanceof OffDocumentExtensionAttachment) {
+ ExtensionAttachment attachment = ((OffDocumentExtensionAttachment)odi).getAttachment();
+ if (attachment != null) {
+ if (AFPExtensionAttachment.CATEGORY.equals(attachment.getCategory())) {
+ if (attachment instanceof AFPIncludeFormMap) {
+ handleIncludeFormMap((AFPIncludeFormMap)attachment);
+ }
+ }
+ }
+ }
+ }
+
+ private void handleIncludeFormMap(AFPIncludeFormMap formMap) {
+ ResourceAccessor accessor = new DefaultFOPResourceAccessor(
+ getUserAgent(), null, null);
+ try {
+ this.resourceManager.createIncludedResource(formMap.getName(),
+ formMap.getSrc(), accessor,
+ ResourceObject.TYPE_FORMDEF);
+ } catch (IOException ioe) {
+ AFPEventProducer eventProducer
+ = AFPEventProducer.Provider.get(userAgent.getEventBroadcaster());
+ eventProducer.resourceEmbeddingError(this, formMap.getName(), ioe);
+ }
}
/** {@inheritDoc} */
@@ -566,6 +594,16 @@ public class AFPRenderer extends AbstractPathOrientedRenderer implements AFPCust
AFPFontAttributes fontAttributes = pageFonts.registerFont(internalFontName, font, fontSize);
Font fnt = getFontFromArea(text);
+ if (font.isEmbeddable()) {
+ CharacterSet charSet = font.getCharacterSet(fontSize);
+ try {
+ this.resourceManager.embedFont(font, charSet);
+ } catch (IOException ioe) {
+ AFPEventProducer eventProducer
+ = AFPEventProducer.Provider.get(userAgent.getEventBroadcaster());
+ eventProducer.resourceEmbeddingError(this, charSet.getName(), ioe);
+ }
+ }
// create text data info
AFPTextDataInfo textDataInfo = new AFPTextDataInfo();
diff --git a/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java b/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java
index 95cc239b3..007dd3861 100644
--- a/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java
+++ b/src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java
@@ -68,8 +68,12 @@ public class AFPRendererConfigurator extends PrintRendererConfigurator
}
private AFPFontInfo buildFont(Configuration fontCfg, String fontPath)
- throws ConfigurationException {
+ throws ConfigurationException {
+
+ FontManager fontManager = this.userAgent.getFactory().getFontManager();
+ FontTriplet.Matcher referencedFontsMatcher = fontManager.getReferencedFontsMatcher();
+ boolean embeddable = true;
Configuration[] triple = fontCfg.getChildren("font-triplet");
List/**/ tripletList = new java.util.ArrayList/**/();
if (triple.length == 0) {
@@ -81,6 +85,9 @@ public class AFPRendererConfigurator extends PrintRendererConfigurator
FontTriplet triplet = new FontTriplet(triple[j].getAttribute("name"),
triple[j].getAttribute("style"),
weight);
+ if (referencedFontsMatcher != null && referencedFontsMatcher.matches(triplet)) {
+ embeddable = false;
+ }
tripletList.add(triplet);
}
@@ -110,7 +117,7 @@ public class AFPRendererConfigurator extends PrintRendererConfigurator
}
ResourceAccessor accessor = new DefaultFOPResourceAccessor(
this.userAgent,
- this.userAgent.getFactory().getFontManager().getFontBaseURL(),
+ fontManager.getFontBaseURL(),
baseURI);
String type = afpFontCfg.getAttribute("type");
@@ -135,11 +142,12 @@ public class AFPRendererConfigurator extends PrintRendererConfigurator
// Create a new font object
RasterFont font = new RasterFont(name);
+ font.setEmbeddable(embeddable);
Configuration[] rasters = afpFontCfg.getChildren("afp-raster-font");
if (rasters.length == 0) {
- log.error(
- "Mandatory font configuration elements ' 0 && pageSetupExtn != null) {
- pageSetupExtn.setContent(content.toString());
- content.setLength(0); //Reset text buffer (see characters())
+ if (AFPExtensionAttachment.CATEGORY.equals(uri)) {
+ if (AFPElementMapping.INCLUDE_FORM_MAP.equals(localName)) {
+ AFPIncludeFormMap formMap = new AFPIncludeFormMap();
+ String name = lastAttributes.getValue("name");
+ formMap.setName(name);
+ String src = lastAttributes.getValue("src");
+ try {
+ formMap.setSrc(new URI(src));
+ } catch (URISyntaxException e) {
+ throw new SAXException("Invalid URI: " + src, e);
+ }
+ this.returnedObject = formMap;
+ } else {
+ AFPPageSetup pageSetupExtn = null;
+ if (AFPElementMapping.INVOKE_MEDIUM_MAP.equals(localName)) {
+ this.returnedObject = new AFPInvokeMediumMap();
+ } else {
+ pageSetupExtn = new AFPPageSetup(localName);
+ this.returnedObject = pageSetupExtn;
+ }
+ String name = lastAttributes.getValue("name");
+ if (name != null) {
+ returnedObject.setName(name);
+ }
+ String value = lastAttributes.getValue("value");
+ if (value != null && pageSetupExtn != null) {
+ pageSetupExtn.setValue(value);
+ }
+ if (content.length() > 0 && pageSetupExtn != null) {
+ pageSetupExtn.setContent(content.toString());
+ content.setLength(0); //Reset text buffer (see characters())
+ }
}
}
}
diff --git a/src/java/org/apache/fop/render/afp/extensions/AFPIncludeFormMap.java b/src/java/org/apache/fop/render/afp/extensions/AFPIncludeFormMap.java
new file mode 100644
index 000000000..06c7cbc9d
--- /dev/null
+++ b/src/java/org/apache/fop/render/afp/extensions/AFPIncludeFormMap.java
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.render.afp.extensions;
+
+import java.net.URI;
+
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.AttributesImpl;
+
+import org.apache.fop.fo.extensions.ExtensionAttachment;
+
+/**
+ * This extension allows to include an AFP form map resource. It is implemented as an extension
+ * attachment ({@link ExtensionAttachment}).
+ */
+public class AFPIncludeFormMap extends AFPExtensionAttachment {
+
+ private static final long serialVersionUID = 8548056652642588914L;
+
+ /** src attribute containing the URI to the form map resource */
+ protected static final String ATT_SRC = "src";
+
+ /**
+ * the URI identifying the form map resource.
+ */
+ protected URI src;
+
+ /**
+ * Default constructor.
+ */
+ public AFPIncludeFormMap() {
+ super(AFPElementMapping.INCLUDE_FORM_MAP);
+ }
+
+ /**
+ * Returns the URI of the form map.
+ * @return the form map URI
+ */
+ public URI getSrc() {
+ return this.src;
+ }
+
+ /**
+ * Sets the URI of the form map.
+ * @param value the form map URI
+ */
+ public void setSrc(URI value) {
+ this.src = value;
+ }
+
+ /** {@inheritDoc} */
+ public void toSAX(ContentHandler handler) throws SAXException {
+ AttributesImpl atts = new AttributesImpl();
+ if (name != null && name.length() > 0) {
+ atts.addAttribute(null, ATT_NAME, ATT_NAME, "CDATA", name);
+ }
+ if (this.src != null) {
+ atts.addAttribute(null, ATT_SRC, ATT_SRC, "CDATA", this.src.toASCIIString());
+ }
+ handler.startElement(CATEGORY, elementName, elementName, atts);
+ handler.endElement(CATEGORY, elementName, elementName);
+ }
+
+ /** {@inheritDoc} */
+ public String toString() {
+ return getClass().getName() + "(element-name=" + getElementName()
+ + " name=" + getName() + " src=" + getSrc() + ")";
+ }
+}
diff --git a/src/java/org/apache/fop/render/afp/extensions/AFPIncludeFormMapElement.java b/src/java/org/apache/fop/render/afp/extensions/AFPIncludeFormMapElement.java
new file mode 100644
index 000000000..719d8c765
--- /dev/null
+++ b/src/java/org/apache/fop/render/afp/extensions/AFPIncludeFormMapElement.java
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* $Id$ */
+
+package org.apache.fop.render.afp.extensions;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.Locator;
+
+import org.apache.fop.apps.FOPException;
+import org.apache.fop.fo.Constants;
+import org.apache.fop.fo.FONode;
+import org.apache.fop.fo.PropertyList;
+import org.apache.fop.fo.extensions.ExtensionAttachment;
+import org.apache.fop.fo.extensions.ExtensionObj;
+
+/**
+ * This class extends the {@link ExtensionObj} class. It represents the "include-form-map"
+ * extension in the FO tree.
+ */
+public class AFPIncludeFormMapElement extends AbstractAFPExtensionObject {
+
+ private static final String ATT_SRC = "src";
+
+ /**
+ * Constructs an AFP object (called by Maker).
+ *
+ * @param parent the parent formatting object
+ * @param name the name of the AFP element
+ */
+ public AFPIncludeFormMapElement(FONode parent, String name) {
+ super(parent, name);
+ }
+
+ private AFPIncludeFormMap getFormMapAttachment() {
+ return (AFPIncludeFormMap)getExtensionAttachment();
+ }
+
+ /** {@inheritDoc} */
+ protected void startOfNode() throws FOPException {
+ super.startOfNode();
+ if (parent.getNameId() != Constants.FO_DECLARATIONS) {
+ invalidChildError(getLocator(), parent.getName(), getNamespaceURI(), getName(),
+ "rule.childOfDeclarations");
+ }
+ }
+
+ /** {@inheritDoc} */
+ public void processNode(String elementName, Locator locator,
+ Attributes attlist, PropertyList propertyList)
+ throws FOPException {
+ super.processNode(elementName, locator, attlist, propertyList);
+ AFPIncludeFormMap formMap = getFormMapAttachment();
+ String attr = attlist.getValue(ATT_SRC);
+ if (attr != null && attr.length() > 0) {
+ try {
+ formMap.setSrc(new URI(attr));
+ } catch (URISyntaxException e) {
+ getFOValidationEventProducer().invalidPropertyValue(this,
+ elementName, ATT_SRC, attr, null, getLocator());
+ }
+ } else {
+ missingPropertyError(ATT_SRC);
+ }
+ }
+
+ /** {@inheritDoc} */
+ protected ExtensionAttachment instantiateExtensionAttachment() {
+ return new AFPIncludeFormMap();
+ }
+}
diff --git a/src/java/org/apache/fop/render/afp/extensions/AFPPageSetupElement.java b/src/java/org/apache/fop/render/afp/extensions/AFPPageSetupElement.java
index 0c6dfadc4..19f98f32a 100755
--- a/src/java/org/apache/fop/render/afp/extensions/AFPPageSetupElement.java
+++ b/src/java/org/apache/fop/render/afp/extensions/AFPPageSetupElement.java
@@ -36,6 +36,9 @@ import org.apache.fop.fo.extensions.ExtensionAttachment;
*/
public class AFPPageSetupElement extends AbstractAFPExtensionObject {
+ private static final String ATT_VALUE = "value";
+ private static final String ATT_SRC = "src";
+
/**
* Constructs an AFP object (called by Maker).
*
@@ -86,18 +89,18 @@ public class AFPPageSetupElement extends AbstractAFPExtensionObject {
super.processNode(elementName, locator, attlist, propertyList);
AFPPageSetup pageSetup = getPageSetupAttachment();
if (AFPElementMapping.INCLUDE_PAGE_SEGMENT.equals(elementName)) {
- String attr = attlist.getValue("src");
+ String attr = attlist.getValue(ATT_SRC);
if (attr != null && attr.length() > 0) {
pageSetup.setValue(attr);
} else {
- throw new FOPException(elementName + " must have a src attribute.");
+ missingPropertyError(ATT_SRC);
}
} else if (AFPElementMapping.TAG_LOGICAL_ELEMENT.equals(elementName)) {
- String attr = attlist.getValue("value");
+ String attr = attlist.getValue(ATT_VALUE);
if (attr != null && attr.length() > 0) {
pageSetup.setValue(attr);
} else {
- throw new FOPException(elementName + " must have a value attribute.");
+ missingPropertyError(ATT_VALUE);
}
}
}
diff --git a/status.xml b/status.xml
index a26b7bc9e..1ce3a0471 100644
--- a/status.xml
+++ b/status.xml
@@ -58,6 +58,15 @@
documents. Example: the fix of marks layering will be such a case when it's done.
-->
+
+ AFP Output: Added support for embedding external AFP form maps (form defs) using the
+ afp:include-form-map extension.
+
+
+ AFP Output: Added support for AFP font embedding. Note: this changes the default behaviour.
+ Like with PDF and PS, all fonts are embedded by default unless matched in the
+ "referenced-fonts" section in the configuration.
+
Bugfix: Error while writing TLE's attribute qualifier in the output.
diff --git a/test/layoutengine/standard-testcases/afp-extension_1.xml b/test/layoutengine/standard-testcases/afp-extension_1.xml
index 70bbef450..41659ab6d 100644
--- a/test/layoutengine/standard-testcases/afp-extension_1.xml
+++ b/test/layoutengine/standard-testcases/afp-extension_1.xml
@@ -36,8 +36,13 @@
+
+
+
+
+
-
+
Text on page .
@@ -47,6 +52,9 @@
+
+
+
@@ -57,7 +65,7 @@
-
+
@@ -65,6 +73,9 @@
+
+
+
@@ -74,7 +85,7 @@
-
+
diff --git a/test/resources/afp/F1SAMPLE.afp b/test/resources/afp/F1SAMPLE.afp
new file mode 100644
index 0000000000000000000000000000000000000000..9dfd5b910503399f6344491a33459121e14cdcac
GIT binary patch
literal 834
zcmZ|ONlwEs6b9fwsgPPIp+JFB=6RlHRyl`PU2+u8!J;%05@!IF1rjWfl}0R)dI5$7
zNJ!x&&LeiC#v8|x-}{o^5y;ENGteWVNfXEmIP&HeC?LKBDzbhF^wLVLP*aP@T_D=v
z(S|;Ol59KyMZXo?y}GU&mwEvD1&Xpx69*PTt~+4XEoJLE@`@S`(k2>F|7*G(vO)(h
zc(dN|WqpS~sy`JUj{1Alznu10pppAW|ARdLpiu^m>7a@U8t(?GnxKgUWOsrl88nsl
zSD