blob: 90fe3b0f16b20bbd6e832a9cc06542068cc0cc0c [file] [log] [blame]
edisonn@google.com1be794f2013-06-21 21:43:09 +00001#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
edisonn@google.com131d4ee2013-06-26 17:48:12 +000010#include "SkTypeface.h"
edisonn@google.com1be794f2013-06-21 21:43:09 +000011#include "SkUtils.h"
edisonn@google.comb857a0c2013-06-25 20:45:40 +000012#include "SkPdfBasics.h"
13#include "SkPdfUtils.h"
14
edisonn@google.com1be794f2013-06-21 21:43:09 +000015
16class SkPdfType0Font;
17class SkPdfType1Font;
18class SkPdfType3Font;
19class SkPdfTrueTypeFont;
edisonn@google.com1be794f2013-06-21 21:43:09 +000020class 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);
edisonn@google.com6e49c342013-06-27 20:03:43 +000032SkPdfFont* fontFromName(SkPdfObject* obj, const char* fontName);
edisonn@google.com1be794f2013-06-21 21:43:09 +000033
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;
edisonn@google.comb857a0c2013-06-25 20:45:40 +000048public:
49 unsigned int operator[](int i) const { return text[i]; }
50 int size() const { return len; }
edisonn@google.com1be794f2013-06-21 21:43:09 +000051};
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;
edisonn@google.comb857a0c2013-06-25 20:45:40 +000065 static SkPdfEncoding* fromName(const char* name);
edisonn@google.com1be794f2013-06-21 21:43:09 +000066};
67
edisonn@google.comb857a0c2013-06-25 20:45:40 +000068std::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
edisonn@google.com1be794f2013-06-21 21:43:09 +000080class 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
edisonn@google.com6e49c342013-06-27 20:03:43 +0000102// 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};
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000124
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
edisonn@google.com1be794f2013-06-21 21:43:09 +0000147class SkPdfFont {
148public:
149 SkPdfFont* fBaseFont;
150 SkPdfEncoding* fEncoding;
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000151 SkPdfToUnicode* fToUnicode;
152
edisonn@google.com1be794f2013-06-21 21:43:09 +0000153
154public:
edisonn@google.com6e49c342013-06-27 20:03:43 +0000155 SkPdfFont() : fBaseFont(NULL), fEncoding(SkPdfDefaultEncoding::instance()), fToUnicode(NULL) {}
edisonn@google.com1be794f2013-06-21 21:43:09 +0000156
157 const SkPdfEncoding* encoding() const {return fEncoding;}
158
edisonn@google.com6e49c342013-06-27 20:03:43 +0000159 void drawText(const SkDecodedText& text, SkPaint* paint, PdfContext* pdfContext, SkCanvas* canvas) {
edisonn@google.com1be794f2013-06-21 21:43:09 +0000160 for (int i = 0 ; i < text.size(); i++) {
edisonn@google.com6e49c342013-06-27 20:03:43 +0000161 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));
edisonn@google.com1be794f2013-06-21 21:43:09 +0000164 }
165 }
166
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000167 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 }
edisonn@google.com1be794f2013-06-21 21:43:09 +0000186 };
187
188 static SkPdfFont* fontFromPdfDictionary(SkPdfFontDictionary* dict);
edisonn@google.com6e49c342013-06-27 20:03:43 +0000189 static SkPdfFont* Default() {return fontFromName(NULL, "TimesNewRoman");}
edisonn@google.com1be794f2013-06-21 21:43:09 +0000190
191 static SkPdfType0Font* fontFromType0FontDictionary(SkPdfType0FontDictionary* dict);
192 static SkPdfType1Font* fontFromType1FontDictionary(SkPdfType1FontDictionary* dict);
193 static SkPdfType3Font* fontFromType3FontDictionary(SkPdfType3FontDictionary* dict);
194 static SkPdfTrueTypeFont* fontFromTrueTypeFontDictionary(SkPdfTrueTypeFontDictionary* dict);
edisonn@google.com1be794f2013-06-21 21:43:09 +0000195 static SkPdfMultiMasterFont* fontFromMultiMasterFontDictionary(SkPdfMultiMasterFontDictionary* dict);
196
edisonn@google.com6e49c342013-06-27 20:03:43 +0000197 static SkPdfFont* fontFromFontDescriptor(SkPdfFontDescriptorDictionary* fd, bool loadFromName = true);
198
edisonn@google.com1be794f2013-06-21 21:43:09 +0000199public:
edisonn@google.com6e49c342013-06-27 20:03:43 +0000200 virtual double drawOneChar(unsigned int ch, SkPaint* paint, PdfContext* pdfContext, SkCanvas* canvas) = 0;
edisonn@google.com1be794f2013-06-21 21:43:09 +0000201 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:
edisonn@google.com6e49c342013-06-27 20:03:43 +0000211 virtual double drawOneChar(unsigned int ch, SkPaint* paint, PdfContext* pdfContext, SkCanvas* canvas) {
edisonn@google.com1be794f2013-06-21 21:43:09 +0000212 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);
edisonn@google.com6e49c342013-06-27 20:03:43 +0000222 return SkScalarToDouble(textWidth);
edisonn@google.com1be794f2013-06-21 21:43:09 +0000223 }
224
edisonn@google.com1be794f2013-06-21 21:43:09 +0000225 virtual void afterWord(SkPaint* paint, SkMatrix* matrix) {}
226};
227
edisonn@google.com1be794f2013-06-21 21:43:09 +0000228class SkPdfType0Font : public SkPdfFont {
edisonn@google.com1be794f2013-06-21 21:43:09 +0000229public:
230 SkPdfType0Font(SkPdfType0FontDictionary* dict);
231
232public:
edisonn@google.com1be794f2013-06-21 21:43:09 +0000233
edisonn@google.com6e49c342013-06-27 20:03:43 +0000234 virtual double drawOneChar(unsigned int ch, SkPaint* paint, PdfContext* pdfContext, SkCanvas* canvas) {
235 return fBaseFont->drawOneChar(ToUnicode(ch), paint, pdfContext, canvas);
edisonn@google.com1be794f2013-06-21 21:43:09 +0000236 }
237
238 virtual void afterWord(SkPaint* paint, SkMatrix* matrix) {
edisonn@google.com1be794f2013-06-21 21:43:09 +0000239 }
240};
241
edisonn@google.com1be794f2013-06-21 21:43:09 +0000242class SkPdfType1Font : public SkPdfFont {
243public:
244 SkPdfType1Font(SkPdfType1FontDictionary* dict) {
edisonn@google.com6e49c342013-06-27 20:03:43 +0000245 if (dict->has_FontDescriptor()) {
246 fBaseFont = SkPdfFont::fontFromFontDescriptor(dict->FontDescriptor());
247 } else {
248 fBaseFont = fontFromName(dict, dict->BaseFont().c_str());
249 }
edisonn@google.com1be794f2013-06-21 21:43:09 +0000250 }
251
edisonn@google.com1be794f2013-06-21 21:43:09 +0000252public:
edisonn@google.com6e49c342013-06-27 20:03:43 +0000253 virtual double drawOneChar(unsigned int ch, SkPaint* paint, PdfContext* pdfContext, SkCanvas* canvas) {
254 return fBaseFont->drawOneChar(ToUnicode(ch), paint, pdfContext, canvas);
edisonn@google.com1be794f2013-06-21 21:43:09 +0000255 }
256
257 virtual void afterWord(SkPaint* paint, SkMatrix* matrix) {
258
259 }
edisonn@google.com6e49c342013-06-27 20:03:43 +0000260};
edisonn@google.com1be794f2013-06-21 21:43:09 +0000261
edisonn@google.com6e49c342013-06-27 20:03:43 +0000262class SkPdfTrueTypeFont : public SkPdfType1Font {
edisonn@google.com1be794f2013-06-21 21:43:09 +0000263public:
edisonn@google.com6e49c342013-06-27 20:03:43 +0000264 SkPdfTrueTypeFont(SkPdfTrueTypeFontDictionary* dict) : SkPdfType1Font(dict) {
edisonn@google.com1be794f2013-06-21 21:43:09 +0000265 }
266};
267
edisonn@google.com6e49c342013-06-27 20:03:43 +0000268class SkPdfMultiMasterFont : public SkPdfType1Font {
edisonn@google.com1be794f2013-06-21 21:43:09 +0000269public:
edisonn@google.com6e49c342013-06-27 20:03:43 +0000270 SkPdfMultiMasterFont(SkPdfMultiMasterFontDictionary* dict) : SkPdfType1Font(dict) {
edisonn@google.com1be794f2013-06-21 21:43:09 +0000271 }
272};
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000273/*
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*/
edisonn@google.com1be794f2013-06-21 21:43:09 +0000302
303class SkPdfType3Font : public SkPdfFont {
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000304 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
edisonn@google.com1be794f2013-06-21 21:43:09 +0000319public:
320 SkPdfType3Font(SkPdfType3FontDictionary* dict) {
edisonn@google.com6e49c342013-06-27 20:03:43 +0000321 fBaseFont = fontFromName(dict, dict->BaseFont().c_str());
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000322
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 }
edisonn@google.com1be794f2013-06-21 21:43:09 +0000377 }
378
379public:
edisonn@google.com6e49c342013-06-27 20:03:43 +0000380 virtual double drawOneChar(unsigned int ch, SkPaint* paint, PdfContext* pdfContext, SkCanvas* canvas) {
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000381 if (ch < fFirstChar || ch > fLastChar || !fChars[ch - fFirstChar].fObj) {
edisonn@google.com6e49c342013-06-27 20:03:43 +0000382 return fBaseFont->drawOneChar(ToUnicode(ch), paint, pdfContext, canvas);
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000383 }
edisonn@google.com1be794f2013-06-21 21:43:09 +0000384
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000385#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);
edisonn@google.com1be794f2013-06-21 21:43:09 +0000393
edisonn@google.com6e49c342013-06-27 20:03:43 +0000394 // 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));
edisonn@google.com1be794f2013-06-21 21:43:09 +0000397 }
398
399 virtual void afterWord(SkPaint* paint, SkMatrix* matrix) {
400
401 }
402};
403
404#endif // __DEFINED__SkPdfFont