Closed Bug 490475 Opened 15 years ago Closed 13 years ago

fontconfig render settings affect spacing of characters when printing

Categories

(Core :: Graphics, defect)

x86
Linux
defect
Not set
major

Tracking

()

RESOLVED FIXED
mozilla2.0b11

People

(Reporter: pixelmonkey, Assigned: u285178)

References

Details

Attachments

(2 files)

User-Agent:       Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.9) Gecko/2009042113 Ubuntu/8.10 (intrepid) Firefox/3.0.9
Build Identifier: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.9) Gecko/2009042113 Ubuntu/8.10 (intrepid) Firefox/3.0.9

Printing documents in Firefox 3.0 or 3.5 on Ubuntu Intrepid has font kerning issues.  You can see these issues in the Print Preview dialog and once printed.  The issues are pretty sublte but definitely there; for example, two letters overlapping or squished together, or too much spacing between two letters.

The amazing thing is that if I take the same text and paste it into OpenOffice.org or some other GNOME application and print from there, it prints fine.  It's definitely a Firefox problem specifically.

Reproducible: Always

Steps to Reproduce:
1. Print or print preview any web-page
2. Notice font kerning issues
Actual Results:  
Letters spaced inconsistently, either too much of a gap or "squished together"

Expected Results:  
Kerning that matches the rest of Linux desktop

Font hinting settings in gnome-appearance-properties do not affect this.
Status: UNCONFIRMED → RESOLVED
Closed: 15 years ago
Resolution: --- → DUPLICATE
The fix in bug 403513 dealt with gnome (and Xft) font properties incorrectly affecting print output.

The issue here is the effect of fontconfig settings, which Ubuntu provides.
Removing 10-antialias.conf,
10-hinting.conf, 10-hinting-medium.conf, 10-no-subpixel.conf, and
53-monospace-lcd-filter.conf from /etc/fonts/conf.d will solve the problem (unless there are other similar fontconfig settings elsewhere).
Resolution: DUPLICATE → INVALID
Summary: Font kerning problems when printing on Firefox 3.0 and 3.5 → Font kerning problems when printing on Firefox 3.0 and 3.5 due to Ubuntu fontconfig settings
I'll reopen this because maybe we can do something about this.

If I understand postscript and pdf surfaces correctly, they usually only position a glyph, without rendering it, essentially making a guess about how the glyph will be rendered on the final device.  We should probably guess the rendering options to use for measuring rather than looking at fontconfig settings.

I wonder whether maybe we should skip the FcRenderPrepare for print output, but that provides synthetic oblique through changing the font matrix.  It also provides synthetic bold, but I'm not sure if that works for printing.

When fonts can't be embedded, I assume the glyph is rendered to an image with pixels.  In this case we probably should use (some of) the fontconfig settings, though I'm not sure it's worth the effort.
Status: RESOLVED → UNCONFIRMED
Component: General → GFX: Thebes
Product: Firefox → Core
QA Contact: general → thebes
Resolution: INVALID → ---
Summary: Font kerning problems when printing on Firefox 3.0 and 3.5 due to Ubuntu fontconfig settings → fontconfig render settings affect spacing of characters when printing
Version: unspecified → Trunk
Status: UNCONFIRMED → NEW
Ever confirmed: true
(Regarding comment 2)

