Firmware SDK
twr_gfx.c
1 #include <twr_gfx.h>
2 
3 void twr_gfx_init(twr_gfx_t *self, void *display, const twr_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 twr_gfx_set_font(twr_gfx_t *self, const twr_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 twr_gfx_draw_pixel(twr_gfx_t *self, int x, int y, uint32_t color)
43 {
44  int tmp;
45 
46  switch (self->_rotation)
47  {
49  {
50  tmp = x;
51  x = self->_caps.width - 1 - y;
52  y = tmp;
53  break;
54  }
56  {
57  x = self->_caps.width - 1 - x;
58  y = self->_caps.height - 1 - y;
59  break;
60  }
62  {
63  tmp = y;
64  y = self->_caps.height - 1 - x;
65  x = tmp;
66  break;
67  }
68  case TWR_GFX_ROTATION_0:
69  {
70  break;
71  }
72  default:
73  {
74  break;
75  }
76  }
77 
78  if (x >= self->_caps.width || y >= self->_caps.height || x < 0 || y < 0)
79  {
80  return;
81  }
82 
83  self->_driver->draw_pixel(self->_display, x, y, color);
84 }
85 
86 int twr_gfx_draw_char(twr_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 twr_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  twr_gfx_draw_pixel(self, left + x, top + y, color);
123  }
124  }
125  }
126  }
127  }
128 
129  return w;
130 }
131 
132 int twr_gfx_calc_char_width(twr_gfx_t *self, uint8_t ch)
133 {
134  if (!self->_font)
135  {
136  return 0;
137  }
138 
139  const twr_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 twr_gfx_draw_string(twr_gfx_t *self, int left, int top, char *str, uint32_t color)
153 {
154  while(*str)
155  {
156  left += twr_gfx_draw_char(self, left, top, *str, color);
157  str++;
158  }
159  return left;
160 }
161 
163 {
164  int width = 0;
165  while(*str)
166  {
167  width += twr_gfx_calc_char_width(self, *str);
168  str++;
169  }
170  return width;
171 }
172 
173 int twr_gfx_printf(twr_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 twr_gfx_draw_string(self, left, top, buffer, color);
186 }
187 
188 void twr_gfx_draw_line(twr_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  twr_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  twr_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  twr_gfx_draw_pixel(self, y0, x0, color);
262  }
263  else
264  {
265  twr_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 twr_gfx_draw_rectangle(twr_gfx_t *self, int x0, int y0, int x1, int y1, uint32_t color)
279 {
280  twr_gfx_draw_line(self, x0, y0, x0, y1, color);
281  twr_gfx_draw_line(self, x0, y1, x1, y1, color);
282  twr_gfx_draw_line(self, x1, y0, x1, y1, color);
283  twr_gfx_draw_line(self, x1, y0, x0, y0, color);
284 }
285 
286 void twr_gfx_draw_fill_rectangle(twr_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  twr_gfx_draw_pixel(self, x0, y, color);
294  }
295  }
296 }
297 
298 void twr_gfx_draw_fill_rectangle_dithering(twr_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))) >> (dx + 4*dy);
308  twr_gfx_draw_pixel(self, x0, y, d_color);
309  }
310  }
311 }
312 
313 void twr_gfx_draw_fill_rectangle_dithering_color(twr_gfx_t *self, int x0, int y0, int x1, int y1, uint16_t pattern, uint32_t color_fg, uint32_t color_bg)
314 {
315  int y;
316  for (; x0 <= x1; x0++)
317  {
318  for (y = y0; y <= y1; y++)
319  {
320  uint8_t dx = x0 % 4;
321  uint8_t dy = y % 4;
322  uint32_t d_color = pattern & (1 << (dx + 4*dy)) ? color_fg : color_bg;
323  twr_gfx_draw_pixel(self, x0, y, d_color);
324  }
325  }
326 }
327 
328 void twr_gfx_draw_circle(twr_gfx_t *self, int x0, int y0, int radius, uint32_t color)
329 {
330  int x = radius-1;
331  int y = 0;
332  int dx = 1;
333  int dy = 1;
334  int err = dx - (radius << 1);
335 
336  while (x >= y)
337  {
338 
339  twr_gfx_draw_pixel(self, x0 - y, y0 + x, color);
340  twr_gfx_draw_pixel(self, x0 - x, y0 + y, color);
341  twr_gfx_draw_pixel(self, x0 - x, y0 - y, color);
342  twr_gfx_draw_pixel(self, x0 - y, y0 - x, color);
343  twr_gfx_draw_pixel(self, x0 + y, y0 - x, color);
344  twr_gfx_draw_pixel(self, x0 + x, y0 - y, color);
345  twr_gfx_draw_pixel(self, x0 + x, y0 + y, color);
346  twr_gfx_draw_pixel(self, x0 + y, y0 + x, color);
347 
348  if (err <= 0)
349  {
350  y++;
351  err += dy;
352  dy += 2;
353  }
354  if (err > 0)
355  {
356  x--;
357  dx += 2;
358  err += (-radius << 1) + dx;
359  }
360  }
361 }
362 
363 void twr_gfx_draw_fill_circle(twr_gfx_t *self, int x0, int y0, int radius, uint32_t color)
364 {
365  int x = radius-1;
366  int y = 0;
367  int dx = 1;
368  int dy = 1;
369  int err = dx - (radius << 1);
370 
371  while (x >= y)
372  {
373  twr_gfx_draw_line(self, x0 - y, y0 - x, x0 + y, y0 - x, color);
374  twr_gfx_draw_line(self, x0 - x, y0 - y, x0 + x, y0 - y, color);
375  twr_gfx_draw_line(self, x0 - x, y0 + y, x0 + x, y0 + y, color);
376  twr_gfx_draw_line(self, x0 - y, y0 + x, x0 + y, y0 + x, color);
377 
378  if (err <= 0)
379  {
380  y++;
381  err += dy;
382  dy += 2;
383  }
384  if (err > 0)
385  {
386  x--;
387  dx += 2;
388  err += (-radius << 1) + dx;
389  }
390  }
391 }
392 
393 void twr_gfx_draw_round_corner(twr_gfx_t *self, int x0, int y0, int radius, twr_gfx_round_corner_t corner, uint32_t color)
394 {
395  int x = radius-1;
396  int y = 0;
397  int dx = 1;
398  int dy = 1;
399  int err = dx - (radius << 1);
400 
401  while (x >= y)
402  {
403  if (corner & TWR_GFX_ROUND_CORNER_RIGHT_TOP)
404  {
405  twr_gfx_draw_pixel(self, x0 + y, y0 - x, color);
406  twr_gfx_draw_pixel(self, x0 + x, y0 - y, color);
407  }
408 
410  {
411  twr_gfx_draw_pixel(self, x0 + x, y0 + y, color);
412  twr_gfx_draw_pixel(self, x0 + y, y0 + x, color);
413  }
414 
416  {
417  twr_gfx_draw_pixel(self, x0 - y, y0 + x, color);
418  twr_gfx_draw_pixel(self, x0 - x, y0 + y, color);
419  }
420 
421  if (corner & TWR_GFX_ROUND_CORNER_LEFT_TOP)
422  {
423  twr_gfx_draw_pixel(self, x0 - x, y0 - y, color);
424  twr_gfx_draw_pixel(self, x0 - y, y0 - x, color);
425  }
426 
427  if (err <= 0)
428  {
429  y++;
430  err += dy;
431  dy += 2;
432  }
433  if (err > 0)
434  {
435  x--;
436  dx += 2;
437  err += (-radius << 1) + dx;
438  }
439  }
440 }
441 
442 void twr_gfx_draw_fill_round_corner(twr_gfx_t *self, int x0, int y0, int radius, twr_gfx_round_corner_t corner, uint32_t color)
443 {
444  int x = radius-1;
445  int y = 0;
446  int dx = 1;
447  int dy = 1;
448  int err = dx - (radius << 1);
449 
450  while (x >= y)
451  {
452  if (corner & TWR_GFX_ROUND_CORNER_RIGHT_TOP)
453  {
454  twr_gfx_draw_line(self, x0, y0 - x, x0 + y, y0 - x, color);
455  twr_gfx_draw_line(self, x0, y0 - y, x0 + x, y0 - y, color);
456  }
457 
459  {
460  twr_gfx_draw_line(self, x0, y0 + y, x0 + x, y0 + y, color);
461  twr_gfx_draw_line(self, x0, y0 + x, x0 + y, y0 + x, color);
462  }
463 
465  {
466  twr_gfx_draw_line(self, x0 - y, y0 + x, x0, y0 + x, color);
467  twr_gfx_draw_line(self, x0 - x, y0 + y, x0, y0 + y, color);
468  }
469 
470  if (corner & TWR_GFX_ROUND_CORNER_LEFT_TOP)
471  {
472  twr_gfx_draw_line(self, x0 - x, y0 - y, x0, y0 - y, color);
473  twr_gfx_draw_line(self, x0 - y, y0 - x, x0, y0 - x, color);
474  }
475 
476  if (err <= 0)
477  {
478  y++;
479  err += dy;
480  dy += 2;
481  }
482  if (err > 0)
483  {
484  x--;
485  dx += 2;
486  err += (-radius << 1) + dx;
487  }
488  }
489 }
490 
492 {
493  return self->_driver->update(self->_display);
494 }
void twr_gfx_draw_fill_round_corner(twr_gfx_t *self, int x0, int y0, int radius, twr_gfx_round_corner_t corner, uint32_t color)
Lcd draw fill round corner, using Midpoint circle algorithm.
Definition: twr_gfx.c:442
void twr_gfx_draw_rectangle(twr_gfx_t *self, int x0, int y0, int x1, int y1, uint32_t color)
Display draw rectangle.
Definition: twr_gfx.c:278
void twr_gfx_draw_fill_rectangle(twr_gfx_t *self, int x0, int y0, int x1, int y1, uint32_t color)
Display draw fill rectangle.
Definition: twr_gfx.c:286
void twr_gfx_draw_round_corner(twr_gfx_t *self, int x0, int y0, int radius, twr_gfx_round_corner_t corner, uint32_t color)
Lcd draw round corner, using Midpoint circle algorithm.
Definition: twr_gfx.c:393
void twr_gfx_draw_line(twr_gfx_t *self, int x0, int y0, int x1, int y1, uint32_t color)
Display draw line.
Definition: twr_gfx.c:188
void twr_gfx_set_font(twr_gfx_t *self, const twr_font_t *font)
Set font.
Definition: twr_gfx.c:27
twr_gfx_caps_t twr_gfx_get_caps(twr_gfx_t *self)
Get Display capabilities.
Definition: twr_gfx.c:17
void twr_gfx_set_rotation(twr_gfx_t *self, twr_gfx_rotation_t rotation)
Set rotation.
Definition: twr_gfx.c:32
int twr_gfx_draw_char(twr_gfx_t *self, int left, int top, uint8_t ch, uint32_t color)
Display draw char.
Definition: twr_gfx.c:86
void twr_gfx_init(twr_gfx_t *self, void *display, const twr_gfx_driver_t *driver)
Initialize button.
Definition: twr_gfx.c:3
twr_gfx_rotation_t twr_gfx_get_rotation(twr_gfx_t *self)
Get rotation.
Definition: twr_gfx.c:37
bool twr_gfx_display_is_ready(twr_gfx_t *self)
Check if display driver is ready for commands.
Definition: twr_gfx.c:12
int twr_gfx_calc_string_width(twr_gfx_t *self, char *str)
Calc width string.
Definition: twr_gfx.c:162
void twr_gfx_draw_fill_rectangle_dithering_color(twr_gfx_t *self, int x0, int y0, int x1, int y1, uint16_t pattern, uint32_t color_fg, uint32_t color_bg)
Display draw fill rectangle with a dithering pattern defined in the pattern parameter,...
Definition: twr_gfx.c:313
void twr_gfx_draw_fill_rectangle_dithering(twr_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: twr_gfx.c:298
void twr_gfx_draw_circle(twr_gfx_t *self, int x0, int y0, int radius, uint32_t color)
Lcd draw circle, using Midpoint circle algorithm.
Definition: twr_gfx.c:328
twr_gfx_rotation_t
Rotation.
Definition: twr_gfx.h:47
void twr_gfx_draw_pixel(twr_gfx_t *self, int x, int y, uint32_t color)
Draw pixel.
Definition: twr_gfx.c:42
void twr_gfx_clear(twr_gfx_t *self)
Clear.
Definition: twr_gfx.c:22
twr_gfx_round_corner_t
Definition: twr_gfx.h:63
int twr_gfx_draw_string(twr_gfx_t *self, int left, int top, char *str, uint32_t color)
Display draw string.
Definition: twr_gfx.c:152
void twr_gfx_draw_fill_circle(twr_gfx_t *self, int x0, int y0, int radius, uint32_t color)
Lcd draw fill circle, using Midpoint circle algorithm.
Definition: twr_gfx.c:363
int twr_gfx_printf(twr_gfx_t *self, int left, int top, uint32_t color, char *format,...)
Display string.
Definition: twr_gfx.c:173
bool twr_gfx_update(twr_gfx_t *self)
Display update, send data.
Definition: twr_gfx.c:491
int twr_gfx_calc_char_width(twr_gfx_t *self, uint8_t ch)
Calc width character.
Definition: twr_gfx.c:132
@ TWR_GFX_ROTATION_270
Rotation 270 degrees.
Definition: twr_gfx.h:58
@ TWR_GFX_ROTATION_180
Rotation 180 degrees.
Definition: twr_gfx.h:55
@ TWR_GFX_ROTATION_90
Rotation 90 degrees.
Definition: twr_gfx.h:52
@ TWR_GFX_ROTATION_0
Rotation 0 degrees.
Definition: twr_gfx.h:49
@ TWR_GFX_ROUND_CORNER_RIGHT_TOP
Round corner right top.
Definition: twr_gfx.h:65
@ TWR_GFX_ROUND_CORNER_LEFT_TOP
Round corner left top.
Definition: twr_gfx.h:74
@ TWR_GFX_ROUND_CORNER_RIGHT_BOTTOM
Round corner right bottom.
Definition: twr_gfx.h:68
@ TWR_GFX_ROUND_CORNER_LEFT_BOTTOM
Round corner left bottom.
Definition: twr_gfx.h:71
Display size.
Definition: twr_gfx.h:14
Display driver interface.
Definition: twr_gfx.h:23
Instance.
Definition: twr_gfx.h:81