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

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

Issue 1471033002: Fix Google3 fonts. (Closed) Base URL: https://skia.googlesource.com/skia@master
Patch Set: Move files back to ports. Created 5 years 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 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 "SkFontConfigInterfaceDirect.h"
10 #include "SkBuffer.h" 11 #include "SkBuffer.h"
11 #include "SkDataTable.h" 12 #include "SkDataTable.h"
12 #include "SkFontConfigInterface.h"
13 #include "SkFontStyle.h" 13 #include "SkFontStyle.h"
14 #include "SkMutex.h" 14 #include "SkMutex.h"
15 #include "SkStream.h" 15 #include "SkStream.h"
16 #include "SkString.h" 16 #include "SkString.h"
17 #include "SkTArray.h" 17 #include "SkTArray.h"
18 #include "SkTDArray.h" 18 #include "SkTDArray.h"
19 #include "SkTemplates.h" 19 #include "SkTemplates.h"
20 #include "SkTypeface.h" 20 #include "SkTypeface.h"
21 #include "SkTypes.h" 21 #include "SkTypes.h"
22 22
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
100 SkASSERT(iden0 != iden1); 100 SkASSERT(iden0 != iden1);
101 101
102 make_iden(&iden1); 102 make_iden(&iden1);
103 SkASSERT(iden0 == iden1); 103 SkASSERT(iden0 == iden1);
104 104
105 test_writeToMemory(iden0, 0); 105 test_writeToMemory(iden0, 0);
106 test_writeToMemory(iden0, 0); 106 test_writeToMemory(iden0, 0);
107 } 107 }
108 #endif 108 #endif
109 109
110 class SkFontConfigInterfaceDirect : public SkFontConfigInterface {
111 public:
112 SkFontConfigInterfaceDirect();
113 virtual ~SkFontConfigInterfaceDirect();
114
115 virtual bool matchFamilyName(const char familyName[],
116 SkTypeface::Style requested,
117 FontIdentity* outFontIdentifier,
118 SkString* outFamilyName,
119 SkTypeface::Style* outStyle) override;
120 SkStreamAsset* openStream(const FontIdentity&) override;
121
122 // new APIs
123 SkDataTable* getFamilyNames() override;
124 virtual bool matchFamilySet(const char inFamilyName[],
125 SkString* outFamilyName,
126 SkTArray<FontIdentity>*) override;
127
128 private:
129 SkMutex mutex_;
130 };
131
132 SkFontConfigInterface* SkFontConfigInterface::GetSingletonDirectInterface(SkBase Mutex* mutex) {
133 SkAutoMutexAcquire ac(mutex);
134 static SkFontConfigInterfaceDirect* singleton = nullptr;
135 if (singleton == nullptr) {
136 singleton = new SkFontConfigInterfaceDirect;
137 }
138 return singleton;
139 }
140
141 /////////////////////////////////////////////////////////////////////////////// 110 ///////////////////////////////////////////////////////////////////////////////
142 111
143 // Returns the string from the pattern, or nullptr 112 // Returns the string from the pattern, or nullptr
144 static const char* get_name(FcPattern* pattern, const char field[], 113 const char* SkFontConfigInterfaceDirect::GetName(FcPattern* pattern, const char field[],
145 int index = 0) { 114 int index) {
146 const char* name; 115 const char* name;
147 if (FcPatternGetString(pattern, field, index, 116 if (FcPatternGetString(pattern, field, index,
148 (FcChar8**)&name) != FcResultMatch) { 117 (FcChar8**)&name) != FcResultMatch) {
149 name = nullptr; 118 name = nullptr;
150 } 119 }
151 return name; 120 return name;
152 } 121 }
153 122
154 /////////////////////////////////////////////////////////////////////////////// 123 ///////////////////////////////////////////////////////////////////////////////
155 124
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after
327 // basic font names like "Sans", "Serif" or "Monospace". This function 296 // basic font names like "Sans", "Serif" or "Monospace". This function
328 // tells you whether a given request is for such a fallback. 297 // tells you whether a given request is for such a fallback.
329 bool IsFallbackFontAllowed(const SkString& family) { 298 bool IsFallbackFontAllowed(const SkString& family) {
330 const char* family_cstr = family.c_str(); 299 const char* family_cstr = family.c_str();
331 return family.isEmpty() || 300 return family.isEmpty() ||
332 strcasecmp(family_cstr, "sans") == 0 || 301 strcasecmp(family_cstr, "sans") == 0 ||
333 strcasecmp(family_cstr, "serif") == 0 || 302 strcasecmp(family_cstr, "serif") == 0 ||
334 strcasecmp(family_cstr, "monospace") == 0; 303 strcasecmp(family_cstr, "monospace") == 0;
335 } 304 }
336 305
337 static bool valid_pattern(FcPattern* pattern) { 306 // Retrieves |is_bold|, |is_italic| and |font_family| properties from |font|.
307 SkTypeface::Style GetFontStyle(FcPattern* font) {
308 int resulting_bold;
309 if (FcPatternGetInteger(font, FC_WEIGHT, 0, &resulting_bold))
310 resulting_bold = FC_WEIGHT_NORMAL;
311
312 int resulting_italic;
313 if (FcPatternGetInteger(font, FC_SLANT, 0, &resulting_italic))
314 resulting_italic = FC_SLANT_ROMAN;
315
316 // If we ask for an italic font, fontconfig might take a roman font and set
317 // the undocumented property FC_MATRIX to a skew matrix. It'll then say
318 // that the font is italic or oblique. So, if we see a matrix, we don't
319 // believe that it's italic.
320 FcValue matrix;
321 const bool have_matrix = FcPatternGet(font, FC_MATRIX, 0, &matrix) == 0;
322
323 // If we ask for an italic font, fontconfig might take a roman font and set
324 // FC_EMBOLDEN.
325 FcValue embolden;
326 const bool have_embolden = FcPatternGet(font, FC_EMBOLDEN, 0, &embolden) == 0;
327
328 int styleBits = 0;
329 if (resulting_bold > FC_WEIGHT_MEDIUM && !have_embolden) {
330 styleBits |= SkTypeface::kBold;
331 }
332 if (resulting_italic > FC_SLANT_ROMAN && !have_matrix) {
333 styleBits |= SkTypeface::kItalic;
334 }
335
336 return (SkTypeface::Style)styleBits;
337 }
338
339 } // anonymous namespace
340
341 ///////////////////////////////////////////////////////////////////////////////
342
343 #define kMaxFontFamilyLength 2048
344
345 SkFontConfigInterfaceDirect::SkFontConfigInterfaceDirect() {
346 SkAutoMutexAcquire ac(mutex_);
347
348 FcInit();
349
350 SkDEBUGCODE(fontconfiginterface_unittest();)
351 }
352
353 SkFontConfigInterfaceDirect::~SkFontConfigInterfaceDirect() {
354 }
355
356 bool SkFontConfigInterfaceDirect::isValidPattern(FcPattern* pattern) {
338 #ifdef SK_FONT_CONFIG_ONLY_ALLOW_SCALABLE_FONTS 357 #ifdef SK_FONT_CONFIG_ONLY_ALLOW_SCALABLE_FONTS
339 FcBool is_scalable; 358 FcBool is_scalable;
340 if (FcPatternGetBool(pattern, FC_SCALABLE, 0, &is_scalable) != FcResultMatch 359 if (FcPatternGetBool(pattern, FC_SCALABLE, 0, &is_scalable) != FcResultMatch
341 || !is_scalable) { 360 || !is_scalable) {
342 return false; 361 return false;
343 } 362 }
344 #endif 363 #endif
345 364
346 // fontconfig can also return fonts which are unreadable 365 // fontconfig can also return fonts which are unreadable
347 const char* c_filename = get_name(pattern, FC_FILE); 366 const char* c_filename = GetName(pattern, FC_FILE);
348 if (!c_filename) { 367 if (!c_filename) {
349 return false; 368 return false;
350 } 369 }
351 if (access(c_filename, R_OK) != 0) { 370 if (access(c_filename, R_OK) != 0) {
352 return false; 371 return false;
353 } 372 }
373
354 return true; 374 return true;
355 } 375 }
356 376
357 // Find matching font from |font_set| for the given font family. 377 // Find matching font from |font_set| for the given font family.
358 FcPattern* MatchFont(FcFontSet* font_set, 378 FcPattern* SkFontConfigInterfaceDirect::MatchFont(FcFontSet* font_set,
359 const char* post_config_family, 379 const char* post_config_family ,
360 const SkString& family) { 380 const SkString& family) {
361 // Older versions of fontconfig have a bug where they cannot select 381 // Older versions of fontconfig have a bug where they cannot select
362 // only scalable fonts so we have to manually filter the results. 382 // only scalable fonts so we have to manually filter the results.
363 FcPattern* match = nullptr; 383 FcPattern* match = nullptr;
364 for (int i = 0; i < font_set->nfont; ++i) { 384 for (int i = 0; i < font_set->nfont; ++i) {
365 FcPattern* current = font_set->fonts[i]; 385 FcPattern* current = font_set->fonts[i];
366 if (valid_pattern(current)) { 386 if (this->isValidPattern(current)) {
367 match = current; 387 match = current;
368 break; 388 break;
369 } 389 }
370 } 390 }
371 391
372 if (match && !IsFallbackFontAllowed(family)) { 392 if (match && !IsFallbackFontAllowed(family)) {
373 bool acceptable_substitute = false; 393 bool acceptable_substitute = false;
374 for (int id = 0; id < 255; ++id) { 394 for (int id = 0; id < 255; ++id) {
375 const char* post_match_family = get_name(match, FC_FAMILY, id); 395 const char* post_match_family = GetName(match, FC_FAMILY, id);
376 if (!post_match_family) 396 if (!post_match_family)
377 break; 397 break;
378 acceptable_substitute = 398 acceptable_substitute =
379 (strcasecmp(post_config_family, post_match_family) == 0 || 399 (strcasecmp(post_config_family, post_match_family) == 0 ||
380 // Workaround for Issue 12530: 400 // Workaround for Issue 12530:
381 // requested family: "Bitstream Vera Sans" 401 // requested family: "Bitstream Vera Sans"
382 // post_config_family: "Arial" 402 // post_config_family: "Arial"
383 // post_match_family: "Bitstream Vera Sans" 403 // post_match_family: "Bitstream Vera Sans"
384 // -> We should treat this case as a good match. 404 // -> We should treat this case as a good match.
385 strcasecmp(family.c_str(), post_match_family) == 0) || 405 strcasecmp(family.c_str(), post_match_family) == 0) ||
386 IsMetricCompatibleReplacement(family.c_str(), post_match_family); 406 IsMetricCompatibleReplacement(family.c_str(), post_match_family);
387 if (acceptable_substitute) 407 if (acceptable_substitute)
388 break; 408 break;
389 } 409 }
390 if (!acceptable_substitute) 410 if (!acceptable_substitute)
391 return nullptr; 411 return nullptr;
392 } 412 }
393 413
394 return match; 414 return match;
395 } 415 }
396 416
397 // Retrieves |is_bold|, |is_italic| and |font_family| properties from |font|.
398 SkTypeface::Style GetFontStyle(FcPattern* font) {
399 int resulting_bold;
400 if (FcPatternGetInteger(font, FC_WEIGHT, 0, &resulting_bold))
401 resulting_bold = FC_WEIGHT_NORMAL;
402
403 int resulting_italic;
404 if (FcPatternGetInteger(font, FC_SLANT, 0, &resulting_italic))
405 resulting_italic = FC_SLANT_ROMAN;
406
407 // If we ask for an italic font, fontconfig might take a roman font and set
408 // the undocumented property FC_MATRIX to a skew matrix. It'll then say
409 // that the font is italic or oblique. So, if we see a matrix, we don't
410 // believe that it's italic.
411 FcValue matrix;
412 const bool have_matrix = FcPatternGet(font, FC_MATRIX, 0, &matrix) == 0;
413
414 // If we ask for an italic font, fontconfig might take a roman font and set
415 // FC_EMBOLDEN.
416 FcValue embolden;
417 const bool have_embolden = FcPatternGet(font, FC_EMBOLDEN, 0, &embolden) == 0;
418
419 int styleBits = 0;
420 if (resulting_bold > FC_WEIGHT_MEDIUM && !have_embolden) {
421 styleBits |= SkTypeface::kBold;
422 }
423 if (resulting_italic > FC_SLANT_ROMAN && !have_matrix) {
424 styleBits |= SkTypeface::kItalic;
425 }
426
427 return (SkTypeface::Style)styleBits;
428 }
429
430 } // anonymous namespace
431
432 ///////////////////////////////////////////////////////////////////////////////
433
434 #define kMaxFontFamilyLength 2048
435
436 SkFontConfigInterfaceDirect::SkFontConfigInterfaceDirect() {
437 SkAutoMutexAcquire ac(mutex_);
438
439 FcInit();
440
441 SkDEBUGCODE(fontconfiginterface_unittest();)
442 }
443
444 SkFontConfigInterfaceDirect::~SkFontConfigInterfaceDirect() {
445 }
446
447 bool SkFontConfigInterfaceDirect::matchFamilyName(const char familyName[], 417 bool SkFontConfigInterfaceDirect::matchFamilyName(const char familyName[],
448 SkTypeface::Style style, 418 SkTypeface::Style style,
449 FontIdentity* outIdentity, 419 FontIdentity* outIdentity,
450 SkString* outFamilyName, 420 SkString* outFamilyName,
451 SkTypeface::Style* outStyle) { 421 SkTypeface::Style* outStyle) {
452 SkString familyStr(familyName ? familyName : ""); 422 SkString familyStr(familyName ? familyName : "");
453 if (familyStr.size() > kMaxFontFamilyLength) { 423 if (familyStr.size() > kMaxFontFamilyLength) {
454 return false; 424 return false;
455 } 425 }
456 426
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
494 // -> good match 464 // -> good match
495 // 465 //
496 // and for a missing font: 466 // and for a missing font:
497 // requested family: "Monaco" 467 // requested family: "Monaco"
498 // post_config_family: "Monaco" 468 // post_config_family: "Monaco"
499 // post_match_family: "Times New Roman" 469 // post_match_family: "Times New Roman"
500 // -> BAD match 470 // -> BAD match
501 // 471 //
502 // However, we special-case fallback fonts; see IsFallbackFontAllowed(). 472 // However, we special-case fallback fonts; see IsFallbackFontAllowed().
503 473
504 const char* post_config_family = get_name(pattern, FC_FAMILY); 474 const char* post_config_family = GetName(pattern, FC_FAMILY);
505 if (!post_config_family) { 475 if (!post_config_family) {
506 // we can just continue with an empty name, e.g. default font 476 // we can just continue with an empty name, e.g. default font
507 post_config_family = ""; 477 post_config_family = "";
508 } 478 }
509 479
510 FcResult result; 480 FcResult result;
511 FcFontSet* font_set = FcFontSort(0, pattern, 0, 0, &result); 481 FcFontSet* font_set = FcFontSort(0, pattern, 0, 0, &result);
512 if (!font_set) { 482 if (!font_set) {
513 FcPatternDestroy(pattern); 483 FcPatternDestroy(pattern);
514 return false; 484 return false;
515 } 485 }
516 486
517 FcPattern* match = MatchFont(font_set, post_config_family, familyStr); 487 FcPattern* match = this->MatchFont(font_set, post_config_family, familyStr);
518 if (!match) { 488 if (!match) {
519 FcPatternDestroy(pattern); 489 FcPatternDestroy(pattern);
520 FcFontSetDestroy(font_set); 490 FcFontSetDestroy(font_set);
521 return false; 491 return false;
522 } 492 }
523 493
524 FcPatternDestroy(pattern); 494 FcPatternDestroy(pattern);
525 495
526 // From here out we just extract our results from 'match' 496 // From here out we just extract our results from 'match'
527 497
528 post_config_family = get_name(match, FC_FAMILY); 498 post_config_family = GetName(match, FC_FAMILY);
529 if (!post_config_family) { 499 if (!post_config_family) {
530 FcFontSetDestroy(font_set); 500 FcFontSetDestroy(font_set);
531 return false; 501 return false;
532 } 502 }
533 503
534 const char* c_filename = get_name(match, FC_FILE); 504 const char* c_filename = GetName(match, FC_FILE);
535 if (!c_filename) { 505 if (!c_filename) {
536 FcFontSetDestroy(font_set); 506 FcFontSetDestroy(font_set);
537 return false; 507 return false;
538 } 508 }
539 509
540 int face_index; 510 int face_index;
541 if (FcPatternGetInteger(match, FC_INDEX, 0, &face_index) != FcResultMatch) { 511 if (FcPatternGetInteger(match, FC_INDEX, 0, &face_index) != FcResultMatch) {
542 FcFontSetDestroy(font_set); 512 FcFontSetDestroy(font_set);
543 return false; 513 return false;
544 } 514 }
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
592 FcFontSet* fs = FcFontList(nullptr, pat, os); 562 FcFontSet* fs = FcFontList(nullptr, pat, os);
593 SkAutoTCallVProc<FcFontSet, FcFontSetDestroy> autoDestroyFs(fs); 563 SkAutoTCallVProc<FcFontSet, FcFontSetDestroy> autoDestroyFs(fs);
594 if (nullptr == fs) { 564 if (nullptr == fs) {
595 return nullptr; 565 return nullptr;
596 } 566 }
597 567
598 SkTDArray<const char*> names; 568 SkTDArray<const char*> names;
599 SkTDArray<size_t> sizes; 569 SkTDArray<size_t> sizes;
600 for (int i = 0; i < fs->nfont; ++i) { 570 for (int i = 0; i < fs->nfont; ++i) {
601 FcPattern* match = fs->fonts[i]; 571 FcPattern* match = fs->fonts[i];
602 const char* famName = get_name(match, FC_FAMILY); 572 const char* famName = GetName(match, FC_FAMILY);
603 if (famName && !find_name(names, famName)) { 573 if (famName && !find_name(names, famName)) {
604 *names.append() = famName; 574 *names.append() = famName;
605 *sizes.append() = strlen(famName) + 1; 575 *sizes.append() = strlen(famName) + 1;
606 } 576 }
607 } 577 }
608 578
609 return SkDataTable::NewCopyArrays((const void*const*)names.begin(), 579 return SkDataTable::NewCopyArrays((const void*const*)names.begin(),
610 sizes.begin(), names.count()); 580 sizes.begin(), names.count());
611 } 581 }
612 582
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
655 // -> good match 625 // -> good match
656 // 626 //
657 // and for a missing font: 627 // and for a missing font:
658 // requested family: "Monaco" 628 // requested family: "Monaco"
659 // post_config_family: "Monaco" 629 // post_config_family: "Monaco"
660 // post_match_family: "Times New Roman" 630 // post_match_family: "Times New Roman"
661 // -> BAD match 631 // -> BAD match
662 // 632 //
663 // However, we special-case fallback fonts; see IsFallbackFontAllowed(). 633 // However, we special-case fallback fonts; see IsFallbackFontAllowed().
664 634
665 const char* post_config_family = get_name(pattern, FC_FAMILY); 635 const char* post_config_family = GetName(pattern, FC_FAMILY);
666 636
667 FcResult result; 637 FcResult result;
668 FcFontSet* font_set = FcFontSort(0, pattern, 0, 0, &result); 638 FcFontSet* font_set = FcFontSort(0, pattern, 0, 0, &result);
669 if (!font_set) { 639 if (!font_set) {
670 FcPatternDestroy(pattern); 640 FcPatternDestroy(pattern);
671 return false; 641 return false;
672 } 642 }
673 643
674 FcPattern* match = MatchFont(font_set, post_config_family, familyStr); 644 FcPattern* match = this->MatchFont(font_set, post_config_family, familyStr);
675 if (!match) { 645 if (!match) {
676 FcPatternDestroy(pattern); 646 FcPatternDestroy(pattern);
677 FcFontSetDestroy(font_set); 647 FcFontSetDestroy(font_set);
678 return false; 648 return false;
679 } 649 }
680 650
681 FcPatternDestroy(pattern); 651 FcPatternDestroy(pattern);
682 652
683 // From here out we just extract our results from 'match' 653 // From here out we just extract our results from 'match'
684 654
(...skipping 24 matching lines...) Expand all
709 outFamilyName->set((const char*)post_config_family); 679 outFamilyName->set((const char*)post_config_family);
710 } 680 }
711 if (outStyle) { 681 if (outStyle) {
712 *outStyle = GetFontStyle(match); 682 *outStyle = GetFontStyle(match);
713 } 683 }
714 return true; 684 return true;
715 685
716 //////////////////// 686 ////////////////////
717 687
718 int count; 688 int count;
719 FcPattern** match = MatchFont(font_set, post_config_family, &count); 689 FcPattern** match = this->MatchFont(font_set, post_config_family, &count );
720 if (!match) { 690 if (!match) {
721 FcPatternDestroy(pattern); 691 FcPatternDestroy(pattern);
722 FcFontSetDestroy(font_set); 692 FcFontSetDestroy(font_set);
723 return nullptr; 693 return nullptr;
724 } 694 }
725 695
726 FcPatternDestroy(pattern); 696 FcPatternDestroy(pattern);
727 697
728 SkTDArray<FcPattern*> trimmedMatches; 698 SkTDArray<FcPattern*> trimmedMatches;
729 for (int i = 0; i < count; ++i) { 699 for (int i = 0; i < count; ++i) {
730 const char* justName = find_just_name(get_name(match[i], FC_FILE)); 700 const char* justName = find_just_name(GetName(match[i], FC_FILE));
731 if (!is_lower(*justName)) { 701 if (!is_lower(*justName)) {
732 *trimmedMatches.append() = match[i]; 702 *trimmedMatches.append() = match[i];
733 } 703 }
734 } 704 }
735 705
736 SkFontStyleSet_FC* sset = new SkFontStyleSet_FC (trimmedMatches.begin(), trimmedMatches.count()); 706 SkFontStyleSet_FC* sset = new SkFontStyleSet_FC (trimmedMatches.begin(), trimmedMatches.count());
737 #endif 707 #endif
738 return false; 708 return false;
739 } 709 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698