Skip to content

[web] Refactor webparagraph painters to separate CK properly#186684

Merged
auto-submit[bot] merged 3 commits into
flutter:masterfrom
mdebbar:webpargraph_painter
May 20, 2026
Merged

[web] Refactor webparagraph painters to separate CK properly#186684
auto-submit[bot] merged 3 commits into
flutter:masterfrom
mdebbar:webpargraph_painter

Conversation

@mdebbar

@mdebbar mdebbar commented May 18, 2026

Copy link
Copy Markdown
Contributor
  • Unify under one Painter class.
  • Move CanvasKitPainter to the canvaskit/ folder.
  • Create the entry point for a future SkwasmPainter.
  • Move decoration logic to a different file (it'll probably be deleted later).
  • Always draw background because it's not cached in the paragraph image.
  • Change the bytesPerRow parameter from double to int.

Part of #172561

@mdebbar mdebbar requested a review from Rusino May 18, 2026 15:34
@flutter-dashboard flutter-dashboard Bot added the CICD Run CI/CD label May 18, 2026
@flutter-dashboard

Copy link
Copy Markdown

It looks like this pull request may not have tests. Please make sure to add tests or get an explicit test exemption before merging.

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. If you believe this PR qualifies for a test exemption, contact "@test-exemption-reviewer" in the #hackers channel in Discord (don't just cc them here, they won't see it!). 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.

@github-actions github-actions Bot added engine flutter/engine related. See also e: labels. platform-web Web applications specifically labels May 18, 2026

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request refactors the web paragraph painting architecture by introducing the WebParagraphPainter abstraction and moving decoration logic to a specialized painter. It updates the CanvasKit API to use integer values for row bytes and implements a caching mechanism for paragraph images. Review feedback highlights a coordinate system mismatch in decoration painting, a naming convention violation for constants, and the need for safer handling of null styles, empty dimensions, and buffer conversions.

ui.Offset(line.advance.left + line.formattingShift, line.advance.top),
);
// TODO(jlavrova): Implement decorations entirely on ui.Canvas
DomCanvasDecorationPainter.fillDecorations(_paintContext, block, sourceRect);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

high

There is a coordinate system mismatch here. sourceRect is calculated in physical pixels (scaled by DPR), but _paintContext has already been scaled by DPR in _resizePaintCanvas. Passing sourceRect to fillDecorations will result in double-scaling of the decoration dimensions because fillDecorations uses the rect width/height directly for drawing. You should pass a rectangle in logical pixels instead.

Suggested change
DomCanvasDecorationPainter.fillDecorations(_paintContext, block, sourceRect);
DomCanvasDecorationPainter.fillDecorations(_paintContext, block, ui.Rect.fromLTWH(0, 0, targetRect.width, targetRect.height));


final double thickness = _calculateThickness(block.style);

const DoubleDecorationSpacing = 3.0;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

The constant DoubleDecorationSpacing should follow the Dart naming convention for local constants, which is lowerCamelCase. Using UpperCamelCase makes it look like a class or type name.

References
  1. Effective Dart: Style recommends using lowerCamelCase for constant names. (link)

paintContext.lineWidth = thickness;
paintContext.strokeStyle = block.style.decorationColor!.toCssString();

switch (block.style.decorationStyle!) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

The force unwrap block.style.decorationStyle! is potentially unsafe if decorationStyle is null. It's better to provide a default value, such as ui.TextDecorationStyle.solid.

Suggested change
switch (block.style.decorationStyle!) {
switch (block.style.decorationStyle ?? ui.TextDecorationStyle.solid) {

layout,
offset,
ui.window.devicePixelRatio,
);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

If the paragraph is empty or has zero width/height, sourceRect will be empty. Calling getImageData with zero dimensions on a 2D context will throw an IndexSizeError. It's safer to check if the rectangle is empty before proceeding with painting.

Suggested change
);
);
if (sourceRect.isEmpty) {
return;
}

sourceRect.width.ceil(),
sourceRect.height.ceil(),
);
return imageData.data.buffer.asUint8List();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

When converting Uint8ClampedList to Uint8List via the buffer, it is safer to specify the offset and length to ensure you are viewing the correct portion of the buffer, even if getImageData currently returns a fresh buffer.

Suggested change
return imageData.data.buffer.asUint8List();
return imageData.data.buffer.asUint8List(imageData.data.offsetInBytes, imageData.data.lengthInBytes);

Rusino
Rusino previously approved these changes May 18, 2026
@github-actions github-actions Bot removed the CICD Run CI/CD label May 19, 2026
@mdebbar mdebbar added the CICD Run CI/CD label May 19, 2026
@github-actions github-actions Bot removed the CICD Run CI/CD label May 19, 2026
@mdebbar mdebbar added the CICD Run CI/CD label May 19, 2026
@flutter-dashboard

