| 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 |