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