diff --git a/crates/typst-render/src/lib.rs b/crates/typst-render/src/lib.rs index 8c519795e..fa4a9bf18 100644 --- a/crates/typst-render/src/lib.rs +++ b/crates/typst-render/src/lib.rs @@ -465,12 +465,7 @@ fn render_outline_glyph( write_bitmap(canvas, &bitmap, &state, sampler)?; } Paint::Solid(color) => { - write_bitmap( - canvas, - &bitmap, - &state, - to_sk_color_u8_without_alpha(*color).premultiply(), - )?; + write_bitmap(canvas, &bitmap, &state, to_sk_color_u8(*color).premultiply())?; } Paint::Pattern(pattern) => { let pixmap = render_pattern_frame(&state, pattern); @@ -548,7 +543,8 @@ fn write_bitmap( let color = sampler.sample((x as _, y as _)); let color = bytemuck::cast(color); let pi = (y * cw + x) as usize; - if cov == 255 { + // Fast path if color is opaque. + if cov == u8::MAX && color & 0xFF == 0xFF { pixels[pi] = color; continue; } @@ -771,17 +767,6 @@ fn scaled_texture(image: &Image, w: u32, h: u32) -> Option> { trait PaintSampler: Copy { /// Sample the color at the `pos` in the pixmap. fn sample(self, pos: (u32, u32)) -> sk::PremultipliedColorU8; - - /// Write the sampler to a pixmap. - fn write_to_pixmap(self, canvas: &mut sk::Pixmap) { - let width = canvas.width(); - for x in 0..canvas.width() { - for y in 0..canvas.height() { - let color = self.sample((x, y)); - canvas.pixels_mut()[(y * width + x) as usize] = color; - } - } - } } impl PaintSampler for sk::PremultipliedColorU8 { @@ -835,7 +820,7 @@ impl PaintSampler for GradientSampler<'_> { self.transform_to_parent.map_point(&mut point); // Sample the gradient - to_sk_color_u8_without_alpha(self.gradient.sample_at( + to_sk_color_u8(self.gradient.sample_at( (point.x, point.y), (self.container_size.x.to_f32(), self.container_size.y.to_f32()), )) @@ -1027,9 +1012,9 @@ fn to_sk_color(color: Color) -> sk::Color { sk::Color::from_rgba8(r, g, b, a) } -fn to_sk_color_u8_without_alpha(color: Color) -> sk::ColorU8 { - let [r, g, b, _] = color.to_rgb().to_vec4_u8(); - sk::ColorU8::from_rgba(r, g, b, 255) +fn to_sk_color_u8(color: Color) -> sk::ColorU8 { + let [r, g, b, a] = color.to_rgb().to_vec4_u8(); + sk::ColorU8::from_rgba(r, g, b, a) } fn to_sk_line_cap(cap: LineCap) -> sk::LineCap { diff --git a/tests/ref/text/font.png b/tests/ref/text/font.png index d3893ce8f..39c8a951b 100644 Binary files a/tests/ref/text/font.png and b/tests/ref/text/font.png differ diff --git a/tests/typ/text/font.typ b/tests/typ/text/font.typ index 07d00d143..736ded41b 100644 --- a/tests/typ/text/font.typ +++ b/tests/typ/text/font.typ @@ -30,6 +30,12 @@ Emoji: 🐪, 🌋, 🏞 This is #text(rgb("FA644B"))[way more] colorful. ] +// Transparency. +#block(fill: green)[ + #set text(fill: rgb("FF000080")) + This text is transparent. +] + // Disable font fallback beyond the user-specified list. // Without disabling, New Computer Modern Math would come to the rescue. #set text(font: ("PT Sans", "Twitter Color Emoji"), fallback: false)