Skip to content

Commit 9b31697

Browse files
committed
Support blending of N colours at once
1 parent 5452580 commit 9b31697

File tree

2 files changed

+29
-22
lines changed

2 files changed

+29
-22
lines changed

docs/src/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,6 @@ StyledStrings.SimpleColor
341341
StyledStrings.parse(::Type{StyledStrings.SimpleColor}, ::String)
342342
StyledStrings.tryparse(::Type{StyledStrings.SimpleColor}, ::String)
343343
StyledStrings.merge(::StyledStrings.Face, ::StyledStrings.Face)
344-
StyledStrings.blend(::StyledStrings.SimpleColor, ::StyledStrings.SimpleColor, ::Real)
344+
StyledStrings.blend
345345
StyledStrings.recolor
346346
```

src/faces.jl

Lines changed: 28 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -914,13 +914,15 @@ function rgbcolor(color::Union{Symbol, SimpleColor})
914914
end
915915

916916
"""
917-
blend(a::Union{Symbol, SimpleColor}, b::Union{Symbol, SimpleColor}, α::Real)
917+
blend(a::Union{Symbol, SimpleColor}, [b::Union{Symbol, SimpleColor} => α::Real]...)
918918
919919
Blend colors `a` and `b` in Oklab space, with mix ratio `α` (0–1).
920920
921921
The colors `a` and `b` can either be `SimpleColor`s, or `Symbol`s naming a face
922922
or base color. The mix ratio `α` combines `(1 - α)` of `a` with `α` of `b`.
923923
924+
Multiple colors can be blended at once by providing multiple `b => α` pairs.
925+
924926
# Examples
925927
926928
```julia-repl
@@ -934,9 +936,11 @@ julia> blend(:green, SimpleColor(0xffffff), 0.3)
934936
SimpleColor(■ #74be93)
935937
```
936938
"""
937-
function blend(c1::SimpleColor, c2::SimpleColor, α::Real)
938-
function oklab(rgb::RGBTuple)
939-
r, g, b = (Tuple(rgb) ./ 255) .^ 2.2
939+
function blend end
940+
941+
function blend(primaries::Pair{RGBTuple, <:Real}...)
942+
function oklab(rgb::RGBTuple)
943+
r, g, b = (rgb.r / 255)^2.2, (rgb.g / 255)^2.2, (rgb.b / 255)^2.2
940944
l = cbrt(0.4122214708 * r + 0.5363325363 * g + 0.0514459929 * b)
941945
m = cbrt(0.2119034982 * r + 0.6806995451 * g + 0.1073969566 * b)
942946
s = cbrt(0.0883024619 * r + 0.2817188376 * g + 0.6299787005 * b)
@@ -955,22 +959,25 @@ function blend(c1::SimpleColor, c2::SimpleColor, α::Real)
955959
b = -0.0041960863 * l - 0.7034186147 * m + 1.7076147010 * s
956960
(r = tohex(r), g = tohex(g), b = tohex(b))
957961
end
958-
lab1 = oklab(rgbcolor(c1))
959-
lab2 = oklab(rgbcolor(c2))
960-
mix = (L = (1 - α) * lab1.L + α * lab2.L,
961-
a = (1 - α) * lab1.a + α * lab2.a,
962-
b = (1 - α) * lab1.b + α * lab2.b)
963-
SimpleColor(rgb(mix))
964-
end
965-
966-
function blend(f1::Union{Symbol, SimpleColor}, f2::Union{Symbol, SimpleColor}, α::Real)
967-
function face_or_color(name::Symbol)
968-
c = getface(name).foreground
969-
if c.value === :foreground && haskey(FACES.basecolors, name)
970-
c = SimpleColor(name)
971-
end
972-
c
962+
L′, a′, b′ = 0.0, 0.0, 0.0
963+
for (color, α) in primaries
964+
lab = oklab(color)
965+
L′ += lab.L * α
966+
a′ += lab.a * α
967+
b′ += lab.b * α
973968
end
974-
face_or_color(c::SimpleColor) = c
975-
blend(face_or_color(f1), face_or_color(f2), α)
969+
mix = (L = L′, a = a′, b = b′)
970+
rgb(mix)
976971
end
972+
973+
blend(base::RGBTuple, primaries::Pair{RGBTuple, <:Real}...) =
974+
blend(base => 1.0 - sum(last, primaries), primaries...)
975+
976+
blend(primaries::Pair{<:Union{Symbol, SimpleColor}, <:Real}...) =
977+
SimpleColor(blend((rgbcolor(c) => w for (c, w) in primaries)...))
978+
979+
blend(base::Union{Symbol, SimpleColor}, primaries::Pair{<:Union{Symbol, SimpleColor}, <:Real}...) =
980+
SimpleColor(blend(rgbcolor(base), (rgbcolor(c) => w for (c, w) in primaries)...))
981+
982+
blend(a::Union{Symbol, SimpleColor}, b::Union{Symbol, SimpleColor}, α::Real) =
983+
blend(a => 1 - α, b => α)

0 commit comments

Comments
 (0)