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