Skip to content

Commit e6d69a2

Browse files
committed
[css-paint-api] Update EXPLAINER.md to include inputArguments and paint efficiency.
1 parent 3fcc307 commit e6d69a2

File tree

1 file changed

+80
-11
lines changed

1 file changed

+80
-11
lines changed

css-paint-api/EXPLAINER.md

+80-11
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,37 @@ This means that the memory and cpu usage of the page would go down, the renderin
2121
have to keep in memory the additional DOM nodes, in addition to performing style-recalc, layout,
2222
painting for all these additional divs.
2323

24+
### Efficiency Gains ###
25+
26+
Providing a "hook" into the rendering engine allows for efficiency gains which are difficult to
27+
achieve with current APIs.
28+
29+
#### Invalidation ####
30+
31+
As the CSS paint API Invalidation is based off style changes, this check can occur in the same pass
32+
as the rest of the box tree. For example:
33+
34+
```css
35+
my-button {
36+
--property-which-invalidates-paint: no-hover;
37+
}
38+
39+
my-button:hover {
40+
--property-which-invalidates-paint: hover;
41+
}
42+
```
43+
44+
To achieve the same effect with current APIs you have to rebuild the engines invalidation logic
45+
which is potentially less efficient.
46+
47+
#### Painting ####
48+
49+
Once a box has been invalidated, a rendering engine isn't required to paint it that frame. For
50+
example some rendering engines just paint what is visible within the "visual viewport". This means
51+
that only a smaller amount of work is needed to be done.
52+
53+
A naive implementation with existing APIs may try and paint everything within the document.
54+
2455
### Extensibility of CSS ###
2556

2657
We believe that allowing developers to extend CSS is good for the ecosystem. As an example if a
@@ -87,11 +118,15 @@ The `paint` function is your callback into the browsers paint phase in the rende
87118
- `size`, the size of the area in which you should paint.
88119
- `style`, the computed style of the element which are you currently painting.
89120
90-
The `style` is a Typed-OM style map. It will _only_ contain the CSS properties that you listed under the static `inputProperties` accessor.
121+
The `style` is a Typed-OM style map. It will _only_ contain the CSS properties that you listed under
122+
the static `inputProperties` accessor.
91123
92-
This is to allow the engine to cache results of your paint class. For example if `--some-other-property` changes the user-agent knows that this doesn't affect your paint class, and can re-use the stored result.
124+
This is to allow the engine to cache results of your paint class. For example if
125+
`--some-other-property` changes the user-agent knows that this doesn't affect your paint class, and
126+
can re-use the stored result.
93127
94-
The only time when your paint class _must_ be called is when the element it is painting into is within the viewport, and the size or CSS input properties have changed.
128+
The only time when your paint class _must_ be called is when the element it is painting into is
129+
within the viewport, and the size or CSS input properties have changed.
95130
96131
Why classes?
97132
------------
@@ -127,7 +162,8 @@ class BorderRectPainter extends RectPainter {
127162
registerPaint('border-rect', BorderRectPainter);
128163
```
129164
130-
Classes also give the developer a specific point in time to perform pre-initialization work. As an example:
165+
Classes also give the developer a specific point in time to perform pre-initialization work. As an
166+
example:
131167
132168
```js
133169
registerPaint('lots-of-paths', class {
@@ -146,14 +182,18 @@ registerPaint('lots-of-paths', class {
146182
});
147183
```
148184
149-
In this example `performPathPreInit` is doing CPU intensive work which should only be done once. Without classes this would typically be done when the script is first run, instead this is performed when the class instance is first created (which may be much later in time).
185+
In this example `performPathPreInit` is doing CPU intensive work which should only be done once.
186+
Without classes this would typically be done when the script is first run, instead this is performed
187+
when the class instance is first created (which may be much later in time).
150188
151189
Drawing Images
152190
--------------
153191
154-
The API works in conjunction with the [CSS Properties and Values](https://drafts.css-houdini.org/css-properties-values-api/) proposal and the [CSS Typed OM](https://drafts.css-houdini.org/css-typed-om/) proposal.
192+
The API works in conjunction with the [CSS Properties and Values](https://drafts.css-houdini.org/css-properties-values-api/)
193+
proposal and the [CSS Typed OM](https://drafts.css-houdini.org/css-typed-om/) proposal.
155194
156-
Using the Properties and Values `registerProperty` method, developers can create a custom CSS property with the `<image>` type. E.g.
195+
Using the Properties and Values `registerProperty` method, developers can create a custom CSS
196+
property with the `<image>` type. E.g.
157197
158198
```js
159199
registerProperty({
@@ -162,7 +202,8 @@ registerProperty({
162202
});
163203
```
164204
165-
This tells the rendering engine to treat the CSS property `--profile-image` as an image; and as a result the style engine will parse and begin loading that image.
205+
This tells the rendering engine to treat the CSS property `--profile-image` as an image; and as a
206+
result the style engine will parse and begin loading that image.
166207
167208
You can then directly draw this image from within your paint method:
168209
@@ -200,7 +241,35 @@ The above example would be used in CSS by:
200241
}
201242
```
202243
203-
Paint Efficiency
204-
----------------
244+
Paint Arguments
245+
---------------
246+
247+
It is also possible with this API to have additional arguments to the `paint()` function, for
248+
example:
249+
250+
```js
251+
registerPaint('circle-args', class {
252+
static inputArguments = ['<color>'];
253+
254+
paint(ctx, size, _, args) {
255+
const color = args[0].cssText;
256+
ctx.fillStyle = color;
205257

206-
TODO
258+
const x = size.width / 2;
259+
const y = size.height / 2;
260+
const radius = Math.min(x, y);
261+
262+
ctx.beginPath();
263+
ctx.arc(x, y, radius, 0, 2 * Math.PI, false);
264+
ctx.fill();
265+
}
266+
});
267+
```
268+
269+
```js
270+
my-element {
271+
background:
272+
paint(circle-args, red) center/50% no-repeat,
273+
paint(cirlce-args, blue);
274+
}
275+
```

0 commit comments

Comments
 (0)