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