mirror of
https://github.com/typst/typst
synced 2025-05-14 17:15:28 +08:00
Implement alpha modification methods for colors (#3516)
Co-authored-by: Laurenz <laurmaedje@gmail.com>
This commit is contained in:
parent
a518e2dd4d
commit
9d8df00ffb
@ -6,7 +6,7 @@ use ecow::{eco_format, EcoString, EcoVec};
|
|||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use palette::encoding::{self, Linear};
|
use palette::encoding::{self, Linear};
|
||||||
use palette::{
|
use palette::{
|
||||||
Darken, Desaturate, FromColor, Lighten, OklabHue, RgbHue, Saturate, ShiftHue,
|
Alpha, Darken, Desaturate, FromColor, Lighten, OklabHue, RgbHue, Saturate, ShiftHue,
|
||||||
};
|
};
|
||||||
use qcms::Profile;
|
use qcms::Profile;
|
||||||
|
|
||||||
@ -1128,6 +1128,47 @@ impl Color {
|
|||||||
) -> StrResult<Color> {
|
) -> StrResult<Color> {
|
||||||
Self::mix_iter(colors, space)
|
Self::mix_iter(colors, space)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Makes a color more transparent by a given factor.
|
||||||
|
///
|
||||||
|
/// This method is relative to the existing alpha value.
|
||||||
|
/// If the scale is positive, calculates `alpha - alpha * scale`.
|
||||||
|
/// Negative scales behave like `color.opacify(-scale)`.
|
||||||
|
///
|
||||||
|
/// ```example
|
||||||
|
/// #block(fill: red)[opaque]
|
||||||
|
/// #block(fill: red.transparentize(50%))[half red]
|
||||||
|
/// #block(fill: red.transparentize(75%))[quarter red]
|
||||||
|
/// ```
|
||||||
|
#[func]
|
||||||
|
pub fn transparentize(
|
||||||
|
self,
|
||||||
|
/// The factor to change the alpha value by.
|
||||||
|
scale: Ratio,
|
||||||
|
) -> StrResult<Color> {
|
||||||
|
self.scale_alpha(-scale)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Makes a color more opaque by a given scale.
|
||||||
|
///
|
||||||
|
/// This method is relative to the existing alpha value.
|
||||||
|
/// If the scale is positive, calculates `alpha + scale - alpha * scale`.
|
||||||
|
/// Negative scales behave like `color.transparentize(-scale)`.
|
||||||
|
///
|
||||||
|
/// ```example
|
||||||
|
/// #let half-red = red.transparentize(50%)
|
||||||
|
/// #block(fill: half-red.opacify(100%))[opaque]
|
||||||
|
/// #block(fill: half-red.opacify(50%))[three quarters red]
|
||||||
|
/// #block(fill: half-red.opacify(-50%))[one quarter red]
|
||||||
|
/// ```
|
||||||
|
#[func]
|
||||||
|
pub fn opacify(
|
||||||
|
self,
|
||||||
|
/// The scale to change the alpha value by.
|
||||||
|
scale: Ratio,
|
||||||
|
) -> StrResult<Color> {
|
||||||
|
self.scale_alpha(scale)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Color {
|
impl Color {
|
||||||
@ -1265,6 +1306,31 @@ impl Color {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Scales the alpha value of a color by a given amount.
|
||||||
|
///
|
||||||
|
/// For positive scales, computes `alpha + scale - alpha * scale`.
|
||||||
|
/// For non-positive scales, computes `alpha + alpha * scale`.
|
||||||
|
fn scale_alpha(self, scale: Ratio) -> StrResult<Color> {
|
||||||
|
#[inline]
|
||||||
|
fn transform<C>(mut color: Alpha<C, f32>, scale: Ratio) -> Alpha<C, f32> {
|
||||||
|
let scale = scale.get() as f32;
|
||||||
|
let factor = if scale > 0.0 { 1.0 - color.alpha } else { color.alpha };
|
||||||
|
color.alpha = (color.alpha + scale * factor).clamp(0.0, 1.0);
|
||||||
|
color
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(match self {
|
||||||
|
Color::Luma(c) => Color::Luma(transform(c, scale)),
|
||||||
|
Color::Oklab(c) => Color::Oklab(transform(c, scale)),
|
||||||
|
Color::Oklch(c) => Color::Oklch(transform(c, scale)),
|
||||||
|
Color::Rgb(c) => Color::Rgb(transform(c, scale)),
|
||||||
|
Color::LinearRgb(c) => Color::LinearRgb(transform(c, scale)),
|
||||||
|
Color::Cmyk(_) => bail!("CMYK does not have an alpha component"),
|
||||||
|
Color::Hsl(c) => Color::Hsl(transform(c, scale)),
|
||||||
|
Color::Hsv(c) => Color::Hsv(transform(c, scale)),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/// Converts the color to a vec of four floats.
|
/// Converts the color to a vec of four floats.
|
||||||
pub fn to_vec4(&self) -> [f32; 4] {
|
pub fn to_vec4(&self) -> [f32; 4] {
|
||||||
match self {
|
match self {
|
||||||
|
@ -83,3 +83,19 @@
|
|||||||
#test-repr(luma(20%).lighten(50%), luma(60%))
|
#test-repr(luma(20%).lighten(50%), luma(60%))
|
||||||
#test-repr(luma(80%).darken(20%), luma(64%))
|
#test-repr(luma(80%).darken(20%), luma(64%))
|
||||||
#test-repr(luma(80%).negate(space: luma), luma(20%))
|
#test-repr(luma(80%).negate(space: luma), luma(20%))
|
||||||
|
|
||||||
|
---
|
||||||
|
// Test alpha modification.
|
||||||
|
// Ref: false
|
||||||
|
#test-repr(luma(100%, 100%).transparentize(50%), luma(100%, 50%))
|
||||||
|
#test-repr(luma(100%, 100%).transparentize(75%), luma(100%, 25%))
|
||||||
|
#test-repr(luma(100%, 50%).transparentize(50%), luma(100%, 25%))
|
||||||
|
#test-repr(luma(100%, 10%).transparentize(250%), luma(100%, 0%))
|
||||||
|
#test-repr(luma(100%, 40%).transparentize(-50%), luma(100%, 70%))
|
||||||
|
#test-repr(luma(100%, 0%).transparentize(-100%), luma(100%, 100%))
|
||||||
|
|
||||||
|
#test-repr(luma(100%, 50%).opacify(50%), luma(100%, 75%))
|
||||||
|
#test-repr(luma(100%, 20%).opacify(100%), luma(100%, 100%))
|
||||||
|
#test-repr(luma(100%, 100%).opacify(250%), luma(100%, 100%))
|
||||||
|
#test-repr(luma(100%, 50%).opacify(-50%), luma(100%, 25%))
|
||||||
|
#test-repr(luma(100%, 0%).opacify(0%), luma(100%, 0%))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user