import 'dart:ui' as ui;

import 'package:flutter/material.dart';

class GradientText extends StatelessWidget {
  const GradientText(
    this.text, {
    super.key,
    required this.gradient,
    this.style = const TextStyle(),
  });

  final String text;
  final TextStyle style;
  final Gradient gradient;

  @override
  Widget build(BuildContext context) {
    // Get exact size of the text view
    final TextPainter _painter = TextPainter(
        text: TextSpan(text: text, style: style),
        textDirection: TextDirection.rtl);
    // Call layout method so width and height of this text widget get measured
    _painter.layout();

    return CustomPaint(
      size: _painter.size,
      painter:
          _GradientTextPainter(text: text, style: style, gradient: gradient),
    );
  }
}

class _GradientTextPainter extends CustomPainter {
  _GradientTextPainter({
    required this.text,
    required this.style,
    required this.gradient,
  });
  final Gradient gradient;
  final String text;
  final TextStyle style;

  @override
  void paint(Canvas canvas, Size size) {
    final Paint _gradientShaderPaint = Paint()
      ..shader = gradient
          .createShader(Rect.fromLTWH(0.0, 0.0, size.width, size.height));

    final ui.ParagraphBuilder _builder =
        ui.ParagraphBuilder(ui.ParagraphStyle())
          ..pushStyle(ui.TextStyle(
            foreground: _gradientShaderPaint,
            fontSize: style.fontSize,
            fontWeight: style.fontWeight,
            height: style.height,
            decoration: style.decoration,
            decorationColor: style.decorationColor,
            decorationStyle: style.decorationStyle,
            fontStyle: style.fontStyle,
            letterSpacing: style.letterSpacing,
            fontFamily: style.fontFamily,
            locale: style.locale,
            textBaseline: style.textBaseline,
            wordSpacing: style.wordSpacing,
          ))
          ..addText(text);

    final ui.Paragraph _paragraph = _builder.build();
    _paragraph.layout(ui.ParagraphConstraints(width: size.width));

    canvas.drawParagraph(_paragraph, Offset.zero);
  }

  @override
  bool shouldRepaint(_GradientTextPainter oldDelegate) {
    return gradient != oldDelegate.gradient ||
        text != oldDelegate.text ||
        style != oldDelegate.style;
  }
}