blob: 386aaf5c6f5a49170fe2ceedac815bb052c9b77d [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.com3aa35552013-08-14 18:26:20 +000012#include "SkPdfGraphicsState.h"
edisonn@google.comb857a0c2013-06-25 20:45:40 +000013#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.com3aa35552013-08-14 18:26:20 +000041SkPdfFont* fontFromName(SkPdfNativeDoc* doc, SkPdfNativeObject* 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.com3aa35552013-08-14 18:26:20 +000080 SkPdfNativeDoc* 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.com3aa35552013-08-14 18:26:20 +000086 SkPdfToUnicode(SkPdfNativeDoc* 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.com3aa35552013-08-14 18:26:20 +0000173 void drawText(const SkDecodedText& text, SkPaint* paint, SkPdfContext* 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.com3aa35552013-08-14 18:26:20 +0000181
182#ifdef PDF_TRACE_DRAWTEXT
183 SkPaint col;
184 col.setColor(SK_ColorMAGENTA);
185 SkRect rect = SkRect::MakeXYWH(SkDoubleToScalar(0.0), SkDoubleToScalar(0.0), SkDoubleToScalar(10.0), SkDoubleToScalar(10.0));
186 canvas->save();
187 canvas->setMatrix(pdfContext->fGraphicsState.fMatrixTm);
188 canvas->drawRect(rect, col);
189 canvas->restore();
190#endif
edisonn@google.com6e49c342013-06-27 20:03:43 +0000191 double width = drawOneChar(text[i], paint, pdfContext, canvas);
192 pdfContext->fGraphicsState.fMatrixTm.preTranslate(SkDoubleToScalar(width), SkDoubleToScalar(0.0));
edisonn@google.com1be794f2013-06-21 21:43:09 +0000193 }
194 }
195
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000196 void ToUnicode(const SkDecodedText& textIn, SkUnicodeText* textOut) const {
197 if (fToUnicode) {
198 textOut->text = new uint16_t[textIn.len];
199 textOut->len = textIn.len;
200 for (int i = 0; i < textIn.len; i++) {
201 textOut->text[i] = fToUnicode->fCMapEncoding[textIn.text[i]];
202 }
203 } else {
204 textOut->text = textIn.text;
205 textOut->len = textIn.len;
206 }
207 };
208
209 inline unsigned int ToUnicode(unsigned int ch) const {
210 if (fToUnicode) {
211 return fToUnicode->fCMapEncoding[ch];
212 } else {
213 return ch;
214 }
edisonn@google.com1be794f2013-06-21 21:43:09 +0000215 };
216
edisonn@google.com3aa35552013-08-14 18:26:20 +0000217 static SkPdfFont* fontFromPdfDictionary(SkPdfNativeDoc* doc, SkPdfFontDictionary* dict);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000218 static SkPdfFont* Default() {return fontFromName(NULL, NULL, "TimesNewRoman");}
edisonn@google.com1be794f2013-06-21 21:43:09 +0000219
edisonn@google.com3aa35552013-08-14 18:26:20 +0000220 static SkPdfType0Font* fontFromType0FontDictionary(SkPdfNativeDoc* doc, SkPdfType0FontDictionary* dict);
221 static SkPdfType1Font* fontFromType1FontDictionary(SkPdfNativeDoc* doc, SkPdfType1FontDictionary* dict);
222 static SkPdfType3Font* fontFromType3FontDictionary(SkPdfNativeDoc* doc, SkPdfType3FontDictionary* dict);
223 static SkPdfTrueTypeFont* fontFromTrueTypeFontDictionary(SkPdfNativeDoc* doc, SkPdfTrueTypeFontDictionary* dict);
224 static SkPdfMultiMasterFont* fontFromMultiMasterFontDictionary(SkPdfNativeDoc* doc, SkPdfMultiMasterFontDictionary* dict);
edisonn@google.com1be794f2013-06-21 21:43:09 +0000225
edisonn@google.com3aa35552013-08-14 18:26:20 +0000226 static SkPdfFont* fontFromFontDescriptor(SkPdfNativeDoc* doc, SkPdfFontDescriptorDictionary* fd, bool loadFromName = true);
edisonn@google.com6e49c342013-06-27 20:03:43 +0000227
edisonn@google.com1be794f2013-06-21 21:43:09 +0000228public:
edisonn@google.com3aa35552013-08-14 18:26:20 +0000229 virtual double drawOneChar(unsigned int ch, SkPaint* paint, SkPdfContext* pdfContext, SkCanvas* canvas) = 0;
edisonn@google.com1be794f2013-06-21 21:43:09 +0000230 virtual void afterWord(SkPaint* paint, SkMatrix* matrix) = 0;
edisonn@google.com571c70b2013-07-10 17:09:50 +0000231
232private:
edisonn@google.com3aa35552013-08-14 18:26:20 +0000233 static SkPdfFont* fontFromPdfDictionaryOnce(SkPdfNativeDoc* doc, SkPdfFontDictionary* dict);
edisonn@google.com1be794f2013-06-21 21:43:09 +0000234};
235
236class SkPdfStandardFont : public SkPdfFont {
237 SkTypeface* fTypeface;
238
239public:
240 SkPdfStandardFont(SkTypeface* typeface) : fTypeface(typeface) {}
241
242public:
edisonn@google.com3aa35552013-08-14 18:26:20 +0000243 virtual double drawOneChar(unsigned int ch, SkPaint* paint, SkPdfContext* pdfContext, SkCanvas* canvas) {
edisonn@google.com1be794f2013-06-21 21:43:09 +0000244 paint->setTypeface(fTypeface);
245 paint->setTextEncoding(SkPaint::kUTF8_TextEncoding);
246
247 unsigned long ch4 = ch;
248 char utf8[10];
249 int len = SkUTF8_FromUnichar(ch4, utf8);
250
251 canvas->drawText(utf8, len, SkDoubleToScalar(0), SkDoubleToScalar(0), *paint);
252
253 SkScalar textWidth = paint->measureText(utf8, len);
edisonn@google.com6e49c342013-06-27 20:03:43 +0000254 return SkScalarToDouble(textWidth);
edisonn@google.com1be794f2013-06-21 21:43:09 +0000255 }
256
edisonn@google.com1be794f2013-06-21 21:43:09 +0000257 virtual void afterWord(SkPaint* paint, SkMatrix* matrix) {}
258};
259
edisonn@google.com1be794f2013-06-21 21:43:09 +0000260class SkPdfType0Font : public SkPdfFont {
edisonn@google.com1be794f2013-06-21 21:43:09 +0000261public:
edisonn@google.com3aa35552013-08-14 18:26:20 +0000262 SkPdfType0Font(SkPdfNativeDoc* doc, SkPdfType0FontDictionary* dict);
edisonn@google.com1be794f2013-06-21 21:43:09 +0000263
264public:
edisonn@google.com1be794f2013-06-21 21:43:09 +0000265
edisonn@google.com3aa35552013-08-14 18:26:20 +0000266 virtual double drawOneChar(unsigned int ch, SkPaint* paint, SkPdfContext* pdfContext, SkCanvas* canvas) {
edisonn@google.com6e49c342013-06-27 20:03:43 +0000267 return fBaseFont->drawOneChar(ToUnicode(ch), paint, pdfContext, canvas);
edisonn@google.com1be794f2013-06-21 21:43:09 +0000268 }
269
270 virtual void afterWord(SkPaint* paint, SkMatrix* matrix) {
edisonn@google.com1be794f2013-06-21 21:43:09 +0000271 }
272};
273
edisonn@google.com1be794f2013-06-21 21:43:09 +0000274class SkPdfType1Font : public SkPdfFont {
275public:
edisonn@google.com3aa35552013-08-14 18:26:20 +0000276 SkPdfType1Font(SkPdfNativeDoc* doc, SkPdfType1FontDictionary* dict) {
edisonn@google.com6e49c342013-06-27 20:03:43 +0000277 if (dict->has_FontDescriptor()) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000278 fBaseFont = SkPdfFont::fontFromFontDescriptor(doc, dict->FontDescriptor(doc));
edisonn@google.com6e49c342013-06-27 20:03:43 +0000279 } else {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000280 fBaseFont = fontFromName(doc, dict, dict->BaseFont(doc).c_str());
edisonn@google.com6e49c342013-06-27 20:03:43 +0000281 }
edisonn@google.com3aa35552013-08-14 18:26:20 +0000282
283 if (dict->isEncodingAName(doc)) {
284 fEncoding = SkPdfEncoding::fromName(dict->getEncodingAsName(doc).c_str());
285 } else if (dict->isEncodingADictionary(doc)) {
286 //SkPdfDictionary* dictEnc = dict->getEncodingAsDictionary(doc);
287 }
288 dict->FontDescriptor(doc);
edisonn@google.com1be794f2013-06-21 21:43:09 +0000289 }
290
edisonn@google.com1be794f2013-06-21 21:43:09 +0000291public:
edisonn@google.com3aa35552013-08-14 18:26:20 +0000292 virtual double drawOneChar(unsigned int ch, SkPaint* paint, SkPdfContext* pdfContext, SkCanvas* canvas) {
edisonn@google.com6e49c342013-06-27 20:03:43 +0000293 return fBaseFont->drawOneChar(ToUnicode(ch), paint, pdfContext, canvas);
edisonn@google.com1be794f2013-06-21 21:43:09 +0000294 }
295
296 virtual void afterWord(SkPaint* paint, SkMatrix* matrix) {
297
298 }
edisonn@google.com6e49c342013-06-27 20:03:43 +0000299};
edisonn@google.com1be794f2013-06-21 21:43:09 +0000300
edisonn@google.com6e49c342013-06-27 20:03:43 +0000301class SkPdfTrueTypeFont : public SkPdfType1Font {
edisonn@google.com1be794f2013-06-21 21:43:09 +0000302public:
edisonn@google.com3aa35552013-08-14 18:26:20 +0000303 SkPdfTrueTypeFont(SkPdfNativeDoc* doc, SkPdfTrueTypeFontDictionary* dict) : SkPdfType1Font(doc, dict) {
edisonn@google.com1be794f2013-06-21 21:43:09 +0000304 }
305};
306
edisonn@google.com6e49c342013-06-27 20:03:43 +0000307class SkPdfMultiMasterFont : public SkPdfType1Font {
edisonn@google.com1be794f2013-06-21 21:43:09 +0000308public:
edisonn@google.com3aa35552013-08-14 18:26:20 +0000309 SkPdfMultiMasterFont(SkPdfNativeDoc* doc, SkPdfMultiMasterFontDictionary* dict) : SkPdfType1Font(doc, dict) {
edisonn@google.com1be794f2013-06-21 21:43:09 +0000310 }
311};
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000312/*
313class CIDToGIDMap {
314 virtual unsigned int map(unsigned int cid) = 0;
315 static CIDToGIDMap* fromName(const char* name);
316};
317
318class CIDToGIDMap_Identity {
319 virtual unsigned int map(unsigned int cid) { return cid; }
320
321 static CIDToGIDMap_Identity* instance() {
322 static CIDToGIDMap_Identity* inst = new CIDToGIDMap_Identity();
323 return inst;
324 }
325};
326
327CIDToGIDMap* CIDToGIDMap::fromName(const char* name) {
328 // The only one supported right now is Identity
329 if (strcmp(name, "Identity") == 0) {
330 return CIDToGIDMap_Identity::instance();
331 }
332
333#ifdef PDF_TRACE
334 // TODO(edisonn): warning/report
335 printf("Unknown CIDToGIDMap: %s\n", name);
336#endif
337 return NULL;
338}
339CIDToGIDMap* fCidToGid;
340*/
edisonn@google.com1be794f2013-06-21 21:43:09 +0000341
342class SkPdfType3Font : public SkPdfFont {
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000343 struct Type3FontChar {
edisonn@google.com3aa35552013-08-14 18:26:20 +0000344 SkPdfNativeObject* fObj;
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000345 double fWidth;
346 };
347
348 SkPdfDictionary* fCharProcs;
349 SkPdfEncodingDictionary* fEncodingDict;
350 unsigned int fFirstChar;
351 unsigned int fLastChar;
352
353 SkRect fFontBBox;
354 SkMatrix fFonMatrix;
355
356 Type3FontChar* fChars;
357
edisonn@google.com1be794f2013-06-21 21:43:09 +0000358public:
edisonn@google.com3aa35552013-08-14 18:26:20 +0000359 SkPdfType3Font(SkPdfNativeDoc* parsed, SkPdfType3FontDictionary* dict) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000360 fBaseFont = fontFromName(parsed, dict, dict->BaseFont(parsed).c_str());
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000361
362 if (dict->has_Encoding()) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000363 if (dict->isEncodingAName(parsed)) {
364 fEncoding = SkPdfEncoding::fromName(dict->getEncodingAsName(parsed).c_str());
365 } else if (dict->isEncodingAEncodingdictionary(parsed)) {
edisonn@google.com2fd5d362013-07-23 19:43:48 +0000366 // No encoding.
367 fEncoding = SkPdfDefaultEncoding::instance();
edisonn@google.com571c70b2013-07-10 17:09:50 +0000368 fEncodingDict = dict->getEncodingAsEncodingdictionary(parsed);
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000369 }
370 }
371
372 // null?
edisonn@google.com571c70b2013-07-10 17:09:50 +0000373 fCharProcs = dict->CharProcs(parsed);
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000374
375 fToUnicode = NULL;
376 if (dict->has_ToUnicode()) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000377 fToUnicode = new SkPdfToUnicode(parsed, dict->ToUnicode(parsed));
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000378 }
379
edisonn@google.coma3356fc2013-07-10 18:20:06 +0000380 fFirstChar = (unsigned int)dict->FirstChar(parsed);
381 fLastChar = (unsigned int)dict->LastChar(parsed);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000382 fFonMatrix = dict->has_FontMatrix() ? dict->FontMatrix(parsed) : SkMatrix::I();
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000383
edisonn@google.com571c70b2013-07-10 17:09:50 +0000384 if (dict->has_FontBBox()) {
385 fFontBBox = dict->FontBBox(parsed);
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000386 }
387
388 fChars = new Type3FontChar[fLastChar - fFirstChar + 1];
389
390 memset(fChars, 0, sizeof(fChars[0]) * (fLastChar - fFirstChar + 1));
391
edisonn@google.com571c70b2013-07-10 17:09:50 +0000392 const SkPdfArray* widths = dict->Widths(parsed);
393 for (unsigned int i = 0 ; i < widths->size(); i++) {
edisonn@google.comac4bedc2013-07-25 21:40:23 +0000394 if ((fFirstChar + i) >= fFirstChar && (fFirstChar + i) <= fLastChar) {
395 fChars[i].fWidth = (*widths)[i]->numberValue();
396 } else {
397 // TODO(edisonn): report pdf corruption
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000398 }
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000399 }
400
edisonn@google.com571c70b2013-07-10 17:09:50 +0000401 const SkPdfArray* diffs = fEncodingDict->Differences(parsed);
402 unsigned int j = fFirstChar;
403 for (unsigned int i = 0 ; i < diffs->size(); i++) {
404 if ((*diffs)[i]->isInteger()) {
edisonn@google.coma3356fc2013-07-10 18:20:06 +0000405 j = (unsigned int)(*diffs)[i]->intValue();
edisonn@google.com571c70b2013-07-10 17:09:50 +0000406 } else if ((*diffs)[i]->isName()) {
edisonn@google.comac4bedc2013-07-25 21:40:23 +0000407 if (j >= fFirstChar && j <= fLastChar) {
408 fChars[j - fFirstChar].fObj = fCharProcs->get((*diffs)[i]);
409 } else {
410 // TODO(edisonn): report pdf corruption
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000411 }
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000412 j++;
413 } else {
edisonn@google.comac4bedc2013-07-25 21:40:23 +0000414 // TODO(edisonn): report bad pdf
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000415 }
416 }
edisonn@google.com1be794f2013-06-21 21:43:09 +0000417 }
418
419public:
edisonn@google.com3aa35552013-08-14 18:26:20 +0000420 virtual double drawOneChar(unsigned int ch, SkPaint* paint, SkPdfContext* pdfContext, SkCanvas* canvas) {
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000421 if (ch < fFirstChar || ch > fLastChar || !fChars[ch - fFirstChar].fObj) {
edisonn@google.com6e49c342013-06-27 20:03:43 +0000422 return fBaseFont->drawOneChar(ToUnicode(ch), paint, pdfContext, canvas);
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000423 }
edisonn@google.com1be794f2013-06-21 21:43:09 +0000424
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000425#ifdef PDF_TRACE
426 printf("Type 3 char to unicode: %c\n", ToUnicode(ch));
427 if (ToUnicode(ch) == 'A') {
428 printf("break;\n");
429 }
430#endif
431
edisonn@google.com571c70b2013-07-10 17:09:50 +0000432 // TODO(edisonn): is it better to resolve the reference at load time, or now?
433 doType3Char(pdfContext, canvas, pdfContext->fPdfDoc->resolveReference(fChars[ch - fFirstChar].fObj), fFontBBox, fFonMatrix, pdfContext->fGraphicsState.fCurFontSize);
edisonn@google.com1be794f2013-06-21 21:43:09 +0000434
edisonn@google.com6e49c342013-06-27 20:03:43 +0000435 // TODO(edisonn): verify/test translate code, not tested yet
436 pdfContext->fGraphicsState.fMatrixTm.preTranslate(SkDoubleToScalar(pdfContext->fGraphicsState.fCurFontSize * fChars[ch - fFirstChar].fWidth),
437 SkDoubleToScalar(0.0));
edisonn@google.com571c70b2013-07-10 17:09:50 +0000438 return fChars[ch - fFirstChar].fWidth;
edisonn@google.com1be794f2013-06-21 21:43:09 +0000439 }
440
441 virtual void afterWord(SkPaint* paint, SkMatrix* matrix) {
442
443 }
444};
445
446#endif // __DEFINED__SkPdfFont