blob: 12cc8990320548cb3d4bc43a84641db3535c58c1 [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
edisonn@google.come50d9a12013-10-10 20:58:22 +000011#include "SkPdfGraphicsState.h"
edisonn@google.com1be794f2013-06-21 21:43:09 +000012#include "SkPdfHeaders_autogen.h"
edisonn@google.com3aac1f92013-07-02 22:42:53 +000013#include "SkPdfMapper_autogen.h"
edisonn@google.comb857a0c2013-06-25 20:45:40 +000014#include "SkPdfUtils.h"
edisonn@google.come50d9a12013-10-10 20:58:22 +000015#include "SkTypeface.h"
edisonn@google.com063d7072013-08-16 15:05:08 +000016#include "SkTDict.h"
edisonn@google.come50d9a12013-10-10 20:58:22 +000017#include "SkUtils.h"
edisonn@google.com1be794f2013-06-21 21:43:09 +000018
19class SkPdfType0Font;
20class SkPdfType1Font;
21class SkPdfType3Font;
22class SkPdfTrueTypeFont;
edisonn@google.com1be794f2013-06-21 21:43:09 +000023class SkPdfMultiMasterFont;
24class SkPdfFont;
25
edisonn@google.com1be794f2013-06-21 21:43:09 +000026struct SkPdfStandardFontEntry {
edisonn@google.com596d2e22013-07-10 17:44:55 +000027 // We don't own this pointer!
edisonn@google.com1be794f2013-06-21 21:43:09 +000028 const char* fName;
29 bool fIsBold;
30 bool fIsItalic;
edisonn@google.com596d2e22013-07-10 17:44:55 +000031 SkPdfStandardFontEntry()
32 : fName(NULL),
33 fIsBold(false),
34 fIsItalic(false) {}
35
36 SkPdfStandardFontEntry(const char* name, bool bold, bool italic)
37 : fName(name),
38 fIsBold(bold),
39 fIsItalic(italic) {}
edisonn@google.com1be794f2013-06-21 21:43:09 +000040};
41
edisonn@google.com063d7072013-08-16 15:05:08 +000042SkTDict<SkPdfStandardFontEntry>& getStandardFonts();
edisonn@google.com1be794f2013-06-21 21:43:09 +000043SkTypeface* SkTypefaceFromPdfStandardFont(const char* fontName, bool bold, bool italic);
edisonn@google.com3aa35552013-08-14 18:26:20 +000044SkPdfFont* fontFromName(SkPdfNativeDoc* doc, SkPdfNativeObject* obj, const char* fontName);
edisonn@google.com1be794f2013-06-21 21:43:09 +000045
46struct SkUnencodedText {
47 void* text;
48 int len;
49
50public:
edisonn@google.com3aac1f92013-07-02 22:42:53 +000051 SkUnencodedText(const SkPdfString* obj) {
52 text = (void*)obj->c_str();
edisonn@google.come878e722013-07-29 19:10:58 +000053 len = obj->lenstr();
edisonn@google.com1be794f2013-06-21 21:43:09 +000054 }
55};
56
57struct SkDecodedText {
58 uint16_t* text;
59 int len;
edisonn@google.comb857a0c2013-06-25 20:45:40 +000060public:
61 unsigned int operator[](int i) const { return text[i]; }
62 int size() const { return len; }
edisonn@google.com1be794f2013-06-21 21:43:09 +000063};
64
65struct SkUnicodeText {
66 uint16_t* text;
67 int len;
68
69public:
70 unsigned int operator[](int i) const { return text[i]; }
71 int size() const { return len; }
72};
73
74class SkPdfEncoding {
75public:
76 virtual bool decodeText(const SkUnencodedText& textIn, SkDecodedText* textOut) const = 0;
edisonn@google.comb857a0c2013-06-25 20:45:40 +000077 static SkPdfEncoding* fromName(const char* name);
edisonn@google.com1be794f2013-06-21 21:43:09 +000078};
79
edisonn@google.com063d7072013-08-16 15:05:08 +000080SkTDict<SkPdfEncoding*>& getStandardEncodings();
edisonn@google.comb857a0c2013-06-25 20:45:40 +000081
82class SkPdfToUnicode {
edisonn@google.com3aa35552013-08-14 18:26:20 +000083 SkPdfNativeDoc* fParsed;
edisonn@google.comb857a0c2013-06-25 20:45:40 +000084 // TODO(edisonn): hide public members
85public:
86 unsigned short* fCMapEncoding;
87 unsigned char* fCMapEncodingFlag;
88
edisonn@google.com3aa35552013-08-14 18:26:20 +000089 SkPdfToUnicode(SkPdfNativeDoc* parsed, SkPdfStream* stream);
edisonn@google.comb857a0c2013-06-25 20:45:40 +000090};
91
92
edisonn@google.com1be794f2013-06-21 21:43:09 +000093class SkPdfIdentityHEncoding : public SkPdfEncoding {
94public:
95 virtual bool decodeText(const SkUnencodedText& textIn, SkDecodedText* textOut) const {
96 // TODO(edisonn): SkASSERT(textIn.len % 2 == 0); or report error?
97
98 uint16_t* text = (uint16_t*)textIn.text;
99 textOut->text = new uint16_t[textIn.len / 2];
100 textOut->len = textIn.len / 2;
101
102 for (int i = 0; i < textOut->len; i++) {
103 textOut->text[i] = ((text[i] << 8) & 0xff00) | ((text[i] >> 8) & 0x00ff);
104 }
105
106 return true;
107 }
108
109 static SkPdfIdentityHEncoding* instance() {
110 static SkPdfIdentityHEncoding* inst = new SkPdfIdentityHEncoding();
111 return inst;
112 }
113};
114
edisonn@google.com6e49c342013-06-27 20:03:43 +0000115// TODO(edisonn): using this one when no encoding is specified
116class SkPdfDefaultEncoding : public SkPdfEncoding {
117public:
118 virtual bool decodeText(const SkUnencodedText& textIn, SkDecodedText* textOut) const {
119 // TODO(edisonn): SkASSERT(textIn.len % 2 == 0); or report error?
120
121 unsigned char* text = (unsigned char*)textIn.text;
122 textOut->text = new uint16_t[textIn.len];
123 textOut->len = textIn.len;
124
125 for (int i = 0; i < textOut->len; i++) {
126 textOut->text[i] = text[i];
127 }
128
129 return true;
130 }
131
132 static SkPdfDefaultEncoding* instance() {
133 static SkPdfDefaultEncoding* inst = new SkPdfDefaultEncoding();
134 return inst;
135 }
136};
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000137
138class SkPdfCIDToGIDMapIdentityEncoding : public SkPdfEncoding {
139public:
140 virtual bool decodeText(const SkUnencodedText& textIn, SkDecodedText* textOut) const {
141 // TODO(edisonn): SkASSERT(textIn.len % 2 == 0); or report error?
142
edisonn@google.com571c70b2013-07-10 17:09:50 +0000143 uint16_t* text = (uint16_t*)textIn.text;
144 textOut->text = new uint16_t[textIn.len / 2];
145 textOut->len = textIn.len / 2;
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000146
147 for (int i = 0; i < textOut->len; i++) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000148 textOut->text[i] = ((text[i] << 8) & 0xff00) | ((text[i] >> 8) & 0x00ff);
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000149 }
150
151 return true;
152 }
153
154 static SkPdfCIDToGIDMapIdentityEncoding* instance() {
155 static SkPdfCIDToGIDMapIdentityEncoding* inst = new SkPdfCIDToGIDMapIdentityEncoding();
156 return inst;
157 }
158};
159
edisonn@google.com1be794f2013-06-21 21:43:09 +0000160class SkPdfFont {
161public:
162 SkPdfFont* fBaseFont;
163 SkPdfEncoding* fEncoding;
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000164 SkPdfToUnicode* fToUnicode;
165
edisonn@google.com1be794f2013-06-21 21:43:09 +0000166
167public:
edisonn@google.com6e49c342013-06-27 20:03:43 +0000168 SkPdfFont() : fBaseFont(NULL), fEncoding(SkPdfDefaultEncoding::instance()), fToUnicode(NULL) {}
edisonn@google.com1be794f2013-06-21 21:43:09 +0000169
edisonn@google.com7ee12ca2013-08-05 18:18:06 +0000170 virtual ~SkPdfFont() {
171 // TODO(edisonn): NYI (will leak for now)
172 }
173
edisonn@google.com1be794f2013-06-21 21:43:09 +0000174 const SkPdfEncoding* encoding() const {return fEncoding;}
175
edisonn@google.come50d9a12013-10-10 20:58:22 +0000176 void drawText(const SkDecodedText& text, SkPaint* paint, SkPdfContext* pdfContext,
177 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);
edisonn@google.come50d9a12013-10-10 20:58:22 +0000183 printf("DrawText at (%f, %f)\n", SkScalarToDouble(point.x()),
184 SkScalarToDouble(point.y()));
edisonn@google.come57c62d2013-08-07 18:04:15 +0000185#endif // PDF_TRACE
edisonn@google.com3aa35552013-08-14 18:26:20 +0000186
187#ifdef PDF_TRACE_DRAWTEXT
188 SkPaint col;
189 col.setColor(SK_ColorMAGENTA);
edisonn@google.come50d9a12013-10-10 20:58:22 +0000190 SkRect rect = SkRect::MakeXYWH(SkDoubleToScalar(0.0),
191 SkDoubleToScalar(0.0),
192 SkDoubleToScalar(10.0),
193 SkDoubleToScalar(10.0));
edisonn@google.com3aa35552013-08-14 18:26:20 +0000194 canvas->save();
195 canvas->setMatrix(pdfContext->fGraphicsState.fMatrixTm);
196 canvas->drawRect(rect, col);
197 canvas->restore();
198#endif
edisonn@google.com6e49c342013-06-27 20:03:43 +0000199 double width = drawOneChar(text[i], paint, pdfContext, canvas);
edisonn@google.come50d9a12013-10-10 20:58:22 +0000200 pdfContext->fGraphicsState.fMatrixTm.preTranslate(SkDoubleToScalar(width),
201 SkDoubleToScalar(0.0));
edisonn@google.com1be794f2013-06-21 21:43:09 +0000202 }
203 }
204
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000205 void ToUnicode(const SkDecodedText& textIn, SkUnicodeText* textOut) const {
206 if (fToUnicode) {
207 textOut->text = new uint16_t[textIn.len];
208 textOut->len = textIn.len;
209 for (int i = 0; i < textIn.len; i++) {
210 textOut->text[i] = fToUnicode->fCMapEncoding[textIn.text[i]];
211 }
212 } else {
213 textOut->text = textIn.text;
214 textOut->len = textIn.len;
215 }
216 };
217
218 inline unsigned int ToUnicode(unsigned int ch) const {
edisonn@google.comf68aed32013-08-22 15:37:21 +0000219 if (fToUnicode && fToUnicode->fCMapEncoding) {
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000220 return fToUnicode->fCMapEncoding[ch];
221 } else {
222 return ch;
223 }
edisonn@google.com1be794f2013-06-21 21:43:09 +0000224 };
225
edisonn@google.com3aa35552013-08-14 18:26:20 +0000226 static SkPdfFont* fontFromPdfDictionary(SkPdfNativeDoc* doc, SkPdfFontDictionary* dict);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000227 static SkPdfFont* Default() {return fontFromName(NULL, NULL, "TimesNewRoman");}
edisonn@google.com1be794f2013-06-21 21:43:09 +0000228
edisonn@google.come50d9a12013-10-10 20:58:22 +0000229 static SkPdfType0Font* fontFromType0FontDictionary(SkPdfNativeDoc* doc,
230 SkPdfType0FontDictionary* dict);
231 static SkPdfType1Font* fontFromType1FontDictionary(SkPdfNativeDoc* doc,
232 SkPdfType1FontDictionary* dict);
233 static SkPdfType3Font* fontFromType3FontDictionary(SkPdfNativeDoc* doc,
234 SkPdfType3FontDictionary* dict);
235 static SkPdfTrueTypeFont* fontFromTrueTypeFontDictionary(SkPdfNativeDoc* doc,
236 SkPdfTrueTypeFontDictionary* dict);
237 static SkPdfMultiMasterFont* fontFromMultiMasterFontDictionary(
238 SkPdfNativeDoc* doc, SkPdfMultiMasterFontDictionary* dict);
edisonn@google.com1be794f2013-06-21 21:43:09 +0000239
edisonn@google.come50d9a12013-10-10 20:58:22 +0000240 static SkPdfFont* fontFromFontDescriptor(SkPdfNativeDoc* doc,
241 SkPdfFontDescriptorDictionary* fd,
242 bool loadFromName = true);
edisonn@google.com6e49c342013-06-27 20:03:43 +0000243
edisonn@google.com1be794f2013-06-21 21:43:09 +0000244public:
edisonn@google.come50d9a12013-10-10 20:58:22 +0000245 virtual double drawOneChar(unsigned int ch, SkPaint* paint, SkPdfContext* pdfContext,
246 SkCanvas* canvas) = 0;
edisonn@google.com1be794f2013-06-21 21:43:09 +0000247 virtual void afterWord(SkPaint* paint, SkMatrix* matrix) = 0;
edisonn@google.com571c70b2013-07-10 17:09:50 +0000248
249private:
edisonn@google.com3aa35552013-08-14 18:26:20 +0000250 static SkPdfFont* fontFromPdfDictionaryOnce(SkPdfNativeDoc* doc, SkPdfFontDictionary* dict);
edisonn@google.com1be794f2013-06-21 21:43:09 +0000251};
252
253class SkPdfStandardFont : public SkPdfFont {
254 SkTypeface* fTypeface;
255
256public:
257 SkPdfStandardFont(SkTypeface* typeface) : fTypeface(typeface) {}
258
259public:
edisonn@google.come50d9a12013-10-10 20:58:22 +0000260 virtual double drawOneChar(unsigned int ch, SkPaint* paint, SkPdfContext* pdfContext,
261 SkCanvas* canvas) {
edisonn@google.com1be794f2013-06-21 21:43:09 +0000262 paint->setTypeface(fTypeface);
263 paint->setTextEncoding(SkPaint::kUTF8_TextEncoding);
264
265 unsigned long ch4 = ch;
266 char utf8[10];
267 int len = SkUTF8_FromUnichar(ch4, utf8);
268
269 canvas->drawText(utf8, len, SkDoubleToScalar(0), SkDoubleToScalar(0), *paint);
270
271 SkScalar textWidth = paint->measureText(utf8, len);
edisonn@google.com6e49c342013-06-27 20:03:43 +0000272 return SkScalarToDouble(textWidth);
edisonn@google.com1be794f2013-06-21 21:43:09 +0000273 }
274
edisonn@google.com1be794f2013-06-21 21:43:09 +0000275 virtual void afterWord(SkPaint* paint, SkMatrix* matrix) {}
276};
277
edisonn@google.com1be794f2013-06-21 21:43:09 +0000278class SkPdfType0Font : public SkPdfFont {
edisonn@google.com1be794f2013-06-21 21:43:09 +0000279public:
edisonn@google.com3aa35552013-08-14 18:26:20 +0000280 SkPdfType0Font(SkPdfNativeDoc* doc, SkPdfType0FontDictionary* dict);
edisonn@google.com1be794f2013-06-21 21:43:09 +0000281
282public:
edisonn@google.com1be794f2013-06-21 21:43:09 +0000283
edisonn@google.come50d9a12013-10-10 20:58:22 +0000284 virtual double drawOneChar(unsigned int ch, SkPaint* paint, SkPdfContext* pdfContext,
285 SkCanvas* canvas) {
edisonn@google.com6e49c342013-06-27 20:03:43 +0000286 return fBaseFont->drawOneChar(ToUnicode(ch), paint, pdfContext, canvas);
edisonn@google.com1be794f2013-06-21 21:43:09 +0000287 }
288
289 virtual void afterWord(SkPaint* paint, SkMatrix* matrix) {
edisonn@google.com1be794f2013-06-21 21:43:09 +0000290 }
291};
292
edisonn@google.com1be794f2013-06-21 21:43:09 +0000293class SkPdfType1Font : public SkPdfFont {
294public:
edisonn@google.com3aa35552013-08-14 18:26:20 +0000295 SkPdfType1Font(SkPdfNativeDoc* doc, SkPdfType1FontDictionary* dict) {
edisonn@google.com6e49c342013-06-27 20:03:43 +0000296 if (dict->has_FontDescriptor()) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000297 fBaseFont = SkPdfFont::fontFromFontDescriptor(doc, dict->FontDescriptor(doc));
edisonn@google.com6e49c342013-06-27 20:03:43 +0000298 } else {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000299 fBaseFont = fontFromName(doc, dict, dict->BaseFont(doc).c_str());
edisonn@google.com6e49c342013-06-27 20:03:43 +0000300 }
edisonn@google.com3aa35552013-08-14 18:26:20 +0000301
302 if (dict->isEncodingAName(doc)) {
303 fEncoding = SkPdfEncoding::fromName(dict->getEncodingAsName(doc).c_str());
304 } else if (dict->isEncodingADictionary(doc)) {
305 //SkPdfDictionary* dictEnc = dict->getEncodingAsDictionary(doc);
306 }
307 dict->FontDescriptor(doc);
edisonn@google.com1be794f2013-06-21 21:43:09 +0000308 }
309
edisonn@google.com1be794f2013-06-21 21:43:09 +0000310public:
edisonn@google.come50d9a12013-10-10 20:58:22 +0000311 virtual double drawOneChar(unsigned int ch, SkPaint* paint, SkPdfContext* pdfContext,
312 SkCanvas* canvas) {
edisonn@google.com6e49c342013-06-27 20:03:43 +0000313 return fBaseFont->drawOneChar(ToUnicode(ch), paint, pdfContext, canvas);
edisonn@google.com1be794f2013-06-21 21:43:09 +0000314 }
315
316 virtual void afterWord(SkPaint* paint, SkMatrix* matrix) {
317
318 }
edisonn@google.com6e49c342013-06-27 20:03:43 +0000319};
edisonn@google.com1be794f2013-06-21 21:43:09 +0000320
edisonn@google.com6e49c342013-06-27 20:03:43 +0000321class SkPdfTrueTypeFont : public SkPdfType1Font {
edisonn@google.com1be794f2013-06-21 21:43:09 +0000322public:
edisonn@google.come50d9a12013-10-10 20:58:22 +0000323 SkPdfTrueTypeFont(SkPdfNativeDoc* doc, SkPdfTrueTypeFontDictionary* dict)
324 : SkPdfType1Font(doc, dict) {}
edisonn@google.com1be794f2013-06-21 21:43:09 +0000325};
326
edisonn@google.com6e49c342013-06-27 20:03:43 +0000327class SkPdfMultiMasterFont : public SkPdfType1Font {
edisonn@google.com1be794f2013-06-21 21:43:09 +0000328public:
edisonn@google.come50d9a12013-10-10 20:58:22 +0000329 SkPdfMultiMasterFont(SkPdfNativeDoc* doc, SkPdfMultiMasterFontDictionary* dict)
330 : SkPdfType1Font(doc, dict) {}
edisonn@google.com1be794f2013-06-21 21:43:09 +0000331};
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000332/*
333class CIDToGIDMap {
334 virtual unsigned int map(unsigned int cid) = 0;
335 static CIDToGIDMap* fromName(const char* name);
336};
337
338class CIDToGIDMap_Identity {
339 virtual unsigned int map(unsigned int cid) { return cid; }
340
341 static CIDToGIDMap_Identity* instance() {
342 static CIDToGIDMap_Identity* inst = new CIDToGIDMap_Identity();
343 return inst;
344 }
345};
346
347CIDToGIDMap* CIDToGIDMap::fromName(const char* name) {
348 // The only one supported right now is Identity
349 if (strcmp(name, "Identity") == 0) {
350 return CIDToGIDMap_Identity::instance();
351 }
352
353#ifdef PDF_TRACE
354 // TODO(edisonn): warning/report
355 printf("Unknown CIDToGIDMap: %s\n", name);
356#endif
357 return NULL;
358}
359CIDToGIDMap* fCidToGid;
360*/
edisonn@google.com1be794f2013-06-21 21:43:09 +0000361
362class SkPdfType3Font : public SkPdfFont {
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000363 struct Type3FontChar {
edisonn@google.com3aa35552013-08-14 18:26:20 +0000364 SkPdfNativeObject* fObj;
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000365 double fWidth;
366 };
367
368 SkPdfDictionary* fCharProcs;
369 SkPdfEncodingDictionary* fEncodingDict;
370 unsigned int fFirstChar;
371 unsigned int fLastChar;
372
373 SkRect fFontBBox;
374 SkMatrix fFonMatrix;
375
376 Type3FontChar* fChars;
377
edisonn@google.com1be794f2013-06-21 21:43:09 +0000378public:
edisonn@google.com3aa35552013-08-14 18:26:20 +0000379 SkPdfType3Font(SkPdfNativeDoc* parsed, SkPdfType3FontDictionary* dict) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000380 fBaseFont = fontFromName(parsed, dict, dict->BaseFont(parsed).c_str());
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000381
382 if (dict->has_Encoding()) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000383 if (dict->isEncodingAName(parsed)) {
384 fEncoding = SkPdfEncoding::fromName(dict->getEncodingAsName(parsed).c_str());
385 } else if (dict->isEncodingAEncodingdictionary(parsed)) {
edisonn@google.com2fd5d362013-07-23 19:43:48 +0000386 // No encoding.
387 fEncoding = SkPdfDefaultEncoding::instance();
edisonn@google.com571c70b2013-07-10 17:09:50 +0000388 fEncodingDict = dict->getEncodingAsEncodingdictionary(parsed);
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000389 }
390 }
391
392 // null?
edisonn@google.com571c70b2013-07-10 17:09:50 +0000393 fCharProcs = dict->CharProcs(parsed);
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000394
395 fToUnicode = NULL;
396 if (dict->has_ToUnicode()) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000397 fToUnicode = new SkPdfToUnicode(parsed, dict->ToUnicode(parsed));
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000398 }
399
edisonn@google.coma3356fc2013-07-10 18:20:06 +0000400 fFirstChar = (unsigned int)dict->FirstChar(parsed);
401 fLastChar = (unsigned int)dict->LastChar(parsed);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000402 fFonMatrix = dict->has_FontMatrix() ? dict->FontMatrix(parsed) : SkMatrix::I();
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000403
edisonn@google.com571c70b2013-07-10 17:09:50 +0000404 if (dict->has_FontBBox()) {
405 fFontBBox = dict->FontBBox(parsed);
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000406 }
407
408 fChars = new Type3FontChar[fLastChar - fFirstChar + 1];
409
410 memset(fChars, 0, sizeof(fChars[0]) * (fLastChar - fFirstChar + 1));
411
edisonn@google.com571c70b2013-07-10 17:09:50 +0000412 const SkPdfArray* widths = dict->Widths(parsed);
413 for (unsigned int i = 0 ; i < widths->size(); i++) {
edisonn@google.comac4bedc2013-07-25 21:40:23 +0000414 if ((fFirstChar + i) >= fFirstChar && (fFirstChar + i) <= fLastChar) {
415 fChars[i].fWidth = (*widths)[i]->numberValue();
416 } else {
417 // TODO(edisonn): report pdf corruption
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000418 }
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000419 }
420
edisonn@google.com571c70b2013-07-10 17:09:50 +0000421 const SkPdfArray* diffs = fEncodingDict->Differences(parsed);
422 unsigned int j = fFirstChar;
423 for (unsigned int i = 0 ; i < diffs->size(); i++) {
424 if ((*diffs)[i]->isInteger()) {
edisonn@google.coma3356fc2013-07-10 18:20:06 +0000425 j = (unsigned int)(*diffs)[i]->intValue();
edisonn@google.com571c70b2013-07-10 17:09:50 +0000426 } else if ((*diffs)[i]->isName()) {
edisonn@google.comac4bedc2013-07-25 21:40:23 +0000427 if (j >= fFirstChar && j <= fLastChar) {
428 fChars[j - fFirstChar].fObj = fCharProcs->get((*diffs)[i]);
429 } else {
430 // TODO(edisonn): report pdf corruption
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000431 }
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000432 j++;
433 } else {
edisonn@google.comac4bedc2013-07-25 21:40:23 +0000434 // TODO(edisonn): report bad pdf
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000435 }
436 }
edisonn@google.com1be794f2013-06-21 21:43:09 +0000437 }
438
439public:
edisonn@google.come50d9a12013-10-10 20:58:22 +0000440 virtual double drawOneChar(unsigned int ch, SkPaint* paint, SkPdfContext* pdfContext,
441 SkCanvas* canvas) {
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000442 if (ch < fFirstChar || ch > fLastChar || !fChars[ch - fFirstChar].fObj) {
edisonn@google.com6e49c342013-06-27 20:03:43 +0000443 return fBaseFont->drawOneChar(ToUnicode(ch), paint, pdfContext, canvas);
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000444 }
edisonn@google.com1be794f2013-06-21 21:43:09 +0000445
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000446#ifdef PDF_TRACE
447 printf("Type 3 char to unicode: %c\n", ToUnicode(ch));
448 if (ToUnicode(ch) == 'A') {
449 printf("break;\n");
450 }
451#endif
452
edisonn@google.com571c70b2013-07-10 17:09:50 +0000453 // TODO(edisonn): is it better to resolve the reference at load time, or now?
edisonn@google.come50d9a12013-10-10 20:58:22 +0000454 doType3Char(pdfContext,
455 canvas,
456 pdfContext->fPdfDoc->resolveReference(fChars[ch - fFirstChar].fObj),
457 fFontBBox,
458 fFonMatrix,
459 pdfContext->fGraphicsState.fCurFontSize);
edisonn@google.com1be794f2013-06-21 21:43:09 +0000460
edisonn@google.com6e49c342013-06-27 20:03:43 +0000461 // TODO(edisonn): verify/test translate code, not tested yet
edisonn@google.come50d9a12013-10-10 20:58:22 +0000462 pdfContext->fGraphicsState.fMatrixTm.preTranslate(
463 SkDoubleToScalar(pdfContext->fGraphicsState.fCurFontSize *
464 fChars[ch - fFirstChar].fWidth),
465 SkDoubleToScalar(0.0));
edisonn@google.com571c70b2013-07-10 17:09:50 +0000466 return fChars[ch - fFirstChar].fWidth;
edisonn@google.com1be794f2013-06-21 21:43:09 +0000467 }
468
edisonn@google.come50d9a12013-10-10 20:58:22 +0000469 virtual void afterWord(SkPaint* paint, SkMatrix* matrix) {}
edisonn@google.com1be794f2013-06-21 21:43:09 +0000470};
471
edisonn@google.comcf2cfa12013-08-21 16:31:37 +0000472#endif // SkPdfFont_DEFINED