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:11:22 UTC
svn commit: r1645075 - in /pdfbox/trunk:
examples/src/main/java/org/apache/pdfbox/examples/pdmodel/ parent/ pdfbox/
pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/
Author: jahewson
Date: Fri Dec 12 21:11:22 2014
New Revision: 1645075
URL: http://svn.apache.org/r1645075
Log:
PDFBOX-2524: Embedding of Type0/CIDFontType2 fonts, thanks to Keiji Suzuki
Added:
pdfbox/trunk/examples/src/main/java/org/apache/pdfbox/examples/pdmodel/EmbeddedFonts.java (with props)
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDCIDFontType2Embedder.java (with props)
Modified:
pdfbox/trunk/parent/pom.xml
pdfbox/trunk/pdfbox/pom.xml
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDType0Font.java
Added: pdfbox/trunk/examples/src/main/java/org/apache/pdfbox/examples/pdmodel/EmbeddedFonts.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/examples/src/main/java/org/apache/pdfbox/examples/pdmodel/EmbeddedFonts.java?rev=1645075&view=auto
==============================================================================
--- pdfbox/trunk/examples/src/main/java/org/apache/pdfbox/examples/pdmodel/EmbeddedFonts.java (added)
+++ pdfbox/trunk/examples/src/main/java/org/apache/pdfbox/examples/pdmodel/EmbeddedFonts.java Fri Dec 12 21:11:22 2014
@@ -0,0 +1,66 @@
+/*
+ * 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.examples.pdmodel;
+
+import java.io.File;
+import java.io.IOException;
+import org.apache.pdfbox.pdmodel.PDDocument;
+import org.apache.pdfbox.pdmodel.PDPage;
+import org.apache.pdfbox.pdmodel.common.PDRectangle;
+import org.apache.pdfbox.pdmodel.edit.PDPageContentStream;
+import org.apache.pdfbox.pdmodel.font.PDType0Font;
+
+/**
+ * An example of using an embedded TrueType font with Unicode text.
+ *
+ * @author Keiji Suzuki
+ * @author John Hewson
+ */
+public class EmbeddedFonts
+{
+ public static void main(String[] args) throws IOException
+ {
+ PDDocument document = new PDDocument();
+ PDPage page = new PDPage(PDRectangle.A4);
+ document.addPage(page);
+
+ String dir = "../pdfbox/src/main/resources/org/apache/pdfbox/resources/ttf/";
+ PDType0Font font = PDType0Font.load(document, new File(dir + "LiberationSans-Regular.ttf"));
+
+ PDPageContentStream stream = new PDPageContentStream(document, page);
+
+ stream.beginText();
+ stream.setFont(font, 12);
+ stream.setLeading(12 * 1.2);
+
+ stream.moveTextPositionByAmount(50, 600);
+ stream.drawString("PDFBox Unicode with Embedded TrueType Font");
+ stream.newLine();
+
+ stream.drawString("Supports full Unicode text ?");
+ stream.newLine();
+
+ stream.drawString("English ??????? ???? Ti?ng Vi?t");
+
+ stream.endText();
+ stream.close();
+
+ document.save("example.pdf");
+ document.close();
+ }
+}
Propchange: pdfbox/trunk/examples/src/main/java/org/apache/pdfbox/examples/pdmodel/EmbeddedFonts.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: pdfbox/trunk/parent/pom.xml
URL: http://svn.apache.org/viewvc/pdfbox/trunk/parent/pom.xml?rev=1645075&r1=1645074&r2=1645075&view=diff
==============================================================================
--- pdfbox/trunk/parent/pom.xml (original)
+++ pdfbox/trunk/parent/pom.xml Fri Dec 12 21:11:22 2014
@@ -46,7 +46,8 @@
</issueManagement>
<properties>
- <project.build.sourceEncoding>ISO-8859-1</project.build.sourceEncoding>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>
<dependencyManagement>
@@ -149,6 +150,7 @@
<showDeprecation>true</showDeprecation>
<target>1.6</target>
<source>1.6</source>
+ <encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
Modified: pdfbox/trunk/pdfbox/pom.xml
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/pom.xml?rev=1645075&r1=1645074&r2=1645075&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/pom.xml (original)
+++ pdfbox/trunk/pdfbox/pom.xml Fri Dec 12 21:11:22 2014
@@ -95,14 +95,6 @@
</resources>
<plugins>
<plugin>
- <artifactId>maven-compiler-plugin</artifactId>
- <configuration>
- <showDeprecation>true</showDeprecation>
- <target>1.6</target>
- <source>1.6</source>
- </configuration>
- </plugin>
- <plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>-Xmx128m</argLine>
Added: 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=1645075&view=auto
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDCIDFontType2Embedder.java (added)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDCIDFontType2Embedder.java Fri Dec 12 21:11:22 2014
@@ -0,0 +1,215 @@
+/*
+ * 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.InputStream;
+import java.io.IOException;
+
+import org.apache.pdfbox.cos.COSArray;
+import org.apache.pdfbox.cos.COSDictionary;
+import org.apache.pdfbox.cos.COSInteger;
+import org.apache.pdfbox.cos.COSName;
+import org.apache.pdfbox.pdmodel.PDDocument;
+
+/**
+ * Embedded PDCIDFontType2 builder. Helper class to populate a PDCIDFontType2 and its parent
+ * PDType0Font from a TTF.
+ *
+ * @author Keiji Suzuki
+ * @author John Hewson
+ */
+final class PDCIDFontType2Embedder extends TrueTypeEmbedder
+{
+ private final PDType0Font parent;
+ private final COSDictionary cidFont;
+
+ /**
+ * Creates a new TrueType font embedder for the given TTF as a PDCIDFontType2.
+ *
+ * @param document parent document
+ * @param dict font dictionary
+ * @param ttfStream TTF stream
+ * @param parent parent Type 0 font
+ * @throws IOException if the TTF could not be read
+ */
+ PDCIDFontType2Embedder(PDDocument document, COSDictionary dict, InputStream ttfStream,
+ PDType0Font parent) throws IOException
+ {
+ super(document, dict, ttfStream);
+ this.parent = parent;
+
+ // parent Type 0 font
+ dict.setItem(COSName.SUBTYPE, COSName.TYPE0);
+ dict.setName(COSName.BASE_FONT, fontDescriptor.getFontName());
+ dict.setItem(COSName.ENCODING, COSName.IDENTITY_H); // CID = GID
+
+ // descendant CIDFont
+ cidFont = createCIDFont();
+ COSArray descendantFonts = new COSArray();
+ descendantFonts.add(cidFont);
+ dict.setItem(COSName.DESCENDANT_FONTS, descendantFonts);
+ }
+
+ private COSDictionary toCIDSystemInfo(String registry, String ordering, int supplement)
+ {
+ COSDictionary info = new COSDictionary();
+ info.setString(COSName.REGISTRY, registry);
+ info.setString(COSName.ORDERING, ordering);
+ info.setInt(COSName.SUPPLEMENT, supplement);
+ return info;
+ }
+
+ private COSDictionary createCIDFont() throws IOException
+ {
+ COSDictionary cidFont = new COSDictionary();
+
+ // Type, Subtype
+ cidFont.setItem(COSName.TYPE, COSName.FONT);
+ cidFont.setItem(COSName.SUBTYPE, COSName.CID_FONT_TYPE2);
+
+ // BaseFont
+ cidFont.setName(COSName.BASE_FONT, fontDescriptor.getFontName());
+
+ // CIDSystemInfo
+ COSDictionary info = toCIDSystemInfo("Adobe", "Identity", 0);
+ cidFont.setItem(COSName.CIDSYSTEMINFO, info);
+
+ // FontDescriptor
+ cidFont.setItem(COSName.FONT_DESC, fontDescriptor.getCOSObject());
+
+ // W - widths
+ int[] subwidths = ttf.getHorizontalMetrics().getAdvanceWidth();
+ int[] gidwidths = new int[subwidths.length*2];
+ for (int i = 0; i < subwidths.length; i++)
+ {
+ gidwidths[i * 2] = i;
+ gidwidths[i * 2 + 1] = subwidths[i];
+ }
+ cidFont.setItem(COSName.W, getWidths(gidwidths));
+
+ // CIDToGIDMap - todo: optional (can be used for easy sub-setting)
+ cidFont.setItem(COSName.CID_TO_GID_MAP, COSName.IDENTITY);
+
+ return cidFont;
+ }
+
+ private COSArray getWidths(int[] widths) throws IOException
+ {
+ if (widths.length == 0)
+ {
+ throw new IllegalArgumentException("length of widths must be > 0");
+ }
+
+ float scaling = 1000f / ttf.getHeader().getUnitsPerEm();
+
+ long lastCid = widths[0];
+ long lastValue = Math.round(widths[1] * scaling);
+
+ COSArray inner = null;
+ COSArray outer = new COSArray();
+ outer.add(COSInteger.get(lastCid));
+
+ final int FIRST = 0, BRACKET = 1, SERIAL = 2;
+ int state = FIRST;
+
+ for (int i = 2; i < widths.length; i += 2)
+ {
+ long cid = widths[i];
+ long value = Math.round(widths[i + 1] * scaling);
+
+ switch (state)
+ {
+ case FIRST:
+ if (cid == lastCid + 1 && value == lastValue)
+ {
+ state = SERIAL;
+ }
+ else if (cid == lastCid + 1)
+ {
+ state = BRACKET;
+ inner = new COSArray();
+ inner.add(COSInteger.get(lastValue));
+ }
+ else
+ {
+ inner = new COSArray();
+ inner.add(COSInteger.get(lastValue));
+ outer.add(inner);
+ outer.add(COSInteger.get(cid));
+ }
+ break;
+ case BRACKET:
+ if (cid == lastCid + 1 && value == lastValue)
+ {
+ state = SERIAL;
+ outer.add(inner);
+ outer.add(COSInteger.get(lastCid));
+ }
+ else if (cid == lastCid + 1)
+ {
+ inner.add(COSInteger.get(lastValue));
+ }
+ else
+ {
+ state = FIRST;
+ inner.add(COSInteger.get(lastValue));
+ outer.add(inner);
+ outer.add(COSInteger.get(cid));
+ }
+ break;
+ case SERIAL:
+ if (cid != lastCid + 1 || value != lastValue)
+ {
+ outer.add(COSInteger.get(lastCid));
+ outer.add(COSInteger.get(lastValue));
+ outer.add(COSInteger.get(cid));
+ state = FIRST;
+ }
+ break;
+ }
+ lastValue = value;
+ lastCid = cid;
+ }
+
+ switch (state)
+ {
+ case FIRST:
+ inner = new COSArray();
+ inner.add(COSInteger.get(lastValue));
+ outer.add(inner);
+ break;
+ case BRACKET:
+ inner.add(COSInteger.get(lastValue));
+ outer.add(inner);
+ break;
+ case SERIAL:
+ outer.add(COSInteger.get(lastCid));
+ outer.add(COSInteger.get(lastValue));
+ break;
+ }
+ return outer;
+ }
+
+ /**
+ * Returns the descendant CIDFont.
+ */
+ public PDCIDFont getCIDFont() throws IOException
+ {
+ return PDFontFactory.createDescendantFont(cidFont, parent);
+ }
+}
Propchange: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDCIDFontType2Embedder.java
------------------------------------------------------------------------------
svn:eol-style = native
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=1645075&r1=1645074&r2=1645075&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 Fri Dec 12 21:11:22 2014
@@ -16,6 +16,8 @@
*/
package org.apache.pdfbox.pdmodel.font;
+import java.io.File;
+import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
@@ -27,6 +29,7 @@ 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.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.font.encoding.GlyphList;
import org.apache.pdfbox.pdmodel.font.encoding.StandardEncoding;
import org.apache.pdfbox.util.Matrix;
@@ -46,7 +49,33 @@ public class PDType0Font extends PDFont
private boolean isCMapPredefined;
/**
- * Constructor.
+ * Loads a TTF to be embedded into a document.
+ *
+ * @param doc The PDF document that will hold the embedded font.
+ * @param file A TrueType font.
+ * @return A Type0 font with a CIDFontType2 descendant.
+ * @throws IOException If there is an error reading the font file.
+ */
+ public static PDType0Font load(PDDocument doc, File file) throws IOException
+ {
+ return new PDType0Font(doc, new FileInputStream(file));
+ }
+
+ /**
+ * Loads a TTF to be embedded into a document.
+ *
+ * @param doc The PDF document that will hold the embedded font.
+ * @param input A TrueType font.
+ * @return A Type0 font with a CIDFontType2 descendant.
+ * @throws IOException If there is an error reading the font stream.
+ */
+ public static PDType0Font load(PDDocument doc, InputStream input) throws IOException
+ {
+ return new PDType0Font(doc, input);
+ }
+
+ /**
+ * Constructor for reading a Type0 font from a PDF file.
*
* @param fontDictionary The font dictionary according to the PDF specification.
*/
@@ -73,6 +102,16 @@ public class PDType0Font extends PDFont
}
/**
+ * Private. Creates a new TrueType font for embedding.
+ */
+ private PDType0Font(PDDocument document, InputStream ttfStream) throws IOException
+ {
+ PDCIDFontType2Embedder embedder =
+ new PDCIDFontType2Embedder(document, dict, ttfStream, this);
+ descendantFont = embedder.getCIDFont();
+ }
+
+ /**
* Reads the font's Encoding entry, which should be a CMap name/stream.
*/
private void readEncoding() throws IOException