Vastly simplify GDISP mcufont interface code.
Fix boundary cases. Prevent overwriting of defined display area. Improve performance. Remove hardware acceleration for fonts (unlikely anyway unles the hardware understood our software font structures)
This commit is contained in:
parent
12085b8014
commit
7c303eb72e
6 changed files with 156 additions and 415 deletions
|
@ -36,12 +36,6 @@ typedef int16_t coord_t;
|
||||||
|
|
||||||
#if GFX_USE_GDISP || defined(__DOXYGEN__)
|
#if GFX_USE_GDISP || defined(__DOXYGEN__)
|
||||||
|
|
||||||
/*===========================================================================*/
|
|
||||||
/* Include the low level driver configuration information */
|
|
||||||
/*===========================================================================*/
|
|
||||||
|
|
||||||
#include "gdisp_lld_config.h"
|
|
||||||
|
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
/* Type definitions */
|
/* Type definitions */
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
|
@ -480,35 +474,6 @@ extern "C" {
|
||||||
void gdispFillArc(coord_t x, coord_t y, coord_t radius, coord_t startangle, coord_t endangle, color_t color);
|
void gdispFillArc(coord_t x, coord_t y, coord_t radius, coord_t startangle, coord_t endangle, color_t color);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Basic Text Rendering Functions */
|
|
||||||
|
|
||||||
#if GDISP_NEED_TEXT || defined(__DOXYGEN__)
|
|
||||||
/**
|
|
||||||
* @brief Draw a text character.
|
|
||||||
*
|
|
||||||
* @param[in] x,y The position for the text
|
|
||||||
* @param[in] c The character to draw
|
|
||||||
* @param[in] font The font to use
|
|
||||||
* @param[in] color The color to use
|
|
||||||
*
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
void gdispDrawChar(coord_t x, coord_t y, uint16_t c, font_t font, color_t color);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Draw a text character with a filled background.
|
|
||||||
*
|
|
||||||
* @param[in] x,y The position for the text
|
|
||||||
* @param[in] c The character to draw
|
|
||||||
* @param[in] font The font to use
|
|
||||||
* @param[in] color The color to use
|
|
||||||
* @param[in] bgcolor The background color to use
|
|
||||||
*
|
|
||||||
* @api
|
|
||||||
*/
|
|
||||||
void gdispFillChar(coord_t x, coord_t y, uint16_t c, font_t font, color_t color, color_t bgcolor);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Read a pixel Function */
|
/* Read a pixel Function */
|
||||||
|
|
||||||
#if GDISP_NEED_PIXELREAD || defined(__DOXYGEN__)
|
#if GDISP_NEED_PIXELREAD || defined(__DOXYGEN__)
|
||||||
|
@ -591,8 +556,6 @@ extern "C" {
|
||||||
#define gdispFillArc(x, y, radius, sangle, eangle, color) gdisp_lld_fill_arc(x, y, radius, sangle, eangle, color)
|
#define gdispFillArc(x, y, radius, sangle, eangle, color) gdisp_lld_fill_arc(x, y, radius, sangle, eangle, color)
|
||||||
#define gdispDrawEllipse(x, y, a, b, color) gdisp_lld_draw_ellipse(x, y, a, b, color)
|
#define gdispDrawEllipse(x, y, a, b, color) gdisp_lld_draw_ellipse(x, y, a, b, color)
|
||||||
#define gdispFillEllipse(x, y, a, b, color) gdisp_lld_fill_ellipse(x, y, a, b, color)
|
#define gdispFillEllipse(x, y, a, b, color) gdisp_lld_fill_ellipse(x, y, a, b, color)
|
||||||
#define gdispDrawChar(x, y, c, font, color) gdisp_lld_draw_char(x, y, c, font, color)
|
|
||||||
#define gdispFillChar(x, y, c, font, color, bgcolor) gdisp_lld_fill_char(x, y, c, font, color, bgcolor)
|
|
||||||
#define gdispGetPixelColor(x, y) gdisp_lld_get_pixel_color(x, y)
|
#define gdispGetPixelColor(x, y) gdisp_lld_get_pixel_color(x, y)
|
||||||
#define gdispVerticalScroll(x, y, cx, cy, lines, bgcolor) gdisp_lld_vertical_scroll(x, y, cx, cy, lines, bgcolor)
|
#define gdispVerticalScroll(x, y, cx, cy, lines, bgcolor) gdisp_lld_vertical_scroll(x, y, cx, cy, lines, bgcolor)
|
||||||
#define gdispControl(what, value) gdisp_lld_control(what, value)
|
#define gdispControl(what, value) gdisp_lld_control(what, value)
|
||||||
|
@ -652,9 +615,34 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color);
|
||||||
void gdispFillConvexPoly(coord_t tx, coord_t ty, const point *pntarray, unsigned cnt, color_t color);
|
void gdispFillConvexPoly(coord_t tx, coord_t ty, const point *pntarray, unsigned cnt, color_t color);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Extra Text Functions */
|
/* Text Functions */
|
||||||
|
|
||||||
#if GDISP_NEED_TEXT || defined(__DOXYGEN__)
|
#if GDISP_NEED_TEXT || defined(__DOXYGEN__)
|
||||||
|
/**
|
||||||
|
* @brief Draw a text character.
|
||||||
|
*
|
||||||
|
* @param[in] x,y The position for the text
|
||||||
|
* @param[in] c The character to draw
|
||||||
|
* @param[in] font The font to use
|
||||||
|
* @param[in] color The color to use
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
void gdispDrawChar(coord_t x, coord_t y, uint16_t c, font_t font, color_t color);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Draw a text character with a filled background.
|
||||||
|
*
|
||||||
|
* @param[in] x,y The position for the text
|
||||||
|
* @param[in] c The character to draw
|
||||||
|
* @param[in] font The font to use
|
||||||
|
* @param[in] color The color to use
|
||||||
|
* @param[in] bgcolor The background color to use
|
||||||
|
*
|
||||||
|
* @api
|
||||||
|
*/
|
||||||
|
void gdispFillChar(coord_t x, coord_t y, uint16_t c, font_t font, color_t color, color_t bgcolor);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Draw a text string.
|
* @brief Draw a text string.
|
||||||
*
|
*
|
||||||
|
|
|
@ -461,135 +461,6 @@ GDISPDriver GDISP;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if GDISP_NEED_TEXT && !GDISP_HARDWARE_TEXT
|
|
||||||
#include "mcufont.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if GDISP_NEED_TEXT && !GDISP_HARDWARE_TEXT
|
|
||||||
static void gdisp_lld_draw_char_callback(int16_t x, int16_t y, uint8_t count, uint8_t alpha, void *state) {
|
|
||||||
color_t color = *(color_t*)state;
|
|
||||||
if (alpha == 255)
|
|
||||||
{
|
|
||||||
if (count == 1)
|
|
||||||
gdisp_lld_draw_pixel(x, y, color);
|
|
||||||
else
|
|
||||||
gdisp_lld_fill_area(x, y, count, 1, color);
|
|
||||||
}
|
|
||||||
#if GDISP_NEED_ANTIALIAS
|
|
||||||
else
|
|
||||||
{
|
|
||||||
while (count--)
|
|
||||||
{
|
|
||||||
color_t oldColor;
|
|
||||||
|
|
||||||
oldColor = gdisp_lld_get_pixel_color(x, y);
|
|
||||||
oldColor = gdispBlendColor(color, oldColor, alpha);
|
|
||||||
gdisp_lld_draw_pixel(x, y, oldColor);
|
|
||||||
|
|
||||||
x++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void gdisp_lld_draw_char(coord_t x, coord_t y, uint16_t c, font_t font, color_t color) {
|
|
||||||
mf_render_character(font, x, y, c, gdisp_lld_draw_char_callback, &color);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if GDISP_NEED_TEXT && !GDISP_HARDWARE_TEXTFILLS
|
|
||||||
typedef struct {
|
|
||||||
int16_t x0;
|
|
||||||
int16_t y0;
|
|
||||||
int16_t x1;
|
|
||||||
int16_t y1;
|
|
||||||
int16_t x;
|
|
||||||
int16_t y;
|
|
||||||
color_t fg;
|
|
||||||
color_t bg;
|
|
||||||
} gdisp_lld_fill_char_state_t;
|
|
||||||
|
|
||||||
static void gdisp_lld_fill_char_callback(int16_t x, int16_t y, uint8_t count, uint8_t alpha, void *state) {
|
|
||||||
gdisp_lld_fill_char_state_t *s = state;
|
|
||||||
|
|
||||||
if (y > s->y && s->x != s->x0)
|
|
||||||
{
|
|
||||||
/* Fill background to the end of current line */
|
|
||||||
gdisp_lld_fill_area(s->x, s->y, s->x1 - s->x, 1, s->bg);
|
|
||||||
s->y++;
|
|
||||||
s->x = s->x0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (y > s->y)
|
|
||||||
{
|
|
||||||
/* Fill background for given number of full lines */
|
|
||||||
gdisp_lld_fill_area(s->x0, s->y, s->x1 - s->x0, y - s->y, s->bg);
|
|
||||||
s->y = y;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (x > s->x)
|
|
||||||
{
|
|
||||||
/* Fill background from previous X position */
|
|
||||||
gdisp_lld_fill_area(s->x, s->y, x - s->x, 1, s->bg);
|
|
||||||
s->x = x;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!count)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (y == s->y)
|
|
||||||
{
|
|
||||||
s->x += count;
|
|
||||||
|
|
||||||
if (s->x == s->x1)
|
|
||||||
{
|
|
||||||
s->x = s->x0;
|
|
||||||
s->y++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Draw the foreground */
|
|
||||||
if (alpha == 255 || alpha == 0)
|
|
||||||
{
|
|
||||||
if (count == 1)
|
|
||||||
gdisp_lld_draw_pixel(x, y, alpha ? s->fg : s->bg);
|
|
||||||
else
|
|
||||||
gdisp_lld_fill_area(x, y, count, 1, alpha ? s->fg : s->bg);
|
|
||||||
}
|
|
||||||
#if GDISP_NEED_ANTIALIAS
|
|
||||||
else
|
|
||||||
{
|
|
||||||
while (count--)
|
|
||||||
{
|
|
||||||
color_t color;
|
|
||||||
color = gdispBlendColor(s->fg, s->bg, alpha);
|
|
||||||
gdisp_lld_draw_pixel(x, y, color);
|
|
||||||
|
|
||||||
x++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void gdisp_lld_fill_char(coord_t x, coord_t y, uint16_t c, font_t font, color_t color, color_t bgcolor) {
|
|
||||||
gdisp_lld_fill_char_state_t state;
|
|
||||||
|
|
||||||
state.x0 = x;
|
|
||||||
state.y0 = y;
|
|
||||||
state.x1 = x + mf_character_width(font, c) + font->baseline_x;
|
|
||||||
state.y1 = y + font->height;
|
|
||||||
state.x = x;
|
|
||||||
state.y = y;
|
|
||||||
state.fg = color;
|
|
||||||
state.bg = bgcolor;
|
|
||||||
|
|
||||||
mf_render_character(font, x, y, c, gdisp_lld_fill_char_callback, &state);
|
|
||||||
|
|
||||||
gdisp_lld_fill_char_callback(state.x0, state.y1, 0, 0, &state);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#if GDISP_NEED_CONTROL && !GDISP_HARDWARE_CONTROL
|
#if GDISP_NEED_CONTROL && !GDISP_HARDWARE_CONTROL
|
||||||
void gdisp_lld_control(unsigned what, void *value) {
|
void gdisp_lld_control(unsigned what, void *value) {
|
||||||
(void)what;
|
(void)what;
|
||||||
|
@ -657,14 +528,6 @@ void *gdisp_lld_query(unsigned what) {
|
||||||
gdisp_lld_fill_circle(msg->fillarc.x, msg->fillarc.y, msg->fillarc.radius, msg->fillarc.startangle, msg->fillarc.endangle, msg->fillarc.color);
|
gdisp_lld_fill_circle(msg->fillarc.x, msg->fillarc.y, msg->fillarc.radius, msg->fillarc.startangle, msg->fillarc.endangle, msg->fillarc.color);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
#if GDISP_NEED_TEXT
|
|
||||||
case GDISP_LLD_MSG_DRAWCHAR:
|
|
||||||
gdisp_lld_draw_char(msg->drawchar.x, msg->drawchar.y, msg->drawchar.c, msg->drawchar.font, msg->drawchar.color);
|
|
||||||
break;
|
|
||||||
case GDISP_LLD_MSG_FILLCHAR:
|
|
||||||
gdisp_lld_fill_char(msg->fillchar.x, msg->fillchar.y, msg->fillchar.c, msg->fillchar.font, msg->fillchar.color, msg->fillchar.bgcolor);
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
#if GDISP_NEED_PIXELREAD
|
#if GDISP_NEED_PIXELREAD
|
||||||
case GDISP_LLD_MSG_GETPIXELCOLOR:
|
case GDISP_LLD_MSG_GETPIXELCOLOR:
|
||||||
msg->getpixelcolor.result = gdisp_lld_get_pixel_color(msg->getpixelcolor.x, msg->getpixelcolor.y);
|
msg->getpixelcolor.result = gdisp_lld_get_pixel_color(msg->getpixelcolor.x, msg->getpixelcolor.y);
|
||||||
|
|
|
@ -106,22 +106,6 @@
|
||||||
#define GDISP_HARDWARE_ARCFILLS FALSE
|
#define GDISP_HARDWARE_ARCFILLS FALSE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Hardware accelerated text drawing.
|
|
||||||
* @details If set to @p FALSE software emulation is used.
|
|
||||||
*/
|
|
||||||
#ifndef GDISP_HARDWARE_TEXT
|
|
||||||
#define GDISP_HARDWARE_TEXT FALSE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Hardware accelerated text drawing with a filled background.
|
|
||||||
* @details If set to @p FALSE software emulation is used.
|
|
||||||
*/
|
|
||||||
#ifndef GDISP_HARDWARE_TEXTFILLS
|
|
||||||
#define GDISP_HARDWARE_TEXTFILLS FALSE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Hardware accelerated scrolling.
|
* @brief Hardware accelerated scrolling.
|
||||||
* @details If set to @p FALSE there is no support for scrolling.
|
* @details If set to @p FALSE there is no support for scrolling.
|
||||||
|
@ -167,26 +151,6 @@
|
||||||
* @name GDISP software algorithm choices
|
* @name GDISP software algorithm choices
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
/**
|
|
||||||
* @brief For filled text drawing, use a background fill and then draw
|
|
||||||
* the text instead of using a blit or direct pixel drawing.
|
|
||||||
* @details If set to @p TRUE background fill and then text draw is used.
|
|
||||||
* @note This is ignored if hardware accelerated text is supported.
|
|
||||||
*/
|
|
||||||
#ifndef GDISP_SOFTWARE_TEXTFILLDRAW
|
|
||||||
#define GDISP_SOFTWARE_TEXTFILLDRAW FALSE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief For filled text drawing, when using a bitmap blit
|
|
||||||
* use a column by column buffer rather than a full character
|
|
||||||
* buffer to save memory at a small performance cost.
|
|
||||||
* @details If set to @p TRUE background fill one character column at a time.
|
|
||||||
* @note This is ignored if software text using blit is not being used.
|
|
||||||
*/
|
|
||||||
#ifndef GDISP_SOFTWARE_TEXTBLITCOLUMN
|
|
||||||
#define GDISP_SOFTWARE_TEXTBLITCOLUMN FALSE
|
|
||||||
#endif
|
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -42,10 +42,6 @@ typedef enum gdisp_msgaction {
|
||||||
GDISP_LLD_MSG_DRAWARC,
|
GDISP_LLD_MSG_DRAWARC,
|
||||||
GDISP_LLD_MSG_FILLARC,
|
GDISP_LLD_MSG_FILLARC,
|
||||||
#endif
|
#endif
|
||||||
#if GDISP_NEED_TEXT
|
|
||||||
GDISP_LLD_MSG_DRAWCHAR,
|
|
||||||
GDISP_LLD_MSG_FILLCHAR,
|
|
||||||
#endif
|
|
||||||
#if GDISP_NEED_PIXELREAD
|
#if GDISP_NEED_PIXELREAD
|
||||||
GDISP_LLD_MSG_GETPIXELCOLOR,
|
GDISP_LLD_MSG_GETPIXELCOLOR,
|
||||||
#endif
|
#endif
|
||||||
|
@ -151,23 +147,6 @@ typedef union gdisp_lld_msg {
|
||||||
coord_t startangle, endangle;
|
coord_t startangle, endangle;
|
||||||
color_t color;
|
color_t color;
|
||||||
} fillarc;
|
} fillarc;
|
||||||
struct gdisp_lld_msg_drawchar {
|
|
||||||
gfxQueueItem qi;
|
|
||||||
gdisp_msgaction_t action; // GDISP_LLD_MSG_DRAWCHAR
|
|
||||||
coord_t x, y;
|
|
||||||
uint16_t c;
|
|
||||||
font_t font;
|
|
||||||
color_t color;
|
|
||||||
} drawchar;
|
|
||||||
struct gdisp_lld_msg_fillchar {
|
|
||||||
gfxQueueItem qi;
|
|
||||||
gdisp_msgaction_t action; // GDISP_LLD_MSG_FILLCHAR
|
|
||||||
coord_t x, y;
|
|
||||||
uint16_t c;
|
|
||||||
font_t font;
|
|
||||||
color_t color;
|
|
||||||
color_t bgcolor;
|
|
||||||
} fillchar;
|
|
||||||
struct gdisp_lld_msg_getpixelcolor {
|
struct gdisp_lld_msg_getpixelcolor {
|
||||||
gfxQueueItem qi;
|
gfxQueueItem qi;
|
||||||
gdisp_msgaction_t action; // GDISP_LLD_MSG_GETPIXELCOLOR
|
gdisp_msgaction_t action; // GDISP_LLD_MSG_GETPIXELCOLOR
|
||||||
|
|
|
@ -296,6 +296,10 @@
|
||||||
/* #define GDISP_USE_GPIO */
|
/* #define GDISP_USE_GPIO */
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
|
#if GFX_USE_GDISP
|
||||||
|
#include "gdisp_lld_config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* _GDISP_OPTIONS_H */
|
#endif /* _GDISP_OPTIONS_H */
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
|
|
|
@ -16,10 +16,6 @@
|
||||||
|
|
||||||
#if GFX_USE_GDISP
|
#if GFX_USE_GDISP
|
||||||
|
|
||||||
#ifdef GDISP_NEED_TEXT
|
|
||||||
#include "mcufont.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Include the low level driver information */
|
/* Include the low level driver information */
|
||||||
#include "gdisp/lld/gdisp_lld.h"
|
#include "gdisp/lld/gdisp_lld.h"
|
||||||
|
|
||||||
|
@ -399,43 +395,6 @@ void gdispFillRoundedBox(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t r
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if (GDISP_NEED_TEXT && GDISP_NEED_MULTITHREAD)
|
|
||||||
void gdispDrawChar(coord_t x, coord_t y, uint16_t c, font_t font, color_t color) {
|
|
||||||
gfxMutexEnter(&gdispMutex);
|
|
||||||
gdisp_lld_draw_char(x, y, c, font, color);
|
|
||||||
gfxMutexExit(&gdispMutex);
|
|
||||||
}
|
|
||||||
#elif GDISP_NEED_TEXT && GDISP_NEED_ASYNC
|
|
||||||
void gdispDrawChar(coord_t x, coord_t y, uint16_t c, font_t font, color_t color) {
|
|
||||||
gdisp_lld_msg_t *p = gdispAllocMsg(GDISP_LLD_MSG_DRAWCHAR);
|
|
||||||
p->drawchar.x = x;
|
|
||||||
p->drawchar.y = y;
|
|
||||||
p->drawchar.c = c;
|
|
||||||
p->drawchar.font = font;
|
|
||||||
p->drawchar.color = color;
|
|
||||||
gfxQueuePut(&gdispQueue, &p->qi, TIME_IMMEDIATE);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if (GDISP_NEED_TEXT && GDISP_NEED_MULTITHREAD)
|
|
||||||
void gdispFillChar(coord_t x, coord_t y, uint16_t c, font_t font, color_t color, color_t bgcolor) {
|
|
||||||
gfxMutexEnter(&gdispMutex);
|
|
||||||
gdisp_lld_fill_char(x, y, c, font, color, bgcolor);
|
|
||||||
gfxMutexExit(&gdispMutex);
|
|
||||||
}
|
|
||||||
#elif GDISP_NEED_TEXT && GDISP_NEED_ASYNC
|
|
||||||
void gdispFillChar(coord_t x, coord_t y, uint16_t c, font_t font, color_t color, color_t bgcolor) {
|
|
||||||
gdisp_lld_msg_t *p = gdispAllocMsg(GDISP_LLD_MSG_FILLCHAR);
|
|
||||||
p->fillchar.x = x;
|
|
||||||
p->fillchar.y = y;
|
|
||||||
p->fillchar.c = c;
|
|
||||||
p->fillchar.font = font;
|
|
||||||
p->fillchar.color = color;
|
|
||||||
p->fillchar.bgcolor = bgcolor;
|
|
||||||
gfxQueuePut(&gdispQueue, &p->qi, TIME_IMMEDIATE);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if (GDISP_NEED_PIXELREAD && (GDISP_NEED_MULTITHREAD || GDISP_NEED_ASYNC))
|
#if (GDISP_NEED_PIXELREAD && (GDISP_NEED_MULTITHREAD || GDISP_NEED_ASYNC))
|
||||||
color_t gdispGetPixelColor(coord_t x, coord_t y) {
|
color_t gdispGetPixelColor(coord_t x, coord_t y) {
|
||||||
color_t c;
|
color_t c;
|
||||||
|
@ -620,21 +579,84 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if GDISP_NEED_TEXT
|
#if GDISP_NEED_TEXT
|
||||||
|
#include "mcufont.h"
|
||||||
|
|
||||||
|
#if GDISP_NEED_ANTIALIAS && GDISP_NEED_PIXELREAD
|
||||||
|
static void text_draw_char_callback(int16_t x, int16_t y, uint8_t count, uint8_t alpha, void *state) {
|
||||||
|
if (alpha == 255) {
|
||||||
|
if (count == 1)
|
||||||
|
gdispDrawPixel(x, y, ((color_t *)state)[0]);
|
||||||
|
else
|
||||||
|
gdispFillArea(x, y, count, 1, ((color_t *)state)[0]);
|
||||||
|
} else {
|
||||||
|
while (count--) {
|
||||||
|
gdispDrawPixel(x, y, gdispBlendColor(((color_t *)state)[0], gdispGetPixelColor(x, y), alpha));
|
||||||
|
x++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static void text_draw_char_callback(int16_t x, int16_t y, uint8_t count, uint8_t alpha, void *state) {
|
||||||
|
if (alpha > 0x80) { // A best approximation when using anti-aliased fonts but we can't actually draw them anti-aliased
|
||||||
|
if (count == 1)
|
||||||
|
gdispDrawPixel(x, y, ((color_t *)state)[0]);
|
||||||
|
else
|
||||||
|
gdispFillArea(x, y, count, 1, ((color_t *)state)[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void gdispDrawChar(coord_t x, coord_t y, uint16_t c, font_t font, color_t color) {
|
||||||
|
/* No mutex required as we only call high level functions which have their own mutex */
|
||||||
|
mf_render_character(font, x, y, c, text_draw_char_callback, &color);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if GDISP_NEED_ANTIALIAS
|
||||||
|
static void text_fill_char_callback(int16_t x, int16_t y, uint8_t count, uint8_t alpha, void *state) {
|
||||||
|
if (alpha == 255) {
|
||||||
|
if (count == 1)
|
||||||
|
gdispDrawPixel(x, y, ((color_t *)state)[0]);
|
||||||
|
else
|
||||||
|
gdispFillArea(x, y, count, 1, ((color_t *)state)[0]);
|
||||||
|
} else {
|
||||||
|
while (count--) {
|
||||||
|
gdispDrawPixel(x, y, gdispBlendColor(((color_t *)state)[0], ((color_t *)state)[1], alpha));
|
||||||
|
x++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#define text_fill_char_callback text_draw_char_callback
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void gdispFillChar(coord_t x, coord_t y, uint16_t c, font_t font, color_t color, color_t bgcolor) {
|
||||||
|
/* No mutex required as we only call high level functions which have their own mutex */
|
||||||
|
color_t state[2];
|
||||||
|
|
||||||
|
state[0] = color;
|
||||||
|
state[1] = bgcolor;
|
||||||
|
|
||||||
|
gdispFillArea(x, y, mf_character_width(font, c) + font->baseline_x, font->height, bgcolor);
|
||||||
|
mf_render_character(font, x, y, c, text_fill_char_callback, state);
|
||||||
|
}
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
font_t font;
|
font_t font;
|
||||||
color_t color;
|
color_t color;
|
||||||
|
coord_t x, y;
|
||||||
|
coord_t cx, cy;
|
||||||
} gdispDrawString_state_t;
|
} gdispDrawString_state_t;
|
||||||
|
|
||||||
/* Callback to render characters. */
|
/* Callback to render characters. */
|
||||||
static uint8_t gdispDrawString_callback(int16_t x, int16_t y,
|
static uint8_t gdispDrawString_callback(int16_t x, int16_t y, mf_char character, void *state)
|
||||||
mf_char character, void *state)
|
|
||||||
{
|
{
|
||||||
gdispDrawString_state_t *s = state;
|
gdispDrawString_state_t *s = state;
|
||||||
uint8_t w;
|
uint8_t w;
|
||||||
|
|
||||||
gdispDrawChar(x, y, character, s->font, s->color);
|
|
||||||
w = mf_character_width(s->font, character);
|
w = mf_character_width(s->font, character);
|
||||||
|
if (x >= s->x && x+w < s->x + s->cx && y >= s->y && y+s->font->height <= s->y + s->cy)
|
||||||
|
mf_render_character(s->font, x, y, character, text_draw_char_callback, &s->color);
|
||||||
return w;
|
return w;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -644,80 +666,31 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) {
|
||||||
|
|
||||||
state.font = font;
|
state.font = font;
|
||||||
state.color = color;
|
state.color = color;
|
||||||
|
state.x = x;
|
||||||
|
state.y = y;
|
||||||
|
state.cx = GDISP.Width - x;
|
||||||
|
state.cy = GDISP.Height - y;
|
||||||
|
|
||||||
mf_render_aligned(font, x, y, MF_ALIGN_LEFT, str, 0,
|
mf_render_aligned(font, x, y, MF_ALIGN_LEFT, str, 0, gdispDrawString_callback, &state);
|
||||||
gdispDrawString_callback, &state);
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#if GDISP_NEED_TEXT
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
coord_t y0;
|
|
||||||
coord_t prev_x;
|
|
||||||
font_t font;
|
font_t font;
|
||||||
color_t color;
|
color_t color[2];
|
||||||
color_t bgcolor;
|
coord_t x, y;
|
||||||
bool_t rightalign;
|
coord_t cx, cy;
|
||||||
} gdispFillString_state_t;
|
} gdispFillString_state_t;
|
||||||
|
|
||||||
/* Callback to render characters. */
|
/* Callback to render characters. */
|
||||||
static uint8_t gdispFillString_callback(int16_t x, int16_t y,
|
static uint8_t gdispFillString_callback(int16_t x, int16_t y, mf_char character, void *state)
|
||||||
mf_char character, void *state)
|
|
||||||
{
|
{
|
||||||
gdispFillString_state_t *s = state;
|
gdispFillString_state_t *s = state;
|
||||||
uint8_t w;
|
uint8_t w;
|
||||||
int16_t right_edge;
|
|
||||||
w = mf_character_width(s->font, character);
|
|
||||||
right_edge = x + w + s->font->baseline_x;
|
|
||||||
|
|
||||||
if (!s->rightalign)
|
|
||||||
{
|
|
||||||
if (s->prev_x < x)
|
|
||||||
{
|
|
||||||
/* Fill any space between characters */
|
|
||||||
gdispFillArea(s->prev_x, s->y0, x - s->prev_x, s->font->height,
|
|
||||||
s->bgcolor);
|
|
||||||
}
|
|
||||||
else if (s->prev_x > x)
|
|
||||||
{
|
|
||||||
/* Uh, looks like there is some kerning going on. If we would
|
|
||||||
* just call gdispFillChar() here, it would overwrite part of
|
|
||||||
* the previous character. Instead, fill background separately.
|
|
||||||
*/
|
|
||||||
gdispFillArea(s->prev_x, s->y0, right_edge - s->prev_x,
|
|
||||||
s->font->height, s->bgcolor);
|
|
||||||
gdispDrawChar(x, y, character, s->font, s->color);
|
|
||||||
s->prev_x = right_edge;
|
|
||||||
return w;
|
|
||||||
}
|
|
||||||
|
|
||||||
s->prev_x = right_edge;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* When rendering right-aligned text, the characters are drawn
|
|
||||||
* from right to left. */
|
|
||||||
if (s->prev_x > right_edge)
|
|
||||||
{
|
|
||||||
/* Fill any space between characters */
|
|
||||||
gdispFillArea(right_edge, s->y0, s->prev_x - right_edge,
|
|
||||||
s->font->height, s->bgcolor);
|
|
||||||
}
|
|
||||||
else if (s->prev_x < right_edge)
|
|
||||||
{
|
|
||||||
gdispFillArea(x, s->y0, s->prev_x - x,
|
|
||||||
s->font->height, s->bgcolor);
|
|
||||||
gdispDrawChar(x, y, character, s->font, s->color);
|
|
||||||
s->prev_x = x;
|
|
||||||
return w;
|
|
||||||
}
|
|
||||||
|
|
||||||
s->prev_x = x;
|
|
||||||
}
|
|
||||||
|
|
||||||
gdispFillChar(x, y, character, s->font, s->color, s->bgcolor);
|
w = mf_character_width(s->font, character);
|
||||||
|
if (x >= s->x && x+w < s->x + s->cx && y >= s->y && y+s->font->height <= s->y + s->cy)
|
||||||
|
mf_render_character(s->font, x, y, character, text_fill_char_callback, s->color);
|
||||||
return w;
|
return w;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -725,104 +698,78 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) {
|
||||||
/* No mutex required as we only call high level functions which have their own mutex */
|
/* No mutex required as we only call high level functions which have their own mutex */
|
||||||
gdispFillString_state_t state;
|
gdispFillString_state_t state;
|
||||||
|
|
||||||
state.y0 = y;
|
|
||||||
state.prev_x = x;
|
|
||||||
state.font = font;
|
state.font = font;
|
||||||
state.color = color;
|
state.color[0] = color;
|
||||||
state.bgcolor = bgcolor;
|
state.color[1] = bgcolor;
|
||||||
state.rightalign = false;
|
state.x = x;
|
||||||
|
state.y = y;
|
||||||
|
state.cx = mf_get_string_width(font, str, 0, 0);
|
||||||
|
state.cy = font->height;
|
||||||
|
|
||||||
x += font->baseline_x;
|
gdispFillArea(x, y, state.cx, state.cy, bgcolor);
|
||||||
mf_render_aligned(font, x, y, MF_ALIGN_LEFT, str, 0,
|
mf_render_aligned(font, x+font->baseline_x, y, MF_ALIGN_LEFT, str, 0, gdispFillString_callback, &state);
|
||||||
gdispFillString_callback, &state);
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#if GDISP_NEED_TEXT
|
|
||||||
void gdispDrawStringBox(coord_t x, coord_t y, coord_t cx, coord_t cy, const char* str, font_t font, color_t color, justify_t justify) {
|
void gdispDrawStringBox(coord_t x, coord_t y, coord_t cx, coord_t cy, const char* str, font_t font, color_t color, justify_t justify) {
|
||||||
/* No mutex required as we only call high level functions which have their own mutex */
|
/* No mutex required as we only call high level functions which have their own mutex */
|
||||||
gdispDrawString_state_t state;
|
gdispDrawString_state_t state;
|
||||||
|
|
||||||
state.font = font;
|
state.font = font;
|
||||||
state.color = color;
|
state.color = color;
|
||||||
|
state.x = x;
|
||||||
|
state.y = y;
|
||||||
|
state.cx = cx;
|
||||||
|
state.cy = cy;
|
||||||
|
|
||||||
/* Select the anchor position */
|
/* Select the anchor position */
|
||||||
if (justify == justifyLeft)
|
switch(justify) {
|
||||||
x += font->baseline_x;
|
case justifyCenter:
|
||||||
else if (justify == justifyCenter)
|
|
||||||
x += (cx + 1) / 2;
|
x += (cx + 1) / 2;
|
||||||
else if (justify == justifyRight)
|
break;
|
||||||
|
case justifyRight:
|
||||||
x += cx;
|
x += cx;
|
||||||
|
break;
|
||||||
|
default: // justifyLeft
|
||||||
|
x += font->baseline_x;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
y += (cy+1 - font->height)/2;
|
||||||
|
|
||||||
mf_render_aligned(font, x, y, justify, str, 0,
|
mf_render_aligned(font, x, y, justify, str, 0, gdispDrawString_callback, &state);
|
||||||
gdispDrawString_callback, &state);
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#if GDISP_NEED_TEXT
|
|
||||||
void gdispFillStringBox(coord_t x, coord_t y, coord_t cx, coord_t cy, const char* str, font_t font, color_t color, color_t bgcolor, justify_t justify) {
|
void gdispFillStringBox(coord_t x, coord_t y, coord_t cx, coord_t cy, const char* str, font_t font, color_t color, color_t bgcolor, justify_t justify) {
|
||||||
/* No mutex required as we only call high level functions which have their own mutex */
|
/* No mutex required as we only call high level functions which have their own mutex */
|
||||||
gdispFillString_state_t state;
|
gdispFillString_state_t state;
|
||||||
int16_t min_x, max_x;
|
|
||||||
|
|
||||||
min_x = x;
|
|
||||||
max_x = x + cx;
|
|
||||||
|
|
||||||
state.y0 = y + (cy - font->height + 1) / 2;
|
|
||||||
state.prev_x = x;
|
|
||||||
state.font = font;
|
state.font = font;
|
||||||
state.color = color;
|
state.color[0] = color;
|
||||||
state.bgcolor = bgcolor;
|
state.color[1] = bgcolor;
|
||||||
state.rightalign = false;
|
state.x = x;
|
||||||
|
state.y = y;
|
||||||
/* Fill above the text */
|
state.cx = cx;
|
||||||
if (state.y0 > y)
|
state.cy = cy;
|
||||||
{
|
|
||||||
gdispFillArea(x, y, cx, state.y0 - y, bgcolor);
|
gdispFillArea(x, y, cx, cy, bgcolor);
|
||||||
}
|
|
||||||
|
|
||||||
/* Fill below the text */
|
|
||||||
if (state.y0 + font->height < y + cy)
|
|
||||||
{
|
|
||||||
gdispFillArea(x, state.y0 + font->height, cx,
|
|
||||||
(y + cy) - (state.y0 + font->height), bgcolor);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Select the anchor position */
|
/* Select the anchor position */
|
||||||
if (justify == justifyLeft)
|
switch(justify) {
|
||||||
{
|
case justifyCenter:
|
||||||
x += font->baseline_x;
|
|
||||||
}
|
|
||||||
else if (justify == justifyCenter)
|
|
||||||
{
|
|
||||||
x += (cx + 1) / 2;
|
x += (cx + 1) / 2;
|
||||||
}
|
break;
|
||||||
else if (justify == justifyRight)
|
case justifyRight:
|
||||||
{
|
|
||||||
state.rightalign = true;
|
|
||||||
state.prev_x = x + cx;
|
|
||||||
x += cx;
|
x += cx;
|
||||||
|
break;
|
||||||
|
default: // justifyLeft
|
||||||
|
x += font->baseline_x;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
y += (cy+1 - font->height)/2;
|
||||||
|
|
||||||
/* Render */
|
/* Render */
|
||||||
mf_render_aligned(font, x, state.y0, justify, str, 0,
|
mf_render_aligned(font, x, y, justify, str, 0, gdispFillString_callback, &state);
|
||||||
gdispFillString_callback, &state);
|
|
||||||
|
|
||||||
/* Fill any space left */
|
|
||||||
if (!state.rightalign && state.prev_x < max_x)
|
|
||||||
{
|
|
||||||
gdispFillArea(state.prev_x, state.y0, max_x - state.prev_x,
|
|
||||||
state.font->height, bgcolor);
|
|
||||||
}
|
|
||||||
else if (state.rightalign && state.prev_x > min_x)
|
|
||||||
{
|
|
||||||
gdispFillArea(min_x, state.y0, state.prev_x - min_x,
|
|
||||||
state.font->height, bgcolor);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#if GDISP_NEED_TEXT
|
|
||||||
coord_t gdispGetFontMetric(font_t font, fontmetric_t metric) {
|
coord_t gdispGetFontMetric(font_t font, fontmetric_t metric) {
|
||||||
/* No mutex required as we only read static data */
|
/* No mutex required as we only read static data */
|
||||||
switch(metric) {
|
switch(metric) {
|
||||||
|
@ -835,16 +782,12 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) {
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#if GDISP_NEED_TEXT
|
|
||||||
coord_t gdispGetCharWidth(char c, font_t font) {
|
coord_t gdispGetCharWidth(char c, font_t font) {
|
||||||
/* No mutex required as we only read static data */
|
/* No mutex required as we only read static data */
|
||||||
return mf_character_width(font, c);
|
return mf_character_width(font, c);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#if GDISP_NEED_TEXT
|
|
||||||
coord_t gdispGetStringWidth(const char* str, font_t font) {
|
coord_t gdispGetStringWidth(const char* str, font_t font) {
|
||||||
/* No mutex required as we only read static data */
|
/* No mutex required as we only read static data */
|
||||||
return mf_get_string_width(font, str, 0, 0);
|
return mf_get_string_width(font, str, 0, 0);
|
||||||
|
|
Loading…
Add table
Reference in a new issue