Skip to content
This repository was archived by the owner on Mar 3, 2023. It is now read-only.
This repository was archived by the owner on Mar 3, 2023. It is now read-only.

We need a better approach to text measurement #6055

@nathansobo

Description

@nathansobo

When Chrome 39 added support for subpixel font scaling, it broke our approach to horizontal position measurement. We disabled subpixel scaling with a flag, but that was only a temporary stopgap measure. The truth is our existing approach to measuring horizontal positions on screen is somewhat ill-conceived, and it needs to be changed.

The existing approach

In our existing approach, we attempt to measure the width of characters in a given context. So, for example, we can determine that the width of an a character in the .source.coffee .meta.function.coffee is 11px at the current font size. Then, when we calculate the pixel position for a given row and column, we just simply total up the recorded width for every character we encounter.

The problem is that for non fixed-width fonts, a given character doesn't have a single width. Kerning, ligatures, and other stuff the type rendering engine does can result in an a taking up different amount of space in different contexts. I am not an expert in this area yet. What's worse, when subpixel font scaling is turned on, Chrome starts reporting different widths even for fixed width fonts. We're going to need a different approach.

Idea for a better approach

My current thinking is that when calculating a pixel position, we need to explicitly measure the distance from the beginning of the line to the column in question rather than consulting our encyclopedia of character widths. This was our original approach but I moved away from it because we were naively reading the DOM whenever we needed to translate positions, which was causing reflows.

But we actually can safely read this information, so long as we do so either at the start of an update before we actually update the DOM, or at the end of an update, after we are finished updating the DOM. When simply moving the cursor, we can measure before the update. When typing, however, we need to measure after the update in order for the content to be on screen, then trigger another update based on our measurement.

We may also be able to make these measurements off-DOM, like in an iframe or something. My main concern here is making sure that we capture all the styling that's applied to the text. We may be able to draw a line at the shadow boundary, and just say the only styling that we will apply for purposes of character measurement is the syntax themes. Theme stylesheets could easily be loaded in an iframe via the atom-styles element. Or we could set up the entire world in this iframe and measure there.

Or maybe there's some other, better approach to character measurement out there that Atom should apply instead. The main requirements are as follows:

  • Measurement should not force a blocking reflow.
  • Measurement should capture user styling as seamlessly as possible.
  • Measurement should handle different widths being reported for the same character in different contexts, as is currently the case with subpixel font scaling enabled.

Can anyone from the community help out with this? Ideas are welcome if they're specific. Code would be even more helpful. @as-cii I know I'm pinging you on a ton of stuff lately but this seems right in your wheelhouse based on your recent presenter work.

/cc @atom/non-github-maintainers

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions