aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorVincent Hennebert <vhennebert@apache.org>2010-08-27 18:40:49 +0000
committerVincent Hennebert <vhennebert@apache.org>2010-08-27 18:40:49 +0000
commit519ac01c92c11a0305f13b7124fe2242cfb5b922 (patch)
treef5b07da5fb23e3b08bb1b863f929a4778cf01784 /src
parent001ddbb84ad0805b8112a861df08f9ca7d56fc3e (diff)
downloadxmlgraphics-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')
-rw-r--r--src/java/org/apache/fop/fonts/SingleByteFont.java25
-rw-r--r--src/java/org/apache/fop/fonts/truetype/TTFFile.java129
-rw-r--r--src/java/org/apache/fop/fonts/truetype/TTFFontLoader.java6
-rw-r--r--src/java/org/apache/fop/render/ps/PSFontUtils.java57
-rw-r--r--src/java/org/apache/fop/render/ps/PSPainter.java1
-rw-r--r--src/java/org/apache/fop/render/ps/PSTextPainter.java1
-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);
}