SkPdfFont.h revision a3356fce903ff75dc332b53dd3a860ba810b9519
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->len(); 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 const SkPdfEncoding* encoding() const {return fEncoding;} 168 169 void drawText(const SkDecodedText& text, SkPaint* paint, PdfContext* pdfContext, SkCanvas* canvas) { 170 for (int i = 0 ; i < text.size(); i++) { 171 double width = drawOneChar(text[i], paint, pdfContext, canvas); 172 pdfContext->fGraphicsState.fMatrixTm.preTranslate(SkDoubleToScalar(width), SkDoubleToScalar(0.0)); 173 canvas->translate(SkDoubleToScalar(width), SkDoubleToScalar(0.0)); 174 } 175 } 176 177 void ToUnicode(const SkDecodedText& textIn, SkUnicodeText* textOut) const { 178 if (fToUnicode) { 179 textOut->text = new uint16_t[textIn.len]; 180 textOut->len = textIn.len; 181 for (int i = 0; i < textIn.len; i++) { 182 textOut->text[i] = fToUnicode->fCMapEncoding[textIn.text[i]]; 183 } 184 } else { 185 textOut->text = textIn.text; 186 textOut->len = textIn.len; 187 } 188 }; 189 190 inline unsigned int ToUnicode(unsigned int ch) const { 191 if (fToUnicode) { 192 return fToUnicode->fCMapEncoding[ch]; 193 } else { 194 return ch; 195 } 196 }; 197 198 static SkPdfFont* fontFromPdfDictionary(SkNativeParsedPDF* doc, SkPdfFontDictionary* dict); 199 static SkPdfFont* Default() {return fontFromName(NULL, NULL, "TimesNewRoman");} 200 201 static SkPdfType0Font* fontFromType0FontDictionary(SkNativeParsedPDF* doc, SkPdfType0FontDictionary* dict); 202 static SkPdfType1Font* fontFromType1FontDictionary(SkNativeParsedPDF* doc, SkPdfType1FontDictionary* dict); 203 static SkPdfType3Font* fontFromType3FontDictionary(SkNativeParsedPDF* doc, SkPdfType3FontDictionary* dict); 204 static SkPdfTrueTypeFont* fontFromTrueTypeFontDictionary(SkNativeParsedPDF* doc, SkPdfTrueTypeFontDictionary* dict); 205 static SkPdfMultiMasterFont* fontFromMultiMasterFontDictionary(SkNativeParsedPDF* doc, SkPdfMultiMasterFontDictionary* dict); 206 207 static SkPdfFont* fontFromFontDescriptor(SkNativeParsedPDF* doc, SkPdfFontDescriptorDictionary* fd, bool loadFromName = true); 208 209public: 210 virtual double drawOneChar(unsigned int ch, SkPaint* paint, PdfContext* pdfContext, SkCanvas* canvas) = 0; 211 virtual void afterWord(SkPaint* paint, SkMatrix* matrix) = 0; 212 213private: 214 static SkPdfFont* fontFromPdfDictionaryOnce(SkNativeParsedPDF* doc, SkPdfFontDictionary* dict); 215}; 216 217class SkPdfStandardFont : public SkPdfFont { 218 SkTypeface* fTypeface; 219 220public: 221 SkPdfStandardFont(SkTypeface* typeface) : fTypeface(typeface) {} 222 223public: 224 virtual double drawOneChar(unsigned int ch, SkPaint* paint, PdfContext* pdfContext, SkCanvas* canvas) { 225 paint->setTypeface(fTypeface); 226 paint->setTextEncoding(SkPaint::kUTF8_TextEncoding); 227 228 unsigned long ch4 = ch; 229 char utf8[10]; 230 int len = SkUTF8_FromUnichar(ch4, utf8); 231 232 canvas->drawText(utf8, len, SkDoubleToScalar(0), SkDoubleToScalar(0), *paint); 233 234 SkScalar textWidth = paint->measureText(utf8, len); 235 return SkScalarToDouble(textWidth); 236 } 237 238 virtual void afterWord(SkPaint* paint, SkMatrix* matrix) {} 239}; 240 241class SkPdfType0Font : public SkPdfFont { 242public: 243 SkPdfType0Font(SkNativeParsedPDF* doc, SkPdfType0FontDictionary* dict); 244 245public: 246 247 virtual double drawOneChar(unsigned int ch, SkPaint* paint, PdfContext* pdfContext, SkCanvas* canvas) { 248 return fBaseFont->drawOneChar(ToUnicode(ch), paint, pdfContext, canvas); 249 } 250 251 virtual void afterWord(SkPaint* paint, SkMatrix* matrix) { 252 } 253}; 254 255class SkPdfType1Font : public SkPdfFont { 256public: 257 SkPdfType1Font(SkNativeParsedPDF* doc, SkPdfType1FontDictionary* dict) { 258 if (dict->has_FontDescriptor()) { 259 fBaseFont = SkPdfFont::fontFromFontDescriptor(doc, dict->FontDescriptor(doc)); 260 } else { 261 fBaseFont = fontFromName(doc, dict, dict->BaseFont(doc).c_str()); 262 } 263 } 264 265public: 266 virtual double drawOneChar(unsigned int ch, SkPaint* paint, PdfContext* pdfContext, SkCanvas* canvas) { 267 return fBaseFont->drawOneChar(ToUnicode(ch), paint, pdfContext, canvas); 268 } 269 270 virtual void afterWord(SkPaint* paint, SkMatrix* matrix) { 271 272 } 273}; 274 275class SkPdfTrueTypeFont : public SkPdfType1Font { 276public: 277 SkPdfTrueTypeFont(SkNativeParsedPDF* doc, SkPdfTrueTypeFontDictionary* dict) : SkPdfType1Font(doc, dict) { 278 } 279}; 280 281class SkPdfMultiMasterFont : public SkPdfType1Font { 282public: 283 SkPdfMultiMasterFont(SkNativeParsedPDF* doc, SkPdfMultiMasterFontDictionary* dict) : SkPdfType1Font(doc, dict) { 284 } 285}; 286/* 287class CIDToGIDMap { 288 virtual unsigned int map(unsigned int cid) = 0; 289 static CIDToGIDMap* fromName(const char* name); 290}; 291 292class CIDToGIDMap_Identity { 293 virtual unsigned int map(unsigned int cid) { return cid; } 294 295 static CIDToGIDMap_Identity* instance() { 296 static CIDToGIDMap_Identity* inst = new CIDToGIDMap_Identity(); 297 return inst; 298 } 299}; 300 301CIDToGIDMap* CIDToGIDMap::fromName(const char* name) { 302 // The only one supported right now is Identity 303 if (strcmp(name, "Identity") == 0) { 304 return CIDToGIDMap_Identity::instance(); 305 } 306 307#ifdef PDF_TRACE 308 // TODO(edisonn): warning/report 309 printf("Unknown CIDToGIDMap: %s\n", name); 310#endif 311 return NULL; 312} 313CIDToGIDMap* fCidToGid; 314*/ 315 316class SkPdfType3Font : public SkPdfFont { 317 struct Type3FontChar { 318 const SkPdfObject* fObj; 319 double fWidth; 320 }; 321 322 SkPdfDictionary* fCharProcs; 323 SkPdfEncodingDictionary* fEncodingDict; 324 unsigned int fFirstChar; 325 unsigned int fLastChar; 326 327 SkRect fFontBBox; 328 SkMatrix fFonMatrix; 329 330 Type3FontChar* fChars; 331 332public: 333 SkPdfType3Font(SkNativeParsedPDF* parsed, SkPdfType3FontDictionary* dict) { 334 fBaseFont = fontFromName(parsed, dict, dict->BaseFont(parsed).c_str()); 335 336 if (dict->has_Encoding()) { 337 if (dict->isEncodingAName(parsed)) { 338 fEncoding = SkPdfEncoding::fromName(dict->getEncodingAsName(parsed).c_str()); 339 } else if (dict->isEncodingAEncodingdictionary(parsed)) { 340 // technically, there is no encoding. 341 fEncoding = SkPdfCIDToGIDMapIdentityEncoding::instance(); 342 fEncodingDict = dict->getEncodingAsEncodingdictionary(parsed); 343 } 344 } 345 346 // null? 347 fCharProcs = dict->CharProcs(parsed); 348 349 fToUnicode = NULL; 350 if (dict->has_ToUnicode()) { 351 fToUnicode = new SkPdfToUnicode(parsed, dict->ToUnicode(parsed)); 352 } 353 354 fFirstChar = (unsigned int)dict->FirstChar(parsed); 355 fLastChar = (unsigned int)dict->LastChar(parsed); 356 fFonMatrix = dict->has_FontMatrix() ? dict->FontMatrix(parsed) : SkMatrix::I(); 357 358 if (dict->has_FontBBox()) { 359 fFontBBox = dict->FontBBox(parsed); 360 } 361 362 fChars = new Type3FontChar[fLastChar - fFirstChar + 1]; 363 364 memset(fChars, 0, sizeof(fChars[0]) * (fLastChar - fFirstChar + 1)); 365 366 367 const SkPdfArray* widths = dict->Widths(parsed); 368 for (unsigned int i = 0 ; i < widths->size(); i++) { 369 if ((fFirstChar + i) < fFirstChar || (fFirstChar + i) > fLastChar) { 370 printf("break; error 1\n"); 371 } 372 fChars[i].fWidth = (*widths)[i]->numberValue(); 373 } 374 375 const SkPdfArray* diffs = fEncodingDict->Differences(parsed); 376 unsigned int j = fFirstChar; 377 for (unsigned int i = 0 ; i < diffs->size(); i++) { 378 if ((*diffs)[i]->isInteger()) { 379 j = (unsigned int)(*diffs)[i]->intValue(); 380 } else if ((*diffs)[i]->isName()) { 381 if (j < fFirstChar || j > fLastChar) { 382 printf("break; error 2\n"); 383 } 384 fChars[j - fFirstChar].fObj = fCharProcs->get((*diffs)[i]->nameValue()); 385 j++; 386 } else { 387 // err 388 } 389 } 390 } 391 392public: 393 virtual double drawOneChar(unsigned int ch, SkPaint* paint, PdfContext* pdfContext, SkCanvas* canvas) { 394 if (ch < fFirstChar || ch > fLastChar || !fChars[ch - fFirstChar].fObj) { 395 return fBaseFont->drawOneChar(ToUnicode(ch), paint, pdfContext, canvas); 396 } 397 398#ifdef PDF_TRACE 399 printf("Type 3 char to unicode: %c\n", ToUnicode(ch)); 400 if (ToUnicode(ch) == 'A') { 401 printf("break;\n"); 402 } 403#endif 404 405 // TODO(edisonn): is it better to resolve the reference at load time, or now? 406 doType3Char(pdfContext, canvas, pdfContext->fPdfDoc->resolveReference(fChars[ch - fFirstChar].fObj), fFontBBox, fFonMatrix, pdfContext->fGraphicsState.fCurFontSize); 407 408 // TODO(edisonn): verify/test translate code, not tested yet 409 pdfContext->fGraphicsState.fMatrixTm.preTranslate(SkDoubleToScalar(pdfContext->fGraphicsState.fCurFontSize * fChars[ch - fFirstChar].fWidth), 410 SkDoubleToScalar(0.0)); 411 return fChars[ch - fFirstChar].fWidth; 412 } 413 414 virtual void afterWord(SkPaint* paint, SkMatrix* matrix) { 415 416 } 417}; 418 419#endif // __DEFINED__SkPdfFont 420