Browse Source

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
pull/37/head
Jeremias Maerki 15 years ago
parent
commit
eddaaaf4b4

+ 2
- 1
build.xml View File

@@ -355,12 +355,13 @@ list of possible build targets.
<fileset dir="${src.java.dir}">
<include name="**/*.java"/>
<exclude name="org/apache/fop/render/*/**/*.java"/>
<exclude name="org/apache/fop/afp/**/*.java"/>
</fileset>
</eventResourceGenerator>
<fixcrlf file="${src.java.dir}/org/apache/fop/events/EventFormatter.xml" tab="remove" tablength="2"/>
<eventResourceGenerator modelfile="${build.gensrc.dir}/org/apache/fop/afp/event-model.xml" translationfile="${src.java.dir}/org/apache/fop/afp/AFPEventProducer.xml">
<fileset dir="${src.java.dir}">
<include name="org/apache/fop/render/afp/**/*.java"/>
<include name="org/apache/fop/afp/**/*.java"/>
</fileset>
</eventResourceGenerator>
<fixcrlf file="${src.java.dir}/org/apache/fop/afp/AFPEventProducer.xml" tab="remove" tablength="2"/>

+ 34
- 0
src/documentation/content/xdocs/trunk/output.xml View File

@@ -651,6 +651,11 @@ out = proc.getOutputStream();]]></source>
<font-triplet name="monospace" style="normal" weight="bold"/>
<font-triplet name="Courier" style="normal" weight="bold"/>
</font>]]></source>
<p>
By default, all manually configured fonts are embedded, unless they are matched in the
<a href="fonts.html#embedding"><code>referenced-fonts</code> section of the configuration file</a>.
However, the default fonts shown above will not be embedded.
</p>
</section>
<section id="afp-renderer-resolution-config">
<title>Output Resolution</title>
@@ -836,6 +841,35 @@ out = proc.getOutputStream();]]></source>
available on the target platform.
</p>
</section>
<section id="afp-form-maps">
<title>Form Maps/Defs</title>
<p>
Apache FOP supports embedding an external form map resource in the
generated AFP output. This is done using the <code>afp:include-form-map</code>
extension. An example:
</p>
<source><![CDATA[
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"
xmlns:afp="http://xmlgraphics.apache.org/fop/extensions/afp">
[..]
<fo:declarations>
<afp:include-form-map name="F1SAMP1" src="file:f1samp1.fde"/>
</fo:declarations>
]]></source>
<p>
The <code>afp:include-form-map</code> is to be placed as a direct child of
<code>fo:declarations</code>. The <code>name</code> is an AFP resource name
(max. 8 characters) and the <code>src</code> attribute is the URI identifying the
external form map resource. When such a form map is embedded, you can use the
<code>afp:invoke-medium-map</code> extension (described above) to invoke any medium
map included in the form map.
</p>
<note>
Apache FOP doesn't support a way to define a form map or medium map using XML means
inside an XSL-FO document. You will have to build the form map with some third-party
tool.
</note>
</section>
</section>
<section id="afp-foreign-attributes">
<title>Foreign Attributes</title>

+ 10
- 0
src/java/org/apache/fop/afp/AFPEventProducer.java View File

@@ -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);
}

+ 1
- 0
src/java/org/apache/fop/afp/AFPEventProducer.xml View File

@@ -3,4 +3,5 @@
<message key="org.apache.fop.afp.AFPEventProducer.warnDefaultFontSetup">No AFP fonts configured. Using default setup.</message>
<message key="org.apache.fop.afp.AFPEventProducer.warnMissingDefaultFont">No AFP default "any", {style}, {weight} font configured.</message>
<message key="org.apache.fop.afp.AFPEventProducer.characterSetEncodingError">An error occurred when attempting to encode character set {charSetName} with encoding scheme {encoding}.</message>
<message key="org.apache.fop.afp.AFPEventProducer.resourceEmbeddingError">An error occurs while embedding the resource named "{resourceName}".[ Reason: {e}]</message>
</catalogue>

+ 46
- 8
src/java/org/apache/fop/afp/AFPResourceManager.java View File

@@ -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);

+ 18
- 12
src/java/org/apache/fop/afp/fonts/AFPBase12FontCollection.java View File

@@ -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;
}

}

+ 11
- 1
src/java/org/apache/fop/afp/fonts/AFPFont.java View File

@@ -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} */

+ 4
- 2
src/java/org/apache/fop/afp/util/DefaultFOPResourceAccessor.java View File

@@ -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());

+ 0
- 3
src/java/org/apache/fop/events/EventFormatter.xml View File

