Summary: | Konqueror doesn't parse font-family CSS correctly if first font doesn't exist [testcase] | ||
---|---|---|---|
Product: | [Applications] konqueror | Reporter: | Jason <jglane> |
Component: | khtml | Assignee: | Stephan Kulow <coolo> |
Status: | RESOLVED FIXED | ||
Severity: | normal | CC: | bradd-kde, walter |
Priority: | NOR | ||
Version First Reported In: | unspecified | ||
Target Milestone: | --- | ||
Platform: | Compiled Sources | ||
OS: | Linux | ||
Latest Commit: | Version Fixed In: | ||
Sentry Crash Report: | |||
Attachments: | test case |
Description
Jason
2003-06-30 22:57:34 UTC
Sorry, should be font-family css attribute. Correcting the title accordingly *** Bug 60976 has been marked as a duplicate of this bug. *** I too have encountered this bug, and I think I have discovered the root cause. (Source path and line numbers are from the kdelibs-3.1-10.src.rpm package distributed with Red Hat Linux 9.) The code for font family selection appears in khtml/css/cssstyleselector.cpp lines 2432-2474. That code correctly includes a loop over the stylesheet's font-family value, but it handles the "not found" case incorrectly. QString face = static_cast<FontFamilyValueImpl *>(val)->fontName(); if ( !face.isNull() || face.isEmpty() ) { if(face == "serif") { face = settings->serifFontName(); } else if(face == "sans-serif") { face = settings->sansSerifFontName(); } else if( face == "cursive") { face = settings->cursiveFontName(); } else if( face == "fantasy") { face = settings->fantasyFontName(); } else if( face == "monospace") { face = settings->fixedFontName(); } else if( face == "konq_default") { face = settings->stdFontName(); } if ( !face.isEmpty() ) { fontDef.family = face; if (style->setFontDef( fontDef )) fontDirty = true; } return; } The goal is apparently to look up the font-family in the Qt font database and set the font-family if there's a match. However, the "if" condition is incorrect: It's always true, even if there's no match! Because of this, the first font-family always "matches"; if the font doesn't actually exist, Konqueror apparently uses its default font. It looks like there's a set of parentheses missing. I think the following code would be correct: if ( ! (face.isNull() || face.isEmpty()) ) { However, I think the test can be simplified further. All Null QStrings are also Empty. Therefore, the following test should be equivalent: if ( !face.isEmpty() ) { Unfortunately, I don't have a good test system to test this change. The error is simple, though, and this one-line change should be sufficient to fix it, unless I'm overlooking something. Hopefully, the KDE developers can fix it easily. Note that I also discovered another possible bug while investigating this. At first, I thought this might be an Xft bug. I tried creating an alias for the missing font, but that made no difference. Qt's font database does not include aliases in the db.families() call (used by KHTMLSettings::AvailableFamilies() and indirectly by the CSS routines). Therefore, a user cannot supply aliases for fonts used in font-family declarations, which is a potential problem for Linux users who have URW Palladio installed instead of a true Palatino font (for example). I don't know whether there's a way to fix this using Qt; a brief skim of the manpages didn't turn anything up. Therefore, this problem might be a Qt bug rather than a KHTML bug. Subject: Re: [PATCH] Konqueror doesn't parse font-family CSS correctly if first font doesn't exist [testcase] Thanks Bradd for your detective work and clear description of the problem! The following patch against current KDE_3_1_BRANCH fixes the problem for me: If anyone with CVS privileges could apply the patch, or something very similar this bug can be closed. I don't know if it the problem exists in HEAD as I'm not running it, and the code seems to have changed quite a bit. Jason Index: cssstyleselector.cpp =================================================================== RCS file: /home/kde/kdelibs/khtml/css/cssstyleselector.cpp,v retrieving revision 1.242.2.4 diff -u -3 -p -r1.242.2.4 cssstyleselector.cpp --- cssstyleselector.cpp 30 Apr 2003 21:41:07 -0000 1.242.2.4 +++ cssstyleselector.cpp 5 Aug 2003 08:13:00 -0000 @@ -2451,7 +2451,8 @@ void CSSStyleSelector::applyRule( DOM::C CSSPrimitiveValueImpl *val = static_cast<CSSPrimitiveValueImpl *>(item); if(!val->primitiveType() == CSSPrimitiveValue::CSS_STRING) return; QString face = static_cast<FontFamilyValueImpl *>(val)->fontName(); - if ( !face.isNull() || face.isEmpty() ) { + + if ( !face.isEmpty() ) { if(face == "serif") { face = settings->serifFontName(); } unfortunately the code in HEAD looks slightly different. But I attach a test case that breaks. Created attachment 2858 [details]
test case
should display in courier, displays in default sans font
sent patch to kfm-devel for review Subject: kdelibs/khtml CVS commit by coolo: do not break on non existant fonts in css font lists CCMAIL: 60556-done@bugs.kde.org M +5 -0 ChangeLog 1.44 M +3 -2 css/cssstyleselector.cpp 1.294 --- kdelibs/khtml/ChangeLog #1.43:1.44 @@ -1,2 +1,7 @@ +2003-10-23 Stephan Kulow <coolo@kde.org> + + * css/cssstyleselector.cpp (applyRule): if the first font isn't found, + continue looking (#60556) + 2003-10-22 Dirk Mueller <mueller@kde.org> --- kdelibs/khtml/css/cssstyleselector.cpp #1.293:1.294 @@ -2928,8 +2928,9 @@ void CSSStyleSelector::applyRule( int id if ( !face.isEmpty() ) { fontDef.family = face; - if (style->setFontDef( fontDef )) + if (style->setFontDef( fontDef )) { fontDirty = true; - } return; + } + } } break; This change created bug #67768 Subject: kdelibs/khtml CVS commit by coolo: slightly modified patch by Paul Sprakes to fix his own bug report which turned out to be a regression introduced by my fix for #60556 (see #67768 for detailed descriptions) CCMAIL: 60556@bugs.kde.org CCMAIL: 67768-done@bugs.kde.org CCMAIL: 67973-done@bugs.kde.org (will work out regression tests now :) M +6 -0 ChangeLog 1.102 M +7 -14 css/cssstyleselector.cpp 1.301 --- kdelibs/khtml/ChangeLog #1.101:1.102 @@ -1,2 +1,8 @@ +2003-11-23 Stephan Kulow <coolo@kde.org> + + * css/cssstyleselector.cpp (applyRule): fixing my fix for #60556, which + introduced quite some regressions (thanks to Paul Sprakes for working + that out with me) + 2003-11-22 Stephan Kulow <coolo@kde.org> --- kdelibs/khtml/css/cssstyleselector.cpp #1.300:1.301 @@ -1852,6 +1852,5 @@ void CSSStyleSelector::applyRule( int id } } - if (style->setFontDef( fontDef )) - fontDirty = true; + fontDirty |= style->setFontDef( fontDef ); break; } @@ -1874,6 +1873,5 @@ void CSSStyleSelector::applyRule( int id return; } - if (style->setFontDef( fontDef )) - fontDirty = true; + fontDirty |= style->setFontDef( fontDef ); break; } @@ -1918,6 +1916,5 @@ void CSSStyleSelector::applyRule( int id } } - if (style->setFontDef( fontDef )) - fontDirty = true; + fontDirty |= style->setFontDef( fontDef ); break; } @@ -2773,6 +2770,5 @@ void CSSStyleSelector::applyRule( int id fontDef.size = size; - if (style->setFontDef( fontDef )) - fontDirty = true; + fontDirty |= style->setFontDef( fontDef ); return; } @@ -2982,10 +2978,8 @@ void CSSStyleSelector::applyRule( int id if ( !face.isEmpty() ) { fontDef.family = face; - if (style->setFontDef( fontDef )) { - fontDirty = true; + fontDirty |= style->setFontDef( fontDef ); return; } } - } break; } @@ -3164,6 +3158,5 @@ void CSSStyleSelector::applyRule( int id FontDef fontDef = parentStyle->htmlFont().fontDef; style->setLineHeight( parentStyle->lineHeight() ); - if (style->setFontDef( fontDef )) - fontDirty = true; + fontDirty |= style->setFontDef( fontDef ); } else if ( value->isFontValue() ) { FontValueImpl *font = static_cast<FontValueImpl *>(value); |