Skip to content

Drawing a paragraph with a gradient fill style on canvas results in incorrect gradient positioning #18710

@sir-boformer

Description

@sir-boformer

A change that was introduced a few days ago in libtxt changed the way a paragraph with a gradient is drawn on a canvas, e.g.:

final colors = [
  Color(0xffff0000), Color(0xffffff00), Color(0xff00ff00),
  Color(0xff00ffff), Color(0xff0000ff), Color(0xffff00ff), Color(0xffff0000),
];
final colorStops = [0 / 6, 1 / 6, 2 / 6, 3 / 6, 4 / 6, 5 / 6, 6 / 6];
final gradient = new ui.Gradient.linear(
  Offset(0.0, 0.0),
  Offset(0.0, size.height),
  colors,
  colorStops,
);
final gradientPaint = new Paint()..shader = gradient;

final paragraphStyle = new ui.ParagraphStyle(
  fontSize: 60.0,
  textAlign: TextAlign.center,
);
final paragraphBuilder = new ui.ParagraphBuilder(paragraphStyle)
  ..pushStyle(new ui.TextStyle(foreground: gradientPaint))
  ..addText('TEST');
final paragraph = paragraphBuilder.build();
paragraph.layout(new ui.ParagraphConstraints(width: size.width / 2));

final offset1 = new Offset(size.width * 0.5, size.height * 0.33);
canvas.drawParagraph(paragraph, offset1);

Usually, when you draw a path, shape or text with a gradient paint (without using Canvas.translate), the gradient is positioned absolutely in the canvas. That behavior is consistent with other canvas implementations (Android, HTML5).

A few days ago, @GaryQian introduced a change in libtxt: Now the canvas->translate method is used to position the paragraph in the canvas. A side effect is that the gradient origin is also translated, so now it is positioned relative to the text. This is the relevant code:

https://github.com/flutter/engine/blob/975d4ead668c8a5e8abe5b0a69a6f7f3e4984579/third_party/txt/src/txt/paragraph.cc#L874-L883

That change makes it impossible to draw a paragraph with an absolutely positioned gradient without reconstructing the shader. There is no way to revert the canvas->translate call.

Here is a comparison the behavior on Android and Flutter, with example projects:

Android: Flutter:
Example Project Example Project

More info/discussion can be found here and here

@dnfield @Hixie

Metadata

Metadata

Assignees

No one assigned

    Labels

    a: typographyText rendering, possibly libtxtengineflutter/engine related. See also e: labels.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions