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

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

Issue 427293003: Implement SkFontMgr_Android::onMatchFamilyStyleCharacter. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Remove commented out test shim. 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 | « no previous file | no next file » | 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 2014 Google Inc. 2 * Copyright 2014 Google Inc.
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 "SkFontDescriptor.h" 9 #include "SkFontDescriptor.h"
10 #include "SkFontHost_FreeType_common.h" 10 #include "SkFontHost_FreeType_common.h"
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
52 private: 52 private:
53 typedef SkTypeface_FreeType INHERITED; 53 typedef SkTypeface_FreeType INHERITED;
54 }; 54 };
55 55
56 class SkTypeface_AndroidSystem : public SkTypeface_Android { 56 class SkTypeface_AndroidSystem : public SkTypeface_Android {
57 public: 57 public:
58 SkTypeface_AndroidSystem(const SkString pathName, 58 SkTypeface_AndroidSystem(const SkString pathName,
59 int index, 59 int index,
60 Style style, 60 Style style,
61 bool isFixedPitch, 61 bool isFixedPitch,
62 const SkString familyName) 62 const SkString familyName,
63 const SkLanguage& lang,
64 SkPaintOptionsAndroid::FontVariant variant)
63 : INHERITED(index, style, isFixedPitch, familyName) 65 : INHERITED(index, style, isFixedPitch, familyName)
64 , fPathName(pathName) { } 66 , fPathName(pathName)
67 , fLang(lang)
68 , fVariant(variant) { }
65 69
66 virtual void onGetFontDescriptor(SkFontDescriptor* desc, 70 virtual void onGetFontDescriptor(SkFontDescriptor* desc,
67 bool* serialize) const SK_OVERRIDE { 71 bool* serialize) const SK_OVERRIDE {
68 SkASSERT(desc); 72 SkASSERT(desc);
69 SkASSERT(serialize); 73 SkASSERT(serialize);
70 desc->setFamilyName(fFamilyName.c_str()); 74 desc->setFamilyName(fFamilyName.c_str());
71 desc->setFontFileName(fPathName.c_str()); 75 desc->setFontFileName(fPathName.c_str());
72 *serialize = false; 76 *serialize = false;
73 } 77 }
74 virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE { 78 virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE {
75 *ttcIndex = fIndex; 79 *ttcIndex = fIndex;
76 return SkStream::NewFromFile(fPathName.c_str()); 80 return SkStream::NewFromFile(fPathName.c_str());
77 } 81 }
78 82
79 private: 83 const SkString fPathName;
80 SkString fPathName; 84 const SkLanguage fLang;
85 const SkPaintOptionsAndroid::FontVariant fVariant;
81 86
82 typedef SkTypeface_Android INHERITED; 87 typedef SkTypeface_Android INHERITED;
83 }; 88 };
84 89
85 class SkTypeface_AndroidStream : public SkTypeface_Android { 90 class SkTypeface_AndroidStream : public SkTypeface_Android {
86 public: 91 public:
87 SkTypeface_AndroidStream(SkStream* stream, 92 SkTypeface_AndroidStream(SkStream* stream,
88 int index, 93 int index,
89 Style style, 94 Style style,
90 bool isFixedPitch, 95 bool isFixedPitch,
(...skipping 22 matching lines...) Expand all
113 }; 118 };
114 119
115 void get_path_for_sys_fonts(SkString* full, const SkString& name) { 120 void get_path_for_sys_fonts(SkString* full, const SkString& name) {
116 full->set(getenv("ANDROID_ROOT")); 121 full->set(getenv("ANDROID_ROOT"));
117 full->append(SK_FONT_FILE_PREFIX); 122 full->append(SK_FONT_FILE_PREFIX);
118 full->append(name); 123 full->append(name);
119 } 124 }
120 125
121 class SkFontStyleSet_Android : public SkFontStyleSet { 126 class SkFontStyleSet_Android : public SkFontStyleSet {
122 public: 127 public:
123 explicit SkFontStyleSet_Android(FontFamily* family) { 128 explicit SkFontStyleSet_Android(const FontFamily& family) {
129 const SkString* cannonicalFamilyName = NULL;
130 if (family.fNames.count() > 0) {
131 cannonicalFamilyName = &family.fNames[0];
132 }
124 // TODO? make this lazy 133 // TODO? make this lazy
125 for (int i = 0; i < family->fFontFiles.count(); ++i) { 134 for (int i = 0; i < family.fFontFiles.count(); ++i) {
126 const SkString& fileName = family->fFontFiles[i].fFileName; 135 const FontFileInfo& fontFile = family.fFontFiles[i];
127 136
128 SkString pathName; 137 SkString pathName;
129 get_path_for_sys_fonts(&pathName, fileName); 138 get_path_for_sys_fonts(&pathName, fontFile.fFileName);
130 139
131 SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(pathName.c_str() )); 140 SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(pathName.c_str() ));
132 if (!stream.get()) { 141 if (!stream.get()) {
133 DEBUG_FONT(("---- SystemFonts[%d] file=%s (NOT EXIST)", i, fileN ame.c_str())); 142 DEBUG_FONT(("---- SystemFonts[%d] file=%s (NOT EXIST)", i, pathN ame.c_str()));
134 continue; 143 continue;
135 } 144 }
136 145
137 const int ttcIndex = family->fFontFiles[i].fIndex; 146 const int ttcIndex = fontFile.fIndex;
138 SkString fontName; 147 SkString familyName;
139 SkTypeface::Style style; 148 SkTypeface::Style style;
140 bool isFixedWidth; 149 bool isFixedWidth;
141 if (!SkTypeface_FreeType::ScanFont(stream.get(), ttcIndex, 150 if (!SkTypeface_FreeType::ScanFont(stream.get(), ttcIndex,
142 &fontName, &style, &isFixedWidth) ) { 151 &familyName, &style, &isFixedWidt h)) {
143 DEBUG_FONT(("---- SystemFonts[%d] file=%s (INVALID)", i, fileNam e.c_str())); 152 DEBUG_FONT(("---- SystemFonts[%d] file=%s (INVALID)", i, pathNam e.c_str()));
144 continue; 153 continue;
145 } 154 }
146 155
156 const SkLanguage& lang = fontFile.fPaintOptions.getLanguage();
157 SkPaintOptionsAndroid::FontVariant variant = fontFile.fPaintOptions. getFontVariant();
158
159 // The first specified family name overrides the family name found i n the font.
160 // TODO: SkTypeface_AndroidSystem::onCreateFamilyNameIterator should return
161 // all of the specified family names in addition to the names found in the font.
162 if (cannonicalFamilyName != NULL) {
163 familyName = *cannonicalFamilyName;
164 }
165
147 fStyles.push_back().reset(SkNEW_ARGS(SkTypeface_AndroidSystem, 166 fStyles.push_back().reset(SkNEW_ARGS(SkTypeface_AndroidSystem,
148 (pathName, ttcIndex, 167 (pathName, ttcIndex,
149 style, isFixedWidth, fontName) )); 168 style, isFixedWidth, familyNam e,
169 lang, variant)));
150 } 170 }
151 } 171 }
152 172
153 virtual int count() SK_OVERRIDE { 173 virtual int count() SK_OVERRIDE {
154 return fStyles.count(); 174 return fStyles.count();
155 } 175 }
156 virtual void getStyle(int index, SkFontStyle* style, SkString* name) SK_OVER RIDE { 176 virtual void getStyle(int index, SkFontStyle* style, SkString* name) SK_OVER RIDE {
157 if (index < 0 || fStyles.count() <= index) { 177 if (index < 0 || fStyles.count() <= index) {
158 return; 178 return;
159 } 179 }
160 if (style) { 180 if (style) {
161 *style = this->style(index); 181 *style = this->style(index);
162 } 182 }
163 if (name) { 183 if (name) {
164 name->reset(); 184 name->reset();
165 } 185 }
166 } 186 }
167 virtual SkTypeface* createTypeface(int index) SK_OVERRIDE { 187 virtual SkTypeface_AndroidSystem* createTypeface(int index) SK_OVERRIDE {
168 if (index < 0 || fStyles.count() <= index) { 188 if (index < 0 || fStyles.count() <= index) {
169 return NULL; 189 return NULL;
170 } 190 }
171 return SkRef(fStyles[index].get()); 191 return SkRef(fStyles[index].get());
172 } 192 }
173 193
174 /** Find the typeface in this style set that most closely matches the given pattern. 194 /** Find the typeface in this style set that most closely matches the given pattern.
175 * TODO: consider replacing with SkStyleSet_Indirect::matchStyle(); 195 * TODO: consider replacing with SkStyleSet_Indirect::matchStyle();
176 * this simpler version using match_score() passes all our tests. 196 * this simpler version using match_score() passes all our tests.
177 */ 197 */
178 virtual SkTypeface* matchStyle(const SkFontStyle& pattern) SK_OVERRIDE { 198 virtual SkTypeface_AndroidSystem* matchStyle(const SkFontStyle& pattern) SK_ OVERRIDE {
179 if (0 == fStyles.count()) { 199 if (0 == fStyles.count()) {
180 return NULL; 200 return NULL;
181 } 201 }
182 SkTypeface* closest = fStyles[0]; 202 SkTypeface_AndroidSystem* closest = fStyles[0];
183 int minScore = std::numeric_limits<int>::max(); 203 int minScore = std::numeric_limits<int>::max();
184 for (int i = 0; i < fStyles.count(); ++i) { 204 for (int i = 0; i < fStyles.count(); ++i) {
185 SkFontStyle style = this->style(i); 205 SkFontStyle style = this->style(i);
186 int score = match_score(pattern, style); 206 int score = match_score(pattern, style);
187 if (score < minScore) { 207 if (score < minScore) {
188 closest = fStyles[i]; 208 closest = fStyles[i];
189 minScore = score; 209 minScore = score;
190 } 210 }
191 } 211 }
192 return SkRef(closest); 212 return SkRef(closest);
(...skipping 13 matching lines...) Expand all
206 return SkFontStyle::kUpright_Slant; 226 return SkFontStyle::kUpright_Slant;
207 } 227 }
208 static int match_score(const SkFontStyle& pattern, const SkFontStyle& candid ate) { 228 static int match_score(const SkFontStyle& pattern, const SkFontStyle& candid ate) {
209 int score = 0; 229 int score = 0;
210 score += abs((pattern.width() - candidate.width()) * 100); 230 score += abs((pattern.width() - candidate.width()) * 100);
211 score += abs((pattern.isItalic() == candidate.isItalic()) ? 0 : 1000); 231 score += abs((pattern.isItalic() == candidate.isItalic()) ? 0 : 1000);
212 score += abs(pattern.weight() - candidate.weight()); 232 score += abs(pattern.weight() - candidate.weight());
213 return score; 233 return score;
214 } 234 }
215 235
216 SkTArray<SkAutoTUnref<SkTypeface>, true> fStyles; 236 SkTArray<SkAutoTUnref<SkTypeface_AndroidSystem>, true> fStyles;
217 237
218 friend struct NameToFamily; 238 friend struct NameToFamily;
219 friend class SkFontMgr_Android; 239 friend class SkFontMgr_Android;
220 240
221 typedef SkFontStyleSet INHERITED; 241 typedef SkFontStyleSet INHERITED;
222 }; 242 };
223 243
224 /** On Android a single family can have many names, but our API assumes unique n ames. 244 /** On Android a single family can have many names, but our API assumes unique n ames.
225 * Map names to the back end so that all names for a given family refer to the same 245 * Map names to the back end so that all names for a given family refer to the same
226 * (non-replicated) set of typefaces. 246 * (non-replicated) set of typefaces.
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
266 virtual SkFontStyleSet* onMatchFamily(const char familyName[]) const SK_OVER RIDE { 286 virtual SkFontStyleSet* onMatchFamily(const char familyName[]) const SK_OVER RIDE {
267 if (!familyName) { 287 if (!familyName) {
268 return NULL; 288 return NULL;
269 } 289 }
270 SkAutoAsciiToLC tolc(familyName); 290 SkAutoAsciiToLC tolc(familyName);
271 for (int i = 0; i < fNameToFamilyMap.count(); ++i) { 291 for (int i = 0; i < fNameToFamilyMap.count(); ++i) {
272 if (fNameToFamilyMap[i].name.equals(tolc.lc())) { 292 if (fNameToFamilyMap[i].name.equals(tolc.lc())) {
273 return SkRef(fNameToFamilyMap[i].styleSet); 293 return SkRef(fNameToFamilyMap[i].styleSet);
274 } 294 }
275 } 295 }
296 // TODO: eventually we should not need to name fallback families.
297 for (int i = 0; i < fFallbackNameToFamilyMap.count(); ++i) {
298 if (fFallbackNameToFamilyMap[i].name.equals(tolc.lc())) {
299 return SkRef(fFallbackNameToFamilyMap[i].styleSet);
300 }
301 }
276 return NULL; 302 return NULL;
277 } 303 }
278 304
279 virtual SkTypeface* onMatchFamilyStyle(const char familyName[], 305 virtual SkTypeface* onMatchFamilyStyle(const char familyName[],
280 const SkFontStyle& style) const SK_OV ERRIDE { 306 const SkFontStyle& style) const SK_OV ERRIDE {
281 SkAutoTUnref<SkFontStyleSet> sset(this->matchFamily(familyName)); 307 SkAutoTUnref<SkFontStyleSet> sset(this->matchFamily(familyName));
282 return sset->matchStyle(style); 308 return sset->matchStyle(style);
283 } 309 }
284 310
285 virtual SkTypeface* onMatchFaceStyle(const SkTypeface* typeface, 311 virtual SkTypeface* onMatchFaceStyle(const SkTypeface* typeface,
286 const SkFontStyle& style) const SK_OVER RIDE { 312 const SkFontStyle& style) const SK_OVER RIDE {
287 for (int i = 0; i < fFontStyleSets.count(); ++i) { 313 for (int i = 0; i < fFontStyleSets.count(); ++i) {
288 for (int j = 0; j < fFontStyleSets[i]->fStyles.count(); ++j) { 314 for (int j = 0; j < fFontStyleSets[i]->fStyles.count(); ++j) {
289 if (fFontStyleSets[i]->fStyles[j] == typeface) { 315 if (fFontStyleSets[i]->fStyles[j] == typeface) {
290 return fFontStyleSets[i]->matchStyle(style); 316 return fFontStyleSets[i]->matchStyle(style);
291 } 317 }
292 } 318 }
293 } 319 }
294 return NULL; 320 return NULL;
295 } 321 }
296 322
323 virtual SkTypeface* onMatchFamilyStyleCharacter(const char familyName[],
324 const SkFontStyle& style,
325 const char bpc47[],
326 uint32_t character) const SK _OVERRIDE
327 {
328 // If the familyName maps to a family, then match the style and get the variant.
329 // Otherwise "elegant" unless the family name ends in "compact".
330 bool isCompact = false;
331 if (familyName) {
332 size_t familyNameLen = strlen(familyName);
333 static const char compactLiteral[] = "compact";
334 static const size_t compactLiteralLen = SK_ARRAY_COUNT(compactLitera l);
335 if (compactLiteralLen <= familyNameLen) {
djsollen 2014/08/01 20:24:04 should this be < or would a font with the name "co
bungeman-skia 2014/08/04 19:24:20 So, when I wrote this I was under the impression f
336 const char* familyNameEnd = familyName + familyNameLen - compact LiteralLen;
337 isCompact = SkToBool(strcmp(familyNameEnd, compactLiteral));
338 }
339 }
340
341 uint32_t ignoredVariantMask = SkPaintOptionsAndroid::kCompact_Variant;
342 if (isCompact) {
343 ignoredVariantMask = ~SkPaintOptionsAndroid::kCompact_Variant;
344 }
345
346 for (int i = 0; i < 2; ++i, ignoredVariantMask = ~ignoredVariantMask) {
djsollen 2014/08/01 20:24:04 document that the second time through the loop loo
bungeman-skia 2014/08/04 19:24:20 Changed the logic to make this more obvious and ad
347 SkLanguage lang(bpc47);
348 do {
349 const SkString& langTag = lang.getTag();
350 for (int i = 0; i < fFallbackNameToFamilyMap.count(); ++i) {
351 SkFontStyleSet_Android* family = fFallbackNameToFamilyMap[i] .styleSet;
352 SkAutoTUnref<SkTypeface_AndroidSystem> face(family->matchSty le(style));
353
354 if (!langTag.isEmpty() && langTag != face->fLang.getTag()) {
355 continue;
356 }
357
358 if (SkToBool(face->fVariant & ignoredVariantMask)) {
359 continue;
360 }
361
362 SkPaint paint;
363 paint.setTypeface(face);
364 paint.setTextEncoding(SkPaint::kUTF32_TextEncoding);
365
366 uint16_t glyphID;
367 paint.textToGlyphs(&character, sizeof(character), &glyphID);
368 if (glyphID != 0) {
369 return face.detach();
370 }
371 }
372 } while (!lang.getTag().isEmpty() && (lang = lang.getParent(), true) );
djsollen 2014/08/01 20:24:04 At first glance it is not clear that the last run
bungeman-skia 2014/08/04 19:24:20 Documented.
373 }
374 return NULL;
375 }
376
297 virtual SkTypeface* onCreateFromData(SkData* data, int ttcIndex) const SK_OV ERRIDE { 377 virtual SkTypeface* onCreateFromData(SkData* data, int ttcIndex) const SK_OV ERRIDE {
298 SkAutoTUnref<SkStream> stream(new SkMemoryStream(data)); 378 SkAutoTUnref<SkStream> stream(new SkMemoryStream(data));
299 return this->createFromStream(stream, ttcIndex); 379 return this->createFromStream(stream, ttcIndex);
300 } 380 }
301 381
302 virtual SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const SK_OVERRIDE { 382 virtual SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const SK_OVERRIDE {
303 SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path)); 383 SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path));
304 return stream.get() ? this->createFromStream(stream, ttcIndex) : NULL; 384 return stream.get() ? this->createFromStream(stream, ttcIndex) : NULL;
305 } 385 }
306 386
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
340 } 420 }
341 421
342 422
343 private: 423 private:
344 424
345 SkTArray<SkAutoTUnref<SkFontStyleSet_Android>, true> fFontStyleSets; 425 SkTArray<SkAutoTUnref<SkFontStyleSet_Android>, true> fFontStyleSets;
346 SkFontStyleSet* fDefaultFamily; 426 SkFontStyleSet* fDefaultFamily;
347 SkTypeface* fDefaultTypeface; 427 SkTypeface* fDefaultTypeface;
348 428
349 SkTDArray<NameToFamily> fNameToFamilyMap; 429 SkTDArray<NameToFamily> fNameToFamilyMap;
430 SkTDArray<NameToFamily> fFallbackNameToFamilyMap;
350 431
351 void buildNameToFamilyMap(SkTDArray<FontFamily*> families) { 432 void buildNameToFamilyMap(SkTDArray<FontFamily*> families) {
352 for (int i = 0; i < families.count(); i++) { 433 for (int i = 0; i < families.count(); i++) {
353 fFontStyleSets.push_back().reset( 434 FontFamily& family = *families[i];
354 SkNEW_ARGS(SkFontStyleSet_Android, (families[i]))); 435
355 for (int j = 0; j < families[i]->fNames.count(); j++) { 436 SkTDArray<NameToFamily>* nameToFamily = &fNameToFamilyMap;
356 NameToFamily* nextEntry = fNameToFamilyMap.append(); 437 if (family.fIsFallbackFont) {
357 SkNEW_PLACEMENT_ARGS(&nextEntry->name, SkString, (families[i]->f Names[j])); 438 nameToFamily = &fFallbackNameToFamilyMap;
358 nextEntry->styleSet = fFontStyleSets.back().get(); 439
440 if (0 == family.fNames.count()) {
441 SkString& fallbackName = family.fNames.push_back();
442 fallbackName.printf("%.2x##fallback", i);
443 }
444 }
445
446 SkFontStyleSet_Android* newSet = SkNEW_ARGS(SkFontStyleSet_Android, (family));
447 if (0 == newSet->count()) {
448 SkDELETE(newSet);
449 continue;
450 }
451 fFontStyleSets.push_back().reset(newSet);
452
453 for (int j = 0; j < family.fNames.count(); j++) {
454 NameToFamily* nextEntry = nameToFamily->append();
455 SkNEW_PLACEMENT_ARGS(&nextEntry->name, SkString, (family.fNames[ j]));
456 nextEntry->styleSet = newSet;
359 } 457 }
360 } 458 }
361 } 459 }
362 460
363 void findDefaultFont() { 461 void findDefaultFont() {
364 SkASSERT(!fFontStyleSets.empty()); 462 SkASSERT(!fFontStyleSets.empty());
365 463
366 static const char* gDefaultNames[] = { "sans-serif" }; 464 static const char* gDefaultNames[] = { "sans-serif" };
367 for (size_t i = 0; i < SK_ARRAY_COUNT(gDefaultNames); ++i) { 465 for (size_t i = 0; i < SK_ARRAY_COUNT(gDefaultNames); ++i) {
368 SkFontStyleSet* set = this->onMatchFamily(gDefaultNames[i]); 466 SkFontStyleSet* set = this->onMatchFamily(gDefaultNames[i]);
(...skipping 17 matching lines...) Expand all
386 } 484 }
387 485
388 typedef SkFontMgr INHERITED; 486 typedef SkFontMgr INHERITED;
389 }; 487 };
390 488
391 /////////////////////////////////////////////////////////////////////////////// 489 ///////////////////////////////////////////////////////////////////////////////
392 490
393 SkFontMgr* SkFontMgr::Factory() { 491 SkFontMgr* SkFontMgr::Factory() {
394 return SkNEW(SkFontMgr_Android); 492 return SkNEW(SkFontMgr_Android);
395 } 493 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698