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