OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2011 The Android Open Source Project | 2 * Copyright 2011 The Android Open Source Project |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkFontConfigParser_android.h" | 8 #include "SkFontConfigParser_android.h" |
9 #include "SkFontMgr_android.h" | 9 #include "SkFontMgr_android.h" |
10 #include "SkStream.h" | 10 #include "SkStream.h" |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
52 kNameSet_CurrentTag, | 52 kNameSet_CurrentTag, |
53 kFileSet_CurrentTag | 53 kFileSet_CurrentTag |
54 }; | 54 }; |
55 | 55 |
56 /** | 56 /** |
57 * The FamilyData structure is passed around by the parser so that each handler | 57 * The FamilyData structure is passed around by the parser so that each handler |
58 * can read these variables that are relevant to the current parsing. | 58 * can read these variables that are relevant to the current parsing. |
59 */ | 59 */ |
60 struct FamilyData { | 60 struct FamilyData { |
61 FamilyData(XML_Parser parser, SkTDArray<FontFamily*>& families, | 61 FamilyData(XML_Parser parser, SkTDArray<FontFamily*>& families, |
62 const SkString& basePath, bool isFallback) | 62 const SkString& basePath, bool isFallback, const char* filename) |
63 : fParser(parser) | 63 : fParser(parser) |
64 , fFamilies(families) | 64 , fFamilies(families) |
65 , fCurrentFamily(NULL) | 65 , fCurrentFamily(NULL) |
66 , fCurrentFontInfo(NULL) | 66 , fCurrentFontInfo(NULL) |
67 , fCurrentTag(kNo_CurrentTag) | 67 , fCurrentTag(kNo_CurrentTag) |
68 , fVersion(0) | 68 , fVersion(0) |
69 , fBasePath(basePath) | 69 , fBasePath(basePath) |
70 , fIsFallback(isFallback) | 70 , fIsFallback(isFallback) |
| 71 , fFilename(filename) |
71 { }; | 72 { }; |
72 | 73 |
73 XML_Parser fParser; // The expat parser doing the work
, owned by caller | 74 XML_Parser fParser; // The expat parser doing the work
, owned by caller |
74 SkTDArray<FontFamily*>& fFamilies; // The array to append families, o
wned by caller | 75 SkTDArray<FontFamily*>& fFamilies; // The array to append families, o
wned by caller |
75 SkAutoTDelete<FontFamily> fCurrentFamily; // The family being created, owned
by this | 76 SkAutoTDelete<FontFamily> fCurrentFamily; // The family being created, owned
by this |
76 FontFileInfo* fCurrentFontInfo; // The fontInfo being created, own
ed by fCurrentFamily | 77 FontFileInfo* fCurrentFontInfo; // The fontInfo being created, own
ed by fCurrentFamily |
77 CurrentTag fCurrentTag; // The kind of tag currently being
parsed. | 78 CurrentTag fCurrentTag; // The kind of tag currently being
parsed. |
78 int fVersion; // The version of the file parsed. | 79 int fVersion; // The version of the file parsed. |
79 const SkString& fBasePath; // The current base path. | 80 const SkString& fBasePath; // The current base path. |
80 const bool fIsFallback; // Indicates the file being parsed
is a fallback file | 81 const bool fIsFallback; // Indicates the file being parsed
is a fallback file |
| 82 const char* fFilename; // The name of the file currently
being parsed. |
81 }; | 83 }; |
82 | 84 |
83 /** Parses a null terminated string into an integer type, checking for overflow. | 85 /** Parses a null terminated string into an integer type, checking for overflow. |
84 * http://www.w3.org/TR/html-markup/datatypes.html#common.data.integer.non-nega
tive-def | 86 * http://www.w3.org/TR/html-markup/datatypes.html#common.data.integer.non-nega
tive-def |
85 * | 87 * |
86 * If the string cannot be parsed into 'value', returns false and does not chan
ge 'value'. | 88 * If the string cannot be parsed into 'value', returns false and does not chan
ge 'value'. |
87 */ | 89 */ |
88 template <typename T> static bool parse_non_negative_integer(const char* s, T* v
alue) { | 90 template <typename T> static bool parse_non_negative_integer(const char* s, T* v
alue) { |
89 SK_COMPILE_ASSERT(std::numeric_limits<T>::is_integer, T_must_be_integer); | 91 SK_COMPILE_ASSERT(std::numeric_limits<T>::is_integer, T_must_be_integer); |
90 const T nMax = std::numeric_limits<T>::max() / 10; | 92 const T nMax = std::numeric_limits<T>::max() / 10; |
(...skipping 15 matching lines...) Expand all Loading... |
106 return true; | 108 return true; |
107 } | 109 } |
108 | 110 |
109 static bool memeq(const char* s1, const char* s2, size_t n1, size_t n2) { | 111 static bool memeq(const char* s1, const char* s2, size_t n1, size_t n2) { |
110 return n1 == n2 && 0 == memcmp(s1, s2, n1); | 112 return n1 == n2 && 0 == memcmp(s1, s2, n1); |
111 } | 113 } |
112 #define MEMEQ(c, s, n) memeq(c, s, sizeof(c) - 1, n) | 114 #define MEMEQ(c, s, n) memeq(c, s, sizeof(c) - 1, n) |
113 | 115 |
114 #define ATTS_NON_NULL(a, i) (a[i] != NULL && a[i+1] != NULL) | 116 #define ATTS_NON_NULL(a, i) (a[i] != NULL && a[i+1] != NULL) |
115 | 117 |
| 118 #define SK_FONTCONFIGPARSER_PREFIX "[SkFontConfigParser] " |
| 119 |
| 120 #define SK_FONTCONFIGPARSER_WARNING(message, ...) SkDebugf( \ |
| 121 SK_FONTCONFIGPARSER_PREFIX "%s:%d:%d: warning: " message "\n", \ |
| 122 self->fFilename, \ |
| 123 XML_GetCurrentLineNumber(self->fParser), \ |
| 124 XML_GetCurrentColumnNumber(self->fParser), \ |
| 125 ##__VA_ARGS__); |
| 126 |
116 namespace lmpParser { | 127 namespace lmpParser { |
117 | 128 |
118 static void family_element_handler(FontFamily* family, const char** attributes)
{ | 129 static void family_element_handler(FontFamily* family, const char** attributes)
{ |
119 // A non-fallback <family> tag must have a canonical name attribute. | 130 // A <family> element without a 'name' (string) attribute is a fallback font
. |
120 // A fallback <family> tag has no name, and may have lang and variant | 131 // The element may have 'lang' (string) and 'variant' ("elegant", "compact")
attributes. |
121 // attributes. | 132 // The element should contain <font> elements. |
122 family->fIsFallbackFont = true; | 133 family->fIsFallbackFont = true; |
123 for (size_t i = 0; ATTS_NON_NULL(attributes, i); i += 2) { | 134 for (size_t i = 0; ATTS_NON_NULL(attributes, i); i += 2) { |
124 const char* name = attributes[i]; | 135 const char* name = attributes[i]; |
125 const char* value = attributes[i+1]; | 136 const char* value = attributes[i+1]; |
126 size_t nameLen = strlen(name); | 137 size_t nameLen = strlen(name); |
127 size_t valueLen = strlen(value); | 138 size_t valueLen = strlen(value); |
128 if (MEMEQ("name", name, nameLen)) { | 139 if (MEMEQ("name", name, nameLen)) { |
129 SkAutoAsciiToLC tolc(value); | 140 SkAutoAsciiToLC tolc(value); |
130 family->fNames.push_back().set(tolc.lc()); | 141 family->fNames.push_back().set(tolc.lc()); |
131 family->fIsFallbackFont = false; | 142 family->fIsFallbackFont = false; |
132 } else if (MEMEQ("lang", name, nameLen)) { | 143 } else if (MEMEQ("lang", name, nameLen)) { |
133 family->fLanguage = SkLanguage(value, valueLen); | 144 family->fLanguage = SkLanguage(value, valueLen); |
134 } else if (MEMEQ("variant", name, nameLen)) { | 145 } else if (MEMEQ("variant", name, nameLen)) { |
135 // Value should be either elegant or compact. | |
136 if (MEMEQ("elegant", value, valueLen)) { | 146 if (MEMEQ("elegant", value, valueLen)) { |
137 family->fVariant = kElegant_FontVariant; | 147 family->fVariant = kElegant_FontVariant; |
138 } else if (MEMEQ("compact", value, valueLen)) { | 148 } else if (MEMEQ("compact", value, valueLen)) { |
139 family->fVariant = kCompact_FontVariant; | 149 family->fVariant = kCompact_FontVariant; |
140 } | 150 } |
141 } | 151 } |
142 } | 152 } |
143 } | 153 } |
144 | 154 |
145 static void XMLCALL font_file_name_handler(void* data, const char* s, int len) { | 155 static void XMLCALL font_file_name_handler(void* data, const char* s, int len) { |
146 FamilyData* self = static_cast<FamilyData*>(data); | 156 FamilyData* self = static_cast<FamilyData*>(data); |
147 self->fCurrentFontInfo->fFileName.append(s, len); | 157 self->fCurrentFontInfo->fFileName.append(s, len); |
148 } | 158 } |
149 | 159 |
150 static void font_element_handler(FamilyData* self, FontFileInfo* file, const cha
r** attributes) { | 160 static void font_element_handler(FamilyData* self, FontFileInfo* file, const cha
r** attributes) { |
151 // A <font> should have weight (integer) and style (normal, italic) attribut
es. | 161 // A <font> element should be contained in a <family> element. |
152 // NOTE: we ignore the style. | 162 // The element may have 'weight' (non-negative integer), 'style' ("normal",
"italic"), |
| 163 // and 'index' (non-negative integer) attributes. |
153 // The element should contain a filename. | 164 // The element should contain a filename. |
154 for (size_t i = 0; ATTS_NON_NULL(attributes, i); i += 2) { | 165 for (size_t i = 0; ATTS_NON_NULL(attributes, i); i += 2) { |
155 const char* name = attributes[i]; | 166 const char* name = attributes[i]; |
156 const char* value = attributes[i+1]; | 167 const char* value = attributes[i+1]; |
157 size_t nameLen = strlen(name); | 168 size_t nameLen = strlen(name); |
158 if (MEMEQ("weight", name, nameLen)) { | 169 if (MEMEQ("weight", name, nameLen)) { |
159 if (!parse_non_negative_integer(value, &file->fWeight)) { | 170 if (!parse_non_negative_integer(value, &file->fWeight)) { |
160 SkDebugf("---- Font weight %s (INVALID)", value); | 171 SK_FONTCONFIGPARSER_WARNING("'%s' is an invalid weight", value); |
161 } | 172 } |
162 } else if (MEMEQ("style", name, nameLen)) { | 173 } else if (MEMEQ("style", name, nameLen)) { |
163 size_t valueLen = strlen(value); | 174 size_t valueLen = strlen(value); |
164 if (MEMEQ("normal", value, valueLen)) { | 175 if (MEMEQ("normal", value, valueLen)) { |
165 file->fStyle = FontFileInfo::Style::kNormal; | 176 file->fStyle = FontFileInfo::Style::kNormal; |
166 } else if (MEMEQ("italic", value, valueLen)) { | 177 } else if (MEMEQ("italic", value, valueLen)) { |
167 file->fStyle = FontFileInfo::Style::kItalic; | 178 file->fStyle = FontFileInfo::Style::kItalic; |
168 } | 179 } |
169 } else if (MEMEQ("index", name, nameLen)) { | 180 } else if (MEMEQ("index", name, nameLen)) { |
170 if (!parse_non_negative_integer(value, &file->fIndex)) { | 181 if (!parse_non_negative_integer(value, &file->fIndex)) { |
171 SkDebugf("---- Font index %s (INVALID)", value); | 182 SK_FONTCONFIGPARSER_WARNING("'%s' is an invalid index", value); |
172 } | 183 } |
173 } | 184 } |
174 } | 185 } |
175 XML_SetCharacterDataHandler(self->fParser, font_file_name_handler); | 186 XML_SetCharacterDataHandler(self->fParser, font_file_name_handler); |
176 } | 187 } |
177 | 188 |
178 static FontFamily* find_family(FamilyData* self, const SkString& familyName) { | 189 static FontFamily* find_family(FamilyData* self, const SkString& familyName) { |
179 for (int i = 0; i < self->fFamilies.count(); i++) { | 190 for (int i = 0; i < self->fFamilies.count(); i++) { |
180 FontFamily* candidate = self->fFamilies[i]; | 191 FontFamily* candidate = self->fFamilies[i]; |
181 for (int j = 0; j < candidate->fNames.count(); j++) { | 192 for (int j = 0; j < candidate->fNames.count(); j++) { |
182 if (candidate->fNames[j] == familyName) { | 193 if (candidate->fNames[j] == familyName) { |
183 return candidate; | 194 return candidate; |
184 } | 195 } |
185 } | 196 } |
186 } | 197 } |
187 return NULL; | 198 return NULL; |
188 } | 199 } |
189 | 200 |
190 static void alias_element_handler(FamilyData* self, const char** attributes) { | 201 static void alias_element_handler(FamilyData* self, const char** attributes) { |
191 // An <alias> must have name and to attributes. | 202 // A <alias> element must have 'name' (string) and 'to' (string) attributes. |
192 // It may have weight (integer). | 203 // The element may also have a 'weight' (non-negative integer) attribute. |
193 // If it *does not* have a weight, it is a variant name for a <family>. | 204 // The 'name' introduces a new family name. |
194 // If it *does* have a weight, it names the <font>(s) of a specific weight | 205 // The 'to' specifies which (previous) <family> to alias. |
195 // from a <family>. | 206 // If it *does not* have a weight, 'name' is an alias for the entire 'to' <f
amily>. |
| 207 // If it *does* have a weight, 'name' is a new family consisting of the <fon
t>(s) with 'weight' |
| 208 // from the 'to' <family>. |
196 | 209 |
197 SkString aliasName; | 210 SkString aliasName; |
198 SkString to; | 211 SkString to; |
199 int weight = 0; | 212 int weight = 0; |
200 for (size_t i = 0; ATTS_NON_NULL(attributes, i); i += 2) { | 213 for (size_t i = 0; ATTS_NON_NULL(attributes, i); i += 2) { |
201 const char* name = attributes[i]; | 214 const char* name = attributes[i]; |
202 const char* value = attributes[i+1]; | 215 const char* value = attributes[i+1]; |
203 size_t nameLen = strlen(name); | 216 size_t nameLen = strlen(name); |
204 if (MEMEQ("name", name, nameLen)) { | 217 if (MEMEQ("name", name, nameLen)) { |
205 SkAutoAsciiToLC tolc(value); | 218 SkAutoAsciiToLC tolc(value); |
206 aliasName.set(tolc.lc()); | 219 aliasName.set(tolc.lc()); |
207 } else if (MEMEQ("to", name, nameLen)) { | 220 } else if (MEMEQ("to", name, nameLen)) { |
208 to.set(value); | 221 to.set(value); |
209 } else if (MEMEQ("weight", name, nameLen)) { | 222 } else if (MEMEQ("weight", name, nameLen)) { |
210 if (!parse_non_negative_integer(value, &weight)) { | 223 if (!parse_non_negative_integer(value, &weight)) { |
211 SkDebugf("---- Font weight %s (INVALID)", value); | 224 SK_FONTCONFIGPARSER_WARNING("'%s' is an invalid weight", value); |
212 } | 225 } |
213 } | 226 } |
214 } | 227 } |
215 | 228 |
216 // Assumes that the named family is already declared | 229 // Assumes that the named family is already declared |
217 FontFamily* targetFamily = find_family(self, to); | 230 FontFamily* targetFamily = find_family(self, to); |
218 if (!targetFamily) { | 231 if (!targetFamily) { |
219 SkDebugf("---- Font alias target %s (NOT FOUND)", to.c_str()); | 232 SK_FONTCONFIGPARSER_WARNING("'%s' alias target not found", to.c_str()); |
220 return; | 233 return; |
221 } | 234 } |
222 | 235 |
223 if (weight) { | 236 if (weight) { |
224 FontFamily* family = new FontFamily(targetFamily->fBasePath, self->fIsFa
llback); | 237 FontFamily* family = new FontFamily(targetFamily->fBasePath, self->fIsFa
llback); |
225 family->fNames.push_back().set(aliasName); | 238 family->fNames.push_back().set(aliasName); |
226 | 239 |
227 for (int i = 0; i < targetFamily->fFonts.count(); i++) { | 240 for (int i = 0; i < targetFamily->fFonts.count(); i++) { |
228 if (targetFamily->fFonts[i].fWeight == weight) { | 241 if (targetFamily->fFonts[i].fWeight == weight) { |
229 family->fFonts.push_back(targetFamily->fFonts[i]); | 242 family->fFonts.push_back(targetFamily->fFonts[i]); |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
292 | 305 |
293 /** | 306 /** |
294 * Handler for font files. This processes the attributes for language and | 307 * Handler for font files. This processes the attributes for language and |
295 * variants then lets textHandler handle the actual file name | 308 * variants then lets textHandler handle the actual file name |
296 */ | 309 */ |
297 static void font_file_element_handler(FamilyData* self, const char** attributes)
{ | 310 static void font_file_element_handler(FamilyData* self, const char** attributes)
{ |
298 FontFamily& currentFamily = *self->fCurrentFamily.get(); | 311 FontFamily& currentFamily = *self->fCurrentFamily.get(); |
299 FontFileInfo& newFileInfo = currentFamily.fFonts.push_back(); | 312 FontFileInfo& newFileInfo = currentFamily.fFonts.push_back(); |
300 if (attributes) { | 313 if (attributes) { |
301 for (size_t i = 0; ATTS_NON_NULL(attributes, i); i += 2) { | 314 for (size_t i = 0; ATTS_NON_NULL(attributes, i); i += 2) { |
302 const char* attributeName = attributes[i]; | 315 const char* name = attributes[i]; |
303 const char* attributeValue = attributes[i+1]; | 316 const char* value = attributes[i+1]; |
304 size_t nameLength = strlen(attributeName); | 317 size_t nameLen = strlen(name); |
305 size_t valueLength = strlen(attributeValue); | 318 size_t valueLen = strlen(value); |
306 if (MEMEQ("variant", attributeName, nameLength)) { | 319 if (MEMEQ("variant", name, nameLen)) { |
307 const FontVariant prevVariant = currentFamily.fVariant; | 320 const FontVariant prevVariant = currentFamily.fVariant; |
308 if (MEMEQ("elegant", attributeValue, valueLength)) { | 321 if (MEMEQ("elegant", value, valueLen)) { |
309 currentFamily.fVariant = kElegant_FontVariant; | 322 currentFamily.fVariant = kElegant_FontVariant; |
310 } else if (MEMEQ("compact", attributeValue, valueLength)) { | 323 } else if (MEMEQ("compact", value, valueLen)) { |
311 currentFamily.fVariant = kCompact_FontVariant; | 324 currentFamily.fVariant = kCompact_FontVariant; |
312 } | 325 } |
313 if (currentFamily.fFonts.count() > 1 && currentFamily.fVariant !
= prevVariant) { | 326 if (currentFamily.fFonts.count() > 1 && currentFamily.fVariant !
= prevVariant) { |
314 SkDebugf("Every font file within a family must have identica
l variants"); | 327 SK_FONTCONFIGPARSER_WARNING("'%s' unexpected variant found\n
" |
| 328 "Note: Every font file within a family must have identic
al variants.", |
| 329 value); |
315 } | 330 } |
316 | 331 |
317 } else if (MEMEQ("lang", attributeName, nameLength)) { | 332 } else if (MEMEQ("lang", name, nameLen)) { |
318 SkLanguage prevLang = currentFamily.fLanguage; | 333 SkLanguage prevLang = currentFamily.fLanguage; |
319 currentFamily.fLanguage = SkLanguage(attributeValue, valueLength
); | 334 currentFamily.fLanguage = SkLanguage(value, valueLen); |
320 if (currentFamily.fFonts.count() > 1 && currentFamily.fLanguage
!= prevLang) { | 335 if (currentFamily.fFonts.count() > 1 && currentFamily.fLanguage
!= prevLang) { |
321 SkDebugf("Every font file within a family must have identica
l languages"); | 336 SK_FONTCONFIGPARSER_WARNING("'%s' unexpected language found\
n" |
| 337 "Note: Every font file within a family must have identic
al languages.", |
| 338 value); |
322 } | 339 } |
323 | 340 |
324 } else if (MEMEQ("index", attributeName, nameLength)) { | 341 } else if (MEMEQ("index", name, nameLen)) { |
325 if (!parse_non_negative_integer(attributeValue, &newFileInfo.fIn
dex)) { | 342 if (!parse_non_negative_integer(value, &newFileInfo.fIndex)) { |
326 SkDebugf("---- SystemFonts index=%s (INVALID)", attributeVal
ue); | 343 SK_FONTCONFIGPARSER_WARNING("'%s' is an invalid index", valu
e); |
327 } | 344 } |
328 } | 345 } |
329 } | 346 } |
330 } | 347 } |
331 self->fCurrentFontInfo = &newFileInfo; | 348 self->fCurrentFontInfo = &newFileInfo; |
332 XML_SetCharacterDataHandler(self->fParser, text_handler); | 349 XML_SetCharacterDataHandler(self->fParser, text_handler); |
333 } | 350 } |
334 | 351 |
335 /** | 352 /** |
336 * Handler for the start of a tag. The only tags we expect are familyset, family
, | 353 * Handler for the start of a tag. The only tags we expect are familyset, family
, |
337 * nameset, fileset, name, and file. | 354 * nameset, fileset, name, and file. |
338 */ | 355 */ |
339 static void XMLCALL start_element_handler(void* data, const char* tag, const cha
r** attributes) { | 356 static void XMLCALL start_element_handler(void* data, const char* tag, const cha
r** attributes) { |
340 FamilyData* self = static_cast<FamilyData*>(data); | 357 FamilyData* self = static_cast<FamilyData*>(data); |
341 size_t len = strlen(tag); | 358 size_t len = strlen(tag); |
342 if (MEMEQ("familyset", tag, len)) { | 359 if (MEMEQ("familyset", tag, len)) { |
343 // The familyset tag has an optional "version" attribute with an integer
value >= 0 | 360 // The <familyset> element has an optional 'version' (non-negative integ
er) attribute. |
344 for (size_t i = 0; ATTS_NON_NULL(attributes, i); i += 2) { | 361 for (size_t i = 0; ATTS_NON_NULL(attributes, i); i += 2) { |
345 size_t nameLen = strlen(attributes[i]); | 362 size_t nameLen = strlen(attributes[i]); |
346 if (!MEMEQ("version", attributes[i], nameLen)) continue; | 363 if (!MEMEQ("version", attributes[i], nameLen)) continue; |
347 const char* valueString = attributes[i+1]; | 364 const char* valueString = attributes[i+1]; |
348 int version; | 365 int version; |
349 if (parse_non_negative_integer(valueString, &version) && (version >=
21)) { | 366 if (parse_non_negative_integer(valueString, &version) && (version >=
21)) { |
350 XML_SetElementHandler(self->fParser, | 367 XML_SetElementHandler(self->fParser, |
351 lmpParser::start_element_handler, | 368 lmpParser::start_element_handler, |
352 lmpParser::end_element_handler); | 369 lmpParser::end_element_handler); |
353 self->fVersion = version; | 370 self->fVersion = version; |
354 } | 371 } |
355 } | 372 } |
356 } else if (MEMEQ("family", tag, len)) { | 373 } else if (MEMEQ("family", tag, len)) { |
357 self->fCurrentFamily.reset(new FontFamily(self->fBasePath, self->fIsFall
back)); | 374 self->fCurrentFamily.reset(new FontFamily(self->fBasePath, self->fIsFall
back)); |
358 // The Family tag has an optional "order" attribute with an integer valu
e >= 0 | 375 // The <family> element has an optional 'order' (non-negative integer) a
ttribute. |
359 // If this attribute does not exist, the default value is -1 | 376 // If this attribute does not exist, the default value is -1. |
360 for (size_t i = 0; ATTS_NON_NULL(attributes, i); i += 2) { | 377 for (size_t i = 0; ATTS_NON_NULL(attributes, i); i += 2) { |
361 const char* valueString = attributes[i+1]; | 378 const char* valueString = attributes[i+1]; |
362 int value; | 379 int value; |
363 if (parse_non_negative_integer(valueString, &value)) { | 380 if (parse_non_negative_integer(valueString, &value)) { |
364 self->fCurrentFamily->fOrder = value; | 381 self->fCurrentFamily->fOrder = value; |
365 } | 382 } |
366 } | 383 } |
367 } else if (MEMEQ("nameset", tag, len)) { | 384 } else if (MEMEQ("nameset", tag, len)) { |
368 self->fCurrentTag = kNameSet_CurrentTag; | 385 self->fCurrentTag = kNameSet_CurrentTag; |
369 } else if (MEMEQ("fileset", tag, len)) { | 386 } else if (MEMEQ("fileset", tag, len)) { |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
405 const XML_Char *entityName, | 422 const XML_Char *entityName, |
406 int is_parameter_entity, | 423 int is_parameter_entity, |
407 const XML_Char *value, | 424 const XML_Char *value, |
408 int value_length, | 425 int value_length, |
409 const XML_Char *base, | 426 const XML_Char *base, |
410 const XML_Char *systemId, | 427 const XML_Char *systemId, |
411 const XML_Char *publicId, | 428 const XML_Char *publicId, |
412 const XML_Char *notationName) | 429 const XML_Char *notationName) |
413 { | 430 { |
414 FamilyData* self = static_cast<FamilyData*>(data); | 431 FamilyData* self = static_cast<FamilyData*>(data); |
415 SkDebugf("Entity declaration %s found, stopping processing.", entityName); | 432 SK_FONTCONFIGPARSER_WARNING("'%s' entity declaration found, stopping process
ing", entityName); |
416 XML_StopParser(self->fParser, XML_FALSE); | 433 XML_StopParser(self->fParser, XML_FALSE); |
417 } | 434 } |
418 | 435 |
419 static const XML_Memory_Handling_Suite sk_XML_alloc = { | 436 static const XML_Memory_Handling_Suite sk_XML_alloc = { |
420 sk_malloc_throw, | 437 sk_malloc_throw, |
421 sk_realloc_throw, | 438 sk_realloc_throw, |
422 sk_free | 439 sk_free |
423 }; | 440 }; |
424 | 441 |
425 template<typename T> struct remove_ptr {typedef T type;}; | 442 template<typename T> struct remove_ptr {typedef T type;}; |
426 template<typename T> struct remove_ptr<T*> {typedef T type;}; | 443 template<typename T> struct remove_ptr<T*> {typedef T type;}; |
427 | 444 |
428 /** | 445 /** |
429 * This function parses the given filename and stores the results in the given | 446 * This function parses the given filename and stores the results in the given |
430 * families array. Returns the version of the file, negative if the file does no
t exist. | 447 * families array. Returns the version of the file, negative if the file does no
t exist. |
431 */ | 448 */ |
432 static int parse_config_file(const char* filename, SkTDArray<FontFamily*>& famil
ies, | 449 static int parse_config_file(const char* filename, SkTDArray<FontFamily*>& famil
ies, |
433 const SkString& basePath, bool isFallback) | 450 const SkString& basePath, bool isFallback) |
434 { | 451 { |
435 SkFILEStream file(filename); | 452 SkFILEStream file(filename); |
436 | 453 |
437 // Some of the files we attempt to parse (in particular, /vendor/etc/fallbac
k_fonts.xml) | 454 // Some of the files we attempt to parse (in particular, /vendor/etc/fallbac
k_fonts.xml) |
438 // are optional - failure here is okay because one of these optional files m
ay not exist. | 455 // are optional - failure here is okay because one of these optional files m
ay not exist. |
439 if (!file.isValid()) { | 456 if (!file.isValid()) { |
440 SkDebugf("File %s could not be opened.\n", filename); | 457 SkDebugf(SK_FONTCONFIGPARSER_PREFIX "'%s' could not be opened\n", filena
me); |
441 return -1; | 458 return -1; |
442 } | 459 } |
443 | 460 |
444 SkAutoTCallVProc<remove_ptr<XML_Parser>::type, XML_ParserFree> parser( | 461 SkAutoTCallVProc<remove_ptr<XML_Parser>::type, XML_ParserFree> parser( |
445 XML_ParserCreate_MM(NULL, &sk_XML_alloc, NULL)); | 462 XML_ParserCreate_MM(NULL, &sk_XML_alloc, NULL)); |
446 if (!parser) { | 463 if (!parser) { |
447 SkDebugf("Could not create XML parser.\n"); | 464 SkDebugf(SK_FONTCONFIGPARSER_PREFIX "could not create XML parser\n"); |
448 return -1; | 465 return -1; |
449 } | 466 } |
450 | 467 |
451 FamilyData self(parser, families, basePath, isFallback); | 468 FamilyData self(parser, families, basePath, isFallback, filename); |
452 XML_SetUserData(parser, &self); | 469 XML_SetUserData(parser, &self); |
453 | 470 |
454 // Disable entity processing, to inhibit internal entity expansion. See expa
t CVE-2013-0340 | 471 // Disable entity processing, to inhibit internal entity expansion. See expa
t CVE-2013-0340 |
455 XML_SetEntityDeclHandler(parser, xml_entity_decl_handler); | 472 XML_SetEntityDeclHandler(parser, xml_entity_decl_handler); |
456 | 473 |
457 // Start parsing oldschool; switch these in flight if we detect a newer vers
ion of the file. | 474 // Start parsing oldschool; switch these in flight if we detect a newer vers
ion of the file. |
458 XML_SetElementHandler(parser, jbParser::start_element_handler, jbParser::end
_element_handler); | 475 XML_SetElementHandler(parser, jbParser::start_element_handler, jbParser::end
_element_handler); |
459 | 476 |
460 // One would assume it would be faster to have a buffer on the stack and cal
l XML_Parse. | 477 // One would assume it would be faster to have a buffer on the stack and cal
l XML_Parse. |
461 // But XML_Parse will call XML_GetBuffer anyway and memmove the passed buffe
r into it. | 478 // But XML_Parse will call XML_GetBuffer anyway and memmove the passed buffe
r into it. |
462 // (Unless XML_CONTEXT_BYTES is undefined, but all users define it.) | 479 // (Unless XML_CONTEXT_BYTES is undefined, but all users define it.) |
463 // In debug, buffer a small odd number of bytes to detect slicing in XML_Cha
racterDataHandler. | 480 // In debug, buffer a small odd number of bytes to detect slicing in XML_Cha
racterDataHandler. |
464 static const int bufferSize = 512 SkDEBUGCODE( - 507); | 481 static const int bufferSize = 512 SkDEBUGCODE( - 507); |
465 bool done = false; | 482 bool done = false; |
466 while (!done) { | 483 while (!done) { |
467 void* buffer = XML_GetBuffer(parser, bufferSize); | 484 void* buffer = XML_GetBuffer(parser, bufferSize); |
468 if (!buffer) { | 485 if (!buffer) { |
469 SkDebugf("Could not buffer enough to continue.\n"); | 486 SkDebugf(SK_FONTCONFIGPARSER_PREFIX "could not buffer enough to cont
inue\n"); |
470 return -1; | 487 return -1; |
471 } | 488 } |
472 size_t len = file.read(buffer, bufferSize); | 489 size_t len = file.read(buffer, bufferSize); |
473 done = file.isAtEnd(); | 490 done = file.isAtEnd(); |
474 XML_Status status = XML_ParseBuffer(parser, len, done); | 491 XML_Status status = XML_ParseBuffer(parser, len, done); |
475 if (XML_STATUS_ERROR == status) { | 492 if (XML_STATUS_ERROR == status) { |
476 XML_Error error = XML_GetErrorCode(parser); | 493 XML_Error error = XML_GetErrorCode(parser); |
477 int line = XML_GetCurrentLineNumber(parser); | 494 int line = XML_GetCurrentLineNumber(parser); |
478 int column = XML_GetCurrentColumnNumber(parser); | 495 int column = XML_GetCurrentColumnNumber(parser); |
479 int index = XML_GetCurrentByteIndex(parser); | |
480 const XML_LChar* errorString = XML_ErrorString(error); | 496 const XML_LChar* errorString = XML_ErrorString(error); |
481 SkDebugf("Line: %d Column: %d (Offset: %d) Error %d: %s.\n", | 497 SkDebugf(SK_FONTCONFIGPARSER_PREFIX "%s:%d:%d error %d: %s.\n", |
482 line, column, index, error, errorString); | 498 filename, line, column, error, errorString); |
483 return -1; | 499 return -1; |
484 } | 500 } |
485 } | 501 } |
486 return self.fVersion; | 502 return self.fVersion; |
487 } | 503 } |
488 | 504 |
489 /** Returns the version of the system font file actually found, negative if none
. */ | 505 /** Returns the version of the system font file actually found, negative if none
. */ |
490 static int append_system_font_families(SkTDArray<FontFamily*>& fontFamilies, | 506 static int append_system_font_families(SkTDArray<FontFamily*>& fontFamilies, |
491 const SkString& basePath) | 507 const SkString& basePath) |
492 { | 508 { |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
634 const char* tag = fTag.c_str(); | 650 const char* tag = fTag.c_str(); |
635 | 651 |
636 // strip off the rightmost "-.*" | 652 // strip off the rightmost "-.*" |
637 const char* parentTagEnd = strrchr(tag, '-'); | 653 const char* parentTagEnd = strrchr(tag, '-'); |
638 if (parentTagEnd == NULL) { | 654 if (parentTagEnd == NULL) { |
639 return SkLanguage(); | 655 return SkLanguage(); |
640 } | 656 } |
641 size_t parentTagLen = parentTagEnd - tag; | 657 size_t parentTagLen = parentTagEnd - tag; |
642 return SkLanguage(tag, parentTagLen); | 658 return SkLanguage(tag, parentTagLen); |
643 } | 659 } |
OLD | NEW |