Skip to content

[Impeller] RawMagnifier doesn't render at particular coordinates #136058

@gaaclarke

Description

@gaaclarke

This spawned off from #126583

cc @gerken-tss

original comment (link)

Soo …

Sorry I got you waiting. I was a little busy and it took me some time to isolate the issue.
But now I have an easy-to-test example!

First the symptoms:

Screen.Recording.2023-07-05.at.17.19.41.mov

As you can see, the BackDropFilter that is being used by RawMagnifier widget here behaves strangely. While the right part of the image is being scaled properly within the magnifier, when I cross a certain threshold with the cursor, it kind of skips an area of the image.

I had a look into the implementation of RawMagnifier and saw that Matrix4 is in use there.

Now the code:

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: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final double _size = 160;
  Offset _position = Offset.zero;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Stack(
        children: [
          GestureDetector(
            onPanUpdate: (DragUpdateDetails details) {
              final RenderBox? box = context.findRenderObject() as RenderBox?;

              setState(() {
                _position = _calculateFocalPointOffset(
                  box,
                  details.globalPosition,
                );
              });
            },
            child: Wrap(
              children: [
                for (int i = 1; i <= 100; i++)
                  Container(
                    width: 32,
                    height: 32,
                    color: i % 2 == 0 ? Colors.red : Colors.green,
                  ),
              ],
            ),
          ),
          Align(
            alignment: Alignment.topRight,
            child: RawMagnifier(
              decoration: MagnifierDecoration(
                shape: CircleBorder(
                  side: BorderSide(
                    color: Theme.of(context).primaryColor,
                    width: 5,
                  ),
                ),
              ),
              size: Size(_size, _size),
              focalPointOffset: _position,
              magnificationScale: 2.0,
            ),
          ),
        ],
      ),
    );
  }

  Offset _calculateFocalPointOffset(RenderBox? box, Offset globalTouchPoint) {
    return Offset(
      globalTouchPoint.dx - (box?.size.width ?? 0) + (_size / 2),
      globalTouchPoint.dy - (_size / 2),
    );
  }
}

You can just copy this off into the main.dart file of your application and run it. By dragging over the green-red-tiled widget you control the focal point of the magnifier.
I replaced the image asset by this tiled widget in order for you to have no dependencies of downloading an image before running it.

  • If you run this application in the iOS simulator (or real device) with impeller, you get the same behaviour as in the video
  • If you run it with the --no-enable-impeller flag, everything works fine
  • I also realized that replacing the Alignment widget with a Positioned widget makes it work. But in any case, the behaviour should not differ at all between the impeller app and the skia app.

I also tested re-implementing the RawMagnifier widget with my own implementation using a Matrix4 and I got the same results, so it's nothing related to this particular Magnifier widget.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P1High-priority issues at the top of the work liste: impellerImpeller rendering backend issues and features requestsengineflutter/engine related. See also e: labels.team-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