mirror of
https://github.com/typst/typst
synced 2025-05-14 04:56:26 +08:00
Support negative dimensions in rectangles (#3807)
This commit is contained in:
parent
c413bef11d
commit
29af23663d
@ -827,7 +827,7 @@ fn write_shape(ctx: &mut PageContext, pos: Point, shape: &Shape) {
|
||||
Geometry::Rect(size) => {
|
||||
let w = size.x.to_f32();
|
||||
let h = size.y.to_f32();
|
||||
if w > 0.0 && h > 0.0 {
|
||||
if w.abs() > f32::EPSILON && h.abs() > f32::EPSILON {
|
||||
ctx.content.rect(x, y, w, h);
|
||||
}
|
||||
}
|
||||
|
@ -570,7 +570,18 @@ fn render_shape(canvas: &mut sk::Pixmap, state: State, shape: &Shape) -> Option<
|
||||
Geometry::Rect(size) => {
|
||||
let w = size.x.to_f32();
|
||||
let h = size.y.to_f32();
|
||||
let rect = sk::Rect::from_xywh(0.0, 0.0, w, h)?;
|
||||
let rect = if w < 0.0 || h < 0.0 {
|
||||
// Skia doesn't normally allow for negative dimensions, but
|
||||
// Typst supports them, so we apply a transform if needed
|
||||
// Because this operation is expensive according to tiny-skia's
|
||||
// docs, we prefer to not apply it if not needed
|
||||
let transform = sk::Transform::from_scale(w.signum(), h.signum());
|
||||
let rect = sk::Rect::from_xywh(0.0, 0.0, w.abs(), h.abs())?;
|
||||
rect.transform(transform)?
|
||||
} else {
|
||||
sk::Rect::from_xywh(0.0, 0.0, w, h)?
|
||||
};
|
||||
|
||||
sk::PathBuilder::from_rect(rect)
|
||||
}
|
||||
Geometry::Path(ref path) => convert_path(path)?,
|
||||
@ -941,8 +952,10 @@ fn to_sk_paint<'a>(
|
||||
.container_transform
|
||||
.post_concat(state.transform.invert().unwrap()),
|
||||
};
|
||||
let width = (container_size.x.to_f32() * state.pixel_per_pt).ceil() as u32;
|
||||
let height = (container_size.y.to_f32() * state.pixel_per_pt).ceil() as u32;
|
||||
let width =
|
||||
(container_size.x.to_f32().abs() * state.pixel_per_pt).ceil() as u32;
|
||||
let height =
|
||||
(container_size.y.to_f32().abs() * state.pixel_per_pt).ceil() as u32;
|
||||
|
||||
*pixmap = Some(cached(
|
||||
gradient,
|
||||
@ -958,8 +971,10 @@ fn to_sk_paint<'a>(
|
||||
sk::SpreadMode::Pad,
|
||||
sk::FilterQuality::Nearest,
|
||||
1.0,
|
||||
fill_transform
|
||||
.pre_scale(1.0 / state.pixel_per_pt, 1.0 / state.pixel_per_pt),
|
||||
fill_transform.pre_scale(
|
||||
container_size.x.signum() as f32 / state.pixel_per_pt,
|
||||
container_size.y.signum() as f32 / state.pixel_per_pt,
|
||||
),
|
||||
);
|
||||
|
||||
sk_paint.anti_alias = gradient.anti_alias();
|
||||
|
@ -117,6 +117,11 @@ impl Abs {
|
||||
pub fn approx_eq(self, other: Self) -> bool {
|
||||
self == other || (self - other).to_raw().abs() < 1e-6
|
||||
}
|
||||
|
||||
/// Returns a number that represent the sign of this length
|
||||
pub fn signum(self) -> f64 {
|
||||
self.0.get().signum()
|
||||
}
|
||||
}
|
||||
|
||||
impl Numeric for Abs {
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 242 KiB After Width: | Height: | Size: 256 KiB |
@ -61,3 +61,18 @@
|
||||
#set par(justify: true)
|
||||
#lorem(100)
|
||||
#rect(lorem(100))
|
||||
|
||||
---
|
||||
// Negative dimensions
|
||||
#rect(width: -1cm, fill: gradient.linear(red, blue))[Reverse left]
|
||||
|
||||
#rect(width: 1cm, fill: gradient.linear(red, blue))[Left]
|
||||
|
||||
#align(center, rect(width: -1cm, fill: gradient.linear(red, blue))[Reverse center])
|
||||
|
||||
#align(center, rect(width: 1cm, fill: gradient.linear(red, blue))[Center])
|
||||
|
||||
#align(right, rect(width: -1cm, fill: gradient.linear(red, blue))[Reverse right])
|
||||
|
||||
#align(right, rect(width: 1cm, fill: gradient.linear(red, blue))[Right])
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user