76 for (
const auto &item :
g_font_map.path_to_file_font_id.items()) {
80 for (
const auto &item :
g_font_map.name_to_mem_font_id.items()) {
89 int fontid =
g_font_map.path_to_file_font_id.add_or_modify(
116 int fontid =
g_font_map.name_to_mem_font_id.add_or_modify(
147 g_font_map.path_to_file_font_id.remove_if([&](
auto item) {
return item.value == fontid; });
148 g_font_map.name_to_mem_font_id.remove_if([&](
auto item) {
return item.value == fontid; });
161 if (
data->text_size < 1.0f ||
162 ((
data->color[3] == 0.0f) &&
164 (
data->outline_color[3] == 0.0f ||
data->outline_width <= 0.0f ||
181 data->text_font =
nullptr;
182 data->text_blf_id = -1;
183 data->text_size = 60.0f;
186 data->shadow_color[3] = 0.7f;
188 data->shadow_offset = 0.04f;
189 data->shadow_blur = 0.0f;
190 data->box_color[0] = 0.2f;
191 data->box_color[1] = 0.2f;
192 data->box_color[2] = 0.2f;
193 data->box_color[3] = 0.7f;
194 data->box_margin = 0.01f;
195 data->box_roundness = 0.0f;
196 data->outline_color[3] = 0.7f;
197 data->outline_width = 0.05f;
200 data->text_len_bytes = strlen(
data->text_ptr);
207 data->wrap_width = 1.0f;
212 if (
data ==
nullptr) {
217 if (do_id_user &&
data->text_font !=
nullptr) {
219 data->text_font =
nullptr;
223 if (
data->text_blf_id >= 0) {
225 data->text_blf_id = -1;
232 if (vfont ==
nullptr) {
269 MEM_delete(
data->runtime);
287 data->runtime =
nullptr;
288 data->text_blf_id = -1;
315 const rcti &shadow_rect)
317 dst +=
int64_t(start_line) * width;
318 for (
int y = start_line;
y < start_line + height;
y++) {
319 for (
int x = 0;
x < width;
x++) {
321 if (
x >= shadow_rect.
xmin &&
x <= shadow_rect.
xmax) {
322 float accum_weight = 0.0f;
325 for (
int nx = xmin, index = (xmin -
x) + half_size; nx <= xmax; nx++, index++) {
326 float weight = gaussian[index];
327 int offset =
y * width + nx;
328 accum += rect[offset] * weight;
329 accum_weight += weight;
331 accum *= (1.0f / accum_weight);
347 const rcti &shadow_rect)
349 dst +=
int64_t(start_line) * width;
350 for (
int y = start_line;
y < start_line + height;
y++) {
351 for (
int x = 0;
x < width;
x++) {
353 if (
x >= shadow_rect.
xmin &&
x <= shadow_rect.
xmax) {
354 float accum_weight = 0.0f;
357 for (
int ny = ymin, index = (ymin -
y) + half_size; ny <= ymax; ny++, index++) {
358 float weight = gaussian[index];
359 int offset = ny * width +
x;
360 accum += rect[offset] * weight;
361 accum_weight += weight;
363 accum *= (1.0f / accum_weight);
382 const rcti &shadow_rect,
390 for (
int x = shadow_rect.
xmin;
x <= shadow_rect.
xmax;
x++) {
392 size_t src_offset = width * src_y + src_x;
393 size_t dst_offset = width *
y +
x;
394 r_shadow_mask[dst_offset] =
input[src_offset * 4 + 3];
401 const rcti &shadow_rect,
402 const float4 &shadow_color,
409 size_t offset =
y * width + shadow_rect.
xmin;
411 for (
int x = shadow_rect.
xmin;
x <= shadow_rect.
xmax;
x++, offset++, dst += 4) {
412 uchar a = shadow_mask[offset];
418 float4 col2 = shadow_color * (a * (1.0f / 255.0f));
420 float fac = 1.0f - col1.w;
431 const int width = context->rectx;
432 const int height = context->recty;
434 const float blur_amount = line_height * 0.5f *
data->shadow_blur;
435 bool do_blur = blur_amount >= 1.0f;
440 sinf(
data->shadow_angle) * line_height *
data->shadow_offset);
442 rcti shadow_rect = rect;
452 const int half_size = int(blur_amount + 0.5f);
455 BLI_rcti_pad(&shadow_rect, half_size + 1, half_size + 1);
462 const int y_first = y_range.
first();
463 const int y_size = y_range.
size();
476 const int y_first = y_range.
first();
477 const int y_size = y_range.
size();
517 for (
const int64_t y : sub_y_range) {
518 size_t index =
y *
size.x;
525 float minimum_squared_distance = std::numeric_limits<float>::max();
526 for (
int dy = -step_size; dy <= step_size; dy += step_size) {
528 if (yy < 0 || yy >=
size.y) {
531 for (
int dx = -step_size; dx <= step_size; dx += step_size) {
533 if (xx < 0 || xx >=
size.x) {
542 if (squared_distance < minimum_squared_distance) {
543 minimum_squared_distance = squared_distance;
549 output[index +
x] = closest_texel;
581 const int outline_width = int(runtime->
line_height * 0.5f *
data->outline_width);
582 if (outline_width < 1 || data->outline_color[3] <= 0.0f ||
591 const size_t pixel_count = size_t(
size.x) *
size.y;
598 out->byte_buffer.colorspace);
603 BLI_rcti_pad(&outline_rect, outline_width + 1, outline_width + 1);
615 for (const int y : y_range) {
616 size_t index = size_t(y) * size.x;
617 for (int x = 0; x < size.x; x++, index++) {
618 bool is_opaque = tmp_buf[index].w >= 128;
620 coord.x = is_opaque ? x : JFA_INVALID;
621 coord.y = is_opaque ? y : JFA_INVALID;
622 boundary[index] = coord;
638 while (step_size != 0) {
640 *result_to_flood, *result_after_flooding,
size, rect_x_range, rect_y_range, step_size);
641 std::swap(result_to_flood, result_after_flooding);
651 const float text_color_alpha =
data->color[3];
657 for (
const int y : y_range) {
658 size_t index = size_t(
y) *
size.x + rect_x_range.start();
659 uchar *dst =
out->byte_buffer.data + index * 4;
660 for (
int x = rect_x_range.start();
x < rect_x_range.one_after_last();
x++, index++, dst += 4)
662 JFACoord closest_texel = (*result_to_flood)[index];
681 float text_alpha = tmp_buf[index].w * (1.0f / 255.0f);
682 float mul_opaque_text = text_alpha >= 1.0f ? 0.0f : 1.0f;
683 float mul_transparent_text = 1.0f - text_alpha;
691 float mfac = 1.0f - col1.
w;
699 runtime->font,
nullptr,
out->byte_buffer.data,
size.x,
size.y,
out->byte_buffer.colorspace);
707 const ImBuf *ibuf,
const float col[4],
int x1,
int y1,
int x2,
int y2,
float corner_radius)
709 const int width = ibuf->
x;
710 const int height = ibuf->
y;
721 if (x1 == x2 || y1 == y2) {
731 for (
const int y : y_range) {
733 float origin_x = 0.0f, origin_y = 0.0f;
734 for (
int x = x1;
x < x2;
x++) {
736 float fac = 1.0f - pix.w;
738 float4 premul_col = premul_col_base;
739 bool is_corner =
false;
740 if (
x < x1 + corner_radius &&
y < y1 + corner_radius) {
742 origin_x = x1 + corner_radius - 1;
743 origin_y = y1 + corner_radius - 1;
745 else if (
x >= x2 - corner_radius &&
y < y1 + corner_radius) {
747 origin_x = x2 - corner_radius;
748 origin_y = y1 + corner_radius - 1;
752 origin_x = x1 + corner_radius - 1;
753 origin_y = y2 - corner_radius;
755 else if (
x >= x2 - corner_radius &&
y >= y2 - corner_radius) {
757 origin_x = x2 - corner_radius;
758 origin_y = y2 - corner_radius;
765 constexpr float curve_pow = 2.1f;
768 float alpha =
math::clamp(corner_radius - r, 0.0f, 1.0f);
772 float4 dst_fl = fac * premul_col + pix;
785 if (context ==
nullptr) {
786 return data->text_size;
791 return size_scale *
data->text_size;
805 data->text_blf_id = -1;
810 if (
data->text_blf_id >= 0) {
811 font =
data->text_blf_id;
822 const int len_max =
data->text_len_bytes;
831 while (byte_offset <= len_max) {
832 const char *
str =
data->text_ptr + byte_offset;
836 char_info.
index = char_index;
837 char_info.
offset = byte_offset;
840 characters.
append(char_info);
842 byte_offset += char_length;
855 if (
data->wrap_width == 0.0f) {
856 return std::numeric_limits<int>::max();
858 return data->wrap_width * image_size.x;
864 const int2 image_size,
869 float2 char_position{0.0f, 0.0f};
873 for (
CharInfo &character : characters) {
874 char ch =
data->text_ptr[character.offset];
876 character.position = char_position;
877 last_space = &character;
881 last_space =
nullptr;
883 if (ch !=
'\0' && char_position.x > wrap_width && last_space !=
nullptr) {
887 char_position.x += character.advance_x;
891 char_position = {0.0f, 0.0f};
893 for (
CharInfo &character : characters) {
894 character.position = char_position;
895 runtime->
lines.last().characters.append(character);
896 runtime->
lines.last().width = char_position.x;
898 char_position.x += character.advance_x;
900 if (character.do_wrap ||
data->text_ptr[character.offset] ==
'\n') {
917 const char *buf = &
data->text_ptr[last_visible_char.
offset];
927 for (
const LineInfo &line : lines) {
928 width_max = std::max(width_max, line.width);
937 const float line_offset = (width_max - line_width);
940 return {line_offset, 0.0f};
943 return {line_offset / 2.0f, 0.0f};
953 switch (
data->anchor_x) {
958 anchor_offset.x = -width_max / 2.0f;
961 anchor_offset.x = -width_max;
964 switch (
data->anchor_y) {
969 anchor_offset.y = text_height / 2.0f;
972 anchor_offset.y = text_height;
976 return anchor_offset;
982 rctf glyph_bounds_max;
984 const int text_height = (runtime->
lines.size() - 1) * runtime->
line_height +
990 if (width_max == 0) {
991 width_max = text_height * 2;
994 const float2 image_center{
data->loc[0] * image_size.x,
data->loc[1] * image_size.y};
1005 const int2 image_size)
1010 const float2 image_center{
data->loc[0] * image_size.x,
data->loc[1] * image_size.y};
1011 const float2 line_height_offset{0.0f,
1017 const float2 alignment =
math::round(image_center + line_height_offset + alignment_x + anchor);
1030 runtime->
font = font;
1063 if (
data->runtime !=
nullptr) {
1064 MEM_delete(
data->runtime);
1068 data->runtime = runtime;
1073 BLF_buffer(font,
nullptr,
nullptr, 0, 0,
nullptr);
1083 if (
out->byte_buffer.data) {
1084 const int margin =
data->box_margin *
out->x;
1089 float corner_radius =
data->box_roundness * (maxy - miny) / 2.0f;
void BKE_id_full_name_get(char name[MAX_ID_FULL_NAME], const ID *id, char separator_char)
@ LIB_ID_CREATE_NO_USER_REFCOUNT
int BLF_load_mem_unique(const char *name, const unsigned char *mem, int mem_size) ATTR_NONNULL(1
void BLF_size(int fontid, float size)
int BLF_descender(int fontid) ATTR_WARN_UNUSED_RESULT
void BLF_enable(int fontid, FontFlags flag)
void BLF_addref_id(int fontid)
void BLF_buffer(int fontid, float *fbuf, unsigned char *cbuf, int w, int h, const ColorSpace *colorspace)
bool BLF_bounds_max(int fontid, rctf *r_bounds) ATTR_NONNULL(2)
void BLF_draw_buffer(int fontid, const char *str, size_t str_len, ResultBLF *r_info=nullptr) ATTR_NONNULL(2)
bool BLF_is_loaded_id(int fontid) ATTR_WARN_UNUSED_RESULT
int BLF_glyph_advance(int fontid, const char *str)
void BLF_buffer_col(int fontid, const float srgb_color[4]) ATTR_NONNULL(2)
int BLF_load_unique(const char *filepath) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
float BLF_width(int fontid, const char *str, size_t str_len, ResultBLF *r_info=nullptr) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(2)
void BLF_disable(int fontid, FontFlags flag)
bool BLF_unload_id(int fontid)
bool BLF_is_builtin(int fontid)
int BLF_height_max(int fontid) ATTR_WARN_UNUSED_RESULT
void BLF_position(int fontid, float x, float y, float z)
MINLINE int power_of_2_max_i(int n)
MINLINE int clamp_i(int value, int min, int max)
MINLINE void straight_to_premul_v4_v4(float premul[4], const float straight[4])
MINLINE void copy_v4_fl(float r[4], float f)
bool BLI_path_abs(char path[FILE_MAX], const char *basepath) ATTR_NONNULL(1
void BLI_rcti_pad(struct rcti *rect, int pad_x, int pad_y)
void BLI_rcti_translate(struct rcti *rect, int x, int y)
BLI_INLINE float BLI_rctf_size_y(const struct rctf *rct)
char * BLI_strdup(const char *str) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC
char * BLI_strdup_null(const char *str) ATTR_WARN_UNUSED_RESULT ATTR_MALLOC
char * STRNCPY(char(&dst)[N], const char *src)
int BLI_str_utf8_size_safe(const char *p) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
size_t BLI_strlen_utf8(const char *strc) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT
#define ID_BLEND_PATH_FROM_GLOBAL(_id)
@ SEQ_TEXT_ALIGN_X_CENTER
@ SEQ_TEXT_ALIGN_Y_BOTTOM
@ SEQ_TEXT_ALIGN_Y_CENTER
#define STRIP_FONT_NOT_LOADED
BMesh const char void * data
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
static void mul(btAlignedObjectArray< T > &items, const Q &value)
constexpr int64_t first() const
constexpr int64_t size() const
static constexpr IndexRange from_begin_end(const int64_t begin, const int64_t end)
void append(const T &value)
#define pf(_x, _i)
Prefetch 64.
float distance(VecOp< float, D >, VecOp< float, D >) RET
void * MEM_callocN(size_t len, const char *str)
void * MEM_dupallocN(const void *vmemh)
void MEM_freeN(void *vmemh)
T clamp(const T &a, const T &min, const T &max)
T distance(const T &a, const T &b)
T min(const T &a, const T &b)
T interpolate(const T &a, const T &b, const FactorT &t)
T distance_squared(const VecBase< T, Size > &a, const VecBase< T, Size > &b)
T max(const T &a, const T &b)
int text_effect_font_init(const RenderData *context, const Strip *strip, FontFlags font_flags)
static float2 horizontal_alignment_offset_get(const TextVars *data, float line_width, int width_max)
static int wrap_width_get(const TextVars *data, const int2 image_size)
static int text_effect_line_size_get(const RenderData *context, const Strip *strip)
static ImBuf * do_text_effect(const RenderData *context, SeqRenderState *, Strip *strip, float, float, ImBuf *, ImBuf *)
TextVarsRuntime * text_effect_calc_runtime(const Strip *strip, int font, const int2 image_size)
static void calc_boundbox(const TextVars *data, TextVarsRuntime *runtime, const int2 image_size)
static void initialize_shadow_alpha(int width, int height, int2 offset, const rcti &shadow_rect, const uchar *input, Array< uchar > &r_shadow_mask)
static void text_draw(const char *text_ptr, const TextVarsRuntime *runtime, float color[4])
void text_effect_get_handle(EffectHandle &rval)
float get_render_scale_factor(eSpaceSeq_Proxy_RenderSize render_size, short scene_render_scale)
Array< float > make_gaussian_blur_kernel(float rad, int size)
void store_premul_pixel(const blender::float4 &pix, uchar *dst)
ImBuf * prepare_effect_imbufs(const RenderData *context, ImBuf *ibuf1, ImBuf *ibuf2, bool uninitialized_pixels)
static Vector< CharInfo > build_character_info(const TextVars *data, int font)
static float2 anchor_offset_get(const TextVars *data, int width_max, int text_height)
blender::float4 load_premul_pixel(const uchar *ptr)
static SeqFontMap g_font_map
static void init_text_effect(Strip *strip)
static StripEarlyOut early_out_text(const Strip *strip, float)
void effect_text_font_load(TextVars *data, const bool do_id_user)
bool effects_can_render_text(const Strip *strip)
static void jump_flooding_pass(Span< JFACoord > input, MutableSpan< JFACoord > output, int2 size, IndexRange x_range, IndexRange y_range, int step_size)
static void apply_word_wrapping(const TextVars *data, TextVarsRuntime *runtime, const int2 image_size, Vector< CharInfo > &characters)
static void composite_shadow(int width, const rcti &shadow_rect, const float4 &shadow_color, const Array< uchar > &shadow_mask, uchar *output)
static void load_text_effect(Strip *strip)
static void apply_text_alignment(const TextVars *data, TextVarsRuntime *runtime, const int2 image_size)
static int num_inputs_text()
static rcti draw_text_outline(const RenderData *context, const TextVars *data, const TextVarsRuntime *runtime, ImBuf *out)
static void text_gaussian_blur_y(const Span< float > gaussian, int half_size, int start_line, int width, int height, const uchar *rect, uchar *dst, const rcti &shadow_rect)
static int text_box_width_get(const Vector< LineInfo > &lines)
void effect_text_font_unload(TextVars *data, const bool do_id_user)
static void draw_text_shadow(const RenderData *context, const TextVars *data, int line_height, const rcti &rect, ImBuf *out)
static void text_gaussian_blur_x(const Span< float > gaussian, int half_size, int start_line, int width, int height, const uchar *rect, uchar *dst, const rcti &shadow_rect)
static void free_text_effect(Strip *strip, const bool do_id_user)
static int strip_load_font_mem(const std::string &name, const uchar *data, int data_size)
static void copy_text_effect(Strip *dst, const Strip *src, const int flag)
static void strip_unload_font(int fontid)
static int strip_load_font_file(const std::string &path)
static void fill_rect_alpha_under(const ImBuf *ibuf, const float col[4], int x1, int y1, int x2, int y2, float corner_radius)
constexpr uint16_t JFA_INVALID
static void clamp_rect(int width, int height, rcti &r_rect)
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
blender::VecBase< uint8_t, 4 > uchar4
VecBase< float, 4 > float4
VecBase< int32_t, 2 > int2
VecBase< float, 2 > float2
ImBufByteBuffer byte_buffer
struct PackedFile * packedfile
void(* copy)(Strip *dst, const Strip *src, int flag)
ImBuf *(* execute)(const RenderData *context, SeqRenderState *state, Strip *strip, float timeline_frame, float fac, ImBuf *ibuf1, ImBuf *ibuf2)
void(* free)(Strip *strip, bool do_id_user)
StripEarlyOut(* early_out)(const Strip *strip, float fac)
void(* load)(Strip *seqconst)
void(* init)(Strip *strip)
Vector< CharInfo > characters
Map< std::string, int > path_to_file_font_id
std::recursive_mutex mutex
Map< std::string, int > name_to_mem_font_id