OLD | NEW |
| (Empty) |
1 /* | |
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 // 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 | |
12 #ifndef SkPdfFont_DEFINED | |
13 #define SkPdfFont_DEFINED | |
14 | |
15 #include "SkPdfContext.h" | |
16 #include "SkPdfHeaders_autogen.h" | |
17 #include "SkPdfMapper_autogen.h" | |
18 #include "SkPdfUtils.h" | |
19 #include "SkTypeface.h" | |
20 #include "SkTDict.h" | |
21 #include "SkUtils.h" | |
22 | |
23 class SkPdfType0Font; | |
24 class SkPdfType1Font; | |
25 class SkPdfType3Font; | |
26 class SkPdfTrueTypeFont; | |
27 class SkPdfMultiMasterFont; | |
28 class SkPdfFont; | |
29 | |
30 struct SkPdfStandardFontEntry { | |
31 // We don't own this pointer! | |
32 const char* fName; | |
33 bool fIsBold; | |
34 bool fIsItalic; | |
35 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) {} | |
44 }; | |
45 | |
46 SkTDict<SkPdfStandardFontEntry>& getStandardFonts(); | |
47 SkTypeface* SkTypefaceFromPdfStandardFont(const char* fontName, bool bold, bool
italic); | |
48 SkPdfFont* fontFromName(SkPdfNativeDoc* doc, SkPdfNativeObject* obj, const char*
fontName); | |
49 | |
50 struct SkUnencodedText { | |
51 void* text; | |
52 int len; | |
53 | |
54 public: | |
55 SkUnencodedText(const SkPdfString* obj) { | |
56 text = (void*)obj->c_str(); | |
57 len = (int) obj->lenstr(); | |
58 } | |
59 }; | |
60 | |
61 struct SkDecodedText { | |
62 uint16_t* text; | |
63 int len; | |
64 public: | |
65 unsigned int operator[](int i) const { return text[i]; } | |
66 int size() const { return len; } | |
67 }; | |
68 | |
69 struct SkUnicodeText { | |
70 uint16_t* text; | |
71 int len; | |
72 | |
73 public: | |
74 unsigned int operator[](int i) const { return text[i]; } | |
75 int size() const { return len; } | |
76 }; | |
77 | |
78 class SkPdfEncoding { | |
79 public: | |
80 virtual ~SkPdfEncoding() {} | |
81 virtual bool decodeText(const SkUnencodedText& textIn, SkDecodedText* textOu
t) const = 0; | |
82 static SkPdfEncoding* fromName(const char* name); | |
83 }; | |
84 | |
85 SkTDict<SkPdfEncoding*>& getStandardEncodings(); | |
86 | |
87 class SkPdfToUnicode { | |
88 // TODO(edisonn): hide public members | |
89 public: | |
90 unsigned short* fCMapEncoding; | |
91 unsigned char* fCMapEncodingFlag; | |
92 | |
93 SkPdfToUnicode(SkPdfNativeDoc* parsed, SkPdfStream* stream); | |
94 }; | |
95 | |
96 | |
97 class SkPdfIdentityHEncoding : public SkPdfEncoding { | |
98 public: | |
99 virtual ~SkPdfIdentityHEncoding() {} | |
100 virtual bool decodeText(const SkUnencodedText& textIn, SkDecodedText* textOu
t) const { | |
101 // TODO(edisonn): SkASSERT(textIn.len % 2 == 0); or report error? | |
102 | |
103 uint16_t* text = (uint16_t*)textIn.text; | |
104 textOut->text = new uint16_t[textIn.len / 2]; | |
105 textOut->len = textIn.len / 2; | |
106 | |
107 for (int i = 0; i < textOut->len; i++) { | |
108 textOut->text[i] = ((text[i] << 8) & 0xff00) | ((text[i] >> 8) & 0x0
0ff); | |
109 } | |
110 | |
111 return true; | |
112 } | |
113 | |
114 static SkPdfIdentityHEncoding* instance() { | |
115 static SkPdfIdentityHEncoding* inst = new SkPdfIdentityHEncoding(); | |
116 return inst; | |
117 } | |
118 }; | |
119 | |
120 // TODO(edisonn): using this one when no encoding is specified | |
121 class SkPdfDefaultEncoding : public SkPdfEncoding { | |
122 public: | |
123 virtual ~SkPdfDefaultEncoding() {} | |
124 virtual bool decodeText(const SkUnencodedText& textIn, SkDecodedText* textOu
t) const { | |
125 // TODO(edisonn): SkASSERT(textIn.len % 2 == 0); or report error? | |
126 | |
127 unsigned char* text = (unsigned char*)textIn.text; | |
128 textOut->text = new uint16_t[textIn.len]; | |
129 textOut->len = textIn.len; | |
130 | |
131 for (int i = 0; i < textOut->len; i++) { | |
132 textOut->text[i] = text[i]; | |
133 } | |
134 | |
135 return true; | |
136 } | |
137 | |
138 static SkPdfDefaultEncoding* instance() { | |
139 static SkPdfDefaultEncoding* inst = new SkPdfDefaultEncoding(); | |
140 return inst; | |
141 } | |
142 }; | |
143 | |
144 class SkPdfCIDToGIDMapIdentityEncoding : public SkPdfEncoding { | |
145 public: | |
146 virtual ~SkPdfCIDToGIDMapIdentityEncoding() {} | |
147 virtual bool decodeText(const SkUnencodedText& textIn, SkDecodedText* textOu
t) const { | |
148 // TODO(edisonn): SkASSERT(textIn.len % 2 == 0); or report error? | |
149 | |
150 uint16_t* text = (uint16_t*)textIn.text; | |
151 textOut->text = new uint16_t[textIn.len / 2]; | |
152 textOut->len = textIn.len / 2; | |
153 | |
154 for (int i = 0; i < textOut->len; i++) { | |
155 textOut->text[i] = ((text[i] << 8) & 0xff00) | ((text[i] >> 8) & 0x0
0ff); | |
156 } | |
157 | |
158 return true; | |
159 } | |
160 | |
161 static SkPdfCIDToGIDMapIdentityEncoding* instance() { | |
162 static SkPdfCIDToGIDMapIdentityEncoding* inst = new SkPdfCIDToGIDMapIden
tityEncoding(); | |
163 return inst; | |
164 } | |
165 }; | |
166 | |
167 class SkPdfFont { | |
168 public: | |
169 SkPdfFont* fBaseFont; | |
170 SkPdfEncoding* fEncoding; | |
171 SkPdfToUnicode* fToUnicode; | |
172 | |
173 | |
174 public: | |
175 SkPdfFont() : fBaseFont(NULL), fEncoding(SkPdfDefaultEncoding::instance()),
fToUnicode(NULL) {} | |
176 | |
177 virtual ~SkPdfFont() { | |
178 // TODO(edisonn): NYI (will leak for now) | |
179 } | |
180 | |
181 const SkPdfEncoding* encoding() const {return fEncoding;} | |
182 | |
183 void drawText(const SkDecodedText& text, SkPaint* paint, SkPdfContext* pdfCo
ntext, | |
184 SkCanvas* canvas) { | |
185 for (int i = 0 ; i < text.size(); i++) { | |
186 canvas->setMatrix(pdfContext->fGraphicsState.fMatrixTm); | |
187 #ifdef PDF_TRACE | |
188 SkPoint point = SkPoint::Make(SkDoubleToScalar(0), SkDoubleToScalar(
0)); | |
189 pdfContext->fGraphicsState.fMatrixTm.mapPoints(&point, 1); | |
190 printf("DrawText at (%f, %f)\n", SkScalarToDouble(point.x()), | |
191 SkScalarToDouble(point.y())); | |
192 #endif // PDF_TRACE | |
193 | |
194 #ifdef PDF_TRACE_DRAWTEXT | |
195 SkPaint col; | |
196 col.setColor(SK_ColorMAGENTA); | |
197 SkRect rect = SkRect::MakeXYWH(SkDoubleToScalar(0.0), | |
198 SkDoubleToScalar(0.0), | |
199 SkDoubleToScalar(10.0), | |
200 SkDoubleToScalar(10.0)); | |
201 canvas->save(); | |
202 canvas->setMatrix(pdfContext->fGraphicsState.fMatrixTm); | |
203 canvas->drawRect(rect, col); | |
204 canvas->restore(); | |
205 #endif | |
206 double width = drawOneChar(text[i], paint, pdfContext, canvas); | |
207 pdfContext->fGraphicsState.fMatrixTm.preTranslate(SkDoubleToScalar(w
idth), | |
208 SkDoubleToScalar(0
.0)); | |
209 } | |
210 } | |
211 | |
212 void ToUnicode(const SkDecodedText& textIn, SkUnicodeText* textOut) const { | |
213 if (fToUnicode) { | |
214 textOut->text = new uint16_t[textIn.len]; | |
215 textOut->len = textIn.len; | |
216 for (int i = 0; i < textIn.len; i++) { | |
217 textOut->text[i] = fToUnicode->fCMapEncoding[textIn.text[i]]; | |
218 } | |
219 } else { | |
220 textOut->text = textIn.text; | |
221 textOut->len = textIn.len; | |
222 } | |
223 }; | |
224 | |
225 inline unsigned int ToUnicode(unsigned int ch) const { | |
226 if (fToUnicode && fToUnicode->fCMapEncoding) { | |
227 return fToUnicode->fCMapEncoding[ch]; | |
228 } else { | |
229 return ch; | |
230 } | |
231 }; | |
232 | |
233 static SkPdfFont* fontFromPdfDictionary(SkPdfNativeDoc* doc, SkPdfFontDictio
nary* dict); | |
234 static SkPdfFont* Default() {return fontFromName(NULL, NULL, "TimesNewRoman"
);} | |
235 | |
236 static SkPdfType0Font* fontFromType0FontDictionary(SkPdfNativeDoc* doc, | |
237 SkPdfType0FontDictionary*
dict); | |
238 static SkPdfType1Font* fontFromType1FontDictionary(SkPdfNativeDoc* doc, | |
239 SkPdfType1FontDictionary*
dict); | |
240 static SkPdfType3Font* fontFromType3FontDictionary(SkPdfNativeDoc* doc, | |
241 SkPdfType3FontDictionary*
dict); | |
242 static SkPdfTrueTypeFont* fontFromTrueTypeFontDictionary(SkPdfNativeDoc* doc
, | |
243 SkPdfTrueTypeFontDi
ctionary* dict); | |
244 static SkPdfMultiMasterFont* fontFromMultiMasterFontDictionary( | |
245 SkPdfNativeDoc* doc, SkPdfMultiMasterFontDictionary* dict); | |
246 | |
247 static SkPdfFont* fontFromFontDescriptor(SkPdfNativeDoc* doc, | |
248 SkPdfFontDescriptorDictionary* fd, | |
249 bool loadFromName = true); | |
250 | |
251 public: | |
252 virtual double drawOneChar(unsigned int ch, SkPaint* paint, SkPdfContext* pd
fContext, | |
253 SkCanvas* canvas) = 0; | |
254 virtual void afterWord(SkPaint* paint, SkMatrix* matrix) = 0; | |
255 | |
256 private: | |
257 static SkPdfFont* fontFromPdfDictionaryOnce(SkPdfNativeDoc* doc, SkPdfFontDi
ctionary* dict); | |
258 }; | |
259 | |
260 class SkPdfStandardFont : public SkPdfFont { | |
261 SkTypeface* fTypeface; | |
262 | |
263 public: | |
264 SkPdfStandardFont(SkTypeface* typeface) : fTypeface(typeface) {} | |
265 | |
266 public: | |
267 virtual double drawOneChar(unsigned int ch, SkPaint* paint, SkPdfContext* pd
fContext, | |
268 SkCanvas* canvas) { | |
269 paint->setTypeface(fTypeface); | |
270 paint->setTextEncoding(SkPaint::kUTF8_TextEncoding); | |
271 | |
272 unsigned long ch4 = ch; | |
273 char utf8[10]; | |
274 size_t len = SkUTF8_FromUnichar((SkUnichar) ch4, utf8); | |
275 | |
276 canvas->drawText(utf8, len, SkDoubleToScalar(0), SkDoubleToScalar(0), *p
aint); | |
277 | |
278 SkScalar textWidth = paint->measureText(utf8, len); | |
279 return SkScalarToDouble(textWidth); | |
280 } | |
281 | |
282 virtual void afterWord(SkPaint* paint, SkMatrix* matrix) {} | |
283 }; | |
284 | |
285 class SkPdfType0Font : public SkPdfFont { | |
286 public: | |
287 SkPdfType0Font(SkPdfNativeDoc* doc, SkPdfType0FontDictionary* dict); | |
288 | |
289 public: | |
290 | |
291 virtual double drawOneChar(unsigned int ch, SkPaint* paint, SkPdfContext* pd
fContext, | |
292 SkCanvas* canvas) { | |
293 return fBaseFont->drawOneChar(ToUnicode(ch), paint, pdfContext, canvas); | |
294 } | |
295 | |
296 virtual void afterWord(SkPaint* paint, SkMatrix* matrix) { | |
297 } | |
298 }; | |
299 | |
300 class SkPdfType1Font : public SkPdfFont { | |
301 public: | |
302 SkPdfType1Font(SkPdfNativeDoc* doc, SkPdfType1FontDictionary* dict) { | |
303 if (dict->has_FontDescriptor()) { | |
304 fBaseFont = SkPdfFont::fontFromFontDescriptor(doc, dict->FontDescrip
tor(doc)); | |
305 } else { | |
306 fBaseFont = fontFromName(doc, dict, dict->BaseFont(doc).c_str()); | |
307 } | |
308 | |
309 if (dict->isEncodingAName(doc)) { | |
310 fEncoding = SkPdfEncoding::fromName(dict->getEncodingAsName(doc).c_s
tr()); | |
311 } else if (dict->isEncodingADictionary(doc)) { | |
312 //SkPdfDictionary* dictEnc = dict->getEncodingAsDictionary(doc); | |
313 } | |
314 dict->FontDescriptor(doc); | |
315 } | |
316 | |
317 public: | |
318 virtual double drawOneChar(unsigned int ch, SkPaint* paint, SkPdfContext*
pdfContext, | |
319 SkCanvas* canvas) { | |
320 return fBaseFont->drawOneChar(ToUnicode(ch), paint, pdfContext, canvas
); | |
321 } | |
322 | |
323 virtual void afterWord(SkPaint* paint, SkMatrix* matrix) { | |
324 | |
325 } | |
326 }; | |
327 | |
328 class SkPdfTrueTypeFont : public SkPdfType1Font { | |
329 public: | |
330 SkPdfTrueTypeFont(SkPdfNativeDoc* doc, SkPdfTrueTypeFontDictionary* dict) | |
331 : SkPdfType1Font(doc, dict) {} | |
332 }; | |
333 | |
334 class SkPdfMultiMasterFont : public SkPdfType1Font { | |
335 public: | |
336 SkPdfMultiMasterFont(SkPdfNativeDoc* doc, SkPdfMultiMasterFontDictionary* di
ct) | |
337 : SkPdfType1Font(doc, dict) {} | |
338 }; | |
339 /* | |
340 class CIDToGIDMap { | |
341 virtual unsigned int map(unsigned int cid) = 0; | |
342 static CIDToGIDMap* fromName(const char* name); | |
343 }; | |
344 | |
345 class CIDToGIDMap_Identity { | |
346 virtual unsigned int map(unsigned int cid) { return cid; } | |
347 | |
348 static CIDToGIDMap_Identity* instance() { | |
349 static CIDToGIDMap_Identity* inst = new CIDToGIDMap_Identity(); | |
350 return inst; | |
351 } | |
352 }; | |
353 | |
354 CIDToGIDMap* CIDToGIDMap::fromName(const char* name) { | |
355 // The only one supported right now is Identity | |
356 if (strcmp(name, "Identity") == 0) { | |
357 return CIDToGIDMap_Identity::instance(); | |
358 } | |
359 | |
360 #ifdef PDF_TRACE | |
361 // TODO(edisonn): warning/report | |
362 printf("Unknown CIDToGIDMap: %s\n", name); | |
363 #endif | |
364 return NULL; | |
365 } | |
366 CIDToGIDMap* fCidToGid; | |
367 */ | |
368 | |
369 class SkPdfType3Font : public SkPdfFont { | |
370 struct Type3FontChar { | |
371 SkPdfNativeObject* fObj; | |
372 double fWidth; | |
373 }; | |
374 | |
375 SkPdfDictionary* fCharProcs; | |
376 SkPdfEncodingDictionary* fEncodingDict; | |
377 unsigned int fFirstChar; | |
378 unsigned int fLastChar; | |
379 | |
380 SkRect fFontBBox; | |
381 SkMatrix fFonMatrix; | |
382 | |
383 Type3FontChar* fChars; | |
384 | |
385 public: | |
386 SkPdfType3Font(SkPdfNativeDoc* parsed, SkPdfType3FontDictionary* dict) { | |
387 fBaseFont = fontFromName(parsed, dict, dict->BaseFont(parsed).c_str()); | |
388 | |
389 if (dict->has_Encoding()) { | |
390 if (dict->isEncodingAName(parsed)) { | |
391 fEncoding = SkPdfEncoding::fromName(dict->getEncodingAsName(par
sed).c_str()); | |
392 } else if (dict->isEncodingAEncodingdictionary(parsed)) { | |
393 // No encoding. | |
394 fEncoding = SkPdfDefaultEncoding::instance(); | |
395 fEncodingDict = dict->getEncodingAsEncodingdictionary(parsed); | |
396 } | |
397 } | |
398 | |
399 // null? | |
400 fCharProcs = dict->CharProcs(parsed); | |
401 | |
402 fToUnicode = NULL; | |
403 if (dict->has_ToUnicode()) { | |
404 fToUnicode = new SkPdfToUnicode(parsed, dict->ToUnicode(parsed)); | |
405 } | |
406 | |
407 fFirstChar = (unsigned int)dict->FirstChar(parsed); | |
408 fLastChar = (unsigned int)dict->LastChar(parsed); | |
409 fFonMatrix = dict->has_FontMatrix() ? dict->FontMatrix(parsed) : SkMatri
x::I(); | |
410 | |
411 if (dict->has_FontBBox()) { | |
412 fFontBBox = dict->FontBBox(parsed); | |
413 } | |
414 | |
415 fChars = new Type3FontChar[fLastChar - fFirstChar + 1]; | |
416 | |
417 memset(fChars, 0, sizeof(fChars[0]) * (fLastChar - fFirstChar + 1)); | |
418 | |
419 const SkPdfArray* widths = dict->Widths(parsed); | |
420 for (unsigned int i = 0 ; i < widths->size(); i++) { | |
421 if ((fFirstChar + i) >= fFirstChar && (fFirstChar + i) <= fLastChar)
{ | |
422 fChars[i].fWidth = (*widths)[i]->numberValue(); | |
423 } else { | |
424 // TODO(edisonn): report pdf corruption | |
425 } | |
426 } | |
427 | |
428 const SkPdfArray* diffs = fEncodingDict->Differences(parsed); | |
429 unsigned int j = fFirstChar; | |
430 for (unsigned int i = 0 ; i < diffs->size(); i++) { | |
431 if ((*diffs)[i]->isInteger()) { | |
432 j = (unsigned int)(*diffs)[i]->intValue(); | |
433 } else if ((*diffs)[i]->isName()) { | |
434 if (j >= fFirstChar && j <= fLastChar) { | |
435 fChars[j - fFirstChar].fObj = fCharProcs->get((*diffs)[i]); | |
436 } else { | |
437 // TODO(edisonn): report pdf corruption | |
438 } | |
439 j++; | |
440 } else { | |
441 // TODO(edisonn): report bad pdf | |
442 } | |
443 } | |
444 } | |
445 | |
446 public: | |
447 virtual double drawOneChar(unsigned int ch, SkPaint* paint, SkPdfContext* pd
fContext, | |
448 SkCanvas* canvas) { | |
449 if (ch < fFirstChar || ch > fLastChar || !fChars[ch - fFirstChar].fObj)
{ | |
450 return fBaseFont->drawOneChar(ToUnicode(ch), paint, pdfContext, canv
as); | |
451 } | |
452 | |
453 #ifdef PDF_TRACE | |
454 printf("Type 3 char to unicode: %c\n", ToUnicode(ch)); | |
455 if (ToUnicode(ch) == 'A') { | |
456 printf("break;\n"); | |
457 } | |
458 #endif | |
459 | |
460 // TODO(edisonn): is it better to resolve the reference at load time, or
now? | |
461 doType3Char(pdfContext, | |
462 canvas, | |
463 pdfContext->fPdfDoc->resolveReference(fChars[ch - fFirstChar
].fObj), | |
464 fFontBBox, | |
465 fFonMatrix, | |
466 pdfContext->fGraphicsState.fCurFontSize); | |
467 | |
468 // TODO(edisonn): verify/test translate code, not tested yet | |
469 pdfContext->fGraphicsState.fMatrixTm.preTranslate( | |
470 SkDoubleToScalar(pdfContext->fGraphicsState.fCurFontSize * | |
471 fChars[ch - fFirstChar].fWidth), | |
472 SkDoubleToScalar(0.0)); | |
473 return fChars[ch - fFirstChar].fWidth; | |
474 } | |
475 | |
476 virtual void afterWord(SkPaint* paint, SkMatrix* matrix) {} | |
477 }; | |
478 | |
479 #endif // SkPdfFont_DEFINED | |
OLD | NEW |