1 /* 2 * Common font-related functions. 3 * 4 * Copyright (C) 2018 Paul Boddie <paul@boddie.org.uk> 5 * 6 * This program is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation, either version 3 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program. If not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 #include <stdlib.h> 21 22 #include "display.h" 23 #include "font.h" 24 25 26 27 /* Initialise a font configuration. */ 28 29 void init_font(font_config_t *cfg, uint8_t *chars, uint32_t *table, 30 uint32_t base, uint32_t limit) 31 { 32 cfg->chars = (char_definition_t *) chars; 33 cfg->table = table; 34 cfg->base = base; 35 cfg->limit = limit; 36 } 37 38 39 40 /* Return the character definition for the given character. */ 41 42 char_definition_t *get_char_definition(font_config_t *fcfg, char c) 43 { 44 /* Obtain the offset from the table and combine it with the character 45 definitions base address. */ 46 47 if ((c >= fcfg->base) && (c < fcfg->limit)) 48 return (char_definition_t *) ((uint8_t *) fcfg->chars + fcfg->table[c - fcfg->base]); 49 else 50 return NULL; 51 } 52 53 /* Write a character to the screen, returning the next character position. */ 54 55 int write_char(display_config_t *cfg, font_config_t *fcfg, char c, 56 int x, int y, uint8_t colour) 57 { 58 int sy, dx, dy; 59 char_definition_t *chardef = get_char_definition(fcfg, c); 60 uint8_t *imagerow = chardef->data, 61 *displayline = cfg->screen_start + y * cfg->line_length, 62 bitmap, mask; 63 64 /* Space is a special case. */ 65 66 if (c == ' ') 67 return x + 3; 68 69 for (sy = 0, dy = y; (sy < chardef->height) && (dy < cfg->line_count); sy++, dy++) 70 { 71 if (displayline >= cfg->screen_limit) 72 displayline -= cfg->screen_size; 73 74 bitmap = *imagerow; 75 76 for (dx = x, mask = 1 << (chardef->width - 1); (mask) && (dx < cfg->line_length); dx++, mask >>= 1) 77 { 78 if (bitmap & mask) 79 displayline[display_get_position(cfg, dx)] = colour; 80 } 81 82 imagerow += 1; 83 displayline += cfg->line_length; 84 } 85 86 return x + chardef->width; 87 }