diff options
Diffstat (limited to 'framebuffer')
-rw-r--r-- | framebuffer/font_internal.c | 35 | ||||
-rw-r--r-- | framebuffer/font_internal.h | 5 | ||||
-rw-r--r-- | framebuffer/framebuffer.c | 3 |
3 files changed, 40 insertions, 3 deletions
diff --git a/framebuffer/font_internal.c b/framebuffer/font_internal.c index 5aada8f11..4edb4ee4c 100644 --- a/framebuffer/font_internal.c +++ b/framebuffer/font_internal.c @@ -221,6 +221,12 @@ fb_get_glyph(uint32_t ucs4, enum fb_font_style style) unsigned int offset; uint16_t g_offset; + /* Internal font has no glyphs beyond U+FFFF and there isn't + * space to render a >4 digit codepoint; just show replacement + * character. */ + if (ucs4 > 0xffff) + ucs4 = 0xfffd; + switch (style) { case FB_BOLD_ITALIC: section = fb_bold_italic_section_table[ucs4 / 256]; @@ -287,11 +293,24 @@ static nserror utf8_from_local(const char *string, return NSERROR_OK; } + static bool nsfont_width(const plot_font_style_t *fstyle, const char *string, size_t length, int *width) { - *width = FB_FONT_WIDTH * utf8_bounded_length(string, length); + size_t nxtchr = 0; + + *width = 0; + while (nxtchr < length) { + uint32_t ucs4; + ucs4 = utf8_to_ucs4(string + nxtchr, length - nxtchr); + if (codepoint_displayable(ucs4)) { + *width += FB_FONT_WIDTH; + } + + nxtchr = utf8_next(string, length, nxtchr); + } + return true; } @@ -315,10 +334,15 @@ static bool nsfont_position_in_string(const plot_font_style_t *fstyle, int x_pos = 0; while (nxtchr < length) { + uint32_t ucs4; if (abs(x_pos - x) <= (FB_FONT_WIDTH / 2)) break; - x_pos += FB_FONT_WIDTH; + ucs4 = utf8_to_ucs4(string + nxtchr, length - nxtchr); + if (codepoint_displayable(ucs4)) { + x_pos += FB_FONT_WIDTH; + } + nxtchr = utf8_next(string, length, nxtchr); } @@ -363,13 +387,18 @@ static bool nsfont_split(const plot_font_style_t *fstyle, *actual_x = 0; while (nxtchr < length) { + uint32_t ucs4; if (string[nxtchr] == ' ') { last_space_x = *actual_x; last_space_idx = nxtchr; } - *actual_x += FB_FONT_WIDTH; + ucs4 = utf8_to_ucs4(string + nxtchr, length - nxtchr); + if (codepoint_displayable(ucs4)) { + *actual_x += FB_FONT_WIDTH; + } + if (*actual_x > x && last_space_idx != 0) { /* string has exceeded available width and we've * found a space; return previous space */ diff --git a/framebuffer/font_internal.h b/framebuffer/font_internal.h index 236183ace..ead179c99 100644 --- a/framebuffer/font_internal.h +++ b/framebuffer/font_internal.h @@ -19,6 +19,8 @@ #ifndef NETSURF_FB_FONT_INTERNAL_H #define NETSURF_FB_FONT_INTERNAL_H +#include <stdbool.h> + struct fb_font_desc { const char *name; int width, height, pitch; @@ -39,5 +41,8 @@ enum fb_font_style fb_get_font_style(const plot_font_style_t *fstyle); const uint8_t * fb_get_glyph(uint32_t ucs4, enum fb_font_style style); +#define codepoint_displayable(u) \ + (!(u >= 0x200b && u <= 0x200f)) + #endif /* NETSURF_FB_FONT_INTERNAL_H */ diff --git a/framebuffer/framebuffer.c b/framebuffer/framebuffer.c index 0115d838c..4cd064c34 100644 --- a/framebuffer/framebuffer.c +++ b/framebuffer/framebuffer.c @@ -140,6 +140,9 @@ static bool framebuffer_plot_text(int x, int y, const char *text, size_t length, ucs4 = utf8_to_ucs4(text + nxtchr, length - nxtchr); nxtchr = utf8_next(text, length, nxtchr); + if (!codepoint_displayable(ucs4)) + continue; + loc.x0 = x; loc.y0 = y; loc.x1 = loc.x0 + FB_FONT_WIDTH; |