Skip to content

Add ParagraphStyle.hyphenCharacter to dart:ui - #195345

Merged
auto-submit[bot] merged 2 commits into
flutter:masterfrom
dbebawy:hyphen-character-189617
Nov 7, 2026
Merged

auto-submit[bot] merged 2 commits into
flutter:masterfrom
dbebawy:hyphen-character-189617

Conversation

@dbebawy

@dbebawy dbebawy commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

Adds hyphenCharacter to dart:ui's ParagraphStyle, so apps can choose the string drawn at the end of a line that breaks at a soft hyphen (U+00AD) instead of always "-". If it is null, "-" is drawn as before. The empty string draws nothing, and the line still breaks there.

The engine passes it to Skia's ParagraphStyle::setSoftHyphenString, which already reserves the string's width when breaking lines and includes it in selection boxes. Skwasm gets a paragraphStyle_setSoftHyphenString binding for the same call, and CanvasKit sets the softHyphenString property that rolled in with #195339.

This is the additive dart:ui part of #189617. The name and shape follow the API question there, and I am happy to change them. The framework side (TextStyle.getParagraphStyle, TextPainter, RenderParagraph, RichText and Text) is ready as a follow-up PR, along with a breaking change page for flutter/website, since a new getParagraphStyle parameter breaks classes that override it. I will open both once this lands.

WebParagraph stores the value but does not draw soft hyphens yet. #195366 adds soft hyphens there for #193506, and can use this value once both land.

Part of #189617.

Pre-launch Checklist

@github-actions github-actions Bot added a: text input Entering text in a text field or keyboard related problems engine flutter/engine related. See also e: labels. platform-web Web applications specifically team-web Owned by Web platform team labels Oct 26, 2026
@dbebawy dbebawy mentioned this pull request Oct 26, 2026
10 of 11 tasks
@dbebawy
dbebawy force-pushed the hyphen-character-189617 branch from 3a4d22a to 96ed910 Compare October 27, 2026 01:11
@dbebawy
dbebawy force-pushed the hyphen-character-189617 branch from 96ed910 to 278163b Compare November 3, 2026 18:38
@dbebawy
dbebawy marked this pull request as ready for review November 3, 2026 18:38

@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 adds support for a custom hyphenCharacter in ParagraphStyle across the Flutter engine, including the native C++ Skia implementation and the Web UI (CanvasKit, Skwasm, and HTML) backends. It also adds corresponding unit tests. The review feedback suggests a minor improvement in the Skwasm implementation to remove a redundant null-assertion operator, leveraging Dart's automatic type promotion.

Comment on lines +429 to +433
if (style.hyphenCharacter != null) {
final SkStringHandle hyphenCharacterHandle = skStringFromDartString(style.hyphenCharacter!);
paragraphStyleSetSoftHyphenString(handle, hyphenCharacterHandle);
skStringFree(hyphenCharacterHandle);
}

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

Since style.hyphenCharacter is a final field on EngineParagraphStyle, Dart's type promotion automatically promotes it to a non-nullable String inside the if block. The null-assertion operator ! on style.hyphenCharacter! is redundant and can be safely removed to improve code cleanliness and leverage Dart's type system idiomatic promotion.

Suggested change
if (style.hyphenCharacter != null) {
final SkStringHandle hyphenCharacterHandle = skStringFromDartString(style.hyphenCharacter!);
paragraphStyleSetSoftHyphenString(handle, hyphenCharacterHandle);
skStringFree(hyphenCharacterHandle);
}
if (style.hyphenCharacter != null) {
final SkStringHandle hyphenCharacterHandle = skStringFromDartString(style.hyphenCharacter);
paragraphStyleSetSoftHyphenString(handle, hyphenCharacterHandle);
skStringFree(hyphenCharacterHandle);
}
References
  1. Follow Effective Dart guidelines and idiomatic Dart style, leveraging Dart's type promotion without redundant null assertions. (link)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I think this would not compile, since hyphenCharacter is a public field from another library and Dart only promotes private final fields. I am happy to switch to a local variable like the CanvasKit path if a reviewer prefers it.

@dbebawy

dbebawy commented Nov 3, 2026

Copy link
Copy Markdown
Contributor Author

@Rusino @mdebbar This adds ParagraphStyle.hyphenCharacter to dart:ui (and the web backends) as the first part of #189617. The framework part would follow once this lands. Could one of you take a look and add CICD when you have a chance?

@gaaclarke
gaaclarke self-requested a review November 3, 2026 21:41
@dbebawy
dbebawy force-pushed the hyphen-character-189617 branch from 278163b to f622039 Compare November 3, 2026 23:04
@flutter-zl flutter-zl added the CICD Run CI/CD label Nov 4, 2026
@flutter-zl
flutter-zl requested a review from mdebbar November 4, 2026 19:19

@gaaclarke gaaclarke left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This looks good to me. I glanced over the web stuff and didn't notice anything, the second reviewer can be from the web team. I just have one request to better document the weird asserts we have in the tests.