Copy link
Copy Markdown

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.

For more guidance, visit Writing a golden file test for package:flutter.

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

Changes reported for pull request #186684 at sha 988b794

@flutter-dashboard flutter-dashboard Bot added the will affect goldens Changes to golden files label May 19, 2026
@mdebbar mdebbar added the autosubmit Merge PR when tree becomes green via auto submit App label May 19, 2026
@mdebbar mdebbar requested a review from Rusino May 20, 2026 01:36
@auto-submit auto-submit Bot added this pull request to the merge queue May 20, 2026
Merged via the queue into flutter:master with commit 06a22c5 May 20, 2026
204 of 205 checks passed
@flutter-dashboard flutter-dashboard Bot removed the autosubmit Merge PR when tree becomes green via auto submit App label May 20, 2026
@mdebbar mdebbar deleted the webpargraph_painter branch May 20, 2026 16:37
auto-submit Bot pushed a commit to flutter/packages that referenced this pull request May 20, 2026
flutter/flutter@259aeae...e03b91f

2026-05-20 engine-flutter-autoroll@skia.org Roll Packages from ade10ca to 1dfbada (6 revisions) (flutter/flutter#186811)
2026-05-20 brunocorona.alcantar@gmail.com Fix AnimatedList.separated assert when removing last item mid-removal… (flutter/flutter#186389)
2026-05-20 engine-flutter-autoroll@skia.org Roll Skia from d45969a5752e to 5f4f454b9662 (2 revisions) (flutter/flutter#186809)
2026-05-20 engine-flutter-autoroll@skia.org Roll Fuchsia Linux SDK from -F9Ci3Opxt06MixDl... to iKCvaD58jKStYGla0... (flutter/flutter#186796)
2026-05-20 engine-flutter-autoroll@skia.org Roll Skia from 19ad9707e5c6 to d45969a5752e (2 revisions) (flutter/flutter#186792)
2026-05-20 engine-flutter-autoroll@skia.org Roll Skia from 3471ebf5af0c to 19ad9707e5c6 (9 revisions) (flutter/flutter#186772)
2026-05-20 mdebbar@google.com [web] Refactor webparagraph painters to separate CK properly (flutter/flutter#186684)
2026-05-19 31859944+LongCatIsLooong@users.noreply.github.com Enable Swift testing in the iOS embedder (flutter/flutter#185712)
2026-05-19 mdebbar@google.com [web] Rename WebParagraph goldens (flutter/flutter#186680)
2026-05-19 engine-flutter-autoroll@skia.org Roll Skia from f1b406860c5e to 3471ebf5af0c (5 revisions) (flutter/flutter#186745)
2026-05-19 154381524+flutteractionsbot@users.noreply.github.com Revert "Ship gen_snapshot for linux-arm64 hosts targeting Android" (flutter/flutter#186693)
2026-05-19 bkonyi@google.com [ Tool ] Remove legacy analytics code (flutter/flutter#184994)
2026-05-19 chingjun@google.com Update Vulkan enum values (flutter/flutter#186694)
2026-05-19 1961493+harryterkelsen@users.noreply.github.com fix(web): Fixes CSS override detection when the browser has a default font size (flutter/flutter#186474)
2026-05-19 30870216+gaaclarke@users.noreply.github.com adds linux impeller hello world integration test (flutter/flutter#186715)
2026-05-19 jason-simmons@users.noreply.github.com Update the list of binaries in the code signing verification test to include new Dart snapshots (flutter/flutter#186754)
2026-05-19 brunocorona.alcantar@gmail.com Make EdgeDraggingAutoScroller respect ScrollPhysics (flutter/flutter#186541)
2026-05-19 bkonyi@google.com [ Widget Preview ] Fix inspector split resize focus loss over WebViews (flutter/flutter#186432)
2026-05-19 engine-flutter-autoroll@skia.org Roll Packages from b9bdd37 to ade10ca (1 revision) (flutter/flutter#186746)
2026-05-19 jason-simmons@users.noreply.github.com Manual Dart roll from 8e30b88e4d5a to 66873d2da857 (flutter/flutter#186690)
2026-05-19 bkonyi@google.com [ Widget Preview ] Improve zoom behavior and add zoom slider (flutter/flutter#186422)

If this roll has caused a breakage, revert this CL and stop the roller
using the controls here:
https://autoroll.skia.org/r/flutter-packages
Please CC stuartmorgan@google.com on the revert to ensure that a human
is aware of the problem.

To file a bug in Packages: 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
matthewhendrix pushed a commit to matthewhendrix/flutter that referenced this pull request May 23, 2026
…#186684)

- Unify under one `Painter` class.
- Move `CanvasKitPainter` to the `canvaskit/` folder.
- Create the entry point for a future `SkwasmPainter`.
- Move decoration logic to a different file (it'll probably be deleted
later).
- Always draw background because it's not cached in the paragraph image.
- Change the `bytesPerRow` parameter from `double` to `int`.

Part of flutter#172561
creatorpiyush pushed a commit to creatorpiyush/packages that referenced this pull request Jun 10, 2026
…r#11747)

flutter/flutter@259aeae...e03b91f

2026-05-20 engine-flutter-autoroll@skia.org Roll Packages from ade10ca to 1dfbada (6 revisions) (flutter/flutter#186811)
2026-05-20 brunocorona.alcantar@gmail.com Fix AnimatedList.separated assert when removing last item mid-removal… (flutter/flutter#186389)
2026-05-20 engine-flutter-autoroll@skia.org Roll Skia from d45969a5752e to 5f4f454b9662 (2 revisions) (flutter/flutter#186809)
2026-05-20 engine-flutter-autoroll@skia.org Roll Fuchsia Linux SDK from -F9Ci3Opxt06MixDl... to iKCvaD58jKStYGla0... (flutter/flutter#186796)
2026-05-20 engine-flutter-autoroll@skia.org Roll Skia from 19ad9707e5c6 to d45969a5752e (2 revisions) (flutter/flutter#186792)
2026-05-20 engine-flutter-autoroll@skia.org Roll Skia from 3471ebf5af0c to 19ad9707e5c6 (9 revisions) (flutter/flutter#186772)
2026-05-20 mdebbar@google.com [web] Refactor webparagraph painters to separate CK properly (flutter/flutter#186684)
2026-05-19 31859944+LongCatIsLooong@users.noreply.github.com Enable Swift testing in the iOS embedder (flutter/flutter#185712)
2026-05-19 mdebbar@google.com [web] Rename WebParagraph goldens (flutter/flutter#186680)
2026-05-19 engine-flutter-autoroll@skia.org Roll Skia from f1b406860c5e to 3471ebf5af0c (5 revisions) (flutter/flutter#186745)
2026-05-19 154381524+flutteractionsbot@users.noreply.github.com Revert "Ship gen_snapshot for linux-arm64 hosts targeting Android" (flutter/flutter#186693)
2026-05-19 bkonyi@google.com [ Tool ] Remove legacy analytics code (flutter/flutter#184994)
2026-05-19 chingjun@google.com Update Vulkan enum values (flutter/flutter#186694)
2026-05-19 1961493+harryterkelsen@users.noreply.github.com fix(web): Fixes CSS override detection when the browser has a default font size (flutter/flutter#186474)
2026-05-19 30870216+gaaclarke@users.noreply.github.com adds linux impeller hello world integration test (flutter/flutter#186715)
2026-05-19 jason-simmons@users.noreply.github.com Update the list of binaries in the code signing verification test to include new Dart snapshots (flutter/flutter#186754)
2026-05-19 brunocorona.alcantar@gmail.com Make EdgeDraggingAutoScroller respect ScrollPhysics (flutter/flutter#186541)
2026-05-19 bkonyi@google.com [ Widget Preview ] Fix inspector split resize focus loss over WebViews (flutter/flutter#186432)
2026-05-19 engine-flutter-autoroll@skia.org Roll Packages from b9bdd37 to ade10ca (1 revision) (flutter/flutter#186746)
2026-05-19 jason-simmons@users.noreply.github.com Manual Dart roll from 8e30b88e4d5a to 66873d2da857 (flutter/flutter#186690)
2026-05-19 bkonyi@google.com [ Widget Preview ] Improve zoom behavior and add zoom slider (flutter/flutter#186422)

If this roll has caused a breakage, revert this CL and stop the roller
using the controls here:
https://autoroll.skia.org/r/flutter-packages
Please CC stuartmorgan@google.com on the revert to ensure that a human
is aware of the problem.

To file a bug in Packages: 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
via-guy pushed a commit to via-guy/flutter that referenced this pull request Jun 26, 2026
…#186684)

- Unify under one `Painter` class.
- Move `CanvasKitPainter` to the `canvaskit/` folder.
- Create the entry point for a future `SkwasmPainter`.
- Move decoration logic to a different file (it'll probably be deleted
later).
- Always draw background because it's not cached in the paragraph image.
- Change the `bytesPerRow` parameter from `double` to `int`.

Part of flutter#172561
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CICD Run CI/CD engine flutter/engine related. See also e: labels. platform-web Web applications specifically will affect goldens Changes to golden files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants