You are viewing a plain text version of this content. The canonical link for it is here.
Posted to fop-commits@xmlgraphics.apache.org by ss...@apache.org on 2015/12/02 15:16:54 UTC

svn commit: r1717631 - in /xmlgraphics/fop-pdf-images/trunk: src/java/org/apache/fop/render/pdf/pdfbox/ test/java/org/apache/fop/render/pdf/

Author: ssteiner
Date: Wed Dec  2 14:16:54 2015
New Revision: 1717631

URL: http://svn.apache.org/viewvc?rev=1717631&view=rev
Log:
FOP-2546: ArrayIndexOutOfBoundsException merging fonts

Modified:
    xmlgraphics/fop-pdf-images/trunk/src/java/org/apache/fop/render/pdf/pdfbox/FOPPDFSingleByteFont.java
    xmlgraphics/fop-pdf-images/trunk/src/java/org/apache/fop/render/pdf/pdfbox/MergeCFFFonts.java
    xmlgraphics/fop-pdf-images/trunk/src/java/org/apache/fop/render/pdf/pdfbox/MergeTTFonts.java
    xmlgraphics/fop-pdf-images/trunk/test/java/org/apache/fop/render/pdf/PDFBoxAdapterTestCase.java

Modified: xmlgraphics/fop-pdf-images/trunk/src/java/org/apache/fop/render/pdf/pdfbox/FOPPDFSingleByteFont.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop-pdf-images/trunk/src/java/org/apache/fop/render/pdf/pdfbox/FOPPDFSingleByteFont.java?rev=1717631&r1=1717630&r2=1717631&view=diff
==============================================================================
--- xmlgraphics/fop-pdf-images/trunk/src/java/org/apache/fop/render/pdf/pdfbox/FOPPDFSingleByteFont.java (original)
+++ xmlgraphics/fop-pdf-images/trunk/src/java/org/apache/fop/render/pdf/pdfbox/FOPPDFSingleByteFont.java Wed Dec  2 14:16:54 2015
@@ -37,7 +37,6 @@ import org.apache.pdfbox.cos.COSBase;
 import org.apache.pdfbox.cos.COSDictionary;
 import org.apache.pdfbox.cos.COSName;
 import org.apache.pdfbox.cos.COSNumber;
-import org.apache.pdfbox.encoding.DictionaryEncoding;
 import org.apache.pdfbox.encoding.Encoding;
 import org.apache.pdfbox.encoding.EncodingManager;
 import org.apache.pdfbox.pdmodel.common.PDStream;
@@ -61,7 +60,7 @@ public class FOPPDFSingleByteFont extend
     protected Map<String, Integer> charMapGlobal = new LinkedHashMap<String, Integer>();
     private Map<Integer, Integer> newWidth = new HashMap<Integer, Integer>();
     private Map<String, byte[]> charStringsDict;
-    private MergeTTFonts.Cmap newCmap = new MergeTTFonts.Cmap();
+    private List<MergeTTFonts.Cmap> newCmap = new ArrayList<MergeTTFonts.Cmap>();
     private Map<Integer, String> encodingMap = new TreeMap<Integer, String>();
     private int encodingSkip;
     private MergeTTFonts mergeTTFonts = new MergeTTFonts();
@@ -183,18 +182,27 @@ public class FOPPDFSingleByteFont extend
             TrueTypeFont ttfont = ((PDTrueTypeFont) font).getTTFFont();
             CMAPEncodingEntry[] cmapList = ttfont.getCMAP().getCmaps();
             for (CMAPEncodingEntry c : cmapList) {
-                newCmap.platformId = c.getPlatformId();
-                newCmap.platformEncodingId = c.getPlatformEncodingId();
+                MergeTTFonts.Cmap tempCmap = getNewCmap(c.getPlatformId(), c.getPlatformEncodingId());
                 for (int i = 0; i < 256 * 256; i++) {
                     if (c.getGlyphId(i) != 0) {
-                        newCmap.glyphIdToCharacterCode.put(i, c.getGlyphId(i));
+                        tempCmap.glyphIdToCharacterCode.put(i, c.getGlyphId(i));
                     }
                 }
+                newCmap.add(tempCmap);
             }
             FOPPDFMultiByteFont.mergeMaxp(ttfont, mergeTTFonts.maxp);
         }
     }
 
