import org.apache.xmlgraphics.java2d.Dimension2DDouble;
+import org.apache.fop.fonts.NamedCharacter;
+import org.apache.fop.fonts.SingleByteEncoding;
+
/**
* Represents the contents of a Type 1 AFM font metrics file.
*/
return m;
}
+ /**
+ * The character codes in an AFM cannot always be trusted to be the same values as in the
+ * font's primary encoding. Therefore, we provide a way to override this primary encoding.
+ * @param encoding the encoding to replace the one given in the AFM
+ */
+ public void overridePrimaryEncoding(SingleByteEncoding encoding) {
+ Iterator iter = this.charMetrics.iterator();
+ while (iter.hasNext()) {
+ AFMCharMetrics cm = (AFMCharMetrics)iter.next();
+ NamedCharacter nc = cm.getCharacter();
+ if (nc.hasSingleUnicodeValue()) {
+ int mapped = encoding.mapChar(nc.getSingleUnicodeValue());
+ if (mapped > 0) {
+ cm.setCharCode(mapped);
+ } else {
+ cm.setCharCode(-1);
+ }
+ } else {
+ //No Unicode equivalent
+ cm.setCharCode(-1);
+ }
+ }
+ }
+
/** {@inheritDoc} */
public String toString() {
return "AFM: " + getFullName();
import org.apache.fop.fonts.FontLoader;
import org.apache.fop.fonts.FontResolver;
import org.apache.fop.fonts.FontType;
+import org.apache.fop.fonts.SingleByteEncoding;
import org.apache.fop.fonts.SingleByteFont;
/**
if (afm != null) {
String encoding = afm.getEncodingScheme();
singleFont.setUseNativeEncoding(true);
- if ("StandardEncoding".equals(encoding)) {
+ if ("AdobeStandardEncoding".equals(encoding)) {
singleFont.setEncoding(CodePointMapping.STANDARD_ENCODING);
+ addUnencodedBasedOnEncoding(afm);
+ //char codes in the AFM cannot be relied on in this case, so we override
+ afm.overridePrimaryEncoding(singleFont.getEncoding());
} else {
String effEncodingName;
if ("FontSpecific".equals(encoding)) {
}
CodePointMapping mapping = buildCustomEncoding(effEncodingName, afm);
singleFont.setEncoding(mapping);
- }
- List charMetrics = afm.getCharMetrics();
- for (int i = 0, c = afm.getCharCount(); i < c; i++) {
- AFMCharMetrics metrics = (AFMCharMetrics)charMetrics.get(i);
- if (!metrics.hasCharCode() && metrics.getCharacter() != null) {
- singleFont.addUnencodedCharacter(metrics.getCharacter(),
- (int)Math.round(metrics.getWidthX()));
- }
+ addUnencodedBasedOnAFM(afm);
}
} else {
if (pfm.getCharSet() >= 0 && pfm.getCharSet() <= 2) {
}
}
+ private Set toGlyphSet(String[] glyphNames) {
+ Set glyphSet = new java.util.HashSet();
+ for (int i = 0, c = glyphNames.length; i < c; i++) {
+ glyphSet.add(glyphNames[i]);
+ }
+ return glyphSet;
+ }
+
+ /**
+ * Adds characters not encoded in the font's primary encoding. This method is used when we
+ * don't trust the AFM to expose the same encoding as the primary font.
+ * @param afm the AFM file.
+ */
+ private void addUnencodedBasedOnEncoding(AFMFile afm) {
+ SingleByteEncoding encoding = singleFont.getEncoding();
+ Set glyphNames = toGlyphSet(encoding.getCharNameMap());
+ List charMetrics = afm.getCharMetrics();
+ for (int i = 0, c = afm.getCharCount(); i < c; i++) {
+ AFMCharMetrics metrics = (AFMCharMetrics)charMetrics.get(i);
+ String charName = metrics.getCharName();
+ if (charName != null && !glyphNames.contains(charName)) {
+ singleFont.addUnencodedCharacter(metrics.getCharacter(),
+ (int)Math.round(metrics.getWidthX()));
+ }
+ }
+ }
+
+ /**
+ * Adds characters not encoded in the font's primary encoding. This method is used when
+ * the primary encoding is built based on the character codes in the AFM rather than
+ * the specified encoding (ex. with symbolic fonts).
+ * @param afm the AFM file
+ */
+ private void addUnencodedBasedOnAFM(AFMFile afm) {
+ List charMetrics = afm.getCharMetrics();
+ for (int i = 0, c = afm.getCharCount(); i < c; i++) {
+ AFMCharMetrics metrics = (AFMCharMetrics)charMetrics.get(i);
+ if (!metrics.hasCharCode() && metrics.getCharacter() != null) {
+ singleFont.addUnencodedCharacter(metrics.getCharacter(),
+ (int)Math.round(metrics.getWidthX()));
+ }
+ }
+ }
+
private void handleFontName(AFMFile afm, PFMFile pfm) {
//Font name
if (afm != null) {