001: /*
002: * Copyright 2004 by Paulo Soares.
003: *
004: * The contents of this file are subject to the Mozilla Public License Version 1.1
005: * (the "License"); you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at http://www.mozilla.org/MPL/
007: *
008: * Software distributed under the License is distributed on an "AS IS" basis,
009: * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
010: * for the specific language governing rights and limitations under the License.
011: *
012: * The Original Code is 'iText, a free JAVA-PDF library'.
013: *
014: * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
015: * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
016: * All Rights Reserved.
017: * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
018: * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
019: *
020: * Contributor(s): all the names of the contributors are added in the source code
021: * where applicable.
022: *
023: * Alternatively, the contents of this file may be used under the terms of the
024: * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
025: * provisions of LGPL are applicable instead of those above. If you wish to
026: * allow use of your version of this file only under the terms of the LGPL
027: * License and not to allow others to use your version of this file under
028: * the MPL, indicate your decision by deleting the provisions above and
029: * replace them with the notice and other provisions required by the LGPL.
030: * If you do not delete the provisions above, a recipient may use your version
031: * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
032: *
033: * This library is free software; you can redistribute it and/or modify it
034: * under the terms of the MPL as stated above or under the terms of the GNU
035: * Library General Public License as published by the Free Software Foundation;
036: * either version 2 of the License, or any later version.
037: *
038: * This library is distributed in the hope that it will be useful, but WITHOUT
039: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
040: * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
041: * details.
042: *
043: * If you didn't download this code from the following link, you should check if
044: * you aren't using an obsolete version:
045: * http://www.lowagie.com/iText/
046: */
047: package com.lowagie.text.pdf;
048:
049: import java.io.IOException;
050: import java.util.ArrayList;
051: import java.util.HashMap;
052:
053: import com.lowagie.text.DocumentException;
054: import com.lowagie.text.ExceptionConverter;
055:
056: /**
057: *
058: * @author psoares
059: */
060: public class DocumentFont extends BaseFont {
061: // code, [glyph, width]
062: private HashMap metrics = new HashMap();
063: private String fontName;
064: private PRIndirectReference refFont;
065: private PdfDictionary font;
066: private IntHashtable uni2byte = new IntHashtable();
067: private float Ascender = 800;
068: private float CapHeight = 700;
069: private float Descender = -200;
070: private float ItalicAngle = 0;
071: private float llx = -50;
072: private float lly = -200;
073: private float urx = 100;
074: private float ury = 900;
075: private boolean isType0 = false;
076:
077: private BaseFont cjkMirror;
078:
079: private static String cjkNames[] = { "HeiseiMin-W3",
080: "HeiseiKakuGo-W5", "STSong-Light", "MHei-Medium",
081: "MSung-Light", "HYGoThic-Medium", "HYSMyeongJo-Medium",
082: "MSungStd-Light", "STSongStd-Light",
083: "HYSMyeongJoStd-Medium", "KozMinPro-Regular" };
084:
085: private static String cjkEncs[] = { "UniJIS-UCS2-H",
086: "UniJIS-UCS2-H", "UniGB-UCS2-H", "UniCNS-UCS2-H",
087: "UniCNS-UCS2-H", "UniKS-UCS2-H", "UniKS-UCS2-H",
088: "UniCNS-UCS2-H", "UniGB-UCS2-H", "UniKS-UCS2-H",
089: "UniJIS-UCS2-H" };
090:
091: private static String cjkNames2[] = { "MSungStd-Light",
092: "STSongStd-Light", "HYSMyeongJoStd-Medium",
093: "KozMinPro-Regular" };
094:
095: private static String cjkEncs2[] = { "UniCNS-UCS2-H",
096: "UniGB-UCS2-H", "UniKS-UCS2-H", "UniJIS-UCS2-H",
097: "UniCNS-UTF16-H", "UniGB-UTF16-H", "UniKS-UTF16-H",
098: "UniJIS-UTF16-H" };
099:
100: private static final int stdEnc[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
101: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
102: 0, 0, 32, 33, 34, 35, 36, 37, 38, 8217, 40, 41, 42, 43, 44,
103: 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
104: 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74,
105: 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
106: 90, 91, 92, 93, 94, 95, 8216, 97, 98, 99, 100, 101, 102,
107: 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114,
108: 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126,
109: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
110: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 161, 162, 163,
111: 8260, 165, 402, 167, 164, 39, 8220, 171, 8249, 8250, 64257,
112: 64258, 0, 8211, 8224, 8225, 183, 0, 182, 8226, 8218, 8222,
113: 8221, 187, 8230, 8240, 0, 191, 0, 96, 180, 710, 732, 175,
114: 728, 729, 168, 0, 730, 184, 0, 733, 731, 711, 8212, 0, 0,
115: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 198, 0, 170, 0,
116: 0, 0, 0, 321, 216, 338, 186, 0, 0, 0, 0, 0, 230, 0, 0, 0,
117: 305, 0, 0, 322, 248, 339, 223, 0, 0, 0, 0 };
118:
119: /** Creates a new instance of DocumentFont */
120: DocumentFont(PRIndirectReference refFont) {
121: encoding = "";
122: fontSpecific = false;
123: this .refFont = refFont;
124: fontType = FONT_TYPE_DOCUMENT;
125: font = (PdfDictionary) PdfReader.getPdfObject(refFont);
126: fontName = PdfName.decodeName(((PdfName) PdfReader
127: .getPdfObject(font.get(PdfName.BASEFONT))).toString());
128: PdfName subType = (PdfName) PdfReader.getPdfObject(font
129: .get(PdfName.SUBTYPE));
130: if (PdfName.TYPE1.equals(subType)
131: || PdfName.TRUETYPE.equals(subType))
132: doType1TT();
133: else {
134: for (int k = 0; k < cjkNames.length; ++k) {
135: if (fontName.startsWith(cjkNames[k])) {
136: fontName = cjkNames[k];
137: try {
138: cjkMirror = BaseFont.createFont(fontName,
139: cjkEncs[k], false);
140: } catch (Exception e) {
141: throw new ExceptionConverter(e);
142: }
143: return;
144: }
145: }
146: String enc = PdfName.decodeName(((PdfName) PdfReader
147: .getPdfObject(font.get(PdfName.ENCODING)))
148: .toString());
149: for (int k = 0; k < cjkEncs2.length; ++k) {
150: if (enc.startsWith(cjkEncs2[k])) {
151: try {
152: if (k > 3)
153: k -= 4;
154: cjkMirror = BaseFont.createFont(cjkNames2[k],
155: cjkEncs2[k], false);
156: } catch (Exception e) {
157: throw new ExceptionConverter(e);
158: }
159: return;
160: }
161: }
162: if (PdfName.TYPE0.equals(subType)
163: && enc.equals("Identity-H")) {
164: processType0(font);
165: isType0 = true;
166: }
167: }
168: }
169:
170: private void processType0(PdfDictionary font) {
171: try {
172: byte[] touni = PdfReader
173: .getStreamBytes((PRStream) PdfReader
174: .getPdfObjectRelease(font
175: .get(PdfName.TOUNICODE)));
176: PdfArray df = (PdfArray) PdfReader.getPdfObjectRelease(font
177: .get(PdfName.DESCENDANTFONTS));
178: PdfDictionary cidft = (PdfDictionary) PdfReader
179: .getPdfObjectRelease((PdfObject) df.getArrayList()
180: .get(0));
181: PdfNumber dwo = (PdfNumber) PdfReader
182: .getPdfObjectRelease(cidft.get(PdfName.DW));
183: int dw = 1000;
184: if (dwo != null)
185: dw = dwo.intValue();
186: IntHashtable widths = readWidths((PdfArray) PdfReader
187: .getPdfObjectRelease(cidft.get(PdfName.W)));
188: PdfDictionary fontDesc = (PdfDictionary) PdfReader
189: .getPdfObjectRelease(cidft
190: .get(PdfName.FONTDESCRIPTOR));
191: fillFontDesc(fontDesc);
192: fillMetrics(touni, widths, dw);
193: } catch (Exception e) {
194: throw new ExceptionConverter(e);
195: }
196: }
197:
198: private IntHashtable readWidths(PdfArray ws) {
199: IntHashtable hh = new IntHashtable();
200: if (ws == null)
201: return hh;
202: ArrayList ar = ws.getArrayList();
203: for (int k = 0; k < ar.size(); ++k) {
204: int c1 = ((PdfNumber) PdfReader
205: .getPdfObjectRelease((PdfObject) ar.get(k)))
206: .intValue();
207: PdfObject obj = PdfReader
208: .getPdfObjectRelease((PdfObject) ar.get(++k));
209: if (obj.isArray()) {
210: ArrayList ar2 = ((PdfArray) obj).getArrayList();
211: for (int j = 0; j < ar2.size(); ++j) {
212: int c2 = ((PdfNumber) PdfReader
213: .getPdfObjectRelease((PdfObject) ar2.get(j)))
214: .intValue();
215: hh.put(c1++, c2);
216: }
217: } else {
218: int c2 = ((PdfNumber) obj).intValue();
219: int w = ((PdfNumber) PdfReader
220: .getPdfObjectRelease((PdfObject) ar.get(++k)))
221: .intValue();
222: for (; c1 <= c2; ++c1)
223: hh.put(c1, w);
224: }
225: }
226: return hh;
227: }
228:
229: private String decodeString(PdfString ps) {
230: if (ps.isHexWriting())
231: return PdfEncodings.convertToString(ps.getBytes(),
232: "UnicodeBigUnmarked");
233: else
234: return ps.toUnicodeString();
235: }
236:
237: private void fillMetrics(byte[] touni, IntHashtable widths, int dw) {
238: try {
239: PdfContentParser ps = new PdfContentParser(new PRTokeniser(
240: touni));
241: PdfObject ob = null;
242: PdfObject last = null;
243: while ((ob = ps.readPRObject()) != null) {
244: if (ob.type() == PdfContentParser.COMMAND_TYPE) {
245: if (ob.toString().equals("beginbfchar")) {
246: int n = ((PdfNumber) last).intValue();
247: for (int k = 0; k < n; ++k) {
248: String cid = decodeString((PdfString) ps
249: .readPRObject());
250: String uni = decodeString((PdfString) ps
251: .readPRObject());
252: if (uni.length() == 1) {
253: int cidc = (int) cid.charAt(0);
254: int unic = (int) uni.charAt(uni
255: .length() - 1);
256: int w = dw;
257: if (widths.containsKey(cidc))
258: w = widths.get(cidc);
259: metrics.put(new Integer(unic),
260: new int[] { cidc, w });
261: }
262: }
263: } else if (ob.toString().equals("beginbfrange")) {
264: int n = ((PdfNumber) last).intValue();
265: for (int k = 0; k < n; ++k) {
266: String cid1 = decodeString((PdfString) ps
267: .readPRObject());
268: String cid2 = decodeString((PdfString) ps
269: .readPRObject());
270: int cid1c = (int) cid1.charAt(0);
271: int cid2c = (int) cid2.charAt(0);
272: PdfObject ob2 = ps.readPRObject();
273: if (ob2.isString()) {
274: String uni = decodeString((PdfString) ob2);
275: if (uni.length() == 1) {
276: int unic = (int) uni.charAt(uni
277: .length() - 1);
278: for (; cid1c <= cid2c; cid1c++, unic++) {
279: int w = dw;
280: if (widths.containsKey(cid1c))
281: w = widths.get(cid1c);
282: metrics.put(new Integer(unic),
283: new int[] { cid1c, w });
284: }
285: }
286: } else {
287: ArrayList ar = ((PdfArray) ob2)
288: .getArrayList();
289: for (int j = 0; j < ar.size(); ++j, ++cid1c) {
290: String uni = decodeString((PdfString) ar
291: .get(j));
292: if (uni.length() == 1) {
293: int unic = (int) uni.charAt(uni
294: .length() - 1);
295: int w = dw;
296: if (widths.containsKey(cid1c))
297: w = widths.get(cid1c);
298: metrics.put(new Integer(unic),
299: new int[] { cid1c, w });
300: }
301: }
302: }
303: }
304: }
305: } else
306: last = ob;
307: }
308: } catch (Exception e) {
309: throw new ExceptionConverter(e);
310: }
311: }
312:
313: private void doType1TT() {
314: PdfObject enc = PdfReader.getPdfObject(font
315: .get(PdfName.ENCODING));
316: if (enc == null)
317: fillEncoding(null);
318: else {
319: if (enc.isName())
320: fillEncoding((PdfName) enc);
321: else {
322: PdfDictionary encDic = (PdfDictionary) enc;
323: enc = PdfReader.getPdfObject(encDic
324: .get(PdfName.BASEENCODING));
325: if (enc == null)
326: fillEncoding(null);
327: else
328: fillEncoding((PdfName) enc);
329: PdfArray diffs = (PdfArray) PdfReader
330: .getPdfObject(encDic.get(PdfName.DIFFERENCES));
331: if (diffs != null) {
332: ArrayList dif = diffs.getArrayList();
333: int currentNumber = 0;
334: for (int k = 0; k < dif.size(); ++k) {
335: PdfObject obj = (PdfObject) dif.get(k);
336: if (obj.isNumber())
337: currentNumber = ((PdfNumber) obj)
338: .intValue();
339: else {
340: int c[] = GlyphList.nameToUnicode(PdfName
341: .decodeName(((PdfName) obj)
342: .toString()));
343: if (c != null && c.length > 0)
344: uni2byte.put(c[0], currentNumber);
345: ++currentNumber;
346: }
347: }
348: }
349: }
350: }
351: PdfArray newWidths = (PdfArray) PdfReader.getPdfObject(font
352: .get(PdfName.WIDTHS));
353: PdfNumber first = (PdfNumber) PdfReader.getPdfObject(font
354: .get(PdfName.FIRSTCHAR));
355: PdfNumber last = (PdfNumber) PdfReader.getPdfObject(font
356: .get(PdfName.LASTCHAR));
357: if (BuiltinFonts14.containsKey(fontName)) {
358: BaseFont bf;
359: try {
360: bf = BaseFont.createFont(fontName, WINANSI, false);
361: } catch (Exception e) {
362: throw new ExceptionConverter(e);
363: }
364: int e[] = uni2byte.toOrderedKeys();
365: for (int k = 0; k < e.length; ++k) {
366: int n = uni2byte.get(e[k]);
367: widths[n] = bf.getRawWidth(n, GlyphList
368: .unicodeToName(e[k]));
369: }
370: Ascender = bf.getFontDescriptor(ASCENT, 1000);
371: CapHeight = bf.getFontDescriptor(CAPHEIGHT, 1000);
372: Descender = bf.getFontDescriptor(DESCENT, 1000);
373: ItalicAngle = bf.getFontDescriptor(ITALICANGLE, 1000);
374: llx = bf.getFontDescriptor(BBOXLLX, 1000);
375: lly = bf.getFontDescriptor(BBOXLLY, 1000);
376: urx = bf.getFontDescriptor(BBOXURX, 1000);
377: ury = bf.getFontDescriptor(BBOXURY, 1000);
378: }
379: if (first != null && last != null && newWidths != null) {
380: int f = first.intValue();
381: ArrayList ar = newWidths.getArrayList();
382: for (int k = 0; k < ar.size(); ++k) {
383: widths[f + k] = ((PdfNumber) ar.get(k)).intValue();
384: }
385: }
386: fillFontDesc((PdfDictionary) PdfReader.getPdfObject(font
387: .get(PdfName.FONTDESCRIPTOR)));
388: }
389:
390: private void fillFontDesc(PdfDictionary fontDesc) {
391: if (fontDesc == null)
392: return;
393: PdfNumber v = (PdfNumber) PdfReader.getPdfObject(fontDesc
394: .get(PdfName.ASCENT));
395: if (v != null)
396: Ascender = v.floatValue();
397: v = (PdfNumber) PdfReader.getPdfObject(fontDesc
398: .get(PdfName.CAPHEIGHT));
399: if (v != null)
400: CapHeight = v.floatValue();
401: v = (PdfNumber) PdfReader.getPdfObject(fontDesc
402: .get(PdfName.DESCENT));
403: if (v != null)
404: Descender = v.floatValue();
405: v = (PdfNumber) PdfReader.getPdfObject(fontDesc
406: .get(PdfName.ITALICANGLE));
407: if (v != null)
408: ItalicAngle = v.floatValue();
409: PdfArray bbox = (PdfArray) PdfReader.getPdfObject(fontDesc
410: .get(PdfName.FONTBBOX));
411: if (bbox != null) {
412: ArrayList ar = bbox.getArrayList();
413: llx = ((PdfNumber) ar.get(0)).floatValue();
414: lly = ((PdfNumber) ar.get(1)).floatValue();
415: urx = ((PdfNumber) ar.get(2)).floatValue();
416: ury = ((PdfNumber) ar.get(3)).floatValue();
417: if (llx > urx) {
418: float t = llx;
419: llx = urx;
420: urx = t;
421: }
422: if (lly > ury) {
423: float t = lly;
424: lly = ury;
425: ury = t;
426: }
427: }
428: }
429:
430: private void fillEncoding(PdfName encoding) {
431: if (PdfName.MAC_ROMAN_ENCODING.equals(encoding)
432: || PdfName.WIN_ANSI_ENCODING.equals(encoding)) {
433: byte b[] = new byte[256];
434: for (int k = 0; k < 256; ++k)
435: b[k] = (byte) k;
436: String enc = WINANSI;
437: if (PdfName.MAC_ROMAN_ENCODING.equals(encoding))
438: enc = MACROMAN;
439: String cv = PdfEncodings.convertToString(b, enc);
440: char arr[] = cv.toCharArray();
441: for (int k = 0; k < 256; ++k)
442: uni2byte.put(arr[k], k);
443: } else {
444: for (int k = 0; k < 256; ++k)
445: uni2byte.put(stdEnc[k], k);
446: }
447: }
448:
449: /** Gets the family name of the font. If it is a True Type font
450: * each array element will have {Platform ID, Platform Encoding ID,
451: * Language ID, font name}. The interpretation of this values can be
452: * found in the Open Type specification, chapter 2, in the 'name' table.<br>
453: * For the other fonts the array has a single element with {"", "", "",
454: * font name}.
455: * @return the family name of the font
456: *
457: */
458: public String[][] getFamilyFontName() {
459: return null;
460: }
461:
462: /** Gets the font parameter identified by <CODE>key</CODE>. Valid values
463: * for <CODE>key</CODE> are <CODE>ASCENT</CODE>, <CODE>CAPHEIGHT</CODE>, <CODE>DESCENT</CODE>,
464: * <CODE>ITALICANGLE</CODE>, <CODE>BBOXLLX</CODE>, <CODE>BBOXLLY</CODE>, <CODE>BBOXURX</CODE>
465: * and <CODE>BBOXURY</CODE>.
466: * @param key the parameter to be extracted
467: * @param fontSize the font size in points
468: * @return the parameter in points
469: *
470: */
471: public float getFontDescriptor(int key, float fontSize) {
472: if (cjkMirror != null)
473: return cjkMirror.getFontDescriptor(key, fontSize);
474: switch (key) {
475: case AWT_ASCENT:
476: case ASCENT:
477: return Ascender * fontSize / 1000;
478: case CAPHEIGHT:
479: return CapHeight * fontSize / 1000;
480: case AWT_DESCENT:
481: case DESCENT:
482: return Descender * fontSize / 1000;
483: case ITALICANGLE:
484: return ItalicAngle;
485: case BBOXLLX:
486: return llx * fontSize / 1000;
487: case BBOXLLY:
488: return lly * fontSize / 1000;
489: case BBOXURX:
490: return urx * fontSize / 1000;
491: case BBOXURY:
492: return ury * fontSize / 1000;
493: case AWT_LEADING:
494: return 0;
495: case AWT_MAXADVANCE:
496: return (urx - llx) * fontSize / 1000;
497: }
498: return 0;
499: }
500:
501: /** Gets the full name of the font. If it is a True Type font
502: * each array element will have {Platform ID, Platform Encoding ID,
503: * Language ID, font name}. The interpretation of this values can be
504: * found in the Open Type specification, chapter 2, in the 'name' table.<br>
505: * For the other fonts the array has a single element with {"", "", "",
506: * font name}.
507: * @return the full name of the font
508: *
509: */
510: public String[][] getFullFontName() {
511: return null;
512: }
513:
514: /** Gets the kerning between two Unicode chars.
515: * @param char1 the first char
516: * @param char2 the second char
517: * @return the kerning to be applied
518: *
519: */
520: public int getKerning(char char1, char char2) {
521: return 0;
522: }
523:
524: /** Gets the postscript font name.
525: * @return the postscript font name
526: *
527: */
528: public String getPostscriptFontName() {
529: return fontName;
530: }
531:
532: /** Gets the width from the font according to the Unicode char <CODE>c</CODE>
533: * or the <CODE>name</CODE>. If the <CODE>name</CODE> is null it's a symbolic font.
534: * @param c the unicode char
535: * @param name the glyph name
536: * @return the width of the char
537: *
538: */
539: int getRawWidth(int c, String name) {
540: return 0;
541: }
542:
543: /** Checks if the font has any kerning pairs.
544: * @return <CODE>true</CODE> if the font has any kerning pairs
545: *
546: */
547: public boolean hasKernPairs() {
548: return false;
549: }
550:
551: /** Outputs to the writer the font dictionaries and streams.
552: * @param writer the writer for this document
553: * @param ref the font indirect reference
554: * @param params several parameters that depend on the font type
555: * @throws IOException on error
556: * @throws DocumentException error in generating the object
557: *
558: */
559: void writeFont(PdfWriter writer, PdfIndirectReference ref,
560: Object[] params) throws DocumentException, IOException {
561: }
562:
563: /**
564: * Gets the width of a <CODE>char</CODE> in normalized 1000 units.
565: * @param char1 the unicode <CODE>char</CODE> to get the width of
566: * @return the width in normalized 1000 units
567: */
568: public int getWidth(char char1) {
569: if (cjkMirror != null)
570: return cjkMirror.getWidth(char1);
571: else if (isType0) {
572: int[] ws = (int[]) metrics.get(new Integer((int) char1));
573: if (ws != null)
574: return ws[1];
575: else
576: return 0;
577: } else
578: return super .getWidth(char1);
579: }
580:
581: public int getWidth(String text) {
582: if (cjkMirror != null)
583: return cjkMirror.getWidth(text);
584: else if (isType0) {
585: char[] chars = text.toCharArray();
586: int len = chars.length;
587: int total = 0;
588: for (int k = 0; k < len; ++k) {
589: int[] ws = (int[]) metrics.get(new Integer(
590: (int) chars[k]));
591: if (ws != null)
592: total += ws[1];
593: }
594: return total;
595: } else
596: return super .getWidth(text);
597: }
598:
599: byte[] convertToBytes(String text) {
600: if (cjkMirror != null)
601: return PdfEncodings.convertToBytes(text,
602: CJKFont.CJK_ENCODING);
603: else if (isType0) {
604: char[] chars = text.toCharArray();
605: int len = chars.length;
606: byte[] b = new byte[len * 2];
607: int bptr = 0;
608: for (int k = 0; k < len; ++k) {
609: int[] ws = (int[]) metrics.get(new Integer(
610: (int) chars[k]));
611: if (ws != null) {
612: int g = ws[0];
613: b[bptr++] = (byte) (g / 256);
614: b[bptr++] = (byte) (g);
615: }
616: }
617: if (bptr == b.length)
618: return b;
619: else {
620: byte[] nb = new byte[bptr];
621: System.arraycopy(b, 0, nb, 0, bptr);
622: return nb;
623: }
624: } else {
625: char cc[] = text.toCharArray();
626: byte b[] = new byte[cc.length];
627: int ptr = 0;
628: for (int k = 0; k < cc.length; ++k) {
629: if (uni2byte.containsKey(cc[k]))
630: b[ptr++] = (byte) uni2byte.get(cc[k]);
631: }
632: if (ptr == b.length)
633: return b;
634: else {
635: byte[] b2 = new byte[ptr];
636: System.arraycopy(b, 0, b2, 0, ptr);
637: return b2;
638: }
639: }
640: }
641:
642: byte[] convertToBytes(char char1) {
643: if (cjkMirror != null)
644: return PdfEncodings.convertToBytes(char1,
645: CJKFont.CJK_ENCODING);
646: else if (isType0) {
647: int[] ws = (int[]) metrics.get(new Integer((int) char1));
648: if (ws != null) {
649: int g = ws[0];
650: return new byte[] { (byte) (g / 256), (byte) (g) };
651: } else
652: return new byte[0];
653: } else {
654: if (uni2byte.containsKey(char1))
655: return new byte[] { (byte) uni2byte.get(char1) };
656: else
657: return new byte[0];
658: }
659: }
660:
661: PdfIndirectReference getIndirectReference() {
662: return refFont;
663: }
664:
665: public boolean charExists(char c) {
666: if (cjkMirror != null)
667: return cjkMirror.charExists(c);
668: else if (isType0) {
669: return metrics.containsKey(new Integer((int) c));
670: } else
671: return super .charExists(c);
672: }
673:
674: /**
675: * Sets the font name that will appear in the pdf font dictionary.
676: * It does nothing in this case as the font is already in the document.
677: * @param name the new font name
678: */
679: public void setPostscriptFontName(String name) {
680: }
681:
682: public boolean setKerning(char char1, char char2, int kern) {
683: return false;
684: }
685:
686: public int[] getCharBBox(char c) {
687: return null;
688: }
689:
690: protected int[] getRawCharBBox(int c, String name) {
691: return null;
692: }
693: }
|