1 47 package com.lowagie.text.pdf; 48 49 import java.io.IOException ; 50 import java.util.ArrayList ; 51 import java.util.HashMap ; 52 53 import com.lowagie.text.DocumentException; 54 import com.lowagie.text.ExceptionConverter; 55 56 60 public class DocumentFont extends BaseFont { 61 private HashMap metrics = new HashMap (); 63 private String fontName; 64 private PRIndirectReference refFont; 65 private PdfDictionary font; 66 private IntHashtable uni2byte = new IntHashtable(); 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 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(((PdfName)PdfReader.getPdfObject(font.get(PdfName.BASEFONT))).toString()); 118 PdfName subType = (PdfName)PdfReader.getPdfObject(font.get(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(((PdfName)PdfReader.getPdfObject(font.get(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 155 private void processType0(PdfDictionary font) { 156 try { 157 byte[] touni = PdfReader.getStreamBytes((PRStream)PdfReader.getPdfObjectRelease(font.get(PdfName.TOUNICODE))); 158 PdfArray df = (PdfArray)PdfReader.getPdfObjectRelease(font.get(PdfName.DESCENDANTFONTS)); 159 PdfDictionary cidft = (PdfDictionary)PdfReader.getPdfObjectRelease((PdfObject)df.getArrayList().get(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 fillMetrics(touni, widths, dw); 168 } catch (Exception e) { 169 throw new ExceptionConverter(e); 170 } 171 } 172 173 private IntHashtable readWidths(PdfArray ws) { 174 IntHashtable hh = new IntHashtable(); 175 if (ws == null) 176 return hh; 177 ArrayList ar = ws.getArrayList(); 178 for (int k = 0; k < ar.size(); ++k) { 179 int c1 = ((PdfNumber)PdfReader.getPdfObjectRelease((PdfObject)ar.get(k))).intValue(); 180 PdfObject obj = PdfReader.getPdfObjectRelease((PdfObject)ar.get(++k)); 181 if (obj.isArray()) { 182 ArrayList ar2 = ((PdfArray)obj).getArrayList(); 183 for (int j = 0; j < ar2.size(); ++j) { 184 int c2 = ((PdfNumber)PdfReader.getPdfObjectRelease((PdfObject)ar2.get(j))).intValue(); 185 hh.put(c1++, c2); 186 } 187 } 188 else { 189 int c2 = ((PdfNumber)obj).intValue(); 190 int w = ((PdfNumber)PdfReader.getPdfObjectRelease((PdfObject)ar.get(++k))).intValue(); 191 for (; c1 <= c2; ++c1) 192 hh.put(c1, w); 193 } 194 } 195 return hh; 196 } 197 198 private String decodeString(PdfString ps) { 199 if (ps.isHexWriting()) 200 return PdfEncodings.convertToString(ps.getBytes(), "UnicodeBigUnmarked"); 201 else 202 return ps.toUnicodeString(); 203 } 204 205 private void fillMetrics(byte[] touni, IntHashtable widths, int dw) { 206 try { 207 PdfContentParser ps = new PdfContentParser(new PRTokeniser(touni)); 208 PdfObject ob = null; 209 PdfObject last = null; 210 while ((ob = ps.readPRObject()) != null) { 211 if (ob.type() == PdfContentParser.COMMAND_TYPE) { 212 if (ob.toString().equals("beginbfchar")) { 213 int n = ((PdfNumber)last).intValue(); 214 for (int k = 0; k < n; ++k) { 215 String cid = decodeString((PdfString)ps.readPRObject()); 216 String uni = decodeString((PdfString)ps.readPRObject()); 217 if (uni.length() == 1) { 218 int cidc = (int)cid.charAt(0); 219 int unic = (int)uni.charAt(uni.length() - 1); 220 int w = dw; 221 if (widths.containsKey(cidc)) 222 w = widths.get(cidc); 223 metrics.put(new Integer (unic), new int[]{cidc, w}); 224 } 225 } 226 } 227 else if (ob.toString().equals("beginbfrange")) { 228 int n = ((PdfNumber)last).intValue(); 229 for (int k = 0; k < n; ++k) { 230 String cid1 = decodeString((PdfString)ps.readPRObject()); 231 String cid2 = decodeString((PdfString)ps.readPRObject()); 232 int cid1c = (int)cid1.charAt(0); 233 int cid2c = (int)cid2.charAt(0); 234 PdfObject ob2 = ps.readPRObject(); 235 if (ob2.isString()) { 236 String uni = decodeString((PdfString)ob2); 237 if (uni.length() == 1) { 238 int unic = (int)uni.charAt(uni.length() - 1); 239 for (; cid1c <= cid2c; cid1c++, unic++) { 240 int w = dw; 241 if (widths.containsKey(cid1c)) 242 w = widths.get(cid1c); 243 metrics.put(new Integer (unic), new int[]{cid1c, w}); 244 } 245 } 246 } 247 else { 248 ArrayList ar = ((PdfArray)ob2).getArrayList(); 249 for (int j = 0; j < ar.size(); ++j, ++cid1c) { 250 String uni = decodeString((PdfString)ar.get(j)); 251 if (uni.length() == 1) { 252 int unic = (int)uni.charAt(uni.length() - 1); 253 int w = dw; 254 if (widths.containsKey(cid1c)) 255 w = widths.get(cid1c); 256 metrics.put(new Integer (unic), new int[]{cid1c, w}); 257 } 258 } 259 } 260 } 261 } 262 } 263 else 264 last = ob; 265 } 266 } 267 catch (Exception e) { 268 throw new ExceptionConverter(e); 269 } 270 } 271 272 private void doType1TT() { 273 PdfObject enc = PdfReader.getPdfObject(font.get(PdfName.ENCODING)); 274 if (enc == null) 275 fillEncoding(null); 276 else { 277 if (enc.isName()) 278 fillEncoding((PdfName)enc); 279 else { 280 PdfDictionary encDic = (PdfDictionary)enc; 281 enc = PdfReader.getPdfObject(encDic.get(PdfName.BASEENCODING)); 282 if (enc == null) 283 fillEncoding(null); 284 else 285 fillEncoding((PdfName)enc); 286 PdfArray diffs = (PdfArray)PdfReader.getPdfObject(encDic.get(PdfName.DIFFERENCES)); 287 if (diffs != null) { 288 ArrayList dif = diffs.getArrayList(); 289 int currentNumber = 0; 290 for (int k = 0; k < dif.size(); ++k) { 291 PdfObject obj = (PdfObject)dif.get(k); 292 if (obj.isNumber()) 293 currentNumber = ((PdfNumber)obj).intValue(); 294 else { 295 int c[] = GlyphList.nameToUnicode(PdfName.decodeName(((PdfName)obj).toString())); 296 if (c != null && c.length > 0) 297 uni2byte.put(c[0], currentNumber); 298 ++currentNumber; 299 } 300 } 301 } 302 } 303 } 304 PdfArray newWidths = (PdfArray)PdfReader.getPdfObject(font.get(PdfName.WIDTHS)); 305 PdfNumber first = (PdfNumber)PdfReader.getPdfObject(font.get(PdfName.FIRSTCHAR)); 306 PdfNumber last = (PdfNumber)PdfReader.getPdfObject(font.get(PdfName.LASTCHAR)); 307 if (BuiltinFonts14.containsKey(fontName)) { 308 BaseFont bf; 309 try { 310 bf = BaseFont.createFont(fontName, WINANSI, false); 311 } 312 catch (Exception e) { 313 throw new ExceptionConverter(e); 314 } 315 int e[] = uni2byte.toOrderedKeys(); 316 for (int k = 0; k < e.length; ++k) { 317 int n = uni2byte.get(e[k]); 318 widths[n] = bf.getRawWidth(n, GlyphList.unicodeToName(e[k])); 319 } 320 Ascender = bf.getFontDescriptor(ASCENT, 1000); 321 CapHeight = bf.getFontDescriptor(CAPHEIGHT, 1000); 322 Descender = bf.getFontDescriptor(DESCENT, 1000); 323 ItalicAngle = bf.getFontDescriptor(ITALICANGLE, 1000); 324 llx = bf.getFontDescriptor(BBOXLLX, 1000); 325 lly = bf.getFontDescriptor(BBOXLLY, 1000); 326 urx = bf.getFontDescriptor(BBOXURX, 1000); 327 ury = bf.getFontDescriptor(BBOXURY, 1000); 328 } 329 if (first != null && last != null && newWidths != null) { 330 int f = first.intValue(); 331 ArrayList ar = newWidths.getArrayList(); 332 for (int k = 0; k < ar.size(); ++k) { 333 widths[f + k] = ((PdfNumber)ar.get(k)).intValue(); 334 } 335 } 336 fillFontDesc((PdfDictionary)PdfReader.getPdfObject(font.get(PdfName.FONTDESCRIPTOR))); 337 } 338 339 private void fillFontDesc(PdfDictionary fontDesc) { 340 if (fontDesc == null) 341 return; 342 PdfNumber v = (PdfNumber)PdfReader.getPdfObject(fontDesc.get(PdfName.ASCENT)); 343 if (v != null) 344 Ascender = v.floatValue(); 345 v = (PdfNumber)PdfReader.getPdfObject(fontDesc.get(PdfName.CAPHEIGHT)); 346 if (v != null) 347 CapHeight = v.floatValue(); 348 v = (PdfNumber)PdfReader.getPdfObject(fontDesc.get(PdfName.DESCENT)); 349 if (v != null) 350 Descender = v.floatValue(); 351 v = (PdfNumber)PdfReader.getPdfObject(fontDesc.get(PdfName.ITALICANGLE)); 352 if (v != null) 353 ItalicAngle = v.floatValue(); 354 PdfArray bbox = (PdfArray)PdfReader.getPdfObject(fontDesc.get(PdfName.FONTBBOX)); 355 if (bbox != null) { 356 ArrayList ar = bbox.getArrayList(); 357 llx = ((PdfNumber)ar.get(0)).floatValue(); 358 lly = ((PdfNumber)ar.get(1)).floatValue(); 359 urx = ((PdfNumber)ar.get(2)).floatValue(); 360 ury = ((PdfNumber)ar.get(3)).floatValue(); 361 if (llx > urx) { 362 float t = llx; 363 llx = urx; 364 urx = t; 365 } 366 if (lly > ury) { 367 float t = lly; 368 lly = ury; 369 ury = t; 370 } 371 } 372 } 373 374 private void fillEncoding(PdfName encoding) { 375 if (PdfName.MAC_ROMAN_ENCODING.equals(encoding) || PdfName.WIN_ANSI_ENCODING.equals(encoding)) { 376 byte b[] = new byte[256]; 377 for (int k = 0; k < 256; ++k) 378 b[k] = (byte)k; 379 String enc = WINANSI; 380 if (PdfName.MAC_ROMAN_ENCODING.equals(encoding)) 381 enc = MACROMAN; 382 String cv = PdfEncodings.convertToString(b, enc); 383 char arr[] = cv.toCharArray(); 384 for (int k = 0; k < 256; ++k) 385 uni2byte.put(arr[k], k); 386 } 387 else { 388 for (int k = 0; k < 256; ++k) 389 uni2byte.put(stdEnc[k], k); 390 } 391 } 392 393 402 public String [][] getFamilyFontName() { 403 return null; 404 } 405 406 415 public float getFontDescriptor(int key, float fontSize) { 416 if (cjkMirror != null) 417 return cjkMirror.getFontDescriptor(key, fontSize); 418 switch (key) { 419 case AWT_ASCENT: 420 case ASCENT: 421 return Ascender * fontSize / 1000; 422 case CAPHEIGHT: 423 return CapHeight * fontSize / 1000; 424 case AWT_DESCENT: 425 case DESCENT: 426 return Descender * fontSize / 1000; 427 case ITALICANGLE: 428 return ItalicAngle; 429 case BBOXLLX: 430 return llx * fontSize / 1000; 431 case BBOXLLY: 432 return lly * fontSize / 1000; 433 case BBOXURX: 434 return urx * fontSize / 1000; 435 case BBOXURY: 436 return ury * fontSize / 1000; 437 case AWT_LEADING: 438 return 0; 439 case AWT_MAXADVANCE: 440 return (urx - llx) * fontSize / 1000; 441 } 442 return 0; 443 } 444 445 454 public String [][] getFullFontName() { 455 return null; 456 } 457 458 464 public int getKerning(char char1, char char2) { 465 return 0; 466 } 467 468 472 public String getPostscriptFontName() { 473 return fontName; 474 } 475 476 483 int getRawWidth(int c, String name) { 484 return 0; 485 } 486 487 491 public boolean hasKernPairs() { 492 return false; 493 } 494 495 503 void writeFont(PdfWriter writer, PdfIndirectReference ref, Object [] params) throws DocumentException, IOException { 504 } 505 506 public int getWidth(String text) { 507 if (cjkMirror != null) 508 return cjkMirror.getWidth(text); 509 else if (isType0) { 510 char[] chars = text.toCharArray(); 511 int len = chars.length; 512 int total = 0; 513 for (int k = 0; k < len; ++k) { 514 int[] ws = (int[])metrics.get(new Integer ((int)chars[k])); 515 if (ws != null) 516 total += ws[1]; 517 } 518 return total; 519 } 520 else 521 return super.getWidth(text); 522 } 523 524 byte[] convertToBytes(String text) { 525 if (cjkMirror != null) 526 return PdfEncodings.convertToBytes(text, CJKFont.CJK_ENCODING); 527 else if (isType0) { 528 char[] chars = text.toCharArray(); 529 int len = chars.length; 530 byte[] b = new byte[len * 2]; 531 int bptr = 0; 532 for (int k = 0; k < len; ++k) { 533 int[] ws = (int[])metrics.get(new Integer ((int)chars[k])); 534 if (ws != null) { 535 int g = ws[0]; 536 b[bptr++] = (byte)(g / 256); 537 b[bptr++] = (byte)(g); 538 } 539 } 540 if (bptr == b.length) 541 return b; 542 else { 543 byte[] nb = new byte[bptr]; 544 System.arraycopy(b, 0, nb, 0, bptr); 545 return nb; 546 } 547 } 548 else { 549 char cc[] = text.toCharArray(); 550 byte b[] = new byte[cc.length]; 551 int ptr = 0; 552 for (int k = 0; k < cc.length; ++k) { 553 if (uni2byte.containsKey(cc[k])) 554 b[ptr++] = (byte)uni2byte.get(cc[k]); 555 } 556 if (ptr == b.length) 557 return b; 558 else { 559 byte[] b2 = new byte[ptr]; 560 System.arraycopy(b, 0, b2, 0, ptr); 561 return b2; 562 } 563 } 564 } 565 566 PdfIndirectReference getIndirectReference() { 567 return refFont; 568 } 569 570 public boolean charExists(char c) { 571 if (cjkMirror != null) 572 return cjkMirror.charExists(c); 573 else if (isType0) { 574 return metrics.containsKey(new Integer ((int)c)); 575 } 576 else 577 return super.charExists(c); 578 } 579 580 585 public void setPostscriptFontName(String name) { 586 } 587 588 public boolean setKerning(char char1, char char2, int kern) { 589 return false; 590 } 591 592 public int[] getCharBBox(char c) { 593 return null; 594 } 595 596 protected int[] getRawCharBBox(int c, String name) { 597 return null; 598 } 599 } | Popular Tags |