OLD | NEW |
(Empty) | |
| 1 /* libs/graphics/ports/SkFontHost_fontconfig_direct.cpp |
| 2 ** |
| 3 ** Copyright 2009, Google Inc. |
| 4 ** |
| 5 ** Licensed under the Apache License, Version 2.0 (the "License"); |
| 6 ** you may not use this file except in compliance with the License. |
| 7 ** You may obtain a copy of the License at |
| 8 ** |
| 9 ** http://www.apache.org/licenses/LICENSE-2.0 |
| 10 ** |
| 11 ** Unless required by applicable law or agreed to in writing, software |
| 12 ** distributed under the License is distributed on an "AS IS" BASIS, |
| 13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 14 ** See the License for the specific language governing permissions and |
| 15 ** limitations under the License. |
| 16 */ |
| 17 |
| 18 #include "SkFontHost_fontconfig_direct.h" |
| 19 |
| 20 #include <unistd.h> |
| 21 #include <fcntl.h> |
| 22 |
| 23 #include <fontconfig/fontconfig.h> |
| 24 |
| 25 FontConfigDirect::FontConfigDirect() |
| 26 : next_file_id_(0) { |
| 27 FcInit(); |
| 28 } |
| 29 |
| 30 bool FontConfigDirect::Match(std::string* result_family, |
| 31 unsigned* result_fileid, |
| 32 bool fileid_valid, unsigned fileid, |
| 33 const std::string& family, int is_bold, |
| 34 int is_italic) { |
| 35 SkAutoMutexAcquire ac(mutex_); |
| 36 FcPattern* pattern = FcPatternCreate(); |
| 37 |
| 38 FcValue fcvalue; |
| 39 if (fileid_valid) { |
| 40 const std::map<unsigned, std::string>::const_iterator |
| 41 i = fileid_to_filename_.find(fileid); |
| 42 if (i == fileid_to_filename_.end()) { |
| 43 FcPatternDestroy(pattern); |
| 44 return false; |
| 45 } |
| 46 |
| 47 fcvalue.type = FcTypeString; |
| 48 fcvalue.u.s = (FcChar8*) i->second.c_str(); |
| 49 FcPatternAdd(pattern, FC_FILE, fcvalue, 0); |
| 50 } |
| 51 if (!family.empty()) { |
| 52 fcvalue.type = FcTypeString; |
| 53 fcvalue.u.s = (FcChar8*) family.c_str(); |
| 54 FcPatternAdd(pattern, FC_FAMILY, fcvalue, 0); |
| 55 } |
| 56 if (is_bold > 0) { |
| 57 fcvalue.type = FcTypeInteger; |
| 58 fcvalue.u.i = is_bold ? FC_WEIGHT_BOLD : FC_WEIGHT_NORMAL; |
| 59 FcPatternAdd(pattern, FC_WEIGHT, fcvalue, 0); |
| 60 } |
| 61 if (is_italic > 0) { |
| 62 fcvalue.type = FcTypeInteger; |
| 63 fcvalue.u.i = is_bold ? FC_SLANT_ITALIC : FC_SLANT_ROMAN; |
| 64 FcPatternAdd(pattern, FC_SLANT, fcvalue, 0); |
| 65 } |
| 66 |
| 67 FcConfigSubstitute(0, pattern, FcMatchPattern); |
| 68 FcDefaultSubstitute(pattern); |
| 69 |
| 70 // Font matching: |
| 71 // CSS often specifies a fallback list of families: |
| 72 // font-family: a, b, c, serif; |
| 73 // However, fontconfig will always do its best to find *a* font when asked |
| 74 // for something so we need a way to tell if the match which it has found is |
| 75 // "good enough" for us. Otherwise, we can return NULL which gets piped up |
| 76 // and lets WebKit know to try the next CSS family name. However, fontconfig |
| 77 // configs allow substitutions (mapping "Arial -> Helvetica" etc) and we |
| 78 // wish to support that. |
| 79 // |
| 80 // Thus, if a specific family is requested we set @family_requested. Then we |
| 81 // record two strings: the family name after config processing and the |
| 82 // family name after resolving. If the two are equal, it's a good match. |
| 83 // |
| 84 // So consider the case where a user has mapped Arial to Helvetica in their |
| 85 // config. |
| 86 // requested family: "Arial" |
| 87 // post_config_family: "Helvetica" |
| 88 // post_match_family: "Helvetica" |
| 89 // -> good match |
| 90 // |
| 91 // and for a missing font: |
| 92 // requested family: "Monaco" |
| 93 // post_config_family: "Monaco" |
| 94 // post_match_family: "Times New Roman" |
| 95 // -> BAD match |
| 96 FcChar8* post_config_family; |
| 97 FcPatternGetString(pattern, FC_FAMILY, 0, &post_config_family); |
| 98 |
| 99 FcResult result; |
| 100 FcPattern* match = FcFontMatch(0, pattern, &result); |
| 101 if (!match) { |
| 102 FcPatternDestroy(pattern); |
| 103 return false; |
| 104 } |
| 105 |
| 106 FcChar8* post_match_family; |
| 107 FcPatternGetString(match, FC_FAMILY, 0, &post_match_family); |
| 108 const bool family_names_match = |
| 109 family.empty() ? |
| 110 true : |
| 111 strcasecmp((char *)post_config_family, (char *)post_match_family) == 0; |
| 112 |
| 113 FcPatternDestroy(pattern); |
| 114 |
| 115 if (!family_names_match) { |
| 116 FcPatternDestroy(match); |
| 117 return false; |
| 118 } |
| 119 |
| 120 FcChar8* c_filename; |
| 121 if (FcPatternGetString(match, FC_FILE, 0, &c_filename) != FcResultMatch) { |
| 122 FcPatternDestroy(match); |
| 123 return NULL; |
| 124 } |
| 125 const std::string filename((char *) c_filename); |
| 126 |
| 127 unsigned out_fileid; |
| 128 if (fileid_valid) { |
| 129 out_fileid = fileid; |
| 130 } else { |
| 131 const std::map<std::string, unsigned>::const_iterator |
| 132 i = filename_to_fileid_.find(filename); |
| 133 if (i == filename_to_fileid_.end()) { |
| 134 out_fileid = next_file_id_++; |
| 135 filename_to_fileid_[filename] = out_fileid; |
| 136 fileid_to_filename_[out_fileid] = filename; |
| 137 } else { |
| 138 out_fileid = i->second; |
| 139 } |
| 140 } |
| 141 |
| 142 if (*result_fileid) |
| 143 *result_fileid = out_fileid; |
| 144 |
| 145 FcChar8* c_family; |
| 146 if (FcPatternGetString(match, FC_FAMILY, 0, &c_family)) { |
| 147 FcPatternDestroy(match); |
| 148 return NULL; |
| 149 } |
| 150 |
| 151 if (result_family) |
| 152 *result_family = (char *) c_family; |
| 153 |
| 154 return true; |
| 155 } |
| 156 |
| 157 int FontConfigDirect::Open(unsigned fileid) { |
| 158 SkAutoMutexAcquire ac(mutex_); |
| 159 const std::map<unsigned, std::string>::const_iterator |
| 160 i = fileid_to_filename_.find(fileid); |
| 161 if (i == fileid_to_filename_.end()) |
| 162 return -1; |
| 163 |
| 164 return open(i->second.c_str(), O_RDONLY); |
| 165 } |
OLD | NEW |