diff options
author | agl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-12-03 22:44:09 +0000 |
---|---|---|
committer | agl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-12-03 22:44:09 +0000 |
commit | b3467a4dd2f9d7c6473c1fcd22a31c2ac39a2d88 (patch) | |
tree | e2f55061517c5aaf3e87beca9c335bfcc9e530c1 | |
parent | 378f3ac5cd7c0c170cf3e8e54aa627defcb590da (diff) | |
download | chromium_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.cpp | 50 | ||||
-rw-r--r-- | skia/sgl/SkTypeface.cpp | 3 | ||||
-rw-r--r-- | webkit/port/platform/graphics/chromium/FontCacheLinux.cpp | 2 | ||||
-rw-r--r-- | webkit/tools/test_shell/resources/linux-fontconfig-config | 11 |
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> |