]> source.dussan.org Git - xmlgraphics-fop.git/commitdiff
Missing files from previous commit, Vincent Hennebert's patch, attachment 18917 to...
authorBertrand Delacretaz <bdelacretaz@apache.org>
Wed, 27 Sep 2006 15:36:13 +0000 (15:36 +0000)
committerBertrand Delacretaz <bdelacretaz@apache.org>
Wed, 27 Sep 2006 15:36:13 +0000 (15:36 +0000)
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/foray-font@450481 13f79535-47bb-0310-9956-ffa450edef68

src/java/org/apache/fop/pdf/FontMap.java [new file with mode: 0644]
src/java/org/apache/fop/pdf/PDFFontFileStream.java [new file with mode: 0644]
src/java/org/apache/fop/pdf/PDFToUnicodeCMap.java [new file with mode: 0644]

diff --git a/src/java/org/apache/fop/pdf/FontMap.java b/src/java/org/apache/fop/pdf/FontMap.java
new file mode 100644 (file)
index 0000000..3aa23a8
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * Copyright 1999-2005 The Apache Software Foundation.
+ * 
+ * Licensed 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.
+ */
+
+/* $Id$ */
+package org.apache.fop.pdf;
+
+import java.util.Hashtable;
+import java.util.Map;
+import java.util.Set;
+
+import org.axsl.fontR.FontConsumer;
+import org.axsl.fontR.FontUse;
+
+/**
+ * Class that stores a mapping of each FontUse to a corresponding internal name
+ * (F1, F2...), used to refer to a font in the PDF file.
+ */
+public class FontMap  {
+    
+    /**
+     * The Map iself. Keys are FontUse instances, values are String (internal
+     * name).
+     */
+    private Map fontMap;
+    
+    /**
+     * Font consumer associated to this map.
+     */
+    private FontConsumer fontConsumer;
+    
+    
+    /**
+     * Builds a font mapping of the FontUses available from the font server
+     * associated to the given font consumer.
+     * 
+     * @param fontConsumer font consumer from which to get the FontUses
+     */
+    public FontMap(FontConsumer fontConsumer) {
+        this.fontConsumer = fontConsumer;
+        this.fontMap = new Hashtable();
+    }
+
+    /**
+     * Builds a font mapping of (possibly all) the FontUses available from the
+     * font server associated to the given font consumer.
+     * 
+     * @param fontConsumer
+     *            font consumer from which to get the FontUses
+     * @param registerAllFonts
+     *            if <code>true</code>, all of the FontUses available from
+     *            the font server are registered (useful for poscript output).
+     *            Otherwise font uses are only registered when needed. This is
+     *            the default.
+     */
+    public FontMap(FontConsumer fontConsumer, boolean registerAllFonts) {
+        this.fontConsumer = fontConsumer;
+        if (!registerAllFonts) {
+            this.fontMap = new Hashtable();
+        } else {
+               // TODO vh: re-enable
+//            FontUse[] fontUses = fontConsumer.getFontServer().getAllFontUses(true, false);
+//            fontMap = new Hashtable(fontUses.length);
+//            for (int i = 0; i < fontUses.length; i++) {
+//                fontMap.put(fontUses[i], "F" + new Integer(i));    
+//            }        
+        }
+    }
+    
+    /**
+     * Returns the font consumer associated to this font map.
+     * @return the font consumer
+     */
+    public FontConsumer getFontConsumer() {
+        return fontConsumer;
+    }
+
+    /**
+     * Returns the internal name associated to the given FontUse instance.
+     * @param fontUse a FontUse
+     * @return the corresponding internal name
+     */
+    public String getInternalName(FontUse fontUse) {
+        String internalName;
+        if (!fontMap.containsKey(fontUse)) {
+            internalName = "F" + (fontMap.size() + 1);
+            fontMap.put(fontUse, internalName);
+        } else {
+            internalName = (String) fontMap.get(fontUse); 
+        }
+        return internalName;
+    }
+    
+    /**
+     * Returns the number of registered font uses.
+     * @return number of mappings
+     */
+    public int getSize() {
+        return fontMap.size();
+    }
+    
+    /**
+     * Returns the mappings contained in this font map. Each element in the
+     * returned set is a Map.Entry, in which the key is a FontUse and the value
+     * its corresponding internal name.
+     * 
+     * @return a set of the mappings contained in this font map.
+     */
+    public Set getMappings() {
+        return fontMap.entrySet();
+    }
+}
diff --git a/src/java/org/apache/fop/pdf/PDFFontFileStream.java b/src/java/org/apache/fop/pdf/PDFFontFileStream.java
new file mode 100644 (file)
index 0000000..ca28d57
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2004 The FOray Project.
+ *      http://www.foray.org
+ * 
+ * Licensed 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.
+ * 
+ * This work is in part derived from the following work(s), used with the
+ * permission of the licensor:
+ *      Apache FOP, licensed by the Apache Software Foundation
+ *
+ */
+
+/* $Id$ */
+package org.apache.fop.pdf;
+
+import org.axsl.fontR.FontConsumer;
+import org.axsl.fontR.FontUse;
+import org.axsl.fontR.output.FontPDF;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+
+public class PDFFontFileStream extends PDFStream {
+    private FontUse font;
+    private FontPDF fontOutput;
+
+    public PDFFontFileStream(FontUse font, FontConsumer fontConsumer) {
+        super();
+        if (!font.getFont().isEmbeddable()) {
+            // TODO vh: better error handling
+            log.error("Can't create PDFFontFileStream for a Font "
+                    + "that is not embeddable.");
+            return;
+        }
+        this.font = font;
+        this.fontOutput = (FontPDF)font.getFontOutput("application/pdf");
+        byte[] fontFileStream = fontOutput.getContents();
+        // TODO vh
+//        addFilter("flate");
+//        addFilter("ascii-85");
+        try {
+            setData(fontFileStream);
+        } catch (IOException ioe) {
+            log.error("Failed to embed font "
+                    + font.getPostscriptName() + ": " + ioe.getMessage());
+        }
+    }
+
+    protected int output(OutputStream stream) throws IOException {
+        int length = 0;
+        // TODO vh
+//        String filterEntry = applyFilters();
+        String preData
+                = getObjectID() + "\n<< /Length "
+                + getDataLength()
+                + " "
+//                + filterEntry
+                + fontOutput.getPDFFontFileStreamAdditional()
+                + " >>\n";
+
+        byte[] p;
+        try {
+            p = preData.getBytes(PDFDocument.ENCODING);
+        } catch (UnsupportedEncodingException ue) {
+            p = preData.getBytes();
+        }
+
+        stream.write(p);
+        length += p.length;
+
+        length += outputStreamData(data, stream);
+        try {
+            p = ("\nendobj\n").getBytes(PDFDocument.ENCODING);
+        } catch (UnsupportedEncodingException ue) {
+            p = ("\nendobj\n").getBytes();
+        }
+        stream.write(p);
+        length += p.length;
+        return length;
+    }
+
+}
diff --git a/src/java/org/apache/fop/pdf/PDFToUnicodeCMap.java b/src/java/org/apache/fop/pdf/PDFToUnicodeCMap.java
new file mode 100644 (file)
index 0000000..a181058
--- /dev/null
@@ -0,0 +1,259 @@
+package org.apache.fop.pdf;
+
+import org.apache.fop.fonts.CIDFont;
+
+public class PDFToUnicodeCMap extends PDFCMap {
+
+    /**
+     * handle to read font
+     */
+    protected CIDFont cidFont;
+
+    /**
+     * Constructor.
+     *
+     * @param name One of the registered names found in Table 5.14 in PDF
+     * Reference, Second Edition.
+     * @param sysInfo The attributes of the character collection of the CIDFont.
+     */
+    public PDFToUnicodeCMap(CIDFont cidMetrics, String name, PDFCIDSystemInfo sysInfo) {
+        super(name, sysInfo);
+        cidFont = cidMetrics;
+    }
+
+    public void fillInPDF(StringBuffer p) {
+        writeCIDInit(p);
+        writeCIDSystemInfo(p);
+        writeVersionTypeName(p);
+        writeCodeSpaceRange(p);
+        writeBFEntries(p);
+        writeWrapUp(p);
+        add(p.toString());
+    }
+
+    protected void writeCIDSystemInfo(StringBuffer p) {
+        p.append("/CIDSystemInfo\n");
+        p.append("<< /Registry (Adobe)\n");
+        p.append("/Ordering (UCS)\n");
+        p.append("/Supplement 0\n");
+        p.append(">> def\n");
+    }
+
+    protected void writeVersionTypeName(StringBuffer p) {
+        p.append("/CMapName /Adobe-Identity-UCS def\n");
+        p.append("/CMapType 2 def\n");
+    }
+
+    /**
+     * Writes the character mappings for this font.
+     */
+    protected void writeBFEntries(StringBuffer p) {
+        if(cidFont == null) return;
+
+        char[] charArray = cidFont.getCharsUsed();
+
+        if(charArray != null) {
+            writeBFCharEntries(p, charArray);
+            writeBFRangeEntries(p, charArray);
+        }
+    }
+
+    protected void writeBFCharEntries(StringBuffer p, char[] charArray) {
+        int completedEntries = 0;
+        int totalEntries = 0;
+        for (int i = 0; i < charArray.length; i++) {
+            if (! partOfRange(charArray, i)) {
+                totalEntries ++;
+            }
+        }
+        if (totalEntries < 1) {
+            return;
+        }
+        int remainingEntries = totalEntries;
+        /* Limited to 100 entries in each section */
+        int entriesThisSection = Math.min(remainingEntries, 100);
+        int remainingEntriesThisSection = entriesThisSection;
+        p.append(entriesThisSection + " beginbfchar\n");
+        for (int i = 0; i < charArray.length; i++) {
+            if (partOfRange(charArray, i)) {
+                continue;
+            }
+            p.append("<" + padHexString(Integer.toHexString(i), 4)
+                    + "> ");
+            p.append("<" + padHexString(Integer.toHexString(charArray[i]), 4)
+                    + ">\n");
+            /* Compute the statistics. */
+            completedEntries ++;
+            remainingEntries = totalEntries - completedEntries;
+            remainingEntriesThisSection --;
+            if (remainingEntriesThisSection < 1) {
+                if (remainingEntries > 0) {
+                    p.append("endbfchar\n");
+                    entriesThisSection = Math.min(remainingEntries, 100);
+                    remainingEntriesThisSection = entriesThisSection;
+                    p.append(entriesThisSection + " beginbfchar\n");
+                }
+            }
+        }
+        p.append("endbfchar\n");
+    }
+
+    protected void writeBFRangeEntries(StringBuffer p, char[] charArray) {
+        int completedEntries = 0;
+        int totalEntries = 0;
+        for (int i = 0; i < charArray.length; i++) {
+            if (startOfRange(charArray, i)) {
+                totalEntries ++;
+            }
+        }
+        if (totalEntries < 1) {
+            return;
+        }
+        int remainingEntries = totalEntries;
+        int entriesThisSection = Math.min(remainingEntries, 100);
+        int remainingEntriesThisSection = entriesThisSection;
+        p.append(entriesThisSection + " beginbfrange\n");
+        for (int i = 0; i < charArray.length; i++) {
+            if (! startOfRange(charArray, i)) {
+                continue;
+            }
+            p.append("<"
+                    + padHexString(Integer.toHexString(i), 4)
+                    + "> ");
+            p.append("<"
+                    + padHexString(Integer.toHexString
+                            (endOfRange(charArray, i)), 4)
+                    + "> ");
+            p.append("<"
+                    + padHexString(Integer.toHexString(charArray[i]), 4)
+                    + ">\n");
+            /* Compute the statistics. */
+            completedEntries ++;
+            remainingEntries = totalEntries - completedEntries;
+            if (remainingEntriesThisSection < 1) {
+                if (remainingEntries > 0) {
+                    p.append("endbfrange\n");
+                    entriesThisSection = Math.min(remainingEntries, 100);
+                    remainingEntriesThisSection = entriesThisSection;
+                    p.append(entriesThisSection + " beginbfrange\n");
+                }
+            }
+        }
+        p.append("endbfrange\n");
+    }
+
+    /**
+     * Find the end of the current range.
+     * @param charArray The array which is being tested.
+     * @param startOfRange The index to the array element that is the start of
+     * the range.
+     * @return The index to the element that is the end of the range.
+     */
+    private int endOfRange(char[] charArray, int startOfRange) {
+        int endOfRange = -1;
+        for (int i = startOfRange; i < charArray.length - 1 && endOfRange < 0;
+                i++) {
+            if (! sameRangeEntryAsNext(charArray, i)) {
+                endOfRange = i;
+            }
+        }
+        return endOfRange;
+    }
+
+    /**
+     * Determine whether this array element should be part of a bfchar entry or
+     * a bfrange entry.
+     * @param charArray The array to be tested.
+     * @param arrayIndex The index to the array element to be tested.
+     * @return True if this array element should be included in a range.
+     */
+    private boolean partOfRange(char[] charArray, int arrayIndex) {
+        if (charArray.length < 2) {
+            return false;
+        }
+        if (arrayIndex == 0) {
+            return sameRangeEntryAsNext(charArray, 0);
+        }
+        if (arrayIndex == charArray.length - 1) {
+            return sameRangeEntryAsNext(charArray, arrayIndex - 1);
+        }
+        if (sameRangeEntryAsNext(charArray, arrayIndex - 1)) {
+            return true;
+        }
+        if (sameRangeEntryAsNext(charArray, arrayIndex)) {
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Determine whether two bytes can be written in the same bfrange entry.
+     * @param charArray The array to be tested.
+     * @param firstItem The first of the two items in the array to be tested.
+     * The second item is firstItem + 1.
+     * @return True if both 1) the next item in the array is sequential with
+     * this one, and 2) the first byte of the character in the first position
+     * is equal to the first byte of the character in the second position.
+     */
+    private boolean sameRangeEntryAsNext(char[] charArray, int firstItem) {
+        if (charArray[firstItem] + 1 != charArray[firstItem + 1]) {
+            return false;
+        }
+        if (firstItem / 256 != (firstItem + 1) / 256) {
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Determine whether this array element should be the start of a bfrange
+     * entry.
+     * @param charArray The array to be tested.
+     * @param arrayIndex The index to the array element to be tested.
+     * @return True if this array element is the beginning of a range.
+     */
+    private boolean startOfRange(char[] charArray, int arrayIndex) {
+        // Can't be the start of a range if not part of a range.
+        if (! partOfRange(charArray, arrayIndex)) {
+            return false;
+        }
+        // If first element in the array, must be start of a range
+        if (arrayIndex == 0) {
+            return true;
+        }
+        // If last element in the array, cannot be start of a range
+        if (arrayIndex == charArray.length - 1) {
+            return false;
+        }
+        /*
+         * If part of same range as the previous element is, cannot be start
+         * of range.
+         */
+        if (sameRangeEntryAsNext(charArray, arrayIndex - 1)) {
+            return false;
+        }
+        // Otherwise, this is start of a range.
+        return true;
+    }
+
+    /**
+     * Prepends the input string with a sufficient number of "0" characters to
+     * get the returned string to be numChars length.
+     * @param input The input string.
+     * @param numChars The minimum characters in the output string.
+     * @return The padded string.
+     */
+    public static String padHexString(String input, int numChars) {
+        int length = input.length();
+        if (length >= numChars) {
+            return input;
+        }
+        StringBuffer returnString = new StringBuffer();
+        for (int i = 1; i <= numChars - length; i++) {
+            returnString.append("0");
+        }
+        returnString.append(input);
+        return returnString.toString();
+    }
+
+}
\ No newline at end of file