+    private MergeTTFonts.Cmap getNewCmap(int platformID, int platformEncodingID) {
+        for (MergeTTFonts.Cmap cmap : newCmap) {
+            if (cmap.platformId == platformID && cmap.platformEncodingId == platformEncodingID) {
+                return cmap;
+            }
+        }
+        return new MergeTTFonts.Cmap(platformID, platformEncodingID);
+    }
+
     @Override
     public boolean hasChar(char c) {
         return charMapGlobal.containsKey(String.valueOf(c));
@@ -329,10 +337,7 @@ public class FOPPDFSingleByteFont extend
             return c.lookup(i, size);
         }
         Encoding enc = (Encoding)cmap;
-        if (enc instanceof DictionaryEncoding) {
-            return enc.getName(i);
-        }
-        return enc.getCharacter(i);
+        return enc.getName(i);
     }
 
     public String getEncodingName() {
@@ -360,7 +365,7 @@ public class FOPPDFSingleByteFont extend
         for (int i = fontForEnc.getFirstChar(); i <= fontForEnc.getLastChar(); i++) {
             if (codeToName.keySet().contains(i)) {
                 String s = codeToName.get(i);
-                if (!added.contains(s)) {
+                if (!added.contains(s) || (added.contains(s) && !encodingMap.containsKey(i))) {
                     if (!encodingMap.containsKey(i)) {
                         encodingMap.put(i, s);
                     } else {

Modified: xmlgraphics/fop-pdf-images/trunk/src/java/org/apache/fop/render/pdf/pdfbox/MergeCFFFonts.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop-pdf-images/trunk/src/java/org/apache/fop/render/pdf/pdfbox/MergeCFFFonts.java?rev=1717631&r1=1717630&r2=1717631&view=diff
==============================================================================
--- xmlgraphics/fop-pdf-images/trunk/src/java/org/apache/fop/render/pdf/pdfbox/MergeCFFFonts.java (original)
+++ xmlgraphics/fop-pdf-images/trunk/src/java/org/apache/fop/render/pdf/pdfbox/MergeCFFFonts.java Wed Dec  2 14:16:54 2015
@@ -49,9 +49,7 @@ public class MergeCFFFonts extends OTFSu
     private List<Integer> chars = new ArrayList<Integer>();
     private List<String> added = new ArrayList<String>();
     private Map<Integer, Integer> range = new LinkedHashMap<Integer, Integer>();
-    private Set<String> stringsForRange = new HashSet<String>();
     private int noOfFonts;
-    private CFFEncoding encoding = null;
 
     public MergeCFFFonts() throws IOException {
         gidToSID = new LinkedHashMap<Integer, Integer>();
@@ -63,23 +61,24 @@ public class MergeCFFFonts extends OTFSu
         FontFileReader fontFile = new FontFileReader(stream);
         CFFParser p = new CFFParser();
         CFFFont ff = p.parse(fontFile.getAllBytes()).get(0);
-        if (used.containsAll(ff.getCharStringsDict().keySet())) {
+
+        if (used.containsAll(getStrings(ff).keySet())) {
             return;
         }
         fontFileSize += fontFile.getFileSize();
         this.fontFile = fontFile;
-        used.addAll(ff.getCharStringsDict().keySet());
+        used.addAll(getStrings(ff).keySet());
         if (fileFont == null) {
             fileFont = ff;
         }
         LinkedHashMap<Integer, Integer> sg = new LinkedHashMap<Integer, Integer>();
-        for (int i = 0; i < ff.getCharset().getEntries().size() + 1; i++) {
+        for (int i = 0; i < ff.getCharStringsDict().size() + 1; i++) {
             sg.put(i, i);
         }
         subsetGlyphsList.add(sg);
         cffReader = new CFFDataReader(fontFile);
-        for (CFFCharset.Entry e : ff.getCharset().getEntries()) {
-            int sid = e.getSID();
+
+        for (int sid : getSids(ff.getCharset())) {
             if (sid >= NUM_STANDARD_STRINGS) {
                 int index = sid - NUM_STANDARD_STRINGS;
                 if (index <= cffReader.getStringIndex().getNumObjects()) {
@@ -91,36 +90,18 @@ public class MergeCFFFonts extends OTFSu
             }
         }
 
-        encoding = ff.getEncoding();
+        CFFEncoding encoding = ff.getEncoding();
         if (!(encoding instanceof CFFStandardEncoding)) {
             for (CFFEncoding.Entry e : encoding.getEntries()) {
                 int c = e.getCode();
-                if (!chars.contains(c)) {
+                if (!chars.contains(c) && c != 0) {
                     chars.add(c);
                 }
             }
         }
+        setupMapping(ff.getCharset(), sg);
 
-        int subsetGlyphIndex = 0;
-        for (CFFCharset.Entry e : ff.getCharset().getEntries()) {
-            int sid = e.getSID();
-            int gid = sg.get(subsetGlyphIndex);
-
-            //Check whether the SID falls into the standard string set
-            if (sid < NUM_STANDARD_STRINGS) {
-                gidToSID.put(sg.get(gid), sid);
-            } else {
-                int index = sid - NUM_STANDARD_STRINGS;
-                if (index <= cffReader.getStringIndex().getNumObjects()) {
-                    gidToSID.put(sg.get(gid), stringIndexData.size() + NUM_STANDARD_STRINGS - 1);
-                } else {
-                    gidToSID.put(sg.get(gid), index);
-                }
-            }
-            subsetGlyphIndex++;
-        }
-
-        for (Map.Entry<String, byte[]> s : ff.getCharStringsDict().entrySet()) {
+        for (Map.Entry<String, byte[]> s : getStrings(ff).entrySet()) {
             if (!added.contains(s.getKey())) {
                 subsetCharStringsIndex.add(s.getValue());
                 added.add(s.getKey());
@@ -131,16 +112,49 @@ public class MergeCFFFonts extends OTFSu
         String cClass = cSet.getClass().getName();
         if (cClass.equals("org.apache.fontbox.cff.CFFParser$Format1Charset")
                 || cClass.equals("org.apache.fontbox.cff.CFFParser$Format0Charset")) {
-            for (CFFCharset.Entry m : cSet.getEntries()) {
-                if (!stringsForRange.contains(m.getName())) {
-                    range.put(m.getSID(), 0);
-                    stringsForRange.add(m.getName());
-                }
+            for (int sid : getSids(cSet)) {
+                range.put(sid, 0);
             }
         }
         noOfFonts++;
     }
 
+    private void setupMapping(CFFCharset charset, LinkedHashMap<Integer, Integer> sg) {
+        int subsetGlyphIndex = 0;
+        for (int sid : getSids(charset)) {
+            if (sg.containsKey(subsetGlyphIndex)) {
+                int gid = sg.get(subsetGlyphIndex);
+
+                //Check whether the SID falls into the standard string set
+                if (sid < NUM_STANDARD_STRINGS) {
+                    gidToSID.put(sg.get(gid), sid);
+                } else {
+                    int index = sid - NUM_STANDARD_STRINGS;
+                    if (index <= cffReader.getStringIndex().getNumObjects()) {
+                        gidToSID.put(sg.get(gid), stringIndexData.size() + NUM_STANDARD_STRINGS - 1);
+                    } else {
+                        gidToSID.put(sg.get(gid), index);
+                    }
+                }
+                subsetGlyphIndex++;
+            }
+        }
+    }
+
+    public static List<Integer> getSids(CFFCharset cSet) {
+        List<Integer> sids = new ArrayList<Integer>();
+        for (CFFCharset.Entry x : cSet.getEntries()) {
+            if (x.getSID() != 0) {
+                sids.add(x.getSID());
+            }
+        }
+        return sids;
+    }
+
+    public static Map<String, byte[]> getStrings(CFFFont ff) throws IOException {
+        return ff.getCharStringsDict();
+    }
+
     public void writeFont() throws IOException {
         output = new byte[fontFileSize * 2];
         if (noOfFonts == 1) {
@@ -260,26 +274,6 @@ public class MergeCFFFonts extends OTFSu
     }
 
     protected void writeEncoding() throws IOException {
-        if (encoding instanceof CFFStandardEncoding) {
-            LinkedHashMap<String, CFFDataReader.DICTEntry> topDICT = cffReader.getTopDictEntries();
-            final CFFDataReader.DICTEntry encodingEntry = topDICT.get("Encoding");
-            if (encodingEntry != null && encodingEntry.getOperands().get(0).intValue() != 0
-                    && encodingEntry.getOperands().get(0).intValue() != 1) {
-                int len = encoding.getEntries().size();
-                if (len != gidToSID.size() - 1) {
-                    return;
-                }
-                writeByte(0);
-                writeByte(len);
-                for (Map.Entry<Integer, Integer> gid : gidToSID.entrySet()) {
-                    if (gid.getKey() == 0) {
-                        continue;
-                    }
-                    int code = encoding.getCode(gid.getValue());
-                    writeByte(code);
-                }
-            }
-        }
         if (!chars.isEmpty()) {
             writeCard16(chars.size());
             for (int i : chars) {
@@ -289,6 +283,7 @@ public class MergeCFFFonts extends OTFSu
     }
 
     protected void writeStringIndex() throws IOException {
+        int stringIndexSize = stringIndexData.size();
         for (String s : strings) {
             stringIndexData.add(s.getBytes("US-ASCII"));
         }
@@ -296,8 +291,10 @@ public class MergeCFFFonts extends OTFSu
         //Write the String Index
         if (!stringIndexData.isEmpty()) {
             if (!strings.isEmpty() && !new String(stringIndexData.get(0), "UTF-8").equals(strings.get(0))) {
-                //Move copyright string to end
-                stringIndexData.add(stringIndexData.remove(0));
+                //Keep strings in order as they are referenced from the TopDICT
+                for (int i = 0; i < stringIndexSize; i++) {
+                    stringIndexData.add(stringIndexData.remove(0));
+                }
             } else {
                 String notice = (String)fileFont.getProperty("Notice");
                 if (notice != null && !(fileFont instanceof CFFFontROS)) {

Modified: xmlgraphics/fop-pdf-images/trunk/src/java/org/apache/fop/render/pdf/pdfbox/MergeTTFonts.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop-pdf-images/trunk/src/java/org/apache/fop/render/pdf/pdfbox/MergeTTFonts.java?rev=1717631&r1=1717630&r2=1717631&view=diff
==============================================================================
--- xmlgraphics/fop-pdf-images/trunk/src/java/org/apache/fop/render/pdf/pdfbox/MergeTTFonts.java (original)
+++ xmlgraphics/fop-pdf-images/trunk/src/java/org/apache/fop/render/pdf/pdfbox/MergeTTFonts.java Wed Dec  2 14:16:54 2015
@@ -17,6 +17,7 @@
 package org.apache.fop.render.pdf.pdfbox;
 
 import java.io.IOException;
+import java.util.List;
 import java.util.Map;
 import java.util.TreeMap;
 
@@ -107,6 +108,9 @@ public class MergeTTFonts extends TTFSub
                 byte[] glyphData = gly.getValue().data;
                 int glyphLength = glyphData.length;
                 int i = gly.getKey();
+                if (i >= origIndexesLen) {
+                    continue;
+                }
                 int endOffset1 = endOffset;
                 // Copy glyph
                 writeBytes(glyphData);
@@ -261,7 +265,7 @@ public class MergeTTFonts extends TTFSub
         }
     }
 
-    public void writeFont(Cmap cmap) throws IOException {
+    public void writeFont(List<Cmap> cmap) throws IOException {
         output = new byte[size * 2];
         createDirectory();     // Create the TrueType header and directory
         int sgsize = added.size();
@@ -270,11 +274,7 @@ public class MergeTTFonts extends TTFSub
 //            copyTable(fontFile, OFTableName.CMAP);
         }
         createHmtx();           // Create hmtx table
-        if (cid || locaFormat == 1) {
-            createLoca(sgsize);    // create empty loca table
-        } else {
-            createLoca(numberOfGlyphs / 2);    // create empty loca table
-        }
+        createLoca(sgsize);    // create empty loca table
         createHead(fontFile);
         createOS2(fontFile);                          // copy the OS/2 table
         if (!cid) {
@@ -287,23 +287,10 @@ public class MergeTTFonts extends TTFSub
         } else {
             writeMaxp();
         }
-        boolean optionalTableFound;
-        optionalTableFound = createCvt(fontFile);    // copy the cvt table
-        if (!optionalTableFound) {
-            // cvt is optional (used in TrueType fonts only)
-            log.debug("TrueType: ctv table not present. Skipped.");
-        }
-        optionalTableFound = createFpgm(fontFile);    // copy fpgm table
-        if (!optionalTableFound) {
-            // fpgm is optional (used in TrueType fonts only)
-            log.debug("TrueType: fpgm table not present. Skipped.");
-        }
+        createCvt(fontFile);    // copy the cvt table
+        createFpgm(fontFile);    // copy fpgm table
         createPost(fontFile);                         // copy the post table
-        optionalTableFound = createPrep(fontFile);    // copy prep table
-        if (!optionalTableFound) {
-            // prep is optional (used in TrueType fonts only)
-            log.debug("TrueType: prep table not present. Skipped.");
-        }
+        createPrep(fontFile);    // copy prep table
         createName(fontFile);                         // copy the name table
         createGlyf(); //create glyf table and update loca table
         pad4();
@@ -334,35 +321,40 @@ public class MergeTTFonts extends TTFSub
         realSize += currentPos - startPos;
     }
 
-    private void writeCMAP(Cmap cmap) {
+    private void writeCMAP(List<Cmap> cmaps) {
         int checksum = currentPos;
         pad4();
         int cmapPos = currentPos;
         writeUShort(0); //version
-        writeUShort(1); //number of tables
-
-        Map<Integer, Integer> glyphIdToCharacterCode = cmap.glyphIdToCharacterCode;
-        writeUShort(cmap.platformId); //platformid
-        writeUShort(cmap.platformEncodingId); //platformEncodingId
-        writeULong(currentPos, currentPos - cmapPos + 12); //subTableOffset
-        currentPos += 12;
+        writeUShort(cmaps.size()); //number of tables
 
-        writeUShort(12); //subtableFormat
-        writeUShort(0);
-        writeULong(currentPos, (glyphIdToCharacterCode.size() * 12) + 16);
-        currentPos += 4;
-        writeULong(currentPos, 0);
-        currentPos += 4;
-        writeULong(currentPos, glyphIdToCharacterCode.size());
-        currentPos += 4;
+        int tablesSize = 8 * cmaps.size();
+        for (int i = 0; i < cmaps.size(); i++) {
+            Cmap cmap = cmaps.get(i);
+            writeUShort(cmap.platformId); //platformid
+            writeUShort(cmap.platformEncodingId); //platformEncodingId
+            writeULong(currentPos, 4 + tablesSize + getCmapOffset(cmaps, i)); //subTableOffset
+            currentPos += 4;
+        }
 
-        for (Map.Entry<Integer, Integer> g : glyphIdToCharacterCode.entrySet()) {
-            writeULong(currentPos, g.getKey());
+        for (Cmap cmap : cmaps) {
+            writeUShort(12); //subtableFormat
+            writeUShort(0);
+            writeULong(currentPos, (cmap.glyphIdToCharacterCode.size() * 12) + 16);
             currentPos += 4;
-            writeULong(currentPos, g.getKey());
+            writeULong(currentPos, 0);
             currentPos += 4;
-            writeULong(currentPos, g.getValue());
+            writeULong(currentPos, cmap.glyphIdToCharacterCode.size());
             currentPos += 4;
+
+            for (Map.Entry<Integer, Integer> g : cmap.glyphIdToCharacterCode.entrySet()) {
+                writeULong(currentPos, g.getKey());
+                currentPos += 4;
+                writeULong(currentPos, g.getKey());
+                currentPos += 4;
+                writeULong(currentPos, g.getValue());
+                currentPos += 4;
+            }
         }
 
 //            writeUShort(6); //subtableFormat
@@ -396,6 +388,15 @@ public class MergeTTFonts extends TTFSub
         realSize += currentPos - cmapPos;
     }
 
+    private int getCmapOffset(List<Cmap> cmaps, int index) {
+        int result = 0;
+        for (int i = 0; i < index; i++) {
+            Cmap curCmap = cmaps.get(i);
+            result += (curCmap.glyphIdToCharacterCode.size() * 12) + 16;
+        }
+        return result;
+    }
+
     /**
      * Get index from starting at lowest glyph position
      * @param glyphs map
@@ -421,5 +422,10 @@ public class MergeTTFonts extends TTFSub
         int platformId;
         int platformEncodingId;
         Map<Integer, Integer> glyphIdToCharacterCode = new TreeMap<Integer, Integer>();
+
+        public Cmap(int platformID, int platformEncodingID) {
+            this.platformId = platformID;
+            this.platformEncodingId = platformEncodingID;
+        }
     }
 }

Modified: xmlgraphics/fop-pdf-images/trunk/test/java/org/apache/fop/render/pdf/PDFBoxAdapterTestCase.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop-pdf-images/trunk/test/java/org/apache/fop/render/pdf/PDFBoxAdapterTestCase.java?rev=1717631&r1=1717630&r2=1717631&view=diff
==============================================================================
--- xmlgraphics/fop-pdf-images/trunk/test/java/org/apache/fop/render/pdf/PDFBoxAdapterTestCase.java (original)
+++ xmlgraphics/fop-pdf-images/trunk/test/java/org/apache/fop/render/pdf/PDFBoxAdapterTestCase.java Wed Dec  2 14:16:54 2015
@@ -284,7 +284,7 @@ public class PDFBoxAdapterTestCase {
         Assert.assertEquals(name, "TimesNewRomanPSMT_TrueType");
         Assert.assertEquals(mbfont.getFontName(), "TimesNewRomanPSMT_TrueType");
         byte[] is = IOUtils.toByteArray(mbfont.getInputStream());
-        Assert.assertEquals(is.length, 34264);
+        Assert.assertEquals(is.length, 41352);
         doc.close();
         doc2.close();
     }



---------------------------------------------------------------------
To unsubscribe, e-mail: fop-commits-unsubscribe@xmlgraphics.apache.org
For additional commands, e-mail: fop-commits-help@xmlgraphics.apache.org