Font hinting is a mechanism to make outline/vector fonts (intended for print) also legible on screen (or other low-resolution raster rendering output), by using instructions embedded in the font to determine how to line the shapes up to the raster grid (see: http://www.microsoft.com/typography/tools/trtalr.aspx for an explanation).  As such it should not affect printing at all.

Setting fontconfig hinting (whether system-wide in /etc/fonts.{conf,d} or for a user in .fonts.conf and included files) is a perfectly legitimate to tweak font rendering for the display (can vary based on the screen size, resolution, pixel arrangements, user preferences, etc.).  The problem is that these settings break printing whereas they should not affect it at all.

Pinning the problem on these settings, and suggesting removing them as a "fix" to the problem, is slipping around the bug.
(In reply to comment #3)
> If I understand postscript and pdf surfaces correctly, they usually only
> position a glyph, without rendering it, essentially making a guess about how
> the glyph will be rendered on the final device.  We should probably guess the
> rendering options to use for measuring rather than looking at fontconfig
> settings.

PS/PDF can position each individual glyph or draw strings of glyphs where each glyph is positioned at its natural glyph advance. All hinting should be disabled when generating PDF/PS output as it is a device independent format and no assumptions can be made about what devices it will be rendered on.

The cairo PDF and PS surfaces default to all hinting off:

static void
_cairo_pdf_surface_get_font_options (void                  *abstract_surface,
				     cairo_font_options_t  *options)
{
    _cairo_font_options_init_default (options);

    cairo_font_options_set_hint_style (options, CAIRO_HINT_STYLE_NONE);
    cairo_font_options_set_hint_metrics (options, CAIRO_HINT_METRICS_OFF);
    cairo_font_options_set_antialias (options, CAIRO_ANTIALIAS_GRAY);
}

> When fonts can't be embedded, I assume the glyph is rendered to an image with
> pixels.  In this case we probably should use (some of) the fontconfig
> settings, though I'm not sure it's worth the effort.

I'm not sure what you mean by "When fonts can't be embedded" as cairo PDF/PS always embeds (and subsets) the fonts used. If subsetting fails it will fallback to embedding a font generated from the unhinted outlines of the glyphs. Only bitmap fonts result in a embedded bitmap font generated from the glyphs rendered at 72dpi.
(In reply to comment #4)
> Setting fontconfig hinting (whether system-wide in /etc/fonts.{conf,d} or
> for a user in .fonts.conf and included files) is a perfectly legitimate to
> tweak font rendering for the display (can vary based on the screen size,
> resolution, pixel arrangements, user preferences, etc.).

Fontconfig rules are very powerful, but it is not always a good idea to use
this power.  For example, if a pattern already has pixelsize set then it is
not a good idea to always change the pixelsize to some favorite pixelsize.  If
the pixelsize is changed, then the new pixelsize will be used.

If the pattern already has hinting set to false, then I do not think it is a
good idea for fontconfig rules to always change hinting to true.
I can't think of a good reason to have a fontconfig rule that sets hinting to
true as this is the default anyway.  If an application has set hinting to
false, then it may have good reason for doing so.

But, unfortunately, there do exist fontconfig rules that are always replacing
the value of hinting with true.

What we don't currently have is a way to determine which fontconfig rules we
should ignore, though hinting and rgba are good candidates for being ignored.

(In reply to comment #5)
> If subsetting fails it will fallback to embedding a font generated from the
> unhinted outlines of the glyphs. Only bitmap fonts result in a embedded
> bitmap font generated from the glyphs rendered at 72dpi.

Thanks, Adrian.  That's helpful to know.
Has anything changed related to this in the development branch?  I still notice this irritating bug in Firefox 3.5.5.

It seems to me that the reported effect (though possibly not the root cause, if Cairo is doing anything else raster-specific used by the code in the printing path, the effect of other settings may slip in) should be fixable by adding a few statements to override the hinting and RGBA settings in the printing path to none.  Would you accept a patch to do that, and if so could it get integrated to the next Firefox 3.5 minor release?

I realize the Firefox developers may be busy with other issues and not have time for this.  So I would be happy to spend a few hours myself getting to know some Cairo and learn whatever has changed in the Mozilla build system since I last compiled it to work on producing a fix for this symptom, if you could use one, since the hard-to-read print output (or conversely, hard-to-read on-screen rendering without the right options) has been annoying me for a long while now.
As for the broader issue, to recap first the general notes:

hinting, RGBA, and pixel sizes of fonts are meaningless in print or vector output (and the first two also pretty unnecessary on high-resolution raster output, but that does not apply to pixel displays), and any meaning artificially given to them in vector space for supposed analogy with raster rendering just distorts the vector output.

If using a font rendering mechanism to detect the metrics of glyphs for individual character positioning (by the symptoms and discussion it seems that this is happening, since if plain strings are provided to the PostScript show operator, it uses the constant metrics embedded in the font, and the kerning wouldn't ever differ), then a pure vector rendering mechanism should be used, and not one that assumes any pixelization or sampling, as when the PostScript/PDA renderer processes the fonts, it is doing this completely in vector space.

And for the specific fonts.conf issue:

I agree that a configuration forcing hinting if application code explicitly disables it is a bad idea.  It does not however seem to me that these fonts.conf settings are written with that intention - they are there to configure the right level of hinting for on-screen rendering, whatever the default may be.  The default hinting seems to be "slight", and increasing it to "full" makes sense, but where it is set to off this should have no effect.  If an application explicitly sets hinting to false, fonts.conf settings should not override that.

Having read a bit about fontconfig, this makes me wonder what this is doing in the "pattern" instead of at a later stage as an actual rendering setting.  I think the whole code path that deals with hinting, or adjusting the position of glyphs in any way based on raster parameters, should not at all be reached when printing, so these settings should have no effect then.  I do not really know Cairo however and realize that parts of its interface may not be making this functionality modular enough.  As I mentioned, a real fix at the root may involve bigger changes, and if the problematic assumptions go beyond Mozilla code, I can't expect more than a careful workaround from here.
(In reply to comment #8)
> I agree that a configuration forcing hinting if application code explicitly
> disables it is a bad idea.  It does not however seem to me that these
> fonts.conf settings are written with that intention - they are there to
> configure the right level of hinting for on-screen rendering, whatever the
> default may be.  The default hinting seems to be "slight", and increasing it
> to "full" makes sense, but where it is set to off this should have no
> effect.  If an application explicitly sets hinting to false, fonts.conf
> settings should not override that.

From fontconfig's perspective, hintfull is the default for "hintstyle".  Some
screen settings may be setting this to something else and screen settings are
one sensible place to set hintstyle.

But the issue here is the "hinting" property.  If hinting is false then
hintstyle will not be used.  (The "rgba" property may also be having an
effect.)

Fixing the fontconfig configuration is going to be easiest way to fix this.


I'm not usually keen on overriding the user (or sysadmin's) configurations,
but could perhaps tolerate an exception here because turning hinting on is not
very useful for printing.  The override would need to happen after
FcFontRenderPrepare().

gfxPangoFcFont, which calls FcFontRenderPrepare(), doesn't know whether the
font is for printing or not.  The easiest way to provide this information
might be by adding a new property to the pattern in PrepareSortPattern().


Another option is to change the resolution of the printing surfaces to
something suitable for a printer (at least 300dpi).  That way any hinting
effects become insignificant.  (If hinting were significant at printer
resolutions then we would want hinting in the printer drivers.)

Apparently the reason why we don't do this now is that widgets with GTK themes
don't look right.  But I don't think we should be using GTK themes for widgets
in printing anyway, so this could be turned off.


> Having read a bit about fontconfig, this makes me wonder what this is doing
> in the "pattern" instead of at a later stage as an actual rendering setting.
> I think the whole code path that deals with hinting, or adjusting the
> position of glyphs in any way based on raster parameters, should not at all
> be reached when printing, so these settings should have no effect then.

These are rendering settings.  The same code paths are used for screen and
print layout (with different rendering parameters).
(In reply to comment #7)
> Would you accept a patch to do that, and if so could it get
> integrated to the next Firefox 3.5 minor release?

It is very unlikely that a patch would end up in a minor release.
Minor releases usually only include fixes for security and stability issues (and sometimes serious regressions).

I would consider a patch for the next major version, which would be 3.7.
When testing potential fixes for this bug I suggest checking the PostScript output. Currently I'm seeing strings like this:

[<00010002>-14<0003>15<0004>-14<0005>14<00060007>-14<0008>-14<0009>14<000
a>28<000b>-42<000c>]TJ

If glyphs are positioned are there natural unhinted glyph advances the above string would be:

<000100020003000400050006000700080009000a000b000c>Tj

Cairo defines PostScript functions equivalent to PDF operators so the same printing code can be shared by PS and PDF. The "Tj" is the PDF equivalent of the PostScript "show" than prints a string of text. "TJ" is the PDF operator that prints a string with a relative offset adjustment between each glyph for use with kerned text.

Cairo checks for strings of glyphs that are at their natural glyph advance and optimises the output to avoid positioning each individual glyph. PostScript output that uses "Tj" (except when kerning is required) is going to be result in smaller and more efficent output.
(In reply to comment #9)
> But the issue here is the "hinting" property.  If hinting is false then
> hintstyle will not be used.  (The "rgba" property may also be having an
> effect.)

Sorry, my omission.  It is both the hintstyle and hinting property.  However there are occasions when hinting needs to be set to true.  The only premise which would ensure one never need to set it is if it *always* defaults to true just for screen rendering - and then if it would *always* default to false for printing then this problem would not occur in the first place.  This is not the case.

> Fixing the fontconfig configuration is going to be easiest way to fix this.

As per the reasons above, this is not always possible or desirable.  It would work, if fontconfig would allow settings per medium (with something like <match meidum="print">) but if fontconfig would be aware of such things then settings like hinting and rgba wouldn't exist for these media at all.

> I'm not usually keen on overriding the user (or sysadmin's) configurations,

I would agree, when the set configured settings are used properly.  However as we are seeing a "leak", of settings having an ill effect they should not have: until that is fixed, overriding the setting to neuter its ill effect in a at a stage where it should have no effect whatsoever, should be acceptable.  Surely I was not suggesting that as an end-all fix to the root problem.

> but could perhaps tolerate an exception here because turning hinting on is not
> very useful for printing.

s/is not very useful/makes no sense/.  I would go so far as saying that it is never anybody's intention when specifying hinting/rgba settings that they will have any effect on printing.

> The override would need to happen after FcFontRenderPrepare().

Thanks, when I get to look at the code I'll keep that in mind.

> gfxPangoFcFont, which calls FcFontRenderPrepare(), doesn't know whether the
> font is for printing or not.  The easiest way to provide this information
> might be by adding a new property to the pattern in PrepareSortPattern().

As mentioned, I don't see what this has to do with the pattern at all.  After deciding on what font to use and what attributes to apply, hinting and RGBA are settings for the screen rendering mechanism, once a font pattern was chosen.  If fontconfig is used as a generic font selection mechanism independent of how the fonts are rendered (i.e. framebuffer/PostScript), it should not include any device dependent settings like hinting/rgba at all.  Anyway this is not a Mozilla issue but a matter of fontconfig's interface, so I don't expect it to be changed here.

> Another option is to change the resolution of the printing surfaces to
> something suitable for a printer (at least 300dpi).  That way any hinting
> effects become insignificant.

This strikes me as a very ugly and wasteful workaround - performing an adjustment that makes no sense in the first place, and increasing its resolution to reducing the ill effect, instead of just dropping that adjustment.

> > I think the whole code path that deals with hinting, or adjusting the
> > position of glyphs in any way based on raster parameters, should not at all
> > be reached when printing, so these settings should have no effect then.
> 
> These are rendering settings.

Specifically, screen/raster rendering settings.

> The same code paths are used for screen and print layout (with different rendering parameters).

That should definitely not be the case.

Some of the code can meaningfully be shared between screen and print rendering.  i.e. the selection of fonts and properties, initial positioning, line wrapping, and more.

However the actual FreeType *raster-device-specific* glyph rendering code (including things such as RGBA/antialiasing) is *not at all used* when printing.  On print, an instruction is simply placed in the output to render a given glyph (or string of glyphs [*]) from a given character in a given position, and the printer/PostScript/PDF engine does that at a later stage.  And the hinting code, responsible for positioning adjustments to *compensate for limitations of that raster-device-specific glyph rendering*, is as such also raster-device-specific, and should *only* be used in contexts where the that raster-device-specific glyph rendering code is used.

[*] I agree with Adrian's comment #11 - positioning individual glyphs within a line in one font is only done when a special adjustment of a character is needed, such as for kerning or hinting, and otherwise (it seems) Cairo relies on PostScript/PDF for the natural font-metric based advance by outputting a chunk of unadjusted glyphs in one string (I'm not sure of the state today of extended metrics/kerning by PostScript/PDF, but seems like Cairo does not rely on that).  So looking at the PostScript output for a string of digits interleaved with latin letters, that involves no kerning in a typical font, is a good way to test that positioning is not distorted by hinting.
> It is very unlikely that a patch would end up in a minor release.
> Minor releases usually only include fixes for security and stability issues
> (and sometimes serious regressions).
> 
> I would consider a patch for the next major version, which would be 3.7.

Cool.  I will try to find the time and do that before 3.7 then.  (The main initial barrier is just the effort it takes to get the head development branch sources and then everything required to build a working runnable standalone Firefox binary from that -- I have not touched Mozilla's complex build framework in a long time but it took a few hours last time I did)
(In reply to comment #12)
> However
> there are occasions when hinting needs to be set to true.  The only premise
> which would ensure one never need to set it is if it *always* defaults to true
> just for screen rendering - and then if it would *always* default to false for
> printing then this problem would not occur in the first place.  This is not the
> case.

hinting always defaults to true (through FcDefaultSubstitute).  Mozilla sets hinting to false for printing.  hinting does not need to be set to true.

> > Fixing the fontconfig configuration is going to be easiest way to fix this.
> 
> As per the reasons above, this is not always possible or desirable.  It would
> work, if fontconfig would allow settings per medium (with something like <match
> meidum="print">) but if fontconfig would be aware of such things then settings
> like hinting and rgba wouldn't exist for these media at all.

> If fontconfig is used as a generic font selection mechanism independent of how
> the fonts are rendered (i.e. framebuffer/PostScript), it should not include any
> device dependent settings like hinting/rgba at all.

This is exactly why fontconfig configurations should not blindly change hinting and rgba settings.

medium="print" may be a useful property in some situations, but is usually not necessary as we already have hinting set correctly for the medium, and rgba set correctly for the screen.

There are only problems when fontconfig configuration files change the (correct) supplied values.
It is rather hard not to have hinting and rgba activated in the fontconfig settings.

For example KDEs systemsettings will re-add and activate hinting and rgba in $HOME/.fonts.conf, when modifying anything in Appearance->Fonts.
Testing with mozilla-central and cairo git I'm still seeing ugly text. The recent changes to cairo subsetting to output latin text as literal strings shows how bad the problem is.

The following is an extract of the PostScript output from printing a webpage:

  BT
  6.788535 0 0 6.788535 68.400179 347.973235 Tm
  /f-2-0 1 Tf
  [(W)44(h)-44(e)-44(n)-44( )-22(a)-44(st)-22(r)33(o)-44(n)-44(o)-43(m)33
  (e)-44(r)33(s )-22(se)-44(a)-44(r)33(ch)-44( )-22(f)-22(o)-44(r)33( )-22
  (l)22(i)22(f)-22(e)]TJ
  ET

if text was correctly positioned when printed I would expect to see:

  BT
  6.788535 0 0 6.788535 68.400179 347.973235 Tm
  /f-2-0 1 Tf
  [(When astronomers search for life)]TJ
  ET


(In reply to comment #9)
> I'm not usually keen on overriding the user (or sysadmin's) configurations,
> but could perhaps tolerate an exception here because turning hinting on is not
> very useful for printing.

Hinting does not make sense for printing. What is the target device pixel grid you are aligning to? There isn't one. PS/PDF is a device independent vector based format.
Let me see if I've got this right.  If a user is so misguided as to turn on hinting for screen rendering, they get lousy printed output because Firefox
uses FcRenderPrepare, whose only benefit is to produce synthetic oblique, for printing as well as screen rendering.  

It may come as a surprise to Firefox developers but most font families have an oblique/italic variant and synthetic obliquing is hardly ever necessary.  Surely this minor benefit doesn't compensate for lousy printed output for *everybody*.

And it seems the only workaround is for me to fix the ~/.fonts.conf files of my users and beg them not to change font settings.  And this has been known for over a year and no one has volunteered to fix this bug.  Not surprisingly, no other application seems to have this problem; in particular google-chrome produces good printed output. Need I say more?
I had a look at gfxPangoFonts.cpp and the problem is the line 

 cairo_font_options_set_hint_metrics(fontOptions, CAIRO_HINT_METRICS_ON);

in CreateScaledFont().

Testing with metrics set to off produced perfect print output. I'm not sure what hint metrics has to do with fontconfig as the above line does not depend on the fontconfig pattern and even the comment above it says this is the one option not recorded in the fontconfig pattern.

This option should really be obtained from cairo_surface_get_font_options() to get the correct metrics option for the surface. If the surface is not available, this should at least be dependent on whether the font is for printing. Hintstyle should also be set to none for printing although this only affects the use of fallback fonts where cairo embeds a font created from the glyph outlines.
(In reply to comment #3)
> I wonder whether maybe we should skip the FcRenderPrepare for print output, but
> that provides synthetic oblique through changing the font matrix.  It also
> provides synthetic bold, but I'm not sure if that works for printing.

The current cairo git contains a fix to make synthetic bold fonts print correctly. If the FT embolden option is set cairo will use a fallback font. ie the outlines obtained from FT will be used instead of subsetting the font file.
This patch adds a "printing" fontconfig property if the font is for printing. When creating the font, if printing is true, hint metrics and hint style are disabled.
Comment on attachment 498471 [details] [diff] [review]
disable hinting when printing

Thanks, Adrian!

>+
>+

My only nit to pick is that I don't like double blank lines taking up space in my editor.

This is a low risk change that we should consider for FF4.
It only changes behavior when printing.
Attachment #498471 - Flags: review+
Attachment #498471 - Flags: approval2.0?
The same logic applies to mozilla-1.9.2 branch, I run Firefox 3.6 and Thunderbird 3.1 with this patch and kerning is finally perfect in PDF printouts (kerning in PostScript output differs from the PDF one both on trunk and on branch with cairo-1.10 and --enable-system-cairo, but this is an unrelated story). Why not taking this improvement to the branch?
Thank you ! It's really much better
Attachment #498471 - Flags: approval2.0? → approval2.0+
http://hg.mozilla.org/mozilla-central/rev/922a9e593e6f
Assignee: nobody → ajohnson
Status: NEW → RESOLVED
Closed: 15 years ago13 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla2.0b11
Blocks: 546044
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: