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