1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
// Copyright 2025 the Vello Authors
// SPDX-License-Identifier: Apache-2.0 OR MIT
// After you edit the crate's doc comment, run this command, then check README.md for any missing links
// cargo rdme --workspace-project=vello_cpu
//! Vello CPU is a 2D graphics rendering engine written in Rust, for devices with no or underpowered GPUs.
//!
//! We also develop [Vello](https://crates.io/crates/vello), which makes use of the GPU for 2D rendering and has higher performance than Vello CPU.
//! Vello CPU is being developed as part of work to address shortcomings in Vello.
//!
//! # Usage
//!
//! To use Vello CPU, you need to:
//!
//! - Create a [`RenderContext`][], a 2D drawing context for a fixed-size scene area.
//! - For each object in your scene:
//! - Set how the object will be painted, using [`set_paint`][RenderContext::set_paint].
//! - Set the shape to be drawn for that object, using methods like [`fill_path`][RenderContext::fill_path],
//! [`stroke_path`][RenderContext::stroke_path], or [`glyph_run`][RenderContext::glyph_run].
//! - Render it to an image using [`RenderContext::render`][].
//!
//! ```rust
//! use vello_cpu::{RenderContext, Resources, Pixmap};
//! use vello_cpu::{color::{palette::css, PremulRgba8}, kurbo::Rect};
//! let width = 10;
//! let height = 5;
//! let mut context = RenderContext::new(width, height);
//! let mut resources = Resources::new();
//! context.set_paint(css::MAGENTA);
//! context.fill_rect(&Rect::from_points((3., 1.), (7., 4.)));
//!
//! let mut target = Pixmap::new(width, height);
//! // While calling `flush` is only strictly necessary if you are rendering using
//! // multiple threads, it is recommended to always do this.
//! context.flush();
//! context.render(&mut target, &mut resources);
//!
//! let expected_render = b"\
//! 0000000000\
//! 0001111000\
//! 0001111000\
//! 0001111000\
//! 0000000000";
//! let magenta = css::MAGENTA.premultiply().to_rgba8();
//! let transparent = PremulRgba8 {r: 0, g: 0, b: 0, a: 0};
//! let mut result = Vec::new();
//! for pixel in target.data() {
//! if *pixel == magenta {
//! result.push(b'1');
//! } else if *pixel == transparent {
//! result.push(b'0');
//! } else {
//! panic!("Got unexpected pixel value {pixel:?}");
//! }
//! }
//! assert_eq!(&result, expected_render);
//! ```
//!
//! See the
//! [examples](https://github.com/linebender/vello/tree/main/sparse_strips/vello_cpu/examples)
//! for more complete demonstrations of Vello CPU's API.
//!
//! # Features
//!
//! - `std` (enabled by default): Get floating point functions from the standard library
//! (likely using your target's libc).
//! - `libm`: Use floating point implementations from [libm][].
//! - `png`(enabled by default): Allow loading [`Pixmap`]s from PNG images.
//! Also required for rendering glyphs with an embedded PNG. Implies `std`.
//! - `multithreading`: Enable multi-threaded rendering. Implies `std`.
//! - `text` (enabled by default): Enables glyph rendering ([`glyph_run`][RenderContext::glyph_run]).
//! - `u8_pipeline` (enabled by default): Enable the u8 pipeline, for speed focused rendering using u8 math.
//! The `u8` pipeline will be used for [`OptimizeSpeed`][RenderMode::OptimizeSpeed], if both pipelines are enabled.
//! If you're using Vello CPU for application rendering, you should prefer this pipeline.
//! - `f32_pipeline`: Enable the `f32` pipeline, which is slower but has more accurate
//! results. This is espectially useful for rendering test snapshots.
//! The `f32` pipeline will be used for [`OptimizeQuality`][RenderMode::OptimizeQuality], if both pipelines are enabled.
//!
//! At least one of `std` and `libm` is required; `std` overrides `libm`.
//! At least one of `u8_pipeline` and `f32_pipeline` must be enabled.
//! You might choose to disable one of these pipelines if your application
//! won't use it, so as to reduce binary size.
//!
//! # Current state
//!
//! Vello CPU is a solid CPU-only 2D renderer with broad, reliable feature
//! support. It provides excellent performance across a wide range of workloads,
//! with optimized SIMD implementations for all major architectures. The
//! renderer is still under active development, however, and a few limitations
//! remain:
//!
//! - Complex filter graphs are currently not supported at all and will panic.
//! In multi-threaded mode, even simple filters are currently unsupported.
//! - Parts of the API and its documentation are still suboptimal, for example
//! the [`Resources`][] lifecycle.
//! - Some exposed features remain experimental and are not recommended for use,
//! including glyph caching. Experimental APIs are identified in their method
//! documentation.
//! - There is still more room for performance improvements, in particular on
//! x86 systems and also for multi-threaded rendering.
//!
//! With that said, we are continuously improving Vello CPU and will address
//! these and other limitations in future releases.
//!
//! # Performance
//!
//! Performance benchmarks can be found [here](https://laurenzv.github.io/vello_chart/),
//! As can be seen, Vello CPU achieves compelling performance on both,
//! aarch64 and x86 platforms. We also have SIMD optimizations for WASM SIMD,
//! meaning that you can expect good performance there as well.
//!
//! # Implementation
//!
//! If you want to gain a better understanding of Vello CPU and the
//! sparse strips paradigm, you can take a look at the [accompanying
//! master's thesis](https://ethz.ch/content/dam/ethz/special-interest/infk/inst-pls/plf-dam/documents/StudentProjects/MasterTheses/2025-Laurenz-Thesis.pdf)
//! that was written on the topic. Note that parts of the descriptions might
//! become outdated as the implementation changes, but it should give a good
//! overview nevertheless.
//!
//! <!-- We can't directly link to the libm crate built locally, because our feature is only a pass-through -->
//! [libm]: https://crates.io/crates/libm
// LINEBENDER LINT SET - lib.rs - v3
// See https://linebender.org/wiki/canonical-lints/
// These lints shouldn't apply to examples or tests.
// These lints shouldn't apply to examples.
// Targeting e.g. 32-bit means structs containing usize can give false positives for 64-bit.
// END LINEBENDER LINT SET
extern crate alloc;
extern crate core;
// Unused in release mode because it's only used directly in the `text_debug` module
// (or transitively in vello_common).
use png as _;
extern crate std;
compile_error!;
pub use ;
// Note: The first one is not something that should be
// exposed, but is currently needed by vello_sparse_tests.
pub use Glyph;
pub use ;
pub use Level;
pub use Mask;
pub use ;
pub use ;
pub use ;
/// The selected rendering mode.
/// For using [`RenderMode::OptimizeQuality`] you also need to enable `f32_pipeline` feature.