blob: 324f0f65b436371fc37850edd22c10923716d15a [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"
edisonn@google.com3aac1f92013-07-02 22:42:53 +00005#include "SkPdfMapper_autogen.h"
edisonn@google.com1be794f2013-06-21 21:43:09 +00006
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.com571c70b2013-07-10 17:09:50 +000032SkPdfFont* fontFromName(SkNativeParsedPDF* doc, SkPdfObject* obj, const char* fontName);
edisonn@google.com1be794f2013-06-21 21:43:09 +000033
34struct SkUnencodedText {
35 void* text;
36 int len;
37
38public:
edisonn@google.com3aac1f92013-07-02 22:42:53 +000039 SkUnencodedText(const SkPdfString* obj) {
40 text = (void*)obj->c_str();
41 len = obj->len();
edisonn@google.com1be794f2013-06-21 21:43:09 +000042 }
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 {
edisonn@google.com571c70b2013-07-10 17:09:50 +000071 SkNativeParsedPDF* fParsed;
edisonn@google.comb857a0c2013-06-25 20:45:40 +000072 // TODO(edisonn): hide public members
73public:
74 unsigned short* fCMapEncoding;
75 unsigned char* fCMapEncodingFlag;
76
edisonn@google.com571c70b2013-07-10 17:09:50 +000077 SkPdfToUnicode(SkNativeParsedPDF* parsed, SkPdfStream* stream);
edisonn@google.comb857a0c2013-06-25 20:45:40 +000078};
79
80
edisonn@google.com1be794f2013-06-21 21:43:09 +000081class SkPdfIdentityHEncoding : public SkPdfEncoding {
82public:
83 virtual bool decodeText(const SkUnencodedText& textIn, SkDecodedText* textOut) const {
84 // TODO(edisonn): SkASSERT(textIn.len % 2 == 0); or report error?
85
86 uint16_t* text = (uint16_t*)textIn.text;
87 textOut->text = new uint16_t[textIn.len / 2];
88 textOut->len = textIn.len / 2;
89
90 for (int i = 0; i < textOut->len; i++) {
91 textOut->text[i] = ((text[i] << 8) & 0xff00) | ((text[i] >> 8) & 0x00ff);
92 }
93
94 return true;
95 }
96
97 static SkPdfIdentityHEncoding* instance() {
98 static SkPdfIdentityHEncoding* inst = new SkPdfIdentityHEncoding();
99 return inst;
100 }
101};
102
edisonn@google.com6e49c342013-06-27 20:03:43 +0000103// TODO(edisonn): using this one when no encoding is specified
104class SkPdfDefaultEncoding : public SkPdfEncoding {
105public:
106 virtual bool decodeText(const SkUnencodedText& textIn, SkDecodedText* textOut) const {
107 // TODO(edisonn): SkASSERT(textIn.len % 2 == 0); or report error?
108
109 unsigned char* text = (unsigned char*)textIn.text;
110 textOut->text = new uint16_t[textIn.len];
111 textOut->len = textIn.len;
112
113 for (int i = 0; i < textOut->len; i++) {
114 textOut->text[i] = text[i];
115 }
116
117 return true;
118 }
119
120 static SkPdfDefaultEncoding* instance() {
121 static SkPdfDefaultEncoding* inst = new SkPdfDefaultEncoding();
122 return inst;
123 }
124};
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000125
126class SkPdfCIDToGIDMapIdentityEncoding : public SkPdfEncoding {
127public:
128 virtual bool decodeText(const SkUnencodedText& textIn, SkDecodedText* textOut) const {
129 // TODO(edisonn): SkASSERT(textIn.len % 2 == 0); or report error?
130
edisonn@google.com571c70b2013-07-10 17:09:50 +0000131 uint16_t* text = (uint16_t*)textIn.text;
132 textOut->text = new uint16_t[textIn.len / 2];
133 textOut->len = textIn.len / 2;
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000134
135 for (int i = 0; i < textOut->len; i++) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000136 textOut->text[i] = ((text[i] << 8) & 0xff00) | ((text[i] >> 8) & 0x00ff);
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000137 }
138
139 return true;
140 }
141
142 static SkPdfCIDToGIDMapIdentityEncoding* instance() {
143 static SkPdfCIDToGIDMapIdentityEncoding* inst = new SkPdfCIDToGIDMapIdentityEncoding();
144 return inst;
145 }
146};
147
edisonn@google.com1be794f2013-06-21 21:43:09 +0000148class SkPdfFont {
149public:
150 SkPdfFont* fBaseFont;
151 SkPdfEncoding* fEncoding;
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000152 SkPdfToUnicode* fToUnicode;
153
edisonn@google.com1be794f2013-06-21 21:43:09 +0000154
155public:
edisonn@google.com6e49c342013-06-27 20:03:43 +0000156 SkPdfFont() : fBaseFont(NULL), fEncoding(SkPdfDefaultEncoding::instance()), fToUnicode(NULL) {}
edisonn@google.com1be794f2013-06-21 21:43:09 +0000157
158 const SkPdfEncoding* encoding() const {return fEncoding;}
159
edisonn@google.com6e49c342013-06-27 20:03:43 +0000160 void drawText(const SkDecodedText& text, SkPaint* paint, PdfContext* pdfContext, SkCanvas* canvas) {
edisonn@google.com1be794f2013-06-21 21:43:09 +0000161 for (int i = 0 ; i < text.size(); i++) {
edisonn@google.com6e49c342013-06-27 20:03:43 +0000162 double width = drawOneChar(text[i], paint, pdfContext, canvas);
163 pdfContext->fGraphicsState.fMatrixTm.preTranslate(SkDoubleToScalar(width), SkDoubleToScalar(0.0));
164 canvas->translate(SkDoubleToScalar(width), SkDoubleToScalar(0.0));
edisonn@google.com1be794f2013-06-21 21:43:09 +0000165 }
166 }
167
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000168 void ToUnicode(const SkDecodedText& textIn, SkUnicodeText* textOut) const {
169 if (fToUnicode) {
170 textOut->text = new uint16_t[textIn.len];
171 textOut->len = textIn.len;
172 for (int i = 0; i < textIn.len; i++) {
173 textOut->text[i] = fToUnicode->fCMapEncoding[textIn.text[i]];
174 }
175 } else {
176 textOut->text = textIn.text;
177 textOut->len = textIn.len;
178 }
179 };
180
181 inline unsigned int ToUnicode(unsigned int ch) const {
182 if (fToUnicode) {
183 return fToUnicode->fCMapEncoding[ch];
184 } else {
185 return ch;
186 }
edisonn@google.com1be794f2013-06-21 21:43:09 +0000187 };
188
edisonn@google.com571c70b2013-07-10 17:09:50 +0000189 static SkPdfFont* fontFromPdfDictionary(SkNativeParsedPDF* doc, SkPdfFontDictionary* dict);
190 static SkPdfFont* Default() {return fontFromName(NULL, NULL, "TimesNewRoman");}
edisonn@google.com1be794f2013-06-21 21:43:09 +0000191
edisonn@google.com571c70b2013-07-10 17:09:50 +0000192 static SkPdfType0Font* fontFromType0FontDictionary(SkNativeParsedPDF* doc, SkPdfType0FontDictionary* dict);
193 static SkPdfType1Font* fontFromType1FontDictionary(SkNativeParsedPDF* doc, SkPdfType1FontDictionary* dict);
194 static SkPdfType3Font* fontFromType3FontDictionary(SkNativeParsedPDF* doc, SkPdfType3FontDictionary* dict);
195 static SkPdfTrueTypeFont* fontFromTrueTypeFontDictionary(SkNativeParsedPDF* doc, SkPdfTrueTypeFontDictionary* dict);
196 static SkPdfMultiMasterFont* fontFromMultiMasterFontDictionary(SkNativeParsedPDF* doc, SkPdfMultiMasterFontDictionary* dict);
edisonn@google.com1be794f2013-06-21 21:43:09 +0000197
edisonn@google.com571c70b2013-07-10 17:09:50 +0000198 static SkPdfFont* fontFromFontDescriptor(SkNativeParsedPDF* doc, SkPdfFontDescriptorDictionary* fd, bool loadFromName = true);
edisonn@google.com6e49c342013-06-27 20:03:43 +0000199
edisonn@google.com1be794f2013-06-21 21:43:09 +0000200public:
edisonn@google.com6e49c342013-06-27 20:03:43 +0000201 virtual double drawOneChar(unsigned int ch, SkPaint* paint, PdfContext* pdfContext, SkCanvas* canvas) = 0;
edisonn@google.com1be794f2013-06-21 21:43:09 +0000202 virtual void afterWord(SkPaint* paint, SkMatrix* matrix) = 0;
edisonn@google.com571c70b2013-07-10 17:09:50 +0000203
204private:
205 static SkPdfFont* fontFromPdfDictionaryOnce(SkNativeParsedPDF* doc, SkPdfFontDictionary* dict);
edisonn@google.com1be794f2013-06-21 21:43:09 +0000206};
207
208class SkPdfStandardFont : public SkPdfFont {
209 SkTypeface* fTypeface;
210
211public:
212 SkPdfStandardFont(SkTypeface* typeface) : fTypeface(typeface) {}
213
214public:
edisonn@google.com6e49c342013-06-27 20:03:43 +0000215 virtual double drawOneChar(unsigned int ch, SkPaint* paint, PdfContext* pdfContext, SkCanvas* canvas) {
edisonn@google.com1be794f2013-06-21 21:43:09 +0000216 paint->setTypeface(fTypeface);
217 paint->setTextEncoding(SkPaint::kUTF8_TextEncoding);
218
219 unsigned long ch4 = ch;
220 char utf8[10];
221 int len = SkUTF8_FromUnichar(ch4, utf8);
222
223 canvas->drawText(utf8, len, SkDoubleToScalar(0), SkDoubleToScalar(0), *paint);
224
225 SkScalar textWidth = paint->measureText(utf8, len);
edisonn@google.com6e49c342013-06-27 20:03:43 +0000226 return SkScalarToDouble(textWidth);
edisonn@google.com1be794f2013-06-21 21:43:09 +0000227 }
228
edisonn@google.com1be794f2013-06-21 21:43:09 +0000229 virtual void afterWord(SkPaint* paint, SkMatrix* matrix) {}
230};
231
edisonn@google.com1be794f2013-06-21 21:43:09 +0000232class SkPdfType0Font : public SkPdfFont {
edisonn@google.com1be794f2013-06-21 21:43:09 +0000233public:
edisonn@google.com571c70b2013-07-10 17:09:50 +0000234 SkPdfType0Font(SkNativeParsedPDF* doc, SkPdfType0FontDictionary* dict);
edisonn@google.com1be794f2013-06-21 21:43:09 +0000235
236public:
edisonn@google.com1be794f2013-06-21 21:43:09 +0000237
edisonn@google.com6e49c342013-06-27 20:03:43 +0000238 virtual double drawOneChar(unsigned int ch, SkPaint* paint, PdfContext* pdfContext, SkCanvas* canvas) {
239 return fBaseFont->drawOneChar(ToUnicode(ch), paint, pdfContext, canvas);
edisonn@google.com1be794f2013-06-21 21:43:09 +0000240 }
241
242 virtual void afterWord(SkPaint* paint, SkMatrix* matrix) {
edisonn@google.com1be794f2013-06-21 21:43:09 +0000243 }
244};
245
edisonn@google.com1be794f2013-06-21 21:43:09 +0000246class SkPdfType1Font : public SkPdfFont {
247public:
edisonn@google.com571c70b2013-07-10 17:09:50 +0000248 SkPdfType1Font(SkNativeParsedPDF* doc, SkPdfType1FontDictionary* dict) {
edisonn@google.com6e49c342013-06-27 20:03:43 +0000249 if (dict->has_FontDescriptor()) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000250 fBaseFont = SkPdfFont::fontFromFontDescriptor(doc, dict->FontDescriptor(doc));
edisonn@google.com6e49c342013-06-27 20:03:43 +0000251 } else {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000252 fBaseFont = fontFromName(doc, dict, dict->BaseFont(doc).c_str());
edisonn@google.com6e49c342013-06-27 20:03:43 +0000253 }
edisonn@google.com1be794f2013-06-21 21:43:09 +0000254 }
255
edisonn@google.com1be794f2013-06-21 21:43:09 +0000256public:
edisonn@google.com6e49c342013-06-27 20:03:43 +0000257 virtual double drawOneChar(unsigned int ch, SkPaint* paint, PdfContext* pdfContext, SkCanvas* canvas) {
258 return fBaseFont->drawOneChar(ToUnicode(ch), paint, pdfContext, canvas);
edisonn@google.com1be794f2013-06-21 21:43:09 +0000259 }
260
261 virtual void afterWord(SkPaint* paint, SkMatrix* matrix) {
262
263 }
edisonn@google.com6e49c342013-06-27 20:03:43 +0000264};
edisonn@google.com1be794f2013-06-21 21:43:09 +0000265
edisonn@google.com6e49c342013-06-27 20:03:43 +0000266class SkPdfTrueTypeFont : public SkPdfType1Font {
edisonn@google.com1be794f2013-06-21 21:43:09 +0000267public:
edisonn@google.com571c70b2013-07-10 17:09:50 +0000268 SkPdfTrueTypeFont(SkNativeParsedPDF* doc, SkPdfTrueTypeFontDictionary* dict) : SkPdfType1Font(doc, dict) {
edisonn@google.com1be794f2013-06-21 21:43:09 +0000269 }
270};
271
edisonn@google.com6e49c342013-06-27 20:03:43 +0000272class SkPdfMultiMasterFont : public SkPdfType1Font {
edisonn@google.com1be794f2013-06-21 21:43:09 +0000273public:
edisonn@google.com571c70b2013-07-10 17:09:50 +0000274 SkPdfMultiMasterFont(SkNativeParsedPDF* doc, SkPdfMultiMasterFontDictionary* dict) : SkPdfType1Font(doc, dict) {
edisonn@google.com1be794f2013-06-21 21:43:09 +0000275 }
276};
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000277/*
278class CIDToGIDMap {
279 virtual unsigned int map(unsigned int cid) = 0;
280 static CIDToGIDMap* fromName(const char* name);
281};
282
283class CIDToGIDMap_Identity {
284 virtual unsigned int map(unsigned int cid) { return cid; }
285
286 static CIDToGIDMap_Identity* instance() {
287 static CIDToGIDMap_Identity* inst = new CIDToGIDMap_Identity();
288 return inst;
289 }
290};
291
292CIDToGIDMap* CIDToGIDMap::fromName(const char* name) {
293 // The only one supported right now is Identity
294 if (strcmp(name, "Identity") == 0) {
295 return CIDToGIDMap_Identity::instance();
296 }
297
298#ifdef PDF_TRACE
299 // TODO(edisonn): warning/report
300 printf("Unknown CIDToGIDMap: %s\n", name);
301#endif
302 return NULL;
303}
304CIDToGIDMap* fCidToGid;
305*/
edisonn@google.com1be794f2013-06-21 21:43:09 +0000306
307class SkPdfType3Font : public SkPdfFont {
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000308 struct Type3FontChar {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000309 const SkPdfObject* fObj;
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000310 double fWidth;
311 };
312
313 SkPdfDictionary* fCharProcs;
314 SkPdfEncodingDictionary* fEncodingDict;
315 unsigned int fFirstChar;
316 unsigned int fLastChar;
317
318 SkRect fFontBBox;
319 SkMatrix fFonMatrix;
320
321 Type3FontChar* fChars;
322
edisonn@google.com1be794f2013-06-21 21:43:09 +0000323public:
edisonn@google.com571c70b2013-07-10 17:09:50 +0000324 SkPdfType3Font(SkNativeParsedPDF* parsed, SkPdfType3FontDictionary* dict) {
325 fBaseFont = fontFromName(parsed, dict, dict->BaseFont(parsed).c_str());
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000326
327 if (dict->has_Encoding()) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000328 if (dict->isEncodingAName(parsed)) {
329 fEncoding = SkPdfEncoding::fromName(dict->getEncodingAsName(parsed).c_str());
330 } else if (dict->isEncodingAEncodingdictionary(parsed)) {
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000331 // technically, there is no encoding.
332 fEncoding = SkPdfCIDToGIDMapIdentityEncoding::instance();
edisonn@google.com571c70b2013-07-10 17:09:50 +0000333 fEncodingDict = dict->getEncodingAsEncodingdictionary(parsed);
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000334 }
335 }
336
337 // null?
edisonn@google.com571c70b2013-07-10 17:09:50 +0000338 fCharProcs = dict->CharProcs(parsed);
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000339
340 fToUnicode = NULL;
341 if (dict->has_ToUnicode()) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000342 fToUnicode = new SkPdfToUnicode(parsed, dict->ToUnicode(parsed));
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000343 }
344
edisonn@google.com571c70b2013-07-10 17:09:50 +0000345 fFirstChar = dict->FirstChar(parsed);
346 fLastChar = dict->LastChar(parsed);
347 fFonMatrix = dict->has_FontMatrix() ? dict->FontMatrix(parsed) : SkMatrix::I();
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000348
edisonn@google.com571c70b2013-07-10 17:09:50 +0000349 if (dict->has_FontBBox()) {
350 fFontBBox = dict->FontBBox(parsed);
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000351 }
352
353 fChars = new Type3FontChar[fLastChar - fFirstChar + 1];
354
355 memset(fChars, 0, sizeof(fChars[0]) * (fLastChar - fFirstChar + 1));
356
357
edisonn@google.com571c70b2013-07-10 17:09:50 +0000358 const SkPdfArray* widths = dict->Widths(parsed);
359 for (unsigned int i = 0 ; i < widths->size(); i++) {
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000360 if ((fFirstChar + i) < fFirstChar || (fFirstChar + i) > fLastChar) {
361 printf("break; error 1\n");
362 }
edisonn@google.com571c70b2013-07-10 17:09:50 +0000363 fChars[i].fWidth = (*widths)[i]->numberValue();
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000364 }
365
edisonn@google.com571c70b2013-07-10 17:09:50 +0000366 const SkPdfArray* diffs = fEncodingDict->Differences(parsed);
367 unsigned int j = fFirstChar;
368 for (unsigned int i = 0 ; i < diffs->size(); i++) {
369 if ((*diffs)[i]->isInteger()) {
370 j = (*diffs)[i]->intValue();
371 } else if ((*diffs)[i]->isName()) {
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000372 if (j < fFirstChar || j > fLastChar) {
373 printf("break; error 2\n");
374 }
edisonn@google.com571c70b2013-07-10 17:09:50 +0000375 fChars[j - fFirstChar].fObj = fCharProcs->get((*diffs)[i]->nameValue());
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000376 j++;
377 } else {
378 // err
379 }
380 }
edisonn@google.com1be794f2013-06-21 21:43:09 +0000381 }
382
383public:
edisonn@google.com6e49c342013-06-27 20:03:43 +0000384 virtual double drawOneChar(unsigned int ch, SkPaint* paint, PdfContext* pdfContext, SkCanvas* canvas) {
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000385 if (ch < fFirstChar || ch > fLastChar || !fChars[ch - fFirstChar].fObj) {
edisonn@google.com6e49c342013-06-27 20:03:43 +0000386 return fBaseFont->drawOneChar(ToUnicode(ch), paint, pdfContext, canvas);
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000387 }
edisonn@google.com1be794f2013-06-21 21:43:09 +0000388
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000389#ifdef PDF_TRACE
390 printf("Type 3 char to unicode: %c\n", ToUnicode(ch));
391 if (ToUnicode(ch) == 'A') {
392 printf("break;\n");
393 }
394#endif
395
edisonn@google.com571c70b2013-07-10 17:09:50 +0000396 // TODO(edisonn): is it better to resolve the reference at load time, or now?
397 doType3Char(pdfContext, canvas, pdfContext->fPdfDoc->resolveReference(fChars[ch - fFirstChar].fObj), fFontBBox, fFonMatrix, pdfContext->fGraphicsState.fCurFontSize);
edisonn@google.com1be794f2013-06-21 21:43:09 +0000398
edisonn@google.com6e49c342013-06-27 20:03:43 +0000399 // TODO(edisonn): verify/test translate code, not tested yet
400 pdfContext->fGraphicsState.fMatrixTm.preTranslate(SkDoubleToScalar(pdfContext->fGraphicsState.fCurFontSize * fChars[ch - fFirstChar].fWidth),
401 SkDoubleToScalar(0.0));
edisonn@google.com571c70b2013-07-10 17:09:50 +0000402 return fChars[ch - fFirstChar].fWidth;
edisonn@google.com1be794f2013-06-21 21:43:09 +0000403 }
404
405 virtual void afterWord(SkPaint* paint, SkMatrix* matrix) {
406
407 }
408};
409
410#endif // __DEFINED__SkPdfFont