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]