BLF API: Add BLF_width_to_strlen,rstrlen gives a byte offset from a string width

This commit is contained in:
Campbell Barton 2013-12-16 21:47:10 +11:00
parent c193dbe30b
commit ce3f42e16a
4 changed files with 176 additions and 0 deletions

View File

@ -79,6 +79,11 @@ void BLF_draw(int fontid, const char *str, size_t len);
void BLF_draw_ascii(int fontid, const char *str, size_t len);
int BLF_draw_mono(int fontid, const char *str, size_t len, int cwidth);
/* Get the string byte offset that fits within a given width */
size_t BLF_width_to_strlen(int fontid, const char *str, size_t len, float width, float *r_width);
/* Same as BLF_width_to_strlen but search from the string end */
size_t BLF_width_to_rstrlen(int fontid, const char *str, size_t len, float width, float *r_width);
/* This function return the bounding box of the string
* and are not multiplied by the aspect.
*/

View File

@ -592,6 +592,46 @@ int BLF_draw_mono(int fontid, const char *str, size_t len, int cwidth)
return columns;
}
size_t BLF_width_to_strlen(int fontid, const char *str, size_t len, float width, float *r_width)
{
FontBLF *font = blf_get(fontid);
if (font) {
const float xa = (font->flags & BLF_ASPECT) ? font->aspect[0] : 1.0f;
size_t ret;
ret = blf_font_width_to_strlen(font, str, len, width / xa, r_width);
if (r_width) {
*r_width *= xa;
}
return ret;
}
if (r_width) {
*r_width = 0.0f;
}
return 0;
}
size_t BLF_width_to_rstrlen(int fontid, const char *str, size_t len, float width, float *r_width)
{
FontBLF *font = blf_get(fontid);
if (font) {
const float xa = (font->flags & BLF_ASPECT) ? font->aspect[0] : 1.0f;
size_t ret;
ret = blf_font_width_to_rstrlen(font, str, len, width / xa, r_width);
if (r_width) {
*r_width *= xa;
}
return ret;
}
if (r_width) {
*r_width = 0.0f;
}
return 0;
}
void BLF_boundbox(int fontid, const char *str, size_t len, rctf *box)
{
FontBLF *font = blf_get(fontid);

View File

@ -49,6 +49,7 @@
#include "BLI_string.h"
#include "BLI_string_utf8.h"
#include "BLI_threads.h"
#include "BLI_alloca.h"
#include "BLI_linklist.h" /* linknode */
#include "BLI_strict_flags.h"
@ -415,6 +416,134 @@ void blf_font_buffer(FontBLF *font, const char *str)
}
}
size_t blf_font_width_to_strlen(FontBLF *font, const char *str, size_t len, float width, float *r_width)
{
unsigned int c;
GlyphBLF *g, *g_prev = NULL;
FT_Vector delta;
int pen_x = 0;
size_t i = 0, i_prev;
GlyphBLF **glyph_ascii_table = font->glyph_cache->glyph_ascii_table;
const int width_i = (int)width + 1;
int width_new;
BLF_KERNING_VARS(font, has_kerning, kern_mode);
blf_font_ensure_ascii_table(font);
while ((i_prev = i), (width_new = pen_x), ((i < len) && str[i]))
{
BLF_UTF8_NEXT_FAST(font, g, str, i, c, glyph_ascii_table);
if (c == BLI_UTF8_ERR)
break;
if (g == NULL)
continue;
if (has_kerning)
BLF_KERNING_STEP(font, kern_mode, g_prev, g, delta, pen_x);
pen_x += (int)g->advance;
if (width_i < pen_x) {
break;
}
g_prev = g;
}
if (r_width) {
*r_width = (float)width_new;
}
return i_prev;
}
size_t blf_font_width_to_rstrlen(FontBLF *font, const char *str, size_t len, float width, float *r_width)
{
unsigned int c;
GlyphBLF *g, *g_prev = NULL;
FT_Vector delta;
int pen_x = 0;
size_t i = 0, i_prev;
GlyphBLF **glyph_ascii_table = font->glyph_cache->glyph_ascii_table;
const int width_i = (int)width + 1;
int width_new;
bool is_malloc;
int (*width_accum)[2];
int width_accum_ofs = 0;
BLF_KERNING_VARS(font, has_kerning, kern_mode);
/* skip allocs in simple cases */
len = BLI_strnlen(str, len);
if (width_i <= 1 || len == 0) {
if (r_width) {
*r_width = 0.0f;
}
return len;
}
if (len < 2048) {
width_accum = BLI_array_alloca(width_accum, len);
is_malloc = false;
}
else {
width_accum = MEM_mallocN(sizeof(*width_accum) * len, __func__);
is_malloc = true;
}
blf_font_ensure_ascii_table(font);
while ((i < len) && str[i]) {
BLF_UTF8_NEXT_FAST(font, g, str, i, c, glyph_ascii_table);
if (c == BLI_UTF8_ERR)
break;
if (g == NULL)
continue;
if (has_kerning)
BLF_KERNING_STEP(font, kern_mode, g_prev, g, delta, pen_x);
pen_x += (int)g->advance;
width_accum[width_accum_ofs][0] = (int)i;
width_accum[width_accum_ofs][1] = pen_x;
width_accum_ofs++;
g_prev = g;
}
if (pen_x > width_i && width_accum_ofs != 0) {
const int min_x = pen_x - width_i;
/* search backwards */
width_new = pen_x;
while (width_accum_ofs-- > 0) {
if (min_x > width_accum[width_accum_ofs][1]) {
break;
}
}
width_accum_ofs++;
width_new = pen_x - width_accum[width_accum_ofs][1];
i_prev = (size_t)width_accum[width_accum_ofs][0];
}
else {
width_new = pen_x;
i_prev = 0;
}
if (is_malloc) {
MEM_freeN(width_accum);
}
if (r_width) {
*r_width = (float)width_new;
}
return i_prev;
}
void blf_font_boundbox(FontBLF *font, const char *str, size_t len, rctf *box)
{
unsigned int c;

View File

@ -55,6 +55,8 @@ void blf_font_draw(struct FontBLF *font, const char *str, size_t len);
void blf_font_draw_ascii(struct FontBLF *font, const char *str, size_t len);
int blf_font_draw_mono(struct FontBLF *font, const char *str, size_t len, int cwidth);
void blf_font_buffer(struct FontBLF *font, const char *str);
size_t blf_font_width_to_strlen(struct FontBLF *font, const char *str, size_t len, float width, float *r_width);
size_t blf_font_width_to_rstrlen(struct FontBLF *font, const char *str, size_t len, float width, float *r_width);
void blf_font_boundbox(struct FontBLF *font, const char *str, size_t len, struct rctf *box);
void blf_font_width_and_height(struct FontBLF *font, const char *str, size_t len, float *width, float *height);
float blf_font_width(struct FontBLF *font, const char *str, size_t len);