feat: Support text align on new text rendering pipeline (#3147)

Support text align on new text rendering pipeline.

![image](https://github.com/flame-engine/flame/assets/882703/62f91c8e-f38f-48b0-8c59-06efb10acdf3)

![image](https://github.com/flame-engine/flame/assets/882703/b00afb90-6051-4a2c-aac6-ac36ea1bcba2)
This commit is contained in:
Luan Nico
2024-05-06 08:13:10 -04:00
committed by GitHub
parent ce9392abd8
commit 194d553656
4 changed files with 44 additions and 2 deletions

View File

@ -67,7 +67,15 @@ void addRenderingStories(Dashbook dashbook) {
)
..add(
'Rich Text',
(_) => GameWidget(game: RichTextExample()),
(context) => GameWidget(
game: RichTextExample(
textAlign: context.listProperty(
'Text align',
TextAlign.left,
TextAlign.values,
),
),
),
codeLink: baseLink('rendering/rich_text_example.dart'),
info: RichTextExample.description,
);

View File

@ -4,6 +4,10 @@ import 'package:flame/text.dart';
import 'package:flutter/painting.dart';
class RichTextExample extends FlameGame {
final TextAlign textAlign;
RichTextExample({this.textAlign = TextAlign.left});
static const String description =
'A non-interactive example of how to render rich text in Flame.';
@ -23,11 +27,15 @@ class RichTextExample extends FlameGame {
),
paragraph: BlockStyle(
padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 16),
textAlign: textAlign,
background: BackgroundStyle(
color: const Color(0xFF004D40),
borderColor: const Color(0xFFAAAAAA),
),
),
header1: BlockStyle(
textAlign: textAlign,
),
);
final document = DocumentRoot([
HeaderNode.simple('1984', level: 1),

View File

@ -1,3 +1,5 @@
import 'dart:ui';
import 'package:flame/src/text/common/utils.dart';
import 'package:flame/src/text/elements/group_element.dart';
import 'package:flame/text.dart';
@ -26,6 +28,7 @@ abstract class TextBlockNode extends BlockNode {
final lines = <InlineTextElement>[];
final horizontalOffset = style.padding.left;
var verticalOffset = style.padding.top;
final textAlign = style.textAlign ?? TextAlign.left;
while (!layoutBuilder.isDone) {
final element = layoutBuilder.layOutNextLine(contentWidth);
if (element == null) {
@ -36,7 +39,12 @@ abstract class TextBlockNode extends BlockNode {
} else {
final metrics = element.metrics;
assert(metrics.left == 0 && metrics.baseline == 0);
element.translate(horizontalOffset, verticalOffset + metrics.ascent);
final dx = horizontalOffset +
(contentWidth - metrics.width) * _relativeOffset(textAlign);
final dy = verticalOffset + metrics.ascent;
element.translate(dx, dy);
lines.add(element);
verticalOffset += metrics.height;
}
@ -50,4 +58,19 @@ abstract class TextBlockNode extends BlockNode {
children: elements,
);
}
double _relativeOffset(TextAlign textAlign) {
return switch (textAlign) {
TextAlign.left => 0,
TextAlign.right => 1,
TextAlign.center => 0.5,
// NOTE: we do not support non-LRT text directions
TextAlign.start => 0,
TextAlign.end => 1,
// Not supported by Flame
TextAlign.justify => throw UnimplementedError(
'The text rendering pipeline cannot justify text.',
),
};
}
}

View File

@ -11,6 +11,7 @@ class BlockStyle extends FlameTextStyle {
EdgeInsets? padding,
this.background,
this.text,
this.textAlign,
}) : _margin = margin,
_padding = padding;
@ -18,6 +19,7 @@ class BlockStyle extends FlameTextStyle {
final EdgeInsets? _padding;
final BackgroundStyle? background;
final InlineTextStyle? text;
final TextAlign? textAlign;
EdgeInsets get margin => _margin ?? EdgeInsets.zero;
EdgeInsets get padding => _padding ?? EdgeInsets.zero;
@ -29,6 +31,7 @@ class BlockStyle extends FlameTextStyle {
padding: other._padding ?? _padding,
background: other.background ?? background,
text: FlameTextStyle.merge(text, other.text),
textAlign: other.textAlign ?? textAlign,
);
}
}