Add colour-composite operator and use it to fix contrast tests for translucent colours

This commit is contained in:
Jeremy Ruston
2026-07-22 15:05:49 +01:00
parent 4259ce4979
commit 503c60f666
6 changed files with 74 additions and 2 deletions
+11
View File
@@ -46,6 +46,17 @@ exports["colour-set-alpha"] = makeSerialColourOperator(function (colour, operato
return colour.display().toString();
});
exports["colour-composite"] = makeSerialColourOperator(function (colour, operator, options) {
// Composite each translucent input colour over the backdrop given in the operand
var backdrop = $tw.utils.parseCSSColorObject(operator.operand);
if(backdrop && colour.alpha < 1) {
var alpha = colour.alpha;
colour.alpha = 1;
colour = backdrop.mix(colour,alpha,{space: "srgb"});
}
return colour.display().toString();
});
exports["colour-contrast"] = makeParallelColourOperator(function (colours, operator, options) {
var colourContrasts = [];
$tw.utils.each(colours,function(colour,index) {
+2 -1
View File
@@ -152,8 +152,9 @@ tags: $:/tags/Macro
[<colour-result>prefix[<<colour ]suffix[>>]removeprefix[<<colour ]removesuffix[>>]addprefix<colour-function-prefix>addsuffix<colour-function-suffix>] :else[<colour-result>]
\end tf.colour-inner-transform-classic-palette-entry
<!-- Translucent entries are composited over the background entry before their contrast is measured -->
\function tf.check-colour-contrast-subfunction()
[function[colour],<paletteEntryA>] [function[colour],<paletteEntryB>] +[colour-contrast:DeltaPhi[]fixed[3]]
[function[colour],[background]] =>backdrop [function[colour],<paletteEntryA>colour-composite<backdrop>] =>colourA [function[colour],<paletteEntryB>colour-composite<backdrop>] =>colourB [<colourA>] [<colourB>] +[colour-contrast:DeltaPhi[]fixed[3]]
\end tf.check-colour-contrast-subfunction
\function tf.check-colour-contrast(paletteEntryA,paletteEntryB,threshold)
@@ -0,0 +1,20 @@
title: Operators/Colour/ColourComposite
description: Compositing translucent colours over a backdrop
type: text/vnd.tiddlywiki-multiple
tags: [[$:/tags/wiki-test-spec]]
title: Output
\parsermode inline
<$text text={{{ [subfilter{Filter}] }}}/>
+
title: Filter
=[[#1919191A]colour-composite[white]]
=[[red]colour-composite[white]]
=[[#80808080]colour-composite[black]]
+[join[,]]
+
title: ExpectedResult
rgb(90.804% 90.804% 90.804%),rgb(100% 0% 0%),rgb(25.196% 25.196% 25.196%)
@@ -0,0 +1,30 @@
created: 20260722103000000
modified: 20260722103000000
tags: [[Filter Operators]] [[Colour Operators]]
title: colour-composite Operator
caption: colour-composite
op-purpose: composite translucent colour values over a backdrop colour
op-input: a selection of colour values
op-parameter: the backdrop colour
op-output: the composited colours
<<.from-version "5.5.0">> See ColourPalettes for background.
The <<.op colour-composite>> operator composites each input colour over the backdrop colour given in the parameter, returning the opaque colour that results when the input is displayed on top of the backdrop colour. Opaque input colours are returned unchanged, as is any input when the backdrop cannot be parsed as a colour.
Compositing is needed when measuring the contrast of translucent colours. The [[readability tests|Palette Readability Tests]] of the core palettes composite translucent entries over the palette background before measuring their contrast.
For example, this filter expression composites a 10% black wash over the current page background colour:
```
[[#0000001A]colour-composite{{{ [function[colour],[page-background]] }}}]
```
Input values that cannot be parsed as colours are returned as empty strings.
See also the following related operators:
* <<.olink colour-set-alpha>> to set the alpha channel of a colour value
* <<.olink colour-contrast>> to measure the contrast between pairs of colours
<<.operator-examples "colour-composite">>
@@ -0,0 +1,9 @@
created: 20260722103000000
modified: 20260722103000000
tags: [[colour-composite Operator]] [[Operator Examples]]
title: colour-composite Operator (Examples)
type: text/vnd.tiddlywiki
<<.operator-example 1 "[[#1919191A]colour-composite[white]]" "a 10% near-black wash over white gives a light grey">>
<<.operator-example 2 "[[#EFEFEF1A]colour-composite[#333333]]" "the same idiom in a dark palette gives a slightly lightened grey">>
<<.operator-example 3 "[[red]colour-composite[white]]" "opaque colours are returned unchanged">>
@@ -3,7 +3,7 @@ description: New filter operators for manipulating colour values
release: 5.5.0
tags: $:/tags/ChangeNote
created: 20260718000000000
modified: 20260718000000000
modified: 20260722103000000
change-type: feature
change-category: filters
github-links: https://github.com/TiddlyWiki/TiddlyWiki5/pull/8702
@@ -13,6 +13,7 @@ A suite of new filter operators for manipulating colour values, backed by the [[
* <<.olink colour-lighten>> and <<.olink colour-darken>> for lightening and darkening colours
* <<.olink colour-set-alpha>> for setting the opacity of a colour
* <<.olink colour-composite>> for compositing translucent colours over a backdrop
* <<.olink colour-get-oklch>> and <<.olink colour-set-oklch>> for reading and writing the lightness, chroma and hue components of a colour
* <<.olink colour-contrast>> for measuring the contrast between colours
* <<.olink colour-best-contrast>> for choosing the colour from a list that gives the best contrast with a target colour