blob: 4fac286ec201de106bbec8279d5fc8cdaf22cb76 [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
4std::map<std::string, SkPdfStandardFontEntry>& getStandardFonts() {
5 static std::map<std::string, SkPdfStandardFontEntry> gPdfStandardFonts;
6
7 // TODO (edisonn): , vs - ? what does it mean?
8 // TODO (edisonn): MT, PS, Oblique=italic?, ... what does it mean?
9 if (gPdfStandardFonts.empty()) {
10 gPdfStandardFonts["Arial"] = {"Arial", false, false};
11 gPdfStandardFonts["Arial,Bold"] = {"Arial", true, false};
12 gPdfStandardFonts["Arial,BoldItalic"] = {"Arial", true, true};
13 gPdfStandardFonts["Arial,Italic"] = {"Arial", false, true};
14 gPdfStandardFonts["Arial-Bold"] = {"Arial", true, false};
15 gPdfStandardFonts["Arial-BoldItalic"] = {"Arial", true, true};
16 gPdfStandardFonts["Arial-BoldItalicMT"] = {"Arial", true, true};
17 gPdfStandardFonts["Arial-BoldMT"] = {"Arial", true, false};
18 gPdfStandardFonts["Arial-Italic"] = {"Arial", false, true};
19 gPdfStandardFonts["Arial-ItalicMT"] = {"Arial", false, true};
20 gPdfStandardFonts["ArialMT"] = {"Arial", false, false};
21 gPdfStandardFonts["Courier"] = {"Courier New", false, false};
22 gPdfStandardFonts["Courier,Bold"] = {"Courier New", true, false};
23 gPdfStandardFonts["Courier,BoldItalic"] = {"Courier New", true, true};
24 gPdfStandardFonts["Courier,Italic"] = {"Courier New", false, true};
25 gPdfStandardFonts["Courier-Bold"] = {"Courier New", true, false};
26 gPdfStandardFonts["Courier-BoldOblique"] = {"Courier New", true, true};
27 gPdfStandardFonts["Courier-Oblique"] = {"Courier New", false, true};
28 gPdfStandardFonts["CourierNew"] = {"Courier New", false, false};
29 gPdfStandardFonts["CourierNew,Bold"] = {"Courier New", true, false};
30 gPdfStandardFonts["CourierNew,BoldItalic"] = {"Courier New", true, true};
31 gPdfStandardFonts["CourierNew,Italic"] = {"Courier New", false, true};
32 gPdfStandardFonts["CourierNew-Bold"] = {"Courier New", true, false};
33 gPdfStandardFonts["CourierNew-BoldItalic"] = {"Courier New", true, true};
34 gPdfStandardFonts["CourierNew-Italic"] = {"Courier New", false, true};
35 gPdfStandardFonts["CourierNewPS-BoldItalicMT"] = {"Courier New", true, true};
36 gPdfStandardFonts["CourierNewPS-BoldMT"] = {"Courier New", true, false};
37 gPdfStandardFonts["CourierNewPS-ItalicMT"] = {"Courier New", false, true};
38 gPdfStandardFonts["CourierNewPSMT"] = {"Courier New", false, false};
39 gPdfStandardFonts["Helvetica"] = {"Helvetica", false, false};
40 gPdfStandardFonts["Helvetica,Bold"] = {"Helvetica", true, false};
41 gPdfStandardFonts["Helvetica,BoldItalic"] = {"Helvetica", true, true};
42 gPdfStandardFonts["Helvetica,Italic"] = {"Helvetica", false, true};
43 gPdfStandardFonts["Helvetica-Bold"] = {"Helvetica", true, false};
44 gPdfStandardFonts["Helvetica-BoldItalic"] = {"Helvetica", true, true};
45 gPdfStandardFonts["Helvetica-BoldOblique"] = {"Helvetica", true, true};
46 gPdfStandardFonts["Helvetica-Italic"] = {"Helvetica", false, true};
47 gPdfStandardFonts["Helvetica-Oblique"] = {"Helvetica", false, true};
48 gPdfStandardFonts["Times-Bold"] = {"Times New Roman", true, false};
49 gPdfStandardFonts["Times-BoldItalic"] = {"Times New Roman", true, true};
50 gPdfStandardFonts["Times-Italic"] = {"Times New Roman", false, true};
51 gPdfStandardFonts["Times-Roman"] = {"Times New Roman", false, false};
52 gPdfStandardFonts["TimesNewRoman"] = {"Times New Roman", false, false};
53 gPdfStandardFonts["TimesNewRoman,Bold"] = {"Times New Roman", true, false};
54 gPdfStandardFonts["TimesNewRoman,BoldItalic"] = {"Times New Roman", true, true};
55 gPdfStandardFonts["TimesNewRoman,Italic"] = {"Times New Roman", false, true};
56 gPdfStandardFonts["TimesNewRoman-Bold"] = {"Times New Roman", true, false};
57 gPdfStandardFonts["TimesNewRoman-BoldItalic"] = {"Times New Roman", true, true};
58 gPdfStandardFonts["TimesNewRoman-Italic"] = {"Times New Roman", false, true};
59 gPdfStandardFonts["TimesNewRomanPS"] = {"Times New Roman", false, false};
60 gPdfStandardFonts["TimesNewRomanPS-Bold"] = {"Times New Roman", true, false};
61 gPdfStandardFonts["TimesNewRomanPS-BoldItalic"] = {"Times New Roman", true, true};
62 gPdfStandardFonts["TimesNewRomanPS-BoldItalicMT"] = {"Times New Roman", true, true};
63 gPdfStandardFonts["TimesNewRomanPS-BoldMT"] = {"Times New Roman", true, false};
64 gPdfStandardFonts["TimesNewRomanPS-Italic"] = {"Times New Roman", false, true};
65 gPdfStandardFonts["TimesNewRomanPS-ItalicMT"] = {"Times New Roman", false, true};
66 gPdfStandardFonts["TimesNewRomanPSMT"] = {"Times New Roman", false, false};
67 gPdfStandardFonts["Symbol"] = {"Symbol", false, false};
68 gPdfStandardFonts["ZapfDingbats"] = {"ZapfDingbats", false, false};
69
70 // TODO(edisonn): these are hacks. Load Post Script font name.
71 // see FT_Get_Postscript_Name
72 // Font config is not using it, yet.
73 //https://bugs.freedesktop.org/show_bug.cgi?id=18095
edisonn@google.comb857a0c2013-06-25 20:45:40 +000074
edisonn@google.com1be794f2013-06-21 21:43:09 +000075 gPdfStandardFonts["Arial-Black"] = {"Arial", true, false};
76 gPdfStandardFonts["DejaVuSans"] = {"DejaVu Sans", false, false};
77 gPdfStandardFonts["DejaVuSansMono"] = {"DejaVuSans Mono", false, false};
78 gPdfStandardFonts["DejaVuSansMono-Bold"] = {"DejaVuSans Mono", true, false};
79 gPdfStandardFonts["DejaVuSansMono-Oblique"] = {"DejaVuSans Mono", false, true};
80 gPdfStandardFonts["Georgia-Bold"] = {"Georgia", true, false};
81 gPdfStandardFonts["Georgia-BoldItalic"] = {"Georgia", true, true};
82 gPdfStandardFonts["Georgia-Italic"] = {"Georgia", false, true};
83 gPdfStandardFonts["TrebuchetMS"] = {"Trebuchet MS", false, false};
84 gPdfStandardFonts["TrebuchetMS-Bold"] = {"Trebuchet MS", true, false};
85 gPdfStandardFonts["Verdana-Bold"] = {"Verdana", true, false};
86 gPdfStandardFonts["WenQuanYiMicroHei"] = {"WenQuanYi Micro Hei", false, false};
edisonn@google.comb857a0c2013-06-25 20:45:40 +000087
88 // TODO(edisonn): list all phonts available, builf post script name as in pdf spec
89 /*
90 * The PostScript name for the value of BaseFontis determined in one of two ways:
91• Use the PostScript name that is an optional entry in the “name” table of the
92TrueType font itself.
93• In the absence of such an entry in the “name” table, derive a PostScript name
94from the name by which the font is known in the host operating system: on a
95Windows system, it is based on the lfFaceName field in a LOGFONT structure; in
96the Mac OS, it is based on the name of the FONDresource. If the name contains
97any spaces, the spaces are removed.
98If the font in a source document uses a bold or italic style, but there is no font
99data for that style, the host operating system will synthesize the style. In this case,
100a comma and the style name (one of Bold, Italic, or BoldItalic) are appended to the
101font name. For example, for a TrueType font that is a bold variant of the New
102 */
103
104 /*
105 * If the value of Subtype is MMType1.
106• If the PostScript name of the instance contains spaces, the spaces are replaced
107by underscores in the value of BaseFont. For instance, as illustrated in Example
1085.7, the name “MinionMM 366 465 11 ” (which ends with a space character)
109becomes /MinionMM_366_465_11_.
110 */
111
112 // might not work on all oses ?
113 //
114
edisonn@google.com1be794f2013-06-21 21:43:09 +0000115 }
116
117 return gPdfStandardFonts;
118}
119
120SkTypeface* SkTypefaceFromPdfStandardFont(const char* fontName, bool bold, bool italic) {
121 std::map<std::string, SkPdfStandardFontEntry>& standardFontMap = getStandardFonts();
122
123 SkTypeface* typeface = NULL;
124 if (standardFontMap.find(fontName) != standardFontMap.end()) {
125 SkPdfStandardFontEntry fontData = standardFontMap[fontName];
126
127 // TODO(edisonn): How does the bold/italic specified in standard definition combines with
128 // the one in /font key? use OR for now.
129 bold = bold || fontData.fIsBold;
130 italic = italic || fontData.fIsItalic;
131
132 typeface = SkTypeface::CreateFromName(
133 fontData.fName,
134 SkTypeface::Style((bold ? SkTypeface::kBold : 0) |
135 (italic ? SkTypeface::kItalic : 0)));
136 } else {
137 typeface = SkTypeface::CreateFromName(
138 fontName,
139 SkTypeface::kNormal);
140 }
141
142 if (typeface) {
143 typeface->ref();
144 }
145 return typeface;
146}
147
148SkPdfFont* SkPdfFontFromName(SkPdfObject* obj, const char* fontName) {
149 SkTypeface* typeface = SkTypefaceFromPdfStandardFont(fontName, false, false);
150 if (typeface != NULL) {
151 return new SkPdfStandardFont(typeface);
152 }
153// SkPdfObject* font = obtainFont(pdfContext, fontName);
154// if (!font->asFontDictionary()) {
155// return NULL;
156// }
157// SkPdfFont::fontFromPdfDictionary(font->asDictionary());
158// }
159 // TODO(edisonn): deal with inherited fonts, load from parent objects
160 return SkPdfFont::Default();
161}
162
163SkPdfFont* SkPdfFont::fontFromPdfDictionary(SkPdfFontDictionary* dict) {
164 if (dict == NULL) {
165 return NULL; // TODO(edisonn): report default one?
166 }
167
168 switch (dict->getType()) {
169 case kType0FontDictionary_SkPdfObjectType:
170 return fontFromType0FontDictionary(dict->asType0FontDictionary());
171
172 case kTrueTypeFontDictionary_SkPdfObjectType:
173 return fontFromTrueTypeFontDictionary(dict->asTrueTypeFontDictionary());
174
175 case kType1FontDictionary_SkPdfObjectType:
176 return fontFromType1FontDictionary(dict->asType1FontDictionary());
177
178 case kCIDFontDictionary_SkPdfObjectType:
179 return fontFromCIDFontDictionary(dict->asCIDFontDictionary());
180
181 case kMultiMasterFontDictionary_SkPdfObjectType:
182 return fontFromMultiMasterFontDictionary(dict->asMultiMasterFontDictionary());
183
184 case kType3FontDictionary_SkPdfObjectType:
185 return fontFromType3FontDictionary(dict->asType3FontDictionary());
186 }
187 return NULL; // TODO(edisonn): report error?
188}
189
190SkPdfType0Font* SkPdfFont::fontFromType0FontDictionary(SkPdfType0FontDictionary* dict) {
191 if (dict == NULL) {
192 return NULL; // default one?
193 }
194
195 return new SkPdfType0Font(dict);
196}
197
198SkPdfType1Font* SkPdfFont:: fontFromType1FontDictionary(SkPdfType1FontDictionary* dict) {
199 if (dict == NULL) {
200 return NULL; // default one?
201 }
202
203 return new SkPdfType1Font(dict);
204}
205
206SkPdfType3Font* SkPdfFont::fontFromType3FontDictionary(SkPdfType3FontDictionary* dict) {
207 if (dict == NULL) {
208 return NULL; // default one?
209 }
210
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000211
212
edisonn@google.com1be794f2013-06-21 21:43:09 +0000213 return new SkPdfType3Font(dict);
214}
215
216SkPdfTrueTypeFont* SkPdfFont::fontFromTrueTypeFontDictionary(SkPdfTrueTypeFontDictionary* dict) {
217 if (dict == NULL) {
218 return NULL; // default one?
219 }
220
221 return new SkPdfTrueTypeFont(dict);
222}
223
224SkPdfCIDFont* SkPdfFont::fontFromCIDFontDictionary(SkPdfCIDFontDictionary* dict) {
225 if (dict == NULL) {
226 return NULL; // default one?
227 }
228
229 return new SkPdfCIDFont(dict);
230}
231
232SkPdfMultiMasterFont* SkPdfFont::fontFromMultiMasterFontDictionary(SkPdfMultiMasterFontDictionary* dict) {
233 if (dict == NULL) {
234 return NULL; // default one?
235 }
236
237 return new SkPdfMultiMasterFont(dict);
238}
239
240static int skstoi(const SkPdfString* str) {
241 int ret = 0;
242 for (int i = 0 ; i < str->podofo()->GetString().GetLength(); i++) {
243 ret = (ret << 8) + ((unsigned char*)str->podofo()->GetString().GetString())[i];
244 }
245 return ret;
246}
247
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000248SkPdfToUnicode::SkPdfToUnicode(const SkPdfStream* stream) {
edisonn@google.com1be794f2013-06-21 21:43:09 +0000249 fCMapEncoding = NULL;
250 fCMapEncodingFlag = NULL;
251
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000252 if (stream) {
edisonn@google.com1be794f2013-06-21 21:43:09 +0000253 SkPdfTokenizer tokenizer(stream);
254 PdfToken token;
255
256 fCMapEncoding = new unsigned short[256 * 256];
257 fCMapEncodingFlag = new unsigned char[256 * 256];
258 for (int i = 0 ; i < 256 * 256; i++) {
259 fCMapEncoding[i] = i;
260 fCMapEncodingFlag[i] = 0;
261 }
262
263 // TODO(edisonn): deal with multibyte character, or longer strings.
264 // Ritght now we deal with up 2 characters, e.g. <0020> but not longer like <00660066006C>
265 //2 beginbfrange
266 //<0000> <005E> <0020>
267 //<005F> <0061> [<00660066> <00660069> <00660066006C>]
268
269 while (tokenizer.readToken(&token)) {
270
271 if (token.fType == kKeyword_TokenType && strcmp(token.fKeyword, "begincodespacerange") == 0) {
272 while (tokenizer.readToken(&token) && !(token.fType == kKeyword_TokenType && strcmp(token.fKeyword, "endcodespacerange") == 0)) {
273// tokenizer.PutBack(token);
274// tokenizer.readToken(&token);
275 // TODO(edisonn): check token type! ignore/report errors.
276 int start = skstoi(token.fObject->asString());
277 tokenizer.readToken(&token);
278 int end = skstoi(token.fObject->asString());
279 for (int i = start; i <= end; i++) {
280 fCMapEncodingFlag[i] |= 1;
281 }
282 }
283 }
284
285 if (token.fType == kKeyword_TokenType && strcmp(token.fKeyword, "beginbfchar") == 0) {
286 while (tokenizer.readToken(&token) && !(token.fType == kKeyword_TokenType && strcmp(token.fKeyword, "endbfchar") == 0)) {
287// tokenizer.PutBack(token);
288// tokenizer.readToken(&token);
289 int from = skstoi(token.fObject->asString());
290 tokenizer.readToken(&token);
291 int to = skstoi(token.fObject->asString());
292
293 fCMapEncodingFlag[from] |= 2;
294 fCMapEncoding[from] = to;
295 }
296 }
297
298 if (token.fType == kKeyword_TokenType && strcmp(token.fKeyword, "beginbfrange") == 0) {
299 while (tokenizer.readToken(&token) && !(token.fType == kKeyword_TokenType && strcmp(token.fKeyword, "endbfrange") == 0)) {
300// tokenizer.PutBack(token);
301// tokenizer.readToken(&token);
302 int start = skstoi(token.fObject->asString());
303 tokenizer.readToken(&token);
304 int end = skstoi(token.fObject->asString());
305
306
307 tokenizer.readToken(&token); // [ or just an array directly?
308// tokenizer.PutBack(token);
309
310 if (token.fType == kObject_TokenType && token.fObject->asString()) {
311// tokenizer.readToken(&token);
312 int value = skstoi(token.fObject->asString());
313
314 for (int i = start; i <= end; i++) {
315 fCMapEncodingFlag[i] |= 2;
316 fCMapEncoding[i] = value;
317 value++;
318 // if i != end, verify last byte id not if, ignore/report error
319 }
320
321 // read one string
322 } else if (token.fType == kObject_TokenType && token.fObject->asArray()) {
323// tokenizer.readToken(&token);
324 for (int i = 0; i < token.fObject->asArray()->size(); i++) {
325 fCMapEncodingFlag[start + i] |= 2;
326 fCMapEncoding[start + i] = skstoi((*token.fObject->asArray())[i]->asString());
327 }
328 // read array
329 }
330
331 //fCMapEncodingFlag[from] = 1;
332 //fCMapEncoding[from] = to;
333 }
334 }
335 }
336 }
337}
edisonn@google.comb857a0c2013-06-25 20:45:40 +0000338
339
340SkPdfType0Font::SkPdfType0Font(SkPdfType0FontDictionary* dict) {
341 fBaseFont = SkPdfFontFromName(dict, dict->BaseFont().c_str());
342 fEncoding = NULL;
343
344 if (dict->has_Encoding()) {
345 if (dict->isEncodingAName()) {
346 fEncoding = SkPdfEncoding::fromName(dict->getEncodingAsName().c_str());
347 } else if (dict->isEncodingAStream()) {
348 //fEncoding = loadEncodingFromStream(dict->getEncodingAsStream());
349 } else {
350 // TODO(edisonn): error ... warning .. assert?
351 }
352 }
353
354 if (dict->has_ToUnicode()) {
355 fToUnicode = new SkPdfToUnicode(dict->ToUnicode());
356 }
357}
358
359std::map<std::string, SkPdfEncoding*>& getStandardEncodings() {
360 static std::map<std::string, SkPdfEncoding*> encodings;
361 if (encodings.empty()) {
362 encodings["Identity-H"] = SkPdfIdentityHEncoding::instance();
363 }
364
365 return encodings;
366}
367
368
369SkPdfEncoding* SkPdfEncoding::fromName(const char* name) {
370 SkPdfEncoding* encoding = getStandardEncodings()[name];
371
372#ifdef PDF_TRACE
373 if (encoding == NULL) {
374 printf("Encoding not found: %s\n", name);
375 }
376#endif
377 return encoding;
378}