CommonPIC32

Annotated lib/font.c

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