mirror of
https://github.com/flame-engine/flame.git
synced 2025-11-01 10:38:17 +08:00
This PR continues the work for enabling rich text support within Flame. Here I add support for different text fragments having different TextStyles, and allow those styles to be inheritable within the text node tree.
97 lines
2.5 KiB
Dart
97 lines
2.5 KiB
Dart
import 'dart:ui';
|
|
|
|
import 'package:flame/text.dart';
|
|
|
|
/// Text formatter suitable for use in golden tests. This formatter renders
|
|
/// words as rectangles.
|
|
///
|
|
/// Rendering regular text in golden tests is unreliable due to differences in
|
|
/// font definitions across platforms and different algorithms used for anti-
|
|
/// aliasing.
|
|
class DebugTextFormatter extends TextFormatter {
|
|
DebugTextFormatter({
|
|
this.color = const Color(0xFFFFFFFF),
|
|
this.fontSize = 16.0,
|
|
this.lineHeight = 1.2,
|
|
this.fontWeight = FontWeight.normal,
|
|
this.fontStyle = FontStyle.normal,
|
|
});
|
|
|
|
final Color color;
|
|
final double fontSize;
|
|
final double lineHeight;
|
|
final FontWeight fontWeight;
|
|
final FontStyle fontStyle;
|
|
|
|
@override
|
|
TextElement format(String text) => _DebugTextElement(this, text);
|
|
}
|
|
|
|
class _DebugTextElement extends TextElement {
|
|
_DebugTextElement(this.style, this.text) {
|
|
final charWidth = style.fontSize * 1.0;
|
|
final charHeight = style.fontSize;
|
|
paint
|
|
..color = style.color
|
|
..style = PaintingStyle.stroke
|
|
..strokeWidth = 2.0 * (style.fontWeight.index + 1) / 4;
|
|
metrics = LineMetrics(
|
|
width: text.length * charWidth,
|
|
ascent: charHeight * (style.lineHeight + 1) / 2,
|
|
descent: charHeight * (style.lineHeight - 1) / 2,
|
|
baseline: charHeight * (style.lineHeight + 1) / 2,
|
|
);
|
|
assert(metrics.left == 0 && metrics.top == 0);
|
|
_initRects(charWidth, charHeight);
|
|
}
|
|
|
|
final DebugTextFormatter style;
|
|
final String text;
|
|
final List<Rect> rects = [];
|
|
final Paint paint = Paint();
|
|
@override
|
|
late final LineMetrics metrics;
|
|
|
|
@override
|
|
void render(Canvas canvas) {
|
|
canvas.save();
|
|
if (style.fontStyle == FontStyle.italic) {
|
|
canvas.skew(-0.25, 0);
|
|
canvas.translate(metrics.bottom * 0.25, 0);
|
|
}
|
|
for (final rect in rects) {
|
|
canvas.drawRect(rect, paint);
|
|
}
|
|
canvas.restore();
|
|
}
|
|
|
|
@override
|
|
void translate(double dx, double dy) {
|
|
metrics.translate(dx, dy);
|
|
for (var i = 0; i < rects.length; i++) {
|
|
rects[i] = rects[i].translate(dx, dy);
|
|
}
|
|
}
|
|
|
|
void _initRects(double charWidth, double charHeight) {
|
|
var i0 = 0;
|
|
while (true) {
|
|
while (i0 < text.length && text[i0] == ' ') {
|
|
i0 += 1;
|
|
}
|
|
if (i0 == text.length) {
|
|
break;
|
|
}
|
|
var i1 = i0;
|
|
while (i1 < text.length && text[i1] != ' ') {
|
|
i1 += 1;
|
|
}
|
|
rects.add(
|
|
Rect.fromLTRB(i0 * charWidth, 0, i1 * charWidth, charHeight)
|
|
.deflate(paint.strokeWidth / 2),
|
|
);
|
|
i0 = i1;
|
|
}
|
|
}
|
|
}
|