Home | History | Annotate | Download | only in PdfViewer
      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;
     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 
     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:
     55     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]; }
     66     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]; }
     75     int size() const { return len; }
     76 };
     77 
     78 class SkPdfEncoding {
     79 public:
     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:
     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
    121 class SkPdfDefaultEncoding : public SkPdfEncoding {
    122 public:
    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 
    144 class SkPdfCIDToGIDMapIdentityEncoding : public SkPdfEncoding {
    145 public:
    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 
    167 class SkPdfFont {
    168 public:
    169     SkPdfFont* fBaseFont;
    170     SkPdfEncoding* fEncoding;
    171     SkPdfToUnicode* fToUnicode;
    172 
    173 
    174 public:
    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 
    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:
    264     SkPdfStandardFont(SkTypeface* typeface) : fTypeface(typeface) {}
    265 
    266 public:
    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 
    285 class SkPdfType0Font : public SkPdfFont {
    286 public:
    287     SkPdfType0Font(SkPdfNativeDoc* doc, SkPdfType0FontDictionary* dict);
    288 
    289 public:
    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 
    300 class SkPdfType1Font : public SkPdfFont {
    301 public:
    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:
    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 
    328 class SkPdfTrueTypeFont : public SkPdfType1Font {
    329 public:
    330     SkPdfTrueTypeFont(SkPdfNativeDoc* doc, SkPdfTrueTypeFontDictionary* dict)
    331             : SkPdfType1Font(doc, dict) {}
    332 };
    333 
    334 class SkPdfMultiMasterFont : public SkPdfType1Font {
    335 public:
    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:
    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:
    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