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

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: Do you speak-a my language? 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
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 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
70 return false; 70 return false;
71 } 71 }
72 n = (n * 10) + d; 72 n = (n * 10) + d;
73 } 73 }
74 *value = n; 74 *value = n;
75 return true; 75 return true;
76 } 76 }
77 77
78 namespace lmpParser { 78 namespace lmpParser {
79 79
80 void familyElementHandler(FontFamily* family, const char** attributes) {
81 // A non-fallback <family> tag must have a canonical name attribute.
82 // A (fallback) <family> tag may have lang and variant attributes.
83 for (int i = 0; attributes[i] != NULL; i += 2) {
palmer 2014/08/06 21:05:30 Is there a guarantee that |attributes| always has
reed1 2014/08/06 21:20:05 Skia uses int instead of size_t for most counters
tomhudson 2014/08/07 14:39:42 We expect that the XML Parser (expat) guarantees t
84 const char* name = attributes[i];
85 const char* value = attributes[i+1];
reed1 2014/08/06 21:20:05 could assert that value != NULL, to address the co
86 int nameLen = strlen(name);
palmer 2014/08/06 21:05:29 strlen returns size_t, not int. (The 2 types diffe
reed1 2014/08/06 21:20:05 +1
tomhudson 2014/08/07 14:39:43 Done ~ 16x. (Old code.) There are many other inst
87 int valueLen = strlen(value);
88 if (nameLen == 4 && !strncmp("name", name, nameLen)) {
89 family->fNames.push_back().set(value);
90 } else if (nameLen == 4 && !strncmp("lang", name, nameLen)) {
91 family->fLanguage = SkLanguage (value);
92 } else if (nameLen == 7 && !strncmp("variant", name, nameLen)) {
93 // Value should be either elegant or compact.
94 if (valueLen == 7 && !strncmp("elegant", value, valueLen)) {
95 family->fVariant = SkPaintOptionsAndroid::kElegant_Variant;
96 } else if (valueLen == 7 && !strncmp("compact", value, valueLen)) {
97 family->fVariant = SkPaintOptionsAndroid::kCompact_Variant;
98 }
99 }
100 }
101 }
102
103 void fontFileNameHandler(void *data, const char *s, int len) {
palmer 2014/08/06 21:05:30 Nit: "void *data" conflicts with the "FontFamily*
tomhudson 2014/08/07 14:39:42 Done. Unfortunately, https://sites.google.com/site
104 FamilyData *familyData = (FamilyData*) data;
palmer 2014/08/06 21:05:30 Prefer C++ style cast?
105 familyData->currentFontInfo->fFileName.set(s, len);
palmer 2014/08/06 21:05:30 If |set| is defined to take an int length argument
reed1 2014/08/06 21:20:05 +1
tomhudson 2014/08/07 14:39:43 SkString::set() takes size_t, but is happy to impl
106 }
107
108 void familyElementEndHandler(FontFamily* family) {
109 for (int i = 0; i < family->fFontFiles.count(); i++) {
palmer 2014/08/06 21:05:29 size_t, and if |count| returns int, that's a bug
reed1 2014/08/06 21:20:05 count() returns an int.
tomhudson 2014/08/07 14:39:42 Acknowledged. Filed http://skbug.com/2811. Since w
110 family->fFontFiles[i].fPaintOptions.setLanguage(family->fLanguage);
111 family->fFontFiles[i].fPaintOptions.setFontVariant(family->fVariant);
112 }
113 }
114
115 void fontElementHandler(XML_Parser* parser, FontFileInfo* file, const char** att ributes) {
116 // A <font> should have weight (integer) and style (normal, italic) attribut es.
117 // NOTE: we ignore the style.
118 // The element should contain a filename.
119 for (int i = 0; attributes[i] != NULL; i += 2) {
palmer 2014/08/06 21:05:29 Same int and += 2 comments as above
tomhudson 2014/08/07 14:39:43 Done.
120 const char* name = attributes[i];
121 const char* value = attributes[i+1];
122 int nameLen = strlen(name);
123 if (nameLen == 6 && !strncmp("weight", name, nameLen)) {
124 parseNonNegativeInteger(value, &file->fWeight);
palmer 2014/08/06 21:05:30 What if parsing fails?
tomhudson 2014/08/07 14:39:42 Done.
125 }
126 }
127 XML_SetCharacterDataHandler(*parser, fontFileNameHandler);
128 }
129
130 FontFamily* findFamily(FamilyData* familyData, const char* familyName) {
131 unsigned int nameLen = strlen(familyName);
palmer 2014/08/06 21:05:29 size_t, not unsigned int
tomhudson 2014/08/07 14:39:42 Done.
132 for (int i = 0; i < familyData->families.count(); i++) {
133 FontFamily* candidate = familyData->families[i];
134 for (int j = 0; j < candidate->fNames.count(); j++) {
135 if (!strncmp(candidate->fNames[j].c_str(), familyName, nameLen) &&
136 nameLen == strlen(candidate->fNames[j].c_str())) {
137 return candidate;
138 }
139 }
140 }
141
142 return NULL;
143 }
144
145 void aliasElementHandler(FamilyData* familyData, const char** attributes) {
146 // An <alias> must have name and to attributes.
147 // It may have weight (integer).
148 // If it *does not* have a weight, it is a variant name for a <family>.
149 // If it *does* have a weight, it names the <font>(s) of a specific weight
150 // from a <family>.
151
152 SkString aliasName;
153 SkString to;
154 int weight = 0;
155 for (int i = 0; attributes[i] != NULL; i += 2) {
156 const char* name = attributes[i];
157 const char* value = attributes[i+1];
158 int nameLen = strlen(name);
159 if (nameLen == 4 && !strncmp("name", name, nameLen)) {
160 aliasName.set(value);
161 } else if (nameLen == 2 && !strncmp("to", name, nameLen)) {
162 to.set(value);
163 } else if (nameLen == 6 && !strncmp("weight", name, nameLen)) {
164 parseNonNegativeInteger(value, &weight);
165 }
166 }
167
168 // Assumes that the named family is already declared
169 FontFamily* targetFamily = findFamily(familyData, to.c_str());
170 if (!targetFamily) {
171 SkDebugf("---- Font alias target %s (NOT FOUND)", to.c_str());
172 return;
173 }
174
175 if (weight) {
176 FontFamily* family = new FontFamily();
177 family->fNames.push_back().set(aliasName);
178
179 for (int i = 0; i < targetFamily->fFontFiles.count(); i++) {
180 if (targetFamily->fFontFiles[i].fWeight == weight) {
181 family->fFontFiles.push_back(targetFamily->fFontFiles[i]);
182 }
183 }
184 *familyData->families.append() = family;
185 } else {
186 targetFamily->fNames.push_back().set(aliasName);
187 }
188 }
189
190 bool findWeight400(FontFamily* family) {
191 for (int i = 0; i < family->fFontFiles.count(); i++) {
192 if (family->fFontFiles[i].fWeight == 400) {
193 return true;
194 }
195 }
196 return false;
197 }
198
199 bool desiredWeight(int weight) {
200 return (weight == 400 || weight == 700);
201 }
202
203 int countDesiredWeight(FontFamily* family) {
204 int count = 0;
205 for (int i = 0; i < family->fFontFiles.count(); i++) {
206 if (desiredWeight(family->fFontFiles[i].fWeight)) {
207 count++;
208 }
209 }
210 return count;
211 }
212
213 // To meet Skia's expectations, any family that contains weight=400
214 // fonts should *only* contain {400,700}
215 void purgeUndesiredWeights(FontFamily* family) {
216 int count = countDesiredWeight(family);
217 for (int i = 1, j = 0; i < family->fFontFiles.count(); i++) {
218 if (desiredWeight(family->fFontFiles[j].fWeight)) {
219 j++;
220 }
221 if ((i != j) && desiredWeight(family->fFontFiles[i].fWeight)) {
222 family->fFontFiles[j] = family->fFontFiles[i];
223 }
224 }
225 family->fFontFiles.resize_back(count);
226 }
227
228 void familysetElementEndHandler(FamilyData* familyData) {
229 for (int i = 0; i < familyData->families.count(); i++) {
230 if (findWeight400(familyData->families[i])) {
231 purgeUndesiredWeights(familyData->families[i]);
232 }
233 }
234 }
235
80 void startElementHandler(void* data, const char* tag, 236 void startElementHandler(void* data, const char* tag,
81 const char** attributes) { 237 const char** attributes) {
82 //SkDebugf("lmp started %s", tag); 238 FamilyData* familyData = (FamilyData*) data;
239 int len = strlen(tag);
240 if (len == 6 && !strncmp(tag, "family", len)) {
241 familyData->currentFamily = new FontFamily();
242 familyElementHandler(familyData->currentFamily, attributes);
243 } else if (len == 4 && !strncmp(tag, "font", len)) {
244 FontFileInfo* file = &familyData->currentFamily->fFontFiles.push_back();
245 familyData->currentFontInfo = file;
246 fontElementHandler(familyData->parser, file, attributes);
247 } else if (len == 5 && !strncmp(tag, "alias", len)) {
248 aliasElementHandler(familyData, attributes);
249 }
83 } 250 }
84 251
85 void endElementHandler(void* data, const char* tag) { 252 void endElementHandler(void* data, const char* tag) {
86 253 FamilyData *familyData = (FamilyData*) data;
87 //SkDebugf("lmp ended %s", tag); 254 int len = strlen(tag);
88 255 if (len == 9 && strncmp(tag, "familyset", len) == 0) {
256 familysetElementEndHandler(familyData);
257 } else if (len == 6 && strncmp(tag, "family", len) == 0) {
258 familyElementEndHandler(familyData->currentFamily);
259 *familyData->families.append() = familyData->currentFamily;
260 familyData->currentFamily = NULL;
261 } else if (len == 4 && !strncmp(tag, "font", len)) {
262 XML_SetCharacterDataHandler(*familyData->parser, NULL);
263 }
89 } 264 }
90 265
91 } // lmpParser 266 } // lmpParser
92 267
93 namespace jbParser { 268 namespace jbParser {
94 269
95 /** 270 /**
96 * Handler for arbitrary text. This is used to parse the text inside each name 271 * Handler for arbitrary text. This is used to parse the text inside each name
97 * or file tag. The resulting strings are put into the fNames or FontFileInfo ar rays. 272 * or file tag. The resulting strings are put into the fNames or FontFileInfo ar rays.
98 */ 273 */
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
172 const char* valueString = atts[i+1]; 347 const char* valueString = atts[i+1];
173 int version; 348 int version;
174 if (parseNonNegativeInteger(valueString, &version) && (version >= 21 )) { 349 if (parseNonNegativeInteger(valueString, &version) && (version >= 21 )) {
175 XML_SetElementHandler(*familyData->parser, 350 XML_SetElementHandler(*familyData->parser,
176 lmpParser::startElementHandler, 351 lmpParser::startElementHandler,
177 lmpParser::endElementHandler); 352 lmpParser::endElementHandler);
178 } 353 }
179 } 354 }
180 } else if (len == 6 && strncmp(tag, "family", len) == 0) { 355 } else if (len == 6 && strncmp(tag, "family", len) == 0) {
181 familyData->currentFamily = new FontFamily(); 356 familyData->currentFamily = new FontFamily();
182 familyData->currentFamily->order = -1; 357 familyData->currentFamily->order = -1;
tomhudson 2014/08/07 14:39:42 This default value is set in the FontFamily constr
183 // The Family tag has an optional "order" attribute with an integer valu e >= 0 358 // The Family tag has an optional "order" attribute with an integer valu e >= 0
184 // If this attribute does not exist, the default value is -1 359 // If this attribute does not exist, the default value is -1
185 for (int i = 0; atts[i] != NULL; i += 2) { 360 for (int i = 0; atts[i] != NULL; i += 2) {
186 const char* valueString = atts[i+1]; 361 const char* valueString = atts[i+1];
187 int value; 362 int value;
188 if (parseNonNegativeInteger(valueString, &value)) { 363 if (parseNonNegativeInteger(valueString, &value)) {
189 familyData->currentFamily->order = value; 364 familyData->currentFamily->order = value;
190 } 365 }
191 } 366 }
192 } else if (len == 7 && strncmp(tag, "nameset", len) == 0) { 367 } else if (len == 7 && strncmp(tag, "nameset", len) == 0) {
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after
385 SkString locale(6); 560 SkString locale(6);
386 char* localeCStr = locale.writable_str(); 561 char* localeCStr = locale.writable_str();
387 562
388 strncpy(localeCStr, propLang, 2); 563 strncpy(localeCStr, propLang, 2);
389 localeCStr[2] = '-'; 564 localeCStr[2] = '-';
390 strncpy(&localeCStr[3], propRegn, 2); 565 strncpy(&localeCStr[3], propRegn, 2);
391 localeCStr[5] = '\0'; 566 localeCStr[5] = '\0';
392 567
393 return locale; 568 return locale;
394 } 569 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698