blob: 85ce6512d9bd2e4e2e08af6d3e2556ac74e222b2 [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
edisonn@google.comd03c2c72013-10-11 18:26:45 +00008// TODO(edisonn): this file not commented much on purpose.
9// It will probably need heavy refactoring soon anyway to support all encodings, fonts and
10// proper text sizing and spacing
11
edisonn@google.comcf2cfa12013-08-21 16:31:37 +000012#ifndef SkPdfFont_DEFINED
13#define SkPdfFont_DEFINED
edisonn@google.com1be794f2013-06-21 21:43:09 +000014
edisonn@google.come50d9a12013-10-10 20:58:22 +000015#include "SkPdfGraphicsState.h"
edisonn@google.com1be794f2013-06-21 21:43:09 +000016#include "SkPdfHeaders_autogen.h"
edisonn@google.com3aac1f92013-07-02 22:42:53 +000017#include "SkPdfMapper_autogen.h"
edisonn@google.comb857a0c2013-06-25 20:45:40 +000018#include "SkPdfUtils.h"
edisonn@google.come50d9a12013-10-10 20:58:22 +000019#include "SkTypeface.h"
edisonn@google.com063d7072013-08-16 15:05:08 +000020#include "SkTDict.h"
edisonn@google.come50d9a12013-10-10 20:58:22 +000021#include "SkUtils.h"
edisonn@google.com1be794f2013-06-21 21:43:09 +000022
23class SkPdfType0Font;
24class SkPdfType1Font;
25class SkPdfType3Font;
26class SkPdfTrueTypeFont;
edisonn@google.com1be794f2013-06-21 21:43:09 +000027class SkPdfMultiMasterFont;
28class SkPdfFont;
29
edisonn@google.com1be794f2013-06-21 21:43:09 +000030struct SkPdfStandardFontEntry {
edisonn@google.com596d2e22013-07-10 17:44:55 +000031 // We don't own this pointer!
edisonn@google.com1be794f2013-06-21 21:43:09 +000032 const char* fName;
33 bool fIsBold;
34 bool fIsItalic;
edisonn@google.com596d2e22013-07-10 17:44:55 +000035 SkPdfStandardFontEntry()
36 : fName(NULL),
37 fIsBold(false),
38 fIsItalic(false) {}
39
40 SkPdfStandardFontEntry(const char* name, bool bold, bool italic)
41 : fName(name),
42 fIsBold(bold),
43 fIsItalic(italic) {}
edisonn@google.com1be794f2013-06-21 21:43:09 +000044};
45
edisonn@google.com063d7072013-08-16 15:05:08 +000046SkTDict<SkPdfStandardFontEntry>& getStandardFonts();
edisonn@google.com1be794f2013-06-21 21:43:09 +000047SkTypeface* SkTypefaceFromPdfStandardFont(const char* fontName, bool bold, bool italic);
edisonn@google.com3aa35552013-08-14 18:26:20 +000048SkPdfFont* fontFromName(SkPdfNativeDoc* doc, SkPdfNativeObject* obj, const char* fontName);
edisonn@google.com1be794f2013-06-21 21:43:09 +000049
50struct SkUnencodedText {
51 void* text;
52 int len;
53
54public:
edisonn@google.com3aac1f92013-07-02 22:42:53 +000055 SkUnencodedText(const SkPdfString* obj) {
56 text = (void*)obj->c_str();
edisonn@google.come878e722013-07-29 19:10:58 +000057 len = obj->lenstr();
edisonn@google.com1be794f2013-06-21 21:43:09 +000058 }
59};
60
61struct SkDecodedText {
62 uint16_t* text;
63 int len;
edisonn@google.comb857a0c2013-06-25 20:45:40 +000064public:
65 unsigned int operator[](int i) const { return text[i]; }
66 int size() const { return len; }
edisonn@google.com1be794f2013-06-21 21:43:09 +000067};
68
69struct SkUnicodeText {
70 uint16_t* text;
71 int len;
72
73public:
74 unsigned int operator[](int i) const { return text[i]; }
75 int size() const { return len; }
76};
77
78class SkPdfEncoding {
79public:
80 virtual bool decodeText(const SkUnencodedText& textIn, SkDecodedText* textOut) const = 0;
edisonn@google.comb857a0c2013-06-25 20:45:40 +000081 static SkPdfEncoding* fromName(const char* name);
edisonn@google.com1be794f2013-06-21 21:43:09 +000082};
83
edisonn@google.com063d7072013-08-16 15:05:08 +000084SkTDict<SkPdfEncoding*>& getStandardEncodings();
edisonn@google.comb857a0c2013-06-25 20:45:40 +000085
86class SkPdfToUnicode {
edisonn@google.com3aa35552013-08-14 18:26:20 +000087 SkPdfNativeDoc* fParsed;
edisonn@google.comb857a0c2013-06-25 20:45:40 +000088 // TODO(edisonn): hide public members
89public:
90 unsigned short* fCMapEncoding;
91 unsigned char* fCMapEncodingFlag;
92
edisonn@google.com3aa35552013-08-14 18:26:20 +000093 SkPdfToUnicode(SkPdfNativeDoc* parsed, SkPdfStream* stream);
edisonn@google.comb857a0c2013-06-25 20:45:40 +000094};
95
96
edisonn@google.com1be794f2013-06-21 21:43:09 +000097class SkPdfIdentityHEncoding : public SkPdfEncoding {
98public:
99 virtual bool decodeText(const SkUnencodedText& textIn, SkDecodedText* textOut) const {
100 // TODO(edisonn): SkASSERT(textIn.len % 2 == 0); or report error?
101
102 uint16_t* text = (uint16_t*)textIn.text;
103 textOut->text = new uint16_t[textIn.len / 2];
104 textOut->len = textIn.len / 2;
105
106 for (int i = 0; i < textOut->len; i++) {
107 textOut->text[i] = ((text[i] << 8) & 0xff00) | ((text[i] >> 8) & 0x00ff);
108 }
109
110 return true;
111 }
112
113 static SkPdfIdentityHEncoding* instance() {
114 static SkPdfIdentityHEncoding* inst = new SkPdfIdentityHEncoding();
115 return inst;
116 }
117};
118
edisonn@google.com6e49c342013-06-27 20:03:43 +0000119// TODO(edisonn): using this one when no encoding is specified
120class SkPdfDefaultEncoding : public SkPdfEncoding {
121public:
122 virtual bool decodeText(const SkUnencodedText& textIn, SkDecodedText* textOut) const {
123 // TODO(edisonn): SkASSERT(textIn.len % 2 == 0); or report error?
124
125 unsigned char* text = (unsigned char*)textIn.text;
126 textOut->text = new uint16_t[textIn.len];
127 textOut->len = textIn.len;
128
129 for (int i = 0; i < textOut->len; i++) {
130 textOut->text[i] = text[i];
131 }
132
133 return true;
134 }
135
136 static SkPdfDefaultEncoding* instance() {
137 static SkPdfDefaultEncoding* inst = new SkPdfDefaultEncoding();
138 return inst;
139 }
140};
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000141
142class SkPdfCIDToGIDMapIdentityEncoding : public SkPdfEncoding {
143public:
144 virtual bool decodeText(const SkUnencodedText& textIn, SkDecodedText* textOut) const {
145 // TODO(edisonn): SkASSERT(textIn.len % 2 == 0); or report error?
146
edisonn@google.com571c70b2013-07-10 17:09:50 +0000147 uint16_t* text = (uint16_t*)textIn.text;
148 textOut->text = new uint16_t[textIn.len / 2];
149 textOut->len = textIn.len / 2;
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000150
151 for (int i = 0; i < textOut->len; i++) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000152 textOut->text[i] = ((text[i] << 8) & 0xff00) | ((text[i] >> 8) & 0x00ff);
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000153 }
154
155 return true;
156 }
157
158 static SkPdfCIDToGIDMapIdentityEncoding* instance() {
159 static SkPdfCIDToGIDMapIdentityEncoding* inst = new SkPdfCIDToGIDMapIdentityEncoding();
160 return inst;
161 }
162};
163
edisonn@google.com1be794f2013-06-21 21:43:09 +0000164class SkPdfFont {
165public:
166 SkPdfFont* fBaseFont;
167 SkPdfEncoding* fEncoding;
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000168 SkPdfToUnicode* fToUnicode;
169
edisonn@google.com1be794f2013-06-21 21:43:09 +0000170
171public:
edisonn@google.com6e49c342013-06-27 20:03:43 +0000172 SkPdfFont() : fBaseFont(NULL), fEncoding(SkPdfDefaultEncoding::instance()), fToUnicode(NULL) {}
edisonn@google.com1be794f2013-06-21 21:43:09 +0000173
edisonn@google.com7ee12ca2013-08-05 18:18:06 +0000174 virtual ~SkPdfFont() {
175 // TODO(edisonn): NYI (will leak for now)
176 }
177
edisonn@google.com1be794f2013-06-21 21:43:09 +0000178 const SkPdfEncoding* encoding() const {return fEncoding;}
179
edisonn@google.come50d9a12013-10-10 20:58:22 +0000180 void drawText(const SkDecodedText& text, SkPaint* paint, SkPdfContext* pdfContext,
181 SkCanvas* canvas) {
edisonn@google.com1be794f2013-06-21 21:43:09 +0000182 for (int i = 0 ; i < text.size(); i++) {
edisonn@google.come57c62d2013-08-07 18:04:15 +0000183 canvas->setMatrix(pdfContext->fGraphicsState.fMatrixTm);
184#ifdef PDF_TRACE
185 SkPoint point = SkPoint::Make(SkDoubleToScalar(0), SkDoubleToScalar(0));
186 pdfContext->fGraphicsState.fMatrixTm.mapPoints(&point, 1);
edisonn@google.come50d9a12013-10-10 20:58:22 +0000187 printf("DrawText at (%f, %f)\n", SkScalarToDouble(point.x()),
188 SkScalarToDouble(point.y()));
edisonn@google.come57c62d2013-08-07 18:04:15 +0000189#endif // PDF_TRACE
edisonn@google.com3aa35552013-08-14 18:26:20 +0000190
191#ifdef PDF_TRACE_DRAWTEXT
192 SkPaint col;
193 col.setColor(SK_ColorMAGENTA);
edisonn@google.come50d9a12013-10-10 20:58:22 +0000194 SkRect rect = SkRect::MakeXYWH(SkDoubleToScalar(0.0),
195 SkDoubleToScalar(0.0),
196 SkDoubleToScalar(10.0),
197 SkDoubleToScalar(10.0));
edisonn@google.com3aa35552013-08-14 18:26:20 +0000198 canvas->save();
199 canvas->setMatrix(pdfContext->fGraphicsState.fMatrixTm);
200 canvas->drawRect(rect, col);
201 canvas->restore();
202#endif
edisonn@google.com6e49c342013-06-27 20:03:43 +0000203 double width = drawOneChar(text[i], paint, pdfContext, canvas);
edisonn@google.come50d9a12013-10-10 20:58:22 +0000204 pdfContext->fGraphicsState.fMatrixTm.preTranslate(SkDoubleToScalar(width),
205 SkDoubleToScalar(0.0));
edisonn@google.com1be794f2013-06-21 21:43:09 +0000206 }
207 }
208
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000209 void ToUnicode(const SkDecodedText& textIn, SkUnicodeText* textOut) const {
210 if (fToUnicode) {
211 textOut->text = new uint16_t[textIn.len];
212 textOut->len = textIn.len;
213 for (int i = 0; i < textIn.len; i++) {
214 textOut->text[i] = fToUnicode->fCMapEncoding[textIn.text[i]];
215 }
216 } else {
217 textOut->text = textIn.text;
218 textOut->len = textIn.len;
219 }
220 };
221
222 inline unsigned int ToUnicode(unsigned int ch) const {
edisonn@google.comf68aed32013-08-22 15:37:21 +0000223 if (fToUnicode && fToUnicode->fCMapEncoding) {
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000224 return fToUnicode->fCMapEncoding[ch];
225 } else {
226 return ch;
227 }
edisonn@google.com1be794f2013-06-21 21:43:09 +0000228 };
229
edisonn@google.com3aa35552013-08-14 18:26:20 +0000230 static SkPdfFont* fontFromPdfDictionary(SkPdfNativeDoc* doc, SkPdfFontDictionary* dict);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000231 static SkPdfFont* Default() {return fontFromName(NULL, NULL, "TimesNewRoman");}
edisonn@google.com1be794f2013-06-21 21:43:09 +0000232
edisonn@google.come50d9a12013-10-10 20:58:22 +0000233 static SkPdfType0Font* fontFromType0FontDictionary(SkPdfNativeDoc* doc,
234 SkPdfType0FontDictionary* dict);
235 static SkPdfType1Font* fontFromType1FontDictionary(SkPdfNativeDoc* doc,
236 SkPdfType1FontDictionary* dict);
237 static SkPdfType3Font* fontFromType3FontDictionary(SkPdfNativeDoc* doc,
238 SkPdfType3FontDictionary* dict);
239 static SkPdfTrueTypeFont* fontFromTrueTypeFontDictionary(SkPdfNativeDoc* doc,
240 SkPdfTrueTypeFontDictionary* dict);
241 static SkPdfMultiMasterFont* fontFromMultiMasterFontDictionary(
242 SkPdfNativeDoc* doc, SkPdfMultiMasterFontDictionary* dict);
edisonn@google.com1be794f2013-06-21 21:43:09 +0000243
edisonn@google.come50d9a12013-10-10 20:58:22 +0000244 static SkPdfFont* fontFromFontDescriptor(SkPdfNativeDoc* doc,
245 SkPdfFontDescriptorDictionary* fd,
246 bool loadFromName = true);
edisonn@google.com6e49c342013-06-27 20:03:43 +0000247
edisonn@google.com1be794f2013-06-21 21:43:09 +0000248public:
edisonn@google.come50d9a12013-10-10 20:58:22 +0000249 virtual double drawOneChar(unsigned int ch, SkPaint* paint, SkPdfContext* pdfContext,
250 SkCanvas* canvas) = 0;
edisonn@google.com1be794f2013-06-21 21:43:09 +0000251 virtual void afterWord(SkPaint* paint, SkMatrix* matrix) = 0;
edisonn@google.com571c70b2013-07-10 17:09:50 +0000252
253private:
edisonn@google.com3aa35552013-08-14 18:26:20 +0000254 static SkPdfFont* fontFromPdfDictionaryOnce(SkPdfNativeDoc* doc, SkPdfFontDictionary* dict);
edisonn@google.com1be794f2013-06-21 21:43:09 +0000255};
256
257class SkPdfStandardFont : public SkPdfFont {
258 SkTypeface* fTypeface;
259
260public:
261 SkPdfStandardFont(SkTypeface* typeface) : fTypeface(typeface) {}
262
263public:
edisonn@google.come50d9a12013-10-10 20:58:22 +0000264 virtual double drawOneChar(unsigned int ch, SkPaint* paint, SkPdfContext* pdfContext,
265 SkCanvas* canvas) {
edisonn@google.com1be794f2013-06-21 21:43:09 +0000266 paint->setTypeface(fTypeface);
267 paint->setTextEncoding(SkPaint::kUTF8_TextEncoding);
268
269 unsigned long ch4 = ch;
270 char utf8[10];
271 int len = SkUTF8_FromUnichar(ch4, utf8);
272
273 canvas->drawText(utf8, len, SkDoubleToScalar(0), SkDoubleToScalar(0), *paint);
274
275 SkScalar textWidth = paint->measureText(utf8, len);
edisonn@google.com6e49c342013-06-27 20:03:43 +0000276 return SkScalarToDouble(textWidth);
edisonn@google.com1be794f2013-06-21 21:43:09 +0000277 }
278
edisonn@google.com1be794f2013-06-21 21:43:09 +0000279 virtual void afterWord(SkPaint* paint, SkMatrix* matrix) {}
280};
281
edisonn@google.com1be794f2013-06-21 21:43:09 +0000282class SkPdfType0Font : public SkPdfFont {
edisonn@google.com1be794f2013-06-21 21:43:09 +0000283public:
edisonn@google.com3aa35552013-08-14 18:26:20 +0000284 SkPdfType0Font(SkPdfNativeDoc* doc, SkPdfType0FontDictionary* dict);
edisonn@google.com1be794f2013-06-21 21:43:09 +0000285
286public:
edisonn@google.com1be794f2013-06-21 21:43:09 +0000287
edisonn@google.come50d9a12013-10-10 20:58:22 +0000288 virtual double drawOneChar(unsigned int ch, SkPaint* paint, SkPdfContext* pdfContext,
289 SkCanvas* canvas) {
edisonn@google.com6e49c342013-06-27 20:03:43 +0000290 return fBaseFont->drawOneChar(ToUnicode(ch), paint, pdfContext, canvas);
edisonn@google.com1be794f2013-06-21 21:43:09 +0000291 }
292
293 virtual void afterWord(SkPaint* paint, SkMatrix* matrix) {
edisonn@google.com1be794f2013-06-21 21:43:09 +0000294 }
295};
296
edisonn@google.com1be794f2013-06-21 21:43:09 +0000297class SkPdfType1Font : public SkPdfFont {
298public:
edisonn@google.com3aa35552013-08-14 18:26:20 +0000299 SkPdfType1Font(SkPdfNativeDoc* doc, SkPdfType1FontDictionary* dict) {
edisonn@google.com6e49c342013-06-27 20:03:43 +0000300 if (dict->has_FontDescriptor()) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000301 fBaseFont = SkPdfFont::fontFromFontDescriptor(doc, dict->FontDescriptor(doc));
edisonn@google.com6e49c342013-06-27 20:03:43 +0000302 } else {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000303 fBaseFont = fontFromName(doc, dict, dict->BaseFont(doc).c_str());
edisonn@google.com6e49c342013-06-27 20:03:43 +0000304 }
edisonn@google.com3aa35552013-08-14 18:26:20 +0000305
306 if (dict->isEncodingAName(doc)) {
307 fEncoding = SkPdfEncoding::fromName(dict->getEncodingAsName(doc).c_str());
308 } else if (dict->isEncodingADictionary(doc)) {
309 //SkPdfDictionary* dictEnc = dict->getEncodingAsDictionary(doc);
310 }
311 dict->FontDescriptor(doc);
edisonn@google.com1be794f2013-06-21 21:43:09 +0000312 }
313
edisonn@google.com1be794f2013-06-21 21:43:09 +0000314public:
edisonn@google.come50d9a12013-10-10 20:58:22 +0000315 virtual double drawOneChar(unsigned int ch, SkPaint* paint, SkPdfContext* pdfContext,
316 SkCanvas* canvas) {
edisonn@google.com6e49c342013-06-27 20:03:43 +0000317 return fBaseFont->drawOneChar(ToUnicode(ch), paint, pdfContext, canvas);
edisonn@google.com1be794f2013-06-21 21:43:09 +0000318 }
319
320 virtual void afterWord(SkPaint* paint, SkMatrix* matrix) {
321
322 }
edisonn@google.com6e49c342013-06-27 20:03:43 +0000323};
edisonn@google.com1be794f2013-06-21 21:43:09 +0000324
edisonn@google.com6e49c342013-06-27 20:03:43 +0000325class SkPdfTrueTypeFont : public SkPdfType1Font {
edisonn@google.com1be794f2013-06-21 21:43:09 +0000326public:
edisonn@google.come50d9a12013-10-10 20:58:22 +0000327 SkPdfTrueTypeFont(SkPdfNativeDoc* doc, SkPdfTrueTypeFontDictionary* dict)
328 : SkPdfType1Font(doc, dict) {}
edisonn@google.com1be794f2013-06-21 21:43:09 +0000329};
330
edisonn@google.com6e49c342013-06-27 20:03:43 +0000331class SkPdfMultiMasterFont : public SkPdfType1Font {
edisonn@google.com1be794f2013-06-21 21:43:09 +0000332public:
edisonn@google.come50d9a12013-10-10 20:58:22 +0000333 SkPdfMultiMasterFont(SkPdfNativeDoc* doc, SkPdfMultiMasterFontDictionary* dict)
334 : SkPdfType1Font(doc, dict) {}
edisonn@google.com1be794f2013-06-21 21:43:09 +0000335};
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000336/*
337class CIDToGIDMap {
338 virtual unsigned int map(unsigned int cid) = 0;
339 static CIDToGIDMap* fromName(const char* name);
340};
341
342class CIDToGIDMap_Identity {
343 virtual unsigned int map(unsigned int cid) { return cid; }
344
345 static CIDToGIDMap_Identity* instance() {
346 static CIDToGIDMap_Identity* inst = new CIDToGIDMap_Identity();
347 return inst;
348 }
349};
350
351CIDToGIDMap* CIDToGIDMap::fromName(const char* name) {
352 // The only one supported right now is Identity
353 if (strcmp(name, "Identity") == 0) {
354 return CIDToGIDMap_Identity::instance();
355 }
356
357#ifdef PDF_TRACE
358 // TODO(edisonn): warning/report
359 printf("Unknown CIDToGIDMap: %s\n", name);
360#endif
361 return NULL;
362}
363CIDToGIDMap* fCidToGid;
364*/
edisonn@google.com1be794f2013-06-21 21:43:09 +0000365
366class SkPdfType3Font : public SkPdfFont {
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000367 struct Type3FontChar {
edisonn@google.com3aa35552013-08-14 18:26:20 +0000368 SkPdfNativeObject* fObj;
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000369 double fWidth;
370 };
371
372 SkPdfDictionary* fCharProcs;
373 SkPdfEncodingDictionary* fEncodingDict;
374 unsigned int fFirstChar;
375 unsigned int fLastChar;
376
377 SkRect fFontBBox;
378 SkMatrix fFonMatrix;
379
380 Type3FontChar* fChars;
381
edisonn@google.com1be794f2013-06-21 21:43:09 +0000382public:
edisonn@google.com3aa35552013-08-14 18:26:20 +0000383 SkPdfType3Font(SkPdfNativeDoc* parsed, SkPdfType3FontDictionary* dict) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000384 fBaseFont = fontFromName(parsed, dict, dict->BaseFont(parsed).c_str());
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000385
386 if (dict->has_Encoding()) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000387 if (dict->isEncodingAName(parsed)) {
388 fEncoding = SkPdfEncoding::fromName(dict->getEncodingAsName(parsed).c_str());
389 } else if (dict->isEncodingAEncodingdictionary(parsed)) {
edisonn@google.com2fd5d362013-07-23 19:43:48 +0000390 // No encoding.
391 fEncoding = SkPdfDefaultEncoding::instance();
edisonn@google.com571c70b2013-07-10 17:09:50 +0000392 fEncodingDict = dict->getEncodingAsEncodingdictionary(parsed);
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000393 }
394 }
395
396 // null?
edisonn@google.com571c70b2013-07-10 17:09:50 +0000397 fCharProcs = dict->CharProcs(parsed);
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000398
399 fToUnicode = NULL;
400 if (dict->has_ToUnicode()) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000401 fToUnicode = new SkPdfToUnicode(parsed, dict->ToUnicode(parsed));
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000402 }
403
edisonn@google.coma3356fc2013-07-10 18:20:06 +0000404 fFirstChar = (unsigned int)dict->FirstChar(parsed);
405 fLastChar = (unsigned int)dict->LastChar(parsed);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000406 fFonMatrix = dict->has_FontMatrix() ? dict->FontMatrix(parsed) : SkMatrix::I();
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000407
edisonn@google.com571c70b2013-07-10 17:09:50 +0000408 if (dict->has_FontBBox()) {
409 fFontBBox = dict->FontBBox(parsed);
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000410 }
411
412 fChars = new Type3FontChar[fLastChar - fFirstChar + 1];
413
414 memset(fChars, 0, sizeof(fChars[0]) * (fLastChar - fFirstChar + 1));
415
edisonn@google.com571c70b2013-07-10 17:09:50 +0000416 const SkPdfArray* widths = dict->Widths(parsed);
417 for (unsigned int i = 0 ; i < widths->size(); i++) {
edisonn@google.comac4bedc2013-07-25 21:40:23 +0000418 if ((fFirstChar + i) >= fFirstChar && (fFirstChar + i) <= fLastChar) {
419 fChars[i].fWidth = (*widths)[i]->numberValue();
420 } else {
421 // TODO(edisonn): report pdf corruption
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000422 }
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000423 }
424
edisonn@google.com571c70b2013-07-10 17:09:50 +0000425 const SkPdfArray* diffs = fEncodingDict->Differences(parsed);
426 unsigned int j = fFirstChar;
427 for (unsigned int i = 0 ; i < diffs->size(); i++) {
428 if ((*diffs)[i]->isInteger()) {
edisonn@google.coma3356fc2013-07-10 18:20:06 +0000429 j = (unsigned int)(*diffs)[i]->intValue();
edisonn@google.com571c70b2013-07-10 17:09:50 +0000430 } else if ((*diffs)[i]->isName()) {
edisonn@google.comac4bedc2013-07-25 21:40:23 +0000431 if (j >= fFirstChar && j <= fLastChar) {
432 fChars[j - fFirstChar].fObj = fCharProcs->get((*diffs)[i]);
433 } else {
434 // TODO(edisonn): report pdf corruption
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000435 }
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000436 j++;
437 } else {
edisonn@google.comac4bedc2013-07-25 21:40:23 +0000438 // TODO(edisonn): report bad pdf
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000439 }
440 }
edisonn@google.com1be794f2013-06-21 21:43:09 +0000441 }
442
443public:
edisonn@google.come50d9a12013-10-10 20:58:22 +0000444 virtual double drawOneChar(unsigned int ch, SkPaint* paint, SkPdfContext* pdfContext,
445 SkCanvas* canvas) {
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000446 if (ch < fFirstChar || ch > fLastChar || !fChars[ch - fFirstChar].fObj) {
edisonn@google.com6e49c342013-06-27 20:03:43 +0000447 return fBaseFont->drawOneChar(ToUnicode(ch), paint, pdfContext, canvas);
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000448 }
edisonn@google.com1be794f2013-06-21 21:43:09 +0000449
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000450#ifdef PDF_TRACE
451 printf("Type 3 char to unicode: %c\n", ToUnicode(ch));
452 if (ToUnicode(ch) == 'A') {
453 printf("break;\n");
454 }
455#endif
456
edisonn@google.com571c70b2013-07-10 17:09:50 +0000457 // TODO(edisonn): is it better to resolve the reference at load time, or now?
edisonn@google.come50d9a12013-10-10 20:58:22 +0000458 doType3Char(pdfContext,
459 canvas,
460 pdfContext->fPdfDoc->resolveReference(fChars[ch - fFirstChar].fObj),
461 fFontBBox,
462 fFonMatrix,
463 pdfContext->fGraphicsState.fCurFontSize);
edisonn@google.com1be794f2013-06-21 21:43:09 +0000464
edisonn@google.com6e49c342013-06-27 20:03:43 +0000465 // TODO(edisonn): verify/test translate code, not tested yet
edisonn@google.come50d9a12013-10-10 20:58:22 +0000466 pdfContext->fGraphicsState.fMatrixTm.preTranslate(
467 SkDoubleToScalar(pdfContext->fGraphicsState.fCurFontSize *
468 fChars[ch - fFirstChar].fWidth),
469 SkDoubleToScalar(0.0));
edisonn@google.com571c70b2013-07-10 17:09:50 +0000470 return fChars[ch - fFirstChar].fWidth;
edisonn@google.com1be794f2013-06-21 21:43:09 +0000471 }
472
edisonn@google.come50d9a12013-10-10 20:58:22 +0000473 virtual void afterWord(SkPaint* paint, SkMatrix* matrix) {}
edisonn@google.com1be794f2013-06-21 21:43:09 +0000474};
475
edisonn@google.comcf2cfa12013-08-21 16:31:37 +0000476#endif // SkPdfFont_DEFINED