Repository: flutter
Issue: [engine] WebUI engine's TextLayoutService doesn't handle TextAlign.justify correctly for Chinese text
Labels: engine,a: internationalization,a: typography,platform-web,P2,team-web,triaged-web

### Steps to reproduce

Test this widget:
```dart
class Test extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // return CustomPaint(painter: _TestPainter(), child: Container());
    final str = '你好世界你好世界你好世界你好世界啦啦啦啦哈哈哈哈哈哈';
    return Padding(
        padding: EdgeInsets.symmetric(horizontal: 20, vertical: 30),
        child: Container(
          decoration: BoxDecoration(border: Border.all(color: Colors.red)),
          child: Text(str,
              style: TextStyle(fontSize: 50), textAlign: TextAlign.justify),
        ));
  }
}
```

And I just checked the webui engine.
I think the problem is because of:

https://github.com/flutter/engine/blob/a1994d326c83751b504481f0399d5f3622faf7e5/lib/web_ui/lib/src/engine/text/layout_service.dart#L184
and
https://github.com/flutter/engine/blob/dd8840d74d8b713549949861f8b3ec6a02787e14/lib/web_ui/lib/src/engine/text/layout_fragmenter.dart#L339
Quote:
```dart
  /// Adjust the width of this fragment for paragraph justification.
  void justifyTo({required double paragraphWidth}) {
    // Only justify this fragment if it's not a trailing space in the line.
    if (end > line.endIndex - line.trailingSpaces) {
      // Don't justify fragments that are part of trailing spaces of the line.
      return;
    }

    if (trailingSpaces == 0) {
      // If this fragment has no spaces, there's nothing to justify.
      return;
    }

    final double justificationTotal = paragraphWidth - line.width;
    final double justificationPerSpace = justificationTotal / line.nonTrailingSpaces;
    _extraWidthForJustification = justificationPerSpace * trailingSpaces;
  }
```

The above codes adjust the spaces between fragments, which is correct for English words which are separated by spaces.
However, Chinese words in sentences are rarely separated by spaces, so the code ends here:
```dart
    if (trailingSpaces == 0) {
      // If this fragment has no spaces, there's nothing to justify.
      return;
    }
```
**So when laying out Chinese paragraph, TextAlign.justify is the same as TextAlign.left in ltr direction. Please check the image below.**

And I think there's a simple solution to this: every fragment should be treated as having at least one traling space except for the last fragment in each lines.

### Expected results

macOS result:
<img width="485" alt="截屏2024-05-16 22 46 51" src="https://github.com/flutter/flutter/assets/23557738/7f98c28d-7d13-4d73-aa51-784dcb704677">


### Actual results

Chrome result:
<img width="332" alt="截屏2024-05-16 22 44 28" src="https://github.com/flutter/flutter/assets/23557738/20544ca3-353a-4bfd-b966-2f944191a729">

### Code sample

Test this widget:
```dart
class Test extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // return CustomPaint(painter: _TestPainter(), child: Container());
    final str = '你好世界你好世界你好世界你好世界啦啦啦啦哈哈哈哈哈哈';
    return Padding(
        padding: EdgeInsets.symmetric(horizontal: 20, vertical: 30),
        child: Container(
          decoration: BoxDecoration(border: Border.all(color: Colors.red)),
          child: Text(str,
              style: TextStyle(fontSize: 50), textAlign: TextAlign.justify),
        ));
  }
}
```


### Screenshots or Video

_No response_

### Logs

_No response_

### Flutter Doctor output

<details open><summary>Doctor output</summary>

```console
[✓] Flutter (Channel stable, 3.19.6, on macOS 14.4.1 23E224 darwin-x64, locale
    zh-Hans-CN)
    • Flutter version 3.19.6 on channel stable at /Users/lai/sdk/flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision 54e66469a9 (4 weeks ago), 2024-04-17 13:08:03 -0700
    • Engine revision c4cd48e186
    • Dart version 3.3.4
    • DevTools version 2.31.1

[✗] Android toolchain - develop for Android devices
    ✗ Unable to locate Android SDK.
      Install Android Studio from:
      https://developer.android.com/studio/index.html
      On first launch it will assist you in installing the Android SDK
      components.
      (or visit https://flutter.dev/docs/get-started/install/macos#android-setup
      for detailed instructions).
      If the Android SDK has been installed to a custom location, please use
      `flutter config --android-sdk` to update to that location.


[✓] Xcode - develop for iOS and macOS (Xcode 15.2)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Build 15C500b
    • CocoaPods version 1.14.3

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[!] Android Studio (not installed)
    • Android Studio not found; download from
      https://developer.android.com/studio/index.html
      (or visit https://flutter.dev/docs/get-started/install/macos#android-setup
      for detailed instructions).

[✓] VS Code (version 1.89.1)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.88.0

[✓] Proxy Configuration
    • HTTP_PROXY is set
    • NO_PROXY is
      192.168.0.0/16,10.0.0.0/8,172.16.0.0/12,127.0.0.1,localhost,*.local,::1,ti
      mestamp.apple.com,sequoia.apple.com,seed-sequoia.siri.apple.com
    • NO_PROXY contains localhost
    • NO_PROXY contains 127.0.0.1
    • NO_PROXY contains ::1

[✓] Connected device (3 available)
    • la iPhone (mobile) • 00008110-000C5C893A00401E • ios            • iOS
      17.2.1 21C66
    • macOS (desktop)    • macos                     • darwin-x64     • macOS
      14.4.1 23E224 darwin-x64
    • Chrome (web)       • chrome                    • web-javascript • Google
      Chrome 124.0.6367.209

[✓] Network resources
    • All expected network resources are available.

! Doctor found issues in 2 categories.
```

</details>