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 // TODO(edisonn): this file not commented much on purpose. 9 // It will probably need heavy refactoring soon anyway to support all encodings, fonts and 10 // proper text sizing and spacing 11 12 #ifndef SkPdfFont_DEFINED 13 #define SkPdfFont_DEFINED 14 15 #include "SkPdfContext.h" 16 #include "SkPdfHeaders_autogen.h" 17 #include "SkPdfMapper_autogen.h" 18 #include "SkPdfUtils.h" 19 #include "SkTypeface.h" 20 #include "SkTDict.h" 21 #include "SkUtils.h" 22 23 class SkPdfType0Font; 24 class SkPdfType1Font; 25 class SkPdfType3Font; 26 class SkPdfTrueTypeFont; 27 class SkPdfMultiMasterFont; 28 class SkPdfFont; 29 30 struct SkPdfStandardFontEntry { 31 // We don't own this pointer! 32 const char* fName; 33 bool fIsBold; 34 bool fIsItalic; SkPdfStandardFontEntrySkPdfStandardFontEntry35 SkPdfStandardFontEntry() 36 : fName(NULL), 37 fIsBold(false), 38 fIsItalic(false) {} 39 SkPdfStandardFontEntrySkPdfStandardFontEntry40 SkPdfStandardFontEntry(const char* name, bool bold, bool italic) 41 : fName(name), 42 fIsBold(bold), 43 fIsItalic(italic) {} 44 }; 45 46 SkTDict<SkPdfStandardFontEntry>& getStandardFonts(); 47 SkTypeface* SkTypefaceFromPdfStandardFont(const char* fontName, bool bold, bool italic); 48 SkPdfFont* fontFromName(SkPdfNativeDoc* doc, SkPdfNativeObject* obj, const char* fontName); 49 50 struct SkUnencodedText { 51 void* text; 52 int len; 53 54 public: SkUnencodedTextSkUnencodedText55 SkUnencodedText(const SkPdfString* obj) { 56 text = (void*)obj->c_str(); 57 len = (int) obj->lenstr(); 58 } 59 }; 60 61 struct SkDecodedText { 62 uint16_t* text; 63 int len; 64 public: 65 unsigned int operator[](int i) const { return text[i]; } sizeSkDecodedText66 int size() const { return len; } 67 }; 68 69 struct SkUnicodeText { 70 uint16_t* text; 71 int len; 72 73 public: 74 unsigned int operator[](int i) const { return text[i]; } sizeSkUnicodeText75 int size() const { return len; } 76 }; 77 78 class SkPdfEncoding { 79 public: ~SkPdfEncoding()80 virtual ~SkPdfEncoding() {} 81 virtual bool decodeText(const SkUnencodedText& textIn, SkDecodedText* textOut) const = 0; 82 static SkPdfEncoding* fromName(const char* name); 83 }; 84 85 SkTDict<SkPdfEncoding*>& getStandardEncodings(); 86 87 class SkPdfToUnicode { 88 // TODO(edisonn): hide public members 89 public: 90 unsigned short* fCMapEncoding; 91 unsigned char* fCMapEncodingFlag; 92 93 SkPdfToUnicode(SkPdfNativeDoc* parsed, SkPdfStream* stream); 94 }; 95 96 97 class SkPdfIdentityHEncoding : public SkPdfEncoding { 98 public: ~SkPdfIdentityHEncoding()99 virtual ~SkPdfIdentityHEncoding() {} decodeText(const SkUnencodedText & textIn,SkDecodedText * textOut)100 virtual bool decodeText(const SkUnencodedText& textIn, SkDecodedText* textOut) const { 101 // TODO(edisonn): SkASSERT(textIn.len % 2 == 0); or report error? 102 103 uint16_t* text = (uint16_t*)textIn.text; 104 textOut->text = new uint16_t[textIn.len / 2]; 105 textOut->len = textIn.len / 2; 106 107 for (int i = 0; i < textOut->len; i++) { 108 textOut->text[i] = ((text[i] << 8) & 0xff00) | ((text[i] >> 8) & 0x00ff); 109 } 110 111 return true; 112 } 113 instance()114 static SkPdfIdentityHEncoding* instance() { 115 static SkPdfIdentityHEncoding* inst = new SkPdfIdentityHEncoding(); 116 return inst; 117 } 118 }; 119 120 // TODO(edisonn): using this one when no encoding is specified 121 class SkPdfDefaultEncoding : public SkPdfEncoding { 122 public: ~SkPdfDefaultEncoding()123 virtual ~SkPdfDefaultEncoding() {} decodeText(const SkUnencodedText & textIn,SkDecodedText * textOut)124 virtual bool decodeText(const SkUnencodedText& textIn, SkDecodedText* textOut) const { 125 // TODO(edisonn): SkASSERT(textIn.len % 2 == 0); or report error? 126 127 unsigned char* text = (unsigned char*)textIn.text; 128 textOut->text = new uint16_t[textIn.len]; 129 textOut->len = textIn.len; 130 131 for (int i = 0; i < textOut->len; i++) { 132 textOut->text[i] = text[i]; 133 } 134 135 return true; 136 } 137 instance()138 static SkPdfDefaultEncoding* instance() { 139 static SkPdfDefaultEncoding* inst = new SkPdfDefaultEncoding(); 140 return inst; 141 } 142 }; 143 144 class SkPdfCIDToGIDMapIdentityEncoding : public SkPdfEncoding { 145 public: ~SkPdfCIDToGIDMapIdentityEncoding()146 virtual ~SkPdfCIDToGIDMapIdentityEncoding() {} decodeText(const SkUnencodedText & textIn,SkDecodedText * textOut)147 virtual bool decodeText(const SkUnencodedText& textIn, SkDecodedText* textOut) const { 148 // TODO(edisonn): SkASSERT(textIn.len % 2 == 0); or report error? 149 150 uint16_t* text = (uint16_t*)textIn.text; 151 textOut->text = new uint16_t[textIn.len / 2]; 152 textOut->len = textIn.len / 2; 153 154 for (int i = 0; i < textOut->len; i++) { 155 textOut->text[i] = ((text[i] << 8) & 0xff00) | ((text[i] >> 8) & 0x00ff); 156 } 157 158 return true; 159 } 160 instance()161 static SkPdfCIDToGIDMapIdentityEncoding* instance() { 162 static SkPdfCIDToGIDMapIdentityEncoding* inst = new SkPdfCIDToGIDMapIdentityEncoding(); 163 return inst; 164 } 165 }; 166 167 class SkPdfFont { 168 public: 169 SkPdfFont* fBaseFont; 170 SkPdfEncoding* fEncoding; 171 SkPdfToUnicode* fToUnicode; 172 173 174 public: SkPdfFont()175 SkPdfFont() : fBaseFont(NULL), fEncoding(SkPdfDefaultEncoding::instance()), fToUnicode(NULL) {} 176 ~SkPdfFont()177 virtual ~SkPdfFont() { 178 // TODO(edisonn): NYI (will leak for now) 179 } 180 encoding()181 const SkPdfEncoding* encoding() const {return fEncoding;} 182 drawText(const SkDecodedText & text,SkPaint * paint,SkPdfContext * pdfContext,SkCanvas * canvas)183 void drawText(const SkDecodedText& text, SkPaint* paint, SkPdfContext* pdfContext, 184 SkCanvas* canvas) { 185 for (int i = 0 ; i < text.size(); i++) { 186 canvas->setMatrix(pdfContext->fGraphicsState.fMatrixTm); 187 #ifdef PDF_TRACE 188 SkPoint point = SkPoint::Make(SkDoubleToScalar(0), SkDoubleToScalar(0)); 189 pdfContext->fGraphicsState.fMatrixTm.mapPoints(&point, 1); 190 printf("DrawText at (%f, %f)\n", SkScalarToDouble(point.x()), 191 SkScalarToDouble(point.y())); 192 #endif // PDF_TRACE 193 194 #ifdef PDF_TRACE_DRAWTEXT 195 SkPaint col; 196 col.setColor(SK_ColorMAGENTA); 197 SkRect rect = SkRect::MakeXYWH(SkDoubleToScalar(0.0), 198 SkDoubleToScalar(0.0), 199 SkDoubleToScalar(10.0), 200 SkDoubleToScalar(10.0)); 201 canvas->save(); 202 canvas->setMatrix(pdfContext->fGraphicsState.fMatrixTm); 203 canvas->drawRect(rect, col); 204 canvas->restore(); 205 #endif 206 double width = drawOneChar(text[i], paint, pdfContext, canvas); 207 pdfContext->fGraphicsState.fMatrixTm.preTranslate(SkDoubleToScalar(width), 208 SkDoubleToScalar(0.0)); 209 } 210 } 211 ToUnicode(const SkDecodedText & textIn,SkUnicodeText * textOut)212 void ToUnicode(const SkDecodedText& textIn, SkUnicodeText* textOut) const { 213 if (fToUnicode) { 214 textOut->text = new uint16_t[textIn.len]; 215 textOut->len = textIn.len; 216 for (int i = 0; i < textIn.len; i++) { 217 textOut->text[i] = fToUnicode->fCMapEncoding[textIn.text[i]]; 218 } 219 } else { 220 textOut->text = textIn.text; 221 textOut->len = textIn.len; 222 } 223 }; 224 ToUnicode(unsigned int ch)225 inline unsigned int ToUnicode(unsigned int ch) const { 226 if (fToUnicode && fToUnicode->fCMapEncoding) { 227 return fToUnicode->fCMapEncoding[ch]; 228 } else { 229 return ch; 230 } 231 }; 232 233 static SkPdfFont* fontFromPdfDictionary(SkPdfNativeDoc* doc, SkPdfFontDictionary* dict); Default()234 static SkPdfFont* Default() {return fontFromName(NULL, NULL, "TimesNewRoman");} 235 236 static SkPdfType0Font* fontFromType0FontDictionary(SkPdfNativeDoc* doc, 237 SkPdfType0FontDictionary* dict); 238 static SkPdfType1Font* fontFromType1FontDictionary(SkPdfNativeDoc* doc, 239 SkPdfType1FontDictionary* dict); 240 static SkPdfType3Font* fontFromType3FontDictionary(SkPdfNativeDoc* doc, 241 SkPdfType3FontDictionary* dict); 242 static SkPdfTrueTypeFont* fontFromTrueTypeFontDictionary(SkPdfNativeDoc* doc, 243 SkPdfTrueTypeFontDictionary* dict); 244 static SkPdfMultiMasterFont* fontFromMultiMasterFontDictionary( 245 SkPdfNativeDoc* doc, SkPdfMultiMasterFontDictionary* dict); 246 247 static SkPdfFont* fontFromFontDescriptor(SkPdfNativeDoc* doc, 248 SkPdfFontDescriptorDictionary* fd, 249 bool loadFromName = true); 250 251 public: 252 virtual double drawOneChar(unsigned int ch, SkPaint* paint, SkPdfContext* pdfContext, 253 SkCanvas* canvas) = 0; 254 virtual void afterWord(SkPaint* paint, SkMatrix* matrix) = 0; 255 256 private: 257 static SkPdfFont* fontFromPdfDictionaryOnce(SkPdfNativeDoc* doc, SkPdfFontDictionary* dict); 258 }; 259 260 class SkPdfStandardFont : public SkPdfFont { 261 SkTypeface* fTypeface; 262 263 public: SkPdfStandardFont(SkTypeface * typeface)264 SkPdfStandardFont(SkTypeface* typeface) : fTypeface(typeface) {} 265 266 public: drawOneChar(unsigned int ch,SkPaint * paint,SkPdfContext * pdfContext,SkCanvas * canvas)267 virtual double drawOneChar(unsigned int ch, SkPaint* paint, SkPdfContext* pdfContext, 268 SkCanvas* canvas) { 269 paint->setTypeface(fTypeface); 270 paint->setTextEncoding(SkPaint::kUTF8_TextEncoding); 271 272 unsigned long ch4 = ch; 273 char utf8[10]; 274 size_t len = SkUTF8_FromUnichar((SkUnichar) ch4, utf8); 275 276 canvas->drawText(utf8, len, SkDoubleToScalar(0), SkDoubleToScalar(0), *paint); 277 278 SkScalar textWidth = paint->measureText(utf8, len); 279 return SkScalarToDouble(textWidth); 280 } 281 afterWord(SkPaint * paint,SkMatrix * matrix)282 virtual void afterWord(SkPaint* paint, SkMatrix* matrix) {} 283 }; 284 285 class SkPdfType0Font : public SkPdfFont { 286 public: 287 SkPdfType0Font(SkPdfNativeDoc* doc, SkPdfType0FontDictionary* dict); 288 289 public: 290 drawOneChar(unsigned int ch,SkPaint * paint,SkPdfContext * pdfContext,SkCanvas * canvas)291 virtual double drawOneChar(unsigned int ch, SkPaint* paint, SkPdfContext* pdfContext, 292 SkCanvas* canvas) { 293 return fBaseFont->drawOneChar(ToUnicode(ch), paint, pdfContext, canvas); 294 } 295 afterWord(SkPaint * paint,SkMatrix * matrix)296 virtual void afterWord(SkPaint* paint, SkMatrix* matrix) { 297 } 298 }; 299 300 class SkPdfType1Font : public SkPdfFont { 301 public: SkPdfType1Font(SkPdfNativeDoc * doc,SkPdfType1FontDictionary * dict)302 SkPdfType1Font(SkPdfNativeDoc* doc, SkPdfType1FontDictionary* dict) { 303 if (dict->has_FontDescriptor()) { 304 fBaseFont = SkPdfFont::fontFromFontDescriptor(doc, dict->FontDescriptor(doc)); 305 } else { 306 fBaseFont = fontFromName(doc, dict, dict->BaseFont(doc).c_str()); 307 } 308 309 if (dict->isEncodingAName(doc)) { 310 fEncoding = SkPdfEncoding::fromName(dict->getEncodingAsName(doc).c_str()); 311 } else if (dict->isEncodingADictionary(doc)) { 312 //SkPdfDictionary* dictEnc = dict->getEncodingAsDictionary(doc); 313 } 314 dict->FontDescriptor(doc); 315 } 316 317 public: drawOneChar(unsigned int ch,SkPaint * paint,SkPdfContext * pdfContext,SkCanvas * canvas)318 virtual double drawOneChar(unsigned int ch, SkPaint* paint, SkPdfContext* pdfContext, 319 SkCanvas* canvas) { 320 return fBaseFont->drawOneChar(ToUnicode(ch), paint, pdfContext, canvas); 321 } 322 afterWord(SkPaint * paint,SkMatrix * matrix)323 virtual void afterWord(SkPaint* paint, SkMatrix* matrix) { 324 325 } 326 }; 327 328 class SkPdfTrueTypeFont : public SkPdfType1Font { 329 public: SkPdfTrueTypeFont(SkPdfNativeDoc * doc,SkPdfTrueTypeFontDictionary * dict)330 SkPdfTrueTypeFont(SkPdfNativeDoc* doc, SkPdfTrueTypeFontDictionary* dict) 331 : SkPdfType1Font(doc, dict) {} 332 }; 333 334 class SkPdfMultiMasterFont : public SkPdfType1Font { 335 public: SkPdfMultiMasterFont(SkPdfNativeDoc * doc,SkPdfMultiMasterFontDictionary * dict)336 SkPdfMultiMasterFont(SkPdfNativeDoc* doc, SkPdfMultiMasterFontDictionary* dict) 337 : SkPdfType1Font(doc, dict) {} 338 }; 339 /* 340 class CIDToGIDMap { 341 virtual unsigned int map(unsigned int cid) = 0; 342 static CIDToGIDMap* fromName(const char* name); 343 }; 344 345 class CIDToGIDMap_Identity { 346 virtual unsigned int map(unsigned int cid) { return cid; } 347 348 static CIDToGIDMap_Identity* instance() { 349 static CIDToGIDMap_Identity* inst = new CIDToGIDMap_Identity(); 350 return inst; 351 } 352 }; 353 354 CIDToGIDMap* CIDToGIDMap::fromName(const char* name) { 355 // The only one supported right now is Identity 356 if (strcmp(name, "Identity") == 0) { 357 return CIDToGIDMap_Identity::instance(); 358 } 359 360 #ifdef PDF_TRACE 361 // TODO(edisonn): warning/report 362 printf("Unknown CIDToGIDMap: %s\n", name); 363 #endif 364 return NULL; 365 } 366 CIDToGIDMap* fCidToGid; 367 */ 368 369 class SkPdfType3Font : public SkPdfFont { 370 struct Type3FontChar { 371 SkPdfNativeObject* fObj; 372 double fWidth; 373 }; 374 375 SkPdfDictionary* fCharProcs; 376 SkPdfEncodingDictionary* fEncodingDict; 377 unsigned int fFirstChar; 378 unsigned int fLastChar; 379 380 SkRect fFontBBox; 381 SkMatrix fFonMatrix; 382 383 Type3FontChar* fChars; 384 385 public: SkPdfType3Font(SkPdfNativeDoc * parsed,SkPdfType3FontDictionary * dict)386 SkPdfType3Font(SkPdfNativeDoc* parsed, SkPdfType3FontDictionary* dict) { 387 fBaseFont = fontFromName(parsed, dict, dict->BaseFont(parsed).c_str()); 388 389 if (dict->has_Encoding()) { 390 if (dict->isEncodingAName(parsed)) { 391 fEncoding = SkPdfEncoding::fromName(dict->getEncodingAsName(parsed).c_str()); 392 } else if (dict->isEncodingAEncodingdictionary(parsed)) { 393 // No encoding. 394 fEncoding = SkPdfDefaultEncoding::instance(); 395 fEncodingDict = dict->getEncodingAsEncodingdictionary(parsed); 396 } 397 } 398 399 // null? 400 fCharProcs = dict->CharProcs(parsed); 401 402 fToUnicode = NULL; 403 if (dict->has_ToUnicode()) { 404 fToUnicode = new SkPdfToUnicode(parsed, dict->ToUnicode(parsed)); 405 } 406 407 fFirstChar = (unsigned int)dict->FirstChar(parsed); 408 fLastChar = (unsigned int)dict->LastChar(parsed); 409 fFonMatrix = dict->has_FontMatrix() ? dict->FontMatrix(parsed) : SkMatrix::I(); 410 411 if (dict->has_FontBBox()) { 412 fFontBBox = dict->FontBBox(parsed); 413 } 414 415 fChars = new Type3FontChar[fLastChar - fFirstChar + 1]; 416 417 memset(fChars, 0, sizeof(fChars[0]) * (fLastChar - fFirstChar + 1)); 418 419 const SkPdfArray* widths = dict->Widths(parsed); 420 for (unsigned int i = 0 ; i < widths->size(); i++) { 421 if ((fFirstChar + i) >= fFirstChar && (fFirstChar + i) <= fLastChar) { 422 fChars[i].fWidth = (*widths)[i]->numberValue(); 423 } else { 424 // TODO(edisonn): report pdf corruption 425 } 426 } 427 428 const SkPdfArray* diffs = fEncodingDict->Differences(parsed); 429 unsigned int j = fFirstChar; 430 for (unsigned int i = 0 ; i < diffs->size(); i++) { 431 if ((*diffs)[i]->isInteger()) { 432 j = (unsigned int)(*diffs)[i]->intValue(); 433 } else if ((*diffs)[i]->isName()) { 434 if (j >= fFirstChar && j <= fLastChar) { 435 fChars[j - fFirstChar].fObj = fCharProcs->get((*diffs)[i]); 436 } else { 437 // TODO(edisonn): report pdf corruption 438 } 439 j++; 440 } else { 441 // TODO(edisonn): report bad pdf 442 } 443 } 444 } 445 446 public: drawOneChar(unsigned int ch,SkPaint * paint,SkPdfContext * pdfContext,SkCanvas * canvas)447 virtual double drawOneChar(unsigned int ch, SkPaint* paint, SkPdfContext* pdfContext, 448 SkCanvas* canvas) { 449 if (ch < fFirstChar || ch > fLastChar || !fChars[ch - fFirstChar].fObj) { 450 return fBaseFont->drawOneChar(ToUnicode(ch), paint, pdfContext, canvas); 451 } 452 453 #ifdef PDF_TRACE 454 printf("Type 3 char to unicode: %c\n", ToUnicode(ch)); 455 if (ToUnicode(ch) == 'A') { 456 printf("break;\n"); 457 } 458 #endif 459 460 // TODO(edisonn): is it better to resolve the reference at load time, or now? 461 doType3Char(pdfContext, 462 canvas, 463 pdfContext->fPdfDoc->resolveReference(fChars[ch - fFirstChar].fObj), 464 fFontBBox, 465 fFonMatrix, 466 pdfContext->fGraphicsState.fCurFontSize); 467 468 // TODO(edisonn): verify/test translate code, not tested yet 469 pdfContext->fGraphicsState.fMatrixTm.preTranslate( 470 SkDoubleToScalar(pdfContext->fGraphicsState.fCurFontSize * 471 fChars[ch - fFirstChar].fWidth), 472 SkDoubleToScalar(0.0)); 473 return fChars[ch - fFirstChar].fWidth; 474 } 475 afterWord(SkPaint * paint,SkMatrix * matrix)476 virtual void afterWord(SkPaint* paint, SkMatrix* matrix) {} 477 }; 478 479 #endif // SkPdfFont_DEFINED 480