1use std::cmp::min;
18
19use accumulate::accumulate;
20use geom::Point;
21
22pub struct Raster {
27 w: usize,
28 h: usize,
29 a: Vec<f32>,
30}
31
32fn recip(x: f32) -> f32 {
34 x.recip()
35}
36
37impl Raster {
38 pub fn new(w: usize, h: usize) -> Raster {
39 Raster {
40 w: w,
41 h: h,
42 a: vec![0.0; w * h + 4],
43 }
44 }
45
46 pub fn draw_line(&mut self, p0: &Point, p1: &Point) {
47 if p0.y == p1.y {
49 return;
50 }
51 let (dir, p0, p1) = if p0.y < p1.y {
52 (1.0, p0, p1)
53 } else {
54 (-1.0, p1, p0)
55 };
56 let dxdy = (p1.x - p0.x) / (p1.y - p0.y);
57 let mut x = p0.x;
58 let y0 = p0.y as usize; if p0.y < 0.0 {
60 x -= p0.y * dxdy;
61 }
62 for y in y0..min(self.h, p1.y.ceil() as usize) {
63 let linestart = y * self.w;
64 let dy = ((y + 1) as f32).min(p1.y) - (y as f32).max(p0.y);
65 let xnext = x + dxdy * dy;
66 let d = dy * dir;
67 let (x0, x1) = if x < xnext { (x, xnext) } else { (xnext, x) };
68 let x0floor = x0.floor();
69 let x0i = x0floor as i32;
70 let x1ceil = x1.ceil();
71 let x1i = x1ceil as i32;
72 if x1i <= x0i + 1 {
73 let xmf = 0.5 * (x + xnext) - x0floor;
74 self.a[linestart + x0i as usize] += d - d * xmf;
75 self.a[linestart + (x0i + 1) as usize] += d * xmf;
76 } else {
77 let s = recip(x1 - x0);
78 let x0f = x0 - x0floor;
79 let a0 = 0.5 * s * (1.0 - x0f) * (1.0 - x0f);
80 let x1f = x1 - x1ceil + 1.0;
81 let am = 0.5 * s * x1f * x1f;
82 self.a[linestart + x0i as usize] += d * a0;
83 if x1i == x0i + 2 {
84 self.a[linestart + (x0i + 1) as usize] += d * (1.0 - a0 - am);
85 } else {
86 let a1 = s * (1.5 - x0f);
87 self.a[linestart + (x0i + 1) as usize] += d * (a1 - a0);
88 for xi in x0i + 2..x1i - 1 {
89 self.a[linestart + xi as usize] += d * s;
90 }
91 let a2 = a1 + (x1i - x0i - 3) as f32 * s;
92 self.a[linestart + (x1i - 1) as usize] += d * (1.0 - a2 - am);
93 }
94 self.a[linestart + x1i as usize] += d * am;
95 }
96 x = xnext;
97 }
98 }
99
100 pub fn draw_quad(&mut self, p0: &Point, p1: &Point, p2: &Point) {
101 let devx = p0.x - 2.0 * p1.x + p2.x;
103 let devy = p0.y - 2.0 * p1.y + p2.y;
104 let devsq = devx * devx + devy * devy;
105 if devsq < 0.333 {
106 self.draw_line(p0, p2);
107 return;
108 }
109 let tol = 3.0;
110 let n = 1 + (tol * (devx * devx + devy * devy)).sqrt().sqrt().floor() as usize;
111 let mut p = *p0;
113 let nrecip = recip(n as f32);
114 let mut t = 0.0;
115 for _i in 0..n - 1 {
116 t += nrecip;
117 let pn = Point::lerp(t, &Point::lerp(t, p0, p1), &Point::lerp(t, p1, p2));
118 self.draw_line(&p, &pn);
119 p = pn;
120 }
121 self.draw_line(&p, p2);
122 }
123
124 pub fn get_bitmap(&self) -> Vec<u8> {
137 accumulate(&self.a[0..self.w * self.h])
138 }
139}