Skip to content

[Impeller] Round rects with elliptical radii broken. #133793

@flar

Description

@flar

I noticed this while looking through the code. SkRRect classifies simple RRects as rectangles that have the same radii at all 4 corners, but the 2 radii at each corner do not have to be the same. Impeller uses that property to assume that all radii at all corners are the same.

The following example shows the problem. It renders an RRect using drawRRect and then traces its expected outline using a compination of drawLine and drawArc methods. The two should match.

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(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

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

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text(widget.title),
      ),
      body: Center(
        child: CustomPaint(
          foregroundPainter: MyPainter(),
          size: Size(300, 300),
        ),
      ),
    );
  }
}

class MyPainter extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
    canvas.drawRRect(
      RRect.fromRectAndRadius(
        const Rect.fromLTRB(50, 50, 250, 250),
        const Radius.elliptical(60, 30),
      ),
      Paint()..color = Colors.green,
    );
    Paint strokePaint = Paint()
      ..color = Colors.purple
      ..strokeWidth = 3.0
      ..style = PaintingStyle.stroke;
    double q = 90 * pi / 180;
    canvas.drawLine(const Offset(110, 50), const Offset(190, 50), strokePaint);
    canvas.drawLine(const Offset(250, 80), const Offset(250, 220), strokePaint);
    canvas.drawLine(const Offset(190, 250), const Offset(110, 250), strokePaint);
    canvas.drawLine(const Offset(50, 220), const Offset(50, 80), strokePaint);
    canvas.drawArc(const Rect.fromLTRB(50, 50, 170, 110), q*2, q, false, strokePaint);
    canvas.drawArc(const Rect.fromLTRB(130, 50, 250, 110), q*3, q, false, strokePaint);
    canvas.drawArc(const Rect.fromLTRB(130, 190, 250, 250), 0, q, false, strokePaint);
    canvas.drawArc(const Rect.fromLTRB(50, 190, 170, 250), q, q, false, strokePaint);
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) => true;

}
Correct output from Skia Screenshot 2023-08-31 at 11 57 59 AM
Incorrect output from Impeller Screenshot 2023-08-31 at 11 58 16 AM

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Important issues not at the top of the work liste: impellerImpeller rendering backend issues and features requestsengineflutter/engine related. See also e: labels.found in release: 3.13Found to occur in 3.13found in release: 3.14Found to occur in 3.14good first issueRelatively approachable for first-time contributorshas 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 teamtriaged-engineTriaged by Engine team

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions