Skip to main content

vello_cpu/filter/
mod.rs

1// Copyright 2025 the Vello Authors
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3
4//! Filter effects implementation for `vello_cpu`.
5//!
6//! This module provides CPU-based implementations of SVG filter effects,
7//! supporting both low-precision (u8) and high-precision (f32) rendering paths.
8//! Filters are applied to rendered layer pixmaps and may use scratch storage for
9//! intermediate buffers.
10
11pub(crate) mod context;
12mod drop_shadow;
13mod flood;
14mod gaussian_blur;
15mod offset;
16mod shift;
17
18use context::ScratchBuffer;
19use vello_common::filter::PreparedFilter;
20use vello_common::filter_effects::Filter;
21use vello_common::kurbo::Affine;
22use vello_common::pixmap::Pixmap;
23
24/// Trait for filter effects that can be applied to layers.
25///
26/// Each filter implements this trait with both u8 and f32 variants
27/// to support different rendering backends and precision requirements.
28/// The low-precision path (`execute_lowp`) uses 8-bit color channels for
29/// better performance, while the high-precision path (`execute_highp`)
30/// uses 32-bit floating-point for higher quality at the cost of speed.
31pub(crate) trait FilterEffect {
32    /// Apply the low-precision (u8) version of the filter.
33    ///
34    /// # Arguments
35    /// * `pixmap` - The target pixmap containing rendering metadata
36    /// * `filter_scratch` - Reusable scratch storage for intermediate buffers
37    fn execute_lowp(&self, pixmap: &mut Pixmap, filter_scratch: &mut ScratchBuffer);
38
39    /// Apply the high-precision (f32) version of the filter.
40    ///
41    /// # Arguments
42    /// * `pixmap` - The target pixmap containing rendering metadata
43    /// * `filter_scratch` - Reusable scratch storage for intermediate buffers
44    fn execute_highp(&self, pixmap: &mut Pixmap, filter_scratch: &mut ScratchBuffer);
45}
46
47/// Apply the low-precision (u8) version of a filter effect to a layer.
48///
49/// This function dispatches filter primitives from a filter graph to their
50/// corresponding CPU implementations using 8-bit color channels.
51///
52/// # Arguments
53/// * `filter` - The filter containing the graph of primitives to apply
54/// * `pixmap` - The target pixmap containing rendering metadata
55/// * `filter_scratch` - Reusable scratch storage for intermediate buffers
56/// * `transform` - The transformation matrix to extract scale from for filter parameters
57///
58/// # Limitations
59/// Currently only supports filter graphs with a single primitive.
60/// Multi-primitive filter graphs are not yet implemented.
61pub(crate) fn filter_lowp(
62    filter: &Filter,
63    pixmap: &mut Pixmap,
64    filter_scratch: &mut ScratchBuffer,
65    transform: Affine,
66) {
67    let prepared_filter = PreparedFilter::new(filter, &transform);
68
69    match prepared_filter {
70        PreparedFilter::Flood(flood) => {
71            flood.execute_lowp(pixmap, filter_scratch);
72        }
73        PreparedFilter::GaussianBlur(blur) => {
74            blur.execute_lowp(pixmap, filter_scratch);
75        }
76        PreparedFilter::Offset(offset) => {
77            offset.execute_lowp(pixmap, filter_scratch);
78        }
79        PreparedFilter::DropShadow(drop_shadow) => {
80            drop_shadow.execute_lowp(pixmap, filter_scratch);
81        }
82    }
83}
84
85/// Apply the high-precision (f32) version of a filter effect to a layer.
86///
87/// This function dispatches filter primitives from a filter graph to their
88/// corresponding CPU implementations using 32-bit floating-point color channels.
89///
90/// # Arguments
91/// * `filter` - The filter containing the graph of primitives to apply
92/// * `pixmap` - The target pixmap containing rendering metadata
93/// * `filter_scratch` - Reusable scratch storage for intermediate buffers
94/// * `transform` - The transformation matrix to extract scale from for filter parameters
95///
96/// # Limitations
97/// Currently only supports filter graphs with a single primitive.
98/// Multi-primitive filter graphs are not yet implemented.
99pub(crate) fn filter_highp(
100    filter: &Filter,
101    pixmap: &mut Pixmap,
102    filter_scratch: &mut ScratchBuffer,
103    transform: Affine,
104) {
105    let prepared_filter = PreparedFilter::new(filter, &transform);
106
107    match prepared_filter {
108        PreparedFilter::Flood(flood) => {
109            flood.execute_highp(pixmap, filter_scratch);
110        }
111        PreparedFilter::GaussianBlur(blur) => {
112            blur.execute_highp(pixmap, filter_scratch);
113        }
114        PreparedFilter::Offset(offset) => {
115            offset.execute_highp(pixmap, filter_scratch);
116        }
117        PreparedFilter::DropShadow(drop_shadow) => {
118            drop_shadow.execute_highp(pixmap, filter_scratch);
119        }
120    }
121}