Repository: flutter
Issue: [vector_graphics] Optimize masks
Labels: package,team-engine,p: vector_graphics

_Imported from https://github.com/dnfield/vector_graphics/issues/22_

Original report by @dnfield on Mar 24, 2022

Masks should be optimized away. Today they have to be implemented with a saveLayer/RT switch, which is especially sad.

Consider this SVG:

```svg
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
  <path fill-rule="evenodd" clip-rule="evenodd" d="M15.094 17.092a.882.882 0 01-.623-1.503l2.656-2.66H4.28a.883.883 0 010-1.765h12.846L14.47 8.503a.88.88 0 011.245-1.245l4.611 4.611a.252.252 0 010 .354l-4.611 4.611a.876.876 0 01-.622.258z" fill="#424242" />
  <mask id="a" maskUnits="userSpaceOnUse" x="3" y="7" width="18" height="11">
    <path fill-rule="evenodd" clip-rule="evenodd" d="M15.094 17.092a.882.882 0 01-.623-1.503l2.656-2.66H4.28a.883.883 0 010-1.765h12.846L14.47 8.503a.88.88 0 011.245-1.245l4.611 4.611a.252.252 0 010 .354l-4.611 4.611a.876.876 0 01-.622.258z" fill="#fff" />
  </mask>
  <g mask="url(#a)">
    <path fill-rule="evenodd" clip-rule="evenodd" d="M0 0h24v24.375H0V0z" fill="#fff" />
  </g>
</svg>
```

It is trivially expressed as a single path that should be fast to draw. We should be able to easily calculate everything here and just encode that path.

---
Comment by @dnfield on Mar 29, 2022
To clarify:

```svg
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
  <path d="M15.094 17.092a.882.882 0 01-.623-1.503l2.656-2.66H4.28a.883.883 0 010-1.765h12.846L14.47 8.503a.88.88 0 011.245-1.245l4.611 4.611a.252.252 0 010 .354l-4.611 4.611a.876.876 0 01-.622.258z" fill="#fff" />  
</svg>
```

Draws the same thing as the above SVG with no masks, and would involve no saveLayers.

---
Comment by @dnfield on Mar 29, 2022
(Probably what happened is the designer drew the arrow, selected it, changed the color, and/or maybe used some kind of masking tool in the editor...?)

---
Comment by @dnfield on Jun 6, 2022
Relevant part of spec: https://www.w3.org/TR/SVG11/masking.html#Masking

---
Comment by @dnfield on Jun 6, 2022
MDN: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/mask

---
Comment by @c-h-i-a-m-a-k-a-2 on Jul 20, 2022
Further Masking Optimizer improvement: Multi-path masks should be able to also be resolved. 

Example:

```
<svg viewBox="-10 -10 120 120">
  <mask id="myMask">
    <rect x="0" y="0" width="100" height="100" fill="white" />
    <path d="M10,35 A20,20,0,0,1,50,35 A20,20,0,0,1,90,35 Q90,65,50,95 Q10,65,10,35 Z" fill="black" />
  </mask>
  <polygon points="-10,110 110,110 110,-10" fill="orange" />
  <circle cx="50" cy="50" r="50" mask="url(#myMask)" />
</svg>

```


---
Comment by @c-h-i-a-m-a-k-a-2 on Jul 20, 2022
Further Masking Optimizer improvement: Paths that have the "stroke-width" attribute set should be able to be optimized. 

Example:

```
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
  <mask id="a" maskUnits="userSpaceOnUse" x="3" y="7" width="18" height="11">
    <path fill-rule="evenodd" clip-rule="evenodd" d="M15.094 17.092a.882.882 0 01-.623-1.503l2.656-2.66H4.28a.883.883 0 010-1.765h12.846L14.47 8.503a.88.88 0 011.245-1.245l4.611 4.611a.252.252 0 010 .354l-4.611 4.611a.876.876 0 01-.622.258z" fill="#fff"  stroke-width="2"/>
  </mask>
  <g mask="url(#a)">
    <path fill-rule="evenodd" clip-rule="evenodd" d="M0 0h24v24.375H0V0z" fill="#fff" />
  </g>
</svg>


```