30

I am wondering why and when you would use Canvas.save, Canvas.restore, and maybe even Canvas.saveLayer.
I have heard that they are really useful, but I do not know when to use them.

1
  • 1
    fun fact : im using your repo and also wonder what save and store did rofl ( funvas btw ) Commented Nov 1, 2022 at 11:25

1 Answer 1

46

Canvas.save and Canvas.saveLayer work slightly differently, but they both have the same counterpart:

Canvas.restore

This allows you to restore the state before the most recent entry on the save stack, i.e. it "Pops the current save stack". This means that any transformations and clips done to the canvas in the current state will be removed and if saveLayer was used, the saved layer will be composited into the canvas (the draw order will remain the same).

Canvas.save

As I mentioned earlier, this allows you to save the state the canvas is in. You can do any transformation and clips you want and those will be removed using restore:

canvas.save();

canvas.transform(..); // Transforms the canvas, which will affect the draw call.
canvas.drawRect(...); // Affected by the transform.

canvas.restore();

canvas.drawRect(...); // Not affected by the transform.

You can use any number of save before restore and the stack will remember all entries, i.e. restore will always pop the most recent entry.

When would I use this?

Example: if you wanted to rotate a single piece when drawing a bigger picture, you can simply do the rotation inside a save-restore block and draw something without the rotation on top afterwards.

Note that all children of a RenderObject will use the same PaintingContext, i.e. the same Canvas. So if you transform the canvas in a single child, it will also be transformed for all other children that draw afterwards. This is potentially unwanted behavior and the reason why you always want to save and restore the canvas state.

Canvas.saveLayer

This is a bit more complicated and I urge you to read the comprehensive documentation of this method. Btw, saveLayer does not work in Flutter web as of January, 2019.

The basic difference between saveLayer and save is that saveLayer will composite the layer upon usage of restore. For a simple example, I constructed this snippet without bounds (which is why null is passed), which will save the whole canvas:

canvas.drawRect(rect, Paint()..color = const Color(0xffff0000)); // Draws a red rect.
canvas.saveLayer(null, Paint()..blendMode = BlendMode.multiply); // Saves the whole canvas.

canvas.drawRect(
  rect.shift(const Offset(20, 20)),
  Paint()..color = const Color(0xff0000ff), // Draws a blue rect.
);

canvas.restore(); // Composites the red rect into the blue rect.

Screen capture

Note that the blue rect will still be composited above the red rect.

This example could also be achieved without using saveLayer because the Paint.blendMode I used can also be passed to Canvas.drawRect. However, when using e.g. a TextPainter, you cannot pass blend modes. Additionally, saveLayer allows you to pass bounds, which gives far more possibilites (read the documentation for more information, also about clips). Clipping is actually probably the most useful operation in combination with saveLayer - I did not include it in order to have a simple example.

This is how the example would look without saveLayer:

Screen capture

Sign up to request clarification or add additional context in comments.

7 Comments

I appreciate your interesting questions and answers. But I was wondering why you create these questions and reply to them immediately. Wouldn't it make more sense to write an article about it?
@JoãoSoares Nice question :) So why I create them: This and with this one I answered a question on Twitter - I actually linked to it in my question. Generally, I do this when I ask myself something and think it would be useful for others to find out what my research has shown. For example, turns out this question was extremely popular after I asked about it - I was able to help many people.
@JoãoSoares As I accept my own answers in that case (to show that the question has an answer), I could also write articles, yes. I will be getting into writing articles - I recently wrote this "test" article (maybe it is interesting to you). However, I see a few benefits to writing an answer in this article style on SO: it is more concise and easier to find, probably helps more people and there are less expectations.
@JoãoSoares I will try to write an article about render objects and stuff (in connection to the Flutter Clock challenge) soon and then I can see how that works out for me. If you have any feedback about my style of writing or w/e or any questions in general, just HMU. I am glad to answer them :)
Thank you for the replies. I am definitely interested. I love Flutter and have dedicated a lot of time to it. Learning more is always great and it looks like you have a lot to teach. Thank you for sharing.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.