I'm soliciting interest for improving text rendering on the Linux desktop by applying gamma correction for the text. I have written a couple of JavaScript demos (for use in chromium or firefox) that can demonstrate the problem and what I think should be done about it. To view these demos, a TFT display with RGB subpixel order is required. Chromium is preferred because of faster JavaScript execution. I have not tested the demo on other browsers. Firstly, a screenshot highlighting the difference between Linux and Windows 7 font rendering. The gnome font settings are set to 'no hinting', and LCD with RGB subpixel order. I've also installed the msttcorefonts to have the Arial font used on the demo: http://bel.fi/~alankila/lcd/lcd.png The Linux browser's rendering on the bottom left shows a dirty halo around the text on black-on-white, clear color fringing on white-on-black, and significant darkening of the green-on-violet test cases. In summary, the javascript results are similar on both linux and windows, and the windows 7 output resembles the javascript output much more than linux output. Subjectively, the linux results are far worse than the others. The actual demo can be played with here: http://bel.fi/~alankila/lcd/ The demo renders the text anew on changes to text field input value. For instance, replacing the gamma 2.0 value with neutral gamma 1.0 produces javascript results that are distinctly similar to those given by linux browsers. Therefore it seems likely that lacking gamma correction on text output is the reason for the poor results on Linux. As additional evidence, executing "xgamma -gamma 2.0" makes the Linux browser results seem fairly similar as the javascript results are with normal gamma value, indicating that Linux font rendering can be remedied by use of linear gamma display. From this, it is fair to conclude that the key problem is the assumption that alpha blending can be performed as linear blend between color values in sRGB space. This is only true if the sRGB space maps linearly to physical intensity ("screen space") of the pixel on the display surface, in other words, only when gamma is 1.0. When it is not 1.0, it is necessary to raise the color component to the gamma, then perform blending linearly, and then raise to 1/gamma to get back to sRGB space. Typical monitors use gamma values from 1.8 to 2.2, and therefore all alpha blending operations should, in principle, compensate for gamma. However, that may be unacceptably slow, so a compromise might be to fix only text, where this problem matters most. In addition, the difference between 1.8 or 2.2 to 2.0 is not very large, indicating that it may be acceptable to treat the gamma value as fixed constant, rather than user-specified variable. To demonstrate the screen space alpha blending, I have made another page which works as a measuring tool for display system's gamma value: http://bel.fi/~alankila/lcd/gamma.html it is based on the color blending idea which is used on the LCD test page to show how fonts can be put on screen without color fringing artifacts. For instance, on the leftmost blocks calibrated for gamma 2.0, the middle square is 0xb4b4b4 in color. This is because the light intensity midpoint between 0x000 and 0xfff is not 0x888, but it is actually given by: desired_intensity^(1/gamma) = 0.5^(1/2.0) = 0.707, which mapped to 0 .. 255 range gives 0.707 * 255 = 0xb4. This provides the clue to understanding why Linux results on the green-on-violet text seem much too dark. The combination of 0xf0f and 0x0f0 tends to produce the value 0x888 when gamma is being ignored, but it is much too dark. The same problem is responsible for the color fringing in the other cases as well, of course.
I did a lot of work with gamma correction (though I normally call it "linear" as the numbers are in a linear relationship with light). A few corrections: First gamma correction is much MORE useful for thick filled shapes. Text and thin lines are actually the problem cases, not the best ones as you claim. I believe Cairo should do gamma correct antialising of all shapes, and would prefer lines be attacked before letters if necessary. There is a HUGE problem that for thin lines and text, users expect the reverse to be perceptually inverted, not light-inverted. Linear white-on-black letters look much too thin compared to the same image drawn black-on-white. This is not an antialising issue, users actually accept negative film of such text as being the correct reverse image, despite being on a medium with a large gamma correction. In addition the same font and lines drawn black-on-white looks much to thin when drawn gamma-corrected (drawn white-on-black looks thicker but appears to be less objectionable to users, as your demo shows). Windows solution, judging by your screen shots, appears to be to disable antialising of black-on-white by turning up the hinting excessively, I think this looks like crap and would prefer a different approach. Unfortunatly black-on-white text is far more common than any other so solutions may involve strategic thickening of letters and lines before rendering so the gamma-corrected output looks the same weight as the non-corrected output, and also so inverse images seem perceptually linear. Another problem is ARGB image composites. It definitely looks FAR better when gamma corrected, adding images looks precisely like a double exposure, for instance, and rendered antialised edges of objects composite correctly. The problem is that a huge number of ARGB images are simply "painted to composite correctly" when done in gamma space, and identifying these is very difficult. One idea is to add linear-correct compositing as new operations, leaving OVER etc, as they are. This is ugly because now there is a different operation for images than for other Cairo drawing (assuming we want gamma correction to be the default). Alternative is to analyze the image and identify sharp edges which want gamma correction, but leave large partially-transparent areas alone. Another alternative is to just do it but people are going to bitch because their output looks different than Windows. I am unsure if there is a good solution other than making gamma-correction be a new set of composite operations and not making them the default. Then at least programs can know when they are requesting this. I would not do the Windows crap output of text. Implementation can be done by just assuming gamma is 2.0. This is plenty close enough, well below the threshold of other errors in the hardware and perceptual environment. It has the advantage that the gamma calculation is x^2 or sqrt(x), meaning that expressions can often be simplified greatly. A tiny lookup table for sqrt() for all 8-bit values might help. My pages on gamma correct blending: http://mysite.verizon.net/spitzak/conversion/index.html Page describing when gamma correction does not work, including screen shot of reversed text showing the weight problems: http://mysite.verizon.net/spitzak/conversion/notlinear.html Bill Spitzak
Thank you for your comments, Bill. The reason why I claim thin shapes to be the most important is that in context of fonts, which are rarely transparent, the opaque, filled-in areas will work and all problems are at boundaries. I do not want to currently complicate the matter by talking about what is seen as perceptively equivalent thickness given white-on-black vs. black-on-white. I will personally be satisfied with the removal of color fringing at the present time. What Windows 7 does doesn't matter to me. I'm not proposing that we emulate windows 7 strong hinting. I just want to show an OS that does things better than Linux does, to give a sense of perspective on how it could be improves. OS X screenshot would have served this function just as well, but I do not own an Apple computer. As to the discussion of new set of OVER primitives, etc. I have no real personal interest on matter. The idea of providing new set of operators (or a flag, or whatever) for gamma-corrected alpha blending seems fine by me. However, I believe the way Linux currently does text is wrong and does not need preserving. Linux should definitely do it more like the other OS's do. I believe this point is both practical and tenable, so I pick this battle. I would like to leave discussion of image blending, or changes to RENDER extension, or whatever it entails to another time and another bug report. :) Your image processing pages were fascinating. I liked the improved blur, especially the one that compensated for saturated pixels. I am somewhat distressed by what the sample in notlinear.html looked like. I had expected it to look better. Perhaps I will take it as a starting point for future improvement. However, right now, I really want to see the gamma-corrected OVER for text. Later, maybe, improvements that relate to perception but aren't physically obvious.
Created attachment 117586 [details] [review] Modification of pixman-glyph.c to compile with current pixman Trying to revive this discussion... Build pixman with this patch, then do: LD_PRELOAD=pixman/.libs/libpixman-1.so \ CAIRO_DEBUG=xrender-version=-1 \ some-application-like-firefox Firefox screenshots: http://imgur.com/a/Xb1at Before/after with autohinted Liberation Sans, before/after with Adobe-CFF-engine-hinted Source Sans Pro. Use wheel thingy the corner of a preview to download full size image. Text renders much cleaner.
(In case it's unclear, I did not write the patch, Antti did, I just made it compile for 0.32.6. Original source is https://bel.fi/alankila/lcd/alpcor.html)
I think the consensus is that this is not a freetype bug. If you use qt-5 (KDE) you can get nice alpha blended fonts if you set QPlatformIntegration::FontSmoothingGamma to 1.8. diff --git a/src/plugins/platforms/xcb/qxcbintegration.cpp b/src/plugins/platforms/xcb/qxcbintegration.cpp index 258359d20f28..8181aeaf5c8b 100644 --- a/src/plugins/platforms/xcb/qxcbintegration.cpp +++ b/src/plugins/platforms/xcb/qxcbintegration.cpp @@ -357,7 +357,7 @@ QVariant QXcbIntegration::styleHint(QPlatformIntegration::StyleHint hint) const break; // Not implemented, use defaults case QPlatformIntegration::FontSmoothingGamma: // Match Qt 4.8 text rendering, and rendering of other X11 toolkits. - return qreal(1.0); + return qreal(1.8); case QPlatformIntegration::StartDragDistance: { // The default (in QPlatformTheme::defaultThemeHint) is 10 pixels, but // on a high-resolution screen it makes sense to increase it. Similarly for Chromium you can get alpha blended fonts with a simple patch: diff --git a/include/core/SkPostConfig.h b/include/core/SkPostConfig.h index d08f68a1d91c..97fec8b47826 100644 --- a/include/core/SkPostConfig.h +++ b/include/core/SkPostConfig.h @@ -389,12 +389,9 @@ ////////////////////////////////////////////////////////////////////// -#if defined(SK_GAMMA_EXPONENT) && defined(SK_GAMMA_SRGB) -# error "cannot define both SK_GAMMA_EXPONENT and SK_GAMMA_SRGB" -#elif defined(SK_GAMMA_SRGB) -# define SK_GAMMA_EXPONENT (0.0f) -#elif !defined(SK_GAMMA_EXPONENT) -# define SK_GAMMA_EXPONENT (2.2f) -#endif +#undef SK_GAMMA_EXPONENT +#undef SK_GAMMA_CONTRAST +# define SK_GAMMA_EXPONENT (1.8f) +# define SK_GAMMA_CONTRAST (0.0f) #endif // SkPostConfig_DEFINED The reason this is not the default is because most people use crappy TrueType fonts. And for them a gamma of 1.8 will make look fonts too light. You really have to use freetype's new CFF engine to get good results.
Forgot to mention the Chromium patch needs to be applied in: chromium/src/third_party/skia
-- GitLab Migration Automatic Message -- This bug has been migrated to freedesktop.org's GitLab instance and has been closed from further activity. You can subscribe and participate further through the new bug through this link to our GitLab instance: https://gitlab.freedesktop.org/cairo/cairo/issues/2.
Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.