153 lines
7.6 KiB
C
153 lines
7.6 KiB
C
#include "font.h"
|
|
#include "display.h"
|
|
#include "lvgl.h"
|
|
#include "stdbool.h"
|
|
#include <stdint.h>
|
|
|
|
static uint16_t find_glyph_id_in_cmap(const lv_font_fmt_txt_cmap_t * cmap, uint32_t character)
|
|
{
|
|
uint16_t cmap_last_character = cmap->range_start + cmap->range_length - 1;
|
|
bool character_exists_in_cmap = character >= cmap->range_start && character <= cmap_last_character;
|
|
if (character_exists_in_cmap)
|
|
{
|
|
uint16_t glyph_id = cmap->glyph_id_start - cmap->range_start + character;
|
|
return glyph_id;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
bool lv_font_get_glyph_dsc_fmt_txt(const lv_font_t * font, lv_font_fmt_txt_glyph_dsc_t * dsc_out, uint32_t character)
|
|
{
|
|
lv_font_fmt_txt_dsc_t *font_dsc = (lv_font_fmt_txt_dsc_t *) font->dsc;
|
|
for (uint16_t i = 0; i < font_dsc->cmap_num; i++)
|
|
{
|
|
uint16_t glyph_id = find_glyph_id_in_cmap(font_dsc->cmaps + i, character);
|
|
|
|
if (glyph_id == 0) continue;
|
|
|
|
*dsc_out = font_dsc->glyph_dsc[glyph_id];
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// Left as a dummy definition for LVGL font compatibility.
|
|
// We're not processing the bitmaps with draw buffers like LVGL does.
|
|
const void * lv_font_get_bitmap_fmt_txt(lv_font_fmt_txt_glyph_dsc_t * g_dsc, lv_draw_buf_t * draw_buf)
|
|
{
|
|
}
|
|
|
|
/**
|
|
* @brief Draws a single character to the framebuffer using the specified font.
|
|
*
|
|
* This function renders a character glyph from an LVGL font to the framebuffer at the
|
|
* specified location. The character is drawn in the provided color using a 1-bit bitmap
|
|
* format where set bits are drawn as colored pixels and unset bits are left transparent.
|
|
*
|
|
* @param framebuffer Pointer to the framebuffer array where the character will be drawn.
|
|
* Must be large enough to accommodate the character at the specified
|
|
* location (typically DISPLAY_HEIGHT * DISPLAY_WIDTH pixels).
|
|
* @param font Pointer to the LVGL font structure containing glyph data and metrics.
|
|
* The font must be a valid LVGL formatted text font (lv_font_fmt_txt_dsc_t).
|
|
* @param x_loc X coordinate (horizontal position) where the top-left of the character
|
|
* bounding box will be drawn. Must be within framebuffer bounds.
|
|
* @param y_loc Y coordinate (vertical position) where the top-left of the character
|
|
* bounding box will be drawn. Must be within framebuffer bounds.
|
|
* @param character The ASCII character code (0-255) to be drawn.
|
|
* @param color The RGB565 color value to use when drawing the character pixels.
|
|
* Pixels corresponding to set bits in the glyph bitmap will be drawn
|
|
* in this color.
|
|
*
|
|
* @return The advance width of the drawn glyph in pixels (lower 16 bits of glyph_dsc.adv_w).
|
|
* This value can be used to calculate the x position for the next character when
|
|
* drawing text. Returns 0 if the character glyph was not found in the font.
|
|
*
|
|
* @note The function performs no bounds checking. Ensure x_loc and y_loc are within
|
|
* the framebuffer dimensions to prevent buffer overruns.
|
|
* @note The glyph bitmap is stored in a packed 1-bit format where each bit represents
|
|
* one pixel (1 = draw pixel, 0 = skip pixel).
|
|
* @note If the character is not found in the font's character map, the function returns
|
|
* 0 without drawing anything.
|
|
*/
|
|
uint16_t draw_character(pixel_t *framebuffer, const lv_font_t *font, const uint16_t x_loc, const uint16_t y_loc, const char character, pixel_t color)
|
|
{
|
|
const lv_font_fmt_txt_dsc_t *font_dsc = (lv_font_fmt_txt_dsc_t *)font->dsc;
|
|
lv_font_fmt_txt_glyph_dsc_t glyph_dsc;
|
|
bool glyph_found = lv_font_get_glyph_dsc_fmt_txt(font, &glyph_dsc, character);
|
|
if (!glyph_found) return 0;
|
|
|
|
const uint16_t glyph_width = glyph_dsc.box_w;
|
|
const uint16_t glyph_height = glyph_dsc.box_h;
|
|
const int8_t glyph_ofs_x = glyph_dsc.ofs_x;
|
|
const int8_t glyph_ofs_y = glyph_dsc.ofs_y;
|
|
const uint32_t num_bitmap_bits = glyph_height * glyph_width;
|
|
|
|
for (uint32_t bitmap_pixel_index = 0; bitmap_pixel_index < num_bitmap_bits; bitmap_pixel_index++)
|
|
{
|
|
const uint8_t current_bit_in_byte = bitmap_pixel_index % 8;
|
|
const uint16_t bitmap_byte_index = glyph_dsc.bitmap_index + (bitmap_pixel_index / 8);
|
|
const int32_t fb_pixel_x = x_loc + (bitmap_pixel_index % glyph_width) + glyph_ofs_x;
|
|
const int32_t fb_pixel_y = y_loc + font->line_height - glyph_height + (bitmap_pixel_index / glyph_width) - glyph_ofs_y - font->base_line;
|
|
const uint32_t fb_pixel_index = (fb_pixel_y * DISPLAY_WIDTH) + fb_pixel_x;
|
|
|
|
const bool bit_on = font_dsc->glyph_bitmap[bitmap_byte_index] & (0x80 >> current_bit_in_byte);
|
|
if (bit_on)
|
|
{
|
|
if (fb_pixel_x >= 0 && fb_pixel_x < DISPLAY_WIDTH && fb_pixel_y >= 0 && fb_pixel_y < DISPLAY_HEIGHT)
|
|
{
|
|
framebuffer[fb_pixel_index] = color;
|
|
}
|
|
}
|
|
}
|
|
|
|
return (glyph_dsc.adv_w & 0x0000FFFF);
|
|
}
|
|
|
|
/**
|
|
* @brief Draws a null-terminated string to the framebuffer using the specified font.
|
|
*
|
|
* This function renders a complete string of characters to the framebuffer by iteratively
|
|
* calling draw_character() for each character in the string. Characters are drawn horizontally
|
|
* from left to right, with each character's advance width determining the spacing for the
|
|
* next character. All characters are drawn on the same baseline (y_loc remains constant).
|
|
*
|
|
* @param framebuffer Pointer to the framebuffer array where the string will be drawn.
|
|
* Must be large enough to accommodate the entire string at the specified
|
|
* location (typically DISPLAY_HEIGHT * DISPLAY_WIDTH pixels).
|
|
* @param font Pointer to the LVGL font structure containing glyph data and metrics.
|
|
* The font must be a valid LVGL formatted text font (lv_font_fmt_txt_dsc_t).
|
|
* @param x_loc X coordinate (horizontal position) where the first character's top-left
|
|
* bounding box will be drawn. Must be within framebuffer bounds.
|
|
* @param y_loc Y coordinate (vertical position) where all characters' top-left bounding
|
|
* boxes will be drawn. Must be within framebuffer bounds.
|
|
* @param string Pointer to a null-terminated C string (array of uint8_t) containing
|
|
* the characters to be drawn. The function will stop drawing when it
|
|
* encounters a null terminator ('\0').
|
|
* @param color The RGB565 color value to use when drawing all character pixels.
|
|
* Pixels corresponding to set bits in each glyph bitmap will be drawn
|
|
* in this color.
|
|
*
|
|
* @note The function performs no bounds checking. Ensure x_loc and y_loc are within
|
|
* the framebuffer dimensions, and that the entire string will fit within the
|
|
* framebuffer bounds to prevent buffer overruns.
|
|
* @note Characters not found in the font (draw_character returns 0) will be skipped
|
|
* without advancing the x position, which may cause subsequent characters to
|
|
* overlap with missing characters.
|
|
* @note The string must be null-terminated. The function will continue drawing until
|
|
* it encounters a '\0' character.
|
|
* @note All characters in the string are drawn on the same horizontal baseline (y_loc
|
|
* remains constant for all characters).
|
|
*/
|
|
void draw_string(pixel_t *framebuffer, const lv_font_t *font, const uint16_t x_loc, const uint16_t y_loc, const char *string, pixel_t color)
|
|
{
|
|
uint32_t current_x = x_loc << 4;
|
|
|
|
for (const char *char_ptr = string; *char_ptr != '\0'; char_ptr++)
|
|
{
|
|
uint16_t advance_width = draw_character(framebuffer, font, current_x >> 4, y_loc, *char_ptr, color);
|
|
current_x += advance_width;
|
|
}
|
|
}
|