Author: ssteiner
Date: Fri Sep 12 14:15:21 2014
New Revision: 1624558

URL: http://svn.apache.org/r1624558
Log:
FOP-2302: Merge PDF fonts, separate classes

Added:
    
xmlgraphics/fop-pdf-images/trunk/src/java/org/apache/fop/render/pdf/pdfbox/FOPPDFFont.java
   (with props)
    
xmlgraphics/fop-pdf-images/trunk/src/java/org/apache/fop/render/pdf/pdfbox/FOPPDFMultiByteFont.java
   (with props)
    
xmlgraphics/fop-pdf-images/trunk/src/java/org/apache/fop/render/pdf/pdfbox/FOPPDFSingleByteFont.java
   (with props)
    
xmlgraphics/fop-pdf-images/trunk/src/java/org/apache/fop/render/pdf/pdfbox/MergeFontsPDFWriter.java
   (with props)
    
xmlgraphics/fop-pdf-images/trunk/src/java/org/apache/fop/render/pdf/pdfbox/PDFWriter.java
   (with props)
Modified:
    
xmlgraphics/fop-pdf-images/trunk/src/java/org/apache/fop/render/pdf/pdfbox/MergeTTFonts.java
    
xmlgraphics/fop-pdf-images/trunk/src/java/org/apache/fop/render/pdf/pdfbox/PDFBoxAdapter.java
    
xmlgraphics/fop-pdf-images/trunk/test/java/org/apache/fop/render/pdf/PDFBoxAdapterTestCase.java

Added: 
xmlgraphics/fop-pdf-images/trunk/src/java/org/apache/fop/render/pdf/pdfbox/FOPPDFFont.java
URL: 
http://svn.apache.org/viewvc/xmlgraphics/fop-pdf-images/trunk/src/java/org/apache/fop/render/pdf/pdfbox/FOPPDFFont.java?rev=1624558&view=auto
==============================================================================
--- 
xmlgraphics/fop-pdf-images/trunk/src/java/org/apache/fop/render/pdf/pdfbox/FOPPDFFont.java
 (added)
+++ 
xmlgraphics/fop-pdf-images/trunk/src/java/org/apache/fop/render/pdf/pdfbox/FOPPDFFont.java
 Fri Sep 12 14:15:21 2014
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.fop.render.pdf.pdfbox;
+
+import java.io.IOException;
+
+import org.apache.pdfbox.cos.COSDictionary;
+
+import org.apache.fop.pdf.PDFDictionary;
+import org.apache.fop.pdf.RefPDFFont;
+
+interface FOPPDFFont extends RefPDFFont {
+    String getFontName();
+    void setRef(PDFDictionary d);
+    String addFont(COSDictionary fontdata) throws IOException;
+    int size();
+}

Propchange: 
xmlgraphics/fop-pdf-images/trunk/src/java/org/apache/fop/render/pdf/pdfbox/FOPPDFFont.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 
xmlgraphics/fop-pdf-images/trunk/src/java/org/apache/fop/render/pdf/pdfbox/FOPPDFMultiByteFont.java
URL: 
http://svn.apache.org/viewvc/xmlgraphics/fop-pdf-images/trunk/src/java/org/apache/fop/render/pdf/pdfbox/FOPPDFMultiByteFont.java?rev=1624558&view=auto
==============================================================================
--- 
xmlgraphics/fop-pdf-images/trunk/src/java/org/apache/fop/render/pdf/pdfbox/FOPPDFMultiByteFont.java
 (added)
+++ 
xmlgraphics/fop-pdf-images/trunk/src/java/org/apache/fop/render/pdf/pdfbox/FOPPDFMultiByteFont.java
 Fri Sep 12 14:15:21 2014
