KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > fop > pdf > PDFToUnicodeCMap


1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */

17
18 /* $Id: PDFToUnicodeCMap.java 462814 2006-10-11 14:30:34Z jeremias $ */
19  
20 package org.apache.fop.pdf;
21
22 import org.apache.fop.fonts.CIDFont;
23
24 /**
25  * Class representing ToUnicode CMaps.
26  * Here are some documentation resources:
27  * <ul>
28  * <li>PDF Reference, Second Edition, Section 5.6.4, for general information
29  * about CMaps in PDF Files.</li>
30  * <li>PDF Reference, Second Edition, Section 5.9, for specific information
31  * about ToUnicodeCMaps in PDF Files.</li>
32  * <li>
33  * <a HREF="http://partners.adobe.com/asn/developer/pdfs/tn/5411.ToUnicode.pdf">
34  * Adobe Technical Note #5411, "ToUnicode Mapping File Tutorial"</a>.
35  * </ul>
36  */

37 public class PDFToUnicodeCMap extends PDFCMap {
38
39     /**
40      * handle to read font
41      */

42     protected CIDFont cidFont;
43
44     /**
45      * Constructor.
46      *
47      * @param cidMetrics the CID font for which this Unicode CMap is built
48      * @param name One of the registered names found in Table 5.14 in PDF
49      * Reference, Second Edition.
50      * @param sysInfo The attributes of the character collection of the CIDFont.
51      */

52     public PDFToUnicodeCMap(CIDFont cidMetrics, String JavaDoc name, PDFCIDSystemInfo sysInfo) {
53         super(name, sysInfo);
54         cidFont = cidMetrics;
55     }
56
57     /** @see org.apache.fop.pdf.PDFCMap#fillInPDF(java.lang.StringBuffer) */
58     public void fillInPDF(StringBuffer JavaDoc p) {
59         writeCIDInit(p);
60         writeCIDSystemInfo(p);
61         writeVersionTypeName(p);
62         writeCodeSpaceRange(p);
63         writeBFEntries(p);
64         writeWrapUp(p);
65         add(p.toString());
66     }
67
68     /** @see org.apache.fop.pdf.PDFCMap#writeCIDSystemInfo(java.lang.StringBuffer) */
69     protected void writeCIDSystemInfo(StringBuffer JavaDoc p) {
70         p.append("/CIDSystemInfo\n");
71         p.append("<< /Registry (Adobe)\n");
72         p.append("/Ordering (UCS)\n");
73         p.append("/Supplement 0\n");
74         p.append(">> def\n");
75     }
76
77     /** @see org.apache.fop.pdf.PDFCMap#writeVersionTypeName(java.lang.StringBuffer) */
78     protected void writeVersionTypeName(StringBuffer JavaDoc p) {
79         p.append("/CMapName /Adobe-Identity-UCS def\n");
80         p.append("/CMapType 2 def\n");
81     }
82
83     /**
84      * Writes the character mappings for this font.
85      * @param p StingBuffer to write to
86      */

87     protected void writeBFEntries(StringBuffer JavaDoc p) {
88         if (cidFont == null) {
89             return;
90         }
91
92         char[] charArray = cidFont.getCharsUsed();
93
94         if (charArray != null) {
95             writeBFCharEntries(p, charArray);
96             writeBFRangeEntries(p, charArray);
97         }
98     }
99
100     /**
101      * Writes the entries for single characters of a base font (only characters which cannot be
102      * expressed as part of a character range).
103      * @param p StringBuffer to write to
104      * @param charArray all the characters to map
105      */

106     protected void writeBFCharEntries(StringBuffer JavaDoc p, char[] charArray) {
107         int totalEntries = 0;
108         for (int i = 0; i < charArray.length; i++) {
109             if (!partOfRange(charArray, i)) {
110                 totalEntries++;
111             }
112         }
113         if (totalEntries < 1) {
114             return;
115         }
116         int remainingEntries = totalEntries;
117         int charIndex = 0;
118         do {
119             /* Limited to 100 entries in each section */
120             int entriesThisSection = Math.min(remainingEntries, 100);
121             p.append(entriesThisSection + " beginbfchar\n");
122             for (int i = 0; i < entriesThisSection; i++) {
123                 /* Go to the next char not in a range */
124                 while (partOfRange(charArray, charIndex)) {
125                     charIndex++;
126                 }
127                 p.append("<" + padHexString(Integer.toHexString(charIndex), 4) + "> ");
128                 p.append("<" + padHexString(Integer.toHexString(charArray[charIndex]), 4) + ">\n");
129                 charIndex++;
130             }
131             remainingEntries -= entriesThisSection;
132             p.append("endbfchar\n");
133         } while (remainingEntries > 0);
134     }
135
136     /**
137      * Writes the entries for character ranges for a base font.
138      * @param p StringBuffer to write to
139      * @param charArray all the characters to map
140      */

141     protected void writeBFRangeEntries(StringBuffer JavaDoc p, char[] charArray) {
142         int totalEntries = 0;
143         for (int i = 0; i < charArray.length; i++) {
144             if (startOfRange(charArray, i)) {
145                 totalEntries++;
146             }
147         }
148         if (totalEntries < 1) {
149             return;
150         }
151         int remainingEntries = totalEntries;
152         int charIndex = 0;
153         do {
154             /* Limited to 100 entries in each section */
155             int entriesThisSection = Math.min(remainingEntries, 100);
156             p.append(entriesThisSection + " beginbfrange\n");
157             for (int i = 0; i < entriesThisSection; i++) {
158                 /* Go to the next start of a range */
159                 while (!startOfRange(charArray, charIndex)) {
160                     charIndex++;
161                 }
162                 p.append("<" + padHexString(Integer.toHexString(charIndex), 4) + "> ");
163                 p.append("<"
164                         + padHexString(Integer.toHexString(endOfRange(charArray, charIndex)), 4)
165                         + "> ");
166                 p.append("<" + padHexString(Integer.toHexString(charArray[charIndex]), 4) + ">\n");
167                 charIndex++;
168             }
169             remainingEntries -= entriesThisSection;
170             p.append("endbfrange\n");
171         } while (remainingEntries > 0);
172     }
173
174     /**
175      * Find the end of the current range.
176      * @param charArray The array which is being tested.
177      * @param startOfRange The index to the array element that is the start of
178      * the range.
179      * @return The index to the element that is the end of the range.
180      */

181     private int endOfRange(char[] charArray, int startOfRange) {
182         int i = startOfRange;
183         while (i < charArray.length - 1 && sameRangeEntryAsNext(charArray, i)) {
184             i++;
185         }
186         return i;
187     }
188
189     /**
190      * Determine whether this array element should be part of a bfchar entry or
191      * a bfrange entry.
192      * @param charArray The array to be tested.
193      * @param arrayIndex The index to the array element to be tested.
194      * @return True if this array element should be included in a range.
195      */

196     private boolean partOfRange(char[] charArray, int arrayIndex) {
197         if (charArray.length < 2) {
198             return false;
199         }
200         if (arrayIndex == 0) {
201             return sameRangeEntryAsNext(charArray, 0);
202         }
203         if (arrayIndex == charArray.length - 1) {
204             return sameRangeEntryAsNext(charArray, arrayIndex - 1);
205         }
206         if (sameRangeEntryAsNext(charArray, arrayIndex - 1)) {
207             return true;
208         }
209         if (sameRangeEntryAsNext(charArray, arrayIndex)) {
210             return true;
211         }
212         return false;
213     }
214
215     /**
216      * Determine whether two bytes can be written in the same bfrange entry.
217      * @param charArray The array to be tested.
218      * @param firstItem The first of the two items in the array to be tested.
219      * The second item is firstItem + 1.
220      * @return True if both 1) the next item in the array is sequential with
221      * this one, and 2) the first byte of the character in the first position
222      * is equal to the first byte of the character in the second position.
223      */

224     private boolean sameRangeEntryAsNext(char[] charArray, int firstItem) {
225         if (charArray[firstItem] + 1 != charArray[firstItem + 1]) {
226             return false;
227         }
228         if (firstItem / 256 != (firstItem + 1) / 256) {
229             return false;
230         }
231         return true;
232     }
233
234     /**
235      * Determine whether this array element should be the start of a bfrange
236      * entry.
237      * @param charArray The array to be tested.
238      * @param arrayIndex The index to the array element to be tested.
239      * @return True if this array element is the beginning of a range.
240      */

241     private boolean startOfRange(char[] charArray, int arrayIndex) {
242         // Can't be the start of a range if not part of a range.
243
if (!partOfRange(charArray, arrayIndex)) {
244             return false;
245         }
246         // If first element in the array, must be start of a range
247
if (arrayIndex == 0) {
248             return true;
249         }
250         // If last element in the array, cannot be start of a range
251
if (arrayIndex == charArray.length - 1) {
252             return false;
253         }
254         /*
255          * If part of same range as the previous element is, cannot be start
256          * of range.
257          */

258         if (sameRangeEntryAsNext(charArray, arrayIndex - 1)) {
259             return false;
260         }
261         // Otherwise, this is start of a range.
262
return true;
263     }
264
265     /**
266      * Prepends the input string with a sufficient number of "0" characters to
267      * get the returned string to be numChars length.
268      * @param input The input string.
269      * @param numChars The minimum characters in the output string.
270      * @return The padded string.
271      */

272     public static String JavaDoc padHexString(String JavaDoc input, int numChars) {
273         int length = input.length();
274         if (length >= numChars) {
275             return input;
276         }
277         StringBuffer JavaDoc returnString = new StringBuffer JavaDoc();
278         for (int i = 1; i <= numChars - length; i++) {
279             returnString.append("0");
280         }
281         returnString.append(input);
282         return returnString.toString();
283     }
284
285 }
286
Popular Tags