@@ -27,18 +27,20 @@ urlPrefix: https://html.spec.whatwg.org/multipage/scripting.html; type: dfn;
27
27
text: scratch bitmap
28
28
text: set bitmap dimensions
29
29
urlPrefix: http://www.ecma-international.org/ecma-262/6.0/#sec-; type: dfn;
30
+ text: constructor
30
31
text: Construct
31
32
text: IsArray
32
33
text: IsCallable
33
34
text: IsConstructor
34
35
text: HasProperty
35
36
url: get-o-p; text: Get
37
+ url: terms-and-definitions-function; text: function
36
38
</pre>
37
39
38
40
Introduction {#intro}
39
41
=====================
40
42
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
42
44
box based on that box's geometry (as generated by the layout stage) and computed style.
43
45
44
46
This specification describes an API which allows developers to paint a part of an box in
@@ -113,11 +115,25 @@ interface PaintWorkletGlobalScope : WorkletGlobalScope {
113
115
</pre>
114
116
</div>
115
117
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
+
116
132
Registering Custom Paint {#registering-custom-paint}
117
133
====================================================
118
134
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.
121
137
122
138
The {{PaintWorkletGlobalScope}} has a <dfn>paint name to instance map</dfn> . Initially this map is
123
139
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:
131
147
1. If the |name| is not a valid <<ident>> , <a>throw</a> a <a>TypeError</a> and abort all these
132
148
steps.
133
149
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|).
136
165
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
138
174
<a>TypeError</a> and abort all these steps.
139
175
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").
141
177
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,
143
182
<a>throw</a> a <a>TypeError</a> and abort all these steps.
144
183
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:
146
185
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|
149
191
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
151
195
map</a> of the associated <a>document</a> .
152
196
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
+
153
200
Note: The list of CSS properties provided by the input properties getter can either be custom or
154
201
native CSS properties.
155
202
@@ -298,25 +345,34 @@ following steps:
298
345
select or create. It may use a single {{PaintWorkletGlobalScope}} or multiple and
299
346
randomly assign between them.
300
347
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.
304
353
305
354
6. Let |paintInstance| be the result of looking up |name| on |workletGlobalScope|'s <a>paint
306
355
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> .
309
356
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|.
311
361
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
313
369
map</a> of the |workletGlobalScope|.
314
370
315
371
7. Let |inputProperties| be the result of looking up |name| on the associated <a>document</a> 's
316
372
<a>paint name to input properties map</a> .
317
373
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|.
320
376
321
377
9. Let |renderingContext| be the result of <a>create a PaintRenderingContext2D object</a> given:
322
378
- "width" - The width given by |concreteObjectSize|.
@@ -340,7 +396,7 @@ following steps:
340
396
341
397
12. The image output is to be produced from the |renderingContext| given to the method.
342
398
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> .
344
400
345
401
13. Set the <a>paint valid flag</a> for the |paintFunction| to <a>paint-valid</a> .
346
402
@@ -423,17 +479,22 @@ document.registerProperty({
423
479
registerPaint('circle' , class {
424
480
static get inputProperties() { return ['--image'] ; }
425
481
paint(ctx, geom, properties) {
426
- // This relies on a TypedOM image object which doesn't exist yet.
427
482
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;
437
498
}
438
499
}
439
500
});
@@ -442,7 +503,7 @@ registerPaint('circle', class {
442
503
Example 3: Conic-gradient {#example-3}
443
504
--------------------------------------
444
505
445
- Issue: Add conic-gradient as a use case.
506
+ Issue: Add conic-gradient as a use case once we have function arguments .
446
507
447
508
Example 4: Different color based on geometry {#example-4}
448
509
---------------------------------------------------------
0 commit comments