@@ -0,0 +1,351 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.fop.render.pdf.pdfbox;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.TreeMap;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.fontbox.cff.CFFFont;
+import org.apache.fontbox.cmap.CMap;
+import org.apache.fontbox.ttf.CMAPEncodingEntry;
+import org.apache.fontbox.ttf.GlyphData;
+import org.apache.fontbox.ttf.MaximumProfileTable;
+import org.apache.fontbox.ttf.TrueTypeFont;
+
+import org.apache.pdfbox.cos.COSArray;
+import org.apache.pdfbox.cos.COSBase;
+import org.apache.pdfbox.cos.COSDictionary;
+import org.apache.pdfbox.cos.COSName;
+import org.apache.pdfbox.cos.COSObject;
+import org.apache.pdfbox.encoding.Encoding;
+import org.apache.pdfbox.pdmodel.common.PDStream;
+import org.apache.pdfbox.pdmodel.font.PDCIDFont;
+import org.apache.pdfbox.pdmodel.font.PDCIDFontType0Font;
+import org.apache.pdfbox.pdmodel.font.PDCIDFontType2Font;
+import org.apache.pdfbox.pdmodel.font.PDFont;
+import org.apache.pdfbox.pdmodel.font.PDFontDescriptorDictionary;
+import org.apache.pdfbox.pdmodel.font.PDFontFactory;
+import org.apache.pdfbox.pdmodel.font.PDTrueTypeFont;
+import org.apache.pdfbox.pdmodel.font.PDType0Font;
+
+import org.apache.fop.fonts.CIDFontType;
+import org.apache.fop.fonts.CustomFont;
+import org.apache.fop.fonts.EmbeddingMode;
+import org.apache.fop.fonts.FontType;
+import org.apache.fop.fonts.MultiByteFont;
+import org.apache.fop.fonts.truetype.FontFileReader;
+import org.apache.fop.pdf.PDFDictionary;
+import org.apache.fop.util.CharUtilities;
+
+public class FOPPDFMultiByteFont extends MultiByteFont implements FOPPDFFont {
+    protected PDFDictionary ref;
+    private Map<Integer, Integer> newWidth = new TreeMap<Integer, Integer>();
+    private Map<String, Integer> charMapGlobal = new LinkedHashMap<String, 
Integer>();
+    private MergeTTFonts mergeTTFonts = new MergeTTFonts();
+    private MergeCFFFonts mergeCFFFonts = new MergeCFFFonts();
+    //private Map<String, GlyphData> glyphs = new HashMap<String, GlyphData>();
+    private final Map<COSDictionary, PDFont> fontMap = new 
HashMap<COSDictionary, PDFont>();
+
+    public FOPPDFMultiByteFont(COSDictionary fontData, String name) throws 
IOException {
+        super(null, EmbeddingMode.SUBSET);
+        //this stops fop modifying font later on
+        setEmbeddingMode(EmbeddingMode.FULL);
+        readFontBBox(fontData);
+        setFontName(name);
+        addFont(fontData);
+    }
+
+    public String addFont(COSDictionary fontData) throws IOException {
+        PDFont font = getFont(fontData);
+        setProperties(this, font);
+        PDFont mainFont = font;
+        TrueTypeFont ttf = null;
+        if (font instanceof PDType0Font) {
+            PDCIDFont cidFont = (PDCIDFont) ((PDType0Font) 
font).getDescendantFont();
+            setDefaultWidth((int) cidFont.getDefaultWidth());
+            mainFont = cidFont;
+            if (cidFont instanceof PDCIDFontType0Font) {
+                setCIDType(CIDFontType.CIDTYPE0);
+                setFontType(FontType.CIDTYPE0);
+            } else {
+                ttf = ((PDCIDFontType2Font) cidFont).getTTFFont();
+            }
+        } else {
+            ttf = ((PDTrueTypeFont) font).getTTFFont();
+            setDefaultWidth(1000);
+        }
+        GlyphData[] glyphData = new GlyphData[0];
+        if (ttf != null) {
+            glyphData = ttf.getGlyph().getGlyphs();
+        }
+        Map<Integer, Integer> oldToNewGIMap = new HashMap<Integer, Integer>();
+        if (charMapGlobal.isEmpty()) {
+            oldToNewGIMap.put(0, 0); // .notdef glyph
+        }
+        CMap c = mainFont.getToUnicodeCMap();
+        if (c == null) {
+            c = font.getToUnicodeCMap();
+        }
+        Map<Integer, String> mapping = getMapping(mainFont, c, 
glyphData.length);
+        //if (glyphData.length > 0 && differentGlyphData(glyphData, mapping)) {
+        //    return null;
+        //}
+        Map<Integer, String> gidToGlyph = new TreeMap<Integer, 
String>(mapping);
+        if (mainFont instanceof PDTrueTypeFont) {
+            CMAPEncodingEntry cmap = ttf.getCMAP().getCmaps()[0];
+            gidToGlyph.clear();
+            int[] gidToCode = cmap.getGlyphIdToCharacterCode();
+            for (int i = 1; i < glyphData.length && i < gidToCode.length; i++) 
{
+                String mappedChar = mapping.get(gidToCode[i]);
+                gidToGlyph.put(i, mappedChar);
+            }
+        }
+        readCharMap(font, gidToGlyph, glyphData, mainFont, oldToNewGIMap);
+        FontFileReader ffr = readFontFile(mainFont);
+        if (ttf != null) {
+            mergeMaxp(ttf, mergeTTFonts.maxp);
+            int sizeNoCompGlyphs = oldToNewGIMap.size();
+            mergeTTFonts.readFont(ffr, oldToNewGIMap, true);
+            if (oldToNewGIMap.size() > sizeNoCompGlyphs) {
+                cidSet.mapChar(256 * 256, (char) 0);
+            }
+        } else {
+            mergeCFFFonts.readType1CFont(new 
ByteArrayInputStream(ffr.getAllBytes()), getEmbedFontName());
+        }
+        return getFontName();
+    }
+
+    private void readCharMap(PDFont font, Map<Integer, String> gidToGlyph, 
GlyphData[] glyphData,
+                             PDFont mainFont, Map<Integer, Integer> 
oldToNewGIMap) {
+        int widthPos = font.getFirstChar() + 1;
+        for (Map.Entry<Integer, String> i : gidToGlyph.entrySet()) {
+            String mappedChar = i.getValue();
+            int key = i.getKey();
+            boolean skipWidth = (mappedChar == null) || mappedChar.length() == 
0;
+            if (skipWidth) {
+                mappedChar = (char)charMapGlobal.size() + "tmp";
+            } else if (mappedChar.length() > 1) {
+                mappedChar = "" + (char)mappedChar.hashCode();
+            }
+            if (!charMapGlobal.containsKey(mappedChar)) {
+                if (glyphData.length > 0
+                        && glyphData[key] == null
+                        && 
!CharUtilities.isAdjustableSpace(mappedChar.charAt(0))) {
+                    continue;
+                }
+                boolean addToEnd = charMapGlobal.containsValue(key);
+                if (addToEnd) {
+                    addPrivateUseMapping(mappedChar.charAt(0), 
charMapGlobal.size() + 1);
+                    charMapGlobal.put(mappedChar, charMapGlobal.size() + 1);
+                } else {
+                    addPrivateUseMapping(mappedChar.charAt(0), key);
+                    charMapGlobal.put(mappedChar, key);
+                }
+                int glyph = 0;
+                if (hasChar(mappedChar.charAt(0))) {
+                    glyph = (int) mapChar(mappedChar.charAt(0));
+                }
+                oldToNewGIMap.put(key, glyph);
+                if (!skipWidth) {
+                    if (!(mainFont instanceof PDTrueTypeFont)) {
+                        widthPos = key;
+                    }
+                    float w = font.getFontWidth(widthPos);
+                    if (w >= 0) {
+                        if (mainFont instanceof PDCIDFontType0Font) {
+                            newWidth.put(key, (int)w);
+                        } else {
+                            newWidth.put(glyph, (int)w);
+                        }
+                    }
+                }
+            }
+            if (!skipWidth) {
+                widthPos++;
+            }
+        }
+    }
+
+    private Map<Integer, String> getMapping(PDFont font, CMap c, int len) 
throws IOException {
+        Map<Integer, String> mapping = new HashMap<Integer, String>();
+        if (font instanceof PDCIDFontType0Font) {
+            Collection<CFFFont.Mapping> mappings =
+                    ((PDCIDFontType0Font) 
font).getType1CFont().getCFFFont().getMappings();
+            for (CFFFont.Mapping m : mappings) {
+                String character = Encoding.getCharacterForName(m.getName());
+                mapping.put(m.getSID(), character);
+            }
+        }
+        if (c != null) {
+            int last = font.getLastChar();
+            if (last == -1) {
+                last = len;
+            }
+            int size = 1;
+            if (c.hasTwoByteMappings()) {
+                size = 2;
+            }
+            for (int i = font.getFirstChar(); i <= last; i++) {
+                String l = c.lookup(i, size);
+                if (l != null) {
+                    mapping.put(i, l);
+                }
+            }
+        }
+        return mapping;
+    }
+
+//        private boolean differentGlyphData(GlyphData[] data, Map<Integer, 
String> mapping) throws IOException {
+//            Map<String, Integer> tmpMap = new HashMap<String, Integer>();
+//            for (Map.Entry<Integer, String> entry : mapping.entrySet()) {
+//                if (!tmpMap.containsKey(entry.getValue())) {
+//                    tmpMap.put(entry.getValue(), entry.getKey());
+//                }
+//            }
+//            mapping.clear();
+//            for (Map.Entry<String, Integer> entry : tmpMap.entrySet()) {
+//                mapping.put(entry.getValue(), entry.getKey());
+//            }
+//
+//            for (Map.Entry<Integer, String> n : mapping.entrySet()) {
+//                if (data[n.getKey()] != null) {
+//                    if (glyphs.containsKey(n.getValue()) && 
!glyphs.get(n.getValue()).equals(data[n.getKey()])) {
+//                        return true;
+//                    }
+//                    glyphs.put(n.getValue(), data[n.getKey()]);
+//                }
+//            }
+//            return false;
+//        }
+
+    private FontFileReader readFontFile(PDFont font) throws IOException {
+        PDFontDescriptorDictionary fd = (PDFontDescriptorDictionary) 
font.getFontDescriptor();
+        PDStream ff = fd.getFontFile3();
+        if (ff == null) {
+            ff = fd.getFontFile2();
+            if (ff == null) {
+                ff = fd.getFontFile();
+            }
+        }
+        InputStream is = ff.createInputStream();
+        return new FontFileReader(new 
ByteArrayInputStream(IOUtils.toByteArray(is)));
+    }
+
+    public Map<Integer, Integer> getWidthsMap() {
+        return newWidth;
+    }
+
+    public PDFDictionary getRef() {
+        return ref;
+    }
+
+    public void setRef(PDFDictionary d) {
+        ref = d;
+    }
+
+    public int size() {
+        if (getFontType() == FontType.CIDTYPE0) {
+            return 1;
+        }
+        return 0;
+    }
+
+    private void readFontBBox(COSBase b) throws IOException {
+        if (b instanceof COSDictionary) {
+            COSDictionary dict = (COSDictionary)b;
+            for (Map.Entry<COSName, COSBase> n : dict.entrySet()) {
+                readFontBBox(n.getValue());
+                if (n.getKey() == COSName.FONT_BBOX) {
+                    COSArray w = (COSArray)n.getValue();
+                    float[] bboxf = w.toFloatArray();
+                    int[] bbox = new int[bboxf.length];
+                    for (int i = 0; i < bbox.length; i++) {
+                        bbox[i] = (int)bboxf[i];
+                    }
+                    setFontBBox(bbox);
+                }
+            }
+        } else if (b instanceof COSObject) {
+            COSObject o = (COSObject)b;
+            readFontBBox(o.getObject());
+        } else if (b instanceof COSArray) {
+            COSArray o = (COSArray)b;
+            for (int i = 0; i < o.size(); i++) {
+                readFontBBox(o.get(i));
+            }
+        }
+    }
+
+    public boolean isEmbeddable() {
+        return true;
+    }
+
+    public InputStream getInputStream() throws IOException {
+        if (getFontType() == FontType.CIDTYPE0) {
+            mergeCFFFonts.writeFont();
+            return new ByteArrayInputStream(mergeCFFFonts.getFontSubset());
+        }
+        mergeTTFonts.writeFont(null);
+        return new ByteArrayInputStream(mergeTTFonts.getFontSubset());
+    }
+
+    protected PDFont getFont(COSDictionary fontData) throws IOException {
+        if (!fontMap.containsKey(fontData)) {
+            if (fontMap.size() > 10) {
+                fontMap.clear();
+            }
+            fontMap.put(fontData, PDFontFactory.createFont(fontData));
+        }
+        return fontMap.get(fontData);
+    }
+
+    protected static void setProperties(CustomFont cFont, PDFont font) {
+        if (font.getFontDescriptor() != null) {
+            cFont.setCapHeight((int) font.getFontDescriptor().getCapHeight());
+            cFont.setAscender((int)font.getFontDescriptor().getAscent());
+            cFont.setDescender((int)font.getFontDescriptor().getDescent());
+            cFont.setXHeight((int)font.getFontDescriptor().getXHeight());
+            cFont.setStemV((int)font.getFontDescriptor().getStemV());
+        }
+    }
+
+    protected static void mergeMaxp(TrueTypeFont ttf, MaximumProfileTable 
outMaxp) {
+        MaximumProfileTable mp = ttf.getMaximumProfile();
+        outMaxp.setVersion(mp.getVersion());
+        outMaxp.setNumGlyphs(outMaxp.getNumGlyphs() + mp.getNumGlyphs());
+        outMaxp.setMaxPoints(outMaxp.getMaxPoints() + mp.getMaxPoints());
+        outMaxp.setMaxContours(outMaxp.getMaxContours() + mp.getMaxContours());
+        outMaxp.setMaxCompositePoints(outMaxp.getMaxCompositePoints() + 
mp.getMaxCompositePoints());
+        outMaxp.setMaxCompositeContours(outMaxp.getMaxCompositeContours() + 
mp.getMaxCompositeContours());
+        outMaxp.setMaxZones(outMaxp.getMaxZones() + mp.getMaxZones());
+        outMaxp.setMaxTwilightPoints(outMaxp.getMaxTwilightPoints() + 
mp.getMaxTwilightPoints());
+        outMaxp.setMaxStorage(outMaxp.getMaxStorage() + mp.getMaxStorage());
+        outMaxp.setMaxFunctionDefs(outMaxp.getMaxFunctionDefs() + 
mp.getMaxFunctionDefs());
+        outMaxp.setMaxInstructionDefs(outMaxp.getMaxInstructionDefs() + 
mp.getMaxInstructionDefs());
+        outMaxp.setMaxStackElements(outMaxp.getMaxStackElements() + 
mp.getMaxStackElements());
+        outMaxp.setMaxSizeOfInstructions(outMaxp.getMaxSizeOfInstructions() + 
mp.getMaxSizeOfInstructions());
+        outMaxp.setMaxComponentElements(outMaxp.getMaxComponentElements() + 
mp.getMaxComponentElements());
+        outMaxp.setMaxComponentDepth(outMaxp.getMaxComponentDepth() + 
mp.getMaxComponentDepth());
+    }
+}

