]> source.dussan.org Git - xmlgraphics-fop.git/commitdiff
Bugzilla #48512:
authorJeremias Maerki <jeremias@apache.org>
Tue, 16 Feb 2010 09:36:40 +0000 (09:36 +0000)
committerJeremias Maerki <jeremias@apache.org>
Tue, 16 Feb 2010 09:36:40 +0000 (09:36 +0000)
Reverted rev 908543.
For some Type 1 fonts, the encoding mapped characters in the AFM file don't match the font's primary encoding. This change tries to address this fact.

git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@910445 13f79535-47bb-0310-9956-ffa450edef68

src/java/org/apache/fop/fonts/type1/AFMFile.java
src/java/org/apache/fop/fonts/type1/Type1FontLoader.java

index c427ff22f76df163b549493997a8eca67ce98548..427a87691e73a168e9fdccbd96202f297caf527a 100644 (file)
@@ -28,6 +28,9 @@ import java.util.Map;
 
 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.
  */
@@ -442,6 +445,30 @@ public class AFMFile {
         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();
index 4d068f1dff3c29fe0b2145c119cbe38210925b8a..d5036de7ba4c7962a4f893d32a25ca391adddce2 100644 (file)
@@ -32,6 +32,7 @@ import org.apache.fop.fonts.CodePointMapping;
 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;
 
 /**
@@ -141,8 +142,11 @@ public class Type1FontLoader extends FontLoader {
         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)) {
@@ -156,14 +160,7 @@ public class Type1FontLoader extends FontLoader {
                 }
                 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) {
@@ -176,6 +173,50 @@ public class Type1FontLoader extends FontLoader {
         }
     }
 
+    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) {