blob: 520c820f1bdb0bb1cc903cc56fd467e9efbb07ce [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
73 gPdfStandardFonts["Arial-Black"] = {"Arial", true, false};
74 gPdfStandardFonts["DejaVuSans"] = {"DejaVu Sans", false, false};
75 gPdfStandardFonts["DejaVuSansMono"] = {"DejaVuSans Mono", false, false};
76 gPdfStandardFonts["DejaVuSansMono-Bold"] = {"DejaVuSans Mono", true, false};
77 gPdfStandardFonts["DejaVuSansMono-Oblique"] = {"DejaVuSans Mono", false, true};
78 gPdfStandardFonts["Georgia-Bold"] = {"Georgia", true, false};
79 gPdfStandardFonts["Georgia-BoldItalic"] = {"Georgia", true, true};
80 gPdfStandardFonts["Georgia-Italic"] = {"Georgia", false, true};
81 gPdfStandardFonts["TrebuchetMS"] = {"Trebuchet MS", false, false};
82 gPdfStandardFonts["TrebuchetMS-Bold"] = {"Trebuchet MS", true, false};
83 gPdfStandardFonts["Verdana-Bold"] = {"Verdana", true, false};
84 gPdfStandardFonts["WenQuanYiMicroHei"] = {"WenQuanYi Micro Hei", false, false};
85 }
86
87 return gPdfStandardFonts;
88}
89
90SkTypeface* SkTypefaceFromPdfStandardFont(const char* fontName, bool bold, bool italic) {
91 std::map<std::string, SkPdfStandardFontEntry>& standardFontMap = getStandardFonts();
92
93 SkTypeface* typeface = NULL;
94 if (standardFontMap.find(fontName) != standardFontMap.end()) {
95 SkPdfStandardFontEntry fontData = standardFontMap[fontName];
96
97 // TODO(edisonn): How does the bold/italic specified in standard definition combines with
98 // the one in /font key? use OR for now.
99 bold = bold || fontData.fIsBold;
100 italic = italic || fontData.fIsItalic;
101
102 typeface = SkTypeface::CreateFromName(
103 fontData.fName,
104 SkTypeface::Style((bold ? SkTypeface::kBold : 0) |
105 (italic ? SkTypeface::kItalic : 0)));
106 } else {
107 typeface = SkTypeface::CreateFromName(
108 fontName,
109 SkTypeface::kNormal);
110 }
111
112 if (typeface) {
113 typeface->ref();
114 }
115 return typeface;
116}
117
118SkPdfFont* SkPdfFontFromName(SkPdfObject* obj, const char* fontName) {
119 SkTypeface* typeface = SkTypefaceFromPdfStandardFont(fontName, false, false);
120 if (typeface != NULL) {
121 return new SkPdfStandardFont(typeface);
122 }
123// SkPdfObject* font = obtainFont(pdfContext, fontName);
124// if (!font->asFontDictionary()) {
125// return NULL;
126// }
127// SkPdfFont::fontFromPdfDictionary(font->asDictionary());
128// }
129 // TODO(edisonn): deal with inherited fonts, load from parent objects
130 return SkPdfFont::Default();
131}
132
133SkPdfFont* SkPdfFont::fontFromPdfDictionary(SkPdfFontDictionary* dict) {
134 if (dict == NULL) {
135 return NULL; // TODO(edisonn): report default one?
136 }
137
138 switch (dict->getType()) {
139 case kType0FontDictionary_SkPdfObjectType:
140 return fontFromType0FontDictionary(dict->asType0FontDictionary());
141
142 case kTrueTypeFontDictionary_SkPdfObjectType:
143 return fontFromTrueTypeFontDictionary(dict->asTrueTypeFontDictionary());
144
145 case kType1FontDictionary_SkPdfObjectType:
146 return fontFromType1FontDictionary(dict->asType1FontDictionary());
147
148 case kCIDFontDictionary_SkPdfObjectType:
149 return fontFromCIDFontDictionary(dict->asCIDFontDictionary());
150
151 case kMultiMasterFontDictionary_SkPdfObjectType:
152 return fontFromMultiMasterFontDictionary(dict->asMultiMasterFontDictionary());
153
154 case kType3FontDictionary_SkPdfObjectType:
155 return fontFromType3FontDictionary(dict->asType3FontDictionary());
156 }
157 return NULL; // TODO(edisonn): report error?
158}
159
160SkPdfType0Font* SkPdfFont::fontFromType0FontDictionary(SkPdfType0FontDictionary* dict) {
161 if (dict == NULL) {
162 return NULL; // default one?
163 }
164
165 return new SkPdfType0Font(dict);
166}
167
168SkPdfType1Font* SkPdfFont:: fontFromType1FontDictionary(SkPdfType1FontDictionary* dict) {
169 if (dict == NULL) {
170 return NULL; // default one?
171 }
172
173 return new SkPdfType1Font(dict);
174}
175
176SkPdfType3Font* SkPdfFont::fontFromType3FontDictionary(SkPdfType3FontDictionary* dict) {
177 if (dict == NULL) {
178 return NULL; // default one?
179 }
180
181 return new SkPdfType3Font(dict);
182}
183
184SkPdfTrueTypeFont* SkPdfFont::fontFromTrueTypeFontDictionary(SkPdfTrueTypeFontDictionary* dict) {
185 if (dict == NULL) {
186 return NULL; // default one?
187 }
188
189 return new SkPdfTrueTypeFont(dict);
190}
191
192SkPdfCIDFont* SkPdfFont::fontFromCIDFontDictionary(SkPdfCIDFontDictionary* dict) {
193 if (dict == NULL) {
194 return NULL; // default one?
195 }
196
197 return new SkPdfCIDFont(dict);
198}
199
200SkPdfMultiMasterFont* SkPdfFont::fontFromMultiMasterFontDictionary(SkPdfMultiMasterFontDictionary* dict) {
201 if (dict == NULL) {
202 return NULL; // default one?
203 }
204
205 return new SkPdfMultiMasterFont(dict);
206}
207
208static int skstoi(const SkPdfString* str) {
209 int ret = 0;
210 for (int i = 0 ; i < str->podofo()->GetString().GetLength(); i++) {
211 ret = (ret << 8) + ((unsigned char*)str->podofo()->GetString().GetString())[i];
212 }
213 return ret;
214}
215
216SkPdfType0Font::SkPdfType0Font(SkPdfType0FontDictionary* dict) {
217 fBaseFont = SkPdfFontFromName(dict, dict->BaseFont().c_str());
218
219 // TODO(edisonn): load encoding, let it now to be Identity-H by default
220 if (dict->has_Encoding()) {
221 if (dict->isEncodingAName()) {
222 //report encoding not supported
223 //fEncoding = loadEncodingFromName(dict->getEncodingAsName().c_str());
224 } else if (dict->isEncodingAStream()) {
225 //fEncoding = loadEncodingFromStream(dict->getEncodingAsStream());
226 } else {
227 // error
228 }
229 }
230
231 fCMapEncoding = NULL;
232 fCMapEncodingFlag = NULL;
233
234 if (dict->has_ToUnicode()) {
235 const SkPdfStream* stream = dict->ToUnicode();
236 SkPdfTokenizer tokenizer(stream);
237 PdfToken token;
238
239 fCMapEncoding = new unsigned short[256 * 256];
240 fCMapEncodingFlag = new unsigned char[256 * 256];
241 for (int i = 0 ; i < 256 * 256; i++) {
242 fCMapEncoding[i] = i;
243 fCMapEncodingFlag[i] = 0;
244 }
245
246 // TODO(edisonn): deal with multibyte character, or longer strings.
247 // Ritght now we deal with up 2 characters, e.g. <0020> but not longer like <00660066006C>
248 //2 beginbfrange
249 //<0000> <005E> <0020>
250 //<005F> <0061> [<00660066> <00660069> <00660066006C>]
251
252 while (tokenizer.readToken(&token)) {
253
254 if (token.fType == kKeyword_TokenType && strcmp(token.fKeyword, "begincodespacerange") == 0) {
255 while (tokenizer.readToken(&token) && !(token.fType == kKeyword_TokenType && strcmp(token.fKeyword, "endcodespacerange") == 0)) {
256// tokenizer.PutBack(token);
257// tokenizer.readToken(&token);
258 // TODO(edisonn): check token type! ignore/report errors.
259 int start = skstoi(token.fObject->asString());
260 tokenizer.readToken(&token);
261 int end = skstoi(token.fObject->asString());
262 for (int i = start; i <= end; i++) {
263 fCMapEncodingFlag[i] |= 1;
264 }
265 }
266 }
267
268 if (token.fType == kKeyword_TokenType && strcmp(token.fKeyword, "beginbfchar") == 0) {
269 while (tokenizer.readToken(&token) && !(token.fType == kKeyword_TokenType && strcmp(token.fKeyword, "endbfchar") == 0)) {
270// tokenizer.PutBack(token);
271// tokenizer.readToken(&token);
272 int from = skstoi(token.fObject->asString());
273 tokenizer.readToken(&token);
274 int to = skstoi(token.fObject->asString());
275
276 fCMapEncodingFlag[from] |= 2;
277 fCMapEncoding[from] = to;
278 }
279 }
280
281 if (token.fType == kKeyword_TokenType && strcmp(token.fKeyword, "beginbfrange") == 0) {
282 while (tokenizer.readToken(&token) && !(token.fType == kKeyword_TokenType && strcmp(token.fKeyword, "endbfrange") == 0)) {
283// tokenizer.PutBack(token);
284// tokenizer.readToken(&token);
285 int start = skstoi(token.fObject->asString());
286 tokenizer.readToken(&token);
287 int end = skstoi(token.fObject->asString());
288
289
290 tokenizer.readToken(&token); // [ or just an array directly?
291// tokenizer.PutBack(token);
292
293 if (token.fType == kObject_TokenType && token.fObject->asString()) {
294// tokenizer.readToken(&token);
295 int value = skstoi(token.fObject->asString());
296
297 for (int i = start; i <= end; i++) {
298 fCMapEncodingFlag[i] |= 2;
299 fCMapEncoding[i] = value;
300 value++;
301 // if i != end, verify last byte id not if, ignore/report error
302 }
303
304 // read one string
305 } else if (token.fType == kObject_TokenType && token.fObject->asArray()) {
306// tokenizer.readToken(&token);
307 for (int i = 0; i < token.fObject->asArray()->size(); i++) {
308 fCMapEncodingFlag[start + i] |= 2;
309 fCMapEncoding[start + i] = skstoi((*token.fObject->asArray())[i]->asString());
310 }
311 // read array
312 }
313
314 //fCMapEncodingFlag[from] = 1;
315 //fCMapEncoding[from] = to;
316 }
317 }
318 }
319 }
320}