Author: jeremias
Date: Thu Nov 11 20:03:43 2010
New Revision: 1034094

URL: http://svn.apache.org/viewvc?rev=1034094&view=rev
Log:
PostScript Output: Bugfix for the occasional badly rendered glyph on HP 
Laserjets.
Reason: the /sfnts entry should split strings at glyph boundaries which 
currently doesn't happen.
Solution: Switch to the /GlyphDirectory approach described in the section 
"Incremental Definition of Type 42 Fonts" in the PS language reference. This 
way all glyphs are separated into single strings which seems to solve the 
problem. It is also much closer to the approach taken by the various PostScript 
printer drivers on Windows.

Modified:
    
xmlgraphics/fop/branches/Temp_TrueTypeInPostScript/src/java/org/apache/fop/fonts/truetype/TTFSubSetFile.java
    
xmlgraphics/fop/branches/Temp_TrueTypeInPostScript/src/java/org/apache/fop/render/ps/PSFontUtils.java

Modified: 
xmlgraphics/fop/branches/Temp_TrueTypeInPostScript/src/java/org/apache/fop/fonts/truetype/TTFSubSetFile.java
URL: 
http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_TrueTypeInPostScript/src/java/org/apache/fop/fonts/truetype/TTFSubSetFile.java?rev=1034094&r1=1034093&r2=1034094&view=diff
==============================================================================
--- 
xmlgraphics/fop/branches/Temp_TrueTypeInPostScript/src/java/org/apache/fop/fonts/truetype/TTFSubSetFile.java
 (original)
+++ 
xmlgraphics/fop/branches/Temp_TrueTypeInPostScript/src/java/org/apache/fop/fonts/truetype/TTFSubSetFile.java
 Thu Nov 11 20:03:43 2010
@@ -20,7 +20,6 @@
 package org.apache.fop.fonts.truetype;
 
 import java.io.IOException;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 
