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> |
11 #include <unistd.h> | 11 #include <unistd.h> |
12 #include <fcntl.h> | 12 #include <fcntl.h> |
13 | 13 |
14 #include <fontconfig/fontconfig.h> | 14 #include <fontconfig/fontconfig.h> |
15 | 15 |
| 16 #include "SkBuffer.h" |
16 #include "SkFontConfigInterface.h" | 17 #include "SkFontConfigInterface.h" |
17 #include "SkStream.h" | 18 #include "SkStream.h" |
18 | 19 |
| 20 size_t SkFontConfigInterface::FontIdentity::writeToMemory(void* addr) const { |
| 21 size_t size = sizeof(fID) + sizeof(fTTCIndex); |
| 22 size += sizeof(int32_t) + sizeof(int32_t) + sizeof(uint8_t); // weight, widt
h, italic |
| 23 size += sizeof(int32_t) + fString.size(); // store length+data |
| 24 if (addr) { |
| 25 SkWBuffer buffer(addr, size); |
| 26 |
| 27 buffer.write32(fID); |
| 28 buffer.write32(fTTCIndex); |
| 29 buffer.write32(fString.size()); |
| 30 buffer.write32(fStyle.weight()); |
| 31 buffer.write32(fStyle.width()); |
| 32 buffer.write8(fStyle.slant()); |
| 33 buffer.write(fString.c_str(), fString.size()); |
| 34 buffer.padToAlign4(); |
| 35 |
| 36 SkASSERT(buffer.pos() == size); |
| 37 } |
| 38 return size; |
| 39 } |
| 40 |
| 41 size_t SkFontConfigInterface::FontIdentity::readFromMemory(const void* addr, |
| 42 size_t size) { |
| 43 SkRBuffer buffer(addr, size); |
| 44 |
| 45 fID = buffer.readU32(); |
| 46 fTTCIndex = buffer.readU32(); |
| 47 size_t strLen = buffer.readU32(); |
| 48 int weight = buffer.readU32(); |
| 49 int width = buffer.readU32(); |
| 50 SkFontStyle::Slant slant = (SkFontStyle::Slant)buffer.readU8(); |
| 51 fStyle = SkFontStyle(weight, width, slant); |
| 52 fString.resize(strLen); |
| 53 buffer.read(fString.writable_str(), strLen); |
| 54 buffer.skipToAlign4(); |
| 55 |
| 56 return buffer.pos(); // the actual number of bytes read |
| 57 } |
| 58 |
| 59 #ifdef SK_DEBUG |
| 60 static void make_iden(SkFontConfigInterface::FontIdentity* iden) { |
| 61 iden->fID = 10; |
| 62 iden->fTTCIndex = 2; |
| 63 iden->fString.set("Hello world"); |
| 64 iden->fStyle = SkFontStyle(300, 6, SkFontStyle::kItalic_Slant); |
| 65 } |
| 66 |
| 67 static void test_writeToMemory(const SkFontConfigInterface::FontIdentity& iden0, |
| 68 int initValue) { |
| 69 SkFontConfigInterface::FontIdentity iden1; |
| 70 |
| 71 size_t size0 = iden0.writeToMemory(NULL); |
| 72 |
| 73 SkAutoMalloc storage(size0); |
| 74 memset(storage.get(), initValue, size0); |
| 75 |
| 76 size_t size1 = iden0.writeToMemory(storage.get()); |
| 77 SkASSERT(size0 == size1); |
| 78 |
| 79 SkASSERT(iden0 != iden1); |
| 80 size_t size2 = iden1.readFromMemory(storage.get(), size1); |
| 81 SkASSERT(size2 == size1); |
| 82 SkASSERT(iden0 == iden1); |
| 83 } |
| 84 |
| 85 static void fontconfiginterface_unittest() { |
| 86 SkFontConfigInterface::FontIdentity iden0, iden1; |
| 87 |
| 88 SkASSERT(iden0 == iden1); |
| 89 |
| 90 make_iden(&iden0); |
| 91 SkASSERT(iden0 != iden1); |
| 92 |
| 93 make_iden(&iden1); |
| 94 SkASSERT(iden0 == iden1); |
| 95 |
| 96 test_writeToMemory(iden0, 0); |
| 97 test_writeToMemory(iden0, 0); |
| 98 } |
| 99 #endif |
| 100 |
19 class SkFontConfigInterfaceDirect : public SkFontConfigInterface { | 101 class SkFontConfigInterfaceDirect : public SkFontConfigInterface { |
20 public: | 102 public: |
21 SkFontConfigInterfaceDirect(); | 103 SkFontConfigInterfaceDirect(); |
22 virtual ~SkFontConfigInterfaceDirect(); | 104 virtual ~SkFontConfigInterfaceDirect(); |
23 | 105 |
24 virtual bool matchFamilyName(const char familyName[], | 106 virtual bool matchFamilyName(const char familyName[], |
25 SkTypeface::Style requested, | 107 SkTypeface::Style requested, |
26 FontIdentity* outFontIdentifier, | 108 FontIdentity* outFontIdentifier, |
27 SkString* outFamilyName, | 109 SkString* outFamilyName, |
28 SkTypeface::Style* outStyle) SK_OVERRIDE; | 110 SkTypeface::Style* outStyle) SK_OVERRIDE; |
(...skipping 15 matching lines...) Expand all Loading... |
44 static SkMutex gMutex; | 126 static SkMutex gMutex; |
45 SkAutoMutexAcquire ac(gMutex); | 127 SkAutoMutexAcquire ac(gMutex); |
46 | 128 |
47 if (NULL == gDirect) { | 129 if (NULL == gDirect) { |
48 gDirect = new SkFontConfigInterfaceDirect; | 130 gDirect = new SkFontConfigInterfaceDirect; |
49 } | 131 } |
50 } | 132 } |
51 return gDirect; | 133 return gDirect; |
52 } | 134 } |
53 | 135 |
54 #if 0 | |
55 int SkFontConfigInterface::countFamilies() { return 0; } | |
56 | |
57 int SkFontConfigInterface::getFamilySet(int index, SkString* outFamilyName, | |
58 FontIdentity outIdentities[], | |
59 int maxCount) { | |
60 return 0; | |
61 } | |
62 | |
63 int SkFontConfigInterface::matchFamilySet(const char familyName[], | |
64 SkString* outFamilyName, | |
65 FontIdentity outIdentities[], | |
66 int maxCount) { | |
67 return 0; | |
68 } | |
69 #endif | |
70 | |
71 /////////////////////////////////////////////////////////////////////////////// | 136 /////////////////////////////////////////////////////////////////////////////// |
72 | 137 |
73 // Returns the string from the pattern, or NULL | 138 // Returns the string from the pattern, or NULL |
74 static const char* get_name(FcPattern* pattern, const char field[], | 139 static const char* get_name(FcPattern* pattern, const char field[], |
75 int index = 0) { | 140 int index = 0) { |
76 const char* name; | 141 const char* name; |
77 if (FcPatternGetString(pattern, field, index, | 142 if (FcPatternGetString(pattern, field, index, |
78 (FcChar8**)&name) != FcResultMatch) { | 143 (FcChar8**)&name) != FcResultMatch) { |
79 name = NULL; | 144 name = NULL; |
80 } | 145 } |
(...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
347 return (SkTypeface::Style)styleBits; | 412 return (SkTypeface::Style)styleBits; |
348 } | 413 } |
349 | 414 |
350 } // anonymous namespace | 415 } // anonymous namespace |
351 | 416 |
352 /////////////////////////////////////////////////////////////////////////////// | 417 /////////////////////////////////////////////////////////////////////////////// |
353 | 418 |
354 #define kMaxFontFamilyLength 2048 | 419 #define kMaxFontFamilyLength 2048 |
355 | 420 |
356 SkFontConfigInterfaceDirect::SkFontConfigInterfaceDirect() { | 421 SkFontConfigInterfaceDirect::SkFontConfigInterfaceDirect() { |
| 422 SkAutoMutexAcquire ac(mutex_); |
| 423 |
357 FcInit(); | 424 FcInit(); |
| 425 |
| 426 SkDEBUGCODE(fontconfiginterface_unittest();) |
358 } | 427 } |
359 | 428 |
360 SkFontConfigInterfaceDirect::~SkFontConfigInterfaceDirect() { | 429 SkFontConfigInterfaceDirect::~SkFontConfigInterfaceDirect() { |
361 } | 430 } |
362 | 431 |
363 bool SkFontConfigInterfaceDirect::matchFamilyName(const char familyName[], | 432 bool SkFontConfigInterfaceDirect::matchFamilyName(const char familyName[], |
364 SkTypeface::Style style, | 433 SkTypeface::Style style, |
365 FontIdentity* outIdentity, | 434 FontIdentity* outIdentity, |
366 SkString* outFamilyName, | 435 SkString* outFamilyName, |
367 SkTypeface::Style* outStyle) { | 436 SkTypeface::Style* outStyle) { |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
483 int count = list.count(); | 552 int count = list.count(); |
484 for (int i = 0; i < count; ++i) { | 553 for (int i = 0; i < count; ++i) { |
485 if (!strcmp(list[i], str)) { | 554 if (!strcmp(list[i], str)) { |
486 return true; | 555 return true; |
487 } | 556 } |
488 } | 557 } |
489 return false; | 558 return false; |
490 } | 559 } |
491 | 560 |
492 SkDataTable* SkFontConfigInterfaceDirect::getFamilyNames() { | 561 SkDataTable* SkFontConfigInterfaceDirect::getFamilyNames() { |
| 562 SkAutoMutexAcquire ac(mutex_); |
| 563 |
493 FcPattern* pat = FcPatternCreate(); | 564 FcPattern* pat = FcPatternCreate(); |
494 FcObjectSet* os = FcObjectSetBuild (FC_FAMILY, (char *) 0); | 565 FcObjectSet* os = FcObjectSetBuild (FC_FAMILY, (char *) 0); |
495 if (NULL == os) { | 566 if (NULL == os) { |
496 return NULL; | 567 return NULL; |
497 } | 568 } |
498 FcFontSet* fs = FcFontList(NULL, pat, os); | 569 FcFontSet* fs = FcFontList(NULL, pat, os); |
499 if (NULL == fs) { | 570 if (NULL == fs) { |
500 FcObjectSetDestroy(os); | 571 FcObjectSetDestroy(os); |
501 return NULL; | 572 return NULL; |
502 } | 573 } |
(...skipping 13 matching lines...) Expand all Loading... |
516 FcObjectSetDestroy(os); | 587 FcObjectSetDestroy(os); |
517 FcPatternDestroy(pat); | 588 FcPatternDestroy(pat); |
518 | 589 |
519 return SkDataTable::NewCopyArrays((const void*const*)names.begin(), | 590 return SkDataTable::NewCopyArrays((const void*const*)names.begin(), |
520 sizes.begin(), names.count()); | 591 sizes.begin(), names.count()); |
521 } | 592 } |
522 | 593 |
523 bool SkFontConfigInterfaceDirect::matchFamilySet(const char inFamilyName[], | 594 bool SkFontConfigInterfaceDirect::matchFamilySet(const char inFamilyName[], |
524 SkString* outFamilyName, | 595 SkString* outFamilyName, |
525 SkTArray<FontIdentity>* ids) { | 596 SkTArray<FontIdentity>* ids) { |
| 597 SkAutoMutexAcquire ac(mutex_); |
| 598 |
| 599 #if 0 |
| 600 std::string familyStr(familyName ? familyName : ""); |
| 601 if (familyStr.length() > kMaxFontFamilyLength) { |
| 602 return false; |
| 603 } |
| 604 |
| 605 SkAutoMutexAcquire ac(mutex_); |
| 606 |
| 607 FcPattern* pattern = FcPatternCreate(); |
| 608 |
| 609 if (familyName) { |
| 610 FcPatternAddString(pattern, FC_FAMILY, (FcChar8*)familyName); |
| 611 } |
| 612 FcPatternAddBool(pattern, FC_SCALABLE, FcTrue); |
| 613 |
| 614 FcConfigSubstitute(NULL, pattern, FcMatchPattern); |
| 615 FcDefaultSubstitute(pattern); |
| 616 |
| 617 // Font matching: |
| 618 // CSS often specifies a fallback list of families: |
| 619 // font-family: a, b, c, serif; |
| 620 // However, fontconfig will always do its best to find *a* font when asked |
| 621 // for something so we need a way to tell if the match which it has found is |
| 622 // "good enough" for us. Otherwise, we can return NULL which gets piped up |
| 623 // and lets WebKit know to try the next CSS family name. However, fontconfig |
| 624 // configs allow substitutions (mapping "Arial -> Helvetica" etc) and we |
| 625 // wish to support that. |
| 626 // |
| 627 // Thus, if a specific family is requested we set @family_requested. Then we |
| 628 // record two strings: the family name after config processing and the |
| 629 // family name after resolving. If the two are equal, it's a good match. |
| 630 // |
| 631 // So consider the case where a user has mapped Arial to Helvetica in their |
| 632 // config. |
| 633 // requested family: "Arial" |
| 634 // post_config_family: "Helvetica" |
| 635 // post_match_family: "Helvetica" |
| 636 // -> good match |
| 637 // |
| 638 // and for a missing font: |
| 639 // requested family: "Monaco" |
| 640 // post_config_family: "Monaco" |
| 641 // post_match_family: "Times New Roman" |
| 642 // -> BAD match |
| 643 // |
| 644 // However, we special-case fallback fonts; see IsFallbackFontAllowed(). |
| 645 |
| 646 const char* post_config_family = get_name(pattern, FC_FAMILY); |
| 647 |
| 648 FcResult result; |
| 649 FcFontSet* font_set = FcFontSort(0, pattern, 0, 0, &result); |
| 650 if (!font_set) { |
| 651 FcPatternDestroy(pattern); |
| 652 return false; |
| 653 } |
| 654 |
| 655 FcPattern* match = MatchFont(font_set, post_config_family, familyStr); |
| 656 if (!match) { |
| 657 FcPatternDestroy(pattern); |
| 658 FcFontSetDestroy(font_set); |
| 659 return false; |
| 660 } |
| 661 |
| 662 FcPatternDestroy(pattern); |
| 663 |
| 664 // From here out we just extract our results from 'match' |
| 665 |
| 666 if (FcPatternGetString(match, FC_FAMILY, 0, &post_config_family) != FcResult
Match) { |
| 667 FcFontSetDestroy(font_set); |
| 668 return false; |
| 669 } |
| 670 |
| 671 FcChar8* c_filename; |
| 672 if (FcPatternGetString(match, FC_FILE, 0, &c_filename) != FcResultMatch) { |
| 673 FcFontSetDestroy(font_set); |
| 674 return false; |
| 675 } |
| 676 |
| 677 int face_index; |
| 678 if (FcPatternGetInteger(match, FC_INDEX, 0, &face_index) != FcResultMatch) { |
| 679 FcFontSetDestroy(font_set); |
| 680 return false; |
| 681 } |
| 682 |
| 683 FcFontSetDestroy(font_set); |
| 684 |
| 685 if (outIdentity) { |
| 686 outIdentity->fTTCIndex = face_index; |
| 687 outIdentity->fString.set((const char*)c_filename); |
| 688 } |
| 689 if (outFamilyName) { |
| 690 outFamilyName->set((const char*)post_config_family); |
| 691 } |
| 692 if (outStyle) { |
| 693 *outStyle = GetFontStyle(match); |
| 694 } |
| 695 return true; |
| 696 |
| 697 //////////////////// |
| 698 |
| 699 int count; |
| 700 FcPattern** match = MatchFont(font_set, post_config_family, &count); |
| 701 if (!match) { |
| 702 FcPatternDestroy(pattern); |
| 703 FcFontSetDestroy(font_set); |
| 704 return NULL; |
| 705 } |
| 706 |
| 707 FcPatternDestroy(pattern); |
| 708 |
| 709 SkTDArray<FcPattern*> trimmedMatches; |
| 710 for (int i = 0; i < count; ++i) { |
| 711 const char* justName = find_just_name(get_name(match[i], FC_FILE)); |
| 712 if (!is_lower(*justName)) { |
| 713 *trimmedMatches.append() = match[i]; |
| 714 } |
| 715 } |
| 716 |
| 717 SkFontStyleSet_FC* sset = SkNEW_ARGS(SkFontStyleSet_FC, |
| 718 (trimmedMatches.begin(), |
| 719 trimmedMatches.count())); |
| 720 #endif |
526 return false; | 721 return false; |
527 } | 722 } |
| 723 |
OLD | NEW |