px-fwlib 0.10.0
Cross-platform embedded library and documentation for 8/16/32-bit microcontrollers generated with Doxygen 1.9.2
px_gfx.c
1/* =============================================================================
2 ____ ___ ____ ___ _ _ ___ __ __ ___ __ __ TM
3 | _ \ |_ _| / ___| / _ \ | \ | | / _ \ | \/ | |_ _| \ \/ /
4 | |_) | | | | | | | | | | \| | | | | | | |\/| | | | \ /
5 | __/ | | | |___ | |_| | | |\ | | |_| | | | | | | | / \
6 |_| |___| \____| \___/ |_| \_| \___/ |_| |_| |___| /_/\_\
7
8 Copyright (c) 2018 Pieter Conradie <https://piconomix.com>
9
10 License: MIT
11 https://github.com/piconomix/px-fwlib/blob/master/LICENSE.md
12
13 Title: px_gfx.h : Basic monochrome graphics library
14 Author(s): Pieter Conradie
15 Creation Date: 2018-05-07
16
17============================================================================= */
18
19/* _____STANDARD INCLUDES____________________________________________________ */
20#include <string.h>
21#include <stdarg.h>
22
23/* _____PROJECT INCLUDES_____________________________________________________ */
24#include "px_gfx.h"
25#include "px_gfx_disp.h"
26#include "px_gfx_fonts.h"
27#include "px_log.h"
28
29/* _____LOCAL DEFINITIONS____________________________________________________ */
30PX_LOG_NAME("px_gfx");
31
32/// Graphic drawing properties
33typedef struct
34{
35 px_gfx_color_t color_fg; ///< Foreground color
36 px_gfx_color_t color_bg; ///< Background color
37 px_gfx_align_t align; ///< Alignment
38 bool vp_active; ///< View port active flag
39 px_gfx_view_port_t vp; ///< View port
40 const px_gfx_font_t * font; ///< Current font
42
43/// Graphics state definition
44typedef struct
45{
46 px_gfx_draw_prop_t draw_prop;
47 px_gfx_area_t update_area; ///< Area of frame to be updated
48} px_gfx_t;
49
50/* _____MACROS_______________________________________________________________ */
51
52/* _____GLOBAL VARIABLES_____________________________________________________ */
53
54/* _____LOCAL VARIABLES______________________________________________________ */
55/// Graphic state
56static px_gfx_t px_gfx;
57
58/// Default drawing attributes
59static const px_gfx_draw_prop_t px_gfx_draw_prop_default =
60{
61 .color_fg = PX_GFX_COLOR_ON,
62 .color_bg = PX_GFX_COLOR_OFF,
63 .align = PX_GFX_ALIGN_TOP_LEFT,
64 .vp_active = false,
65 .vp =
66 {
67 .x = 0,
68 .y = 0,
69 .width = PX_GFX_DISP_SIZE_X,
70 .height = PX_GFX_DISP_SIZE_Y,
71 .xy_ref = PX_GFX_XY_REF_REL,
72 },
73 .font = &PX_GFX_CFG_DEFAULT_FONT,
74};
75
76/* _____LOCAL FUNCTION DECLARATIONS__________________________________________ */
77
78/* _____LOCAL FUNCTIONS______________________________________________________ */
79static void px_gfx_update_area_reset(void)
80{
81 px_gfx.update_area.x1 = PX_GFX_X_MAX + 1;
82 px_gfx.update_area.x2 = PX_GFX_X_MIN - 1;
83 px_gfx.update_area.y1 = PX_GFX_Y_MAX + 1;
84 px_gfx.update_area.y2 = PX_GFX_Y_MIN - 1;
85}
86
87static bool px_gfx_update_area_is_set(void)
88{
89 if(px_gfx.update_area.x1 <= PX_GFX_X_MAX)
90 {
91 return true;
92 }
93 else
94 {
95 return false;
96 }
97}
98
99static void px_gfx_update_area(px_gfx_xy_t x1,
100 px_gfx_xy_t y1,
101 px_gfx_xy_t x2,
102 px_gfx_xy_t y2)
103{
104 // Swap coordinates if required
105 if(x1 > x2) PX_SWAP(px_gfx_xy_t, x1, x2);
106 if(y1 > y2) PX_SWAP(px_gfx_xy_t, y1, y2);
107 // Outside display area?
108 if((x1 < PX_GFX_X_MIN) && (x2 < PX_GFX_X_MIN)) return;
109 if((x1 > PX_GFX_X_MAX) && (x2 > PX_GFX_X_MAX)) return;
110 if((y1 < PX_GFX_Y_MIN) && (y2 < PX_GFX_Y_MIN)) return;
111 if((y1 > PX_GFX_Y_MAX) && (y2 > PX_GFX_Y_MAX)) return;
112 // Clip to display if required
113 if(x1 < PX_GFX_X_MIN) x1 = PX_GFX_X_MIN;
114 if(x2 > PX_GFX_X_MAX) x2 = PX_GFX_X_MAX;
115 if(y1 < PX_GFX_Y_MIN) y1 = PX_GFX_Y_MIN;
116 if(y2 > PX_GFX_Y_MAX) y2 = PX_GFX_Y_MAX;
117 // Update area
118 if(px_gfx.update_area.x1 > x1) px_gfx.update_area.x1 = x1;
119 if(px_gfx.update_area.x2 < x2) px_gfx.update_area.x2 = x2;
120 if(px_gfx.update_area.y1 > y1) px_gfx.update_area.y1 = y1;
121 if(px_gfx.update_area.y2 < y2) px_gfx.update_area.y2 = y2;
122}
123
124static px_gfx_xy_t px_gfx_vp_adjust_x(px_gfx_xy_t x)
125{
126 if( (px_gfx.draw_prop.vp_active) && (px_gfx.draw_prop.vp.xy_ref == PX_GFX_XY_REF_REL) )
127 {
128 return (x + px_gfx.draw_prop.vp.x);
129 }
130 else
131 {
132 return x;
133 }
134}
135
136static px_gfx_xy_t px_gfx_vp_adjust_y(px_gfx_xy_t y)
137{
138 if( (px_gfx.draw_prop.vp_active) && (px_gfx.draw_prop.vp.xy_ref == PX_GFX_XY_REF_REL) )
139 {
140 return (y + px_gfx.draw_prop.vp.y);
141 }
142 else
143 {
144 return y;
145 }
146}
147
148static void px_gfx_vp_draw_pixel(px_gfx_xy_t x, px_gfx_xy_t y, px_gfx_color_t color)
149{
150 // View port active?
151 if(px_gfx.draw_prop.vp_active)
152 {
153 // X and Y coordinate inside viewport?
154 if( (x < px_gfx.draw_prop.vp.x )
155 ||(x >= px_gfx.draw_prop.vp.x + px_gfx.draw_prop.vp.width )
156 ||(y < px_gfx.draw_prop.vp.y )
157 ||(y >= px_gfx.draw_prop.vp.y + px_gfx.draw_prop.vp.height) )
158 {
159 // No
160 return;
161 }
162 }
163 // X and Y coordinate inside display area?
164 if( (x < PX_GFX_X_MIN)
165 ||(x > PX_GFX_X_MAX)
166 ||(y < PX_GFX_Y_MIN)
167 ||(y > PX_GFX_Y_MAX) )
168 {
169 // No
170 return;
171 }
172 // Draw pixel
173 px_gfx_disp_buf_pixel(x, y, color);
174}
175
176/* _____GLOBAL FUNCTIONS_____________________________________________________ */
177void px_gfx_init(void)
178{
181}
182
184{
185 px_gfx_update_area_reset();
186 px_gfx_update_area(0, 0, PX_GFX_X_MAX, PX_GFX_DISP_SIZE_Y);
187 px_gfx_disp_buf_clear();
188}
189
190void px_gfx_draw(void)
191{
192 px_gfx_update_area(0, 0, PX_GFX_X_MAX, PX_GFX_DISP_SIZE_Y);
193 px_gfx_disp_update(&px_gfx.update_area);
194 px_gfx_update_area_reset();
195}
196
198{
199 if(px_gfx_update_area_is_set())
200 {
201 px_gfx_disp_update(&px_gfx.update_area);
202 px_gfx_update_area_reset();
203 }
204}
205
207{
208 memcpy(area, &px_gfx.update_area, sizeof(px_gfx_area_t));
209
210 return px_gfx_update_area_is_set();
211}
212
214{
215 memcpy(&px_gfx.draw_prop, &px_gfx_draw_prop_default, sizeof(px_gfx.draw_prop));
216}
217
219{
220 px_gfx_color_t old = px_gfx.draw_prop.color_fg;
221 px_gfx.draw_prop.color_fg = color;
222
223 return old;
224}
225
227{
228 px_gfx_color_t old = px_gfx.draw_prop.color_bg;
229 px_gfx.draw_prop.color_bg = color;
230
231 return old;
232}
233
235{
236 px_gfx_align_t old = px_gfx.draw_prop.align;
237 px_gfx.draw_prop.align = align;
238
239 return old;
240}
241
243{
244 px_gfx.draw_prop.vp.x = x;
245 px_gfx.draw_prop.vp.y = y;
246 px_gfx.draw_prop.vp.width = width;
247 px_gfx.draw_prop.vp.height = height;
248 px_gfx.draw_prop.vp.xy_ref = xy_ref;
249 px_gfx.draw_prop.vp_active = true;
250}
251
253{
254 memcpy(&px_gfx.draw_prop.vp, &px_gfx_draw_prop_default.vp, sizeof(px_gfx.draw_prop.vp));
255 px_gfx.draw_prop.vp_active = false;
256}
257
259{
260 const px_gfx_font_t * old = px_gfx.draw_prop.font;
261 px_gfx.draw_prop.font = font;
262
263 return old;
264}
265
267{
268 // Adjust coordinates relative to viewport
269 x = px_gfx_vp_adjust_x(x);
270 y = px_gfx_vp_adjust_y(y);
271 // Update dirty area
272 px_gfx_update_area(x, y, x, y);
273 // Draw pixel
274 px_gfx_vp_draw_pixel(x, y, px_gfx.draw_prop.color_fg);
275}
276
278{
279 // Vertical line?
280 if(x1 == x2)
281 {
282 // Must y1 and y2 be swapped?
283 if(y2 < y1)
284 {
285 // Yes
286 PX_SWAP(px_gfx_xy_t, y1, y2);
287 }
288 px_gfx_draw_line_ver(x1, y1, y2 - y1 + 1);
289 }
290 // Horizontal line?
291 else if(y1 == y2)
292 {
293 // Must x1 and x2 be swapped?
294 if(x2 < x1)
295 {
296 // Yes
297 PX_SWAP(px_gfx_xy_t, x1, x2);
298 }
299 px_gfx_draw_line_hor(x1, y1, x2 - x1 + 1);
300 }
301 else
302 {
303 // http://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm
304 px_gfx_xy_t x, y, dx, dy, err;
305 bool ystep, swap_xy;
306
307 // Adjust coordinates relative to viewport
308 x1 = px_gfx_vp_adjust_x(x1);
309 y1 = px_gfx_vp_adjust_y(y1);
310 x2 = px_gfx_vp_adjust_x(x2);
311 y2 = px_gfx_vp_adjust_y(y2);
312 // Update dirty area
313 px_gfx_update_area(x1, y1, x2, y2);
314 // Calculate absolute dx
315 if(x2 > x1)
316 {
317 dx = x2 - x1;
318 }
319 else
320 {
321 dx = x1 - x2;
322 }
323 // Calculate absolute dy
324 if(y2 > y1)
325 {
326 dy = y2 - y1;
327 }
328 else
329 {
330 dy = y1 - y2;
331 }
332 // Is rate of change dy greater than rate of change dx?
333 if(dy > dx)
334 {
335 // x & y must be swapped
336 swap_xy = true;
337 PX_SWAP(px_gfx_xy_t, dx, dy);
338 PX_SWAP(px_gfx_xy_t, x1, y1);
339 PX_SWAP(px_gfx_xy_t, x2, y2);
340 }
341 else
342 {
343 swap_xy = false;
344 }
345
346 // Must [x1,y1] & [x2,y2] be swapped?
347 if(x1 > x2)
348 {
349 // Yes
350 PX_SWAP(px_gfx_xy_t, x1, x2);
351 PX_SWAP(px_gfx_xy_t, y1, y2);
352 }
353 // Start error with dx / 2
354 err = dx >> 1;
355 // Positive slope?
356 if( y2 > y1 )
357 {
358 // Yes. Change of y in positive direction
359 ystep = true;
360 }
361 else
362 {
363 // No. Change of y in negative direction
364 ystep = false;
365 }
366 // Start at [x1,y1] and finish at [x2,...]
367 y = y1;
368 for(x = x1; x <= x2; x++)
369 {
370 // Is x & y swapped?
371 if(swap_xy)
372 {
373 // Yes
374 px_gfx_vp_draw_pixel(y, x, px_gfx.draw_prop.color_fg);
375 }
376 else
377 {
378 // No
379 px_gfx_vp_draw_pixel(x, y, px_gfx.draw_prop.color_fg);
380 }
381 // Acumulate error for next point
382 err -= dy;
383 // Error negative?
384 if (err < 0)
385 {
386 // Step y
387 if(ystep)
388 {
389 // In positive direction
390 y++;
391 }
392 else
393 {
394 // In negative direction
395 y--;
396 }
397 // Add dx
398 err += dx;
399 }
400 }
401 }
402}
403
405{
406 px_gfx_xy_t i;
407
408 // Adjust coordinates relative to viewport
409 x = px_gfx_vp_adjust_x(x);
410 y = px_gfx_vp_adjust_y(y);
411 // Update dirty area
412 px_gfx_update_area(x, y, x + width - 1, y);
413 // Draw horizontal line
414 for(i = 0; i < width; i++)
415 {
416 px_gfx_vp_draw_pixel(x, y, px_gfx.draw_prop.color_fg);
417 x++;
418 }
419}
420
422{
423 px_gfx_xy_t j;
424
425 // Adjust coordinates relative to viewport
426 x = px_gfx_vp_adjust_x(x);
427 y = px_gfx_vp_adjust_y(y);
428 // Update dirty area
429 px_gfx_update_area(x, y, x, y + height - 1);
430 // Draw vertical line
431 for(j = 0; j < height; j++)
432 {
433 px_gfx_vp_draw_pixel(x, y, px_gfx.draw_prop.color_fg);
434 y++;
435 }
436}
437
439{
440 px_gfx_draw_line_hor(x, y, width); // Top
441 px_gfx_draw_line_hor(x, y + height - 1, width); // Bottom
442 px_gfx_draw_line_ver(x, y, height); // Left
443 px_gfx_draw_line_ver(x + width - 1, y, height); // Right
444}
445
447{
448 px_gfx_xy_t i, j;
449
450 // Adjust coordinates relative to viewport
451 x = px_gfx_vp_adjust_x(x);
452 y = px_gfx_vp_adjust_y(y);
453 // Update dirty area
454 px_gfx_update_area(x, y, x + width - 1, y + height - 1);
455 // Draw fill
456 for(j = y; j < y + height; j++)
457 {
458 for(i = x; i < x + width; i++)
459 {
460 px_gfx_vp_draw_pixel(i, j, px_gfx.draw_prop.color_fg);
461 }
462 }
463}
464
466{
467 px_gfx_xy_t i, j;
468
469 // Adjust coordinates relative to viewport
470 x = px_gfx_vp_adjust_x(x);
471 y = px_gfx_vp_adjust_y(y);
472 // Update dirty area
473 px_gfx_update_area(x, y, x + width - 1, y + height - 1);
474 // Draw fill
475 for(j = y; j < y + height; j++)
476 {
477 for(i = x; i < x + width; i++)
478 {
479 px_gfx_vp_draw_pixel(i, j, px_gfx.draw_prop.color_bg);
480 }
481 }
482}
483
485{
486 // https://en.wikipedia.org/wiki/Midpoint_circle_algorithm
487 // https://rosettacode.org/wiki/Bitmap/Midpoint_circle_algorithm#C
488 px_gfx_xy_t f = 1 - radius;
489 px_gfx_xy_t ddf_x = 1;
490 px_gfx_xy_t ddf_y = -2 * radius;
491 px_gfx_xy_t dx = 0;
492 px_gfx_xy_t dy = radius;
493
494 // Adjust coordinates relative to viewport
495 x = px_gfx_vp_adjust_x(x);
496 y = px_gfx_vp_adjust_y(y);
497 // Update dirty area
498 px_gfx_update_area(x - radius, y - radius,
499 x + radius, y + radius);
500 // 0 deg (12 o'clock)
501 px_gfx_vp_draw_pixel(x, y + radius, px_gfx.draw_prop.color_fg);
502 // 90 deg (3 o'clock)
503 px_gfx_vp_draw_pixel(x + radius, y, px_gfx.draw_prop.color_fg);
504 // 180 deg (6 o'clock)
505 px_gfx_vp_draw_pixel(x, y - radius, px_gfx.draw_prop.color_fg);
506 // 270 deg (9 o'clock)
507 px_gfx_vp_draw_pixel(x - radius, y, px_gfx.draw_prop.color_fg);
508 // Repeat for each pixel in octant (45 deg pie)
509 while(dx < dy)
510 {
511 // Must y pixel be stepped?
512 if(f >= 0)
513 {
514 // Yes
515 dy--;
516 // Update decision
517 ddf_y += 2;
518 f += ddf_y;
519 }
520 // Next pixel in x direction
521 dx++;
522 // Update decision
523 ddf_x += 2;
524 f += ddf_x;
525 // Draw pixel in each octant (45 deg pie)
526 px_gfx_vp_draw_pixel(x + dx, y + dy, px_gfx.draw_prop.color_fg);
527 px_gfx_vp_draw_pixel(x - dx, y + dy, px_gfx.draw_prop.color_fg);
528 px_gfx_vp_draw_pixel(x + dx, y - dy, px_gfx.draw_prop.color_fg);
529 px_gfx_vp_draw_pixel(x - dx, y - dy, px_gfx.draw_prop.color_fg);
530 px_gfx_vp_draw_pixel(x + dy, y + dx, px_gfx.draw_prop.color_fg);
531 px_gfx_vp_draw_pixel(x - dy, y + dx, px_gfx.draw_prop.color_fg);
532 px_gfx_vp_draw_pixel(x + dy, y - dx, px_gfx.draw_prop.color_fg);
533 px_gfx_vp_draw_pixel(x - dy, y - dx, px_gfx.draw_prop.color_fg);
534 }
535}
536
538{
539 px_gfx_xy_t i;
540 px_gfx_xy_t j;
541 uint8_t mask;
542 const uint8_t * data = img->data;
543
544 // Set alignment
545 if(px_gfx.draw_prop.align & PX_GFX_ALIGN_H_MID)
546 {
547 x -= (img->width + 1) / 2 - 1;
548 }
549 if(px_gfx.draw_prop.align & PX_GFX_ALIGN_H_RIGHT)
550 {
551 x -= img->width;
552 }
553 if(px_gfx.draw_prop.align & PX_GFX_ALIGN_V_MID)
554 {
555 y -= img->height / 2 - 1;
556 }
557 if(px_gfx.draw_prop.align & PX_GFX_ALIGN_V_BOT)
558 {
559 y -= img->height - 1;
560 }
561 // Adjust coordinates relative to viewport
562 x = px_gfx_vp_adjust_x(x);
563 y = px_gfx_vp_adjust_y(y);
564 // Update dirty area
565 px_gfx_update_area(x, y, x + img->width - 1, y + img->height - 1);
566 // Repeat for each row
567 for(j = 0; j < img->height; j++)
568 {
569 // Start at most significant bit
570 mask = 1<<7;
571 // Repeat for each pixel in row
572 for(i = 0; i < img->width; i++)
573 {
574 if(*data & mask)
575 {
576 // Foreground color pixel
577 px_gfx_vp_draw_pixel(x + i, y + j, px_gfx.draw_prop.color_fg);
578 }
579 else
580 {
581 // Does pixel need to be drawn?
582 if(px_gfx.draw_prop.color_bg != PX_GFX_COLOR_TRANSPARENT)
583 {
584 // Background color pixel
585 px_gfx_vp_draw_pixel(x + i, y + j, px_gfx.draw_prop.color_bg);
586 }
587 }
588 // Next bit
589 mask >>= 1;
590 // Finished with byte?
591 if(mask == 0x00)
592 {
593 // Next byte
594 data++;
595 // Start again at most significant bit
596 mask = 1<<7;
597 }
598 }
599 // Ended on 8-bit boundary?
600 if(mask != (1 << 7))
601 {
602 // No. Ignore rest of bits in byte
603 data++;
604 }
605 }
606}
607
609{
610 px_gfx_img_t img;
611 const px_gfx_font_t * font = px_gfx.draw_prop.font;
612 const uint8_t * data = font->data;
613 int width_bytes = (font->width + 7) / 8;
614
615 // Find glyph
616 while(*data != 0x00)
617 {
618 // Match?
619 if(*data == glyph)
620 {
621 break;
622 }
623 // Next glyph
624 data += (width_bytes * font->height) + 1;
625 }
626 // Not found?
627 if(*data == 0x00)
628 {
629 return;
630 }
631 // Advance to start of glyph data
632 data++;
633 // Set image parameters
634 img.width = font->width;
635 img.height = font->height;
636 img.data = data;
637 // Draw glyph
638 px_gfx_draw_img(x, y, &img);
639}
640
641void px_gfx_draw_str(px_gfx_xy_t x, px_gfx_xy_t y, const char * str)
642{
643 const px_gfx_font_t * font = px_gfx.draw_prop.font;
644
645 // Save alignment
646 px_gfx_align_t align = px_gfx.draw_prop.align;
647 // No string?
648 if((str == NULL) || (strlen(str) == 0))
649 {
650 return;
651 }
652 // Set alignment
653 if(px_gfx.draw_prop.align & PX_GFX_ALIGN_H_MID)
654 {
655 x -= (font->width * (px_gfx_xy_t)strlen(str)) / 2;
656 }
657 if(px_gfx.draw_prop.align & PX_GFX_ALIGN_H_RIGHT)
658 {
659 x -= (font->width * (px_gfx_xy_t)strlen(str)) - 2;
660 }
661 if(px_gfx.draw_prop.align & PX_GFX_ALIGN_V_MID)
662 {
663 y -= (font->height - 1) / 2;
664 }
665 if(px_gfx.draw_prop.align & PX_GFX_ALIGN_V_BOT)
666 {
667 y -= font->height - 2;
668 }
669 px_gfx.draw_prop.align = PX_GFX_ALIGN_TOP_LEFT;
670 // Draw each glyph
671 while(*str != '\0')
672 {
673 px_gfx_draw_char(x, y, *str++);
674 x += font->width;
675 }
676 // Restore alignment
677 px_gfx.draw_prop.align = align;
678}
679
680void px_gfx_printf(px_gfx_xy_t x, px_gfx_xy_t y, const char * format, ...)
681{
682 va_list args;
683 char str[PX_GFX_CFG_STR_BUFFER_SIZE];
684
685 // Output user formatted string
686 va_start(args, format);
687 vsnprintf(str, PX_GFX_CFG_STR_BUFFER_SIZE, format, args);
688 va_end(args);
689 // Append terminating zero in case of buffer overrun
690 str[PX_GFX_CFG_STR_BUFFER_SIZE-1] = '\0';
691 // Draw string
692 px_gfx_draw_str(x, y, str);
693}
694
#define PX_SWAP(type_t, i, j)
Swap the value of two variables.
Definition: px_defs.h:299
#define NULL
NULL pointer.
Definition: px_defs.h:49
px_gfx_xy_t x
Left.
Definition: px_gfx.h:149
px_gfx_xy_t y
Top.
Definition: px_gfx.h:150
px_gfx_xy_ref_t xy_ref
Coordinate reference.
Definition: px_gfx.h:153
px_gfx_xy_t y2
Bottom.
Definition: px_gfx.h:136
px_gfx_xy_t x1
Left.
Definition: px_gfx.h:133
px_gfx_xy_t x2
Right.
Definition: px_gfx.h:135
px_gfx_xy_t width
Width.
Definition: px_gfx.h:151
px_gfx_xy_t height
Height.
Definition: px_gfx.h:152
px_gfx_xy_t y1
Top.
Definition: px_gfx.h:134
void px_gfx_draw_line_hor(px_gfx_xy_t x, px_gfx_xy_t y, px_gfx_xy_t width)
Draw a horizontal line using the current foreground color.
Definition: px_gfx.c:404
px_gfx_color_t
Foreground and background color definitions.
Definition: px_gfx.h:85
void px_gfx_printf(px_gfx_xy_t x, px_gfx_xy_t y, const char *format,...)
Draw a formatted font string using the current foreground color.
Definition: px_gfx.c:680
void px_gfx_view_port_set(px_gfx_xy_t x, px_gfx_xy_t y, px_gfx_xy_t width, px_gfx_xy_t height, px_gfx_xy_ref_t xy_ref)
Set a drawing view port.
Definition: px_gfx.c:242
px_gfx_align_t px_gfx_align_set(px_gfx_align_t align)
Set the new alignment.
Definition: px_gfx.c:234
px_gfx_xy_ref_t
X Y coordinate reference.
Definition: px_gfx.h:141
void px_gfx_draw(void)
Redraw whole display using display buffer.
Definition: px_gfx.c:190
void px_gfx_draw_char(px_gfx_xy_t x, px_gfx_xy_t y, char glyph)
Draw a font character using the current foreground color.
Definition: px_gfx.c:608
px_gfx_color_t px_gfx_color_bg_set(px_gfx_color_t color)
Set the new background drawing color.
Definition: px_gfx.c:226
px_gfx_align_t
Alignment definition.
Definition: px_gfx.h:94
void px_gfx_view_port_reset(void)
Reset view port.
Definition: px_gfx.c:252
void px_gfx_draw_img(px_gfx_xy_t x, px_gfx_xy_t y, const px_gfx_img_t *img)
Draw a graphic image using the current foreground and background color.
Definition: px_gfx.c:537
void px_gfx_draw_line(px_gfx_xy_t x1, px_gfx_xy_t y1, px_gfx_xy_t x2, px_gfx_xy_t y2)
Draw a line using the current foreground color.
Definition: px_gfx.c:277
int16_t px_gfx_xy_t
Size definition of an X or Y coordinate.
Definition: px_gfx.h:71
bool px_gfx_update_area_get(px_gfx_area_t *area)
Get total area of frame that has changed.
Definition: px_gfx.c:206
void px_gfx_draw_fill_fg(px_gfx_xy_t x, px_gfx_xy_t y, px_gfx_xy_t width, px_gfx_xy_t height)
Draw a solid rectangular fill in the current foreground color.
Definition: px_gfx.c:446
void px_gfx_draw_str(px_gfx_xy_t x, px_gfx_xy_t y, const char *str)
Draw a font string using the current foreground color.
Definition: px_gfx.c:641
void px_gfx_draw_rect(px_gfx_xy_t x, px_gfx_xy_t y, px_gfx_xy_t width, px_gfx_xy_t height)
Draw a rectangle using the current foreground color.
Definition: px_gfx.c:438
void px_gfx_draw_prop_reset(void)
Reset drawing properties to default.
Definition: px_gfx.c:213
void px_gfx_draw_update(void)
Update display with total area that has changed in display buffer.
Definition: px_gfx.c:197
void px_gfx_buf_clear(void)
Clear display buffer.
Definition: px_gfx.c:183
void px_gfx_draw_pixel(px_gfx_xy_t x, px_gfx_xy_t y)
Draw a pixel using the current foreground color.
Definition: px_gfx.c:266
void px_gfx_draw_circ(px_gfx_xy_t x, px_gfx_xy_t y, px_gfx_xy_t radius)
Draw a circle using the current foreground color.
Definition: px_gfx.c:484
void px_gfx_draw_fill_bg(px_gfx_xy_t x, px_gfx_xy_t y, px_gfx_xy_t width, px_gfx_xy_t height)
Draw a solid rectangular fill in the current background color.
Definition: px_gfx.c:465
void px_gfx_init(void)
Initialise graphics library.
Definition: px_gfx.c:177
px_gfx_color_t px_gfx_color_fg_set(px_gfx_color_t color)
Set the new foreground drawing color.
Definition: px_gfx.c:218
const px_gfx_font_t * px_gfx_font_set(const px_gfx_font_t *font)
Set the new font.
Definition: px_gfx.c:258
void px_gfx_draw_line_ver(px_gfx_xy_t x, px_gfx_xy_t y, px_gfx_xy_t height)
Draw a vertical line using the current foreground color.
Definition: px_gfx.c:421
@ PX_GFX_XY_REF_REL
Coordinate references are relative to view port.
Definition: px_gfx.h:142
@ PX_GFX_ALIGN_V_BOT
Vertical (y) bottom.
Definition: px_gfx.h:97
@ PX_GFX_ALIGN_V_MID
Vertical (y) middle.
Definition: px_gfx.h:96
@ PX_GFX_ALIGN_H_MID
Horizontal (x) middle.
Definition: px_gfx.h:99
@ PX_GFX_ALIGN_H_RIGHT
Horizontal (x) right.
Definition: px_gfx.h:100
Area definition.
Definition: px_gfx.h:132
Font definition.
Definition: px_gfx.h:124
Image definition.
Definition: px_gfx.h:116
View port definition.
Definition: px_gfx.h:148
#define PX_LOG_NAME(name)
Macro to declare a log name string once for each file to reduce code size.
Definition: px_log.h:349
Graphic drawing properties.
Definition: px_gfx.c:34
bool vp_active
View port active flag.
Definition: px_gfx.c:38
px_gfx_color_t color_fg
Foreground color.
Definition: px_gfx.c:35
px_gfx_color_t color_bg
Background color.
Definition: px_gfx.c:36
px_gfx_view_port_t vp
View port.
Definition: px_gfx.c:39
px_gfx_align_t align
Alignment.
Definition: px_gfx.c:37
const px_gfx_font_t * font
Current font.
Definition: px_gfx.c:40
Graphics state definition.
Definition: px_gfx.c:45
px_gfx_area_t update_area
Area of frame to be updated.
Definition: px_gfx.c:47