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