1 /* 2 * Copyright 2013 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #include "SkPdfFont.h" 9 10 #include "SkPdfNativeTokenizer.h" 11 #include "SkStream.h" 12 #include "SkTypeface.h" 13 14 SkTDict<SkPdfStandardFontEntry>& getStandardFonts() { 15 static SkTDict<SkPdfStandardFontEntry> gPdfStandardFonts(100); 16 17 // TODO (edisonn): , vs - ? what does it mean? 18 // TODO (edisonn): MT, PS, Oblique=italic?, ... what does it mean? 19 if (gPdfStandardFonts.count() == 0) { 20 gPdfStandardFonts.set("Arial", SkPdfStandardFontEntry("Arial", false, false)); 21 gPdfStandardFonts.set("Arial,Bold", SkPdfStandardFontEntry("Arial", true, false)); 22 gPdfStandardFonts.set("Arial,BoldItalic", SkPdfStandardFontEntry("Arial", true, true)); 23 gPdfStandardFonts.set("Arial,Italic", SkPdfStandardFontEntry("Arial", false, true)); 24 gPdfStandardFonts.set("Arial-Bold", SkPdfStandardFontEntry("Arial", true, false)); 25 gPdfStandardFonts.set("Arial-BoldItalic", SkPdfStandardFontEntry("Arial", true, true)); 26 gPdfStandardFonts.set("Arial-BoldItalicMT", SkPdfStandardFontEntry("Arial", true, true)); 27 gPdfStandardFonts.set("Arial-BoldMT", SkPdfStandardFontEntry("Arial", true, false)); 28 gPdfStandardFonts.set("Arial-Italic", SkPdfStandardFontEntry("Arial", false, true)); 29 gPdfStandardFonts.set("Arial-ItalicMT", SkPdfStandardFontEntry("Arial", false, true)); 30 gPdfStandardFonts.set("ArialMT", SkPdfStandardFontEntry("Arial", false, false)); 31 gPdfStandardFonts.set("Courier", SkPdfStandardFontEntry("Courier New", false, false)); 32 gPdfStandardFonts.set("Courier,Bold", SkPdfStandardFontEntry("Courier New", true, false)); 33 gPdfStandardFonts.set("Courier,BoldItalic", SkPdfStandardFontEntry("Courier New", true, true)); 34 gPdfStandardFonts.set("Courier,Italic", SkPdfStandardFontEntry("Courier New", false, true)); 35 gPdfStandardFonts.set("Courier-Bold", SkPdfStandardFontEntry("Courier New", true, false)); 36 gPdfStandardFonts.set("Courier-BoldOblique", SkPdfStandardFontEntry("Courier New", true, true)); 37 gPdfStandardFonts.set("Courier-Oblique", SkPdfStandardFontEntry("Courier New", false, true)); 38 gPdfStandardFonts.set("CourierNew", SkPdfStandardFontEntry("Courier New", false, false)); 39 gPdfStandardFonts.set("CourierNew,Bold", SkPdfStandardFontEntry("Courier New", true, false)); 40 gPdfStandardFonts.set("CourierNew,BoldItalic", SkPdfStandardFontEntry("Courier New", true, true)); 41 gPdfStandardFonts.set("CourierNew,Italic", SkPdfStandardFontEntry("Courier New", false, true)); 42 gPdfStandardFonts.set("CourierNew-Bold", SkPdfStandardFontEntry("Courier New", true, false)); 43 gPdfStandardFonts.set("CourierNew-BoldItalic", SkPdfStandardFontEntry("Courier New", true, true)); 44 gPdfStandardFonts.set("CourierNew-Italic", SkPdfStandardFontEntry("Courier New", false, true)); 45 gPdfStandardFonts.set("CourierNewPS-BoldItalicMT", SkPdfStandardFontEntry("Courier New", true, true)); 46 gPdfStandardFonts.set("CourierNewPS-BoldMT", SkPdfStandardFontEntry("Courier New", true, false)); 47 gPdfStandardFonts.set("CourierNewPS-ItalicMT", SkPdfStandardFontEntry("Courier New", false, true)); 48 gPdfStandardFonts.set("CourierNewPSMT", SkPdfStandardFontEntry("Courier New", false, false)); 49 gPdfStandardFonts.set("Helvetica", SkPdfStandardFontEntry("Helvetica", false, false)); 50 gPdfStandardFonts.set("Helvetica,Bold", SkPdfStandardFontEntry("Helvetica", true, false)); 51 gPdfStandardFonts.set("Helvetica,BoldItalic", SkPdfStandardFontEntry("Helvetica", true, true)); 52 gPdfStandardFonts.set("Helvetica,Italic", SkPdfStandardFontEntry("Helvetica", false, true)); 53 gPdfStandardFonts.set("Helvetica-Bold", SkPdfStandardFontEntry("Helvetica", true, false)); 54 gPdfStandardFonts.set("Helvetica-BoldItalic", SkPdfStandardFontEntry("Helvetica", true, true)); 55 gPdfStandardFonts.set("Helvetica-BoldOblique", SkPdfStandardFontEntry("Helvetica", true, true)); 56 gPdfStandardFonts.set("Helvetica-Italic", SkPdfStandardFontEntry("Helvetica", false, true)); 57 gPdfStandardFonts.set("Helvetica-Oblique", SkPdfStandardFontEntry("Helvetica", false, true)); 58 gPdfStandardFonts.set("Times-Bold", SkPdfStandardFontEntry("Times New Roman", true, false)); 59 gPdfStandardFonts.set("Times-BoldItalic", SkPdfStandardFontEntry("Times New Roman", true, true)); 60 gPdfStandardFonts.set("Times-Italic", SkPdfStandardFontEntry("Times New Roman", false, true)); 61 gPdfStandardFonts.set("Times-Roman", SkPdfStandardFontEntry("Times New Roman", false, false)); 62 gPdfStandardFonts.set("TimesNewRoman", SkPdfStandardFontEntry("Times New Roman", false, false)); 63 gPdfStandardFonts.set("TimesNewRoman,Bold", SkPdfStandardFontEntry("Times New Roman", true, false)); 64 gPdfStandardFonts.set("TimesNewRoman,BoldItalic", SkPdfStandardFontEntry("Times New Roman", true, true)); 65 gPdfStandardFonts.set("TimesNewRoman,Italic", SkPdfStandardFontEntry("Times New Roman", false, true)); 66 gPdfStandardFonts.set("TimesNewRoman-Bold", SkPdfStandardFontEntry("Times New Roman", true, false)); 67 gPdfStandardFonts.set("TimesNewRoman-BoldItalic", SkPdfStandardFontEntry("Times New Roman", true, true)); 68 gPdfStandardFonts.set("TimesNewRoman-Italic", SkPdfStandardFontEntry("Times New Roman", false, true)); 69 gPdfStandardFonts.set("TimesNewRomanPS", SkPdfStandardFontEntry("Times New Roman", false, false)); 70 gPdfStandardFonts.set("TimesNewRomanPS-Bold", SkPdfStandardFontEntry("Times New Roman", true, false)); 71 gPdfStandardFonts.set("TimesNewRomanPS-BoldItalic", SkPdfStandardFontEntry("Times New Roman", true, true)); 72 gPdfStandardFonts.set("TimesNewRomanPS-BoldItalicMT", SkPdfStandardFontEntry("Times New Roman", true, true)); 73 gPdfStandardFonts.set("TimesNewRomanPS-BoldMT", SkPdfStandardFontEntry("Times New Roman", true, false)); 74 gPdfStandardFonts.set("TimesNewRomanPS-Italic", SkPdfStandardFontEntry("Times New Roman", false, true)); 75 gPdfStandardFonts.set("TimesNewRomanPS-ItalicMT", SkPdfStandardFontEntry("Times New Roman", false, true)); 76 gPdfStandardFonts.set("TimesNewRomanPSMT", SkPdfStandardFontEntry("Times New Roman", false, false)); 77 gPdfStandardFonts.set("Symbol", SkPdfStandardFontEntry("Symbol", false, false)); 78 gPdfStandardFonts.set("ZapfDingbats", SkPdfStandardFontEntry("ZapfDingbats", false, false)); 79 80 // TODO(edisonn): these are hacks. Load Post Script font name. 81 // see FT_Get_Postscript_Name 82 // Font config is not using it, yet. 83 //https://bugs.freedesktop.org/show_bug.cgi?id=18095 84 85 gPdfStandardFonts.set("Arial-Black", SkPdfStandardFontEntry("Arial", true, false)); 86 gPdfStandardFonts.set("DejaVuSans", SkPdfStandardFontEntry("DejaVu Sans", false, false)); 87 gPdfStandardFonts.set("DejaVuSansMono", SkPdfStandardFontEntry("DejaVuSans Mono", false, false)); 88 gPdfStandardFonts.set("DejaVuSansMono-Bold", SkPdfStandardFontEntry("DejaVuSans Mono", true, false)); 89 gPdfStandardFonts.set("DejaVuSansMono-Oblique", SkPdfStandardFontEntry("DejaVuSans Mono", false, true)); 90 gPdfStandardFonts.set("Georgia-Bold", SkPdfStandardFontEntry("Georgia", true, false)); 91 gPdfStandardFonts.set("Georgia-BoldItalic", SkPdfStandardFontEntry("Georgia", true, true)); 92 gPdfStandardFonts.set("Georgia-Italic", SkPdfStandardFontEntry("Georgia", false, true)); 93 gPdfStandardFonts.set("TrebuchetMS", SkPdfStandardFontEntry("Trebuchet MS", false, false)); 94 gPdfStandardFonts.set("TrebuchetMS-Bold", SkPdfStandardFontEntry("Trebuchet MS", true, false)); 95 gPdfStandardFonts.set("Verdana-Bold", SkPdfStandardFontEntry("Verdana", true, false)); 96 gPdfStandardFonts.set("WenQuanYiMicroHei", SkPdfStandardFontEntry("WenQuanYi Micro Hei", false, false)); 97 98 // TODO(edisonn): list all fonts available, buil post script name as in pdf spec 99 // TODO(edisonn): Does it work in all OSs ? 100 /* 101 * The PostScript name for the value of BaseFontis determined in one of two ways: 102 Use the PostScript name that is an optional entry in the name table of the 103 TrueType font itself. 104 In the absence of such an entry in the name table, derive a PostScript name 105 from the name by which the font is known in the host operating system: on a 106 Windows system, it is based on the lfFaceName eld in a LOGFONT structure; in 107 the Mac OS, it is based on the name of the FONDresource. If the name contains 108 any spaces, the spaces are removed. 109 If the font in a source document uses a bold or italic style, but there is no font 110 data for that style, the host operating system will synthesize the style. In this case, 111 a comma and the style name (one of Bold, Italic, or BoldItalic) are appended to the 112 font name. For example, for a TrueType font that is a bold variant of the New 113 */ 114 115 /* 116 * If the value of Subtype is MMType1. 117 If the PostScript name of the instance contains spaces, the spaces are replaced 118 by underscores in the value of BaseFont. For instance, as illustrated in Example 119 5.7, the name MinionMM 366 465 11 (which ends with a space character) 120 becomes /MinionMM_366_465_11_. 121 */ 122 } 123 124 return gPdfStandardFonts; 125 } 126 127 SkTypeface* SkTypefaceFromPdfStandardFont(const char* fontName, bool bold, bool italic) { 128 SkTDict<SkPdfStandardFontEntry>& standardFontMap = getStandardFonts(); 129 130 SkTypeface* typeface = NULL; 131 SkPdfStandardFontEntry fontData; 132 133 if (standardFontMap.find(fontName, &fontData)) { 134 // TODO(edisonn): How does the bold/italic specified in standard definition combines with 135 // the one in /font key? use OR for now. 136 bold = bold || fontData.fIsBold; 137 italic = italic || fontData.fIsItalic; 138 139 typeface = SkTypeface::CreateFromName( 140 fontData.fName, 141 SkTypeface::Style((bold ? SkTypeface::kBold : 0) | 142 (italic ? SkTypeface::kItalic : 0))); 143 } else { 144 typeface = SkTypeface::CreateFromName( 145 fontName, 146 SkTypeface::kNormal); 147 } 148 149 if (typeface) { 150 typeface->ref(); 151 } 152 return typeface; 153 } 154 155 SkPdfFont* SkPdfFont::fontFromFontDescriptor(SkPdfNativeDoc* doc, SkPdfFontDescriptorDictionary* fd, 156 bool loadFromName) { 157 // TODO(edisonn): partial implementation. 158 // Only one, at most be available 159 SkPdfStream* pdfStream = NULL; 160 if (fd->has_FontFile()) { 161 pdfStream = fd->FontFile(doc); 162 } else if (fd->has_FontFile2()) { 163 pdfStream = fd->FontFile2(doc); 164 } if (fd->has_FontFile3()) { 165 pdfStream = fd->FontFile3(doc); 166 } else { 167 if (loadFromName) { 168 return fontFromName(doc, fd, fd->FontName(doc).c_str()); 169 } 170 } 171 172 const unsigned char* uncompressedStream = NULL; 173 size_t uncompressedStreamLength = 0; 174 175 // TODO(edisonn): report warning to be used in testing. 176 if (!pdfStream || 177 !pdfStream->GetFilteredStreamRef(&uncompressedStream, &uncompressedStreamLength) || 178 !uncompressedStream || 179 !uncompressedStreamLength) { 180 return NULL; 181 } 182 183 SkMemoryStream* skStream = new SkMemoryStream(uncompressedStream, uncompressedStreamLength); 184 SkTypeface* face = SkTypeface::CreateFromStream(skStream); 185 186 if (face == NULL) { 187 // TODO(edisonn): report warning to be used in testing. 188 return NULL; 189 } 190 191 face->ref(); 192 193 return new SkPdfStandardFont(face); 194 } 195 196 SkPdfFont* fontFromName(SkPdfNativeDoc* doc, SkPdfNativeObject* obj, const char* fontName) { 197 SkTypeface* typeface = SkTypefaceFromPdfStandardFont(fontName, false, false); 198 if (typeface != NULL) { 199 return new SkPdfStandardFont(typeface); 200 } 201 202 // TODO(edisonn): perf - make a map 203 for (unsigned int i = 0 ; i < doc->objects(); i++) { 204 SkPdfNativeObject* obj = doc->object(i); 205 if (!obj || !obj->isDictionary()) { 206 continue; 207 } 208 209 SkPdfFontDescriptorDictionary* fd = obj->asDictionary()->asFontDescriptorDictionary(); 210 211 if (!fd->valid()) { 212 continue; 213 } 214 215 if (fd->has_FontName() && fd->FontName(doc).equals(fontName)) { 216 SkPdfFont* font = SkPdfFont::fontFromFontDescriptor(doc, fd, false); 217 if (font) { 218 return font; 219 } else { 220 // failed to load font descriptor 221 break; 222 } 223 } 224 } 225 226 // TODO(edisonn): warning/report issue 227 return SkPdfFont::Default(); 228 } 229 230 SkPdfFont* SkPdfFont::fontFromPdfDictionaryOnce(SkPdfNativeDoc* doc, SkPdfFontDictionary* dict) { 231 // TODO(edisonn): keep the type in a smart way in the SkPdfNativeObject 232 // 1) flag, isResolved (1bit): reset at reset, add/remove/update (array) and set(dict) 233 // in a tree like structure, 3-4 bits for all the datatypes inheriting from obj (int, real, ...) 234 // if is a dict, reserve a few bytes to encode type of dict, and so on like in a tree 235 // issue: type can be determined from context! atribute night be missing/wrong 236 switch (doc->mapper()->mapFontDictionary(dict)) { 237 case kType0FontDictionary_SkPdfNativeObjectType: 238 return fontFromType0FontDictionary(doc, dict->asType0FontDictionary()); 239 240 case kTrueTypeFontDictionary_SkPdfNativeObjectType: 241 return fontFromTrueTypeFontDictionary(doc, dict->asTrueTypeFontDictionary()); 242 243 case kType1FontDictionary_SkPdfNativeObjectType: 244 return fontFromType1FontDictionary(doc, dict->asType1FontDictionary()); 245 246 case kMultiMasterFontDictionary_SkPdfNativeObjectType: 247 return fontFromMultiMasterFontDictionary(doc, dict->asMultiMasterFontDictionary()); 248 249 case kType3FontDictionary_SkPdfNativeObjectType: 250 return fontFromType3FontDictionary(doc, dict->asType3FontDictionary()); 251 252 default: 253 // TODO(edisonn): report error? 254 return NULL; 255 } 256 } 257 258 SkPdfFont* SkPdfFont::fontFromPdfDictionary(SkPdfNativeDoc* doc, SkPdfFontDictionary* dict) { 259 if (dict == NULL) { 260 return NULL; // TODO(edisonn): report default one? 261 } 262 263 if (!dict->hasData(SkPdfNativeObject::kFont_Data)) { 264 dict->setData(fontFromPdfDictionaryOnce(doc, dict), SkPdfNativeObject::kFont_Data); 265 } 266 return (SkPdfFont*)dict->data(SkPdfNativeObject::kFont_Data); 267 } 268 269 270 271 SkPdfType0Font* SkPdfFont::fontFromType0FontDictionary(SkPdfNativeDoc* doc, 272 SkPdfType0FontDictionary* dict) { 273 if (dict == NULL) { 274 return NULL; // default one? 275 } 276 277 return new SkPdfType0Font(doc, dict); 278 } 279 280 SkPdfType1Font* SkPdfFont:: fontFromType1FontDictionary(SkPdfNativeDoc* doc, 281 SkPdfType1FontDictionary* dict) { 282 if (dict == NULL) { 283 return NULL; // default one? 284 } 285 286 return new SkPdfType1Font(doc, dict); 287 } 288 289 SkPdfType3Font* SkPdfFont::fontFromType3FontDictionary(SkPdfNativeDoc* doc, 290 SkPdfType3FontDictionary* dict) { 291 if (dict == NULL) { 292 return NULL; // default one? 293 } 294 295 296 297 return new SkPdfType3Font(doc, dict); 298 } 299 300 SkPdfTrueTypeFont* SkPdfFont::fontFromTrueTypeFontDictionary(SkPdfNativeDoc* doc, 301 SkPdfTrueTypeFontDictionary* dict) { 302 if (dict == NULL) { 303 return NULL; // default one? 304 } 305 306 return new SkPdfTrueTypeFont(doc, dict); 307 } 308 309 SkPdfMultiMasterFont* SkPdfFont::fontFromMultiMasterFontDictionary( 310 SkPdfNativeDoc* doc, SkPdfMultiMasterFontDictionary* dict) { 311 if (dict == NULL) { 312 return NULL; // default one? 313 } 314 315 return new SkPdfMultiMasterFont(doc, dict); 316 } 317 318 static int skstoi(const SkPdfNativeObject* str) { 319 // TODO(edisonn): report err of it is not a (hex) string 320 int ret = 0; 321 for (unsigned int i = 0 ; i < str->lenstr(); i++) { 322 ret = (ret << 8) + ((unsigned char*)str->c_str())[i]; 323 } 324 // TODO(edisonn): character larger than 0x0000ffff not supported right now. 325 return ret & 0x0000ffff; 326 } 327 328 #define tokenIsKeyword(token,keyword) (token.fType == kKeyword_TokenType && \ 329 token.fKeywordLength==sizeof(keyword)-1 && \ 330 strncmp(token.fKeyword, keyword, sizeof(keyword)-1) == 0) 331 332 SkPdfToUnicode::SkPdfToUnicode(SkPdfNativeDoc* parsed, SkPdfStream* stream) { 333 fCMapEncoding = NULL; 334 fCMapEncodingFlag = NULL; 335 336 if (stream) { 337 // Since font will be cached, the font has to sit in the per doc allocator, not to be 338 // freed after the page is done drawing. 339 SkPdfNativeTokenizer tokenizer(stream, parsed->allocator(), parsed); 340 PdfToken token; 341 342 fCMapEncoding = new unsigned short[256 * 256]; 343 fCMapEncodingFlag = new unsigned char[256 * 256]; 344 for (int i = 0 ; i < 256 * 256; i++) { 345 fCMapEncoding[i] = i; 346 fCMapEncodingFlag[i] = 0; 347 } 348 349 // TODO(edisonn): deal with multibyte character, or longer strings. 350 // Right now we deal with up 2 characters, e.g. <0020> but not longer like <00660066006C> 351 //2 beginbfrange 352 //<0000> <005E> <0020> 353 //<005F> <0061> [<00660066> <00660069> <00660066006C>] 354 355 while (tokenizer.readToken(&token)) { 356 357 if (tokenIsKeyword(token, "begincodespacerange")) { 358 while (tokenizer.readToken(&token) && 359 !tokenIsKeyword(token, "endcodespacerange")) { 360 // tokenizer.PutBack(token); 361 // tokenizer.readToken(&token); 362 // TODO(edisonn): check token type! ignore/report errors. 363 int start = skstoi(token.fObject); 364 tokenizer.readToken(&token); 365 int end = skstoi(token.fObject); 366 for (int i = start; i <= end; i++) { 367 fCMapEncodingFlag[i] |= 1; 368 } 369 } 370 } 371 372 if (tokenIsKeyword(token, "beginbfchar")) { 373 while (tokenizer.readToken(&token) && !tokenIsKeyword(token, "endbfchar")) { 374 // tokenizer.PutBack(token); 375 // tokenizer.readToken(&token); 376 int from = skstoi(token.fObject); 377 tokenizer.readToken(&token); 378 int to = skstoi(token.fObject); 379 380 fCMapEncodingFlag[from] |= 2; 381 fCMapEncoding[from] = to; 382 } 383 } 384 385 if (tokenIsKeyword(token, "beginbfrange")) { 386 while (tokenizer.readToken(&token) && !tokenIsKeyword(token, "endbfrange")) { 387 // tokenizer.PutBack(token); 388 // tokenizer.readToken(&token); 389 int start = skstoi(token.fObject); 390 tokenizer.readToken(&token); 391 int end = skstoi(token.fObject); 392 393 394 tokenizer.readToken(&token); // [ or just an array directly? 395 // do not putback, we will reuse the read. See next commented read. 396 // tokenizer.PutBack(token); 397 398 // TODO(edisonn): read spec: any string or only hex string? 399 if (token.fType == kObject_TokenType && token.fObject->isAnyString()) { 400 // tokenizer.readToken(&token); 401 int value = skstoi(token.fObject); 402 403 for (int i = start; i <= end; i++) { 404 fCMapEncodingFlag[i] |= 2; 405 fCMapEncoding[i] = value; 406 value++; 407 // if i != end, verify last byte id not if, ignore/report error 408 } 409 410 // read one string 411 } else if (token.fType == kObject_TokenType && token.fObject->isArray()) { 412 // tokenizer.readToken(&token); 413 // read array 414 for (unsigned int i = 0; i < token.fObject->size(); i++) { 415 fCMapEncodingFlag[start + i] |= 2; 416 fCMapEncoding[start + i] = skstoi((*token.fObject)[i]); 417 } 418 } else { 419 tokenizer.PutBack(token); 420 } 421 } 422 } 423 } 424 } 425 } 426 427 SkPdfType0Font::SkPdfType0Font(SkPdfNativeDoc* doc, SkPdfType0FontDictionary* dict) { 428 fBaseFont = fontFromName(doc, dict, dict->BaseFont(doc).c_str()); 429 fEncoding = NULL; 430 431 if (dict->has_Encoding()) { 432 if (dict->isEncodingAName(doc)) { 433 fEncoding = SkPdfEncoding::fromName(dict->getEncodingAsName(doc).c_str()); 434 } else if (dict->isEncodingAStream(doc)) { 435 // TODO(edisonn): NYI 436 //fEncoding = loadEncodingFromStream(dict->getEncodingAsStream()); 437 } else { 438 // TODO(edisonn): error ... warning .. assert? 439 } 440 } 441 442 if (dict->has_ToUnicode()) { 443 fToUnicode = new SkPdfToUnicode(doc, dict->ToUnicode(doc)); 444 } 445 } 446 447 SkTDict<SkPdfEncoding*>& getStandardEncodings() { 448 static SkTDict<SkPdfEncoding*> encodings(10); 449 if (encodings.count() == 0) { 450 encodings.set("Identity-H", SkPdfIdentityHEncoding::instance()); 451 } 452 453 return encodings; 454 } 455 456 SkPdfEncoding* SkPdfEncoding::fromName(const char* name) { 457 SkPdfEncoding* encoding = NULL; 458 if (!getStandardEncodings().find(name, &encoding)) { 459 encoding = NULL; 460 } 461 462 #ifdef PDF_TRACE 463 if (encoding == NULL) { 464 printf("Encoding not found: %s\n", name); 465 } 466 #endif 467 return encoding; 468 } 469