|
31 | 31 | #include <QtCore5Compat/QTextCodec> |
32 | 32 | #endif |
33 | 33 |
|
34 | | -#include <QMutexLocker> |
35 | 34 | #include "typewriter.h" |
36 | 35 | #include <string> |
| 36 | +#include <QMutexLocker> |
37 | 37 |
|
38 | 38 | static QMutex g_mutex; |
39 | 39 |
|
40 | 40 | struct TypewriterFilterData |
41 | 41 | { |
42 | 42 | TypeWriter typewriter; |
43 | | - bool enabled; |
44 | 43 | std::string original_text; |
45 | | - int last_frame; |
46 | | - |
47 | | - TypewriterFilterData() : enabled(false), last_frame(-1) {} |
| 44 | + int macro_type; |
| 45 | + |
| 46 | + TypewriterFilterData() {} |
48 | 47 | }; |
49 | 48 |
|
50 | 49 | static void close_typewriter_filter_data(void *data) |
51 | 50 | { |
52 | 51 | delete static_cast<TypewriterFilterData *>(data); |
53 | 52 | } |
54 | 53 |
|
55 | | -static std::string get_typewriter_text_for_filter(mlt_properties filter_properties, const char *original_text, mlt_position position) |
| 54 | +static std::string get_typewriter_text_for_filter(mlt_properties filter_properties, |
| 55 | + const char *original_text, |
| 56 | + mlt_position position) |
56 | 57 | { |
57 | 58 | if (!mlt_properties_get_int(filter_properties, "typewriter") || !original_text) { |
58 | 59 | return original_text ? std::string(original_text) : std::string(""); |
59 | 60 | } |
60 | | - |
61 | | - TypewriterFilterData *tw_data = static_cast<TypewriterFilterData *>( |
| 61 | + |
| 62 | + auto *tw_data = static_cast<TypewriterFilterData *>( |
62 | 63 | mlt_properties_get_data(filter_properties, "_typewriter_filter_data", NULL)); |
63 | | - |
| 64 | + |
64 | 65 | if (!tw_data) { |
65 | 66 | tw_data = new TypewriterFilterData(); |
66 | | - mlt_properties_set_data(filter_properties, "_typewriter_filter_data", |
67 | | - static_cast<void *>(tw_data), 0, |
68 | | - close_typewriter_filter_data, NULL); |
| 67 | + mlt_properties_set_data(filter_properties, |
| 68 | + "_typewriter_filter_data", |
| 69 | + static_cast<void *>(tw_data), |
| 70 | + 0, |
| 71 | + close_typewriter_filter_data, |
| 72 | + NULL); |
69 | 73 | } |
70 | | - |
71 | | - std::string text_str = std::string(original_text); |
72 | | - |
| 74 | + |
| 75 | + auto text_str = std::string(original_text); |
| 76 | + unsigned int step_length = mlt_properties_get_int(filter_properties, "typewriter.step_length"); |
| 77 | + unsigned int step_sigma = mlt_properties_get_int(filter_properties, "typewriter.step_sigma"); |
| 78 | + unsigned int random_seed = mlt_properties_get_int(filter_properties, "typewriter.random_seed"); |
| 79 | + int macro_type = mlt_properties_get_int(filter_properties, "typewriter.macro_type"); |
| 80 | + |
73 | 81 | // Check if text or typewriter settings changed |
74 | | - if (tw_data->original_text != text_str || tw_data->last_frame != position) { |
75 | | - if (tw_data->original_text != text_str) { |
76 | | - tw_data->original_text = text_str; |
77 | | - tw_data->typewriter.setPattern(text_str); |
78 | | - |
79 | | - int step_length = mlt_properties_get_int(filter_properties, "typewriter.step_length"); |
80 | | - int step_sigma = mlt_properties_get_int(filter_properties, "typewriter.step_sigma"); |
81 | | - int random_seed = mlt_properties_get_int(filter_properties, "typewriter.random_seed"); |
82 | | - int macro_type = mlt_properties_get_int(filter_properties, "typewriter.macro_type"); |
83 | | - |
84 | | - if (step_length <= 0) step_length = 25; |
85 | | - |
86 | | - tw_data->typewriter.setFrameStep(step_length); |
87 | | - tw_data->typewriter.setStepSigma(step_sigma); |
88 | | - tw_data->typewriter.setStepSeed(random_seed); |
89 | | - |
90 | | - // Apply macro type if specified |
91 | | - if (macro_type > 0) { |
92 | | - char *buff = new char[text_str.length() + 10]; |
93 | | - char c = 0; |
94 | | - switch (macro_type) { |
95 | | - case 1: c = 'c'; break; // character |
96 | | - case 2: c = 'w'; break; // word |
97 | | - case 3: c = 'l'; break; // line |
98 | | - default: break; |
99 | | - } |
100 | | - if (c != 0) { |
101 | | - sprintf(buff, ":%c{%s}", c, text_str.c_str()); |
102 | | - tw_data->typewriter.setPattern(std::string(buff)); |
103 | | - } |
104 | | - delete[] buff; |
| 82 | + if (tw_data->original_text != text_str || tw_data->typewriter.getFrameStep() != step_length |
| 83 | + || tw_data->typewriter.getStepSigma() != step_sigma |
| 84 | + || tw_data->typewriter.getStepSeed() != random_seed || tw_data->macro_type != macro_type) { |
| 85 | + tw_data->original_text = text_str; |
| 86 | + tw_data->typewriter.setPattern(text_str); |
| 87 | + |
| 88 | + if (step_length == 0) |
| 89 | + step_length = 25; |
| 90 | + |
| 91 | + tw_data->typewriter.setFrameStep(step_length); |
| 92 | + tw_data->typewriter.setStepSigma(step_sigma); |
| 93 | + tw_data->typewriter.setStepSeed(random_seed); |
| 94 | + tw_data->macro_type = macro_type; |
| 95 | + |
| 96 | + // Apply macro type if specified |
| 97 | + if (macro_type > 0) { |
| 98 | + char *buff = new char[text_str.length() + 10]; |
| 99 | + char c = 0; |
| 100 | + switch (macro_type) { |
| 101 | + case 1: |
| 102 | + c = 'c'; |
| 103 | + break; // character |
| 104 | + case 2: |
| 105 | + c = 'w'; |
| 106 | + break; // word |
| 107 | + case 3: |
| 108 | + c = 'l'; |
| 109 | + break; // line |
| 110 | + default: |
| 111 | + break; |
| 112 | + } |
| 113 | + if (c != 0) { |
| 114 | + sprintf(buff, ":%c{%s}", c, text_str.c_str()); |
| 115 | + tw_data->typewriter.setPattern(std::string(buff)); |
105 | 116 | } |
106 | | - |
107 | | - tw_data->typewriter.parse(); |
| 117 | + delete[] buff; |
108 | 118 | } |
109 | | - tw_data->last_frame = position; |
| 119 | + |
| 120 | + tw_data->typewriter.parse(); |
110 | 121 | } |
111 | | - |
| 122 | + |
112 | 123 | std::string rendered_text = tw_data->typewriter.render(position); |
113 | | - |
| 124 | + |
114 | 125 | // Add blinking cursor if enabled |
115 | | - int cursor_enabled = mlt_properties_get_int(filter_properties, "typewriter.cursor"); |
| 126 | + auto cursor_enabled = mlt_properties_get_int(filter_properties, "typewriter.cursor"); |
116 | 127 | if (cursor_enabled) { |
117 | | - int cursor_blink_rate = mlt_properties_get_int(filter_properties, "typewriter.cursor_blink_rate"); |
118 | | - if (cursor_blink_rate < 0) cursor_blink_rate = 25; // Default to 25 frames (1 second at 25fps) |
119 | | - |
| 128 | + int cursor_blink_rate = mlt_properties_get_int(filter_properties, |
| 129 | + "typewriter.cursor_blink_rate"); |
| 130 | + if (cursor_blink_rate < 0) |
| 131 | + cursor_blink_rate = 25; // Default to 25 frames (1 second at 25fps) |
| 132 | + |
120 | 133 | // Check if we should show cursor (blink on/off) |
121 | 134 | bool show_cursor = (cursor_blink_rate == 0) || (position / cursor_blink_rate) % 2 == 0; |
122 | | - |
| 135 | + |
123 | 136 | // Only show cursor if text is still being typed or if we're at the end |
124 | 137 | bool still_typing = !tw_data->typewriter.isEnd(); |
125 | | - |
| 138 | + |
126 | 139 | if (still_typing || cursor_enabled == 2) { // 2 = always show cursor |
127 | 140 | char *cursor_char = mlt_properties_get(filter_properties, "typewriter.cursor_char"); |
128 | 141 | if (!show_cursor) { |
129 | | - cursor_char = (char*)" "; |
| 142 | + cursor_char = (char *) " "; |
130 | 143 | } else if (!cursor_char || strlen(cursor_char) == 0) { |
131 | | - cursor_char = (char*)"|"; // Default cursor character |
| 144 | + cursor_char = (char *) "|"; // Default cursor character |
132 | 145 | } |
133 | 146 | rendered_text += cursor_char; |
134 | 147 | } |
135 | 148 | } |
136 | | - |
| 149 | + |
137 | 150 | return rendered_text; |
138 | 151 | } |
139 | 152 |
|
@@ -585,7 +598,7 @@ mlt_filter filter_qtext_init(mlt_profile profile, mlt_service_type type, const c |
585 | 598 | mlt_properties_set_double(filter_properties, "pixel_ratio", 1.0); |
586 | 599 | mlt_properties_set_double(filter_properties, "opacity", 1.0); |
587 | 600 | mlt_properties_set_int(filter_properties, "_filter_private", 1); |
588 | | - |
| 601 | + |
589 | 602 | // Initialize typewriter properties |
590 | 603 | mlt_properties_set_int(filter_properties, "typewriter", 0); |
591 | 604 | mlt_properties_set_int(filter_properties, "typewriter.step_length", 25); |
|
0 commit comments