summaryrefslogtreecommitdiffstats
path: root/skia/ext/SkFontHost_fontconfig_direct.cpp
diff options
context:
space:
mode:
authoragl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-06-15 18:15:08 +0000
committeragl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-06-15 18:15:08 +0000
commitabe3ad93b1996ad1b1aff121dbce6be533e579c3 (patch)
tree635542dd62d6b7df4c05a3c39f2c737730e23376 /skia/ext/SkFontHost_fontconfig_direct.cpp
parent89d156b666af4d4f4c83579be31e9092155bbaf7 (diff)
downloadchromium_src-abe3ad93b1996ad1b1aff121dbce6be533e579c3.zip
chromium_src-abe3ad93b1996ad1b1aff121dbce6be533e579c3.tar.gz
chromium_src-abe3ad93b1996ad1b1aff121dbce6be533e579c3.tar.bz2
Linux: Add support for chrooted renderers.
http://code.google.com/p/chromium/wiki/LinuxSandboxIPC Without filesystem access from the renderers, we need another way of dealing with fontconfig and font loading. This add support for: * An "SBX_D" environment variable in the renderers which is used to signal the end of dynamic linking so that the chroot can be enforced. * A sandbox_host process, running outside the sandbox, to deal with fontconfig requests from the renderers. See the wiki page for the reasoning behind making it a separate process. * A new, custom SkFontHost for Skia. Because this is Chrome specific, it will live outside the upstream Skia tree. This FontHost can be configured either to drive fontconfig directly (for the browser process and for any unsandboxed renderers) or to use an IPC system. Since the same SkFontHost has to be linked into both the browser and renderer (they are the same binary), this switch has to be made at run time. Sandbox IPC calls are rare (a couple of dozen at page load time) and add about 50us of overhead for each call. (Reland of r17575 which was reverted in r17577) http://codereview.chromium.org/112074 BUG=8081 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@18405 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'skia/ext/SkFontHost_fontconfig_direct.cpp')
-rw-r--r--skia/ext/SkFontHost_fontconfig_direct.cpp180
1 files changed, 180 insertions, 0 deletions
diff --git a/skia/ext/SkFontHost_fontconfig_direct.cpp b/skia/ext/SkFontHost_fontconfig_direct.cpp
new file mode 100644
index 0000000..001fccd
--- /dev/null
+++ b/skia/ext/SkFontHost_fontconfig_direct.cpp
@@ -0,0 +1,180 @@
+/* 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();
+}
+
+// -----------------------------------------------------------------------------
+// Normally we only return exactly the font asked for. In last-resort cases,
+// the request is for one of the basic font names "Sans", "Serif" or
+// "Monospace". This function tells you whether a given request is for such a
+// fallback.
+// -----------------------------------------------------------------------------
+static bool IsFallbackFontAllowed(const std::string& family)
+{
+ return family == "Sans" ||
+ family == "Serif" ||
+ family == "Monospace";
+}
+
+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
+ //
+ // However, we special-case fallback fonts; see IsFallbackFontAllowed().
+ 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 && !IsFallbackFontAllowed(family)) {
+ 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);
+}