Propchange: 
xmlgraphics/fop-pdf-images/trunk/src/java/org/apache/fop/render/pdf/pdfbox/FOPPDFMultiByteFont.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 
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=1624558&view=auto
==============================================================================
--- 
xmlgraphics/fop-pdf-images/trunk/src/java/org/apache/fop/render/pdf/pdfbox/FOPPDFSingleByteFont.java
 (added)
+++ 
xmlgraphics/fop-pdf-images/trunk/src/java/org/apache/fop/render/pdf/pdfbox/FOPPDFSingleByteFont.java
 Fri Sep 12 14:15:21 2014
@@ -0,0 +1,491 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.fop.render.pdf.pdfbox;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+
+import org.apache.fontbox.cmap.CMap;
+import org.apache.fontbox.ttf.CMAPEncodingEntry;
+import org.apache.fontbox.ttf.TrueTypeFont;
+
+import org.apache.pdfbox.cos.COSArray;
+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;
+import org.apache.pdfbox.pdmodel.font.PDFont;
+import org.apache.pdfbox.pdmodel.font.PDFontDescriptorDictionary;
+import org.apache.pdfbox.pdmodel.font.PDFontFactory;
+import org.apache.pdfbox.pdmodel.font.PDTrueTypeFont;
+import org.apache.pdfbox.pdmodel.font.PDType1Font;
+
+import org.apache.fop.fonts.EmbeddingMode;
+import org.apache.fop.fonts.FontType;
+import org.apache.fop.fonts.SingleByteEncoding;
+import org.apache.fop.fonts.SingleByteFont;
+import org.apache.fop.fonts.truetype.FontFileReader;
+import org.apache.fop.pdf.PDFDictionary;
+
+public class FOPPDFSingleByteFont extends SingleByteFont implements FOPPDFFont 
{
+    private int fontCount;
+    private PDFont font;
+    protected PDFDictionary ref;
+    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 Map<Integer, String> encodingMap = new TreeMap<Integer, String>();
+    private int encodingSkip;
+    private MergeTTFonts mergeTTFonts = new MergeTTFonts();
+    private MergeCFFFonts mergeCFFFonts = new MergeCFFFonts();
+    private MergeType1Fonts mergeType1Fonts = new MergeType1Fonts();
+    private String shortFontName;
+    private final Map<COSDictionary, PDFont> fontMap = new 
HashMap<COSDictionary, PDFont>();
+
+    public FOPPDFSingleByteFont(COSDictionary fontData, String name) throws 
IOException {
+        super(null, EmbeddingMode.FULL);
+        if (fontData.getItem(COSName.SUBTYPE) == COSName.TRUE_TYPE) {
+            setFontType(FontType.TRUETYPE);
+        }
+        width = new int[0];
+        font = getFont(fontData);
+        setFirstChar(font.getFirstChar());
+        setLastChar(font.getLastChar());
+        shortFontName = MergeFontsPDFWriter.getName(font.getBaseFont());
+        loadFontFile(font);
+        float[] bBoxF = font.getFontBoundingBox().getCOSArray().toFloatArray();
+        int[] bBox = new int[bBoxF.length];
+        for (int i = 0; i < bBox.length; i++) {
+            bBox[i] = (int)bBoxF[i];
+        }
+        setFontBBox(bBox);
+
+        setFontName(name);
+        Object cmap = getCmap(font);
+        for (int i = font.getFirstChar(); i <= font.getLastChar(); i++) {
+            String mappedChar = getChar(cmap, i);
+            if (mappedChar != null && !charMapGlobal.containsKey(mappedChar)) {
+                charMapGlobal.put(mappedChar, i);
+            }
+        }
+        //mark font as used
+        notifyMapOperation();
+        FOPPDFMultiByteFont.setProperties(this, font);
+        if (font.getWidths() != null) {
+            //if width contains 0 we cant rely on codeToNameMap
+            boolean usesZero = font.getWidths().contains(0);
+            Set<Integer> codeToName = 
getCodeToName(font.getFontEncoding()).keySet();
+            for (int i = getFirstChar();
+                 i <= Math.min(getLastChar(), getFirstChar() + 
font.getWidths().size()); i++) {
+                if (usesZero || codeToName.contains(i)) {
+                    int w = font.getWidths().get(i - getFirstChar());
+                    newWidth.put(i, w);
+                } else {
+                    newWidth.put(i, 0);
+                }
+            }
+        }
+        mapping = new FOPPDFEncoding();
+        encodingSkip = font.getLastChar() + 1;
+        addEncoding(font);
+    }
+
+    private Map<Integer, String> getCodeToName(Encoding encoding) {
+        Map<Integer, String> codeToName = new HashMap<Integer, String>();
+        if (encoding != null) {
+            COSBase cos = encoding.getCOSObject();
+            if (cos instanceof COSDictionary) {
+                COSDictionary enc = (COSDictionary) cos;
+                COSName baseEncodingName = (COSName) 
enc.getDictionaryObject(COSName.BASE_ENCODING);
+                if (baseEncodingName != null) {
+                    try {
+                        Encoding baseEncoding = 
EncodingManager.INSTANCE.getEncoding(baseEncodingName);
+                        codeToName.putAll(baseEncoding.getCodeToNameMap());
+                    } catch (IOException e) {
+                        throw new RuntimeException(e);
+                    }
+                }
+                COSArray differences = 
(COSArray)enc.getDictionaryObject(COSName.DIFFERENCES);
+                int currentIndex = -1;
+                for (int i = 0; differences != null && i < differences.size(); 
i++) {
+                    COSBase next = differences.getObject(i);
+                    if (next instanceof COSNumber) {
+                        currentIndex = ((COSNumber)next).intValue();
+                    } else if (next instanceof COSName) {
+                        COSName name = (COSName)next;
+                        codeToName.put(currentIndex++, name.getName());
+                    }
+                }
+            } else {
+                return encoding.getCodeToNameMap();
+            }
+        }
+        return codeToName;
+    }
+
+    private Object getCmap(PDFont font) throws IOException {
+        if (font.getFontEncoding() != null) {
+            return font.getFontEncoding();
+        }
+        return font.getToUnicodeCMap();
+    }
+
+    private PDStream readFontFile(PDFont font) throws IOException {
+        PDFontDescriptorDictionary fd = (PDFontDescriptorDictionary) 
font.getFontDescriptor();
+        setFlags(fd.getFlags());
+        PDStream ff = fd.getFontFile3();
+        if (ff == null) {
+            ff = fd.getFontFile2();
+            if (ff == null) {
+                ff = fd.getFontFile();
+            }
+        } else {
+            setFontType(FontType.TYPE1C);
+        }
+        if (ff == null) {
+            throw new IOException(font.getBaseFont() + " no font file");
+        }
+        return ff;
+    }
+
+    private void loadFontFile(PDFont font) throws IOException {
+        PDStream ff = readFontFile(font);
+        mergeFontFile(ff.createInputStream(), font);
+        if (font instanceof PDTrueTypeFont) {
+            TrueTypeFont ttfont = ((PDTrueTypeFont) font).getTTFFont();
+            CMAPEncodingEntry[] cmapList = ttfont.getCMAP().getCmaps();
+            for (CMAPEncodingEntry c : cmapList) {
+                newCmap.platformId = c.getPlatformId();
+                newCmap.platformEncodingId = c.getPlatformEncodingId();
+                for (int i = 0; i < 256 * 256; i++) {
+                    if (c.getGlyphId(i) != 0) {
+                        newCmap.glyphIdToCharacterCode.put(i, c.getGlyphId(i));
+                    }
+                }
+            }
+            FOPPDFMultiByteFont.mergeMaxp(ttfont, mergeTTFonts.maxp);
+        }
+    }
+
+    @Override
+    public boolean hasChar(char c) {
+        return charMapGlobal.containsKey(String.valueOf(c));
+    }
+
+    @Override
+    public char mapChar(char c) {
+        return mapping.mapChar(c);
+    }
+
+    public String getEmbedFontName() {
+        return shortFontName;
+    }
+
+    public int[] getWidths() {
+        width = new int[getLastChar() - getFirstChar() + 1];
+        for (int i = getFirstChar(); i <= getLastChar(); i++) {
+            if (newWidth.containsKey(i)) {
+                width[i - getFirstChar()] = newWidth.get(i);
+            } else {
+                width[i - getFirstChar()] = 0;
+            }
+        }
+        return width.clone();
+    }
+
+    public String addFont(COSDictionary fontData) throws IOException {
+        PDFont font = getFont(fontData);
+        if (font instanceof PDType1Font && differentGlyphData((PDType1Font) 
font)) {
+            return null;
+        }
+        mergeWidths(font);
+        if (font.getFirstChar() < getFirstChar()) {
+            setFirstChar(font.getFirstChar());
+        }
+        for (int w : newWidth.keySet()) {
+            if (w > getLastChar()) {
+                setLastChar(w);
+            }
+        }
+        loadFontFile(font);
+        addEncoding(font);
+        return getFontName();
+    }
+
+    public int size() {
+        return fontCount;
+    }
+
+    private Map<String, byte[]> getCharStringsDict(PDType1Font font) throws 
IOException {
+        if (getFontType() == FontType.TYPE1) {
+            return font.getType1Font().getCharStringsDict();
+        }
+        return font.getType1CFont().getCFFFont().getCharStringsDict();
+    }
+
+    private boolean differentGlyphData(PDType1Font otherFont) throws 
IOException {
+        if (charStringsDict == null) {
+            charStringsDict = getCharStringsDict((PDType1Font) font);
+        }
+        for (Map.Entry<String, byte[]> s : 
getCharStringsDict(otherFont).entrySet()) {
+            if (charStringsDict.containsKey(s.getKey())) {
+                int numberDiff = 0;
+                byte[] b1 = charStringsDict.get(s.getKey());
+                byte[] b2 = s.getValue();
+                int b1Index = b1.length - 1;
+                int b2Index = b2.length - 1;
+                while (b1Index >= 0 && b2Index >= 0) {
+                    if (b1[b1Index] != b2[b2Index]) {
+                        numberDiff++;
+                        if (numberDiff > 2) {
+                            break;
+                        }
+                    }
+                    b1Index--;
+                    b2Index--;
+                }
+                if (numberDiff > 2) {
+//                        log.info(getFontName() + " " + s.getKey() + " not 
equal " + numberdiff);
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    private void mergeWidths(PDFont font) throws IOException {
+        int w = 0;
+        int skipGlyphIndex = getLastChar() + 1;
+        Object cmap = getCmap(font);
+        Set<Integer> codeToName = 
getCodeToName(font.getFontEncoding()).keySet();
+        for (int i = font.getFirstChar(); i <= font.getLastChar(); i++) {
+            boolean addedWidth = false;
+            int glyphIndexPos = skipGlyphIndex;
+            if (font instanceof PDTrueTypeFont) {
+                glyphIndexPos = i;
+            }
+            int neww = 0;
+            if (font.getWidths() != null) {
+                neww = font.getWidths().get(i - font.getFirstChar());
+                if (!newWidth.containsKey(i) || newWidth.get(i) == 0) {
+                    if (getFontType() == FontType.TYPE1
+                            || font instanceof PDTrueTypeFont
+                            || codeToName.contains(i)) {
+                        newWidth.put(i, neww);
+                        glyphIndexPos = i;
+                    } else {
+                        newWidth.put(i, 0);
+                    }
+                    addedWidth = true;
+                }
+            }
+            String mappedChar = getChar(cmap, i);
+            if (mappedChar != null && !charMapGlobal.containsKey(mappedChar)) {
+                charMapGlobal.put(mappedChar, glyphIndexPos);
+                if (!addedWidth && w < font.getWidths().size()) {
+                    newWidth.put(newWidth.size() + getFirstChar(), neww);
+                }
+                skipGlyphIndex++;
+            }
+            w++;
+        }
+    }
+
+    private String getChar(Object cmap, int i) throws IOException {
+        if (cmap instanceof CMap) {
+            CMap c = (CMap)cmap;
+            int size = 1;
+            if (c.hasTwoByteMappings()) {
+                size = 2;
+            }
+            return c.lookup(i, size);
+        }
+        Encoding enc = (Encoding)cmap;
+        if (enc instanceof DictionaryEncoding) {
+            return enc.getName(i);
+        }
+        return enc.getCharacter(i);
+    }
+
+    public String getEncodingName() {
+        if (font.getFontEncoding() != null) {
+            COSBase cosObject = font.getFontEncoding().getCOSObject();
+            if (cosObject != null) {
+                if (cosObject instanceof COSDictionary) {
+                    COSBase item = ((COSDictionary) 
cosObject).getItem(COSName.BASE_ENCODING);
+                    if (item != null) {
+                        return ((COSName)item).getName();
+                    }
+                } else if (cosObject instanceof COSName) {
+                    return ((COSName) cosObject).getName();
+                } else {
+                    throw new RuntimeException(cosObject.toString() + " not 
supported");
+                }
+            }
+        }
+        return null;
+    }
+
+    private void addEncoding(PDFont fontForEnc) {
+        List<String> added = new ArrayList<String>(encodingMap.values());
+        Map<Integer, String> codeToName = 
getCodeToName(fontForEnc.getFontEncoding());
+        for (int i = fontForEnc.getFirstChar(); i <= fontForEnc.getLastChar(); 
i++) {
+            if (codeToName.keySet().contains(i)) {
+                String s = codeToName.get(i);
+                if (!added.contains(s)) {
+                    if (!encodingMap.containsKey(i)) {
+                        encodingMap.put(i, s);
+                    } else {
+                        encodingMap.put(encodingSkip, s);
+                        encodingSkip++;
+                    }
+                }
+            }
+        }
+    }
+
+    class FOPPDFEncoding implements SingleByteEncoding {
+        private boolean cmap;
+
+        public String getName() {
+            return "FOPPDFEncoding";
+        }
+
+        public char mapChar(char c) {
+            if (charMapGlobal.containsKey(String.valueOf(c))) {
+                return (char)charMapGlobal.get(String.valueOf(c)).intValue();
+            }
+            return 0;
+        }
+
+        public String[] getCharNameMap() {
+            Collection<String> v = encodingMap.values();
+            return v.toArray(new String[v.size()]);
+        }
+
+        public char[] getUnicodeCharMap() {
+            if (cmap) {
+                if (MergeFontsPDFWriter.getToUnicode(font) == null) {
+                    return new char[0];
+                }
+                List<String> cmapStrings = new ArrayList<String>();
+                Map<Integer, String> cm = new HashMap<Integer, String>();
+                for (Map.Entry<String, Integer> o : charMapGlobal.entrySet()) {
+                    cm.put(o.getValue(), o.getKey());
+                }
+                for (int i = 0; i < getLastChar() + 1; i++) {
+                    if (cm.containsKey(i)) {
+                        cmapStrings.add(cm.get(i));
+                    } else {
+                        cmapStrings.add(" ");
+                    }
+                }
+                return fromStringToCharArray(cmapStrings);
+            }
+            cmap = true;
+            return toCharArray(encodingMap.keySet());
+        }
+
+        private char[] fromStringToCharArray(Collection<String> list) {
+            char[] ret = new char[list.size()];
+            int i = 0;
+            for (String e : list) {
+                if (e.length() > 0) {
+                    ret[i++] = e.charAt(0);
+                }
+            }
+            return ret;
+        }
+
+        private char[] toCharArray(Collection<Integer> list) {
+            char[] ret = new char[list.size()];
+            int i = 0;
+            for (int e : list) {
+                ret[i++] = (char)e;
+            }
+            return ret;
+        }
+    }
+
+    public PDFDictionary getRef() {
+        return ref;
+    }
+
+    public void setRef(PDFDictionary d) {
+        ref = d;
+    }
+
+    public boolean isEmbeddable() {
+        return true;
+    }
+
+    public boolean isSymbolicFont() {
+        return false;
+    }
+
+    private void mergeFontFile(InputStream ff, PDFont pdFont) throws 
IOException {
+        if (getFontType() == FontType.TRUETYPE) {
+            Map<Integer, Integer> chars = new HashMap<Integer, Integer>();
+            chars.put(0, 0);
+            mergeTTFonts.readFont(new FontFileReader(ff), chars, false);
+        } else if (getFontType() == FontType.TYPE1) {
+            mergeType1Fonts.readFont(ff, (PDType1Font) pdFont);
+        } else {
+            mergeCFFFonts.readType1CFont(ff, shortFontName);
+        }
+        fontCount++;
+    }
+
+    public InputStream getInputStream() throws IOException {
+        if (getFontType() == FontType.TYPE1C) {
+            mergeCFFFonts.writeFont();
+            return new ByteArrayInputStream(mergeCFFFonts.getFontSubset());
+        }
+        if (getFontType() == FontType.TRUETYPE) {
+            mergeTTFonts.writeFont(newCmap);
+            return new ByteArrayInputStream(mergeTTFonts.getFontSubset());
+        }
+        if (getFontType() == FontType.TYPE1) {
+            return new ByteArrayInputStream(mergeType1Fonts.writeFont());
+        }
+        return null;
+    }
+
+    protected PDFont getFont(COSDictionary fontData) throws IOException {
+        if (!fontMap.containsKey(fontData)) {
+            if (fontMap.size() > 10) {
+                fontMap.clear();
+            }
+            fontMap.put(fontData, PDFontFactory.createFont(fontData));
+        }
+        return fontMap.get(fontData);
+    }
+}

Propchange: 
xmlgraphics/fop-pdf-images/trunk/src/java/org/apache/fop/render/pdf/pdfbox/FOPPDFSingleByteFont.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 
xmlgraphics/fop-pdf-images/trunk/src/java/org/apache/fop/render/pdf/pdfbox/MergeFontsPDFWriter.java
URL: 
http://svn.apache.org/viewvc/xmlgraphics/fop-pdf-images/trunk/src/java/org/apache/fop/render/pdf/pdfbox/MergeFontsPDFWriter.java?rev=1624558&view=auto
==============================================================================
--- 
xmlgraphics/fop-pdf-images/trunk/src/java/org/apache/fop/render/pdf/pdfbox/MergeFontsPDFWriter.java
 (added)
+++ 
xmlgraphics/fop-pdf-images/trunk/src/java/org/apache/fop/render/pdf/pdfbox/MergeFontsPDFWriter.java
 Fri Sep 12 14:15:21 2014
@@ -0,0 +1,318 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.fop.render.pdf.pdfbox;
+
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.regex.Pattern;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.fontbox.cff.CFFFont;
+import org.apache.fontbox.cff.CFFFontROS;
+import org.apache.fontbox.cff.charset.CFFCharset;
+import org.apache.fontbox.cff.encoding.CFFEncoding;
+import org.apache.fontbox.ttf.CMAPEncodingEntry;
+import org.apache.fontbox.ttf.TrueTypeFont;
+
+import org.apache.pdfbox.cos.COSBase;
+import org.apache.pdfbox.cos.COSDictionary;
+import org.apache.pdfbox.cos.COSName;
+import org.apache.pdfbox.cos.COSString;
+import org.apache.pdfbox.pdmodel.common.PDStream;
+import org.apache.pdfbox.pdmodel.font.PDCIDFontType0Font;
+import org.apache.pdfbox.pdmodel.font.PDCIDFontType2Font;
+import org.apache.pdfbox.pdmodel.font.PDFont;
+import org.apache.pdfbox.pdmodel.font.PDFontDescriptorDictionary;
+import org.apache.pdfbox.pdmodel.font.PDFontFactory;
+import org.apache.pdfbox.pdmodel.font.PDTrueTypeFont;
+import org.apache.pdfbox.pdmodel.font.PDType0Font;
+import org.apache.pdfbox.pdmodel.font.PDType1Font;
+import org.apache.pdfbox.util.operator.PDFOperator;
+
+import org.apache.fop.fonts.FontInfo;
+import org.apache.fop.fonts.SingleByteFont;
+import org.apache.fop.fonts.Typeface;
+import org.apache.fop.fonts.truetype.OTFSubSetFile;
+import org.apache.fop.pdf.PDFText;
+
+public class MergeFontsPDFWriter extends PDFWriter {
+    protected static final Log log = 
LogFactory.getLog(MergeFontsPDFWriter.class);
+    private COSDictionary fonts;
+    private FontInfo fontInfo;
+    private Typeface font;
+    private PDFont oldFont = null;
+    protected Map<COSName, String> fontsToRemove = new HashMap<COSName, 
String>();
+    private final Map<COSDictionary, PDFont> fontMap = new 
HashMap<COSDictionary, PDFont>();
+    private static final Pattern SUBSET_PATTERN = 
Pattern.compile("[A-Z][A-Z][A-Z][A-Z][A-Z][A-Z]\\+.+");
+    private Collection<String> parentFonts;
+
+    public MergeFontsPDFWriter(COSDictionary fonts, FontInfo fontInfo, String 
key, List<COSName> resourceNames) {
+        super(key, resourceNames);
+        this.fonts = fonts;
+        this.fontInfo = fontInfo;
+    }
+
+    public String writeText(PDStream pdStream) throws IOException {
+        String txt = super.writeText(pdStream);
+        if (fontsToRemove.isEmpty()) {
+            return null;
+        }
+        for (COSName cn : fontsToRemove.keySet()) {
+            fonts.removeItem(cn);
+        }
+        parentFonts = fontsToRemove.values();
+        return txt;
+    }
+
+    protected void readPDFArguments(PDFOperator op, Collection<COSBase> 
arguments) throws IOException {
+        for (COSBase c : arguments) {
+            if (c instanceof COSName) {
+                COSName cn = (COSName)c;
+                COSDictionary fontData = 
(COSDictionary)fonts.getDictionaryObject(cn.getName());
+                String internalName = fontsToRemove.get(cn);
+                if (internalName == null && fontData != null) {
+                    internalName = getNewFont(fontData, fontInfo, 
fontsToRemove.values());
+                }
+                if (fontData == null || internalName == null) {
+                    s.append("/" + cn.getName());
+                    addKey(cn);
+                    if (op.getOperation().equals("Tf")) {
+                        font = null;
+                        oldFont = null;
+                    }
+                } else {
+                    s.append("/" + internalName);
+                    fontsToRemove.put(cn, internalName);
+                    font = fontInfo.getUsedFonts().get(internalName);
+                    oldFont = getFont(fontData);
+                }
+                s.append(" ");
+            } else if (c instanceof COSString && font != null && 
((FOPPDFFont)font).size() != 1) {
+                List<String> word = readCOSString((COSString)c, oldFont);
+                if (word == null) {
+                    s.append(PDFText.escapeString(getString((COSString) c)));
+                } else {
+                    String x = getMappedWord(word, font, ((COSString) 
c).getBytes());
+                    if (x == null) {
+                        s.append(PDFText.escapeString(getString((COSString) 
c)));
+                    } else {
+                        s.append(x);
+                    }
+                }
+            } else {
+                processArg(op, c);
+            }
+        }
+    }
+
+    private String getNewFont(COSDictionary fontData, FontInfo fontinfo, 
Collection<String> usedFonts)
+        throws IOException {
+        String base = getUniqueFontName(fontData);
+        if (base == null || usedFonts.contains(base) || (parentFonts != null 
&& parentFonts.contains(base))) {
+            return null;
+        }
+        try {
+            for (Typeface t : fontinfo.getUsedFonts().values()) {
+                if (t instanceof FOPPDFFont && base.equals(t.getFontName())) {
+                    return ((FOPPDFFont)t).addFont(fontData);
+                }
+            }
+            if (base.endsWith("cid") || fontData.getItem(COSName.SUBTYPE) != 
COSName.TYPE1
+                    && fontData.getItem(COSName.SUBTYPE) != COSName.TRUE_TYPE) 
{
+                fontinfo.addMetrics(base, new FOPPDFMultiByteFont(fontData, 
base));
+            } else {
+                fontinfo.addMetrics(base, new FOPPDFSingleByteFont(fontData, 
base));
+            }
+        } catch (IOException e) {
+            log.warn(e.getMessage());
+            return null;
+        }
+        fontinfo.useFont(base);
+        return base;
+    }
+
+    private String getUniqueFontName(COSDictionary fontData) throws 
IOException {
+        PDFont font = getFont(fontData);
+        String extra = "";
+        String name = getName(font.getBaseFont()) + "_" + 
((COSName)fontData.getItem(COSName.SUBTYPE)).getName();
+        if (font instanceof PDType0Font
+                && ((PDType0Font) font).getDescendantFont() instanceof 
PDCIDFontType0Font
+                && ((PDCIDFontType0Font) ((PDType0Font) 
font).getDescendantFont()).getType1CFont() != null) {
+            CFFFont cffFont =
+                    ((PDCIDFontType0Font) ((PDType0Font) 
font).getDescendantFont()).getType1CFont().getCFFFont();
+            if (cffFont instanceof CFFFontROS
+                    && ((CFFFontROS)cffFont).getFdSelect().getClass().getName()
+                    
.equals("org.apache.fontbox.cff.CFFParser$Format0FDSelect")) {
+                extra += "format0";
+            }
+            return name + extra;
+        } else if (font instanceof PDType0Font
+                && getToUnicode(font) != null
+                && ((PDType0Font) font).getDescendantFont() instanceof 
PDCIDFontType2Font) {
+            if (!isSubsetFont(font.getBaseFont())) {
+                extra = "f3";
+            }
+            return name + extra;
+        } else if (font instanceof PDTrueTypeFont && 
isSubsetFont(font.getBaseFont())) {
+            TrueTypeFont tt = ((PDTrueTypeFont) font).getTTFFont();
+            for (CMAPEncodingEntry c : tt.getCMAP().getCmaps()) {
+                if (c.getGlyphId(1) > 0) {
+                    extra = "cid";
+                }
+            }
+            return name + extra;
+        } else if (font instanceof PDType1Font) {
+            return getNamePDType1Font(name, (PDType1Font) font);
+        }
+        return null;
+    }
+
+    private String getNamePDType1Font(String name, PDType1Font font) throws 
IOException {
+        String extra = "";
+        if (font.getType1CFont() == null
+                || font.getType1CFont().getCFFFont() == null) {
+            if (font.getFontDescriptor() instanceof 
PDFontDescriptorDictionary) {
+                return name;
+            }
+            return null;
+        }
+        CFFEncoding encoding = font.getType1CFont().getCFFFont().getEncoding();
+        String eClass = encoding.getClass().getName();
+        if (eClass.equals("org.apache.fontbox.cff.CFFParser$Format1Encoding")) 
{
+            extra = "f1enc";
+        } else if 
(eClass.equals("org.apache.fontbox.cff.CFFParser$Format0Encoding")) {
+            extra = "f0enc";
+        }
+        CFFCharset cs = font.getType1CFont().getCFFFont().getCharset();
+        if (cs.getEntries().get(0).getSID() < 
OTFSubSetFile.NUM_STANDARD_STRINGS) {
+            extra += "stdcs";
+        }
+        if 
(cs.getClass().getName().equals("org.apache.fontbox.cff.CFFParser$Format1Charset"))
 {
+            extra += "f1cs";
+        }
+        return name + extra;
+    }
+
+    private String getString(COSString s) throws UnsupportedEncodingException {
+        String encoding = "ISO-8859-1";
+        byte[] data = s.getBytes();
+        int start = 0;
+        if (data.length > 2) {
+            if (data[0] == (byte) 0xFF && data[1] == (byte) 0xFE) {
+                encoding = "UTF-16LE";
+                start = 2;
+            } else if (data[0] == (byte) 0xFE && data[1] == (byte) 0xFF) {
+                encoding = "UTF-16BE";
+                start = 2;
+            }
+        }
+        return new String(data, start, data.length - start, encoding);
+    }
+
+    private String getMappedWord(List<String> word, Typeface font, byte[] 
bytes) throws IOException {
+        StringBuffer newOct = new StringBuffer();
+        StringBuilder newHex = new StringBuilder();
+        int i = 0;
+        for (String str : word) {
+            Integer mapped = getMapping(bytes[i]);
+            if (mapped == null) {
+                char c = str.charAt(0);
+                if (str.length() > 1) {
+                    c = (char) str.hashCode();
+                }
+                if (font.hasChar(c)) {
+                    mapped = (int)font.mapChar(c);
+                } else {
+                    return null;
+                }
+            }
+            newHex.append(String.format("%1$04x", mapped & 
0xFFFF).toUpperCase(Locale.getDefault()));
+            PDFText.escapeStringChar((char)mapped.intValue(), newOct);
+            i++;
+        }
+        if (font instanceof SingleByteFont) {
+            return "(" + newOct.toString() + ")";
+        }
+        return "<" + newHex.toString() + ">";
+    }
+
+    private Integer getMapping(byte i) throws IOException {
+        if (oldFont.getFontEncoding() != null && font instanceof 
FOPPDFSingleByteFont) {
+            String name = oldFont.getFontEncoding().getName(i);
+            if (name != null && 
((FOPPDFSingleByteFont)font).charMapGlobal.containsKey(name)) {
+                return ((FOPPDFSingleByteFont)font).charMapGlobal.get(name);
+            }
+        }
+        return null;
+    }
+
+    private List<String> readCOSString(COSString s, PDFont oldFont) throws 
IOException {
+        List<String> word = new ArrayList<String>();
+        byte[] string = s.getBytes();
+        int codeLength;
+//            String t1Str = new String(string, "UTF-8");
+        for (int i = 0; i < string.length; i += codeLength) {
+            codeLength = 1;
+            String c = oldFont.encode(string, i, codeLength);
+//                if (oldFont instanceof PDType1Font && i < t1Str.length()) {
+//                    c = ((PDType1Font)oldFont).encodetype1(string, i, 
codeLength);
+//                }
+            if (c == null && i + 1 < string.length) {
+                codeLength++;
+                c = oldFont.encode(string, i, codeLength);
+            }
+            if (c == null) {
+                return null;
+            }
+            word.add(c);
+        }
+        return word;
+    }
+
+    protected PDFont getFont(COSDictionary fontData) throws IOException {
+        if (!fontMap.containsKey(fontData)) {
+            if (fontMap.size() > 10) {
+                fontMap.clear();
+            }
+            fontMap.put(fontData, PDFontFactory.createFont(fontData));
+        }
+        return fontMap.get(fontData);
+    }
+
+    private static boolean isSubsetFont(String s) {
+        return SUBSET_PATTERN.matcher(s).matches();
+    }
+
+    protected static String getName(String name) {
+        if (isSubsetFont(name)) {
+            return name.split("\\+")[1].replace(" ", "");
+        }
+        return name.replace(" ", "");
+    }
+
+    protected static COSBase getToUnicode(PDFont font) {
+        COSDictionary dict = (COSDictionary) font.getCOSObject();
+        return dict.getDictionaryObject(COSName.TO_UNICODE);
+    }
+}

Propchange: 
xmlgraphics/fop-pdf-images/trunk/src/java/org/apache/fop/render/pdf/pdfbox/MergeFontsPDFWriter.java
------------------------------------------------------------------------------
    svn:eol-style = native

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=1624558&r1=1624557&r2=1624558&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
 Fri Sep 12 14:15:21 2014
@@ -261,7 +261,7 @@ public class MergeTTFonts extends TTFSub
         }
     }
 
-    public void writeFont(PDFBoxAdapter.Cmap cmap) throws IOException {
+    public void writeFont(Cmap cmap) throws IOException {
         output = new byte[size * 2];
         createDirectory();     // Create the TrueType header and directory
         int sgsize = added.size();
@@ -334,7 +334,7 @@ public class MergeTTFonts extends TTFSub
         realSize += currentPos - startPos;
     }
 
-    private void writeCMAP(PDFBoxAdapter.Cmap cmap) {
+    private void writeCMAP(Cmap cmap) {
         int checksum = currentPos;
         pad4();
         int cmapPos = currentPos;
@@ -416,4 +416,10 @@ public class MergeTTFonts extends TTFSub
         }
         return origIndexes;
     }
+
+    public static class Cmap {
+        int platformId;
+        int platformEncodingId;
+        Map<Integer, Integer> glyphIdToCharacterCode = new TreeMap<Integer, 
Integer>();
+    }
 }



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

Reply via email to