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

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: Complete basic implementation 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) {
84 const char* name = attributes[i];
85 const char* value = attributes[i+1];
86 int nameLen = strlen(name);
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->language.set(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->variant = SkPaintOptionsAndroid::kElegant_Variant;
96 } else if (valueLen == 7 && !strncmp("compact", value, valueLen)) {
97 family->variant = SkPaintOptionsAndroid::kCompact_Variant;
98 }
99 }
100 }
101 }
102
103 void fontFileNameHandler(void *data, const char *s, int len) {
104 FamilyData *familyData = (FamilyData*) data;
105 familyData->currentFontInfo->fFileName.set(s, len);
106 }
107
108 void familyElementEndHandler(FontFamily* family) {
109 for (int i = 0; i < family->fFontFiles.count(); i++) {
110 family->fFontFiles[i].fPaintOptions.setLanguage(family->language);
djsollen 2014/08/05 17:46:15 no immediate change here, but post m37 let's remov
tomhudson 2014/08/05 19:35:35 Acknowledged. http://skbug.com/2803
111 family->fFontFiles[i].fPaintOptions.setFontVariant(family->variant);
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) {
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->weight);
125 }
126 }
127 XML_SetCharacterDataHandler(*parser, fontFileNameHandler);
128 }
129
130 FontFamily* findFamily(FamilyData* familyData, const char* familyName) {
131 unsigned int nameLen = strlen(familyName);
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].weight == 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].weight == 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].weight)) {
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) {
djsollen 2014/08/05 17:46:15 so after tracing a few examples though my head, I'
tomhudson 2014/08/05 19:35:35 Acknowledged. http://skbug.com/2804
216 int count = countDesiredWeight(family);
217 for (int i = 1, j = 0; i < family->fFontFiles.count(); i++) {
218 if (desiredWeight(family->fFontFiles[j].weight)) {
219 j++;
220 }
221 if ((i != j) && desiredWeight(family->fFontFiles[i].weight)) {
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 286 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