1 50 51 package com.lowagie.text.pdf; 52 53 import java.io.IOException ; 54 import java.util.Arrays ; 55 import java.util.Comparator ; 56 import java.util.HashMap ; 57 58 import com.lowagie.text.DocumentException; 59 65 class TrueTypeFontUnicode extends TrueTypeFont implements Comparator { 66 67 69 boolean vertical = false; 70 71 81 TrueTypeFontUnicode(String ttFile, String enc, boolean emb, byte ttfAfm[]) throws DocumentException, IOException { 82 String nameBase = getBaseName(ttFile); 83 String ttcName = getTTCName(nameBase); 84 if (nameBase.length() < ttFile.length()) { 85 style = ttFile.substring(nameBase.length()); 86 } 87 encoding = enc; 88 embedded = emb; 89 fileName = ttcName; 90 ttcIndex = ""; 91 if (ttcName.length() < nameBase.length()) 92 ttcIndex = nameBase.substring(ttcName.length() + 1); 93 fontType = FONT_TYPE_TTUNI; 94 if ((fileName.toLowerCase().endsWith(".ttf") || fileName.toLowerCase().endsWith(".otf") || fileName.toLowerCase().endsWith(".ttc")) && ((enc.equals(IDENTITY_H) || enc.equals(IDENTITY_V)) && emb)) { 95 process(ttfAfm); 96 if (os_2.fsType == 2) 97 throw new DocumentException(fileName + style + " cannot be embedded due to licensing restrictions."); 98 if ((cmap31 == null && !fontSpecific) || (cmap10 == null && fontSpecific)) 100 directTextToByte=true; 101 if (fontSpecific) { 103 fontSpecific = false; 104 String tempEncoding = encoding; 105 encoding = ""; 106 createEncoding(); 107 encoding = tempEncoding; 108 fontSpecific = true; 109 } 110 } 111 else 112 throw new DocumentException(fileName + " " + style + " is not a TTF font file."); 113 vertical = enc.endsWith("V"); 114 } 115 116 121 public int getWidth(String text) 122 { 123 if (vertical) 124 return text.length() * 1000; 125 int total = 0; 126 if (fontSpecific) { 127 char cc[] = text.toCharArray(); 128 int len = cc.length; 129 for (int k = 0; k < len; ++k) { 130 char c = cc[k]; 131 if ((c & 0xff00) == 0 || (c & 0xff00) == 0xf000) 132 total += getRawWidth(c & 0xff, null); 133 } 134 } 135 else { 136 int len = text.length(); 137 for (int k = 0; k < len; ++k) 138 total += getRawWidth(text.charAt(k), encoding); 139 } 140 return total; 141 } 142 143 149 private PdfStream getToUnicode(Object metrics[]) { 150 if (metrics.length == 0) 151 return null; 152 StringBuffer buf = new StringBuffer ( 153 "/CIDInit /ProcSet findresource begin\n" + 154 "12 dict begin\n" + 155 "begincmap\n" + 156 "/CIDSystemInfo\n" + 157 "<< /Registry (Adobe)\n" + 158 "/Ordering (UCS)\n" + 159 "/Supplement 0\n" + 160 ">> def\n" + 161 "/CMapName /Adobe-Identity-UCS def\n" + 162 "/CMapType 2 def\n" + 163 "1 begincodespacerange\n" + 164 "<0000><FFFF>\n" + 165 "endcodespacerange\n"); 166 int size = 0; 167 for (int k = 0; k < metrics.length; ++k) { 168 if (size == 0) { 169 if (k != 0) { 170 buf.append("endbfrange\n"); 171 } 172 size = Math.min(100, metrics.length - k); 173 buf.append(size).append(" beginbfrange\n"); 174 } 175 --size; 176 int metric[] = (int[])metrics[k]; 177 String fromTo = toHex(metric[0]); 178 buf.append(fromTo).append(fromTo).append(toHex(metric[2])).append('\n'); 179 } 180 buf.append( 181 "endbfrange\n" + 182 "endcmap\n" + 183 "CMapName currentdict /CMap defineresource pop\n" + 184 "end end\n"); 185 String s = buf.toString(); 186 PdfStream stream = new PdfStream(PdfEncodings.convertToBytes(s, null)); 187 stream.flateCompress(); 188 return stream; 189 } 190 191 195 static String toHex(int n) { 196 String s = Integer.toHexString(n); 197 return "<0000".substring(0, 5 - s.length()) + s + ">"; 198 } 199 200 206 private PdfDictionary getCIDFontType2(PdfIndirectReference fontDescriptor, String subsetPrefix, Object metrics[]) { 207 PdfDictionary dic = new PdfDictionary(PdfName.FONT); 208 if (cff) { 210 dic.put(PdfName.SUBTYPE, PdfName.CIDFONTTYPE0); 211 dic.put(PdfName.BASEFONT, new PdfName(subsetPrefix+fontName+"-"+encoding)); 212 } 213 else { 214 dic.put(PdfName.SUBTYPE, PdfName.CIDFONTTYPE2); 215 dic.put(PdfName.BASEFONT, new PdfName(subsetPrefix + fontName)); 216 } 217 dic.put(PdfName.FONTDESCRIPTOR, fontDescriptor); 218 if (!cff) 219 dic.put(PdfName.CIDTOGIDMAP,PdfName.IDENTITY); 220 PdfDictionary cdic = new PdfDictionary(); 221 cdic.put(PdfName.REGISTRY, new PdfString("Adobe")); 222 cdic.put(PdfName.ORDERING, new PdfString("Identity")); 223 cdic.put(PdfName.SUPPLEMENT, new PdfNumber(0)); 224 dic.put(PdfName.CIDSYSTEMINFO, cdic); 225 if (!vertical) { 226 dic.put(PdfName.DW, new PdfNumber(1000)); 227 StringBuffer buf = new StringBuffer ("["); 228 int lastNumber = -10; 229 boolean firstTime = true; 230 for (int k = 0; k < metrics.length; ++k) { 231 int metric[] = (int[])metrics[k]; 232 if (metric[1] == 1000) 233 continue; 234 int m = metric[0]; 235 if (m == lastNumber + 1) { 236 buf.append(' ').append(metric[1]); 237 } 238 else { 239 if (!firstTime) { 240 buf.append(']'); 241 } 242 firstTime = false; 243 buf.append(m).append('[').append(metric[1]); 244 } 245 lastNumber = m; 246 } 247 if (buf.length() > 1) { 248 buf.append("]]"); 249 dic.put(PdfName.W, new PdfLiteral(buf.toString())); 250 } 251 } 252 return dic; 253 } 254 255 261 private PdfDictionary getFontBaseType(PdfIndirectReference descendant, String subsetPrefix, PdfIndirectReference toUnicode) { 262 PdfDictionary dic = new PdfDictionary(PdfName.FONT); 263 264 dic.put(PdfName.SUBTYPE, PdfName.TYPE0); 265 if (cff) 267 dic.put(PdfName.BASEFONT, new PdfName(subsetPrefix+fontName+"-"+encoding)); 268 else 270 dic.put(PdfName.BASEFONT, new PdfName(subsetPrefix + fontName)); 271 dic.put(PdfName.ENCODING, new PdfName(encoding)); 273 dic.put(PdfName.DESCENDANTFONTS, new PdfArray(descendant)); 274 if (toUnicode != null) 275 dic.put(PdfName.TOUNICODE, toUnicode); 276 return dic; 277 } 278 279 284 public int compare(Object o1, Object o2) { 285 int m1 = ((int[])o1)[0]; 286 int m2 = ((int[])o2)[0]; 287 if (m1 < m2) 288 return -1; 289 if (m1 == m2) 290 return 0; 291 return 1; 292 } 293 294 301 void writeFont(PdfWriter writer, PdfIndirectReference ref, Object params[]) throws DocumentException, IOException { 302 HashMap longTag = (HashMap )params[0]; 303 addRangeUni(longTag, true, subset); 304 Object metrics[] = longTag.values().toArray(); 305 Arrays.sort(metrics, this); 306 PdfIndirectReference ind_font = null; 307 PdfObject pobj = null; 308 PdfIndirectObject obj = null; 309 if (cff) { 311 RandomAccessFileOrArray rf2 = new RandomAccessFileOrArray(rf); 312 byte b[] = new byte[cffLength]; 313 try { 314 rf2.reOpen(); 315 rf2.seek(cffOffset); 316 rf2.readFully(b); 317 } finally { 318 try { 319 rf2.close(); 320 } catch (Exception e) { 321 } 323 } 324 if (subset || subsetRanges != null) { 325 CFFFontSubset cff = new CFFFontSubset(new RandomAccessFileOrArray(b),longTag); 326 b = cff.Process( (cff.getNames())[0] ); 327 } 328 pobj = new StreamFont(b, "CIDFontType0C"); 329 obj = writer.addToBody(pobj); 330 ind_font = obj.getIndirectReference(); 331 } else { 332 byte[] b; 333 if (subset || directoryOffset != 0) { 334 TrueTypeFontSubSet sb = new TrueTypeFontSubSet(fileName, new RandomAccessFileOrArray(rf), longTag, directoryOffset, false, false); 335 b = sb.process(); 336 } 337 else { 338 b = getFullFont(); 339 } 340 int lengths[] = new int[]{b.length}; 341 pobj = new StreamFont(b, lengths); 342 obj = writer.addToBody(pobj); 343 ind_font = obj.getIndirectReference(); 344 } 345 String subsetPrefix = ""; 346 if (subset) 347 subsetPrefix = createSubsetPrefix(); 348 PdfDictionary dic = getFontDescriptor(ind_font, subsetPrefix); 349 obj = writer.addToBody(dic); 350 ind_font = obj.getIndirectReference(); 351 352 pobj = getCIDFontType2(ind_font, subsetPrefix, metrics); 353 obj = writer.addToBody(pobj); 354 ind_font = obj.getIndirectReference(); 355 356 pobj = getToUnicode(metrics); 357 PdfIndirectReference toUnicodeRef = null; 358 359 if (pobj != null) { 360 obj = writer.addToBody(pobj); 361 toUnicodeRef = obj.getIndirectReference(); 362 } 363 364 pobj = getFontBaseType(ind_font, subsetPrefix, toUnicodeRef); 365 writer.addToBody(pobj, ref); 366 } 367 368 372 byte[] convertToBytes(String text) 373 { 374 return null; 375 } 376 377 383 public boolean charExists(char c) { 384 HashMap map = null; 385 if (fontSpecific) 386 map = cmap10; 387 else 388 map = cmap31; 389 if (map == null) 390 return false; 391 if (fontSpecific) { 392 if ((c & 0xff00) == 0 || (c & 0xff00) == 0xf000) 393 return map.get(new Integer (c & 0xff)) != null; 394 else 395 return false; 396 } 397 else 398 return map.get(new Integer (c)) != null; 399 } 400 401 408 public boolean setCharAdvance(char c, int advance) { 409 HashMap map = null; 410 if (fontSpecific) 411 map = cmap10; 412 else 413 map = cmap31; 414 if (map == null) 415 return false; 416 int m[] = null; 417 if (fontSpecific) { 418 if ((c & 0xff00) == 0 || (c & 0xff00) == 0xf000) 419 m = (int[])map.get(new Integer (c & 0xff)); 420 else 421 return false; 422 } 423 else 424 m = (int[])map.get(new Integer (c)); 425 if (m == null) 426 return false; 427 else 428 m[1] = advance; 429 return true; 430 } 431 432 public int[] getCharBBox(char c) { 433 if (bboxes == null) 434 return null; 435 HashMap map = null; 436 if (fontSpecific) 437 map = cmap10; 438 else 439 map = cmap31; 440 if (map == null) 441 return null; 442 int m[] = null; 443 if (fontSpecific) { 444 if ((c & 0xff00) == 0 || (c & 0xff00) == 0xf000) 445 m = (int[])map.get(new Integer (c & 0xff)); 446 else 447 return null; 448 } 449 else 450 m = (int[])map.get(new Integer (c)); 451 if (m == null) 452 return null; 453 return bboxes[m[0]]; 454 } 455 } 456 | Popular Tags |