agg_rust/
span_converter.rs1use crate::renderer_scanline::SpanGenerator;
7
8pub trait SpanConverterFunction {
17 type Color;
18
19 fn prepare(&mut self) {}
20
21 fn convert(&mut self, span: &mut [Self::Color], x: i32, y: i32, len: u32);
22}
23
24pub struct SpanConverter<SG: SpanGenerator, SC: SpanConverterFunction<Color = SG::Color>> {
35 span_gen: SG,
36 span_cnv: SC,
37}
38
39impl<SG: SpanGenerator, SC: SpanConverterFunction<Color = SG::Color>> SpanConverter<SG, SC> {
40 pub fn new(span_gen: SG, span_cnv: SC) -> Self {
41 Self { span_gen, span_cnv }
42 }
43
44 pub fn generator(&self) -> &SG {
45 &self.span_gen
46 }
47
48 pub fn generator_mut(&mut self) -> &mut SG {
49 &mut self.span_gen
50 }
51
52 pub fn converter(&self) -> &SC {
53 &self.span_cnv
54 }
55
56 pub fn converter_mut(&mut self) -> &mut SC {
57 &mut self.span_cnv
58 }
59}
60
61impl<SG: SpanGenerator, SC: SpanConverterFunction<Color = SG::Color>> SpanGenerator
62 for SpanConverter<SG, SC>
63{
64 type Color = SG::Color;
65
66 fn prepare(&mut self) {
67 self.span_gen.prepare();
68 self.span_cnv.prepare();
69 }
70
71 fn generate(&mut self, span: &mut [Self::Color], x: i32, y: i32, len: u32) {
72 self.span_gen.generate(span, x, y, len);
73 self.span_cnv.convert(span, x, y, len);
74 }
75}
76
77#[cfg(test)]
82mod tests {
83 use super::*;
84 use crate::color::Rgba8;
85
86 struct FillRed;
87 impl SpanGenerator for FillRed {
88 type Color = Rgba8;
89 fn prepare(&mut self) {}
90 fn generate(&mut self, span: &mut [Rgba8], _x: i32, _y: i32, len: u32) {
91 for pixel in span.iter_mut().take(len as usize) {
92 *pixel = Rgba8::new(255, 0, 0, 255);
93 }
94 }
95 }
96
97 struct HalveAlpha;
98 impl SpanConverterFunction for HalveAlpha {
99 type Color = Rgba8;
100 fn convert(&mut self, span: &mut [Rgba8], _x: i32, _y: i32, len: u32) {
101 for pixel in span.iter_mut().take(len as usize) {
102 pixel.a /= 2;
103 }
104 }
105 }
106
107 #[test]
108 fn test_converter_pipeline() {
109 let gen = FillRed;
110 let cnv = HalveAlpha;
111 let mut pipeline = SpanConverter::new(gen, cnv);
112
113 pipeline.prepare();
114 let mut span = vec![Rgba8::new(0, 0, 0, 0); 3];
115 pipeline.generate(&mut span, 0, 0, 3);
116
117 assert_eq!(span[0].r, 255);
118 assert_eq!(span[0].a, 127); assert_eq!(span[2].r, 255);
120 assert_eq!(span[2].a, 127);
121 }
122
123 #[test]
124 fn test_access_inner() {
125 let gen = FillRed;
126 let cnv = HalveAlpha;
127 let pipeline = SpanConverter::new(gen, cnv);
128 let _gen_ref = pipeline.generator();
129 let _cnv_ref = pipeline.converter();
130 }
131
132 #[test]
133 fn test_identity_converter() {
134 struct IdentityConv;
135 impl SpanConverterFunction for IdentityConv {
136 type Color = Rgba8;
137 fn convert(&mut self, _span: &mut [Rgba8], _x: i32, _y: i32, _len: u32) {}
138 }
139
140 let gen = FillRed;
141 let cnv = IdentityConv;
142 let mut pipeline = SpanConverter::new(gen, cnv);
143
144 let mut span = vec![Rgba8::new(0, 0, 0, 0); 2];
145 pipeline.generate(&mut span, 0, 0, 2);
146 assert_eq!(span[0].r, 255);
147 assert_eq!(span[0].a, 255); }
149
150 #[test]
151 fn test_converter_receives_coordinates() {
152 struct TrackCoords {
153 last_x: i32,
154 last_y: i32,
155 }
156 impl SpanConverterFunction for TrackCoords {
157 type Color = Rgba8;
158 fn convert(&mut self, _span: &mut [Rgba8], x: i32, y: i32, _len: u32) {
159 self.last_x = x;
160 self.last_y = y;
161 }
162 }
163
164 let gen = FillRed;
165 let cnv = TrackCoords {
166 last_x: 0,
167 last_y: 0,
168 };
169 let mut pipeline = SpanConverter::new(gen, cnv);
170
171 let mut span = vec![Rgba8::new(0, 0, 0, 0); 1];
172 pipeline.generate(&mut span, 42, 99, 1);
173 assert_eq!(pipeline.converter().last_x, 42);
174 assert_eq!(pipeline.converter().last_y, 99);
175 }
176}