From b3467a4dd2f9d7c6473c1fcd22a31c2ac39a2d88 Mon Sep 17 00:00:00 2001 From: "agl@chromium.org" Date: Wed, 3 Dec 2008 22:44:09 +0000 Subject: 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 --- skia/ports/SkFontHost_fontconfig.cpp | 50 ++++++++++++++++++++++ skia/sgl/SkTypeface.cpp | 3 +- .../platform/graphics/chromium/FontCacheLinux.cpp | 2 + .../test_shell/resources/linux-fontconfig-config | 11 +++++ 4 files changed, 65 insertions(+), 1 deletion(-) 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 @@ + + + + Helvetica + + + Arial + + + sans-serif -- cgit v1.1