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 /* Space is a special case. */ 28 29 static char_definition_t space = { 30 .width = 3, .height = 9, .data = {0, 0, 0, 0, 0, 0, 0, 0, 0} 31 }; 32 33 34 35 /* Return the character definition for the given character. */ 36 37 char_definition_t *get_char_definition(font_config_t *fcfg, char c) 38 { 39 /* Obtain the offset from the table and combine it with the character 40 definitions base address. */ 41 42 if ((c >= fcfg->range->base) && (c < fcfg->range->limit)) 43 return (char_definition_t *) ((uint8_t *) fcfg->chars + fcfg->range->table[c - fcfg->range->base]); 44 else 45 return &space; 46 } 47 48 /* Write a character to the screen, returning the next character position. */ 49 50 int write_char(display_config_t *cfg, font_config_t *fcfg, char c, 51 int x, int y, uint8_t colour) 52 { 53 int sy, dx, dy; 54 char_definition_t *chardef = get_char_definition(fcfg, c); 55 uint8_t *imagerow = chardef->data, 56 *displayline = cfg->screen_start + y * cfg->line_length, 57 bitmap, mask; 58 59 for (sy = 0, dy = y; (sy < chardef->height) && (dy < cfg->line_count); sy++, dy++) 60 { 61 if (displayline >= cfg->screen_limit) 62 displayline -= cfg->screen_size; 63 64 bitmap = *imagerow; 65 66 for (dx = x, mask = 1 << (chardef->width - 1); (mask) && (dx < cfg->line_length); dx++, mask >>= 1) 67 { 68 if (bitmap & mask) 69 displayline[display_get_position(cfg, dx)] = colour; 70 } 71 72 imagerow += 1; 73 displayline += cfg->line_length; 74 } 75 76 return x + chardef->width; 77 } 78 79 /* Write a string to the screen, updating the coordinates to indicate the next 80 character position. */ 81 82 void write_string(display_config_t *cfg, font_config_t *fcfg, const char *s, 83 int *x, int *y, uint8_t colour) 84 { 85 const int line_height = 9; 86 87 while (*s) 88 { 89 if (*x + get_char_definition(fcfg, *s)->width > cfg->line_length) 90 { 91 *x = 0; *y += line_height; 92 } 93 94 if (*y + line_height >= cfg->line_count) 95 break; 96 97 *x = write_char(cfg, fcfg, *s, *x, *y, colour); 98 s++; 99 } 100 }