gint-with-thread/src/render/topti.c

92 lines
2.2 KiB
C

#include <gint/defs/types.h>
#include <gint/display.h>
#include "../render/render.h"
/* TODO: These parameters will eventually be specified by the font */
#define CHAR_SPACING 1
#define PROP_SPACING 5
/* dfont(): Set the default font for text rendering */
font_t const *dfont(font_t const * font)
{
font_t const *old_font = topti_font;
topti_font = font ? font : gint_default_font;
return old_font;
}
/* topti_glyph_index(): Obtain the glyph index of a Unicode code point */
int topti_glyph_index(font_t const *f, uint32_t code_point)
{
int glyph_start = 0;
for(int i = 0; i < f->block_count; i++)
{
int diff = code_point - f->blocks[i].start;
if(diff >= 0 && diff < f->blocks[i].length)
{
return glyph_start + diff;
}
glyph_start += f->blocks[i].length;
}
return -1;
}
/* topti_offset(): Use a font index to find the location of a glyph */
int topti_offset(font_t const *f, uint glyph)
{
/* Non-proportional fonts don't need an index */
if(!f->prop) return glyph * f->storage_size;
uint8_t const *width = f->glyph_width;
/* The index gives us the position of all glyphs whose IDs are
multiples of 8. Start with a close one and iterate from there. */
uint g = glyph & ~0x7;
int offset = f->glyph_index[g >> 3];
/* Traverse the width array (which is in bits) while converting to
longword size */
while(g < glyph) offset += (width[g++] * f->data_height + 31) >> 5;
return offset;
}
/* dsize(): Get the width and height of rendered text */
void dsize(const char *str, font_t const * f, int *w, int *h)
{
if(!f) f = topti_font;
if(h) *h = f->line_height;
if(!w) return;
/* Width for monospaced fonts is easy, unfortunately we still need to
compute the length of [str]. Critical applications might do the
product themselves to avoid this cost. */
if(!f->prop)
{
int length = 0;
while(*str++) length++;
*w = (f->width + CHAR_SPACING) * length - CHAR_SPACING;
return;
}
/* For proportional fonts, fetch the width of each individual glyphs */
int width = 0, c;
while((c = *str++))
{
if(c == ' ')
{
width += PROP_SPACING + CHAR_SPACING;
continue;
}
int glyph = topti_glyph_index(f, c);
if(glyph >= 0) width += f->glyph_width[glyph] + CHAR_SPACING;
}
*w = width - CHAR_SPACING;
}