Firmware SDK
 All Data Structures Functions Variables Typedefs Enumerations Enumerator Groups Pages
bc_gfx.c
1 #include <bc_gfx.h>
2 
3 void bc_gfx_init(bc_gfx_t *self, void *display, const bc_gfx_driver_t *driver)
4 {
5  memset(self, 0, sizeof(*self));
6  self->_display = display;
7  self->_driver = driver;
8 
9  self->_caps = driver->get_caps(self->_display);
10 }
11 
13 {
14  return self->_driver->is_ready(self->_display);
15 }
16 
18 {
19  return self->_caps;
20 }
21 
23 {
24  self->_driver->clear(self->_display);
25 }
26 
27 void bc_gfx_set_font(bc_gfx_t *self, const bc_font_t *font)
28 {
29  self->_font = font;
30 }
31 
33 {
34  self->_rotation = rotation;
35 }
36 
38 {
39  return self->_rotation;
40 }
41 
42 void bc_gfx_draw_pixel(bc_gfx_t *self, int x, int y, uint32_t color)
43 {
44  if (x >= self->_caps.width || y >= self->_caps.height || x < 0 || y < 0)
45  {
46  return;
47  }
48 
49  int tmp;
50 
51  switch (self->_rotation)
52  {
53  case BC_GFX_ROTATION_90:
54  {
55  tmp = x;
56  x = self->_caps.height - 1 - y;
57  y = tmp;
58  break;
59  }
61  {
62  x = self->_caps.width - 1 - x;
63  y = self->_caps.height - 1 - y;
64  break;
65  }
67  {
68  tmp = y;
69  y = self->_caps.width - 1 - x;
70  x = tmp;
71  break;
72  }
73  case BC_GFX_ROTATION_0:
74  {
75  break;
76  }
77  default:
78  {
79  break;
80  }
81  }
82 
83  self->_driver->draw_pixel(self->_display, x, y, color);
84 }
85 
86 int bc_gfx_draw_char(bc_gfx_t *self, int left, int top, uint8_t ch, uint32_t color)
87 {
88  if (!self->_font)
89  {
90  return 0;
91  }
92 
93  const bc_font_t *font = self->_font;
94 
95  int w = 0;
96  uint8_t h = 0;
97  uint16_t i;
98  uint16_t x;
99  uint16_t y;
100  uint8_t bytes;
101 
102  for (i = 0; i < font->length; i++)
103  {
104  if (font->chars[i].code == ch)
105  {
106  w = font->chars[i].image->width;
107  h = font->chars[i].image->heigth;
108 
109  bytes = (w + 7) / 8;
110 
111  for (y = 0; y < h; y++)
112  {
113  for (x = 0; x < w; x++)
114  {
115  uint32_t byteIndex = x / 8;
116  byteIndex += y * bytes;
117 
118  uint8_t bitMask = 1 << (7 - (x % 8));
119 
120  if ((font->chars[i].image->image[byteIndex] & bitMask) == 0)
121  {
122  bc_gfx_draw_pixel(self, left + x, top + y, color);
123  }
124  }
125  }
126  }
127  }
128 
129  return w;
130 }
131 
132 int bc_gfx_calc_char_width(bc_gfx_t *self, uint8_t ch)
133 {
134  if (!self->_font)
135  {
136  return 0;
137  }
138 
139  const bc_font_t *font = self->_font;
140 
141  for (int i = 0; i < font->length; i++)
142  {
143  if (font->chars[i].code == ch)
144  {
145  return font->chars[i].image->width;
146  }
147  }
148 
149  return 0;
150 }
151 
152 int bc_gfx_draw_string(bc_gfx_t *self, int left, int top, char *str, uint32_t color)
153 {
154  while(*str)
155  {
156  left += bc_gfx_draw_char(self, left, top, *str, color);
157  str++;
158  }
159  return left;
160 }
161 
162 int bc_gfx_calc_string_width(bc_gfx_t *self, char *str)
163 {
164  int width = 0;
165  while(*str)
166  {
167  width += bc_gfx_calc_char_width(self, *str);
168  str++;
169  }
170  return width;
171 }
172 
173 int bc_gfx_printf(bc_gfx_t *self, int left, int top, uint32_t color, char *format, ...)
174 {
175  va_list ap;
176 
177  char buffer[32];
178 
179  va_start(ap, format);
180 
181  vsnprintf(buffer, sizeof(buffer), format, ap);
182 
183  va_end(ap);
184 
185  return bc_gfx_draw_string(self, left, top, buffer, color);
186 }
187 
188 void bc_gfx_draw_line(bc_gfx_t *self, int x0, int y0, int x1, int y1, uint32_t color)
189 {
190  int tmp;
191 
192  if (y0 == y1)
193  {
194  if (x0 > x1)
195  {
196  tmp = x0;
197  x0 = x1;
198  x1 = tmp;
199  }
200 
201  for (; x0 <= x1; x0++)
202  {
203  bc_gfx_draw_pixel(self, x0, y0, color);
204  }
205 
206  return;
207  }
208  else if (x0 == x1)
209  {
210  if (y0 > y1)
211  {
212  tmp = y0;
213  y0 = y1;
214  y1 = tmp;
215  }
216 
217  for (; y0 <= y1; y0++)
218  {
219  bc_gfx_draw_pixel(self, x0, y0, color);
220  }
221 
222  return;
223  }
224 
225  int16_t step = abs(y1 - y0) > abs(x1 - x0);
226 
227  if (step)
228  {
229  tmp = x0;
230  x0 = y0;
231  y0 = tmp;
232 
233  tmp = x1;
234  x1 = y1;
235  y1 = tmp;
236  }
237 
238  if (x0 > x1)
239  {
240  tmp = x0;
241  x0 = x1;
242  x1 = tmp;
243 
244  tmp = y0;
245  y0 = y1;
246  y1 = tmp;
247  }
248 
249  int16_t dx = x1 - x0;
250  int16_t dy = abs(y1 - y0);
251 
252  int16_t err = dx / 2;
253  int16_t ystep;
254 
255  ystep = y0 < y1 ? 1 : -1;
256 
257  for (; x0 <= x1; x0++)
258  {
259  if (step)
260  {
261  bc_gfx_draw_pixel(self, y0, x0, color);
262  }
263  else
264  {
265  bc_gfx_draw_pixel(self, x0, y0, color);
266  }
267 
268  err -= dy;
269 
270  if (err < 0)
271  {
272  y0 += ystep;
273  err += dx;
274  }
275  }
276 }
277 
278 void bc_gfx_draw_rectangle(bc_gfx_t *self, int x0, int y0, int x1, int y1, uint32_t color)
279 {
280  bc_gfx_draw_line(self, x0, y0, x0, y1, color);
281  bc_gfx_draw_line(self, x0, y1, x1, y1, color);
282  bc_gfx_draw_line(self, x1, y0, x1, y1, color);
283  bc_gfx_draw_line(self, x1, y0, x0, y0, color);
284 }
285 
286 void bc_gfx_draw_fill_rectangle(bc_gfx_t *self, int x0, int y0, int x1, int y1, uint32_t color)
287 {
288  int y;
289  for (; x0 <= x1; x0++)
290  {
291  for (y = y0; y <= y1; y++)
292  {
293  bc_gfx_draw_pixel(self, x0, y, color);
294  }
295  }
296 }
297 
298 void bc_gfx_draw_fill_rectangle_dithering(bc_gfx_t *self, int x0, int y0, int x1, int y1, uint32_t color)
299 {
300  int y;
301  for (; x0 <= x1; x0++)
302  {
303  for (y = y0; y <= y1; y++)
304  {
305  uint8_t dx = x0 % 4;
306  uint8_t dy = y % 4;
307  uint32_t d_color = color & (1 << (dx + 4*dy));
308  bc_gfx_draw_pixel(self, x0, y, d_color);
309  }
310  }
311 }
312 
313 void bc_gfx_draw_circle(bc_gfx_t *self, int x0, int y0, int radius, uint32_t color)
314 {
315  int x = radius-1;
316  int y = 0;
317  int dx = 1;
318  int dy = 1;
319  int err = dx - (radius << 1);
320 
321  while (x >= y)
322  {
323 
324  bc_gfx_draw_pixel(self, x0 - y, y0 + x, color);
325  bc_gfx_draw_pixel(self, x0 - x, y0 + y, color);
326  bc_gfx_draw_pixel(self, x0 - x, y0 - y, color);
327  bc_gfx_draw_pixel(self, x0 - y, y0 - x, color);
328  bc_gfx_draw_pixel(self, x0 + y, y0 - x, color);
329  bc_gfx_draw_pixel(self, x0 + x, y0 - y, color);
330  bc_gfx_draw_pixel(self, x0 + x, y0 + y, color);
331  bc_gfx_draw_pixel(self, x0 + y, y0 + x, color);
332 
333  if (err <= 0)
334  {
335  y++;
336  err += dy;
337  dy += 2;
338  }
339  if (err > 0)
340  {
341  x--;
342  dx += 2;
343  err += (-radius << 1) + dx;
344  }
345  }
346 }
347 
348 void bc_gfx_draw_fill_circle(bc_gfx_t *self, int x0, int y0, int radius, uint32_t color)
349 {
350  int x = radius-1;
351  int y = 0;
352  int dx = 1;
353  int dy = 1;
354  int err = dx - (radius << 1);
355 
356  while (x >= y)
357  {
358  bc_gfx_draw_line(self, x0 - y, y0 - x, x0 + y, y0 - x, color);
359  bc_gfx_draw_line(self, x0 - x, y0 - y, x0 + x, y0 - y, color);
360  bc_gfx_draw_line(self, x0 - x, y0 + y, x0 + x, y0 + y, color);
361  bc_gfx_draw_line(self, x0 - y, y0 + x, x0 + y, y0 + x, color);
362 
363  if (err <= 0)
364  {
365  y++;
366  err += dy;
367  dy += 2;
368  }
369  if (err > 0)
370  {
371  x--;
372  dx += 2;
373  err += (-radius << 1) + dx;
374  }
375  }
376 }
377 
378 void bc_gfx_draw_round_corner(bc_gfx_t *self, int x0, int y0, int radius, bc_gfx_round_corner_t corner, uint32_t color)
379 {
380  int x = radius-1;
381  int y = 0;
382  int dx = 1;
383  int dy = 1;
384  int err = dx - (radius << 1);
385 
386  while (x >= y)
387  {
388  if (corner & BC_GFX_ROUND_CORNER_RIGHT_TOP)
389  {
390  bc_gfx_draw_pixel(self, x0 + y, y0 - x, color);
391  bc_gfx_draw_pixel(self, x0 + x, y0 - y, color);
392  }
393 
395  {
396  bc_gfx_draw_pixel(self, x0 + x, y0 + y, color);
397  bc_gfx_draw_pixel(self, x0 + y, y0 + x, color);
398  }
399 
400  if (corner & BC_GFX_ROUND_CORNER_LEFT_BOTTOM)
401  {
402  bc_gfx_draw_pixel(self, x0 - y, y0 + x, color);
403  bc_gfx_draw_pixel(self, x0 - x, y0 + y, color);
404  }
405 
406  if (corner & BC_GFX_ROUND_CORNER_LEFT_TOP)
407  {
408  bc_gfx_draw_pixel(self, x0 - x, y0 - y, color);
409  bc_gfx_draw_pixel(self, x0 - y, y0 - x, color);
410  }
411 
412  if (err <= 0)
413  {
414  y++;
415  err += dy;
416  dy += 2;
417  }
418  if (err > 0)
419  {
420  x--;
421  dx += 2;
422  err += (-radius << 1) + dx;
423  }
424  }
425 }
426 
427 void bc_gfx_draw_fill_round_corner(bc_gfx_t *self, int x0, int y0, int radius, bc_gfx_round_corner_t corner, uint32_t color)
428 {
429  int x = radius-1;
430  int y = 0;
431  int dx = 1;
432  int dy = 1;
433  int err = dx - (radius << 1);
434 
435  while (x >= y)
436  {
437  if (corner & BC_GFX_ROUND_CORNER_RIGHT_TOP)
438  {
439  bc_gfx_draw_line(self, x0, y0 - x, x0 + y, y0 - x, color);
440  bc_gfx_draw_line(self, x0, y0 - y, x0 + x, y0 - y, color);
441  }
442 
444  {
445  bc_gfx_draw_line(self, x0, y0 + y, x0 + x, y0 + y, color);
446  bc_gfx_draw_line(self, x0, y0 + x, x0 + y, y0 + x, color);
447  }
448 
449  if (corner & BC_GFX_ROUND_CORNER_LEFT_BOTTOM)
450  {
451  bc_gfx_draw_line(self, x0 - y, y0 + x, x0, y0 + x, color);
452  bc_gfx_draw_line(self, x0 - x, y0 + y, x0, y0 + y, color);
453  }
454 
455  if (corner & BC_GFX_ROUND_CORNER_LEFT_TOP)
456  {
457  bc_gfx_draw_line(self, x0 - x, y0 - y, x0, y0 - y, color);
458  bc_gfx_draw_line(self, x0 - y, y0 - x, x0, y0 - x, color);
459  }
460 
461  if (err <= 0)
462  {
463  y++;
464  err += dy;
465  dy += 2;
466  }
467  if (err > 0)
468  {
469  x--;
470  dx += 2;
471  err += (-radius << 1) + dx;
472  }
473  }
474 }
475 
477 {
478  return self->_driver->update(self->_display);
479 }
bc_gfx_rotation_t
Rotation.
Definition: bc_gfx.h:46
int bc_gfx_draw_char(bc_gfx_t *self, int left, int top, uint8_t ch, uint32_t color)
Display draw char.
Definition: bc_gfx.c:86
void bc_gfx_clear(bc_gfx_t *self)
Clear.
Definition: bc_gfx.c:22
void bc_gfx_init(bc_gfx_t *self, void *display, const bc_gfx_driver_t *driver)
Initialize button.
Definition: bc_gfx.c:3
void bc_gfx_draw_pixel(bc_gfx_t *self, int x, int y, uint32_t color)
Draw pixel.
Definition: bc_gfx.c:42
Display size.
Definition: bc_gfx.h:13
void bc_gfx_draw_fill_round_corner(bc_gfx_t *self, int x0, int y0, int radius, bc_gfx_round_corner_t corner, uint32_t color)
Lcd draw fill round corner, using Midpoint circle algorithm.
Definition: bc_gfx.c:427
bc_gfx_round_corner_t
Definition: bc_gfx.h:62
bc_gfx_caps_t(* get_caps)(void *self)
Callback for get capabilities.
Definition: bc_gfx.h:40
Rotation 90 degrees.
Definition: bc_gfx.h:52
int bc_gfx_printf(bc_gfx_t *self, int left, int top, uint32_t color, char *format,...)
Display string.
Definition: bc_gfx.c:173
Display driver interface.
Definition: bc_gfx.h:22
int bc_gfx_calc_char_width(bc_gfx_t *self, uint8_t ch)
Calc width character.
Definition: bc_gfx.c:132
void bc_gfx_set_rotation(bc_gfx_t *self, bc_gfx_rotation_t rotation)
Set rotation.
Definition: bc_gfx.c:32
void bc_gfx_draw_fill_rectangle(bc_gfx_t *self, int x0, int y0, int x1, int y1, uint32_t color)
Display draw fill rectangle.
Definition: bc_gfx.c:286
void bc_gfx_draw_rectangle(bc_gfx_t *self, int x0, int y0, int x1, int y1, uint32_t color)
Display draw rectangle.
Definition: bc_gfx.c:278
int bc_gfx_calc_string_width(bc_gfx_t *self, char *str)
Calc width string.
Definition: bc_gfx.c:162
int bc_gfx_draw_string(bc_gfx_t *self, int left, int top, char *str, uint32_t color)
Display draw string.
Definition: bc_gfx.c:152
void bc_gfx_draw_circle(bc_gfx_t *self, int x0, int y0, int radius, uint32_t color)
Lcd draw circle, using Midpoint circle algorithm.
Definition: bc_gfx.c:313
Rotation 180 degrees.
Definition: bc_gfx.h:55
bool bc_gfx_display_is_ready(bc_gfx_t *self)
Check if display driver is ready for commands.
Definition: bc_gfx.c:12
void bc_gfx_draw_round_corner(bc_gfx_t *self, int x0, int y0, int radius, bc_gfx_round_corner_t corner, uint32_t color)
Lcd draw round corner, using Midpoint circle algorithm.
Definition: bc_gfx.c:378
void bc_gfx_draw_fill_circle(bc_gfx_t *self, int x0, int y0, int radius, uint32_t color)
Lcd draw fill circle, using Midpoint circle algorithm.
Definition: bc_gfx.c:348
Round corner left top.
Definition: bc_gfx.h:74
Round corner left bottom.
Definition: bc_gfx.h:71
bool bc_gfx_update(bc_gfx_t *self)
Display update, send data.
Definition: bc_gfx.c:476
Instance.
Definition: bc_gfx.h:80
bc_gfx_rotation_t bc_gfx_get_rotation(bc_gfx_t *self)
Get rotation.
Definition: bc_gfx.c:37
void bc_gfx_set_font(bc_gfx_t *self, const bc_font_t *font)
Set font.
Definition: bc_gfx.c:27
void bc_gfx_draw_line(bc_gfx_t *self, int x0, int y0, int x1, int y1, uint32_t color)
Display draw line.
Definition: bc_gfx.c:188
Round corner right bottom.
Definition: bc_gfx.h:68
Round corner right top.
Definition: bc_gfx.h:65
Rotation 270 degrees.
Definition: bc_gfx.h:58
bc_gfx_caps_t bc_gfx_get_caps(bc_gfx_t *self)
Get Display capabilities.
Definition: bc_gfx.c:17
Rotation 0 degrees.
Definition: bc_gfx.h:49
void bc_gfx_draw_fill_rectangle_dithering(bc_gfx_t *self, int x0, int y0, int x1, int y1, uint32_t color)
Display draw fill rectangle with a dithering pattern defined in the color parameter.
Definition: bc_gfx.c:298