]> git.defcon.no Git - avrfbosd/blob - draw.c
567b923aaeda8dcfec66f7f048e3487eaece0547
[avrfbosd] / draw.c
1 #include "draw.h"
2 #include <stdlib.h>
3
4 extern uint8_t* screen_buffer;
5 extern uint8_t hres_bytes;
6
7 void sp(uint8_t x, uint8_t y, uint8_t color)
8 {
9 if (color==0) screen_buffer[(x/8) + (y*hres_bytes)] &= ~0x80 >> (x&7);
10 else if (color==1) screen_buffer[(x/8) + (y*hres_bytes)] |= 0x80 >> (x&7);
11 else screen_buffer[(x/8) + (y*hres_bytes)] ^= 0x80 >> (x&7);
12 }
13
14 void set_pixel(uint8_t x, uint8_t y, uint8_t color)
15 {
16 if (x >= hres_bytes*8 || y >= VRES)
17 return;
18 sp(x,y,color);
19 }
20
21 void fill(uint8_t color)
22 {
23 switch(color) {
24 case c_BLACK:
25 for (int i = 0; i < (hres_bytes*VRES); i++)
26 screen_buffer[i] = 0;
27 break;
28 case c_WHITE:
29 for (int i = 0; i < (hres_bytes*VRES); i++)
30 screen_buffer[i] = 0xFF;
31 break;
32 case c_INVERT:
33 for (int i = 0; i < (hres_bytes*VRES); i++)
34 screen_buffer[i] = ~screen_buffer[i];
35 break;
36 }
37 }
38
39
40 /*
41 Bresenham's line algorithm, optimized and simplified.
42 function line(x0, y0, x1, y1)
43 dx := abs(x1-x0)
44 dy := abs(y1-y0)
45 if x0 < x1 then sx := 1 else sx := -1
46 if y0 < y1 then sy := 1 else sy := -1
47 err := dx-dy
48
49 loop
50 setPixel(x0,y0)
51 if x0 = x1 and y0 = y1 exit loop
52 e2 := 2*err
53 if e2 > -dy then
54 err := err - dy
55 x0 := x0 + sx
56 end if
57 if e2 < dx then
58 err := err + dx
59 y0 := y0 + sy
60 end if
61 end loop
62 */
63 void draw_line(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t c)
64 {
65
66 if (x0 > hres_bytes*8 || y0 > VRES) // || x1 > hres_bytes*8 || y1 > VRES)
67 return;
68
69 int dx, dy, sx, sy, err, p;
70
71 dx = abs( x1-x0 );
72 dy = abs( y1-y0 );
73 if ( x0 < x1 ) sx = 1; else sx = -1;
74 if ( y0 < y1 ) sy = 1; else sy = -1;
75 err = dx - dy;
76
77 while (1)
78 {
79 sp(x0, y0, c);
80 if ( ( x0 == x1 ) && ( y0 == y1 ) ) return;
81 if ( x0 > hres_bytes*8 || y0 > VRES ) return;
82
83 p = 2 * err;
84 if ( p > -dy )
85 {
86 err = err - dy;
87 x0 = x0 + sx;
88 }
89 if ( p < dx )
90 {
91 err = err + dx;
92 y0 = y0 + sy;
93 }
94 }
95 }
96 // draw_row and draw_col ...
97 // These whould really be used for optimization.
98 // As is, they exist for conveniance, not speed :P
99 void draw_col(uint8_t x, uint8_t y0, uint8_t y1, uint8_t c)
100 {
101 draw_line( x, y0, x, y1, c );
102 }
103 void draw_row(uint8_t y, uint8_t x0, uint8_t x1, uint8_t c)
104 {
105 draw_line( x0, y, x1, y, c );
106 }
107
108
109 void _draw_rect(uint8_t x0, uint8_t y0, uint8_t w, uint8_t h, int8_t c, int8_t fc )
110 {
111 if ( fc != -1 )
112 for (unsigned char i = 0; i < h; i++)
113 draw_line(x0,y0+i,x0+w,y0+i,c);
114
115 draw_line(x0,y0,x0+w,y0,c);
116 draw_line(x0,y0,x0,y0+h,c);
117 draw_line(x0+w,y0,x0+w,y0+h,c);
118 draw_line(x0,y0+h,x0+w,y0+h,c);
119 }
120
121 void _draw_circle(uint8_t x0, uint8_t y0, uint8_t radius, int8_t c, int8_t fc) {
122
123 int f = 1 - radius;
124 int ddF_x = 1;
125 int ddF_y = -2 * radius;
126 int x = 0;
127 int y = radius;
128 uint8_t pyy = y,pyx = x;
129
130 //there is a fill color
131 if (fc != -1)
132 draw_row(y0,x0-radius,x0+radius,fc);
133
134 sp(x0, y0 + radius,c);
135 sp(x0, y0 - radius,c);
136 sp(x0 + radius, y0,c);
137 sp(x0 - radius, y0,c);
138
139 while(x < y) {
140 if(f >= 0) {
141 y--;
142 ddF_y += 2;
143 f += ddF_y;
144 }
145 x++;
146 ddF_x += 2;
147 f += ddF_x;
148 //there is a fill color
149 if (fc > -1) {
150 //prevent double draws on the same rows
151 if (pyy != y) {
152 draw_row(y0+y,x0-x,x0+x,fc);
153 draw_row(y0-y,x0-x,x0+x,fc);
154 }
155 if (pyx != x && x != y) {
156 draw_row(y0+x,x0-y,x0+y,fc);
157 draw_row(y0-x,x0-y,x0+y,fc);
158 }
159 pyy = y;
160 pyx = x;
161 }
162
163 sp(x0 + x, y0 + y,c);
164 sp(x0 - x, y0 + y,c);
165 sp(x0 + x, y0 - y,c);
166 sp(x0 - x, y0 - y,c);
167 sp(x0 + y, y0 + x,c);
168 sp(x0 - y, y0 + x,c);
169 sp(x0 + y, y0 - x,c);
170 sp(x0 - y, y0 - x,c);
171 }
172 }
173
174 void draw_rect(uint8_t x0, uint8_t y0, uint8_t w, uint8_t h, uint8_t c)
175 {
176 _draw_rect(x0, y0, w, h, c, -1);
177 }
178
179 void fill_rect(uint8_t x0, uint8_t y0, uint8_t w, uint8_t h, uint8_t c)
180 {
181 _draw_rect(x0, y0, w, h, c, c);
182 }
183
184 void draw_circle(uint8_t x0, uint8_t y0, uint8_t radius, char c)
185 {
186 _draw_circle(x0, y0, radius, c, -1);
187 }
188
189 void fill_circle(uint8_t x0, uint8_t y0, uint8_t radius, char c)
190 {
191 _draw_circle(x0, y0, radius, c, c);
192 }
193
194 void draw_8bpp_bitmap( uint8_t pos_x, uint8_t pos_y, uint8_t width, uint8_t height, const uint8_t* image )
195 {
196 for ( int v = 0; v < height; v++ )
197 {
198 for ( int h = 0; h < width; h++ )
199 {
200 uint8_t t = image[v*width+h];
201 set_pixel( pos_x + h, pos_y + v, t);
202 }
203 }
204 }
205
206 void pgm_draw_8bpp_bitmap( uint8_t pos_x, uint8_t pos_y, uint8_t width, uint8_t height, const uint8_t* image )
207 {
208 for ( int v = 0; v < height; v++ )
209 {
210 for ( int h = 0; h < width; h++ )
211 {
212 uint8_t t = pgm_read_byte(&(image[v*width+h]));
213 set_pixel( pos_x + h, pos_y + v, t);
214 }
215 }
216 }
217