Closed Bug 227889 Opened 21 years ago Closed 13 years ago

[xft] font matching does not follow CSS matching algorithm

Categories

(Core Graveyard :: GFX: Gtk, defect)

x86
Linux
defect
Not set
normal

Tracking

(Not tracked)

RESOLVED INCOMPLETE

People

(Reporter: bryner, Unassigned)

References

Details

(Keywords: css2)

Attachments

(1 file)

With the following fonts installed on my system (fontconfig fc-list output):

LucidaTypewriter:style=Bold:weight=200
LucidaTypewriter:style=Regular:weight=100
Verdana:style=Bold Italic:weight=200
Verdana:style=Bold:weight=200
Verdana:style=Regular:weight=100
Verdana:style=Italic:weight=100

and these CSS properties:

font-family: LucidaTypewriter, Verdana;
font-style: italic;

the font matching does not follow
http://www.w3.org/TR/CSS21/fonts.html#algorithm . In particular, the matching
algorithm specifies that font-style must match as follows:

'italic' will be satisfied if there is either a face in the UA's font database
labeled with the CSS keyword 'italic' (preferred) or 'oblique'. Otherwise the
values must be matched exactly or font-style will fail.

There is no italic style for LucidaTypewriter, so it should move on to Verdana
and use that.  Instead, it uses non-italic LucidaTypewriter.
Attached file testcase
Looking at the code, it's probably similarly not possible for a bitmapped font
to be skipped if it's not available at the requested size (which the spec also
says should happen).
The solution worked out for scalable fonts was to synthesize an oblique face
when not available so that the font-style property would always match; this
makes it essentially identical to all of the other properties which are
secondary to the family name in match priority.

So, the only remaining issues are with bitmap fonts.  As bitmap fonts continue
to grow less and less important, I think we should focus on conformance with the
specification, rather than an ideal result.  The UA is allowed discretion in the
matching of bitmap font sizes (so that the current scheme which allows arbitrary
error is conformant, if not ideal).  But, font styles provide no wiggle room to
claim conformance with the current implementation.

It seems to me that the CSS specification requires an application-specified
font-style to be of primary import, more important in fact than the family name
when selecting a font.  If so, I can add a new matching table entry which places
strongly bound slant values above strongly bound family names, while leaving
weakly bound slant values below weakly bound family names.  That, and a bit of
code to make slant comparisons equate italic and oblique should fix the problem.
  
Let me know if this will suffice, and I'll add it to fontconfig which is
scheduled to have a release (2.3) shortly.  I was hoping to have localized
family and style names ready for that release, but if this issue is blocking CSS
conformance in Mozilla, I can make a release without that functionality and pend
the family and style name changes until 2.4.
That's how I would read the spec... what you suggested sounds like it should fix
the problem.  Thanks.
Hmm. Well, the code was certainly easy to write, but now I'm getting a very
undesireable result.  Asking for 'bitstream vera serif:italic' yields another
family (Times New Roman), because there is no "real" slanted form of Bitstream
Vera Serif.  The matching rules can't "look ahead" to see the rendering
manipulation rules which construct a shear transformation to artifically oblique
the font.

So, unless I can figure out a way around this, I've got the choice between a
version which works well with scalable fonts but is non-conformant with bitmap
fonts and a version which is conformant with all fonts but works poorly with
scalable fonts.

I haven't thought of a way to reconcile these two versions and come up with
something that can admit scalable fonts as being "obliquable" and yet skip over
bitmap fonts.

One possiblity would be to add artificial obliquing to bitmap fonts; it would be
easy to add a slight slant when loading them.  I'd rather sacrifice the
experience with bitmap fonts than with scalable ones.

Other suggestions would be welcome, and of course I'll keep thinking as well.
There's also the issue of aliases I was discussing with you today.
Currently a match request of "helvetica,serif" will get expanded to
"helvetica,<list of fonts in serif alias>,serif, <list of fonts in
alias containing helvetica>,sans-serif".  Without a helvetica font
installed, the usual out-of-box case on linux, this will return a
serif font while we would prefer a reasonable helvetica substitution.
Status: NEW → ASSIGNED
tor: We would?
hixie: I would certainly expect a page that specifies just helvetica (to
which we add serif as the fallback) to display in a sans-serif font.
Why?

