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/12 22:02:49 UTC
svn commit: r1645072 - in /pdfbox/trunk:
fontbox/src/main/java/org/apache/fontbox/ttf/
pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/
Author: jahewson
Date: Fri Dec 12 21:02:49 2014
New Revision: 1645072
URL: http://svn.apache.org/r1645072
Log:
PDFBOX-2524: Refactor common functionality of PDTrueTypeFont into super class
Added:
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/TrueTypeEmbedder.java (with props)
Modified:
pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/ttf/OS2WindowsMetricsTable.java
pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/ttf/TTFSubsetter.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDTrueTypeFontEmbedder.java
Modified: pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/ttf/OS2WindowsMetricsTable.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/ttf/OS2WindowsMetricsTable.java?rev=1645072&r1=1645071&r2=1645072&view=diff
==============================================================================
--- pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/ttf/OS2WindowsMetricsTable.java (original)
+++ pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/ttf/OS2WindowsMetricsTable.java Fri Dec 12 21:02:49 2014
@@ -483,19 +483,19 @@ public class OS2WindowsMetricsTable exte
}
/**
- * @return Returns the typeLineGap.
+ * @return Returns the typoLineGap.
*/
- public int getTypeLineGap()
+ public int getTypoLineGap()
{
- return typeLineGap;
+ return typoLineGap;
}
/**
- * @param typeLineGapValue The typeLineGap to set.
+ * @param typeLineGapValue The typoLineGap to set.
*/
- public void setTypeLineGap(int typeLineGapValue)
+ public void setTypoLineGap(int typeLineGapValue)
{
- this.typeLineGap = typeLineGapValue;
+ this.typoLineGap = typeLineGapValue;
}
/**
@@ -674,6 +674,46 @@ public class OS2WindowsMetricsTable exte
this.winDescent = winDescentValue;
}
+ /**
+ * Returns the sxHeight.
+ */
+ public int getHeight()
+ {
+ return sxHeight;
+ }
+
+ /**
+ * Returns the sCapHeight.
+ */
+ public int getCapHeight()
+ {
+ return sCapHeight;
+ }
+
+ /**
+ * Returns the usDefaultChar.
+ */
+ public int getDefaultChar()
+ {
+ return usDefaultChar;
+ }
+
+ /**
+ * Returns the usBreakChar.
+ */
+ public int getBreakChar()
+ {
+ return usBreakChar;
+ }
+
+ /**
+ * Returns the usMaxContext.
+ */
+ public int getMaxContext()
+ {
+ return usMaxContext;
+ }
+
private int version;
private short averageCharWidth;
private int weightClass;
@@ -702,11 +742,16 @@ public class OS2WindowsMetricsTable exte
private int lastCharIndex;
private int typoAscender;
private int typoDescender;
- private int typeLineGap;
+ private int typoLineGap;
private int winAscent;
private int winDescent;
private long codePageRange1 = -1;
private long codePageRange2 = -1;
+ private int sxHeight;
+ private int sCapHeight;
+ private int usDefaultChar;
+ private int usBreakChar;
+ private int usMaxContext;
/**
* A tag that identifies this table type.
@@ -750,7 +795,7 @@ public class OS2WindowsMetricsTable exte
lastCharIndex = data.readUnsignedShort();
typoAscender = data.readSignedShort();
typoDescender = data.readSignedShort();
- typeLineGap = data.readSignedShort();
+ typoLineGap = data.readSignedShort();
winAscent = data.readUnsignedShort();
winDescent = data.readUnsignedShort();
if (version >= 1)
@@ -758,6 +803,14 @@ public class OS2WindowsMetricsTable exte
codePageRange1 = data.readUnsignedInt();
codePageRange2 = data.readUnsignedInt();
}
+ if (version >= 1.2)
+ {
+ sxHeight = data.readSignedShort();
+ sCapHeight = data.readSignedShort();
+ usDefaultChar = data.readUnsignedShort();
+ usBreakChar = data.readUnsignedShort();
+ usMaxContext = data.readUnsignedShort();
+ }
initialized = true;
}
}
Modified: pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/ttf/TTFSubsetter.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/ttf/TTFSubsetter.java?rev=1645072&r1=1645071&r2=1645072&view=diff
==============================================================================
--- pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/ttf/TTFSubsetter.java (original)
+++ pdfbox/trunk/fontbox/src/main/java/org/apache/fontbox/ttf/TTFSubsetter.java Fri Dec 12 21:02:49 2014
@@ -536,7 +536,7 @@ public class TTFSubsetter
*/
writeUint16(dos,os2.getTypoAscender());
writeUint16(dos,os2.getTypoDescender());
- writeUint16(dos,os2.getTypeLineGap());
+ writeUint16(dos,os2.getTypoLineGap());
writeUint16(dos,os2.getWinAscent());
writeUint16(dos,os2.getWinDescent());
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=1645072&r1=1645071&r2=1645072&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 Fri Dec 12 21:02:49 2014
@@ -14,39 +14,23 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.pdfbox.pdmodel.font;
-import org.apache.fontbox.ttf.CmapSubtable;
-import org.apache.fontbox.ttf.CmapTable;
-import org.apache.fontbox.ttf.GlyphData;
-import org.apache.fontbox.ttf.GlyphTable;
-import org.apache.fontbox.ttf.HeaderTable;
-import org.apache.fontbox.ttf.HorizontalHeaderTable;
-import org.apache.fontbox.ttf.HorizontalMetricsTable;
-import org.apache.fontbox.ttf.NameRecord;
-import org.apache.fontbox.ttf.NamingTable;
-import org.apache.fontbox.ttf.OS2WindowsMetricsTable;
-import org.apache.fontbox.ttf.PostScriptTable;
-import org.apache.fontbox.ttf.TTFParser;
-import org.apache.fontbox.ttf.TrueTypeFont;
-import org.apache.pdfbox.cos.COSDictionary;
-import org.apache.pdfbox.cos.COSName;
-import org.apache.pdfbox.pdmodel.font.encoding.Encoding;
-import org.apache.pdfbox.pdmodel.font.encoding.GlyphList;
-import org.apache.pdfbox.pdmodel.font.encoding.WinAnsiEncoding;
-import org.apache.pdfbox.io.IOUtils;
-import org.apache.pdfbox.pdmodel.PDDocument;
-import org.apache.pdfbox.pdmodel.common.COSArrayList;
-import org.apache.pdfbox.pdmodel.common.PDRectangle;
-import org.apache.pdfbox.pdmodel.common.PDStream;
+package org.apache.pdfbox.pdmodel.font;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
+import org.apache.fontbox.ttf.HorizontalMetricsTable;
+import org.apache.pdfbox.cos.COSDictionary;
+import org.apache.pdfbox.cos.COSName;
+import org.apache.pdfbox.pdmodel.PDDocument;
+import org.apache.pdfbox.pdmodel.common.COSArrayList;
+import org.apache.pdfbox.pdmodel.font.encoding.Encoding;
+import org.apache.pdfbox.pdmodel.font.encoding.GlyphList;
+import org.apache.pdfbox.pdmodel.font.encoding.WinAnsiEncoding;
/**
* Embedded PDTrueTypeFont builder. Helper class to populate a PDTrueTypeFont from a TTF.
@@ -54,209 +38,42 @@ import java.util.Map;
* @author John Hewson
* @author Ben Litchfield
*/
-class PDTrueTypeFontEmbedder
+final class PDTrueTypeFontEmbedder extends TrueTypeEmbedder
{
private final Encoding fontEncoding;
- private final TrueTypeFont ttf;
- private final PDFontDescriptor fontDescriptor;
/**
- * Creates a new TrueType font for embedding.
+ * Creates a new TrueType font embedder for the given TTF as a PDTrueTypeFont.
+ *
+ * @param document parent document
+ * @param dict font dictionary
+ * @param ttfStream TTF stream
+ * @throws IOException if the TTF could not be read
*/
PDTrueTypeFontEmbedder(PDDocument document, COSDictionary dict, InputStream ttfStream)
throws IOException
{
+ super(document, dict, ttfStream);
dict.setItem(COSName.SUBTYPE, COSName.TRUE_TYPE);
- PDStream stream = new PDStream(document, ttfStream, false);
- stream.getStream().setInt(COSName.LENGTH1, stream.getByteArray().length); // todo: wrong?
- stream.addCompression();
-
- // only support winansi encoding right now, should really
- // just use Identity-H with unicode mapping
+ // only support WinAnsiEncoding encoding right now
Encoding encoding = new WinAnsiEncoding(); // fixme: read encoding from TTF
-
this.fontEncoding = encoding;
dict.setItem(COSName.ENCODING, encoding.getCOSObject());
- // as the stream was close within the PDStream constructor, we have to recreate it
- InputStream stream2 = null;
- PDFontDescriptor fd;
- try
- {
- stream2 = stream.createInputStream();
- ttf = new TTFParser().parse(stream2);
- fd = createFontDescriptor(dict, ttf);
- }
- finally
- {
- IOUtils.closeQuietly(stream2);
- }
+ // add the font descriptor
+ dict.setItem(COSName.FONT_DESC, fontDescriptor);
- fd.setFontFile2(stream);
- dict.setItem(COSName.FONT_DESC, fd);
- fontDescriptor = fd;
+ // set the glyph widths
+ setWidths(dict);
}
- // creates a new font descriptor dictionary for the given TTF
- private PDFontDescriptor createFontDescriptor(COSDictionary dict, TrueTypeFont ttf)
- throws IOException
+ /**
+ * Sets the glyph widths in the font dictionary.
+ */
+ private void setWidths(COSDictionary font) throws IOException
{
- PDFontDescriptor fd = new PDFontDescriptor();
-
- NamingTable naming = ttf.getNaming();
- List<NameRecord> records = naming.getNameRecords();
- for (NameRecord nr : records)
- {
- if (nr.getNameId() == NameRecord.NAME_POSTSCRIPT_NAME)
- {
- dict.setName(COSName.BASE_FONT, nr.getString());
- fd.setFontName(nr.getString());
- }
- else if (nr.getNameId() == NameRecord.NAME_FONT_FAMILY_NAME)
- {
- fd.setFontFamily(nr.getString());
- }
- }
-
- OS2WindowsMetricsTable os2 = ttf.getOS2Windows();
- boolean isSymbolic = false;
- switch (os2.getFamilyClass())
- {
- case OS2WindowsMetricsTable.FAMILY_CLASS_SYMBOLIC:
- isSymbolic = true;
- break;
- case OS2WindowsMetricsTable.FAMILY_CLASS_SCRIPTS:
- fd.setScript(true);
- break;
- case OS2WindowsMetricsTable.FAMILY_CLASS_CLAREDON_SERIFS:
- case OS2WindowsMetricsTable.FAMILY_CLASS_FREEFORM_SERIFS:
- case OS2WindowsMetricsTable.FAMILY_CLASS_MODERN_SERIFS:
- case OS2WindowsMetricsTable.FAMILY_CLASS_OLDSTYLE_SERIFS:
- case OS2WindowsMetricsTable.FAMILY_CLASS_SLAB_SERIFS:
- fd.setSerif(true);
- break;
- }
-
- switch (os2.getWidthClass())
- {
- case OS2WindowsMetricsTable.WIDTH_CLASS_ULTRA_CONDENSED:
- fd.setFontStretch("UltraCondensed");
- break;
- case OS2WindowsMetricsTable.WIDTH_CLASS_EXTRA_CONDENSED:
- fd.setFontStretch("ExtraCondensed");
- break;
- case OS2WindowsMetricsTable.WIDTH_CLASS_CONDENSED:
- fd.setFontStretch("Condensed");
- break;
- case OS2WindowsMetricsTable.WIDTH_CLASS_SEMI_CONDENSED:
- fd.setFontStretch("SemiCondensed");
- break;
- case OS2WindowsMetricsTable.WIDTH_CLASS_MEDIUM:
- fd.setFontStretch("Normal");
- break;
- case OS2WindowsMetricsTable.WIDTH_CLASS_SEMI_EXPANDED:
- fd.setFontStretch("SemiExpanded");
- break;
- case OS2WindowsMetricsTable.WIDTH_CLASS_EXPANDED:
- fd.setFontStretch("Expanded");
- break;
- case OS2WindowsMetricsTable.WIDTH_CLASS_EXTRA_EXPANDED:
- fd.setFontStretch("ExtraExpanded");
- break;
- case OS2WindowsMetricsTable.WIDTH_CLASS_ULTRA_EXPANDED:
- fd.setFontStretch("UltraExpanded");
- break;
- }
- fd.setFontWeight(os2.getWeightClass());
- fd.setSymbolic(isSymbolic);
- fd.setNonSymbolic(!isSymbolic);
-
- // todo retval.setItalic
- // todo retval.setAllCap
- // todo retval.setSmallCap
- // todo retval.setForceBold
-
- HeaderTable header = ttf.getHeader();
- PDRectangle rect = new PDRectangle();
- float scaling = 1000f / header.getUnitsPerEm();
- rect.setLowerLeftX(header.getXMin() * scaling);
- rect.setLowerLeftY(header.getYMin() * scaling);
- rect.setUpperRightX(header.getXMax() * scaling);
- rect.setUpperRightY(header.getYMax() * scaling);
- fd.setFontBoundingBox(rect);
-
- HorizontalHeaderTable hHeader = ttf.getHorizontalHeader();
- fd.setAscent(hHeader.getAscender() * scaling);
- fd.setDescent(hHeader.getDescender() * scaling);
-
- GlyphTable glyphTable = ttf.getGlyph();
- GlyphData[] glyphs = glyphTable.getGlyphs();
-
- PostScriptTable ps = ttf.getPostScript();
- fd.setFixedPitch(ps.getIsFixedPitch() > 0);
- fd.setItalicAngle(ps.getItalicAngle());
-
- String[] names = ps.getGlyphNames();
-
- if (names != null)
- {
- for (int i = 0; i < names.length; i++)
- {
- // if we have a capital H then use that, otherwise use the tallest letter
- if (names[i].equals("H"))
- {
- fd.setCapHeight(glyphs[i].getBoundingBox().getUpperRightY() / scaling);
- }
- if (names[i].equals("x"))
- {
- fd.setXHeight(glyphs[i].getBoundingBox().getUpperRightY() / scaling);
- }
- }
- }
-
- // hmm there does not seem to be a clear definition for StemV,
- // this is close enough and I am told it doesn't usually get used.
- fd.setStemV(fd.getFontBoundingBox().getWidth() * .13f);
-
- CmapTable cmapTable = ttf.getCmap();
- CmapSubtable uniMap = cmapTable.getSubtable(CmapTable.PLATFORM_UNICODE,
- CmapTable.ENCODING_UNICODE_2_0_FULL);
- if (uniMap == null)
- {
- uniMap = cmapTable.getSubtable(CmapTable.PLATFORM_UNICODE,
- CmapTable.ENCODING_UNICODE_2_0_BMP);
- }
- if (uniMap == null)
- {
- uniMap = cmapTable.getSubtable(CmapTable.PLATFORM_WINDOWS,
- CmapTable.ENCODING_WIN_UNICODE);
- }
- if (uniMap == null)
- {
- // Microsoft's "Recommendations for OpenType Fonts" says that "Symbol" encoding
- // actually means "Unicode, non-standard character set"
- uniMap = cmapTable.getSubtable(CmapTable.PLATFORM_WINDOWS,
- CmapTable.ENCODING_WIN_SYMBOL);
- }
- if (uniMap == null)
- {
- // there should always be a usable cmap, if this happens we haven't tried hard enough
- // to find one. Furthermore, if we loaded the font from disk then we should've checked
- // first to see that it had a suitable cmap before calling createFontDescriptor
- throw new IllegalArgumentException("ttf: no suitable cmap for font '" +
- ttf.getNaming().getFontFamily() + "', found: " +
- Arrays.toString(cmapTable.getCmaps()));
- }
-
- if (this.getFontEncoding() == null)
- {
- // todo: calling this.getFontEncoding() doesn't work if the font is loaded
- // from the local system, because it relies on the FontDescriptor!
- // We make do for now by returning an incomplete descriptor pending further
- // refactoring of PDFont#determineEncoding().
- return fd;
- }
+ float scaling = 1000f / ttf.getHeader().getUnitsPerEm();
Map<Integer, String> codeToName = this.getFontEncoding().getCodeToNameMap();
@@ -265,33 +82,35 @@ class PDTrueTypeFontEmbedder
HorizontalMetricsTable hMet = ttf.getHorizontalMetrics();
int[] widthValues = hMet.getAdvanceWidth();
+
// some monospaced fonts provide only one value for the width
- // instead of an array containing the same value for every glyphid
- boolean isMonospaced = fd.isFixedPitch() || widthValues.length == 1;
- int nWidths = lastChar - firstChar + 1;
- List<Integer> widths = new ArrayList<Integer>(nWidths);
+ // instead of an array containing the same value for every glyph id
+ boolean isMonospaced = ttf.getHorizontalHeader().getNumberOfHMetrics() == 1;
+
+ int numWidths = lastChar - firstChar + 1;
+ List<Integer> widths = new ArrayList<Integer>(numWidths);
+
// use the first width as default
// proportional fonts -> width of the .notdef character
// monospaced-fonts -> the first width
int defaultWidth = Math.round(widthValues[0] * scaling);
- for (int i = 0; i < nWidths; i++)
+ for (int i = 0; i < numWidths; i++)
{
widths.add(defaultWidth);
}
- // A character code is mapped to a glyph name via the provided font encoding
- // Afterwards, the glyph name is translated to a glyph ID.
- // For details, see PDFReference16.pdf, Section 5.5.5, p.401
- //
+ // a character code is mapped to a glyph name via the provided font encoding
+ // afterwards, the glyph name is translated to a glyph ID.
for (Map.Entry<Integer, String> e : codeToName.entrySet())
{
String name = e.getValue();
// pdf code to unicode by glyph list.
if (!name.equals(".notdef"))
{
- String c = GlyphList.getAdobeGlyphList().toUnicode(name); // todo: we're supposed to use the 'provided font encoding'
+ // todo: we're supposed to use the 'provided font encoding'
+ String c = GlyphList.getAdobeGlyphList().toUnicode(name);
int charCode = c.codePointAt(0);
- int gid = uniMap.getGlyphId(charCode);
+ int gid = cmap.getGlyphId(charCode);
if (gid != 0)
{
if (isMonospaced)
@@ -306,11 +125,10 @@ class PDTrueTypeFontEmbedder
}
}
}
- dict.setItem(COSName.WIDTHS, COSArrayList.converterToCOSArray(widths));
- dict.setInt(COSName.FIRST_CHAR, firstChar);
- dict.setInt(COSName.LAST_CHAR, lastChar);
- return fd;
+ font.setInt(COSName.FIRST_CHAR, firstChar);
+ font.setInt(COSName.LAST_CHAR, lastChar);
+ font.setItem(COSName.WIDTHS, COSArrayList.converterToCOSArray(widths));
}
/**
@@ -320,20 +138,4 @@ class PDTrueTypeFontEmbedder
{
return fontEncoding;
}
-
- /**
- * Returns the FontBox font.
- */
- public TrueTypeFont getTrueTypeFont()
- {
- return ttf;
- }
-
- /**
- * Returns the font descriptor.
- */
- public PDFontDescriptor getFontDescriptor()
- {
- return fontDescriptor;
- }
}
Added: 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=1645072&view=auto
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/TrueTypeEmbedder.java (added)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/TrueTypeEmbedder.java Fri Dec 12 21:02:49 2014
@@ -0,0 +1,210 @@
+/*
+ * 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 org.apache.fontbox.ttf.CmapSubtable;
+import org.apache.fontbox.ttf.CmapTable;
+import org.apache.fontbox.ttf.HeaderTable;
+import org.apache.fontbox.ttf.HorizontalHeaderTable;
+import org.apache.fontbox.ttf.OS2WindowsMetricsTable;
+import org.apache.fontbox.ttf.PostScriptTable;
+import org.apache.fontbox.ttf.TTFParser;
+import org.apache.fontbox.ttf.TrueTypeFont;
+import org.apache.pdfbox.cos.COSDictionary;
+import org.apache.pdfbox.cos.COSName;
+import org.apache.pdfbox.io.IOUtils;
+import org.apache.pdfbox.pdmodel.PDDocument;
+import org.apache.pdfbox.pdmodel.common.PDRectangle;
+import org.apache.pdfbox.pdmodel.common.PDStream;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * Common functionality for embedding TrueType fonts.
+ *
+ * @author Ben Litchfield
+ * @author John Hewson
+ */
+abstract class TrueTypeEmbedder
+{
+ private static final int ITALIC = 1;
+ private static final int OBLIQUE = 256;
+
+ protected final TrueTypeFont ttf;
+ protected final PDFontDescriptor fontDescriptor;
+ protected final CmapSubtable cmap;
+
+ /**
+ * Creates a new TrueType font for embedding.
+ */
+ TrueTypeEmbedder(PDDocument document, COSDictionary dict, 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;
+ try
+ {
+ stream2 = stream.createInputStream();
+ ttf = new TTFParser().parse(stream2);
+ fd = createFontDescriptor(ttf);
+ }
+ finally
+ {
+ IOUtils.closeQuietly(stream2);
+ }
+
+ fd.setFontFile2(stream);
+ dict.setName(COSName.BASE_FONT, ttf.getName());
+
+ fontDescriptor = fd;
+
+ // choose a Unicode "cmap"
+ cmap = getUnicodeCmap(ttf.getCmap());
+ }
+
+ /**
+ * Creates a new font descriptor dictionary for the given TTF.
+ */
+ private PDFontDescriptor createFontDescriptor(TrueTypeFont ttf) throws IOException
+ {
+ PDFontDescriptor fd = new PDFontDescriptor();
+ fd.setFontName(ttf.getName());
+
+ OS2WindowsMetricsTable os2 = ttf.getOS2Windows();
+ PostScriptTable post = ttf.getPostScript();
+
+ // Flags
+ fd.setFixedPitch(post.getIsFixedPitch() > 0 ||
+ ttf.getHorizontalHeader().getNumberOfHMetrics() == 1);
+
+ int fsSelection = os2.getFsSelection();
+ fd.setItalic((fsSelection & ITALIC) == fsSelection ||
+ (fsSelection & OBLIQUE) == fsSelection);
+
+ switch (os2.getFamilyClass())
+ {
+ case OS2WindowsMetricsTable.FAMILY_CLASS_CLAREDON_SERIFS:
+ case OS2WindowsMetricsTable.FAMILY_CLASS_FREEFORM_SERIFS:
+ case OS2WindowsMetricsTable.FAMILY_CLASS_MODERN_SERIFS:
+ case OS2WindowsMetricsTable.FAMILY_CLASS_OLDSTYLE_SERIFS:
+ case OS2WindowsMetricsTable.FAMILY_CLASS_SLAB_SERIFS:
+ fd.setSerif(true);
+ break;
+ case OS2WindowsMetricsTable.FAMILY_CLASS_SCRIPTS:
+ fd.setScript(true);
+ break;
+ }
+
+ fd.setFontWeight(os2.getWeightClass());
+
+ fd.setSymbolic(true);
+ fd.setNonSymbolic(false);
+
+ // ItalicAngle
+ fd.setItalicAngle(post.getItalicAngle());
+
+ // FontBBox
+ HeaderTable header = ttf.getHeader();
+ PDRectangle rect = new PDRectangle();
+ float scaling = 1000f / header.getUnitsPerEm();
+ rect.setLowerLeftX(header.getXMin() * scaling);
+ rect.setLowerLeftY(header.getYMin() * scaling);
+ rect.setUpperRightX(header.getXMax() * scaling);
+ rect.setUpperRightY(header.getYMax() * scaling);
+ fd.setFontBoundingBox(rect);
+
+ // Ascent, Descent
+ HorizontalHeaderTable hHeader = ttf.getHorizontalHeader();
+ fd.setAscent(hHeader.getAscender() * scaling);
+ fd.setDescent(hHeader.getDescender() * scaling);
+
+ // CapHeight, XHeight
+ if (os2.getVersion() >= 1.2)
+ {
+ fd.setCapHeight(os2.getCapHeight() / scaling);
+ fd.setXHeight(os2.getHeight() / scaling);
+ }
+ else
+ {
+ // estimate by summing the typographical +ve ascender and -ve descender
+ fd.setCapHeight((os2.getTypoAscender() + os2.getTypoDescender()) / scaling);
+
+ // estimate by halfing the typographical ascender
+ fd.setXHeight((os2.getTypoAscender() / 2) / scaling);
+ }
+
+ // StemV - there's no true TTF equivalent of this, so we estimate it
+ fd.setStemV(fd.getFontBoundingBox().getWidth() * .13f);
+
+ return fd;
+ }
+
+ /**
+ * Returns the best Unicode from the font (the most general).
+ */
+ private CmapSubtable getUnicodeCmap(CmapTable cmapTable) throws IOException
+ {
+ CmapSubtable cmap = cmapTable.getSubtable(CmapTable.PLATFORM_UNICODE,
+ CmapTable.ENCODING_UNICODE_2_0_FULL);
+ if (cmap == null)
+ {
+ cmap = cmapTable.getSubtable(CmapTable.PLATFORM_UNICODE,
+ CmapTable.ENCODING_UNICODE_2_0_BMP);
+ }
+ if (cmap == null)
+ {
+ cmap = cmapTable.getSubtable(CmapTable.PLATFORM_WINDOWS,
+ CmapTable.ENCODING_WIN_UNICODE);
+ }
+ if (cmap == null)
+ {
+ // Microsoft's "Recommendations for OpenType Fonts" says that "Symbol" encoding
+ // actually means "Unicode, non-standard character set"
+ cmap = cmapTable.getSubtable(CmapTable.PLATFORM_WINDOWS,
+ CmapTable.ENCODING_WIN_SYMBOL);
+ }
+ if (cmap == null)
+ {
+ throw new IOException("The TrueType font does not contain a Unicode cmap");
+ }
+ return cmap;
+ }
+
+
+ /**
+ * Returns the FontBox font.
+ */
+ public TrueTypeFont getTrueTypeFont()
+ {
+ return ttf;
+ }
+
+ /**
+ * Returns the font descriptor.
+ */
+ public PDFontDescriptor getFontDescriptor()
+ {
+ return fontDescriptor;
+ }
+}
Propchange: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/TrueTypeEmbedder.java
------------------------------------------------------------------------------
svn:eol-style = native