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

Conversation

@jonahwilliams
Copy link
Contributor

@jonahwilliams jonahwilliams commented May 25, 2024

Multiple fixes to text rendering that match skia behavior on almost all bugs I've found, except for the glyphs are still slightly too fine for some CJK text. The fixes are:

  1. Compute the gylph size in the typographer context, using text size * scale factor text, instead of computing smaller bounds and scaling it up. This was not accurate and as a result we would positon glyphs incorrect by multiple pixels sometimes, causing uneven rows.

  2. Match Skia's rounding behavior. previously we were rounding in multiple places, Skia rounds once. This is important to prevent jumping.

  3. Use 4 subpixel X positions for rendering. This is the big one that ensures the visible layout matches exactly. Adds support for Y, both, and none positioning too. I couldn't find any examples of just Y or both. Some fonts may specify that have no subpixel positioning. So we don't bother to compute it for those.

Fixes flutter/flutter#138386 / mostly, except slightly not bold enough.
Fixes flutter/flutter#147577 / mostly, except slightly not bold enough.
Fixes flutter/flutter#140475
Fixes flutter/flutter#141467
Fixes flutter/flutter#135523
Fixes flutter/flutter#127815

@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 "@test-exemption-reviewer" in the #hackers channel in Chat (don't just cc them here, they won't see it! Use 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.

