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 23class SkPdfType0Font; 24class SkPdfType1Font; 25class SkPdfType3Font; 26class SkPdfTrueTypeFont; 27class SkPdfMultiMasterFont; 28class SkPdfFont; 29 30struct SkPdfStandardFontEntry { 31 // We don't own this pointer! 32 const char* fName; 33 bool fIsBold; 34 bool fIsItalic; 35 SkPdfStandardFontEntry() 36 : fName(NULL), 37 fIsBold(false), 38 fIsItalic(false) {} 39 40 SkPdfStandardFontEntry(const char* name, bool bold, bool italic) 41 : fName(name), 42 fIsBold(bold), 43 fIsItalic(italic) {} 44}; 45 46SkTDict<SkPdfStandardFontEntry>& getStandardFonts(); 47SkTypeface* SkTypefaceFromPdfStandardFont(const char* fontName, bool bold, bool italic); 48SkPdfFont* fontFromName(SkPdfNativeDoc* doc, SkPdfNativeObject* obj, const char* fontName); 49 50struct SkUnencodedText { 51 void* text; 52 int len; 53 54public: 55 SkUnencodedText(const SkPdfString* obj) { 56 text = (void*)obj->c_str(); 57 len = (int) obj->lenstr(); 58 } 59}; 60 61struct SkDecodedText { 62 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