• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "SkPdfFont.h"
9 
10 #include "SkPdfNativeTokenizer.h"
11 #include "SkStream.h"
12 #include "SkTypeface.h"
13 
getStandardFonts()14 SkTDict<SkPdfStandardFontEntry>& getStandardFonts() {
15     static SkTDict<SkPdfStandardFontEntry> gPdfStandardFonts(100);
16 
17     // TODO (edisonn): , vs - ? what does it mean?
18     // TODO (edisonn): MT, PS, Oblique=italic?, ... what does it mean?
19     if (gPdfStandardFonts.count() == 0) {
20         gPdfStandardFonts.set("Arial", SkPdfStandardFontEntry("Arial", false, false));
21         gPdfStandardFonts.set("Arial,Bold", SkPdfStandardFontEntry("Arial", true, false));
22         gPdfStandardFonts.set("Arial,BoldItalic", SkPdfStandardFontEntry("Arial", true, true));
23         gPdfStandardFonts.set("Arial,Italic", SkPdfStandardFontEntry("Arial", false, true));
24         gPdfStandardFonts.set("Arial-Bold", SkPdfStandardFontEntry("Arial", true, false));
25         gPdfStandardFonts.set("Arial-BoldItalic", SkPdfStandardFontEntry("Arial", true, true));
26         gPdfStandardFonts.set("Arial-BoldItalicMT", SkPdfStandardFontEntry("Arial", true, true));
27         gPdfStandardFonts.set("Arial-BoldMT", SkPdfStandardFontEntry("Arial", true, false));
28         gPdfStandardFonts.set("Arial-Italic", SkPdfStandardFontEntry("Arial", false, true));
29         gPdfStandardFonts.set("Arial-ItalicMT", SkPdfStandardFontEntry("Arial", false, true));
30         gPdfStandardFonts.set("ArialMT", SkPdfStandardFontEntry("Arial", false, false));
31         gPdfStandardFonts.set("Courier", SkPdfStandardFontEntry("Courier New", false, false));
32         gPdfStandardFonts.set("Courier,Bold", SkPdfStandardFontEntry("Courier New", true, false));
33         gPdfStandardFonts.set("Courier,BoldItalic", SkPdfStandardFontEntry("Courier New", true, true));
34         gPdfStandardFonts.set("Courier,Italic", SkPdfStandardFontEntry("Courier New", false, true));
35         gPdfStandardFonts.set("Courier-Bold", SkPdfStandardFontEntry("Courier New", true, false));
36         gPdfStandardFonts.set("Courier-BoldOblique", SkPdfStandardFontEntry("Courier New", true, true));
37         gPdfStandardFonts.set("Courier-Oblique", SkPdfStandardFontEntry("Courier New", false, true));
38         gPdfStandardFonts.set("CourierNew", SkPdfStandardFontEntry("Courier New", false, false));
39         gPdfStandardFonts.set("CourierNew,Bold", SkPdfStandardFontEntry("Courier New", true, false));
40         gPdfStandardFonts.set("CourierNew,BoldItalic", SkPdfStandardFontEntry("Courier New", true, true));
41         gPdfStandardFonts.set("CourierNew,Italic", SkPdfStandardFontEntry("Courier New", false, true));
42         gPdfStandardFonts.set("CourierNew-Bold", SkPdfStandardFontEntry("Courier New", true, false));
43         gPdfStandardFonts.set("CourierNew-BoldItalic", SkPdfStandardFontEntry("Courier New", true, true));
44         gPdfStandardFonts.set("CourierNew-Italic", SkPdfStandardFontEntry("Courier New", false, true));
45         gPdfStandardFonts.set("CourierNewPS-BoldItalicMT", SkPdfStandardFontEntry("Courier New", true, true));
46         gPdfStandardFonts.set("CourierNewPS-BoldMT", SkPdfStandardFontEntry("Courier New", true, false));
47         gPdfStandardFonts.set("CourierNewPS-ItalicMT", SkPdfStandardFontEntry("Courier New", false, true));
48         gPdfStandardFonts.set("CourierNewPSMT", SkPdfStandardFontEntry("Courier New", false, false));
49         gPdfStandardFonts.set("Helvetica", SkPdfStandardFontEntry("Helvetica", false, false));
50         gPdfStandardFonts.set("Helvetica,Bold", SkPdfStandardFontEntry("Helvetica", true, false));
51         gPdfStandardFonts.set("Helvetica,BoldItalic", SkPdfStandardFontEntry("Helvetica", true, true));
52         gPdfStandardFonts.set("Helvetica,Italic", SkPdfStandardFontEntry("Helvetica", false, true));
53         gPdfStandardFonts.set("Helvetica-Bold", SkPdfStandardFontEntry("Helvetica", true, false));
54         gPdfStandardFonts.set("Helvetica-BoldItalic", SkPdfStandardFontEntry("Helvetica", true, true));
55         gPdfStandardFonts.set("Helvetica-BoldOblique", SkPdfStandardFontEntry("Helvetica", true, true));
56         gPdfStandardFonts.set("Helvetica-Italic", SkPdfStandardFontEntry("Helvetica", false, true));
57         gPdfStandardFonts.set("Helvetica-Oblique", SkPdfStandardFontEntry("Helvetica", false, true));
58         gPdfStandardFonts.set("Times-Bold", SkPdfStandardFontEntry("Times New Roman", true, false));
59         gPdfStandardFonts.set("Times-BoldItalic", SkPdfStandardFontEntry("Times New Roman", true, true));
60         gPdfStandardFonts.set("Times-Italic", SkPdfStandardFontEntry("Times New Roman", false, true));
61         gPdfStandardFonts.set("Times-Roman", SkPdfStandardFontEntry("Times New Roman", false, false));
62         gPdfStandardFonts.set("TimesNewRoman", SkPdfStandardFontEntry("Times New Roman", false, false));
63         gPdfStandardFonts.set("TimesNewRoman,Bold", SkPdfStandardFontEntry("Times New Roman", true, false));
64         gPdfStandardFonts.set("TimesNewRoman,BoldItalic", SkPdfStandardFontEntry("Times New Roman", true, true));
65         gPdfStandardFonts.set("TimesNewRoman,Italic", SkPdfStandardFontEntry("Times New Roman", false, true));
66         gPdfStandardFonts.set("TimesNewRoman-Bold", SkPdfStandardFontEntry("Times New Roman", true, false));
67         gPdfStandardFonts.set("TimesNewRoman-BoldItalic", SkPdfStandardFontEntry("Times New Roman", true, true));
68         gPdfStandardFonts.set("TimesNewRoman-Italic", SkPdfStandardFontEntry("Times New Roman", false, true));
69         gPdfStandardFonts.set("TimesNewRomanPS", SkPdfStandardFontEntry("Times New Roman", false, false));
70         gPdfStandardFonts.set("TimesNewRomanPS-Bold", SkPdfStandardFontEntry("Times New Roman", true, false));
71         gPdfStandardFonts.set("TimesNewRomanPS-BoldItalic", SkPdfStandardFontEntry("Times New Roman", true, true));
72         gPdfStandardFonts.set("TimesNewRomanPS-BoldItalicMT", SkPdfStandardFontEntry("Times New Roman", true, true));
73         gPdfStandardFonts.set("TimesNewRomanPS-BoldMT", SkPdfStandardFontEntry("Times New Roman", true, false));
74         gPdfStandardFonts.set("TimesNewRomanPS-Italic", SkPdfStandardFontEntry("Times New Roman", false, true));
75         gPdfStandardFonts.set("TimesNewRomanPS-ItalicMT", SkPdfStandardFontEntry("Times New Roman", false, true));
76         gPdfStandardFonts.set("TimesNewRomanPSMT", SkPdfStandardFontEntry("Times New Roman", false, false));
77         gPdfStandardFonts.set("Symbol", SkPdfStandardFontEntry("Symbol", false, false));
78         gPdfStandardFonts.set("ZapfDingbats", SkPdfStandardFontEntry("ZapfDingbats", false, false));
79 
80         // TODO(edisonn): these are hacks. Load Post Script font name.
81         // see FT_Get_Postscript_Name
82         // Font config is not using it, yet.
83         //https://bugs.freedesktop.org/show_bug.cgi?id=18095
84 
85         gPdfStandardFonts.set("Arial-Black", SkPdfStandardFontEntry("Arial", true, false));
86         gPdfStandardFonts.set("DejaVuSans", SkPdfStandardFontEntry("DejaVu Sans", false, false));
87         gPdfStandardFonts.set("DejaVuSansMono", SkPdfStandardFontEntry("DejaVuSans Mono", false, false));
88         gPdfStandardFonts.set("DejaVuSansMono-Bold", SkPdfStandardFontEntry("DejaVuSans Mono", true, false));
89         gPdfStandardFonts.set("DejaVuSansMono-Oblique", SkPdfStandardFontEntry("DejaVuSans Mono", false, true));
90         gPdfStandardFonts.set("Georgia-Bold", SkPdfStandardFontEntry("Georgia", true, false));
91         gPdfStandardFonts.set("Georgia-BoldItalic", SkPdfStandardFontEntry("Georgia", true, true));
92         gPdfStandardFonts.set("Georgia-Italic", SkPdfStandardFontEntry("Georgia", false, true));
93         gPdfStandardFonts.set("TrebuchetMS", SkPdfStandardFontEntry("Trebuchet MS", false, false));
94         gPdfStandardFonts.set("TrebuchetMS-Bold", SkPdfStandardFontEntry("Trebuchet MS", true, false));
95         gPdfStandardFonts.set("Verdana-Bold", SkPdfStandardFontEntry("Verdana", true, false));
96         gPdfStandardFonts.set("WenQuanYiMicroHei", SkPdfStandardFontEntry("WenQuanYi Micro Hei", false, false));
97 
98         // TODO(edisonn): list all fonts available, buil post script name as in pdf spec
99         // TODO(edisonn): Does it work in all OSs ?
100         /*
101          * The PostScript name for the value of BaseFontis determined in one of two ways:
102 • Use the PostScript name that is an optional entry in the “name” table of the
103 TrueType font itself.
104 • In the absence of such an entry in the “name” table, derive a PostScript name
105 from the name by which the font is known in the host operating system: on a
106 Windows system, it is based on the lfFaceName field in a LOGFONT structure; in
107 the Mac OS, it is based on the name of the FONDresource. If the name contains
108 any spaces, the spaces are removed.
109 If the font in a source document uses a bold or italic style, but there is no font
110 data for that style, the host operating system will synthesize the style. In this case,
111 a comma and the style name (one of Bold, Italic, or BoldItalic) are appended to the
112 font name. For example, for a TrueType font that is a bold variant of the New
113          */
114 
115         /*
116          * If the value of Subtype is MMType1.
117 • If the PostScript name of the instance contains spaces, the spaces are replaced
118 by underscores in the value of BaseFont. For instance, as illustrated in Example
119 5.7, the name “MinionMM 366 465 11 ” (which ends with a space character)
120 becomes /MinionMM_366_465_11_.
121          */
122     }
123 
124     return gPdfStandardFonts;
125 }
126 
SkTypefaceFromPdfStandardFont(const char * fontName,bool bold,bool italic)127 SkTypeface* SkTypefaceFromPdfStandardFont(const char* fontName, bool bold, bool italic) {
128     SkTDict<SkPdfStandardFontEntry>& standardFontMap = getStandardFonts();
129 
130     SkTypeface* typeface = NULL;
131     SkPdfStandardFontEntry fontData;
132 
133     if (standardFontMap.find(fontName, &fontData)) {
134         // TODO(edisonn): How does the bold/italic specified in standard definition combines with
135         // the one in /font key? use OR for now.
136         bold = bold || fontData.fIsBold;
137         italic = italic || fontData.fIsItalic;
138 
139         typeface = SkTypeface::CreateFromName(
140             fontData.fName,
141             SkTypeface::Style((bold ? SkTypeface::kBold : 0) |
142                               (italic ? SkTypeface::kItalic : 0)));
143     } else {
144         typeface = SkTypeface::CreateFromName(
145             fontName,
146             SkTypeface::kNormal);
147     }
148 
149     if (typeface) {
150         typeface->ref();
151     }
152     return typeface;
153 }
154 
fontFromFontDescriptor(SkPdfNativeDoc * doc,SkPdfFontDescriptorDictionary * fd,bool loadFromName)155 SkPdfFont* SkPdfFont::fontFromFontDescriptor(SkPdfNativeDoc* doc, SkPdfFontDescriptorDictionary* fd,
156                                              bool loadFromName) {
157     // TODO(edisonn): partial implementation.
158     // Only one, at most be available
159     SkPdfStream* pdfStream = NULL;
160     if (fd->has_FontFile()) {
161         pdfStream = fd->FontFile(doc);
162     } else if (fd->has_FontFile2()) {
163         pdfStream = fd->FontFile2(doc);
164     } if (fd->has_FontFile3()) {
165         pdfStream = fd->FontFile3(doc);
166     } else {
167         if (loadFromName) {
168             return fontFromName(doc, fd, fd->FontName(doc).c_str());
169         }
170     }
171 
172     const unsigned char* uncompressedStream = NULL;
173     size_t uncompressedStreamLength = 0;
174 
175     // TODO(edisonn): report warning to be used in testing.
176     if (!pdfStream ||
177             !pdfStream->GetFilteredStreamRef(&uncompressedStream, &uncompressedStreamLength) ||
178             !uncompressedStream ||
179             !uncompressedStreamLength) {
180         return NULL;
181     }
182 
183     SkMemoryStream* skStream = new SkMemoryStream(uncompressedStream, uncompressedStreamLength);
184     SkTypeface* face = SkTypeface::CreateFromStream(skStream);
185 
186     if (face == NULL) {
187         // TODO(edisonn): report warning to be used in testing.
188         return NULL;
189     }
190 
191     face->ref();
192 
193     return new SkPdfStandardFont(face);
194 }
195 
fontFromName(SkPdfNativeDoc * doc,SkPdfNativeObject * obj,const char * fontName)196 SkPdfFont* fontFromName(SkPdfNativeDoc* doc, SkPdfNativeObject* obj, const char* fontName) {
197     SkTypeface* typeface = SkTypefaceFromPdfStandardFont(fontName, false, false);
198     if (typeface != NULL) {
199         return new SkPdfStandardFont(typeface);
200     }
201 
202     // TODO(edisonn): perf - make a map
203     for (unsigned int i = 0 ; i < doc->objects(); i++) {
204         SkPdfNativeObject* obj = doc->object(i);
205         if (!obj || !obj->isDictionary()) {
206             continue;
207         }
208 
209         SkPdfFontDescriptorDictionary* fd = obj->asDictionary()->asFontDescriptorDictionary();
210 
211         if (!fd->valid()) {
212             continue;
213         }
214 
215         if (fd->has_FontName() && fd->FontName(doc).equals(fontName)) {
216             SkPdfFont* font = SkPdfFont::fontFromFontDescriptor(doc, fd, false);
217             if (font) {
218                 return font;
219             } else {
220                 // failed to load font descriptor
221                 break;
222             }
223         }
224     }
225 
226     // TODO(edisonn): warning/report issue
227     return SkPdfFont::Default();
228 }
229 
fontFromPdfDictionaryOnce(SkPdfNativeDoc * doc,SkPdfFontDictionary * dict)230 SkPdfFont* SkPdfFont::fontFromPdfDictionaryOnce(SkPdfNativeDoc* doc, SkPdfFontDictionary* dict) {
231     // TODO(edisonn): keep the type in a smart way in the SkPdfNativeObject
232     // 1) flag, isResolved (1bit): reset at reset, add/remove/update (array) and set(dict)
233     // in a tree like structure, 3-4 bits for all the datatypes inheriting from obj (int, real, ...)
234     // if is a dict, reserve a few bytes to encode type of dict, and so on like in a tree
235     // issue: type can be determined from context! atribute night be missing/wrong
236     switch (doc->mapper()->mapFontDictionary(dict)) {
237         case kType0FontDictionary_SkPdfNativeObjectType:
238             return fontFromType0FontDictionary(doc, dict->asType0FontDictionary());
239 
240         case kTrueTypeFontDictionary_SkPdfNativeObjectType:
241             return fontFromTrueTypeFontDictionary(doc, dict->asTrueTypeFontDictionary());
242 
243         case kType1FontDictionary_SkPdfNativeObjectType:
244             return fontFromType1FontDictionary(doc, dict->asType1FontDictionary());
245 
246         case kMultiMasterFontDictionary_SkPdfNativeObjectType:
247             return fontFromMultiMasterFontDictionary(doc, dict->asMultiMasterFontDictionary());
248 
249         case kType3FontDictionary_SkPdfNativeObjectType:
250             return fontFromType3FontDictionary(doc, dict->asType3FontDictionary());
251 
252         default:
253             // TODO(edisonn): report error?
254             return NULL;
255     }
256 }
257 
fontFromPdfDictionary(SkPdfNativeDoc * doc,SkPdfFontDictionary * dict)258 SkPdfFont* SkPdfFont::fontFromPdfDictionary(SkPdfNativeDoc* doc, SkPdfFontDictionary* dict) {
259     if (dict == NULL) {
260         return NULL;  // TODO(edisonn): report default one?
261     }
262 
263     if (!dict->hasData(SkPdfNativeObject::kFont_Data)) {
264         dict->setData(fontFromPdfDictionaryOnce(doc, dict), SkPdfNativeObject::kFont_Data);
265     }
266     return (SkPdfFont*)dict->data(SkPdfNativeObject::kFont_Data);
267 }
268 
269 
270 
fontFromType0FontDictionary(SkPdfNativeDoc * doc,SkPdfType0FontDictionary * dict)271 SkPdfType0Font* SkPdfFont::fontFromType0FontDictionary(SkPdfNativeDoc* doc,
272                                                        SkPdfType0FontDictionary* dict) {
273     if (dict == NULL) {
274         return NULL;  // default one?
275     }
276 
277     return new SkPdfType0Font(doc, dict);
278 }
279 
fontFromType1FontDictionary(SkPdfNativeDoc * doc,SkPdfType1FontDictionary * dict)280 SkPdfType1Font* SkPdfFont:: fontFromType1FontDictionary(SkPdfNativeDoc* doc,
281                                                         SkPdfType1FontDictionary* dict) {
282     if (dict == NULL) {
283         return NULL;  // default one?
284     }
285 
286     return new SkPdfType1Font(doc, dict);
287 }
288 
fontFromType3FontDictionary(SkPdfNativeDoc * doc,SkPdfType3FontDictionary * dict)289 SkPdfType3Font* SkPdfFont::fontFromType3FontDictionary(SkPdfNativeDoc* doc,
290                                                        SkPdfType3FontDictionary* dict) {
291     if (dict == NULL) {
292         return NULL;  // default one?
293     }
294 
295 
296 
297     return new SkPdfType3Font(doc, dict);
298 }
299 
fontFromTrueTypeFontDictionary(SkPdfNativeDoc * doc,SkPdfTrueTypeFontDictionary * dict)300 SkPdfTrueTypeFont* SkPdfFont::fontFromTrueTypeFontDictionary(SkPdfNativeDoc* doc,
301                                                              SkPdfTrueTypeFontDictionary* dict) {
302     if (dict == NULL) {
303         return NULL;  // default one?
304     }
305 
306     return new SkPdfTrueTypeFont(doc, dict);
307 }
308 
fontFromMultiMasterFontDictionary(SkPdfNativeDoc * doc,SkPdfMultiMasterFontDictionary * dict)309 SkPdfMultiMasterFont* SkPdfFont::fontFromMultiMasterFontDictionary(
310         SkPdfNativeDoc* doc, SkPdfMultiMasterFontDictionary* dict) {
311     if (dict == NULL) {
312         return NULL;  // default one?
313     }
314 
315     return new SkPdfMultiMasterFont(doc, dict);
316 }
317 
skstoi(const SkPdfNativeObject * str)318 static int skstoi(const SkPdfNativeObject* str) {
319     // TODO(edisonn): report err of it is not a (hex) string
320     int ret = 0;
321     for (unsigned int i = 0 ; i < str->lenstr(); i++) {
322         ret = (ret << 8) + ((unsigned char*)str->c_str())[i];
323     }
324     // TODO(edisonn): character larger than 0x0000ffff not supported right now.
325     return ret & 0x0000ffff;
326 }
327 
328 #define tokenIsKeyword(token,keyword) (token.fType == kKeyword_TokenType && \
329                                       token.fKeywordLength==sizeof(keyword)-1 && \
330                                       strncmp(token.fKeyword, keyword, sizeof(keyword)-1) == 0)
331 
SkPdfToUnicode(SkPdfNativeDoc * parsed,SkPdfStream * stream)332 SkPdfToUnicode::SkPdfToUnicode(SkPdfNativeDoc* parsed, SkPdfStream* stream) {
333     fCMapEncoding = NULL;
334     fCMapEncodingFlag = NULL;
335 
336     if (stream) {
337         // Since font will be cached, the font has to sit in the per doc allocator, not to be
338         // freed after the page is done drawing.
339         SkPdfNativeTokenizer tokenizer(stream, parsed->allocator(), parsed);
340         PdfToken token;
341 
342         fCMapEncoding = new unsigned short[256 * 256];
343         fCMapEncodingFlag = new unsigned char[256 * 256];
344         for (int i = 0 ; i < 256 * 256; i++) {
345             fCMapEncoding[i] = i;
346             fCMapEncodingFlag[i] = 0;
347         }
348 
349         // TODO(edisonn): deal with multibyte character, or longer strings.
350         // Right now we deal with up 2 characters, e.g. <0020> but not longer like <00660066006C>
351         //2 beginbfrange
352         //<0000> <005E> <0020>
353         //<005F> <0061> [<00660066> <00660069> <00660066006C>]
354 
355         while (tokenizer.readToken(&token)) {
356 
357             if (tokenIsKeyword(token, "begincodespacerange")) {
358                 while (tokenizer.readToken(&token) &&
359                        !tokenIsKeyword(token, "endcodespacerange")) {
360 //                    tokenizer.PutBack(token);
361 //                    tokenizer.readToken(&token);
362                     // TODO(edisonn): check token type! ignore/report errors.
363                     int start = skstoi(token.fObject);
364                     tokenizer.readToken(&token);
365                     int end = skstoi(token.fObject);
366                     for (int i = start; i <= end; i++) {
367                         fCMapEncodingFlag[i] |= 1;
368                     }
369                 }
370             }
371 
372             if (tokenIsKeyword(token, "beginbfchar")) {
373                 while (tokenizer.readToken(&token) && !tokenIsKeyword(token, "endbfchar")) {
374 //                    tokenizer.PutBack(token);
375 //                    tokenizer.readToken(&token);
376                     int from = skstoi(token.fObject);
377                     tokenizer.readToken(&token);
378                     int to = skstoi(token.fObject);
379 
380                     fCMapEncodingFlag[from] |= 2;
381                     fCMapEncoding[from] = to;
382                 }
383             }
384 
385             if (tokenIsKeyword(token, "beginbfrange")) {
386                 while (tokenizer.readToken(&token) && !tokenIsKeyword(token, "endbfrange")) {
387 //                    tokenizer.PutBack(token);
388 //                    tokenizer.readToken(&token);
389                     int start = skstoi(token.fObject);
390                     tokenizer.readToken(&token);
391                     int end = skstoi(token.fObject);
392 
393 
394                     tokenizer.readToken(&token); // [ or just an array directly?
395                     // do not putback, we will reuse the read. See next commented read.
396 //                    tokenizer.PutBack(token);
397 
398                     // TODO(edisonn): read spec: any string or only hex string?
399                     if (token.fType == kObject_TokenType && token.fObject->isAnyString()) {
400 //                        tokenizer.readToken(&token);
401                         int value = skstoi(token.fObject);
402 
403                         for (int i = start; i <= end; i++) {
404                             fCMapEncodingFlag[i] |= 2;
405                             fCMapEncoding[i] = value;
406                             value++;
407                             // if i != end, verify last byte id not if, ignore/report error
408                         }
409 
410                         // read one string
411                     } else if (token.fType == kObject_TokenType && token.fObject->isArray()) {
412 //                        tokenizer.readToken(&token);
413                         // read array
414                         for (unsigned int i = 0; i < token.fObject->size(); i++) {
415                             fCMapEncodingFlag[start + i] |= 2;
416                             fCMapEncoding[start + i] = skstoi((*token.fObject)[i]);
417                         }
418                     } else {
419                         tokenizer.PutBack(token);
420                     }
421                 }
422             }
423         }
424     }
425 }
426 
SkPdfType0Font(SkPdfNativeDoc * doc,SkPdfType0FontDictionary * dict)427 SkPdfType0Font::SkPdfType0Font(SkPdfNativeDoc* doc, SkPdfType0FontDictionary* dict) {
428     fBaseFont = fontFromName(doc, dict, dict->BaseFont(doc).c_str());
429     fEncoding = NULL;
430 
431     if (dict->has_Encoding()) {
432         if (dict->isEncodingAName(doc)) {
433             fEncoding = SkPdfEncoding::fromName(dict->getEncodingAsName(doc).c_str());
434         } else if (dict->isEncodingAStream(doc)) {
435             // TODO(edisonn): NYI
436             //fEncoding = loadEncodingFromStream(dict->getEncodingAsStream());
437         } else {
438             // TODO(edisonn): error ... warning .. assert?
439         }
440     }
441 
442     if (dict->has_ToUnicode()) {
443         fToUnicode = new SkPdfToUnicode(doc, dict->ToUnicode(doc));
444     }
445 }
446 
getStandardEncodings()447 SkTDict<SkPdfEncoding*>& getStandardEncodings() {
448     static SkTDict<SkPdfEncoding*> encodings(10);
449     if (encodings.count() == 0) {
450         encodings.set("Identity-H", SkPdfIdentityHEncoding::instance());
451     }
452 
453     return encodings;
454 }
455 
fromName(const char * name)456 SkPdfEncoding* SkPdfEncoding::fromName(const char* name) {
457     SkPdfEncoding* encoding = NULL;
458     if (!getStandardEncodings().find(name, &encoding)) {
459         encoding = NULL;
460     }
461 
462 #ifdef PDF_TRACE
463     if (encoding == NULL) {
464         printf("Encoding not found: %s\n", name);
465     }
466 #endif
467     return encoding;
468 }
469