Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

[Impeller] Switch to nearest sampling for the text atlas #39104

Merged
merged 1 commit into from
Jan 25, 2023

Conversation

bdero
Copy link
Member

@bdero bdero commented Jan 24, 2023

Resolves flutter/flutter#118613.

  • Remove residual position offsets. These were used to help mitigate the infamous glyph overlap problem, which has since been solved.
  • Always pixel snap the source position.
  • Switch from linear sampling to nearest sampling.

Before (top), after (bottom):
Screenshot 2023-01-24 at 12 21 11 PM

Before:
Screen Shot 2023-01-24 at 12 14 44 PM

After:
Screen Shot 2023-01-24 at 12 17 31 PM

@bdero bdero self-assigned this Jan 24, 2023
@flutter-dashboard
Copy link

It looks like this pull request may not have tests. Please make sure to add tests before merging. If you need an exemption to this rule, contact Hixie on the #hackers channel in Chat (don't just cc him here, he won't see it! He's on Discord!).

If you are not sure if you need tests, consider this rule of thumb: the purpose of a test is to make sure someone doesn't accidentally revert the fix. Ask yourself, is there anything in your PR that you feel it is important we not accidentally revert back to how it was before your fix?

Reviewers: Read the Tree Hygiene page and make sure this patch meets those guidelines before LGTMing.

@bdero
Copy link
Member Author

bdero commented Jan 24, 2023

Unfortunately, given the nature of using an atlas, rotated text still looks crunchy.

image

There are a number of solutions that come to mind. Pick your poison. ;)

  • Easiest solution: Turn on linear sampling whenever the transform contains stuff other than a translation. Downside: Text is slightly blurry when rotated.
  • Render larger glyphs to the atlas and scale them down. Downside: We 4x the atlas area.
  • Render the fully transformed glyphs to the atlas. Downside: Reduced cacheability of atlases.

@jonahwilliams
Copy link
Member

I have some thoughts!

Easiest solution: Turn on linear sampling whenever the transform contains stuff other than a translation. Downside: Text is slightly blurry when rotated.

This seems like a good approach at least for now, though hopefully this doesn't need to be done for all text? I'm assuming this won't make us any worse off than we are today.

Render larger glyphs to the atlas and scale them down. Downside: We 4x the atlas area.

I'd be really skeptical about any sort of supersampling techniques. Populating the glyph atlas is already very expensive, I'd actually be less worried about the memory usage.

Render the fully transformed glyphs to the atlas. Downside: Reduced cacheability of atlases.

Since rotated text is actually quite rare, I don't think this would be the worst thing. Though we'd go through a lot of churn in the cases where this is animated. You might want something like incremental appends first : #38253

There are a few places in the framework where this happens, like the cupertino picker thingy.

Separately:

  • Does rendering rotated text work better if we're using a signed distance field approach?
  • What does Skia do?

Copy link
Member

@chinmaygarde chinmaygarde left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Turn on linear sampling whenever the transform contains stuff other than a translation.

This seems like the best solution for now. But I'd be curious to see what the Skia behavior is (after we land this).

Does rendering rotated text work better if we're using a signed distance field approach?

We'll have more options but not all text can be rendered using SDF.

@@ -26,7 +26,8 @@ void main() {
gl_Position = IPPositionForGlyphPosition(
frame_info.mvp, unit_position, destination_position, destination_size);
v_unit_position = unit_position;
v_source_position = source_position;
// Pixel snap the source (sampling) start position.
v_source_position = round(source_position);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be floor instead of round?

Eh, nevermind.

@jonahwilliams
Copy link
Member

Right, bitmap emojis and colr fonts.

@bdero
Copy link
Member Author

bdero commented Jan 24, 2023

This seems like a good approach at least for now, though hopefully this doesn't need to be done for all text? I'm assuming this won't make us any worse off than we are today.

SGTM, throwing together a solution for this in a follow-up. We can avoid doing this whenever text is scale/translation only, which is the most common case.

Does rendering rotated text work better if we're using a signed distance field approach?

Yes. For SDF-based rendering, we would linear sample the distance from the SDF glyph to determine if we're inside/outside the shape + perform AA ourselves based on the distance. This problem only exists if the AA is pre-rendered by something else and we need to somewhat preserve it. (On this note, we could also turn off AA to lessen the blurriness being added by the non-pixel aligned linear sampling, but this would still have oscillating crunchiness that weaves in an out with the pixel alignment)

What does Skia do?

I'm not sure if Skia caches things to intermediary atlases and/or SDFs, but what I do know for sure is that it must either path render or generate an SDF as a first step for TTFs, since TTF glyphs are just paths!

If it happens to cache path-rendered non-SDF glyphs (which I doubt), then option 3 would seem likely. But then again, it could be doing AA post-op..

@bdero bdero merged commit 5405f2c into flutter:main Jan 25, 2023
auto-submit bot pushed a commit to flutter/flutter that referenced this pull request Jan 25, 2023
…119095)

* 6aa30b294 Roll Skia from 1bc48bcb1201 to b72fececbdcc (14 revisions) (flutter/engine#39108)

* 5405f2c26 [Impeller] Switch to nearest sampling for the text atlas (flutter/engine#39104)
ricardoamador pushed a commit to ricardoamador/engine that referenced this pull request Jan 25, 2023
zanderso pushed a commit to zanderso/engine that referenced this pull request Jan 26, 2023
XilaiZhang pushed a commit that referenced this pull request Jan 31, 2023
* [Impeller] Switch to nearest sampling for the text atlas (#39104)

* [Impeller] Linear sample atlas glyphs when the CTM isn't translation/scale only (#39112)

---------

Co-authored-by: Brandon DeRosier <[email protected]>
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
No open projects
Archived in project
Development

Successfully merging this pull request may close these issues.

[Impeller] fonts are blurry
3 participants