ASF Bugzilla – Attachment 17104 Details for
Bug 5335
Text with embedded CID fonts not retrievable from pdf
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
FOP 0.20.5 generates ToUnicode maps for CID embedded TTF fonts
fop-0.20.5-toUnicodeCMap.patch (text/plain), 21.68 KB, created by
Adam Strzelecki
on 2005-12-01 15:53:51 UTC
(
hide
)
Description:
FOP 0.20.5 generates ToUnicode maps for CID embedded TTF fonts
Filename:
MIME Type:
Creator:
Adam Strzelecki
Created:
2005-12-01 15:53:51 UTC
Size:
21.68 KB
patch
obsolete
>diff -ruwbN src-org/org/apache/fop/pdf/PDFCMap.java src/org/apache/fop/pdf/PDFCMap.java >--- src-org/org/apache/fop/pdf/PDFCMap.java Tue Jul 15 03:03:28 2003 >+++ src/org/apache/fop/pdf/PDFCMap.java Wed Nov 30 16:49:30 2005 >@@ -50,6 +50,9 @@ > */ > package org.apache.fop.pdf; > >+import java.io.IOException; >+import java.io.OutputStream; >+ > /** > * class representing the CMap encodings. > * >@@ -203,54 +206,97 @@ > this.base = base; > } > >+ protected int output(OutputStream stream) throws IOException { >+ fillInPDF(new StringBuffer()); >+ return super.output(stream); >+ } >+ > public void fillInPDF(StringBuffer p) { >+ writePreStream(p); >+ writeStreamComments(p); >+ writeCIDInit(p); >+ writeCIDSystemInfo(p); >+ writeVersionTypeName(p); >+ writeCodeSpaceRange(p); >+ writeCIDRange(p); >+ writeBFEntries(p); >+ writeWrapUp(p); >+ writeStreamAfterComments(p); >+ writeUseCMap(p); >+ add(p.toString()); >+ } >+ >+ protected void writePreStream(StringBuffer p) { > // p.append("/Type /CMap\n"); > // p.append(sysInfo.toPDFString()); >- // p.append("/CMapName /" + name); >- // p.append("\n"); >+ // p.append("/CMapName /" + name + EOL); >+ } >+ >+ protected void writeStreamComments(StringBuffer p) { > p.append("%!PS-Adobe-3.0 Resource-CMap\n"); > p.append("%%DocumentNeededResources: ProcSet (CIDInit)\n"); > p.append("%%IncludeResource: ProcSet (CIDInit)\n"); > p.append("%%BeginResource: CMap (" + name + ")\n"); > p.append("%%EndComments\n"); >+ } > >+ protected void writeCIDInit(StringBuffer p) { > p.append("/CIDInit /ProcSet findresource begin\n"); > p.append("12 dict begin\n"); > p.append("begincmap\n"); >+ } > >+ protected void writeCIDSystemInfo(StringBuffer p) { > p.append("/CIDSystemInfo 3 dict dup begin\n"); > p.append(" /Registry (Adobe) def\n"); > p.append(" /Ordering (Identity) def\n"); > p.append(" /Supplement 0 def\n"); > p.append("end def\n"); >+ } > >+ protected void writeVersionTypeName(StringBuffer p) { > p.append("/CMapVersion 1 def\n"); > p.append("/CMapType 1 def\n"); > p.append("/CMapName /" + name + " def\n"); >+ } > >+ protected void writeCodeSpaceRange(StringBuffer p) { > p.append("1 begincodespacerange\n"); > p.append("<0000> <FFFF>\n"); > p.append("endcodespacerange\n"); >+ } >+ >+ protected void writeCIDRange(StringBuffer p) { > p.append("1 begincidrange\n"); > p.append("<0000> <FFFF> 0\n"); > p.append("endcidrange\n"); >+ } > >+ protected void writeBFEntries(StringBuffer p) { > // p.append("1 beginbfrange\n"); > // p.append("<0020> <0100> <0000>\n"); > // p.append("endbfrange\n"); >+ } > >+ protected void writeWrapUp(StringBuffer p) { > p.append("endcmap\n"); > p.append("CMapName currentdict /CMap defineresource pop\n"); > p.append("end\n"); > p.append("end\n"); >+ } >+ >+ protected void writeStreamAfterComments(StringBuffer p) { > p.append("%%EndResource\n"); > p.append("%%EOF\n"); >+ } >+ >+ protected void writeUseCMap(StringBuffer p) { > /* >- * p.append(" /Type /CMap\n/CMapName /" + name); >- * p.append("\n"); >- * p.append("\n/WMode "); p.append(wMode); >+ * p.append(" /Type /CMap"); >+ * p.append("/CMapName /" + name + EOL); >+ * p.append("/WMode " + wMode + EOL); > * if (base != null) { >- * p.append("\n/UseCMap "); >+ * p.append("/UseCMap "); > * if (base instanceof String) { > * p.append("/"+base); > * } else { // base instanceof PDFStream >diff -ruwbN src-org/org/apache/fop/pdf/PDFDocument.java src/org/apache/fop/pdf/PDFDocument.java >--- src-org/org/apache/fop/pdf/PDFDocument.java Tue Jul 15 03:03:12 2003 >+++ src/org/apache/fop/pdf/PDFDocument.java Thu Dec 1 12:47:13 2005 >@@ -876,25 +876,14 @@ > subtype); > > PDFFontNonBase14 font = null; >+ > if (subtype == PDFFont.TYPE0) { >- /* >- * Temporary commented out - customized CMaps >- * isn't needed until /ToUnicode support is added >- * PDFCMap cmap = new PDFCMap(++this.objectcount, >- * "fop-ucs-H", >- * new PDFCIDSystemInfo("Adobe", >- * "Identity", >- * 0)); >- * cmap.addContents(); >- * this.objects.add(cmap); >- */ > font = > (PDFFontNonBase14)PDFFont.createFont(++this.objectcount, > fontname, subtype, > basefont, > "Identity-H"); > } else { >- > font = > (PDFFontNonBase14)PDFFont.createFont(++this.objectcount, > fontname, subtype, >@@ -923,8 +912,13 @@ > (PDFCIDFontDescriptor)pdfdesc); > this.objects.add(cidFont); > >- // ((PDFFontType0)font).setCMAP(cmap); >- >+ PDFCMap cmap = new PDFToUnicodeCMap(cidMetrics, ++this.objectcount, >+ "fop-ucs-H", >+ new PDFCIDSystemInfo("Adobe", >+ "Identity", >+ 0)); >+ this.objects.add(cmap); >+ ((PDFFontType0)font).setCMAP(cmap); > ((PDFFontType0)font).setDescendantFonts(cidFont); > } else { > font.setWidthMetrics(metrics.getFirstChar(), >diff -ruwbN src-org/org/apache/fop/pdf/PDFToUnicodeCMap.java src/org/apache/fop/pdf/PDFToUnicodeCMap.java >--- src-org/org/apache/fop/pdf/PDFToUnicodeCMap.java Thu Jan 1 00:00:00 1970 >+++ src/org/apache/fop/pdf/PDFToUnicodeCMap.java Thu Dec 1 14:46:33 2005 >@@ -0,0 +1,322 @@ >+/* >+ * $Id: PDFToUnicodeCMap.java,v 1.3.2.1 2005/12/01 12:00:00 ono Exp $ >+ * ============================================================================ >+ * The Apache Software License, Version 1.1 >+ * ============================================================================ >+ * >+ * Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without modifica- >+ * tion, are permitted provided that the following conditions are met: >+ * >+ * 1. Redistributions of source code must retain the above copyright notice, >+ * this list of conditions and the following disclaimer. >+ * >+ * 2. Redistributions in binary form must reproduce the above copyright notice, >+ * this list of conditions and the following disclaimer in the documentation >+ * and/or other materials provided with the distribution. >+ * >+ * 3. The end-user documentation included with the redistribution, if any, must >+ * include the following acknowledgment: "This product includes software >+ * developed by the Apache Software Foundation (http://www.apache.org/)." >+ * Alternately, this acknowledgment may appear in the software itself, if >+ * and wherever such third-party acknowledgments normally appear. >+ * >+ * 4. The names "FOP" and "Apache Software Foundation" must not be used to >+ * endorse or promote products derived from this software without prior >+ * written permission. For written permission, please contact >+ * apache@apache.org. >+ * >+ * 5. Products derived from this software may not be called "Apache", nor may >+ * "Apache" appear in their name, without prior written permission of the >+ * Apache Software Foundation. >+ * >+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, >+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND >+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE >+ * APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, >+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- >+ * DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS >+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON >+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT >+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF >+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. >+ * ============================================================================ >+ * >+ * This software consists of voluntary contributions made by many individuals >+ * on behalf of the Apache Software Foundation and was originally created by >+ * James Tauber <jtauber@jtauber.com>. For more information on the Apache >+ * Software Foundation, please see <http://www.apache.org/>. >+ */ >+package org.apache.fop.pdf; >+ >+/** >+ * Class representing ToUnicode CMaps. >+ * Here are some documentation resources: >+ * <ul> >+ * <li>PDF Reference, Second Edition, Section 5.6.4, for general information >+ * about CMaps in PDF Files.</li> >+ * <li>PDF Reference, Second Edition, Section 5.9, for specific information >+ * about ToUnicodeCMaps in PDF Files.</li> >+ * <li> >+ * <a href="http://partners.adobe.com/asn/developer/pdfs/tn/5411.ToUnicode.pdf"> >+ * Adobe Technical Note #5411, "ToUnicode Mapping File Tutorial"</a>. >+ * </ul> >+ */ >+import org.apache.fop.render.pdf.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, int number, String name, PDFCIDSystemInfo sysInfo) { >+ super(number, 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(); >+ } >+ >+} >diff -ruwbN src-org/org/apache/fop/render/pdf/CIDFont.java src/org/apache/fop/render/pdf/CIDFont.java >--- src-org/org/apache/fop/render/pdf/CIDFont.java Tue Jul 15 03:03:10 2003 >+++ src/org/apache/fop/render/pdf/CIDFont.java Thu Dec 1 12:40:06 2005 >@@ -85,4 +85,8 @@ > return null; > } > >+ /** >+ * Returns char[] array . >+ */ >+ public abstract char[] getCharsUsed(); > } >diff -ruwbN src-org/org/apache/fop/render/pdf/fonts/MultiByteFont.java src/org/apache/fop/render/pdf/fonts/MultiByteFont.java >--- src-org/org/apache/fop/render/pdf/fonts/MultiByteFont.java Tue Jul 15 03:03:18 2003 >+++ src/org/apache/fop/render/pdf/fonts/MultiByteFont.java Thu Dec 1 13:21:45 2005 >@@ -111,6 +111,12 @@ > * usedGlyphsIndex contains new glyph, original index > */ > private Map usedGlyphsIndex = new java.util.HashMap(); >+ >+ /** >+ * usedCharsIndex contains new glyph, original char >+ */ >+ private Map usedCharsIndex = new java.util.HashMap(); >+ > int usedGlyphsCount = 0; > > public MultiByteFont() { >@@ -364,6 +370,8 @@ > new Integer(usedGlyphsCount)); > usedGlyphsIndex.put(new Integer(usedGlyphsCount), > new Integer(retIdx)); >+ usedCharsIndex.put(new Integer(usedGlyphsCount), >+ new Integer(idx)); > retIdx = usedGlyphsCount; > // System.out.println(c+"("+(int)c+") = "+retIdx); > usedGlyphsCount++; >@@ -375,6 +383,27 @@ > return (char)retIdx; > } > >+ /** The invalid Unicode character, suitable as a return value in methods >+ * that need to return an invalid character. */ >+ public static final char INVALID_UNICODE_CHAR = 0xFFFF; >+ >+ public char[] getCharsUsed() { >+ if (! isEmbeddable()) { >+ return null; >+ } >+ char[] charArray = new char[usedGlyphsCount]; >+ for (int i = 0; i < usedGlyphsCount; i++) { >+ Integer mapValue = (Integer)usedCharsIndex.get(new Integer(i)); >+ if(mapValue != null) { >+ char arrayItem = (char) mapValue.intValue(); >+ charArray[i] = arrayItem; >+ } >+ else { >+ charArray[i] = INVALID_UNICODE_CHAR; >+ } >+ } >+ return charArray; >+ } > } > > >diff -ruwbN src-org/org/apache/fop/render/pdf/fonts/SingleByteFont.java src/org/apache/fop/render/pdf/fonts/SingleByteFont.java >--- src-org/org/apache/fop/render/pdf/fonts/SingleByteFont.java Tue Jul 15 03:03:24 2003 >+++ src/org/apache/fop/render/pdf/fonts/SingleByteFont.java Wed Nov 30 17:51:38 2005 >@@ -281,5 +281,8 @@ > } > } > >+ public char[] getCharsUsed() { >+ return null; >+ } > } >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 5335
:
3939
| 17104 |
17203
|
18987