mirror of
https://github.com/typst/typst
synced 2025-05-14 17:15:28 +08:00
Fix text fill within clip: true
blocks in PNG export (#5502)
This commit is contained in:
parent
cda94ab405
commit
884c02872c
@ -164,29 +164,41 @@ fn write_bitmap<S: PaintSampler>(
|
|||||||
// If we have a clip mask we first render to a pixmap that we then blend
|
// If we have a clip mask we first render to a pixmap that we then blend
|
||||||
// with our canvas
|
// with our canvas
|
||||||
if state.mask.is_some() {
|
if state.mask.is_some() {
|
||||||
|
let cw = canvas.width() as i32;
|
||||||
|
let ch = canvas.height() as i32;
|
||||||
let mw = bitmap.width;
|
let mw = bitmap.width;
|
||||||
let mh = bitmap.height;
|
let mh = bitmap.height;
|
||||||
|
|
||||||
|
let left = bitmap.left;
|
||||||
|
let top = bitmap.top;
|
||||||
|
|
||||||
// Pad the pixmap with 1 pixel in each dimension so that we do
|
// Pad the pixmap with 1 pixel in each dimension so that we do
|
||||||
// not get any problem with floating point errors along their border
|
// not get any problem with floating point errors along their border
|
||||||
let mut pixmap = sk::Pixmap::new(mw + 2, mh + 2)?;
|
let mut pixmap = sk::Pixmap::new(mw + 2, mh + 2)?;
|
||||||
|
let pixels = bytemuck::cast_slice_mut::<u8, u32>(pixmap.data_mut());
|
||||||
for x in 0..mw {
|
for x in 0..mw {
|
||||||
for y in 0..mh {
|
for y in 0..mh {
|
||||||
let alpha = bitmap.coverage[(y * mw + x) as usize];
|
let alpha = bitmap.coverage[(y * mw + x) as usize];
|
||||||
let color = sampler.sample((x, y));
|
|
||||||
pixmap.pixels_mut()[((y + 1) * (mw + 2) + (x + 1)) as usize] =
|
|
||||||
sk::ColorU8::from_rgba(
|
|
||||||
color.red(),
|
|
||||||
color.green(),
|
|
||||||
color.blue(),
|
|
||||||
alpha,
|
|
||||||
)
|
|
||||||
.premultiply();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let left = bitmap.left;
|
// To sample at the correct position, we need to convert each
|
||||||
let top = bitmap.top;
|
// pixel's position in the bitmap (x and y) to its final
|
||||||
|
// expected position in the canvas. Due to padding, this
|
||||||
|
// pixel's position in the pixmap will be (x + 1, y + 1).
|
||||||
|
// Then, when drawing the pixmap to the canvas, we place its
|
||||||
|
// top-left corner at position (left - 1, top - 1). Therefore,
|
||||||
|
// the final position of this pixel in the canvas is given by
|
||||||
|
// (left - 1 + x + 1, top - 1 + y + 1) = (left + x, top + y).
|
||||||
|
let sample_pos = (
|
||||||
|
(left + x as i32).clamp(0, cw) as u32,
|
||||||
|
(top + y as i32).clamp(0, ch) as u32,
|
||||||
|
);
|
||||||
|
let color = sampler.sample(sample_pos);
|
||||||
|
let color = bytemuck::cast(color);
|
||||||
|
|
||||||
|
let applied = alpha_mul(color, alpha as u32);
|
||||||
|
pixels[((y + 1) * (mw + 2) + (x + 1)) as usize] = applied;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
canvas.draw_pixmap(
|
canvas.draw_pixmap(
|
||||||
left - 1,
|
left - 1,
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 908 B |
Binary file not shown.
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
BIN
tests/ref/issue-5499-text-fill-in-clip-block.png
Normal file
BIN
tests/ref/issue-5499-text-fill-in-clip-block.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.5 KiB |
@ -81,3 +81,34 @@ I
|
|||||||
// Warning: 17-34 Typst's default font has changed from Linux Libertine to its successor Libertinus Serif
|
// Warning: 17-34 Typst's default font has changed from Linux Libertine to its successor Libertinus Serif
|
||||||
// Hint: 17-34 please set the font to `"Libertinus Serif"` instead
|
// Hint: 17-34 please set the font to `"Libertinus Serif"` instead
|
||||||
#set text(font: "Linux Libertine")
|
#set text(font: "Linux Libertine")
|
||||||
|
|
||||||
|
--- issue-5499-text-fill-in-clip-block ---
|
||||||
|
|
||||||
|
#let pat = pattern(
|
||||||
|
size: (30pt, 30pt),
|
||||||
|
relative: "parent",
|
||||||
|
square(
|
||||||
|
size: 30pt,
|
||||||
|
fill: gradient
|
||||||
|
.conic(..color.map.rainbow),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
#block(clip: false, height: 2em, {
|
||||||
|
text(fill: blue, "Hello")
|
||||||
|
[ ]
|
||||||
|
text(fill: blue.darken(20%).transparentize(50%), "Hello")
|
||||||
|
[ ]
|
||||||
|
text(fill: gradient.linear(..color.map.rainbow), "Hello")
|
||||||
|
[ ]
|
||||||
|
text(fill: pat, "Hello")
|
||||||
|
})
|
||||||
|
#block(clip: true, height: 2em, {
|
||||||
|
text(fill: blue, "Hello")
|
||||||
|
[ ]
|
||||||
|
text(fill: blue.darken(20%).transparentize(50%), "Hello")
|
||||||
|
[ ]
|
||||||
|
text(fill: gradient.linear(..color.map.rainbow), "Hello")
|
||||||
|
[ ]
|
||||||
|
text(fill: pat, "Hello")
|
||||||
|
})
|
||||||
|
Loading…
x
Reference in New Issue
Block a user