| 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);
|
| +}
|
|
|