mirror of
				https://github.com/flame-engine/flame.git
				synced 2025-10-31 08:56:01 +08:00 
			
		
		
		
	refactor!: Kill TextRenderer, Long Live TextRenderer (#2683)
This will:
    kill the TextRenderer inheritance chain
    incorporate the functionality of the base TextRenderer in the base TextFormatter
    rename TextFormatter to TextRenderer and appropriate references
That is because both essentially do the same job; encompass the style (or "how") information about how to render text, but using two slightly different interfaces. While that could allow for more flexibility, it is a faux choice that needlessly complicates the pipeline. By having a single interface to comply with, we still allow for custom renders while at the same time making all the code downstream simpler to use and understand.
			
			
This commit is contained in:
		| @ -3,94 +3,70 @@ | |||||||
| Flame has some dedicated classes to help you render text. | Flame has some dedicated classes to help you render text. | ||||||
|  |  | ||||||
|  |  | ||||||
| ## TextRenderer |  | ||||||
|  |  | ||||||
| `TextRenderer` is the abstract class used by Flame to render text. Flame provides one |  | ||||||
| implementation for this called `TextPaint` but anyone can implement this abstraction |  | ||||||
| and create a custom way to render text. |  | ||||||
|  |  | ||||||
|  |  | ||||||
| ## TextPaint |  | ||||||
|  |  | ||||||
| `TextPaint` is the built-in implementation of text rendering in Flame, it is based on top of |  | ||||||
| Flutter's `TextPainter` class (hence the name), and it can be configured by the style class `TextStyle` |  | ||||||
| which contains all typographical information required to render text; i.e., font size and color, |  | ||||||
| font family, etc. |  | ||||||
|  |  | ||||||
| Example usage: |  | ||||||
|  |  | ||||||
| ```dart |  | ||||||
| const TextPaint textPaint = TextPaint( |  | ||||||
|   style: TextStyle( |  | ||||||
|     fontSize: 48.0, |  | ||||||
|     fontFamily: 'Awesome Font', |  | ||||||
|   ), |  | ||||||
| ); |  | ||||||
| ``` |  | ||||||
|  |  | ||||||
| Note: there are several packages that contain the class `TextStyle`, make sure that you import |  | ||||||
| either `package:flutter/material.dart` or `package:flutter/painting.dart` and if you also need to |  | ||||||
| import `dart:ui` you need to import it like this (since that contains another class that is also |  | ||||||
| named `TextStyle`): |  | ||||||
|  |  | ||||||
| ```dart |  | ||||||
| import 'dart:ui' hide TextStyle; |  | ||||||
| ``` |  | ||||||
|  |  | ||||||
| Some common properties of `TextStyle` are the following (here is the |  | ||||||
| [full list](https://api.flutter.dev/flutter/painting/TextStyle-class.html)): |  | ||||||
|  |  | ||||||
| - `fontFamily`: a commonly available font, like Arial (default), or a custom font added in your |  | ||||||
|  pubspec (see [here](https://docs.flutter.dev/cookbook/design/fonts) how to do it). |  | ||||||
| - `fontSize`: font size, in pts (default `24.0`). |  | ||||||
| - `height`: height of text line, as a multiple of font size (default `null`). |  | ||||||
| - `color`: the color, as a `ui.Color` (default white). |  | ||||||
|  |  | ||||||
| For more information regarding colors and how to create then, see the |  | ||||||
| [Colors and the Palette](palette.md) guide. |  | ||||||
|  |  | ||||||
| After the creation of the `TextPaint` object you can use its `render` method to draw strings on |  | ||||||
| a canvas: |  | ||||||
|  |  | ||||||
| ```dart |  | ||||||
| textPaint.render(canvas, "Flame is awesome", Vector2(10, 10)); |  | ||||||
| ``` |  | ||||||
|  |  | ||||||
| If you want to set the anchor of the text you can also do that in the render call, with the optional |  | ||||||
| `anchor` parameter: |  | ||||||
|  |  | ||||||
| ```dart |  | ||||||
| textPaint.render(canvas, 'Flame is awesome', Vector2(10, 10), anchor: Anchor.topCenter); |  | ||||||
| ``` |  | ||||||
|  |  | ||||||
|  |  | ||||||
| ## Text Components | ## Text Components | ||||||
|  |  | ||||||
| Flame provides two text components that make it even easier to render text in your game: | The simplest way to render text with Flame is to leverage one of the provided text-rendering | ||||||
| `TextComponent` and `TextBoxComponent`. | components: | ||||||
|  |  | ||||||
|  | - `TextComponent` for rendering a single line of text | ||||||
|  | - `TextBoxComponent` for bounding multi-line text within a sized box, including the possibility of a | ||||||
|  |   typing effect | ||||||
|  |  | ||||||
|  | Both components are showcased in [this | ||||||
|  | example](https://github.com/flame-engine/flame/blob/main/examples/lib/stories/rendering/text_example.dart). | ||||||
|  |  | ||||||
|  |  | ||||||
| ### TextComponent | ### TextComponent | ||||||
|  |  | ||||||
| `TextComponent` is a simple component that renders a single line of text. | `TextComponent` is a simple component that renders a single line of text. | ||||||
|  |  | ||||||
| Example usage: | Simple usage: | ||||||
|  |  | ||||||
| ```dart | ```dart | ||||||
| final style = TextStyle(color: BasicPalette.white.color); | class MyGame extends FlameGame { | ||||||
| final regular = TextPaint(style: style); |   @override | ||||||
|  |   void onLoad() { | ||||||
|  |     add( | ||||||
|  |       TextComponent( | ||||||
|  |         text: 'Hello, Flame', | ||||||
|  |         position = Vector2.all(16.0), | ||||||
|  |       ), | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | In order to configure aspects of the rendering like font family, size, color, etc, you need to | ||||||
|  | provide (or amend) a `TextRenderer` with such information; while you can read more details ab out | ||||||
|  | this interface below, the simplest implementation you can use is the `TextPaint`, which takes a | ||||||
|  | Flutter `TextStyle`: | ||||||
|  |  | ||||||
|  | ```dart | ||||||
|  | final regular = TextPaint( | ||||||
|  |   style: TextStyle( | ||||||
|  |     fontSize: 48.0, | ||||||
|  |     color: BasicPalette.white.color, | ||||||
|  |   ), | ||||||
|  | ); | ||||||
|  |  | ||||||
| class MyGame extends FlameGame { | class MyGame extends FlameGame { | ||||||
|   @override |   @override | ||||||
|   void onLoad() { |   void onLoad() { | ||||||
|     add(TextComponent(text: 'Hello, Flame', textRenderer: regular) |     add( | ||||||
|       ..anchor = Anchor.topCenter |       TextComponent( | ||||||
|       ..x = size.width / 2 // size is a property from game |         text: 'Hello, Flame', | ||||||
|       ..y = 32.0); |         textRenderer: regular, | ||||||
|  |         anchor: Anchor.topCenter, | ||||||
|  |         position: Vector2(size.width / 2, 32.0), | ||||||
|  |       ), | ||||||
|  |     ); | ||||||
|   } |   } | ||||||
| } | } | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
|  | You can find all the options under [TextComponent's | ||||||
|  | API](https://pub.dev/documentation/flame/latest/components/TextComponent-class.html). | ||||||
|  |  | ||||||
|  |  | ||||||
| ### TextBoxComponent | ### TextBoxComponent | ||||||
|  |  | ||||||
| @ -101,12 +77,15 @@ You can decide if the box should grow as the text is written or if it should be | |||||||
| `growingBox` variable in the `TextBoxConfig`. A static box could either have a fixed size (setting | `growingBox` variable in the `TextBoxConfig`. A static box could either have a fixed size (setting | ||||||
| the `size` property of the `TextBoxComponent`), or to automatically shrink to fit the text content. | the `size` property of the `TextBoxComponent`), or to automatically shrink to fit the text content. | ||||||
|  |  | ||||||
| In addition, the `align` property allows you to control the the horizontal and vertical alignment | In addition, the `align` property allows you to control the the horizontal and vertical alignment of | ||||||
| of the text content. For example, setting `align` to `Anchor.center` will center the text within | the text content. For example, setting `align` to `Anchor.center` will center the text within its | ||||||
| its bounding box both vertically and horizontally. | bounding box both vertically and horizontally. | ||||||
|  |  | ||||||
| If you want to change the margins of the box use the `margins` variable in the `TextBoxConfig`. | If you want to change the margins of the box use the `margins` variable in the `TextBoxConfig`. | ||||||
|  |  | ||||||
|  | Finally, if you want to simulate a "typing" effect, by showing each character of the string one by | ||||||
|  | one as if being typed in real-time, you can provide the `boxConfig.timePerChar` parameter. | ||||||
|  |  | ||||||
| Example usage: | Example usage: | ||||||
|  |  | ||||||
| ```dart | ```dart | ||||||
| @ -130,5 +109,219 @@ class MyTextBox extends TextBoxComponent { | |||||||
| } | } | ||||||
| ``` | ``` | ||||||
|  |  | ||||||
| Both components are showcased in an example | You can find all the options under [TextBoxComponent's | ||||||
| [here](https://github.com/flame-engine/flame/blob/main/examples/lib/stories/rendering/text_example.dart) | API](https://pub.dev/documentation/flame/latest/components/TextBoxComponent-class.html). | ||||||
|  |  | ||||||
|  |  | ||||||
|  | ## Infrastructure | ||||||
|  |  | ||||||
|  | If you are not using the Flame Component System, want to understand the infrastructure behind text | ||||||
|  | rendering, want to customize fonts and styles used, or want to create your own custom renderers, | ||||||
|  | this section is for you. | ||||||
|  |  | ||||||
|  | - `TextRenderer`: renderers know "how" to render text; in essence they contain the style information | ||||||
|  |   to render any string | ||||||
|  | - `TextElement`: an element is formatted, "laid-out" piece of text, include the string ("what") and | ||||||
|  |   the style ("how") | ||||||
|  |  | ||||||
|  | The following diagram showcases the class and inheritance structure of the text rendering pipeline: | ||||||
|  |  | ||||||
|  | ```mermaid | ||||||
|  | classDiagram | ||||||
|  |     %% renderers | ||||||
|  |     note for TextRenderer "This just the style (how). | ||||||
|  |     It knows how to take a text string and create a TextElement. | ||||||
|  |     `render` is just a helper to `format(text).render(...)`. Same for `getLineMetrics`." | ||||||
|  |     class TextRenderer { | ||||||
|  |         TextElement format(String text) | ||||||
|  |         LineMetrics getLineMetrics(String text) | ||||||
|  |         void render(Canvas canvas, String text, ...) | ||||||
|  |     } | ||||||
|  |     class TextPaint | ||||||
|  |     class SpriteFontRenderer | ||||||
|  |     class DebugTextRenderer | ||||||
|  |      | ||||||
|  |     %% elements | ||||||
|  |     class TextElement { | ||||||
|  |         LineMetrics metrics | ||||||
|  |         render(Canvas canvas, ...) | ||||||
|  |     } | ||||||
|  |     class TextPainterTextElement | ||||||
|  |          | ||||||
|  |     TextRenderer --> TextPaint | ||||||
|  |     TextRenderer --> SpriteFontRenderer | ||||||
|  |     TextRenderer --> DebugTextRenderer | ||||||
|  |  | ||||||
|  |     TextRenderer *-- TextElement | ||||||
|  |     TextPaint *-- TextPainterTextElement | ||||||
|  |     SpriteFontRenderer *-- SpriteFontTextElement | ||||||
|  |  | ||||||
|  |     note for TextElement "This is the text (what) and the style (how); | ||||||
|  |     laid out and ready to render." | ||||||
|  |     TextElement --> TextPainterTextElement | ||||||
|  |     TextElement --> SpriteFontTextElement | ||||||
|  |     TextElement --> Others | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  |  | ||||||
|  | ### TextRenderer | ||||||
|  |  | ||||||
|  | `TextRenderer` is the abstract class used by Flame to render text. Implementations of `TextRenderer` | ||||||
|  | must include the information about the "how" the text is rendered. Font style, size, color, etc. It | ||||||
|  | should be able to combine that information with a given string of text, via the `format` method, to | ||||||
|  | generate a `TextElement`. | ||||||
|  |  | ||||||
|  | Flame provides two concrete implementations: | ||||||
|  |  | ||||||
|  | - `TextPaint`: most used, uses Flutter `TextPainter` to render regular text | ||||||
|  | - `SpriteFontRenderer`: uses a `SpriteFont` (a spritesheet-based font) to render bitmap text | ||||||
|  | - `DebugTextRenderer`: only intended to be used for Golden Tests | ||||||
|  |  | ||||||
|  | But you can also provide your own if you want to extend to other customized forms of text rendering. | ||||||
|  |  | ||||||
|  | The main job of a `TextRenderer` is to format a string of text into a `TextElement`, that then can | ||||||
|  | be rendered onto the screen: | ||||||
|  |  | ||||||
|  | ```dart | ||||||
|  | final textElement = textRenderer.format("Flame is awesome") | ||||||
|  | textElement.render(...)  | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | However the renderer provides a helper method to directly create the element and render it: | ||||||
|  |  | ||||||
|  | ```dart | ||||||
|  | textRenderer.render( | ||||||
|  |   canvas, | ||||||
|  |   'Flame is awesome', | ||||||
|  |   Vector2(10, 10), | ||||||
|  |   anchor: Anchor.topCenter, | ||||||
|  | ); | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  |  | ||||||
|  | #### TextPaint | ||||||
|  |  | ||||||
|  | `TextPaint` is the built-in implementation of text rendering in Flame. It is based on top of | ||||||
|  | Flutter's `TextPainter` class (hence the name), and it can be configured by the style class | ||||||
|  | `TextStyle`, which contains all typographical information required to render text; i.e., font size | ||||||
|  | and color, font family, etc. | ||||||
|  |  | ||||||
|  | Outside of the style you can also optionally provide one extra parameter which is the | ||||||
|  | `textDirection` (but that is typically already set to `ltr` or left-to-right). | ||||||
|  |  | ||||||
|  | Example usage: | ||||||
|  |  | ||||||
|  | ```dart | ||||||
|  | const TextPaint textPaint = TextPaint( | ||||||
|  |   style: TextStyle( | ||||||
|  |     fontSize: 48.0, | ||||||
|  |     fontFamily: 'Awesome Font', | ||||||
|  |   ), | ||||||
|  | ); | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | Note: there are several packages that contain the class `TextStyle`. We export the right one (from | ||||||
|  | Flutter) via the `text` module: | ||||||
|  |  | ||||||
|  | ```dart | ||||||
|  | import 'package:flame/text.dart'; | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | But if you want to import it explicitly, make sure that you import it from | ||||||
|  | `package:flutter/painting.dart` (or from material or widgets). If you also need to import `dart:ui`, | ||||||
|  | you might need to hide its version of `TextStyle`, since that module contains a different class with | ||||||
|  | the same name: | ||||||
|  |  | ||||||
|  | ```dart | ||||||
|  | import 'package:flutter/painting.dart'; | ||||||
|  | import 'dart:ui' hide TextStyle; | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | Some common properties of `TextStyle` are the following (here is the [full | ||||||
|  | list](https://api.flutter.dev/flutter/painting/TextStyle-class.html)): | ||||||
|  |  | ||||||
|  | - `fontFamily`: a commonly available font, like Arial (default), or a custom font added in your | ||||||
|  |  pubspec (see [here](https://docs.flutter.dev/cookbook/design/fonts) how to do it). | ||||||
|  | - `fontSize`: font size, in pts (default `24.0`). | ||||||
|  | - `height`: height of text line, as a multiple of font size (default `null`). | ||||||
|  | - `color`: the color, as a `ui.Color` (default white). | ||||||
|  |  | ||||||
|  | For more information regarding colors and how to create then, see the [Colors and the | ||||||
|  | Palette](palette.md) guide. | ||||||
|  |  | ||||||
|  |  | ||||||
|  | #### SpriteFontRenderer | ||||||
|  |  | ||||||
|  | The other renderer option provided out of the box is `SpriteFontRenderer`, which allows you to | ||||||
|  | provide a `SpriteFont` based off of a spritesheet. TODO | ||||||
|  |  | ||||||
|  |  | ||||||
|  | #### DebugTextRenderer | ||||||
|  |  | ||||||
|  | This renderer is intended to be used for Golden Tests. Rendering normal font-based text in Golden | ||||||
|  | Tests is unreliable due to differences in font definitions across platforms and different algorithms | ||||||
|  | used for anti-aliasing. This renderer will render text as if each word was a solid rectangle, making | ||||||
|  | it possible to test the layout, positioning and sizing of the elements without having to rely on | ||||||
|  | font-based rendering. | ||||||
|  |  | ||||||
|  |  | ||||||
|  | ## Text Elements | ||||||
|  |  | ||||||
|  | Text Elements are "pre-compiled", formatted and laid-out pieces of text with a specific styling | ||||||
|  | applied, ready to be rendered at any given position. | ||||||
|  |  | ||||||
|  | `TextElement` implements the `Element` interface and must implement their two methods, one that | ||||||
|  | teaches how to translate it around and another on how to draw it to the canvas: | ||||||
|  |  | ||||||
|  | ```dart | ||||||
|  |   void translate(double dx, double dy); | ||||||
|  |   void draw(Canvas canvas); | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | These methods are intended to be overwritten by the implementations of `TextElement` but probably | ||||||
|  | will not be called directly by users; because a convenient `render` method is provided: | ||||||
|  |  | ||||||
|  | ```dart | ||||||
|  |   void render( | ||||||
|  |     Canvas canvas, | ||||||
|  |     Vector2 position, { | ||||||
|  |     Anchor anchor = Anchor.topLeft, | ||||||
|  |   }) | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  | That allows the element to be rendered at a specific position, using a given anchor. | ||||||
|  |  | ||||||
|  | The interface also mandates (and provides) a getter for the LineMetrics object associated with that | ||||||
|  | `TextElement`, which allows you (and the `render` implementation) to access sizing information | ||||||
|  | related to the element (width, height, ascend, etc). | ||||||
|  |  | ||||||
|  | ```dart | ||||||
|  |   LineMetrics get metrics; | ||||||
|  | ``` | ||||||
|  |  | ||||||
|  |  | ||||||
|  | ## Elements, Nodes, and Styles | ||||||
|  |  | ||||||
|  | While normal renderers always work with TextElements directly, there is a bigger underlying | ||||||
|  | infrastructure that can be used to render more rich or formatter text. | ||||||
|  |  | ||||||
|  | Elements are a superset of TextElements that represent an arbitrary rendering block within a | ||||||
|  | rich-text document. Essentially, they are concrete and "physical": they are objects that are ready | ||||||
|  | to be rendered on a canvas. | ||||||
|  |  | ||||||
|  | This property distinguishes them from Nodes, which are structured pieces of text, and from Styles, | ||||||
|  | which are descriptors for how arbitrary pieces of text ought to be rendered. | ||||||
|  |  | ||||||
|  | So a user would use Node to describe a desired document of rich text; define Styles to apply to it; | ||||||
|  | and use that to generate an Element. Depending on the type of rendering, the Element generated will | ||||||
|  | be a TextElement, which brings us back to the normal flow of the rendering pipeline. The unique | ||||||
|  | property of the Text-type element is that it exposes a LineMetrics that can be used for advanced | ||||||
|  | rendering; while the other elements only expose a simpler `draw` method which is unaware of sizing | ||||||
|  | and positioning. | ||||||
|  |  | ||||||
|  | However the other types of Elements, Nodes and Style must be used if the intent is to create an | ||||||
|  | entire Document, enriched with formatted text. Currently these extra features of the system are not | ||||||
|  | exposed through FCS, but can be used directly. | ||||||
|  |  | ||||||
|  | An example of such usages can be seen in [this | ||||||
|  | example](https://github.com/flame-engine/flame/blob/main/examples/lib/stories/rendering/rich_text_example.dart). | ||||||
|  | |||||||
| @ -208,7 +208,7 @@ class MyKeyboardDetector extends HardwareKeyboardDetector | |||||||
|  |  | ||||||
| class KeyboardKey extends PositionComponent { | class KeyboardKey extends PositionComponent { | ||||||
|   KeyboardKey({required this.text, super.position}) { |   KeyboardKey({required this.text, super.position}) { | ||||||
|     textElement = textRenderer.formatter.format(text); |     textElement = textRenderer.format(text); | ||||||
|     width = textElement.metrics.width + padding.x; |     width = textElement.metrics.width + padding.x; | ||||||
|     height = textElement.metrics.height + padding.y; |     height = textElement.metrics.height + padding.y; | ||||||
|     textElement.translate( |     textElement.translate( | ||||||
|  | |||||||
| @ -1,6 +1,7 @@ | |||||||
| import 'package:flame/components.dart'; | import 'package:flame/components.dart'; | ||||||
| import 'package:flame/game.dart'; | import 'package:flame/game.dart'; | ||||||
| import 'package:flame/palette.dart'; | import 'package:flame/palette.dart'; | ||||||
|  | import 'package:flame/text.dart'; | ||||||
| import 'package:flutter/material.dart'; | import 'package:flutter/material.dart'; | ||||||
|  |  | ||||||
| class TextExample extends FlameGame { | class TextExample extends FlameGame { | ||||||
|  | |||||||
| @ -48,5 +48,5 @@ export 'src/geometry/circle_component.dart'; | |||||||
| export 'src/geometry/polygon_component.dart'; | export 'src/geometry/polygon_component.dart'; | ||||||
| export 'src/geometry/rectangle_component.dart'; | export 'src/geometry/rectangle_component.dart'; | ||||||
| export 'src/geometry/shape_component.dart'; | export 'src/geometry/shape_component.dart'; | ||||||
| export 'src/text/text_paint.dart'; | export 'src/text/renderers/text_paint.dart'; | ||||||
| export 'src/timer.dart'; | export 'src/timer.dart'; | ||||||
|  | |||||||
| @ -18,4 +18,4 @@ export 'src/game/mixins/single_game_instance.dart'; | |||||||
| export 'src/game/notifying_vector2.dart'; | export 'src/game/notifying_vector2.dart'; | ||||||
| export 'src/game/projector.dart'; | export 'src/game/projector.dart'; | ||||||
| export 'src/game/transform2d.dart'; | export 'src/game/transform2d.dart'; | ||||||
| export 'src/text/text_paint.dart'; | export 'src/text/renderers/text_paint.dart'; | ||||||
|  | |||||||
| @ -1,5 +1,5 @@ | |||||||
| import 'package:flame/components.dart'; | import 'package:flame/components.dart'; | ||||||
| import 'package:flame/src/text/text_renderer.dart'; | import 'package:flame/text.dart'; | ||||||
|  |  | ||||||
| /// The [FpsTextComponent] is a [TextComponent] that writes out the current FPS. | /// The [FpsTextComponent] is a [TextComponent] that writes out the current FPS. | ||||||
| /// It has a [FpsComponent] as a child which does the actual calculations. | /// It has a [FpsComponent] as a child which does the actual calculations. | ||||||
|  | |||||||
| @ -273,7 +273,7 @@ class TextBoxComponent<T extends TextRenderer> extends TextComponent { | |||||||
|         line = line.substring(0, nChars); |         line = line.substring(0, nChars); | ||||||
|       } |       } | ||||||
|  |  | ||||||
|       final textElement = textRenderer.formatter.format(line); |       final textElement = textRenderer.format(line); | ||||||
|       final metrics = textElement.metrics; |       final metrics = textElement.metrics; | ||||||
|  |  | ||||||
|       final position = Vector2( |       final position = Vector2( | ||||||
|  | |||||||
| @ -42,7 +42,7 @@ class TextComponent<T extends TextRenderer> extends PositionComponent { | |||||||
|  |  | ||||||
|   @internal |   @internal | ||||||
|   void updateBounds() { |   void updateBounds() { | ||||||
|     _textElement = _textRenderer.formatter.format(_text); |     _textElement = _textRenderer.format(_text); | ||||||
|     final measurements = _textElement.metrics; |     final measurements = _textElement.metrics; | ||||||
|     _textElement.translate(0, measurements.ascent); |     _textElement.translate(0, measurements.ascent); | ||||||
|     size.setValues(measurements.width, measurements.height); |     size.setValues(measurements.width, measurements.height); | ||||||
|  | |||||||
| @ -1,7 +0,0 @@ | |||||||
| import 'package:flame/src/text/elements/text_element.dart'; |  | ||||||
|  |  | ||||||
| /// [TextFormatter] is an abstract interface for a class that can convert an |  | ||||||
| /// arbitrary string of text into a renderable [TextElement]. |  | ||||||
| abstract class TextFormatter { |  | ||||||
|   TextElement format(String text); |  | ||||||
| } |  | ||||||
| @ -1,28 +0,0 @@ | |||||||
| import 'package:flame/src/text/elements/text_painter_text_element.dart'; |  | ||||||
| import 'package:flame/src/text/formatters/text_formatter.dart'; |  | ||||||
| import 'package:flutter/rendering.dart'; |  | ||||||
|  |  | ||||||
| /// [TextPainterTextFormatter] applies a Flutter [TextStyle] to a string of |  | ||||||
| /// text, creating a [TextPainterTextElement]. |  | ||||||
| class TextPainterTextFormatter extends TextFormatter { |  | ||||||
|   TextPainterTextFormatter({ |  | ||||||
|     required this.style, |  | ||||||
|     this.textDirection = TextDirection.ltr, |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   final TextStyle style; // NOTE: this is a Flutter TextStyle |  | ||||||
|   final TextDirection textDirection; |  | ||||||
|  |  | ||||||
|   @override |  | ||||||
|   TextPainterTextElement format(String text) { |  | ||||||
|     final tp = _textToTextPainter(text); |  | ||||||
|     return TextPainterTextElement(tp); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   TextPainter _textToTextPainter(String text) { |  | ||||||
|     return TextPainter( |  | ||||||
|       text: TextSpan(text: text, style: style), |  | ||||||
|       textDirection: textDirection, |  | ||||||
|     )..layout(); |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| @ -1,6 +1,6 @@ | |||||||
| import 'package:flame/src/text/elements/text_element.dart'; | import 'package:flame/src/text/elements/text_element.dart'; | ||||||
| import 'package:flame/src/text/formatters/text_formatter.dart'; |  | ||||||
| import 'package:flame/src/text/nodes/text_node.dart'; | import 'package:flame/src/text/nodes/text_node.dart'; | ||||||
|  | import 'package:flame/src/text/renderers/text_renderer.dart'; | ||||||
| import 'package:flame/src/text/styles/document_style.dart'; | import 'package:flame/src/text/styles/document_style.dart'; | ||||||
| import 'package:flame/src/text/styles/flame_text_style.dart'; | import 'package:flame/src/text/styles/flame_text_style.dart'; | ||||||
|  |  | ||||||
| @ -20,11 +20,11 @@ class PlainTextNode extends TextNode { | |||||||
|  |  | ||||||
| class _PlainTextLayoutBuilder extends TextNodeLayoutBuilder { | class _PlainTextLayoutBuilder extends TextNodeLayoutBuilder { | ||||||
|   _PlainTextLayoutBuilder(this.node) |   _PlainTextLayoutBuilder(this.node) | ||||||
|       : formatter = node.textStyle.asTextFormatter(), |       : renderer = node.textStyle.asTextRenderer(), | ||||||
|         words = node.text.split(' '); |         words = node.text.split(' '); | ||||||
|  |  | ||||||
|   final PlainTextNode node; |   final PlainTextNode node; | ||||||
|   final TextFormatter formatter; |   final TextRenderer renderer; | ||||||
|   final List<String> words; |   final List<String> words; | ||||||
|   int index0 = 0; |   int index0 = 0; | ||||||
|   int index1 = 1; |   int index1 = 1; | ||||||
| @ -38,7 +38,7 @@ class _PlainTextLayoutBuilder extends TextNodeLayoutBuilder { | |||||||
|     int? tentativeIndex0; |     int? tentativeIndex0; | ||||||
|     while (index1 <= words.length) { |     while (index1 <= words.length) { | ||||||
|       final textPiece = words.sublist(index0, index1).join(' '); |       final textPiece = words.sublist(index0, index1).join(' '); | ||||||
|       final formattedPiece = formatter.format(textPiece); |       final formattedPiece = renderer.format(textPiece); | ||||||
|       if (formattedPiece.metrics.width > availableWidth) { |       if (formattedPiece.metrics.width > availableWidth) { | ||||||
|         break; |         break; | ||||||
|       } else { |       } else { | ||||||
|  | |||||||
| @ -4,12 +4,12 @@ import 'dart:ui' hide LineMetrics; | |||||||
| import 'package:flame/src/text/common/line_metrics.dart'; | import 'package:flame/src/text/common/line_metrics.dart'; | ||||||
| import 'package:flame/src/text/common/sprite_font.dart'; | import 'package:flame/src/text/common/sprite_font.dart'; | ||||||
| import 'package:flame/src/text/elements/sprite_font_text_element.dart'; | import 'package:flame/src/text/elements/sprite_font_text_element.dart'; | ||||||
| import 'package:flame/src/text/formatters/text_formatter.dart'; | import 'package:flame/src/text/renderers/text_renderer.dart'; | ||||||
| 
 | 
 | ||||||
| /// [SpriteFontTextFormatter] will render text using a [SpriteFont] font, | /// [SpriteFontRenderer] will render text using a [SpriteFont] font, | ||||||
| /// creating a [SpriteFontTextElement]. | /// creating a [SpriteFontTextElement]. | ||||||
| class SpriteFontTextFormatter extends TextFormatter { | class SpriteFontRenderer extends TextRenderer { | ||||||
|   SpriteFontTextFormatter.fromFont( |   SpriteFontRenderer.fromFont( | ||||||
|     this.font, { |     this.font, { | ||||||
|     this.scale = 1.0, |     this.scale = 1.0, | ||||||
|     this.letterSpacing = 0.0, |     this.letterSpacing = 0.0, | ||||||
| @ -1,28 +1,24 @@ | |||||||
| import 'package:flame/src/cache/memory_cache.dart'; | import 'package:flame/cache.dart'; | ||||||
| import 'package:flame/src/text/formatters/text_painter_text_formatter.dart'; | import 'package:flame/src/text/elements/text_painter_text_element.dart'; | ||||||
| import 'package:flame/src/text/text_renderer.dart'; | import 'package:flame/src/text/renderers/text_renderer.dart'; | ||||||
| import 'package:flutter/rendering.dart'; | import 'package:flutter/rendering.dart'; | ||||||
| 
 | 
 | ||||||
| /// [TextRenderer] implementation based on Flutter's [TextPainter]. | /// [TextPaint] applies a Flutter [TextStyle] to a string of | ||||||
| /// | /// text, creating a [TextPainterTextElement]. | ||||||
| /// This renderer uses a fixed [style] to draw the text. This style cannot be | class TextPaint extends TextRenderer { | ||||||
| /// modified dynamically, if you need to change any attribute of the text at |  | ||||||
| /// runtime, such as color, then create a new [TextPaint] object using |  | ||||||
| /// [copyWith]. |  | ||||||
| class TextPaint extends TextRenderer<TextPainterTextFormatter> { |  | ||||||
|   TextPaint({ |   TextPaint({ | ||||||
|     TextStyle? style, |     TextStyle? style, | ||||||
|     TextDirection? textDirection, |     this.textDirection = TextDirection.ltr, | ||||||
|   }) : super( |   }) : style = style ?? defaultTextStyle; | ||||||
|           TextPainterTextFormatter( |  | ||||||
|             style: style ?? defaultTextStyle, |  | ||||||
|             textDirection: textDirection ?? TextDirection.ltr, |  | ||||||
|           ), |  | ||||||
|         ); |  | ||||||
| 
 | 
 | ||||||
|   TextStyle get style => formatter.style; |   final TextStyle style; | ||||||
|  |   final TextDirection textDirection; | ||||||
| 
 | 
 | ||||||
|   TextDirection get textDirection => formatter.textDirection; |   @override | ||||||
|  |   TextPainterTextElement format(String text) { | ||||||
|  |     final tp = toTextPainter(text); | ||||||
|  |     return TextPainterTextElement(tp); | ||||||
|  |   } | ||||||
| 
 | 
 | ||||||
|   final MemoryCache<String, TextPainter> _textPainterCache = MemoryCache(); |   final MemoryCache<String, TextPainter> _textPainterCache = MemoryCache(); | ||||||
| 
 | 
 | ||||||
| @ -64,8 +60,8 @@ class TextPaint extends TextRenderer<TextPainterTextFormatter> { | |||||||
|     TextDirection? textDirection, |     TextDirection? textDirection, | ||||||
|   }) { |   }) { | ||||||
|     return TextPaint( |     return TextPaint( | ||||||
|       style: transform(formatter.style), |       style: transform(style), | ||||||
|       textDirection: textDirection ?? formatter.textDirection, |       textDirection: textDirection ?? this.textDirection, | ||||||
|     ); |     ); | ||||||
|   } |   } | ||||||
| } | } | ||||||
							
								
								
									
										22
									
								
								packages/flame/lib/src/text/renderers/text_renderer.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								packages/flame/lib/src/text/renderers/text_renderer.dart
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,22 @@ | |||||||
|  | import 'package:flame/extensions.dart'; | ||||||
|  | import 'package:flame/src/anchor.dart'; | ||||||
|  | import 'package:flame/text.dart'; | ||||||
|  |  | ||||||
|  | /// [TextRenderer] is an abstract interface for a class that can convert an | ||||||
|  | /// arbitrary string of text into a renderable [TextElement]. | ||||||
|  | abstract class TextRenderer { | ||||||
|  |   TextElement format(String text); | ||||||
|  |  | ||||||
|  |   LineMetrics getLineMetrics(String text) { | ||||||
|  |     return format(text).metrics; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   void render( | ||||||
|  |     Canvas canvas, | ||||||
|  |     String text, | ||||||
|  |     Vector2 position, { | ||||||
|  |     Anchor anchor = Anchor.topLeft, | ||||||
|  |   }) { | ||||||
|  |     format(text).render(canvas, position, anchor: anchor); | ||||||
|  |   } | ||||||
|  | } | ||||||
| @ -1,38 +0,0 @@ | |||||||
| import 'dart:ui'; |  | ||||||
|  |  | ||||||
| import 'package:flame/src/text/common/sprite_font.dart'; |  | ||||||
| import 'package:flame/src/text/formatters/sprite_font_text_formatter.dart'; |  | ||||||
| import 'package:flame/src/text/text_renderer.dart'; |  | ||||||
|  |  | ||||||
| /// [TextRenderer] implementation that uses a spritesheet of various font glyphs |  | ||||||
| /// to render text. |  | ||||||
| /// |  | ||||||
| /// For example, suppose there is a spritesheet with sprites for characters from |  | ||||||
| /// A to Z. Mapping these sprites into a [SpriteFontRenderer] allows then to |  | ||||||
| /// write text using these sprite images as the font. |  | ||||||
| /// |  | ||||||
| /// Currently, this class supports monospace fonts only -- the widths and the |  | ||||||
| /// heights of all characters must be the same. |  | ||||||
| /// Extra space between letters can be added via the `letterSpacing` parameter |  | ||||||
| /// (it can also be negative to "squish" characters together). Finally, the |  | ||||||
| /// `scale` parameter allows scaling the font to be bigger/smaller relative to |  | ||||||
| /// its size in the source image. |  | ||||||
| /// |  | ||||||
| /// The `paint` parameter is used to composite the character images onto the |  | ||||||
| /// canvas. Its default value will draw the character images as-is. Changing |  | ||||||
| /// the opacity of the paint's color will make the text semi-transparent. |  | ||||||
| class SpriteFontRenderer extends TextRenderer<SpriteFontTextFormatter> { |  | ||||||
|   SpriteFontRenderer.fromFont( |  | ||||||
|     SpriteFont font, { |  | ||||||
|     Color? color, |  | ||||||
|     double scale = 1, |  | ||||||
|     double letterSpacing = 0, |  | ||||||
|   }) : super( |  | ||||||
|           SpriteFontTextFormatter.fromFont( |  | ||||||
|             font, |  | ||||||
|             scale: scale, |  | ||||||
|             letterSpacing: letterSpacing, |  | ||||||
|             color: color, |  | ||||||
|           ), |  | ||||||
|         ); |  | ||||||
| } |  | ||||||
| @ -1,5 +1,5 @@ | |||||||
| import 'package:flame/src/text/formatters/text_formatter.dart'; | import 'package:flame/src/text/renderers/text_paint.dart'; | ||||||
| import 'package:flame/src/text/formatters/text_painter_text_formatter.dart'; | import 'package:flame/src/text/renderers/text_renderer.dart'; | ||||||
| import 'package:flame/src/text/styles/style.dart'; | import 'package:flame/src/text/styles/style.dart'; | ||||||
| import 'package:flutter/rendering.dart'; | import 'package:flutter/rendering.dart'; | ||||||
| import 'package:meta/meta.dart'; | import 'package:meta/meta.dart'; | ||||||
| @ -24,7 +24,7 @@ class FlameTextStyle extends Style { | |||||||
|   final FontStyle? fontStyle; |   final FontStyle? fontStyle; | ||||||
|   final double? letterSpacing; |   final double? letterSpacing; | ||||||
|  |  | ||||||
|   late final TextFormatter formatter = asTextFormatter(); |   late final TextRenderer renderer = asTextRenderer(); | ||||||
|  |  | ||||||
|   @override |   @override | ||||||
|   FlameTextStyle copyWith(FlameTextStyle other) { |   FlameTextStyle copyWith(FlameTextStyle other) { | ||||||
| @ -40,8 +40,8 @@ class FlameTextStyle extends Style { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   @internal |   @internal | ||||||
|   TextPainterTextFormatter asTextFormatter() { |   TextPaint asTextRenderer() { | ||||||
|     return TextPainterTextFormatter( |     return TextPaint( | ||||||
|       style: TextStyle( |       style: TextStyle( | ||||||
|         color: color, |         color: color, | ||||||
|         fontFamily: fontFamily, |         fontFamily: fontFamily, | ||||||
|  | |||||||
| @ -1,44 +0,0 @@ | |||||||
| import 'dart:ui'; |  | ||||||
|  |  | ||||||
| import 'package:flame/src/anchor.dart'; |  | ||||||
| import 'package:flame/text.dart'; |  | ||||||
| import 'package:vector_math/vector_math_64.dart'; |  | ||||||
|  |  | ||||||
| /// [TextRenderer] is the most basic API for drawing text. |  | ||||||
| /// |  | ||||||
| /// A text renderer contains a [formatter] that embodies a particular style |  | ||||||
| /// for rendering text, such as font-family, color, size, and so on. |  | ||||||
| /// At the same time, nor the text renderer or the [formatter] are tied to a |  | ||||||
| /// specific string -- it can render any text fragment that you give it. |  | ||||||
| /// |  | ||||||
| /// A text renderer object has two functions: to measure the size of a text |  | ||||||
| /// string that it will have when rendered, and to actually render that string |  | ||||||
| /// onto a canvas. |  | ||||||
| /// |  | ||||||
| /// [TextRenderer] is a low-level API that may be somewhat inconvenient to use |  | ||||||
| /// directly. Instead, consider using components such as TextComponent or |  | ||||||
| /// TextBoxComponent. |  | ||||||
| /// |  | ||||||
| /// See [TextFormatter] for more information about existing options. |  | ||||||
| class TextRenderer<T extends TextFormatter> { |  | ||||||
|   TextRenderer(this.formatter); |  | ||||||
|  |  | ||||||
|   final T formatter; |  | ||||||
|  |  | ||||||
|   TextElement format(String text) { |  | ||||||
|     return formatter.format(text); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   LineMetrics getLineMetrics(String text) { |  | ||||||
|     return format(text).metrics; |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   void render( |  | ||||||
|     Canvas canvas, |  | ||||||
|     String text, |  | ||||||
|     Vector2 position, { |  | ||||||
|     Anchor anchor = Anchor.topLeft, |  | ||||||
|   }) { |  | ||||||
|     format(text).render(canvas, position, anchor: anchor); |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| @ -1,3 +1,5 @@ | |||||||
|  | export 'package:flutter/painting.dart' show TextStyle; | ||||||
|  |  | ||||||
| export 'src/text/common/glyph.dart' show Glyph; | export 'src/text/common/glyph.dart' show Glyph; | ||||||
| export 'src/text/common/line_metrics.dart' show LineMetrics; | export 'src/text/common/line_metrics.dart' show LineMetrics; | ||||||
| export 'src/text/common/sprite_font.dart' show SpriteFont; | export 'src/text/common/sprite_font.dart' show SpriteFont; | ||||||
| @ -10,11 +12,6 @@ export 'src/text/elements/sprite_font_text_element.dart' | |||||||
| export 'src/text/elements/text_element.dart' show TextElement; | export 'src/text/elements/text_element.dart' show TextElement; | ||||||
| export 'src/text/elements/text_painter_text_element.dart' | export 'src/text/elements/text_painter_text_element.dart' | ||||||
|     show TextPainterTextElement; |     show TextPainterTextElement; | ||||||
| export 'src/text/formatters/sprite_font_text_formatter.dart' |  | ||||||
|     show SpriteFontTextFormatter; |  | ||||||
| export 'src/text/formatters/text_formatter.dart' show TextFormatter; |  | ||||||
| export 'src/text/formatters/text_painter_text_formatter.dart' |  | ||||||
|     show TextPainterTextFormatter; |  | ||||||
| export 'src/text/nodes/block_node.dart' show BlockNode; | export 'src/text/nodes/block_node.dart' show BlockNode; | ||||||
| export 'src/text/nodes/bold_text_node.dart' show BoldTextNode; | export 'src/text/nodes/bold_text_node.dart' show BoldTextNode; | ||||||
| export 'src/text/nodes/column_node.dart' show ColumnNode; | export 'src/text/nodes/column_node.dart' show ColumnNode; | ||||||
| @ -26,12 +23,12 @@ export 'src/text/nodes/paragraph_node.dart' show ParagraphNode; | |||||||
| export 'src/text/nodes/plain_text_node.dart' show PlainTextNode; | export 'src/text/nodes/plain_text_node.dart' show PlainTextNode; | ||||||
| export 'src/text/nodes/text_block_node.dart' show TextBlockNode; | export 'src/text/nodes/text_block_node.dart' show TextBlockNode; | ||||||
| export 'src/text/nodes/text_node.dart' show TextNode; | export 'src/text/nodes/text_node.dart' show TextNode; | ||||||
| export 'src/text/sprite_font_renderer.dart' show SpriteFontRenderer; | export 'src/text/renderers/sprite_font_renderer.dart' show SpriteFontRenderer; | ||||||
|  | export 'src/text/renderers/text_paint.dart' show TextPaint; | ||||||
|  | export 'src/text/renderers/text_renderer.dart' show TextRenderer; | ||||||
|  | export 'src/text/renderers/text_renderer_factory.dart' show TextRendererFactory; | ||||||
| export 'src/text/styles/background_style.dart' show BackgroundStyle; | export 'src/text/styles/background_style.dart' show BackgroundStyle; | ||||||
| export 'src/text/styles/block_style.dart' show BlockStyle; | export 'src/text/styles/block_style.dart' show BlockStyle; | ||||||
| export 'src/text/styles/document_style.dart' show DocumentStyle; | export 'src/text/styles/document_style.dart' show DocumentStyle; | ||||||
| export 'src/text/styles/flame_text_style.dart' show FlameTextStyle; | export 'src/text/styles/flame_text_style.dart' show FlameTextStyle; | ||||||
| export 'src/text/styles/style.dart' show Style; | export 'src/text/styles/style.dart' show Style; | ||||||
| export 'src/text/text_paint.dart' show TextPaint; |  | ||||||
| export 'src/text/text_renderer.dart' show TextRenderer; |  | ||||||
| export 'src/text/text_renderer_factory.dart' show TextRendererFactory; |  | ||||||
|  | |||||||
| @ -1,9 +1,8 @@ | |||||||
| import 'dart:ui' hide TextStyle; | import 'dart:ui'; | ||||||
|  |  | ||||||
| import 'package:canvas_test/canvas_test.dart'; | import 'package:canvas_test/canvas_test.dart'; | ||||||
| import 'package:flame/components.dart'; | import 'package:flame/components.dart'; | ||||||
| import 'package:flame/palette.dart'; | import 'package:flame/palette.dart'; | ||||||
| import 'package:flame/text.dart'; |  | ||||||
| import 'package:flame_test/flame_test.dart'; | import 'package:flame_test/flame_test.dart'; | ||||||
| import 'package:flutter_test/flutter_test.dart'; | import 'package:flutter_test/flutter_test.dart'; | ||||||
|  |  | ||||||
| @ -193,7 +192,7 @@ class _FramedTextBox extends TextBoxComponent { | |||||||
|     super.position, |     super.position, | ||||||
|     super.size, |     super.size, | ||||||
|   }) : super( |   }) : super( | ||||||
|           textRenderer: TextRenderer(DebugTextFormatter(fontSize: 22)), |           textRenderer: DebugTextRenderer(fontSize: 22), | ||||||
|         ); |         ); | ||||||
|  |  | ||||||
|   final Paint _borderPaint = Paint() |   final Paint _borderPaint = Paint() | ||||||
|  | |||||||
| @ -12,10 +12,10 @@ void main() { | |||||||
|   group('SpriteFontRenderer', () { |   group('SpriteFontRenderer', () { | ||||||
|     test('creating SpriteFontRenderer', () async { |     test('creating SpriteFontRenderer', () async { | ||||||
|       final renderer = await createRenderer(); |       final renderer = await createRenderer(); | ||||||
|       expect(renderer.formatter.font.source, isA<Image>()); |       expect(renderer.font.source, isA<Image>()); | ||||||
|       expect(renderer.formatter.font.size, 6); |       expect(renderer.font.size, 6); | ||||||
|       expect(renderer.formatter.scale, 1.0); |       expect(renderer.scale, 1.0); | ||||||
|       expect(renderer.formatter.letterSpacing, 0); |       expect(renderer.letterSpacing, 0); | ||||||
|  |  | ||||||
|       expect( |       expect( | ||||||
|         () => renderer.render(MockCanvas(), 'Ї', Vector2.zero()), |         () => renderer.render(MockCanvas(), 'Ї', Vector2.zero()), | ||||||
| @ -48,7 +48,7 @@ void main() { | |||||||
|           TextComponent( |           TextComponent( | ||||||
|             text: 'FLAME', |             text: 'FLAME', | ||||||
|             textRenderer: (await createRenderer(scale: 25)) |             textRenderer: (await createRenderer(scale: 25)) | ||||||
|               ..formatter.paint.color = const Color(0x44000000), |               ..paint.color = const Color(0x44000000), | ||||||
|             position: Vector2(400, 500), |             position: Vector2(400, 500), | ||||||
|             anchor: Anchor.center, |             anchor: Anchor.center, | ||||||
|           ), |           ), | ||||||
|  | |||||||
| @ -32,11 +32,7 @@ void main() { | |||||||
|   }); |   }); | ||||||
| } | } | ||||||
|  |  | ||||||
| class _CustomTextRenderer extends TextRenderer<_CustomTextFormatter> { | class _CustomTextRenderer extends TextRenderer { | ||||||
|   _CustomTextRenderer() : super(_CustomTextFormatter()); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| class _CustomTextFormatter extends TextFormatter { |  | ||||||
|   @override |   @override | ||||||
|   TextElement format(String text) { |   TextElement format(String text) { | ||||||
|     return CustomTextElement(); |     return CustomTextElement(); | ||||||
|  | |||||||
| @ -1,6 +1,6 @@ | |||||||
| export 'src/close_to_aabb.dart' show closeToAabb; | export 'src/close_to_aabb.dart' show closeToAabb; | ||||||
| export 'src/close_to_vector.dart'; | export 'src/close_to_vector.dart'; | ||||||
| export 'src/debug_text_formatter.dart' show DebugTextFormatter; | export 'src/debug_text_renderer.dart' show DebugTextRenderer; | ||||||
| export 'src/expect_double.dart'; | export 'src/expect_double.dart'; | ||||||
| export 'src/fails_assert.dart'; | export 'src/fails_assert.dart'; | ||||||
| export 'src/flame_test.dart'; | export 'src/flame_test.dart'; | ||||||
|  | |||||||
| @ -8,8 +8,8 @@ import 'package:flame/text.dart'; | |||||||
| /// Rendering regular text in golden tests is unreliable due to differences in | /// Rendering regular text in golden tests is unreliable due to differences in | ||||||
| /// font definitions across platforms and different algorithms used for anti- | /// font definitions across platforms and different algorithms used for anti- | ||||||
| /// aliasing. | /// aliasing. | ||||||
| class DebugTextFormatter extends TextFormatter { | class DebugTextRenderer extends TextRenderer { | ||||||
|   DebugTextFormatter({ |   DebugTextRenderer({ | ||||||
|     this.color = const Color(0xFFFFFFFF), |     this.color = const Color(0xFFFFFFFF), | ||||||
|     this.fontSize = 16.0, |     this.fontSize = 16.0, | ||||||
|     this.lineHeight = 1.2, |     this.lineHeight = 1.2, | ||||||
| @ -45,7 +45,7 @@ class _DebugTextElement extends TextElement { | |||||||
|     _initRects(charWidth, charHeight); |     _initRects(charWidth, charHeight); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   final DebugTextFormatter style; |   final DebugTextRenderer style; | ||||||
|   final String text; |   final String text; | ||||||
|   final List<Rect> rects = []; |   final List<Rect> rects = []; | ||||||
|   final Paint paint = Paint(); |   final Paint paint = Paint(); | ||||||
| @ -12,26 +12,26 @@ void main() { | |||||||
|       (game) async { |       (game) async { | ||||||
|         game.add( |         game.add( | ||||||
|           TextElementsComponent([ |           TextElementsComponent([ | ||||||
|             DebugTextFormatter().format('one two  three')..translate(5, 5), |             DebugTextRenderer().format('one two  three')..translate(5, 5), | ||||||
|             DebugTextFormatter().format(' x ')..translate(5, 25), |             DebugTextRenderer().format(' x ')..translate(5, 25), | ||||||
|             DebugTextFormatter().format('  ')..translate(5, 45), |             DebugTextRenderer().format('  ')..translate(5, 45), | ||||||
|             DebugTextFormatter().format('')..translate(25, 45), |             DebugTextRenderer().format('')..translate(25, 45), | ||||||
|             DebugTextFormatter(color: const Color(0xFFFF88AA)) |             DebugTextRenderer(color: const Color(0xFFFF88AA)) | ||||||
|                 .format('Flame Engine') |                 .format('Flame Engine') | ||||||
|               ..translate(5, 65), |               ..translate(5, 65), | ||||||
|             DebugTextFormatter(fontWeight: FontWeight.bold).format('Blue Fire') |             DebugTextRenderer(fontWeight: FontWeight.bold).format('Blue Fire') | ||||||
|               ..translate(5, 85), |               ..translate(5, 85), | ||||||
|             DebugTextFormatter(fontWeight: FontWeight.w900).format('Blue Fire') |             DebugTextRenderer(fontWeight: FontWeight.w900).format('Blue Fire') | ||||||
|               ..translate(5, 105), |               ..translate(5, 105), | ||||||
|             DebugTextFormatter(fontStyle: FontStyle.italic).format('Blue Fire') |             DebugTextRenderer(fontStyle: FontStyle.italic).format('Blue Fire') | ||||||
|               ..translate(5, 125), |               ..translate(5, 125), | ||||||
|             DebugTextFormatter( |             DebugTextRenderer( | ||||||
|               fontWeight: FontWeight.bold, |               fontWeight: FontWeight.bold, | ||||||
|               fontStyle: FontStyle.italic, |               fontStyle: FontStyle.italic, | ||||||
|               color: const Color(0xFF0088FF), |               color: const Color(0xFF0088FF), | ||||||
|             ).format('a b c d e f g h i') |             ).format('a b c d e f g h i') | ||||||
|               ..translate(5, 145), |               ..translate(5, 145), | ||||||
|             DebugTextFormatter(fontSize: 10).format('www.flame-engine.org') |             DebugTextRenderer(fontSize: 10).format('www.flame-engine.org') | ||||||
|               ..translate(5, 165), |               ..translate(5, 165), | ||||||
|           ]), |           ]), | ||||||
|         ); |         ); | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user
	 Luan Nico
					Luan Nico