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