|
| 1 | +import 'dart:ui' as ui; |
1 | 2 | import 'package:flutter/material.dart'; |
2 | 3 | import 'package:flutter_text_decorator/src/modules/underline/base/underline_painter.dart'; |
| 4 | +import 'package:flutter_text_decorator/src/modules/underline/mixins/line_gap_mixin.dart'; |
3 | 5 |
|
4 | 6 | /// A [CustomPainter] that draws a curved or wavy underline beneath text. |
5 | 7 | /// |
@@ -28,39 +30,58 @@ import 'package:flutter_text_decorator/src/modules/underline/base/underline_pain |
28 | 30 | /// ), |
29 | 31 | /// ) |
30 | 32 | /// ``` |
31 | | -class CurvedUnderlinePainter extends UnderlinePainter { |
32 | | - CurvedUnderlinePainter({required this.text, required super.color, required super.strokeWidth, super.textStyle}); |
| 33 | +class CurvedUnderlinePainter extends UnderlinePainter with LineGap { |
| 34 | + CurvedUnderlinePainter({ |
| 35 | + required this.text, |
| 36 | + required super.color, |
| 37 | + required super.strokeWidth, |
| 38 | + this.curvyFactor = 3, |
| 39 | + super.textStyle, |
| 40 | + }); |
33 | 41 |
|
34 | 42 | final String text; |
| 43 | + final double curvyFactor; |
35 | 44 |
|
36 | 45 | @override |
37 | 46 | void paint(Canvas canvas, Size size) { |
38 | | - final textSpan = TextSpan(text: text, style: textStyle); |
39 | 47 | final textPainter = TextPainter( |
40 | | - text: textSpan, |
41 | | - textDirection: TextDirection.ltr, |
42 | | - )..layout(); |
| 48 | + text: TextSpan(text: text, style: textStyle ?? const TextStyle()), |
| 49 | + textDirection: ui.TextDirection.ltr, |
| 50 | + )..layout(maxWidth: size.width); |
43 | 51 |
|
44 | 52 | final paint = Paint() |
45 | 53 | ..color = color |
46 | 54 | ..style = PaintingStyle.stroke |
47 | 55 | ..strokeWidth = strokeWidth; |
48 | | - final path = Path() |
49 | | - ..moveTo(5, size.height * 1.1) |
50 | | - ..cubicTo( |
51 | | - size.width - textPainter.width / 2, |
52 | | - size.height + 1, |
53 | | - size.width - textPainter.width / 4, |
54 | | - size.height - 7, |
55 | | - size.width, |
56 | | - size.height, |
57 | | - ); |
58 | 56 |
|
59 | | - canvas.drawPath(path, paint); |
| 57 | + final lines = textPainter.computeLineMetrics(); |
| 58 | + |
| 59 | + double yOffset = 0; |
| 60 | + |
| 61 | + for (final line in lines) { |
| 62 | + final double startX = line.left; |
| 63 | + final double xEnd = startX + line.width; |
| 64 | + |
| 65 | + if (line.width <= 0) continue; |
| 66 | + |
| 67 | + yOffset += calculateGapBetweenLines(line: line, lineIndex: line.lineNumber, strokeWidth: strokeWidth); |
| 68 | + |
| 69 | + final double y1 = yOffset - strokeWidth * curvyFactor; |
| 70 | + final double y2 = yOffset + strokeWidth * curvyFactor; |
| 71 | + final double yEnd = yOffset; |
| 72 | + final double x1 = startX + xEnd * (1 / 3); |
| 73 | + final double x2 = startX + xEnd * (2 / 3); |
| 74 | + final double x3 = xEnd; |
| 75 | + final double y3 = yEnd; |
| 76 | + |
| 77 | + final Path path = Path() |
| 78 | + ..moveTo(startX, yOffset) |
| 79 | + ..cubicTo(x1, y1, x2, y2, x3, y3); |
| 80 | + |
| 81 | + canvas.drawPath(path, paint); |
| 82 | + } |
60 | 83 | } |
61 | 84 |
|
62 | 85 | @override |
63 | | - bool shouldRepaint(covariant CustomPainter oldDelegate) { |
64 | | - return false; |
65 | | - } |
| 86 | + bool shouldRepaint(covariant CustomPainter oldDelegate) => false; |
66 | 87 | } |
0 commit comments