Skip to content

Commit ab20b4c

Browse files
committed
[css-images-4] Per WG resolution, cross-fade() takes 1+ arguments. Define sizing and painting of the new function arguments in detail.
1 parent 1f55cc3 commit ab20b4c

File tree

1 file changed

+134
-27
lines changed

1 file changed

+134
-27
lines changed

css-images-4/Overview.bs

Lines changed: 134 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -376,8 +376,6 @@ Image Fallbacks and Annotations: the ''image()'' notation {#image-notation}
376376
Combining images: the ''cross-fade()'' notation {#cross-fade-function}
377377
----------------------------------------------------------------------
378378

379-
380-
381379
When transitioning between images,
382380
CSS requires a way to explicitly refer to the intermediate image
383381
that is a combination of the start and end images.
@@ -392,37 +390,146 @@ Combining images: the ''cross-fade()'' notation {#cross-fade-function}
392390
The syntax for ''cross-fade()'' is defined as:
393391

394392
395-
cross-fade() = cross-fade( <> , <>? )
396-
<cf-mixing-image> = <>? && <>
397-
<cf-final-image> = <> | <>
393+
cross-fade() = cross-fade( <># )
394+
<cf-image> = <>? && [ <> | <> ]
398395
399396

400397
The function represents an image generated by
401-
combining two images.
398+
combining two or more images.
402399

403-
The <> represents how much of the first image is retained
404-
when it is blended with the second image.
400+
The <> represents how much of each image is retained
401+
when it is blended with the other images.
405402
The <> must be between ''0%'' and ''100%'' inclusive;
406403
any other value is invalid.
407-
If omitted,
408-
it defaults to the value ''50%''.
409-
410-
If the last argument is a <>,
411-
it represents a solid-color image with the same intrinsic dimensions as the first image.
412-
If omitted,
413-
it defaults to the color ''transparent''.
414-
415-
More precisely,
416-
given ''cross-fade(p A, B)'',
417-
where A and B are images
418-
and p is a percentage between 0% and 100%,
419-
the function represents an image
420-
with width equal to widthA × p + widthB × (1-p)
421-
and height equal to heightA × p + heightB × (1-p).
422-
The contents of the image must be constructed by
423-
first scaling A and B to the size of the generated image,
424-
then applying dissolve(A,p) plus dissolve(B,1-p).
425-
The "dissolve()" function and "plus" compositing operator are defined in the literature by Porter-Duff. [[PORTERDUFF]]
404+
405+
If any percentages are omitted,
406+
all the specified percentages are summed together
407+
and subtracted from ''100%'',
408+
the result is floored at ''0%'',
409+
then divided equally between all images with omitted percentages
410+
at computed-value time.
411+
412+
413+
While this is not reflected in the computed value,
414+
when all the arguments’ percentages sum to greater than ''100%'',
415+
the sizing/painting details effectively rescale them so that they sum to exactly ''100%''.
416+
417+
On the other hand,
418+
when the sum is less than ''100%'',
419+
the sizing/painting details effectively act like there's an additional ''transparent'' argument,
420+
with its percentage set to the remaining value
421+
necessary to make the sum equal ''100%''.
422+
423+
424+
If a <> is provided,
425+
it represents a solid-color image
426+
with “automatic” dimensions
427+
(it doesn't participate in the sizing of the result image at all;
428+
see details in the sizing details below).
429+
430+
### ''cross-fade()'' Sizing ### {#cross-fade-sizing}
431+
432+
The dimensions of the image represented by a ''cross-fade()''
433+
are a weighted average of dimensions of the <> arguments to the function;
434+
the <> arguments have no effect.
435+
They are calculated as follows:
436+
437+
438+
To determine the intrinsic dimensions of a cross-fade():
439+
440+
1. Let |images| be an empty list.
441+
442+
2. For each |argument| of the ''cross-fade()'' function with an <> value:
443+
1. Let |item| be a [=tuple=] consisting of a width, a height, and a percentage.
444+
2. Run the [=object size negotation=] algorithm for the <>,
445+
as appropriate for the context in which the ''cross-fade()'' appears,
446+
and set |item|’s width and height
447+
to the width and height of the resulting [=concrete object size=].
448+
3. Set |item|’s percentage to the |argument|’s percentage.
449+
450+
3. If |images| is empty,
451+
return no intrinsic dimensions.
452+
453+
4. Let |percentage sum| be the sum of all the percentages of the [=list/items=] in |images|.
454+
455+
5. [=list/For each=] |item| in |images|,
456+
divide |item|’s percentage by |percentage sum|,
457+
and set |item|’s percentage to the result.
458+
459+
Assert: The percentages in |images| now sum to ''100%''.
460+
461+
6. Let |final width| and |final height| be ''0px''.
462+
463+
7. [=list/For each=] |item| in |images|,
464+
multiply |item|’s width by |item|’s percentage
465+
and add the result to |final width|,
466+
and multiply |item|’s height by |item|’s percentage
467+
and add the result to |final height|.
468+
469+
8. Return an intrinsic width of |final width|
470+
and an intrinsic height of |final height|.
471+
472+
473+
### ''cross-fade()'' Painting ### {#cross-fade-painting}
474+
475+
The image represented by a ''cross-fade()''
476+
is a weighted average of the input arguments to the function,
477+
calculated as follows:
478+
479+
480+
481+
To determine the appearance of a cross-fade():
482+
483+
1. Let |images| be an empty list.
484+
485+
2. Let |size| be a [=tuple=] of width and height,
486+
initialized to the result of finding the [=concrete object size=]
487+
of the ''cross-fade()'' function
488+
(using the [=intrinsic dimensions of a cross-fade()=]).
489+
490+
3. For each |argument| of the ''cross-fade()'' function:
491+
1. Let |item| be a [=tuple=] consisting of an image and a percentage.
492+
2. If |argument| has an <>,
493+
rescale it to |size|’s width and height
494+
and set |item|’s image to the result.
495+
Otherwise, |argument| has a <>;
496+
set |item|’s image to a solid-color image of the <>,
497+
with |size|’s dimensions.
498+
3. Set |item|’s percentage to the |argument|’s percentage.
499+
500+
4. Let |percentage sum| be the sum of all the percentages of the [=list/items=] in |images|.
501+
502+
5. [=list/For each=] |item| in |images|,
503+
divide |item|’s percentage by |percentage sum|,
504+
and set |item|’s percentage to the result.
505+
506+
6. Let |final image| be an image
507+
with |size|’s dimensions,
508+
and every pixel being the weighted linear average of the corresponding pixels of [=list/each=] |item|’s image in |images|,
509+
weighted according to the |item|’s percentage.
510+
(Average both the color channels and the alpha channel of the pixels.)
511+
512+
Note: This is applying the Porter-Duff dissolve operator to each source image,
513+
then combining them all together with the Porter-Duff plus operator. [[PORTER-DUFF]]
514+
515+
Issue: What color space does this average take place in? sRGB? Controlled by @color-space?
516+
517+
8. If |percentage sum| is less than ''100%'',
518+
multiply the alpha channel of every pixel in |final image| by |percentage sum|.
519+
520+
Note: This ensures that ''cross-fade(img 50%)'' doesn't darken the image
521+
(as would happen by blending with transparent black),
522+
but just makes it more transparent,
523+
as the author almost certainly intends.
524+
525+
Issue: Should this also apply to explicit ''transparent'' arguments?
526+
527+
for making ''transparent'' generally act like just “transparency”,
528+
rather than specifically being transparent black.
529+
We'd specify this by filtering them out in step 3.
530+
531+
8. Return |final image|.
532+
426533

427534
commit comments
Comments
 (0)