blob: bbbaa7a73e0e66edb36f2e214aec25075a05bdfc [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
edisonn@google.com1be794f2013-06-21 21:43:09 +000023struct SkPdfStandardFontEntry {
edisonn@google.com596d2e22013-07-10 17:44:55 +000024 // We don't own this pointer!
edisonn@google.com1be794f2013-06-21 21:43:09 +000025 const char* fName;
26 bool fIsBold;
27 bool fIsItalic;
edisonn@google.com596d2e22013-07-10 17:44:55 +000028 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) {}
edisonn@google.com1be794f2013-06-21 21:43:09 +000037};
38
39std::map<std::string, SkPdfStandardFontEntry>& getStandardFonts();
40SkTypeface* SkTypefaceFromPdfStandardFont(const char* fontName, bool bold, bool italic);
edisonn@google.com571c70b2013-07-10 17:09:50 +000041SkPdfFont* fontFromName(SkNativeParsedPDF* doc, SkPdfObject* obj, const char* fontName);
edisonn@google.com1be794f2013-06-21 21:43:09 +000042
43struct SkUnencodedText {
44 void* text;
45 int len;
46
47public:
edisonn@google.com3aac1f92013-07-02 22:42:53 +000048 SkUnencodedText(const SkPdfString* obj) {
49 text = (void*)obj->c_str();
edisonn@google.come878e722013-07-29 19:10:58 +000050 len = obj->lenstr();
edisonn@google.com1be794f2013-06-21 21:43:09 +000051 }
52};
53
54struct SkDecodedText {
55 uint16_t* text;
56 int len;
edisonn@google.comb857a0c2013-06-25 20:45:40 +000057public:
58 unsigned int operator[](int i) const { return text[i]; }
59 int size() const { return len; }
edisonn@google.com1be794f2013-06-21 21:43:09 +000060};
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;
edisonn@google.comb857a0c2013-06-25 20:45:40 +000074 static SkPdfEncoding* fromName(const char* name);
edisonn@google.com1be794f2013-06-21 21:43:09 +000075};
76
edisonn@google.comb857a0c2013-06-25 20:45:40 +000077std::map<std::string, SkPdfEncoding*>& getStandardEncodings();
78
79class SkPdfToUnicode {
edisonn@google.com571c70b2013-07-10 17:09:50 +000080 SkNativeParsedPDF* fParsed;
edisonn@google.comb857a0c2013-06-25 20:45:40 +000081 // TODO(edisonn): hide public members
82public:
83 unsigned short* fCMapEncoding;
84 unsigned char* fCMapEncodingFlag;
85
edisonn@google.com571c70b2013-07-10 17:09:50 +000086 SkPdfToUnicode(SkNativeParsedPDF* parsed, SkPdfStream* stream);
edisonn@google.comb857a0c2013-06-25 20:45:40 +000087};
88
89
edisonn@google.com1be794f2013-06-21 21:43:09 +000090class 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
edisonn@google.com6e49c342013-06-27 20:03:43 +0000112// 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};
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000134
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
edisonn@google.com571c70b2013-07-10 17:09:50 +0000140 uint16_t* text = (uint16_t*)textIn.text;
141 textOut->text = new uint16_t[textIn.len / 2];
142 textOut->len = textIn.len / 2;
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000143
144 for (int i = 0; i < textOut->len; i++) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000145 textOut->text[i] = ((text[i] << 8) & 0xff00) | ((text[i] >> 8) & 0x00ff);
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000146 }
147
148 return true;
149 }
150
151 static SkPdfCIDToGIDMapIdentityEncoding* instance() {
152 static SkPdfCIDToGIDMapIdentityEncoding* inst = new SkPdfCIDToGIDMapIdentityEncoding();
153 return inst;
154 }
155};
156
edisonn@google.com1be794f2013-06-21 21:43:09 +0000157class SkPdfFont {
158public:
159 SkPdfFont* fBaseFont;
160 SkPdfEncoding* fEncoding;
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000161 SkPdfToUnicode* fToUnicode;
162
edisonn@google.com1be794f2013-06-21 21:43:09 +0000163
164public:
edisonn@google.com6e49c342013-06-27 20:03:43 +0000165 SkPdfFont() : fBaseFont(NULL), fEncoding(SkPdfDefaultEncoding::instance()), fToUnicode(NULL) {}
edisonn@google.com1be794f2013-06-21 21:43:09 +0000166
edisonn@google.com7ee12ca2013-08-05 18:18:06 +0000167 virtual ~SkPdfFont() {
168 // TODO(edisonn): NYI (will leak for now)
169 }
170
edisonn@google.com1be794f2013-06-21 21:43:09 +0000171 const SkPdfEncoding* encoding() const {return fEncoding;}
172
edisonn@google.com6e49c342013-06-27 20:03:43 +0000173 void drawText(const SkDecodedText& text, SkPaint* paint, PdfContext* pdfContext, SkCanvas* canvas) {
edisonn@google.com1be794f2013-06-21 21:43:09 +0000174 for (int i = 0 ; i < text.size(); i++) {
edisonn@google.come57c62d2013-08-07 18:04:15 +0000175 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
edisonn@google.com6e49c342013-06-27 20:03:43 +0000181 double width = drawOneChar(text[i], paint, pdfContext, canvas);
182 pdfContext->fGraphicsState.fMatrixTm.preTranslate(SkDoubleToScalar(width), SkDoubleToScalar(0.0));
edisonn@google.com1be794f2013-06-21 21:43:09 +0000183 }
184 }
185
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000186 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 }
edisonn@google.com1be794f2013-06-21 21:43:09 +0000205 };
206
edisonn@google.com571c70b2013-07-10 17:09:50 +0000207 static SkPdfFont* fontFromPdfDictionary(SkNativeParsedPDF* doc, SkPdfFontDictionary* dict);
208 static SkPdfFont* Default() {return fontFromName(NULL, NULL, "TimesNewRoman");}
edisonn@google.com1be794f2013-06-21 21:43:09 +0000209
edisonn@google.com571c70b2013-07-10 17:09:50 +0000210 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);
edisonn@google.com1be794f2013-06-21 21:43:09 +0000215
edisonn@google.com571c70b2013-07-10 17:09:50 +0000216 static SkPdfFont* fontFromFontDescriptor(SkNativeParsedPDF* doc, SkPdfFontDescriptorDictionary* fd, bool loadFromName = true);
edisonn@google.com6e49c342013-06-27 20:03:43 +0000217
edisonn@google.com1be794f2013-06-21 21:43:09 +0000218public:
edisonn@google.com6e49c342013-06-27 20:03:43 +0000219 virtual double drawOneChar(unsigned int ch, SkPaint* paint, PdfContext* pdfContext, SkCanvas* canvas) = 0;
edisonn@google.com1be794f2013-06-21 21:43:09 +0000220 virtual void afterWord(SkPaint* paint, SkMatrix* matrix) = 0;
edisonn@google.com571c70b2013-07-10 17:09:50 +0000221
222private:
223 static SkPdfFont* fontFromPdfDictionaryOnce(SkNativeParsedPDF* doc, SkPdfFontDictionary* dict);
edisonn@google.com1be794f2013-06-21 21:43:09 +0000224};
225
226class SkPdfStandardFont : public SkPdfFont {
227 SkTypeface* fTypeface;
228
229public:
230 SkPdfStandardFont(SkTypeface* typeface) : fTypeface(typeface) {}
231
232public:
edisonn@google.com6e49c342013-06-27 20:03:43 +0000233 virtual double drawOneChar(unsigned int ch, SkPaint* paint, PdfContext* pdfContext, SkCanvas* canvas) {
edisonn@google.com1be794f2013-06-21 21:43:09 +0000234 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);
edisonn@google.com6e49c342013-06-27 20:03:43 +0000244 return SkScalarToDouble(textWidth);
edisonn@google.com1be794f2013-06-21 21:43:09 +0000245 }
246
edisonn@google.com1be794f2013-06-21 21:43:09 +0000247 virtual void afterWord(SkPaint* paint, SkMatrix* matrix) {}
248};
249
edisonn@google.com1be794f2013-06-21 21:43:09 +0000250class SkPdfType0Font : public SkPdfFont {
edisonn@google.com1be794f2013-06-21 21:43:09 +0000251public:
edisonn@google.com571c70b2013-07-10 17:09:50 +0000252 SkPdfType0Font(SkNativeParsedPDF* doc, SkPdfType0FontDictionary* dict);
edisonn@google.com1be794f2013-06-21 21:43:09 +0000253
254public:
edisonn@google.com1be794f2013-06-21 21:43:09 +0000255
edisonn@google.com6e49c342013-06-27 20:03:43 +0000256 virtual double drawOneChar(unsigned int ch, SkPaint* paint, PdfContext* pdfContext, SkCanvas* canvas) {
257 return fBaseFont->drawOneChar(ToUnicode(ch), paint, pdfContext, canvas);
edisonn@google.com1be794f2013-06-21 21:43:09 +0000258 }
259
260 virtual void afterWord(SkPaint* paint, SkMatrix* matrix) {
edisonn@google.com1be794f2013-06-21 21:43:09 +0000261 }
262};
263
edisonn@google.com1be794f2013-06-21 21:43:09 +0000264class SkPdfType1Font : public SkPdfFont {
265public:
edisonn@google.com571c70b2013-07-10 17:09:50 +0000266 SkPdfType1Font(SkNativeParsedPDF* doc, SkPdfType1FontDictionary* dict) {
edisonn@google.com6e49c342013-06-27 20:03:43 +0000267 if (dict->has_FontDescriptor()) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000268 fBaseFont = SkPdfFont::fontFromFontDescriptor(doc, dict->FontDescriptor(doc));
edisonn@google.com6e49c342013-06-27 20:03:43 +0000269 } else {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000270 fBaseFont = fontFromName(doc, dict, dict->BaseFont(doc).c_str());
edisonn@google.com6e49c342013-06-27 20:03:43 +0000271 }
edisonn@google.com1be794f2013-06-21 21:43:09 +0000272 }
273
edisonn@google.com1be794f2013-06-21 21:43:09 +0000274public:
edisonn@google.com6e49c342013-06-27 20:03:43 +0000275 virtual double drawOneChar(unsigned int ch, SkPaint* paint, PdfContext* pdfContext, SkCanvas* canvas) {
276 return fBaseFont->drawOneChar(ToUnicode(ch), paint, pdfContext, canvas);
edisonn@google.com1be794f2013-06-21 21:43:09 +0000277 }
278
279 virtual void afterWord(SkPaint* paint, SkMatrix* matrix) {
280
281 }
edisonn@google.com6e49c342013-06-27 20:03:43 +0000282};
edisonn@google.com1be794f2013-06-21 21:43:09 +0000283
edisonn@google.com6e49c342013-06-27 20:03:43 +0000284class SkPdfTrueTypeFont : public SkPdfType1Font {
edisonn@google.com1be794f2013-06-21 21:43:09 +0000285public:
edisonn@google.com571c70b2013-07-10 17:09:50 +0000286 SkPdfTrueTypeFont(SkNativeParsedPDF* doc, SkPdfTrueTypeFontDictionary* dict) : SkPdfType1Font(doc, dict) {
edisonn@google.com1be794f2013-06-21 21:43:09 +0000287 }
288};
289
edisonn@google.com6e49c342013-06-27 20:03:43 +0000290class SkPdfMultiMasterFont : public SkPdfType1Font {
edisonn@google.com1be794f2013-06-21 21:43:09 +0000291public:
edisonn@google.com571c70b2013-07-10 17:09:50 +0000292 SkPdfMultiMasterFont(SkNativeParsedPDF* doc, SkPdfMultiMasterFontDictionary* dict) : SkPdfType1Font(doc, dict) {
edisonn@google.com1be794f2013-06-21 21:43:09 +0000293 }
294};
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000295/*
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*/
edisonn@google.com1be794f2013-06-21 21:43:09 +0000324
325class SkPdfType3Font : public SkPdfFont {
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000326 struct Type3FontChar {
edisonn@google.comb0145ce2013-08-05 16:23:23 +0000327 SkPdfObject* fObj;
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000328 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
edisonn@google.com1be794f2013-06-21 21:43:09 +0000341public:
edisonn@google.com571c70b2013-07-10 17:09:50 +0000342 SkPdfType3Font(SkNativeParsedPDF* parsed, SkPdfType3FontDictionary* dict) {
343 fBaseFont = fontFromName(parsed, dict, dict->BaseFont(parsed).c_str());
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000344
345 if (dict->has_Encoding()) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000346 if (dict->isEncodingAName(parsed)) {
347 fEncoding = SkPdfEncoding::fromName(dict->getEncodingAsName(parsed).c_str());
348 } else if (dict->isEncodingAEncodingdictionary(parsed)) {
edisonn@google.com2fd5d362013-07-23 19:43:48 +0000349 // No encoding.
350 fEncoding = SkPdfDefaultEncoding::instance();
edisonn@google.com571c70b2013-07-10 17:09:50 +0000351 fEncodingDict = dict->getEncodingAsEncodingdictionary(parsed);
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000352 }
353 }
354
355 // null?
edisonn@google.com571c70b2013-07-10 17:09:50 +0000356 fCharProcs = dict->CharProcs(parsed);
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000357
358 fToUnicode = NULL;
359 if (dict->has_ToUnicode()) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000360 fToUnicode = new SkPdfToUnicode(parsed, dict->ToUnicode(parsed));
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000361 }
362
edisonn@google.coma3356fc2013-07-10 18:20:06 +0000363 fFirstChar = (unsigned int)dict->FirstChar(parsed);
364 fLastChar = (unsigned int)dict->LastChar(parsed);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000365 fFonMatrix = dict->has_FontMatrix() ? dict->FontMatrix(parsed) : SkMatrix::I();
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000366
edisonn@google.com571c70b2013-07-10 17:09:50 +0000367 if (dict->has_FontBBox()) {
368 fFontBBox = dict->FontBBox(parsed);
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000369 }
370
371 fChars = new Type3FontChar[fLastChar - fFirstChar + 1];
372
373 memset(fChars, 0, sizeof(fChars[0]) * (fLastChar - fFirstChar + 1));
374
edisonn@google.com571c70b2013-07-10 17:09:50 +0000375 const SkPdfArray* widths = dict->Widths(parsed);
376 for (unsigned int i = 0 ; i < widths->size(); i++) {
edisonn@google.comac4bedc2013-07-25 21:40:23 +0000377 if ((fFirstChar + i) >= fFirstChar && (fFirstChar + i) <= fLastChar) {
378 fChars[i].fWidth = (*widths)[i]->numberValue();
379 } else {
380 // TODO(edisonn): report pdf corruption
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000381 }
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000382 }
383
edisonn@google.com571c70b2013-07-10 17:09:50 +0000384 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()) {
edisonn@google.coma3356fc2013-07-10 18:20:06 +0000388 j = (unsigned int)(*diffs)[i]->intValue();
edisonn@google.com571c70b2013-07-10 17:09:50 +0000389 } else if ((*diffs)[i]->isName()) {
edisonn@google.comac4bedc2013-07-25 21:40:23 +0000390 if (j >= fFirstChar && j <= fLastChar) {
391 fChars[j - fFirstChar].fObj = fCharProcs->get((*diffs)[i]);
392 } else {
393 // TODO(edisonn): report pdf corruption
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000394 }
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000395 j++;
396 } else {
edisonn@google.comac4bedc2013-07-25 21:40:23 +0000397 // TODO(edisonn): report bad pdf
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000398 }
399 }
edisonn@google.com1be794f2013-06-21 21:43:09 +0000400 }
401
402public:
edisonn@google.com6e49c342013-06-27 20:03:43 +0000403 virtual double drawOneChar(unsigned int ch, SkPaint* paint, PdfContext* pdfContext, SkCanvas* canvas) {
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000404 if (ch < fFirstChar || ch > fLastChar || !fChars[ch - fFirstChar].fObj) {
edisonn@google.com6e49c342013-06-27 20:03:43 +0000405 return fBaseFont->drawOneChar(ToUnicode(ch), paint, pdfContext, canvas);
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000406 }
edisonn@google.com1be794f2013-06-21 21:43:09 +0000407
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000408#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
edisonn@google.com571c70b2013-07-10 17:09:50 +0000415 // 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);
edisonn@google.com1be794f2013-06-21 21:43:09 +0000417
edisonn@google.com6e49c342013-06-27 20:03:43 +0000418 // 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));
edisonn@google.com571c70b2013-07-10 17:09:50 +0000421 return fChars[ch - fFirstChar].fWidth;
edisonn@google.com1be794f2013-06-21 21:43:09 +0000422 }
423
424 virtual void afterWord(SkPaint* paint, SkMatrix* matrix) {
425
426 }
427};
428
429#endif // __DEFINED__SkPdfFont