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

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

Issue 1471033002: Fix Google3 fonts. (Closed) Base URL: https://skia.googlesource.com/skia@master
Patch Set: Rename back to SkFontConfigInterface_direct.h 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-2015 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 "SkBuffer.h" 10 #include "SkBuffer.h"
11 #include "SkDataTable.h" 11 #include "SkDataTable.h"
12 #include "SkFontConfigInterface.h" 12 #include "SkFontConfigInterface_direct.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 static const char* get_name(FcPattern* pattern, const char field[],
145 int index = 0) { 114 int index = 0) {
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 }
(...skipping 176 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::isAccessible(const char* filename) {
357 if (access(filename, R_OK) != 0) {
358 return false;
359 }
360 return true;
361 }
362
363 bool SkFontConfigInterfaceDirect::isValidPattern(FcPattern* pattern) {
338 #ifdef SK_FONT_CONFIG_ONLY_ALLOW_SCALABLE_FONTS 364 #ifdef SK_FONT_CONFIG_ONLY_ALLOW_SCALABLE_FONTS
339 FcBool is_scalable; 365 FcBool is_scalable;
340 if (FcPatternGetBool(pattern, FC_SCALABLE, 0, &is_scalable) != FcResultMatch 366 if (FcPatternGetBool(pattern, FC_SCALABLE, 0, &is_scalable) != FcResultMatch
341 || !is_scalable) { 367 || !is_scalable) {
342 return false; 368 return false;
343 } 369 }
344 #endif 370 #endif
345 371
346 // fontconfig can also return fonts which are unreadable 372 // fontconfig can also return fonts which are unreadable
347 const char* c_filename = get_name(pattern, FC_FILE); 373 const char* c_filename = get_name(pattern, FC_FILE);
348 if (!c_filename) { 374 if (!c_filename) {
349 return false; 375 return false;
350 } 376 }
351 if (access(c_filename, R_OK) != 0) { 377 return this->isAccessible(c_filename);
352 return false;
353 }
354 return true;
355 } 378 }
356 379
357 // Find matching font from |font_set| for the given font family. 380 // Find matching font from |font_set| for the given font family.
358 FcPattern* MatchFont(FcFontSet* font_set, 381 FcPattern* SkFontConfigInterfaceDirect::MatchFont(FcFontSet* font_set,
359 const char* post_config_family, 382 const char* post_config_family ,
360 const SkString& family) { 383 const SkString& family) {
361 // Older versions of fontconfig have a bug where they cannot select 384 // Older versions of fontconfig have a bug where they cannot select
362 // only scalable fonts so we have to manually filter the results. 385 // only scalable fonts so we have to manually filter the results.
363 FcPattern* match = nullptr; 386 FcPattern* match = nullptr;
364 for (int i = 0; i < font_set->nfont; ++i) { 387 for (int i = 0; i < font_set->nfont; ++i) {
365 FcPattern* current = font_set->fonts[i]; 388 FcPattern* current = font_set->fonts[i];
366 if (valid_pattern(current)) { 389 if (this->isValidPattern(current)) {
367 match = current; 390 match = current;
368 break; 391 break;
369 } 392 }
370 } 393 }
371 394
372 if (match && !IsFallbackFontAllowed(family)) { 395 if (match && !IsFallbackFontAllowed(family)) {
373 bool acceptable_substitute = false; 396 bool acceptable_substitute = false;
374 for (int id = 0; id < 255; ++id) { 397 for (int id = 0; id < 255; ++id) {
375 const char* post_match_family = get_name(match, FC_FAMILY, id); 398 const char* post_match_family = get_name(match, FC_FAMILY, id);
376 if (!post_match_family) 399 if (!post_match_family)
(...skipping 10 matching lines...) Expand all
387 if (acceptable_substitute) 410 if (acceptable_substitute)
388 break; 411 break;
389 } 412 }
390 if (!acceptable_substitute) 413 if (!acceptable_substitute)
391 return nullptr; 414 return nullptr;
392 } 415 }
393 416
394 return match; 417 return match;
395 } 418 }
396 419
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[], 420 bool SkFontConfigInterfaceDirect::matchFamilyName(const char familyName[],
448 SkTypeface::Style style, 421 SkTypeface::Style style,
449 FontIdentity* outIdentity, 422 FontIdentity* outIdentity,
450 SkString* outFamilyName, 423 SkString* outFamilyName,
451 SkTypeface::Style* outStyle) { 424 SkTypeface::Style* outStyle) {
452 SkString familyStr(familyName ? familyName : ""); 425 SkString familyStr(familyName ? familyName : "");
453 if (familyStr.size() > kMaxFontFamilyLength) { 426 if (familyStr.size() > kMaxFontFamilyLength) {
454 return false; 427 return false;
455 } 428 }
456 429
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
507 post_config_family = ""; 480 post_config_family = "";
508 } 481 }
509 482
510 FcResult result; 483 FcResult result;
511 FcFontSet* font_set = FcFontSort(0, pattern, 0, 0, &result); 484 FcFontSet* font_set = FcFontSort(0, pattern, 0, 0, &result);
512 if (!font_set) { 485 if (!font_set) {
513 FcPatternDestroy(pattern); 486 FcPatternDestroy(pattern);
514 return false; 487 return false;
515 } 488 }
516 489
517 FcPattern* match = MatchFont(font_set, post_config_family, familyStr); 490 FcPattern* match = this->MatchFont(font_set, post_config_family, familyStr);
518 if (!match) { 491 if (!match) {
519 FcPatternDestroy(pattern); 492 FcPatternDestroy(pattern);
520 FcFontSetDestroy(font_set); 493 FcFontSetDestroy(font_set);
521 return false; 494 return false;
522 } 495 }
523 496
524 FcPatternDestroy(pattern); 497 FcPatternDestroy(pattern);
525 498
526 // From here out we just extract our results from 'match' 499 // From here out we just extract our results from 'match'
527 500
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
664 637
665 const char* post_config_family = get_name(pattern, FC_FAMILY); 638 const char* post_config_family = get_name(pattern, FC_FAMILY);
666 639
667 FcResult result; 640 FcResult result;
668 FcFontSet* font_set = FcFontSort(0, pattern, 0, 0, &result); 641 FcFontSet* font_set = FcFontSort(0, pattern, 0, 0, &result);
669 if (!font_set) { 642 if (!font_set) {
670 FcPatternDestroy(pattern); 643 FcPatternDestroy(pattern);
671 return false; 644 return false;
672 } 645 }
673 646
674 FcPattern* match = MatchFont(font_set, post_config_family, familyStr); 647 FcPattern* match = this->MatchFont(font_set, post_config_family, familyStr);
675 if (!match) { 648 if (!match) {
676 FcPatternDestroy(pattern); 649 FcPatternDestroy(pattern);
677 FcFontSetDestroy(font_set); 650 FcFontSetDestroy(font_set);
678 return false; 651 return false;
679 } 652 }
680 653
681 FcPatternDestroy(pattern); 654 FcPatternDestroy(pattern);
682 655
683 // From here out we just extract our results from 'match' 656 // From here out we just extract our results from 'match'
684 657
(...skipping 24 matching lines...) Expand all
709 outFamilyName->set((const char*)post_config_family); 682 outFamilyName->set((const char*)post_config_family);
710 } 683 }
711 if (outStyle) { 684 if (outStyle) {
712 *outStyle = GetFontStyle(match); 685 *outStyle = GetFontStyle(match);
713 } 686 }
714 return true; 687 return true;
715 688
716 //////////////////// 689 ////////////////////
717 690
718 int count; 691 int count;
719 FcPattern** match = MatchFont(font_set, post_config_family, &count); 692 FcPattern** match = this->MatchFont(font_set, post_config_family, &count );
720 if (!match) { 693 if (!match) {
721 FcPatternDestroy(pattern); 694 FcPatternDestroy(pattern);
722 FcFontSetDestroy(font_set); 695 FcFontSetDestroy(font_set);
723 return nullptr; 696 return nullptr;
724 } 697 }
725 698
726 FcPatternDestroy(pattern); 699 FcPatternDestroy(pattern);
727 700
728 SkTDArray<FcPattern*> trimmedMatches; 701 SkTDArray<FcPattern*> trimmedMatches;
729 for (int i = 0; i < count; ++i) { 702 for (int i = 0; i < count; ++i) {
730 const char* justName = find_just_name(get_name(match[i], FC_FILE)); 703 const char* justName = find_just_name(get_name(match[i], FC_FILE));
731 if (!is_lower(*justName)) { 704 if (!is_lower(*justName)) {
732 *trimmedMatches.append() = match[i]; 705 *trimmedMatches.append() = match[i];
733 } 706 }
734 } 707 }
735 708
736 SkFontStyleSet_FC* sset = new SkFontStyleSet_FC (trimmedMatches.begin(), trimmedMatches.count()); 709 SkFontStyleSet_FC* sset = new SkFontStyleSet_FC (trimmedMatches.begin(), trimmedMatches.count());
737 #endif 710 #endif
738 return false; 711 return false;
739 } 712 }
OLDNEW
« no previous file with comments | « src/ports/SkFontConfigInterface_direct.h ('k') | src/ports/SkFontConfigInterface_direct_factory.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698