[cairo] glyph extents
Behdad Esfahbod
behdad at behdad.org
Tue Mar 17 10:51:20 PDT 2009
Hi Jonathan,
Sorry to jump in the game this late. I read the comments on the mozilla bug
and I agree with pretty much everything you and roc said there. To clarify,
cairo's (and pango's) ink extents are supposed to be the tight bounding box of
all areas affected by the operation. So your patch is fixing one bug
(not-inclusive box) with another (not-tight), but I'm happy enough with it, so
you should feel free to push that in master (or have Vlad or Jeff do if you
don't have access).
Now I new our text extents are kind of a mess and have been thinking about it
for a while. For example, we may use the same scaled font for raster and
vector backends. Clearly it doesn't make any sense to consider filter effects
into extents used with a vector backend. Perhaps the easiest way to
differentiate those cases is to check whether metrics-hinting is enabled. So:
* If metrics-hinting is enabled, the returned extents are the user-space
tight bounding box of all the pixels affected by the glyph raster,
* If metrics-hinting is disabled, the returned extents are the user-space
tight bounding box of the glyph path. The glyph path may have been modified
as a result of hinting, but that's a separate issue.
Now if MathML is (ab)using ink extents in its heuristics, that's another
issue. The MathML code can try to turn subpixel off, or paint the glyph to an
A1 or A8 surface and compute the tight perceived bounding box itself, etc.
That's really the heuristic's concern.
Cheers,
behdad
On 02/16/2009 10:54 AM, Jonathan Kew wrote:
> I'd like to ask for clarification of the glyph extents returned by
> cairo_scaled_font_glyph_extents() (and related APIs that are relying on
> the same font data). There is an issue here for the Windows back-end
> that leads to poor visual results in certain situations.
>
> The Cairo documentation says that:
>
> The extents describe a user-space rectangle that encloses the
> "inked" portion of the glyphs, (as they would be drawn by
> cairo_show_glyphs() if the cairo graphics state were set to
> the same font_face, font_matrix, ctm, and font_options as
> scaled_font).
>
> It seems to me that the meaning of "inked" is a little unclear in the
> presence of antialiasing, especially at a subpixel level -- does it mean
> the area that a user perceives as the "solid ink" of the glyph, or does
> it mean every pixel that is touched in any way by drawing the glyph? The
> difference can be quite significant, especially on Windows with
> ClearType enabled.
>
> The attached image shows some text (enlarged to make the pixels clearly
> visible) rendered through Cairo on Vista with no smoothing, with
> "standard" font smoothing, and with ClearType. Consider what the glyph
> extents of the initial "f" should be, for example.
>
> In the first case, the "inked" portion of the "f" is obviously 4 pixels
> wide, from (0,0) to (4,9) relative to the origin at which the glyph was
> drawn (where co-ordinates refer to the "grid lines" between pixels, not
> to the pixels themselves).
>
> In the second case, with standard font smoothing, the inked area of the
> "f" is still 4 pixels wide (although note that other glyphs have changed
> their inked extents).
>
> In the third case, with ClearType, note how many more pixels have been
> touched. There is a yellow pixel to the left of the crossbar of the "f",
> so its inked area now begins at (-1,0); not quite so obvious is that it
> also extends one pixel further right at the top, contributing a slight
> blue tint to the otherwise yellow antialiasing of the "i". (This faint
> blue pixel from the "f" can be seen clearly on the subsequent
> occurrences.) So the ClearType "f" touches pixels within the area (-1,0)
> to (5,9), two pixels wider than its non-ClearType counterpart. The "x"
> has similarly extended from 5 to 7 pixels wide, the "i" and "l" from 1
> to 3, and the "e" from 4 to 6.
>
> The problem we have is that on Windows, the "black box" returned in the
> GLYPHMETRICS structure by GetGlyphOutlineW, which provides the basis for
> Cairo's glyph extents, does NOT take account of these ClearType pixels
> that "bleed" beyond what we might call the "visual" ink rect. This means
> that the glyph extents Cairo uses and returns to callers do not actually
> include every pixel that is touched by painting the glyph.
>
> This leads to problems when the glyph extents are used as a basis for
> clipping a drawing operation, for example, or for invalidating an area
> where text has been changed. We are seeing visual bugs in Firefox
> (clipped text drawing, and residual visual artifacts when text moves or
> changes) as a direct result of this issue.
>
> https://bugzilla.mozilla.org/show_bug.cgi?id=445087 (clipped drawing
> occurs within Cairo)
> https://bugzilla.mozilla.org/show_bug.cgi?id=475968 (antialiasing
> artifacts left on screen)
>
> The first of these reports has a small standalone Cairo/Windows test
> program that demonstrates the issue:
> https://bug445087.bugzilla.mozilla.org/attachment.cgi?id=359255
> along with a screenshot showing the results:
> https://bug445087.bugzilla.mozilla.org/attachment.cgi?id=359258
>
> To resolve this, we'd like to patch the Cairo win32 font backend to add
> pixels on each side of the "black box" rect returned by GDI, so that the
> glyph extents Cairo is using will include the potential ClearType
> smoothing pixels; see attached patch. A question is whether this
> "padding" of the glyph box should be done in all cases, or only when
> ClearType is enabled. The latter might seem more correct, but on the
> other hand this means that glyph extents would change on the fly if the
> user (or application) changes the font smoothing settings; this might
> not be desirable.
>
> It is also true that this patch will give extents that will sometimes be
> larger than strictly necessary. I think this is fairly innocuous; the
> effect will be that we do a little more redrawing than is actually
> needed, but that is vastly preferable to redrawing too little!
> Unfortunately, there does not appear to be any way to get "true" ink
> extents from Windows unless we were to actually paint the glyphs to a
> surface and then examine the pixels to see which ones have been colored,
> which would clearly be way too expensive for this purpose.
>
> If the Cairo team feels that we should not be messing with the metrics
> returned by Windows, but allow those to remain "visual ink" extents
> rather than true "every touched pixel" extents, then it will be
> necessary to patch in a number of other places instead (both within and
> outside Cairo) to add the equivalent padding when these extents are
> used. (See the "alternative" patch at mozilla bug 445087 for one example
> of this, where the code in cairo-surface-fallback.c uses glyph extents
> to clip a text painting operation.)
>
> Could this patch (or another solution to the issue) possibly go into
> 1.10? That would be really helpful to us.
> - Jonathan
>
>
>
>
>
> ------------------------------------------------------------------------
>
> _______________________________________________
> cairo mailing list
> cairo at cairographics.org
> http://lists.cairographics.org/mailman/listinfo/cairo
More information about the cairo
mailing list