Index: skia/ext/SkFontHost_fontconfig_direct.cpp |
diff --git a/skia/ext/SkFontHost_fontconfig_direct.cpp b/skia/ext/SkFontHost_fontconfig_direct.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..167d7bd349d9f3fa6c6c062ad6403203b5a88df9 |
--- /dev/null |
+++ b/skia/ext/SkFontHost_fontconfig_direct.cpp |
@@ -0,0 +1,165 @@ |
+/* libs/graphics/ports/SkFontHost_fontconfig_direct.cpp |
+** |
+** Copyright 2009, Google Inc. |
+** |
+** Licensed under the Apache License, Version 2.0 (the "License"); |
+** you may not use this file except in compliance with the License. |
+** You may obtain a copy of the License at |
+** |
+** http://www.apache.org/licenses/LICENSE-2.0 |
+** |
+** Unless required by applicable law or agreed to in writing, software |
+** distributed under the License is distributed on an "AS IS" BASIS, |
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
+** See the License for the specific language governing permissions and |
+** limitations under the License. |
+*/ |
+ |
+#include "SkFontHost_fontconfig_direct.h" |
+ |
+#include <unistd.h> |
+#include <fcntl.h> |
+ |
+#include <fontconfig/fontconfig.h> |
+ |
+FontConfigDirect::FontConfigDirect() |
+ : next_file_id_(0) { |
+ FcInit(); |
+} |
+ |
+bool FontConfigDirect::Match(std::string* result_family, |
+ unsigned* result_fileid, |
+ bool fileid_valid, unsigned fileid, |
+ const std::string& family, int is_bold, |
+ int is_italic) { |
+ SkAutoMutexAcquire ac(mutex_); |
+ FcPattern* pattern = FcPatternCreate(); |
+ |
+ FcValue fcvalue; |
+ if (fileid_valid) { |
+ const std::map<unsigned, std::string>::const_iterator |
+ i = fileid_to_filename_.find(fileid); |
+ if (i == fileid_to_filename_.end()) { |
+ FcPatternDestroy(pattern); |
+ return false; |
+ } |
+ |
+ fcvalue.type = FcTypeString; |
+ fcvalue.u.s = (FcChar8*) i->second.c_str(); |
+ FcPatternAdd(pattern, FC_FILE, fcvalue, 0); |
+ } |
+ if (!family.empty()) { |
+ fcvalue.type = FcTypeString; |
+ fcvalue.u.s = (FcChar8*) family.c_str(); |
+ FcPatternAdd(pattern, FC_FAMILY, fcvalue, 0); |
+ } |
+ if (is_bold > 0) { |
+ fcvalue.type = FcTypeInteger; |
+ fcvalue.u.i = is_bold ? FC_WEIGHT_BOLD : FC_WEIGHT_NORMAL; |
+ FcPatternAdd(pattern, FC_WEIGHT, fcvalue, 0); |
+ } |
+ if (is_italic > 0) { |
+ fcvalue.type = FcTypeInteger; |
+ fcvalue.u.i = is_bold ? FC_SLANT_ITALIC : FC_SLANT_ROMAN; |
+ FcPatternAdd(pattern, FC_SLANT, fcvalue, 0); |
+ } |
+ |
+ FcConfigSubstitute(0, pattern, FcMatchPattern); |
+ FcDefaultSubstitute(pattern); |
+ |
+ // Font matching: |
+ // CSS often specifies a fallback list of families: |
+ // font-family: a, b, c, serif; |
+ // However, fontconfig will always do its best to find *a* font when asked |
+ // for something so we need a way to tell if the match which it has found is |
+ // "good enough" for us. Otherwise, we can return NULL which gets piped up |
+ // and lets WebKit know to try the next CSS family name. However, fontconfig |
+ // configs allow substitutions (mapping "Arial -> Helvetica" etc) and we |
+ // wish to support that. |
+ // |
+ // Thus, if a specific family is requested we set @family_requested. Then we |
+ // record two strings: the family name after config processing and the |
+ // family name after resolving. If the two are equal, it's a good match. |
+ // |
+ // So consider the case where a user has mapped Arial to Helvetica in their |
+ // config. |
+ // requested family: "Arial" |
+ // post_config_family: "Helvetica" |
+ // post_match_family: "Helvetica" |
+ // -> good match |
+ // |
+ // and for a missing font: |
+ // requested family: "Monaco" |
+ // post_config_family: "Monaco" |
+ // post_match_family: "Times New Roman" |
+ // -> BAD match |
+ FcChar8* post_config_family; |
+ FcPatternGetString(pattern, FC_FAMILY, 0, &post_config_family); |
+ |
+ FcResult result; |
+ FcPattern* match = FcFontMatch(0, pattern, &result); |
+ if (!match) { |
+ FcPatternDestroy(pattern); |
+ return false; |
+ } |
+ |
+ FcChar8* post_match_family; |
+ FcPatternGetString(match, FC_FAMILY, 0, &post_match_family); |
+ const bool family_names_match = |
+ family.empty() ? |
+ true : |
+ strcasecmp((char *)post_config_family, (char *)post_match_family) == 0; |
+ |
+ FcPatternDestroy(pattern); |
+ |
+ if (!family_names_match) { |
+ FcPatternDestroy(match); |
+ return false; |
+ } |
+ |
+ FcChar8* c_filename; |
+ if (FcPatternGetString(match, FC_FILE, 0, &c_filename) != FcResultMatch) { |
+ FcPatternDestroy(match); |
+ return NULL; |
+ } |
+ const std::string filename((char *) c_filename); |
+ |
+ unsigned out_fileid; |
+ if (fileid_valid) { |
+ out_fileid = fileid; |
+ } else { |
+ const std::map<std::string, unsigned>::const_iterator |
+ i = filename_to_fileid_.find(filename); |
+ if (i == filename_to_fileid_.end()) { |
+ out_fileid = next_file_id_++; |
+ filename_to_fileid_[filename] = out_fileid; |
+ fileid_to_filename_[out_fileid] = filename; |
+ } else { |
+ out_fileid = i->second; |
+ } |
+ } |
+ |
+ if (*result_fileid) |
+ *result_fileid = out_fileid; |
+ |
+ FcChar8* c_family; |
+ if (FcPatternGetString(match, FC_FAMILY, 0, &c_family)) { |
+ FcPatternDestroy(match); |
+ return NULL; |
+ } |
+ |
+ if (result_family) |
+ *result_family = (char *) c_family; |
+ |
+ return true; |
+} |
+ |
+int FontConfigDirect::Open(unsigned fileid) { |
+ SkAutoMutexAcquire ac(mutex_); |
+ const std::map<unsigned, std::string>::const_iterator |
+ i = fileid_to_filename_.find(fileid); |
+ if (i == fileid_to_filename_.end()) |
+ return -1; |
+ |
+ return open(i->second.c_str(), O_RDONLY); |
+} |