If the author wanted to default to something other than the user's default, he 
would have said:

   font-family: Helvetica, sans-serif;
I like to make the reasably safe assumption that most web designers
are idiots, and when they say "font-family: helvetica" they mean "a
font without the twiddly bits".
Then you should suggest that to www-style@w3.org, but in the meantime, our doing 
that would be non-compliant.
I agree with Hixie.  This is not a case where an alias exists for Helvetica
itself.  This is fontconfig appending sans-serif fonts to the end of the list so
that if no families you gave in your pattern matched, it can come up with
something close to one of them.  What the author says explicitly should always
be preferred.

However, in the case tor is talking about, I'm wondering whether the 'serif' was
specified in CSS, or if we just appended it to the pattern because no CSS
generic font families were listed.  If that's the case, we may want to examine
that code, because I think we're defeating fontconfig's attempt to find a
reasonable default font based on the font you wanted to match.
I'm talking about the case where only a single font was specified, ex:

  <font style="font-family: helvetica">Helvetica</font>
See

http://lxr.mozilla.org/seamonkey/source/gfx/src/gtk/nsFontMetricsXft.cpp#462

and 

http://lxr.mozilla.org/seamonkey/source/gfx/src/gtk/nsFontMetricsXft.cpp#1193

for the code I think could be changed.  It seems to me that if no generic font
was specified in css, we should go ahead and call FcConfigSubst without
appending 'serif' to the pattern.  Then we could inspect the pattern to see if
fallback fonts are in place... if not, we could then append serif and call
FcConfigSubst again.  Just an idea.
Ok, I had been assuming that the 'serif' entry in the pattern came from the
document and not from the browser configuration.  If you don't append 'serif',
things will work as desired.  Fontconfig will continue to ensure that as much of
the Unicode space is covered as can be managed from the available fonts, the
pattern only changes the order in which fonts are considered for inclusion. 
Seems like an opportunity to fix a bug by deleting code.  Always the best
outcome when it works.
Found what appear to be a couple bugs in our xft glue:

  * "serif" is being added to the font list before SetupFCPattern is called,
    where it could be handled by the generic font fallback.

  * if more than one generic is listed in the font list, only the mGeneric
    font will be added to the pattern.
Ok, so... back to the oblique problem.  Could you not just check FC_SCALABLE and
cause that to match an oblique style?
Fontconfig computes a 'distance' from the pattern to each available font; the
list returned from FcFontSort is sorted based on that metric.  Seemed like a
good idea when I wrote the code, and it works really well most of the time. 
That overall distance is actually an ordered list of distances for each property
in the font and pattern; each of these is computed without reference to the
remaining pattern elements.  What you need to do in this case is *reorder* the
list of values depending on two things: 1) whether the font was scalable
(FC_SCALABLE) and 2) whether the configuration contained instructions to take
that scalable face and shear it when an oblique varient was requested.  I'm
having trouble figuring out how that can be managed, even assuming arbitrary
modifications to the existing code (which I'm not averse to).

I'll be the first to admit that fontconfig is probably too configurable; and
that configurability makes solving problems like this harder.  However, I've
seen people find uses for most of the flexibility it offers, so I'd like to work
within the current visible artifacts of the architecture (match/edit rules,
multi-valued pattern elements).

Again, I can "solve" this issue by shearing bitmap fonts where necessary.  I
think that violates the spirit of bitmap fonts, but I guess I wonder how hard we
should work to enable people to continue to use such horrors anyways.
tor: I was responding to your comment 6, where you said "helvetica,serif". If 
the author just says "helvetica" then we should default to the user's default 
font selection.
Assignee: bryner → nobody
Status: ASSIGNED → NEW
QA Contact: ian → gtk
Does this bug still occur in a recent trunk build?
Product: Core → Core Graveyard
The current font-handling code bears very little resemblance to what it was at the time this bug was last discussed, and it rather sounds like it was a fontconfig issue rather than a bug in Firefox anyway.

If there is still a problem here, please file a new bug in Core:Graphics with a self-contained testcase; if possible, use @font-face in this test case so everyone is looking at exactly the same font(s).
Status: NEW → RESOLVED
Closed: 13 years ago
Resolution: --- → INCOMPLETE
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: