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