-
Notifications
You must be signed in to change notification settings - Fork 6k
Started filtering out close line segments in rrect polylines. #55929
Conversation
|
It looks like this pull request may not have tests. Please make sure to add tests before merging. If you need an exemption, contact "@test-exemption-reviewer" in the #hackers channel in Discord (don't just cc them here, they won't see it!). 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. The test exemption team is a small volunteer group, so all reviewers should feel empowered to ask for tests, without delegating that responsibility entirely to the test exemption group. |
jonahwilliams
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
impeller/geometry/path_builder.cc
Outdated
| } | ||
|
|
||
| void PathBuilder::AddLinearComponent(const Point& p1, const Point& p2) { | ||
| if (ScalarNearlyEqual(p1.x, p2.x) && ScalarNearlyEqual(p1.y, p2.y)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we know what the transform is? The skippable distance should take that into account for when we zoom in on a shape.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The transform doesn't matter because we are hitting the limits of the float32 format. So even if this is scaled up to be meaningful the points would be unstable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, we don't practically care about rendering correctly with a 1000000000x scale.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
.001 is nowhere near a 1000000000x scale. Scaling up by 100 can affect pixelization. Scaling by 1000 could leave a pixel gap or miss a pixel entirely.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And "the limits of float32 format" - how are you defining that? It can handle 10^(+/-37) and it can represent pixels up to +/- 16 million before it loses sub-pixel accuracy.
If you want to take float precision into account then you should use the built-in ulp-based tests.
Note that large scales aren't necessariy for large zooms. A developer could create geometry in the 0.0->1.0 coordinate space and then scale it into place. On a 4k monitor that could involve scales larger than 1000x.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
how are you defining that?
It's the standard definition for Impeller, ScalarIsNearly which uses the tolerance kEhCloseEnough which is 1e-3f. If that isn't sufficient we should consider changing kEhCloseEnough (and ScalarIsNearly).
flar
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This solution is fixing a symptom of a deeper flaw in the logic of the join procs.
edit: Nevermind, I see you added that info to the issue, let me read through it. |
flar
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried my suggested fix in the join procs and it didn't improve the situation. My guess is that the bevel join is drawing the join in the wrong direction. I still see an issue here because nearly colinear lines can have outer corners that are far apart and the join proc just lets it go, which is not appropriate.
For now, I'll withdraw my "request changes" from this PR. I still believe it is not the right solution here, but until I can nail down the issues in the join procs, I don't have any other suggestions - I just wish it was based more on the transform and the line width as tiny lines at small angles can swing widely at the outer end of their stroked representaiton...
I'll spend some time poking around in the miter join. Maybe we can tighten the epsilon here too if we land this. A scale of 1000x before seeing the difference isn't so big, 10,000x sounds more in the realm were we might omit something. |
1000 is fine if we're talking pixel distances (perhaps even too generous). If we can factor the transform in (it would only need to be computed once at the start of the operation) then we just supply that computed number as the "nearly" metric in the function (it takes a 3rd arg that defaults to kEhCloseEnough). But we also have to consider that if a bunch of really tiny lines are changing direction then the resulting widened line might have some noticeable curving to it that will look more like "spinning in place". That may be obscured by the widened parts next to it, but only if they are long enough to cover the turning of the widened pen. Any change in direction is like a person walking holding a really long ladder sideways and turning around and often the slapstick of the swinging ladder is visible outside the scene. And, if this is the only contour in the path, then we should treat it like a zero-length line and do just a giant square or circle per the cap (bevel typically does a big square even though it doesn't normally have any decoration). Lots of considerations that I think are ignored by this simple fix, but so far I don't have any more targeted fix that gets rid of those dimples. I'm still asking the question - even if only in my head - how does eliminating a segment cause the dimple to join? |
|
@flar here's a new thought I haven't explored yet. Do you think the fact the polyline is oscillating is messing it up? It goes up down up. My PR filters that out by virtue of the points being so close to eachother. I see we are calculating directions at some point in the math. |
|
I exhausted my timebox to debug the miter join. I didn't find anything. For this PR I can move the tolerance to 1e-5 which is a 100,000x scale which I think is within our acceptable limit. Some tests are failing though since there is code that banks on adding duplicate values to the path, like FillPathGeometry when representing points. We might have to pull on that thread a bit but might be well entrenched with how things work. |
|
What could be happening is that the lines are so small and their directions flip a lot and so we end up doing the miter join on the wrong side of that gap because it looks like the 2 adjacent lines are concave rather than convex? |
|
If we skip a join on one segment that is nearly colinear then that segment still becomes the basis for the join for the next line. We should probably maintain the previous segment for computing the next join? |
|
I'm switching this to just be applicable to rrect paths. I think there is probably a deeper bug in the polyline that gives it that minute squiggle in it. If it never manifests elsewhere though its probably not worth chasing down. I've added a unique interactive test for the rounded rect to verify further that this is good. (and discovered another error: flutter/flutter#157173) |
|
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. |
…157215) flutter/engine@76d310e...dd37446 2024-10-19 [email protected] Move keymap from FlKeyboardViewDelegate to FlKeyboardManager (flutter/engine#55942) 2024-10-19 [email protected] [UI] fix scene builder parameter naming. (flutter/engine#55969) 2024-10-19 [email protected] iOS: Improve thread safety of first frame callback (flutter/engine#55966) 2024-10-18 [email protected] iOS: Fix flaky tests (remove timeouts) (flutter/engine#55961) 2024-10-18 [email protected] [Impeller] allocate the impeller onscreen texture from the render target cache. (flutter/engine#55943) 2024-10-18 [email protected] Roll Fuchsia Linux SDK from 9F_NaKPd2twhbPwP7... to tNQZ8d5mRYpe3--lk... (flutter/engine#55963) 2024-10-18 [email protected] Started filtering out close line segments in rrect polylines. (flutter/engine#55929) 2024-10-18 [email protected] [Impeller] libImpeller: Allow custom font registrations. (flutter/engine#55934) 2024-10-18 [email protected] Re-reland "iOS: Migrate FlutterEngine to ARC" (flutter/engine#55962) 2024-10-18 [email protected] [Impeller] libImpeller: Add a README. (flutter/engine#55940) 2024-10-18 [email protected] iOS: Eliminate needless profiler metrics ivar (flutter/engine#55957) 2024-10-18 98614782+auto-submit[bot]@users.noreply.github.com Reverts "[Impeller] one descriptor pool per frame. (#55939)" (flutter/engine#55959) 2024-10-18 [email protected] Revert "Reland "iOS: Migrate FlutterEngine to ARC" (#55937)" (flutter/engine#55954) 2024-10-18 [email protected] Roll Dart SDK from 993d3069f42e to a51df90298ca (7 revisions) (flutter/engine#55951) 2024-10-18 [email protected] [engine] add back opt out for merged threads. (flutter/engine#55952) 2024-10-18 [email protected] [Impeller] one descriptor pool per frame. (flutter/engine#55939) 2024-10-18 [email protected] [Impeller] add mechanism for sharing bdf inputs. (flutter/engine#55701) Also rolling transitive DEPS: fuchsia/sdk/core/linux-amd64 from 9F_NaKPd2twh to tNQZ8d5mRYpe 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] 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
…r/engine#55929) fixes flutter#156422 tests: AiksTest.GradientOvalStrokeMaskBlurSigmaZero This filtering needs to happen somewheres. I opted for putting it inside of the AddLinearComponent instead of where it was affected me in the test: https://github.com/flutter/engine/blob/45237cc63f86b133d2a09574422cc0fa5216971d/impeller/geometry/path_builder.cc#L180 This seems preferable. A tiny line segment should never matter. The rub is that its only happening here. We might want to do this in other places as well. It's equally unimportant to have a tiny curve. [C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
fixes flutter/flutter#156422
tests: AiksTest.GradientOvalStrokeMaskBlurSigmaZero
This filtering needs to happen somewheres. I opted for putting it inside of the AddLinearComponent instead of where it was affected me in the test:
engine/impeller/geometry/path_builder.cc
Line 180 in 31aaaaa
This seems preferable. A tiny line segment should never matter. The rub is that its only happening here. We might want to do this in other places as well. It's equally unimportant to have a tiny curve.
Pre-launch Checklist
///).If you need help, consider asking for advice on the #hackers-new channel on Discord.