Files
test/source/blender/sequencer/SEQ_effects.hh
Richard Antalik 77a5478c0f VSE: Add text alignment feature
Previously, alignment did exist, but it only changed whole text block
position in relation to a fixed point. This was later renamed to "Anchor".
Now it correctly aligns each line of text. Alignment works with newline
character and word wrapping.
Currently newline characters can't be entered directly, but this should
be resolved soon.

To keep existing anchoring feature, new DNA fields are added and
values from old alignment are copied there.

This PR is part of bigger change [1], and originally I expected to
implement this feature at later stage. But the design called for drawing
text character by character, which would mean, that I would have to
rewrite text alignment anyway.

To render the text, a struct is built, where position and width of each
character is stored. In addition, width of each line is stored. This allows
to implement proper text alignment feature, instead of existing
anchoring. Text is then drawn character by character in a loop.

There are some small differences in text rendering, since this is only
approximation of how BLF library draws glyphs, but it is very close.
For text bounbox, `BLF_boundbox()` is used on per line basis,
because some fonts do not use their full height and this information
is not available on VSE side.

[1] https://projects.blender.org/blender/blender/issues/126547

Pull Request: https://projects.blender.org/blender/blender/pulls/126660
2024-10-04 12:20:33 +02:00

122 lines
3.0 KiB
C++

/* SPDX-FileCopyrightText: 2004 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
#include "BLI_math_vector_types.hh"
#include "BLI_vector.hh"
/** \file
* \ingroup sequencer
*/
struct ImBuf;
struct SeqRenderData;
struct Sequence;
struct TextVars;
enum class StripEarlyOut {
NoInput = -1, /* No input needed. */
DoEffect = 0, /* No early out (do the effect). */
UseInput1 = 1, /* Output = input1. */
UseInput2 = 2, /* Output = input2. */
};
/* Wipe effect */
enum {
DO_SINGLE_WIPE,
DO_DOUBLE_WIPE,
/* DO_BOX_WIPE, */ /* UNUSED */
/* DO_CROSS_WIPE, */ /* UNUSED */
DO_IRIS_WIPE,
DO_CLOCK_WIPE,
};
struct SeqEffectHandle {
bool multithreaded;
bool supports_mask;
/* constructors & destructor */
/* init is _only_ called on first creation */
void (*init)(Sequence *seq);
/* number of input strips needed
* (called directly after construction) */
int (*num_inputs)();
/* load is called first time after readblenfile in
* get_sequence_effect automatically */
void (*load)(Sequence *seqconst);
/* duplicate */
void (*copy)(Sequence *dst, const Sequence *src, int flag);
/* destruct */
void (*free)(Sequence *seq, bool do_id_user);
StripEarlyOut (*early_out)(const Sequence *seq, float fac);
/* sets the default `fac` value */
void (*get_default_fac)(const Scene *scene,
const Sequence *seq,
float timeline_frame,
float *fac);
/* execute the effect
* sequence effects are only required to either support
* float-rects or byte-rects
* (mixed cases are handled one layer up...) */
ImBuf *(*execute)(const SeqRenderData *context,
Sequence *seq,
float timeline_frame,
float fac,
ImBuf *ibuf1,
ImBuf *ibuf2);
ImBuf *(*init_execution)(const SeqRenderData *context, ImBuf *ibuf1, ImBuf *ibuf2);
void (*execute_slice)(const SeqRenderData *context,
Sequence *seq,
float timeline_frame,
float fac,
const ImBuf *ibuf1,
const ImBuf *ibuf2,
int start_line,
int total_lines,
ImBuf *out);
};
SeqEffectHandle SEQ_effect_handle_get(Sequence *seq);
int SEQ_effect_get_num_inputs(int seq_type);
void SEQ_effect_text_font_unload(TextVars *data, bool do_id_user);
void SEQ_effect_text_font_load(TextVars *data, bool do_id_user);
namespace blender::seq {
struct CharInfo {
const char *str_ptr = nullptr;
int byte_length = 0;
float2 position{0.0f, 0.0f};
int advance_x = 0;
bool do_wrap = false;
};
struct LineInfo {
Vector<CharInfo> characters;
int width;
};
struct TextVarsRuntime {
Vector<LineInfo> lines;
rcti text_boundbox;
int line_height;
int font_descender;
int character_count;
int font;
};
} // namespace blender::seq