Open Bug 1509424 Opened 6 years ago Updated 2 years ago

Consider storing gfxShapedText offsets in device pixels instead of app units

Categories

(Core :: Layout: Text and Fonts, enhancement, P3)

enhancement

Tracking

()

People

(Reporter: jrmuizel, Unassigned)

References

(Blocks 1 open bug)

Details

Currently, it looks like we multiple the results of shaping by AppUnitsPerDevPixel and then multiply it again by 1/AppUnitsPerDevPixel when drawing. It seems like we should be able to just take out both of these multiplies.
Component: Graphics: Text → Layout: Text and Fonts
Blocks: 1509158
Jonathan, can you think of any reason not to do this?
Flags: needinfo?(jfkthame)
Are you referring only to the "offsets" (DetailedGlyph::mOffset) used when shaping applies fine adjustments to glyph positions, or more generally to all the glyph advances? Redefining DetailedGlyph::mOffset as being in device pixels would be fine, although as we do quite a bit of processing of glyph positions in appUnits, mixing appUnit advances with devicePixel offsets might be confusing. Converting glyph positioning (both offsets and advances) fully to device pixels sounds much more attractive, but this would be trickier because we depend on usually being able to pack the advance (as an integer number of appUnits) into a 12-bit field within the CompressedGlyph record. If we switch to device pixels, it'll no longer be an integer, so we'll need to re-think how we pack there. We don't want to lose the ability to pack a glyphId, advance, and a few flags into a single 32-bit word for simple text at "normal" sizes.
Flags: needinfo?(jfkthame)
Ah, I misunderstood how the DetailedGlyph/CompressedGlyph stuff worked. I'll think about things more.
A few thoughts: Storing advances as integer appUnit values means that they have a precision of 1/60 CSS px (for un-zoomed content), and the advance can be up to 68px before we have to use an auxiliary DetailedGlyph record (for simple text, in the absence of other shaping complications such as ligatures or x/y-offset positioning). The idea being to optimize the precision/footprint tradeoff for the bulk of text on the web. If we switched to storing them in device pixels, and used a fixed-point representation to pack the value into the 12-bit field in CompressedGlyph, the resulting precision would become dependent on the devicePixelRatio in effect: we'd end up with potentially less-precise measurement when devPixRatio is small, and/or we'd need to switch to DetailedGlyph records at a smaller advance when devPixRatio is large. Neither of these seem desirable effects. I wonder, though, if there's another option: we could store advances (and offsets) as em-relative (font-size-relative) values, with (say) 12 bits of fractional precision. This would allow an advance of up to 1em to be stored directly in the CompressedGlyph -- and in practice, the vast majority of glyphs have an advance much smaller than 1em. The resulting precision (in terms of CSS px) would degrade as font-size increases, but 12 fractional bits would mean that even at a font-size of 1000px, we'd have quarter-px precision, or half a device pixel on a retina screen, which at such a huge font size ought to be good enough. At realistic web-page sizes, the accuracy should be plenty. In some cases this might even let us shared shaped words across different font sizes (depending whether there's size-dependent stuff like optical sizing, tracking, or hinting going on), if we can reliably identify cases where the shaping is size-independent.
Priority: -- → P3
Severity: normal → S3
You need to log in before you can comment on or make changes to this bug.