1use crate::POLY_SUBPIXEL_SHIFT;
4use crate::POLY_SUBPIXEL_SCALE;
5use crate::clip::Clip;
8use crate::scan::ScanlineU8;
9use crate::cell::RasterizerCell;
10use crate::path_storage::PathCommand;
11use crate::path_storage::Vertex;
12
13use crate::VertexSource;
15
16use std::cmp::min;
17use std::cmp::max;
18
19struct RasConvInt {
20}
21impl RasConvInt {
22 pub fn upscale(v: f64) -> i64 {
23 (v * POLY_SUBPIXEL_SCALE as f64).round() as i64
24 }
25 }
29
30#[derive(Debug,PartialEq,Copy,Clone)]
35pub enum FillingRule {
36 NonZero,
37 EvenOdd,
38}
39impl Default for FillingRule {
40 fn default() -> FillingRule {
41 FillingRule::NonZero
42 }
43}
44
45#[derive(Debug,PartialEq,Copy,Clone)]
47pub enum PathStatus {
48 Initial,
49 Closed,
50 MoveTo,
51 LineTo
52}
53impl Default for PathStatus {
54 fn default() -> PathStatus {
55 PathStatus::Initial
56 }
57}
58
59#[derive(Debug, Default)]
61pub struct RasterizerScanline {
62 pub clipper: Clip,
64 pub outline: RasterizerCell,
66 pub status: PathStatus,
68 pub x0: i64,
70 pub y0: i64,
72 scan_y: i64,
74 filling_rule: FillingRule,
76 gamma: Vec<u64>,
78}
79
80impl RasterizerScanline {
81 pub fn reset(&mut self) {
85 self.outline.reset();
86 self.status = PathStatus::Initial;
87 }
88 pub fn add_path<VS: VertexSource>(&mut self, path: &VS) {
92 if ! self.outline.sorted_y.is_empty() {
94 self.reset();
95 }
96 for seg in path.xconvert() {
97 println!("ADD_PATH: {:?}", seg);
98 match seg.cmd {
99 PathCommand::LineTo => self.line_to_d(seg.x, seg.y),
100 PathCommand::MoveTo => self.move_to_d(seg.x, seg.y),
101 PathCommand::Close => self.close_polygon(),
102 PathCommand::Stop => unimplemented!("stop encountered"),
103 }
104 }
105 }
106
107 pub fn rewind_scanlines(&mut self) -> bool {
113 self.close_polygon();
114 self.outline.sort_cells();
115 if self.outline.total_cells() == 0 {
116 false
117 } else {
118 self.scan_y = self.outline.min_y;
119 true
120 }
121 }
122
123 pub(crate) fn sweep_scanline(&mut self, sl: &mut ScanlineU8) -> bool {
129 println!("ADD_PATH: SWEEP SCANLINE: Y: {}", self.scan_y);
130 loop {
131 if self.scan_y < 0 {
132 self.scan_y += 1;
133 continue;
134 }
135 if self.scan_y > self.outline.max_y {
136 return false;
137 }
138 sl.reset_spans();
139 let mut num_cells = self.outline.scanline_num_cells( self.scan_y );
140 let cells = self.outline.scanline_cells( self.scan_y );
141
142 let mut cover = 0;
143
144 let mut iter = cells.iter();
145
146 if let Some(mut cur_cell) = iter.next() {
147 while num_cells > 0 {
148 let mut x = cur_cell.x;
149 let mut area = cur_cell.area;
150
151 cover += cur_cell.cover;
152 println!("ADD_PATH: SWEEP SCANLINES: x,y {} {} {} {} :: {} {} n: {}", cur_cell.x, self.scan_y, cur_cell.area, cur_cell.cover, area, cover, num_cells);
153 num_cells -= 1;
154 while num_cells > 0 {
156 cur_cell = iter.next().unwrap();
157 if cur_cell.x != x {
158 break;
159 }
160 area += cur_cell.area;
161 cover += cur_cell.cover;
162 num_cells -= 1;
163 println!("ADD_PATH: SWEEP SCANLINES: x,y {} {} {} {} :: {} {}", cur_cell.x, self.scan_y, cur_cell.area, cur_cell.cover, area, cover);
164 }
165 println!("ADD_PATH: SWEEP SCANLINES: x,y {} {} {} {} :: {} {}", cur_cell.x, self.scan_y, cur_cell.area, cur_cell.cover, area, cover);
166 if area != 0 {
167 println!("ADD_PATH: SWEEP SCANLINES: ADDING CELL: x {} y {} area {} cover {}", x, self.scan_y, area, cover);
168 let alpha = self.calculate_alpha((cover << (POLY_SUBPIXEL_SHIFT + 1)) - area);
169 if alpha > 0 {
170 sl.add_cell(x, alpha);
171 }
172 x += 1;
173 }
174 if num_cells > 0 && cur_cell.x > x {
175 let alpha = self.calculate_alpha(cover << (POLY_SUBPIXEL_SHIFT + 1));
176 println!("ADD_PATH: SWEEP SCANLINES: ADDING SPAN: {} -> {} Y: {} area {} cover {}", x, cur_cell.x, self.scan_y, area, cover);
177 if alpha > 0 {
178 sl.add_span(x, cur_cell.x - x, alpha);
179 }
180 }
181 }
182 }
183 if sl.num_spans() != 0 {
184 break;
185 }
186 self.scan_y += 1;
187 }
188 sl.finalize(self.scan_y);
189 self.scan_y += 1;
190 true
191 }
192 pub fn min_x(&self) -> i64 {
194 self.outline.min_x
195 }
196 pub fn max_x(&self) -> i64 {
198 self.outline.max_x
199 }
200}
201
202impl RasterizerScanline {
203 pub fn new() -> Self {
205 Self { clipper: Clip::new(), status: PathStatus::Initial,
206 outline: RasterizerCell::new(),
207 x0: 0, y0: 0, scan_y: 0,
208 filling_rule: FillingRule::NonZero,
209 gamma: (0..256).collect(),
210 }
211 }
212 pub fn gamma<F>(&mut self, gfunc: F)
220 where F: Fn(f64) -> f64
221 {
222 let aa_shift = 8;
223 let aa_scale = 1 << aa_shift;
224 let aa_mask = f64::from(aa_scale - 1);
225
226 self.gamma = (0..256)
227 .map(|i| gfunc(f64::from(i) / aa_mask ))
228 .map(|v| (v * aa_mask).round() as u64)
229 .collect();
230 }
231 pub fn new_with_gamma<F>(gfunc: F) -> Self
236 where F: Fn(f64) -> f64
237 {
238 let mut new = Self::new();
239 new.gamma( gfunc );
240 new
241 }
242 pub fn clip_box(&mut self, x1: f64, y1: f64, x2: f64, y2: f64) {
244 self.clipper.clip_box(RasConvInt::upscale(x1),
245 RasConvInt::upscale(y1),
246 RasConvInt::upscale(x2),
247 RasConvInt::upscale(y2));
248 }
249 pub fn move_to_d(&mut self, x: f64, y: f64) {
253 self.x0 = RasConvInt::upscale( x );
254 self.y0 = RasConvInt::upscale( y );
255 self.clipper.move_to(self.x0,self.y0);
256 self.status = PathStatus::MoveTo;
257 }
258 pub fn line_to_d(&mut self, x: f64, y: f64) {
260 let x = RasConvInt::upscale( x );
261 let y = RasConvInt::upscale( y );
262 self.clipper.line_to(&mut self.outline, x,y);
263 self.status = PathStatus::LineTo;
264 }
265 pub fn close_polygon(&mut self) {
269 if self.status == PathStatus::LineTo {
270 self.clipper.line_to(&mut self.outline, self.x0, self.y0);
271 self.status = PathStatus::Closed;
272 }
273 }
274 pub fn calculate_alpha(&self, area: i64) -> u64 {
278 let aa_shift = 8;
279 let aa_scale = 1 << aa_shift;
280 let aa_scale2 = aa_scale * 2;
281 let aa_mask = aa_scale - 1;
282 let aa_mask2 = aa_scale2 - 1;
283
284 let mut cover = area >> (POLY_SUBPIXEL_SHIFT*2 + 1 - aa_shift);
285 cover = cover.abs();
286 if self.filling_rule == FillingRule::EvenOdd {
287 cover *= aa_mask2;
288 if cover > aa_scale {
289 cover = aa_scale2 - cover;
290 }
291 }
292 cover = max(0, min(cover, aa_mask));
293 self.gamma[cover as usize]
294 }
295}
296
297
298
299
300pub(crate) fn len_i64(a: &Vertex<i64>, b: &Vertex<i64>) -> i64 {
301 len_i64_xy(a.x, a.y, b.x, b.y)
302}
303pub(crate) fn len_i64_xy(x1: i64, y1: i64, x2: i64, y2: i64) -> i64 {
304 let dx = x1 as f64 - x2 as f64;
305 let dy = y1 as f64 - y2 as f64;
306 (dx*dx + dy*dy).sqrt().round() as i64
307}
308
309