Lets apps choose the string drawn at a soft hyphen (U+00AD) line break,
instead of always drawing "-". Native and Skwasm pass it to Skia's
ParagraphStyle::setSoftHyphenString. CanvasKit and WebParagraph store it
for now: CanvasKit gets it once its softHyphenString binding rolls in,
and WebParagraph does not draw soft hyphens yet (flutter#193506).

Part of flutter#189617.
CanvasKit's ParagraphStyle gained softHyphenString in Skia 1bd2b0627c,
which rolled into Flutter in flutter#195339. CkParagraphStyle now sets it from
ParagraphStyle.hyphenCharacter, so the hyphenCharacter test runs on
CanvasKit too.

Part of flutter#189617.
@dbebawy
dbebawy force-pushed the hyphen-character-189617 branch from f622039 to e1c6d88 Compare November 5, 2026 12:10
@flutter-dashboard flutter-dashboard Bot removed the CICD Run CI/CD label Nov 5, 2026

@gaaclarke gaaclarke left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

lgtm

@gaaclarke

Copy link
Copy Markdown
Member

@dbebawy friendly reminder, when you want someone to rereview your PR, make sure to hit the "re-request review" button next to their name

@gaaclarke gaaclarke added the CICD Run CI/CD label Nov 5, 2026

@mdebbar mdebbar 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.

Looks good to me. Thanks for contributing this!

@mdebbar mdebbar added the autosubmit Merge PR when tree becomes green via auto submit App label Nov 6, 2026
@auto-submit
auto-submit Bot added this pull request to the merge queue Nov 7, 2026
Merged via the queue into flutter:master with commit 0d7df4b Nov 7, 2026
25 checks passed
@flutter-dashboard flutter-dashboard Bot removed the autosubmit Merge PR when tree becomes green via auto submit App label Nov 7, 2026
auto-submit Bot pushed a commit to flutter/packages that referenced this pull request Nov 7, 2026
flutter/flutter@09175cd...e36b370

2026-11-07 [email protected] Roll Fuchsia Linux SDK from KIc0XZbhLmvDpTluZ... to Sf2yvdTiFXAKkfLkD... (flutter/flutter#196160)
2026-11-07 [email protected] Roll pub packages (flutter/flutter#196155)
2026-11-07 [email protected] [iOS a11y] Use a real `UIScrollView` as a11y scrollable container (flutter/flutter#195731)
2026-11-07 [email protected] Add ParagraphStyle.hyphenCharacter to dart:ui (flutter/flutter#195345)
2026-11-07 [email protected] Roll pub packages (flutter/flutter#196143)
2026-11-06 [email protected] [Linux] Fix layer position when compositing without glBlitFramebuffer (flutter/flutter#196083)
2026-11-06 [email protected] Add support for riscv64 desktop linux engine (flutter/flutter#178712)
2026-11-06 [email protected] Add ResizeImagePolicy.cover (flutter/flutter#194665)
2026-11-06 [email protected] Roll Skia from f533d4034900 to b11315d0a096 (6 revisions) (flutter/flutter#196138)
2026-11-06 [email protected] iOS: Remove dead code/unused imports from FlutterPlatformViewsController (flutter/flutter#196084)
2026-11-06 [email protected] Replace pull_request_target workflows with pull_request + workflow_run (flutter/flutter#195536)
2026-11-06 [email protected] [master] Update Flutter DEPS to Dart 3b174b7217fe09b21da836ea623932b5f041b091 (flutter/flutter#196004)
2026-11-06 [email protected] Fix android_hardware_smoke_test retry mechanisms (flutter/flutter#195708)
2026-11-06 [email protected] Roll Skia from 452b9c1e5db6 to f533d4034900 (1 revision) (flutter/flutter#196129)
2026-11-06 [email protected] [flutter_tools] Use `ErrorHandlingFileSystem.deleteIfExists` for `IOSCoreDeviceControl` temp directory cleanup (flutter/flutter#195913)
2026-11-06 [email protected] Adds guideline tests to flutter create samples (flutter/flutter#195827)
2026-11-06 [email protected] refactor(flutter_tools): unify OptionDescriptor identity and addTo (flutter/flutter#196076)
2026-11-06 [email protected] Roll pub packages (flutter/flutter#196114)
2026-11-06 [email protected] Roll Skia from 5ce64e63a0e7 to 452b9c1e5db6 (5 revisions) (flutter/flutter#196111)
2026-11-06 [email protected] Add PlatformDispatcher.onAlwaysUse24HourFormatChanged callback (flutter/flutter#194670)
2026-11-06 [email protected] Roll Packages from 0478162 to 63881f9 (10 revisions) (flutter/flutter#196108)
2026-11-06 [email protected] Roll Skia from 793b8ac73d4b to 5ce64e63a0e7 (4 revisions) (flutter/flutter#196107)

If this roll has caused a breakage, revert this CL and set the roller
to dry run mode using the controls here:
https://autoroll.skia.org/r/flutter-packages
Please CC [email protected],[email protected] 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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

a: text input Entering text in a text field or keyboard related problems CICD Run CI/CD engine flutter/engine related. See also e: labels. platform-web Web applications specifically team-web Owned by Web platform team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants