Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2)

Side by Side Diff: src/ports/SkFontConfigParser_android.cpp

Issue 446473003: Parser for new fonts.xml format (Closed) Base URL: https://skia.googlesource.com/skia.git@fcparse-lmp-2
Patch Set: Rebase and add missing && Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/ports/SkFontConfigParser_android.h ('k') | src/ports/SkFontMgr_android.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 "SkTDArray.h" 9 #include "SkTDArray.h"
10 #include "SkTSearch.h" 10 #include "SkTSearch.h"
(...skipping 26 matching lines...) Expand all
37 // for now. 37 // for now.
38 #define NO_TAG 0 38 #define NO_TAG 0
39 #define NAMESET_TAG 1 39 #define NAMESET_TAG 1
40 #define FILESET_TAG 2 40 #define FILESET_TAG 2
41 41
42 /** 42 /**
43 * The FamilyData structure is passed around by the parser so that each handler 43 * The FamilyData structure is passed around by the parser so that each handler
44 * can read these variables that are relevant to the current parsing. 44 * can read these variables that are relevant to the current parsing.
45 */ 45 */
46 struct FamilyData { 46 struct FamilyData {
47 FamilyData(XML_Parser *parserRef, SkTDArray<FontFamily*> &familiesRef) : 47 FamilyData(XML_Parser* parserRef, SkTDArray<FontFamily*> &familiesRef) :
48 parser(parserRef), 48 parser(parserRef),
49 families(familiesRef), 49 families(familiesRef),
50 currentFamily(NULL), 50 currentFamily(NULL),
51 currentFontInfo(NULL), 51 currentFontInfo(NULL),
52 currentTag(NO_TAG) {}; 52 currentTag(NO_TAG) {};
53 53
54 XML_Parser *parser; // The expat parser doing the work 54 XML_Parser* parser; // The expat parser doing the work
55 SkTDArray<FontFamily*> &families; // The array that each family is put into as it is parsed 55 SkTDArray<FontFamily*> &families; // The array that each family is put into as it is parsed
56 FontFamily *currentFamily; // The current family being created 56 FontFamily* currentFamily; // The current family being created
57 FontFileInfo *currentFontInfo; // The current fontInfo being created 57 FontFileInfo* currentFontInfo; // The current fontInfo being created
58 int currentTag; // A flag to indicate whether we're in na meset/fileset tags 58 int currentTag; // A flag to indicate whether we're in na meset/fileset tags
59 }; 59 };
60 60
61 /** http://www.w3.org/TR/html-markup/datatypes.html#common.data.integer.non-nega tive-def */ 61 /** http://www.w3.org/TR/html-markup/datatypes.html#common.data.integer.non-nega tive-def */
62 template <typename T> static bool parseNonNegativeInteger(const char* s, T* valu e) { 62 template <typename T> static bool parseNonNegativeInteger(const char* s, T* valu e) {
63 SK_COMPILE_ASSERT(std::numeric_limits<T>::is_integer, T_must_be_integer); 63 SK_COMPILE_ASSERT(std::numeric_limits<T>::is_integer, T_must_be_integer);
64 const T nMax = std::numeric_limits<T>::max() / 10; 64 const T nMax = std::numeric_limits<T>::max() / 10;
65 const T dMax = std::numeric_limits<T>::max() - (nMax * 10); 65 const T dMax = std::numeric_limits<T>::max() - (nMax * 10);
66 T n = 0; 66 T n = 0;
67 for (; *s; ++s) { 67 for (; *s; ++s) {
(...skipping 10 matching lines...) Expand all
78 } 78 }
79 *value = n; 79 *value = n;
80 return true; 80 return true;
81 } 81 }
82 82
83 namespace lmpParser { 83 namespace lmpParser {
84 84
85 void familyElementHandler(FontFamily* family, const char** attributes) { 85 void familyElementHandler(FontFamily* family, const char** attributes) {
86 // A non-fallback <family> tag must have a canonical name attribute. 86 // A non-fallback <family> tag must have a canonical name attribute.
87 // A (fallback) <family> tag may have lang and variant attributes. 87 // A (fallback) <family> tag may have lang and variant attributes.
88 for (int i = 0; attributes[i] != NULL; i += 2) { 88 for (size_t i = 0; attributes[i] != NULL &&
89 attributes[i+1] != NULL; i += 2) {
89 const char* name = attributes[i]; 90 const char* name = attributes[i];
90 const char* value = attributes[i+1]; 91 const char* value = attributes[i+1];
91 int nameLen = strlen(name); 92 size_t nameLen = strlen(name);
92 int valueLen = strlen(value); 93 size_t valueLen = strlen(value);
93 if (nameLen == 4 && !strncmp("name", name, nameLen)) { 94 if (nameLen == 4 && !strncmp("name", name, nameLen)) {
94 family->fNames.push_back().set(value); 95 family->fNames.push_back().set(value);
95 } else if (nameLen == 4 && !strncmp("lang", name, nameLen)) { 96 } else if (nameLen == 4 && !strncmp("lang", name, nameLen)) {
96 family->fLanguage = SkLanguage (value); 97 family->fLanguage = SkLanguage (value);
97 } else if (nameLen == 7 && !strncmp("variant", name, nameLen)) { 98 } else if (nameLen == 7 && !strncmp("variant", name, nameLen)) {
98 // Value should be either elegant or compact. 99 // Value should be either elegant or compact.
99 if (valueLen == 7 && !strncmp("elegant", value, valueLen)) { 100 if (valueLen == 7 && !strncmp("elegant", value, valueLen)) {
100 family->fVariant = SkPaintOptionsAndroid::kElegant_Variant; 101 family->fVariant = SkPaintOptionsAndroid::kElegant_Variant;
101 } else if (valueLen == 7 && !strncmp("compact", value, valueLen)) { 102 } else if (valueLen == 7 && !strncmp("compact", value, valueLen)) {
102 family->fVariant = SkPaintOptionsAndroid::kCompact_Variant; 103 family->fVariant = SkPaintOptionsAndroid::kCompact_Variant;
103 } 104 }
104 } 105 }
105 } 106 }
106 } 107 }
107 108
108 void fontFileNameHandler(void *data, const char *s, int len) { 109 void fontFileNameHandler(void* data, const char* s, int len) {
109 FamilyData *familyData = (FamilyData*) data; 110 FamilyData* familyData = (FamilyData*) data;
110 familyData->currentFontInfo->fFileName.set(s, len); 111 familyData->currentFontInfo->fFileName.set(s, len);
111 } 112 }
112 113
113 void familyElementEndHandler(FontFamily* family) { 114 void familyElementEndHandler(FontFamily* family) {
114 for (int i = 0; i < family->fFontFiles.count(); i++) { 115 for (int i = 0; i < family->fFonts.count(); i++) {
115 family->fFontFiles[i].fPaintOptions.setLanguage(family->fLanguage); 116 family->fFonts[i].fPaintOptions.setLanguage(family->fLanguage);
116 family->fFontFiles[i].fPaintOptions.setFontVariant(family->fVariant); 117 family->fFonts[i].fPaintOptions.setFontVariant(family->fVariant);
117 } 118 }
118 } 119 }
119 120
120 void fontElementHandler(XML_Parser* parser, FontFileInfo* file, const char** att ributes) { 121 void fontElementHandler(XML_Parser* parser, FontFileInfo* file, const char** att ributes) {
121 // A <font> should have weight (integer) and style (normal, italic) attribut es. 122 // A <font> should have weight (integer) and style (normal, italic) attribut es.
122 // NOTE: we ignore the style. 123 // NOTE: we ignore the style.
123 // The element should contain a filename. 124 // The element should contain a filename.
124 for (int i = 0; attributes[i] != NULL; i += 2) { 125 for (size_t i = 0; attributes[i] != NULL &&
126 attributes[i+1] != NULL; i += 2) {
125 const char* name = attributes[i]; 127 const char* name = attributes[i];
126 const char* value = attributes[i+1]; 128 const char* value = attributes[i+1];
127 int nameLen = strlen(name); 129 size_t nameLen = strlen(name);
128 if (nameLen == 6 && !strncmp("weight", name, nameLen)) { 130 if (nameLen == 6 && !strncmp("weight", name, nameLen)) {
129 parseNonNegativeInteger(value, &file->fWeight); 131 if (!parseNonNegativeInteger(value, &file->fWeight)) {
132 SkDebugf("---- Font weight %s (INVALID)", value);
133 file->fWeight = 0;
134 }
130 } 135 }
131 } 136 }
132 XML_SetCharacterDataHandler(*parser, fontFileNameHandler); 137 XML_SetCharacterDataHandler(*parser, fontFileNameHandler);
133 } 138 }
134 139
135 FontFamily* findFamily(FamilyData* familyData, const char* familyName) { 140 FontFamily* findFamily(FamilyData* familyData, const char* familyName) {
136 unsigned int nameLen = strlen(familyName); 141 size_t nameLen = strlen(familyName);
137 for (int i = 0; i < familyData->families.count(); i++) { 142 for (int i = 0; i < familyData->families.count(); i++) {
138 FontFamily* candidate = familyData->families[i]; 143 FontFamily* candidate = familyData->families[i];
139 for (int j = 0; j < candidate->fNames.count(); j++) { 144 for (int j = 0; j < candidate->fNames.count(); j++) {
140 if (!strncmp(candidate->fNames[j].c_str(), familyName, nameLen) && 145 if (!strncmp(candidate->fNames[j].c_str(), familyName, nameLen) &&
141 nameLen == strlen(candidate->fNames[j].c_str())) { 146 nameLen == strlen(candidate->fNames[j].c_str())) {
142 return candidate; 147 return candidate;
143 } 148 }
144 } 149 }
145 } 150 }
146 151
147 return NULL; 152 return NULL;
148 } 153 }
149 154
150 void aliasElementHandler(FamilyData* familyData, const char** attributes) { 155 void aliasElementHandler(FamilyData* familyData, const char** attributes) {
151 // An <alias> must have name and to attributes. 156 // An <alias> must have name and to attributes.
152 // It may have weight (integer). 157 // It may have weight (integer).
153 // If it *does not* have a weight, it is a variant name for a <family>. 158 // If it *does not* have a weight, it is a variant name for a <family>.
154 // If it *does* have a weight, it names the <font>(s) of a specific weight 159 // If it *does* have a weight, it names the <font>(s) of a specific weight
155 // from a <family>. 160 // from a <family>.
156 161
157 SkString aliasName; 162 SkString aliasName;
158 SkString to; 163 SkString to;
159 int weight = 0; 164 int weight = 0;
160 for (int i = 0; attributes[i] != NULL; i += 2) { 165 for (size_t i = 0; attributes[i] != NULL &&
166 attributes[i+1] != NULL; i += 2) {
161 const char* name = attributes[i]; 167 const char* name = attributes[i];
162 const char* value = attributes[i+1]; 168 const char* value = attributes[i+1];
163 int nameLen = strlen(name); 169 size_t nameLen = strlen(name);
164 if (nameLen == 4 && !strncmp("name", name, nameLen)) { 170 if (nameLen == 4 && !strncmp("name", name, nameLen)) {
165 aliasName.set(value); 171 aliasName.set(value);
166 } else if (nameLen == 2 && !strncmp("to", name, nameLen)) { 172 } else if (nameLen == 2 && !strncmp("to", name, nameLen)) {
167 to.set(value); 173 to.set(value);
168 } else if (nameLen == 6 && !strncmp("weight", name, nameLen)) { 174 } else if (nameLen == 6 && !strncmp("weight", name, nameLen)) {
169 parseNonNegativeInteger(value, &weight); 175 parseNonNegativeInteger(value, &weight);
170 } 176 }
171 } 177 }
172 178
173 // Assumes that the named family is already declared 179 // Assumes that the named family is already declared
174 FontFamily* targetFamily = findFamily(familyData, to.c_str()); 180 FontFamily* targetFamily = findFamily(familyData, to.c_str());
175 if (!targetFamily) { 181 if (!targetFamily) {
176 SkDebugf("---- Font alias target %s (NOT FOUND)", to.c_str()); 182 SkDebugf("---- Font alias target %s (NOT FOUND)", to.c_str());
177 return; 183 return;
178 } 184 }
179 185
180 if (weight) { 186 if (weight) {
181 FontFamily* family = new FontFamily(); 187 FontFamily* family = new FontFamily();
182 family->fNames.push_back().set(aliasName); 188 family->fNames.push_back().set(aliasName);
183 189
184 for (int i = 0; i < targetFamily->fFontFiles.count(); i++) { 190 for (int i = 0; i < targetFamily->fFonts.count(); i++) {
185 if (targetFamily->fFontFiles[i].fWeight == weight) { 191 if (targetFamily->fFonts[i].fWeight == weight) {
186 family->fFontFiles.push_back(targetFamily->fFontFiles[i]); 192 family->fFonts.push_back(targetFamily->fFonts[i]);
187 } 193 }
188 } 194 }
189 *familyData->families.append() = family; 195 *familyData->families.append() = family;
190 } else { 196 } else {
191 targetFamily->fNames.push_back().set(aliasName); 197 targetFamily->fNames.push_back().set(aliasName);
192 } 198 }
193 } 199 }
194 200
195 bool findWeight400(FontFamily* family) { 201 bool findWeight400(FontFamily* family) {
196 for (int i = 0; i < family->fFontFiles.count(); i++) { 202 for (int i = 0; i < family->fFonts.count(); i++) {
197 if (family->fFontFiles[i].fWeight == 400) { 203 if (family->fFonts[i].fWeight == 400) {
198 return true; 204 return true;
199 } 205 }
200 } 206 }
201 return false; 207 return false;
202 } 208 }
203 209
204 bool desiredWeight(int weight) { 210 bool desiredWeight(int weight) {
205 return (weight == 400 || weight == 700); 211 return (weight == 400 || weight == 700);
206 } 212 }
207 213
208 int countDesiredWeight(FontFamily* family) { 214 int countDesiredWeight(FontFamily* family) {
209 int count = 0; 215 int count = 0;
210 for (int i = 0; i < family->fFontFiles.count(); i++) { 216 for (int i = 0; i < family->fFonts.count(); i++) {
211 if (desiredWeight(family->fFontFiles[i].fWeight)) { 217 if (desiredWeight(family->fFonts[i].fWeight)) {
212 count++; 218 count++;
213 } 219 }
214 } 220 }
215 return count; 221 return count;
216 } 222 }
217 223
218 // To meet Skia's expectations, any family that contains weight=400 224 // To meet Skia's expectations, any family that contains weight=400
219 // fonts should *only* contain {400,700} 225 // fonts should *only* contain {400,700}
220 void purgeUndesiredWeights(FontFamily* family) { 226 void purgeUndesiredWeights(FontFamily* family) {
221 int count = countDesiredWeight(family); 227 int count = countDesiredWeight(family);
222 for (int i = 1, j = 0; i < family->fFontFiles.count(); i++) { 228 for (int i = 1, j = 0; i < family->fFonts.count(); i++) {
223 if (desiredWeight(family->fFontFiles[j].fWeight)) { 229 if (desiredWeight(family->fFonts[j].fWeight)) {
224 j++; 230 j++;
225 } 231 }
226 if ((i != j) && desiredWeight(family->fFontFiles[i].fWeight)) { 232 if ((i != j) && desiredWeight(family->fFonts[i].fWeight)) {
227 family->fFontFiles[j] = family->fFontFiles[i]; 233 family->fFonts[j] = family->fFonts[i];
228 } 234 }
229 } 235 }
230 family->fFontFiles.resize_back(count); 236 family->fFonts.resize_back(count);
231 } 237 }
232 238
233 void familysetElementEndHandler(FamilyData* familyData) { 239 void familysetElementEndHandler(FamilyData* familyData) {
234 for (int i = 0; i < familyData->families.count(); i++) { 240 for (int i = 0; i < familyData->families.count(); i++) {
235 if (findWeight400(familyData->families[i])) { 241 if (findWeight400(familyData->families[i])) {
236 purgeUndesiredWeights(familyData->families[i]); 242 purgeUndesiredWeights(familyData->families[i]);
237 } 243 }
238 } 244 }
239 } 245 }
240 246
241 void startElementHandler(void* data, const char* tag, 247 void startElementHandler(void* data, const char* tag,
242 const char** attributes) { 248 const char** attributes) {
243 FamilyData* familyData = (FamilyData*) data; 249 FamilyData* familyData = (FamilyData*) data;
244 int len = strlen(tag); 250 size_t len = strlen(tag);
245 if (len == 6 && !strncmp(tag, "family", len)) { 251 if (len == 6 && !strncmp(tag, "family", len)) {
246 familyData->currentFamily = new FontFamily(); 252 familyData->currentFamily = new FontFamily();
247 familyElementHandler(familyData->currentFamily, attributes); 253 familyElementHandler(familyData->currentFamily, attributes);
248 } else if (len == 4 && !strncmp(tag, "font", len)) { 254 } else if (len == 4 && !strncmp(tag, "font", len)) {
249 FontFileInfo* file = &familyData->currentFamily->fFontFiles.push_back(); 255 FontFileInfo* file = &familyData->currentFamily->fFonts.push_back();
250 familyData->currentFontInfo = file; 256 familyData->currentFontInfo = file;
251 fontElementHandler(familyData->parser, file, attributes); 257 fontElementHandler(familyData->parser, file, attributes);
252 } else if (len == 5 && !strncmp(tag, "alias", len)) { 258 } else if (len == 5 && !strncmp(tag, "alias", len)) {
253 aliasElementHandler(familyData, attributes); 259 aliasElementHandler(familyData, attributes);
254 } 260 }
255 } 261 }
256 262
257 void endElementHandler(void* data, const char* tag) { 263 void endElementHandler(void* data, const char* tag) {
258 FamilyData *familyData = (FamilyData*) data; 264 FamilyData* familyData = (FamilyData*) data;
259 int len = strlen(tag); 265 size_t len = strlen(tag);
260 if (len == 9 && strncmp(tag, "familyset", len) == 0) { 266 if (len == 9 && strncmp(tag, "familyset", len) == 0) {
261 familysetElementEndHandler(familyData); 267 familysetElementEndHandler(familyData);
262 } else if (len == 6 && strncmp(tag, "family", len) == 0) { 268 } else if (len == 6 && strncmp(tag, "family", len) == 0) {
263 familyElementEndHandler(familyData->currentFamily); 269 familyElementEndHandler(familyData->currentFamily);
264 *familyData->families.append() = familyData->currentFamily; 270 *familyData->families.append() = familyData->currentFamily;
265 familyData->currentFamily = NULL; 271 familyData->currentFamily = NULL;
266 } else if (len == 4 && !strncmp(tag, "font", len)) { 272 } else if (len == 4 && !strncmp(tag, "font", len)) {
267 XML_SetCharacterDataHandler(*familyData->parser, NULL); 273 XML_SetCharacterDataHandler(*familyData->parser, NULL);
268 } 274 }
269 } 275 }
270 276
271 } // lmpParser 277 } // lmpParser
272 278
273 namespace jbParser { 279 namespace jbParser {
274 280
275 /** 281 /**
276 * Handler for arbitrary text. This is used to parse the text inside each name 282 * Handler for arbitrary text. This is used to parse the text inside each name
277 * or file tag. The resulting strings are put into the fNames or FontFileInfo ar rays. 283 * or file tag. The resulting strings are put into the fNames or FontFileInfo ar rays.
278 */ 284 */
279 static void textHandler(void *data, const char *s, int len) { 285 static void textHandler(void* data, const char* s, int len) {
280 FamilyData *familyData = (FamilyData*) data; 286 FamilyData* familyData = (FamilyData*) data;
281 // Make sure we're in the right state to store this name information 287 // Make sure we're in the right state to store this name information
282 if (familyData->currentFamily && 288 if (familyData->currentFamily &&
283 (familyData->currentTag == NAMESET_TAG || familyData->currentTag == FILESET_TAG)) { 289 (familyData->currentTag == NAMESET_TAG || familyData->currentTag == FILESET_TAG)) {
284 switch (familyData->currentTag) { 290 switch (familyData->currentTag) {
285 case NAMESET_TAG: { 291 case NAMESET_TAG: {
286 SkAutoAsciiToLC tolc(s, len); 292 SkAutoAsciiToLC tolc(s, len);
287 familyData->currentFamily->fNames.push_back().set(tolc.lc(), len); 293 familyData->currentFamily->fNames.push_back().set(tolc.lc(), len);
288 break; 294 break;
289 } 295 }
290 case FILESET_TAG: 296 case FILESET_TAG:
291 if (familyData->currentFontInfo) { 297 if (familyData->currentFontInfo) {
292 familyData->currentFontInfo->fFileName.set(s, len); 298 familyData->currentFontInfo->fFileName.set(s, len);
293 } 299 }
294 break; 300 break;
295 default: 301 default:
296 // Noop - don't care about any text that's not in the Fonts or Names list 302 // Noop - don't care about any text that's not in the Fonts or Names list
297 break; 303 break;
298 } 304 }
299 } 305 }
300 } 306 }
301 307
302 /** 308 /**
303 * Handler for font files. This processes the attributes for language and 309 * Handler for font files. This processes the attributes for language and
304 * variants then lets textHandler handle the actual file name 310 * variants then lets textHandler handle the actual file name
305 */ 311 */
306 static void fontFileElementHandler(FamilyData *familyData, const char **attribut es) { 312 static void fontFileElementHandler(FamilyData* familyData, const char** attribut es) {
307 FontFileInfo& newFileInfo = familyData->currentFamily->fFontFiles.push_back( ); 313 FontFileInfo& newFileInfo = familyData->currentFamily->fFonts.push_back();
308 if (attributes) { 314 if (attributes) {
309 int currentAttributeIndex = 0; 315 size_t currentAttributeIndex = 0;
310 while (attributes[currentAttributeIndex]) { 316 while (attributes[currentAttributeIndex] &&
317 attributes[currentAttributeIndex + 1]) {
311 const char* attributeName = attributes[currentAttributeIndex]; 318 const char* attributeName = attributes[currentAttributeIndex];
312 const char* attributeValue = attributes[currentAttributeIndex+1]; 319 const char* attributeValue = attributes[currentAttributeIndex+1];
313 int nameLength = strlen(attributeName); 320 size_t nameLength = strlen(attributeName);
314 int valueLength = strlen(attributeValue); 321 size_t valueLength = strlen(attributeValue);
315 if (nameLength == 7 && strncmp(attributeName, "variant", nameLength) == 0) { 322 if (nameLength == 7 && strncmp(attributeName, "variant", nameLength) == 0) {
316 if (valueLength == 7 && strncmp(attributeValue, "elegant", value Length) == 0) { 323 if (valueLength == 7 && strncmp(attributeValue, "elegant", value Length) == 0) {
317 newFileInfo.fPaintOptions.setFontVariant(SkPaintOptionsAndro id::kElegant_Variant); 324 newFileInfo.fPaintOptions.setFontVariant(SkPaintOptionsAndro id::kElegant_Variant);
318 } else if (valueLength == 7 && 325 } else if (valueLength == 7 &&
319 strncmp(attributeValue, "compact", valueLength) == 0) { 326 strncmp(attributeValue, "compact", valueLength) == 0) {
320 newFileInfo.fPaintOptions.setFontVariant(SkPaintOptionsAndro id::kCompact_Variant); 327 newFileInfo.fPaintOptions.setFontVariant(SkPaintOptionsAndro id::kCompact_Variant);
321 } 328 }
322 } else if (nameLength == 4 && strncmp(attributeName, "lang", nameLen gth) == 0) { 329 } else if (nameLength == 4 && strncmp(attributeName, "lang", nameLen gth) == 0) {
323 newFileInfo.fPaintOptions.setLanguage(attributeValue); 330 newFileInfo.fPaintOptions.setLanguage(attributeValue);
324 } else if (nameLength == 5 && strncmp(attributeName, "index", nameLe ngth) == 0) { 331 } else if (nameLength == 5 && strncmp(attributeName, "index", nameLe ngth) == 0) {
325 int value; 332 int value;
326 if (parseNonNegativeInteger(attributeValue, &value)) { 333 if (parseNonNegativeInteger(attributeValue, &value)) {
327 newFileInfo.fIndex = value; 334 newFileInfo.fIndex = value;
328 } else { 335 } else {
329 SkDebugf("---- SystemFonts index=%s (INVALID)", attributeVal ue); 336 SkDebugf("---- SystemFonts index=%s (INVALID)", attributeVal ue);
330 } 337 }
331 } 338 }
332 //each element is a pair of attributeName/attributeValue string pair s 339 //each element is a pair of attributeName/attributeValue string pair s
333 currentAttributeIndex += 2; 340 currentAttributeIndex += 2;
334 } 341 }
335 } 342 }
336 familyData->currentFontInfo = &newFileInfo; 343 familyData->currentFontInfo = &newFileInfo;
337 XML_SetCharacterDataHandler(*familyData->parser, textHandler); 344 XML_SetCharacterDataHandler(*familyData->parser, textHandler);
338 } 345 }
339 346
340 /** 347 /**
341 * Handler for the start of a tag. The only tags we expect are familyset, family , 348 * Handler for the start of a tag. The only tags we expect are familyset, family ,
342 * nameset, fileset, name, and file. 349 * nameset, fileset, name, and file.
343 */ 350 */
344 static void startElementHandler(void *data, const char *tag, const char **atts) { 351 static void startElementHandler(void* data, const char* tag, const char** atts) {
345 FamilyData *familyData = (FamilyData*) data; 352 FamilyData* familyData = (FamilyData*) data;
346 int len = strlen(tag); 353 size_t len = strlen(tag);
347 if (len == 9 && strncmp(tag, "familyset", len) == 0) { 354 if (len == 9 && strncmp(tag, "familyset", len) == 0) {
348 // The familyset tag has an optional "version" attribute with an integer value >= 0 355 // The familyset tag has an optional "version" attribute with an integer value >= 0
349 for (int i = 0; atts[i] != NULL; i += 2) { 356 for (size_t i = 0; atts[i] != NULL &&
350 int nameLen = strlen(atts[i]); 357 atts[i+1] != NULL; i += 2) {
358 size_t nameLen = strlen(atts[i]);
351 if (nameLen == 7 && strncmp(atts[i], "version", nameLen)) continue; 359 if (nameLen == 7 && strncmp(atts[i], "version", nameLen)) continue;
352 const char* valueString = atts[i+1]; 360 const char* valueString = atts[i+1];
353 int version; 361 int version;
354 if (parseNonNegativeInteger(valueString, &version) && (version >= 21 )) { 362 if (parseNonNegativeInteger(valueString, &version) && (version >= 21 )) {
355 XML_SetElementHandler(*familyData->parser, 363 XML_SetElementHandler(*familyData->parser,
356 lmpParser::startElementHandler, 364 lmpParser::startElementHandler,
357 lmpParser::endElementHandler); 365 lmpParser::endElementHandler);
358 } 366 }
359 } 367 }
360 } else if (len == 6 && strncmp(tag, "family", len) == 0) { 368 } else if (len == 6 && strncmp(tag, "family", len) == 0) {
361 familyData->currentFamily = new FontFamily(); 369 familyData->currentFamily = new FontFamily();
362 familyData->currentFamily->order = -1;
363 // The Family tag has an optional "order" attribute with an integer valu e >= 0 370 // The Family tag has an optional "order" attribute with an integer valu e >= 0
364 // If this attribute does not exist, the default value is -1 371 // If this attribute does not exist, the default value is -1
365 for (int i = 0; atts[i] != NULL; i += 2) { 372 for (size_t i = 0; atts[i] != NULL &&
373 atts[i+1] != NULL; i += 2) {
366 const char* valueString = atts[i+1]; 374 const char* valueString = atts[i+1];
367 int value; 375 int value;
368 if (parseNonNegativeInteger(valueString, &value)) { 376 if (parseNonNegativeInteger(valueString, &value)) {
369 familyData->currentFamily->order = value; 377 familyData->currentFamily->fOrder = value;
370 } 378 }
371 } 379 }
372 } else if (len == 7 && strncmp(tag, "nameset", len) == 0) { 380 } else if (len == 7 && strncmp(tag, "nameset", len) == 0) {
373 familyData->currentTag = NAMESET_TAG; 381 familyData->currentTag = NAMESET_TAG;
374 } else if (len == 7 && strncmp(tag, "fileset", len) == 0) { 382 } else if (len == 7 && strncmp(tag, "fileset", len) == 0) {
375 familyData->currentTag = FILESET_TAG; 383 familyData->currentTag = FILESET_TAG;
376 } else if (len == 4 && strncmp(tag, "name", len) == 0 && familyData->current Tag == NAMESET_TAG) { 384 } else if (len == 4 && strncmp(tag, "name", len) == 0 && familyData->current Tag == NAMESET_TAG) {
377 // If it's a Name, parse the text inside 385 // If it's a Name, parse the text inside
378 XML_SetCharacterDataHandler(*familyData->parser, textHandler); 386 XML_SetCharacterDataHandler(*familyData->parser, textHandler);
379 } else if (len == 4 && strncmp(tag, "file", len) == 0 && familyData->current Tag == FILESET_TAG) { 387 } else if (len == 4 && strncmp(tag, "file", len) == 0 && familyData->current Tag == FILESET_TAG) {
380 // If it's a file, parse the attributes, then parse the text inside 388 // If it's a file, parse the attributes, then parse the text inside
381 fontFileElementHandler(familyData, atts); 389 fontFileElementHandler(familyData, atts);
382 } 390 }
383 } 391 }
384 392
385 /** 393 /**
386 * Handler for the end of tags. We only care about family, nameset, fileset, 394 * Handler for the end of tags. We only care about family, nameset, fileset,
387 * name, and file. 395 * name, and file.
388 */ 396 */
389 static void endElementHandler(void *data, const char *tag) { 397 static void endElementHandler(void* data, const char* tag) {
390 FamilyData *familyData = (FamilyData*) data; 398 FamilyData* familyData = (FamilyData*) data;
391 int len = strlen(tag); 399 size_t len = strlen(tag);
392 if (len == 6 && strncmp(tag, "family", len)== 0) { 400 if (len == 6 && strncmp(tag, "family", len)== 0) {
393 // Done parsing a Family - store the created currentFamily in the famili es array 401 // Done parsing a Family - store the created currentFamily in the famili es array
394 *familyData->families.append() = familyData->currentFamily; 402 *familyData->families.append() = familyData->currentFamily;
395 familyData->currentFamily = NULL; 403 familyData->currentFamily = NULL;
396 } else if (len == 7 && strncmp(tag, "nameset", len) == 0) { 404 } else if (len == 7 && strncmp(tag, "nameset", len) == 0) {
397 familyData->currentTag = NO_TAG; 405 familyData->currentTag = NO_TAG;
398 } else if (len == 7 && strncmp(tag, "fileset", len) == 0) { 406 } else if (len == 7 && strncmp(tag, "fileset", len) == 0) {
399 familyData->currentTag = NO_TAG; 407 familyData->currentTag = NO_TAG;
400 } else if ((len == 4 && 408 } else if ((len == 4 &&
401 strncmp(tag, "name", len) == 0 && 409 strncmp(tag, "name", len) == 0 &&
402 familyData->currentTag == NAMESET_TAG) || 410 familyData->currentTag == NAMESET_TAG) ||
403 (len == 4 && 411 (len == 4 &&
404 strncmp(tag, "file", len) == 0 && 412 strncmp(tag, "file", len) == 0 &&
405 familyData->currentTag == FILESET_TAG)) { 413 familyData->currentTag == FILESET_TAG)) {
406 // Disable the arbitrary text handler installed to load Name data 414 // Disable the arbitrary text handler installed to load Name data
407 XML_SetCharacterDataHandler(*familyData->parser, NULL); 415 XML_SetCharacterDataHandler(*familyData->parser, NULL);
408 } 416 }
409 } 417 }
410 418
411 } // namespace jbParser 419 } // namespace jbParser
412 420
413 /** 421 /**
414 * This function parses the given filename and stores the results in the given 422 * This function parses the given filename and stores the results in the given
415 * families array. 423 * families array.
416 */ 424 */
417 static void parseConfigFile(const char *filename, SkTDArray<FontFamily*> &famili es) { 425 static void parseConfigFile(const char* filename, SkTDArray<FontFamily*> &famili es) {
418 426
419 FILE* file = fopen(filename, "r"); 427 FILE* file = fopen(filename, "r");
420 428
421 // Some of the files we attempt to parse (in particular, /vendor/etc/fallbac k_fonts.xml) 429 // Some of the files we attempt to parse (in particular, /vendor/etc/fallbac k_fonts.xml)
422 // are optional - failure here is okay because one of these optional files m ay not exist. 430 // are optional - failure here is okay because one of these optional files m ay not exist.
423 if (NULL == file) { 431 if (NULL == file) {
424 return; 432 return;
425 } 433 }
426 434
427 XML_Parser parser = XML_ParserCreate(NULL); 435 XML_Parser parser = XML_ParserCreate(NULL);
428 FamilyData *familyData = new FamilyData(&parser, families); 436 FamilyData* familyData = new FamilyData(&parser, families);
429 XML_SetUserData(parser, familyData); 437 XML_SetUserData(parser, familyData);
430 // Start parsing oldschool; switch these in flight if we detect a newer vers ion of the file. 438 // Start parsing oldschool; switch these in flight if we detect a newer vers ion of the file.
431 XML_SetElementHandler(parser, jbParser::startElementHandler, jbParser::endEl ementHandler); 439 XML_SetElementHandler(parser, jbParser::startElementHandler, jbParser::endEl ementHandler);
432 440
433 char buffer[512]; 441 char buffer[512];
434 bool done = false; 442 bool done = false;
435 while (!done) { 443 while (!done) {
436 fgets(buffer, sizeof(buffer), file); 444 fgets(buffer, sizeof(buffer), file);
437 int len = strlen(buffer); 445 size_t len = strlen(buffer);
438 if (feof(file) != 0) { 446 if (feof(file) != 0) {
439 done = true; 447 done = true;
440 } 448 }
441 XML_Parse(parser, buffer, len, done); 449 XML_Parse(parser, buffer, len, done);
442 } 450 }
443 XML_ParserFree(parser); 451 XML_ParserFree(parser);
444 fclose(file); 452 fclose(file);
445 } 453 }
446 454
447 static void getSystemFontFamilies(SkTDArray<FontFamily*> &fontFamilies) { 455 static void getSystemFontFamilies(SkTDArray<FontFamily*> &fontFamilies) {
(...skipping 12 matching lines...) Expand all
460 // The framework is beyond Android 4.2 and can therefore skip this function 468 // The framework is beyond Android 4.2 and can therefore skip this function
461 return; 469 return;
462 #endif 470 #endif
463 471
464 DIR* fontDirectory = opendir(dir); 472 DIR* fontDirectory = opendir(dir);
465 if (fontDirectory != NULL){ 473 if (fontDirectory != NULL){
466 struct dirent* dirEntry = readdir(fontDirectory); 474 struct dirent* dirEntry = readdir(fontDirectory);
467 while (dirEntry) { 475 while (dirEntry) {
468 476
469 // The size of both the prefix, suffix, and a minimum valid language code 477 // The size of both the prefix, suffix, and a minimum valid language code
470 static const int minSize = strlen(LOCALE_FALLBACK_FONTS_PREFIX) + 478 static const size_t minSize = strlen(LOCALE_FALLBACK_FONTS_PREFIX) +
471 strlen(LOCALE_FALLBACK_FONTS_SUFFIX) + 2; 479 strlen(LOCALE_FALLBACK_FONTS_SUFFIX) + 2;
472 480
473 SkString fileName(dirEntry->d_name); 481 SkString fileName(dirEntry->d_name);
474 if (fileName.size() >= minSize && 482 if (fileName.size() >= minSize &&
475 fileName.startsWith(LOCALE_FALLBACK_FONTS_PREFIX) && 483 fileName.startsWith(LOCALE_FALLBACK_FONTS_PREFIX) &&
476 fileName.endsWith(LOCALE_FALLBACK_FONTS_SUFFIX)) { 484 fileName.endsWith(LOCALE_FALLBACK_FONTS_SUFFIX)) {
477 485
478 static const int fixedLen = strlen(LOCALE_FALLBACK_FONTS_PREFIX) - 486 static const size_t fixedLen = strlen(LOCALE_FALLBACK_FONTS_PREF IX) -
479 strlen(LOCALE_FALLBACK_FONTS_SUFFIX) ; 487 strlen(LOCALE_FALLBACK_FONTS_SUFF IX);
480 488
481 SkString locale(fileName.c_str() - strlen(LOCALE_FALLBACK_FONTS_ PREFIX), 489 SkString locale(fileName.c_str() - strlen(LOCALE_FALLBACK_FONTS_ PREFIX),
482 fileName.size() - fixedLen); 490 fileName.size() - fixedLen);
483 491
484 SkString absoluteFilename; 492 SkString absoluteFilename;
485 absoluteFilename.printf("%s/%s", dir, fileName.c_str()); 493 absoluteFilename.printf("%s/%s", dir, fileName.c_str());
486 494
487 SkTDArray<FontFamily*> langSpecificFonts; 495 SkTDArray<FontFamily*> langSpecificFonts;
488 parseConfigFile(absoluteFilename.c_str(), langSpecificFonts); 496 parseConfigFile(absoluteFilename.c_str(), langSpecificFonts);
489 497
490 for (int i = 0; i < langSpecificFonts.count(); ++i) { 498 for (int i = 0; i < langSpecificFonts.count(); ++i) {
491 FontFamily* family = langSpecificFonts[i]; 499 FontFamily* family = langSpecificFonts[i];
492 for (int j = 0; j < family->fFontFiles.count(); ++j) { 500 for (int j = 0; j < family->fFonts.count(); ++j) {
493 family->fFontFiles[j].fPaintOptions.setLanguage(locale); 501 family->fFonts[j].fPaintOptions.setLanguage(locale);
494 } 502 }
495 *fallbackFonts.append() = family; 503 *fallbackFonts.append() = family;
496 } 504 }
497 } 505 }
498 506
499 // proceed to the next entry in the directory 507 // proceed to the next entry in the directory
500 dirEntry = readdir(fontDirectory); 508 dirEntry = readdir(fontDirectory);
501 } 509 }
502 // cleanup the directory reference 510 // cleanup the directory reference
503 closedir(fontDirectory); 511 closedir(fontDirectory);
504 } 512 }
505 } 513 }
506 514
507 static void getFallbackFontFamilies(SkTDArray<FontFamily*> &fallbackFonts) { 515 static void getFallbackFontFamilies(SkTDArray<FontFamily*> &fallbackFonts) {
508 SkTDArray<FontFamily*> vendorFonts; 516 SkTDArray<FontFamily*> vendorFonts;
509 parseConfigFile(FALLBACK_FONTS_FILE, fallbackFonts); 517 parseConfigFile(FALLBACK_FONTS_FILE, fallbackFonts);
510 parseConfigFile(VENDOR_FONTS_FILE, vendorFonts); 518 parseConfigFile(VENDOR_FONTS_FILE, vendorFonts);
511 519
512 getFallbackFontFamiliesForLocale(fallbackFonts, LOCALE_FALLBACK_FONTS_SYSTEM _DIR); 520 getFallbackFontFamiliesForLocale(fallbackFonts, LOCALE_FALLBACK_FONTS_SYSTEM _DIR);
513 getFallbackFontFamiliesForLocale(vendorFonts, LOCALE_FALLBACK_FONTS_VENDOR_D IR); 521 getFallbackFontFamiliesForLocale(vendorFonts, LOCALE_FALLBACK_FONTS_VENDOR_D IR);
514 522
515 // This loop inserts the vendor fallback fonts in the correct order in the 523 // This loop inserts the vendor fallback fonts in the correct order in the
516 // overall fallbacks list. 524 // overall fallbacks list.
517 int currentOrder = -1; 525 int currentOrder = -1;
518 for (int i = 0; i < vendorFonts.count(); ++i) { 526 for (int i = 0; i < vendorFonts.count(); ++i) {
519 FontFamily* family = vendorFonts[i]; 527 FontFamily* family = vendorFonts[i];
520 int order = family->order; 528 int order = family->fOrder;
521 if (order < 0) { 529 if (order < 0) {
522 if (currentOrder < 0) { 530 if (currentOrder < 0) {
523 // Default case - just add it to the end of the fallback list 531 // Default case - just add it to the end of the fallback list
524 *fallbackFonts.append() = family; 532 *fallbackFonts.append() = family;
525 } else { 533 } else {
526 // no order specified on this font, but we're incrementing the o rder 534 // no order specified on this font, but we're incrementing the o rder
527 // based on an earlier order insertion request 535 // based on an earlier order insertion request
528 *fallbackFonts.insert(currentOrder++) = family; 536 *fallbackFonts.insert(currentOrder++) = family;
529 } 537 }
530 } else { 538 } else {
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
562 if (NULL != testFallbackConfigFile) { 570 if (NULL != testFallbackConfigFile) {
563 parseConfigFile(testFallbackConfigFile, fallbackFonts); 571 parseConfigFile(testFallbackConfigFile, fallbackFonts);
564 } 572 }
565 573
566 // Append all fallback fonts to system fonts 574 // Append all fallback fonts to system fonts
567 for (int i = 0; i < fallbackFonts.count(); ++i) { 575 for (int i = 0; i < fallbackFonts.count(); ++i) {
568 fallbackFonts[i]->fIsFallbackFont = true; 576 fallbackFonts[i]->fIsFallbackFont = true;
569 *fontFamilies.append() = fallbackFonts[i]; 577 *fontFamilies.append() = fallbackFonts[i];
570 } 578 }
571 } 579 }
OLDNEW
« no previous file with comments | « src/ports/SkFontConfigParser_android.h ('k') | src/ports/SkFontMgr_android.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698