@@ -35,6 +34,10 @@ import java.util.Map;
  */
 public class TTFSubSetFile extends TTFFile {
 
+    private static enum OperatingMode {
+        PDF, POSTSCRIPT_GLYPH_DIRECTORY
+    }
+
     private byte[] output = null;
     private int realSize = 0;
     private int currentPos = 0;
@@ -43,37 +46,27 @@ public class TTFSubSetFile extends TTFFi
      * Offsets in name table to be filled out by table.
      * The offsets are to the checkSum field
      */
-    private int cvtDirOffset = 0;
-    private int fpgmDirOffset = 0;
+    private Map<String, Integer> offsets = new java.util.HashMap<String, 
Integer>();
     private int glyfDirOffset = 0;
     private int headDirOffset = 0;
-    private int hheaDirOffset = 0;
     private int hmtxDirOffset = 0;
     private int locaDirOffset = 0;
     private int maxpDirOffset = 0;
-    private int prepDirOffset = 0;
 
     private int checkSumAdjustmentOffset = 0;
     private int locaOffset = 0;
 
-    /**
-     * Initalize the output array
-     */
-    private void init(int size) {
-        output = new byte[size];
-        realSize = 0;
-        currentPos = 0;
-
-        // createDirectory()
-    }
-
-    private int determineTableCount() {
+    private int determineTableCount(OperatingMode operatingMode) {
         int numTables = 4; //4 req'd tables: head,hhea,hmtx,maxp
         if (isCFF()) {
             throw new UnsupportedOperationException(
                     "OpenType fonts with CFF glyphs are not supported");
         } else {
-            numTables += 2; //1 req'd table: glyf,loca
+            if (operatingMode == OperatingMode.POSTSCRIPT_GLYPH_DIRECTORY) {
+                numTables++; //1 table: gdir
+            } else {
+                numTables += 2; //2 req'd tables: glyf,loca
+            }
             if (hasCvt()) {
                 numTables++;
             }
@@ -90,8 +83,8 @@ public class TTFSubSetFile extends TTFFi
     /**
      * Create the directory table
      */
-    private void createDirectory() {
-        int numTables = determineTableCount();
+    private void createDirectory(OperatingMode operatingMode) {
+        int numTables = determineTableCount(operatingMode);
         // Create the TrueType header
         writeByte((byte)0);
         writeByte((byte)1);
@@ -117,22 +110,24 @@ public class TTFSubSetFile extends TTFFi
         // Create space for the table entries
         if (hasCvt()) {
             writeString("cvt ");
-            cvtDirOffset = currentPos;
+            offsets.put("cvt ", currentPos);
             currentPos += 12;
             realSize += 16;
         }
 
         if (hasFpgm()) {
             writeString("fpgm");
-            fpgmDirOffset = currentPos;
+            offsets.put("fpgm", currentPos);
             currentPos += 12;
             realSize += 16;
         }
 
-        writeString("glyf");
-        glyfDirOffset = currentPos;
-        currentPos += 12;
-        realSize += 16;
+        if (operatingMode != OperatingMode.POSTSCRIPT_GLYPH_DIRECTORY) {
+            writeString("glyf");
+            glyfDirOffset = currentPos;
+            currentPos += 12;
+            realSize += 16;
+        }
 
         writeString("head");
         headDirOffset = currentPos;
@@ -140,7 +135,7 @@ public class TTFSubSetFile extends TTFFi
         realSize += 16;
 
         writeString("hhea");
-        hheaDirOffset = currentPos;
+        offsets.put("hhea", currentPos);
         currentPos += 12;
         realSize += 16;
 
@@ -149,10 +144,12 @@ public class TTFSubSetFile extends TTFFi
         currentPos += 12;
         realSize += 16;
 
-        writeString("loca");
-        locaDirOffset = currentPos;
-        currentPos += 12;
-        realSize += 16;
+        if (operatingMode != OperatingMode.POSTSCRIPT_GLYPH_DIRECTORY) {
+            writeString("loca");
+            locaDirOffset = currentPos;
+            currentPos += 12;
+            realSize += 16;
+        }
 
         writeString("maxp");
         maxpDirOffset = currentPos;
@@ -161,37 +158,21 @@ public class TTFSubSetFile extends TTFFi
 
         if (hasPrep()) {
             writeString("prep");
-            prepDirOffset = currentPos;
+            offsets.put("prep", currentPos);
             currentPos += 12;
             realSize += 16;
         }
-    }
-
-
-    /**
-     * Copy the cvt table as is from original font to subset font
-     */
-    private boolean createCvt(FontFileReader in) throws IOException {
-        TTFDirTabEntry entry = (TTFDirTabEntry)dirTabs.get("cvt ");
-        if (entry != null) {
-            pad4();
-            seekTab(in, "cvt ", 0);
-            System.arraycopy(in.getBytes((int)entry.getOffset(), 
(int)entry.getLength()),
-                             0, output, currentPos, (int)entry.getLength());
 
-            int checksum = getCheckSum(currentPos, (int)entry.getLength());
-            writeULong(cvtDirOffset, checksum);
-            writeULong(cvtDirOffset + 4, currentPos);
-            writeULong(cvtDirOffset + 8, (int)entry.getLength());
-            currentPos += (int)entry.getLength();
-            realSize += (int)entry.getLength();
-            return true;
-        } else {
-            return false;
-            //throw new IOException("Can't find cvt table");
+        if (operatingMode == OperatingMode.POSTSCRIPT_GLYPH_DIRECTORY) {
+            //"gdir" indicates to the PostScript interpreter that the 
GlyphDirectory approach
+            //is in use.
+            writeString("gdir");
+            currentPos += 12;
+            realSize += 16;
         }
     }
 
+
     private boolean hasCvt() {
         return dirTabs.containsKey("cvt ");
     }
@@ -205,19 +186,29 @@ public class TTFSubSetFile extends TTFFi
     }
 
     /**
-     * Copy the fpgm table as is from original font to subset font
+     * Create an empty loca table without updating checksum
      */
-    private boolean createFpgm(FontFileReader in) throws IOException {
-        TTFDirTabEntry entry = (TTFDirTabEntry)dirTabs.get("fpgm");
+    private void createLoca(int size) throws IOException {
+        pad4();
+        locaOffset = currentPos;
+        writeULong(locaDirOffset + 4, currentPos);
+        writeULong(locaDirOffset + 8, size * 4 + 4);
+        currentPos += size * 4 + 4;
+        realSize += size * 4 + 4;
+    }
+
+    private boolean copyTable(FontFileReader in, String tableName) throws 
IOException {
+        TTFDirTabEntry entry = (TTFDirTabEntry)dirTabs.get(tableName);
         if (entry != null) {
             pad4();
-            seekTab(in, "fpgm", 0);
+            seekTab(in, tableName, 0);
             System.arraycopy(in.getBytes((int)entry.getOffset(), 
(int)entry.getLength()),
                              0, output, currentPos, (int)entry.getLength());
             int checksum = getCheckSum(currentPos, (int)entry.getLength());
-            writeULong(fpgmDirOffset, checksum);
-            writeULong(fpgmDirOffset + 4, currentPos);
-            writeULong(fpgmDirOffset + 8, (int)entry.getLength());
+            int offset = offsets.get(tableName);
+            writeULong(offset, checksum);
+            writeULong(offset + 4, currentPos);
+            writeULong(offset + 8, (int)entry.getLength());
             currentPos += (int)entry.getLength();
             realSize += (int)entry.getLength();
             return true;
@@ -226,20 +217,19 @@ public class TTFSubSetFile extends TTFFi
         }
     }
 
-
-
     /**
-     * Create an empty loca table without updating checksum
+     * Copy the cvt table as is from original font to subset font
      */
-    private void createLoca(int size) throws IOException {
-        pad4();
-        locaOffset = currentPos;
-        writeULong(locaDirOffset + 4, currentPos);
-        writeULong(locaDirOffset + 8, size * 4 + 4);
-        currentPos += size * 4 + 4;
-        realSize += size * 4 + 4;
+    private boolean createCvt(FontFileReader in) throws IOException {
+        return copyTable(in, "cvt ");
     }
 
+    /**
+     * Copy the fpgm table as is from original font to subset font
+     */
+    private boolean createFpgm(FontFileReader in) throws IOException {
+        return copyTable(in, "fpgm");
+    }
 
     /**
      * Copy the maxp table as is from original font to subset font
@@ -270,23 +260,7 @@ public class TTFSubSetFile extends TTFFi
      * Copy the prep table as is from original font to subset font
      */
     private boolean createPrep(FontFileReader in) throws IOException {
-        TTFDirTabEntry entry = (TTFDirTabEntry)dirTabs.get("prep");
-        if (entry != null) {
-            pad4();
-            seekTab(in, "prep", 0);
-            System.arraycopy(in.getBytes((int)entry.getOffset(), 
(int)entry.getLength()),
-                             0, output, currentPos, (int)entry.getLength());
-
-            int checksum = getCheckSum(currentPos, (int)entry.getLength());
-            writeULong(prepDirOffset, checksum);
-            writeULong(prepDirOffset + 4, currentPos);
-            writeULong(prepDirOffset + 8, (int)entry.getLength());
-            currentPos += (int)entry.getLength();
-            realSize += (int)entry.getLength();
-            return true;
-        } else {
-            return false;
-        }
+        return copyTable(in, "prep");
     }
 
 
@@ -295,21 +269,8 @@ public class TTFSubSetFile extends TTFFi
      * and fill in size of hmtx table
      */
     private void createHhea(FontFileReader in, int size) throws IOException {
-        TTFDirTabEntry entry = (TTFDirTabEntry)dirTabs.get("hhea");
-        if (entry != null) {
-            pad4();
-            seekTab(in, "hhea", 0);
-            System.arraycopy(in.getBytes((int)entry.getOffset(), 
(int)entry.getLength()),
-                             0, output, currentPos, (int)entry.getLength());
-            writeUShort((int)entry.getLength() + currentPos - 2, size);
-
-            int checksum = getCheckSum(currentPos, (int)entry.getLength());
-            writeULong(hheaDirOffset, checksum);
-            writeULong(hheaDirOffset + 4, currentPos);
-            writeULong(hheaDirOffset + 8, (int)entry.getLength());
-            currentPos += (int)entry.getLength();
-            realSize += (int)entry.getLength();
-        } else {
+        boolean copied = copyTable(in, "hhea");
+        if (!copied) {
             throw new IOException("Can't find hhea table");
         }
     }
@@ -354,30 +315,22 @@ public class TTFSubSetFile extends TTFFi
      * Create the glyf table and fill in loca table
      */
     private void createGlyf(FontFileReader in,
-                            Map glyphs) throws IOException {
+                            Map<Integer, Integer> glyphs) throws IOException {
         TTFDirTabEntry entry = (TTFDirTabEntry)dirTabs.get("glyf");
         int size = 0;
-        int start = 0;
+        int startPos = 0;
         int endOffset = 0;    // Store this as the last loca
         if (entry != null) {
             pad4();
-            start = currentPos;
+            startPos = currentPos;
 
             /* Loca table must be in order by glyph index, so build
              * an array first and then write the glyph info and
              * location offset.
              */
-            int[] origIndexes = new int[glyphs.size()];
-
-            Iterator e = glyphs.keySet().iterator();
-            while (e.hasNext()) {
-                Integer origIndex = (Integer)e.next();
-                Integer subsetIndex = (Integer)glyphs.get(origIndex);
-                origIndexes[subsetIndex.intValue()] = origIndex.intValue();
-            }
+            int[] origIndexes = buildSubsetIndexToOrigIndexMap(glyphs);
 
             for (int i = 0; i < origIndexes.length; i++) {
-                int glyphLength = 0;
                 int nextOffset = 0;
                 int origGlyphIndex = origIndexes[i];
                 if (origGlyphIndex >= (mtxTab.length - 1)) {
@@ -385,32 +338,38 @@ public class TTFSubSetFile extends TTFFi
                 } else {
                     nextOffset = (int)mtxTab[origGlyphIndex + 1].getOffset();
                 }
-                glyphLength = nextOffset - 
(int)mtxTab[origGlyphIndex].getOffset();
+                int glyphOffset = (int)mtxTab[origGlyphIndex].getOffset();
+                int glyphLength = nextOffset - glyphOffset;
 
+                byte[] glyphData = in.getBytes(
+                        (int)entry.getOffset() + glyphOffset,
+                        glyphLength);
+                int endOffset1 = endOffset;
                 // Copy glyph
                 System.arraycopy(
-                    in.getBytes((int)entry.getOffset() + 
(int)mtxTab[origGlyphIndex].getOffset(),
-                        glyphLength), 0,
+                    glyphData, 0,
                     output, currentPos,
                     glyphLength);
 
 
                 // Update loca table
-                writeULong(locaOffset + i * 4, currentPos - start);
-                if ((currentPos - start + glyphLength) > endOffset) {
-                    endOffset = (currentPos - start + glyphLength);
+                writeULong(locaOffset + i * 4, currentPos - startPos);
+                if ((currentPos - startPos + glyphLength) > endOffset1) {
+                    endOffset1 = (currentPos - startPos + glyphLength);
                 }
 
                 currentPos += glyphLength;
                 realSize += glyphLength;
 
+                endOffset = endOffset1;
+
             }
 
-            size = currentPos - start;
+            size = currentPos - startPos;
 
-            int checksum = getCheckSum(start, size);
+            int checksum = getCheckSum(startPos, size);
             writeULong(glyfDirOffset, checksum);
-            writeULong(glyfDirOffset + 4, start);
+            writeULong(glyfDirOffset + 4, startPos);
             writeULong(glyfDirOffset + 8, size);
             currentPos += 12;
             realSize += 12;
@@ -425,6 +384,15 @@ public class TTFSubSetFile extends TTFFi
         }
     }
 
+    private int[] buildSubsetIndexToOrigIndexMap(Map<Integer, Integer> glyphs) 
{
+        int[] origIndexes = new int[glyphs.size()];
+        for (Map.Entry<Integer, Integer> glyph : glyphs.entrySet()) {
+            int origIndex = glyph.getKey();
+            int subsetIndex = glyph.getValue();
+            origIndexes[subsetIndex] = origIndex;
+        }
+        return origIndexes;
+    }
 
     /**
      * Create the hmtx table by copying metrics from original
@@ -433,7 +401,7 @@ public class TTFSubSetFile extends TTFFi
      * metric (key) to the subset metric (value)
      */
     private void createHmtx(FontFileReader in,
-                            Map glyphs) throws IOException {
+                            Map<Integer, Integer> glyphs) throws IOException {
         TTFDirTabEntry entry = (TTFDirTabEntry)dirTabs.get("hmtx");
 
         int longHorMetricSize = glyphs.size() * 2;
@@ -443,10 +411,9 @@ public class TTFSubSetFile extends TTFFi
         if (entry != null) {
             pad4();
             //int offset = (int)entry.offset;
-            Iterator e = glyphs.keySet().iterator();
-            while (e.hasNext()) {
-                Integer origIndex = (Integer)e.next();
-                Integer subsetIndex = (Integer)glyphs.get(origIndex);
+            for (Map.Entry<Integer, Integer> glyph : glyphs.entrySet()) {
+                Integer origIndex = glyph.getKey();
+                Integer subsetIndex = glyph.getValue();
 
                 writeUShort(currentPos + subsetIndex.intValue() * 4,
                             mtxTab[origIndex.intValue()].getWx());
@@ -469,9 +436,9 @@ public class TTFSubSetFile extends TTFFi
      * Returns a List containing the glyph itself plus all glyphs
      * that this composite glyph uses
      */
-    private List getIncludedGlyphs(FontFileReader in, int glyphOffset,
+    private List<Integer> getIncludedGlyphs(FontFileReader in, int glyphOffset,
                                      Integer glyphIdx) throws IOException {
-        List ret = new java.util.ArrayList();
+        List<Integer> ret = new java.util.ArrayList<Integer>();
         ret.add(glyphIdx);
         int offset = glyphOffset + 
(int)mtxTab[glyphIdx.intValue()].getOffset() + 10;
         Integer compositeIdx = null;
@@ -479,7 +446,7 @@ public class TTFSubSetFile extends TTFFi
         boolean moreComposites = true;
         while (moreComposites) {
             flags = in.readTTFUShort(offset);
-            compositeIdx = new Integer(in.readTTFUShort(offset + 2));
+            compositeIdx = Integer.valueOf(in.readTTFUShort(offset + 2));
             ret.add(compositeIdx);
 
             offset += 4;
@@ -513,7 +480,7 @@ public class TTFSubSetFile extends TTFFi
      * Rewrite all compositepointers in glyphindex glyphIdx
      *
      */
-    private void remapComposite(FontFileReader in, Map glyphs,
+    private void remapComposite(FontFileReader in, Map<Integer, Integer> 
glyphs,
                                 int glyphOffset,
                                 Integer glyphIdx) throws IOException {
         int offset = glyphOffset + (int)mtxTab[glyphIdx.intValue()].getOffset()
@@ -525,8 +492,8 @@ public class TTFSubSetFile extends TTFFi
 
         while (moreComposites) {
             flags = in.readTTFUShort(offset);
-            compositeIdx = new Integer(in.readTTFUShort(offset + 2));
-            Integer newIdx = (Integer)glyphs.get(compositeIdx);
+            compositeIdx = Integer.valueOf(in.readTTFUShort(offset + 2));
+            Integer newIdx = glyphs.get(compositeIdx);
             if (newIdx == null) {
                 // This errormessage would look much better
                 // if the fontname was printed to
@@ -572,40 +539,35 @@ public class TTFSubSetFile extends TTFFi
      * mapping
      */
     private void scanGlyphs(FontFileReader in,
-                            Map glyphs) throws IOException {
+                            Map<Integer, Integer> glyphs) throws IOException {
         TTFDirTabEntry entry = (TTFDirTabEntry)dirTabs.get("glyf");
-        Map newComposites = null;
-        Map allComposites = new java.util.HashMap();
+        Map<Integer, Integer> newComposites = null;
+        Map<Integer, Integer> allComposites = new java.util.HashMap<Integer, 
Integer>();
 
         int newIndex = glyphs.size();
 
         if (entry != null) {
             while (newComposites == null || newComposites.size() > 0) {
                 // Inefficient to iterate through all glyphs
-                newComposites = new java.util.HashMap();
-
-                Iterator e = glyphs.keySet().iterator();
-                while (e.hasNext()) {
-                    Integer origIndex = (Integer)e.next();
+                newComposites = new java.util.HashMap<Integer, Integer>();
 
+                for (Map.Entry<Integer, Integer> glyph : glyphs.entrySet()) {
+                    int origIndex = glyph.getKey();
                     if (in.readTTFShort(entry.getOffset()
-                                        + 
mtxTab[origIndex.intValue()].getOffset()) < 0) {
+                                        + mtxTab[origIndex].getOffset()) < 0) {
                         // origIndex is a composite glyph
-                        allComposites.put(origIndex, glyphs.get(origIndex));
-                        List composites
+                        allComposites.put(origIndex, glyph.getValue());
+                        List<Integer> composites
                             = getIncludedGlyphs(in, (int)entry.getOffset(),
                                               origIndex);
 
                         // Iterate through all composites pointed to
                         // by this composite and check if they exists
                         // in the glyphs map, add them if not.
-                        Iterator cps = composites.iterator();
-                        while (cps.hasNext()) {
-                            Integer cIdx = (Integer)cps.next();
+                        for (Integer cIdx : composites) {
                             if (glyphs.get(cIdx) == null
                                     && newComposites.get(cIdx) == null) {
-                                newComposites.put(cIdx,
-                                                  new Integer(newIndex));
+                                newComposites.put(cIdx, newIndex);
                                 newIndex++;
                             }
                         }
@@ -613,18 +575,15 @@ public class TTFSubSetFile extends TTFFi
                 }
 
                 // Add composites to glyphs
-                Iterator m = newComposites.keySet().iterator();
-                while (m.hasNext()) {
-                    Integer im = (Integer)m.next();
-                    glyphs.put(im, newComposites.get(im));
+                for (Map.Entry<Integer, Integer> im : 
newComposites.entrySet()) {
+                    glyphs.put(im.getKey(), im.getValue());
                 }
             }
 
             // Iterate through all composites to remap their composite index
-            Iterator ce = allComposites.keySet().iterator();
-            while (ce.hasNext()) {
+            for (Integer idx : allComposites.keySet()) {
                 remapComposite(in, glyphs, (int)entry.getOffset(),
-                               (Integer)ce.next());
+                               idx);
             }
 
         } else {
@@ -653,7 +612,7 @@ public class TTFSubSetFile extends TTFFi
         }
 
         //Copy the Map as we're going to modify it
-        Map subsetGlyphs = new java.util.HashMap(glyphs);
+        Map<Integer, Integer> subsetGlyphs = new java.util.HashMap<Integer, 
Integer>(glyphs);
 
         output = new byte[in.getFileSize()];
 
@@ -666,7 +625,7 @@ public class TTFSubSetFile extends TTFFi
 
         scanGlyphs(in, subsetGlyphs);
 
-        createDirectory();                // Create the TrueType header and 
directory
+        createDirectory(OperatingMode.PDF);     // Create the TrueType header 
and directory
 
         createHead(in);
         createHhea(in, subsetGlyphs.size());    // Create the hhea table
@@ -705,6 +664,121 @@ public class TTFSubSetFile extends TTFFi
     }
 
     /**
+     * Returns a subset of the original font suitable for use in PostScript 
programs.
+     *
+     * @param in FontFileReader to read from
+     * @param name Name to be checked for in the font file
+     * @param glyphs Map of glyphs (glyphs has old index as (Integer) key and
+     * new index as (Integer) value)
+     * @param glyphHandler the handler to receive all glyphs of the subset
+     * @return A subset of the original font
+     * @throws IOException in case of an I/O problem
+     */
+    public byte[] toPostScriptSubset(FontFileReader in, String name,
+                           Map glyphs, GlyphHandler glyphHandler) throws 
IOException {
+
+        //Check if TrueType collection, and that the name exists in the 
collection
+        if (!checkTTC(in, name)) {
+            throw new IOException("Failed to read font");
+        }
+
+        //Copy the Map as we're going to modify it
+        Map<Integer, Integer> subsetGlyphs = new java.util.HashMap(glyphs);
+
+        output = new byte[in.getFileSize()];
+
+        readDirTabs(in);
+        readFontHeader(in);
+        getNumGlyphs(in);
+        readHorizontalHeader(in);
+        readHorizontalMetrics(in);
+        readIndexToLocation(in);
+
+        scanGlyphs(in, subsetGlyphs);
+
+        // Create the TrueType header and directory
+        createDirectory(OperatingMode.POSTSCRIPT_GLYPH_DIRECTORY);
+
+        createHead(in);
+        createHhea(in, subsetGlyphs.size());    // Create the hhea table
+        createHmtx(in, subsetGlyphs);           // Create hmtx table
+        createMaxp(in, subsetGlyphs.size());    // copy the maxp table
+
+        boolean optionalTableFound;
+        optionalTableFound = createCvt(in);    // copy the cvt table
+        if (!optionalTableFound) {
+            // cvt is optional (used in TrueType fonts only)
+            log.debug("TrueType: ctv table not present. Skipped.");
+        }
+
+        optionalTableFound = createFpgm(in);    // copy fpgm table
+        if (!optionalTableFound) {
+            // fpgm is optional (used in TrueType fonts only)
+            log.debug("TrueType: fpgm table not present. Skipped.");
+        }
+
+        optionalTableFound = createPrep(in);    // copy prep table
+        if (!optionalTableFound) {
+            // prep is optional (used in TrueType fonts only)
+            log.debug("TrueType: prep table not present. Skipped.");
+        }
+
+        //Send all the glyphs from the subset
+        handleGlyphSubset(in, subsetGlyphs, glyphHandler);
+
+        pad4();
+        createCheckSumAdjustment();
+
+        byte[] ret = new byte[realSize];
+        System.arraycopy(output, 0, ret, 0, realSize);
+
+        return ret;
+    }
+
+    private void handleGlyphSubset(FontFileReader in, Map<Integer, Integer> 
glyphs,
+            GlyphHandler glyphHandler) throws IOException {
+        TTFDirTabEntry entry = (TTFDirTabEntry)dirTabs.get("glyf");
+        if (entry != null) {
+
+            int[] origIndexes = buildSubsetIndexToOrigIndexMap(glyphs);
+
+            for (int i = 0; i < origIndexes.length; i++) {
+                int nextOffset = 0;
+                int origGlyphIndex = origIndexes[i];
+                if (origGlyphIndex >= (mtxTab.length - 1)) {
+                    nextOffset = (int)lastLoca;
+                } else {
+                    nextOffset = (int)mtxTab[origGlyphIndex + 1].getOffset();
+                }
+                int glyphOffset = (int)mtxTab[origGlyphIndex].getOffset();
+                int glyphLength = nextOffset - glyphOffset;
+
+                byte[] glyphData = in.getBytes(
+                        (int)entry.getOffset() + glyphOffset,
+                        glyphLength);
+
+                glyphHandler.addGlyph(glyphData);
+            }
+        } else {
+            throw new IOException("Can't find glyf table");
+        }
+    }
+
+    /**
+     * Used as callback to handle a number of glyphs.
+     */
+    public static interface GlyphHandler {
+
+        /**
+         * Adds a glyph.
+         * @param glyphData the glyph data
+         * @throws IOException if an I/O error occurs
+         */
+        void addGlyph(byte[] glyphData) throws IOException;
+
+    }
+
+    /**
      * writes a ISO-8859-1 string at the currentPosition
      * updates currentPosition but not realSize
      * @return number of bytes written
@@ -839,10 +913,10 @@ public class TTFSubSetFile extends TTFFi
 
 
     private int getCheckSum(int start, int size) {
-        return (int)getLongCheckSum(start, size);
+        return (int)getLongCheckSum(output, start, size);
     }
 
-    private long getLongCheckSum(int start, int size) {
+    private static long getLongCheckSum(byte[] data, int start, int size) {
         // All the tables here are aligned on four byte boundaries
         // Add remainder to size if it's not a multiple of 4
         int remainder = size % 4;
@@ -853,10 +927,10 @@ public class TTFSubSetFile extends TTFFi
         long sum = 0;
 
         for (int i = 0; i < size; i += 4) {
-            int l = (int)(output[start + i] << 24);
-            l += (int)(output[start + i + 1] << 16);
-            l += (int)(output[start + i + 2] << 16);
-            l += (int)(output[start + i + 3] << 16);
+            int l = (int)(data[start + i] << 24);
+            l += (int)(data[start + i + 1] << 16);
+            l += (int)(data[start + i + 2] << 16);
+            l += (int)(data[start + i + 3] << 16);
             sum += l;
             if (sum > 0xffffffff) {
                 sum = sum - 0xffffffff;
@@ -867,7 +941,7 @@ public class TTFSubSetFile extends TTFFi
     }
 
     private void createCheckSumAdjustment() {
-        long sum = getLongCheckSum(0, realSize);
+        long sum = getLongCheckSum(output, 0, realSize);
         int checksum = (int)(0xb1b0afba - sum);
         writeULong(checkSumAdjustmentOffset, checksum);
     }

Modified: 
xmlgraphics/fop/branches/Temp_TrueTypeInPostScript/src/java/org/apache/fop/render/ps/PSFontUtils.java
URL: 
http://svn.apache.org/viewvc/xmlgraphics/fop/branches/Temp_TrueTypeInPostScript/src/java/org/apache/fop/render/ps/PSFontUtils.java?rev=1034094&r1=1034093&r2=1034094&view=diff
==============================================================================
--- 
xmlgraphics/fop/branches/Temp_TrueTypeInPostScript/src/java/org/apache/fop/render/ps/PSFontUtils.java
 (original)
+++ 
xmlgraphics/fop/branches/Temp_TrueTypeInPostScript/src/java/org/apache/fop/render/ps/PSFontUtils.java
 Thu Nov 11 20:03:43 2010
@@ -43,6 +43,7 @@ import org.apache.xmlgraphics.ps.dsc.Res
 import org.apache.xmlgraphics.util.io.ASCIIHexOutputStream;
 
 import org.apache.fop.fonts.Base14Font;
+import org.apache.fop.fonts.CIDFontType;
 import org.apache.fop.fonts.CIDSubset;
 import org.apache.fop.fonts.CustomFont;
 import org.apache.fop.fonts.Font;
@@ -243,7 +244,8 @@ public class PSFontUtils extends org.apa
                                  */
                                 gen.includeProcsetCIDInitResource();
                             }
-                            PSResource cidFontResource = embedCIDFont(gen, 
(MultiByteFont) tf, in);
+                            PSResource cidFontResource = embedType2CIDFont(gen,
+                                    (MultiByteFont) tf, in);
                             fontResource = 
PSFontResource.createFontResource(fontRes,
                                     gen.getProcsetCIDInitResource(),
                                     gen.getIdentityHCMapResource(),
@@ -311,12 +313,12 @@ public class PSFontUtils extends org.apa
         gen.writeln("/FontType 42 def");
         gen.writeln("/Encoding 256 array");
         gen.writeln("0 1 255{1 index exch/.notdef put}for");
-        Set glyphs = null;
+        Set<String> glyphs = null;
         if (font.getFontType() == FontType.TYPE0) {
             //"/Encoding" is required but ignored for CID fonts
             //so we keep it minimal to save space
         } else {
-            glyphs = new java.util.HashSet();
+            glyphs = new java.util.HashSet<String>();
             for (int i = 0; i < Glyphs.WINANSI_ENCODING.length; i++) {
                 gen.write("dup ");
                 gen.write(i);
@@ -355,16 +357,14 @@ public class PSFontUtils extends org.apa
         }
         gen.writeln("]def");
         gen.write("/CharStrings ");
-        gen.write(1);
-        //gen.write(glyphs.size() + 1);
+        gen.write(glyphs != null ? glyphs.size() + 1 : 1);
         gen.writeln(" dict dup begin");
         gen.write("/");
         gen.write(Glyphs.NOTDEF);
-        gen.writeln(" 0 def"); // TODO always glyph index 0?
-        // TODO ugly and temporary, until CID is implemented
+        gen.writeln(" 0 def"); // .notdef always has to be at index 0
         if (glyphs != null) {
-            for (Iterator iter = glyphs.iterator(); iter.hasNext();) {
-                String glyphName = (String) iter.next();
+            //Only performed in singly-byte mode
+            for (String glyphName : glyphs) {
                 gen.write("/");
                 gen.write(glyphName);
                 gen.write(" ");
@@ -389,8 +389,8 @@ public class PSFontUtils extends org.apa
         return 0;
     }
 
-    private static void composeType0Font(PSGenerator gen, MultiByteFont font, 
InputStream fontStream)
-            throws IOException {
+    private static void composeType0Font(PSGenerator gen, MultiByteFont font,
+            InputStream fontStream) throws IOException {
         String psName = font.getEmbedFontName();
         gen.write("/");
         gen.write(psName);
@@ -399,14 +399,9 @@ public class PSFontUtils extends org.apa
         gen.writeln("] composefont pop");
     }
 
-    private static PSResource embedCIDFont(PSGenerator gen,
+    private static PSResource embedType2CIDFont(final PSGenerator gen,
             MultiByteFont font, InputStream fontStream) throws IOException {
-        FontFileReader reader = new FontFileReader(fontStream);
-
-        TTFSubSetFile subset = new TTFSubSetFile();
-        byte[] subsetFont = subset.readFont(reader,
-                             font.getTTCName(), font.getUsedGlyphs());
-        InputStream subsetInput = new java.io.ByteArrayInputStream(subsetFont);
+        assert font.getCIDType() == CIDFontType.CIDTYPE2;
 
         String psName = font.getEmbedFontName();
         gen.write("%%BeginResource: CIDFont ");
@@ -467,6 +462,25 @@ public class PSFontUtils extends org.apa
             gen.write(gid);
         }
         gen.writeln(">] def");
+
+        //Create tables for subset
+        TTFSubSetFile subset = new TTFSubSetFile();
+        TTFSubSetFile.GlyphHandler glyphHandler = new 
TTFSubSetFile.GlyphHandler() {
+
+            public void addGlyph(byte[] glyphData) throws IOException {
+                ASCIIHexOutputStream hexOut = new 
ASCIIHexOutputStream(gen.getOutputStream());
+                gen.writeln("<");
+                hexOut.write(glyphData);
+                gen.writeln(">");
+            }
+        };
+        gen.writeln("/GlyphDirectory [");
+        FontFileReader reader = new FontFileReader(fontStream);
+        byte[] subsetFont = subset.toPostScriptSubset(reader,
+                             font.getTTCName(), font.getUsedGlyphs(), 
glyphHandler);
+        gen.writeln("] def");
+
+        InputStream subsetInput = new java.io.ByteArrayInputStream(subsetFont);
         createType42DictionaryEntries(gen, font, subsetInput, 
Collections.EMPTY_LIST);
         gen.writeln("CIDFontName currentdict end /CIDFont defineresource pop");
         gen.writeln("end");



---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to