You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pdfbox.apache.org by ja...@apache.org on 2014/12/16 00:54:56 UTC
svn commit: r1645796 [2/2] - in /pdfbox/trunk:
examples/src/main/java/org/apache/pdfbox/examples/pdmodel/
fontbox/src/main/java/org/apache/fontbox/ttf/
pdfbox/src/main/java/org/apache/pdfbox/pdmodel/edit/
pdfbox/src/main/java/org/apache/pdfbox/pdmodel/...
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDCIDFontType2Embedder.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDCIDFontType2Embedder.java?rev=1645796&r1=1645795&r2=1645796&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDCIDFontType2Embedder.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDCIDFontType2Embedder.java Mon Dec 15 23:54:55 2014
@@ -22,6 +22,9 @@ import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.IOException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
import org.apache.pdfbox.cos.COSArray;
import org.apache.pdfbox.cos.COSDictionary;
import org.apache.pdfbox.cos.COSInteger;
@@ -38,8 +41,11 @@ import org.apache.pdfbox.pdmodel.common.
*/
final class PDCIDFontType2Embedder extends TrueTypeEmbedder
{
+ private final PDDocument document;
private final PDType0Font parent;
+ private final COSDictionary dict;
private final COSDictionary cidFont;
+ private final Map<Integer, Integer> gidToUni;
/**
* Creates a new TrueType font embedder for the given TTF as a PDCIDFontType2.
@@ -54,6 +60,8 @@ final class PDCIDFontType2Embedder exten
PDType0Font parent) throws IOException
{
super(document, dict, ttfStream);
+ this.document = document;
+ this.dict = dict;
this.parent = parent;
// parent Type 0 font
@@ -67,25 +75,78 @@ final class PDCIDFontType2Embedder exten
descendantFonts.add(cidFont);
dict.setItem(COSName.DESCENDANT_FONTS, descendantFonts);
+ // build GID -> Unicode map
+ gidToUni = new HashMap<Integer, Integer>();
+ for (int gid = 1, max = ttf.getMaximumProfile().getNumGlyphs(); gid <= max; gid++)
+ {
+ // skip composite glyph components that have no code point
+ Integer codePoint = cmap.getCharacterCode(gid);
+ if (codePoint != null)
+ {
+ gidToUni.put(gid, codePoint); // CID = GID
+ }
+ }
+
// ToUnicode CMap
- dict.setItem(COSName.TO_UNICODE, createToUnicodeCMap(document));
+ buildToUnicodeCMap(null);
}
- private PDStream createToUnicodeCMap(PDDocument document) throws IOException
+ /**
+ * Rebuild a font subset.
+ */
+ protected void buildSubset(InputStream ttfSubset, String tag, Map<Integer, Integer> gidToCid)
+ throws IOException
+ {
+ // build CID2GIDMap, because the content stream has been written with the old GIDs
+ Map<Integer, Integer> cidToGid = new HashMap<Integer, Integer>();
+ for (Map.Entry<Integer, Integer> entry : gidToCid.entrySet())
+ {
+ int newGID = entry.getKey();
+ int oldGID = entry.getValue();
+ cidToGid.put(oldGID, newGID);
+ }
+
+ // buildSubset the relevant part of the font
+ buildFontFile2(ttfSubset);
+ addNameTag(tag);
+ buildWidths(cidToGid);
+ buildCIDToGIDMap(cidToGid);
+ buildToUnicodeCMap(gidToCid);
+ }
+
+ private void buildToUnicodeCMap(Map<Integer, Integer> newGIDToOldCID) throws IOException
{
ToUnicodeWriter toUniWriter = new ToUnicodeWriter();
boolean hasSurrogates = false;
for (int gid = 1, max = ttf.getMaximumProfile().getNumGlyphs(); gid <= max; gid++)
{
- Integer codePoint = cmap.getCharacterCode(gid);
+ // optional CID2GIDMap for subsetting
+ int cid;
+ if (newGIDToOldCID != null)
+ {
+ if (!newGIDToOldCID.containsKey(gid))
+ {
+ continue;
+ }
+ else
+ {
+ cid = newGIDToOldCID.get(gid);
+ }
+ }
+ else
+ {
+ cid = gid;
+ }
+
// skip composite glyph components that have no code point
+ Integer codePoint = gidToUni.get(cid); // old GID -> Unicode
if (codePoint != null)
{
if (codePoint > 0xFFFF)
{
hasSurrogates = true;
}
- toUniWriter.add(gid, new String(new int[]{ codePoint }, 0, 1));
+ toUniWriter.add(cid, new String(new int[]{ codePoint }, 0, 1));
}
}
@@ -106,7 +167,7 @@ final class PDCIDFontType2Embedder exten
}
}
- return stream;
+ dict.setItem(COSName.TO_UNICODE, stream);
}
private COSDictionary toCIDSystemInfo(String registry, String ordering, int supplement)
@@ -137,21 +198,101 @@ final class PDCIDFontType2Embedder exten
cidFont.setItem(COSName.FONT_DESC, fontDescriptor.getCOSObject());
// W - widths
- int numGlyphs = ttf.getNumberOfGlyphs();
- int[] gidwidths = new int[numGlyphs * 2];
- for (int i = 0; i < numGlyphs; i++)
- {
- gidwidths[i * 2] = i;
- gidwidths[i * 2 + 1] = ttf.getHorizontalMetrics().getAdvanceWidth(i);
- }
- cidFont.setItem(COSName.W, getWidths(gidwidths));
+ buildWidths(cidFont);
- // CIDToGIDMap - todo: optional (can be used for easy sub-setting)
+ // CIDToGIDMap
cidFont.setItem(COSName.CID_TO_GID_MAP, COSName.IDENTITY);
return cidFont;
}
+ private void addNameTag(String tag) throws IOException
+ {
+ String name = fontDescriptor.getFontName();
+ String newName = tag + name;
+
+ dict.setName(COSName.BASE_FONT, newName);
+ fontDescriptor.setFontName(newName);
+ cidFont.setName(COSName.BASE_FONT, newName);
+ }
+
+ private void buildCIDToGIDMap(Map<Integer, Integer> cidToGid) throws IOException
+ {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ int cidMax = Collections.max(cidToGid.keySet());
+ for (int i = 0; i <= cidMax; i++)
+ {
+ int gid;
+ if (cidToGid.containsKey(i))
+ {
+ gid = cidToGid.get(i);
+ }
+ else
+ {
+ gid = 0;
+ }
+ out.write(new byte[] { (byte)(gid >> 8 & 0xff), (byte)(gid & 0xff) });
+ }
+
+ InputStream input = new ByteArrayInputStream(out.toByteArray());
+ PDStream stream = new PDStream(document, input, false);
+ stream.getStream().setInt(COSName.LENGTH1, stream.getByteArray().length);
+ stream.addCompression();
+
+ cidFont.setItem(COSName.CID_TO_GID_MAP, stream);
+ }
+
+ /**
+ * Builds withs with a custom CIDToGIDMap (for embedding font subset).
+ */
+ private void buildWidths(Map<Integer, Integer> cidToGid) throws IOException
+ {
+ float scaling = 1000f / ttf.getHeader().getUnitsPerEm();
+
+ COSArray widths = new COSArray();
+ COSArray ws = new COSArray();
+ int prev = -1;
+
+ for (int cid : cidToGid.keySet())
+ {
+ if (!cidToGid.containsKey(cid))
+ {
+ continue;
+ }
+
+ int gid = cidToGid.get(cid);
+ float width = ttf.getHorizontalMetrics().getAdvanceWidth(gid) * scaling;
+
+ // c [w1 w2 ... wn]
+ if (prev != cid - 1)
+ {
+ ws = new COSArray();
+ widths.add(COSInteger.get(cid)); // c
+ widths.add(ws);
+ }
+ ws.add(COSInteger.get(Math.round(width))); // wi
+ prev = cid;
+ }
+
+ cidFont.setItem(COSName.W, widths);
+ }
+
+ /**
+ * Build widths with Identity CIDToGIDMap (for embedding full font).
+ */
+ private void buildWidths(COSDictionary cidFont) throws IOException
+ {
+ int cidMax = ttf.getNumberOfGlyphs();
+ int[] gidwidths = new int[cidMax * 2];
+ for (int cid = 0; cid < cidMax; cid++)
+ {
+ gidwidths[cid * 2] = cid;
+ gidwidths[cid * 2 + 1] = ttf.getHorizontalMetrics().getAdvanceWidth(cid);
+ }
+
+ cidFont.setItem(COSName.W, getWidths(gidwidths));
+ }
+
private COSArray getWidths(int[] widths) throws IOException
{
if (widths.length == 0)
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDFont.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDFont.java?rev=1645796&r1=1645795&r2=1645796&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDFont.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDFont.java Mon Dec 15 23:54:55 2014
@@ -22,6 +22,7 @@ import java.io.InputStream;
import java.util.Collections;
import java.util.List;
+import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.fontbox.afm.FontMetrics;
@@ -565,6 +566,14 @@ public abstract class PDFont implements
return Standard14Fonts.containsName(getName());
}
+ /**
+ * Replaces this font with a subset containing only the given Unicode characters.
+ *
+ * @param codePoints Unicode code points to keep
+ * @throws IOException if the subset could not be written
+ */
+ public abstract void subset(Set<Integer> codePoints) throws IOException;
+
@Override
public abstract boolean isDamaged();
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDSimpleFont.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDSimpleFont.java?rev=1645796&r1=1645795&r2=1645796&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDSimpleFont.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDSimpleFont.java Mon Dec 15 23:54:55 2014
@@ -349,4 +349,11 @@ public abstract class PDSimpleFont exten
}
return super.isStandard14();
}
+
+ @Override
+ public void subset(Set<Integer> codePoints) throws IOException
+ {
+ // only TTF subsetting via PDType0Font is currently supported
+ throw new UnsupportedOperationException();
+ }
}
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDTrueTypeFont.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDTrueTypeFont.java?rev=1645796&r1=1645795&r2=1645796&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDTrueTypeFont.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDTrueTypeFont.java Mon Dec 15 23:54:55 2014
@@ -72,7 +72,10 @@ public class PDTrueTypeFont extends PDSi
* @param file a ttf file.
* @return a PDTrueTypeFont instance.
* @throws IOException If there is an error loading the data.
+ *
+ * @deprecated Use {@link PDType0Font#load(PDDocument, File)} instead.
*/
+ @Deprecated
public static PDTrueTypeFont loadTTF(PDDocument doc, File file) throws IOException
{
return new PDTrueTypeFont(doc, new FileInputStream(file));
@@ -85,7 +88,10 @@ public class PDTrueTypeFont extends PDSi
* @param input a ttf file stream
* @return a PDTrueTypeFont instance.
* @throws IOException If there is an error loading the data.
+ *
+ * @deprecated Use {@link PDType0Font#load(PDDocument, InputStream)} instead.
*/
+ @Deprecated
public static PDTrueTypeFont loadTTF(PDDocument doc, InputStream input) throws IOException
{
return new PDTrueTypeFont(doc, input);
@@ -382,7 +388,7 @@ public class PDTrueTypeFont extends PDSi
{
if (CmapTable.PLATFORM_WINDOWS == cmap.getPlatformId())
{
- if (CmapTable.ENCODING_WIN_UNICODE == cmap.getPlatformEncodingId())
+ if (CmapTable.ENCODING_WIN_UNICODE_BMP == cmap.getPlatformEncodingId())
{
cmapWinUnicode = cmap;
}
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDTrueTypeFontEmbedder.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDTrueTypeFontEmbedder.java?rev=1645796&r1=1645795&r2=1645796&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDTrueTypeFontEmbedder.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDTrueTypeFontEmbedder.java Mon Dec 15 23:54:55 2014
@@ -117,4 +117,12 @@ final class PDTrueTypeFontEmbedder exten
{
return fontEncoding;
}
+
+ @Override
+ protected void buildSubset(InputStream ttfSubset, String tag,
+ Map<Integer, Integer> gidToCid) throws IOException
+ {
+ // use PDType0Font instead
+ throw new UnsupportedOperationException();
+ }
}
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType0Font.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType0Font.java?rev=1645796&r1=1645795&r2=1645796&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType0Font.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType0Font.java Mon Dec 15 23:54:55 2014
@@ -21,6 +21,7 @@ import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.fontbox.cmap.CMap;
@@ -47,6 +48,7 @@ public class PDType0Font extends PDFont
private final PDCIDFont descendantFont;
private CMap cMap, cMapUCS2;
private boolean isCMapPredefined;
+ private PDCIDFontType2Embedder embedder;
/**
* Loads a TTF to be embedded into a document.
@@ -106,13 +108,18 @@ public class PDType0Font extends PDFont
*/
private PDType0Font(PDDocument document, InputStream ttfStream) throws IOException
{
- PDCIDFontType2Embedder embedder =
- new PDCIDFontType2Embedder(document, dict, ttfStream, this);
+ embedder = new PDCIDFontType2Embedder(document, dict, ttfStream, this);
descendantFont = embedder.getCIDFont();
readEncoding();
fetchCMapUCS2();
}
+ @Override
+ public void subset(Set<Integer> codePoints) throws IOException
+ {
+ embedder.subset(codePoints);
+ }
+
/**
* Reads the font's Encoding entry, which should be a CMap name/stream.
*/
Added: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/Subsetter.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/Subsetter.java?rev=1645796&view=auto
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/Subsetter.java (added)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/Subsetter.java Mon Dec 15 23:54:55 2014
@@ -0,0 +1,29 @@
+/*
+ * 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.pdfbox.pdmodel.font;
+
+import java.io.IOException;
+import java.util.Set;
+
+/**
+ * Interface for a font subsetter.
+ */
+interface Subsetter
+{
+ public void subset(Set<Integer> codePoints) throws IOException;
+}
Propchange: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/Subsetter.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/TrueTypeEmbedder.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/TrueTypeEmbedder.java?rev=1645796&r1=1645795&r2=1645796&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/TrueTypeEmbedder.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/TrueTypeEmbedder.java Mon Dec 15 23:54:55 2014
@@ -17,6 +17,12 @@
package org.apache.pdfbox.pdmodel.font;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
import org.apache.fontbox.ttf.CmapSubtable;
import org.apache.fontbox.ttf.CmapTable;
import org.apache.fontbox.ttf.HeaderTable;
@@ -24,6 +30,7 @@ import org.apache.fontbox.ttf.Horizontal
import org.apache.fontbox.ttf.OS2WindowsMetricsTable;
import org.apache.fontbox.ttf.PostScriptTable;
import org.apache.fontbox.ttf.TTFParser;
+import org.apache.fontbox.ttf.TTFSubsetter;
import org.apache.fontbox.ttf.TrueTypeFont;
import org.apache.pdfbox.cos.COSDictionary;
import org.apache.pdfbox.cos.COSName;
@@ -41,13 +48,15 @@ import java.io.InputStream;
* @author Ben Litchfield
* @author John Hewson
*/
-abstract class TrueTypeEmbedder
+abstract class TrueTypeEmbedder implements Subsetter
{
private static final int ITALIC = 1;
private static final int OBLIQUE = 256;
+ private static final String BASE25 = "BCDEFGHIJKLMNOPQRSTUVWXYZ";
- protected final TrueTypeFont ttf;
- protected final PDFontDescriptor fontDescriptor;
+ private final PDDocument document;
+ protected TrueTypeFont ttf;
+ protected PDFontDescriptor fontDescriptor;
protected final CmapSubtable cmap;
/**
@@ -56,35 +65,42 @@ abstract class TrueTypeEmbedder
TrueTypeEmbedder(PDDocument document, COSDictionary dict, InputStream ttfStream)
throws IOException
{
+ this.document = document;
+
+ buildFontFile2(ttfStream);
+ dict.setName(COSName.BASE_FONT, ttf.getName());
+
+ // choose a Unicode "cmap"
+ cmap = getUnicodeCmap(ttf.getCmap());
+ }
+
+ public void buildFontFile2(InputStream ttfStream) throws IOException
+ {
PDStream stream = new PDStream(document, ttfStream, false);
stream.getStream().setInt(COSName.LENGTH1, stream.getByteArray().length);
stream.addCompression();
- // as the stream was close within the PDStream constructor, we have to recreate it
- InputStream stream2 = null;
- PDFontDescriptor fd;
+ // as the stream was closed within the PDStream constructor, we have to recreate it
+ InputStream input = null;
try
{
- stream2 = stream.createInputStream();
- ttf = new TTFParser().parse(stream2);
+ input = stream.createInputStream();
+ ttf = new TTFParser().parseEmbedded(input);
if (!isEmbeddingPermitted(ttf))
{
throw new IOException("This font does not permit embedding");
}
- fd = createFontDescriptor(ttf);
+ if (fontDescriptor == null)
+ {
+ fontDescriptor = createFontDescriptor(ttf);
+ }
}
finally
{
- IOUtils.closeQuietly(stream2);
+ IOUtils.closeQuietly(input);
}
- fd.setFontFile2(stream);
- dict.setName(COSName.BASE_FONT, ttf.getName());
-
- fontDescriptor = fd;
-
- // choose a Unicode "cmap"
- cmap = getUnicodeCmap(ttf.getCmap());
+ fontDescriptor.setFontFile2(stream);
}
/**
@@ -114,6 +130,23 @@ abstract class TrueTypeEmbedder
}
/**
+ * Returns true if the fsType in the OS/2 table permits subsetting.
+ */
+ private boolean isSubsettingPermitted(TrueTypeFont ttf) throws IOException
+ {
+ if (ttf.getOS2Windows() != null)
+ {
+ int fsType = ttf.getOS2Windows().getFsType();
+ if ((fsType & OS2WindowsMetricsTable.FSTYPE_NO_SUBSETTING) ==
+ OS2WindowsMetricsTable.FSTYPE_NO_SUBSETTING)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
* Creates a new font descriptor dictionary for the given TTF.
*/
private PDFontDescriptor createFontDescriptor(TrueTypeFont ttf) throws IOException
@@ -180,7 +213,7 @@ abstract class TrueTypeEmbedder
// estimate by summing the typographical +ve ascender and -ve descender
fd.setCapHeight((os2.getTypoAscender() + os2.getTypoDescender()) / scaling);
- // estimate by halfing the typographical ascender
+ // estimate by halving the typographical ascender
fd.setXHeight((os2.getTypoAscender() / 2) / scaling);
}
@@ -205,7 +238,7 @@ abstract class TrueTypeEmbedder
if (cmap == null)
{
cmap = cmapTable.getSubtable(CmapTable.PLATFORM_WINDOWS,
- CmapTable.ENCODING_WIN_UNICODE);
+ CmapTable.ENCODING_WIN_UNICODE_BMP);
}
if (cmap == null)
{
@@ -221,7 +254,6 @@ abstract class TrueTypeEmbedder
return cmap;
}
-
/**
* Returns the FontBox font.
*/
@@ -237,4 +269,77 @@ abstract class TrueTypeEmbedder
{
return fontDescriptor;
}
+
+ @Override
+ public void subset(Set<Integer> codePoints) throws IOException
+ {
+ if (!isSubsettingPermitted(ttf))
+ {
+ throw new IOException("This font does not permit subsetting");
+ }
+
+ // PDF spec required tables (if present), all others will be removed
+ List<String> tables = new ArrayList<String>();
+ tables.add("head");
+ tables.add("hhea");
+ tables.add("loca");
+ tables.add("maxp");
+ tables.add("cvt");
+ tables.add("prep");
+ tables.add("glyf");
+ tables.add("hmtx");
+ tables.add("fpgm");
+ // Windows ClearType
+ tables.add("gasp");
+
+ // set the GIDs to subset
+ TTFSubsetter subsetter = new TTFSubsetter(getTrueTypeFont(), tables);
+ subsetter.addAll(codePoints);
+
+ // calculate deterministic tag based on the chosen subset
+ Map<Integer, Integer> gidToCid = subsetter.getGIDMap();
+ String tag = getTag(gidToCid);
+ subsetter.setPrefix(tag);
+
+ // save the subset font
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ subsetter.writeToStream(out);
+
+ // re-build the embedded font
+ buildSubset(new ByteArrayInputStream(out.toByteArray()), tag, gidToCid);
+ }
+
+ /**
+ * Rebuild a font subset.
+ */
+ protected abstract void buildSubset(InputStream ttfSubset, String tag,
+ Map<Integer, Integer> gidToCid) throws IOException;
+
+ /**
+ * Returns an uppercase 6-character unique tag for the given subset.
+ */
+ public String getTag(Map<Integer, Integer> gidToCid)
+ {
+ // deterministic
+ long num = gidToCid.hashCode();
+
+ // base25 encode
+ StringBuilder sb = new StringBuilder();
+ do
+ {
+ long div = num / 25;
+ int mod = (int)(num % 25);
+ sb.append(BASE25.charAt(mod));
+ num = div;
+ } while (num != 0 && sb.length() < 6);
+
+ // pad
+ while (sb.length() < 6)
+ {
+ sb.insert(0, 'A');
+ }
+
+ sb.append('+');
+ return sb.toString();
+ }
}
Modified: pdfbox/trunk/tools/src/main/java/org/apache/pdfbox/tools/TextToPDF.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/tools/src/main/java/org/apache/pdfbox/tools/TextToPDF.java?rev=1645796&r1=1645795&r2=1645796&view=diff
==============================================================================
--- pdfbox/trunk/tools/src/main/java/org/apache/pdfbox/tools/TextToPDF.java (original)
+++ pdfbox/trunk/tools/src/main/java/org/apache/pdfbox/tools/TextToPDF.java Mon Dec 15 23:54:55 2014
@@ -29,10 +29,9 @@ import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.edit.PDPageContentStream;
import org.apache.pdfbox.pdmodel.font.PDFont;
-import org.apache.pdfbox.pdmodel.font.PDTrueTypeFont;
+import org.apache.pdfbox.pdmodel.font.PDType0Font;
import org.apache.pdfbox.pdmodel.font.PDType1Font;
-
/**
* This will take a text file and ouput a pdf with that text.
*
@@ -225,7 +224,7 @@ public class TextToPDF
else if( args[i].equals( "-ttf" ))
{
i++;
- PDTrueTypeFont font = PDTrueTypeFont.loadTTF( doc, new File( args[i]));
+ PDFont font = PDType0Font.load( doc, new File( args[i]) );
app.setFont( font );
}
else if( args[i].equals( "-fontSize" ))