diff options
author | Simon Steiner <ssteiner@apache.org> | 2015-08-06 10:59:51 +0000 |
---|---|---|
committer | Simon Steiner <ssteiner@apache.org> | 2015-08-06 10:59:51 +0000 |
commit | 2e1089dd671b8d2283d245972a1bfd93e9d0daa0 (patch) | |
tree | a42ccd3102480265dad7442c165b137509e33af5 /src/java/org | |
parent | cc829b9753aafc5fca96ea4e633433cfbc2795bd (diff) | |
download | xmlgraphics-fop-2e1089dd671b8d2283d245972a1bfd93e9d0daa0.tar.gz xmlgraphics-fop-2e1089dd671b8d2283d245972a1bfd93e9d0daa0.zip |
FOP-2504: Truetype support for AFP
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@1694450 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src/java/org')
13 files changed, 350 insertions, 63 deletions
diff --git a/src/java/org/apache/fop/afp/AFPResourceManager.java b/src/java/org/apache/fop/afp/AFPResourceManager.java index fc34925d2..d4df8daab 100644 --- a/src/java/org/apache/fop/afp/AFPResourceManager.java +++ b/src/java/org/apache/fop/afp/AFPResourceManager.java @@ -36,15 +36,21 @@ 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.ActiveEnvironmentGroup; import org.apache.fop.afp.modca.IncludeObject; import org.apache.fop.afp.modca.IncludedResourceObject; +import org.apache.fop.afp.modca.ObjectContainer; import org.apache.fop.afp.modca.PageSegment; import org.apache.fop.afp.modca.Registry; import org.apache.fop.afp.modca.ResourceGroup; import org.apache.fop.afp.modca.ResourceObject; +import org.apache.fop.afp.modca.triplets.EncodingTriplet; +import org.apache.fop.afp.modca.triplets.FullyQualifiedNameTriplet; import org.apache.fop.afp.util.AFPResourceAccessor; import org.apache.fop.afp.util.AFPResourceUtil; import org.apache.fop.apps.io.InternalResourceResolver; +import org.apache.fop.fonts.FontType; +import org.apache.fop.render.afp.AFPFontConfig; /** * Manages the creation and storage of document resources @@ -330,12 +336,19 @@ public class AFPResourceManager { //Embed fonts (char sets and code pages) if (charSet.getResourceAccessor() != null) { AFPResourceAccessor accessor = charSet.getResourceAccessor(); - createIncludedResource( - charSet.getName(), accessor, - ResourceObject.TYPE_FONT_CHARACTER_SET); - createIncludedResource( - charSet.getCodePage(), accessor, - ResourceObject.TYPE_CODE_PAGE); + if (afpFont.getFontType() == FontType.TRUETYPE) { + + createIncludedResource(afpFont.getFontName(), accessor.resolveURI("."), accessor, + ResourceObject.TYPE_OBJECT_CONTAINER, true, + ((AFPFontConfig.AFPTrueTypeFont) afpFont).getTTC()); + } else { + createIncludedResource( + charSet.getName(), accessor, + ResourceObject.TYPE_FONT_CHARACTER_SET); + createIncludedResource( + charSet.getCodePage(), accessor, + ResourceObject.TYPE_CODE_PAGE); + } } } } @@ -366,7 +379,7 @@ public class AFPResourceManager { + " (" + e.getMessage() + ")"); } - createIncludedResource(resourceName, uri, accessor, resourceObjectType); + createIncludedResource(resourceName, uri, accessor, resourceObjectType, false, null); } /** @@ -378,7 +391,7 @@ public class AFPResourceManager { * @throws IOException if an I/O error occurs while loading the resource */ public void createIncludedResource(String resourceName, URI uri, AFPResourceAccessor accessor, - byte resourceObjectType) throws IOException { + byte resourceObjectType, boolean truetype, String ttc) throws IOException { AFPResourceLevel resourceLevel = new AFPResourceLevel(ResourceType.PRINT_FILE); AFPResourceInfo resourceInfo = new AFPResourceInfo(); @@ -391,15 +404,46 @@ public class AFPResourceManager { if (log.isDebugEnabled()) { log.debug("Adding included resource: " + resourceName); } - IncludedResourceObject resourceContent = new IncludedResourceObject( - resourceName, accessor, uri); - - ResourceObject resourceObject = factory.createResource(resourceName); - resourceObject.setDataObject(resourceContent); - resourceObject.setType(resourceObjectType); ResourceGroup resourceGroup = streamer.getResourceGroup(resourceLevel); - resourceGroup.addObject(resourceObject); + + if (truetype) { + ResourceObject res = factory.createResource(); + res.setType(ResourceObject.TYPE_OBJECT_CONTAINER); + + ActiveEnvironmentGroup.setupTruetypeMDR(res, false); + + ObjectContainer oc = factory.createObjectContainer(); + InputStream is; + try { + is = accessor.createInputStream(new URI(".")); + } catch (URISyntaxException e) { + throw new IOException(e); + } + + if (ttc != null) { + oc.setData(extractTTC(ttc, is)); + } else { + oc.setData(IOUtils.toByteArray(is)); + } + + ActiveEnvironmentGroup.setupTruetypeMDR(oc, true); + + res.addTriplet(new EncodingTriplet(1200)); + + res.setFullyQualifiedName(FullyQualifiedNameTriplet.TYPE_REPLACE_FIRST_GID_NAME, + FullyQualifiedNameTriplet.FORMAT_CHARSTR, resourceName, true); + + res.setDataObject(oc); + resourceGroup.addObject(res); + } else { + ResourceObject resourceObject = factory.createResource(resourceName); + IncludedResourceObject resourceContent = new IncludedResourceObject( + resourceName, accessor, uri); + resourceObject.setDataObject(resourceContent); + resourceObject.setType(resourceObjectType); + resourceGroup.addObject(resourceObject); + } //TODO what is the data object? cachedObject = new CachedObject(resourceName, null); @@ -411,6 +455,23 @@ public class AFPResourceManager { } } + private byte[] extractTTC(String ttc, InputStream is) throws IOException { +// TrueTypeCollection trueTypeCollection = new TrueTypeCollection(is); +// for (TrueTypeFont ttf : trueTypeCollection.getFonts()) { +// String name = ttf.getNaming().getFontFamily(); +// if (name.equals(ttc)) { +// ByteArrayOutputStream bos = new ByteArrayOutputStream(); +// TTFSubsetter s = new TTFSubsetter(ttf, null); +// for (int i = 0; i < 256 * 256; i++) { +// s.addCharCode(i); +// } +// s.writeToStream(bos); +// return bos.toByteArray(); +// } +// } + throw new IOException(ttc + " not supported"); + } + /** * Creates an included resource extracting the named resource from an external source. * @param resourceName the name of the resource diff --git a/src/java/org/apache/fop/afp/fonts/CharacterSet.java b/src/java/org/apache/fop/afp/fonts/CharacterSet.java index d57b14ed7..593b40592 100644 --- a/src/java/org/apache/fop/afp/fonts/CharacterSet.java +++ b/src/java/org/apache/fop/afp/fonts/CharacterSet.java @@ -108,8 +108,12 @@ public class CharacterSet { // the character set name must be 8 chars long this.name = padName(name); - // the code page name must be 8 chars long - this.codePage = padName(codePage); + if (codePage == null) { + this.codePage = null; + } else { + // the code page name must be 8 chars long + this.codePage = padName(codePage); + } this.encoding = encoding; this.encoder = charsetType.getEncoder(encoding); diff --git a/src/java/org/apache/fop/afp/fonts/CharacterSetBuilder.java b/src/java/org/apache/fop/afp/fonts/CharacterSetBuilder.java index e7b9041ba..39d2be845 100644 --- a/src/java/org/apache/fop/afp/fonts/CharacterSetBuilder.java +++ b/src/java/org/apache/fop/afp/fonts/CharacterSetBuilder.java @@ -232,6 +232,12 @@ public abstract class CharacterSetBuilder { eventProducer); } + public CharacterSet build(String characterSetName, String codePageName, String encoding, + Typeface typeface, AFPResourceAccessor accessor, AFPEventProducer eventProducer) + throws IOException { + return new FopCharacterSet(codePageName, encoding, characterSetName, typeface, accessor, eventProducer); + } + private CharacterSet processFont(String characterSetName, String codePageName, String encoding, CharacterSetType charsetType, AFPResourceAccessor accessor, AFPEventProducer eventProducer) throws IOException { diff --git a/src/java/org/apache/fop/afp/fonts/FopCharacterSet.java b/src/java/org/apache/fop/afp/fonts/FopCharacterSet.java index d3af78f7b..9d53cc7ea 100644 --- a/src/java/org/apache/fop/afp/fonts/FopCharacterSet.java +++ b/src/java/org/apache/fop/afp/fonts/FopCharacterSet.java @@ -49,6 +49,12 @@ public class FopCharacterSet extends CharacterSet { this.charSet = charSet; } + public FopCharacterSet(String codePage, String encoding, String name, Typeface charSet, + AFPResourceAccessor accessor, AFPEventProducer eventProducer) { + super(codePage, encoding, CharacterSetType.SINGLE_BYTE, name, accessor, eventProducer); + this.charSet = charSet; + } + /** * Ascender height is the distance from the character baseline to the * top of the character box. A negative ascender height signifies that diff --git a/src/java/org/apache/fop/afp/modca/AbstractTripletStructuredObject.java b/src/java/org/apache/fop/afp/modca/AbstractTripletStructuredObject.java index 662b344c1..d840e2077 100644 --- a/src/java/org/apache/fop/afp/modca/AbstractTripletStructuredObject.java +++ b/src/java/org/apache/fop/afp/modca/AbstractTripletStructuredObject.java @@ -103,7 +103,7 @@ public abstract class AbstractTripletStructuredObject extends AbstractStructured * * @param triplet the triplet to add */ - protected void addTriplet(AbstractTriplet triplet) { + public void addTriplet(AbstractTriplet triplet) { triplets.add(triplet); } @@ -131,7 +131,11 @@ public abstract class AbstractTripletStructuredObject extends AbstractStructured * @param fqName the fully qualified name of this resource */ public void setFullyQualifiedName(byte fqnType, byte fqnFormat, String fqName) { - addTriplet(new FullyQualifiedNameTriplet(fqnType, fqnFormat, fqName)); + addTriplet(new FullyQualifiedNameTriplet(fqnType, fqnFormat, fqName, false)); + } + + public void setFullyQualifiedName(byte fqnType, byte fqnFormat, String fqName, boolean utf16be) { + addTriplet(new FullyQualifiedNameTriplet(fqnType, fqnFormat, fqName, utf16be)); } /** @return the fully qualified name of this triplet or null if it does not exist */ diff --git a/src/java/org/apache/fop/afp/modca/ActiveEnvironmentGroup.java b/src/java/org/apache/fop/afp/modca/ActiveEnvironmentGroup.java index 05f48b47c..48eaa0a40 100644 --- a/src/java/org/apache/fop/afp/modca/ActiveEnvironmentGroup.java +++ b/src/java/org/apache/fop/afp/modca/ActiveEnvironmentGroup.java @@ -23,8 +23,17 @@ import java.io.IOException; import java.io.OutputStream; import java.util.List; +import org.apache.fop.afp.AFPDataObjectInfo; import org.apache.fop.afp.Factory; import org.apache.fop.afp.fonts.AFPFont; +import org.apache.fop.afp.modca.triplets.AbstractTriplet; +import org.apache.fop.afp.modca.triplets.EncodingTriplet; +import org.apache.fop.afp.modca.triplets.FullyQualifiedNameTriplet; +import org.apache.fop.afp.modca.triplets.ObjectClassificationTriplet; +import org.apache.fop.afp.util.BinaryUtils; +import org.apache.fop.apps.MimeConstants; +import org.apache.fop.fonts.FontType; +import org.apache.fop.render.afp.AFPFontConfig; /** * An Active Environment Group (AEG) is associated with each page, @@ -63,6 +72,8 @@ public final class ActiveEnvironmentGroup extends AbstractEnvironmentGroup { /** the resource manager */ private final Factory factory; + private MapDataResource mdr; + /** * Constructor for the ActiveEnvironmentGroup, this takes a * name parameter which must be 8 characters long. @@ -169,27 +180,100 @@ public final class ActiveEnvironmentGroup extends AbstractEnvironmentGroup { * @param orientation the orientation of the font (e.g. 0, 90, 180, 270) */ public void createFont(int fontRef, AFPFont font, int size, int orientation) { - MapCodedFont mapCodedFont = getCurrentMapCodedFont(); - if (mapCodedFont == null) { - mapCodedFont = factory.createMapCodedFont(); - mapCodedFonts.add(mapCodedFont); - } + if (font.getFontType() == FontType.TRUETYPE) { + if (mdr == null) { + mdr = factory.createMapDataResource(); + mapCodedFonts.add(mdr); + } + mdr.addTriplet(new EncodingTriplet(1200)); + String name = font.getFontName(); + if (((AFPFontConfig.AFPTrueTypeFont)font).getTTC() != null) { + name = ((AFPFontConfig.AFPTrueTypeFont)font).getTTC(); + } + mdr.setFullyQualifiedName(FullyQualifiedNameTriplet.TYPE_DATA_OBJECT_EXTERNAL_RESOURCE_REF, + FullyQualifiedNameTriplet.FORMAT_CHARSTR, name, true); + mdr.addTriplet(new FontFullyQualifiedNameTriplet((byte) fontRef)); - try { - mapCodedFont.addFont(fontRef, font, size, orientation); - } catch (MaximumSizeExceededException msee) { - mapCodedFont = factory.createMapCodedFont(); - mapCodedFonts.add(mapCodedFont); + setupTruetypeMDR(mdr, false); + mdr.addTriplet(new DataObjectFontTriplet(size / 1000)); + mdr.finishElement(); + } else { + MapCodedFont mapCodedFont = getCurrentMapCodedFont(); + if (mapCodedFont == null) { + mapCodedFont = factory.createMapCodedFont(); + mapCodedFonts.add(mapCodedFont); + } try { mapCodedFont.addFont(fontRef, font, size, orientation); - } catch (MaximumSizeExceededException ex) { - // Should never happen (but log just in case) - LOG.error("createFont():: resulted in a MaximumSizeExceededException"); + } catch (MaximumSizeExceededException msee) { + mapCodedFont = factory.createMapCodedFont(); + mapCodedFonts.add(mapCodedFont); + + try { + mapCodedFont.addFont(fontRef, font, size, orientation); + } catch (MaximumSizeExceededException ex) { + // Should never happen (but log just in case) + LOG.error("createFont():: resulted in a MaximumSizeExceededException"); + } } } } + public static void setupTruetypeMDR(AbstractTripletStructuredObject mdr, boolean res) { + AFPDataObjectInfo dataInfo = new AFPDataObjectInfo(); + dataInfo.setMimeType(MimeConstants.MIME_AFP_TRUETYPE); + mdr.setObjectClassification(ObjectClassificationTriplet.CLASS_DATA_OBJECT_FONT, + dataInfo.getObjectType(), res, false, res); + } + + public static class FontFullyQualifiedNameTriplet extends AbstractTriplet { + private byte fqName; + public FontFullyQualifiedNameTriplet(byte fqName) { + super(FULLY_QUALIFIED_NAME); + this.fqName = fqName; + } + + public int getDataLength() { + return 5; + } + + public void writeToStream(OutputStream os) throws IOException { + byte[] data = getData(); + data[2] = FullyQualifiedNameTriplet.TYPE_DATA_OBJECT_INTERNAL_RESOURCE_REF; + data[3] = FullyQualifiedNameTriplet.FORMAT_CHARSTR; + data[4] = fqName; + os.write(data); + } + } + + static class DataObjectFontTriplet extends AbstractTriplet { + private int pointSize; + + public DataObjectFontTriplet(int size) { + super(DATA_OBJECT_FONT_DESCRIPTOR); + pointSize = size; + } + + public int getDataLength() { + return 16; + } + + public void writeToStream(OutputStream os) throws IOException { + byte[] data = getData(); + data[3] = 0x20; + byte[] pointSizeBytes = BinaryUtils.convert(pointSize * 20, 2); + data[4] = pointSizeBytes[0]; //vfs + data[5] = pointSizeBytes[1]; +// data[6] = pointSizeBytes[0]; //hsf +// data[7] = pointSizeBytes[1]; + //charrot + data[11] = 0x03; //encenv + data[13] = 0x01; //encid + os.write(data); + } + } + /** * Getter method for the most recent MapCodedFont added to the * Active Environment Group (returns null if no MapCodedFonts exist) diff --git a/src/java/org/apache/fop/afp/modca/MapDataResource.java b/src/java/org/apache/fop/afp/modca/MapDataResource.java index 0bac920bd..c7aa758cf 100644 --- a/src/java/org/apache/fop/afp/modca/MapDataResource.java +++ b/src/java/org/apache/fop/afp/modca/MapDataResource.java @@ -21,7 +21,11 @@ package org.apache.fop.afp.modca; import java.io.IOException; import java.io.OutputStream; +import java.util.ArrayList; +import java.util.List; +import org.apache.fop.afp.modca.triplets.AbstractTriplet; +import org.apache.fop.afp.modca.triplets.Triplet; import org.apache.fop.afp.util.BinaryUtils; /** @@ -29,6 +33,7 @@ import org.apache.fop.afp.util.BinaryUtils; * required for presentation. */ public class MapDataResource extends AbstractTripletStructuredObject { + private List<List<AbstractTriplet>> tripletsList = new ArrayList<List<AbstractTriplet>>(); /** * Main constructor @@ -36,23 +41,45 @@ public class MapDataResource extends AbstractTripletStructuredObject { public MapDataResource() { } + public void finishElement() { + tripletsList.add(triplets); + triplets = new ArrayList<AbstractTriplet>(); + } + + @Override + protected int getTripletDataLength() { + int dataLength = 0; + for (List<AbstractTriplet> l : tripletsList) { + dataLength += getTripletDataLength(l) + 2; + } + return dataLength; + } + + private int getTripletDataLength(List<AbstractTriplet> l) { + int dataLength = 0; + for (Triplet triplet : l) { + dataLength += triplet.getDataLength(); + } + return dataLength; + } + /** {@inheritDoc} */ public void writeToStream(OutputStream os) throws IOException { super.writeStart(os); - byte[] data = new byte[11]; + byte[] data = new byte[9]; copySF(data, Type.MAP, Category.DATA_RESOURCE); int tripletDataLen = getTripletDataLength(); - byte[] len = BinaryUtils.convert(10 + tripletDataLen, 2); + byte[] len = BinaryUtils.convert(8 + tripletDataLen, 2); data[1] = len[0]; data[2] = len[1]; - - len = BinaryUtils.convert(2 + tripletDataLen, 2); - data[9] = len[0]; - data[10] = len[1]; - os.write(data); - writeTriplets(os); + + for (List<AbstractTriplet> l : tripletsList) { + len = BinaryUtils.convert(2 + getTripletDataLength(l), 2); + os.write(len); + writeObjects(l, os); + } } } diff --git a/src/java/org/apache/fop/afp/modca/ObjectContainer.java b/src/java/org/apache/fop/afp/modca/ObjectContainer.java index 50aabb03b..288e5aad0 100644 --- a/src/java/org/apache/fop/afp/modca/ObjectContainer.java +++ b/src/java/org/apache/fop/afp/modca/ObjectContainer.java @@ -36,7 +36,7 @@ import org.apache.fop.afp.util.BinaryUtils; public class ObjectContainer extends AbstractDataObject { /** the object container data maximum length */ - private static final int MAX_DATA_LEN = 32759; + private static final int MAX_DATA_LEN = 8192; private byte[] data; diff --git a/src/java/org/apache/fop/afp/modca/Registry.java b/src/java/org/apache/fop/afp/modca/Registry.java index 50aaca32c..fe0a42790 100644 --- a/src/java/org/apache/fop/afp/modca/Registry.java +++ b/src/java/org/apache/fop/afp/modca/Registry.java @@ -174,24 +174,24 @@ public final class Registry { MimeConstants.MIME_PCL ) ); + mimeObjectTypeMap.put( + MimeConstants.MIME_AFP_TRUETYPE, + new ObjectType( + COMPID_TRUETYPE_OPENTYPE_FONT_RESOURCE_OBJECT, + new byte[] {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x33}, + "TrueType/OpenType Font Resource Object", + true, + MimeConstants.MIME_AFP_TRUETYPE + ) + ); // mimeObjectTypeMap.put( -// null, -// new ObjectType( -// COMPID_TRUETYPE_OPENTYPE_FONT_RESOURCE_OBJECT, -// new byte[] {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x33}, -// "TrueType/OpenType Font Resource Object", -// true, -// null -// ) -// ); -// mimeObjectTypeMap.put( -// null, +// MimeConstants.MIME_AFP_TTC, // new ObjectType( // COMPID_TRUETYPE_OPENTYPE_FONT_COLLECTION_RESOURCE_OBJECT, // new byte[] {0x06, 0x07, 0x2B, 0x12, 0x00, 0x04, 0x01, 0x01, 0x35}, // "TrueType/OpenType Font Collection Resource Object", // true, -// null +// MimeConstants.MIME_AFP_TTC // ) // ); } diff --git a/src/java/org/apache/fop/afp/modca/triplets/FullyQualifiedNameTriplet.java b/src/java/org/apache/fop/afp/modca/triplets/FullyQualifiedNameTriplet.java index db6d8add8..581d215b8 100644 --- a/src/java/org/apache/fop/afp/modca/triplets/FullyQualifiedNameTriplet.java +++ b/src/java/org/apache/fop/afp/modca/triplets/FullyQualifiedNameTriplet.java @@ -150,6 +150,10 @@ public class FullyQualifiedNameTriplet extends AbstractTriplet { /** the actual fully qualified name */ private final String fqName; + private String encoding = AFPConstants.EBCIDIC_ENCODING; + + private int charlen = 1; + /** * Main constructor * @@ -157,11 +161,15 @@ public class FullyQualifiedNameTriplet extends AbstractTriplet { * @param format the fully qualified name format * @param fqName the fully qualified name */ - public FullyQualifiedNameTriplet(byte type, byte format, String fqName) { + public FullyQualifiedNameTriplet(byte type, byte format, String fqName, boolean utf16be) { super(FULLY_QUALIFIED_NAME); this.type = type; this.format = format; this.fqName = fqName; + if (utf16be) { + encoding = "UTF-16BE"; + charlen = 2; + } } /** @@ -180,7 +188,7 @@ public class FullyQualifiedNameTriplet extends AbstractTriplet { /** {@inheritDoc} */ public int getDataLength() { - return 4 + fqName.length(); + return 4 + (fqName.length() * charlen); } /** {@inheritDoc} */ @@ -191,7 +199,6 @@ public class FullyQualifiedNameTriplet extends AbstractTriplet { // FQName byte[] fqNameBytes; - String encoding = AFPConstants.EBCIDIC_ENCODING; if (format == FORMAT_URL) { encoding = AFPConstants.US_ASCII_ENCODING; } diff --git a/src/java/org/apache/fop/render/afp/AFPDocumentHandler.java b/src/java/org/apache/fop/render/afp/AFPDocumentHandler.java index 092e2a425..a2c1389d7 100644 --- a/src/java/org/apache/fop/render/afp/AFPDocumentHandler.java +++ b/src/java/org/apache/fop/render/afp/AFPDocumentHandler.java @@ -399,7 +399,7 @@ public class AFPDocumentHandler extends AbstractBinaryWritingIFDocumentHandler try { getResourceManager().createIncludedResource(formMap.getName(), formMap.getSrc(), accessor, - ResourceObject.TYPE_FORMDEF); + ResourceObject.TYPE_FORMDEF, false, null); } 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/AFPFontConfig.java b/src/java/org/apache/fop/render/afp/AFPFontConfig.java index 149973edd..341123331 100644 --- a/src/java/org/apache/fop/render/afp/AFPFontConfig.java +++ b/src/java/org/apache/fop/render/afp/AFPFontConfig.java @@ -20,6 +20,8 @@ package org.apache.fop.render.afp; import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -42,12 +44,16 @@ import org.apache.fop.afp.util.AFPResourceAccessor; import org.apache.fop.apps.FOPException; import org.apache.fop.apps.io.InternalResourceResolver; import org.apache.fop.events.EventProducer; +import org.apache.fop.fonts.EmbedFontInfo; import org.apache.fop.fonts.FontConfig; import org.apache.fop.fonts.FontManager; import org.apache.fop.fonts.FontManagerConfigurator; import org.apache.fop.fonts.FontTriplet; import org.apache.fop.fonts.FontTriplet.Matcher; +import org.apache.fop.fonts.FontType; +import org.apache.fop.fonts.FontUris; import org.apache.fop.fonts.FontUtil; +import org.apache.fop.fonts.LazyFont; import org.apache.fop.fonts.Typeface; /** @@ -154,6 +160,13 @@ public final class AFPFontConfig implements FontConfig { triplet.getAttribute("style"), weight); tripletList.add(fontTriplet); } + + String tturi = fontCfg.getAttribute("embed-url", null); + if (tturi != null) { + fontFromType(tripletList, "truetype", null, "UTF-16BE", fontCfg, eventProducer, tturi); + return; + } + //build the fonts Configuration[] config = fontCfg.getChildren("afp-font"); if (config.length == 0) { @@ -199,8 +212,9 @@ public final class AFPFontConfig implements FontConfig { embedURI); } else if ("CIDKeyed".equalsIgnoreCase(type)) { config = getCIDKeyedFont(fontTriplets, type, codepage, encoding, cfg, - eventProducer, - embedURI); + eventProducer, embedURI); + } else if ("truetype".equalsIgnoreCase(type)) { + config = getTruetypeFont(fontTriplets, type, codepage, encoding, cfg, eventProducer, embedURI); } else { LOG.error("No or incorrect type attribute: " + type); } @@ -240,6 +254,19 @@ public final class AFPFontConfig implements FontConfig { name, base14, isEmbbedable(fontTriplets), uri); } + private TrueTypeFontConfig getTruetypeFont(List<FontTriplet> fontTriplets, String type, String codepage, + String encoding, Configuration cfg, AFPEventProducer eventProducer, + String uri) throws ConfigurationException { + String name = cfg.getAttribute("name", null); + if (name == null) { + eventProducer.fontConfigMissing(this, "font name attribute", cfg.getLocation()); + return null; + } + String subfont = cfg.getAttribute("sub-font", null); + return new TrueTypeFontConfig(fontTriplets, type, codepage, encoding, "", + name, subfont, isEmbbedable(fontTriplets), uri); + } + private RasterFontConfig getRasterFont(List<FontTriplet> triplets, String type, String codepage, String encoding, Configuration cfg, AFPEventProducer eventProducer, String uri) @@ -281,12 +308,12 @@ public final class AFPFontConfig implements FontConfig { } abstract static class AFPFontConfigData { - private final List<FontTriplet> triplets; + protected final List<FontTriplet> triplets; private final String codePage; private final String encoding; private final String name; private final boolean embeddable; - private final String uri; + protected final String uri; AFPFontConfigData(List<FontTriplet> triplets, String type, String codePage, String encoding, String name, boolean embeddable, String uri) { @@ -334,6 +361,55 @@ public final class AFPFontConfig implements FontConfig { } } + static final class TrueTypeFontConfig extends AFPFontConfigData { + private String characterset; + private String subfont; + + private TrueTypeFontConfig(List<FontTriplet> triplets, String type, String codePage, + String encoding, String characterset, String name, String subfont, + boolean embeddable, String uri) { + super(triplets, type, codePage, encoding, name, embeddable, uri); + this.characterset = characterset; + this.subfont = subfont; + } + + @Override + AFPFontInfo getFontInfo(InternalResourceResolver resourceResolver, AFPEventProducer eventProducer) + throws IOException { + Typeface tf; + try { + tf = new LazyFont(new EmbedFontInfo( + new FontUris(new URI(uri), null) + , false, true, null, subfont), resourceResolver, false).getRealFont(); + } catch (URISyntaxException e) { + throw new IOException(e); + } + AFPResourceAccessor accessor = getAccessor(resourceResolver); + CharacterSet characterSet = CharacterSetBuilder.getDoubleByteInstance().build(characterset, super.codePage, + super.encoding, tf, accessor, eventProducer); + OutlineFont font = new AFPTrueTypeFont(super.name, super.embeddable, characterSet, + eventProducer, subfont); + return getFontInfo(font, this); + } + } + + public static class AFPTrueTypeFont extends OutlineFont { + private String ttc; + public AFPTrueTypeFont(String name, boolean embeddable, CharacterSet charSet, AFPEventProducer eventProducer, + String ttc) { + super(name, embeddable, charSet, eventProducer); + this.ttc = ttc; + } + + public FontType getFontType() { + return FontType.TRUETYPE; + } + + public String getTTC() { + return ttc; + } + } + static final class OutlineFontConfig extends AFPFontConfigData { private final String base14; private final String characterset; diff --git a/src/java/org/apache/fop/render/afp/AFPPainter.java b/src/java/org/apache/fop/render/afp/AFPPainter.java index aaa702afa..bfaa5db74 100644 --- a/src/java/org/apache/fop/render/afp/AFPPainter.java +++ b/src/java/org/apache/fop/render/afp/AFPPainter.java @@ -68,6 +68,7 @@ import org.apache.fop.afp.ptoca.PtocaProducer; import org.apache.fop.afp.util.AFPResourceAccessor; import org.apache.fop.fonts.Font; import org.apache.fop.fonts.FontTriplet; +import org.apache.fop.fonts.FontType; import org.apache.fop.fonts.Typeface; import org.apache.fop.render.ImageHandlerUtil; import org.apache.fop.render.RenderingContext; @@ -973,11 +974,18 @@ public class AFPPainter extends AbstractIFPainter<AFPDocumentHandler> { builder.setVariableSpaceCharacterIncrement(varSpaceCharacterIncrement); boolean fixedSpaceMode = false; + int ttPos = p.x; for (int i = 0; i < l; i++) { char orgChar = text.charAt(i); float glyphAdjust = 0; - if (CharUtilities.isFixedWidthSpace(orgChar)) { + if (afpFont.getFontType() == FontType.TRUETYPE) { + flushText(builder, sb, charSet); + fixedSpaceMode = true; + int charWidth = font.getCharWidth(orgChar); + sb.append(orgChar); + glyphAdjust += charWidth; + } else if (CharUtilities.isFixedWidthSpace(orgChar)) { flushText(builder, sb, charSet); builder.setVariableSpaceCharacterIncrement( fixedSpaceCharacterIncrement); @@ -1005,7 +1013,11 @@ public class AFPPainter extends AbstractIFPainter<AFPDocumentHandler> { glyphAdjust += dx[i + 1]; } - if (glyphAdjust != 0) { + if (afpFont.getFontType() == FontType.TRUETYPE) { + flushText(builder, sb, charSet); + ttPos += Math.round(unitConv.mpt2units(glyphAdjust)); + builder.absoluteMoveInline(ttPos); + } else if (glyphAdjust != 0) { flushText(builder, sb, charSet); int increment = Math.round(unitConv.mpt2units(glyphAdjust)); builder.relativeMoveInline(increment); |