@jonahwilliams jonahwilliams changed the title [Impeller] WIP use scaled font to determine bounds, match Skia position rounding behavior. [Impeller] WIP use scaled font to determine bounds, match Skia position rounding behavior, add subpixel X positioning. May 26, 2024
const auto* glyphs = run.glyphs();
switch (run.positioning()) {
case SkTextBlobRunIterator::kFull_Positioning: {
std::vector<SkRect> glyph_bounds;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

These bounds are wrong, this computation is moved into the typographer contents where the exact scale is applied to the font size.

@jonahwilliams jonahwilliams changed the title [Impeller] WIP use scaled font to determine bounds, match Skia position rounding behavior, add subpixel X positioning. [Impeller] Use scaled font to determine bounds, match Skia position rounding behavior, add subpixel X positioning. May 27, 2024
@flutter-dashboard
Copy link

Golden file changes have been found for this pull request. Click here to view and triage (e.g. because this is an intentional change).

If you are still iterating on this change and are not ready to resolve the images on the Flutter Gold dashboard, consider marking this PR as a draft pull request above. You will still be able to view image results on the dashboard, commenting will be silenced, and the check will not try to resolve itself until marked ready for review.

Changes reported for pull request #53042 at sha 051254a

@jonahwilliams
Copy link
Contributor Author

Remaining issue is that many CJK fonts have fractional Y positions too, fixing that will truly fix all issues.

@jonahwilliams
Copy link
Contributor Author

Actually its not y alignment,it is just slightly less bold. Filled flutter/flutter#149142

@jonahwilliams jonahwilliams changed the title [Impeller] Use scaled font to determine bounds, match Skia position rounding behavior, add subpixel X positioning. [Impeller] Use scaled font to determine bounds, match Skia position rounding behavior, add subpixel X/Y/All/None positioning. May 27, 2024
text_contents->SetTextFrame(text_frame);
text_contents->SetColor(paint.color);
text_contents->SetForceTextColor(paint.mask_blur_descriptor.has_value());
text_contents->SetOffset(position);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

We need to use the original offset to compute the subpixel position now.

jonahwilliams added 2 commits May 27, 2024 12:19
@flutter-dashboard
Copy link

Golden file changes are available for triage from new commit, Click here to view.

Changes reported for pull request #53042 at sha 8a08278

#include "impeller/typographer/font.h"
#include "impeller/typographer/glyph.h"

#include "include/core/SkPaint.h"
Copy link
Member

Choose a reason for hiding this comment

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

Nit: No newline here and include the third_party/skia before the include like the rest.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done


bool TextContents::CanInheritOpacity(const Entity& entity) const {
return !frame_->MaybeHasOverlapping();
return false;
Copy link
Member

Choose a reason for hiding this comment

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

Not sure I follow why this isn't true anymore. Add a comment maybe?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

comment added

switch (
strikeSpec.createScalerContext()->computeAxisAlignmentForHText()) {
case SkAxisAlignment::kNone:
// Skia calls this case none, meaning alignment in both X and Y.
Copy link
Member

Choose a reason for hiding this comment

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

Good call and thanks for documenting. Could also move it into a method AxisAlignment ToAxisAligment(SkAxixalignment align); with the requisite documentation.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

location_in_atlas.y() + height_adjustment, //
glyph_size.width, //
glyph_size.height //
location_in_atlas.x() + 1, //
Copy link
Member

Choose a reason for hiding this comment

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

I don't follow this adjustment. Perhaps a short comment? If I had to guess, perhaps to account for errors in sample locations.

Copy link
Member

Choose a reason for hiding this comment

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

I see the correction to the position later. But still not sure why?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is part of the glyph padding so that we can avoid clearing the atlas. Though I didn't check in this PR, eventually we should be able to remove the clear.

// ---------------------------------------------------------------------------
// Step 1: Determine if the atlas type and font glyph pairs are compatible
// with the current atlas and reuse if possible.
// with the current atlas and reuse if possible. Compute glyph sizes
Copy link
Member

Choose a reason for hiding this comment

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

Also comute glyph sizes.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added more details

//------------------------------------------------------------------------------
/// @brief Determines the axis along which there is subpixel positioning.
///
enum class AxisAlignment : uint8_t {
Copy link
Member

Choose a reason for hiding this comment

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

This is find of course and not suggesting this be modified. But we also have type safe masks now. So this could be mask values with a mask defined as using AxisAlignmentMask = Mask<AxisAlignment>;.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm not really using this as a Mask right now, at least I dont think. I think I could rewrite things a bit to treat axis alignment as an off or on mask for which of X/Y have subpixel positioning?

Copy link
Member

Choose a reason for hiding this comment

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

Nah, this is fine.

///
struct SubpixelGlyph {
Glyph glyph;
Point subpixel;
Copy link
Member

Choose a reason for hiding this comment

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

Perhaps subpixel_offset?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

@flutter-dashboard
Copy link

Golden file changes are available for triage from new commit, Click here to view.

Changes reported for pull request #53042 at sha 4ed6ce2

@jonahwilliams jonahwilliams added the autosubmit Merge PR when tree becomes green via auto submit App label May 28, 2024
@auto-submit auto-submit bot merged commit 9f448d3 into flutter:main May 28, 2024
@jonahwilliams jonahwilliams deleted the clamp branch May 28, 2024 06:43
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request May 28, 2024
…position rounding behavior, add subpixel X/Y/All/None positioning. (flutter/engine#53042)
auto-submit bot pushed a commit to flutter/flutter that referenced this pull request May 28, 2024
…149169)

flutter/engine@b175108...d032390

2024-05-28 [email protected] Roll Skia from 312160c7c920 to 848d9498fd68 (1 revision) (flutter/engine#53059)
2024-05-28 [email protected] [Impeller] Use scaled font to determine bounds, match Skia position rounding behavior, add subpixel X/Y/All/None positioning. (flutter/engine#53042)

If this roll has caused a breakage, revert this CL and stop the roller
using the controls here:
https://autoroll.skia.org/r/flutter-engine-flutter-autoroll
Please CC [email protected],[email protected],[email protected] on the revert to ensure that a human
is aware of the problem.

To file a bug in Flutter: https://github.com/flutter/flutter/issues/new/choose

To report a problem with the AutoRoller itself, please file a bug:
https://issues.skia.org/issues/new?component=1389291&template=1850622

Documentation for the AutoRoller is here:
https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
victorsanni pushed a commit to victorsanni/flutter that referenced this pull request May 31, 2024
…lutter#149169)

flutter/engine@b175108...d032390

2024-05-28 [email protected] Roll Skia from 312160c7c920 to 848d9498fd68 (1 revision) (flutter/engine#53059)
2024-05-28 [email protected] [Impeller] Use scaled font to determine bounds, match Skia position rounding behavior, add subpixel X/Y/All/None positioning. (flutter/engine#53042)

If this roll has caused a breakage, revert this CL and stop the roller
using the controls here:
https://autoroll.skia.org/r/flutter-engine-flutter-autoroll
Please CC [email protected],[email protected],[email protected] on the revert to ensure that a human
is aware of the problem.

To file a bug in Flutter: https://github.com/flutter/flutter/issues/new/choose

To report a problem with the AutoRoller itself, please file a bug:
https://issues.skia.org/issues/new?component=1389291&template=1850622

Documentation for the AutoRoller is here:
https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
@virskor

This comment was marked as off-topic.

@jonahwilliams

This comment was marked as off-topic.

@delfme
Copy link

delfme commented Nov 23, 2024

Thx you for these fixes! If related, it would be great if this other issue could also be addressed: flutter/flutter#120857

Currently, fontWeight is inconsistent on iOS: text appears thinner in light mode and thicker in dark mode. For instance, in light mode, a 'normal' fontWeight looks closer to 'light' than to 'normal'.

The only viable workaround we’ve found is to wrap two Text into a Stack, using the second one to apply an outer stroke that tricks the user’s eye into perceiving a native-like font weight. However, this solution requires Text.rich and results in dirt code.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

autosubmit Merge PR when tree becomes green via auto submit App e: impeller will affect goldens

Projects

None yet

4 participants