Fix font baseline_x problem, decrease word-wrap stack usage, add text justification options
This commit is contained in:
parent
9500ed2bcc
commit
d8c9ca184f
@ -23,6 +23,13 @@ FEATURE: Significantly improved the FreeRTOS port
|
|||||||
FEATURE: Added support for operating system initialisation in FreeRTOS
|
FEATURE: Added support for operating system initialisation in FreeRTOS
|
||||||
FEATURE: Added GFX_OS_CALL_UGFXMAIN configuration option to allow uGFXMain() to be automatically called
|
FEATURE: Added GFX_OS_CALL_UGFXMAIN configuration option to allow uGFXMain() to be automatically called
|
||||||
FEATURE: Added GFX_OS_UGFXMAIN_STACKSIZE configuration option to control uGFXMain() stack size
|
FEATURE: Added GFX_OS_UGFXMAIN_STACKSIZE configuration option to control uGFXMain() stack size
|
||||||
|
FIX: Fixed where a font with more than 255 glyphs could fail to display some glyphs
|
||||||
|
FIX: Fixed where a font with a large x baseline could be incorrectly clipped or word-wrapped
|
||||||
|
IMPROVE: Significantly decrease the stack usage required for word-wrapping
|
||||||
|
FEATURE: Added justifyTop, justifyMiddle & justifyBottom text justification to GDISP
|
||||||
|
FEATURE: Added justifyWordWrap, justifyNoWordWrap text justification to GDISP (requires GDISP_NEED_TEXT_WORDWRAP)
|
||||||
|
FEATURE: Added justifyPad, justifyNoPad text justification to GDISP
|
||||||
|
FEATURE: Added GDISP_NEED_TEXT_BOXPADLR and GDISP_NEED_TEXT_BOXPADTB configuration options
|
||||||
|
|
||||||
|
|
||||||
*** Release 2.7 ***
|
*** Release 2.7 ***
|
||||||
|
@ -84,6 +84,8 @@
|
|||||||
//#define GDISP_NEED_STREAMING FALSE
|
//#define GDISP_NEED_STREAMING FALSE
|
||||||
//#define GDISP_NEED_TEXT FALSE
|
//#define GDISP_NEED_TEXT FALSE
|
||||||
// #define GDISP_NEED_TEXT_WORDWRAP FALSE
|
// #define GDISP_NEED_TEXT_WORDWRAP FALSE
|
||||||
|
// #define GDISP_NEED_TEXT_BOXPADLR 1
|
||||||
|
// #define GDISP_NEED_TEXT_BOXPADTB 1
|
||||||
// #define GDISP_NEED_ANTIALIAS FALSE
|
// #define GDISP_NEED_ANTIALIAS FALSE
|
||||||
// #define GDISP_NEED_UTF8 FALSE
|
// #define GDISP_NEED_UTF8 FALSE
|
||||||
// #define GDISP_NEED_TEXT_KERNING FALSE
|
// #define GDISP_NEED_TEXT_KERNING FALSE
|
||||||
|
@ -20,17 +20,6 @@
|
|||||||
#define GDISP_STARTUP_LOGO_TIMEOUT 0
|
#define GDISP_STARTUP_LOGO_TIMEOUT 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// For internal use only.
|
|
||||||
#if GDISP_NEED_TEXT_WORDWRAP
|
|
||||||
typedef struct wrapParameters {
|
|
||||||
GDisplay* g;
|
|
||||||
coord_t x;
|
|
||||||
coord_t y;
|
|
||||||
font_t font;
|
|
||||||
justify_t justify;
|
|
||||||
} wrapParameters_t;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
/* Driver local variables. */
|
/* Driver local variables. */
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
@ -3340,29 +3329,24 @@ void gdispGDrawBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, co
|
|||||||
/* Callback to render string boxes with word wrap. */
|
/* Callback to render string boxes with word wrap. */
|
||||||
#if GDISP_NEED_TEXT_WORDWRAP
|
#if GDISP_NEED_TEXT_WORDWRAP
|
||||||
static bool mf_countline_callback(mf_str line, uint16_t count, void *state) {
|
static bool mf_countline_callback(mf_str line, uint16_t count, void *state) {
|
||||||
uint16_t *linecount;
|
|
||||||
(void) line;
|
(void) line;
|
||||||
(void) count;
|
(void) count;
|
||||||
|
|
||||||
linecount = (uint16_t*)state;
|
((coord_t*)state)[0]++;
|
||||||
(*linecount)++;
|
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
static bool mf_drawline_callback(mf_str line, uint16_t count, void *state) {
|
static bool mf_drawline_callback(mf_str line, uint16_t count, void *state) {
|
||||||
wrapParameters_t* wrapParameters = (wrapParameters_t*)state;
|
#define GD ((GDisplay *)state)
|
||||||
|
mf_render_aligned(GD->t.font, GD->t.wrapx, GD->t.wrapy, GD->t.lrj, line, count, drawcharglyph, state);
|
||||||
mf_render_aligned(wrapParameters->font, wrapParameters->x, wrapParameters->y, wrapParameters->justify, line, count, drawcharglyph, wrapParameters->g);
|
GD->t.wrapy += GD->t.font->line_height;
|
||||||
|
#undef GD
|
||||||
wrapParameters->y += wrapParameters->font->line_height;
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
static bool mf_fillline_callback(mf_str line, uint16_t count, void *state) {
|
static bool mf_fillline_callback(mf_str line, uint16_t count, void *state) {
|
||||||
wrapParameters_t* wrapParameters = (wrapParameters_t*)state;
|
#define GD ((GDisplay *)state)
|
||||||
|
mf_render_aligned(GD->t.font, GD->t.wrapx, GD->t.wrapy, GD->t.lrj, line, count, fillcharglyph, state);
|
||||||
mf_render_aligned(wrapParameters->font, wrapParameters->x, wrapParameters->y, wrapParameters->justify, line, count, fillcharglyph, wrapParameters->g);
|
GD->t.wrapy += GD->t.font->line_height;
|
||||||
|
#undef GD
|
||||||
wrapParameters->y += wrapParameters->font->line_height;
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -3411,7 +3395,7 @@ void gdispGDrawBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, co
|
|||||||
g->t.font = font;
|
g->t.font = font;
|
||||||
g->t.clipx0 = x;
|
g->t.clipx0 = x;
|
||||||
g->t.clipy0 = y;
|
g->t.clipy0 = y;
|
||||||
g->t.clipx1 = x + mf_get_string_width(font, str, 0, 0) + font->baseline_x;
|
g->t.clipx1 = 32768; //x + mf_get_string_width(font, str, 0, 0) + font->baseline_x;
|
||||||
g->t.clipy1 = y + font->height;
|
g->t.clipy1 = y + font->height;
|
||||||
g->t.color = color;
|
g->t.color = color;
|
||||||
|
|
||||||
@ -3444,24 +3428,55 @@ void gdispGDrawBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, co
|
|||||||
}
|
}
|
||||||
|
|
||||||
void gdispGDrawStringBox(GDisplay *g, 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 gdispGDrawStringBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, const char* str, font_t font, color_t color, justify_t justify) {
|
||||||
#if GDISP_NEED_TEXT_WORDWRAP
|
coord_t totalHeight;
|
||||||
wrapParameters_t wrapParameters;
|
|
||||||
uint16_t nbrLines;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!font)
|
if (!font)
|
||||||
return;
|
return;
|
||||||
MUTEX_ENTER(g);
|
MUTEX_ENTER(g);
|
||||||
|
|
||||||
g->t.font = font;
|
// Apply padding
|
||||||
|
#if GDISP_NEED_TEXT_BOXPADLR != 0 || GDISP_NEED_TEXT_BOXPADTB != 0
|
||||||
|
if (!(justify & justifyNoPad)) {
|
||||||
|
#if GDISP_NEED_TEXT_BOXPADLR != 0
|
||||||
|
x += GDISP_NEED_TEXT_BOXPADLR;
|
||||||
|
cx -= 2*GDISP_NEED_TEXT_BOXPADLR;
|
||||||
|
#endif
|
||||||
|
#if GDISP_NEED_TEXT_BOXPADTB != 0
|
||||||
|
y += GDISP_NEED_TEXT_BOXPADTB;
|
||||||
|
cy -= 2*GDISP_NEED_TEXT_BOXPADTB;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Save the clipping area
|
||||||
g->t.clipx0 = x;
|
g->t.clipx0 = x;
|
||||||
g->t.clipy0 = y;
|
g->t.clipy0 = y;
|
||||||
g->t.clipx1 = x+cx;
|
g->t.clipx1 = x+cx;
|
||||||
g->t.clipy1 = y+cy;
|
g->t.clipy1 = y+cy;
|
||||||
g->t.color = color;
|
|
||||||
|
|
||||||
/* Select the anchor position */
|
// Calculate the total text height
|
||||||
switch(justify) {
|
#if GDISP_NEED_TEXT_WORDWRAP
|
||||||
|
if (!(justify & justifyNoWordWrap)) {
|
||||||
|
// Count the number of lines
|
||||||
|
totalHeight = 0;
|
||||||
|
mf_wordwrap(font, cx, str, mf_countline_callback, &totalHeight);
|
||||||
|
totalHeight *= font->height;
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
totalHeight = font->height;
|
||||||
|
|
||||||
|
// Select the anchor position
|
||||||
|
switch((justify & JUSTIFYMASK_TOPBOTTOM)) {
|
||||||
|
case justifyTop:
|
||||||
|
break;
|
||||||
|
case justifyBottom:
|
||||||
|
y += cy - totalHeight;
|
||||||
|
break;
|
||||||
|
default: // justifyMiddle
|
||||||
|
y += (cy+1 - totalHeight)/2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
switch((justify & JUSTIFYMASK_LEFTRIGHT)) {
|
||||||
case justifyCenter:
|
case justifyCenter:
|
||||||
x += (cx + 1) / 2;
|
x += (cx + 1) / 2;
|
||||||
break;
|
break;
|
||||||
@ -3469,60 +3484,88 @@ void gdispGDrawBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, co
|
|||||||
x += cx;
|
x += cx;
|
||||||
break;
|
break;
|
||||||
default: // justifyLeft
|
default: // justifyLeft
|
||||||
x += font->baseline_x;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Render */
|
/* Render */
|
||||||
|
g->t.font = font;
|
||||||
|
g->t.color = color;
|
||||||
#if GDISP_NEED_TEXT_WORDWRAP
|
#if GDISP_NEED_TEXT_WORDWRAP
|
||||||
wrapParameters.x = x;
|
if (!(justify & justifyNoWordWrap)) {
|
||||||
wrapParameters.y = y;
|
g->t.lrj = (justify & JUSTIFYMASK_LEFTRIGHT);
|
||||||
wrapParameters.font = font;
|
g->t.wrapx = x;
|
||||||
wrapParameters.justify = justify;
|
g->t.wrapy = y;
|
||||||
wrapParameters.g = g;
|
|
||||||
|
mf_wordwrap(font, cx, str, mf_drawline_callback, g);
|
||||||
// Count the number of lines
|
} else
|
||||||
nbrLines = 0;
|
|
||||||
mf_wordwrap(font, cx, str, mf_countline_callback, &nbrLines);
|
|
||||||
wrapParameters.y += (cy+1 - nbrLines*font->height)/2;
|
|
||||||
|
|
||||||
mf_wordwrap(font, cx, str, mf_drawline_callback, &wrapParameters);
|
|
||||||
#else
|
|
||||||
y += (cy+1 - font->height)/2;
|
|
||||||
mf_render_aligned(font, x, y, justify, str, 0, drawcharglyph, g);
|
|
||||||
#endif
|
#endif
|
||||||
|
mf_render_aligned(font, x, y, (justify & JUSTIFYMASK_LEFTRIGHT), str, 0, drawcharglyph, g);
|
||||||
|
|
||||||
autoflush(g);
|
autoflush(g);
|
||||||
MUTEX_EXIT(g);
|
MUTEX_EXIT(g);
|
||||||
}
|
}
|
||||||
|
|
||||||
void gdispGFillStringBox(GDisplay *g, 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 gdispGFillStringBox(GDisplay *g, 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) {
|
||||||
#if GDISP_NEED_TEXT_WORDWRAP
|
coord_t totalHeight;
|
||||||
wrapParameters_t wrapParameters;
|
|
||||||
uint16_t nbrLines;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!font)
|
if (!font)
|
||||||
return;
|
return;
|
||||||
MUTEX_ENTER(g);
|
MUTEX_ENTER(g);
|
||||||
|
|
||||||
|
g->p.x = x;
|
||||||
|
g->p.y = y;
|
||||||
g->p.cx = cx;
|
g->p.cx = cx;
|
||||||
g->p.cy = cy;
|
g->p.cy = cy;
|
||||||
g->t.font = font;
|
|
||||||
g->t.clipx0 = g->p.x = x;
|
|
||||||
g->t.clipy0 = g->p.y = y;
|
|
||||||
g->t.clipx1 = x+cx;
|
|
||||||
g->t.clipy1 = y+cy;
|
|
||||||
g->t.color = color;
|
|
||||||
g->t.bgcolor = g->p.color = bgcolor;
|
|
||||||
|
|
||||||
TEST_CLIP_AREA(g) {
|
TEST_CLIP_AREA(g) {
|
||||||
|
|
||||||
// background fill
|
// background fill
|
||||||
|
g->p.color = bgcolor;
|
||||||
fillarea(g);
|
fillarea(g);
|
||||||
|
|
||||||
/* Select the anchor position */
|
// Apply padding
|
||||||
switch(justify) {
|
#if GDISP_NEED_TEXT_BOXPADLR != 0 || GDISP_NEED_TEXT_BOXPADTB != 0
|
||||||
|
if (!(justify & justifyNoPad)) {
|
||||||
|
#if GDISP_NEED_TEXT_BOXPADLR != 0
|
||||||
|
x += GDISP_NEED_TEXT_BOXPADLR;
|
||||||
|
cx -= 2*GDISP_NEED_TEXT_BOXPADLR;
|
||||||
|
#endif
|
||||||
|
#if GDISP_NEED_TEXT_BOXPADTB != 0
|
||||||
|
y += GDISP_NEED_TEXT_BOXPADTB;
|
||||||
|
cy -= 2*GDISP_NEED_TEXT_BOXPADTB;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Save the clipping area
|
||||||
|
g->t.clipx0 = x;
|
||||||
|
g->t.clipy0 = y;
|
||||||
|
g->t.clipx1 = x+cx;
|
||||||
|
g->t.clipy1 = y+cy;
|
||||||
|
|
||||||
|
// Calculate the total text height
|
||||||
|
#if GDISP_NEED_TEXT_WORDWRAP
|
||||||
|
if (!(justify & justifyNoWordWrap)) {
|
||||||
|
// Count the number of lines
|
||||||
|
totalHeight = 0;
|
||||||
|
mf_wordwrap(font, cx, str, mf_countline_callback, &totalHeight);
|
||||||
|
totalHeight *= font->height;
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
totalHeight = font->height;
|
||||||
|
|
||||||
|
// Select the anchor position
|
||||||
|
switch((justify & JUSTIFYMASK_TOPBOTTOM)) {
|
||||||
|
case justifyTop:
|
||||||
|
break;
|
||||||
|
case justifyBottom:
|
||||||
|
y += cy - totalHeight;
|
||||||
|
break;
|
||||||
|
default: // justifyMiddle
|
||||||
|
y += (cy+1 - totalHeight)/2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
switch((justify & JUSTIFYMASK_LEFTRIGHT)) {
|
||||||
case justifyCenter:
|
case justifyCenter:
|
||||||
x += (cx + 1) / 2;
|
x += (cx + 1) / 2;
|
||||||
break;
|
break;
|
||||||
@ -3530,29 +3573,23 @@ void gdispGDrawBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, co
|
|||||||
x += cx;
|
x += cx;
|
||||||
break;
|
break;
|
||||||
default: // justifyLeft
|
default: // justifyLeft
|
||||||
x += font->baseline_x;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Render */
|
/* Render */
|
||||||
|
g->t.font = font;
|
||||||
|
g->t.color = color;
|
||||||
|
g->t.bgcolor = bgcolor;
|
||||||
#if GDISP_NEED_TEXT_WORDWRAP
|
#if GDISP_NEED_TEXT_WORDWRAP
|
||||||
wrapParameters.x = x;
|
if (!(justify & justifyNoWordWrap)) {
|
||||||
wrapParameters.y = y;
|
g->t.lrj = (justify & JUSTIFYMASK_LEFTRIGHT);
|
||||||
wrapParameters.font = font;
|
g->t.wrapx = x;
|
||||||
wrapParameters.justify = justify;
|
g->t.wrapy = y;
|
||||||
wrapParameters.g = g;
|
|
||||||
|
mf_wordwrap(font, cx, str, mf_fillline_callback, g);
|
||||||
|
} else
|
||||||
// Count the number of lines
|
|
||||||
nbrLines = 0;
|
|
||||||
mf_wordwrap(font, cx, str, mf_countline_callback, &nbrLines);
|
|
||||||
wrapParameters.y += (cy+1 - nbrLines*font->height)/2;
|
|
||||||
|
|
||||||
mf_wordwrap(font, cx, str, mf_fillline_callback, &wrapParameters);
|
|
||||||
#else
|
|
||||||
y += (cy+1 - font->height)/2;
|
|
||||||
mf_render_aligned(font, x, y, justify, str, 0, fillcharglyph, g);
|
|
||||||
#endif
|
#endif
|
||||||
|
mf_render_aligned(font, x, y, (justify & JUSTIFYMASK_LEFTRIGHT), str, 0, fillcharglyph, g);
|
||||||
}
|
}
|
||||||
|
|
||||||
autoflush(g);
|
autoflush(g);
|
||||||
|
@ -58,10 +58,19 @@ typedef struct point {
|
|||||||
* @brief Type for the text justification.
|
* @brief Type for the text justification.
|
||||||
*/
|
*/
|
||||||
typedef enum justify {
|
typedef enum justify {
|
||||||
justifyLeft = 0, /**< Justify Left */
|
justifyLeft = 0x00, /**< Justify Left (the default) */
|
||||||
justifyCenter = 1, /**< Justify Center */
|
justifyCenter = 0x01, /**< Justify Center */
|
||||||
justifyRight = 2 /**< Justify Right */
|
justifyRight = 0x02, /**< Justify Right */
|
||||||
|
justifyTop = 0x10, /**< Justify Top */
|
||||||
|
justifyMiddle = 0x00, /**< Justify Middle (the default) */
|
||||||
|
justifyBottom = 0x20, /**< Justify Bottom */
|
||||||
|
justifyWordWrap = 0x00, /**< Word wrap (the default if GDISP_NEED_TEXT_WORDWRAP is on) */
|
||||||
|
justifyNoWordWrap = 0x40, /**< No word wrap */
|
||||||
|
justifyPad = 0x00, /**< Pad the text box (the default) */
|
||||||
|
justifyNoPad = 0x04 /**< No padding the text box */
|
||||||
} justify_t;
|
} justify_t;
|
||||||
|
#define JUSTIFYMASK_LEFTRIGHT (justifyLeft|justifyCenter|justifyRight)
|
||||||
|
#define JUSTIFYMASK_TOPBOTTOM (justifyTop|justifyMiddle|justifyBottom)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @enum fontmetric
|
* @enum fontmetric
|
||||||
|
@ -367,6 +367,10 @@ struct GDisplay {
|
|||||||
color_t bgcolor;
|
color_t bgcolor;
|
||||||
coord_t clipx0, clipy0;
|
coord_t clipx0, clipy0;
|
||||||
coord_t clipx1, clipy1;
|
coord_t clipx1, clipy1;
|
||||||
|
#if GDISP_NEED_TEXT_WORDWRAP
|
||||||
|
coord_t wrapx, wrapy;
|
||||||
|
justify_t lrj;
|
||||||
|
#endif
|
||||||
} t;
|
} t;
|
||||||
#endif
|
#endif
|
||||||
#if GDISP_LINEBUF_SIZE != 0 && ((GDISP_NEED_SCROLL && !GDISP_HARDWARE_SCROLL) || (!GDISP_HARDWARE_STREAM_WRITE && GDISP_HARDWARE_BITFILLS))
|
#if GDISP_LINEBUF_SIZE != 0 && ((GDISP_NEED_SCROLL && !GDISP_HARDWARE_SCROLL) || (!GDISP_HARDWARE_STREAM_WRITE && GDISP_HARDWARE_BITFILLS))
|
||||||
|
@ -574,6 +574,24 @@
|
|||||||
#ifndef GDISP_NEED_TEXT_WORDWRAP
|
#ifndef GDISP_NEED_TEXT_WORDWRAP
|
||||||
#define GDISP_NEED_TEXT_WORDWRAP FALSE
|
#define GDISP_NEED_TEXT_WORDWRAP FALSE
|
||||||
#endif
|
#endif
|
||||||
|
/**
|
||||||
|
* @brief Adding pixels to the left and right side of the box to pad text.
|
||||||
|
* @details Only has an effect with @p gdispGDrawStringBox() and @p gdispGFillStringBox()
|
||||||
|
* @note Can be turned off by using justifyNoPad
|
||||||
|
* @details Defaults to 1
|
||||||
|
*/
|
||||||
|
#ifndef GDISP_NEED_TEXT_BOXPADLR
|
||||||
|
#define GDISP_NEED_TEXT_BOXPADLR 1
|
||||||
|
#endif
|
||||||
|
/**
|
||||||
|
* @brief Adding pixels to the top and bottom side of the box to pad text.
|
||||||
|
* @details Only has an effect with @p gdispGDrawStringBox() and @p gdispGFillStringBox()
|
||||||
|
* @note Can be turned off by using justifyNoPad
|
||||||
|
* @details Defaults to 1
|
||||||
|
*/
|
||||||
|
#ifndef GDISP_NEED_TEXT_BOXPADTB
|
||||||
|
#define GDISP_NEED_TEXT_BOXPADTB 1
|
||||||
|
#endif
|
||||||
/**
|
/**
|
||||||
* @brief Enable UTF-8 support for text rendering.
|
* @brief Enable UTF-8 support for text rendering.
|
||||||
* @details Defaults to FALSE
|
* @details Defaults to FALSE
|
||||||
|
Loading…
Reference in New Issue
Block a user