From b3dbe17658fe8ca5115abab642cc0f1680d1f0d5 Mon Sep 17 00:00:00 2001 From: Richard Antalik Date: Sun, 13 Jan 2019 21:28:07 -0800 Subject: Add font selection to VSE text strips Allows users to select a font for text strips in the video sequence editor. Related: 3610f1fc43d0 Sequencer: refactor clipboard copy to no longer increase user count. Reviewed by: Brecht Differential Revision: https://developer.blender.org/D3621 --- source/blender/blenfont/BLF_api.h | 1 + source/blender/blenfont/intern/blf.c | 25 ++++- .../blender/blenfont/intern/blf_internal_types.h | 3 + source/blender/blenkernel/BKE_sequencer.h | 6 +- source/blender/blenkernel/intern/library_query.c | 5 + source/blender/blenkernel/intern/seqeffects.c | 124 +++++++++++++++++---- source/blender/blenkernel/intern/sequencer.c | 6 + source/blender/blenloader/intern/readfile.c | 14 +++ .../editors/interface/interface_templates.c | 2 +- source/blender/makesdna/DNA_sequence_types.h | 7 +- source/blender/makesrna/intern/rna_sequencer.c | 22 ++++ 11 files changed, 188 insertions(+), 27 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenfont/BLF_api.h b/source/blender/blenfont/BLF_api.h index 8a3728574f3..75afa0e3018 100644 --- a/source/blender/blenfont/BLF_api.h +++ b/source/blender/blenfont/BLF_api.h @@ -51,6 +51,7 @@ void BLF_batch_reset(void); /* call when changing opengl context. */ void BLF_cache_clear(void); +/* Loads a font, or returns an already loaded font and increments its reference count. */ int BLF_load(const char *name) ATTR_NONNULL(); int BLF_load_mem(const char *name, const unsigned char *mem, int mem_size) ATTR_NONNULL(); diff --git a/source/blender/blenfont/intern/blf.c b/source/blender/blenfont/intern/blf.c index 70a7b862830..70478fd1d1c 100644 --- a/source/blender/blenfont/intern/blf.c +++ b/source/blender/blenfont/intern/blf.c @@ -198,7 +198,8 @@ int BLF_load(const char *name) /* check if we already load this font. */ i = blf_search(name); if (i >= 0) { - /*font = global_font[i];*/ /*UNUSED*/ + font = global_font[i]; + font->reference_count++; return i; } @@ -222,6 +223,7 @@ int BLF_load(const char *name) return -1; } + font->reference_count = 1; global_font[i] = font; return i; } @@ -255,6 +257,7 @@ int BLF_load_unique(const char *name) return -1; } + font->reference_count = 1; global_font[i] = font; return i; } @@ -296,6 +299,7 @@ int BLF_load_mem(const char *name, const unsigned char *mem, int mem_size) return -1; } + font->reference_count = 1; global_font[i] = font; return i; } @@ -326,6 +330,7 @@ int BLF_load_mem_unique(const char *name, const unsigned char *mem, int mem_size return -1; } + font->reference_count = 1; global_font[i] = font; return i; } @@ -339,8 +344,13 @@ void BLF_unload(const char *name) font = global_font[i]; if (font && (STREQ(font->name, name))) { - blf_font_free(font); - global_font[i] = NULL; + BLI_assert(font->reference_count > 0); + font->reference_count--; + + if (font->reference_count == 0) { + blf_font_free(font); + global_font[i] = NULL; + } } } } @@ -349,8 +359,13 @@ void BLF_unload_id(int fontid) { FontBLF *font = blf_get(fontid); if (font) { - blf_font_free(font); - global_font[fontid] = NULL; + BLI_assert(font->reference_count > 0); + font->reference_count--; + + if (font->reference_count == 0) { + blf_font_free(font); + global_font[fontid] = NULL; + } } } diff --git a/source/blender/blenfont/intern/blf_internal_types.h b/source/blender/blenfont/intern/blf_internal_types.h index 265835f4c75..14bc081cd10 100644 --- a/source/blender/blenfont/intern/blf_internal_types.h +++ b/source/blender/blenfont/intern/blf_internal_types.h @@ -194,6 +194,9 @@ typedef struct FontBLF { /* font name. */ char *name; + /* # of times this font was loaded */ + unsigned int reference_count; + /* filename or NULL. */ char *filename; diff --git a/source/blender/blenkernel/BKE_sequencer.h b/source/blender/blenkernel/BKE_sequencer.h index 62c56c0dc24..f5c917302ea 100644 --- a/source/blender/blenkernel/BKE_sequencer.h +++ b/source/blender/blenkernel/BKE_sequencer.h @@ -46,6 +46,7 @@ struct Sequence; struct SequenceModifierData; struct Stereo3dFormat; struct StripElem; +struct TextVars; struct bSound; struct SeqIndexBuildContext; @@ -145,7 +146,7 @@ struct SeqEffectHandle { /* load is called first time after readblenfile in * get_sequence_effect automatically */ - void (*load)(struct Sequence *seq); + void (*load)(struct Sequence *seqconst); /* duplicate */ void (*copy)(struct Sequence *dst, struct Sequence *src, const int flag); @@ -301,6 +302,9 @@ void BKE_sequence_effect_speed_rebuild_map(struct Scene *scene, struct Sequence struct SeqEffectHandle BKE_sequence_get_effect(struct Sequence *seq); int BKE_sequence_effect_get_num_inputs(int seq_type); int BKE_sequence_effect_get_supports_mask(int seq_type); +void BKE_sequencer_text_font_unload(struct TextVars *data, const bool do_id_user); +void BKE_sequencer_text_font_load(struct TextVars *data, const bool do_id_user); + /* ********************************************************************** * Sequencer editing functions diff --git a/source/blender/blenkernel/intern/library_query.c b/source/blender/blenkernel/intern/library_query.c index c902aa8c5d5..b3ddb186fa5 100644 --- a/source/blender/blenkernel/intern/library_query.c +++ b/source/blender/blenkernel/intern/library_query.c @@ -425,6 +425,11 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call for (SequenceModifierData *smd = seq->modifiers.first; smd; smd = smd->next) { CALLBACK_INVOKE(smd->mask_id, IDWALK_CB_USER); } + + if (seq->type == SEQ_TYPE_TEXT && seq->effectdata) { + TextVars *text_data = seq->effectdata; + CALLBACK_INVOKE(text_data->text_font, IDWALK_CB_USER); + } } SEQ_END; } diff --git a/source/blender/blenkernel/intern/seqeffects.c b/source/blender/blenkernel/intern/seqeffects.c index 193db2b623f..7203691d7dc 100644 --- a/source/blender/blenkernel/intern/seqeffects.c +++ b/source/blender/blenkernel/intern/seqeffects.c @@ -37,8 +37,10 @@ #include "MEM_guardedalloc.h" #include "BLI_math.h" /* windows needs for M_PI */ +#include "BLI_threads.h" #include "BLI_utildefines.h" #include "BLI_rect.h" +#include "BLI_path_util.h" #include "BLI_string.h" #include "DNA_scene_types.h" @@ -47,6 +49,8 @@ #include "DNA_space_types.h" #include "BKE_fcurve.h" +#include "BKE_library.h" +#include "BKE_main.h" #include "BKE_sequencer.h" #include "IMB_imbuf_types.h" @@ -3357,6 +3361,7 @@ static ImBuf *do_gaussian_blur_effect( } /*********************** text *************************/ + static void init_text_effect(Sequence *seq) { TextVars *data; @@ -3365,6 +3370,8 @@ static void init_text_effect(Sequence *seq) MEM_freeN(seq->effectdata); data = seq->effectdata = MEM_callocN(sizeof(TextVars), "textvars"); + data->text_font = NULL; + data->text_blf_id = -1; data->text_size = 30; copy_v4_fl(data->color, 1.0f); @@ -3377,6 +3384,64 @@ static void init_text_effect(Sequence *seq) data->align_y = SEQ_TEXT_ALIGN_Y_BOTTOM; } +void BKE_sequencer_text_font_unload(TextVars *data, const bool do_id_user) +{ + if (data) { + /* Unlink the VFont */ + if (do_id_user && data->text_font != NULL) { + id_us_min(&data->text_font->id); + data->text_font = NULL; + } + + /* Unload the BLF font. */ + if (data->text_blf_id >= 0) { + BLF_unload_id(data->text_blf_id); + } + } +} + +void BKE_sequencer_text_font_load(TextVars *data, const bool do_id_user) +{ + if (data->text_font != NULL) { + if (do_id_user) { + id_us_plus(&data->text_font->id); + } + + char path[FILE_MAX]; + STRNCPY(path, data->text_font->name); + BLI_assert(BLI_thread_is_main()); + BLI_path_abs(path, BKE_main_blendfile_path_from_global()); + + data->text_blf_id = BLF_load(path); + } +} + +static void free_text_effect(Sequence *seq, const bool do_id_user) +{ + TextVars *data = seq->effectdata; + BKE_sequencer_text_font_unload(data, do_id_user); + + if (data) { + MEM_freeN(data); + seq->effectdata = NULL; + } +} + +static void load_text_effect(Sequence *seq) +{ + TextVars *data = seq->effectdata; + BKE_sequencer_text_font_load(data, false); +} + +static void copy_text_effect(Sequence *dst, Sequence *src, const int flag) +{ + dst->effectdata = MEM_dupallocN(src->effectdata); + TextVars *data = dst->effectdata; + + data->text_blf_id = -1; + BKE_sequencer_text_font_load(data, (flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0); +} + static int num_inputs_text(void) { return 0; @@ -3403,11 +3468,23 @@ static ImBuf *do_text_effect( int height = out->y; struct ColorManagedDisplay *display; const char *display_device; - const int mono = blf_mono_font_render; // XXX + int font = blf_mono_font_render; int line_height; int y_ofs, x, y; float proxy_size_comp; + if (data->text_blf_id == SEQ_FONT_NOT_LOADED) { + data->text_blf_id = -1; + + if (data->text_font) { + data->text_blf_id = BLF_load(data->text_font->name); + } + } + + if (data->text_blf_id >= 0) { + font = data->text_blf_id; + } + display_device = context->scene->display_settings.display_device; display = IMB_colormanagement_display_get_named(display_device); @@ -3423,18 +3500,18 @@ static ImBuf *do_text_effect( } /* set before return */ - BLF_size(mono, proxy_size_comp * data->text_size, 72); + BLF_size(font, proxy_size_comp * data->text_size, 72); - BLF_enable(mono, BLF_WORD_WRAP); + BLF_enable(font, BLF_WORD_WRAP); /* use max width to enable newlines only */ - BLF_wordwrap(mono, (data->wrap_width != 0.0f) ? data->wrap_width * width : -1); + BLF_wordwrap(font, (data->wrap_width != 0.0f) ? data->wrap_width * width : -1); - BLF_buffer(mono, out->rect_float, (unsigned char *)out->rect, width, height, out->channels, display); + BLF_buffer(font, out->rect_float, (unsigned char *)out->rect, width, height, out->channels, display); - line_height = BLF_height_max(mono); + line_height = BLF_height_max(font); - y_ofs = -BLF_descender(mono); + y_ofs = -BLF_descender(font); x = (data->loc[0] * width); y = (data->loc[1] * height) + y_ofs; @@ -3451,7 +3528,7 @@ static ImBuf *do_text_effect( rctf rect; } wrap; - BLF_boundbox_ex(mono, data->text, sizeof(data->text), &wrap.rect, &wrap.info); + BLF_boundbox_ex(font, data->text, sizeof(data->text), &wrap.rect, &wrap.info); if (data->align == SEQ_TEXT_ALIGN_X_RIGHT) { x -= BLI_rctf_size_x(&wrap.rect); @@ -3474,19 +3551,20 @@ static ImBuf *do_text_effect( /* BLF_SHADOW won't work with buffers, instead use cheap shadow trick */ if (data->flag & SEQ_TEXT_SHADOW) { int fontx, fonty; - fontx = BLF_width_max(mono); + fontx = BLF_width_max(font); fonty = line_height; - BLF_position(mono, x + max_ii(fontx / 25, 1), y + max_ii(fonty / 25, 1), 0.0f); - BLF_buffer_col(mono, data->shadow_color); - BLF_draw_buffer(mono, data->text, BLF_DRAW_STR_DUMMY_MAX); + BLF_position(font, x + max_ii(fontx / 25, 1), y + max_ii(fonty / 25, 1), 0.0f); + BLF_buffer_col(font, data->shadow_color); + BLF_draw_buffer(font, data->text, BLF_DRAW_STR_DUMMY_MAX); } - BLF_position(mono, x, y, 0.0f); - BLF_buffer_col(mono, data->color); - BLF_draw_buffer(mono, data->text, BLF_DRAW_STR_DUMMY_MAX); - BLF_buffer(mono, NULL, NULL, 0, 0, 0, NULL); + BLF_position(font, x, y, 0.0f); + BLF_buffer_col(font, data->color); + BLF_draw_buffer(font, data->text, BLF_DRAW_STR_DUMMY_MAX); - BLF_disable(mono, BLF_WORD_WRAP); + BLF_buffer(font, NULL, NULL, 0, 0, 0, NULL); + + BLF_disable(font, BLF_WORD_WRAP); return out; } @@ -3733,8 +3811,9 @@ static struct SeqEffectHandle get_sequence_effect_impl(int seq_type) case SEQ_TYPE_TEXT: rval.num_inputs = num_inputs_text; rval.init = init_text_effect; - rval.free = free_effect_default; - rval.copy = copy_effect_default; + rval.free = free_text_effect; + rval.load = load_text_effect; + rval.copy = copy_text_effect; rval.early_out = early_out_text; rval.execute = do_text_effect; break; @@ -3763,8 +3842,15 @@ struct SeqEffectHandle BKE_sequence_get_blend(Sequence *seq) struct SeqEffectHandle rval = {false, false, NULL}; if (seq->blend_mode != 0) { + if ((seq->flag & SEQ_EFFECT_NOT_LOADED) != 0) { + /* load the effect first */ + rval = get_sequence_effect_impl(seq->type); + rval.load(seq); + } + rval = get_sequence_effect_impl(seq->blend_mode); if ((seq->flag & SEQ_EFFECT_NOT_LOADED) != 0) { + /* now load the blend and unset unloaded flag */ rval.load(seq); seq->flag &= ~SEQ_EFFECT_NOT_LOADED; } diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index 0f3f35477af..630921f71d1 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -401,7 +401,13 @@ static void sequence_clipboard_pointers(Main *bmain, Sequence *seq, void (*callb callback(bmain, (ID **)&seq->clip); callback(bmain, (ID **)&seq->mask); callback(bmain, (ID **)&seq->sound); + + if (seq->type == SEQ_TYPE_TEXT && seq->effectdata) { + TextVars *text_data = seq->effectdata; + callback(bmain, (ID **)&text_data->text_font); + } } + /* recursive versions of functions above */ void BKE_sequencer_base_clipboard_pointers_free(ListBase *seqbase) { diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 4029f9f9a31..c27e70c9a7e 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -6061,6 +6061,10 @@ static void lib_link_scene(FileData *fd, Main *main) seq->scene_sound = BKE_sound_add_scene_sound_defaults(sce, seq); } } + if (seq->type == SEQ_TYPE_TEXT) { + TextVars *t = seq->effectdata; + t->text_font = newlibadr_us(fd, sce->id.lib, t->text_font); + } BLI_listbase_clear(&seq->anims); lib_link_sequence_modifiers(fd, sce, &seq->modifiers); @@ -6314,6 +6318,11 @@ static void direct_link_scene(FileData *fd, Scene *sce) s->frameMap = NULL; } + if (seq->type == SEQ_TYPE_TEXT) { + TextVars *t = seq->effectdata; + t->text_blf_id = SEQ_FONT_NOT_LOADED; + } + seq->prop = newdataadr(fd, seq->prop); IDP_DirectLinkGroup_OrFree(&seq->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); @@ -9951,6 +9960,11 @@ static void expand_scene(FileData *fd, Main *mainvar, Scene *sce) if (seq->clip) expand_doit(fd, mainvar, seq->clip); if (seq->mask) expand_doit(fd, mainvar, seq->mask); if (seq->sound) expand_doit(fd, mainvar, seq->sound); + + if (seq->type == SEQ_TYPE_TEXT && seq->effectdata) { + TextVars *data = seq->effectdata; + expand_doit(fd, mainvar, data->text_font); + } } SEQ_END; } diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 8b6339c73ca..7cf68a144b2 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -802,7 +802,7 @@ static void template_ID( but = NULL; if (unlinkop) { - but = uiDefIconButO(block, UI_BTYPE_BUT, unlinkop, WM_OP_INVOKE_REGION_WIN, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL); + but = uiDefIconButO(block, UI_BTYPE_BUT, unlinkop, WM_OP_INVOKE_DEFAULT, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL); /* so we can access the template from operators, font unlinking needs this */ UI_but_funcN_set(but, NULL, MEM_dupallocN(template_ui), NULL); } diff --git a/source/blender/makesdna/DNA_sequence_types.h b/source/blender/makesdna/DNA_sequence_types.h index 10cd4697283..186e6955342 100644 --- a/source/blender/makesdna/DNA_sequence_types.h +++ b/source/blender/makesdna/DNA_sequence_types.h @@ -45,6 +45,7 @@ #include "DNA_color_types.h" #include "DNA_listBase.h" #include "DNA_vec_types.h" +#include "DNA_vfont_types.h" struct Ipo; struct Scene; @@ -320,13 +321,15 @@ typedef struct GaussianBlurVars { typedef struct TextVars { char text[512]; + VFont *text_font; + int text_blf_id; int text_size; float color[4], shadow_color[4]; float loc[2]; float wrap_width; char flag; char align, align_y; - char pad[5]; + char pad[1]; } TextVars; /* TextVars.flag */ @@ -348,6 +351,8 @@ enum { SEQ_TEXT_ALIGN_Y_BOTTOM = 2, }; +#define SEQ_FONT_NOT_LOADED -2 + typedef struct ColorMixVars { /** Value from SEQ_TYPE_XXX enumeration. */ int blend_effect; diff --git a/source/blender/makesrna/intern/rna_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c index 433ca729c65..e39a5e57933 100644 --- a/source/blender/makesrna/intern/rna_sequencer.c +++ b/source/blender/makesrna/intern/rna_sequencer.c @@ -32,6 +32,7 @@ #include "DNA_scene_types.h" #include "DNA_sequence_types.h" #include "DNA_movieclip_types.h" +#include "DNA_vfont_types.h" #include "BLI_math.h" @@ -461,6 +462,19 @@ static void rna_SequenceCrop_update(Main *UNUSED(bmain), Scene *UNUSED(scene), P BKE_sequence_invalidate_cache(scene, seq); } +static void rna_Sequence_text_font_set(PointerRNA *ptr, PointerRNA ptr_value) +{ + Sequence *seq = ptr->data; + TextVars *data = seq->effectdata; + VFont *value = ptr_value.data; + + BKE_sequencer_text_font_unload(data, true); + + id_us_plus(&value->id); + data->text_blf_id = SEQ_FONT_NOT_LOADED; + data->text_font = value; +} + /* name functions that ignore the first two characters */ static void rna_Sequence_name_get(PointerRNA *ptr, char *value) { @@ -2407,6 +2421,14 @@ static void rna_def_text(StructRNA *srna) RNA_def_struct_sdna_from(srna, "TextVars", "effectdata"); + prop = RNA_def_property(srna, "font", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "text_font"); + RNA_def_property_ui_icon(prop, ICON_FILE_FONT, false); + RNA_def_property_ui_text(prop, "Font", "Font of the text. Falls back to the UI font by default"); + RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_pointer_funcs(prop, NULL, "rna_Sequence_text_font_set", NULL, NULL); + RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + prop = RNA_def_property(srna, "font_size", PROP_INT, PROP_UNSIGNED); RNA_def_property_int_sdna(prop, NULL, "text_size"); RNA_def_property_ui_text(prop, "Size", "Size of the text"); -- cgit v1.2.3