summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoragl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2008-12-03 22:44:09 +0000
committeragl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2008-12-03 22:44:09 +0000
commitb3467a4dd2f9d7c6473c1fcd22a31c2ac39a2d88 (patch)
treee2f55061517c5aaf3e87beca9c335bfcc9e530c1
parent378f3ac5cd7c0c170cf3e8e54aa627defcb590da (diff)
downloadchromium_src-b3467a4dd2f9d7c6473c1fcd22a31c2ac39a2d88.zip
chromium_src-b3467a4dd2f9d7c6473c1fcd22a31c2ac39a2d88.tar.gz
chromium_src-b3467a4dd2f9d7c6473c1fcd22a31c2ac39a2d88.tar.bz2
Linux: support css font-family fallback.
Currently we'll always take the first element of a font-family list and run with it, using fontconfig's fallback. This adds a, slightly hacky, test to see if the fontconfig result is good enough and, if not, reports the failure back into WebKit so that other font-family elements can be tried. This fixes LayoutTests/css2.1/t040103-escapes-01-b.html Review URL: http://codereview.chromium.org/12914 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@6320 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--skia/ports/SkFontHost_fontconfig.cpp50
-rw-r--r--skia/sgl/SkTypeface.cpp3
-rw-r--r--webkit/port/platform/graphics/chromium/FontCacheLinux.cpp2
-rw-r--r--webkit/tools/test_shell/resources/linux-fontconfig-config11
4 files changed, 65 insertions, 1 deletions
diff --git a/skia/ports/SkFontHost_fontconfig.cpp b/skia/ports/SkFontHost_fontconfig.cpp
index f36bb2e..42cce0d 100644
--- a/skia/ports/SkFontHost_fontconfig.cpp
+++ b/skia/ports/SkFontHost_fontconfig.cpp
@@ -100,6 +100,7 @@ static FcPattern* FontMatch(const char* type, FcType vtype, const void* value,
va_start(ap, value);
FcPattern* pattern = FcPatternCreate();
+ bool family_requested = false;
for (;;) {
FcValue fcvalue;
@@ -116,6 +117,9 @@ static FcPattern* FontMatch(const char* type, FcType vtype, const void* value,
}
FcPatternAdd(pattern, type, fcvalue, 0);
+ if (vtype == FcTypeString && strcmp(type, FC_FAMILY) == 0)
+ family_requested = true;
+
type = va_arg(ap, const char *);
if (!type)
break;
@@ -128,10 +132,56 @@ static FcPattern* FontMatch(const char* type, FcType vtype, const void* value,
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 NULL;
+ }
+
+ FcChar8* post_match_family;
+ FcPatternGetString(match, FC_FAMILY, 0, &post_match_family);
+ const bool family_names_match =
+ !family_requested ?
+ true :
+ strcmp((char *) post_config_family, (char *) post_match_family) == 0;
+
FcPatternDestroy(pattern);
+ if (!family_names_match) {
+ FcPatternDestroy(match);
+ return NULL;
+ }
+
return match;
}
diff --git a/skia/sgl/SkTypeface.cpp b/skia/sgl/SkTypeface.cpp
index 9821c51..79cb631 100644
--- a/skia/sgl/SkTypeface.cpp
+++ b/skia/sgl/SkTypeface.cpp
@@ -26,7 +26,8 @@ bool SkTypeface::Equal(const SkTypeface* facea, const SkTypeface* faceb)
SkTypeface* SkTypeface::Create(const char name[], Style style)
{
SkTypeface* face = SkFontHost::FindTypeface(NULL, name, style);
- face->ref();
+ if (face)
+ face->ref();
return face;
}
diff --git a/webkit/port/platform/graphics/chromium/FontCacheLinux.cpp b/webkit/port/platform/graphics/chromium/FontCacheLinux.cpp
index 06251b6..31b4207 100644
--- a/webkit/port/platform/graphics/chromium/FontCacheLinux.cpp
+++ b/webkit/port/platform/graphics/chromium/FontCacheLinux.cpp
@@ -96,6 +96,8 @@ FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontD
style |= SkTypeface::kItalic;
SkTypeface* tf = SkTypeface::Create(name, (SkTypeface::Style)style);
+ if (!tf)
+ return NULL;
FontPlatformData* result =
new FontPlatformData(tf,
diff --git a/webkit/tools/test_shell/resources/linux-fontconfig-config b/webkit/tools/test_shell/resources/linux-fontconfig-config
index c5492cd..cb1e3773 100644
--- a/webkit/tools/test_shell/resources/linux-fontconfig-config
+++ b/webkit/tools/test_shell/resources/linux-fontconfig-config
@@ -29,6 +29,17 @@
</edit>
</match>
+ <!-- Some layout tests specify Helvetica as a family and we need to make sure
+ that we don't fallback to Times New Roman for them -->
+ <match target="pattern">
+ <test qual="any" name="family">
+ <string>Helvetica</string>
+ </test>
+ <edit name="family" mode="assign">
+ <string>Arial</string>
+ </edit>
+ </match>
+
<match target="pattern">
<test qual="any" name="family">
<string>sans-serif</string>