Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Refactor BitmapCanvas. Fix image compositing bug #15114

Closed
wants to merge 6 commits into from

Conversation

ferhatb
Copy link
Contributor

@ferhatb ferhatb commented Jan 3, 2020

Added endOfPaint call on recording canvas to allow bitmap canvas to dispose after reuse.
Moved all immediate canvas calls from BitmapCanvas into CanvasPool.
Reduced context updates by creating ContextHandle class.
Added regression tests for drawing on top of image in a single Picture.

Fixes flutter/flutter#44845
Fixes flutter/flutter#48032

@googlebot
Copy link

We found a Contributor License Agreement for you (the sender of this pull request), but were unable to find agreements for all the commit author(s) or Co-authors. If you authored these, maybe you used a different email address in the git commits than was used to sign the CLA (login here to double check)? If these were authored by someone else, then they will need to sign a CLA as well, and confirm that they're okay with these being contributed to Google.
In order to pass this check, please resolve this problem and then comment @googlebot I fixed it.. If the bot doesn't comment, it means it doesn't think anything has changed.

ℹ️ Googlers: Go here for more info.

1 similar comment
@googlebot
Copy link

We found a Contributor License Agreement for you (the sender of this pull request), but were unable to find agreements for all the commit author(s) or Co-authors. If you authored these, maybe you used a different email address in the git commits than was used to sign the CLA (login here to double check)? If these were authored by someone else, then they will need to sign a CLA as well, and confirm that they're okay with these being contributed to Google.
In order to pass this check, please resolve this problem and then comment @googlebot I fixed it.. If the bot doesn't comment, it means it doesn't think anything has changed.

ℹ️ Googlers: Go here for more info.

@googlebot googlebot added cla: no and removed cla: yes labels Jan 6, 2020
_canvas.style.transform = '';
_canvasPool.reuse();
_setupInitialTransform();
_canvasPool.contextHandle.reset();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems the logic for resetting the context handle can move into _CanvasPool.reuse().

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lazy allocation changes this quite a bit where initialTransform becomes setter. Not addressing in this PR.

-_bounds.top + canvasPositionCorrectionY + kPaddingPixels,
);
// Returns a data URI containing a representation of the image in this
// canvas.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

///?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@@ -0,0 +1,694 @@
part of engine;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file needs a license header.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@@ -0,0 +1,694 @@
part of engine;

class _CanvasPool extends _SaveStackTracking {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although this class is private it's pretty non-trivial, so some docs could help understand what it does in the future.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

}
if (_reusablePool != null && _reusablePool.isNotEmpty) {
_canvas = _reusablePool[0];
_reusablePool.removeAt(0);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_canvas = _reusablePool.removeAt(0); will save one list look-up.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

});

test('Inner RRect not completely inside Outer RRect', () {
underTest.drawDRRect(rrect, rrect.deflate(1).shift(const Offset(0.0, 10)), somePaint);
underTest.apply(mockCanvas);
// Expect nothing to be called
expect(mockCanvas.methodCallLog.length, equals(0));
expect(mockCanvas.methodCallLog.length, equals(1));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

});

test('Inner RRect same as Outer RRect', () {
underTest.drawDRRect(rrect, rrect, somePaint);
underTest.apply(mockCanvas);
// Expect nothing to be called
expect(mockCanvas.methodCallLog.length, equals(0));
expect(mockCanvas.methodCallLog.length, equals(1));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@@ -50,6 +50,7 @@ void main() async {
RecordingCanvas(const Rect.fromLTRB(0, 0, 400, 300));
rc.save();
rc.drawImage(createTestImage(), Offset(0, 0), new Paint());
rc.restore();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Restores are optional in Flutter AFAIK. What happens if you do not call it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed [_CanvasPool] to count save/restore to handle case.

// Circle should draw on top of image not below.
test('Paints on top of image', () async {
final RecordingCanvas rc =
RecordingCanvas(const Rect.fromLTRB(0, 0, 400, 300));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: indentation is off (throughout the file)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dartfmt Done.


// Regression test for https://github.com/flutter/flutter/issues/44845
// Circle should draw on top of image not below.
test('Paints on top of image', () async {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should also have a test that checks that we can still paint under the image :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ferhatb ferhatb closed this Jan 6, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
3 participants