1 /*
2 * $Id: FontDetails.java 3869 2009-04-17 18:03:45Z blowagie $
3 *
4 * Copyright 2001, 2002 by Paulo Soares.
5 *
6 * The contents of this file are subject to the Mozilla Public License Version 1.1
7 * (the "License"); you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at http://www.mozilla.org/MPL/
9 *
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the License.
13 *
14 * The Original Code is 'iText, a free JAVA-PDF library'.
15 *
16 * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
17 * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
18 * All Rights Reserved.
19 * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
20 * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
21 *
22 * Contributor(s): all the names of the contributors are added in the source code
23 * where applicable.
24 *
25 * Alternatively, the contents of this file may be used under the terms of the
26 * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
27 * provisions of LGPL are applicable instead of those above. If you wish to
28 * allow use of your version of this file only under the terms of the LGPL
29 * License and not to allow others to use your version of this file under
30 * the MPL, indicate your decision by deleting the provisions above and
31 * replace them with the notice and other provisions required by the LGPL.
32 * If you do not delete the provisions above, a recipient may use your version
33 * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
34 *
35 * This library is free software; you can redistribute it and/or modify it
36 * under the terms of the MPL as stated above or under the terms of the GNU
37 * Library General Public License as published by the Free Software Foundation;
38 * either version 2 of the License, or any later version.
39 *
40 * This library is distributed in the hope that it will be useful, but WITHOUT
41 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
42 * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
43 * details.
44 *
45 * If you didn't download this code from the following link, you should check if
46 * you aren't using an obsolete version:
47 * http://www.lowagie.com/iText/
48 */
49
50 package com.lowagie.text.pdf;
51
52 import java.awt.font.GlyphVector;
53 import java.io.UnsupportedEncodingException;
54 import java.util.HashMap;
55
56 import com.lowagie.text.ExceptionConverter;
57 import com.lowagie.text.Utilities;
58
59 /**
60 * Each font in the document will have an instance of this class
61 * where the characters used will be represented.
62 *
63 * @author Paulo Soares (psoares@consiste.pt)
64 */
65 class FontDetails {
66
67 /**
68 * The indirect reference to this font
69 */
70 PdfIndirectReference indirectReference;
71 /**
72 * The font name that appears in the document body stream
73 */
74 PdfName fontName;
75 /**
76 * The font
77 */
78 BaseFont baseFont;
79 /**
80 * The font if it's an instance of <CODE>TrueTypeFontUnicode</CODE>
81 */
82 TrueTypeFontUnicode ttu;
83 /**
84 * The font if it's an instance of <CODE>CJKFont</CODE>
85 */
86 CJKFont cjkFont;
87 /**
88 * The array used with single byte encodings
89 */
90 byte shortTag[];
91 /**
92 * The map used with double byte encodings. The key is Integer(glyph) and
93 * the value is int[]{glyph, width, Unicode code}
94 */
95 HashMap longTag;
96 /**
97 * IntHashtable with CIDs of CJK glyphs that are used in the text.
98 */
99 IntHashtable cjkTag;
100 /**
101 * The font type
102 */
103 int fontType;
104 /**
105 * <CODE>true</CODE> if the font is symbolic
106 */
107 boolean symbolic;
108 /**
109 * Indicates if only a subset of the glyphs and widths for that particular
110 * encoding should be included in the document.
111 */
112 protected boolean subset = true;
113
114 /**
115 * Each font used in a document has an instance of this class.
116 * This class stores the characters used in the document and other
117 * specifics unique to the current working document.
118 * @param fontName the font name
119 * @param indirectReference the indirect reference to the font
120 * @param baseFont the <CODE>BaseFont</CODE>
121 */
122 FontDetails(PdfName fontName, PdfIndirectReference indirectReference, BaseFont baseFont) {
123 this.fontName = fontName;
124 this.indirectReference = indirectReference;
125 this.baseFont = baseFont;
126 fontType = baseFont.getFontType();
127 switch (fontType) {
128 case BaseFont.FONT_TYPE_T1:
129 case BaseFont.FONT_TYPE_TT:
130 shortTag = new byte[256];
131 break;
132 case BaseFont.FONT_TYPE_CJK:
133 cjkTag = new IntHashtable();
134 cjkFont = (CJKFont)baseFont;
135 break;
136 case BaseFont.FONT_TYPE_TTUNI:
137 longTag = new HashMap();
138 ttu = (TrueTypeFontUnicode)baseFont;
139 symbolic = baseFont.isFontSpecific();
140 break;
141 }
142 }
143
144 /**
145 * Gets the indirect reference to this font.
146 * @return the indirect reference to this font
147 */
148 PdfIndirectReference getIndirectReference() {
149 return indirectReference;
150 }
151
152 /**
153 * Gets the font name as it appears in the document body.
154 * @return the font name
155 */
156 PdfName getFontName() {
157 return fontName;
158 }
159
160 /**
161 * Gets the <CODE>BaseFont</CODE> of this font.
162 * @return the <CODE>BaseFont</CODE> of this font
163 */
164 BaseFont getBaseFont() {
165 return baseFont;
166 }
167
168 /**
169 * Converts the text into bytes to be placed in the document.
170 * The conversion is done according to the font and the encoding and the characters
171 * used are stored.
172 * @param text the text to convert
173 * @return the conversion
174 */
175 byte[] convertToBytes(String text) {
176 byte b[] = null;
177 switch (fontType) {
178 case BaseFont.FONT_TYPE_T3:
179 return baseFont.convertToBytes(text);
180 case BaseFont.FONT_TYPE_T1:
181 case BaseFont.FONT_TYPE_TT: {
182 b = baseFont.convertToBytes(text);
183 int len = b.length;
184 for (int k = 0; k < len; ++k)
185 shortTag[b[k] & 0xff] = 1;
186 break;
187 }
188 case BaseFont.FONT_TYPE_CJK: {
189 int len = text.length();
190 for (int k = 0; k < len; ++k)
191 cjkTag.put(cjkFont.getCidCode(text.charAt(k)), 0);
192 b = baseFont.convertToBytes(text);
193 break;
194 }
195 case BaseFont.FONT_TYPE_DOCUMENT: {
196 b = baseFont.convertToBytes(text);
197 break;
198 }
199 case BaseFont.FONT_TYPE_TTUNI: {
200 try {
201 int len = text.length();
202 int metrics[] = null;
203 char glyph[] = new char[len];
204 int i = 0;
205 if (symbolic) {
206 b = PdfEncodings.convertToBytes(text, "symboltt");
207 len = b.length;
208 for (int k = 0; k < len; ++k) {
209 metrics = ttu.getMetricsTT(b[k] & 0xff);
210 if (metrics == null)
211 continue;
212 longTag.put(new Integer(metrics[0]), new int[]{metrics[0], metrics[1], ttu.getUnicodeDifferences(b[k] & 0xff)});
213 glyph[i++] = (char)metrics[0];
214 }
215 }
216 else {
217 for (int k = 0; k < len; ++k) {
218 int val;
219 if (Utilities.isSurrogatePair(text, k)) {
220 val = Utilities.convertToUtf32(text, k);
221 k++;
222 }
223 else {
224 val = text.charAt(k);
225 }
226 metrics = ttu.getMetricsTT(val);
227 if (metrics == null)
228 continue;
229 int m0 = metrics[0];
230 Integer gl = new Integer(m0);
231 if (!longTag.containsKey(gl))
232 longTag.put(gl, new int[]{m0, metrics[1], val});
233 glyph[i++] = (char)m0;
234 }
235 }
236 String s = new String(glyph, 0, i);
237 b = s.getBytes(CJKFont.CJK_ENCODING);
238 }
239 catch (UnsupportedEncodingException e) {
240 throw new ExceptionConverter(e);
241 }
242 break;
243 }
244 }
245 return b;
246 }
247
248 /**
249 * Writes the font definition to the document.
250 * @param writer the <CODE>PdfWriter</CODE> of this document
251 */
252 void writeFont(PdfWriter writer) {
253 try {
254 switch (fontType) {
255 case BaseFont.FONT_TYPE_T3:
256 baseFont.writeFont(writer, indirectReference, null);
257 break;
258 case BaseFont.FONT_TYPE_T1:
259 case BaseFont.FONT_TYPE_TT: {
260 int firstChar;
261 int lastChar;
262 for (firstChar = 0; firstChar < 256; ++firstChar) {
263 if (shortTag[firstChar] != 0)
264 break;
265 }
266 for (lastChar = 255; lastChar >= firstChar; --lastChar) {
267 if (shortTag[lastChar] != 0)
268 break;
269 }
270 if (firstChar > 255) {
271 firstChar = 255;
272 lastChar = 255;
273 }
274 baseFont.writeFont(writer, indirectReference, new Object[]{new Integer(firstChar), new Integer(lastChar), shortTag, Boolean.valueOf(subset)});
275 break;
276 }
277 case BaseFont.FONT_TYPE_CJK:
278 baseFont.writeFont(writer, indirectReference, new Object[]{cjkTag});
279 break;
280 case BaseFont.FONT_TYPE_TTUNI:
281 baseFont.writeFont(writer, indirectReference, new Object[]{longTag, Boolean.valueOf(subset)});
282 break;
283 }
284 }
285 catch(Exception e) {
286 throw new ExceptionConverter(e);
287 }
288 }
289
290 /**
291 * Indicates if all the glyphs and widths for that particular
292 * encoding should be included in the document.
293 * @return <CODE>false</CODE> to include all the glyphs and widths.
294 */
295 public boolean isSubset() {
296 return subset;
297 }
298
299 /**
300 * Indicates if all the glyphs and widths for that particular
301 * encoding should be included in the document. Set to <CODE>false</CODE>
302 * to include all.
303 * @param subset new value of property subset
304 */
305 public void setSubset(boolean subset) {
306 this.subset = subset;
307 }
308 }
309