001: /*
002: * $Id: FontDetails.java 2366 2006-09-14 23:10:58Z xlv $
003: * $Name$
004: *
005: * Copyright 2001, 2002 by Paulo Soares.
006: *
007: * The contents of this file are subject to the Mozilla Public License Version 1.1
008: * (the "License"); you may not use this file except in compliance with the License.
009: * You may obtain a copy of the License at http://www.mozilla.org/MPL/
010: *
011: * Software distributed under the License is distributed on an "AS IS" basis,
012: * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
013: * for the specific language governing rights and limitations under the License.
014: *
015: * The Original Code is 'iText, a free JAVA-PDF library'.
016: *
017: * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
018: * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
019: * All Rights Reserved.
020: * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
021: * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
022: *
023: * Contributor(s): all the names of the contributors are added in the source code
024: * where applicable.
025: *
026: * Alternatively, the contents of this file may be used under the terms of the
027: * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
028: * provisions of LGPL are applicable instead of those above. If you wish to
029: * allow use of your version of this file only under the terms of the LGPL
030: * License and not to allow others to use your version of this file under
031: * the MPL, indicate your decision by deleting the provisions above and
032: * replace them with the notice and other provisions required by the LGPL.
033: * If you do not delete the provisions above, a recipient may use your version
034: * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
035: *
036: * This library is free software; you can redistribute it and/or modify it
037: * under the terms of the MPL as stated above or under the terms of the GNU
038: * Library General Public License as published by the Free Software Foundation;
039: * either version 2 of the License, or any later version.
040: *
041: * This library is distributed in the hope that it will be useful, but WITHOUT
042: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
043: * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
044: * details.
045: *
046: * If you didn't download this code from the following link, you should check if
047: * you aren't using an obsolete version:
048: * http://www.lowagie.com/iText/
049: */
050:
051: package com.lowagie.text.pdf;
052:
053: import java.io.UnsupportedEncodingException;
054: import java.util.HashMap;
055:
056: import com.lowagie.text.ExceptionConverter;
057:
058: /** Each font in the document will have an instance of this class
059: * where the characters used will be represented.
060: *
061: * @author Paulo Soares (psoares@consiste.pt)
062: */
063: class FontDetails {
064:
065: /** The indirect reference to this font
066: */
067: PdfIndirectReference indirectReference;
068: /** The font name that appears in the document body stream
069: */
070: PdfName fontName;
071: /** The font
072: */
073: BaseFont baseFont;
074: /** The font if its an instance of <CODE>TrueTypeFontUnicode</CODE>
075: */
076: TrueTypeFontUnicode ttu;
077:
078: CJKFont cjkFont;
079: /** The array used with single byte encodings
080: */
081: byte shortTag[];
082: /** The map used with double byte encodings. The key is Integer(glyph) and the
083: * value is int[]{glyph, width, Unicode code}
084: */
085: HashMap longTag;
086:
087: IntHashtable cjkTag;
088: /** The font type
089: */
090: int fontType;
091: /** <CODE>true</CODE> if the font is symbolic
092: */
093: boolean symbolic;
094: /** Indicates if all the glyphs and widths for that particular
095: * encoding should be included in the document.
096: */
097: protected boolean subset = true;
098:
099: /** Each font used in a document has an instance of this class.
100: * This class stores the characters used in the document and other
101: * specifics unique to the current working document.
102: * @param fontName the font name
103: * @param indirectReference the indirect reference to the font
104: * @param baseFont the <CODE>BaseFont</CODE>
105: */
106: FontDetails(PdfName fontName,
107: PdfIndirectReference indirectReference, BaseFont baseFont) {
108: this .fontName = fontName;
109: this .indirectReference = indirectReference;
110: this .baseFont = baseFont;
111: fontType = baseFont.getFontType();
112: switch (fontType) {
113: case BaseFont.FONT_TYPE_T1:
114: case BaseFont.FONT_TYPE_TT:
115: shortTag = new byte[256];
116: break;
117: case BaseFont.FONT_TYPE_CJK:
118: cjkTag = new IntHashtable();
119: cjkFont = (CJKFont) baseFont;
120: break;
121: case BaseFont.FONT_TYPE_TTUNI:
122: longTag = new HashMap();
123: ttu = (TrueTypeFontUnicode) baseFont;
124: symbolic = baseFont.isFontSpecific();
125: break;
126: }
127: }
128:
129: /** Gets the indirect reference to this font.
130: * @return the indirect reference to this font
131: */
132: PdfIndirectReference getIndirectReference() {
133: return indirectReference;
134: }
135:
136: /** Gets the font name as it appears in the document body.
137: * @return the font name
138: */
139: PdfName getFontName() {
140: return fontName;
141: }
142:
143: /** Gets the <CODE>BaseFont</CODE> of this font.
144: * @return the <CODE>BaseFont</CODE> of this font
145: */
146: BaseFont getBaseFont() {
147: return baseFont;
148: }
149:
150: /** Converts the text into bytes to be placed in the document.
151: * The conversion is done according to the font and the encoding and the characters
152: * used are stored.
153: * @param text the text to convert
154: * @return the conversion
155: */
156: byte[] convertToBytes(String text) {
157: byte b[] = null;
158: switch (fontType) {
159: case BaseFont.FONT_TYPE_T3:
160: return baseFont.convertToBytes(text);
161: case BaseFont.FONT_TYPE_T1:
162: case BaseFont.FONT_TYPE_TT: {
163: b = baseFont.convertToBytes(text);
164: int len = b.length;
165: for (int k = 0; k < len; ++k)
166: shortTag[((int) b[k]) & 0xff] = 1;
167: break;
168: }
169: case BaseFont.FONT_TYPE_CJK: {
170: int len = text.length();
171: for (int k = 0; k < len; ++k)
172: cjkTag.put(cjkFont.getCidCode(text.charAt(k)), 0);
173: b = baseFont.convertToBytes(text);
174: break;
175: }
176: case BaseFont.FONT_TYPE_DOCUMENT: {
177: b = baseFont.convertToBytes(text);
178: break;
179: }
180: case BaseFont.FONT_TYPE_TTUNI: {
181: try {
182: int len = text.length();
183: int metrics[] = null;
184: char glyph[] = new char[len];
185: int i = 0;
186: if (symbolic) {
187: b = PdfEncodings.convertToBytes(text, "symboltt");
188: len = b.length;
189: for (int k = 0; k < len; ++k) {
190: metrics = ttu.getMetricsTT(b[k] & 0xff);
191: if (metrics == null)
192: continue;
193: longTag
194: .put(
195: new Integer(metrics[0]),
196: new int[] {
197: metrics[0],
198: metrics[1],
199: ttu
200: .getUnicodeDifferences(b[k] & 0xff) });
201: glyph[i++] = (char) metrics[0];
202: }
203: } else {
204: for (int k = 0; k < len; ++k) {
205: char c = text.charAt(k);
206: metrics = ttu.getMetricsTT(c);
207: if (metrics == null)
208: continue;
209: int m0 = metrics[0];
210: Integer gl = new Integer(m0);
211: if (!longTag.containsKey(gl))
212: longTag.put(gl, new int[] { m0, metrics[1],
213: c });
214: glyph[i++] = (char) m0;
215: }
216: }
217: String s = new String(glyph, 0, i);
218: b = s.getBytes(CJKFont.CJK_ENCODING);
219: } catch (UnsupportedEncodingException e) {
220: throw new ExceptionConverter(e);
221: }
222: break;
223: }
224: }
225: return b;
226: }
227:
228: /** Writes the font definition to the document.
229: * @param writer the <CODE>PdfWriter</CODE> of this document
230: */
231: void writeFont(PdfWriter writer) {
232: try {
233: switch (fontType) {
234: case BaseFont.FONT_TYPE_T3:
235: baseFont.writeFont(writer, indirectReference, null);
236: break;
237: case BaseFont.FONT_TYPE_T1:
238: case BaseFont.FONT_TYPE_TT: {
239: int firstChar;
240: int lastChar;
241: for (firstChar = 0; firstChar < 256; ++firstChar) {
242: if (shortTag[firstChar] != 0)
243: break;
244: }
245: for (lastChar = 255; lastChar >= firstChar; --lastChar) {
246: if (shortTag[lastChar] != 0)
247: break;
248: }
249: if (firstChar > 255) {
250: firstChar = 255;
251: lastChar = 255;
252: }
253: baseFont.writeFont(writer, indirectReference,
254: new Object[] { new Integer(firstChar),
255: new Integer(lastChar), shortTag,
256: new Boolean(subset) });
257: break;
258: }
259: case BaseFont.FONT_TYPE_CJK:
260: baseFont.writeFont(writer, indirectReference,
261: new Object[] { cjkTag });
262: break;
263: case BaseFont.FONT_TYPE_TTUNI:
264: baseFont.writeFont(writer, indirectReference,
265: new Object[] { longTag, new Boolean(subset) });
266: break;
267: }
268: } catch (Exception e) {
269: throw new ExceptionConverter(e);
270: }
271: }
272:
273: /** Indicates if all the glyphs and widths for that particular
274: * encoding should be included in the document.
275: * @return <CODE>false</CODE> to include all the glyphs and widths.
276: */
277: public boolean isSubset() {
278: return subset;
279: }
280:
281: /** Indicates if all the glyphs and widths for that particular
282: * encoding should be included in the document. Set to <CODE>false</CODE>
283: * to include all.
284: * @param subset new value of property subset
285: */
286: public void setSubset(boolean subset) {
287: this.subset = subset;
288: }
289: }
|