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

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: Address comments, clarify code. 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 uint32_t variantStyle)
63 : INHERITED(index, style, isFixedPitch, familyName) 65 : INHERITED(index, style, isFixedPitch, familyName)
64 , fPathName(pathName) { } 66 , fPathName(pathName)
67 , fLang(lang)
68 , fVariantStyle(variantStyle) { }
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 uint32_t fVariantStyle;
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 uint32_t variant = fontFile.fPaintOptions.getFontVariant();
158 if (SkPaintOptionsAndroid::kDefault_Variant == variant) {
159 variant = SkPaintOptionsAndroid::kCompact_Variant |
160 SkPaintOptionsAndroid::kElegant_Variant;
161 }
162
163 // The first specified family name overrides the family name found i n the font.
164 // TODO: SkTypeface_AndroidSystem::onCreateFamilyNameIterator should return
165 // all of the specified family names in addition to the names found in the font.
166 if (cannonicalFamilyName != NULL) {
167 familyName = *cannonicalFamilyName;
168 }
169
147 fStyles.push_back().reset(SkNEW_ARGS(SkTypeface_AndroidSystem, 170 fStyles.push_back().reset(SkNEW_ARGS(SkTypeface_AndroidSystem,
148 (pathName, ttcIndex, 171 (pathName, ttcIndex,
149 style, isFixedWidth, fontName) )); 172 style, isFixedWidth, familyNam e,
173 lang, variant)));
150 } 174 }
151 } 175 }
152 176
153 virtual int count() SK_OVERRIDE { 177 virtual int count() SK_OVERRIDE {
154 return fStyles.count(); 178 return fStyles.count();
155 } 179 }
156 virtual void getStyle(int index, SkFontStyle* style, SkString* name) SK_OVER RIDE { 180 virtual void getStyle(int index, SkFontStyle* style, SkString* name) SK_OVER RIDE {
157 if (index < 0 || fStyles.count() <= index) { 181 if (index < 0 || fStyles.count() <= index) {
158 return; 182 return;
159 } 183 }
160 if (style) { 184 if (style) {
161 *style = this->style(index); 185 *style = this->style(index);
162 } 186 }
163 if (name) { 187 if (name) {
164 name->reset(); 188 name->reset();
165 } 189 }
166 } 190 }
167 virtual SkTypeface* createTypeface(int index) SK_OVERRIDE { 191 virtual SkTypeface_AndroidSystem* createTypeface(int index) SK_OVERRIDE {
168 if (index < 0 || fStyles.count() <= index) { 192 if (index < 0 || fStyles.count() <= index) {
169 return NULL; 193 return NULL;
170 } 194 }
171 return SkRef(fStyles[index].get()); 195 return SkRef(fStyles[index].get());
172 } 196 }
173 197
174 /** Find the typeface in this style set that most closely matches the given pattern. 198 /** Find the typeface in this style set that most closely matches the given pattern.
175 * TODO: consider replacing with SkStyleSet_Indirect::matchStyle(); 199 * TODO: consider replacing with SkStyleSet_Indirect::matchStyle();
176 * this simpler version using match_score() passes all our tests. 200 * this simpler version using match_score() passes all our tests.
177 */ 201 */
178 virtual SkTypeface* matchStyle(const SkFontStyle& pattern) SK_OVERRIDE { 202 virtual SkTypeface_AndroidSystem* matchStyle(const SkFontStyle& pattern) SK_ OVERRIDE {
179 if (0 == fStyles.count()) { 203 if (0 == fStyles.count()) {
180 return NULL; 204 return NULL;
181 } 205 }
182 SkTypeface* closest = fStyles[0]; 206 SkTypeface_AndroidSystem* closest = fStyles[0];
183 int minScore = std::numeric_limits<int>::max(); 207 int minScore = std::numeric_limits<int>::max();
184 for (int i = 0; i < fStyles.count(); ++i) { 208 for (int i = 0; i < fStyles.count(); ++i) {
185 SkFontStyle style = this->style(i); 209 SkFontStyle style = this->style(i);
186 int score = match_score(pattern, style); 210 int score = match_score(pattern, style);
187 if (score < minScore) { 211 if (score < minScore) {
188 closest = fStyles[i]; 212 closest = fStyles[i];
189 minScore = score; 213 minScore = score;
190 } 214 }
191 } 215 }
192 return SkRef(closest); 216 return SkRef(closest);
(...skipping 13 matching lines...) Expand all
206 return SkFontStyle::kUpright_Slant; 230 return SkFontStyle::kUpright_Slant;
207 } 231 }
208 static int match_score(const SkFontStyle& pattern, const SkFontStyle& candid ate) { 232 static int match_score(const SkFontStyle& pattern, const SkFontStyle& candid ate) {
209 int score = 0; 233 int score = 0;
210 score += abs((pattern.width() - candidate.width()) * 100); 234 score += abs((pattern.width() - candidate.width()) * 100);
211 score += abs((pattern.isItalic() == candidate.isItalic()) ? 0 : 1000); 235 score += abs((pattern.isItalic() == candidate.isItalic()) ? 0 : 1000);
212 score += abs(pattern.weight() - candidate.weight()); 236 score += abs(pattern.weight() - candidate.weight());
213 return score; 237 return score;
214 } 238 }
215 239
216 SkTArray<SkAutoTUnref<SkTypeface>, true> fStyles; 240 SkTArray<SkAutoTUnref<SkTypeface_AndroidSystem>, true> fStyles;
217 241
218 friend struct NameToFamily; 242 friend struct NameToFamily;
219 friend class SkFontMgr_Android; 243 friend class SkFontMgr_Android;
220 244
221 typedef SkFontStyleSet INHERITED; 245 typedef SkFontStyleSet INHERITED;
222 }; 246 };
223 247
224 /** On Android a single family can have many names, but our API assumes unique n ames. 248 /** 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 249 * Map names to the back end so that all names for a given family refer to the same
226 * (non-replicated) set of typefaces. 250 * (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 { 290 virtual SkFontStyleSet* onMatchFamily(const char familyName[]) const SK_OVER RIDE {
267 if (!familyName) { 291 if (!familyName) {
268 return NULL; 292 return NULL;
269 } 293 }
270 SkAutoAsciiToLC tolc(familyName); 294 SkAutoAsciiToLC tolc(familyName);
271 for (int i = 0; i < fNameToFamilyMap.count(); ++i) { 295 for (int i = 0; i < fNameToFamilyMap.count(); ++i) {
272 if (fNameToFamilyMap[i].name.equals(tolc.lc())) { 296 if (fNameToFamilyMap[i].name.equals(tolc.lc())) {
273 return SkRef(fNameToFamilyMap[i].styleSet); 297 return SkRef(fNameToFamilyMap[i].styleSet);
274 } 298 }
275 } 299 }
300 // TODO: eventually we should not need to name fallback families.
301 for (int i = 0; i < fFallbackNameToFamilyMap.count(); ++i) {
302 if (fFallbackNameToFamilyMap[i].name.equals(tolc.lc())) {
303 return SkRef(fFallbackNameToFamilyMap[i].styleSet);
304 }
305 }
276 return NULL; 306 return NULL;
277 } 307 }
278 308
279 virtual SkTypeface* onMatchFamilyStyle(const char familyName[], 309 virtual SkTypeface* onMatchFamilyStyle(const char familyName[],
280 const SkFontStyle& style) const SK_OV ERRIDE { 310 const SkFontStyle& style) const SK_OV ERRIDE {
281 SkAutoTUnref<SkFontStyleSet> sset(this->matchFamily(familyName)); 311 SkAutoTUnref<SkFontStyleSet> sset(this->matchFamily(familyName));
282 return sset->matchStyle(style); 312 return sset->matchStyle(style);
283 } 313 }
284 314
285 virtual SkTypeface* onMatchFaceStyle(const SkTypeface* typeface, 315 virtual SkTypeface* onMatchFaceStyle(const SkTypeface* typeface,
286 const SkFontStyle& style) const SK_OVER RIDE { 316 const SkFontStyle& style) const SK_OVER RIDE {
287 for (int i = 0; i < fFontStyleSets.count(); ++i) { 317 for (int i = 0; i < fFontStyleSets.count(); ++i) {
288 for (int j = 0; j < fFontStyleSets[i]->fStyles.count(); ++j) { 318 for (int j = 0; j < fFontStyleSets[i]->fStyles.count(); ++j) {
289 if (fFontStyleSets[i]->fStyles[j] == typeface) { 319 if (fFontStyleSets[i]->fStyles[j] == typeface) {
290 return fFontStyleSets[i]->matchStyle(style); 320 return fFontStyleSets[i]->matchStyle(style);
291 } 321 }
292 } 322 }
293 } 323 }
294 return NULL; 324 return NULL;
295 } 325 }
296 326
327 virtual SkTypeface* onMatchFamilyStyleCharacter(const char familyName[],
328 const SkFontStyle& style,
329 const char bpc47[],
330 uint32_t character) const SK _OVERRIDE
331 {
332 // The variant 'elegant' is 'not squashed', 'compact' is 'stays in ascen t/descent'.
333 // The variant 'default' means 'compact and elegant'.
334 // As a result, it is not possible to know the variant context from the font alone.
335 // TODO: add 'is_elegant' and 'is_compact' bits to 'style' request.
336
337 // For compatibility, try 'elegant' fonts first in fallback.
338 uint32_t variantMask = SkPaintOptionsAndroid::kElegant_Variant;
339
340 // The first time match anything in the mask, second time anything not i n the mask.
341 for (bool maskMatches = true; maskMatches != false; maskMatches = false) {
342 SkLanguage lang(bpc47);
343 // Match against the language, removing a segment each time.
344 // The last time through the loop, the language will be empty.
345 // The empty language is special, and matches all languages.
346 do {
347 const SkString& langTag = lang.getTag();
348 for (int i = 0; i < fFallbackNameToFamilyMap.count(); ++i) {
349 SkFontStyleSet_Android* family = fFallbackNameToFamilyMap[i] .styleSet;
350 SkAutoTUnref<SkTypeface_AndroidSystem> face(family->matchSty le(style));
351
352 if (!langTag.isEmpty() && langTag != face->fLang.getTag()) {
353 continue;
354 }
355
356 if (SkToBool(face->fVariantStyle & variantMask) != maskMatch es) {
357 continue;
358 }
359
360 SkPaint paint;
361 paint.setTypeface(face);
362 paint.setTextEncoding(SkPaint::kUTF32_TextEncoding);
363
364 uint16_t glyphID;
365 paint.textToGlyphs(&character, sizeof(character), &glyphID);
366 if (glyphID != 0) {
367 return face.detach();
368 }
369 }
370 } while (!lang.getTag().isEmpty() && (lang = lang.getParent(), true) );
371 }
372 return NULL;
373 }
374
297 virtual SkTypeface* onCreateFromData(SkData* data, int ttcIndex) const SK_OV ERRIDE { 375 virtual SkTypeface* onCreateFromData(SkData* data, int ttcIndex) const SK_OV ERRIDE {
298 SkAutoTUnref<SkStream> stream(new SkMemoryStream(data)); 376 SkAutoTUnref<SkStream> stream(new SkMemoryStream(data));
299 return this->createFromStream(stream, ttcIndex); 377 return this->createFromStream(stream, ttcIndex);
300 } 378 }
301 379
302 virtual SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const SK_OVERRIDE { 380 virtual SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const SK_OVERRIDE {
303 SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path)); 381 SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path));
304 return stream.get() ? this->createFromStream(stream, ttcIndex) : NULL; 382 return stream.get() ? this->createFromStream(stream, ttcIndex) : NULL;
305 } 383 }
306 384
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
340 } 418 }
341 419
342 420
343 private: 421 private:
344 422
345 SkTArray<SkAutoTUnref<SkFontStyleSet_Android>, true> fFontStyleSets; 423 SkTArray<SkAutoTUnref<SkFontStyleSet_Android>, true> fFontStyleSets;
346 SkFontStyleSet* fDefaultFamily; 424 SkFontStyleSet* fDefaultFamily;
347 SkTypeface* fDefaultTypeface; 425 SkTypeface* fDefaultTypeface;
348 426
349 SkTDArray<NameToFamily> fNameToFamilyMap; 427 SkTDArray<NameToFamily> fNameToFamilyMap;
428 SkTDArray<NameToFamily> fFallbackNameToFamilyMap;
350 429
351 void buildNameToFamilyMap(SkTDArray<FontFamily*> families) { 430 void buildNameToFamilyMap(SkTDArray<FontFamily*> families) {
352 for (int i = 0; i < families.count(); i++) { 431 for (int i = 0; i < families.count(); i++) {
353 fFontStyleSets.push_back().reset( 432 FontFamily& family = *families[i];
354 SkNEW_ARGS(SkFontStyleSet_Android, (families[i]))); 433
355 for (int j = 0; j < families[i]->fNames.count(); j++) { 434 SkTDArray<NameToFamily>* nameToFamily = &fNameToFamilyMap;
356 NameToFamily* nextEntry = fNameToFamilyMap.append(); 435 if (family.fIsFallbackFont) {
357 SkNEW_PLACEMENT_ARGS(&nextEntry->name, SkString, (families[i]->f Names[j])); 436 nameToFamily = &fFallbackNameToFamilyMap;
358 nextEntry->styleSet = fFontStyleSets.back().get(); 437
438 if (0 == family.fNames.count()) {
439 SkString& fallbackName = family.fNames.push_back();
440 fallbackName.printf("%.2x##fallback", i);
441 }
442 }
443
444 SkFontStyleSet_Android* newSet = SkNEW_ARGS(SkFontStyleSet_Android, (family));
445 if (0 == newSet->count()) {
446 SkDELETE(newSet);
447 continue;
448 }
449 fFontStyleSets.push_back().reset(newSet);
450
451 for (int j = 0; j < family.fNames.count(); j++) {
452 NameToFamily* nextEntry = nameToFamily->append();
453 SkNEW_PLACEMENT_ARGS(&nextEntry->name, SkString, (family.fNames[ j]));
454 nextEntry->styleSet = newSet;
359 } 455 }
360 } 456 }
361 } 457 }
362 458
363 void findDefaultFont() { 459 void findDefaultFont() {
364 SkASSERT(!fFontStyleSets.empty()); 460 SkASSERT(!fFontStyleSets.empty());
365 461
366 static const char* gDefaultNames[] = { "sans-serif" }; 462 static const char* gDefaultNames[] = { "sans-serif" };
367 for (size_t i = 0; i < SK_ARRAY_COUNT(gDefaultNames); ++i) { 463 for (size_t i = 0; i < SK_ARRAY_COUNT(gDefaultNames); ++i) {
368 SkFontStyleSet* set = this->onMatchFamily(gDefaultNames[i]); 464 SkFontStyleSet* set = this->onMatchFamily(gDefaultNames[i]);
(...skipping 17 matching lines...) Expand all
386 } 482 }
387 483
388 typedef SkFontMgr INHERITED; 484 typedef SkFontMgr INHERITED;
389 }; 485 };
390 486
391 /////////////////////////////////////////////////////////////////////////////// 487 ///////////////////////////////////////////////////////////////////////////////
392 488
393 SkFontMgr* SkFontMgr::Factory() { 489 SkFontMgr* SkFontMgr::Factory() {
394 return SkNEW(SkFontMgr_Android); 490 return SkNEW(SkFontMgr_Android);
395 } 491 }
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