blob: 733ae8705aa0a75cd0bc23c352a702ee6fefd736 [file] [log] [blame]
edisonn@google.com1be794f2013-06-21 21:43:09 +00001#include "SkPdfFont.h"
edisonn@google.com131d4ee2013-06-26 17:48:12 +00002#include "SkPdfParser.h"
edisonn@google.com1be794f2013-06-21 21:43:09 +00003
edisonn@google.comeee4b652013-06-27 13:22:42 +00004#include "SkStream.h"
5#include "SkTypeface.h"
edisonn@google.com3aac1f92013-07-02 22:42:53 +00006#include "SkPdfPodofoTokenizer.h"
edisonn@google.comeee4b652013-06-27 13:22:42 +00007
edisonn@google.com1be794f2013-06-21 21:43:09 +00008std::map<std::string, SkPdfStandardFontEntry>& getStandardFonts() {
9 static std::map<std::string, SkPdfStandardFontEntry> gPdfStandardFonts;
10
11 // TODO (edisonn): , vs - ? what does it mean?
12 // TODO (edisonn): MT, PS, Oblique=italic?, ... what does it mean?
13 if (gPdfStandardFonts.empty()) {
14 gPdfStandardFonts["Arial"] = {"Arial", false, false};
15 gPdfStandardFonts["Arial,Bold"] = {"Arial", true, false};
16 gPdfStandardFonts["Arial,BoldItalic"] = {"Arial", true, true};
17 gPdfStandardFonts["Arial,Italic"] = {"Arial", false, true};
18 gPdfStandardFonts["Arial-Bold"] = {"Arial", true, false};
19 gPdfStandardFonts["Arial-BoldItalic"] = {"Arial", true, true};
20 gPdfStandardFonts["Arial-BoldItalicMT"] = {"Arial", true, true};
21 gPdfStandardFonts["Arial-BoldMT"] = {"Arial", true, false};
22 gPdfStandardFonts["Arial-Italic"] = {"Arial", false, true};
23 gPdfStandardFonts["Arial-ItalicMT"] = {"Arial", false, true};
24 gPdfStandardFonts["ArialMT"] = {"Arial", false, false};
25 gPdfStandardFonts["Courier"] = {"Courier New", false, false};
26 gPdfStandardFonts["Courier,Bold"] = {"Courier New", true, false};
27 gPdfStandardFonts["Courier,BoldItalic"] = {"Courier New", true, true};
28 gPdfStandardFonts["Courier,Italic"] = {"Courier New", false, true};
29 gPdfStandardFonts["Courier-Bold"] = {"Courier New", true, false};
30 gPdfStandardFonts["Courier-BoldOblique"] = {"Courier New", true, true};
31 gPdfStandardFonts["Courier-Oblique"] = {"Courier New", false, true};
32 gPdfStandardFonts["CourierNew"] = {"Courier New", false, false};
33 gPdfStandardFonts["CourierNew,Bold"] = {"Courier New", true, false};
34 gPdfStandardFonts["CourierNew,BoldItalic"] = {"Courier New", true, true};
35 gPdfStandardFonts["CourierNew,Italic"] = {"Courier New", false, true};
36 gPdfStandardFonts["CourierNew-Bold"] = {"Courier New", true, false};
37 gPdfStandardFonts["CourierNew-BoldItalic"] = {"Courier New", true, true};
38 gPdfStandardFonts["CourierNew-Italic"] = {"Courier New", false, true};
39 gPdfStandardFonts["CourierNewPS-BoldItalicMT"] = {"Courier New", true, true};
40 gPdfStandardFonts["CourierNewPS-BoldMT"] = {"Courier New", true, false};
41 gPdfStandardFonts["CourierNewPS-ItalicMT"] = {"Courier New", false, true};
42 gPdfStandardFonts["CourierNewPSMT"] = {"Courier New", false, false};
43 gPdfStandardFonts["Helvetica"] = {"Helvetica", false, false};
44 gPdfStandardFonts["Helvetica,Bold"] = {"Helvetica", true, false};
45 gPdfStandardFonts["Helvetica,BoldItalic"] = {"Helvetica", true, true};
46 gPdfStandardFonts["Helvetica,Italic"] = {"Helvetica", false, true};
47 gPdfStandardFonts["Helvetica-Bold"] = {"Helvetica", true, false};
48 gPdfStandardFonts["Helvetica-BoldItalic"] = {"Helvetica", true, true};
49 gPdfStandardFonts["Helvetica-BoldOblique"] = {"Helvetica", true, true};
50 gPdfStandardFonts["Helvetica-Italic"] = {"Helvetica", false, true};
51 gPdfStandardFonts["Helvetica-Oblique"] = {"Helvetica", false, true};
52 gPdfStandardFonts["Times-Bold"] = {"Times New Roman", true, false};
53 gPdfStandardFonts["Times-BoldItalic"] = {"Times New Roman", true, true};
54 gPdfStandardFonts["Times-Italic"] = {"Times New Roman", false, true};
55 gPdfStandardFonts["Times-Roman"] = {"Times New Roman", false, false};
56 gPdfStandardFonts["TimesNewRoman"] = {"Times New Roman", false, false};
57 gPdfStandardFonts["TimesNewRoman,Bold"] = {"Times New Roman", true, false};
58 gPdfStandardFonts["TimesNewRoman,BoldItalic"] = {"Times New Roman", true, true};
59 gPdfStandardFonts["TimesNewRoman,Italic"] = {"Times New Roman", false, true};
60 gPdfStandardFonts["TimesNewRoman-Bold"] = {"Times New Roman", true, false};
61 gPdfStandardFonts["TimesNewRoman-BoldItalic"] = {"Times New Roman", true, true};
62 gPdfStandardFonts["TimesNewRoman-Italic"] = {"Times New Roman", false, true};
63 gPdfStandardFonts["TimesNewRomanPS"] = {"Times New Roman", false, false};
64 gPdfStandardFonts["TimesNewRomanPS-Bold"] = {"Times New Roman", true, false};
65 gPdfStandardFonts["TimesNewRomanPS-BoldItalic"] = {"Times New Roman", true, true};
66 gPdfStandardFonts["TimesNewRomanPS-BoldItalicMT"] = {"Times New Roman", true, true};
67 gPdfStandardFonts["TimesNewRomanPS-BoldMT"] = {"Times New Roman", true, false};
68 gPdfStandardFonts["TimesNewRomanPS-Italic"] = {"Times New Roman", false, true};
69 gPdfStandardFonts["TimesNewRomanPS-ItalicMT"] = {"Times New Roman", false, true};
70 gPdfStandardFonts["TimesNewRomanPSMT"] = {"Times New Roman", false, false};
71 gPdfStandardFonts["Symbol"] = {"Symbol", false, false};
72 gPdfStandardFonts["ZapfDingbats"] = {"ZapfDingbats", false, false};
73
74 // TODO(edisonn): these are hacks. Load Post Script font name.
75 // see FT_Get_Postscript_Name
76 // Font config is not using it, yet.
77 //https://bugs.freedesktop.org/show_bug.cgi?id=18095
edisonn@google.comb857a0c2013-06-25 20:45:40 +000078
edisonn@google.com1be794f2013-06-21 21:43:09 +000079 gPdfStandardFonts["Arial-Black"] = {"Arial", true, false};
80 gPdfStandardFonts["DejaVuSans"] = {"DejaVu Sans", false, false};
81 gPdfStandardFonts["DejaVuSansMono"] = {"DejaVuSans Mono", false, false};
82 gPdfStandardFonts["DejaVuSansMono-Bold"] = {"DejaVuSans Mono", true, false};
83 gPdfStandardFonts["DejaVuSansMono-Oblique"] = {"DejaVuSans Mono", false, true};
84 gPdfStandardFonts["Georgia-Bold"] = {"Georgia", true, false};
85 gPdfStandardFonts["Georgia-BoldItalic"] = {"Georgia", true, true};
86 gPdfStandardFonts["Georgia-Italic"] = {"Georgia", false, true};
87 gPdfStandardFonts["TrebuchetMS"] = {"Trebuchet MS", false, false};
88 gPdfStandardFonts["TrebuchetMS-Bold"] = {"Trebuchet MS", true, false};
89 gPdfStandardFonts["Verdana-Bold"] = {"Verdana", true, false};
90 gPdfStandardFonts["WenQuanYiMicroHei"] = {"WenQuanYi Micro Hei", false, false};
edisonn@google.comb857a0c2013-06-25 20:45:40 +000091
92 // TODO(edisonn): list all phonts available, builf post script name as in pdf spec
93 /*
94 * The PostScript name for the value of BaseFontis determined in one of two ways:
95• Use the PostScript name that is an optional entry in the “name” table of the
96TrueType font itself.
97• In the absence of such an entry in the “name” table, derive a PostScript name
98from the name by which the font is known in the host operating system: on a
99Windows system, it is based on the lfFaceName field in a LOGFONT structure; in
100the Mac OS, it is based on the name of the FONDresource. If the name contains
101any spaces, the spaces are removed.
102If the font in a source document uses a bold or italic style, but there is no font
103data for that style, the host operating system will synthesize the style. In this case,
104a comma and the style name (one of Bold, Italic, or BoldItalic) are appended to the
105font name. For example, for a TrueType font that is a bold variant of the New
106 */
107
108 /*
109 * If the value of Subtype is MMType1.
110• If the PostScript name of the instance contains spaces, the spaces are replaced
111by underscores in the value of BaseFont. For instance, as illustrated in Example
1125.7, the name “MinionMM 366 465 11 ” (which ends with a space character)
113becomes /MinionMM_366_465_11_.
114 */
115
116 // might not work on all oses ?
117 //
118
edisonn@google.com1be794f2013-06-21 21:43:09 +0000119 }
120
121 return gPdfStandardFonts;
122}
123
124SkTypeface* SkTypefaceFromPdfStandardFont(const char* fontName, bool bold, bool italic) {
125 std::map<std::string, SkPdfStandardFontEntry>& standardFontMap = getStandardFonts();
126
127 SkTypeface* typeface = NULL;
128 if (standardFontMap.find(fontName) != standardFontMap.end()) {
129 SkPdfStandardFontEntry fontData = standardFontMap[fontName];
130
131 // TODO(edisonn): How does the bold/italic specified in standard definition combines with
132 // the one in /font key? use OR for now.
133 bold = bold || fontData.fIsBold;
134 italic = italic || fontData.fIsItalic;
135
136 typeface = SkTypeface::CreateFromName(
137 fontData.fName,
138 SkTypeface::Style((bold ? SkTypeface::kBold : 0) |
139 (italic ? SkTypeface::kItalic : 0)));
140 } else {
141 typeface = SkTypeface::CreateFromName(
142 fontName,
143 SkTypeface::kNormal);
144 }
145
146 if (typeface) {
147 typeface->ref();
148 }
149 return typeface;
150}
151
edisonn@google.com6e49c342013-06-27 20:03:43 +0000152SkPdfFont* SkPdfFont::fontFromFontDescriptor(SkPdfFontDescriptorDictionary* fd, bool loadFromName) {
153 // TODO(edisonn): partial implementation
edisonn@google.comeee4b652013-06-27 13:22:42 +0000154 // Only one, at most be available
edisonn@google.com6e49c342013-06-27 20:03:43 +0000155 SkPdfStream* pdfStream = NULL;
edisonn@google.comeee4b652013-06-27 13:22:42 +0000156 if (fd->has_FontFile()) {
edisonn@google.com6e49c342013-06-27 20:03:43 +0000157 pdfStream = fd->FontFile();
edisonn@google.comeee4b652013-06-27 13:22:42 +0000158 } else if (fd->has_FontFile2()) {
edisonn@google.com6e49c342013-06-27 20:03:43 +0000159 pdfStream = fd->FontFile2();
edisonn@google.comeee4b652013-06-27 13:22:42 +0000160 } if (fd->has_FontFile3()) {
edisonn@google.com6e49c342013-06-27 20:03:43 +0000161 pdfStream = fd->FontFile3();
edisonn@google.comeee4b652013-06-27 13:22:42 +0000162 } else {
edisonn@google.com6e49c342013-06-27 20:03:43 +0000163 if (loadFromName) {
164 return fontFromName(fd, fd->FontName().c_str());
165 }
edisonn@google.comeee4b652013-06-27 13:22:42 +0000166 }
167
edisonn@google.com6e49c342013-06-27 20:03:43 +0000168 char* uncompressedStream = NULL;
edisonn@google.com3aac1f92013-07-02 22:42:53 +0000169 long uncompressedStreamLength = 0;
edisonn@google.com6e49c342013-06-27 20:03:43 +0000170
edisonn@google.com3aac1f92013-07-02 22:42:53 +0000171 // TODO(edisonn): report warning to be used in testing.
172 if (!pdfStream ||
173 !pdfStream->GetFilteredCopy(&uncompressedStream, &uncompressedStreamLength) ||
174 !uncompressedStream ||
175 !uncompressedStreamLength) {
edisonn@google.com6e49c342013-06-27 20:03:43 +0000176 return NULL;
177 }
edisonn@google.com3aac1f92013-07-02 22:42:53 +0000178
edisonn@google.com6e49c342013-06-27 20:03:43 +0000179 SkMemoryStream* skStream = new SkMemoryStream(uncompressedStream, uncompressedStreamLength);
180 SkTypeface* face = SkTypeface::CreateFromStream(skStream);
181
182 if (face == NULL) {
183 // TODO(edisonn): report warning to be used in testing.
184 return NULL;
185 }
186
187 face->ref();
188
189 return new SkPdfStandardFont(face);
edisonn@google.comeee4b652013-06-27 13:22:42 +0000190}
191
edisonn@google.com6e49c342013-06-27 20:03:43 +0000192SkPdfFont* fontFromName(SkPdfObject* obj, const char* fontName) {
edisonn@google.com1be794f2013-06-21 21:43:09 +0000193 SkTypeface* typeface = SkTypefaceFromPdfStandardFont(fontName, false, false);
194 if (typeface != NULL) {
195 return new SkPdfStandardFont(typeface);
196 }
edisonn@google.comeee4b652013-06-27 13:22:42 +0000197
198 // TODO(edisonn): perf - make a map
edisonn@google.com3aac1f92013-07-02 22:42:53 +0000199 for (int i = 0 ; i < obj->doc()->objects(); i++) {
200 const SkPdfObject* podofoFont = obj->doc()->object(i);
edisonn@google.comeee4b652013-06-27 13:22:42 +0000201 SkPdfFontDescriptorDictionary* fd = NULL;
edisonn@google.comab03e682013-06-28 18:51:20 +0000202
edisonn@google.com3aac1f92013-07-02 22:42:53 +0000203 if (obj->doc()->mapper()->mapFontDescriptorDictionary(podofoFont, &fd)) {
edisonn@google.comeee4b652013-06-27 13:22:42 +0000204 if (fd->has_FontName() && fd->FontName() == fontName) {
edisonn@google.com6e49c342013-06-27 20:03:43 +0000205 SkPdfFont* font = SkPdfFont::fontFromFontDescriptor(fd, false);
edisonn@google.comeee4b652013-06-27 13:22:42 +0000206 if (font) {
207 return font;
208 } else {
209 // failed to load font descriptor
210 break;
211 }
212 }
213 }
214 }
215
216 // TODO(edisonn): warning/report issue
edisonn@google.com1be794f2013-06-21 21:43:09 +0000217 return SkPdfFont::Default();
218}
219
220SkPdfFont* SkPdfFont::fontFromPdfDictionary(SkPdfFontDictionary* dict) {
221 if (dict == NULL) {
222 return NULL; // TODO(edisonn): report default one?
223 }
224
225 switch (dict->getType()) {
226 case kType0FontDictionary_SkPdfObjectType:
227 return fontFromType0FontDictionary(dict->asType0FontDictionary());
228
229 case kTrueTypeFontDictionary_SkPdfObjectType:
230 return fontFromTrueTypeFontDictionary(dict->asTrueTypeFontDictionary());
231
232 case kType1FontDictionary_SkPdfObjectType:
233 return fontFromType1FontDictionary(dict->asType1FontDictionary());
234
edisonn@google.com1be794f2013-06-21 21:43:09 +0000235 case kMultiMasterFontDictionary_SkPdfObjectType:
236 return fontFromMultiMasterFontDictionary(dict->asMultiMasterFontDictionary());
237
238 case kType3FontDictionary_SkPdfObjectType:
239 return fontFromType3FontDictionary(dict->asType3FontDictionary());
240 }
241 return NULL; // TODO(edisonn): report error?
242}
243
244SkPdfType0Font* SkPdfFont::fontFromType0FontDictionary(SkPdfType0FontDictionary* dict) {
245 if (dict == NULL) {
246 return NULL; // default one?
247 }
248
249 return new SkPdfType0Font(dict);
250}
251
252SkPdfType1Font* SkPdfFont:: fontFromType1FontDictionary(SkPdfType1FontDictionary* dict) {
253 if (dict == NULL) {
254 return NULL; // default one?
255 }
256
257 return new SkPdfType1Font(dict);
258}
259
260SkPdfType3Font* SkPdfFont::fontFromType3FontDictionary(SkPdfType3FontDictionary* dict) {
261 if (dict == NULL) {
262 return NULL; // default one?
263 }
264
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000265
266
edisonn@google.com1be794f2013-06-21 21:43:09 +0000267 return new SkPdfType3Font(dict);
268}
269
270SkPdfTrueTypeFont* SkPdfFont::fontFromTrueTypeFontDictionary(SkPdfTrueTypeFontDictionary* dict) {
271 if (dict == NULL) {
272 return NULL; // default one?
273 }
274
275 return new SkPdfTrueTypeFont(dict);
276}
277
edisonn@google.com1be794f2013-06-21 21:43:09 +0000278SkPdfMultiMasterFont* SkPdfFont::fontFromMultiMasterFontDictionary(SkPdfMultiMasterFontDictionary* dict) {
279 if (dict == NULL) {
280 return NULL; // default one?
281 }
282
283 return new SkPdfMultiMasterFont(dict);
284}
285
286static int skstoi(const SkPdfString* str) {
287 int ret = 0;
edisonn@google.com3aac1f92013-07-02 22:42:53 +0000288 for (int i = 0 ; i < str->len(); i++) {
289 ret = (ret << 8) + ((unsigned char*)str->c_str())[i];
edisonn@google.com1be794f2013-06-21 21:43:09 +0000290 }
291 return ret;
292}
293
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000294SkPdfToUnicode::SkPdfToUnicode(const SkPdfStream* stream) {
edisonn@google.com1be794f2013-06-21 21:43:09 +0000295 fCMapEncoding = NULL;
296 fCMapEncodingFlag = NULL;
297
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000298 if (stream) {
edisonn@google.com3aac1f92013-07-02 22:42:53 +0000299 SkPdfPodofoTokenizer* tokenizer = stream->doc()->tokenizerOfStream(stream);
edisonn@google.com1be794f2013-06-21 21:43:09 +0000300 PdfToken token;
301
302 fCMapEncoding = new unsigned short[256 * 256];
303 fCMapEncodingFlag = new unsigned char[256 * 256];
304 for (int i = 0 ; i < 256 * 256; i++) {
305 fCMapEncoding[i] = i;
306 fCMapEncodingFlag[i] = 0;
307 }
308
309 // TODO(edisonn): deal with multibyte character, or longer strings.
310 // Ritght now we deal with up 2 characters, e.g. <0020> but not longer like <00660066006C>
311 //2 beginbfrange
312 //<0000> <005E> <0020>
313 //<005F> <0061> [<00660066> <00660069> <00660066006C>]
314
edisonn@google.com3aac1f92013-07-02 22:42:53 +0000315 while (tokenizer->readToken(&token)) {
edisonn@google.com1be794f2013-06-21 21:43:09 +0000316
317 if (token.fType == kKeyword_TokenType && strcmp(token.fKeyword, "begincodespacerange") == 0) {
edisonn@google.com3aac1f92013-07-02 22:42:53 +0000318 while (tokenizer->readToken(&token) && !(token.fType == kKeyword_TokenType && strcmp(token.fKeyword, "endcodespacerange") == 0)) {
319// tokenizer->PutBack(token);
320// tokenizer->readToken(&token);
edisonn@google.com1be794f2013-06-21 21:43:09 +0000321 // TODO(edisonn): check token type! ignore/report errors.
322 int start = skstoi(token.fObject->asString());
edisonn@google.com3aac1f92013-07-02 22:42:53 +0000323 tokenizer->readToken(&token);
edisonn@google.com1be794f2013-06-21 21:43:09 +0000324 int end = skstoi(token.fObject->asString());
325 for (int i = start; i <= end; i++) {
326 fCMapEncodingFlag[i] |= 1;
327 }
328 }
329 }
330
331 if (token.fType == kKeyword_TokenType && strcmp(token.fKeyword, "beginbfchar") == 0) {
edisonn@google.com3aac1f92013-07-02 22:42:53 +0000332 while (tokenizer->readToken(&token) && !(token.fType == kKeyword_TokenType && strcmp(token.fKeyword, "endbfchar") == 0)) {
333// tokenizer->PutBack(token);
334// tokenizer->readToken(&token);
edisonn@google.com1be794f2013-06-21 21:43:09 +0000335 int from = skstoi(token.fObject->asString());
edisonn@google.com3aac1f92013-07-02 22:42:53 +0000336 tokenizer->readToken(&token);
edisonn@google.com1be794f2013-06-21 21:43:09 +0000337 int to = skstoi(token.fObject->asString());
338
339 fCMapEncodingFlag[from] |= 2;
340 fCMapEncoding[from] = to;
341 }
342 }
343
344 if (token.fType == kKeyword_TokenType && strcmp(token.fKeyword, "beginbfrange") == 0) {
edisonn@google.com3aac1f92013-07-02 22:42:53 +0000345 while (tokenizer->readToken(&token) && !(token.fType == kKeyword_TokenType && strcmp(token.fKeyword, "endbfrange") == 0)) {
346// tokenizer->PutBack(token);
347// tokenizer->readToken(&token);
edisonn@google.com1be794f2013-06-21 21:43:09 +0000348 int start = skstoi(token.fObject->asString());
edisonn@google.com3aac1f92013-07-02 22:42:53 +0000349 tokenizer->readToken(&token);
edisonn@google.com1be794f2013-06-21 21:43:09 +0000350 int end = skstoi(token.fObject->asString());
351
352
edisonn@google.com3aac1f92013-07-02 22:42:53 +0000353 tokenizer->readToken(&token); // [ or just an array directly?
354// tokenizer->PutBack(token);
edisonn@google.com1be794f2013-06-21 21:43:09 +0000355
356 if (token.fType == kObject_TokenType && token.fObject->asString()) {
edisonn@google.com3aac1f92013-07-02 22:42:53 +0000357// tokenizer->readToken(&token);
edisonn@google.com1be794f2013-06-21 21:43:09 +0000358 int value = skstoi(token.fObject->asString());
359
360 for (int i = start; i <= end; i++) {
361 fCMapEncodingFlag[i] |= 2;
362 fCMapEncoding[i] = value;
363 value++;
364 // if i != end, verify last byte id not if, ignore/report error
365 }
366
367 // read one string
368 } else if (token.fType == kObject_TokenType && token.fObject->asArray()) {
edisonn@google.com3aac1f92013-07-02 22:42:53 +0000369// tokenizer->readToken(&token);
edisonn@google.com1be794f2013-06-21 21:43:09 +0000370 for (int i = 0; i < token.fObject->asArray()->size(); i++) {
371 fCMapEncodingFlag[start + i] |= 2;
372 fCMapEncoding[start + i] = skstoi((*token.fObject->asArray())[i]->asString());
373 }
374 // read array
375 }
376
377 //fCMapEncodingFlag[from] = 1;
378 //fCMapEncoding[from] = to;
379 }
380 }
381 }
382 }
383}
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000384
385
386SkPdfType0Font::SkPdfType0Font(SkPdfType0FontDictionary* dict) {
edisonn@google.com6e49c342013-06-27 20:03:43 +0000387 fBaseFont = fontFromName(dict, dict->BaseFont().c_str());
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000388 fEncoding = NULL;
389
390 if (dict->has_Encoding()) {
391 if (dict->isEncodingAName()) {
392 fEncoding = SkPdfEncoding::fromName(dict->getEncodingAsName().c_str());
393 } else if (dict->isEncodingAStream()) {
394 //fEncoding = loadEncodingFromStream(dict->getEncodingAsStream());
395 } else {
396 // TODO(edisonn): error ... warning .. assert?
397 }
398 }
399
400 if (dict->has_ToUnicode()) {
401 fToUnicode = new SkPdfToUnicode(dict->ToUnicode());
402 }
403}
404
405std::map<std::string, SkPdfEncoding*>& getStandardEncodings() {
406 static std::map<std::string, SkPdfEncoding*> encodings;
407 if (encodings.empty()) {
408 encodings["Identity-H"] = SkPdfIdentityHEncoding::instance();
409 }
410
411 return encodings;
412}
413
414
415SkPdfEncoding* SkPdfEncoding::fromName(const char* name) {
416 SkPdfEncoding* encoding = getStandardEncodings()[name];
417
418#ifdef PDF_TRACE
419 if (encoding == NULL) {
420 printf("Encoding not found: %s\n", name);
421 }
422#endif
423 return encoding;
424}