{"action":"created","issue":{"url":"https://api.github.com/repos/flutter/flutter/issues/24627","repository_url":"https://api.github.com/repos/flutter/flutter","labels_url":"https://api.github.com/repos/flutter/flutter/issues/24627/labels{/name}","comments_url":"https://api.github.com/repos/flutter/flutter/issues/24627/comments","events_url":"https://api.github.com/repos/flutter/flutter/issues/24627/events","html_url":"https://github.com/flutter/flutter/issues/24627","id":383264765,"node_id":"MDU6SXNzdWUzODMyNjQ3NjU=","number":24627,"title":"Transform.rotate is super slow","user":{"login":"arsen","id":3446647,"node_id":"MDQ6VXNlcjM0NDY2NDc=","avatar_url":"https://avatars3.githubusercontent.com/u/3446647?v=4","gravatar_id":"","url":"https://api.github.com/users/arsen","html_url":"https://github.com/arsen","followers_url":"https://api.github.com/users/arsen/followers","following_url":"https://api.github.com/users/arsen/following{/other_user}","gists_url":"https://api.github.com/users/arsen/gists{/gist_id}","starred_url":"https://api.github.com/users/arsen/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/arsen/subscriptions","organizations_url":"https://api.github.com/users/arsen/orgs","repos_url":"https://api.github.com/users/arsen/repos","events_url":"https://api.github.com/users/arsen/events{/privacy}","received_events_url":"https://api.github.com/users/arsen/received_events","type":"User","site_admin":false},"labels":[{"id":284438921,"node_id":"MDU6TGFiZWwyODQ0Mzg5MjE=","url":"https://api.github.com/repos/flutter/flutter/labels/engine","name":"engine","color":"003570","default":false},{"id":298590876,"node_id":"MDU6TGFiZWwyOTg1OTA4NzY=","url":"https://api.github.com/repos/flutter/flutter/labels/severe:%20performance","name":"severe: performance","color":"e11d21","default":false}],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":{"url":"https://api.github.com/repos/flutter/flutter/milestones/22","html_url":"https://github.com/flutter/flutter/milestone/22","labels_url":"https://api.github.com/repos/flutter/flutter/milestones/22/labels","id":2270094,"node_id":"MDk6TWlsZXN0b25lMjI3MDA5NA==","number":22,"title":"Goals","description":"P2: These are tasks we think are worth fixing in the coming years. It includes issues we've identified that might block fully shipping broad consumer-facing apps, correctness issues, and bugs relating to polish and quality.\r\n\r\nThe date on this milestone is utterly arbitrary and just intended to sort the milestone appropriately.","creator":{"login":"Hixie","id":551196,"node_id":"MDQ6VXNlcjU1MTE5Ng==","avatar_url":"https://avatars2.githubusercontent.com/u/551196?v=4","gravatar_id":"","url":"https://api.github.com/users/Hixie","html_url":"https://github.com/Hixie","followers_url":"https://api.github.com/users/Hixie/followers","following_url":"https://api.github.com/users/Hixie/following{/other_user}","gists_url":"https://api.github.com/users/Hixie/gists{/gist_id}","starred_url":"https://api.github.com/users/Hixie/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Hixie/subscriptions","organizations_url":"https://api.github.com/users/Hixie/orgs","repos_url":"https://api.github.com/users/Hixie/repos","events_url":"https://api.github.com/users/Hixie/events{/privacy}","received_events_url":"https://api.github.com/users/Hixie/received_events","type":"User","site_admin":false},"open_issues":1821,"closed_issues":779,"state":"open","created_at":"2017-01-23T00:27:59Z","updated_at":"2018-12-07T23:03:17Z","due_on":"2031-01-01T08:00:00Z","closed_at":null},"comments":2,"created_at":"2018-11-21T19:31:58Z","updated_at":"2018-12-07T23:49:20Z","closed_at":null,"author_association":"NONE","body":"I'm implementing a card swiping tinder like ui. Cards are being moved during onPanUpdate (within GestureDetector). \r\nWhen applying just regular Transform.translate it is super smooth, but with when I apply also Transform.rotate it is missing a lot of frames (even on iPhone X).\r\n\r\nThis is the sample code:\r\n```dart\r\nclass MemberCard extends StatelessWidget {\r\n  final double width;\r\n  final double height;\r\n  final String photo;\r\n  final double rotation;\r\n  final Offset offset;\r\n  final double scale;\r\n  final bool dropShadow;\r\n\r\n  MemberCard({\r\n    this.width,\r\n    this.height,\r\n    this.photo,\r\n    this.rotation = 0.0,\r\n    this.offset = const Offset(0.0, 0.0),\r\n    this.scale = 1.0,\r\n    this.dropShadow = false,\r\n  });\r\n\r\n  @override\r\n  Widget build(BuildContext context) {\r\n    double angle = rotation * (math.pi / 180.0);\r\n    var matrix = Matrix4.translationValues(offset.dx, offset.dy, 0.0);\r\n    if (scale != 1.0) {\r\n      matrix..scale(scale);\r\n    }\r\n    if (rotation != 0.0) {\r\n      matrix.rotateZ(angle);\r\n    }\r\n\r\n    return Transform(\r\n      alignment: Alignment.center,\r\n      transform: matrix,\r\n      child: Stack(\r\n        children: <Widget>[\r\n          RepaintBoundary(\r\n            child: Container(\r\n              width: width,\r\n              height: height,\r\n              decoration: BoxDecoration(\r\n                boxShadow: dropShadow\r\n                    ? [\r\n                        BoxShadow(\r\n                            color: Colors.black.withOpacity(0.4),\r\n                            blurRadius: 5.0,\r\n                            offset: Offset(0.0, 1.0))\r\n                      ]\r\n                    : [],\r\n                borderRadius: BorderRadius.all(Radius.circular(10.0)),\r\n                color: Colors.white,\r\n                // image: DecorationImage(\r\n                //   image: NetworkImage(photo),\r\n                //   fit: BoxFit.cover,\r\n                // ),\r\n              ),\r\n              child: ClipRRect(\r\n                borderRadius: BorderRadius.circular(10.0),\r\n                child: Image.network(\r\n                  photo,\r\n                  fit: BoxFit.cover,\r\n                  filterQuality: FilterQuality.none,\r\n                ),\r\n              ),\r\n            ),\r\n          ),\r\n        ],\r\n      ),\r\n    );\r\n  }\r\n}\r\n\r\n```"},"comment":{"url":"https://api.github.com/repos/flutter/flutter/issues/comments/445402844","html_url":"https://github.com/flutter/flutter/issues/24627#issuecomment-445402844","issue_url":"https://api.github.com/repos/flutter/flutter/issues/24627","id":445402844,"node_id":"MDEyOklzc3VlQ29tbWVudDQ0NTQwMjg0NA==","user":{"login":"liyuqian","id":22987568,"node_id":"MDQ6VXNlcjIyOTg3NTY4","avatar_url":"https://avatars2.githubusercontent.com/u/22987568?v=4","gravatar_id":"","url":"https://api.github.com/users/liyuqian","html_url":"https://github.com/liyuqian","followers_url":"https://api.github.com/users/liyuqian/followers","following_url":"https://api.github.com/users/liyuqian/following{/other_user}","gists_url":"https://api.github.com/users/liyuqian/gists{/gist_id}","starred_url":"https://api.github.com/users/liyuqian/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/liyuqian/subscriptions","organizations_url":"https://api.github.com/users/liyuqian/orgs","repos_url":"https://api.github.com/users/liyuqian/repos","events_url":"https://api.github.com/users/liyuqian/events{/privacy}","received_events_url":"https://api.github.com/users/liyuqian/received_events","type":"User","site_admin":false},"created_at":"2018-12-07T23:49:20Z","updated_at":"2018-12-07T23:49:20Z","author_association":"CONTRIBUTOR","body":"Rotation is much slower than translation because we can raster cache during translation, but we can't do it during rotation in order to be pixel perfect.\r\n\r\nFor example, an axis-aligned rectangle may not have any anti-aliased pixels, while a slightly rotated rectangle may have tons of anti-aliased pixels as shown below. Therefore we can't reuse the cached pixels with rotation. \r\n\r\nslightly rotated rectangle\r\n![image](https://user-images.githubusercontent.com/22987568/49677870-e9f29500-fa35-11e8-9b2f-eb6c03a9a5b0.png)\r\n\r\nthe anti-aliased pixels of the slightly rotated rectangle:\r\n![image](https://user-images.githubusercontent.com/22987568/49677861-d6dfc500-fa35-11e8-8abc-c31ca4fde799.png)\r\n\r\nIn your specific case, I guess that the shadow is an expensive operation and we currently can't draw a big shadow at 60fps without caching. A solution might be for you to do a snapshot of your shadowed image and rotate that snapshot every frame so Flutter won't try to paint an expensive but pixel-perfect shadow every frame.\r\n\r\nAnother possibility is for us to add an option to RepaintBoundary which enables raster cache during rotation with a sacrifice in fidelity.  @Hixie @chinmaygarde : what's your thought on adding that option to RepaintBoundary? (FYI, We will add raster cache option to RepaintBoundary for retained rendering.)"}}
{"actor":{"display_login":"liyuqian"}}