blob: 09e01ac86ebe560d5cef80a965e52ac911d90ab4 [file] [log] [blame]
edisonn@google.comcf2cfa12013-08-21 16:31:37 +00001/*
2 * Copyright 2013 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#ifndef SkPdfFont_DEFINED
9#define SkPdfFont_DEFINED
edisonn@google.com1be794f2013-06-21 21:43:09 +000010
11#include "SkPdfHeaders_autogen.h"
edisonn@google.com3aac1f92013-07-02 22:42:53 +000012#include "SkPdfMapper_autogen.h"
edisonn@google.com1be794f2013-06-21 21:43:09 +000013
edisonn@google.com131d4ee2013-06-26 17:48:12 +000014#include "SkTypeface.h"
edisonn@google.com1be794f2013-06-21 21:43:09 +000015#include "SkUtils.h"
edisonn@google.com3aa35552013-08-14 18:26:20 +000016#include "SkPdfGraphicsState.h"
edisonn@google.comb857a0c2013-06-25 20:45:40 +000017#include "SkPdfUtils.h"
edisonn@google.com063d7072013-08-16 15:05:08 +000018#include "SkTDict.h"
edisonn@google.com1be794f2013-06-21 21:43:09 +000019
20class SkPdfType0Font;
21class SkPdfType1Font;
22class SkPdfType3Font;
23class SkPdfTrueTypeFont;
edisonn@google.com1be794f2013-06-21 21:43:09 +000024class SkPdfMultiMasterFont;
25class SkPdfFont;
26
edisonn@google.com1be794f2013-06-21 21:43:09 +000027struct SkPdfStandardFontEntry {
edisonn@google.com596d2e22013-07-10 17:44:55 +000028 // We don't own this pointer!
edisonn@google.com1be794f2013-06-21 21:43:09 +000029 const char* fName;
30 bool fIsBold;
31 bool fIsItalic;
edisonn@google.com596d2e22013-07-10 17:44:55 +000032 SkPdfStandardFontEntry()
33 : fName(NULL),
34 fIsBold(false),
35 fIsItalic(false) {}
36
37 SkPdfStandardFontEntry(const char* name, bool bold, bool italic)
38 : fName(name),
39 fIsBold(bold),
40 fIsItalic(italic) {}
edisonn@google.com1be794f2013-06-21 21:43:09 +000041};
42
edisonn@google.com063d7072013-08-16 15:05:08 +000043SkTDict<SkPdfStandardFontEntry>& getStandardFonts();
edisonn@google.com1be794f2013-06-21 21:43:09 +000044SkTypeface* SkTypefaceFromPdfStandardFont(const char* fontName, bool bold, bool italic);
edisonn@google.com3aa35552013-08-14 18:26:20 +000045SkPdfFont* fontFromName(SkPdfNativeDoc* doc, SkPdfNativeObject* obj, const char* fontName);
edisonn@google.com1be794f2013-06-21 21:43:09 +000046
47struct SkUnencodedText {
48 void* text;
49 int len;
50
51public:
edisonn@google.com3aac1f92013-07-02 22:42:53 +000052 SkUnencodedText(const SkPdfString* obj) {
53 text = (void*)obj->c_str();
edisonn@google.come878e722013-07-29 19:10:58 +000054 len = obj->lenstr();
edisonn@google.com1be794f2013-06-21 21:43:09 +000055 }
56};
57
58struct SkDecodedText {
59 uint16_t* text;
60 int len;
edisonn@google.comb857a0c2013-06-25 20:45:40 +000061public:
62 unsigned int operator[](int i) const { return text[i]; }
63 int size() const { return len; }
edisonn@google.com1be794f2013-06-21 21:43:09 +000064};
65
66struct SkUnicodeText {
67 uint16_t* text;
68 int len;
69
70public:
71 unsigned int operator[](int i) const { return text[i]; }
72 int size() const { return len; }
73};
74
75class SkPdfEncoding {
76public:
77 virtual bool decodeText(const SkUnencodedText& textIn, SkDecodedText* textOut) const = 0;
edisonn@google.comb857a0c2013-06-25 20:45:40 +000078 static SkPdfEncoding* fromName(const char* name);
edisonn@google.com1be794f2013-06-21 21:43:09 +000079};
80
edisonn@google.com063d7072013-08-16 15:05:08 +000081SkTDict<SkPdfEncoding*>& getStandardEncodings();
edisonn@google.comb857a0c2013-06-25 20:45:40 +000082
83class SkPdfToUnicode {
edisonn@google.com3aa35552013-08-14 18:26:20 +000084 SkPdfNativeDoc* fParsed;
edisonn@google.comb857a0c2013-06-25 20:45:40 +000085 // TODO(edisonn): hide public members
86public:
87 unsigned short* fCMapEncoding;
88 unsigned char* fCMapEncodingFlag;
89
edisonn@google.com3aa35552013-08-14 18:26:20 +000090 SkPdfToUnicode(SkPdfNativeDoc* parsed, SkPdfStream* stream);
edisonn@google.comb857a0c2013-06-25 20:45:40 +000091};
92
93
edisonn@google.com1be794f2013-06-21 21:43:09 +000094class SkPdfIdentityHEncoding : public SkPdfEncoding {
95public:
96 virtual bool decodeText(const SkUnencodedText& textIn, SkDecodedText* textOut) const {
97 // TODO(edisonn): SkASSERT(textIn.len % 2 == 0); or report error?
98
99 uint16_t* text = (uint16_t*)textIn.text;
100 textOut->text = new uint16_t[textIn.len / 2];
101 textOut->len = textIn.len / 2;
102
103 for (int i = 0; i < textOut->len; i++) {
104 textOut->text[i] = ((text[i] << 8) & 0xff00) | ((text[i] >> 8) & 0x00ff);
105 }
106
107 return true;
108 }
109
110 static SkPdfIdentityHEncoding* instance() {
111 static SkPdfIdentityHEncoding* inst = new SkPdfIdentityHEncoding();
112 return inst;
113 }
114};
115
edisonn@google.com6e49c342013-06-27 20:03:43 +0000116// TODO(edisonn): using this one when no encoding is specified
117class SkPdfDefaultEncoding : public SkPdfEncoding {
118public:
119 virtual bool decodeText(const SkUnencodedText& textIn, SkDecodedText* textOut) const {
120 // TODO(edisonn): SkASSERT(textIn.len % 2 == 0); or report error?
121
122 unsigned char* text = (unsigned char*)textIn.text;
123 textOut->text = new uint16_t[textIn.len];
124 textOut->len = textIn.len;
125
126 for (int i = 0; i < textOut->len; i++) {
127 textOut->text[i] = text[i];
128 }
129
130 return true;
131 }
132
133 static SkPdfDefaultEncoding* instance() {
134 static SkPdfDefaultEncoding* inst = new SkPdfDefaultEncoding();
135 return inst;
136 }
137};
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000138
139class SkPdfCIDToGIDMapIdentityEncoding : public SkPdfEncoding {
140public:
141 virtual bool decodeText(const SkUnencodedText& textIn, SkDecodedText* textOut) const {
142 // TODO(edisonn): SkASSERT(textIn.len % 2 == 0); or report error?
143
edisonn@google.com571c70b2013-07-10 17:09:50 +0000144 uint16_t* text = (uint16_t*)textIn.text;
145 textOut->text = new uint16_t[textIn.len / 2];
146 textOut->len = textIn.len / 2;
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000147
148 for (int i = 0; i < textOut->len; i++) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000149 textOut->text[i] = ((text[i] << 8) & 0xff00) | ((text[i] >> 8) & 0x00ff);
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000150 }
151
152 return true;
153 }
154
155 static SkPdfCIDToGIDMapIdentityEncoding* instance() {
156 static SkPdfCIDToGIDMapIdentityEncoding* inst = new SkPdfCIDToGIDMapIdentityEncoding();
157 return inst;
158 }
159};
160
edisonn@google.com1be794f2013-06-21 21:43:09 +0000161class SkPdfFont {
162public:
163 SkPdfFont* fBaseFont;
164 SkPdfEncoding* fEncoding;
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000165 SkPdfToUnicode* fToUnicode;
166
edisonn@google.com1be794f2013-06-21 21:43:09 +0000167
168public:
edisonn@google.com6e49c342013-06-27 20:03:43 +0000169 SkPdfFont() : fBaseFont(NULL), fEncoding(SkPdfDefaultEncoding::instance()), fToUnicode(NULL) {}
edisonn@google.com1be794f2013-06-21 21:43:09 +0000170
edisonn@google.com7ee12ca2013-08-05 18:18:06 +0000171 virtual ~SkPdfFont() {
172 // TODO(edisonn): NYI (will leak for now)
173 }
174
edisonn@google.com1be794f2013-06-21 21:43:09 +0000175 const SkPdfEncoding* encoding() const {return fEncoding;}
176
edisonn@google.com3aa35552013-08-14 18:26:20 +0000177 void drawText(const SkDecodedText& text, SkPaint* paint, SkPdfContext* pdfContext, SkCanvas* canvas) {
edisonn@google.com1be794f2013-06-21 21:43:09 +0000178 for (int i = 0 ; i < text.size(); i++) {
edisonn@google.come57c62d2013-08-07 18:04:15 +0000179 canvas->setMatrix(pdfContext->fGraphicsState.fMatrixTm);
180#ifdef PDF_TRACE
181 SkPoint point = SkPoint::Make(SkDoubleToScalar(0), SkDoubleToScalar(0));
182 pdfContext->fGraphicsState.fMatrixTm.mapPoints(&point, 1);
183 printf("DrawText at (%f, %f)\n", SkScalarToDouble(point.x()), SkScalarToDouble(point.y()));
184#endif // PDF_TRACE
edisonn@google.com3aa35552013-08-14 18:26:20 +0000185
186#ifdef PDF_TRACE_DRAWTEXT
187 SkPaint col;
188 col.setColor(SK_ColorMAGENTA);
189 SkRect rect = SkRect::MakeXYWH(SkDoubleToScalar(0.0), SkDoubleToScalar(0.0), SkDoubleToScalar(10.0), SkDoubleToScalar(10.0));
190 canvas->save();
191 canvas->setMatrix(pdfContext->fGraphicsState.fMatrixTm);
192 canvas->drawRect(rect, col);
193 canvas->restore();
194#endif
edisonn@google.com6e49c342013-06-27 20:03:43 +0000195 double width = drawOneChar(text[i], paint, pdfContext, canvas);
196 pdfContext->fGraphicsState.fMatrixTm.preTranslate(SkDoubleToScalar(width), SkDoubleToScalar(0.0));
edisonn@google.com1be794f2013-06-21 21:43:09 +0000197 }
198 }
199
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000200 void ToUnicode(const SkDecodedText& textIn, SkUnicodeText* textOut) const {
201 if (fToUnicode) {
202 textOut->text = new uint16_t[textIn.len];
203 textOut->len = textIn.len;
204 for (int i = 0; i < textIn.len; i++) {
205 textOut->text[i] = fToUnicode->fCMapEncoding[textIn.text[i]];
206 }
207 } else {
208 textOut->text = textIn.text;
209 textOut->len = textIn.len;
210 }
211 };
212
213 inline unsigned int ToUnicode(unsigned int ch) const {
214 if (fToUnicode) {
215 return fToUnicode->fCMapEncoding[ch];
216 } else {
217 return ch;
218 }
edisonn@google.com1be794f2013-06-21 21:43:09 +0000219 };
220
edisonn@google.com3aa35552013-08-14 18:26:20 +0000221 static SkPdfFont* fontFromPdfDictionary(SkPdfNativeDoc* doc, SkPdfFontDictionary* dict);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000222 static SkPdfFont* Default() {return fontFromName(NULL, NULL, "TimesNewRoman");}
edisonn@google.com1be794f2013-06-21 21:43:09 +0000223
edisonn@google.com3aa35552013-08-14 18:26:20 +0000224 static SkPdfType0Font* fontFromType0FontDictionary(SkPdfNativeDoc* doc, SkPdfType0FontDictionary* dict);
225 static SkPdfType1Font* fontFromType1FontDictionary(SkPdfNativeDoc* doc, SkPdfType1FontDictionary* dict);
226 static SkPdfType3Font* fontFromType3FontDictionary(SkPdfNativeDoc* doc, SkPdfType3FontDictionary* dict);
227 static SkPdfTrueTypeFont* fontFromTrueTypeFontDictionary(SkPdfNativeDoc* doc, SkPdfTrueTypeFontDictionary* dict);
228 static SkPdfMultiMasterFont* fontFromMultiMasterFontDictionary(SkPdfNativeDoc* doc, SkPdfMultiMasterFontDictionary* dict);
edisonn@google.com1be794f2013-06-21 21:43:09 +0000229
edisonn@google.com3aa35552013-08-14 18:26:20 +0000230 static SkPdfFont* fontFromFontDescriptor(SkPdfNativeDoc* doc, SkPdfFontDescriptorDictionary* fd, bool loadFromName = true);
edisonn@google.com6e49c342013-06-27 20:03:43 +0000231
edisonn@google.com1be794f2013-06-21 21:43:09 +0000232public:
edisonn@google.com3aa35552013-08-14 18:26:20 +0000233 virtual double drawOneChar(unsigned int ch, SkPaint* paint, SkPdfContext* pdfContext, SkCanvas* canvas) = 0;
edisonn@google.com1be794f2013-06-21 21:43:09 +0000234 virtual void afterWord(SkPaint* paint, SkMatrix* matrix) = 0;
edisonn@google.com571c70b2013-07-10 17:09:50 +0000235
236private:
edisonn@google.com3aa35552013-08-14 18:26:20 +0000237 static SkPdfFont* fontFromPdfDictionaryOnce(SkPdfNativeDoc* doc, SkPdfFontDictionary* dict);
edisonn@google.com1be794f2013-06-21 21:43:09 +0000238};
239
240class SkPdfStandardFont : public SkPdfFont {
241 SkTypeface* fTypeface;
242
243public:
244 SkPdfStandardFont(SkTypeface* typeface) : fTypeface(typeface) {}
245
246public:
edisonn@google.com3aa35552013-08-14 18:26:20 +0000247 virtual double drawOneChar(unsigned int ch, SkPaint* paint, SkPdfContext* pdfContext, SkCanvas* canvas) {
edisonn@google.com1be794f2013-06-21 21:43:09 +0000248 paint->setTypeface(fTypeface);
249 paint->setTextEncoding(SkPaint::kUTF8_TextEncoding);
250
251 unsigned long ch4 = ch;
252 char utf8[10];
253 int len = SkUTF8_FromUnichar(ch4, utf8);
254
255 canvas->drawText(utf8, len, SkDoubleToScalar(0), SkDoubleToScalar(0), *paint);
256
257 SkScalar textWidth = paint->measureText(utf8, len);
edisonn@google.com6e49c342013-06-27 20:03:43 +0000258 return SkScalarToDouble(textWidth);
edisonn@google.com1be794f2013-06-21 21:43:09 +0000259 }
260
edisonn@google.com1be794f2013-06-21 21:43:09 +0000261 virtual void afterWord(SkPaint* paint, SkMatrix* matrix) {}
262};
263
edisonn@google.com1be794f2013-06-21 21:43:09 +0000264class SkPdfType0Font : public SkPdfFont {
edisonn@google.com1be794f2013-06-21 21:43:09 +0000265public:
edisonn@google.com3aa35552013-08-14 18:26:20 +0000266 SkPdfType0Font(SkPdfNativeDoc* doc, SkPdfType0FontDictionary* dict);
edisonn@google.com1be794f2013-06-21 21:43:09 +0000267
268public:
edisonn@google.com1be794f2013-06-21 21:43:09 +0000269
edisonn@google.com3aa35552013-08-14 18:26:20 +0000270 virtual double drawOneChar(unsigned int ch, SkPaint* paint, SkPdfContext* pdfContext, SkCanvas* canvas) {
edisonn@google.com6e49c342013-06-27 20:03:43 +0000271 return fBaseFont->drawOneChar(ToUnicode(ch), paint, pdfContext, canvas);
edisonn@google.com1be794f2013-06-21 21:43:09 +0000272 }
273
274 virtual void afterWord(SkPaint* paint, SkMatrix* matrix) {
edisonn@google.com1be794f2013-06-21 21:43:09 +0000275 }
276};
277
edisonn@google.com1be794f2013-06-21 21:43:09 +0000278class SkPdfType1Font : public SkPdfFont {
279public:
edisonn@google.com3aa35552013-08-14 18:26:20 +0000280 SkPdfType1Font(SkPdfNativeDoc* doc, SkPdfType1FontDictionary* dict) {
edisonn@google.com6e49c342013-06-27 20:03:43 +0000281 if (dict->has_FontDescriptor()) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000282 fBaseFont = SkPdfFont::fontFromFontDescriptor(doc, dict->FontDescriptor(doc));
edisonn@google.com6e49c342013-06-27 20:03:43 +0000283 } else {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000284 fBaseFont = fontFromName(doc, dict, dict->BaseFont(doc).c_str());
edisonn@google.com6e49c342013-06-27 20:03:43 +0000285 }
edisonn@google.com3aa35552013-08-14 18:26:20 +0000286
287 if (dict->isEncodingAName(doc)) {
288 fEncoding = SkPdfEncoding::fromName(dict->getEncodingAsName(doc).c_str());
289 } else if (dict->isEncodingADictionary(doc)) {
290 //SkPdfDictionary* dictEnc = dict->getEncodingAsDictionary(doc);
291 }
292 dict->FontDescriptor(doc);
edisonn@google.com1be794f2013-06-21 21:43:09 +0000293 }
294
edisonn@google.com1be794f2013-06-21 21:43:09 +0000295public:
edisonn@google.com3aa35552013-08-14 18:26:20 +0000296 virtual double drawOneChar(unsigned int ch, SkPaint* paint, SkPdfContext* pdfContext, SkCanvas* canvas) {
edisonn@google.com6e49c342013-06-27 20:03:43 +0000297 return fBaseFont->drawOneChar(ToUnicode(ch), paint, pdfContext, canvas);
edisonn@google.com1be794f2013-06-21 21:43:09 +0000298 }
299
300 virtual void afterWord(SkPaint* paint, SkMatrix* matrix) {
301
302 }
edisonn@google.com6e49c342013-06-27 20:03:43 +0000303};
edisonn@google.com1be794f2013-06-21 21:43:09 +0000304
edisonn@google.com6e49c342013-06-27 20:03:43 +0000305class SkPdfTrueTypeFont : public SkPdfType1Font {
edisonn@google.com1be794f2013-06-21 21:43:09 +0000306public:
edisonn@google.com3aa35552013-08-14 18:26:20 +0000307 SkPdfTrueTypeFont(SkPdfNativeDoc* doc, SkPdfTrueTypeFontDictionary* dict) : SkPdfType1Font(doc, dict) {
edisonn@google.com1be794f2013-06-21 21:43:09 +0000308 }
309};
310
edisonn@google.com6e49c342013-06-27 20:03:43 +0000311class SkPdfMultiMasterFont : public SkPdfType1Font {
edisonn@google.com1be794f2013-06-21 21:43:09 +0000312public:
edisonn@google.com3aa35552013-08-14 18:26:20 +0000313 SkPdfMultiMasterFont(SkPdfNativeDoc* doc, SkPdfMultiMasterFontDictionary* dict) : SkPdfType1Font(doc, dict) {
edisonn@google.com1be794f2013-06-21 21:43:09 +0000314 }
315};
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000316/*
317class CIDToGIDMap {
318 virtual unsigned int map(unsigned int cid) = 0;
319 static CIDToGIDMap* fromName(const char* name);
320};
321
322class CIDToGIDMap_Identity {
323 virtual unsigned int map(unsigned int cid) { return cid; }
324
325 static CIDToGIDMap_Identity* instance() {
326 static CIDToGIDMap_Identity* inst = new CIDToGIDMap_Identity();
327 return inst;
328 }
329};
330
331CIDToGIDMap* CIDToGIDMap::fromName(const char* name) {
332 // The only one supported right now is Identity
333 if (strcmp(name, "Identity") == 0) {
334 return CIDToGIDMap_Identity::instance();
335 }
336
337#ifdef PDF_TRACE
338 // TODO(edisonn): warning/report
339 printf("Unknown CIDToGIDMap: %s\n", name);
340#endif
341 return NULL;
342}
343CIDToGIDMap* fCidToGid;
344*/
edisonn@google.com1be794f2013-06-21 21:43:09 +0000345
346class SkPdfType3Font : public SkPdfFont {
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000347 struct Type3FontChar {
edisonn@google.com3aa35552013-08-14 18:26:20 +0000348 SkPdfNativeObject* fObj;
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000349 double fWidth;
350 };
351
352 SkPdfDictionary* fCharProcs;
353 SkPdfEncodingDictionary* fEncodingDict;
354 unsigned int fFirstChar;
355 unsigned int fLastChar;
356
357 SkRect fFontBBox;
358 SkMatrix fFonMatrix;
359
360 Type3FontChar* fChars;
361
edisonn@google.com1be794f2013-06-21 21:43:09 +0000362public:
edisonn@google.com3aa35552013-08-14 18:26:20 +0000363 SkPdfType3Font(SkPdfNativeDoc* parsed, SkPdfType3FontDictionary* dict) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000364 fBaseFont = fontFromName(parsed, dict, dict->BaseFont(parsed).c_str());
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000365
366 if (dict->has_Encoding()) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000367 if (dict->isEncodingAName(parsed)) {
368 fEncoding = SkPdfEncoding::fromName(dict->getEncodingAsName(parsed).c_str());
369 } else if (dict->isEncodingAEncodingdictionary(parsed)) {
edisonn@google.com2fd5d362013-07-23 19:43:48 +0000370 // No encoding.
371 fEncoding = SkPdfDefaultEncoding::instance();
edisonn@google.com571c70b2013-07-10 17:09:50 +0000372 fEncodingDict = dict->getEncodingAsEncodingdictionary(parsed);
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000373 }
374 }
375
376 // null?
edisonn@google.com571c70b2013-07-10 17:09:50 +0000377 fCharProcs = dict->CharProcs(parsed);
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000378
379 fToUnicode = NULL;
380 if (dict->has_ToUnicode()) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000381 fToUnicode = new SkPdfToUnicode(parsed, dict->ToUnicode(parsed));
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000382 }
383
edisonn@google.coma3356fc2013-07-10 18:20:06 +0000384 fFirstChar = (unsigned int)dict->FirstChar(parsed);
385 fLastChar = (unsigned int)dict->LastChar(parsed);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000386 fFonMatrix = dict->has_FontMatrix() ? dict->FontMatrix(parsed) : SkMatrix::I();
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000387
edisonn@google.com571c70b2013-07-10 17:09:50 +0000388 if (dict->has_FontBBox()) {
389 fFontBBox = dict->FontBBox(parsed);
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000390 }
391
392 fChars = new Type3FontChar[fLastChar - fFirstChar + 1];
393
394 memset(fChars, 0, sizeof(fChars[0]) * (fLastChar - fFirstChar + 1));
395
edisonn@google.com571c70b2013-07-10 17:09:50 +0000396 const SkPdfArray* widths = dict->Widths(parsed);
397 for (unsigned int i = 0 ; i < widths->size(); i++) {
edisonn@google.comac4bedc2013-07-25 21:40:23 +0000398 if ((fFirstChar + i) >= fFirstChar && (fFirstChar + i) <= fLastChar) {
399 fChars[i].fWidth = (*widths)[i]->numberValue();
400 } else {
401 // TODO(edisonn): report pdf corruption
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000402 }
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000403 }
404
edisonn@google.com571c70b2013-07-10 17:09:50 +0000405 const SkPdfArray* diffs = fEncodingDict->Differences(parsed);
406 unsigned int j = fFirstChar;
407 for (unsigned int i = 0 ; i < diffs->size(); i++) {
408 if ((*diffs)[i]->isInteger()) {
edisonn@google.coma3356fc2013-07-10 18:20:06 +0000409 j = (unsigned int)(*diffs)[i]->intValue();
edisonn@google.com571c70b2013-07-10 17:09:50 +0000410 } else if ((*diffs)[i]->isName()) {
edisonn@google.comac4bedc2013-07-25 21:40:23 +0000411 if (j >= fFirstChar && j <= fLastChar) {
412 fChars[j - fFirstChar].fObj = fCharProcs->get((*diffs)[i]);
413 } else {
414 // TODO(edisonn): report pdf corruption
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000415 }
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000416 j++;
417 } else {
edisonn@google.comac4bedc2013-07-25 21:40:23 +0000418 // TODO(edisonn): report bad pdf
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000419 }
420 }
edisonn@google.com1be794f2013-06-21 21:43:09 +0000421 }
422
423public:
edisonn@google.com3aa35552013-08-14 18:26:20 +0000424 virtual double drawOneChar(unsigned int ch, SkPaint* paint, SkPdfContext* pdfContext, SkCanvas* canvas) {
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000425 if (ch < fFirstChar || ch > fLastChar || !fChars[ch - fFirstChar].fObj) {
edisonn@google.com6e49c342013-06-27 20:03:43 +0000426 return fBaseFont->drawOneChar(ToUnicode(ch), paint, pdfContext, canvas);
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000427 }
edisonn@google.com1be794f2013-06-21 21:43:09 +0000428
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000429#ifdef PDF_TRACE
430 printf("Type 3 char to unicode: %c\n", ToUnicode(ch));
431 if (ToUnicode(ch) == 'A') {
432 printf("break;\n");
433 }
434#endif
435
edisonn@google.com571c70b2013-07-10 17:09:50 +0000436 // TODO(edisonn): is it better to resolve the reference at load time, or now?
437 doType3Char(pdfContext, canvas, pdfContext->fPdfDoc->resolveReference(fChars[ch - fFirstChar].fObj), fFontBBox, fFonMatrix, pdfContext->fGraphicsState.fCurFontSize);
edisonn@google.com1be794f2013-06-21 21:43:09 +0000438
edisonn@google.com6e49c342013-06-27 20:03:43 +0000439 // TODO(edisonn): verify/test translate code, not tested yet
440 pdfContext->fGraphicsState.fMatrixTm.preTranslate(SkDoubleToScalar(pdfContext->fGraphicsState.fCurFontSize * fChars[ch - fFirstChar].fWidth),
441 SkDoubleToScalar(0.0));
edisonn@google.com571c70b2013-07-10 17:09:50 +0000442 return fChars[ch - fFirstChar].fWidth;
edisonn@google.com1be794f2013-06-21 21:43:09 +0000443 }
444
445 virtual void afterWord(SkPaint* paint, SkMatrix* matrix) {
446
447 }
448};
449
edisonn@google.comcf2cfa12013-08-21 16:31:37 +0000450#endif // SkPdfFont_DEFINED