Repository navigation
[Android] Fix 1px edge clipping on Platform Views by preserving floating-point precision where possible and rounding otherwise instead of truncating - #190311
Conversation
… always be hidden
There was a problem hiding this comment.
Code Review
This pull request modifies the Android platform view embedder to use floating-point values instead of integers for layout and clipping bounds, preventing truncation artifacts on fractional pixel boundaries. Sizing conversions now use rounding instead of truncation, and the mutators stack has been updated to support fractional clip rects. New integration and unit tests are introduced to verify these changes. Feedback on the changes suggests adding a defensive guard in PlatformViewsController.java to prevent a potential division by zero when calculating logical pixels.
| /// The size of the platform view, in *physical* pixels. | ||
| /// | ||
| /// Deliberately not a whole number of pixels. Android view geometry is | ||
| /// integral, so the engine has to snap this to the pixel grid; if it truncates |
There was a problem hiding this comment.
nit: took me too long to realize you were using this to mean "Android view geometry uses integers". At least that what I think you're saying :)
|
autosubmit label was removed for flutter/flutter/190311, because - The status or check suite Dashboard Checks has failed. Please fix the issues identified (or deflake) before re-applying this label. |
|
autosubmit label was removed for flutter/flutter/190311, because - The status or check suite Dashboard Checks has failed. Please fix the issues identified (or deflake) before re-applying this label. |
|
autosubmit label was removed for flutter/flutter/190311, because - The status or check suite Dashboard Checks has failed. Please fix the issues identified (or deflake) before re-applying this label. |
Fixes #189834
It's kind of hard to see in the screenshots that Android studio device mirroring produces, but there's a 1px green border of the underlay box visible pre-change clearly on device. You can kind of see it if you click the screenshot and zoom in.
Golden test screenshots:
Ai description of the changes, which is accurate (i checked)
On Android devices with a fractional Device Pixel Ratio (
dpr, e.g.,2.625on 420dpi screens), converting between logical and physical pixels in floating point often yields values just below a whole integer (e.g.,1080 / 2.625 * 2.625 = 1079.999965). Previously, the C++ Engine and Java embedding truncated these values to integers (static_cast<int32_t>/(int)), systematically shaving 1 physical pixel off the right and bottom edges of Platform Views, clip rectangles, and texture buffer sizes. This left a visible 1px line of underlying background content around the view.This PR fixes precision loss across three equivalence classes in the Android Platform View composition pipeline:
1. Plumb floating-point precision where native APIs accept floats (
RectF/ MethodChannel)pushClipRectandpushClipRRectin C++ JNI (platform_view_android_jni_impl.cc) and Java (FlutterMutatorsStack.java) from integer(IIII)Vto floating-point(FFFF)V, storingRectFand passing floats directly to AndroidPath.addRect(RectF).PlatformViewBufferSizewidth/height frominttodoubleand changedtoLogicalPixels(double)in (PlatformViewsController.java) to return fractionaldoublevalues without integer casting or rounding.2. Round onto the integer grid where Android APIs require integers
DlIRect::Round(GetViewRect(...)).std::round(size_points * dpr)viaToPhysicalPixels(...).3. Sizing & Buffer Reporting by Composition Mode (PlatformViewsController.java)
request.newLogicalWidth,request.newLogicalHeight), bypassing physical-to-logical round-trip conversion entirely.double(physicalPixels / getDisplayDensity()). This allows the framework to size the texture 1:1 and clip it to the widget rather than scaling it down.Testing
PlatformViewSizeIsRoundedNotTruncatedto external_view_embedder_unittests.cc verifying that full-screen dimensions (1080x2400atdpr = 2.625) round to1080, 2400rather than1079, 2399.resizeAndroidView_reportsFractionalBufferSizeandresizeAndroidView_reportsUnshrunkBufferSizeto PlatformViewsControllerTest.java..75physical pixels (200.75unclipped,150.75clipped). Truncation deterministically exposes a 1px green outline on any device, while rounding cleanly occludes the underlay.