#include "duet.h" extern font_t font_duet; /* topti functions exposed to each implementation */ int topti_glyph_index(font_t const *f, uint32_t code_point); int topti_offset(font_t const *f, uint glyph); uint32_t topti_utf8_next(uint8_t const **str_pointer); /* topti_glyph(): Render a glyph on the VRAM Prints a glyph naively using word accesses, because for most fonts with a small size (including gint's 8x9 font) this will be more efficient than the complex logic for longword accesses. This function assumes that at least one of [fg] and [bg] is not transparent. @x0 @y0 Target position on VRAM @data Glyph data @width Subglyph width @height Subglyph height @fg @bg Foreground and background colors */ static void topti_glyph(int x0, int y0, uint32_t const * data, int width, int height, int fg, int bg) { /* A C version of what is usually done in assembler */ for(int y = 0; y < height; y++) { for(int x = 0; x < width; x++) { int bit_number = y * width + x; int bit = (data[bit_number >> 5] >> (31 - (bit_number & 31))) & 1; /* Swithing x->height-y-1 and y->x here gives vertical glyphs */ if((bit ? fg : bg) != C_NONE) dpixel(x0 + (height-y-1), y0 + x, bit ? fg : bg); } } } static void topti_render(int x, int y, char const *str_char, font_t const *f, int fg, int bg, int size) { uint8_t const *str = (void *)str_char; uint8_t const *str0 = str; /* Raw glyph data */ uint32_t const *data = f->data; /* Character spacing waiting to be drawn, in pixels */ int space = 0; /* Read each character from the input string */ while(1) { uint32_t code_point = topti_utf8_next(&str); if(!code_point || (size >= 0 && str - str0 > size)) break; int glyph = topti_glyph_index(f, code_point); if(glyph < 0) continue; int dataw = f->prop ? f->glyph_width[glyph] : f->width; /* Draw character spacing if background is opaque */ if(space && bg >= 0) drect(x, y, x+f->data_height-1, y+space-1, bg); y += space; if(y >= DHEIGHT) break; int index = topti_offset(f, glyph); /* Render glyph */ topti_glyph(x, y, data + index, dataw, f->data_height, fg, bg); /* Switching x -> y here (and some other places, but mostly here) gives vertical text */ y += dataw; space = f->char_spacing; } } void duet_text_opt(int x, int y, int fg, int bg, int halign, int valign, char const *str, int size) { if(halign != DTEXT_LEFT || valign != DTEXT_TOP) { int w, h; dnsize(str, size, &font_duet, &w, &h); if(halign == DTEXT_RIGHT) x -= h - 1; if(halign == DTEXT_CENTER) x -= (h >> 1); if(valign == DTEXT_BOTTOM) y -= w - 1; if(valign == DTEXT_MIDDLE) y -= (w >> 1); } topti_render(x, y, str, &font_duet, fg, bg, size); }