Skip to main content

agg_rust/
span_pattern_rgba.rs

1//! RGBA span pattern generator.
2//!
3//! Port of `agg_span_pattern_rgba.h`.
4//! Generates pixel spans by reading from a tiled source image with
5//! coordinate offsets. Used for repeating pattern fills.
6
7use crate::color::Rgba8;
8use crate::image_accessors::ImageSource;
9use crate::renderer_scanline::SpanGenerator;
10
11/// RGBA span pattern generator — fills spans from a tiled source image.
12///
13/// Port of C++ `span_pattern_rgba<Source>`.
14/// Reads pixels from the attached `ImageSource`, applying x/y offsets
15/// for pattern positioning.
16pub struct SpanPatternRgba<Src> {
17    src: Src,
18    offset_x: u32,
19    offset_y: u32,
20}
21
22impl<Src: ImageSource> SpanPatternRgba<Src> {
23    pub fn new(src: Src, offset_x: u32, offset_y: u32) -> Self {
24        Self {
25            src,
26            offset_x,
27            offset_y,
28        }
29    }
30
31    pub fn source(&self) -> &Src {
32        &self.src
33    }
34
35    pub fn source_mut(&mut self) -> &mut Src {
36        &mut self.src
37    }
38
39    pub fn offset_x(&self) -> u32 {
40        self.offset_x
41    }
42
43    pub fn set_offset_x(&mut self, v: u32) {
44        self.offset_x = v;
45    }
46
47    pub fn offset_y(&self) -> u32 {
48        self.offset_y
49    }
50
51    pub fn set_offset_y(&mut self, v: u32) {
52        self.offset_y = v;
53    }
54}
55
56impl<Src: ImageSource> SpanGenerator for SpanPatternRgba<Src> {
57    type Color = Rgba8;
58
59    fn prepare(&mut self) {}
60
61    fn generate(&mut self, span: &mut [Rgba8], x: i32, y: i32, len: u32) {
62        let sx = x + self.offset_x as i32;
63        let sy = y + self.offset_y as i32;
64
65        let p = self.src.span(sx, sy, len);
66        span[0] = Rgba8::new(p[0] as u32, p[1] as u32, p[2] as u32, p[3] as u32);
67
68        for i in 1..len as usize {
69            let p = self.src.next_x();
70            span[i] = Rgba8::new(p[0] as u32, p[1] as u32, p[2] as u32, p[3] as u32);
71        }
72    }
73}
74
75#[cfg(test)]
76mod tests {
77    use super::*;
78
79    /// A simple test image source that returns a fixed color.
80    struct ConstantSource {
81        pixel: [u8; 4],
82    }
83
84    impl ImageSource for ConstantSource {
85        fn span(&mut self, _x: i32, _y: i32, _len: u32) -> &[u8] {
86            &self.pixel
87        }
88
89        fn next_x(&mut self) -> &[u8] {
90            &self.pixel
91        }
92
93        fn next_y(&mut self) -> &[u8] {
94            &self.pixel
95        }
96    }
97
98    #[test]
99    fn test_constant_pattern() {
100        let src = ConstantSource {
101            pixel: [255, 0, 0, 255],
102        };
103        let mut pattern = SpanPatternRgba::new(src, 0, 0);
104        pattern.prepare();
105
106        let mut span = vec![Rgba8::new(0, 0, 0, 0); 5];
107        pattern.generate(&mut span, 0, 0, 5);
108
109        for c in &span {
110            assert_eq!(c.r, 255);
111            assert_eq!(c.g, 0);
112            assert_eq!(c.b, 0);
113            assert_eq!(c.a, 255);
114        }
115    }
116
117    #[test]
118    fn test_offset() {
119        let src = ConstantSource {
120            pixel: [128, 128, 128, 255],
121        };
122        let mut pattern = SpanPatternRgba::new(src, 10, 20);
123        assert_eq!(pattern.offset_x(), 10);
124        assert_eq!(pattern.offset_y(), 20);
125
126        pattern.set_offset_x(5);
127        pattern.set_offset_y(15);
128        assert_eq!(pattern.offset_x(), 5);
129        assert_eq!(pattern.offset_y(), 15);
130    }
131}