@@ -105,7 +105,4 @@ Any reference to it will be considered a reference to the first occurrence in th
<message key="org.apache.fop.fonts.FontEventAdapter.fontSubstituted">Font "{requested}" not found. Substituting with "{effective}".</message>
<message key="org.apache.fop.fonts.FontEventAdapter.fontLoadingErrorAtAutoDetection">Unable to load font file: {fontURL}.[ Reason: {e}]</message>
<message key="org.apache.fop.fonts.FontEventAdapter.glyphNotAvailable">Glyph "{ch}" (0x{ch,hex}[, {ch,glyph-name}]) not available in font "{fontName}".</message>
<message key="org.apache.fop.afp.AFPEventProducer.warnDefaultFontSetup"/>
<message key="org.apache.fop.afp.AFPEventProducer.warnMissingDefaultFont"/>
<message key="org.apache.fop.afp.AFPEventProducer.characterSetEncodingError"/>
</catalogue>

+ 18
- 1
src/java/org/apache/fop/render/afp/AFPDocumentHandler.java View File

@@ -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);
}
}
}


+ 1
- 13
src/java/org/apache/fop/render/afp/AFPPainter.java View File

@@ -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);
}

+ 40
- 2
src/java/org/apache/fop/render/afp/AFPRenderer.java View File

@@ -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();

+ 13
- 4
src/java/org/apache/fop/render/afp/AFPRendererConfigurator.java View File

@@ -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/*<FontTriplet>*/ tripletList = new java.util.ArrayList/*<FontTriplet>*/();
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 '<afp-raster-font...' are missing");
log.error("Mandatory font configuration elements '<afp-raster-font...'"
+ " are missing at " + afpFontCfg.getLocation());
return null;
}
for (int j = 0; j < rasters.length; j++) {
@@ -212,6 +220,7 @@ public class AFPRendererConfigurator extends PrintRendererConfigurator
}
// Create a new font object
OutlineFont font = new OutlineFont(name, characterSet);
font.setEmbeddable(embeddable);
return new AFPFontInfo(font, tripletList);
} else {
log.error("No or incorrect type attribute");

+ 12
- 0
src/java/org/apache/fop/render/afp/extensions/AFPElementMapping.java View File

@@ -42,6 +42,9 @@ public class AFPElementMapping extends ElementMapping {
/** include page segment element */
public static final String INCLUDE_PAGE_SEGMENT = "include-page-segment";

/** include form map element */
public static final String INCLUDE_FORM_MAP = "include-form-map";

/** NOP */
public static final String NO_OPERATION = "no-operation";

@@ -80,6 +83,9 @@ public class AFPElementMapping extends ElementMapping {
foObjs.put(
INCLUDE_PAGE_OVERLAY,
new AFPIncludePageOverlayMaker());
foObjs.put(
INCLUDE_FORM_MAP,
new AFPIncludeFormMapMaker());
foObjs.put(
NO_OPERATION,
new AFPNoOperationMaker());
@@ -101,6 +107,12 @@ public class AFPElementMapping extends ElementMapping {
}
}

static class AFPIncludeFormMapMaker extends ElementMapping.Maker {
public FONode make(FONode parent) {
return new AFPIncludeFormMapElement(parent, INCLUDE_FORM_MAP);
}
}

static class AFPTagLogicalElementMaker extends ElementMapping.Maker {
public FONode make(FONode parent) {
return new AFPPageSetupElement(parent, TAG_LOGICAL_ELEMENT);

+ 38
- 22
src/java/org/apache/fop/render/afp/extensions/AFPExtensionHandler.java View File

@@ -19,6 +19,9 @@

package org.apache.fop.render.afp.extensions;

import java.net.URI;
import java.net.URISyntaxException;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
@@ -48,13 +51,14 @@ public class AFPExtensionHandler extends DefaultHandler
public void startElement(String uri, String localName, String qName, Attributes attributes)
throws SAXException {
boolean handled = false;
if (AFPPageSetup.CATEGORY.equals(uri)) {
if (AFPExtensionAttachment.CATEGORY.equals(uri)) {
lastAttributes = attributes;
handled = true;
if (localName.equals(AFPElementMapping.NO_OPERATION)
|| localName.equals(AFPElementMapping.TAG_LOGICAL_ELEMENT)
|| localName.equals(AFPElementMapping.INCLUDE_PAGE_OVERLAY)
|| localName.equals(AFPElementMapping.INCLUDE_PAGE_SEGMENT)
|| localName.equals(AFPElementMapping.INCLUDE_FORM_MAP)
|| localName.equals(AFPElementMapping.INVOKE_MEDIUM_MAP)) {
//handled in endElement
} else {
@@ -62,7 +66,7 @@ public class AFPExtensionHandler extends DefaultHandler
}
}
if (!handled) {
if (AFPPageSetup.CATEGORY.equals(uri)) {
if (AFPExtensionAttachment.CATEGORY.equals(uri)) {
throw new SAXException("Unhandled element " + localName
+ " in namespace: " + uri);
} else {
@@ -74,26 +78,38 @@ public class AFPExtensionHandler extends DefaultHandler

/** {@inheritDoc} */
public void endElement(String uri, String localName, String qName) throws SAXException {
if (AFPPageSetup.CATEGORY.equals(uri)) {
AFPPageSetup pageSetupExtn = null;
if (localName.equals(AFPElementMapping.INVOKE_MEDIUM_MAP)) {
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())
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())
}
}
}
}

+ 87
- 0
src/java/org/apache/fop/render/afp/extensions/AFPIncludeFormMap.java View File

@@ -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() + ")";
}
}

+ 89
- 0
src/java/org/apache/fop/render/afp/extensions/AFPIncludeFormMapElement.java View File

@@ -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();
}
}

+ 7
- 4
src/java/org/apache/fop/render/afp/extensions/AFPPageSetupElement.java View File

@@ -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);
}
}
}

