BLF: Utility to Wrap a String into Multiple Lines #118436
|
@ -9,7 +9,9 @@
|
|||
#pragma once
|
||||
|
||||
#include "BLI_compiler_attrs.h"
|
||||
#include "BLI_string_ref.hh"
|
||||
#include "BLI_sys_types.h"
|
||||
#include "BLI_vector.hh"
|
||||
|
||||
/* Name of sub-directory inside #BLENDER_DATAFILES that contains font files. */
|
||||
#define BLF_DATAFILES_FONTS_DIR "fonts"
|
||||
|
@ -254,6 +256,10 @@ void BLF_rotation(int fontid, float angle);
|
|||
void BLF_clipping(int fontid, int xmin, int ymin, int xmax, int ymax);
|
||||
void BLF_wordwrap(int fontid, int wrap_width);
|
||||
|
||||
blender::Vector<blender::StringRef> BLF_string_wrap(int fontid,
|
||||
blender::StringRef str,
|
||||
const int max_pixel_width);
|
||||
|
||||
#if BLF_BLUR_ENABLE
|
||||
void BLF_blur(int fontid, int size);
|
||||
#endif
|
||||
|
|
|
@ -935,6 +935,17 @@ void BLF_draw_buffer(int fontid, const char *str, const size_t str_len)
|
|||
BLF_draw_buffer_ex(fontid, str, str_len, nullptr);
|
||||
}
|
||||
|
||||
blender::Vector<blender::StringRef> BLF_string_wrap(int fontid,
|
||||
blender::StringRef str,
|
||||
const int max_pixel_width)
|
||||
{
|
||||
FontBLF *font = blf_get(fontid);
|
||||
Harley marked this conversation as resolved
|
||||
if (!font) {
|
||||
return {};
|
||||
}
|
||||
return blf_font_string_wrap(font, str, max_pixel_width);
|
||||
}
|
||||
|
||||
char *BLF_display_name_from_file(const char *filepath)
|
||||
{
|
||||
/* While listing font directories this function can be called simultaneously from a greater
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include "BLI_string_cursor_utf8.h"
|
||||
#include "BLI_string_utf8.h"
|
||||
#include "BLI_threads.h"
|
||||
#include "BLI_vector.hh"
|
||||
|
||||
#include "BLF_api.hh"
|
||||
|
||||
|
@ -1085,6 +1086,7 @@ void blf_str_offset_to_glyph_bounds(FontBLF *font,
|
|||
static void blf_font_wrap_apply(FontBLF *font,
|
||||
const char *str,
|
||||
const size_t str_len,
|
||||
const int max_pixel_width,
|
||||
ResultBLF *r_info,
|
||||
void (*callback)(FontBLF *font,
|
||||
GlyphCacheBLF *gc,
|
||||
|
@ -1109,7 +1111,7 @@ static void blf_font_wrap_apply(FontBLF *font,
|
|||
struct WordWrapVars {
|
||||
ft_pix wrap_width;
|
||||
size_t start, last[2];
|
||||
} wrap = {font->wrap_width != -1 ? ft_pix_from_int(font->wrap_width) : INT_MAX, 0, {0, 0}};
|
||||
} wrap = {max_pixel_width != -1 ? ft_pix_from_int(max_pixel_width) : INT_MAX, 0, {0, 0}};
|
||||
|
||||
// printf("%s wrapping (%d, %d) `%s`:\n", __func__, str_len, strlen(str), str);
|
||||
while ((i < str_len) && str[i]) {
|
||||
|
@ -1198,7 +1200,8 @@ static void blf_font_draw__wrap_cb(FontBLF *font,
|
|||
}
|
||||
void blf_font_draw__wrap(FontBLF *font, const char *str, const size_t str_len, ResultBLF *r_info)
|
||||
{
|
||||
blf_font_wrap_apply(font, str, str_len, r_info, blf_font_draw__wrap_cb, nullptr);
|
||||
blf_font_wrap_apply(
|
||||
font, str, str_len, font->wrap_width, r_info, blf_font_draw__wrap_cb, nullptr);
|
||||
}
|
||||
|
||||
/** Utility for #blf_font_boundbox__wrap. */
|
||||
|
@ -1223,7 +1226,8 @@ void blf_font_boundbox__wrap(
|
|||
box->ymin = 32000;
|
||||
box->ymax = -32000;
|
||||
|
||||
blf_font_wrap_apply(font, str, str_len, r_info, blf_font_boundbox_wrap_cb, box);
|
||||
blf_font_wrap_apply(
|
||||
font, str, str_len, font->wrap_width, r_info, blf_font_boundbox_wrap_cb, box);
|
||||
}
|
||||
|
||||
/** Utility for #blf_font_draw_buffer__wrap. */
|
||||
|
@ -1241,7 +1245,37 @@ void blf_font_draw_buffer__wrap(FontBLF *font,
|
|||
const size_t str_len,
|
||||
ResultBLF *r_info)
|
||||
{
|
||||
blf_font_wrap_apply(font, str, str_len, r_info, blf_font_draw_buffer__wrap_cb, nullptr);
|
||||
blf_font_wrap_apply(
|
||||
font, str, str_len, font->wrap_width, r_info, blf_font_draw_buffer__wrap_cb, nullptr);
|
||||
}
|
||||
|
||||
/** Wrap a blender::StringRef. */
|
||||
static void blf_font_string_wrap_cb(FontBLF * /*font*/,
|
||||
GlyphCacheBLF * /*gc*/,
|
||||
const char *str,
|
||||
const size_t str_len,
|
||||
ft_pix /*pen_y*/,
|
||||
void *str_list_ptr)
|
||||
Harley marked this conversation as resolved
Hans Goudey
commented
Just as an example, these two lines do a fair amount of expensive things:
Just as an example, these two lines do a fair amount of expensive things:
- First is the `line` variable. This has to allocate space for `str_len` and copy the characters
- Next is an empty string as the vector increases in size. This is cheap, but worth keeping in mind (
- Finally, putting the sliced string into the vector. Copy assignment allocates new characters for the string in the vector, then copies from `line`. With `std::vector`, `emplace_back` is used to construct the new value in place rather than default constructing it then filling its value with copy assignment. C++ also has `std::move` for this reason: `line` is just temporary data, we can move it into the vector to avoid the copy
|
||||
{
|
||||
blender::Vector<blender::StringRef> *list = static_cast<blender::Vector<blender::StringRef> *>(
|
||||
str_list_ptr);
|
||||
blender::StringRef line(str, str + str_len);
|
||||
list->append(line);
|
||||
}
|
||||
|
||||
blender::Vector<blender::StringRef> blf_font_string_wrap(FontBLF *font,
|
||||
blender::StringRef str,
|
||||
int max_pixel_width)
|
||||
{
|
||||
blender::Vector<blender::StringRef> list;
|
||||
blf_font_wrap_apply(font,
|
||||
str.data(),
|
||||
size_t(str.size()),
|
||||
max_pixel_width,
|
||||
nullptr,
|
||||
blf_font_string_wrap_cb,
|
||||
&list);
|
||||
return list;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
|
@ -8,6 +8,9 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "BLI_string_ref.hh"
|
||||
#include "BLI_vector.hh"
|
||||
|
||||
struct FontBLF;
|
||||
struct GlyphBLF;
|
||||
struct GlyphCacheBLF;
|
||||
|
@ -96,6 +99,10 @@ void blf_font_draw__wrap(struct FontBLF *font,
|
|||
size_t str_len,
|
||||
struct ResultBLF *r_info);
|
||||
|
||||
blender::Vector<blender::StringRef> blf_font_string_wrap(FontBLF *font,
|
||||
blender::StringRef str,
|
||||
int max_pixel_width);
|
||||
|
||||
/**
|
||||
* Use fixed column width, but an utf8 character may occupy multiple columns.
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue
Flip the check and
return {}
inside. It's nice to consistently put error handling at the start of the function