1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2026-01-18 04:23:20 +01:00

Port TTF_RenderUTF8_Shaded and TTF_drawLine_Shaded from SDL_ttf.

This commit is contained in:
Aaron van Geffen
2017-09-22 12:41:46 +02:00
committed by Marijn van der Werf
parent 07cdc79bd7
commit 3357d32ec4
2 changed files with 162 additions and 0 deletions

View File

@@ -54,6 +54,7 @@ TTF_Font * TTF_OpenFont(const char *file, int ptsize);
int TTF_GlyphIsProvided(const TTF_Font *font, codepoint_t ch);
int TTF_SizeUTF8(TTF_Font *font, const char *text, int *w, int *h);
TTFSurface * TTF_RenderUTF8_Solid(TTF_Font *font, const char *text, uint32 colour);
TTFSurface * TTF_RenderUTF8_Shaded(TTF_Font *font, const char *text, uint32 fg, uint32 bg);
void TTF_CloseFont(TTF_Font *font);
void TTF_Quit(void);

View File

@@ -262,6 +262,27 @@ static void TTF_drawLine_Solid(const TTF_Font *font, const TTFSurface *textbuf,
}
}
/* Draw a shaded line of underline_height (+ optional outline)
at the given row. The row value must take the
outline into account.
*/
static void TTF_drawLine_Shaded(const TTF_Font *font, const TTFSurface *textbuf, const int row)
{
int line;
uint8 *dst_check = (uint8*) textbuf->pixels + textbuf->pitch * textbuf->h;
uint8 *dst;
int height;
TTF_initLineMectrics(font, textbuf, row, &dst, &height);
/* Draw line */
for (line=height; line>0 && dst < dst_check; --line)
{
memset(dst, NUM_GRAYS - 1, textbuf->w);
dst += textbuf->pitch;
}
}
static void TTF_SetFTError(const char *msg, FT_Error error)
{
#ifdef USE_FREETYPE_ERRORS
@@ -1261,6 +1282,146 @@ TTFSurface *TTF_RenderUTF8_Solid(TTF_Font *font,
return textbuf;
}
TTFSurface *TTF_RenderUTF8_Shaded(TTF_Font *font,
const char *text, uint32 fg, uint32 bg)
{
bool first;
int xstart;
int width;
int height;
TTFSurface* textbuf;
uint8* src;
uint8* dst;
uint8* dst_check;
int row, col;
FT_Bitmap* current;
c_glyph *glyph;
FT_Error error;
FT_Long use_kerning;
FT_UInt prev_index = 0;
size_t textlen;
TTF_CHECKPOINTER(text, NULL);
/* Get the dimensions of the text surface */
if ((TTF_SizeUTF8(font, text, &width, &height) < 0 ) || !width)
{
TTF_SetError("Text has zero width");
return NULL;
}
/* Create the target surface */
textbuf = calloc(1, sizeof(TTFSurface));
if (textbuf == NULL)
{
return NULL;
}
textbuf->w = width;
textbuf->h = height;
textbuf->pitch = width;
textbuf->pixels = calloc(1, width * height);
/* Adding bound checking to avoid all kinds of memory corruption errors
that may occur. */
dst_check = (uint8*) textbuf->pixels + textbuf->pitch * textbuf->h;
/* check kerning */
use_kerning = FT_HAS_KERNING(font->face) && font->kerning;
/* Load and render each character */
textlen = strlen(text);
first = true;
xstart = 0;
while (textlen > 0)
{
uint16 c = UTF8_getch(&text, &textlen);
if (c == UNICODE_BOM_NATIVE || c == UNICODE_BOM_SWAPPED)
{
continue;
}
error = Find_Glyph(font, c, CACHED_METRICS|CACHED_PIXMAP);
if (error)
{
TTF_SetFTError("Couldn't find glyph", error);
ttf_free_surface(textbuf);
return NULL;
}
glyph = font->current;
/* Ensure the width of the pixmap is correct. On some cases,
* freetype may report a larger pixmap than possible.*/
width = glyph->pixmap.width;
if (font->outline <= 0 && width > glyph->maxx - glyph->minx)
{
width = glyph->maxx - glyph->minx;
}
/* do kerning, if possible AC-Patch */
if (use_kerning && prev_index && glyph->index)
{
FT_Vector delta;
FT_Get_Kerning(font->face, prev_index, glyph->index, ft_kerning_default, &delta);
xstart += delta.x >> 6;
}
/* Compensate for the wrap around with negative minx's */
if (first && (glyph->minx < 0))
{
xstart -= glyph->minx;
}
first = false;
current = &glyph->pixmap;
for (row = 0; row < current->rows; ++row)
{
/* Make sure we don't go either over, or under the
* limit */
if (row + glyph->yoffset < 0)
{
continue;
}
if (row + glyph->yoffset >= textbuf->h)
{
continue;
}
dst = (uint8*) textbuf->pixels +
(row+glyph->yoffset) * textbuf->pitch +
xstart + glyph->minx;
src = current->buffer + row * current->pitch;
for (col=width; col>0 && dst < dst_check; --col)
{
*dst++ |= *src++;
}
}
xstart += glyph->advance;
if (TTF_HANDLE_STYLE_BOLD(font))
{
xstart += font->glyph_overhang;
}
prev_index = glyph->index;
}
/* Handle the underline style */
if (TTF_HANDLE_STYLE_UNDERLINE(font))
{
row = TTF_underline_top_row(font);
TTF_drawLine_Shaded(font, textbuf, row);
}
/* Handle the strikethrough style */
if (TTF_HANDLE_STYLE_STRIKETHROUGH(font))
{
row = TTF_strikethrough_top_row(font);
TTF_drawLine_Shaded(font, textbuf, row);
}
return textbuf;
}
static bool CharacterIsDelimiter(char c, const char *delimiters)
{
while (*delimiters) {