Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

More options for drawing stroked text and paths #137064

Open
zanderso opened this issue Oct 23, 2023 · 4 comments
Open

More options for drawing stroked text and paths #137064

zanderso opened this issue Oct 23, 2023 · 4 comments
Labels
c: proposal A detailed proposal for a change to Flutter P3 Issues that are less important to the Flutter project team-framework Owned by Framework team triaged-framework Triaged by Framework team

Comments

@zanderso
Copy link
Member

Design programs support a number of options for configuring stroke on text and paths. For example, Adobe Illustrator defaults stroked text to "outside".

image002

(Generalizing this a bit, "Inside" to "outside" could be represented as floats between -1.0 and 1.0 with 0.0 mapping to "center".)

Skia does not support this concept natively for text or paths. The concept exists in the SVG standard, however Chrome (and package:flutter_svg which attempts to emulate Chrome) can have undesirable behavior depending on the specific paths that appear in the font:

image (1)

To accomplish this today in Flutter, there are a couple of options. First you can use a Stack of two Text widgets. The top one gets the text fill color. The one behind gets a stroke and you set the one behind to be twice the size of the stroke you need (so that ½ of it is revealed from the edges of the top-fill-colored text). This is problematic because there are two Text widgets when there technically should only be one, for example you'd need to use an ExcludeSemantics widget to wrap one of the Text widgets, and potentially other pitfalls.

Alternatively, you could get down to the render objects and write the code to do this stacked painting without separate widgets. However, then one would need to reimplement all the rest of the functionality of the Text widget, which is a heavy burden.

There are strategies for implementing this natively in Impeller (and possibly also as a feature request for the Skia team). However, for consistency across platforms, implementing this using the render object approach in the framework as part of the existing Text widget seems like it would be the most convenient. Later, if needed for performance for example, we could then explore adding features to Impeller and/or Skia to implement this. Tagging this as 'team-framework'.

@zanderso zanderso added c: proposal A detailed proposal for a change to Flutter team-framework Owned by Framework team labels Oct 23, 2023
@Hixie
Copy link
Contributor

Hixie commented Oct 23, 2023

The last few paragraphs focus on the specific use case of painting text with an outline and a fill. We could implement that directly in TextPainter. The issue topic though talks about this as a general shape and text feature. That would need engine support in Paint, probably.

It would be good to have a concrete use case to drive this.

@Calpoog
Copy link

Calpoog commented Oct 24, 2023

Hey all!

This was spurred by a request of mine so I can provide at least one good use case: Text overlays on maps. It's important for accessibility that text be legible against all kind of different backgrounds on vector or satellite based maps. Google maps has a stroke around points of interest names for that exact purpose. In general, it's a valuable tool in a designer's pocket for aesthetic or functional purposes.

A TextPainter level makes sense. Really it doesn't both me whether it's in the widget, render object, or canvas. The important things have been noted above. It's not as simple as allowing both a fill and stroke which goes behind it. Here's some things to think about:

  1. In some cases users may not want a fill, only a stroke. In that case it's especially important that they can choose an alignment of the stroke to the shape (inside, center, outside – or -1.0 to 1.0). Otherwise thick strokes will just engulf the characters and become blobs. This is a problem that "outside" alignment cannot have.
  2. With a fill and a stroke it's still annoying to need to specify a stroke width of 2x what you need it to be in order for the current center-stroke to look correct. In addition, if you end up using a stroke greater than 2x the width of the individual lines of a character, the stroke from the right side of an l (lowercase L) may begin to bleed out the left side from behind the fill. This is also a problem that "outside" alignment cannot have.
  3. foreground Paint on Text operates on the shape of the text. But a Paint cannot be both a fill and a stroke. A foreground and color cannot exist together. background Paint operates only on the bounding box of the text. Stroke lies somewhere in the theoretically middle.
  4. This isn't just about text! If I want a stroke around any shape, even at a custom painter level, I'd like to have this freedom. This is potentially good motivation for it existing at an impeller level and have explicit properties in TextStyle > TextPainter for control.

@goderbauer goderbauer added P3 Issues that are less important to the Flutter project triaged-framework Triaged by Framework team labels Oct 24, 2023
@v21
Copy link

v21 commented Apr 27, 2024

I'd add - the current approach (applying a foreground: Paint()..style = PaintingStyle.stroke) also has the same downside that the flutter_svg approach has - for fonts where glyphs are made of several components, the stroke outlines each component separately. If you're also doing an opaque fill, then that's okay, you can cover it up - but it makes it impractical to just stroke the text.

Screenshot 2024-04-27 at 12 35 29

@Hixie
Copy link
Contributor

Hixie commented Apr 27, 2024

This issue is a bit vague about specifically what it is about. We should probably close this in favour of more specific use cases. It could be:

  • stroke alignment when painting paths should be configurable
  • paragraphs should have an option to be converted into paths
  • it should be possible to paint text with an outline

...or any number of other things, or maybe several of these.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c: proposal A detailed proposal for a change to Flutter P3 Issues that are less important to the Flutter project team-framework Owned by Framework team triaged-framework Triaged by Framework team
Projects
None yet
Development

No branches or pull requests

5 participants