Skip to content

Commit 720d787

Browse files
committed
[css-paint-api] Introduce css paint image definition concept.
1 parent 9b5d776 commit 720d787

File tree

1 file changed

+94
-33
lines changed

1 file changed

+94
-33
lines changed

css-paint-api/Overview.bs

+94-33
Original file line numberDiff line numberDiff line change
@@ -27,18 +27,20 @@ urlPrefix: https://html.spec.whatwg.org/multipage/scripting.html; type: dfn;
2727
text: scratch bitmap
2828
text: set bitmap dimensions
2929
urlPrefix: http://www.ecma-international.org/ecma-262/6.0/#sec-; type: dfn;
30+
text: constructor
3031
text: Construct
3132
text: IsArray
3233
text: IsCallable
3334
text: IsConstructor
3435
text: HasProperty
3536
url: get-o-p; text: Get
37+
url: terms-and-definitions-function; text: function
3638
</pre>
3739

3840
Introduction {#intro}
3941
=====================
4042

41-
The paint stage of CSS is responsible for painting the background, content and highlight of an
43+
The paint stage of CSS is responsible for painting the background, content and highlight of a
4244
box based on that box's geometry (as generated by the layout stage) and computed style.
4345

4446
This specification describes an API which allows developers to paint a part of an box in
@@ -113,11 +115,25 @@ interface PaintWorkletGlobalScope : WorkletGlobalScope {
113115
</pre>
114116
</div>
115117

118+
Concepts {#concepts}
119+
====================
120+
121+
A <dfn>paint image definition</dfn> describes an author defined <<image>> which can be referenced by
122+
the <<paint()>> function. It consists of:
123+
124+
- A <dfn>paint image name</dfn>
125+
126+
- A <dfn>class constructor</dfn> which is the class <a>constructor</a>
127+
128+
- A <dfn>paint function</dfn> which is the paint <a>function</a> callback
129+
130+
- A <dfn>class constructor valid flag</dfn>
131+
116132
Registering Custom Paint {#registering-custom-paint}
117133
====================================================
118134

119-
The {{PaintWorkletGlobalScope}} has a <dfn>paint name to constructor map</dfn>. Initially this map
120-
is empty; it is populated when {{registerPaint(name, paintCtor)}} is called.
135+
The {{PaintWorkletGlobalScope}} has a <dfn>paint name to paint image definition map</dfn>. Initially
136+
this map is empty; it is populated when {{registerPaint(name, paintCtor)}} is called.
121137

122138
The {{PaintWorkletGlobalScope}} has a <dfn>paint name to instance map</dfn>. Initially this map is
123139
empty; it is populated when <a>draw a paint image</a> is invoked by the user agent.
@@ -131,25 +147,56 @@ called, the user agent <em>must</em> run the following steps:
131147
1. If the |name| is not a valid <<ident>>, <a>throw</a> a <a>TypeError</a> and abort all these
132148
steps.
133149

134-
2. If the |name| exists as a key in the <a>paint name to constructor map</a>, <a>throw</a> a
135-
<a>NotSupportedError</a> and abort all these steps.
150+
2. If the |name| exists as a key in the <a>paint name to paint image definition map</a>,
151+
<a>throw</a> a <a>NotSupportedError</a> and abort all these steps.
152+
153+
3. Let |inputProperties| be the result of <a>Get</a>(O=|paintCtor|, P="inputProperties").
154+
155+
4. If |inputProperties| is not undefined, and the result of <a>IsArray</a>(argument=
156+
|inputProperties|) is false, <a>throw</a> a <a>TypeError</a> and abort all these steps.
157+
158+
1. Let |len| be the result of <a>ToLength</a>(<a>Get</a>(O=|inputProperties|, P="length")).
159+
160+
2. Let |idx| be 0.
161+
162+
3. Repeat while |idx| < |len|
163+
164+
1. Let |item| be the result of <a>Get</a>(O=|inputProperties|, |idx|).
136165

137-
3. If the result of <a>IsConstructor</a>(argument=|paintCtor|) is false, <a>throw</a> a
166+
2. If the result of <a>Type</a>(|item|) is not String, <a>throw</a> a <a>TypeError</a>
167+
and abort all these steps.
168+
169+
3. TODO prefixed behaviour
170+
171+
If |inputProperties| is undefined, let |inputProperties| be a new empty array.
172+
173+
5. If the result of <a>IsConstructor</a>(argument=|paintCtor|) is false, <a>throw</a> a
138174
<a>TypeError</a> and abort all these steps.
139175

140-
4. Let |prototype| be the result of <a>Get</a>(O=|paintCtor|, P="prototype").
176+
6. Let |prototype| be the result of <a>Get</a>(O=|paintCtor|, P="prototype").
141177

142-
5. If the result of <a>IsCallable</a>(argument=<a>Get</a>(O=|prototype|, P="paint")) is false,
178+
7. If the result of <a>Type</a>(argument=|prototype|) is not Object, <a>throw</a> a
179+
<a>TypeError</a> and abort all these steps.
180+
181+
8. If the result of <a>IsCallable</a>(argument=<a>Get</a>(O=|prototype|, P="paint")) is false,
143182
<a>throw</a> a <a>TypeError</a> and abort all these steps.
144183

145-
6. Let |inputProperties| be the result of <a>Get</a>(O=|paintCtor|, P="inputProperties").
184+
9. Let |definition| be a new <a>paint image definition</a> with:
146185

147-
7. If |inputProperties| is not undefined, and the result of <a>IsArray</a>(argument=
148-
|inputProperties|) is false, <a>throw</a> a <a>TypeError</a> and abort all these steps.
186+
- <a>paint image name</a> being |name|
187+
188+
- <a>class constructor</a> being |constructor|
189+
190+
- <a>paint function</a> being |paint|
149191

150-
8. Add the key-value pair (|name| - |inputProperties|) to the <a>paint name to input properties
192+
- <a>class constructor valid flag</a> being true
193+
194+
10. Add the key-value pair (|name| - |inputProperties|) to the <a>paint name to input properties
151195
map</a> of the associated <a>document</a>.
152196

197+
11. Add the key-value pair (|name| - |definition|) to the <a>paint name to paint image
198+
definition map</a> of the associated <a>document</a>.
199+
153200
Note: The list of CSS properties provided by the input properties getter can either be custom or
154201
native CSS properties.
155202

@@ -298,25 +345,34 @@ following steps:
298345
select or create. It may use a single {{PaintWorkletGlobalScope}} or multiple and
299346
randomly assign between them.
300347

301-
5. If no paint constructor exists on |workletGlobalScope|'s <a>paint name to constructor map</a>
302-
with key |name|, the resulting image output will be an <a>invalid image</a> and the user
303-
agent must abort all these steps.
348+
5. Let |definition| be the result of looking up |name| on the |workletGlobalScope|'s <a>paint
349+
name to paint image definition map</a>.
350+
351+
If |definition| does not exist, let the image output be an <a>invalid image</a> and abort
352+
all these steps.
304353

305354
6. Let |paintInstance| be the result of looking up |name| on |workletGlobalScope|'s <a>paint
306355
name to instance map</a>. If |paintInstance| is null run the following substeps:
307-
1. Let |paintCtor| be the result of looking up |name| on <a>paint name to constructor
308-
map</a>.
309356

310-
2. Let |paintInstance| be the result of <a>Construct</a>(|paintCtor|).
357+
1. If the <a>class constructor valid flag</a> on |definition| is false, let the image output
358+
be an <a>invalid image</a> and abort all these steps.
359+
360+
2. Let |paintCtor| be the <a>class constructor</a> on |definition|.
311361

312-
3. Add the key-value pair (|name| - |paintInstance|) to the <a>paint name to instance
362+
3. Let |paintInstance| be the result of <a>Construct</a>(|paintCtor|).
363+
364+
If <a>Construct</a> throws an exception, set the |definition|'s <a>constructor valid
365+
flag</a> to false, let the image output be an <a>invalid image</a> and abort all these
366+
steps.
367+
368+
4. Add the key-value pair (|name| - |paintInstance|) to the <a>paint name to instance
313369
map</a> of the |workletGlobalScope|.
314370

315371
7. Let |inputProperties| be the result of looking up |name| on the associated <a>document</a>'s
316372
<a>paint name to input properties map</a>.
317373

318-
8. Let |styleMap| be a new {{StylePropertyMap}} populated with <em>only</em> the <a>computed
319-
value</a>'s for properties listed in |inputProperties|.
374+
8. Let |styleMap| be a new {{StylePropertyMapReadOnly}} populated with <em>only</em> the
375+
<a>computed value</a>'s for properties listed in |inputProperties|.
320376

321377
9. Let |renderingContext| be the result of <a>create a PaintRenderingContext2D object</a> given:
322378
- "width" - The width given by |concreteObjectSize|.
@@ -340,7 +396,7 @@ following steps:
340396

341397
12. The image output is to be produced from the |renderingContext| given to the method.
342398

343-
If an exception is <a>thrown</a> the resulting image output will be an <a>invalid image</a>.
399+
If an exception is <a>thrown</a> the let the image output be an <a>invalid image</a>.
344400

345401
13. Set the <a>paint valid flag</a> for the |paintFunction| to <a>paint-valid</a>.
346402

@@ -423,17 +479,22 @@ document.registerProperty({
423479
registerPaint('circle', class {
424480
static get inputProperties() { return ['--image']; }
425481
paint(ctx, geom, properties) {
426-
// This relies on a TypedOM image object which doesn't exist yet.
427482
const img = properties.get('--image');
428-
if (img.loaded) {
429-
// The image is loaded! Draw the image.
430-
ctx.drawImage(img.data, 0, 0, geom.width, geom.height);
431-
} else if (img.invalid) {
432-
// The image is invalid (e.g. it didn't load), draw a sad face.
433-
drawSadFace(ctx);
434-
} else {
435-
// The image is loading, draw some mountains.
436-
drawMountains(ctx);
483+
484+
switch (img.state) {
485+
case 'ready':
486+
// The image is loaded! Draw the image.
487+
ctx.drawImage(img, 0, 0, geom.width, geom.height);
488+
break;
489+
case 'pending':
490+
// The image is loading, draw some mountains.
491+
drawMountains(ctx);
492+
break;
493+
case 'invalid':
494+
default:
495+
// The image is invalid (e.g. it didn't load), draw a sad face.
496+
drawSadFace(ctx);
497+
break;
437498
}
438499
}
439500
});
@@ -442,7 +503,7 @@ registerPaint('circle', class {
442503
Example 3: Conic-gradient {#example-3}
443504
--------------------------------------
444505

445-
Issue: Add conic-gradient as a use case.
506+
Issue: Add conic-gradient as a use case once we have function arguments.
446507

447508
Example 4: Different color based on geometry {#example-4}
448509
---------------------------------------------------------

0 commit comments

Comments
 (0)