1a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch/* 2a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch * Copyright 2013 Google Inc. 3a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch * 4a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch * Use of this source code is governed by a BSD-style license that can be 55f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * found in the LICENSE file. 6a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch */ 75c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 8116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// TODO(edisonn): this file not commented much on purpose. 95f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// It will probably need heavy refactoring soon anyway to support all encodings, fonts and 10a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch// proper text sizing and spacing 11a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 12a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#ifndef SkPdfFont_DEFINED 13a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#define SkPdfFont_DEFINED 14a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 15a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "SkPdfContext.h" 16a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "SkPdfHeaders_autogen.h" 17a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "SkPdfMapper_autogen.h" 18a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "SkPdfUtils.h" 19a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "SkTypeface.h" 20a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "SkTDict.h" 21a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "SkUtils.h" 22a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 23a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochclass SkPdfType0Font; 24a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochclass SkPdfType1Font; 25a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochclass SkPdfType3Font; 26a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochclass SkPdfTrueTypeFont; 27cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)class SkPdfMultiMasterFont; 28a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochclass SkPdfFont; 29a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 30a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochstruct SkPdfStandardFontEntry { 31a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch // We don't own this pointer! 32a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch const char* fName; 33a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch bool fIsBold; 34a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch bool fIsItalic; 35a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch SkPdfStandardFontEntry() 36a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch : fName(NULL), 37a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch fIsBold(false), 38a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch fIsItalic(false) {} 39a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu SkPdfStandardFontEntry(const char* name, bool bold, bool italic) 415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu : fName(name), 42116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch fIsBold(bold), 431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci fIsItalic(italic) {} 445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}; 455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuSkTDict<SkPdfStandardFontEntry>& getStandardFonts(); 475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuSkTypeface* SkTypefaceFromPdfStandardFont(const char* fontName, bool bold, bool italic); 485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuSkPdfFont* fontFromName(SkPdfNativeDoc* doc, SkPdfNativeObject* obj, const char* fontName); 495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liustruct SkUnencodedText { 51a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch void* text; 52a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch int len; 53a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 54a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochpublic: 55a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch SkUnencodedText(const SkPdfString* obj) { 56a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch text = (void*)obj->c_str(); 57a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch len = (int) obj->lenstr(); 58a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch } 59a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}; 60a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 61a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochstruct SkDecodedText { 62a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch uint16_t* text; 63 int len; 64public: 65 unsigned int operator[](int i) const { return text[i]; } 66 int size() const { return len; } 67}; 68 69struct SkUnicodeText { 70 uint16_t* text; 71 int len; 72 73public: 74 unsigned int operator[](int i) const { return text[i]; } 75 int size() const { return len; } 76}; 77 78class SkPdfEncoding { 79public: 80 virtual ~SkPdfEncoding() {} 81 virtual bool decodeText(const SkUnencodedText& textIn, SkDecodedText* textOut) const = 0; 82 static SkPdfEncoding* fromName(const char* name); 83}; 84 85SkTDict<SkPdfEncoding*>& getStandardEncodings(); 86 87class SkPdfToUnicode { 88 // TODO(edisonn): hide public members 89public: 90 unsigned short* fCMapEncoding; 91 unsigned char* fCMapEncodingFlag; 92 93 SkPdfToUnicode(SkPdfNativeDoc* parsed, SkPdfStream* stream); 94}; 95 96 97class SkPdfIdentityHEncoding : public SkPdfEncoding { 98public: 99 virtual ~SkPdfIdentityHEncoding() {} 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 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 121class SkPdfDefaultEncoding : public SkPdfEncoding { 122public: 123 virtual ~SkPdfDefaultEncoding() {} 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 138 static SkPdfDefaultEncoding* instance() { 139 static SkPdfDefaultEncoding* inst = new SkPdfDefaultEncoding(); 140 return inst; 141 } 142}; 143 144class SkPdfCIDToGIDMapIdentityEncoding : public SkPdfEncoding { 145public: 146 virtual ~SkPdfCIDToGIDMapIdentityEncoding() {} 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 161 static SkPdfCIDToGIDMapIdentityEncoding* instance() { 162 static SkPdfCIDToGIDMapIdentityEncoding* inst = new SkPdfCIDToGIDMapIdentityEncoding(); 163 return inst; 164 } 165}; 166 167class SkPdfFont { 168public: 169 SkPdfFont* fBaseFont; 170 SkPdfEncoding* fEncoding; 171 SkPdfToUnicode* fToUnicode; 172 173 174public: 175 SkPdfFont() : fBaseFont(NULL), fEncoding(SkPdfDefaultEncoding::instance()), fToUnicode(NULL) {} 176 177 virtual ~SkPdfFont() { 178 // TODO(edisonn): NYI (will leak for now) 179 } 180 181 const SkPdfEncoding* encoding() const {return fEncoding;} 182 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 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 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); 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 251public: 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 256private: 257 static SkPdfFont* fontFromPdfDictionaryOnce(SkPdfNativeDoc* doc, SkPdfFontDictionary* dict); 258}; 259 260class SkPdfStandardFont : public SkPdfFont { 261 SkTypeface* fTypeface; 262 263public: 264 SkPdfStandardFont(SkTypeface* typeface) : fTypeface(typeface) {} 265 266public: 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 282 virtual void afterWord(SkPaint* paint, SkMatrix* matrix) {} 283}; 284 285class SkPdfType0Font : public SkPdfFont { 286public: 287 SkPdfType0Font(SkPdfNativeDoc* doc, SkPdfType0FontDictionary* dict); 288 289public: 290 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 296 virtual void afterWord(SkPaint* paint, SkMatrix* matrix) { 297 } 298}; 299 300class SkPdfType1Font : public SkPdfFont { 301public: 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 317public: 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 323 virtual void afterWord(SkPaint* paint, SkMatrix* matrix) { 324 325 } 326}; 327 328class SkPdfTrueTypeFont : public SkPdfType1Font { 329public: 330 SkPdfTrueTypeFont(SkPdfNativeDoc* doc, SkPdfTrueTypeFontDictionary* dict) 331 : SkPdfType1Font(doc, dict) {} 332}; 333 334class SkPdfMultiMasterFont : public SkPdfType1Font { 335public: 336 SkPdfMultiMasterFont(SkPdfNativeDoc* doc, SkPdfMultiMasterFontDictionary* dict) 337 : SkPdfType1Font(doc, dict) {} 338}; 339/* 340class CIDToGIDMap { 341 virtual unsigned int map(unsigned int cid) = 0; 342 static CIDToGIDMap* fromName(const char* name); 343}; 344 345class 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 354CIDToGIDMap* 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} 366CIDToGIDMap* fCidToGid; 367*/ 368 369class 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 385public: 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 446public: 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 476 virtual void afterWord(SkPaint* paint, SkMatrix* matrix) {} 477}; 478 479#endif // SkPdfFont_DEFINED 480