| 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 |