static bool nsfont_position_in_string(const plot_font_style_t *fstyle, const char *string, size_t length, int x, size_t *char_offset, int *actual_x) { uint32_t ucs4; size_t nxtchr = 0; FT_Glyph glyph; int prev_x = 0; *actual_x = 0; while (nxtchr < length) { ucs4 = utf8_to_ucs4(string + nxtchr, length - nxtchr); glyph = fb_getglyph(fstyle, ucs4); if (glyph == NULL) continue; *actual_x += glyph->advance.x >> 16; if (*actual_x > x) break; prev_x = *actual_x; nxtchr = utf8_next(string, length, nxtchr); } /* choose nearest of previous and last x */ if (abs(*actual_x - x) > abs(prev_x - x)) *actual_x = prev_x; *char_offset = nxtchr; return true; }
static bool framebuffer_plot_text(int x, int y, const char *text, size_t length, const plot_font_style_t *fstyle) { uint32_t ucs4; size_t nxtchr = 0; FT_Glyph glyph; FT_BitmapGlyph bglyph; nsfb_bbox_t loc; while (nxtchr < length) { ucs4 = utf8_to_ucs4(text + nxtchr, length - nxtchr); nxtchr = utf8_next(text, length, nxtchr); glyph = fb_getglyph(fstyle, ucs4); if (glyph == NULL) continue; if (glyph->format == FT_GLYPH_FORMAT_BITMAP) { bglyph = (FT_BitmapGlyph)glyph; loc.x0 = x + bglyph->left; loc.y0 = y - bglyph->top; loc.x1 = loc.x0 + bglyph->bitmap.width; loc.y1 = loc.y0 + bglyph->bitmap.rows; /* now, draw to our target surface */ if (bglyph->bitmap.pixel_mode == FT_PIXEL_MODE_MONO) { nsfb_plot_glyph1(nsfb, &loc, bglyph->bitmap.buffer, bglyph->bitmap.pitch, fstyle->foreground); } else { nsfb_plot_glyph8(nsfb, &loc, bglyph->bitmap.buffer, bglyph->bitmap.pitch, fstyle->foreground); } } x += glyph->advance.x >> 16; } return true; }
static bool nsfont_split(const plot_font_style_t *fstyle, const char *string, size_t length, int x, size_t *char_offset, int *actual_x) { uint32_t ucs4; size_t nxtchr = 0; int last_space_x = 0; int last_space_idx = 0; FT_Glyph glyph; *actual_x = 0; while (nxtchr < length) { ucs4 = utf8_to_ucs4(string + nxtchr, length - nxtchr); glyph = fb_getglyph(fstyle, ucs4); if (glyph == NULL) continue; if (ucs4 == 0x20) { last_space_x = *actual_x; last_space_idx = nxtchr; } *actual_x += glyph->advance.x >> 16; if (*actual_x > x) { /* string has exceeded available width return previous * space */ *actual_x = last_space_x; *char_offset = last_space_idx; return true; } nxtchr = utf8_next(string, length, nxtchr); } *char_offset = nxtchr; return true; }
/** * Measure the width of a string. * * \param fstyle style for this text * \param string UTF-8 string to measure * \param length length of string * \param width updated to width of string[0..length) * \return true on success, false on error and error reported */ static bool nsfont_width(const plot_font_style_t *fstyle, const char *string, size_t length, int *width) { uint32_t ucs4; size_t nxtchr = 0; FT_Glyph glyph; *width = 0; while (nxtchr < length) { ucs4 = utf8_to_ucs4(string + nxtchr, length - nxtchr); nxtchr = utf8_next(string, length, nxtchr); glyph = fb_getglyph(fstyle, ucs4); if (glyph == NULL) continue; *width += glyph->advance.x >> 16; } return true; }