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
use crate::math::Line;
use crate::platform::{abs, as_i32, copysign, f32x4, fract};
use alloc::vec;
use alloc::vec::*;
pub struct Raster {
w: usize,
h: usize,
a: Vec<f32>,
}
impl Raster {
pub fn new(w: usize, h: usize) -> Raster {
Raster {
w,
h,
a: vec![0.0; w * h + 3],
}
}
pub fn draw(&mut self, lines: &Vec<Line>, scale: f32, offset_x: f32, offset_y: f32) {
let params = f32x4::new(1.0 / scale, 1.0 / scale, scale, scale);
let scale = f32x4::splat(scale);
let offset = f32x4::new(offset_x, offset_y, offset_x, offset_y);
for line in lines {
self.line(line, line.coords * scale + offset, line.params * params);
}
}
#[inline(always)]
fn add(&mut self, index: usize, height: f32, mid_x: f32) {
unsafe {
let mid_x = fract(mid_x);
*self.a.get_unchecked_mut(index) += height * (1.0 - mid_x);
*self.a.get_unchecked_mut(index + 1) += height * mid_x;
}
}
#[inline(always)]
fn line(&mut self, line: &Line, coords: f32x4, params: f32x4) {
let (x0, y0, x1, y1) = coords.copied();
let (start_x, start_y, end_x, end_y) = coords.sub_integer(line.nudge).trunc().copied();
let (mut target_x, mut target_y, _, _) =
(coords + line.adjustment).sub_integer(line.nudge).trunc().copied();
let (tdx, tdy, dx, dy) = params.copied();
let sx = copysign(1f32, tdx);
let sy = copysign(1f32, tdy);
let mut tmx = tdx * (target_x - x0);
let mut tmy = tdy * (target_y - y0);
let tdx = abs(tdx);
let tdy = abs(tdy);
let mut x_prev = x0;
let mut y_prev = y0;
let mut index = as_i32(start_x + start_y * self.w as f32);
let index_x_inc = as_i32(sx);
let index_y_inc = as_i32(copysign(self.w as f32, sy));
let mut dist = as_i32(abs(start_x - end_x) + abs(start_y - end_y));
while dist > 0 {
dist -= 1;
let prev_index = index;
let y_next: f32;
let x_next: f32;
if tmx < tmy {
y_next = tmx * dy + y0;
x_next = target_x;
tmx += tdx;
target_x += sx;
index += index_x_inc;
} else {
y_next = target_y;
x_next = tmy * dx + x0;
tmy += tdy;
target_y += sy;
index += index_y_inc;
}
self.add(prev_index as usize, y_prev - y_next, (x_prev + x_next) / 2.0);
x_prev = x_next;
y_prev = y_next;
}
self.add(as_i32(end_x + end_y * self.w as f32) as usize, y_prev - y1, (x_prev + x1) / 2.0);
}
#[inline(always)]
pub fn get_bitmap(&self) -> Vec<u8> {
crate::platform::get_bitmap(&self.a, self.w * self.h)
}
}