// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:async';
import 'dart:math' as math;

import 'package:test/bootstrap/browser.dart';
import 'package:test/test.dart';
import 'package:ui/src/engine.dart';
import 'package:ui/ui.dart' hide window;

import '../../common/test_initialization.dart';
import 'helper.dart';

const Rect bounds = Rect.fromLTWH(0, 0, 800, 600);

void main() {
  internalBootstrapBrowserTest(() => testMain);
}

Future<void> testMain() async {
  setUpUnitTests(
    withImplicitView: true,
    emulateTesterEnvironment: false,
    setUpTestViewDimensions: false,
  );

  test('paints spans and lines correctly', () {
    final BitmapCanvas canvas = BitmapCanvas(bounds, RenderStrategy());

    Offset offset = Offset.zero;
    CanvasParagraph paragraph;

    // Single-line multi-span.
    paragraph = rich(EngineParagraphStyle(fontFamily: 'Roboto'), (CanvasParagraphBuilder builder) {
      builder.pushStyle(EngineTextStyle.only(color: blue));
      builder.addText('Lorem ');
      builder.pushStyle(EngineTextStyle.only(
        color: green,
        background: Paint()..color = red,
      ));
      builder.addText('ipsum ');
      builder.pop();
      builder.addText('.');
    })
      ..layout(constrain(double.infinity));
    canvas.drawParagraph(paragraph, offset);
    offset = offset.translate(0, paragraph.height + 10);

    // Multi-line single-span.
    paragraph = rich(EngineParagraphStyle(fontFamily: 'Roboto'), (CanvasParagraphBuilder builder) {
      builder.addText('Lorem ipsum dolor sit');
    })
      ..layout(constrain(90.0));
    canvas.drawParagraph(paragraph, offset);
    offset = offset.translate(0, paragraph.height + 10);

    // Multi-line multi-span.
    paragraph = rich(EngineParagraphStyle(fontFamily: 'Roboto'), (CanvasParagraphBuilder builder) {
      builder.pushStyle(EngineTextStyle.only(color: blue));
      builder.addText('Lorem ipsum ');
      builder.pushStyle(EngineTextStyle.only(background: Paint()..color = red));
      builder.pushStyle(EngineTextStyle.only(color: green));
      builder.addText('dolor ');
      builder.pop();
      builder.addText('sit');
    })
      ..layout(constrain(90.0));
    canvas.drawParagraph(paragraph, offset);
    offset = offset.translate(0, paragraph.height + 10);

    return takeScreenshot(canvas, bounds, 'canvas_paragraph_general');
  });

  test('respects alignment', () {
    final BitmapCanvas canvas = BitmapCanvas(bounds, RenderStrategy());

    Offset offset = Offset.zero;
    CanvasParagraph paragraph;

    void build(CanvasParagraphBuilder builder) {
      builder.pushStyle(EngineTextStyle.only(color: black));
      builder.addText('Lorem ');
      builder.pushStyle(EngineTextStyle.only(color: blue));
      builder.addText('ipsum ');
      builder.pushStyle(EngineTextStyle.only(color: green));
      builder.addText('dolor ');
      builder.pushStyle(EngineTextStyle.only(color: red));
      builder.addText('sit');
    }

    paragraph = rich(
      EngineParagraphStyle(fontFamily: 'Roboto', textAlign: TextAlign.left),
      build,
    )..layout(constrain(100.0));
    canvas.drawParagraph(paragraph, offset);
    offset = offset.translate(0, paragraph.height + 10);

    paragraph = rich(
      EngineParagraphStyle(fontFamily: 'Roboto', textAlign: TextAlign.center),
      build,
    )..layout(constrain(100.0));
    canvas.drawParagraph(paragraph, offset);
    offset = offset.translate(0, paragraph.height + 10);

    paragraph = rich(
      EngineParagraphStyle(fontFamily: 'Roboto', textAlign: TextAlign.right),
      build,
    )..layout(constrain(100.0));
    canvas.drawParagraph(paragraph, offset);
    offset = offset.translate(0, paragraph.height + 10);

    return takeScreenshot(canvas, bounds, 'canvas_paragraph_align');
  });

  test('respects alignment in DOM mode', () {
    final DomCanvas canvas = DomCanvas(domDocument.createElement('flt-picture'));

    Offset offset = Offset.zero;
    CanvasParagraph paragraph;

    void build(CanvasParagraphBuilder builder) {
      builder.pushStyle(EngineTextStyle.only(color: black));
      builder.addText('Lorem ');
      builder.pushStyle(EngineTextStyle.only(color: blue));
      builder.addText('ipsum ');
      builder.pushStyle(EngineTextStyle.only(color: green));
      builder.addText('dolor ');
      builder.pushStyle(EngineTextStyle.only(color: red));
      builder.addText('sit');
    }

    paragraph = rich(
      EngineParagraphStyle(fontFamily: 'Roboto', textAlign: TextAlign.left),
      build,
    )..layout(constrain(100.0));
    canvas.drawParagraph(paragraph, offset);
    offset = offset.translate(0, paragraph.height + 10);

    paragraph = rich(
      EngineParagraphStyle(fontFamily: 'Roboto', textAlign: TextAlign.center),
      build,
    )..layout(constrain(100.0));
    canvas.drawParagraph(paragraph, offset);
    offset = offset.translate(0, paragraph.height + 10);

    paragraph = rich(
      EngineParagraphStyle(fontFamily: 'Roboto', textAlign: TextAlign.right),
      build,
    )..layout(constrain(100.0));
    canvas.drawParagraph(paragraph, offset);
    offset = offset.translate(0, paragraph.height + 10);

    return takeScreenshot(canvas, bounds, 'canvas_paragraph_align_dom');
  });

  void testAlignAndTransform(EngineCanvas canvas) {
    CanvasParagraph paragraph;

    void build(CanvasParagraphBuilder builder) {
      builder.pushStyle(EngineTextStyle.only(color: white));
      builder.addText('Lorem ');
      builder.pushStyle(EngineTextStyle.only(color: red));
      builder.addText('ipsum\n');
      builder.pushStyle(EngineTextStyle.only(color: yellow));
      builder.addText('dolor');
    }

    void drawParagraphAt(Offset offset, TextAlign align) {
      paragraph = rich(
        EngineParagraphStyle(fontFamily: 'Roboto', fontSize: 20.0, textAlign: align),
        build,
      )..layout(constrain(150.0));
      canvas.save();
      canvas.translate(offset.dx, offset.dy);
      canvas.rotate(math.pi / 4);
      final Rect rect = Rect.fromLTRB(0.0, 0.0, 150.0, paragraph.height);
      canvas.drawRect(rect, SurfacePaintData()..color = black.value);
      canvas.drawParagraph(paragraph, Offset.zero);
      canvas.restore();
    }

    drawParagraphAt(const Offset(50.0, 0.0), TextAlign.left);
    drawParagraphAt(const Offset(150.0, 0.0), TextAlign.center);
    drawParagraphAt(const Offset(250.0, 0.0), TextAlign.right);
  }

  test('alignment and transform', () {
    final BitmapCanvas canvas = BitmapCanvas(bounds, RenderStrategy());
    testAlignAndTransform(canvas);
    return takeScreenshot(canvas, bounds, 'canvas_paragraph_align_transform');
  });

  test('alignment and transform (DOM)', () {
    final DomCanvas canvas = DomCanvas(domDocument.createElement('flt-picture'));
    testAlignAndTransform(canvas);
    return takeScreenshot(canvas, bounds, 'canvas_paragraph_align_transform_dom');
  });

  void testGiantParagraphStyles(EngineCanvas canvas) {
    final CanvasParagraph paragraph = rich(
      EngineParagraphStyle(fontFamily: 'Roboto', fontSize: 80.0),
      (CanvasParagraphBuilder builder) {
        builder.pushStyle(EngineTextStyle.only(color: yellow, fontSize: 24.0));
        builder.addText('Lorem ');
        builder.pushStyle(EngineTextStyle.only(color: red, fontSize: 32.0));
        builder.addText('ipsum');
      },
    )..layout(constrain(double.infinity));
    final Rect rect = Rect.fromLTRB(0.0, 0.0, paragraph.maxIntrinsicWidth, paragraph.height);
    canvas.drawRect(rect, SurfacePaintData()..color = black.value);
    canvas.drawParagraph(paragraph, Offset.zero);
  }

  test('giant paragraph style', () {
    const Rect bounds = Rect.fromLTWH(0, 0, 300, 200);
    final BitmapCanvas canvas = BitmapCanvas(bounds, RenderStrategy());
    testGiantParagraphStyles(canvas);
    return takeScreenshot(canvas, bounds, 'canvas_paragraph_giant_paragraph_style');
  });

  test('giant paragraph style (DOM)', () {
    const Rect bounds = Rect.fromLTWH(0, 0, 300, 200);
    final DomCanvas canvas = DomCanvas(domDocument.createElement('flt-picture'));
    testGiantParagraphStyles(canvas);
    return takeScreenshot(canvas, bounds, 'canvas_paragraph_giant_paragraph_style_dom');
  });

  test('giant font size on the body tag (DOM)', () async {
    const Rect bounds = Rect.fromLTWH(0, 0, 600, 200);

    // Store the old font size value on the body, and set a gaint font size.
    final String oldBodyFontSize = domDocument.body!.style.fontSize;
    domDocument.body!.style.fontSize = '100px';

    final DomCanvas canvas = DomCanvas(domDocument.createElement('flt-picture'));
    Offset offset = const Offset(10.0, 10.0);

    final CanvasParagraph paragraph = rich(
      EngineParagraphStyle(fontFamily: 'Roboto'),
      (CanvasParagraphBuilder builder) {
        builder.pushStyle(EngineTextStyle.only(color: yellow, fontSize: 24.0));
        builder.addText('Lorem ');
        builder.pushStyle(EngineTextStyle.only(color: red, fontSize: 48.0));
        builder.addText('ipsum');
      },
    )..layout(constrain(double.infinity));
    final Rect rect = Rect.fromLTWH(offset.dx, offset.dy, paragraph.maxIntrinsicWidth, paragraph.height);
    canvas.drawRect(rect, SurfacePaintData()..color = black.value);
    canvas.drawParagraph(paragraph, offset);
    offset = offset.translate(paragraph.maxIntrinsicWidth, 0.0);

    // Add some extra padding between the two paragraphs.
    offset = offset.translate(20.0, 0.0);

    // Use the same height as the previous paragraph so that the 2 paragraphs
    // look nice in the screenshot.
    final double placeholderHeight = paragraph.height;
    final double placeholderWidth = paragraph.height * 2;

    final CanvasParagraph paragraph2 = rich(
      EngineParagraphStyle(),
      (CanvasParagraphBuilder builder) {
        builder.addPlaceholder(placeholderWidth, placeholderHeight, PlaceholderAlignment.baseline, baseline: TextBaseline.alphabetic);
      },
    )..layout(constrain(double.infinity));
    final Rect rect2 = Rect.fromLTWH(offset.dx, offset.dy, paragraph2.maxIntrinsicWidth, paragraph2.height);
    canvas.drawRect(rect2, SurfacePaintData()..color = black.value);
    canvas.drawParagraph(paragraph2, offset);
    // Draw a rect in the placeholder.
    // Leave some padding around the placeholder to make the black paragraph
    // background visible.
    const double padding = 5;
    final TextBox placeholderBox = paragraph2.getBoxesForPlaceholders().single;
    canvas.drawRect(
      placeholderBox.toRect().shift(offset).deflate(padding),
      SurfacePaintData()..color = red.value,
    );

    await takeScreenshot(canvas, bounds, 'canvas_paragraph_giant_body_font_size_dom');

    // Restore the old font size value.
    domDocument.body!.style.fontSize = oldBodyFontSize;
  });

  test('paints spans with varying heights/baselines', () {
    final BitmapCanvas canvas = BitmapCanvas(bounds, RenderStrategy());

    final CanvasParagraph paragraph = rich(
      EngineParagraphStyle(fontFamily: 'Roboto'),
      (CanvasParagraphBuilder builder) {
        builder.pushStyle(EngineTextStyle.only(fontSize: 20.0));
        builder.addText('Lorem ');
        builder.pushStyle(EngineTextStyle.only(
          fontSize: 40.0,
          background: Paint()..color = green,
        ));
        builder.addText('ipsum ');
        builder.pushStyle(EngineTextStyle.only(
          fontSize: 10.0,
          color: white,
          background: Paint()..color = black,
        ));
        builder.addText('dolor ');
        builder.pushStyle(EngineTextStyle.only(fontSize: 30.0));
        builder.addText('sit ');
        builder.pop();
        builder.pop();
        builder.pushStyle(EngineTextStyle.only(
          fontSize: 20.0,
          background: Paint()..color = blue,
        ));
        builder.addText('amet');
      },
    )..layout(constrain(220.0));
    canvas.drawParagraph(paragraph, Offset.zero);

    return takeScreenshot(canvas, bounds, 'canvas_paragraph_varying_heights');
  });

  test('respects letter-spacing', () {
    final BitmapCanvas canvas = BitmapCanvas(bounds, RenderStrategy());

    final CanvasParagraph paragraph = rich(
      EngineParagraphStyle(fontFamily: 'Roboto'),
      (CanvasParagraphBuilder builder) {
        builder.pushStyle(EngineTextStyle.only(color: blue));
        builder.addText('Lorem ');
        builder.pushStyle(EngineTextStyle.only(color: green, letterSpacing: 1));
        builder.addText('Lorem ');
        builder.pushStyle(EngineTextStyle.only(color: red, letterSpacing: 3));
        builder.addText('Lorem');
      },
    )..layout(constrain(double.infinity));
    canvas.drawParagraph(paragraph, Offset.zero);

    return takeScreenshot(canvas, bounds, 'canvas_paragraph_letter_spacing');
  });

  test('letter-spacing Thai', () {
    final BitmapCanvas canvas = BitmapCanvas(bounds, RenderStrategy());

    const String yes = '\u0e43\u0e0a\u0e48';
    const String no = '\u0e44\u0e21\u0e48';

    final CanvasParagraph paragraph = rich(
      EngineParagraphStyle(fontFamily: 'Roboto', fontSize: 36),
      (CanvasParagraphBuilder builder) {
        builder.pushStyle(EngineTextStyle.only(color: blue));
        builder.addText('$yes $no ');
        builder.pushStyle(EngineTextStyle.only(color: green, letterSpacing: 1));
        builder.addText('$yes $no ');
        builder.pushStyle(EngineTextStyle.only(color: red, letterSpacing: 3));
        builder.addText('$yes $no');
      },
    )..layout(constrain(double.infinity));
    canvas.drawParagraph(paragraph, const Offset(20, 20));

    return takeScreenshot(canvas, bounds, 'canvas_paragraph_letter_spacing_thai');
  });

  test('draws text decorations', () {
    final BitmapCanvas canvas = BitmapCanvas(bounds, RenderStrategy());
    final List<TextDecorationStyle> decorationStyles = <TextDecorationStyle>[
      TextDecorationStyle.solid,
      TextDecorationStyle.double,
      TextDecorationStyle.dotted,
      TextDecorationStyle.dashed,
      TextDecorationStyle.wavy,
    ];

    final CanvasParagraph paragraph = rich(
      EngineParagraphStyle(fontFamily: 'Roboto'),
      (CanvasParagraphBuilder builder) {
        for (final TextDecorationStyle decorationStyle in decorationStyles) {
          builder.pushStyle(EngineTextStyle.only(
            color: const Color.fromRGBO(50, 50, 255, 1.0),
            decoration: TextDecoration.underline,
            decorationStyle: decorationStyle,
            decorationColor: red,
            fontFamily: 'Roboto',
            fontSize: 30,
          ));
          builder.addText('Hello World');
          builder.pop();
          builder.addText(' ');
        }
      },
    )..layout(constrain(double.infinity));

    canvas.drawParagraph(paragraph, Offset.zero);
    return takeScreenshot(canvas, bounds, 'canvas_paragraph_decoration');
  });

  void testFontFeatures(EngineCanvas canvas) {
    const String text = 'Bb Difficult ';
    const FontFeature enableSmallCaps = FontFeature('smcp');
    const FontFeature disableSmallCaps = FontFeature('smcp', 0);

    const String numeric = '123.4560';
    const FontFeature enableOnum = FontFeature('onum');

    const FontFeature disableLigatures = FontFeature('liga', 0);

    final CanvasParagraph paragraph = rich(
      EngineParagraphStyle(fontFamily: 'Roboto'),
      (CanvasParagraphBuilder builder) {
        // Small Caps
        builder.pushStyle(EngineTextStyle.only(
          height: 1.5,
          color: black,
          fontSize: 32.0,
        ));
        builder.pushStyle(EngineTextStyle.only(
          color: blue,
          fontFeatures: <FontFeature>[enableSmallCaps],
        ));
        builder.addText(text);
        // Make sure disabling a font feature also works.
        builder.pushStyle(EngineTextStyle.only(
          color: black,
          fontFeatures: <FontFeature>[disableSmallCaps],
        ));
        builder.addText(' (smcp)\n');
        builder.pop(); // disableSmallCaps
        builder.pop(); // enableSmallCaps

        // No ligatures
        builder.pushStyle(EngineTextStyle.only(
          color: blue,
          fontFeatures: <FontFeature>[disableLigatures],
        ));
        builder.addText(text);
        builder.pop(); // disableLigatures
        builder.addText(' (no liga)\n');

        // No font features
        builder.pushStyle(EngineTextStyle.only(
          color: blue,
        ));
        builder.addText(text);
        builder.pop(); // color: blue
        builder.addText(' (none)\n');

        // Onum
        builder.pushStyle(EngineTextStyle.only(
          color: blue,
          fontFeatures: <FontFeature>[enableOnum],
        ));
        builder.addText(numeric);
        builder.pop(); // enableOnum
        builder.addText(' (onum)\n');

        // No font features
        builder.pushStyle(EngineTextStyle.only(
          color: blue,
        ));
        builder.addText(numeric);
        builder.pop(); // color: blue
        builder.addText(' (none)\n\n');

        // Multiple font features
        builder.addText('Combined (smcp, onum):\n');
        builder.pushStyle(EngineTextStyle.only(
          color: blue,
          fontFeatures: <FontFeature>[
            enableSmallCaps,
            enableOnum,
          ],
        ));
        builder.addText('$text  $numeric');
        builder.pop(); // enableSmallCaps, enableOnum
      },
    )..layout(constrain(double.infinity));
    canvas.drawParagraph(paragraph, Offset.zero);
  }

  test('font features', () {
    const Rect bounds = Rect.fromLTWH(0, 0, 600, 500);
    final BitmapCanvas canvas = BitmapCanvas(bounds, RenderStrategy());
    testFontFeatures(canvas);
    return takeScreenshot(canvas, bounds, 'canvas_paragraph_font_features');
  });

  test('font features (DOM)', () {
    const Rect bounds = Rect.fromLTWH(0, 0, 600, 500);
    final DomCanvas canvas = DomCanvas(domDocument.createElement('flt-picture'));
    testFontFeatures(canvas);
    return takeScreenshot(canvas, bounds, 'canvas_paragraph_font_features_dom');
  });

  void testFontVariations(EngineCanvas canvas) {
    const String text = 'ABCDE 12345\n';
    FontVariation weight(double w) => FontVariation('wght', w);

    final CanvasParagraph paragraph = rich(
      EngineParagraphStyle(fontFamily: 'RobotoVariable'),
      (CanvasParagraphBuilder builder) {
        builder.pushStyle(EngineTextStyle.only(
          fontSize: 48.0,
        ));
        builder.addText(text);
        builder.pushStyle(EngineTextStyle.only(
          fontSize: 48.0,
          fontVariations: <FontVariation>[weight(900)],
        ));
        builder.addText(text);
        builder.pushStyle(EngineTextStyle.only(
          fontSize: 48.0,
          fontVariations: <FontVariation>[weight(200)],
        ));
        builder.addText(text);
        builder.pop();
        builder.pop();
        builder.pop();
      },
    )..layout(constrain(double.infinity));
    canvas.drawParagraph(paragraph, Offset.zero);
  }

  test('font variations', () {
    const Rect bounds = Rect.fromLTWH(0, 0, 600, 500);
    final BitmapCanvas canvas = BitmapCanvas(bounds, RenderStrategy());
    testFontVariations(canvas);
    return takeScreenshot(canvas, bounds, 'canvas_paragraph_font_variations');
  });

  test('font variations (DOM)', () {
    const Rect bounds = Rect.fromLTWH(0, 0, 600, 500);
    final DomCanvas canvas = DomCanvas(domDocument.createElement('flt-picture'));
    testFontVariations(canvas);
    return takeScreenshot(canvas, bounds, 'canvas_paragraph_font_variations_dom');
  });

  void testBackgroundStyle(EngineCanvas canvas) {
    final CanvasParagraph paragraph = rich(
      EngineParagraphStyle(fontFamily: 'Roboto', fontSize: 40.0),
      (CanvasParagraphBuilder builder) {
        builder.pushStyle(EngineTextStyle.only(color: black));
        builder.pushStyle(EngineTextStyle.only(background: Paint()..color = blue));
        builder.addText('Lor');
        builder.pushStyle(EngineTextStyle.only(background: Paint()..color = black, color: white));
        builder.addText('em ');
        builder.pop();
        builder.pushStyle(EngineTextStyle.only(background: Paint()..color = green));
        builder.addText('ipsu');
        builder.pushStyle(EngineTextStyle.only(background: Paint()..color = yellow));
        builder.addText('m\ndo');
        builder.pushStyle(EngineTextStyle.only(background: Paint()..color = red));
        builder.addText('lor sit');
      },
    );
    paragraph.layout(constrain(double.infinity));
    canvas.drawParagraph(paragraph, Offset.zero);
  }

  test('background style', () {
    const Rect bounds = Rect.fromLTWH(0, 0, 300, 200);
    final BitmapCanvas canvas = BitmapCanvas(bounds, RenderStrategy());
    testBackgroundStyle(canvas);
    return takeScreenshot(canvas, bounds, 'canvas_paragraph_background_style');
  });

  test('background style (DOM)', () {
    const Rect bounds = Rect.fromLTWH(0, 0, 300, 200);
    final DomCanvas canvas = DomCanvas(domDocument.createElement('flt-picture'));
    testBackgroundStyle(canvas);
    return takeScreenshot(canvas, bounds, 'canvas_paragraph_background_style_dom');
  });

  void testForegroundStyle(EngineCanvas canvas) {
    final CanvasParagraph paragraph = rich(
      EngineParagraphStyle(fontFamily: 'Roboto', fontSize: 40.0),
      (CanvasParagraphBuilder builder) {
        builder.pushStyle(EngineTextStyle.only(color: blue));
        builder.addText('Lorem');
        builder.pop();
        builder.pushStyle(EngineTextStyle.only(foreground: Paint()..color = red..style = PaintingStyle.stroke));
        builder.addText('ipsum\n');
        builder.pop();
        builder.pushStyle(EngineTextStyle.only(foreground: Paint()..color = blue..style = PaintingStyle.stroke..strokeWidth = 0.0));
        builder.addText('dolor');
        builder.pop();
        builder.pushStyle(EngineTextStyle.only(foreground: Paint()..color = green..style = PaintingStyle.stroke..strokeWidth = 2.0));
        builder.addText('sit\n');
        builder.pop();
        builder.pushStyle(EngineTextStyle.only(foreground: Paint()..color = yellow..style = PaintingStyle.stroke..strokeWidth = 4.0));
        builder.addText('amet');
      },
    );
    paragraph.layout(constrain(double.infinity));
    canvas.drawParagraph(paragraph, Offset.zero);
  }

  test('foreground style', () {
    const Rect bounds = Rect.fromLTWH(0, 0, 300, 200);
    final BitmapCanvas canvas = BitmapCanvas(bounds, RenderStrategy());
    testForegroundStyle(canvas);
    return takeScreenshot(canvas, bounds, 'canvas_paragraph_foreground_style');
  });

  test('foreground style (DOM)', () {
    const Rect bounds = Rect.fromLTWH(0, 0, 300, 200);
    final DomCanvas canvas = DomCanvas(domDocument.createElement('flt-picture'));
    testForegroundStyle(canvas);
    return takeScreenshot(canvas, bounds, 'canvas_paragraph_foreground_style_dom');
  });

  test('paragraph bounds hug the text inside the paragraph', () async {
    const Rect bounds = Rect.fromLTWH(0, 0, 150, 100);

    final CanvasParagraphBuilder builder = CanvasParagraphBuilder(EngineParagraphStyle(
      fontFamily: 'Ahem',
      fontSize: 20,
      textAlign: TextAlign.center,
    ));

    // Expected layout with center-alignment is something like this:
    //
    // _________________
    // |       A       |
    // |    |AAAAA|    |
    // |    | AAA |    |
    // |----|-----|----|
    // |    |<--->|    |
    // |      100      |
    // |               |
    // |<------------->|
    //        110
    //
    // The width of the paragraph is bigger than the actual content because the
    // longest line "AAAAA" is 100px, which is smaller than 110px specified in
    // the constraint. After the layout and centering the paint bounds would
    // "hug" the text inside the paragraph more tightly than the box allocated
    // for the paragraph.
    builder.addText('A AAAAA AAA');

    final CanvasParagraph paragraph = builder.build();
    paragraph.layout(const ParagraphConstraints(width: 110));
    final BitmapCanvas canvas = BitmapCanvas(bounds, RenderStrategy());
    canvas.translate(20, 20);
    canvas.drawParagraph(paragraph, Offset.zero);
    canvas.drawRect(
      Rect.fromLTRB(
        0,
        0,
        paragraph.width,
        paragraph.height,
      ),
      SurfacePaintData()
        ..style = PaintingStyle.stroke
        ..strokeWidth = 1,
    );

    canvas.drawRect(
      paragraph.paintBounds,
      SurfacePaintData()
        ..color = 0xFF00FF00
        ..style = PaintingStyle.stroke
        ..strokeWidth = 1,
    );

    await takeScreenshot(canvas, bounds, 'canvas_paragraph_bounds');
  });
}