+ 9
- 0
status.xml View File

@@ -58,6 +58,15 @@
documents. Example: the fix of marks layering will be such a case when it's done.
-->
<release version="FOP Trunk" date="TBD">
<action context="Renderers" dev="JM" type="add">
AFP Output: Added support for embedding external AFP form maps (form defs) using the
afp:include-form-map extension.
</action>
<action context="Renderers" dev="JM" type="add">
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.
</action>
<action context="Renderers" dev="AD" type="fix" fixes-bug="47508" due-to="Bharat Attaluri">
Bugfix: Error while writing TLE's attribute qualifier in the output.
</action>

+ 14
- 3
test/layoutengine/standard-testcases/afp-extension_1.xml View File

@@ -36,8 +36,13 @@
<fo:region-body/>
</fo:simple-page-master>
</fo:layout-master-set>
<fo:declarations>
<afp:include-form-map name="FORMMAP1" src="file:../../resources/afp/F1SAMPLE.afp"/>
</fo:declarations>
<fo:page-sequence master-reference="normal" fox:test-ignore="this">
<afp:invoke-medium-map name="MYMAP"/>
<afp:invoke-medium-map name="NOPAR"/>
<afp:tag-logical-element name="foo" value="bar"/>
<fo:flow flow-name="xsl-region-body">
<fo:block>Text on page <fo:page-number/>.</fo:block>
@@ -47,6 +52,9 @@
</fo:root>
</fo>
<checks xmlns:afp="apache:fop:extensions:afp">
<eval expected="FORMMAP1" xpath="/areaTree/extension-attachments/afp:include-form-map/@name"/>
<eval expected="file:../../resources/afp/F1SAMPLE.afp" xpath="/areaTree/extension-attachments/afp:include-form-map/@src"/>
<eval expected="4" xpath="count(/areaTree/pageSequence/pageViewport[@nr=1]/page/extension-attachments/child::*)"/>
<eval expected="O1SAMP1 " xpath="/areaTree/pageSequence/pageViewport[@nr=1]/page/extension-attachments/child::*[1]/@name"/>
<eval expected="S1ISLOGO" xpath="/areaTree/pageSequence/pageViewport[@nr=1]/page/extension-attachments/child::*[2]/@name"/>
@@ -57,7 +65,7 @@
<eval expected="4" xpath="count(/areaTree/pageSequence/pageViewport[@nr=2]/page/extension-attachments/child::*)"/>
<eval expected="2" xpath="count(/areaTree/pageSequence/extension-attachments/child::*)"/>
<eval expected="MYMAP" xpath="/areaTree/pageSequence/extension-attachments/child::*[1]/@name"/>
<eval expected="NOPAR" xpath="/areaTree/pageSequence/extension-attachments/child::*[1]/@name"/>
<eval expected="bar" xpath="/areaTree/pageSequence/extension-attachments/afp:tag-logical-element[@name = 'foo']/@value"/>
<!-- This just tests if extension attributes make it through to the PageSequence object. -->
@@ -65,6 +73,9 @@
</checks>
<if-checks xmlns:if="http://xmlgraphics.apache.org/fop/intermediate"
xmlns:afp="apache:fop:extensions:afp">
<eval expected="FORMMAP1" xpath="/if:document/if:header/afp:include-form-map/@name"/>
<eval expected="file:../../resources/afp/F1SAMPLE.afp" xpath="/if:document/if:header/afp:include-form-map/@src"/>
<eval expected="4" xpath="count(//if:page[@name = '1']/if:page-header/child::*)"/>
<eval expected="O1SAMP1 " xpath="//if:page[@name = '1']/if:page-header/afp:include-page-overlay[1]/@name"/>
<eval expected="S1ISLOGO" xpath="//if:page[@name = '1']/if:page-header/afp:include-page-segment[1]/@name"/>
@@ -74,7 +85,7 @@
<eval expected="4" xpath="count(//if:page[@name = '2']/if:page-header/child::*)"/>
<eval expected="MYMAP" xpath="//if:page-sequence/afp:invoke-medium-map/@name"/>
<eval expected="NOPAR" xpath="//if:page-sequence/afp:invoke-medium-map/@name"/>
<eval expected="bar" xpath="//if:page-sequence/afp:tag-logical-element[@name = 'foo']/@value"/>

<!-- This just tests if extension attributes make it through to the PageSequence object. -->

BIN
test/resources/afp/F1SAMPLE.afp View File


Loading…
Cancel
Save