OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2009 Google Inc. | 2 * Copyright 2009 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 /* migrated from chrome/src/skia/ext/SkFontHost_fontconfig_direct.cpp */ | 8 /* migrated from chrome/src/skia/ext/SkFontHost_fontconfig_direct.cpp */ |
9 | 9 |
10 #include <string> | 10 #include <string> |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
58 int SkFontConfigInterface::matchFamilySet(const char familyName[], | 58 int SkFontConfigInterface::matchFamilySet(const char familyName[], |
59 SkString* outFamilyName, | 59 SkString* outFamilyName, |
60 FontIdentity outIdentities[], | 60 FontIdentity outIdentities[], |
61 int maxCount) { | 61 int maxCount) { |
62 return 0; | 62 return 0; |
63 } | 63 } |
64 #endif | 64 #endif |
65 | 65 |
66 /////////////////////////////////////////////////////////////////////////////// | 66 /////////////////////////////////////////////////////////////////////////////// |
67 | 67 |
| 68 // Returns the string from the pattern, or NULL |
| 69 static const char* get_name(FcPattern* pattern, const char field[], |
| 70 int index = 0) { |
| 71 const char* name; |
| 72 if (FcPatternGetString(pattern, field, index, |
| 73 (FcChar8**)&name) != FcResultMatch) { |
| 74 name = NULL; |
| 75 } |
| 76 return name; |
| 77 } |
| 78 |
| 79 /////////////////////////////////////////////////////////////////////////////// |
| 80 |
68 namespace { | 81 namespace { |
69 | 82 |
70 // Equivalence classes, used to match the Liberation and other fonts | 83 // Equivalence classes, used to match the Liberation and other fonts |
71 // with their metric-compatible replacements. See the discussion in | 84 // with their metric-compatible replacements. See the discussion in |
72 // GetFontEquivClass(). | 85 // GetFontEquivClass(). |
73 enum FontEquivClass | 86 enum FontEquivClass |
74 { | 87 { |
75 OTHER, | 88 OTHER, |
76 SANS, | 89 SANS, |
77 SERIF, | 90 SERIF, |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
231 // basic font names like "Sans", "Serif" or "Monospace". This function | 244 // basic font names like "Sans", "Serif" or "Monospace". This function |
232 // tells you whether a given request is for such a fallback. | 245 // tells you whether a given request is for such a fallback. |
233 bool IsFallbackFontAllowed(const std::string& family) { | 246 bool IsFallbackFontAllowed(const std::string& family) { |
234 const char* family_cstr = family.c_str(); | 247 const char* family_cstr = family.c_str(); |
235 return family.empty() || | 248 return family.empty() || |
236 strcasecmp(family_cstr, "sans") == 0 || | 249 strcasecmp(family_cstr, "sans") == 0 || |
237 strcasecmp(family_cstr, "serif") == 0 || | 250 strcasecmp(family_cstr, "serif") == 0 || |
238 strcasecmp(family_cstr, "monospace") == 0; | 251 strcasecmp(family_cstr, "monospace") == 0; |
239 } | 252 } |
240 | 253 |
| 254 static bool valid_pattern(FcPattern* pattern) { |
| 255 FcBool is_scalable; |
| 256 if (FcPatternGetBool(pattern, FC_SCALABLE, 0, &is_scalable) != FcResultMatch |
| 257 || !is_scalable) { |
| 258 return false; |
| 259 } |
| 260 |
| 261 // fontconfig can also return fonts which are unreadable |
| 262 const char* c_filename = get_name(pattern, FC_FILE); |
| 263 if (!c_filename) { |
| 264 return false; |
| 265 } |
| 266 if (access(c_filename, R_OK) != 0) { |
| 267 return false; |
| 268 } |
| 269 return true; |
| 270 } |
| 271 |
241 // Find matching font from |font_set| for the given font family. | 272 // Find matching font from |font_set| for the given font family. |
242 FcPattern* MatchFont(FcFontSet* font_set, | 273 FcPattern* MatchFont(FcFontSet* font_set, |
243 FcChar8* post_config_family, | 274 const char* post_config_family, |
244 const std::string& family) { | 275 const std::string& family) { |
245 // Older versions of fontconfig have a bug where they cannot select | 276 // Older versions of fontconfig have a bug where they cannot select |
246 // only scalable fonts so we have to manually filter the results. | 277 // only scalable fonts so we have to manually filter the results. |
247 FcPattern* match = NULL; | 278 FcPattern* match = NULL; |
248 for (int i = 0; i < font_set->nfont; ++i) { | 279 for (int i = 0; i < font_set->nfont; ++i) { |
249 FcPattern* current = font_set->fonts[i]; | 280 FcPattern* current = font_set->fonts[i]; |
250 FcBool is_scalable; | 281 if (valid_pattern(current)) { |
251 | 282 match = current; |
252 if (FcPatternGetBool(current, FC_SCALABLE, 0, | 283 break; |
253 &is_scalable) != FcResultMatch || | |
254 !is_scalable) { | |
255 continue; | |
256 } | 284 } |
257 | |
258 // fontconfig can also return fonts which are unreadable | |
259 FcChar8* c_filename; | |
260 if (FcPatternGetString(current, FC_FILE, 0, &c_filename) != FcResultMatch) | |
261 continue; | |
262 | |
263 if (access(reinterpret_cast<char*>(c_filename), R_OK) != 0) | |
264 continue; | |
265 | |
266 match = current; | |
267 break; | |
268 } | 285 } |
269 | 286 |
270 if (match && !IsFallbackFontAllowed(family)) { | 287 if (match && !IsFallbackFontAllowed(family)) { |
271 bool acceptable_substitute = false; | 288 bool acceptable_substitute = false; |
272 for (int id = 0; id < 255; ++id) { | 289 for (int id = 0; id < 255; ++id) { |
273 FcChar8* post_match_family; | 290 const char* post_match_family = get_name(match, FC_FAMILY, id); |
274 if (FcPatternGetString(match, FC_FAMILY, id, &post_match_family) != | 291 if (!post_match_family) |
275 FcResultMatch) | |
276 break; | 292 break; |
277 acceptable_substitute = | 293 acceptable_substitute = |
278 (strcasecmp(reinterpret_cast<char*>(post_config_family), | 294 (strcasecmp(post_config_family, post_match_family) == 0 || |
279 reinterpret_cast<char*>(post_match_family)) == 0 || | |
280 // Workaround for Issue 12530: | 295 // Workaround for Issue 12530: |
281 // requested family: "Bitstream Vera Sans" | 296 // requested family: "Bitstream Vera Sans" |
282 // post_config_family: "Arial" | 297 // post_config_family: "Arial" |
283 // post_match_family: "Bitstream Vera Sans" | 298 // post_match_family: "Bitstream Vera Sans" |
284 // -> We should treat this case as a good match. | 299 // -> We should treat this case as a good match. |
285 strcasecmp(family.c_str(), | 300 strcasecmp(family.c_str(), post_match_family) == 0) || |
286 reinterpret_cast<char*>(post_match_family)) == 0) || | 301 IsMetricCompatibleReplacement(family.c_str(), post_match_family); |
287 IsMetricCompatibleReplacement(family.c_str(), | |
288 reinterpret_cast<char*>(post_match_family)); | |
289 if (acceptable_substitute) | 302 if (acceptable_substitute) |
290 break; | 303 break; |
291 } | 304 } |
292 if (!acceptable_substitute) | 305 if (!acceptable_substitute) |
293 return NULL; | 306 return NULL; |
294 } | 307 } |
295 | 308 |
296 return match; | 309 return match; |
297 } | 310 } |
298 | 311 |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
391 // post_match_family: "Helvetica" | 404 // post_match_family: "Helvetica" |
392 // -> good match | 405 // -> good match |
393 // | 406 // |
394 // and for a missing font: | 407 // and for a missing font: |
395 // requested family: "Monaco" | 408 // requested family: "Monaco" |
396 // post_config_family: "Monaco" | 409 // post_config_family: "Monaco" |
397 // post_match_family: "Times New Roman" | 410 // post_match_family: "Times New Roman" |
398 // -> BAD match | 411 // -> BAD match |
399 // | 412 // |
400 // However, we special-case fallback fonts; see IsFallbackFontAllowed(). | 413 // However, we special-case fallback fonts; see IsFallbackFontAllowed(). |
401 FcChar8* post_config_family; | 414 |
402 FcPatternGetString(pattern, FC_FAMILY, 0, &post_config_family); | 415 const char* post_config_family = get_name(pattern, FC_FAMILY); |
| 416 if (!post_config_family) { |
| 417 return false; |
| 418 } |
403 | 419 |
404 FcResult result; | 420 FcResult result; |
405 FcFontSet* font_set = FcFontSort(0, pattern, 0, 0, &result); | 421 FcFontSet* font_set = FcFontSort(0, pattern, 0, 0, &result); |
406 if (!font_set) { | 422 if (!font_set) { |
407 FcPatternDestroy(pattern); | 423 FcPatternDestroy(pattern); |
408 return false; | 424 return false; |
409 } | 425 } |
410 | 426 |
411 FcPattern* match = MatchFont(font_set, post_config_family, familyStr); | 427 FcPattern* match = MatchFont(font_set, post_config_family, familyStr); |
412 if (!match) { | 428 if (!match) { |
413 FcPatternDestroy(pattern); | 429 FcPatternDestroy(pattern); |
414 FcFontSetDestroy(font_set); | 430 FcFontSetDestroy(font_set); |
415 return false; | 431 return false; |
416 } | 432 } |
417 | 433 |
418 FcPatternDestroy(pattern); | 434 FcPatternDestroy(pattern); |
419 | 435 |
420 // From here out we just extract our results from 'match' | 436 // From here out we just extract our results from 'match' |
421 | 437 |
422 if (FcPatternGetString(match, FC_FAMILY, 0, &post_config_family) != FcResult
Match) { | 438 post_config_family = get_name(match, FC_FAMILY); |
| 439 if (!post_config_family) { |
423 FcFontSetDestroy(font_set); | 440 FcFontSetDestroy(font_set); |
424 return false; | 441 return false; |
425 } | 442 } |
426 | 443 |
427 FcChar8* c_filename; | 444 const char* c_filename = get_name(match, FC_FILE); |
428 if (FcPatternGetString(match, FC_FILE, 0, &c_filename) != FcResultMatch) { | 445 if (!c_filename) { |
429 FcFontSetDestroy(font_set); | 446 FcFontSetDestroy(font_set); |
430 return false; | 447 return false; |
431 } | 448 } |
432 | 449 |
433 int face_index; | 450 int face_index; |
434 if (FcPatternGetInteger(match, FC_INDEX, 0, &face_index) != FcResultMatch) { | 451 if (FcPatternGetInteger(match, FC_INDEX, 0, &face_index) != FcResultMatch) { |
435 FcFontSetDestroy(font_set); | 452 FcFontSetDestroy(font_set); |
436 return false; | 453 return false; |
437 } | 454 } |
438 | 455 |
439 FcFontSetDestroy(font_set); | 456 FcFontSetDestroy(font_set); |
440 | 457 |
441 if (outIdentity) { | 458 if (outIdentity) { |
442 outIdentity->fTTCIndex = face_index; | 459 outIdentity->fTTCIndex = face_index; |
443 outIdentity->fString.set((const char*)c_filename); | 460 outIdentity->fString.set(c_filename); |
444 } | 461 } |
445 if (outFamilyName) { | 462 if (outFamilyName) { |
446 outFamilyName->set((const char*)post_config_family); | 463 outFamilyName->set(post_config_family); |
447 } | 464 } |
448 if (outStyle) { | 465 if (outStyle) { |
449 *outStyle = GetFontStyle(match); | 466 *outStyle = GetFontStyle(match); |
450 } | 467 } |
451 return true; | 468 return true; |
452 } | 469 } |
453 | 470 |
454 SkStream* SkFontConfigInterfaceDirect::openStream(const FontIdentity& identity)
{ | 471 SkStream* SkFontConfigInterfaceDirect::openStream(const FontIdentity& identity)
{ |
455 return SkStream::NewFromFile(identity.fString.c_str()); | 472 return SkStream::NewFromFile(identity.fString.c_str()); |
456 } | 473 } |
457 | 474 |
458 /////////////////////////////////////////////////////////////////////////////// | 475 /////////////////////////////////////////////////////////////////////////////// |
459 | 476 |
460 static const char* get_name(FcPattern* pattern, const char field[]) { | |
461 const char* name; | |
462 if (FcPatternGetString(pattern, field, 0, (FcChar8**)&name) != FcResultMatch
) { | |
463 name = ""; | |
464 } | |
465 return name; | |
466 } | |
467 | |
468 static bool find_name(const SkTDArray<const char*>& list, const char* str) { | 477 static bool find_name(const SkTDArray<const char*>& list, const char* str) { |
469 int count = list.count(); | 478 int count = list.count(); |
470 for (int i = 0; i < count; ++i) { | 479 for (int i = 0; i < count; ++i) { |
471 if (!strcmp(list[i], str)) { | 480 if (!strcmp(list[i], str)) { |
472 return true; | 481 return true; |
473 } | 482 } |
474 } | 483 } |
475 return false; | 484 return false; |
476 } | 485 } |
477 | 486 |
478 SkDataTable* SkFontConfigInterfaceDirect::getFamilyNames() { | 487 SkDataTable* SkFontConfigInterfaceDirect::getFamilyNames() { |
479 FcPattern* pat = FcPatternCreate(); | 488 FcPattern* pat = FcPatternCreate(); |
480 FcObjectSet* os = FcObjectSetBuild (FC_FAMILY, (char *) 0); | 489 FcObjectSet* os = FcObjectSetBuild (FC_FAMILY, (char *) 0); |
481 if (NULL == os) { | 490 if (NULL == os) { |
482 return NULL; | 491 return NULL; |
483 } | 492 } |
484 FcFontSet* fs = FcFontList(NULL, pat, os); | 493 FcFontSet* fs = FcFontList(NULL, pat, os); |
485 if (NULL == fs) { | 494 if (NULL == fs) { |
486 FcObjectSetDestroy(os); | 495 FcObjectSetDestroy(os); |
487 return NULL; | 496 return NULL; |
488 } | 497 } |
489 | 498 |
490 SkTDArray<const char*> names; | 499 SkTDArray<const char*> names; |
491 SkTDArray<size_t> sizes; | 500 SkTDArray<size_t> sizes; |
492 for (int i = 0; i < fs->nfont; ++i) { | 501 for (int i = 0; i < fs->nfont; ++i) { |
493 FcPattern* match = fs->fonts[i]; | 502 FcPattern* match = fs->fonts[i]; |
494 const char* famName = get_name(match, FC_FAMILY); | 503 const char* famName = get_name(match, FC_FAMILY); |
495 if (!find_name(names, famName)) { | 504 if (famName && !find_name(names, famName)) { |
496 *names.append() = famName; | 505 *names.append() = famName; |
497 *sizes.append() = strlen(famName) + 1; | 506 *sizes.append() = strlen(famName) + 1; |
498 } | 507 } |
499 } | 508 } |
500 | 509 |
501 FcFontSetDestroy(fs); | 510 FcFontSetDestroy(fs); |
502 FcObjectSetDestroy(os); | 511 FcObjectSetDestroy(os); |
503 FcPatternDestroy(pat); | 512 FcPatternDestroy(pat); |
504 | 513 |
505 return SkDataTable::NewCopyArrays((const void*const*)names.begin(), | 514 return SkDataTable::NewCopyArrays((const void*const*)names.begin(), |
506 sizes.begin(), names.count()); | 515 sizes.begin(), names.count()); |
507 } | 516 } |
508 | 517 |
509 bool SkFontConfigInterfaceDirect::matchFamilySet(const char inFamilyName[], | 518 bool SkFontConfigInterfaceDirect::matchFamilySet(const char inFamilyName[], |
510 SkString* outFamilyName, | 519 SkString* outFamilyName, |
511 SkTArray<FontIdentity>* ids) { | 520 SkTArray<FontIdentity>* ids) { |
512 return false; | 521 return false; |
513 } | 522 } |
OLD | NEW |