diff options
author | Vincent Hennebert <vhennebert@apache.org> | 2010-08-27 18:40:49 +0000 |
---|---|---|
committer | Vincent Hennebert <vhennebert@apache.org> | 2010-08-27 18:40:49 +0000 |
commit | 519ac01c92c11a0305f13b7124fe2242cfb5b922 (patch) | |
tree | f5b07da5fb23e3b08bb1b863f929a4778cf01784 /src/java | |
parent | 001ddbb84ad0805b8112a861df08f9ca7d56fc3e (diff) | |
download | xmlgraphics-fop-519ac01c92c11a0305f13b7124fe2242cfb5b922.tar.gz xmlgraphics-fop-519ac01c92c11a0305f13b7124fe2242cfb5b922.zip |
Added possibility to use glyphs outside WinAnsiEncoding for TrueType fonts that are not embedded in the PostScript file, and that don't have a list of glyph names ('post' table version 3).
This is done by creating glyph names using Adobe's convention (/u1234) and adding a CharStrings table that maps those glyph names to the actual glyph index.
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_TrueTypeInPostScript@990225 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src/java')
-rw-r--r-- | src/java/org/apache/fop/fonts/SingleByteFont.java | 25 | ||||
-rw-r--r-- | src/java/org/apache/fop/fonts/truetype/TTFFile.java | 129 | ||||
-rw-r--r-- | src/java/org/apache/fop/fonts/truetype/TTFFontLoader.java | 6 | ||||
-rw-r--r-- | src/java/org/apache/fop/render/ps/PSFontUtils.java | 57 | ||||
-rw-r--r-- | src/java/org/apache/fop/render/ps/PSPainter.java | 1 | ||||
-rw-r--r-- | src/java/org/apache/fop/render/ps/PSTextPainter.java | 1 | ||||
-rw-r--r-- | src/java/org/apache/fop/util/HexEncoder.java (renamed from src/java/org/apache/fop/render/ps/HexEncoder.java) | 10 |
7 files changed, 213 insertions, 16 deletions
diff --git a/src/java/org/apache/fop/fonts/SingleByteFont.java b/src/java/org/apache/fop/fonts/SingleByteFont.java index 14cba4815..a09c81670 100644 --- a/src/java/org/apache/fop/fonts/SingleByteFont.java +++ b/src/java/org/apache/fop/fonts/SingleByteFont.java @@ -27,6 +27,8 @@ import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.apache.fop.fonts.truetype.TTFFile.PostScriptVersion; + /** * Generic SingleByte font */ @@ -46,6 +48,8 @@ public class SingleByteFont extends CustomFont { private List cmaps; + private PostScriptVersion ttPostScriptVersion; + /** * Main constructor. */ @@ -335,6 +339,27 @@ public class SingleByteFont extends CustomFont { } } + /** + * Sets the version of the PostScript table stored in the TrueType font represented by + * this instance. + * + * @param version version of the <q>post</q> table + */ + public void setTrueTypePostScriptVersion(PostScriptVersion version) { + ttPostScriptVersion = version; + } + + /** + * Returns the version of the PostScript table stored in the TrueType font represented by + * this instance. + * + * @return the version of the <q>post</q> table + */ + public PostScriptVersion getTrueTypePostScriptVersion() { + assert getFontType() == FontType.TRUETYPE; + return ttPostScriptVersion; + } + /** TODO remove */ public void setCMaps(List cmaps) { this.cmaps = cmaps; diff --git a/src/java/org/apache/fop/fonts/truetype/TTFFile.java b/src/java/org/apache/fop/fonts/truetype/TTFFile.java index 7ad51c676..6f3bb9f49 100644 --- a/src/java/org/apache/fop/fonts/truetype/TTFFile.java +++ b/src/java/org/apache/fop/fonts/truetype/TTFFile.java @@ -41,10 +41,94 @@ import org.apache.fop.fonts.FontUtil; public class TTFFile { static final byte NTABS = 24; - static final int NMACGLYPHS = 258; static final int MAX_CHAR_CODE = 255; static final int ENC_BUF_SIZE = 1024; + private static final String[] MAC_GLYPH_ORDERING = { + /* 0x000 */ + ".notdef", ".null", "nonmarkingreturn", "space", + "exclam", "quotedbl", "numbersign", "dollar", + "percent", "ampersand", "quotesingle", "parenleft", + "parenright", "asterisk", "plus", "comma", + /* 0x010 */ + "hyphen", "period", "slash", "zero", + "one", "two", "three", "four", + "five", "six", "seven", "eight", + "nine", "colon", "semicolon", "less", + /* 0x020 */ + "equal", "greater", "question", "at", + "A", "B", "C", "D", + "E", "F", "G", "H", + "I", "J", "K", "L", + /* 0x030 */ + "M", "N", "O", "P", + "Q", "R", "S", "T", + "U", "V", "W", "X", + "Y", "Z", "bracketleft", "backslash", + /* 0x040 */ + "bracketright", "asciicircum", "underscore", "grave", + "a", "b", "c", "d", + "e", "f", "g", "h", + "i", "j", "k", "l", + /* 0x050 */ + "m", "n", "o", "p", + "q", "r", "s", "t", + "u", "v", "w", "x", + "y", "z", "braceleft", "bar", + /* 0x060 */ + "braceright", "asciitilde", "Adieresis", "Aring", + "Ccedilla", "Eacute", "Ntilde", "Odieresis", + "Udieresis", "aacute", "agrave", "acircumflex", + "adieresis", "atilde", "aring", "ccedilla", + /* 0x070 */ + "eacute", "egrave", "ecircumflex", "edieresis", + "iacute", "igrave", "icircumflex", "idieresis", + "ntilde", "oacute", "ograve", "ocircumflex", + "odieresis", "otilde", "uacute", "ugrave", + /* 0x080 */ + "ucircumflex", "udieresis", "dagger", "degree", + "cent", "sterling", "section", "bullet", + "paragraph", "germandbls", "registered", "copyright", + "trademark", "acute", "dieresis", "notequal", + /* 0x090 */ + "AE", "Oslash", "infinity", "plusminus", + "lessequal", "greaterequal", "yen", "mu", + "partialdiff", "summation", "product", "pi", + "integral", "ordfeminine", "ordmasculine", "Omega", + /* 0x0A0 */ + "ae", "oslash", "questiondown", "exclamdown", + "logicalnot", "radical", "florin", "approxequal", + "Delta", "guillemotleft", "guillemotright", "ellipsis", + "nonbreakingspace", "Agrave", "Atilde", "Otilde", + /* 0x0B0 */ + "OE", "oe", "endash", "emdash", + "quotedblleft", "quotedblright", "quoteleft", "quoteright", + "divide", "lozenge", "ydieresis", "Ydieresis", + "fraction", "currency", "guilsinglleft", "guilsinglright", + /* 0x0C0 */ + "fi", "fl", "daggerdbl", "periodcentered", + "quotesinglbase", "quotedblbase", "perthousand", "Acircumflex", + "Ecircumflex", "Aacute", "Edieresis", "Egrave", + "Iacute", "Icircumflex", "Idieresis", "Igrave", + /* 0x0D0 */ + "Oacute", "Ocircumflex", "apple", "Ograve", + "Uacute", "Ucircumflex", "Ugrave", "dotlessi", + "circumflex", "tilde", "macron", "breve", + "dotaccent", "ring", "cedilla", "hungarumlaut", + /* 0x0E0 */ + "ogonek", "caron", "Lslash", "lslash", + "Scaron", "scaron", "Zcaron", "zcaron", + "brokenbar", "Eth", "eth", "Yacute", + "yacute", "Thorn", "thorn", "minus", + /* 0x0F0 */ + "multiply", "onesuperior", "twosuperior", "threesuperior", + "onehalf", "onequarter", "threequarters", "franc", + "Gbreve", "gbreve", "Idotaccent", "Scedilla", + "scedilla", "Cacute", "cacute", "Ccaron", + /* 0x100 */ + "ccaron", "dcroat" + }; + /** Set to true to get even more debug output than with level DEBUG */ public static final boolean TRACE_ENABLED = false; @@ -64,7 +148,7 @@ public class TTFFile { private int upem; // unitsPerEm from "head" table private int nhmtx; // Number of horizontal metrics - private int postFormat; + private PostScriptVersion postScriptVersion; private int locaFormat; /** * Offset to last loca @@ -160,6 +244,27 @@ public class TTFFile { } /** + * Version of the PostScript table (<q>post</q>) contained in this font. + */ + public static final class PostScriptVersion { + + /** PostScript table version 1.0. */ + public static final PostScriptVersion V1 = new PostScriptVersion(); + + /** PostScript table version 2.0. */ + public static final PostScriptVersion V2 = new PostScriptVersion(); + + /** PostScript table version 3.0. */ + public static final PostScriptVersion V3 = new PostScriptVersion(); + + /** Unknown version of the PostScript table. */ + public static final PostScriptVersion UNKNOWN = new PostScriptVersion(); + + private PostScriptVersion() { } + + } + + /** * Position inputstream to position indicated * in the dirtab offset + offset */ @@ -604,6 +709,10 @@ public class TTFFile { } } + PostScriptVersion getPostScriptVersion() { + return postScriptVersion; + } + /** * Returns the font family names of the font. * @return Set The family names (a Set of Strings) @@ -964,7 +1073,7 @@ public class TTFFile { */ private void readPostScript(FontFileReader in) throws IOException { seekTab(in, "post", 0); - postFormat = in.readTTFLong(); + int postFormat = in.readTTFLong(); italicAngle = in.readTTFULong(); underlinePosition = in.readTTFShort(); underlineThickness = in.readTTFShort(); @@ -977,12 +1086,14 @@ public class TTFFile { switch (postFormat) { case 0x00010000: log.debug("PostScript format 1"); - for (int i = 0; i < Glyphs.MAC_GLYPH_NAMES.length; i++) { - mtxTab[i].setName(Glyphs.MAC_GLYPH_NAMES[i]); + postScriptVersion = PostScriptVersion.V1; + for (int i = 0; i < MAC_GLYPH_ORDERING.length; i++) { + mtxTab[i].setName(MAC_GLYPH_ORDERING[i]); } break; case 0x00020000: log.debug("PostScript format 2"); + postScriptVersion = PostScriptVersion.V2; int numGlyphStrings = 0; // Read Number of Glyphs @@ -1015,11 +1126,11 @@ public class TTFFile { //Set glyph names for (int i = 0; i < l; i++) { - if (mtxTab[i].getIndex() < NMACGLYPHS) { - mtxTab[i].setName(Glyphs.MAC_GLYPH_NAMES[mtxTab[i].getIndex()]); + if (mtxTab[i].getIndex() < MAC_GLYPH_ORDERING.length) { + mtxTab[i].setName(MAC_GLYPH_ORDERING[mtxTab[i].getIndex()]); } else { if (!mtxTab[i].isIndexReserved()) { - int k = mtxTab[i].getIndex() - NMACGLYPHS; + int k = mtxTab[i].getIndex() - MAC_GLYPH_ORDERING.length; if (log.isTraceEnabled()) { log.trace(k + " i=" + i + " mtx=" + mtxTab.length @@ -1035,9 +1146,11 @@ public class TTFFile { case 0x00030000: // PostScript format 3 contains no glyph names log.debug("PostScript format 3"); + postScriptVersion = PostScriptVersion.V3; break; default: log.error("Unknown PostScript format: " + postFormat); + postScriptVersion = PostScriptVersion.UNKNOWN; } } diff --git a/src/java/org/apache/fop/fonts/truetype/TTFFontLoader.java b/src/java/org/apache/fop/fonts/truetype/TTFFontLoader.java index 10e618adf..cf24ea352 100644 --- a/src/java/org/apache/fop/fonts/truetype/TTFFontLoader.java +++ b/src/java/org/apache/fop/fonts/truetype/TTFFontLoader.java @@ -36,6 +36,8 @@ import org.apache.fop.fonts.FontType; import org.apache.fop.fonts.MultiByteFont; import org.apache.fop.fonts.NamedCharacter; import org.apache.fop.fonts.SingleByteFont; +import org.apache.fop.fonts.truetype.TTFFile.PostScriptVersion; +import org.apache.fop.util.HexEncoder; /** * Loads a TrueType font into memory directly from the original font file. @@ -162,6 +164,7 @@ public class TTFFontLoader extends FontLoader { returnFont.setFirstChar(ttf.getFirstChar()); returnFont.setLastChar(ttf.getLastChar()); singleFont.setCMaps(ttf.getCMaps()); + singleFont.setTrueTypePostScriptVersion(ttf.getPostScriptVersion()); copyWidthsSingleByte(ttf); } @@ -187,6 +190,9 @@ public class TTFFontLoader extends FontLoader { if (codePoint <= 0) { int glyphIndex = ce.getGlyphStartIndex() + u - ce.getUnicodeStart(); String glyphName = ttf.getGlyphName(glyphIndex); + if (glyphName == "" && ttf.getPostScriptVersion() != PostScriptVersion.V2) { + glyphName = "u" + HexEncoder.encode(u); + } if (glyphName != "") { String unicode = Character.toString(u); NamedCharacter nc = new NamedCharacter(glyphName, unicode); diff --git a/src/java/org/apache/fop/render/ps/PSFontUtils.java b/src/java/org/apache/fop/render/ps/PSFontUtils.java index e1a477b4e..07ca0e4b5 100644 --- a/src/java/org/apache/fop/render/ps/PSFontUtils.java +++ b/src/java/org/apache/fop/render/ps/PSFontUtils.java @@ -55,6 +55,8 @@ import org.apache.fop.fonts.SingleByteEncoding; import org.apache.fop.fonts.SingleByteFont; import org.apache.fop.fonts.Typeface; import org.apache.fop.fonts.truetype.TTFCmapEntry; +import org.apache.fop.fonts.truetype.TTFFile.PostScriptVersion; +import org.apache.fop.util.HexEncoder; /** * Utility code for font handling in PostScript. @@ -132,8 +134,16 @@ public class PSFontUtils extends org.apache.xmlgraphics.ps.PSFontUtils { SingleByteEncoding encoding = sbf.getAdditionalEncoding(i); defineEncoding(gen, encoding); String postFix = "_" + (i + 1); - PSResource derivedFontRes = defineDerivedFont(gen, tf.getFontName(), - tf.getFontName() + postFix, encoding.getName()); + PSResource derivedFontRes; + if (tf.getFontType() == FontType.TRUETYPE + && sbf.getTrueTypePostScriptVersion() != PostScriptVersion.V2) { + derivedFontRes = defineDerivedTrueTypeFont(gen, eventProducer, + tf.getFontName(), tf.getFontName() + postFix, encoding, + sbf.getCMaps()); + } else { + derivedFontRes = defineDerivedFont(gen, tf.getFontName(), + tf.getFontName() + postFix, encoding.getName()); + } fontResources.put(key + postFix, PSFontResource.createFontResource(derivedFontRes)); } @@ -334,7 +344,10 @@ public class PSFontUtils extends org.apache.xmlgraphics.ps.PSFontUtils { } private static int getGlyphIndex(String glyphName, List cmaps) { - char c = Glyphs.getUnicodeSequenceForGlyphName(glyphName).charAt(0); + return getGlyphIndex(Glyphs.getUnicodeSequenceForGlyphName(glyphName).charAt(0), cmaps); + } + + private static int getGlyphIndex(char c, List cmaps) { for (Iterator iter = cmaps.iterator(); iter.hasNext();) { TTFCmapEntry cmap = (TTFCmapEntry) iter.next(); if (cmap.getUnicodeStart() <= c && c <= cmap.getUnicodeEnd()) { @@ -591,4 +604,42 @@ public class PSFontUtils extends org.apache.xmlgraphics.ps.PSFontUtils { return res; } + private static PSResource defineDerivedTrueTypeFont(PSGenerator gen, + PSEventProducer eventProducer, String baseFontName, String fontName, + SingleByteEncoding encoding, List cmaps) throws IOException { + PSResource res = new PSResource(PSResource.TYPE_FONT, fontName); + gen.writeDSCComment(DSCConstants.BEGIN_RESOURCE, res); + gen.commentln("%XGCDependencies: font " + baseFontName); + gen.commentln("%XGC+ encoding " + encoding.getName()); + gen.writeln("/" + baseFontName + " findfont"); + gen.writeln("dup length dict begin"); + gen.writeln(" {1 index /FID ne {def} {pop pop} ifelse} forall"); + gen.writeln(" /Encoding " + encoding.getName() + " def"); + + gen.writeln(" /CharStrings 256 dict dup begin"); + String[] charNameMap = encoding.getCharNameMap(); + char[] unicodeCharMap = encoding.getUnicodeCharMap(); + assert charNameMap.length == unicodeCharMap.length; + for (int i = 0; i < charNameMap.length; i++) { + String glyphName = charNameMap[i]; + gen.write(" /"); + gen.write(glyphName); + gen.write(" "); + if (glyphName.equals(".notdef")) { + gen.write(0); + } else { + gen.write(getGlyphIndex(unicodeCharMap[i], cmaps)); + } + gen.writeln(" def"); + } + gen.writeln(" end readonly def"); + + gen.writeln(" currentdict"); + gen.writeln("end"); + gen.writeln("/" + fontName + " exch definefont pop"); + gen.writeDSCComment(DSCConstants.END_RESOURCE); + gen.getResourceTracker().registerSuppliedResource(res); + return res; + } + } diff --git a/src/java/org/apache/fop/render/ps/PSPainter.java b/src/java/org/apache/fop/render/ps/PSPainter.java index b31775177..5ed217db1 100644 --- a/src/java/org/apache/fop/render/ps/PSPainter.java +++ b/src/java/org/apache/fop/render/ps/PSPainter.java @@ -55,6 +55,7 @@ import org.apache.fop.render.intermediate.IFState; import org.apache.fop.traits.BorderProps; import org.apache.fop.traits.RuleStyle; import org.apache.fop.util.CharUtilities; +import org.apache.fop.util.HexEncoder; /** * IFPainter implementation that produces PostScript. diff --git a/src/java/org/apache/fop/render/ps/PSTextPainter.java b/src/java/org/apache/fop/render/ps/PSTextPainter.java index c5237fd80..caa778ae2 100644 --- a/src/java/org/apache/fop/render/ps/PSTextPainter.java +++ b/src/java/org/apache/fop/render/ps/PSTextPainter.java @@ -50,6 +50,7 @@ import org.apache.fop.fonts.LazyFont; import org.apache.fop.fonts.MultiByteFont; import org.apache.fop.svg.NativeTextPainter; import org.apache.fop.util.CharUtilities; +import org.apache.fop.util.HexEncoder; /** * Renders the attributed character iterator of a text node. diff --git a/src/java/org/apache/fop/render/ps/HexEncoder.java b/src/java/org/apache/fop/util/HexEncoder.java index e78563102..38f312784 100644 --- a/src/java/org/apache/fop/render/ps/HexEncoder.java +++ b/src/java/org/apache/fop/util/HexEncoder.java @@ -17,12 +17,12 @@ /* $Id$ */ -package org.apache.fop.render.ps; +package org.apache.fop.util; /** - * A helper class to hex-encoded representations of numbers. + * A helper class create to hex-encoded representations of numbers. */ -final class HexEncoder { +public final class HexEncoder { private HexEncoder() { } @@ -34,7 +34,7 @@ final class HexEncoder { * @param width required length of the string * @return an hex-encoded representation of the number */ - static String encode(int n, int width) { + public static String encode(int n, int width) { char[] digits = new char[width]; for (int i = width - 1; i >= 0; i--) { int digit = n & 0xF; @@ -50,7 +50,7 @@ final class HexEncoder { * @param c a character * @return an hex-encoded representation of the character */ - static String encode(char c) { + public static String encode(char c) { return encode(c, 4); } |