blob: a46e31c645ea8c78eb6998777d4f2bf2a2329e3a [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
scroggo@google.comd9067022013-11-20 22:33:39 +000015#include "SkPdfContext.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();
scroggo@google.com5f008652013-12-02 20:58:12 +000057 len = (int) 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:
mtklein@google.com9615f8d2013-11-20 14:29:51 +000080 virtual ~SkPdfEncoding() {}
edisonn@google.com1be794f2013-06-21 21:43:09 +000081 virtual bool decodeText(const SkUnencodedText& textIn, SkDecodedText* textOut) const = 0;
edisonn@google.comb857a0c2013-06-25 20:45:40 +000082 static SkPdfEncoding* fromName(const char* name);
edisonn@google.com1be794f2013-06-21 21:43:09 +000083};
84
edisonn@google.com063d7072013-08-16 15:05:08 +000085SkTDict<SkPdfEncoding*>& getStandardEncodings();
edisonn@google.comb857a0c2013-06-25 20:45:40 +000086
87class SkPdfToUnicode {
edisonn@google.com3aa35552013-08-14 18:26:20 +000088 SkPdfNativeDoc* fParsed;
edisonn@google.comb857a0c2013-06-25 20:45:40 +000089 // TODO(edisonn): hide public members
90public:
91 unsigned short* fCMapEncoding;
92 unsigned char* fCMapEncodingFlag;
93
edisonn@google.com3aa35552013-08-14 18:26:20 +000094 SkPdfToUnicode(SkPdfNativeDoc* parsed, SkPdfStream* stream);
edisonn@google.comb857a0c2013-06-25 20:45:40 +000095};
96
97
edisonn@google.com1be794f2013-06-21 21:43:09 +000098class SkPdfIdentityHEncoding : public SkPdfEncoding {
99public:
mtklein@google.com9615f8d2013-11-20 14:29:51 +0000100 virtual ~SkPdfIdentityHEncoding() {}
edisonn@google.com1be794f2013-06-21 21:43:09 +0000101 virtual bool decodeText(const SkUnencodedText& textIn, SkDecodedText* textOut) const {
102 // TODO(edisonn): SkASSERT(textIn.len % 2 == 0); or report error?
103
104 uint16_t* text = (uint16_t*)textIn.text;
105 textOut->text = new uint16_t[textIn.len / 2];
106 textOut->len = textIn.len / 2;
107
108 for (int i = 0; i < textOut->len; i++) {
109 textOut->text[i] = ((text[i] << 8) & 0xff00) | ((text[i] >> 8) & 0x00ff);
110 }
111
112 return true;
113 }
114
115 static SkPdfIdentityHEncoding* instance() {
116 static SkPdfIdentityHEncoding* inst = new SkPdfIdentityHEncoding();
117 return inst;
118 }
119};
120
edisonn@google.com6e49c342013-06-27 20:03:43 +0000121// TODO(edisonn): using this one when no encoding is specified
122class SkPdfDefaultEncoding : public SkPdfEncoding {
123public:
mtklein@google.com9615f8d2013-11-20 14:29:51 +0000124 virtual ~SkPdfDefaultEncoding() {}
edisonn@google.com6e49c342013-06-27 20:03:43 +0000125 virtual bool decodeText(const SkUnencodedText& textIn, SkDecodedText* textOut) const {
126 // TODO(edisonn): SkASSERT(textIn.len % 2 == 0); or report error?
127
128 unsigned char* text = (unsigned char*)textIn.text;
129 textOut->text = new uint16_t[textIn.len];
130 textOut->len = textIn.len;
131
132 for (int i = 0; i < textOut->len; i++) {
133 textOut->text[i] = text[i];
134 }
135
136 return true;
137 }
138
139 static SkPdfDefaultEncoding* instance() {
140 static SkPdfDefaultEncoding* inst = new SkPdfDefaultEncoding();
141 return inst;
142 }
143};
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000144
145class SkPdfCIDToGIDMapIdentityEncoding : public SkPdfEncoding {
146public:
mtklein@google.com9615f8d2013-11-20 14:29:51 +0000147 virtual ~SkPdfCIDToGIDMapIdentityEncoding() {}
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000148 virtual bool decodeText(const SkUnencodedText& textIn, SkDecodedText* textOut) const {
149 // TODO(edisonn): SkASSERT(textIn.len % 2 == 0); or report error?
150
edisonn@google.com571c70b2013-07-10 17:09:50 +0000151 uint16_t* text = (uint16_t*)textIn.text;
152 textOut->text = new uint16_t[textIn.len / 2];
153 textOut->len = textIn.len / 2;
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000154
155 for (int i = 0; i < textOut->len; i++) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000156 textOut->text[i] = ((text[i] << 8) & 0xff00) | ((text[i] >> 8) & 0x00ff);
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000157 }
158
159 return true;
160 }
161
162 static SkPdfCIDToGIDMapIdentityEncoding* instance() {
163 static SkPdfCIDToGIDMapIdentityEncoding* inst = new SkPdfCIDToGIDMapIdentityEncoding();
164 return inst;
165 }
166};
167
edisonn@google.com1be794f2013-06-21 21:43:09 +0000168class SkPdfFont {
169public:
170 SkPdfFont* fBaseFont;
171 SkPdfEncoding* fEncoding;
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000172 SkPdfToUnicode* fToUnicode;
173
edisonn@google.com1be794f2013-06-21 21:43:09 +0000174
175public:
edisonn@google.com6e49c342013-06-27 20:03:43 +0000176 SkPdfFont() : fBaseFont(NULL), fEncoding(SkPdfDefaultEncoding::instance()), fToUnicode(NULL) {}
edisonn@google.com1be794f2013-06-21 21:43:09 +0000177
edisonn@google.com7ee12ca2013-08-05 18:18:06 +0000178 virtual ~SkPdfFont() {
179 // TODO(edisonn): NYI (will leak for now)
180 }
181
edisonn@google.com1be794f2013-06-21 21:43:09 +0000182 const SkPdfEncoding* encoding() const {return fEncoding;}
183
edisonn@google.come50d9a12013-10-10 20:58:22 +0000184 void drawText(const SkDecodedText& text, SkPaint* paint, SkPdfContext* pdfContext,
185 SkCanvas* canvas) {
edisonn@google.com1be794f2013-06-21 21:43:09 +0000186 for (int i = 0 ; i < text.size(); i++) {
edisonn@google.come57c62d2013-08-07 18:04:15 +0000187 canvas->setMatrix(pdfContext->fGraphicsState.fMatrixTm);
188#ifdef PDF_TRACE
189 SkPoint point = SkPoint::Make(SkDoubleToScalar(0), SkDoubleToScalar(0));
190 pdfContext->fGraphicsState.fMatrixTm.mapPoints(&point, 1);
edisonn@google.come50d9a12013-10-10 20:58:22 +0000191 printf("DrawText at (%f, %f)\n", SkScalarToDouble(point.x()),
192 SkScalarToDouble(point.y()));
edisonn@google.come57c62d2013-08-07 18:04:15 +0000193#endif // PDF_TRACE
edisonn@google.com3aa35552013-08-14 18:26:20 +0000194
195#ifdef PDF_TRACE_DRAWTEXT
196 SkPaint col;
197 col.setColor(SK_ColorMAGENTA);
edisonn@google.come50d9a12013-10-10 20:58:22 +0000198 SkRect rect = SkRect::MakeXYWH(SkDoubleToScalar(0.0),
199 SkDoubleToScalar(0.0),
200 SkDoubleToScalar(10.0),
201 SkDoubleToScalar(10.0));
edisonn@google.com3aa35552013-08-14 18:26:20 +0000202 canvas->save();
203 canvas->setMatrix(pdfContext->fGraphicsState.fMatrixTm);
204 canvas->drawRect(rect, col);
205 canvas->restore();
206#endif
edisonn@google.com6e49c342013-06-27 20:03:43 +0000207 double width = drawOneChar(text[i], paint, pdfContext, canvas);
edisonn@google.come50d9a12013-10-10 20:58:22 +0000208 pdfContext->fGraphicsState.fMatrixTm.preTranslate(SkDoubleToScalar(width),
209 SkDoubleToScalar(0.0));
edisonn@google.com1be794f2013-06-21 21:43:09 +0000210 }
211 }
212
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000213 void ToUnicode(const SkDecodedText& textIn, SkUnicodeText* textOut) const {
214 if (fToUnicode) {
215 textOut->text = new uint16_t[textIn.len];
216 textOut->len = textIn.len;
217 for (int i = 0; i < textIn.len; i++) {
218 textOut->text[i] = fToUnicode->fCMapEncoding[textIn.text[i]];
219 }
220 } else {
221 textOut->text = textIn.text;
222 textOut->len = textIn.len;
223 }
224 };
225
226 inline unsigned int ToUnicode(unsigned int ch) const {
edisonn@google.comf68aed32013-08-22 15:37:21 +0000227 if (fToUnicode && fToUnicode->fCMapEncoding) {
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000228 return fToUnicode->fCMapEncoding[ch];
229 } else {
230 return ch;
231 }
edisonn@google.com1be794f2013-06-21 21:43:09 +0000232 };
233
edisonn@google.com3aa35552013-08-14 18:26:20 +0000234 static SkPdfFont* fontFromPdfDictionary(SkPdfNativeDoc* doc, SkPdfFontDictionary* dict);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000235 static SkPdfFont* Default() {return fontFromName(NULL, NULL, "TimesNewRoman");}
edisonn@google.com1be794f2013-06-21 21:43:09 +0000236
edisonn@google.come50d9a12013-10-10 20:58:22 +0000237 static SkPdfType0Font* fontFromType0FontDictionary(SkPdfNativeDoc* doc,
238 SkPdfType0FontDictionary* dict);
239 static SkPdfType1Font* fontFromType1FontDictionary(SkPdfNativeDoc* doc,
240 SkPdfType1FontDictionary* dict);
241 static SkPdfType3Font* fontFromType3FontDictionary(SkPdfNativeDoc* doc,
242 SkPdfType3FontDictionary* dict);
243 static SkPdfTrueTypeFont* fontFromTrueTypeFontDictionary(SkPdfNativeDoc* doc,
244 SkPdfTrueTypeFontDictionary* dict);
245 static SkPdfMultiMasterFont* fontFromMultiMasterFontDictionary(
246 SkPdfNativeDoc* doc, SkPdfMultiMasterFontDictionary* dict);
edisonn@google.com1be794f2013-06-21 21:43:09 +0000247
edisonn@google.come50d9a12013-10-10 20:58:22 +0000248 static SkPdfFont* fontFromFontDescriptor(SkPdfNativeDoc* doc,
249 SkPdfFontDescriptorDictionary* fd,
250 bool loadFromName = true);
edisonn@google.com6e49c342013-06-27 20:03:43 +0000251
edisonn@google.com1be794f2013-06-21 21:43:09 +0000252public:
edisonn@google.come50d9a12013-10-10 20:58:22 +0000253 virtual double drawOneChar(unsigned int ch, SkPaint* paint, SkPdfContext* pdfContext,
254 SkCanvas* canvas) = 0;
edisonn@google.com1be794f2013-06-21 21:43:09 +0000255 virtual void afterWord(SkPaint* paint, SkMatrix* matrix) = 0;
edisonn@google.com571c70b2013-07-10 17:09:50 +0000256
257private:
edisonn@google.com3aa35552013-08-14 18:26:20 +0000258 static SkPdfFont* fontFromPdfDictionaryOnce(SkPdfNativeDoc* doc, SkPdfFontDictionary* dict);
edisonn@google.com1be794f2013-06-21 21:43:09 +0000259};
260
261class SkPdfStandardFont : public SkPdfFont {
262 SkTypeface* fTypeface;
263
264public:
265 SkPdfStandardFont(SkTypeface* typeface) : fTypeface(typeface) {}
266
267public:
edisonn@google.come50d9a12013-10-10 20:58:22 +0000268 virtual double drawOneChar(unsigned int ch, SkPaint* paint, SkPdfContext* pdfContext,
269 SkCanvas* canvas) {
edisonn@google.com1be794f2013-06-21 21:43:09 +0000270 paint->setTypeface(fTypeface);
271 paint->setTextEncoding(SkPaint::kUTF8_TextEncoding);
272
273 unsigned long ch4 = ch;
274 char utf8[10];
scroggo@google.com5f008652013-12-02 20:58:12 +0000275 size_t len = SkUTF8_FromUnichar((SkUnichar) ch4, utf8);
edisonn@google.com1be794f2013-06-21 21:43:09 +0000276
277 canvas->drawText(utf8, len, SkDoubleToScalar(0), SkDoubleToScalar(0), *paint);
278
279 SkScalar textWidth = paint->measureText(utf8, len);
edisonn@google.com6e49c342013-06-27 20:03:43 +0000280 return SkScalarToDouble(textWidth);
edisonn@google.com1be794f2013-06-21 21:43:09 +0000281 }
282
edisonn@google.com1be794f2013-06-21 21:43:09 +0000283 virtual void afterWord(SkPaint* paint, SkMatrix* matrix) {}
284};
285
edisonn@google.com1be794f2013-06-21 21:43:09 +0000286class SkPdfType0Font : public SkPdfFont {
edisonn@google.com1be794f2013-06-21 21:43:09 +0000287public:
edisonn@google.com3aa35552013-08-14 18:26:20 +0000288 SkPdfType0Font(SkPdfNativeDoc* doc, SkPdfType0FontDictionary* dict);
edisonn@google.com1be794f2013-06-21 21:43:09 +0000289
290public:
edisonn@google.com1be794f2013-06-21 21:43:09 +0000291
edisonn@google.come50d9a12013-10-10 20:58:22 +0000292 virtual double drawOneChar(unsigned int ch, SkPaint* paint, SkPdfContext* pdfContext,
293 SkCanvas* canvas) {
edisonn@google.com6e49c342013-06-27 20:03:43 +0000294 return fBaseFont->drawOneChar(ToUnicode(ch), paint, pdfContext, canvas);
edisonn@google.com1be794f2013-06-21 21:43:09 +0000295 }
296
297 virtual void afterWord(SkPaint* paint, SkMatrix* matrix) {
edisonn@google.com1be794f2013-06-21 21:43:09 +0000298 }
299};
300
edisonn@google.com1be794f2013-06-21 21:43:09 +0000301class SkPdfType1Font : public SkPdfFont {
302public:
edisonn@google.com3aa35552013-08-14 18:26:20 +0000303 SkPdfType1Font(SkPdfNativeDoc* doc, SkPdfType1FontDictionary* dict) {
edisonn@google.com6e49c342013-06-27 20:03:43 +0000304 if (dict->has_FontDescriptor()) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000305 fBaseFont = SkPdfFont::fontFromFontDescriptor(doc, dict->FontDescriptor(doc));
edisonn@google.com6e49c342013-06-27 20:03:43 +0000306 } else {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000307 fBaseFont = fontFromName(doc, dict, dict->BaseFont(doc).c_str());
edisonn@google.com6e49c342013-06-27 20:03:43 +0000308 }
edisonn@google.com3aa35552013-08-14 18:26:20 +0000309
310 if (dict->isEncodingAName(doc)) {
311 fEncoding = SkPdfEncoding::fromName(dict->getEncodingAsName(doc).c_str());
312 } else if (dict->isEncodingADictionary(doc)) {
313 //SkPdfDictionary* dictEnc = dict->getEncodingAsDictionary(doc);
314 }
315 dict->FontDescriptor(doc);
edisonn@google.com1be794f2013-06-21 21:43:09 +0000316 }
317
edisonn@google.com1be794f2013-06-21 21:43:09 +0000318public:
edisonn@google.come50d9a12013-10-10 20:58:22 +0000319 virtual double drawOneChar(unsigned int ch, SkPaint* paint, SkPdfContext* pdfContext,
320 SkCanvas* canvas) {
edisonn@google.com6e49c342013-06-27 20:03:43 +0000321 return fBaseFont->drawOneChar(ToUnicode(ch), paint, pdfContext, canvas);
edisonn@google.com1be794f2013-06-21 21:43:09 +0000322 }
323
324 virtual void afterWord(SkPaint* paint, SkMatrix* matrix) {
325
326 }
edisonn@google.com6e49c342013-06-27 20:03:43 +0000327};
edisonn@google.com1be794f2013-06-21 21:43:09 +0000328
edisonn@google.com6e49c342013-06-27 20:03:43 +0000329class SkPdfTrueTypeFont : public SkPdfType1Font {
edisonn@google.com1be794f2013-06-21 21:43:09 +0000330public:
edisonn@google.come50d9a12013-10-10 20:58:22 +0000331 SkPdfTrueTypeFont(SkPdfNativeDoc* doc, SkPdfTrueTypeFontDictionary* dict)
332 : SkPdfType1Font(doc, dict) {}
edisonn@google.com1be794f2013-06-21 21:43:09 +0000333};
334
edisonn@google.com6e49c342013-06-27 20:03:43 +0000335class SkPdfMultiMasterFont : public SkPdfType1Font {
edisonn@google.com1be794f2013-06-21 21:43:09 +0000336public:
edisonn@google.come50d9a12013-10-10 20:58:22 +0000337 SkPdfMultiMasterFont(SkPdfNativeDoc* doc, SkPdfMultiMasterFontDictionary* dict)
338 : SkPdfType1Font(doc, dict) {}
edisonn@google.com1be794f2013-06-21 21:43:09 +0000339};
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000340/*
341class CIDToGIDMap {
342 virtual unsigned int map(unsigned int cid) = 0;
343 static CIDToGIDMap* fromName(const char* name);
344};
345
346class CIDToGIDMap_Identity {
347 virtual unsigned int map(unsigned int cid) { return cid; }
348
349 static CIDToGIDMap_Identity* instance() {
350 static CIDToGIDMap_Identity* inst = new CIDToGIDMap_Identity();
351 return inst;
352 }
353};
354
355CIDToGIDMap* CIDToGIDMap::fromName(const char* name) {
356 // The only one supported right now is Identity
357 if (strcmp(name, "Identity") == 0) {
358 return CIDToGIDMap_Identity::instance();
359 }
360
361#ifdef PDF_TRACE
362 // TODO(edisonn): warning/report
363 printf("Unknown CIDToGIDMap: %s\n", name);
364#endif
365 return NULL;
366}
367CIDToGIDMap* fCidToGid;
368*/
edisonn@google.com1be794f2013-06-21 21:43:09 +0000369
370class SkPdfType3Font : public SkPdfFont {
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000371 struct Type3FontChar {
edisonn@google.com3aa35552013-08-14 18:26:20 +0000372 SkPdfNativeObject* fObj;
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000373 double fWidth;
374 };
375
376 SkPdfDictionary* fCharProcs;
377 SkPdfEncodingDictionary* fEncodingDict;
378 unsigned int fFirstChar;
379 unsigned int fLastChar;
380
381 SkRect fFontBBox;
382 SkMatrix fFonMatrix;
383
384 Type3FontChar* fChars;
385
edisonn@google.com1be794f2013-06-21 21:43:09 +0000386public:
edisonn@google.com3aa35552013-08-14 18:26:20 +0000387 SkPdfType3Font(SkPdfNativeDoc* parsed, SkPdfType3FontDictionary* dict) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000388 fBaseFont = fontFromName(parsed, dict, dict->BaseFont(parsed).c_str());
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000389
390 if (dict->has_Encoding()) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000391 if (dict->isEncodingAName(parsed)) {
392 fEncoding = SkPdfEncoding::fromName(dict->getEncodingAsName(parsed).c_str());
393 } else if (dict->isEncodingAEncodingdictionary(parsed)) {
edisonn@google.com2fd5d362013-07-23 19:43:48 +0000394 // No encoding.
395 fEncoding = SkPdfDefaultEncoding::instance();
edisonn@google.com571c70b2013-07-10 17:09:50 +0000396 fEncodingDict = dict->getEncodingAsEncodingdictionary(parsed);
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000397 }
398 }
399
400 // null?
edisonn@google.com571c70b2013-07-10 17:09:50 +0000401 fCharProcs = dict->CharProcs(parsed);
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000402
403 fToUnicode = NULL;
404 if (dict->has_ToUnicode()) {
edisonn@google.com571c70b2013-07-10 17:09:50 +0000405 fToUnicode = new SkPdfToUnicode(parsed, dict->ToUnicode(parsed));
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000406 }
407
edisonn@google.coma3356fc2013-07-10 18:20:06 +0000408 fFirstChar = (unsigned int)dict->FirstChar(parsed);
409 fLastChar = (unsigned int)dict->LastChar(parsed);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000410 fFonMatrix = dict->has_FontMatrix() ? dict->FontMatrix(parsed) : SkMatrix::I();
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000411
edisonn@google.com571c70b2013-07-10 17:09:50 +0000412 if (dict->has_FontBBox()) {
413 fFontBBox = dict->FontBBox(parsed);
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000414 }
415
416 fChars = new Type3FontChar[fLastChar - fFirstChar + 1];
417
418 memset(fChars, 0, sizeof(fChars[0]) * (fLastChar - fFirstChar + 1));
419
edisonn@google.com571c70b2013-07-10 17:09:50 +0000420 const SkPdfArray* widths = dict->Widths(parsed);
421 for (unsigned int i = 0 ; i < widths->size(); i++) {
edisonn@google.comac4bedc2013-07-25 21:40:23 +0000422 if ((fFirstChar + i) >= fFirstChar && (fFirstChar + i) <= fLastChar) {
423 fChars[i].fWidth = (*widths)[i]->numberValue();
424 } else {
425 // TODO(edisonn): report pdf corruption
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000426 }
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000427 }
428
edisonn@google.com571c70b2013-07-10 17:09:50 +0000429 const SkPdfArray* diffs = fEncodingDict->Differences(parsed);
430 unsigned int j = fFirstChar;
431 for (unsigned int i = 0 ; i < diffs->size(); i++) {
432 if ((*diffs)[i]->isInteger()) {
edisonn@google.coma3356fc2013-07-10 18:20:06 +0000433 j = (unsigned int)(*diffs)[i]->intValue();
edisonn@google.com571c70b2013-07-10 17:09:50 +0000434 } else if ((*diffs)[i]->isName()) {
edisonn@google.comac4bedc2013-07-25 21:40:23 +0000435 if (j >= fFirstChar && j <= fLastChar) {
436 fChars[j - fFirstChar].fObj = fCharProcs->get((*diffs)[i]);
437 } else {
438 // TODO(edisonn): report pdf corruption
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000439 }
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000440 j++;
441 } else {
edisonn@google.comac4bedc2013-07-25 21:40:23 +0000442 // TODO(edisonn): report bad pdf
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000443 }
444 }
edisonn@google.com1be794f2013-06-21 21:43:09 +0000445 }
446
447public:
edisonn@google.come50d9a12013-10-10 20:58:22 +0000448 virtual double drawOneChar(unsigned int ch, SkPaint* paint, SkPdfContext* pdfContext,
449 SkCanvas* canvas) {
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000450 if (ch < fFirstChar || ch > fLastChar || !fChars[ch - fFirstChar].fObj) {
edisonn@google.com6e49c342013-06-27 20:03:43 +0000451 return fBaseFont->drawOneChar(ToUnicode(ch), paint, pdfContext, canvas);
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000452 }
edisonn@google.com1be794f2013-06-21 21:43:09 +0000453
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000454#ifdef PDF_TRACE
455 printf("Type 3 char to unicode: %c\n", ToUnicode(ch));
456 if (ToUnicode(ch) == 'A') {
457 printf("break;\n");
458 }
459#endif
460
edisonn@google.com571c70b2013-07-10 17:09:50 +0000461 // TODO(edisonn): is it better to resolve the reference at load time, or now?
edisonn@google.come50d9a12013-10-10 20:58:22 +0000462 doType3Char(pdfContext,
463 canvas,
464 pdfContext->fPdfDoc->resolveReference(fChars[ch - fFirstChar].fObj),
465 fFontBBox,
466 fFonMatrix,
467 pdfContext->fGraphicsState.fCurFontSize);
edisonn@google.com1be794f2013-06-21 21:43:09 +0000468
edisonn@google.com6e49c342013-06-27 20:03:43 +0000469 // TODO(edisonn): verify/test translate code, not tested yet
edisonn@google.come50d9a12013-10-10 20:58:22 +0000470 pdfContext->fGraphicsState.fMatrixTm.preTranslate(
471 SkDoubleToScalar(pdfContext->fGraphicsState.fCurFontSize *
472 fChars[ch - fFirstChar].fWidth),
473 SkDoubleToScalar(0.0));
edisonn@google.com571c70b2013-07-10 17:09:50 +0000474 return fChars[ch - fFirstChar].fWidth;
edisonn@google.com1be794f2013-06-21 21:43:09 +0000475 }
476
edisonn@google.come50d9a12013-10-10 20:58:22 +0000477 virtual void afterWord(SkPaint* paint, SkMatrix* matrix) {}
edisonn@google.com1be794f2013-06-21 21:43:09 +0000478};
479
edisonn@google.comcf2cfa12013-08-21 16:31:37 +0000480#endif // SkPdfFont_DEFINED