Skip to content

Painter paint() is offset after canvas.rotate() #164958

@Milvintsiss

Description

@Milvintsiss

This was introduced in 3.29.1, all versions before (including 3.29.0) don't have this issue.
Issue is present both on Android and iOS.

Steps to reproduce

  1. Draw something on the canvas
  2. Use canvas.save()
  3. Use canvas.rotate()
  4. Draw another thing
  5. Use canvas.restore()

Expected results

See attached images

Actual results

See attached images

Code sample

Code sample
import 'dart:math';

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(home: const MyHomePage());
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key});

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text('Custom Paint widget with 3.29.0 :'),
            CustomPaint(painter: MyCustomPainter(), size: const Size(100, 100)),
          ],
        ),
      ),
    );
  }
}

class MyCustomPainter extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
    double radius = size.longestSide / 2 - 15.0;

    final center = Offset(size.longestSide / 2, size.longestSide / 2);

    canvas.drawCircle(center, radius, Paint()..color = Colors.grey);

    TextPainter painter = TextPainter(textDirection: TextDirection.ltr);
    painter.text = TextSpan(
      text: "test",
      style: TextStyle(
        fontSize: radius * 2 / 3,
        color: Colors.black,
      ),
    );
    painter.layout();
    canvas.save();
    final offset = Offset(
      center.dx - painter.width / 2,
      center.dy - painter.height / 2,
    );
    final pivot = painter.size.center(offset);
    canvas.translate(pivot.dx, pivot.dy);
    canvas.rotate(pi);
    canvas.translate(-pivot.dx, -pivot.dy);
    painter.paint(canvas, offset);
    canvas.restore();
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    return false;
  }
}

Screenshots or Video

Screenshots / Video demonstration

|||


|||

Logs

Logs
[Paste your logs here]

Flutter Doctor output

Doctor output
[✓] Flutter (Channel stable, 3.29.1, on macOS 13.7.4 22H420 darwin-x64, locale en-US)
[✓] Android toolchain - develop for Android devices (Android SDK version 35.0.0-rc1)
[✓] Xcode - develop for iOS and macOS (Xcode 15.2)
[✓] Chrome - develop for the web
[✓] Android Studio (version 2024.3)
[✓] Android Studio (version 2023.2)
[✓] IntelliJ IDEA Ultimate Edition (version 2024.3.4)
[✓] VS Code (version 1.97.2)
[✓] Connected device (4 available)
[✓] Network resources

• No issues found!

Metadata

Metadata

Assignees

No one assigned

    Labels

    c: regressionIt was better in the past than it is nowengineflutter/engine related. See also e: labels.found in release: 3.29Found to occur in 3.29has reproducible stepsThe issue has been confirmed reproducible and is ready to work onr: fixedIssue is closed as already fixed in a newer versionteam-engineOwned by Engine team

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions