text: Allow x-adjusted glyph rendering, for better kerning in caches
This commit is contained in:
parent
1349d1a2e0
commit
af69cd6369
@ -20,7 +20,7 @@ extern void tt_draw_glyph(gfx_context_t * ctx, struct TT_Font * font, int x_offs
|
||||
extern int tt_glyph_for_codepoint(struct TT_Font * font, unsigned int codepoint);
|
||||
extern int tt_xadvance_for_glyph(struct TT_Font * font, unsigned int ind);
|
||||
extern float tt_glyph_width(struct TT_Font * font, unsigned int glyph);
|
||||
extern sprite_t * tt_bake_glyph(struct TT_Font * font, unsigned int glyph, uint32_t color, int *_x, int *_y);
|
||||
extern sprite_t * tt_bake_glyph(struct TT_Font * font, unsigned int glyph, uint32_t color, int *_x, int *_y, float xadjust);
|
||||
|
||||
/* Convenience functions for dealing with whole strings */
|
||||
extern int tt_string_width(struct TT_Font * font, const char * s);
|
||||
|
@ -6,6 +6,7 @@
|
||||
* of the NCSA / University of Illinois License - see LICENSE.md
|
||||
* Copyright (C) 2021 K. Lange
|
||||
*/
|
||||
#include <math.h>
|
||||
#include <toaru/markup.h>
|
||||
#include <toaru/list.h>
|
||||
#include <toaru/graphics.h>
|
||||
@ -131,50 +132,55 @@ static int sizeForState(struct MarkupState * state) {
|
||||
|
||||
struct GlyphCacheEntry {
|
||||
struct TT_Font * font;
|
||||
sprite_t * sprite;
|
||||
sprite_t * sprites[3];
|
||||
int xs[3];
|
||||
uint32_t size;
|
||||
uint32_t glyph;
|
||||
uint32_t color;
|
||||
int x;
|
||||
int y;
|
||||
};
|
||||
|
||||
static struct GlyphCacheEntry glyph_cache[1024];
|
||||
|
||||
static void draw_cached_glyph(gfx_context_t * ctx, struct TT_Font * _font, uint32_t size, int x, int y, uint32_t glyph, uint32_t fg) {
|
||||
static void draw_cached_glyph(gfx_context_t * ctx, struct TT_Font * _font, uint32_t size, int x, int y, uint32_t glyph, uint32_t fg, float xadj) {
|
||||
unsigned int hash = (((uintptr_t)_font >> 8) ^ (glyph * size)) & 1023;
|
||||
|
||||
struct GlyphCacheEntry * entry = &glyph_cache[hash];
|
||||
|
||||
if (entry->font != _font || entry->size != size || entry->glyph != glyph) {
|
||||
if (entry->sprite) sprite_free(entry->sprite);
|
||||
if (entry->sprites[0]) sprite_free(entry->sprites[0]);
|
||||
if (entry->sprites[1]) sprite_free(entry->sprites[1]);
|
||||
if (entry->sprites[2]) sprite_free(entry->sprites[2]);
|
||||
tt_set_size(_font, size);
|
||||
|
||||
entry->font = _font;
|
||||
entry->size = size;
|
||||
entry->glyph = glyph;
|
||||
entry->color = _ALP(fg) == 255 ? fg : rgb(0,0,0);
|
||||
entry->sprite = tt_bake_glyph(entry->font, entry->glyph, entry->color, &entry->x, &entry->y);
|
||||
entry->sprites[0] = tt_bake_glyph(entry->font, entry->glyph, entry->color, &entry->xs[0], &entry->y, 0.0);
|
||||
entry->sprites[1] = tt_bake_glyph(entry->font, entry->glyph, entry->color, &entry->xs[1], &entry->y, 0.333);
|
||||
entry->sprites[2] = tt_bake_glyph(entry->font, entry->glyph, entry->color, &entry->xs[2], &entry->y, 0.666);
|
||||
}
|
||||
|
||||
if (entry->sprite) {
|
||||
if (entry->sprites[0]) {
|
||||
int sprite = xadj < 0.166 ? 0 : xadj < 0.5 ? 1 : 2;
|
||||
if (entry->color != fg) {
|
||||
draw_sprite_alpha_paint(ctx, entry->sprite, x + entry->x, y + entry->y, 1.0, fg);
|
||||
draw_sprite_alpha_paint(ctx, entry->sprites[sprite], x + entry->xs[sprite], y + entry->y, 1.0, fg);
|
||||
} else {
|
||||
draw_sprite(ctx, entry->sprite, x + entry->x, y + entry->y);
|
||||
draw_sprite(ctx, entry->sprites[sprite], x + entry->xs[sprite], y + entry->y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int string_draw_internal(gfx_context_t * ctx, struct TT_Font * font, int font_size, int x, int y, char * data, uint32_t color) {
|
||||
int x_offset = x;
|
||||
float x_offset = x;
|
||||
uint32_t cp = 0;
|
||||
uint32_t istate = 0;
|
||||
|
||||
for (const unsigned char * c = (const unsigned char*)data; *c; ++c) {
|
||||
if (!decode(&istate, &cp, *c)) {
|
||||
unsigned int glyph = tt_glyph_for_codepoint(font, cp);
|
||||
draw_cached_glyph(ctx, font, font_size, x_offset, y, glyph, color);
|
||||
draw_cached_glyph(ctx, font, font_size, (int)floor(x_offset), y, glyph, color, x_offset-floor(x_offset));
|
||||
x_offset += tt_glyph_width(font, glyph);
|
||||
}
|
||||
}
|
||||
@ -196,7 +202,7 @@ static int parser_dryrun(struct markup_state * self, void * user, char * data) {
|
||||
struct MarkupState * state = (struct MarkupState*)user;
|
||||
struct TT_Font * font = fontForState(state);
|
||||
tt_set_size(font, sizeForState(state));
|
||||
state->cursor_x += tt_string_width_int(font, data);
|
||||
state->cursor_x += tt_string_width(font, data);
|
||||
if (state->cursor_x > state->max_cursor_x) state->max_cursor_x = state->cursor_x;
|
||||
return 0;
|
||||
}
|
||||
|
10
lib/text.c
10
lib/text.c
@ -682,9 +682,9 @@ static struct TT_Contour * tt_draw_glyph_into(struct TT_Contour * contour, struc
|
||||
return contour;
|
||||
}
|
||||
|
||||
sprite_t * tt_bake_glyph(struct TT_Font * font, unsigned int glyph, uint32_t color, int *_x, int *_y) {
|
||||
sprite_t * tt_bake_glyph(struct TT_Font * font, unsigned int glyph, uint32_t color, int *_x, int *_y, float xadjust) {
|
||||
struct TT_Contour * contour = tt_contour_start(0, 0);
|
||||
contour = tt_draw_glyph_into(contour,font,100,100,glyph);
|
||||
contour = tt_draw_glyph_into(contour,font,100+xadjust,100,glyph);
|
||||
if (!contour->edgeCount) {
|
||||
*_x = 0;
|
||||
*_y = 0;
|
||||
@ -694,11 +694,11 @@ sprite_t * tt_bake_glyph(struct TT_Font * font, unsigned int glyph, uint32_t col
|
||||
|
||||
/* Calculate bounds to render a sprite */
|
||||
struct TT_Shape * shape = tt_contour_finish(contour);
|
||||
int width = shape->lastX - shape->startX + 2;
|
||||
int width = shape->lastX - shape->startX + 3;
|
||||
int height = shape->lastY - shape->startY + 2;
|
||||
|
||||
int off_x = shape->startX - 2; shape->startX -= off_x; shape->lastX -= off_x;
|
||||
int off_y = shape->startY - 2; shape->startY -= off_y; shape->lastY -= off_y;
|
||||
int off_x = shape->startX - 1; shape->startX -= off_x; shape->lastX -= off_x;
|
||||
int off_y = shape->startY - 1; shape->startY -= off_y; shape->lastY -= off_y;
|
||||
|
||||
/* Adjust the entire shape */
|
||||
for (size_t i = 0; i < shape->edgeCount; ++i) {
|
||||
|
Loading…
Reference in New Issue
Block a user