fb: cfb: Fix CFB_FONT_MSB_FIRST font rendering
I broke the rendering of the CFB_FONT_MSB_FIRST font in the previously committed #53796. I will correct the entire font rendering process to make it easier to remove the restriction that the vertical size of the font must be a multiple of 8. Signed-off-by: TOKITA Hiroshi <tokita.hiroshi@gmail.com>
This commit is contained in:
parent
06086ce771
commit
d542e75975
108
subsys/fb/cfb.c
108
subsys/fb/cfb.c
@ -7,6 +7,7 @@
|
||||
#include <zephyr/kernel.h>
|
||||
#include <string.h>
|
||||
#include <zephyr/display/cfb.h>
|
||||
#include <zephyr/sys/byteorder.h>
|
||||
|
||||
#define LOG_LEVEL CONFIG_CFB_LOG_LEVEL
|
||||
#include <zephyr/logging/log.h>
|
||||
@ -15,6 +16,9 @@ LOG_MODULE_REGISTER(cfb);
|
||||
STRUCT_SECTION_START_EXTERN(cfb_font);
|
||||
STRUCT_SECTION_END_EXTERN(cfb_font);
|
||||
|
||||
#define LSB_BIT_MASK(x) BIT_MASK(x)
|
||||
#define MSB_BIT_MASK(x) (BIT_MASK(x) << (8 - x))
|
||||
|
||||
static inline uint8_t byte_reverse(uint8_t b)
|
||||
{
|
||||
b = (b & 0xf0) >> 4 | (b & 0x0f) << 4;
|
||||
@ -92,8 +96,9 @@ static uint8_t draw_char_vtmono(const struct char_framebuffer *fb,
|
||||
bool draw_bg)
|
||||
{
|
||||
const struct cfb_font *fptr = &(fb->fonts[fb->font_idx]);
|
||||
const bool need_reverse = (((fb->screen_info & SCREEN_INFO_MONO_MSB_FIRST) != 0)
|
||||
!= ((fptr->caps & CFB_FONT_MSB_FIRST) != 0));
|
||||
const bool font_is_msbfirst = ((fptr->caps & CFB_FONT_MSB_FIRST) != 0);
|
||||
const bool need_reverse =
|
||||
(((fb->screen_info & SCREEN_INFO_MONO_MSB_FIRST) != 0) != font_is_msbfirst);
|
||||
uint8_t *glyph_ptr;
|
||||
|
||||
if (c < fptr->first_char || c > fptr->last_char) {
|
||||
@ -108,7 +113,7 @@ static uint8_t draw_char_vtmono(const struct char_framebuffer *fb,
|
||||
for (size_t g_x = 0; g_x < fptr->width; g_x++) {
|
||||
const int16_t fb_x = x + g_x;
|
||||
|
||||
for (size_t g_y = 0; g_y < fptr->height; g_y++) {
|
||||
for (size_t g_y = 0; g_y < fptr->height;) {
|
||||
/*
|
||||
* Process glyph rendering in the y direction
|
||||
* by separating per 8-line boundaries.
|
||||
@ -117,66 +122,87 @@ static uint8_t draw_char_vtmono(const struct char_framebuffer *fb,
|
||||
const int16_t fb_y = y + g_y;
|
||||
const size_t fb_index = (fb_y / 8U) * fb->x_res + fb_x;
|
||||
const size_t offset = y % 8;
|
||||
const uint8_t bottom_lines = ((offset + fptr->height) % 8);
|
||||
uint8_t bg_mask;
|
||||
uint8_t byte;
|
||||
uint8_t next_byte;
|
||||
|
||||
if (fb_x < 0 || fb->x_res <= fb_x || fb_y < 0 || fb->y_res <= fb_y) {
|
||||
g_y++;
|
||||
continue;
|
||||
}
|
||||
|
||||
byte = get_glyph_byte(glyph_ptr, fptr, g_x, g_y / 8);
|
||||
|
||||
if (offset == 0) {
|
||||
if (offset == 0 || g_y == 0) {
|
||||
/*
|
||||
* The start row is on an 8-line boundary.
|
||||
* Therefore, it can set the value directly.
|
||||
* The case of drawing the first line of the glyphs or
|
||||
* starting to draw with a tile-aligned position case.
|
||||
* In this case, no character is above it.
|
||||
* So, we process assume that nothing is drawn above.
|
||||
*/
|
||||
bg_mask = 0;
|
||||
g_y += 7;
|
||||
} else if (g_y == 0) {
|
||||
/*
|
||||
* If the starting row is not on the 8-line boundary,
|
||||
* shift the glyph to the starting line, and create a mask
|
||||
* from the 8-line boundary to the starting line.
|
||||
*/
|
||||
byte = byte << offset;
|
||||
bg_mask = BIT_MASK(offset);
|
||||
g_y += (7 - offset);
|
||||
byte = 0;
|
||||
next_byte = get_glyph_byte(glyph_ptr, fptr, g_x, g_y / 8);
|
||||
} else {
|
||||
byte = get_glyph_byte(glyph_ptr, fptr, g_x, g_y / 8);
|
||||
next_byte = get_glyph_byte(glyph_ptr, fptr, g_x, (g_y + 8) / 8);
|
||||
}
|
||||
|
||||
if (font_is_msbfirst) {
|
||||
/*
|
||||
* After the starting row, read and concatenate the next 8-rows
|
||||
* glyph and clip to the 8-line boundary and write 8-lines
|
||||
* at the time.
|
||||
* Create a mask to prevent overwriting the drawing contents
|
||||
* after the end row.
|
||||
* Extract the necessary 8 bits from the combined 2 tiles of glyphs.
|
||||
*/
|
||||
const size_t lines = ((fptr->height - g_y) < 8) ? offset : 8;
|
||||
byte = ((byte << 8) | next_byte) >> (offset);
|
||||
|
||||
if (lines == 8) {
|
||||
uint16_t byte2 = byte;
|
||||
|
||||
byte2 |= (get_glyph_byte(glyph_ptr, fptr, g_x,
|
||||
(g_y + 8) / 8))
|
||||
<< 8;
|
||||
byte = (byte2 >> (8 - offset)) & BIT_MASK(lines);
|
||||
if (g_y == 0) {
|
||||
/*
|
||||
* Create a mask that does not draw offset white space.
|
||||
*/
|
||||
bg_mask = BIT_MASK(8 - offset);
|
||||
} else {
|
||||
byte = (byte >> (8 - offset)) & BIT_MASK(lines);
|
||||
/*
|
||||
* The drawing of the second line onwards
|
||||
* is aligned with the tile, so it draws all the bits.
|
||||
*/
|
||||
bg_mask = 0xFF;
|
||||
}
|
||||
} else {
|
||||
byte = ((next_byte << 8) | byte) >> (8 - offset);
|
||||
if (g_y == 0) {
|
||||
bg_mask = BIT_MASK(8 - offset) << offset;
|
||||
} else {
|
||||
bg_mask = 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
bg_mask = (BIT_MASK(8 - lines) << (lines)) & 0xFF;
|
||||
g_y += (lines - 1);
|
||||
/*
|
||||
* Clip the bottom margin to protect existing draw contents.
|
||||
*/
|
||||
if (((fptr->height - g_y) < 8) && (bottom_lines != 0)) {
|
||||
const uint8_t clip = font_is_msbfirst ? MSB_BIT_MASK(bottom_lines)
|
||||
: LSB_BIT_MASK(bottom_lines);
|
||||
|
||||
bg_mask &= clip;
|
||||
byte &= clip;
|
||||
}
|
||||
|
||||
if (draw_bg) {
|
||||
if (need_reverse) {
|
||||
bg_mask = byte_reverse(bg_mask);
|
||||
}
|
||||
fb->buf[fb_index] &= ~bg_mask;
|
||||
}
|
||||
|
||||
if (need_reverse) {
|
||||
byte = byte_reverse(byte);
|
||||
bg_mask = byte_reverse(bg_mask);
|
||||
}
|
||||
|
||||
if (draw_bg) {
|
||||
fb->buf[fb_index] &= bg_mask;
|
||||
}
|
||||
|
||||
fb->buf[fb_index] |= byte;
|
||||
|
||||
if (g_y == 0) {
|
||||
g_y += (8 - offset);
|
||||
} else if ((fptr->height - g_y) >= 8) {
|
||||
g_y += 8;
|
||||
} else {
|
||||
g_y += bottom_lines;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user