summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2024-12-17 10:25:27 +0100
committerGitHub <noreply@github.com>2024-12-17 09:25:27 +0000
commit134638525516995d5947c5b3f98ffbc13784a143 (patch)
tree549d3ed3b5a4eac66b585314e772fda092058021
parented67220e4b5ae6b3a1bc50f59bd52b5b1dea3a6b (diff)
Rename `pattern` to `tiling` (#5590)
-rw-r--r--crates/typst-layout/src/shapes.rs6
-rw-r--r--crates/typst-library/src/foundations/ops.rs4
-rw-r--r--crates/typst-library/src/foundations/value.rs16
-rw-r--r--crates/typst-library/src/introspection/locator.rs2
-rw-r--r--crates/typst-library/src/text/mod.rs2
-rw-r--r--crates/typst-library/src/visualize/mod.rs11
-rw-r--r--crates/typst-library/src/visualize/paint.rs28
-rw-r--r--crates/typst-library/src/visualize/stroke.rs26
-rw-r--r--crates/typst-library/src/visualize/tiling.rs (renamed from crates/typst-library/src/visualize/pattern.rs)102
-rw-r--r--crates/typst-pdf/src/color.rs4
-rw-r--r--crates/typst-pdf/src/content.rs14
-rw-r--r--crates/typst-pdf/src/lib.rs10
-rw-r--r--crates/typst-pdf/src/resources.rs44
-rw-r--r--crates/typst-pdf/src/tiling.rs (renamed from crates/typst-pdf/src/pattern.rs)34
-rw-r--r--crates/typst-render/src/paint.rs36
-rw-r--r--crates/typst-render/src/shape.rs8
-rw-r--r--crates/typst-render/src/text.rs8
-rw-r--r--crates/typst-svg/src/lib.rs28
-rw-r--r--crates/typst-svg/src/paint.rs97
-rw-r--r--crates/typst-svg/src/shape.rs14
-rw-r--r--crates/typst-svg/src/text.rs2
-rw-r--r--crates/typst-syntax/src/ast.rs4
-rw-r--r--crates/typst-syntax/src/kind.rs2
-rw-r--r--crates/typst-syntax/src/parser.rs2
-rw-r--r--docs/changelog/0.10.0.md2
-rw-r--r--docs/changelog/0.11.1.md2
-rw-r--r--docs/guides/tables.md4
-rw-r--r--tests/ref/grid-stroke-tiling.png (renamed from tests/ref/grid-stroke-pattern.png)bin1815 -> 1815 bytes
-rw-r--r--tests/ref/tiling-line.png (renamed from tests/ref/pattern-line.png)bin125 -> 125 bytes
-rw-r--r--tests/ref/tiling-lines.png (renamed from tests/ref/pattern-lines.png)bin128 -> 128 bytes
-rw-r--r--tests/ref/tiling-pattern-compatibility.pngbin0 -> 125 bytes
-rw-r--r--tests/ref/tiling-relative-parent.png (renamed from tests/ref/pattern-relative-parent.png)bin347 -> 347 bytes
-rw-r--r--tests/ref/tiling-relative-self.png (renamed from tests/ref/pattern-relative-self.png)bin474 -> 474 bytes
-rw-r--r--tests/ref/tiling-small.png (renamed from tests/ref/pattern-small.png)bin83 -> 83 bytes
-rw-r--r--tests/ref/tiling-spacing-negative.png (renamed from tests/ref/pattern-spacing-negative.png)bin202 -> 202 bytes
-rw-r--r--tests/ref/tiling-spacing-positive.png (renamed from tests/ref/pattern-spacing-positive.png)bin241 -> 241 bytes
-rw-r--r--tests/ref/tiling-spacing-zero.png (renamed from tests/ref/pattern-spacing-zero.png)bin215 -> 215 bytes
-rw-r--r--tests/ref/tiling-stroke-relative-parent.png (renamed from tests/ref/pattern-stroke-relative-parent.png)bin757 -> 757 bytes
-rw-r--r--tests/ref/tiling-stroke.png (renamed from tests/ref/pattern-stroke.png)bin383 -> 383 bytes
-rw-r--r--tests/ref/tiling-text.png (renamed from tests/ref/pattern-text.png)bin5302 -> 5302 bytes
-rw-r--r--tests/suite/layout/grid/stroke.typ4
-rw-r--r--tests/suite/layout/table.typ2
-rw-r--r--tests/suite/text/font.typ6
-rw-r--r--tests/suite/visualize/gradient.typ2
-rw-r--r--tests/suite/visualize/pattern.typ159
-rw-r--r--tests/suite/visualize/rect.typ2
-rw-r--r--tests/suite/visualize/tiling.typ163
47 files changed, 426 insertions, 424 deletions
diff --git a/crates/typst-layout/src/shapes.rs b/crates/typst-layout/src/shapes.rs
index db9acece..2044c917 100644
--- a/crates/typst-layout/src/shapes.rs
+++ b/crates/typst-layout/src/shapes.rs
@@ -719,11 +719,7 @@ fn segment(
false
}
- let solid = stroke
- .dash
- .as_ref()
- .map(|pattern| pattern.array.is_empty())
- .unwrap_or(true);
+ let solid = stroke.dash.as_ref().map(|dash| dash.array.is_empty()).unwrap_or(true);
let use_fill = solid && fill_corners(start, end, corners);
let shape = if use_fill {
diff --git a/crates/typst-library/src/foundations/ops.rs b/crates/typst-library/src/foundations/ops.rs
index b41fce8d..8d12966b 100644
--- a/crates/typst-library/src/foundations/ops.rs
+++ b/crates/typst-library/src/foundations/ops.rs
@@ -144,8 +144,8 @@ pub fn add(lhs: Value, rhs: Value) -> HintedStrResult<Value> {
| (Length(thickness), Gradient(gradient)) => {
Stroke::from_pair(gradient, thickness).into_value()
}
- (Pattern(pattern), Length(thickness)) | (Length(thickness), Pattern(pattern)) => {
- Stroke::from_pair(pattern, thickness).into_value()
+ (Tiling(tiling), Length(thickness)) | (Length(thickness), Tiling(tiling)) => {
+ Stroke::from_pair(tiling, thickness).into_value()
}
(Duration(a), Duration(b)) => Duration(a + b),
diff --git a/crates/typst-library/src/foundations/value.rs b/crates/typst-library/src/foundations/value.rs
index 538b4f1b..eb0d6eed 100644
--- a/crates/typst-library/src/foundations/value.rs
+++ b/crates/typst-library/src/foundations/value.rs
@@ -20,7 +20,7 @@ use crate::foundations::{
};
use crate::layout::{Abs, Angle, Em, Fr, Length, Ratio, Rel};
use crate::text::{RawContent, RawElem, TextElem};
-use crate::visualize::{Color, Gradient, Pattern};
+use crate::visualize::{Color, Gradient, Tiling};
/// A computational value.
#[derive(Default, Clone)]
@@ -50,8 +50,8 @@ pub enum Value {
Color(Color),
/// A gradient value: `gradient.linear(...)`.
Gradient(Gradient),
- /// A pattern fill: `pattern(...)`.
- Pattern(Pattern),
+ /// A tiling fill: `tiling(...)`.
+ Tiling(Tiling),
/// A symbol: `arrow.l`.
Symbol(Symbol),
/// A version.
@@ -130,7 +130,7 @@ impl Value {
Self::Fraction(_) => Type::of::<Fr>(),
Self::Color(_) => Type::of::<Color>(),
Self::Gradient(_) => Type::of::<Gradient>(),
- Self::Pattern(_) => Type::of::<Pattern>(),
+ Self::Tiling(_) => Type::of::<Tiling>(),
Self::Symbol(_) => Type::of::<Symbol>(),
Self::Version(_) => Type::of::<Version>(),
Self::Str(_) => Type::of::<Str>(),
@@ -244,7 +244,7 @@ impl Debug for Value {
Self::Fraction(v) => Debug::fmt(v, f),
Self::Color(v) => Debug::fmt(v, f),
Self::Gradient(v) => Debug::fmt(v, f),
- Self::Pattern(v) => Debug::fmt(v, f),
+ Self::Tiling(v) => Debug::fmt(v, f),
Self::Symbol(v) => Debug::fmt(v, f),
Self::Version(v) => Debug::fmt(v, f),
Self::Str(v) => Debug::fmt(v, f),
@@ -282,7 +282,7 @@ impl Repr for Value {
Self::Fraction(v) => v.repr(),
Self::Color(v) => v.repr(),
Self::Gradient(v) => v.repr(),
- Self::Pattern(v) => v.repr(),
+ Self::Tiling(v) => v.repr(),
Self::Symbol(v) => v.repr(),
Self::Version(v) => v.repr(),
Self::Str(v) => v.repr(),
@@ -333,7 +333,7 @@ impl Hash for Value {
Self::Fraction(v) => v.hash(state),
Self::Color(v) => v.hash(state),
Self::Gradient(v) => v.hash(state),
- Self::Pattern(v) => v.hash(state),
+ Self::Tiling(v) => v.hash(state),
Self::Symbol(v) => v.hash(state),
Self::Version(v) => v.hash(state),
Self::Str(v) => v.hash(state),
@@ -640,7 +640,7 @@ primitive! { Rel<Length>: "relative length",
primitive! { Fr: "fraction", Fraction }
primitive! { Color: "color", Color }
primitive! { Gradient: "gradient", Gradient }
-primitive! { Pattern: "pattern", Pattern }
+primitive! { Tiling: "tiling", Tiling }
primitive! { Symbol: "symbol", Symbol }
primitive! { Version: "version", Version }
primitive! {
diff --git a/crates/typst-library/src/introspection/locator.rs b/crates/typst-library/src/introspection/locator.rs
index a84cf163..3ba3d648 100644
--- a/crates/typst-library/src/introspection/locator.rs
+++ b/crates/typst-library/src/introspection/locator.rs
@@ -161,7 +161,7 @@ impl<'a> Locator<'a> {
///
/// Should typically only be created at the document level, though there
/// are a few places where we use it as well that just don't support
- /// introspection (e.g. drawable patterns).
+ /// introspection (e.g. tilings).
pub fn root() -> Self {
Self { local: 0, outer: None }
}
diff --git a/crates/typst-library/src/text/mod.rs b/crates/typst-library/src/text/mod.rs
index 62c87051..91927b57 100644
--- a/crates/typst-library/src/text/mod.rs
+++ b/crates/typst-library/src/text/mod.rs
@@ -249,7 +249,7 @@ pub struct TextElem {
if paint.v.relative() == Smart::Custom(RelativeTo::Self_) {
bail!(
paint.span,
- "gradients and patterns on text must be relative to the parent";
+ "gradients and tilings on text must be relative to the parent";
hint: "make sure to set `relative: auto` on your text fill"
);
}
diff --git a/crates/typst-library/src/visualize/mod.rs b/crates/typst-library/src/visualize/mod.rs
index 5c8bf646..61c56a61 100644
--- a/crates/typst-library/src/visualize/mod.rs
+++ b/crates/typst-library/src/visualize/mod.rs
@@ -6,10 +6,10 @@ mod image;
mod line;
mod paint;
mod path;
-mod pattern;
mod polygon;
mod shape;
mod stroke;
+mod tiling;
pub use self::color::*;
pub use self::gradient::*;
@@ -17,12 +17,12 @@ pub use self::image::*;
pub use self::line::*;
pub use self::paint::*;
pub use self::path::*;
-pub use self::pattern::*;
pub use self::polygon::*;
pub use self::shape::*;
pub use self::stroke::*;
+pub use self::tiling::*;
-use crate::foundations::{category, Category, Scope};
+use crate::foundations::{category, Category, Scope, Type};
/// Drawing and data visualization.
///
@@ -37,7 +37,7 @@ pub(super) fn define(global: &mut Scope) {
global.category(VISUALIZE);
global.define_type::<Color>();
global.define_type::<Gradient>();
- global.define_type::<Pattern>();
+ global.define_type::<Tiling>();
global.define_type::<Stroke>();
global.define_elem::<ImageElem>();
global.define_elem::<LineElem>();
@@ -47,4 +47,7 @@ pub(super) fn define(global: &mut Scope) {
global.define_elem::<CircleElem>();
global.define_elem::<PolygonElem>();
global.define_elem::<PathElem>();
+
+ // Compatibility.
+ global.define("pattern", Type::of::<Tiling>());
}
diff --git a/crates/typst-library/src/visualize/paint.rs b/crates/typst-library/src/visualize/paint.rs
index cd1006aa..a618e515 100644
--- a/crates/typst-library/src/visualize/paint.rs
+++ b/crates/typst-library/src/visualize/paint.rs
@@ -3,7 +3,7 @@ use std::fmt::{self, Debug, Formatter};
use ecow::EcoString;
use crate::foundations::{cast, Repr, Smart};
-use crate::visualize::{Color, Gradient, Pattern, RelativeTo};
+use crate::visualize::{Color, Gradient, RelativeTo, Tiling};
/// How a fill or stroke should be painted.
#[derive(Clone, Eq, PartialEq, Hash)]
@@ -12,8 +12,8 @@ pub enum Paint {
Solid(Color),
/// A gradient.
Gradient(Gradient),
- /// A pattern.
- Pattern(Pattern),
+ /// A tiling.
+ Tiling(Tiling),
}
impl Paint {
@@ -21,7 +21,7 @@ impl Paint {
pub fn unwrap_solid(&self) -> Color {
match self {
Self::Solid(color) => *color,
- Self::Gradient(_) | Self::Pattern(_) => panic!("expected solid color"),
+ Self::Gradient(_) | Self::Tiling(_) => panic!("expected solid color"),
}
}
@@ -30,7 +30,7 @@ impl Paint {
match self {
Self::Solid(_) => Smart::Auto,
Self::Gradient(gradient) => gradient.relative(),
- Self::Pattern(pattern) => pattern.relative(),
+ Self::Tiling(tiling) => tiling.relative(),
}
}
@@ -44,8 +44,8 @@ impl Paint {
Self::Gradient(gradient) => {
Self::Gradient(gradient.clone().with_relative(RelativeTo::Parent))
}
- Self::Pattern(pattern) => {
- Self::Pattern(pattern.clone().with_relative(RelativeTo::Parent))
+ Self::Tiling(tiling) => {
+ Self::Tiling(tiling.clone().with_relative(RelativeTo::Parent))
}
}
}
@@ -56,14 +56,14 @@ impl Debug for Paint {
match self {
Self::Solid(v) => v.fmt(f),
Self::Gradient(v) => v.fmt(f),
- Self::Pattern(v) => v.fmt(f),
+ Self::Tiling(v) => v.fmt(f),
}
}
}
-impl From<Pattern> for Paint {
- fn from(pattern: Pattern) -> Self {
- Self::Pattern(pattern)
+impl From<Tiling> for Paint {
+ fn from(tiling: Tiling) -> Self {
+ Self::Tiling(tiling)
}
}
@@ -72,7 +72,7 @@ impl Repr for Paint {
match self {
Self::Solid(color) => color.repr(),
Self::Gradient(gradient) => gradient.repr(),
- Self::Pattern(pattern) => pattern.repr(),
+ Self::Tiling(tiling) => tiling.repr(),
}
}
}
@@ -94,9 +94,9 @@ cast! {
self => match self {
Self::Solid(color) => color.into_value(),
Self::Gradient(gradient) => gradient.into_value(),
- Self::Pattern(pattern) => pattern.into_value(),
+ Self::Tiling(tiling) => tiling.into_value(),
},
color: Color => Self::Solid(color),
gradient: Gradient => Self::Gradient(gradient),
- pattern: Pattern => Self::Pattern(pattern),
+ tiling: Tiling => Self::Tiling(tiling),
}
diff --git a/crates/typst-library/src/visualize/stroke.rs b/crates/typst-library/src/visualize/stroke.rs
index 4ca10920..2ab493a5 100644
--- a/crates/typst-library/src/visualize/stroke.rs
+++ b/crates/typst-library/src/visualize/stroke.rs
@@ -7,7 +7,7 @@ use crate::foundations::{
Resolve, Smart, StyleChain, Value,
};
use crate::layout::{Abs, Length};
-use crate::visualize::{Color, Gradient, Paint, Pattern};
+use crate::visualize::{Color, Gradient, Paint, Tiling};
/// Defines how to draw a line.
///
@@ -213,9 +213,9 @@ impl<T: Numeric> Stroke<T> {
thickness: self.thickness.map(&f),
cap: self.cap,
join: self.join,
- dash: self.dash.map(|pattern| {
- pattern.map(|pattern| DashPattern {
- array: pattern
+ dash: self.dash.map(|dash| {
+ dash.map(|dash| DashPattern {
+ array: dash
.array
.into_iter()
.map(|l| match l {
@@ -223,7 +223,7 @@ impl<T: Numeric> Stroke<T> {
DashLength::LineWidth => DashLength::LineWidth,
})
.collect(),
- phase: f(pattern.phase),
+ phase: f(dash.phase),
})
}),
miter_limit: self.miter_limit,
@@ -237,14 +237,10 @@ impl Stroke<Abs> {
let thickness = self.thickness.unwrap_or(default.thickness);
let dash = self
.dash
- .map(|pattern| {
- pattern.map(|pattern| DashPattern {
- array: pattern
- .array
- .into_iter()
- .map(|l| l.finish(thickness))
- .collect(),
- phase: pattern.phase,
+ .map(|dash| {
+ dash.map(|dash| DashPattern {
+ array: dash.array.into_iter().map(|l| l.finish(thickness)).collect(),
+ phase: dash.phase,
})
})
.unwrap_or(default.dash);
@@ -372,8 +368,8 @@ cast! {
paint: Smart::Custom(gradient.into()),
..Default::default()
},
- pattern: Pattern => Self {
- paint: Smart::Custom(pattern.into()),
+ tiling: Tiling => Self {
+ paint: Smart::Custom(tiling.into()),
..Default::default()
},
mut dict: Dict => {
diff --git a/crates/typst-library/src/visualize/pattern.rs b/crates/typst-library/src/visualize/tiling.rs
index 2017ea65..d699d3b6 100644
--- a/crates/typst-library/src/visualize/pattern.rs
+++ b/crates/typst-library/src/visualize/tiling.rs
@@ -13,18 +13,18 @@ use crate::layout::{Abs, Axes, Frame, Length, Region, Size};
use crate::visualize::RelativeTo;
use crate::World;
-/// A repeating pattern fill.
+/// A repeating tiling fill.
///
-/// Typst supports the most common pattern type of tiled patterns, where a
-/// pattern is repeated in a grid-like fashion, covering the entire area of an
-/// element that is filled or stroked. The pattern is defined by a tile size and
-/// a body defining the content of each cell. You can also add horizontal or
-/// vertical spacing between the cells of the pattern.
+/// Typst supports the most common type of tilings, where a pattern is repeated
+/// in a grid-like fashion, covering the entire area of an element that is
+/// filled or stroked. The pattern is defined by a tile size and a body defining
+/// the content of each cell. You can also add horizontal or vertical spacing
+/// between the cells of the tiling.
///
/// # Examples
///
/// ```example
-/// #let pat = pattern(size: (30pt, 30pt))[
+/// #let pat = tiling(size: (30pt, 30pt))[
/// #place(line(start: (0%, 0%), end: (100%, 100%)))
/// #place(line(start: (0%, 100%), end: (100%, 0%)))
/// ]
@@ -32,14 +32,14 @@ use crate::World;
/// #rect(fill: pat, width: 100%, height: 60pt, stroke: 1pt)
/// ```
///
-/// Patterns are also supported on text, but only when setting the
-/// [relativeness]($pattern.relative) to either `{auto}` (the default value) or
-/// `{"parent"}`. To create word-by-word or glyph-by-glyph patterns, you can
+/// Tilings are also supported on text, but only when setting the
+/// [relativeness]($tiling.relative) to either `{auto}` (the default value) or
+/// `{"parent"}`. To create word-by-word or glyph-by-glyph tilings, you can
/// wrap the words or characters of your text in [boxes]($box) manually or
/// through a [show rule]($styling/#show-rules).
///
/// ```example
-/// #let pat = pattern(
+/// #let pat = tiling(
/// size: (30pt, 30pt),
/// relative: "parent",
/// square(
@@ -54,13 +54,13 @@ use crate::World;
/// ```
///
/// You can also space the elements further or closer apart using the
-/// [`spacing`]($pattern.spacing) feature of the pattern. If the spacing
-/// is lower than the size of the pattern, the pattern will overlap.
-/// If it is higher, the pattern will have gaps of the same color as the
-/// background of the pattern.
+/// [`spacing`]($tiling.spacing) feature of the tiling. If the spacing
+/// is lower than the size of the tiling, the tiling will overlap.
+/// If it is higher, the tiling will have gaps of the same color as the
+/// background of the tiling.
///
/// ```example
-/// #let pat = pattern(
+/// #let pat = tiling(
/// size: (30pt, 30pt),
/// spacing: (10pt, 10pt),
/// relative: "parent",
@@ -79,11 +79,11 @@ use crate::World;
/// ```
///
/// # Relativeness
-/// The location of the starting point of the pattern is dependent on the
+/// The location of the starting point of the tiling is dependent on the
/// dimensions of a container. This container can either be the shape that it is
/// being painted on, or the closest surrounding container. This is controlled
-/// by the `relative` argument of a pattern constructor. By default, patterns
-/// are relative to the shape they are being painted on, unless the pattern is
+/// by the `relative` argument of a tiling constructor. By default, tilings
+/// are relative to the shape they are being painted on, unless the tiling is
/// applied on text, in which case they are relative to the closest ancestor
/// container.
///
@@ -94,29 +94,33 @@ use crate::World;
/// contains the shape. This includes the boxes and blocks that are implicitly
/// created by show rules and elements. For example, a [`rotate`] will not
/// affect the parent of a gradient, but a [`grid`] will.
-#[ty(scope, cast)]
+///
+/// # Compatibility
+/// This type used to be called `pattern`. The name remains as an alias, but is
+/// deprecated since Typst 0.13.
+#[ty(scope, cast, keywords = ["pattern"])]
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
-pub struct Pattern(Arc<Repr>);
+pub struct Tiling(Arc<Repr>);
-/// Internal representation of [`Pattern`].
+/// Internal representation of [`Tiling`].
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
struct Repr {
- /// The pattern's rendered content.
+ /// The tiling's rendered content.
frame: LazyHash<Frame>,
- /// The pattern's tile size.
+ /// The tiling's tile size.
size: Size,
- /// The pattern's tile spacing.
+ /// The tiling's tile spacing.
spacing: Size,
- /// The pattern's relative transform.
+ /// The tiling's relative transform.
relative: Smart<RelativeTo>,
}
#[scope]
-impl Pattern {
- /// Construct a new pattern.
+impl Tiling {
+ /// Construct a new tiling.
///
/// ```example
- /// #let pat = pattern(
+ /// #let pat = tiling(
/// size: (20pt, 20pt),
/// relative: "parent",
/// place(
@@ -136,15 +140,15 @@ impl Pattern {
engine: &mut Engine,
/// The callsite span.
span: Span,
- /// The bounding box of each cell of the pattern.
+ /// The bounding box of each cell of the tiling.
#[named]
#[default(Spanned::new(Smart::Auto, Span::detached()))]
size: Spanned<Smart<Axes<Length>>>,
- /// The spacing between cells of the pattern.
+ /// The spacing between cells of the tiling.
#[named]
#[default(Spanned::new(Axes::splat(Length::zero()), Span::detached()))]
spacing: Spanned<Axes<Length>>,
- /// The [relative placement](#relativeness) of the pattern.
+ /// The [relative placement](#relativeness) of the tiling.
///
/// For an element placed at the root/top level of the document, the
/// parent is the page itself. For other elements, the parent is the
@@ -153,14 +157,14 @@ impl Pattern {
#[named]
#[default(Smart::Auto)]
relative: Smart<RelativeTo>,
- /// The content of each cell of the pattern.
+ /// The content of each cell of the tiling.
body: Content,
- ) -> SourceResult<Pattern> {
+ ) -> SourceResult<Tiling> {
let size_span = size.span;
if let Smart::Custom(size) = size.v {
// Ensure that sizes are absolute.
if !size.x.em.is_zero() || !size.y.em.is_zero() {
- bail!(size_span, "pattern tile size must be absolute");
+ bail!(size_span, "tile size must be absolute");
}
// Ensure that sizes are non-zero and finite.
@@ -169,25 +173,25 @@ impl Pattern {
|| !size.x.is_finite()
|| !size.y.is_finite()
{
- bail!(size_span, "pattern tile size must be non-zero and non-infinite");
+ bail!(size_span, "tile size must be non-zero and non-infinite");
}
}
// Ensure that spacing is absolute.
if !spacing.v.x.em.is_zero() || !spacing.v.y.em.is_zero() {
- bail!(spacing.span, "pattern tile spacing must be absolute");
+ bail!(spacing.span, "tile spacing must be absolute");
}
// Ensure that spacing is finite.
if !spacing.v.x.is_finite() || !spacing.v.y.is_finite() {
- bail!(spacing.span, "pattern tile spacing must be finite");
+ bail!(spacing.span, "tile spacing must be finite");
}
// The size of the frame
let size = size.v.map(|l| l.map(|a| a.abs));
let region = size.unwrap_or_else(|| Axes::splat(Abs::inf()));
- // Layout the pattern.
+ // Layout the tiling.
let world = engine.world;
let library = world.library();
let locator = Locator::root();
@@ -204,7 +208,7 @@ impl Pattern {
// Check that the frame is non-zero.
if frame.width().is_zero() || frame.height().is_zero() {
bail!(
- span, "pattern tile size must be non-zero";
+ span, "tile size must be non-zero";
hint: "try setting the size manually"
);
}
@@ -218,8 +222,8 @@ impl Pattern {
}
}
-impl Pattern {
- /// Set the relative placement of the pattern.
+impl Tiling {
+ /// Set the relative placement of the tiling.
pub fn with_relative(mut self, relative: RelativeTo) -> Self {
if let Some(this) = Arc::get_mut(&mut self.0) {
this.relative = Smart::Custom(relative);
@@ -233,27 +237,27 @@ impl Pattern {
self
}
- /// Return the frame of the pattern.
+ /// Return the frame of the tiling.
pub fn frame(&self) -> &Frame {
&self.0.frame
}
- /// Return the size of the pattern in absolute units.
+ /// Return the size of the tiling in absolute units.
pub fn size(&self) -> Size {
self.0.size
}
- /// Return the spacing of the pattern in absolute units.
+ /// Return the spacing of the tiling in absolute units.
pub fn spacing(&self) -> Size {
self.0.spacing
}
- /// Returns the relative placement of the pattern.
+ /// Returns the relative placement of the tiling.
pub fn relative(&self) -> Smart<RelativeTo> {
self.0.relative
}
- /// Returns the relative placement of the pattern.
+ /// Returns the relative placement of the tiling.
pub fn unwrap_relative(&self, on_text: bool) -> RelativeTo {
self.0.relative.unwrap_or_else(|| {
if on_text {
@@ -265,10 +269,10 @@ impl Pattern {
}
}
-impl repr::Repr for Pattern {
+impl repr::Repr for Tiling {
fn repr(&self) -> EcoString {
let mut out =
- eco_format!("pattern(({}, {})", self.0.size.x.repr(), self.0.size.y.repr());
+ eco_format!("tiling(({}, {})", self.0.size.x.repr(), self.0.size.y.repr());
if self.0.spacing.is_zero() {
out.push_str(", spacing: (");
diff --git a/crates/typst-pdf/src/color.rs b/crates/typst-pdf/src/color.rs
index 7097c14a..412afca9 100644
--- a/crates/typst-pdf/src/color.rs
+++ b/crates/typst-pdf/src/color.rs
@@ -222,7 +222,7 @@ impl PaintEncode for Paint {
match self {
Self::Solid(c) => c.set_as_fill(ctx, on_text, transforms),
Self::Gradient(gradient) => gradient.set_as_fill(ctx, on_text, transforms),
- Self::Pattern(pattern) => pattern.set_as_fill(ctx, on_text, transforms),
+ Self::Tiling(tiling) => tiling.set_as_fill(ctx, on_text, transforms),
}
}
@@ -235,7 +235,7 @@ impl PaintEncode for Paint {
match self {
Self::Solid(c) => c.set_as_stroke(ctx, on_text, transforms),
Self::Gradient(gradient) => gradient.set_as_stroke(ctx, on_text, transforms),
- Self::Pattern(pattern) => pattern.set_as_stroke(ctx, on_text, transforms),
+ Self::Tiling(tiling) => tiling.set_as_stroke(ctx, on_text, transforms),
}
}
}
diff --git a/crates/typst-pdf/src/content.rs b/crates/typst-pdf/src/content.rs
index ce72365d..d57f2093 100644
--- a/crates/typst-pdf/src/content.rs
+++ b/crates/typst-pdf/src/content.rs
@@ -1,6 +1,6 @@
//! Generic writer for PDF content.
//!
-//! It is used to write page contents, color glyph instructions, and patterns.
+//! It is used to write page contents, color glyph instructions, and tilings.
//!
//! See also [`pdf_writer::Content`].
@@ -96,7 +96,7 @@ pub struct Encoded {
/// objects only through resources.
///
/// Content streams can be used for page contents, but also to describe color
-/// glyphs and patterns.
+/// glyphs and tilings.
pub struct Builder<'a, R = ()> {
/// Settings for PDF export.
pub(crate) options: &'a PdfOptions<'a>,
@@ -187,7 +187,7 @@ impl State {
}
}
-/// Subset of the state used to calculate the transform of gradients and patterns.
+/// Subset of the state used to calculate the transform of gradients and tilings.
#[derive(Debug, Clone, Copy)]
pub(super) struct Transforms {
/// The transform of the current item.
@@ -229,7 +229,7 @@ impl Builder<'_, ()> {
let get_opacity = |paint: &Paint| {
let color = match paint {
Paint::Solid(color) => *color,
- Paint::Gradient(_) | Paint::Pattern(_) => return 255,
+ Paint::Gradient(_) | Paint::Tiling(_) => return 255,
};
color.alpha().map_or(255, |v| (v * 255.0).round() as u8)
@@ -330,10 +330,10 @@ impl Builder<'_, ()> {
self.content.set_line_join(to_pdf_line_join(*join));
}
if self.state.stroke.as_ref().map(|s| &s.dash) != Some(dash) {
- if let Some(pattern) = dash {
+ if let Some(dash) = dash {
self.content.set_dash_pattern(
- pattern.array.iter().map(|l| l.to_f32()),
- pattern.phase.to_f32(),
+ dash.array.iter().map(|l| l.to_f32()),
+ dash.phase.to_f32(),
);
} else {
self.content.set_dash_pattern([], 0.0);
diff --git a/crates/typst-pdf/src/lib.rs b/crates/typst-pdf/src/lib.rs
index f9b4e902..c315684d 100644
--- a/crates/typst-pdf/src/lib.rs
+++ b/crates/typst-pdf/src/lib.rs
@@ -11,8 +11,8 @@ mod image;
mod named_destination;
mod outline;
mod page;
-mod pattern;
mod resources;
+mod tiling;
use std::collections::HashMap;
use std::fmt::{self, Debug, Formatter};
@@ -39,10 +39,10 @@ use crate::gradient::{write_gradients, PdfGradient};
use crate::image::write_images;
use crate::named_destination::{write_named_destinations, NamedDestinations};
use crate::page::{alloc_page_refs, traverse_pages, write_page_tree, EncodedPage};
-use crate::pattern::{write_patterns, PdfPattern};
use crate::resources::{
alloc_resources_refs, write_resource_dictionaries, Resources, ResourcesRefs,
};
+use crate::tiling::{write_tilings, PdfTiling};
/// Export a document into a PDF file.
///
@@ -65,7 +65,7 @@ pub fn pdf(document: &PagedDocument, options: &PdfOptions) -> SourceResult<Vec<u
color_fonts: builder.run(write_color_fonts)?,
images: builder.run(write_images)?,
gradients: builder.run(write_gradients)?,
- patterns: builder.run(write_patterns)?,
+ tilings: builder.run(write_tilings)?,
ext_gs: builder.run(write_graphic_states)?,
})
})?
@@ -267,8 +267,8 @@ struct References {
images: HashMap<Image, Ref>,
/// The IDs of written gradients.
gradients: HashMap<PdfGradient, Ref>,
- /// The IDs of written patterns.
- patterns: HashMap<PdfPattern, Ref>,
+ /// The IDs of written tilings.
+ tilings: HashMap<PdfTiling, Ref>,
/// The IDs of written external graphics states.
ext_gs: HashMap<ExtGState, Ref>,
}
diff --git a/crates/typst-pdf/src/resources.rs b/crates/typst-pdf/src/resources.rs
index d3fde5dd..bdbf2f1e 100644
--- a/crates/typst-pdf/src/resources.rs
+++ b/crates/typst-pdf/src/resources.rs
@@ -23,7 +23,7 @@ use crate::color_font::ColorFontMap;
use crate::extg::ExtGState;
use crate::gradient::PdfGradient;
use crate::image::EncodedImage;
-use crate::pattern::PatternRemapper;
+use crate::tiling::TilingRemapper;
use crate::{PdfChunk, Renumber, WithEverything, WithResources};
/// All the resources that have been collected when traversing the document.
@@ -31,16 +31,16 @@ use crate::{PdfChunk, Renumber, WithEverything, WithResources};
/// This does not allocate references to resources, only track what was used
/// and deduplicate what can be deduplicated.
///
-/// You may notice that this structure is a tree: [`PatternRemapper`] and
+/// You may notice that this structure is a tree: [`TilingRemapper`] and
/// [`ColorFontMap`] (that are present in the fields of [`Resources`]),
/// themselves contain [`Resources`] (that will be called "sub-resources" from
-/// now on). Because color glyphs and patterns are defined using content
+/// now on). Because color glyphs and tilings are defined using content
/// streams, just like pages, they can refer to resources too, which are tracked
/// by the respective sub-resources.
///
/// Each instance of this structure will become a `/Resources` dictionary in
/// the final PDF. It is not possible to use a single shared dictionary for all
-/// pages, patterns and color fonts, because if a resource is listed in its own
+/// pages, tilings and color fonts, because if a resource is listed in its own
/// `/Resources` dictionary, some PDF readers will fail to open the document.
///
/// Because we need to lazily initialize sub-resources (we don't know how deep
@@ -66,8 +66,8 @@ pub struct Resources<R = Ref> {
pub deferred_images: HashMap<usize, (Deferred<StrResult<EncodedImage>>, Span)>,
/// Deduplicates gradients used across the document.
pub gradients: Remapper<PdfGradient>,
- /// Deduplicates patterns used across the document.
- pub patterns: Option<Box<PatternRemapper<R>>>,
+ /// Deduplicates tilings used across the document.
+ pub tilings: Option<Box<TilingRemapper<R>>>,
/// Deduplicates external graphics states used across the document.
pub ext_gs: Remapper<ExtGState>,
/// Deduplicates color glyphs.
@@ -107,8 +107,8 @@ impl<R: Renumber> Renumber for Resources<R> {
color_fonts.resources.renumber(offset);
}
- if let Some(patterns) = &mut self.patterns {
- patterns.resources.renumber(offset);
+ if let Some(tilings) = &mut self.tilings {
+ tilings.resources.renumber(offset);
}
}
}
@@ -122,7 +122,7 @@ impl Default for Resources<()> {
images: Remapper::new("Im"),
deferred_images: HashMap::new(),
gradients: Remapper::new("Gr"),
- patterns: None,
+ tilings: None,
ext_gs: Remapper::new("Gs"),
color_fonts: None,
languages: BTreeMap::new(),
@@ -144,9 +144,9 @@ impl Resources<()> {
images: self.images,
deferred_images: self.deferred_images,
gradients: self.gradients,
- patterns: self
- .patterns
- .zip(refs.patterns.as_ref())
+ tilings: self
+ .tilings
+ .zip(refs.tilings.as_ref())
.map(|(p, r)| Box::new(p.with_refs(r))),
ext_gs: self.ext_gs,
color_fonts: self
@@ -172,8 +172,8 @@ impl<R> Resources<R> {
if let Some(color_fonts) = &self.color_fonts {
color_fonts.resources.traverse(process)?;
}
- if let Some(patterns) = &self.patterns {
- patterns.resources.traverse(process)?;
+ if let Some(tilings) = &self.tilings {
+ tilings.resources.traverse(process)?;
}
Ok(())
}
@@ -186,7 +186,7 @@ impl<R> Resources<R> {
pub struct ResourcesRefs {
pub reference: Ref,
pub color_fonts: Option<Box<ResourcesRefs>>,
- pub patterns: Option<Box<ResourcesRefs>>,
+ pub tilings: Option<Box<ResourcesRefs>>,
}
impl Renumber for ResourcesRefs {
@@ -195,8 +195,8 @@ impl Renumber for ResourcesRefs {
if let Some(color_fonts) = &mut self.color_fonts {
color_fonts.renumber(offset);
}
- if let Some(patterns) = &mut self.patterns {
- patterns.renumber(offset);
+ if let Some(tilings) = &mut self.tilings {
+ tilings.renumber(offset);
}
}
}
@@ -214,8 +214,8 @@ pub fn alloc_resources_refs(
.color_fonts
.as_ref()
.map(|c| Box::new(refs_for(&c.resources, chunk))),
- patterns: resources
- .patterns
+ tilings: resources
+ .tilings
.as_ref()
.map(|p| Box::new(refs_for(&p.resources, chunk))),
}
@@ -231,7 +231,7 @@ pub fn alloc_resources_refs(
/// to the root node of the page tree because using the resource inheritance
/// feature breaks PDF merging with Apple Preview.
///
-/// Also write resource dictionaries for Type3 fonts and patterns.
+/// Also write resource dictionaries for Type3 fonts and PDF patterns.
pub fn write_resource_dictionaries(ctx: &WithEverything) -> SourceResult<(PdfChunk, ())> {
let mut chunk = PdfChunk::new();
let mut used_color_spaces = ColorSpaces::default();
@@ -266,8 +266,8 @@ pub fn write_resource_dictionaries(ctx: &WithEverything) -> SourceResult<(PdfChu
resources
.gradients
.write(&ctx.references.gradients, &mut patterns_dict);
- if let Some(p) = &resources.patterns {
- p.remapper.write(&ctx.references.patterns, &mut patterns_dict);
+ if let Some(p) = &resources.tilings {
+ p.remapper.write(&ctx.references.tilings, &mut patterns_dict);
}
patterns_dict.finish();
diff --git a/crates/typst-pdf/src/pattern.rs b/crates/typst-pdf/src/tiling.rs
index ddc22fbd..f8950f34 100644
--- a/crates/typst-pdf/src/pattern.rs
+++ b/crates/typst-pdf/src/tiling.rs
@@ -5,7 +5,7 @@ use pdf_writer::types::{ColorSpaceOperand, PaintType, TilingType};
use pdf_writer::{Filter, Name, Rect, Ref};
use typst_library::diag::SourceResult;
use typst_library::layout::{Abs, Ratio, Transform};
-use typst_library::visualize::{Pattern, RelativeTo};
+use typst_library::visualize::{RelativeTo, Tiling};
use typst_utils::Numeric;
use crate::color::PaintEncode;
@@ -14,18 +14,18 @@ use crate::{content, transform_to_array, PdfChunk, Resources, WithGlobalRefs};
/// Writes the actual patterns (tiling patterns) to the PDF.
/// This is performed once after writing all pages.
-pub fn write_patterns(
+pub fn write_tilings(
context: &WithGlobalRefs,
-) -> SourceResult<(PdfChunk, HashMap<PdfPattern, Ref>)> {
+) -> SourceResult<(PdfChunk, HashMap<PdfTiling, Ref>)> {
let mut chunk = PdfChunk::new();
let mut out = HashMap::new();
context.resources.traverse(&mut |resources| {
- let Some(patterns) = &resources.patterns else {
+ let Some(patterns) = &resources.tilings else {
return Ok(());
};
for pdf_pattern in patterns.remapper.items() {
- let PdfPattern { transform, pattern, content, .. } = pdf_pattern;
+ let PdfTiling { transform, pattern, content, .. } = pdf_pattern;
if out.contains_key(pdf_pattern) {
continue;
}
@@ -69,11 +69,11 @@ pub fn write_patterns(
/// A pattern and its transform.
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
-pub struct PdfPattern {
+pub struct PdfTiling {
/// The transform to apply to the pattern.
pub transform: Transform,
/// The pattern to paint.
- pub pattern: Pattern,
+ pub pattern: Tiling,
/// The rendered pattern.
pub content: Vec<u8>,
}
@@ -81,14 +81,14 @@ pub struct PdfPattern {
/// Registers a pattern with the PDF.
fn register_pattern(
ctx: &mut content::Builder,
- pattern: &Pattern,
+ pattern: &Tiling,
on_text: bool,
mut transforms: content::Transforms,
) -> SourceResult<usize> {
let patterns = ctx
.resources
- .patterns
- .get_or_insert_with(|| Box::new(PatternRemapper::new()));
+ .tilings
+ .get_or_insert_with(|| Box::new(TilingRemapper::new()));
// Edge cases for strokes.
if transforms.size.x.is_zero() {
@@ -113,7 +113,7 @@ fn register_pattern(
None,
)?;
- let pdf_pattern = PdfPattern {
+ let pdf_pattern = PdfTiling {
transform,
pattern: pattern.clone(),
content: content.content.wait().clone(),
@@ -122,7 +122,7 @@ fn register_pattern(
Ok(patterns.remapper.insert(pdf_pattern))
}
-impl PaintEncode for Pattern {
+impl PaintEncode for Tiling {
fn set_as_fill(
&self,
ctx: &mut content::Builder,
@@ -159,14 +159,14 @@ impl PaintEncode for Pattern {
}
/// De-duplicate patterns and the resources they require to be drawn.
-pub struct PatternRemapper<R> {
+pub struct TilingRemapper<R> {
/// Pattern de-duplicator.
- pub remapper: Remapper<PdfPattern>,
+ pub remapper: Remapper<PdfTiling>,
/// PDF resources that are used by these patterns.
pub resources: Resources<R>,
}
-impl PatternRemapper<()> {
+impl TilingRemapper<()> {
pub fn new() -> Self {
Self {
remapper: Remapper::new("P"),
@@ -175,8 +175,8 @@ impl PatternRemapper<()> {
}
/// Allocate a reference to the resource dictionary of these patterns.
- pub fn with_refs(self, refs: &ResourcesRefs) -> PatternRemapper<Ref> {
- PatternRemapper {
+ pub fn with_refs(self, refs: &ResourcesRefs) -> TilingRemapper<Ref> {
+ TilingRemapper {
remapper: self.remapper,
resources: self.resources.with_refs(refs),
}
diff --git a/crates/typst-render/src/paint.rs b/crates/typst-render/src/paint.rs
index 689f28a8..ce92fd6a 100644
--- a/crates/typst-render/src/paint.rs
+++ b/crates/typst-render/src/paint.rs
@@ -2,7 +2,7 @@ use std::sync::Arc;
use tiny_skia as sk;
use typst_library::layout::{Axes, Point, Ratio, Size};
-use typst_library::visualize::{Color, Gradient, Paint, Pattern, RelativeTo};
+use typst_library::visualize::{Color, Gradient, Paint, RelativeTo, Tiling};
use crate::{AbsExt, State};
@@ -72,26 +72,26 @@ impl PaintSampler for GradientSampler<'_> {
}
}
-/// State used when sampling patterns for text.
+/// State used when sampling tilings for text.
///
/// It caches the inverse transform to the parent, so that we can
/// reuse it instead of recomputing it for each pixel.
#[derive(Clone, Copy)]
-pub struct PatternSampler<'a> {
+pub struct TilingSampler<'a> {
size: Size,
transform_to_parent: sk::Transform,
pixmap: &'a sk::Pixmap,
pixel_per_pt: f32,
}
-impl<'a> PatternSampler<'a> {
+impl<'a> TilingSampler<'a> {
pub fn new(
- pattern: &'a Pattern,
+ tilings: &'a Tiling,
pixmap: &'a sk::Pixmap,
state: &State,
on_text: bool,
) -> Self {
- let relative = pattern.unwrap_relative(on_text);
+ let relative = tilings.unwrap_relative(on_text);
let fill_transform = match relative {
RelativeTo::Self_ => sk::Transform::identity(),
RelativeTo::Parent => state.container_transform.invert().unwrap(),
@@ -99,17 +99,17 @@ impl<'a> PatternSampler<'a> {
Self {
pixmap,
- size: (pattern.size() + pattern.spacing()) * state.pixel_per_pt as f64,
+ size: (tilings.size() + tilings.spacing()) * state.pixel_per_pt as f64,
transform_to_parent: fill_transform,
pixel_per_pt: state.pixel_per_pt,
}
}
}
-impl PaintSampler for PatternSampler<'_> {
+impl PaintSampler for TilingSampler<'_> {
/// Samples a single point in a glyph.
fn sample(self, (x, y): (u32, u32)) -> sk::PremultipliedColorU8 {
- // Compute the point in the pattern's coordinate space.
+ // Compute the point in the tilings's coordinate space.
let mut point = sk::Point { x: x as f32, y: y as f32 };
self.transform_to_parent.map_point(&mut point);
@@ -118,7 +118,7 @@ impl PaintSampler for PatternSampler<'_> {
let y =
(point.y * self.pixel_per_pt).rem_euclid(self.size.y.to_f32()).floor() as u32;
- // Sample the pattern
+ // Sample the tilings
self.pixmap.pixel(x, y).unwrap()
}
}
@@ -218,8 +218,8 @@ pub fn to_sk_paint<'a>(
sk_paint.anti_alias = gradient.anti_alias();
}
- Paint::Pattern(pattern) => {
- let relative = pattern.unwrap_relative(on_text);
+ Paint::Tiling(tilings) => {
+ let relative = tilings.unwrap_relative(on_text);
let fill_transform = match relative {
RelativeTo::Self_ => fill_transform.unwrap_or_default(),
@@ -228,7 +228,7 @@ pub fn to_sk_paint<'a>(
.post_concat(state.transform.invert().unwrap()),
};
- let canvas = render_pattern_frame(&state, pattern);
+ let canvas = render_tiling_frame(&state, tilings);
*pixmap = Some(Arc::new(canvas));
let offset = match relative {
@@ -265,17 +265,17 @@ pub fn to_sk_color_u8(color: Color) -> sk::ColorU8 {
sk::ColorU8::from_rgba(r, g, b, a)
}
-pub fn render_pattern_frame(state: &State, pattern: &Pattern) -> sk::Pixmap {
- let size = pattern.size() + pattern.spacing();
+pub fn render_tiling_frame(state: &State, tilings: &Tiling) -> sk::Pixmap {
+ let size = tilings.size() + tilings.spacing();
let mut canvas = sk::Pixmap::new(
(size.x.to_f32() * state.pixel_per_pt).round() as u32,
(size.y.to_f32() * state.pixel_per_pt).round() as u32,
)
.unwrap();
- // Render the pattern into a new canvas.
+ // Render the tilings into a new canvas.
let ts = sk::Transform::from_scale(state.pixel_per_pt, state.pixel_per_pt);
- let temp_state = State::new(pattern.size(), ts, state.pixel_per_pt);
- crate::render_frame(&mut canvas, temp_state, pattern.frame());
+ let temp_state = State::new(tilings.size(), ts, state.pixel_per_pt);
+ crate::render_frame(&mut canvas, temp_state, tilings.frame());
canvas
}
diff --git a/crates/typst-render/src/shape.rs b/crates/typst-render/src/shape.rs
index f9ff7f3a..57d8ebc1 100644
--- a/crates/typst-render/src/shape.rs
+++ b/crates/typst-render/src/shape.rs
@@ -168,11 +168,11 @@ pub fn to_sk_line_join(join: LineJoin) -> sk::LineJoin {
}
}
-pub fn to_sk_dash_pattern(pattern: &DashPattern<Abs, Abs>) -> Option<sk::StrokeDash> {
+pub fn to_sk_dash_pattern(dash: &DashPattern<Abs, Abs>) -> Option<sk::StrokeDash> {
// tiny-skia only allows dash patterns with an even number of elements,
// while pdf allows any number.
- let pattern_len = pattern.array.len();
+ let pattern_len = dash.array.len();
let len = if pattern_len % 2 == 1 { 2 * pattern_len } else { pattern_len };
- let dash_array = pattern.array.iter().map(|l| l.to_f32()).cycle().take(len).collect();
- sk::StrokeDash::new(dash_array, pattern.phase.to_f32())
+ let dash_array = dash.array.iter().map(|l| l.to_f32()).cycle().take(len).collect();
+ sk::StrokeDash::new(dash_array, dash.phase.to_f32())
}
diff --git a/crates/typst-render/src/text.rs b/crates/typst-render/src/text.rs
index b47659cb..16490aff 100644
--- a/crates/typst-render/src/text.rs
+++ b/crates/typst-render/src/text.rs
@@ -8,7 +8,7 @@ use typst_library::text::color::{glyph_frame, should_outline};
use typst_library::text::{Font, TextItem};
use typst_library::visualize::{FixedStroke, Paint};
-use crate::paint::{self, GradientSampler, PaintSampler, PatternSampler};
+use crate::paint::{self, GradientSampler, PaintSampler, TilingSampler};
use crate::{shape, AbsExt, State};
/// Render a text run into the canvas.
@@ -145,9 +145,9 @@ fn render_outline_glyph(
paint::to_sk_color_u8(*color).premultiply(),
)?;
}
- Paint::Pattern(pattern) => {
- let pixmap = paint::render_pattern_frame(&state, pattern);
- let sampler = PatternSampler::new(pattern, &pixmap, &state, true);
+ Paint::Tiling(tiling) => {
+ let pixmap = paint::render_tiling_frame(&state, tiling);
+ let sampler = TilingSampler::new(tiling, &pixmap, &state, true);
write_bitmap(canvas, &bitmap, &state, sampler)?;
}
}
diff --git a/crates/typst-svg/src/lib.rs b/crates/typst-svg/src/lib.rs
index b21fe4fb..f9951332 100644
--- a/crates/typst-svg/src/lib.rs
+++ b/crates/typst-svg/src/lib.rs
@@ -14,11 +14,11 @@ use typst_library::layout::{
Abs, Frame, FrameItem, FrameKind, GroupItem, Page, PagedDocument, Point, Ratio, Size,
Transform,
};
-use typst_library::visualize::{Geometry, Gradient, Pattern};
+use typst_library::visualize::{Geometry, Gradient, Tiling};
use typst_utils::hash128;
use xmlwriter::XmlWriter;
-use crate::paint::{GradientRef, PatternRef, SVGSubGradient};
+use crate::paint::{GradientRef, SVGSubGradient, TilingRef};
use crate::text::RenderedGlyph;
/// Export a frame into a SVG file.
@@ -92,12 +92,12 @@ struct SVGRenderer {
/// different transforms. Therefore this allows us to reuse the same gradient
/// multiple times.
gradient_refs: Deduplicator<GradientRef>,
- /// Deduplicated patterns with transform matrices. They use a reference
- /// (`href`) to a "source" pattern instead of being defined inline.
- /// This saves a lot of space since patterns are often reused but with
+ /// Deduplicated tilings with transform matrices. They use a reference
+ /// (`href`) to a "source" tiling instead of being defined inline.
+ /// This saves a lot of space since tilings are often reused but with
/// different transforms. Therefore this allows us to reuse the same gradient
/// multiple times.
- pattern_refs: Deduplicator<PatternRef>,
+ tiling_refs: Deduplicator<TilingRef>,
/// These are the actual gradients being written in the SVG file.
/// These gradients are deduplicated because they do not contain the transform
/// matrix, allowing them to be reused across multiple invocations.
@@ -105,12 +105,12 @@ struct SVGRenderer {
/// The `Ratio` is the aspect ratio of the gradient, this is used to correct
/// the angle of the gradient.
gradients: Deduplicator<(Gradient, Ratio)>,
- /// These are the actual patterns being written in the SVG file.
- /// These patterns are deduplicated because they do not contain the transform
+ /// These are the actual tilings being written in the SVG file.
+ /// These tilings are deduplicated because they do not contain the transform
/// matrix, allowing them to be reused across multiple invocations.
///
- /// The `String` is the rendered pattern frame.
- patterns: Deduplicator<Pattern>,
+ /// The `String` is the rendered tiling frame.
+ tilings: Deduplicator<Tiling>,
/// These are the gradients that compose a conic gradient.
conic_subgradients: Deduplicator<SVGSubGradient>,
}
@@ -163,8 +163,8 @@ impl SVGRenderer {
gradient_refs: Deduplicator::new('g'),
gradients: Deduplicator::new('f'),
conic_subgradients: Deduplicator::new('s'),
- pattern_refs: Deduplicator::new('p'),
- patterns: Deduplicator::new('t'),
+ tiling_refs: Deduplicator::new('p'),
+ tilings: Deduplicator::new('t'),
}
}
@@ -272,8 +272,8 @@ impl SVGRenderer {
self.write_gradients();
self.write_gradient_refs();
self.write_subgradients();
- self.write_patterns();
- self.write_pattern_refs();
+ self.write_tilings();
+ self.write_tiling_refs();
self.xml.end_document()
}
diff --git a/crates/typst-svg/src/paint.rs b/crates/typst-svg/src/paint.rs
index 58348c94..75ab41cd 100644
--- a/crates/typst-svg/src/paint.rs
+++ b/crates/typst-svg/src/paint.rs
@@ -4,7 +4,7 @@ use ecow::{eco_format, EcoString};
use ttf_parser::OutlineBuilder;
use typst_library::foundations::Repr;
use typst_library::layout::{Angle, Axes, Frame, Quadrant, Ratio, Size, Transform};
-use typst_library::visualize::{Color, FillRule, Gradient, Paint, Pattern, RatioOrAngle};
+use typst_library::visualize::{Color, FillRule, Gradient, Paint, RatioOrAngle, Tiling};
use typst_utils::hash128;
use xmlwriter::XmlWriter;
@@ -17,7 +17,7 @@ const CONIC_SEGMENT: usize = 360;
impl SVGRenderer {
/// Render a frame to a string.
- pub(super) fn render_pattern_frame(
+ pub(super) fn render_tiling_frame(
&mut self,
state: State,
ts: Transform,
@@ -44,8 +44,8 @@ impl SVGRenderer {
let id = self.push_gradient(gradient, size, ts);
self.xml.write_attribute_fmt("fill", format_args!("url(#{id})"));
}
- Paint::Pattern(pattern) => {
- let id = self.push_pattern(pattern, size, ts);
+ Paint::Tiling(tiling) => {
+ let id = self.push_tiling(tiling, size, ts);
self.xml.write_attribute_fmt("fill", format_args!("url(#{id})"));
}
}
@@ -86,32 +86,31 @@ impl SVGRenderer {
})
}
- pub(super) fn push_pattern(
+ pub(super) fn push_tiling(
&mut self,
- pattern: &Pattern,
+ tiling: &Tiling,
size: Size,
ts: Transform,
) -> Id {
- let pattern_size = pattern.size() + pattern.spacing();
+ let tiling_size = tiling.size() + tiling.spacing();
// Unfortunately due to a limitation of `xmlwriter`, we need to
// render the frame twice: once to allocate all of the resources
// that it needs and once to actually render it.
- self.render_pattern_frame(
- State::new(pattern_size, Transform::identity()),
+ self.render_tiling_frame(
+ State::new(tiling_size, Transform::identity()),
Transform::identity(),
- pattern.frame(),
+ tiling.frame(),
);
- let pattern_id = self.patterns.insert_with(hash128(pattern), || pattern.clone());
- self.pattern_refs
- .insert_with(hash128(&(pattern_id, ts)), || PatternRef {
- id: pattern_id,
- transform: ts,
- ratio: Axes::new(
- Ratio::new(pattern_size.x.to_pt() / size.x.to_pt()),
- Ratio::new(pattern_size.y.to_pt() / size.y.to_pt()),
- ),
- })
+ let tiling_id = self.tilings.insert_with(hash128(tiling), || tiling.clone());
+ self.tiling_refs.insert_with(hash128(&(tiling_id, ts)), || TilingRef {
+ id: tiling_id,
+ transform: ts,
+ ratio: Axes::new(
+ Ratio::new(tiling_size.x.to_pt() / size.x.to_pt()),
+ Ratio::new(tiling_size.y.to_pt() / size.y.to_pt()),
+ ),
+ })
}
/// Write the raw gradients (without transform) to the SVG file.
@@ -188,12 +187,12 @@ impl SVGRenderer {
// Create the path for the segment.
let mut builder = SvgPathBuilder::default();
builder.move_to(
- correct_pattern_pos(center.0),
- correct_pattern_pos(center.1),
+ correct_tiling_pos(center.0),
+ correct_tiling_pos(center.1),
);
builder.line_to(
- correct_pattern_pos(-2.0 * (theta1 + angle).cos() + center.0),
- correct_pattern_pos(2.0 * (theta1 + angle).sin() + center.1),
+ correct_tiling_pos(-2.0 * (theta1 + angle).cos() + center.0),
+ correct_tiling_pos(2.0 * (theta1 + angle).sin() + center.1),
);
builder.arc(
(2.0, 2.0),
@@ -201,10 +200,10 @@ impl SVGRenderer {
0,
1,
(
- correct_pattern_pos(
+ correct_tiling_pos(
-2.0 * (theta2 + angle).cos() + center.0,
),
- correct_pattern_pos(
+ correct_tiling_pos(
2.0 * (theta2 + angle).sin() + center.1,
),
),
@@ -370,19 +369,19 @@ impl SVGRenderer {
self.xml.end_element();
}
- /// Write the raw gradients (without transform) to the SVG file.
- pub(super) fn write_patterns(&mut self) {
- if self.patterns.is_empty() {
+ /// Write the raw tilings (without transform) to the SVG file.
+ pub(super) fn write_tilings(&mut self) {
+ if self.tilings.is_empty() {
return;
}
self.xml.start_element("defs");
- self.xml.write_attribute("id", "patterns");
+ self.xml.write_attribute("id", "tilings");
- for (id, pattern) in
- self.patterns.iter().map(|(i, p)| (i, p.clone())).collect::<Vec<_>>()
+ for (id, tiling) in
+ self.tilings.iter().map(|(i, p)| (i, p.clone())).collect::<Vec<_>>()
{
- let size = pattern.size() + pattern.spacing();
+ let size = tiling.size() + tiling.spacing();
self.xml.start_element("pattern");
self.xml.write_attribute("id", &id);
self.xml.write_attribute("width", &size.x.to_pt());
@@ -396,7 +395,7 @@ impl SVGRenderer {
// Render the frame.
let state = State::new(size, Transform::identity());
let ts = Transform::identity();
- self.render_frame(state, ts, pattern.frame());
+ self.render_frame(state, ts, tiling.frame());
self.xml.end_element();
}
@@ -404,28 +403,28 @@ impl SVGRenderer {
self.xml.end_element()
}
- /// Writes the references to the deduplicated patterns for each usage site.
- pub(super) fn write_pattern_refs(&mut self) {
- if self.pattern_refs.is_empty() {
+ /// Writes the references to the deduplicated tilings for each usage site.
+ pub(super) fn write_tiling_refs(&mut self) {
+ if self.tiling_refs.is_empty() {
return;
}
self.xml.start_element("defs");
- self.xml.write_attribute("id", "pattern-refs");
- for (id, pattern_ref) in self.pattern_refs.iter() {
+ self.xml.write_attribute("id", "tilings-refs");
+ for (id, tiling_ref) in self.tiling_refs.iter() {
self.xml.start_element("pattern");
self.xml
- .write_attribute("patternTransform", &SvgMatrix(pattern_ref.transform));
+ .write_attribute("patternTransform", &SvgMatrix(tiling_ref.transform));
self.xml.write_attribute("id", &id);
// Writing the href attribute to the "reference" pattern.
self.xml
- .write_attribute_fmt("href", format_args!("#{}", pattern_ref.id));
+ .write_attribute_fmt("href", format_args!("#{}", tiling_ref.id));
// Also writing the xlink:href attribute for compatibility.
self.xml
- .write_attribute_fmt("xlink:href", format_args!("#{}", pattern_ref.id));
+ .write_attribute_fmt("xlink:href", format_args!("#{}", tiling_ref.id));
self.xml.end_element();
}
@@ -433,15 +432,15 @@ impl SVGRenderer {
}
}
-/// A reference to a deduplicated pattern, with a transform matrix.
+/// A reference to a deduplicated tiling, with a transform matrix.
///
-/// Allows patterns to be reused across multiple invocations,
-/// simply by changing the transform matrix.
+/// Allows tilings to be reused across multiple invocations, simply by changing
+/// the transform matrix.
#[derive(Hash)]
-pub struct PatternRef {
+pub struct TilingRef {
/// The ID of the deduplicated gradient
id: Id,
- /// The transform matrix to apply to the pattern.
+ /// The transform matrix to apply to the tiling.
transform: Transform,
/// The ratio of the size of the cell to the size of the filled area.
ratio: Axes<Ratio>,
@@ -587,7 +586,7 @@ impl ColorEncode for Color {
}
}
-/// Maps a coordinate in a unit size square to a coordinate in the pattern.
-pub fn correct_pattern_pos(x: f32) -> f32 {
+/// Maps a coordinate in a unit size square to a coordinate in the tiling.
+pub fn correct_tiling_pos(x: f32) -> f32 {
(x + 0.5) / 2.0
}
diff --git a/crates/typst-svg/src/shape.rs b/crates/typst-svg/src/shape.rs
index e188ed8b..151049d6 100644
--- a/crates/typst-svg/src/shape.rs
+++ b/crates/typst-svg/src/shape.rs
@@ -67,8 +67,8 @@ impl SVGRenderer {
)
.post_concat(state.transform.invert().unwrap()),
}
- } else if let Paint::Pattern(pattern) = paint {
- match pattern.unwrap_relative(false) {
+ } else if let Paint::Tiling(tiling) = paint {
+ match tiling.unwrap_relative(false) {
RelativeTo::Self_ => Transform::identity(),
RelativeTo::Parent => state.transform.invert().unwrap(),
}
@@ -112,8 +112,8 @@ impl SVGRenderer {
let id = self.push_gradient(gradient, size, fill_transform);
self.xml.write_attribute_fmt("stroke", format_args!("url(#{id})"));
}
- Paint::Pattern(pattern) => {
- let id = self.push_pattern(pattern, size, fill_transform);
+ Paint::Tiling(tiling) => {
+ let id = self.push_tiling(tiling, size, fill_transform);
self.xml.write_attribute_fmt("stroke", format_args!("url(#{id})"));
}
}
@@ -137,11 +137,11 @@ impl SVGRenderer {
);
self.xml
.write_attribute("stroke-miterlimit", &stroke.miter_limit.get());
- if let Some(pattern) = &stroke.dash {
- self.xml.write_attribute("stroke-dashoffset", &pattern.phase.to_pt());
+ if let Some(dash) = &stroke.dash {
+ self.xml.write_attribute("stroke-dashoffset", &dash.phase.to_pt());
self.xml.write_attribute(
"stroke-dasharray",
- &pattern
+ &dash
.array
.iter()
.map(|dash| dash.to_pt().to_string())
diff --git a/crates/typst-svg/src/text.rs b/crates/typst-svg/src/text.rs
index 76cd53cb..80de3208 100644
--- a/crates/typst-svg/src/text.rs
+++ b/crates/typst-svg/src/text.rs
@@ -165,7 +165,7 @@ impl SVGRenderer {
)
.post_concat(state.transform.invert().unwrap()),
},
- Paint::Pattern(pattern) => match pattern.unwrap_relative(true) {
+ Paint::Tiling(tiling) => match tiling.unwrap_relative(true) {
RelativeTo::Self_ => Transform::identity(),
RelativeTo::Parent => state.transform.invert().unwrap(),
},
diff --git a/crates/typst-syntax/src/ast.rs b/crates/typst-syntax/src/ast.rs
index 34bd0110..45d995a9 100644
--- a/crates/typst-syntax/src/ast.rs
+++ b/crates/typst-syntax/src/ast.rs
@@ -163,7 +163,7 @@ pub enum Expr<'a> {
Parenthesized(Parenthesized<'a>),
/// An array: `(1, "hi", 12cm)`.
Array(Array<'a>),
- /// A dictionary: `(thickness: 3pt, pattern: dashed)`.
+ /// A dictionary: `(thickness: 3pt, dash: "solid")`.
Dict(Dict<'a>),
/// A unary operation: `-x`.
Unary(Unary<'a>),
@@ -1195,7 +1195,7 @@ impl<'a> AstNode<'a> for ArrayItem<'a> {
}
node! {
- /// A dictionary: `(thickness: 3pt, pattern: dashed)`.
+ /// A dictionary: `(thickness: 3pt, dash: "solid")`.
Dict
}
diff --git a/crates/typst-syntax/src/kind.rs b/crates/typst-syntax/src/kind.rs
index a4456b9f..0a7c160b 100644
--- a/crates/typst-syntax/src/kind.rs
+++ b/crates/typst-syntax/src/kind.rs
@@ -224,7 +224,7 @@ pub enum SyntaxKind {
Parenthesized,
/// An array: `(1, "hi", 12cm)`.
Array,
- /// A dictionary: `(thickness: 3pt, pattern: dashed)`.
+ /// A dictionary: `(thickness: 3pt, dash: "solid")`.
Dict,
/// A named pair: `thickness: 3pt`.
Named,
diff --git a/crates/typst-syntax/src/parser.rs b/crates/typst-syntax/src/parser.rs
index cb5e2dd8..6c1778c4 100644
--- a/crates/typst-syntax/src/parser.rs
+++ b/crates/typst-syntax/src/parser.rs
@@ -1077,7 +1077,7 @@ fn expr_with_paren(p: &mut Parser, atomic: bool) {
/// Parses either
/// - a parenthesized expression: `(1 + 2)`, or
/// - an array: `(1, "hi", 12cm)`, or
-/// - a dictionary: `(thickness: 3pt, pattern: dashed)`.
+/// - a dictionary: `(thickness: 3pt, dash: "solid")`.
fn parenthesized_or_array_or_dict(p: &mut Parser) -> SyntaxKind {
let mut state = GroupState {
count: 0,
diff --git a/docs/changelog/0.10.0.md b/docs/changelog/0.10.0.md
index 0b17bea5..5a2a3dea 100644
--- a/docs/changelog/0.10.0.md
+++ b/docs/changelog/0.10.0.md
@@ -31,7 +31,7 @@ description: Changes in Typst 0.10.0
- More LaTeX commands (e.g. for quotes) are now respected in `.bib` files
## Visualization
-- Added support for [patterns]($pattern) as fills and strokes
+- Added support for [patterns]($tiling) as fills and strokes
- The `alpha` parameter of the [`components`]($color.components) function on
colors is now a named parameter **(Breaking change)**
- Added support for the [Oklch]($color.oklch) color space
diff --git a/docs/changelog/0.11.1.md b/docs/changelog/0.11.1.md
index 3269c558..e045914b 100644
--- a/docs/changelog/0.11.1.md
+++ b/docs/changelog/0.11.1.md
@@ -37,7 +37,7 @@ description: Changes in Typst 0.11.1
## Export
- Fixed [smart quotes]($smartquote) in PDF outline
-- Fixed [patterns]($pattern) with spacing in PDF
+- Fixed [patterns]($tiling) with spacing in PDF
- Fixed wrong PDF page labels when [page numbering]($page.numbering) was
disabled after being previously enabled
diff --git a/docs/guides/tables.md b/docs/guides/tables.md
index d5907367..5c9cf11d 100644
--- a/docs/guides/tables.md
+++ b/docs/guides/tables.md
@@ -226,7 +226,7 @@ applications, while academic applications tend to use strokes instead.
To add zebra stripes to a table, we use the `table` function's `fill` argument.
It can take three kinds of arguments:
-- A single color (this can also be a gradient or a pattern) to fill all cells
+- A single color (this can also be a gradient or a tiling) to fill all cells
with. Because we want some cells to have another color, this is not useful if
we want to build zebra tables.
- An array with colors which Typst cycles through for each column. We can use an
@@ -828,7 +828,7 @@ line appears because there is no `top` line that could suppress it.
### How to achieve a double line? { #double-stroke }
Typst does not yet have a native way to draw double strokes, but there are
-multiple ways to emulate them, for example with [patterns]($pattern). We will
+multiple ways to emulate them, for example with [tilings]($tiling). We will
show a different workaround in this section: Table gutters.
Tables can space their cells apart using the `gutter` argument. When a gutter is
diff --git a/tests/ref/grid-stroke-pattern.png b/tests/ref/grid-stroke-tiling.png
index 024f9b20..024f9b20 100644
--- a/tests/ref/grid-stroke-pattern.png
+++ b/tests/ref/grid-stroke-tiling.png
Binary files differ
diff --git a/tests/ref/pattern-line.png b/tests/ref/tiling-line.png
index b891b6d7..b891b6d7 100644
--- a/tests/ref/pattern-line.png
+++ b/tests/ref/tiling-line.png
Binary files differ
diff --git a/tests/ref/pattern-lines.png b/tests/ref/tiling-lines.png
index 008d357e..008d357e 100644
--- a/tests/ref/pattern-lines.png
+++ b/tests/ref/tiling-lines.png
Binary files differ
diff --git a/tests/ref/tiling-pattern-compatibility.png b/tests/ref/tiling-pattern-compatibility.png
new file mode 100644
index 00000000..b891b6d7
--- /dev/null
+++ b/tests/ref/tiling-pattern-compatibility.png
Binary files differ
diff --git a/tests/ref/pattern-relative-parent.png b/tests/ref/tiling-relative-parent.png
index 786057ef..786057ef 100644
--- a/tests/ref/pattern-relative-parent.png
+++ b/tests/ref/tiling-relative-parent.png
Binary files differ
diff --git a/tests/ref/pattern-relative-self.png b/tests/ref/tiling-relative-self.png
index 617e7dd6..617e7dd6 100644
--- a/tests/ref/pattern-relative-self.png
+++ b/tests/ref/tiling-relative-self.png
Binary files differ
diff --git a/tests/ref/pattern-small.png b/tests/ref/tiling-small.png
index 0406252d..0406252d 100644
--- a/tests/ref/pattern-small.png
+++ b/tests/ref/tiling-small.png
Binary files differ
diff --git a/tests/ref/pattern-spacing-negative.png b/tests/ref/tiling-spacing-negative.png
index 659c2283..659c2283 100644
--- a/tests/ref/pattern-spacing-negative.png
+++ b/tests/ref/tiling-spacing-negative.png
Binary files differ
diff --git a/tests/ref/pattern-spacing-positive.png b/tests/ref/tiling-spacing-positive.png
index 3e475eee..3e475eee 100644
--- a/tests/ref/pattern-spacing-positive.png
+++ b/tests/ref/tiling-spacing-positive.png
Binary files differ
diff --git a/tests/ref/pattern-spacing-zero.png b/tests/ref/tiling-spacing-zero.png
index 5118471a..5118471a 100644
--- a/tests/ref/pattern-spacing-zero.png
+++ b/tests/ref/tiling-spacing-zero.png
Binary files differ
diff --git a/tests/ref/pattern-stroke-relative-parent.png b/tests/ref/tiling-stroke-relative-parent.png
index fe9b1174..fe9b1174 100644
--- a/tests/ref/pattern-stroke-relative-parent.png
+++ b/tests/ref/tiling-stroke-relative-parent.png
Binary files differ
diff --git a/tests/ref/pattern-stroke.png b/tests/ref/tiling-stroke.png
index a9f30aa8..a9f30aa8 100644
--- a/tests/ref/pattern-stroke.png
+++ b/tests/ref/tiling-stroke.png
Binary files differ
diff --git a/tests/ref/pattern-text.png b/tests/ref/tiling-text.png
index 2a8da45f..2a8da45f 100644
--- a/tests/ref/pattern-text.png
+++ b/tests/ref/tiling-text.png
Binary files differ
diff --git a/tests/suite/layout/grid/stroke.typ b/tests/suite/layout/grid/stroke.typ
index 3a26b69a..4e81d549 100644
--- a/tests/suite/layout/grid/stroke.typ
+++ b/tests/suite/layout/grid/stroke.typ
@@ -1,5 +1,5 @@
---- grid-stroke-pattern ---
-#let double-line = pattern(size: (1.5pt, 1.5pt), {
+--- grid-stroke-tiling ---
+#let double-line = tiling(size: (1.5pt, 1.5pt), {
place(line(stroke: .6pt, start: (0%, 50%), end: (100%, 50%)))
})
diff --git a/tests/suite/layout/table.typ b/tests/suite/layout/table.typ
index fe138f60..f59d8b42 100644
--- a/tests/suite/layout/table.typ
+++ b/tests/suite/layout/table.typ
@@ -17,7 +17,7 @@
#table(columns: 3, stroke: none, fill: green, [A], [B], [C])
--- table-fill-bad ---
-// Error: 14-19 expected color, gradient, pattern, none, array, or function, found string
+// Error: 14-19 expected color, gradient, tiling, none, array, or function, found string
#table(fill: "hey")
--- table-align-array ---
diff --git a/tests/suite/text/font.typ b/tests/suite/text/font.typ
index 5c972ff3..bb75f4ae 100644
--- a/tests/suite/text/font.typ
+++ b/tests/suite/text/font.typ
@@ -84,7 +84,7 @@ I
--- issue-5499-text-fill-in-clip-block ---
-#let pat = pattern(
+#let t = tiling(
size: (30pt, 30pt),
relative: "parent",
square(
@@ -101,7 +101,7 @@ I
[ ]
text(fill: gradient.linear(..color.map.rainbow), "Hello")
[ ]
- text(fill: pat, "Hello")
+ text(fill: t, "Hello")
})
#block(clip: true, height: 2em, {
text(fill: blue, "Hello")
@@ -110,5 +110,5 @@ I
[ ]
text(fill: gradient.linear(..color.map.rainbow), "Hello")
[ ]
- text(fill: pat, "Hello")
+ text(fill: t, "Hello")
})
diff --git a/tests/suite/visualize/gradient.typ b/tests/suite/visualize/gradient.typ
index d66241f7..b221f411 100644
--- a/tests/suite/visualize/gradient.typ
+++ b/tests/suite/visualize/gradient.typ
@@ -390,7 +390,7 @@
--- gradient-text-bad-relative ---
// Make sure they don't work when `relative: "self"`.
// Hint: 17-61 make sure to set `relative: auto` on your text fill
-// Error: 17-61 gradients and patterns on text must be relative to the parent
+// Error: 17-61 gradients and tilings on text must be relative to the parent
#set text(fill: gradient.linear(red, blue, relative: "self"))
--- gradient-text-global ---
diff --git a/tests/suite/visualize/pattern.typ b/tests/suite/visualize/pattern.typ
deleted file mode 100644
index b87b7755..00000000
--- a/tests/suite/visualize/pattern.typ
+++ /dev/null
@@ -1,159 +0,0 @@
-// Test patterns.
-
---- pattern-line ---
-// Tests that simple patterns work.
-#set page(width: auto, height: auto, margin: 0pt)
-#let pat = pattern(size: (10pt, 10pt), line(stroke: 4pt, start: (0%, 0%), end: (100%, 100%)))
-#rect(width: 50pt, height: 50pt, fill: pat)
-
---- pattern-lines ---
-#set page(width: auto, height: auto, margin: 0pt)
-
-#let pat = pattern(size: (10pt, 10pt), {
- place(line(stroke: 4pt, start: (0%, 0%), end: (100%, 100%)))
- place(line(stroke: 4pt, start: (100%,0%), end: (200%, 100%)))
- place(line(stroke: 4pt, start: (0%,100%), end: (100%, 200%)))
- place(line(stroke: 4pt, start: (-100%,0%), end: (0%, 100%)))
- place(line(stroke: 4pt, start: (0%,-100%), end: (100%, 0%)))
-})
-#rect(width: 50pt, height: 50pt, fill: pat)
-
---- pattern-relative-self ---
-// Test with relative set to `"self"`
-#let pat(..args) = pattern(size: (30pt, 30pt), ..args)[
- #set line(stroke: green)
- #place(top + left, line(start: (0%, 0%), end: (100%, 100%), stroke: 1pt))
- #place(top + left, line(start: (0%, 100%), end: (100%, 0%), stroke: 1pt))
-]
-
-#set page(fill: pat(), width: 100pt, height: 100pt)
-#rect(
- width: 100%,
- height: 100%,
- fill: pat(relative: "self"),
- stroke: 1pt + green,
-)
-
---- pattern-relative-parent ---
-// Test with relative set to `"parent"`
-#let pat(fill, ..args) = pattern(size: (30pt, 30pt), ..args)[
- #rect(width: 100%, height: 100%, fill: fill, stroke: none)
- #place(top + left, line(start: (0%, 0%), end: (100%, 100%), stroke: 1pt))
- #place(top + left, line(start: (0%, 100%), end: (100%, 0%), stroke: 1pt))
-]
-
-#set page(fill: pat(white), width: 100pt, height: 100pt)
-
-#rect(fill: pat(none, relative: "parent"), width: 100%, height: 100%, stroke: 1pt)
-
---- pattern-small ---
-// Tests small patterns for pixel accuracy.
-#box(
- width: 8pt,
- height: 1pt,
- fill: pattern(size: (1pt, 1pt), square(size: 1pt, fill: black))
-)
-#v(-1em)
-#box(
- width: 8pt,
- height: 1pt,
- fill: pattern(size: (2pt, 1pt), square(size: 1pt, fill: black))
-)
-
---- pattern-zero-sized ---
-// Error: 15-52 pattern tile size must be non-zero
-// Hint: 15-52 try setting the size manually
-#line(stroke: pattern(path((0pt, 0pt), (1em, 0pt))))
-
---- pattern-spacing-negative ---
-// Test with spacing set to `(-10pt, -10pt)`
-#let pat(..args) = pattern(size: (30pt, 30pt), ..args)[
- #square(width: 100%, height: 100%, stroke: 1pt, fill: blue)
-]
-
-#set page(width: 100pt, height: 100pt)
-
-#rect(fill: pat(spacing: (-10pt, -10pt)), width: 100%, height: 100%, stroke: 1pt)
-
---- pattern-spacing-zero ---
-// Test with spacing set to `(0pt, 0pt)`
-#let pat(..args) = pattern(size: (30pt, 30pt), ..args)[
- #square(width: 100%, height: 100%, stroke: 1pt, fill: blue)
-]
-
-#set page(width: 100pt, height: 100pt)
-
-#rect(fill: pat(spacing: (0pt, 0pt)), width: 100%, height: 100%, stroke: 1pt)
-
---- pattern-spacing-positive ---
-// Test with spacing set to `(10pt, 10pt)`
-#let pat(..args) = pattern(size: (30pt, 30pt), ..args)[
- #square(width: 100%, height: 100%, stroke: 1pt, fill: blue)
-]
-
-#set page(width: 100pt, height: 100pt)
-
-#rect(fill: pat(spacing: (10pt, 10pt,)), width: 100%, height: 100%, stroke: 1pt)
-
---- pattern-stroke ---
-// Test pattern on strokes
-#align(
- center + top,
- square(
- size: 50pt,
- fill: pattern(
- size: (5pt, 5pt),
- align(horizon + center, circle(fill: blue, radius: 2.5pt))
- ),
- stroke: 7.5pt + pattern(
- size: (5pt, 5pt),
- align(horizon + center, circle(fill: red, radius: 2.5pt))
- )
- )
-)
-
---- pattern-stroke-relative-parent ---
-// Test pattern on strokes with relative set to `"parent"`
-// The pattern on the circle should align with the pattern on the square.
-#align(
- center + top,
- block(
- width: 50pt,
- height: 50pt,
- fill: pattern(size: (5pt, 5pt), circle(radius: 2.5pt, fill: blue)),
- align(center + horizon, circle(
- radius: 15pt,
- stroke: 7.5pt + pattern(
- size: (5pt, 5pt), circle(radius: 2.5pt, fill: red), relative: "parent"
- ),
- ))
- )
-)
-
---- pattern-text ---
-// Test a pattern on some text
-// You shouldn't be able to see the text, if you can then
-// that means that the transform matrices are not being
-// applied to the text correctly.
-#let pat = pattern(
- size: (30pt, 30pt),
- relative: "parent",
- square(size: 30pt, fill: gradient.conic(..color.map.rainbow))
-);
-
-#set page(
- width: 140pt,
- height: 140pt,
- fill: pat
-)
-
-#rotate(45deg, scale(x: 50%, y: 70%, rect(
- width: 100%,
- height: 100%,
- stroke: 1pt,
-)[
- #lorem(10)
-
- #set text(fill: pat)
- #lorem(10)
-]))
diff --git a/tests/suite/visualize/rect.typ b/tests/suite/visualize/rect.typ
index 5dfe29f3..a659287e 100644
--- a/tests/suite/visualize/rect.typ
+++ b/tests/suite/visualize/rect.typ
@@ -55,7 +55,7 @@
#rect(width: 20pt, height: 20pt, stroke: (thickness: 5pt, join: "round"))
--- red-stroke-bad-type ---
-// Error: 15-21 expected length, color, gradient, pattern, dictionary, stroke, none, or auto, found array
+// Error: 15-21 expected length, color, gradient, tiling, dictionary, stroke, none, or auto, found array
#rect(stroke: (1, 2))
--- rect-fill-stroke ---
diff --git a/tests/suite/visualize/tiling.typ b/tests/suite/visualize/tiling.typ
new file mode 100644
index 00000000..5272328d
--- /dev/null
+++ b/tests/suite/visualize/tiling.typ
@@ -0,0 +1,163 @@
+// Test tilings.
+
+--- tiling-line ---
+// Tests that simple tilings work.
+#set page(width: auto, height: auto, margin: 0pt)
+#let t = tiling(size: (10pt, 10pt), line(stroke: 4pt, start: (0%, 0%), end: (100%, 100%)))
+#rect(width: 50pt, height: 50pt, fill: t)
+
+--- tiling-lines ---
+#set page(width: auto, height: auto, margin: 0pt)
+
+#let t = tiling(size: (10pt, 10pt), {
+ place(line(stroke: 4pt, start: (0%, 0%), end: (100%, 100%)))
+ place(line(stroke: 4pt, start: (100%,0%), end: (200%, 100%)))
+ place(line(stroke: 4pt, start: (0%,100%), end: (100%, 200%)))
+ place(line(stroke: 4pt, start: (-100%,0%), end: (0%, 100%)))
+ place(line(stroke: 4pt, start: (0%,-100%), end: (100%, 0%)))
+})
+#rect(width: 50pt, height: 50pt, fill: t)
+
+--- tiling-relative-self ---
+// Test with relative set to `"self"`
+#let t(..args) = tiling(size: (30pt, 30pt), ..args)[
+ #set line(stroke: green)
+ #place(top + left, line(start: (0%, 0%), end: (100%, 100%), stroke: 1pt))
+ #place(top + left, line(start: (0%, 100%), end: (100%, 0%), stroke: 1pt))
+]
+
+#set page(fill: t(), width: 100pt, height: 100pt)
+#rect(
+ width: 100%,
+ height: 100%,
+ fill: t(relative: "self"),
+ stroke: 1pt + green,
+)
+
+--- tiling-relative-parent ---
+// Test with relative set to `"parent"`
+#let t(fill, ..args) = tiling(size: (30pt, 30pt), ..args)[
+ #rect(width: 100%, height: 100%, fill: fill, stroke: none)
+ #place(top + left, line(start: (0%, 0%), end: (100%, 100%), stroke: 1pt))
+ #place(top + left, line(start: (0%, 100%), end: (100%, 0%), stroke: 1pt))
+]
+
+#set page(fill: t(white), width: 100pt, height: 100pt)
+
+#rect(fill: t(none, relative: "parent"), width: 100%, height: 100%, stroke: 1pt)
+
+--- tiling-small ---
+// Tests small tilings for pixel accuracy.
+#box(
+ width: 8pt,
+ height: 1pt,
+ fill: tiling(size: (1pt, 1pt), square(size: 1pt, fill: black))
+)
+#v(-1em)
+#box(
+ width: 8pt,
+ height: 1pt,
+ fill: tiling(size: (2pt, 1pt), square(size: 1pt, fill: black))
+)
+
+--- tiling-zero-sized ---
+// Error: 15-51 tile size must be non-zero
+// Hint: 15-51 try setting the size manually
+#line(stroke: tiling(path((0pt, 0pt), (1em, 0pt))))
+
+--- tiling-spacing-negative ---
+// Test with spacing set to `(-10pt, -10pt)`
+#let t(..args) = tiling(size: (30pt, 30pt), ..args)[
+ #square(width: 100%, height: 100%, stroke: 1pt, fill: blue)
+]
+
+#set page(width: 100pt, height: 100pt)
+
+#rect(fill: t(spacing: (-10pt, -10pt)), width: 100%, height: 100%, stroke: 1pt)
+
+--- tiling-spacing-zero ---
+// Test with spacing set to `(0pt, 0pt)`
+#let t(..args) = tiling(size: (30pt, 30pt), ..args)[
+ #square(width: 100%, height: 100%, stroke: 1pt, fill: blue)
+]
+
+#set page(width: 100pt, height: 100pt)
+
+#rect(fill: t(spacing: (0pt, 0pt)), width: 100%, height: 100%, stroke: 1pt)
+
+--- tiling-spacing-positive ---
+// Test with spacing set to `(10pt, 10pt)`
+#let t(..args) = tiling(size: (30pt, 30pt), ..args)[
+ #square(width: 100%, height: 100%, stroke: 1pt, fill: blue)
+]
+
+#set page(width: 100pt, height: 100pt)
+
+#rect(fill: t(spacing: (10pt, 10pt,)), width: 100%, height: 100%, stroke: 1pt)
+
+--- tiling-stroke ---
+// Test tiling on strokes
+#align(
+ center + top,
+ square(
+ size: 50pt,
+ fill: tiling(
+ size: (5pt, 5pt),
+ align(horizon + center, circle(fill: blue, radius: 2.5pt))
+ ),
+ stroke: 7.5pt + tiling(
+ size: (5pt, 5pt),
+ align(horizon + center, circle(fill: red, radius: 2.5pt))
+ )
+ )
+)
+
+--- tiling-stroke-relative-parent ---
+// Test tiling on strokes with relative set to `"parent"`
+// The tiling on the circle should align with the tiling on the square.
+#align(
+ center + top,
+ block(
+ width: 50pt,
+ height: 50pt,
+ fill: tiling(size: (5pt, 5pt), circle(radius: 2.5pt, fill: blue)),
+ align(center + horizon, circle(
+ radius: 15pt,
+ stroke: 7.5pt + tiling(
+ size: (5pt, 5pt), circle(radius: 2.5pt, fill: red), relative: "parent"
+ ),
+ ))
+ )
+)
+
+--- tiling-text ---
+// Test a tiling on some text. You shouldn't be able to see the text, if you can
+// then that means that the transform matrices are not being applied to the text
+// correctly.
+#let t = tiling(
+ size: (30pt, 30pt),
+ relative: "parent",
+ square(size: 30pt, fill: gradient.conic(..color.map.rainbow))
+);
+
+#set page(
+ width: 140pt,
+ height: 140pt,
+ fill: t
+)
+
+#rotate(45deg, scale(x: 50%, y: 70%, rect(
+ width: 100%,
+ height: 100%,
+ stroke: 1pt,
+)[
+ #lorem(10)
+
+ #set text(fill: t)
+ #lorem(10)
+]))
+
+--- tiling-pattern-compatibility ---
+#set page(width: auto, height: auto, margin: 0pt)
+#let t = pattern(size: (10pt, 10pt), line(stroke: 4pt, start: (0%, 0%), end: (100%, 100%)))
+#rect(width: 50pt, height: 50pt, fill: t)