Mercurial > mplayer.hg
annotate libass/ass_render.c @ 23978:ef6e50c3c172
Revert setting audio output channel count for FFmpeg
The FFmpeg API needs to be fixed before this can be done sanely.
ffdca wants the desired output channel count to be set in
avctx->channels. Unfortunately it also completely fails if the requested
number of channels is not available rather than returning a different
amount (if 6 channels are requested we'd probably rather use stereo than
fail completely).
ffvorbis ignores caller-set values in avctx->channels. It writes the
channel count there once during init. This means the caller can only
set the count before init because later there would be no indication
whether the channel count in avctx reflects real output.
ffwma requires the caller to supply the encoded channel count
in avctx->channels during init or it fails. So it is not possible to
set a different number of desired output channels there before init
either.
author | uau |
---|---|
date | Thu, 02 Aug 2007 21:54:14 +0000 |
parents | 99ac5d381aed |
children | ffc2c7164bc0 |
rev | line source |
---|---|
20008
fa122b7c71c6
Add copyright notice and vim/emacs comments to libass and vf_ass.c.
eugeni
parents:
19965
diff
changeset
|
1 // -*- c-basic-offset: 8; indent-tabs-mode: t -*- |
fa122b7c71c6
Add copyright notice and vim/emacs comments to libass and vf_ass.c.
eugeni
parents:
19965
diff
changeset
|
2 // vim:ts=8:sw=8:noet:ai: |
fa122b7c71c6
Add copyright notice and vim/emacs comments to libass and vf_ass.c.
eugeni
parents:
19965
diff
changeset
|
3 /* |
fa122b7c71c6
Add copyright notice and vim/emacs comments to libass and vf_ass.c.
eugeni
parents:
19965
diff
changeset
|
4 Copyright (C) 2006 Evgeniy Stepanov <eugeni.stepanov@gmail.com> |
fa122b7c71c6
Add copyright notice and vim/emacs comments to libass and vf_ass.c.
eugeni
parents:
19965
diff
changeset
|
5 |
fa122b7c71c6
Add copyright notice and vim/emacs comments to libass and vf_ass.c.
eugeni
parents:
19965
diff
changeset
|
6 This program is free software; you can redistribute it and/or modify |
fa122b7c71c6
Add copyright notice and vim/emacs comments to libass and vf_ass.c.
eugeni
parents:
19965
diff
changeset
|
7 it under the terms of the GNU General Public License as published by |
fa122b7c71c6
Add copyright notice and vim/emacs comments to libass and vf_ass.c.
eugeni
parents:
19965
diff
changeset
|
8 the Free Software Foundation; either version 2 of the License, or |
fa122b7c71c6
Add copyright notice and vim/emacs comments to libass and vf_ass.c.
eugeni
parents:
19965
diff
changeset
|
9 (at your option) any later version. |
fa122b7c71c6
Add copyright notice and vim/emacs comments to libass and vf_ass.c.
eugeni
parents:
19965
diff
changeset
|
10 |
fa122b7c71c6
Add copyright notice and vim/emacs comments to libass and vf_ass.c.
eugeni
parents:
19965
diff
changeset
|
11 This program is distributed in the hope that it will be useful, |
fa122b7c71c6
Add copyright notice and vim/emacs comments to libass and vf_ass.c.
eugeni
parents:
19965
diff
changeset
|
12 but WITHOUT ANY WARRANTY; without even the implied warranty of |
fa122b7c71c6
Add copyright notice and vim/emacs comments to libass and vf_ass.c.
eugeni
parents:
19965
diff
changeset
|
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
fa122b7c71c6
Add copyright notice and vim/emacs comments to libass and vf_ass.c.
eugeni
parents:
19965
diff
changeset
|
14 GNU General Public License for more details. |
fa122b7c71c6
Add copyright notice and vim/emacs comments to libass and vf_ass.c.
eugeni
parents:
19965
diff
changeset
|
15 |
fa122b7c71c6
Add copyright notice and vim/emacs comments to libass and vf_ass.c.
eugeni
parents:
19965
diff
changeset
|
16 You should have received a copy of the GNU General Public License |
fa122b7c71c6
Add copyright notice and vim/emacs comments to libass and vf_ass.c.
eugeni
parents:
19965
diff
changeset
|
17 along with this program; if not, write to the Free Software |
fa122b7c71c6
Add copyright notice and vim/emacs comments to libass and vf_ass.c.
eugeni
parents:
19965
diff
changeset
|
18 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
fa122b7c71c6
Add copyright notice and vim/emacs comments to libass and vf_ass.c.
eugeni
parents:
19965
diff
changeset
|
19 */ |
fa122b7c71c6
Add copyright notice and vim/emacs comments to libass and vf_ass.c.
eugeni
parents:
19965
diff
changeset
|
20 |
18937 | 21 #include "config.h" |
22 | |
23 #include <assert.h> | |
24 #include <math.h> | |
19378 | 25 #include <inttypes.h> |
18937 | 26 #include <ft2build.h> |
27 #include FT_FREETYPE_H | |
28 #include FT_STROKER_H | |
29 #include FT_GLYPH_H | |
30 #include FT_SYNTHESIS_H | |
31 | |
21026
d138463e820b
Collect all includes of mplayer headers in libass in a single file (mputils.h).
eugeni
parents:
20875
diff
changeset
|
32 #include "mputils.h" |
18937 | 33 |
34 #include "ass.h" | |
21322 | 35 #include "ass_font.h" |
19846
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
19825
diff
changeset
|
36 #include "ass_bitmap.h" |
18937 | 37 #include "ass_cache.h" |
38 #include "ass_utils.h" | |
39 #include "ass_fontconfig.h" | |
20477 | 40 #include "ass_library.h" |
18937 | 41 |
42 #define MAX_GLYPHS 1000 | |
43 #define MAX_LINES 100 | |
44 | |
20446
e8adc3778348
Split ass_configure() into several smaller functions.
eugeni
parents:
20320
diff
changeset
|
45 static int last_render_id = 0; |
18937 | 46 |
20446
e8adc3778348
Split ass_configure() into several smaller functions.
eugeni
parents:
20320
diff
changeset
|
47 typedef struct ass_settings_s { |
e8adc3778348
Split ass_configure() into several smaller functions.
eugeni
parents:
20320
diff
changeset
|
48 int frame_width; |
e8adc3778348
Split ass_configure() into several smaller functions.
eugeni
parents:
20320
diff
changeset
|
49 int frame_height; |
e8adc3778348
Split ass_configure() into several smaller functions.
eugeni
parents:
20320
diff
changeset
|
50 double font_size_coeff; // font size multiplier |
e8adc3778348
Split ass_configure() into several smaller functions.
eugeni
parents:
20320
diff
changeset
|
51 double line_spacing; // additional line spacing (in frame pixels) |
e8adc3778348
Split ass_configure() into several smaller functions.
eugeni
parents:
20320
diff
changeset
|
52 int top_margin; // height of top margin. Everything except toptitles is shifted down by top_margin. |
e8adc3778348
Split ass_configure() into several smaller functions.
eugeni
parents:
20320
diff
changeset
|
53 int bottom_margin; // height of bottom margin. (frame_height - top_margin - bottom_margin) is original video height. |
e8adc3778348
Split ass_configure() into several smaller functions.
eugeni
parents:
20320
diff
changeset
|
54 int left_margin; |
e8adc3778348
Split ass_configure() into several smaller functions.
eugeni
parents:
20320
diff
changeset
|
55 int right_margin; |
e8adc3778348
Split ass_configure() into several smaller functions.
eugeni
parents:
20320
diff
changeset
|
56 int use_margins; // 0 - place all subtitles inside original frame |
e8adc3778348
Split ass_configure() into several smaller functions.
eugeni
parents:
20320
diff
changeset
|
57 // 1 - use margins for placing toptitles and subtitles |
e8adc3778348
Split ass_configure() into several smaller functions.
eugeni
parents:
20320
diff
changeset
|
58 double aspect; // frame aspect ratio, d_width / d_height. |
23134
1de2a46a0987
Add -ass-hinting option for setting font hinting method.
eugeni
parents:
23133
diff
changeset
|
59 ass_hinting_t hinting; |
20477 | 60 |
20446
e8adc3778348
Split ass_configure() into several smaller functions.
eugeni
parents:
20320
diff
changeset
|
61 char* default_font; |
e8adc3778348
Split ass_configure() into several smaller functions.
eugeni
parents:
20320
diff
changeset
|
62 char* default_family; |
e8adc3778348
Split ass_configure() into several smaller functions.
eugeni
parents:
20320
diff
changeset
|
63 } ass_settings_t; |
19638
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
64 |
22258
9c1160622400
Reallocate event_images_t, removing limit on simultanious events count.
eugeni
parents:
22221
diff
changeset
|
65 // a rendered event |
9c1160622400
Reallocate event_images_t, removing limit on simultanious events count.
eugeni
parents:
22221
diff
changeset
|
66 typedef struct event_images_s { |
9c1160622400
Reallocate event_images_t, removing limit on simultanious events count.
eugeni
parents:
22221
diff
changeset
|
67 ass_image_t* imgs; |
9c1160622400
Reallocate event_images_t, removing limit on simultanious events count.
eugeni
parents:
22221
diff
changeset
|
68 int top, height; |
9c1160622400
Reallocate event_images_t, removing limit on simultanious events count.
eugeni
parents:
22221
diff
changeset
|
69 int detect_collisions; |
9c1160622400
Reallocate event_images_t, removing limit on simultanious events count.
eugeni
parents:
22221
diff
changeset
|
70 int shift_direction; |
9c1160622400
Reallocate event_images_t, removing limit on simultanious events count.
eugeni
parents:
22221
diff
changeset
|
71 ass_event_t* event; |
9c1160622400
Reallocate event_images_t, removing limit on simultanious events count.
eugeni
parents:
22221
diff
changeset
|
72 } event_images_t; |
9c1160622400
Reallocate event_images_t, removing limit on simultanious events count.
eugeni
parents:
22221
diff
changeset
|
73 |
20477 | 74 struct ass_renderer_s { |
75 ass_library_t* library; | |
76 FT_Library ftlibrary; | |
18937 | 77 fc_instance_t* fontconfig_priv; |
78 ass_settings_t settings; | |
19638
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
79 int render_id; |
19848 | 80 ass_synth_priv_t* synth_priv; |
18937 | 81 |
82 ass_image_t* images_root; // rendering result is stored here | |
21506
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
83 ass_image_t* prev_images_root; |
22258
9c1160622400
Reallocate event_images_t, removing limit on simultanious events count.
eugeni
parents:
22221
diff
changeset
|
84 |
9c1160622400
Reallocate event_images_t, removing limit on simultanious events count.
eugeni
parents:
22221
diff
changeset
|
85 event_images_t* eimg; // temporary buffer for sorting rendered events |
9c1160622400
Reallocate event_images_t, removing limit on simultanious events count.
eugeni
parents:
22221
diff
changeset
|
86 int eimg_size; // allocated buffer size |
18937 | 87 }; |
88 | |
89 typedef enum {EF_NONE = 0, EF_KARAOKE, EF_KARAOKE_KF, EF_KARAOKE_KO} effect_t; | |
90 | |
91 // describes a glyph | |
92 // glyph_info_t and text_info_t are used for text centering and word-wrapping operations | |
93 typedef struct glyph_info_s { | |
94 unsigned symbol; | |
95 FT_Glyph glyph; | |
96 FT_Glyph outline_glyph; | |
19965 | 97 bitmap_t* bm; // glyph bitmap |
98 bitmap_t* bm_o; // outline bitmap | |
99 bitmap_t* bm_s; // shadow bitmap | |
18937 | 100 FT_BBox bbox; |
101 FT_Vector pos; | |
102 char linebreak; // the first (leading) glyph of some line ? | |
19691 | 103 uint32_t c[4]; // colors |
18937 | 104 FT_Vector advance; // 26.6 |
105 effect_t effect_type; | |
19716
e4e492fcc2f7
Bugfix: timing for empty karaoke words was lost, resulting
eugeni
parents:
19693
diff
changeset
|
106 int effect_timing; // time duration of current karaoke word |
e4e492fcc2f7
Bugfix: timing for empty karaoke words was lost, resulting
eugeni
parents:
19693
diff
changeset
|
107 // after process_karaoke_effects: distance in pixels from the glyph origin. |
e4e492fcc2f7
Bugfix: timing for empty karaoke words was lost, resulting
eugeni
parents:
19693
diff
changeset
|
108 // part of the glyph to the left of it is displayed in a different color. |
e4e492fcc2f7
Bugfix: timing for empty karaoke words was lost, resulting
eugeni
parents:
19693
diff
changeset
|
109 int effect_skip_timing; // delay after the end of last karaoke word |
18937 | 110 int asc, desc; // font max ascender and descender |
111 // int height; | |
19848 | 112 int be; // blur edges |
19965 | 113 int shadow; |
22215
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
114 double frx, fry, frz; // rotation |
18937 | 115 |
23017 | 116 bitmap_hash_key_t hash_key; |
18937 | 117 } glyph_info_t; |
118 | |
119 typedef struct line_info_s { | |
120 int asc, desc; | |
121 } line_info_t; | |
122 | |
123 typedef struct text_info_s { | |
124 glyph_info_t* glyphs; | |
125 int length; | |
126 line_info_t lines[MAX_LINES]; | |
127 int n_lines; | |
128 int height; | |
129 } text_info_t; | |
130 | |
131 | |
132 // Renderer state. | |
133 // Values like current font face, color, screen position, clipping and so on are stored here. | |
134 typedef struct render_context_s { | |
135 ass_event_t* event; | |
136 ass_style_t* style; | |
137 | |
21267
9ec30b8622ec
Make ass_new_font return ass_font_t struct (instead of just FT_Face).
eugeni
parents:
21265
diff
changeset
|
138 ass_font_t* font; |
18937 | 139 char* font_path; |
23300 | 140 double font_size; |
18937 | 141 |
142 FT_Stroker stroker; | |
143 int alignment; // alignment overrides go here; if zero, style value will be used | |
22215
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
144 double frx, fry, frz; |
18937 | 145 enum { EVENT_NORMAL, // "normal" top-, sub- or mid- title |
19556 | 146 EVENT_POSITIONED, // happens after pos(,), margins are ignored |
147 EVENT_HSCROLL, // "Banner" transition effect, text_width is unlimited | |
148 EVENT_VSCROLL // "Scroll up", "Scroll down" transition effects | |
18937 | 149 } evt_type; |
150 int pos_x, pos_y; // position | |
151 int org_x, org_y; // origin | |
22207 | 152 char have_origin; // origin is explicitly defined; if 0, get_base_point() is used |
18937 | 153 double scale_x, scale_y; |
22259 | 154 double hspacing; // distance between letters, in pixels |
18937 | 155 double border; // outline width |
19691 | 156 uint32_t c[4]; // colors(Primary, Secondary, so on) in RGBA |
18937 | 157 int clip_x0, clip_y0, clip_x1, clip_y1; |
158 char detect_collisions; | |
19692
5b40e87b9619
Change \fad behaviour so that it does not get cancelled by \r.
eugeni
parents:
19691
diff
changeset
|
159 uint32_t fade; // alpha from \fad |
19848 | 160 char be; // blur edges |
19965 | 161 int shadow; |
18937 | 162 |
163 effect_t effect_type; | |
164 int effect_timing; | |
19716
e4e492fcc2f7
Bugfix: timing for empty karaoke words was lost, resulting
eugeni
parents:
19693
diff
changeset
|
165 int effect_skip_timing; |
18937 | 166 |
19556 | 167 enum { SCROLL_LR, // left-to-right |
168 SCROLL_RL, | |
169 SCROLL_TB, // top-to-bottom | |
170 SCROLL_BT | |
171 } scroll_direction; // for EVENT_HSCROLL, EVENT_VSCROLL | |
172 int scroll_shift; | |
173 | |
18937 | 174 // face properties |
175 char* family; | |
176 unsigned bold; | |
177 unsigned italic; | |
178 | |
179 } render_context_t; | |
180 | |
181 // frame-global data | |
182 typedef struct frame_context_s { | |
20477 | 183 ass_renderer_t* ass_priv; |
18937 | 184 int width, height; // screen dimensions |
185 int orig_height; // frame height ( = screen height - margins ) | |
19538 | 186 int orig_width; // frame width ( = screen width - margins ) |
18937 | 187 ass_track_t* track; |
188 long long time; // frame's timestamp, ms | |
19825
f351a3fc3e42
Make font outline width proportional to movie resolution.
eugeni
parents:
19716
diff
changeset
|
189 double font_scale; |
18937 | 190 double font_scale_x; // x scale applied to all glyphs to preserve text aspect ratio |
19917
6a31849e2b80
In r19831, font size multiplier was mistakenly applied to border width.
eugeni
parents:
19906
diff
changeset
|
191 double border_scale; |
18937 | 192 } frame_context_t; |
193 | |
20477 | 194 static ass_renderer_t* ass_renderer; |
18937 | 195 static ass_settings_t* global_settings; |
196 static text_info_t text_info; | |
197 static render_context_t render_context; | |
198 static frame_context_t frame_context; | |
199 | |
19638
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
200 struct render_priv_s { |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
201 int top, height; |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
202 int render_id; |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
203 }; |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
204 |
18937 | 205 static void ass_lazy_track_init(void) |
206 { | |
207 ass_track_t* track = frame_context.track; | |
208 if (track->PlayResX && track->PlayResY) | |
209 return; | |
210 if (!track->PlayResX && !track->PlayResY) { | |
21066 | 211 mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_NeitherPlayResXNorPlayResYDefined); |
18937 | 212 track->PlayResX = 384; |
213 track->PlayResY = 288; | |
214 } else { | |
19538 | 215 double orig_aspect = (global_settings->aspect * frame_context.height * frame_context.orig_width) / |
216 frame_context.orig_height / frame_context.width; | |
18937 | 217 if (!track->PlayResY) { |
218 track->PlayResY = track->PlayResX / orig_aspect + .5; | |
21066 | 219 mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_PlayResYUndefinedSettingY, track->PlayResY); |
18937 | 220 } else if (!track->PlayResX) { |
221 track->PlayResX = track->PlayResY * orig_aspect + .5; | |
21066 | 222 mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_PlayResXUndefinedSettingX, track->PlayResX); |
18937 | 223 } |
224 } | |
225 } | |
226 | |
20477 | 227 ass_renderer_t* ass_renderer_init(ass_library_t* library) |
18937 | 228 { |
229 int error; | |
230 FT_Library ft; | |
20477 | 231 ass_renderer_t* priv = 0; |
18937 | 232 |
20202
9b67ed06f721
Zerofill libass static variables during initialization.
eugeni
parents:
20201
diff
changeset
|
233 memset(&render_context, 0, sizeof(render_context)); |
9b67ed06f721
Zerofill libass static variables during initialization.
eugeni
parents:
20201
diff
changeset
|
234 memset(&frame_context, 0, sizeof(frame_context)); |
9b67ed06f721
Zerofill libass static variables during initialization.
eugeni
parents:
20201
diff
changeset
|
235 memset(&text_info, 0, sizeof(text_info)); |
9b67ed06f721
Zerofill libass static variables during initialization.
eugeni
parents:
20201
diff
changeset
|
236 |
18937 | 237 error = FT_Init_FreeType( &ft ); |
238 if ( error ) { | |
21066 | 239 mp_msg(MSGT_ASS, MSGL_FATAL, MSGTR_LIBASS_FT_Init_FreeTypeFailed); |
19517 | 240 goto ass_init_exit; |
18937 | 241 } |
242 | |
20477 | 243 priv = calloc(1, sizeof(ass_renderer_t)); |
18937 | 244 if (!priv) { |
245 FT_Done_FreeType(ft); | |
19517 | 246 goto ass_init_exit; |
18937 | 247 } |
19846
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
19825
diff
changeset
|
248 |
19848 | 249 priv->synth_priv = ass_synth_init(); |
250 | |
20477 | 251 priv->library = library; |
252 priv->ftlibrary = ft; | |
18937 | 253 // images_root and related stuff is zero-filled in calloc |
254 | |
21265 | 255 ass_font_cache_init(); |
23017 | 256 ass_bitmap_cache_init(); |
23021
a81c390d4a22
Move outline glyph generation to a separate function, using outline glyph
eugeni
parents:
23017
diff
changeset
|
257 ass_glyph_cache_init(); |
18937 | 258 |
259 text_info.glyphs = calloc(MAX_GLYPHS, sizeof(glyph_info_t)); | |
260 | |
19517 | 261 ass_init_exit: |
21066 | 262 if (priv) mp_msg(MSGT_ASS, MSGL_INFO, MSGTR_LIBASS_Init); |
263 else mp_msg(MSGT_ASS, MSGL_ERR, MSGTR_LIBASS_InitFailed); | |
19517 | 264 |
18937 | 265 return priv; |
266 } | |
267 | |
20477 | 268 void ass_renderer_done(ass_renderer_t* priv) |
18937 | 269 { |
21265 | 270 ass_font_cache_done(); |
23017 | 271 ass_bitmap_cache_done(); |
23021
a81c390d4a22
Move outline glyph generation to a separate function, using outline glyph
eugeni
parents:
23017
diff
changeset
|
272 ass_glyph_cache_done(); |
20201 | 273 if (render_context.stroker) { |
274 FT_Stroker_Done(render_context.stroker); | |
275 render_context.stroker = 0; | |
276 } | |
20477 | 277 if (priv && priv->ftlibrary) FT_Done_FreeType(priv->ftlibrary); |
18937 | 278 if (priv && priv->fontconfig_priv) fontconfig_done(priv->fontconfig_priv); |
19848 | 279 if (priv && priv->synth_priv) ass_synth_done(priv->synth_priv); |
22258
9c1160622400
Reallocate event_images_t, removing limit on simultanious events count.
eugeni
parents:
22221
diff
changeset
|
280 if (priv && priv->eimg) free(priv->eimg); |
18937 | 281 if (priv) free(priv); |
282 if (text_info.glyphs) free(text_info.glyphs); | |
283 } | |
284 | |
285 /** | |
19638
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
286 * \brief Create a new ass_image_t |
18937 | 287 * Parameters are the same as ass_image_t fields. |
288 */ | |
19638
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
289 static ass_image_t* my_draw_bitmap(unsigned char* bitmap, int bitmap_w, int bitmap_h, int stride, int dst_x, int dst_y, uint32_t color) |
18937 | 290 { |
19638
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
291 ass_image_t* img = calloc(1, sizeof(ass_image_t)); |
18937 | 292 |
293 img->w = bitmap_w; | |
294 img->h = bitmap_h; | |
295 img->stride = stride; | |
296 img->bitmap = bitmap; | |
297 img->color = color; | |
298 img->dst_x = dst_x; | |
299 img->dst_y = dst_y; | |
19638
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
300 |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
301 return img; |
18937 | 302 } |
303 | |
304 /** | |
305 * \brief convert bitmap glyph into ass_image_t struct(s) | |
306 * \param bit freetype bitmap glyph, FT_PIXEL_MODE_GRAY | |
307 * \param dst_x bitmap x coordinate in video frame | |
308 * \param dst_y bitmap y coordinate in video frame | |
309 * \param color first color, RGBA | |
310 * \param color2 second color, RGBA | |
311 * \param brk x coordinate relative to glyph origin, color is used to the left of brk, color2 - to the right | |
19638
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
312 * \param tail pointer to the last image's next field, head of the generated list should be stored here |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
313 * \return pointer to the new list tail |
18937 | 314 * Performs clipping. Uses my_draw_bitmap for actual bitmap convertion. |
315 */ | |
19846
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
19825
diff
changeset
|
316 static ass_image_t** render_glyph(bitmap_t* bm, int dst_x, int dst_y, uint32_t color, uint32_t color2, int brk, ass_image_t** tail) |
18937 | 317 { |
318 // brk is relative to dst_x | |
319 // color = color left of brk | |
320 // color2 = color right of brk | |
321 int b_x0, b_y0, b_x1, b_y1; // visible part of the bitmap | |
322 int clip_x0, clip_y0, clip_x1, clip_y1; | |
323 int tmp; | |
19638
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
324 ass_image_t* img; |
18937 | 325 |
19846
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
19825
diff
changeset
|
326 dst_x += bm->left; |
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
19825
diff
changeset
|
327 dst_y += bm->top; |
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
19825
diff
changeset
|
328 brk -= bm->left; |
18937 | 329 |
330 // clipping | |
331 clip_x0 = render_context.clip_x0; | |
332 clip_y0 = render_context.clip_y0; | |
333 clip_x1 = render_context.clip_x1; | |
334 clip_y1 = render_context.clip_y1; | |
335 b_x0 = 0; | |
336 b_y0 = 0; | |
19846
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
19825
diff
changeset
|
337 b_x1 = bm->w; |
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
19825
diff
changeset
|
338 b_y1 = bm->h; |
18937 | 339 |
340 tmp = dst_x - clip_x0; | |
341 if (tmp < 0) { | |
20629
e8885ec63928
Introduce MSGT_ASS, use it for all libass messages.
eugeni
parents:
20503
diff
changeset
|
342 mp_msg(MSGT_ASS, MSGL_DBG2, "clip left\n"); |
18937 | 343 b_x0 = - tmp; |
344 } | |
345 tmp = dst_y - clip_y0; | |
346 if (tmp < 0) { | |
20629
e8885ec63928
Introduce MSGT_ASS, use it for all libass messages.
eugeni
parents:
20503
diff
changeset
|
347 mp_msg(MSGT_ASS, MSGL_DBG2, "clip top\n"); |
18937 | 348 b_y0 = - tmp; |
349 } | |
19846
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
19825
diff
changeset
|
350 tmp = clip_x1 - dst_x - bm->w; |
18937 | 351 if (tmp < 0) { |
20629
e8885ec63928
Introduce MSGT_ASS, use it for all libass messages.
eugeni
parents:
20503
diff
changeset
|
352 mp_msg(MSGT_ASS, MSGL_DBG2, "clip right\n"); |
19846
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
19825
diff
changeset
|
353 b_x1 = bm->w + tmp; |
18937 | 354 } |
19846
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
19825
diff
changeset
|
355 tmp = clip_y1 - dst_y - bm->h; |
18937 | 356 if (tmp < 0) { |
20629
e8885ec63928
Introduce MSGT_ASS, use it for all libass messages.
eugeni
parents:
20503
diff
changeset
|
357 mp_msg(MSGT_ASS, MSGL_DBG2, "clip bottom\n"); |
19846
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
19825
diff
changeset
|
358 b_y1 = bm->h + tmp; |
18937 | 359 } |
360 | |
361 if ((b_y0 >= b_y1) || (b_x0 >= b_x1)) | |
19638
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
362 return tail; |
18937 | 363 |
364 if (brk > b_x0) { // draw left part | |
365 if (brk > b_x1) brk = b_x1; | |
19846
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
19825
diff
changeset
|
366 img = my_draw_bitmap(bm->buffer + bm->w * b_y0 + b_x0, |
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
19825
diff
changeset
|
367 brk - b_x0, b_y1 - b_y0, bm->w, |
18937 | 368 dst_x + b_x0, dst_y + b_y0, color); |
19638
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
369 *tail = img; |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
370 tail = &img->next; |
18937 | 371 } |
372 if (brk < b_x1) { // draw right part | |
373 if (brk < b_x0) brk = b_x0; | |
19846
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
19825
diff
changeset
|
374 img = my_draw_bitmap(bm->buffer + bm->w * b_y0 + brk, |
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
19825
diff
changeset
|
375 b_x1 - brk, b_y1 - b_y0, bm->w, |
18937 | 376 dst_x + brk, dst_y + b_y0, color2); |
19638
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
377 *tail = img; |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
378 tail = &img->next; |
18937 | 379 } |
19638
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
380 return tail; |
18937 | 381 } |
382 | |
383 /** | |
23179 | 384 * \brief Convert text_info_t struct to ass_image_t list |
385 * Splits glyphs in halves when needed (for \kf karaoke). | |
18937 | 386 */ |
19638
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
387 static ass_image_t* render_text(text_info_t* text_info, int dst_x, int dst_y) |
18937 | 388 { |
389 int pen_x, pen_y; | |
23177
134a2baca452
Move glyph_to_bitmap() call and outline glyph deallocation to
eugeni
parents:
23175
diff
changeset
|
390 int i; |
19846
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
19825
diff
changeset
|
391 bitmap_t* bm; |
19638
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
392 ass_image_t* head; |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
393 ass_image_t** tail = &head; |
18937 | 394 |
395 for (i = 0; i < text_info->length; ++i) { | |
23175 | 396 glyph_info_t* info = text_info->glyphs + i; |
19965 | 397 if ((info->symbol == 0) || (info->symbol == '\n') || !info->bm_s || (info->shadow == 0)) |
398 continue; | |
399 | |
400 pen_x = dst_x + info->pos.x + info->shadow; | |
401 pen_y = dst_y + info->pos.y + info->shadow; | |
402 bm = info->bm_s; | |
403 | |
404 tail = render_glyph(bm, pen_x, pen_y, info->c[3], 0, 1000000, tail); | |
405 } | |
406 | |
407 for (i = 0; i < text_info->length; ++i) { | |
408 glyph_info_t* info = text_info->glyphs + i; | |
19873 | 409 if ((info->symbol == 0) || (info->symbol == '\n') || !info->bm_o) |
18937 | 410 continue; |
411 | |
412 pen_x = dst_x + info->pos.x; | |
413 pen_y = dst_y + info->pos.y; | |
19846
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
19825
diff
changeset
|
414 bm = info->bm_o; |
18937 | 415 |
416 if ((info->effect_type == EF_KARAOKE_KO) && (info->effect_timing <= info->bbox.xMax)) { | |
417 // do nothing | |
418 } else | |
19846
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
19825
diff
changeset
|
419 tail = render_glyph(bm, pen_x, pen_y, info->c[2], 0, 1000000, tail); |
18937 | 420 } |
421 for (i = 0; i < text_info->length; ++i) { | |
422 glyph_info_t* info = text_info->glyphs + i; | |
19873 | 423 if ((info->symbol == 0) || (info->symbol == '\n') || !info->bm) |
18937 | 424 continue; |
425 | |
426 pen_x = dst_x + info->pos.x; | |
427 pen_y = dst_y + info->pos.y; | |
19846
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
19825
diff
changeset
|
428 bm = info->bm; |
18937 | 429 |
430 if ((info->effect_type == EF_KARAOKE) || (info->effect_type == EF_KARAOKE_KO)) { | |
431 if (info->effect_timing > info->bbox.xMax) | |
19846
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
19825
diff
changeset
|
432 tail = render_glyph(bm, pen_x, pen_y, info->c[0], 0, 1000000, tail); |
18937 | 433 else |
19846
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
19825
diff
changeset
|
434 tail = render_glyph(bm, pen_x, pen_y, info->c[1], 0, 1000000, tail); |
18937 | 435 } else if (info->effect_type == EF_KARAOKE_KF) { |
19846
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
19825
diff
changeset
|
436 tail = render_glyph(bm, pen_x, pen_y, info->c[0], info->c[1], info->effect_timing, tail); |
18937 | 437 } else |
19846
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
19825
diff
changeset
|
438 tail = render_glyph(bm, pen_x, pen_y, info->c[0], 0, 1000000, tail); |
18937 | 439 } |
440 | |
19638
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
441 *tail = 0; |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
442 return head; |
18937 | 443 } |
444 | |
445 /** | |
446 * \brief Mapping between script and screen coordinates | |
447 */ | |
448 static int x2scr(int x) { | |
19940
fb2063eaa445
Fix width -> orig_width typo causing subtitles to be too far to the right
reimar
parents:
19932
diff
changeset
|
449 return x*frame_context.orig_width / frame_context.track->PlayResX + global_settings->left_margin; |
18937 | 450 } |
451 /** | |
452 * \brief Mapping between script and screen coordinates | |
453 */ | |
454 static int y2scr(int y) { | |
455 return y * frame_context.orig_height / frame_context.track->PlayResY + global_settings->top_margin; | |
456 } | |
457 // the same for toptitles | |
458 static int y2scr_top(int y) { | |
19538 | 459 if (global_settings->use_margins) |
460 return y * frame_context.orig_height / frame_context.track->PlayResY; | |
461 else | |
462 return y * frame_context.orig_height / frame_context.track->PlayResY + global_settings->top_margin; | |
18937 | 463 } |
464 // the same for subtitles | |
465 static int y2scr_sub(int y) { | |
19538 | 466 if (global_settings->use_margins) |
467 return y * frame_context.orig_height / frame_context.track->PlayResY + | |
468 global_settings->top_margin + global_settings->bottom_margin; | |
469 else | |
470 return y * frame_context.orig_height / frame_context.track->PlayResY + global_settings->top_margin; | |
18937 | 471 } |
472 | |
473 static void compute_string_bbox( text_info_t* info, FT_BBox *abbox ) { | |
474 FT_BBox bbox; | |
20718
cde62cf29a7e
Calculate text bounding box in a way that does not depend on actual glyph
eugeni
parents:
20653
diff
changeset
|
475 int i; |
18937 | 476 |
20718
cde62cf29a7e
Calculate text bounding box in a way that does not depend on actual glyph
eugeni
parents:
20653
diff
changeset
|
477 if (text_info.length > 0) { |
cde62cf29a7e
Calculate text bounding box in a way that does not depend on actual glyph
eugeni
parents:
20653
diff
changeset
|
478 bbox.xMin = 32000; |
cde62cf29a7e
Calculate text bounding box in a way that does not depend on actual glyph
eugeni
parents:
20653
diff
changeset
|
479 bbox.xMax = -32000; |
22213
66abe12ad374
Move conversions between 16.16, 26.6 fixed point and int, double to separate
eugeni
parents:
22209
diff
changeset
|
480 bbox.yMin = - d6_to_int(text_info.lines[0].asc) + text_info.glyphs[0].pos.y; |
66abe12ad374
Move conversions between 16.16, 26.6 fixed point and int, double to separate
eugeni
parents:
22209
diff
changeset
|
481 bbox.yMax = d6_to_int(text_info.height - text_info.lines[0].asc) + text_info.glyphs[0].pos.y; |
20718
cde62cf29a7e
Calculate text bounding box in a way that does not depend on actual glyph
eugeni
parents:
20653
diff
changeset
|
482 |
cde62cf29a7e
Calculate text bounding box in a way that does not depend on actual glyph
eugeni
parents:
20653
diff
changeset
|
483 for (i = 0; i < text_info.length; ++i) { |
cde62cf29a7e
Calculate text bounding box in a way that does not depend on actual glyph
eugeni
parents:
20653
diff
changeset
|
484 int s = text_info.glyphs[i].pos.x; |
22213
66abe12ad374
Move conversions between 16.16, 26.6 fixed point and int, double to separate
eugeni
parents:
22209
diff
changeset
|
485 int e = s + d6_to_int(text_info.glyphs[i].advance.x); |
20718
cde62cf29a7e
Calculate text bounding box in a way that does not depend on actual glyph
eugeni
parents:
20653
diff
changeset
|
486 bbox.xMin = FFMIN(bbox.xMin, s); |
cde62cf29a7e
Calculate text bounding box in a way that does not depend on actual glyph
eugeni
parents:
20653
diff
changeset
|
487 bbox.xMax = FFMAX(bbox.xMax, e); |
cde62cf29a7e
Calculate text bounding box in a way that does not depend on actual glyph
eugeni
parents:
20653
diff
changeset
|
488 } |
cde62cf29a7e
Calculate text bounding box in a way that does not depend on actual glyph
eugeni
parents:
20653
diff
changeset
|
489 } else |
cde62cf29a7e
Calculate text bounding box in a way that does not depend on actual glyph
eugeni
parents:
20653
diff
changeset
|
490 bbox.xMin = bbox.xMax = bbox.yMin = bbox.yMax = 0; |
18937 | 491 |
492 /* return string bbox */ | |
493 *abbox = bbox; | |
494 } | |
495 | |
496 | |
497 /** | |
498 * \brief Check if starting part of (*p) matches sample. If true, shift p to the first symbol after the matching part. | |
499 */ | |
19104
2ec2301183cd
marks several read-only string parameters which aren't modified inside the called function as const. Patch by Stefan Huehner, stefan AT huehner-org
reynaldo
parents:
19066
diff
changeset
|
500 static inline int mystrcmp(char** p, const char* sample) { |
18937 | 501 int len = strlen(sample); |
502 if (strncmp(*p, sample, len) == 0) { | |
503 (*p) += len; | |
504 return 1; | |
505 } else | |
506 return 0; | |
507 } | |
508 | |
23300 | 509 static void change_font_size(double sz) |
18937 | 510 { |
19825
f351a3fc3e42
Make font outline width proportional to movie resolution.
eugeni
parents:
19716
diff
changeset
|
511 double size = sz * frame_context.font_scale; |
18937 | 512 |
513 if (size < 1) | |
514 size = 1; | |
515 else if (size > frame_context.height * 2) | |
516 size = frame_context.height * 2; | |
21277 | 517 |
518 ass_font_set_size(render_context.font, size); | |
18937 | 519 |
520 render_context.font_size = sz; | |
521 } | |
522 | |
523 /** | |
524 * \brief Change current font, using setting from render_context. | |
525 */ | |
526 static void update_font(void) | |
527 { | |
528 unsigned val; | |
20477 | 529 ass_renderer_t* priv = frame_context.ass_priv; |
21265 | 530 ass_font_desc_t desc; |
18937 | 531 desc.family = strdup(render_context.family); |
532 | |
533 val = render_context.bold; | |
534 // 0 = normal, 1 = bold, >1 = exact weight | |
535 if (val == 0) val = 80; // normal | |
536 else if (val == 1) val = 200; // bold | |
537 desc.bold = val; | |
538 | |
539 val = render_context.italic; | |
540 if (val == 0) val = 0; // normal | |
541 else if (val == 1) val = 110; //italic | |
542 desc.italic = val; | |
543 | |
21460 | 544 render_context.font = ass_font_new(priv->library, priv->ftlibrary, priv->fontconfig_priv, &desc); |
23213 | 545 free(desc.family); |
18937 | 546 |
21267
9ec30b8622ec
Make ass_new_font return ass_font_t struct (instead of just FT_Face).
eugeni
parents:
21265
diff
changeset
|
547 if (render_context.font) |
18937 | 548 change_font_size(render_context.font_size); |
549 } | |
550 | |
551 /** | |
552 * \brief Change border width | |
19873 | 553 * negative value resets border to style value |
18937 | 554 */ |
555 static void change_border(double border) | |
556 { | |
19918
1de67089c19a
Fix FT_Stroker use in libass. The previous variant ended up with 0-width
eugeni
parents:
19917
diff
changeset
|
557 int b; |
21267
9ec30b8622ec
Make ass_new_font return ass_font_t struct (instead of just FT_Face).
eugeni
parents:
21265
diff
changeset
|
558 if (!render_context.font) return; |
19918
1de67089c19a
Fix FT_Stroker use in libass. The previous variant ended up with 0-width
eugeni
parents:
19917
diff
changeset
|
559 |
19919 | 560 if (border < 0) { |
561 if (render_context.style->BorderStyle == 1) { | |
562 if (render_context.style->Outline == 0 && render_context.style->Shadow > 0) | |
19873 | 563 border = 1.; |
19919 | 564 else |
565 border = render_context.style->Outline; | |
566 } else | |
567 border = 1.; | |
568 } | |
569 render_context.border = border; | |
19873 | 570 |
19919 | 571 b = 64 * border * frame_context.border_scale; |
572 if (b > 0) { | |
19918
1de67089c19a
Fix FT_Stroker use in libass. The previous variant ended up with 0-width
eugeni
parents:
19917
diff
changeset
|
573 if (!render_context.stroker) { |
1de67089c19a
Fix FT_Stroker use in libass. The previous variant ended up with 0-width
eugeni
parents:
19917
diff
changeset
|
574 int error; |
1de67089c19a
Fix FT_Stroker use in libass. The previous variant ended up with 0-width
eugeni
parents:
19917
diff
changeset
|
575 #if (FREETYPE_MAJOR > 2) || ((FREETYPE_MAJOR == 2) && (FREETYPE_MINOR > 1)) |
20477 | 576 error = FT_Stroker_New( ass_renderer->ftlibrary, &render_context.stroker ); |
19918
1de67089c19a
Fix FT_Stroker use in libass. The previous variant ended up with 0-width
eugeni
parents:
19917
diff
changeset
|
577 #else // < 2.2 |
21619
b4b51eb2904f
Keep reselected fonts in an array, adding new ones to the end. Glyph
eugeni
parents:
21617
diff
changeset
|
578 error = FT_Stroker_New( render_context.font->faces[0]->memory, &render_context.stroker ); |
19918
1de67089c19a
Fix FT_Stroker use in libass. The previous variant ended up with 0-width
eugeni
parents:
19917
diff
changeset
|
579 #endif |
1de67089c19a
Fix FT_Stroker use in libass. The previous variant ended up with 0-width
eugeni
parents:
19917
diff
changeset
|
580 if (error) { |
20629
e8885ec63928
Introduce MSGT_ASS, use it for all libass messages.
eugeni
parents:
20503
diff
changeset
|
581 mp_msg(MSGT_ASS, MSGL_V, "failed to get stroker\n"); |
19918
1de67089c19a
Fix FT_Stroker use in libass. The previous variant ended up with 0-width
eugeni
parents:
19917
diff
changeset
|
582 render_context.stroker = 0; |
1de67089c19a
Fix FT_Stroker use in libass. The previous variant ended up with 0-width
eugeni
parents:
19917
diff
changeset
|
583 } |
1de67089c19a
Fix FT_Stroker use in libass. The previous variant ended up with 0-width
eugeni
parents:
19917
diff
changeset
|
584 } |
1de67089c19a
Fix FT_Stroker use in libass. The previous variant ended up with 0-width
eugeni
parents:
19917
diff
changeset
|
585 if (render_context.stroker) |
19873 | 586 FT_Stroker_Set( render_context.stroker, b, |
19919 | 587 FT_STROKER_LINECAP_ROUND, |
588 FT_STROKER_LINEJOIN_ROUND, | |
589 0 ); | |
590 } else { | |
591 FT_Stroker_Done(render_context.stroker); | |
592 render_context.stroker = 0; | |
593 } | |
18937 | 594 } |
595 | |
596 #define _r(c) ((c)>>24) | |
597 #define _g(c) (((c)>>16)&0xFF) | |
598 #define _b(c) (((c)>>8)&0xFF) | |
599 #define _a(c) ((c)&0xFF) | |
600 | |
601 /** | |
602 * \brief Calculate a weighted average of two colors | |
603 * calculates c1*(1-a) + c2*a, but separately for each component except alpha | |
604 */ | |
605 static void change_color(uint32_t* var, uint32_t new, double pwr) | |
606 { | |
607 (*var)= ((uint32_t)(_r(*var) * (1 - pwr) + _r(new) * pwr) << 24) + | |
608 ((uint32_t)(_g(*var) * (1 - pwr) + _g(new) * pwr) << 16) + | |
609 ((uint32_t)(_b(*var) * (1 - pwr) + _b(new) * pwr) << 8) + | |
610 _a(*var); | |
611 } | |
612 | |
613 // like change_color, but for alpha component only | |
614 static void change_alpha(uint32_t* var, uint32_t new, double pwr) | |
615 { | |
616 *var = (_r(*var) << 24) + (_g(*var) << 16) + (_b(*var) << 8) + (_a(*var) * (1 - pwr) + _a(new) * pwr); | |
617 } | |
618 | |
19406
747a5c394a69
Fix wrong handling of transparency in \fad(\fade).
eugeni
parents:
19405
diff
changeset
|
619 /** |
747a5c394a69
Fix wrong handling of transparency in \fad(\fade).
eugeni
parents:
19405
diff
changeset
|
620 * \brief Multiply two alpha values |
747a5c394a69
Fix wrong handling of transparency in \fad(\fade).
eugeni
parents:
19405
diff
changeset
|
621 * \param a first value |
747a5c394a69
Fix wrong handling of transparency in \fad(\fade).
eugeni
parents:
19405
diff
changeset
|
622 * \param b second value |
747a5c394a69
Fix wrong handling of transparency in \fad(\fade).
eugeni
parents:
19405
diff
changeset
|
623 * \return result of multiplication |
747a5c394a69
Fix wrong handling of transparency in \fad(\fade).
eugeni
parents:
19405
diff
changeset
|
624 * Parameters and result are limited by 0xFF. |
747a5c394a69
Fix wrong handling of transparency in \fad(\fade).
eugeni
parents:
19405
diff
changeset
|
625 */ |
747a5c394a69
Fix wrong handling of transparency in \fad(\fade).
eugeni
parents:
19405
diff
changeset
|
626 static uint32_t mult_alpha(uint32_t a, uint32_t b) |
747a5c394a69
Fix wrong handling of transparency in \fad(\fade).
eugeni
parents:
19405
diff
changeset
|
627 { |
747a5c394a69
Fix wrong handling of transparency in \fad(\fade).
eugeni
parents:
19405
diff
changeset
|
628 return 0xFF - (0xFF - a) * (0xFF - b) / 0xFF; |
747a5c394a69
Fix wrong handling of transparency in \fad(\fade).
eugeni
parents:
19405
diff
changeset
|
629 } |
18937 | 630 |
631 /** | |
632 * \brief Calculate alpha value by piecewise linear function | |
633 * Used for \fad, \fade implementation. | |
634 */ | |
19692
5b40e87b9619
Change \fad behaviour so that it does not get cancelled by \r.
eugeni
parents:
19691
diff
changeset
|
635 static unsigned interpolate_alpha(long long now, |
18937 | 636 long long t1, long long t2, long long t3, long long t4, |
637 unsigned a1, unsigned a2, unsigned a3) | |
638 { | |
639 unsigned a; | |
640 double cf; | |
641 if (now <= t1) { | |
642 a = a1; | |
643 } else if (now >= t4) { | |
644 a = a3; | |
645 } else if (now < t2) { // and > t1 | |
646 cf = ((double)(now - t1)) / (t2 - t1); | |
647 a = a1 * (1 - cf) + a2 * cf; | |
648 } else if (now > t3) { | |
649 cf = ((double)(now - t3)) / (t4 - t3); | |
650 a = a2 * (1 - cf) + a3 * cf; | |
651 } else { // t2 <= now <= t3 | |
652 a = a2; | |
653 } | |
654 | |
19692
5b40e87b9619
Change \fad behaviour so that it does not get cancelled by \r.
eugeni
parents:
19691
diff
changeset
|
655 return a; |
18937 | 656 } |
657 | |
22886 | 658 static void reset_render_context(void); |
19873 | 659 |
18937 | 660 /** |
661 * \brief Parse style override tag. | |
662 * \param p string to parse | |
663 * \param pwr multiplier for some tag effects (comes from \t tags) | |
664 */ | |
665 static char* parse_tag(char* p, double pwr) { | |
666 #define skip_all(x) if (*p == (x)) ++p; else { \ | |
667 while ((*p != (x)) && (*p != '}') && (*p != 0)) {++p;} } | |
668 #define skip(x) if (*p == (x)) ++p; else { return p; } | |
669 | |
670 skip_all('\\'); | |
671 if ((*p == '}') || (*p == 0)) | |
672 return p; | |
673 | |
674 if (mystrcmp(&p, "fsc")) { | |
675 char tp = *p++; | |
676 double val; | |
677 if (tp == 'x') { | |
678 if (mystrtod(&p, &val)) { | |
679 val /= 100; | |
22260 | 680 render_context.scale_x = render_context.scale_x * ( 1 - pwr) + val * pwr; |
18937 | 681 } else |
682 render_context.scale_x = render_context.style->ScaleX; | |
683 } else if (tp == 'y') { | |
684 if (mystrtod(&p, &val)) { | |
685 val /= 100; | |
22260 | 686 render_context.scale_y = render_context.scale_y * ( 1 - pwr) + val * pwr; |
18937 | 687 } else |
688 render_context.scale_y = render_context.style->ScaleY; | |
689 } | |
690 } else if (mystrcmp(&p, "fsp")) { | |
22259 | 691 double val; |
692 if (mystrtod(&p, &val)) | |
693 render_context.hspacing = render_context.hspacing * ( 1 - pwr ) + val * pwr; | |
18937 | 694 else |
22259 | 695 render_context.hspacing = render_context.style->Spacing; |
18937 | 696 } else if (mystrcmp(&p, "fs")) { |
23300 | 697 double val; |
698 if (mystrtod(&p, &val)) | |
18937 | 699 val = render_context.font_size * ( 1 - pwr ) + val * pwr; |
700 else | |
701 val = render_context.style->FontSize; | |
21267
9ec30b8622ec
Make ass_new_font return ass_font_t struct (instead of just FT_Face).
eugeni
parents:
21265
diff
changeset
|
702 if (render_context.font) |
18937 | 703 change_font_size(val); |
704 } else if (mystrcmp(&p, "bord")) { | |
705 double val; | |
706 if (mystrtod(&p, &val)) | |
707 val = render_context.border * ( 1 - pwr ) + val * pwr; | |
708 else | |
19873 | 709 val = -1.; // reset to default |
18937 | 710 change_border(val); |
711 } else if (mystrcmp(&p, "move")) { | |
712 int x1, x2, y1, y2; | |
19044 | 713 long long t1, t2, delta_t, t; |
18937 | 714 int x, y; |
715 double k; | |
716 skip('('); | |
717 x1 = strtol(p, &p, 10); | |
718 skip(','); | |
719 y1 = strtol(p, &p, 10); | |
720 skip(','); | |
721 x2 = strtol(p, &p, 10); | |
722 skip(','); | |
723 y2 = strtol(p, &p, 10); | |
19044 | 724 if (*p == ',') { |
725 skip(','); | |
726 t1 = strtoll(p, &p, 10); | |
727 skip(','); | |
728 t2 = strtoll(p, &p, 10); | |
20629
e8885ec63928
Introduce MSGT_ASS, use it for all libass messages.
eugeni
parents:
20503
diff
changeset
|
729 mp_msg(MSGT_ASS, MSGL_DBG2, "movement6: (%d, %d) -> (%d, %d), (%" PRId64 " .. %" PRId64 ")\n", |
19378 | 730 x1, y1, x2, y2, (int64_t)t1, (int64_t)t2); |
19044 | 731 } else { |
732 t1 = 0; | |
733 t2 = render_context.event->Duration; | |
20629
e8885ec63928
Introduce MSGT_ASS, use it for all libass messages.
eugeni
parents:
20503
diff
changeset
|
734 mp_msg(MSGT_ASS, MSGL_DBG2, "movement: (%d, %d) -> (%d, %d)\n", x1, y1, x2, y2); |
19044 | 735 } |
736 skip(')'); | |
737 delta_t = t2 - t1; | |
738 t = frame_context.time - render_context.event->Start; | |
739 if (t < t1) | |
740 k = 0.; | |
741 else if (t > t2) | |
742 k = 1.; | |
743 else k = ((double)(t - t1)) / delta_t; | |
18937 | 744 x = k * (x2 - x1) + x1; |
745 y = k * (y2 - y1) + y1; | |
746 render_context.pos_x = x; | |
747 render_context.pos_y = y; | |
748 render_context.detect_collisions = 0; | |
749 render_context.evt_type = EVENT_POSITIONED; | |
22215
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
750 } else if (mystrcmp(&p, "frx")) { |
19622 | 751 double val; |
22273
13a3013f3a27
Any style modifier followed by no recognizable parameter resets to the default.
eugeni
parents:
22269
diff
changeset
|
752 if (mystrtod(&p, &val)) { |
22276 | 753 val *= M_PI / 180; |
754 render_context.frx = val * pwr + render_context.frx * (1-pwr); | |
22273
13a3013f3a27
Any style modifier followed by no recognizable parameter resets to the default.
eugeni
parents:
22269
diff
changeset
|
755 } else |
13a3013f3a27
Any style modifier followed by no recognizable parameter resets to the default.
eugeni
parents:
22269
diff
changeset
|
756 render_context.frx = 0.; |
22215
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
757 } else if (mystrcmp(&p, "fry")) { |
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
758 double val; |
22273
13a3013f3a27
Any style modifier followed by no recognizable parameter resets to the default.
eugeni
parents:
22269
diff
changeset
|
759 if (mystrtod(&p, &val)) { |
22276 | 760 val *= M_PI / 180; |
761 render_context.fry = val * pwr + render_context.fry * (1-pwr); | |
22273
13a3013f3a27
Any style modifier followed by no recognizable parameter resets to the default.
eugeni
parents:
22269
diff
changeset
|
762 } else |
13a3013f3a27
Any style modifier followed by no recognizable parameter resets to the default.
eugeni
parents:
22269
diff
changeset
|
763 render_context.fry = 0.; |
18937 | 764 } else if (mystrcmp(&p, "frz") || mystrcmp(&p, "fr")) { |
19622 | 765 double val; |
22273
13a3013f3a27
Any style modifier followed by no recognizable parameter resets to the default.
eugeni
parents:
22269
diff
changeset
|
766 if (mystrtod(&p, &val)) { |
22276 | 767 val *= M_PI / 180; |
768 render_context.frz = val * pwr + render_context.frz * (1-pwr); | |
22273
13a3013f3a27
Any style modifier followed by no recognizable parameter resets to the default.
eugeni
parents:
22269
diff
changeset
|
769 } else |
13a3013f3a27
Any style modifier followed by no recognizable parameter resets to the default.
eugeni
parents:
22269
diff
changeset
|
770 render_context.frz = M_PI * render_context.style->Angle / 180.; |
18937 | 771 } else if (mystrcmp(&p, "fn")) { |
772 char* start = p; | |
773 char* family; | |
774 skip_all('\\'); | |
22269
b0ae9876168e
\fn without an argument resets font family to the value from style.
eugeni
parents:
22268
diff
changeset
|
775 if (p > start) { |
b0ae9876168e
\fn without an argument resets font family to the value from style.
eugeni
parents:
22268
diff
changeset
|
776 family = malloc(p - start + 1); |
b0ae9876168e
\fn without an argument resets font family to the value from style.
eugeni
parents:
22268
diff
changeset
|
777 strncpy(family, start, p - start); |
b0ae9876168e
\fn without an argument resets font family to the value from style.
eugeni
parents:
22268
diff
changeset
|
778 family[p - start] = '\0'; |
b0ae9876168e
\fn without an argument resets font family to the value from style.
eugeni
parents:
22268
diff
changeset
|
779 } else |
b0ae9876168e
\fn without an argument resets font family to the value from style.
eugeni
parents:
22268
diff
changeset
|
780 family = strdup(render_context.style->FontName); |
18937 | 781 if (render_context.family) |
782 free(render_context.family); | |
783 render_context.family = family; | |
784 update_font(); | |
785 } else if (mystrcmp(&p, "alpha")) { | |
786 uint32_t val; | |
19691 | 787 int i; |
18937 | 788 if (strtocolor(&p, &val)) { |
789 unsigned char a = val >> 24; | |
19691 | 790 for (i = 0; i < 4; ++i) |
791 change_alpha(&render_context.c[i], a, pwr); | |
18937 | 792 } else { |
19691 | 793 change_alpha(&render_context.c[0], render_context.style->PrimaryColour, pwr); |
794 change_alpha(&render_context.c[1], render_context.style->SecondaryColour, pwr); | |
795 change_alpha(&render_context.c[2], render_context.style->OutlineColour, pwr); | |
796 change_alpha(&render_context.c[3], render_context.style->BackColour, pwr); | |
18937 | 797 } |
798 // FIXME: simplify | |
799 } else if (mystrcmp(&p, "an")) { | |
22273
13a3013f3a27
Any style modifier followed by no recognizable parameter resets to the default.
eugeni
parents:
22269
diff
changeset
|
800 int val; |
13a3013f3a27
Any style modifier followed by no recognizable parameter resets to the default.
eugeni
parents:
22269
diff
changeset
|
801 if (mystrtoi(&p, 10, &val) && val) { |
22276 | 802 int v = (val - 1) / 3; // 0, 1 or 2 for vertical alignment |
803 mp_msg(MSGT_ASS, MSGL_DBG2, "an %d\n", val); | |
804 if (v != 0) v = 3 - v; | |
805 val = ((val - 1) % 3) + 1; // horizontal alignment | |
806 val += v*4; | |
807 mp_msg(MSGT_ASS, MSGL_DBG2, "align %d\n", val); | |
808 render_context.alignment = val; | |
22273
13a3013f3a27
Any style modifier followed by no recognizable parameter resets to the default.
eugeni
parents:
22269
diff
changeset
|
809 } else |
13a3013f3a27
Any style modifier followed by no recognizable parameter resets to the default.
eugeni
parents:
22269
diff
changeset
|
810 render_context.alignment = render_context.style->Alignment; |
18937 | 811 } else if (mystrcmp(&p, "a")) { |
22303 | 812 int val; |
22273
13a3013f3a27
Any style modifier followed by no recognizable parameter resets to the default.
eugeni
parents:
22269
diff
changeset
|
813 if (mystrtoi(&p, 10, &val) && val) |
22276 | 814 render_context.alignment = val; |
22273
13a3013f3a27
Any style modifier followed by no recognizable parameter resets to the default.
eugeni
parents:
22269
diff
changeset
|
815 else |
13a3013f3a27
Any style modifier followed by no recognizable parameter resets to the default.
eugeni
parents:
22269
diff
changeset
|
816 render_context.alignment = render_context.style->Alignment; |
18937 | 817 } else if (mystrcmp(&p, "pos")) { |
818 int v1, v2; | |
819 skip('('); | |
820 v1 = strtol(p, &p, 10); | |
821 skip(','); | |
822 v2 = strtol(p, &p, 10); | |
823 skip(')'); | |
20629
e8885ec63928
Introduce MSGT_ASS, use it for all libass messages.
eugeni
parents:
20503
diff
changeset
|
824 mp_msg(MSGT_ASS, MSGL_DBG2, "pos(%d, %d)\n", v1, v2); |
18937 | 825 render_context.evt_type = EVENT_POSITIONED; |
826 render_context.detect_collisions = 0; | |
827 render_context.pos_x = v1; | |
828 render_context.pos_y = v2; | |
19398
bb5164e0f70f
Allow \fade to be used in place of \fad and vice versa.
eugeni
parents:
19378
diff
changeset
|
829 } else if (mystrcmp(&p, "fad")) { |
bb5164e0f70f
Allow \fade to be used in place of \fad and vice versa.
eugeni
parents:
19378
diff
changeset
|
830 int a1, a2, a3; |
bb5164e0f70f
Allow \fade to be used in place of \fad and vice versa.
eugeni
parents:
19378
diff
changeset
|
831 long long t1, t2, t3, t4; |
bb5164e0f70f
Allow \fade to be used in place of \fad and vice versa.
eugeni
parents:
19378
diff
changeset
|
832 if (*p == 'e') ++p; // either \fad or \fade |
18937 | 833 skip('('); |
834 a1 = strtol(p, &p, 10); | |
835 skip(','); | |
836 a2 = strtol(p, &p, 10); | |
19398
bb5164e0f70f
Allow \fade to be used in place of \fad and vice versa.
eugeni
parents:
19378
diff
changeset
|
837 if (*p == ')') { |
bb5164e0f70f
Allow \fade to be used in place of \fad and vice versa.
eugeni
parents:
19378
diff
changeset
|
838 // 2-argument version (\fad, according to specs) |
bb5164e0f70f
Allow \fade to be used in place of \fad and vice versa.
eugeni
parents:
19378
diff
changeset
|
839 // a1 and a2 are fade-in and fade-out durations |
bb5164e0f70f
Allow \fade to be used in place of \fad and vice versa.
eugeni
parents:
19378
diff
changeset
|
840 t1 = 0; |
bb5164e0f70f
Allow \fade to be used in place of \fad and vice versa.
eugeni
parents:
19378
diff
changeset
|
841 t4 = render_context.event->Duration; |
bb5164e0f70f
Allow \fade to be used in place of \fad and vice versa.
eugeni
parents:
19378
diff
changeset
|
842 t2 = a1; |
bb5164e0f70f
Allow \fade to be used in place of \fad and vice versa.
eugeni
parents:
19378
diff
changeset
|
843 t3 = t4 - a2; |
bb5164e0f70f
Allow \fade to be used in place of \fad and vice versa.
eugeni
parents:
19378
diff
changeset
|
844 a1 = 0xFF; |
bb5164e0f70f
Allow \fade to be used in place of \fad and vice versa.
eugeni
parents:
19378
diff
changeset
|
845 a2 = 0; |
bb5164e0f70f
Allow \fade to be used in place of \fad and vice versa.
eugeni
parents:
19378
diff
changeset
|
846 a3 = 0xFF; |
bb5164e0f70f
Allow \fade to be used in place of \fad and vice versa.
eugeni
parents:
19378
diff
changeset
|
847 } else { |
19399 | 848 // 6-argument version (\fade) |
849 // a1 and a2 (and a3) are opacity values | |
850 skip(','); | |
851 a3 = strtol(p, &p, 10); | |
852 skip(','); | |
853 t1 = strtoll(p, &p, 10); | |
854 skip(','); | |
855 t2 = strtoll(p, &p, 10); | |
856 skip(','); | |
857 t3 = strtoll(p, &p, 10); | |
858 skip(','); | |
859 t4 = strtoll(p, &p, 10); | |
19398
bb5164e0f70f
Allow \fade to be used in place of \fad and vice versa.
eugeni
parents:
19378
diff
changeset
|
860 } |
18937 | 861 skip(')'); |
19692
5b40e87b9619
Change \fad behaviour so that it does not get cancelled by \r.
eugeni
parents:
19691
diff
changeset
|
862 render_context.fade = interpolate_alpha(frame_context.time - render_context.event->Start, t1, t2, t3, t4, a1, a2, a3); |
18937 | 863 } else if (mystrcmp(&p, "org")) { |
864 int v1, v2; | |
865 skip('('); | |
866 v1 = strtol(p, &p, 10); | |
867 skip(','); | |
868 v2 = strtol(p, &p, 10); | |
869 skip(')'); | |
20629
e8885ec63928
Introduce MSGT_ASS, use it for all libass messages.
eugeni
parents:
20503
diff
changeset
|
870 mp_msg(MSGT_ASS, MSGL_DBG2, "org(%d, %d)\n", v1, v2); |
18937 | 871 // render_context.evt_type = EVENT_POSITIONED; |
872 render_context.org_x = v1; | |
873 render_context.org_y = v2; | |
22207 | 874 render_context.have_origin = 1; |
18937 | 875 } else if (mystrcmp(&p, "t")) { |
876 double v[3]; | |
877 int v1, v2; | |
878 double v3; | |
879 int cnt; | |
880 long long t1, t2, t, delta_t; | |
881 double k; | |
882 skip('('); | |
883 for (cnt = 0; cnt < 3; ++cnt) { | |
884 if (*p == '\\') | |
885 break; | |
886 v[cnt] = strtod(p, &p); | |
887 skip(','); | |
888 } | |
889 if (cnt == 3) { | |
890 v1 = v[0]; v2 = v[1]; v3 = v[2]; | |
891 } else if (cnt == 2) { | |
892 v1 = v[0]; v2 = v[1]; v3 = 1.; | |
893 } else if (cnt == 1) { | |
894 v1 = 0; v2 = render_context.event->Duration; v3 = v[0]; | |
895 } else { // cnt == 0 | |
896 v1 = 0; v2 = render_context.event->Duration; v3 = 1.; | |
897 } | |
898 render_context.detect_collisions = 0; | |
899 t1 = v1; | |
900 t2 = v2; | |
901 delta_t = v2 - v1; | |
20875 | 902 if (v3 < 0.) |
903 v3 = 0.; | |
18937 | 904 t = frame_context.time - render_context.event->Start; // FIXME: move to render_context |
23133 | 905 if (t <= t1) |
18937 | 906 k = 0.; |
23133 | 907 else if (t >= t2) |
18937 | 908 k = 1.; |
23133 | 909 else { |
910 assert(delta_t != 0.); | |
911 k = pow(((double)(t - t1)) / delta_t, v3); | |
912 } | |
18937 | 913 while (*p == '\\') |
914 p = parse_tag(p, k); // maybe k*pwr ? no, specs forbid nested \t's | |
915 skip_all(')'); // FIXME: better skip(')'), but much more tags support required | |
916 } else if (mystrcmp(&p, "clip")) { | |
917 int x0, y0, x1, y1; | |
918 int res = 1; | |
919 skip('('); | |
920 res &= mystrtoi(&p, 10, &x0); | |
921 skip(','); | |
922 res &= mystrtoi(&p, 10, &y0); | |
923 skip(','); | |
924 res &= mystrtoi(&p, 10, &x1); | |
925 skip(','); | |
926 res &= mystrtoi(&p, 10, &y1); | |
927 skip(')'); | |
928 if (res) { | |
929 render_context.clip_x0 = render_context.clip_x0 * (1-pwr) + x0 * pwr; | |
930 render_context.clip_x1 = render_context.clip_x1 * (1-pwr) + x1 * pwr; | |
931 render_context.clip_y0 = render_context.clip_y0 * (1-pwr) + y0 * pwr; | |
932 render_context.clip_y1 = render_context.clip_y1 * (1-pwr) + y1 * pwr; | |
933 } else { | |
934 render_context.clip_x0 = 0; | |
935 render_context.clip_y0 = 0; | |
936 render_context.clip_x1 = frame_context.track->PlayResX; | |
937 render_context.clip_y1 = frame_context.track->PlayResY; | |
938 } | |
939 } else if (mystrcmp(&p, "c")) { | |
940 uint32_t val; | |
941 if (!strtocolor(&p, &val)) | |
942 val = render_context.style->PrimaryColour; | |
20629
e8885ec63928
Introduce MSGT_ASS, use it for all libass messages.
eugeni
parents:
20503
diff
changeset
|
943 mp_msg(MSGT_ASS, MSGL_DBG2, "color: %X\n", val); |
19691 | 944 change_color(&render_context.c[0], val, pwr); |
18937 | 945 } else if ((*p >= '1') && (*p <= '4') && (++p) && (mystrcmp(&p, "c") || mystrcmp(&p, "a"))) { |
946 char n = *(p-2); | |
19691 | 947 int cidx = n - '1'; |
18937 | 948 char cmd = *(p-1); |
949 uint32_t val; | |
950 assert((n >= '1') && (n <= '4')); | |
951 if (!strtocolor(&p, &val)) | |
952 switch(n) { | |
953 case '1': val = render_context.style->PrimaryColour; break; | |
954 case '2': val = render_context.style->SecondaryColour; break; | |
955 case '3': val = render_context.style->OutlineColour; break; | |
956 case '4': val = render_context.style->BackColour; break; | |
957 default : val = 0; break; // impossible due to assert; avoid compilation warning | |
958 } | |
959 switch (cmd) { | |
19691 | 960 case 'c': change_color(render_context.c + cidx, val, pwr); break; |
961 case 'a': change_alpha(render_context.c + cidx, val >> 24, pwr); break; | |
21066 | 962 default: mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_BadCommand, n, cmd); break; |
18937 | 963 } |
20629
e8885ec63928
Introduce MSGT_ASS, use it for all libass messages.
eugeni
parents:
20503
diff
changeset
|
964 mp_msg(MSGT_ASS, MSGL_DBG2, "single c/a at %f: %c%c = %X \n", pwr, n, cmd, render_context.c[cidx]); |
18937 | 965 } else if (mystrcmp(&p, "r")) { |
19873 | 966 reset_render_context(); |
18937 | 967 } else if (mystrcmp(&p, "be")) { |
968 int val; | |
19848 | 969 if (mystrtoi(&p, 10, &val)) |
970 render_context.be = val ? 1 : 0; | |
971 else | |
972 render_context.be = 0; | |
18937 | 973 } else if (mystrcmp(&p, "b")) { |
974 int b; | |
22262 | 975 if (mystrtoi(&p, 10, &b)) { |
22275
e104fa52d218
With \t(\b) text becomes bold at the middle of time interval, not at the end
eugeni
parents:
22273
diff
changeset
|
976 if (pwr >= .5) |
22262 | 977 render_context.bold = b; |
978 } else | |
22263 | 979 render_context.bold = render_context.style->Bold; |
18937 | 980 update_font(); |
981 } else if (mystrcmp(&p, "i")) { | |
982 int i; | |
22282 | 983 if (mystrtoi(&p, 10, &i)) { |
22275
e104fa52d218
With \t(\b) text becomes bold at the middle of time interval, not at the end
eugeni
parents:
22273
diff
changeset
|
984 if (pwr >= .5) |
22276 | 985 render_context.italic = i; |
22282 | 986 } else |
22263 | 987 render_context.italic = render_context.style->Italic; |
18937 | 988 update_font(); |
989 } else if (mystrcmp(&p, "kf") || mystrcmp(&p, "K")) { | |
990 int val = strtol(p, &p, 10); | |
991 render_context.effect_type = EF_KARAOKE_KF; | |
19716
e4e492fcc2f7
Bugfix: timing for empty karaoke words was lost, resulting
eugeni
parents:
19693
diff
changeset
|
992 if (render_context.effect_timing) |
e4e492fcc2f7
Bugfix: timing for empty karaoke words was lost, resulting
eugeni
parents:
19693
diff
changeset
|
993 render_context.effect_skip_timing += render_context.effect_timing; |
18937 | 994 render_context.effect_timing = val * 10; |
995 } else if (mystrcmp(&p, "ko")) { | |
996 int val = strtol(p, &p, 10); | |
997 render_context.effect_type = EF_KARAOKE_KO; | |
19716
e4e492fcc2f7
Bugfix: timing for empty karaoke words was lost, resulting
eugeni
parents:
19693
diff
changeset
|
998 if (render_context.effect_timing) |
e4e492fcc2f7
Bugfix: timing for empty karaoke words was lost, resulting
eugeni
parents:
19693
diff
changeset
|
999 render_context.effect_skip_timing += render_context.effect_timing; |
18937 | 1000 render_context.effect_timing = val * 10; |
1001 } else if (mystrcmp(&p, "k")) { | |
1002 int val = strtol(p, &p, 10); | |
1003 render_context.effect_type = EF_KARAOKE; | |
19716
e4e492fcc2f7
Bugfix: timing for empty karaoke words was lost, resulting
eugeni
parents:
19693
diff
changeset
|
1004 if (render_context.effect_timing) |
e4e492fcc2f7
Bugfix: timing for empty karaoke words was lost, resulting
eugeni
parents:
19693
diff
changeset
|
1005 render_context.effect_skip_timing += render_context.effect_timing; |
18937 | 1006 render_context.effect_timing = val * 10; |
19965 | 1007 } else if (mystrcmp(&p, "shad")) { |
1008 int val; | |
1009 if (mystrtoi(&p, 10, &val)) | |
1010 render_context.shadow = val; | |
1011 else | |
1012 render_context.shadow = render_context.style->Shadow; | |
18937 | 1013 } |
1014 | |
1015 return p; | |
1016 | |
1017 #undef skip | |
1018 #undef skip_all | |
1019 } | |
1020 | |
1021 /** | |
1022 * \brief Get next ucs4 char from string, parsing and executing style overrides | |
1023 * \param str string pointer | |
1024 * \return ucs4 code of the next char | |
1025 * On return str points to the unparsed part of the string | |
1026 */ | |
1027 static unsigned get_next_char(char** str) | |
1028 { | |
1029 char* p = *str; | |
1030 unsigned chr; | |
1031 if (*p == '{') { // '\0' goes here | |
1032 p++; | |
1033 while (1) { | |
1034 p = parse_tag(p, 1.); | |
1035 if (*p == '}') { // end of tag | |
1036 p++; | |
1037 if (*p == '{') { | |
1038 p++; | |
1039 continue; | |
1040 } else | |
1041 break; | |
1042 } else if (*p != '\\') | |
20629
e8885ec63928
Introduce MSGT_ASS, use it for all libass messages.
eugeni
parents:
20503
diff
changeset
|
1043 mp_msg(MSGT_ASS, MSGL_V, "Unable to parse: \"%s\" \n", p); |
18937 | 1044 if (*p == 0) |
1045 break; | |
1046 } | |
1047 } | |
1048 if (*p == '\t') { | |
1049 ++p; | |
1050 *str = p; | |
1051 return ' '; | |
1052 } | |
1053 if (*p == '\\') { | |
1054 if ((*(p+1) == 'N') || ((*(p+1) == 'n') && (frame_context.track->WrapStyle == 2))) { | |
1055 p += 2; | |
1056 *str = p; | |
1057 return '\n'; | |
1058 } else if (*(p+1) == 'n') { | |
1059 p += 2; | |
1060 *str = p; | |
1061 return ' '; | |
1062 } | |
1063 } | |
20503 | 1064 chr = utf8_get_char(&p); |
18937 | 1065 *str = p; |
1066 return chr; | |
1067 } | |
1068 | |
19556 | 1069 static void apply_transition_effects(ass_event_t* event) |
1070 { | |
1071 int v[4]; | |
1072 int cnt; | |
1073 char* p = event->Effect; | |
1074 | |
1075 if (!p || !*p) return; | |
1076 | |
1077 cnt = 0; | |
1078 while (cnt < 4 && (p = strchr(p, ';'))) { | |
1079 v[cnt++] = atoi(++p); | |
1080 } | |
1081 | |
1082 if (strncmp(event->Effect, "Banner;", 7) == 0) { | |
1083 int delay; | |
1084 if (cnt < 1) { | |
20629
e8885ec63928
Introduce MSGT_ASS, use it for all libass messages.
eugeni
parents:
20503
diff
changeset
|
1085 mp_msg(MSGT_ASS, MSGL_V, "Error parsing effect: %s \n", event->Effect); |
19556 | 1086 return; |
1087 } | |
1088 if (cnt >= 2 && v[1] == 0) // right-to-left | |
1089 render_context.scroll_direction = SCROLL_RL; | |
1090 else // left-to-right | |
1091 render_context.scroll_direction = SCROLL_LR; | |
1092 | |
1093 delay = v[0]; | |
1094 if (delay == 0) delay = 1; // ? | |
1095 render_context.scroll_shift = (frame_context.time - render_context.event->Start) / delay; | |
1096 render_context.evt_type = EVENT_HSCROLL; | |
1097 return; | |
1098 } | |
1099 | |
1100 if (strncmp(event->Effect, "Scroll up;", 10) == 0) { | |
1101 render_context.scroll_direction = SCROLL_BT; | |
1102 } else if (strncmp(event->Effect, "Scroll down;", 12) == 0) { | |
1103 render_context.scroll_direction = SCROLL_TB; | |
1104 } else { | |
20629
e8885ec63928
Introduce MSGT_ASS, use it for all libass messages.
eugeni
parents:
20503
diff
changeset
|
1105 mp_msg(MSGT_ASS, MSGL_V, "Unknown transition effect: %s \n", event->Effect); |
19556 | 1106 return; |
1107 } | |
1108 // parse scroll up/down parameters | |
1109 { | |
1110 int delay; | |
1111 int y0, y1; | |
1112 if (cnt < 3) { | |
20629
e8885ec63928
Introduce MSGT_ASS, use it for all libass messages.
eugeni
parents:
20503
diff
changeset
|
1113 mp_msg(MSGT_ASS, MSGL_V, "Error parsing effect: %s \n", event->Effect); |
19556 | 1114 return; |
1115 } | |
1116 delay = v[2]; | |
1117 if (delay == 0) delay = 1; // ? | |
1118 render_context.scroll_shift = (frame_context.time - render_context.event->Start) / delay; | |
1119 if (v[0] < v[1]) { | |
1120 y0 = v[0]; y1 = v[1]; | |
1121 } else { | |
1122 y0 = v[1]; y1 = v[0]; | |
1123 } | |
1124 if (y1 == 0) | |
1125 y1 = frame_context.track->PlayResY; // y0=y1=0 means fullscreen scrolling | |
1126 render_context.clip_y0 = y0; | |
1127 render_context.clip_y1 = y1; | |
1128 render_context.evt_type = EVENT_VSCROLL; | |
19638
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
1129 render_context.detect_collisions = 0; |
19556 | 1130 } |
1131 | |
1132 } | |
1133 | |
18937 | 1134 /** |
19873 | 1135 * \brief partially reset render_context to style values |
1136 * Works like {\r}: resets some style overrides | |
1137 */ | |
1138 static void reset_render_context(void) | |
1139 { | |
1140 render_context.c[0] = render_context.style->PrimaryColour; | |
1141 render_context.c[1] = render_context.style->SecondaryColour; | |
1142 render_context.c[2] = render_context.style->OutlineColour; | |
1143 render_context.c[3] = render_context.style->BackColour; | |
1144 render_context.font_size = render_context.style->FontSize; | |
1145 | |
1146 if (render_context.family) | |
1147 free(render_context.family); | |
1148 render_context.family = strdup(render_context.style->FontName); | |
22263 | 1149 render_context.bold = render_context.style->Bold; |
1150 render_context.italic = render_context.style->Italic; | |
19873 | 1151 update_font(); |
1152 | |
1153 change_border(-1.); | |
1154 render_context.scale_x = render_context.style->ScaleX; | |
1155 render_context.scale_y = render_context.style->ScaleY; | |
22259 | 1156 render_context.hspacing = render_context.style->Spacing; |
19873 | 1157 render_context.be = 0; |
19965 | 1158 render_context.shadow = render_context.style->Shadow; |
22215
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
1159 render_context.frx = render_context.fry = 0.; |
22214 | 1160 render_context.frz = M_PI * render_context.style->Angle / 180.; |
19873 | 1161 |
1162 // FIXME: does not reset unsupported attributes. | |
1163 } | |
1164 | |
1165 /** | |
18937 | 1166 * \brief Start new event. Reset render_context. |
1167 */ | |
19873 | 1168 static void init_render_context(ass_event_t* event) |
18937 | 1169 { |
1170 render_context.event = event; | |
1171 render_context.style = frame_context.track->styles + event->Style; | |
19873 | 1172 |
1173 reset_render_context(); | |
1174 | |
18937 | 1175 render_context.evt_type = EVENT_NORMAL; |
22273
13a3013f3a27
Any style modifier followed by no recognizable parameter resets to the default.
eugeni
parents:
22269
diff
changeset
|
1176 render_context.alignment = render_context.style->Alignment; |
18937 | 1177 render_context.pos_x = 0; |
1178 render_context.pos_y = 0; | |
1179 render_context.org_x = 0; | |
1180 render_context.org_y = 0; | |
22207 | 1181 render_context.have_origin = 0; |
18937 | 1182 render_context.clip_x0 = 0; |
1183 render_context.clip_y0 = 0; | |
1184 render_context.clip_x1 = frame_context.track->PlayResX; | |
1185 render_context.clip_y1 = frame_context.track->PlayResY; | |
1186 render_context.detect_collisions = 1; | |
19692
5b40e87b9619
Change \fad behaviour so that it does not get cancelled by \r.
eugeni
parents:
19691
diff
changeset
|
1187 render_context.fade = 0; |
19716
e4e492fcc2f7
Bugfix: timing for empty karaoke words was lost, resulting
eugeni
parents:
19693
diff
changeset
|
1188 render_context.effect_type = EF_NONE; |
e4e492fcc2f7
Bugfix: timing for empty karaoke words was lost, resulting
eugeni
parents:
19693
diff
changeset
|
1189 render_context.effect_timing = 0; |
e4e492fcc2f7
Bugfix: timing for empty karaoke words was lost, resulting
eugeni
parents:
19693
diff
changeset
|
1190 render_context.effect_skip_timing = 0; |
18937 | 1191 |
19556 | 1192 apply_transition_effects(event); |
18937 | 1193 } |
1194 | |
19873 | 1195 static void free_render_context(void) |
18937 | 1196 { |
1197 } | |
1198 | |
23179 | 1199 /** |
1200 * \brief Get normal and outline (border) glyphs | |
1201 * \param symbol ucs4 char | |
1202 * \param info out: struct filled with extracted data | |
1203 * \param advance subpixel shift vector used for cache lookup | |
1204 * Tries to get both glyphs from cache. | |
1205 * If they can't be found, gets a glyph from font face, generates outline with FT_Stroker, | |
1206 * and add them to cache. | |
1207 * The glyphs are returned in info->glyph and info->outline_glyph | |
1208 */ | |
23022 | 1209 static void get_outline_glyph(int symbol, glyph_info_t* info, FT_Vector* advance) |
23021
a81c390d4a22
Move outline glyph generation to a separate function, using outline glyph
eugeni
parents:
23017
diff
changeset
|
1210 { |
a81c390d4a22
Move outline glyph generation to a separate function, using outline glyph
eugeni
parents:
23017
diff
changeset
|
1211 int error; |
a81c390d4a22
Move outline glyph generation to a separate function, using outline glyph
eugeni
parents:
23017
diff
changeset
|
1212 glyph_hash_val_t* val; |
a81c390d4a22
Move outline glyph generation to a separate function, using outline glyph
eugeni
parents:
23017
diff
changeset
|
1213 glyph_hash_key_t key; |
a81c390d4a22
Move outline glyph generation to a separate function, using outline glyph
eugeni
parents:
23017
diff
changeset
|
1214 key.font = render_context.font; |
a81c390d4a22
Move outline glyph generation to a separate function, using outline glyph
eugeni
parents:
23017
diff
changeset
|
1215 key.size = render_context.font_size; |
a81c390d4a22
Move outline glyph generation to a separate function, using outline glyph
eugeni
parents:
23017
diff
changeset
|
1216 key.ch = symbol; |
a81c390d4a22
Move outline glyph generation to a separate function, using outline glyph
eugeni
parents:
23017
diff
changeset
|
1217 key.scale_x = (render_context.scale_x * 0xFFFF); |
a81c390d4a22
Move outline glyph generation to a separate function, using outline glyph
eugeni
parents:
23017
diff
changeset
|
1218 key.scale_y = (render_context.scale_y * 0xFFFF); |
a81c390d4a22
Move outline glyph generation to a separate function, using outline glyph
eugeni
parents:
23017
diff
changeset
|
1219 key.advance = *advance; |
a81c390d4a22
Move outline glyph generation to a separate function, using outline glyph
eugeni
parents:
23017
diff
changeset
|
1220 key.bold = render_context.bold; |
a81c390d4a22
Move outline glyph generation to a separate function, using outline glyph
eugeni
parents:
23017
diff
changeset
|
1221 key.italic = render_context.italic; |
23170
15a05bafc9c7
Bugfix: glyph cache depends on border width, because it contains outline_glyph
eugeni
parents:
23134
diff
changeset
|
1222 key.outline = render_context.border * 0xFFFF; |
23021
a81c390d4a22
Move outline glyph generation to a separate function, using outline glyph
eugeni
parents:
23017
diff
changeset
|
1223 |
a81c390d4a22
Move outline glyph generation to a separate function, using outline glyph
eugeni
parents:
23017
diff
changeset
|
1224 info->glyph = info->outline_glyph = 0; |
a81c390d4a22
Move outline glyph generation to a separate function, using outline glyph
eugeni
parents:
23017
diff
changeset
|
1225 |
a81c390d4a22
Move outline glyph generation to a separate function, using outline glyph
eugeni
parents:
23017
diff
changeset
|
1226 val = cache_find_glyph(&key); |
a81c390d4a22
Move outline glyph generation to a separate function, using outline glyph
eugeni
parents:
23017
diff
changeset
|
1227 if (val) { |
a81c390d4a22
Move outline glyph generation to a separate function, using outline glyph
eugeni
parents:
23017
diff
changeset
|
1228 FT_Glyph_Copy(val->glyph, &info->glyph); |
23086 | 1229 if (val->outline_glyph) |
1230 FT_Glyph_Copy(val->outline_glyph, &info->outline_glyph); | |
23021
a81c390d4a22
Move outline glyph generation to a separate function, using outline glyph
eugeni
parents:
23017
diff
changeset
|
1231 info->bbox = val->bbox_scaled; |
a81c390d4a22
Move outline glyph generation to a separate function, using outline glyph
eugeni
parents:
23017
diff
changeset
|
1232 info->advance.x = val->advance.x; |
a81c390d4a22
Move outline glyph generation to a separate function, using outline glyph
eugeni
parents:
23017
diff
changeset
|
1233 info->advance.y = val->advance.y; |
a81c390d4a22
Move outline glyph generation to a separate function, using outline glyph
eugeni
parents:
23017
diff
changeset
|
1234 } else { |
a81c390d4a22
Move outline glyph generation to a separate function, using outline glyph
eugeni
parents:
23017
diff
changeset
|
1235 glyph_hash_val_t v; |
23134
1de2a46a0987
Add -ass-hinting option for setting font hinting method.
eugeni
parents:
23133
diff
changeset
|
1236 info->glyph = ass_font_get_glyph(frame_context.ass_priv->fontconfig_priv, render_context.font, symbol, global_settings->hinting); |
23021
a81c390d4a22
Move outline glyph generation to a separate function, using outline glyph
eugeni
parents:
23017
diff
changeset
|
1237 if (!info->glyph) |
23022 | 1238 return; |
23021
a81c390d4a22
Move outline glyph generation to a separate function, using outline glyph
eugeni
parents:
23017
diff
changeset
|
1239 info->advance.x = d16_to_d6(info->glyph->advance.x); |
a81c390d4a22
Move outline glyph generation to a separate function, using outline glyph
eugeni
parents:
23017
diff
changeset
|
1240 info->advance.y = d16_to_d6(info->glyph->advance.y); |
a81c390d4a22
Move outline glyph generation to a separate function, using outline glyph
eugeni
parents:
23017
diff
changeset
|
1241 FT_Glyph_Get_CBox( info->glyph, FT_GLYPH_BBOX_PIXELS, &info->bbox); |
a81c390d4a22
Move outline glyph generation to a separate function, using outline glyph
eugeni
parents:
23017
diff
changeset
|
1242 |
23025
ab0943242d1a
Store outline_glyph (glyph border) in glyph cache.
eugeni
parents:
23024
diff
changeset
|
1243 if (render_context.stroker) { |
ab0943242d1a
Store outline_glyph (glyph border) in glyph cache.
eugeni
parents:
23024
diff
changeset
|
1244 info->outline_glyph = info->glyph; |
ab0943242d1a
Store outline_glyph (glyph border) in glyph cache.
eugeni
parents:
23024
diff
changeset
|
1245 error = FT_Glyph_StrokeBorder( &(info->outline_glyph), render_context.stroker, 0 , 0 ); // don't destroy original |
ab0943242d1a
Store outline_glyph (glyph border) in glyph cache.
eugeni
parents:
23024
diff
changeset
|
1246 if (error) { |
ab0943242d1a
Store outline_glyph (glyph border) in glyph cache.
eugeni
parents:
23024
diff
changeset
|
1247 mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_FT_Glyph_Stroke_Error, error); |
ab0943242d1a
Store outline_glyph (glyph border) in glyph cache.
eugeni
parents:
23024
diff
changeset
|
1248 } |
ab0943242d1a
Store outline_glyph (glyph border) in glyph cache.
eugeni
parents:
23024
diff
changeset
|
1249 } |
ab0943242d1a
Store outline_glyph (glyph border) in glyph cache.
eugeni
parents:
23024
diff
changeset
|
1250 |
23086 | 1251 memset(&v, 0, sizeof(v)); |
23021
a81c390d4a22
Move outline glyph generation to a separate function, using outline glyph
eugeni
parents:
23017
diff
changeset
|
1252 FT_Glyph_Copy(info->glyph, &v.glyph); |
23086 | 1253 if (info->outline_glyph) |
1254 FT_Glyph_Copy(info->outline_glyph, &v.outline_glyph); | |
23021
a81c390d4a22
Move outline glyph generation to a separate function, using outline glyph
eugeni
parents:
23017
diff
changeset
|
1255 v.advance = info->advance; |
a81c390d4a22
Move outline glyph generation to a separate function, using outline glyph
eugeni
parents:
23017
diff
changeset
|
1256 v.bbox_scaled = info->bbox; |
a81c390d4a22
Move outline glyph generation to a separate function, using outline glyph
eugeni
parents:
23017
diff
changeset
|
1257 cache_add_glyph(&key, &v); |
a81c390d4a22
Move outline glyph generation to a separate function, using outline glyph
eugeni
parents:
23017
diff
changeset
|
1258 } |
a81c390d4a22
Move outline glyph generation to a separate function, using outline glyph
eugeni
parents:
23017
diff
changeset
|
1259 } |
a81c390d4a22
Move outline glyph generation to a separate function, using outline glyph
eugeni
parents:
23017
diff
changeset
|
1260 |
23173 | 1261 static void transform_3d(FT_Vector shift, FT_Glyph* glyph, FT_Glyph* glyph2, double frx, double fry, double frz); |
1262 | |
18937 | 1263 /** |
23179 | 1264 * \brief Get bitmaps for a glyph |
1265 * \param info glyph info | |
1266 * Tries to get glyph bitmaps from bitmap cache. | |
1267 * If they can't be found, they are generated by rotating and rendering the glyph. | |
1268 * After that, bitmaps are added to the cache. | |
1269 * They are returned in info->bm (glyph), info->bm_o (outline) and info->bm_s (shadow). | |
18937 | 1270 */ |
23027
b4db05aea29e
Fill bitmap_hash_key during parsing stage, call get_bitmap_glyph() much later.
eugeni
parents:
23026
diff
changeset
|
1271 static void get_bitmap_glyph(glyph_info_t* info) |
18937 | 1272 { |
23017 | 1273 bitmap_hash_val_t* val; |
23030 | 1274 bitmap_hash_key_t* key = &info->hash_key; |
18937 | 1275 |
23017 | 1276 val = cache_find_bitmap(key); |
23015 | 1277 /* val = 0; */ |
18937 | 1278 |
1279 if (val) { | |
19846
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
19825
diff
changeset
|
1280 info->bm = val->bm; |
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
19825
diff
changeset
|
1281 info->bm_o = val->bm_o; |
19965 | 1282 info->bm_s = val->bm_s; |
23173 | 1283 } else { |
1284 FT_Vector shift; | |
23177
134a2baca452
Move glyph_to_bitmap() call and outline glyph deallocation to
eugeni
parents:
23175
diff
changeset
|
1285 bitmap_hash_val_t hash_val; |
134a2baca452
Move glyph_to_bitmap() call and outline glyph deallocation to
eugeni
parents:
23175
diff
changeset
|
1286 int error; |
23021
a81c390d4a22
Move outline glyph generation to a separate function, using outline glyph
eugeni
parents:
23017
diff
changeset
|
1287 info->bm = info->bm_o = info->bm_s = 0; |
23177
134a2baca452
Move glyph_to_bitmap() call and outline glyph deallocation to
eugeni
parents:
23175
diff
changeset
|
1288 if (info->glyph && info->symbol != '\n' && info->symbol != 0) { |
23179 | 1289 // calculating rotation shift vector (from rotation origin to the glyph basepoint) |
23178 | 1290 shift.x = int_to_d6(info->hash_key.shift_x); |
1291 shift.y = int_to_d6(info->hash_key.shift_y); | |
23179 | 1292 // apply rotation |
23178 | 1293 transform_3d(shift, &info->glyph, &info->outline_glyph, info->frx, info->fry, info->frz); |
23177
134a2baca452
Move glyph_to_bitmap() call and outline glyph deallocation to
eugeni
parents:
23175
diff
changeset
|
1294 |
23179 | 1295 // render glyph |
23177
134a2baca452
Move glyph_to_bitmap() call and outline glyph deallocation to
eugeni
parents:
23175
diff
changeset
|
1296 error = glyph_to_bitmap(ass_renderer->synth_priv, |
134a2baca452
Move glyph_to_bitmap() call and outline glyph deallocation to
eugeni
parents:
23175
diff
changeset
|
1297 info->glyph, info->outline_glyph, |
134a2baca452
Move glyph_to_bitmap() call and outline glyph deallocation to
eugeni
parents:
23175
diff
changeset
|
1298 &info->bm, &info->bm_o, |
134a2baca452
Move glyph_to_bitmap() call and outline glyph deallocation to
eugeni
parents:
23175
diff
changeset
|
1299 &info->bm_s, info->be); |
134a2baca452
Move glyph_to_bitmap() call and outline glyph deallocation to
eugeni
parents:
23175
diff
changeset
|
1300 if (error) |
134a2baca452
Move glyph_to_bitmap() call and outline glyph deallocation to
eugeni
parents:
23175
diff
changeset
|
1301 info->symbol = 0; |
134a2baca452
Move glyph_to_bitmap() call and outline glyph deallocation to
eugeni
parents:
23175
diff
changeset
|
1302 |
23179 | 1303 // add bitmaps to cache |
23177
134a2baca452
Move glyph_to_bitmap() call and outline glyph deallocation to
eugeni
parents:
23175
diff
changeset
|
1304 hash_val.bm_o = info->bm_o; |
134a2baca452
Move glyph_to_bitmap() call and outline glyph deallocation to
eugeni
parents:
23175
diff
changeset
|
1305 hash_val.bm = info->bm; |
134a2baca452
Move glyph_to_bitmap() call and outline glyph deallocation to
eugeni
parents:
23175
diff
changeset
|
1306 hash_val.bm_s = info->bm_s; |
134a2baca452
Move glyph_to_bitmap() call and outline glyph deallocation to
eugeni
parents:
23175
diff
changeset
|
1307 cache_add_bitmap(&(info->hash_key), &hash_val); |
134a2baca452
Move glyph_to_bitmap() call and outline glyph deallocation to
eugeni
parents:
23175
diff
changeset
|
1308 } |
23173 | 1309 } |
23190 | 1310 // deallocate glyphs |
1311 if (info->glyph) | |
1312 FT_Done_Glyph(info->glyph); | |
1313 if (info->outline_glyph) | |
1314 FT_Done_Glyph(info->outline_glyph); | |
18937 | 1315 } |
1316 | |
1317 /** | |
19932
0b5b9cbbc74e
Move calculation of text parameters (number of lines, height, etc.) from
eugeni
parents:
19931
diff
changeset
|
1318 * This function goes through text_info and calculates text parameters. |
0b5b9cbbc74e
Move calculation of text parameters (number of lines, height, etc.) from
eugeni
parents:
19931
diff
changeset
|
1319 * The following text_info fields are filled: |
0b5b9cbbc74e
Move calculation of text parameters (number of lines, height, etc.) from
eugeni
parents:
19931
diff
changeset
|
1320 * n_lines |
0b5b9cbbc74e
Move calculation of text parameters (number of lines, height, etc.) from
eugeni
parents:
19931
diff
changeset
|
1321 * height |
0b5b9cbbc74e
Move calculation of text parameters (number of lines, height, etc.) from
eugeni
parents:
19931
diff
changeset
|
1322 * lines[].height |
0b5b9cbbc74e
Move calculation of text parameters (number of lines, height, etc.) from
eugeni
parents:
19931
diff
changeset
|
1323 * lines[].asc |
0b5b9cbbc74e
Move calculation of text parameters (number of lines, height, etc.) from
eugeni
parents:
19931
diff
changeset
|
1324 * lines[].desc |
0b5b9cbbc74e
Move calculation of text parameters (number of lines, height, etc.) from
eugeni
parents:
19931
diff
changeset
|
1325 */ |
22886 | 1326 static void measure_text(void) |
19932
0b5b9cbbc74e
Move calculation of text parameters (number of lines, height, etc.) from
eugeni
parents:
19931
diff
changeset
|
1327 { |
0b5b9cbbc74e
Move calculation of text parameters (number of lines, height, etc.) from
eugeni
parents:
19931
diff
changeset
|
1328 int cur_line = 0, max_asc = 0, max_desc = 0; |
0b5b9cbbc74e
Move calculation of text parameters (number of lines, height, etc.) from
eugeni
parents:
19931
diff
changeset
|
1329 int i; |
0b5b9cbbc74e
Move calculation of text parameters (number of lines, height, etc.) from
eugeni
parents:
19931
diff
changeset
|
1330 text_info.height = 0; |
0b5b9cbbc74e
Move calculation of text parameters (number of lines, height, etc.) from
eugeni
parents:
19931
diff
changeset
|
1331 for (i = 0; i < text_info.length + 1; ++i) { |
0b5b9cbbc74e
Move calculation of text parameters (number of lines, height, etc.) from
eugeni
parents:
19931
diff
changeset
|
1332 if ((i == text_info.length) || text_info.glyphs[i].linebreak) { |
0b5b9cbbc74e
Move calculation of text parameters (number of lines, height, etc.) from
eugeni
parents:
19931
diff
changeset
|
1333 text_info.lines[cur_line].asc = max_asc; |
0b5b9cbbc74e
Move calculation of text parameters (number of lines, height, etc.) from
eugeni
parents:
19931
diff
changeset
|
1334 text_info.lines[cur_line].desc = max_desc; |
0b5b9cbbc74e
Move calculation of text parameters (number of lines, height, etc.) from
eugeni
parents:
19931
diff
changeset
|
1335 text_info.height += max_asc + max_desc; |
0b5b9cbbc74e
Move calculation of text parameters (number of lines, height, etc.) from
eugeni
parents:
19931
diff
changeset
|
1336 cur_line ++; |
0b5b9cbbc74e
Move calculation of text parameters (number of lines, height, etc.) from
eugeni
parents:
19931
diff
changeset
|
1337 max_asc = max_desc = 0; |
0b5b9cbbc74e
Move calculation of text parameters (number of lines, height, etc.) from
eugeni
parents:
19931
diff
changeset
|
1338 } |
0b5b9cbbc74e
Move calculation of text parameters (number of lines, height, etc.) from
eugeni
parents:
19931
diff
changeset
|
1339 if (i < text_info.length) { |
0b5b9cbbc74e
Move calculation of text parameters (number of lines, height, etc.) from
eugeni
parents:
19931
diff
changeset
|
1340 glyph_info_t* cur = text_info.glyphs + i; |
0b5b9cbbc74e
Move calculation of text parameters (number of lines, height, etc.) from
eugeni
parents:
19931
diff
changeset
|
1341 if (cur->asc > max_asc) |
22261 | 1342 max_asc = cur->asc; |
19932
0b5b9cbbc74e
Move calculation of text parameters (number of lines, height, etc.) from
eugeni
parents:
19931
diff
changeset
|
1343 if (cur->desc > max_desc) |
22261 | 1344 max_desc = cur->desc; |
19932
0b5b9cbbc74e
Move calculation of text parameters (number of lines, height, etc.) from
eugeni
parents:
19931
diff
changeset
|
1345 } |
0b5b9cbbc74e
Move calculation of text parameters (number of lines, height, etc.) from
eugeni
parents:
19931
diff
changeset
|
1346 } |
0b5b9cbbc74e
Move calculation of text parameters (number of lines, height, etc.) from
eugeni
parents:
19931
diff
changeset
|
1347 } |
0b5b9cbbc74e
Move calculation of text parameters (number of lines, height, etc.) from
eugeni
parents:
19931
diff
changeset
|
1348 |
0b5b9cbbc74e
Move calculation of text parameters (number of lines, height, etc.) from
eugeni
parents:
19931
diff
changeset
|
1349 /** |
18937 | 1350 * \brief rearrange text between lines |
1351 * \param max_text_width maximal text line width in pixels | |
1352 * The algo is similar to the one in libvo/sub.c: | |
1353 * 1. Place text, wrapping it when current line is full | |
1354 * 2. Try moving words from the end of a line to the beginning of the next one while it reduces | |
1355 * the difference in lengths between this two lines. | |
1356 * The result may not be optimal, but usually is good enough. | |
1357 */ | |
1358 static void wrap_lines_smart(int max_text_width) | |
1359 { | |
1360 int i, j; | |
1361 glyph_info_t *cur, *s1, *e1, *s2, *s3, *w; | |
1362 int last_space; | |
1363 int break_type; | |
1364 int exit; | |
1365 int pen_shift_x; | |
1366 int pen_shift_y; | |
1367 int cur_line; | |
1368 | |
1369 last_space = -1; | |
1370 text_info.n_lines = 1; | |
1371 break_type = 0; | |
1372 s1 = text_info.glyphs; // current line start | |
1373 for (i = 0; i < text_info.length; ++i) { | |
19370 | 1374 int break_at, s_offset, len; |
18937 | 1375 cur = text_info.glyphs + i; |
19370 | 1376 break_at = -1; |
1377 s_offset = s1->bbox.xMin + s1->pos.x; | |
1378 len = (cur->bbox.xMax + cur->pos.x) - s_offset; | |
18937 | 1379 |
1380 if (cur->symbol == '\n') { | |
1381 break_type = 2; | |
1382 break_at = i; | |
20629
e8885ec63928
Introduce MSGT_ASS, use it for all libass messages.
eugeni
parents:
20503
diff
changeset
|
1383 mp_msg(MSGT_ASS, MSGL_DBG2, "forced line break at %d\n", break_at); |
18937 | 1384 } |
1385 | |
1386 if (len >= max_text_width) { | |
1387 break_type = 1; | |
1388 break_at = last_space; | |
1389 if (break_at == -1) | |
1390 break_at = i - 1; | |
1391 if (break_at == -1) | |
1392 break_at = 0; | |
20629
e8885ec63928
Introduce MSGT_ASS, use it for all libass messages.
eugeni
parents:
20503
diff
changeset
|
1393 mp_msg(MSGT_ASS, MSGL_DBG2, "overfill at %d\n", i); |
e8885ec63928
Introduce MSGT_ASS, use it for all libass messages.
eugeni
parents:
20503
diff
changeset
|
1394 mp_msg(MSGT_ASS, MSGL_DBG2, "line break at %d\n", break_at); |
18937 | 1395 } |
1396 | |
1397 if (break_at != -1) { | |
1398 // need to use one more line | |
1399 // marking break_at+1 as start of a new line | |
1400 int lead = break_at + 1; // the first symbol of the new line | |
1401 if (text_info.n_lines >= MAX_LINES) { | |
1402 // to many lines ! | |
1403 // no more linebreaks | |
1404 for (j = lead; j < text_info.length; ++j) | |
1405 text_info.glyphs[j].linebreak = 0; | |
1406 break; | |
1407 } | |
1408 if (lead < text_info.length) | |
1409 text_info.glyphs[lead].linebreak = break_type; | |
1410 last_space = -1; | |
1411 s1 = text_info.glyphs + lead; | |
1412 s_offset = s1->bbox.xMin + s1->pos.x; | |
1413 text_info.n_lines ++; | |
1414 } | |
1415 | |
1416 if (cur->symbol == ' ') | |
1417 last_space = i; | |
22913
07ecf1d8922e
Fix lost hard linebreaks in libass by repeating the loop when both soft and
eugeni
parents:
22886
diff
changeset
|
1418 |
07ecf1d8922e
Fix lost hard linebreaks in libass by repeating the loop when both soft and
eugeni
parents:
22886
diff
changeset
|
1419 // make sure the hard linebreak is not forgotten when |
07ecf1d8922e
Fix lost hard linebreaks in libass by repeating the loop when both soft and
eugeni
parents:
22886
diff
changeset
|
1420 // there was a new soft linebreak just inserted |
07ecf1d8922e
Fix lost hard linebreaks in libass by repeating the loop when both soft and
eugeni
parents:
22886
diff
changeset
|
1421 if (cur->symbol == '\n' && break_type == 1) |
07ecf1d8922e
Fix lost hard linebreaks in libass by repeating the loop when both soft and
eugeni
parents:
22886
diff
changeset
|
1422 i--; |
18937 | 1423 } |
1424 #define DIFF(x,y) (((x) < (y)) ? (y - x) : (x - y)) | |
1425 exit = 0; | |
1426 while (!exit) { | |
1427 exit = 1; | |
1428 w = s3 = text_info.glyphs; | |
1429 s1 = s2 = 0; | |
1430 for (i = 0; i <= text_info.length; ++i) { | |
1431 cur = text_info.glyphs + i; | |
1432 if ((i == text_info.length) || cur->linebreak) { | |
1433 s1 = s2; | |
1434 s2 = s3; | |
1435 s3 = cur; | |
1436 if (s1 && (s2->linebreak == 1)) { // have at least 2 lines, and linebreak is 'soft' | |
1437 int l1, l2, l1_new, l2_new; | |
1438 | |
1439 w = s2; | |
1440 do { --w; } while ((w > s1) && (w->symbol == ' ')); | |
19663
042680f89e7d
Fix possible unallocated memory read in libass line wrapping code.
eugeni
parents:
19651
diff
changeset
|
1441 while ((w > s1) && (w->symbol != ' ')) { --w; } |
18937 | 1442 e1 = w; |
19663
042680f89e7d
Fix possible unallocated memory read in libass line wrapping code.
eugeni
parents:
19651
diff
changeset
|
1443 while ((e1 > s1) && (e1->symbol == ' ')) { --e1; } |
18937 | 1444 if (w->symbol == ' ') ++w; |
1445 | |
1446 l1 = ((s2-1)->bbox.xMax + (s2-1)->pos.x) - (s1->bbox.xMin + s1->pos.x); | |
1447 l2 = ((s3-1)->bbox.xMax + (s3-1)->pos.x) - (s2->bbox.xMin + s2->pos.x); | |
1448 l1_new = (e1->bbox.xMax + e1->pos.x) - (s1->bbox.xMin + s1->pos.x); | |
1449 l2_new = ((s3-1)->bbox.xMax + (s3-1)->pos.x) - (w->bbox.xMin + w->pos.x); | |
1450 | |
1451 if (DIFF(l1_new, l2_new) < DIFF(l1, l2)) { | |
1452 w->linebreak = 1; | |
1453 s2->linebreak = 0; | |
1454 exit = 0; | |
1455 } | |
1456 } | |
1457 } | |
1458 if (i == text_info.length) | |
1459 break; | |
1460 } | |
1461 | |
1462 } | |
1463 assert(text_info.n_lines >= 1); | |
1464 #undef DIFF | |
1465 | |
19932
0b5b9cbbc74e
Move calculation of text parameters (number of lines, height, etc.) from
eugeni
parents:
19931
diff
changeset
|
1466 measure_text(); |
0b5b9cbbc74e
Move calculation of text parameters (number of lines, height, etc.) from
eugeni
parents:
19931
diff
changeset
|
1467 |
18937 | 1468 pen_shift_x = 0; |
1469 pen_shift_y = 0; | |
1470 cur_line = 1; | |
1471 for (i = 0; i < text_info.length; ++i) { | |
1472 cur = text_info.glyphs + i; | |
1473 if (cur->linebreak) { | |
1474 int height = text_info.lines[cur_line - 1].desc + text_info.lines[cur_line].asc; | |
1475 cur_line ++; | |
1476 pen_shift_x = - cur->pos.x; | |
22213
66abe12ad374
Move conversions between 16.16, 26.6 fixed point and int, double to separate
eugeni
parents:
22209
diff
changeset
|
1477 pen_shift_y += d6_to_int(height) + global_settings->line_spacing; |
20629
e8885ec63928
Introduce MSGT_ASS, use it for all libass messages.
eugeni
parents:
20503
diff
changeset
|
1478 mp_msg(MSGT_ASS, MSGL_DBG2, "shifting from %d to %d by (%d, %d)\n", i, text_info.length - 1, pen_shift_x, pen_shift_y); |
18937 | 1479 } |
1480 cur->pos.x += pen_shift_x; | |
1481 cur->pos.y += pen_shift_y; | |
1482 } | |
1483 } | |
1484 | |
1485 /** | |
1486 * \brief determine karaoke effects | |
1487 * Karaoke effects cannot be calculated during parse stage (get_next_char()), | |
1488 * so they are done in a separate step. | |
1489 * Parse stage: when karaoke style override is found, its parameters are stored in the next glyph's | |
1490 * (the first glyph of the karaoke word)'s effect_type and effect_timing. | |
1491 * This function: | |
1492 * 1. sets effect_type for all glyphs in the word (_karaoke_ word) | |
1493 * 2. sets effect_timing for all glyphs to x coordinate of the border line between the left and right karaoke parts | |
1494 * (left part is filled with PrimaryColour, right one - with SecondaryColour). | |
1495 */ | |
1496 static void process_karaoke_effects(void) | |
1497 { | |
1498 glyph_info_t *cur, *cur2; | |
1499 glyph_info_t *s1, *e1; // start and end of the current word | |
1500 glyph_info_t *s2; // start of the next word | |
1501 int i; | |
1502 int timing; // current timing | |
1503 int tm_start, tm_end; // timings at start and end of the current word | |
1504 int tm_current; | |
1505 double dt; | |
1506 int x; | |
1507 int x_start, x_end; | |
1508 | |
1509 tm_current = frame_context.time - render_context.event->Start; | |
1510 timing = 0; | |
1511 s1 = s2 = 0; | |
1512 for (i = 0; i <= text_info.length; ++i) { | |
1513 cur = text_info.glyphs + i; | |
1514 if ((i == text_info.length) || (cur->effect_type != EF_NONE)) { | |
1515 s1 = s2; | |
1516 s2 = cur; | |
1517 if (s1) { | |
1518 e1 = s2 - 1; | |
19716
e4e492fcc2f7
Bugfix: timing for empty karaoke words was lost, resulting
eugeni
parents:
19693
diff
changeset
|
1519 tm_start = timing + s1->effect_skip_timing; |
e4e492fcc2f7
Bugfix: timing for empty karaoke words was lost, resulting
eugeni
parents:
19693
diff
changeset
|
1520 tm_end = tm_start + s1->effect_timing; |
18937 | 1521 timing = tm_end; |
20653
402484a85b9f
More precise bounding box calculation for karaoke effects.
eugeni
parents:
20629
diff
changeset
|
1522 x_start = 1000000; |
402484a85b9f
More precise bounding box calculation for karaoke effects.
eugeni
parents:
20629
diff
changeset
|
1523 x_end = -1000000; |
402484a85b9f
More precise bounding box calculation for karaoke effects.
eugeni
parents:
20629
diff
changeset
|
1524 for (cur2 = s1; cur2 <= e1; ++cur2) { |
402484a85b9f
More precise bounding box calculation for karaoke effects.
eugeni
parents:
20629
diff
changeset
|
1525 x_start = FFMIN(x_start, cur2->bbox.xMin + cur2->pos.x); |
402484a85b9f
More precise bounding box calculation for karaoke effects.
eugeni
parents:
20629
diff
changeset
|
1526 x_end = FFMAX(x_end, cur2->bbox.xMax + cur2->pos.x); |
402484a85b9f
More precise bounding box calculation for karaoke effects.
eugeni
parents:
20629
diff
changeset
|
1527 } |
18937 | 1528 |
1529 dt = (tm_current - tm_start); | |
1530 if ((s1->effect_type == EF_KARAOKE) || (s1->effect_type == EF_KARAOKE_KO)) { | |
1531 if (dt > 0) | |
1532 x = x_end + 1; | |
1533 else | |
1534 x = x_start; | |
1535 } else if (s1->effect_type == EF_KARAOKE_KF) { | |
1536 dt /= (tm_end - tm_start); | |
1537 x = x_start + (x_end - x_start) * dt; | |
1538 } else { | |
21066 | 1539 mp_msg(MSGT_ASS, MSGL_ERR, MSGTR_LIBASS_UnknownEffectType_InternalError); |
18937 | 1540 continue; |
1541 } | |
1542 | |
1543 for (cur2 = s1; cur2 <= e1; ++cur2) { | |
1544 cur2->effect_type = s1->effect_type; | |
1545 cur2->effect_timing = x - cur2->pos.x; | |
1546 } | |
1547 } | |
1548 } | |
1549 } | |
1550 } | |
1551 | |
1552 /** | |
20294
4d7c8478e523
Move base point calculation to a separate function. Will be reused soon.
eugeni
parents:
20293
diff
changeset
|
1553 * \brief Calculate base point for positioning and rotation |
4d7c8478e523
Move base point calculation to a separate function. Will be reused soon.
eugeni
parents:
20293
diff
changeset
|
1554 * \param bbox text bbox |
4d7c8478e523
Move base point calculation to a separate function. Will be reused soon.
eugeni
parents:
20293
diff
changeset
|
1555 * \param alignment alignment |
4d7c8478e523
Move base point calculation to a separate function. Will be reused soon.
eugeni
parents:
20293
diff
changeset
|
1556 * \param bx, by out: base point coordinates |
4d7c8478e523
Move base point calculation to a separate function. Will be reused soon.
eugeni
parents:
20293
diff
changeset
|
1557 */ |
4d7c8478e523
Move base point calculation to a separate function. Will be reused soon.
eugeni
parents:
20293
diff
changeset
|
1558 static void get_base_point(FT_BBox bbox, int alignment, int* bx, int* by) |
4d7c8478e523
Move base point calculation to a separate function. Will be reused soon.
eugeni
parents:
20293
diff
changeset
|
1559 { |
4d7c8478e523
Move base point calculation to a separate function. Will be reused soon.
eugeni
parents:
20293
diff
changeset
|
1560 const int halign = alignment & 3; |
4d7c8478e523
Move base point calculation to a separate function. Will be reused soon.
eugeni
parents:
20293
diff
changeset
|
1561 const int valign = alignment & 12; |
4d7c8478e523
Move base point calculation to a separate function. Will be reused soon.
eugeni
parents:
20293
diff
changeset
|
1562 if (bx) |
4d7c8478e523
Move base point calculation to a separate function. Will be reused soon.
eugeni
parents:
20293
diff
changeset
|
1563 switch(halign) { |
4d7c8478e523
Move base point calculation to a separate function. Will be reused soon.
eugeni
parents:
20293
diff
changeset
|
1564 case HALIGN_LEFT: |
4d7c8478e523
Move base point calculation to a separate function. Will be reused soon.
eugeni
parents:
20293
diff
changeset
|
1565 *bx = bbox.xMin; |
4d7c8478e523
Move base point calculation to a separate function. Will be reused soon.
eugeni
parents:
20293
diff
changeset
|
1566 break; |
4d7c8478e523
Move base point calculation to a separate function. Will be reused soon.
eugeni
parents:
20293
diff
changeset
|
1567 case HALIGN_CENTER: |
4d7c8478e523
Move base point calculation to a separate function. Will be reused soon.
eugeni
parents:
20293
diff
changeset
|
1568 *bx = (bbox.xMax + bbox.xMin) / 2; |
4d7c8478e523
Move base point calculation to a separate function. Will be reused soon.
eugeni
parents:
20293
diff
changeset
|
1569 break; |
4d7c8478e523
Move base point calculation to a separate function. Will be reused soon.
eugeni
parents:
20293
diff
changeset
|
1570 case HALIGN_RIGHT: |
4d7c8478e523
Move base point calculation to a separate function. Will be reused soon.
eugeni
parents:
20293
diff
changeset
|
1571 *bx = bbox.xMax; |
4d7c8478e523
Move base point calculation to a separate function. Will be reused soon.
eugeni
parents:
20293
diff
changeset
|
1572 break; |
4d7c8478e523
Move base point calculation to a separate function. Will be reused soon.
eugeni
parents:
20293
diff
changeset
|
1573 } |
4d7c8478e523
Move base point calculation to a separate function. Will be reused soon.
eugeni
parents:
20293
diff
changeset
|
1574 if (by) |
4d7c8478e523
Move base point calculation to a separate function. Will be reused soon.
eugeni
parents:
20293
diff
changeset
|
1575 switch(valign) { |
4d7c8478e523
Move base point calculation to a separate function. Will be reused soon.
eugeni
parents:
20293
diff
changeset
|
1576 case VALIGN_TOP: |
4d7c8478e523
Move base point calculation to a separate function. Will be reused soon.
eugeni
parents:
20293
diff
changeset
|
1577 *by = bbox.yMin; |
4d7c8478e523
Move base point calculation to a separate function. Will be reused soon.
eugeni
parents:
20293
diff
changeset
|
1578 break; |
4d7c8478e523
Move base point calculation to a separate function. Will be reused soon.
eugeni
parents:
20293
diff
changeset
|
1579 case VALIGN_CENTER: |
4d7c8478e523
Move base point calculation to a separate function. Will be reused soon.
eugeni
parents:
20293
diff
changeset
|
1580 *by = (bbox.yMax + bbox.yMin) / 2; |
4d7c8478e523
Move base point calculation to a separate function. Will be reused soon.
eugeni
parents:
20293
diff
changeset
|
1581 break; |
4d7c8478e523
Move base point calculation to a separate function. Will be reused soon.
eugeni
parents:
20293
diff
changeset
|
1582 case VALIGN_SUB: |
4d7c8478e523
Move base point calculation to a separate function. Will be reused soon.
eugeni
parents:
20293
diff
changeset
|
1583 *by = bbox.yMax; |
4d7c8478e523
Move base point calculation to a separate function. Will be reused soon.
eugeni
parents:
20293
diff
changeset
|
1584 break; |
4d7c8478e523
Move base point calculation to a separate function. Will be reused soon.
eugeni
parents:
20293
diff
changeset
|
1585 } |
4d7c8478e523
Move base point calculation to a separate function. Will be reused soon.
eugeni
parents:
20293
diff
changeset
|
1586 } |
4d7c8478e523
Move base point calculation to a separate function. Will be reused soon.
eugeni
parents:
20293
diff
changeset
|
1587 |
4d7c8478e523
Move base point calculation to a separate function. Will be reused soon.
eugeni
parents:
20293
diff
changeset
|
1588 /** |
22215
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
1589 * \brief Multiply 4-vector by 4-matrix |
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
1590 * \param a 4-vector |
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
1591 * \param m 4-matrix] |
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
1592 * \param b out: 4-vector |
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
1593 * Calculates a * m and stores result in b |
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
1594 */ |
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
1595 static inline void transform_point_3d(double *a, double *m, double *b) |
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
1596 { |
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
1597 b[0] = a[0] * m[0] + a[1] * m[4] + a[2] * m[8] + a[3] * m[12]; |
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
1598 b[1] = a[0] * m[1] + a[1] * m[5] + a[2] * m[9] + a[3] * m[13]; |
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
1599 b[2] = a[0] * m[2] + a[1] * m[6] + a[2] * m[10] + a[3] * m[14]; |
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
1600 b[3] = a[0] * m[3] + a[1] * m[7] + a[2] * m[11] + a[3] * m[15]; |
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
1601 } |
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
1602 |
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
1603 /** |
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
1604 * \brief Apply 3d transformation to a vector |
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
1605 * \param v FreeType vector (2d) |
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
1606 * \param m 4-matrix |
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
1607 * Transforms v by m, projects the result back to the screen plane |
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
1608 * Result is returned in v. |
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
1609 */ |
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
1610 static inline void transform_vector_3d(FT_Vector* v, double *m) { |
23033 | 1611 const double camera = 2500 * frame_context.border_scale; // camera distance |
22215
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
1612 double a[4], b[4]; |
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
1613 a[0] = d6_to_double(v->x); |
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
1614 a[1] = d6_to_double(v->y); |
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
1615 a[2] = 0.; |
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
1616 a[3] = 1.; |
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
1617 transform_point_3d(a, m, b); |
23014 | 1618 /* Apply perspective projection with the following matrix: |
1619 2500 0 0 0 | |
1620 0 2500 0 0 | |
1621 0 0 0 0 | |
1622 0 0 8 2500 | |
1623 where 2500 is camera distance, 8 - z-axis scale. | |
1624 Camera is always located in (org_x, org_y, -2500). This means | |
1625 that different subtitle events can be displayed at the same time | |
1626 using different cameras. */ | |
23033 | 1627 b[0] *= camera; |
1628 b[1] *= camera; | |
1629 b[3] = 8 * b[2] + camera; | |
22215
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
1630 if (b[3] < 0.001 && b[3] > -0.001) |
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
1631 b[3] = b[3] < 0. ? -0.001 : 0.001; |
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
1632 v->x = double_to_d6(b[0] / b[3]); |
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
1633 v->y = double_to_d6(b[1] / b[3]); |
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
1634 } |
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
1635 |
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
1636 /** |
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
1637 * \brief Apply 3d transformation to a glyph |
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
1638 * \param glyph FreeType glyph |
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
1639 * \param m 4-matrix |
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
1640 * Transforms glyph by m, projects the result back to the screen plane |
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
1641 * Result is returned in glyph. |
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
1642 */ |
23013
7eb66492a37d
Applying transformation matrix to the glyph and the shift vector separately is
eugeni
parents:
23012
diff
changeset
|
1643 static inline void transform_glyph_3d(FT_Glyph glyph, double *m, FT_Vector shift) { |
22215
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
1644 int i; |
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
1645 FT_Outline* outline = &((FT_OutlineGlyph)glyph)->outline; |
23013
7eb66492a37d
Applying transformation matrix to the glyph and the shift vector separately is
eugeni
parents:
23012
diff
changeset
|
1646 FT_Vector* p = outline->points; |
22215
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
1647 |
23013
7eb66492a37d
Applying transformation matrix to the glyph and the shift vector separately is
eugeni
parents:
23012
diff
changeset
|
1648 for (i=0; i<outline->n_points; i++) { |
7eb66492a37d
Applying transformation matrix to the glyph and the shift vector separately is
eugeni
parents:
23012
diff
changeset
|
1649 p[i].x += shift.x; |
7eb66492a37d
Applying transformation matrix to the glyph and the shift vector separately is
eugeni
parents:
23012
diff
changeset
|
1650 p[i].y += shift.y; |
7eb66492a37d
Applying transformation matrix to the glyph and the shift vector separately is
eugeni
parents:
23012
diff
changeset
|
1651 transform_vector_3d(p + i, m); |
7eb66492a37d
Applying transformation matrix to the glyph and the shift vector separately is
eugeni
parents:
23012
diff
changeset
|
1652 p[i].x -= shift.x; |
7eb66492a37d
Applying transformation matrix to the glyph and the shift vector separately is
eugeni
parents:
23012
diff
changeset
|
1653 p[i].y -= shift.y; |
7eb66492a37d
Applying transformation matrix to the glyph and the shift vector separately is
eugeni
parents:
23012
diff
changeset
|
1654 } |
22215
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
1655 |
23013
7eb66492a37d
Applying transformation matrix to the glyph and the shift vector separately is
eugeni
parents:
23012
diff
changeset
|
1656 //transform_vector_3d(&glyph->advance, m); |
22215
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
1657 } |
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
1658 |
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
1659 /** |
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
1660 * \brief Apply 3d transformation to several objects |
23013
7eb66492a37d
Applying transformation matrix to the glyph and the shift vector separately is
eugeni
parents:
23012
diff
changeset
|
1661 * \param shift FreeType vector |
22215
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
1662 * \param glyph FreeType glyph |
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
1663 * \param glyph2 FreeType glyph |
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
1664 * \param frx x-axis rotation angle |
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
1665 * \param fry y-axis rotation angle |
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
1666 * \param frz z-axis rotation angle |
23013
7eb66492a37d
Applying transformation matrix to the glyph and the shift vector separately is
eugeni
parents:
23012
diff
changeset
|
1667 * Rotates both glyphs by frx, fry and frz. Shift vector is added before rotation and subtracted after it. |
22215
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
1668 */ |
23172 | 1669 static void transform_3d(FT_Vector shift, FT_Glyph* glyph, FT_Glyph* glyph2, double frx, double fry, double frz) |
22215
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
1670 { |
23322
bc9ec60e174d
Revert y-axis rotation. Change order of rotations.
eugeni
parents:
23300
diff
changeset
|
1671 fry = - fry; // FreeType's y axis goes in the opposite direction |
22215
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
1672 if (frx != 0. || fry != 0. || frz != 0.) { |
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
1673 double m[16]; |
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
1674 double sx = sin(frx); |
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
1675 double sy = sin(fry); |
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
1676 double sz = sin(frz); |
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
1677 double cx = cos(frx); |
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
1678 double cy = cos(fry); |
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
1679 double cz = cos(frz); |
23322
bc9ec60e174d
Revert y-axis rotation. Change order of rotations.
eugeni
parents:
23300
diff
changeset
|
1680 m[0] = cy * cz; m[1] = cy*sz; m[2] = -sy; m[3] = 0.0; |
bc9ec60e174d
Revert y-axis rotation. Change order of rotations.
eugeni
parents:
23300
diff
changeset
|
1681 m[4] = -cx*sz + sx*sy*cz; m[5] = cx*cz + sx*sy*sz; m[6] = sx*cy; m[7] = 0.0; |
bc9ec60e174d
Revert y-axis rotation. Change order of rotations.
eugeni
parents:
23300
diff
changeset
|
1682 m[8] = sx*sz + cx*sy*cz; m[9] = -sx*cz + cx*sy*sz; m[10] = cx*cy; m[11] = 0.0; |
bc9ec60e174d
Revert y-axis rotation. Change order of rotations.
eugeni
parents:
23300
diff
changeset
|
1683 m[12] = 0.0; m[13] = 0.0; m[14] = 0.0; m[15] = 1.0; |
22215
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
1684 |
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
1685 if (glyph && *glyph) |
23013
7eb66492a37d
Applying transformation matrix to the glyph and the shift vector separately is
eugeni
parents:
23012
diff
changeset
|
1686 transform_glyph_3d(*glyph, m, shift); |
22215
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
1687 |
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
1688 if (glyph2 && *glyph2) |
23013
7eb66492a37d
Applying transformation matrix to the glyph and the shift vector separately is
eugeni
parents:
23012
diff
changeset
|
1689 transform_glyph_3d(*glyph2, m, shift); |
22215
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
1690 } |
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
1691 } |
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
1692 |
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
1693 /** |
18937 | 1694 * \brief Main ass rendering function, glues everything together |
1695 * \param event event to render | |
1696 * Process event, appending resulting ass_image_t's to images_root. | |
1697 */ | |
19638
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
1698 static int ass_render_event(ass_event_t* event, event_images_t* event_images) |
18937 | 1699 { |
1700 char* p; | |
1701 FT_UInt previous; | |
1702 FT_UInt num_glyphs; | |
1703 FT_Vector pen; | |
1704 unsigned code; | |
1705 FT_BBox bbox; | |
1706 int i, j; | |
1707 FT_Vector shift; | |
1708 int MarginL, MarginR, MarginV; | |
1709 int last_break; | |
1710 int alignment, halign, valign; | |
19556 | 1711 int device_x = 0, device_y = 0; |
18937 | 1712 |
19651 | 1713 if (event->Style >= frame_context.track->n_styles) { |
21066 | 1714 mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_NoStyleFound); |
19650 | 1715 return 1; |
1716 } | |
1717 if (!event->Text) { | |
21066 | 1718 mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_EmptyEvent); |
19650 | 1719 return 1; |
1720 } | |
1721 | |
18937 | 1722 init_render_context(event); |
1723 | |
1724 text_info.length = 0; | |
1725 pen.x = 0; | |
1726 pen.y = 0; | |
1727 previous = 0; | |
1728 num_glyphs = 0; | |
1729 p = event->Text; | |
1730 // Event parsing. | |
1731 while (1) { | |
1732 // get next char, executing style override | |
1733 // this affects render_context | |
1734 code = get_next_char(&p); | |
1735 | |
1736 // face could have been changed in get_next_char | |
21267
9ec30b8622ec
Make ass_new_font return ass_font_t struct (instead of just FT_Face).
eugeni
parents:
21265
diff
changeset
|
1737 if (!render_context.font) { |
18937 | 1738 free_render_context(); |
19638
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
1739 return 1; |
18937 | 1740 } |
1741 | |
1742 if (code == 0) | |
1743 break; | |
1744 | |
1745 if (text_info.length >= MAX_GLYPHS) { | |
21066 | 1746 mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_MAX_GLYPHS_Reached, |
18937 | 1747 (int)(event - frame_context.track->events), event->Start, event->Duration, event->Text); |
1748 break; | |
1749 } | |
1750 | |
21614
5d2ca7ca18b5
Move ascender, descender, and kerning computation to ass_font.c.
eugeni
parents:
21506
diff
changeset
|
1751 if ( previous && code ) { |
18937 | 1752 FT_Vector delta; |
21614
5d2ca7ca18b5
Move ascender, descender, and kerning computation to ass_font.c.
eugeni
parents:
21506
diff
changeset
|
1753 delta = ass_font_get_kerning(render_context.font, previous, code); |
20320
33f0529d29e3
Don't forget to apply scaling coefficients to kerning values.
eugeni
parents:
20302
diff
changeset
|
1754 pen.x += delta.x * render_context.scale_x; |
33f0529d29e3
Don't forget to apply scaling coefficients to kerning values.
eugeni
parents:
20302
diff
changeset
|
1755 pen.y += delta.y * render_context.scale_y; |
18937 | 1756 } |
1757 | |
1758 shift.x = pen.x & 63; | |
1759 shift.y = pen.y & 63; | |
1760 | |
23299
0ee56ec36a40
Limit ass_font_set_transform to nonrotating transformations.
eugeni
parents:
23213
diff
changeset
|
1761 ass_font_set_transform(render_context.font, |
0ee56ec36a40
Limit ass_font_set_transform to nonrotating transformations.
eugeni
parents:
23213
diff
changeset
|
1762 render_context.scale_x * frame_context.font_scale_x, |
0ee56ec36a40
Limit ass_font_set_transform to nonrotating transformations.
eugeni
parents:
23213
diff
changeset
|
1763 render_context.scale_y, |
0ee56ec36a40
Limit ass_font_set_transform to nonrotating transformations.
eugeni
parents:
23213
diff
changeset
|
1764 &shift ); |
23021
a81c390d4a22
Move outline glyph generation to a separate function, using outline glyph
eugeni
parents:
23017
diff
changeset
|
1765 |
23022 | 1766 get_outline_glyph(code, text_info.glyphs + text_info.length, &shift); |
18937 | 1767 |
22401 | 1768 text_info.glyphs[text_info.length].pos.x = pen.x >> 6; |
1769 text_info.glyphs[text_info.length].pos.y = pen.y >> 6; | |
18937 | 1770 |
1771 pen.x += text_info.glyphs[text_info.length].advance.x; | |
22259 | 1772 pen.x += double_to_d6(render_context.hspacing); |
18937 | 1773 pen.y += text_info.glyphs[text_info.length].advance.y; |
1774 | |
21614
5d2ca7ca18b5
Move ascender, descender, and kerning computation to ass_font.c.
eugeni
parents:
21506
diff
changeset
|
1775 previous = code; |
5d2ca7ca18b5
Move ascender, descender, and kerning computation to ass_font.c.
eugeni
parents:
21506
diff
changeset
|
1776 |
18937 | 1777 text_info.glyphs[text_info.length].symbol = code; |
1778 text_info.glyphs[text_info.length].linebreak = 0; | |
19692
5b40e87b9619
Change \fad behaviour so that it does not get cancelled by \r.
eugeni
parents:
19691
diff
changeset
|
1779 for (i = 0; i < 4; ++i) { |
5b40e87b9619
Change \fad behaviour so that it does not get cancelled by \r.
eugeni
parents:
19691
diff
changeset
|
1780 uint32_t clr = render_context.c[i]; |
5b40e87b9619
Change \fad behaviour so that it does not get cancelled by \r.
eugeni
parents:
19691
diff
changeset
|
1781 change_alpha(&clr, mult_alpha(_a(clr), render_context.fade), 1.); |
5b40e87b9619
Change \fad behaviour so that it does not get cancelled by \r.
eugeni
parents:
19691
diff
changeset
|
1782 text_info.glyphs[text_info.length].c[i] = clr; |
5b40e87b9619
Change \fad behaviour so that it does not get cancelled by \r.
eugeni
parents:
19691
diff
changeset
|
1783 } |
18937 | 1784 text_info.glyphs[text_info.length].effect_type = render_context.effect_type; |
1785 text_info.glyphs[text_info.length].effect_timing = render_context.effect_timing; | |
19716
e4e492fcc2f7
Bugfix: timing for empty karaoke words was lost, resulting
eugeni
parents:
19693
diff
changeset
|
1786 text_info.glyphs[text_info.length].effect_skip_timing = render_context.effect_skip_timing; |
19848 | 1787 text_info.glyphs[text_info.length].be = render_context.be; |
19965 | 1788 text_info.glyphs[text_info.length].shadow = render_context.shadow; |
22215
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
1789 text_info.glyphs[text_info.length].frx = render_context.frx; |
fb365c2b3d05
Implement \frx and \fry (and reimplement \frz) as 3d rotations.
eugeni
parents:
22214
diff
changeset
|
1790 text_info.glyphs[text_info.length].fry = render_context.fry; |
22214 | 1791 text_info.glyphs[text_info.length].frz = render_context.frz; |
21614
5d2ca7ca18b5
Move ascender, descender, and kerning computation to ass_font.c.
eugeni
parents:
21506
diff
changeset
|
1792 ass_font_get_asc_desc(render_context.font, code, |
5d2ca7ca18b5
Move ascender, descender, and kerning computation to ass_font.c.
eugeni
parents:
21506
diff
changeset
|
1793 &text_info.glyphs[text_info.length].asc, |
5d2ca7ca18b5
Move ascender, descender, and kerning computation to ass_font.c.
eugeni
parents:
21506
diff
changeset
|
1794 &text_info.glyphs[text_info.length].desc); |
22261 | 1795 text_info.glyphs[text_info.length].asc *= render_context.scale_y; |
1796 text_info.glyphs[text_info.length].desc *= render_context.scale_y; | |
21614
5d2ca7ca18b5
Move ascender, descender, and kerning computation to ass_font.c.
eugeni
parents:
21506
diff
changeset
|
1797 |
23027
b4db05aea29e
Fill bitmap_hash_key during parsing stage, call get_bitmap_glyph() much later.
eugeni
parents:
23026
diff
changeset
|
1798 // fill bitmap_hash_key |
b4db05aea29e
Fill bitmap_hash_key during parsing stage, call get_bitmap_glyph() much later.
eugeni
parents:
23026
diff
changeset
|
1799 text_info.glyphs[text_info.length].hash_key.font = render_context.font; |
b4db05aea29e
Fill bitmap_hash_key during parsing stage, call get_bitmap_glyph() much later.
eugeni
parents:
23026
diff
changeset
|
1800 text_info.glyphs[text_info.length].hash_key.size = render_context.font_size; |
b4db05aea29e
Fill bitmap_hash_key during parsing stage, call get_bitmap_glyph() much later.
eugeni
parents:
23026
diff
changeset
|
1801 text_info.glyphs[text_info.length].hash_key.outline = render_context.border * 0xFFFF; |
b4db05aea29e
Fill bitmap_hash_key during parsing stage, call get_bitmap_glyph() much later.
eugeni
parents:
23026
diff
changeset
|
1802 text_info.glyphs[text_info.length].hash_key.scale_x = render_context.scale_x * 0xFFFF; |
b4db05aea29e
Fill bitmap_hash_key during parsing stage, call get_bitmap_glyph() much later.
eugeni
parents:
23026
diff
changeset
|
1803 text_info.glyphs[text_info.length].hash_key.scale_y = render_context.scale_y * 0xFFFF; |
b4db05aea29e
Fill bitmap_hash_key during parsing stage, call get_bitmap_glyph() much later.
eugeni
parents:
23026
diff
changeset
|
1804 text_info.glyphs[text_info.length].hash_key.frx = render_context.frx * 0xFFFF; |
b4db05aea29e
Fill bitmap_hash_key during parsing stage, call get_bitmap_glyph() much later.
eugeni
parents:
23026
diff
changeset
|
1805 text_info.glyphs[text_info.length].hash_key.fry = render_context.fry * 0xFFFF; |
b4db05aea29e
Fill bitmap_hash_key during parsing stage, call get_bitmap_glyph() much later.
eugeni
parents:
23026
diff
changeset
|
1806 text_info.glyphs[text_info.length].hash_key.frz = render_context.frz * 0xFFFF; |
b4db05aea29e
Fill bitmap_hash_key during parsing stage, call get_bitmap_glyph() much later.
eugeni
parents:
23026
diff
changeset
|
1807 text_info.glyphs[text_info.length].hash_key.bold = render_context.bold; |
b4db05aea29e
Fill bitmap_hash_key during parsing stage, call get_bitmap_glyph() much later.
eugeni
parents:
23026
diff
changeset
|
1808 text_info.glyphs[text_info.length].hash_key.italic = render_context.italic; |
b4db05aea29e
Fill bitmap_hash_key during parsing stage, call get_bitmap_glyph() much later.
eugeni
parents:
23026
diff
changeset
|
1809 text_info.glyphs[text_info.length].hash_key.ch = code; |
b4db05aea29e
Fill bitmap_hash_key during parsing stage, call get_bitmap_glyph() much later.
eugeni
parents:
23026
diff
changeset
|
1810 text_info.glyphs[text_info.length].hash_key.advance = shift; |
b4db05aea29e
Fill bitmap_hash_key during parsing stage, call get_bitmap_glyph() much later.
eugeni
parents:
23026
diff
changeset
|
1811 text_info.glyphs[text_info.length].hash_key.be = render_context.be; |
b4db05aea29e
Fill bitmap_hash_key during parsing stage, call get_bitmap_glyph() much later.
eugeni
parents:
23026
diff
changeset
|
1812 |
18937 | 1813 text_info.length++; |
19716
e4e492fcc2f7
Bugfix: timing for empty karaoke words was lost, resulting
eugeni
parents:
19693
diff
changeset
|
1814 |
e4e492fcc2f7
Bugfix: timing for empty karaoke words was lost, resulting
eugeni
parents:
19693
diff
changeset
|
1815 render_context.effect_type = EF_NONE; |
e4e492fcc2f7
Bugfix: timing for empty karaoke words was lost, resulting
eugeni
parents:
19693
diff
changeset
|
1816 render_context.effect_timing = 0; |
e4e492fcc2f7
Bugfix: timing for empty karaoke words was lost, resulting
eugeni
parents:
19693
diff
changeset
|
1817 render_context.effect_skip_timing = 0; |
18937 | 1818 } |
1819 | |
1820 if (text_info.length == 0) { | |
1821 // no valid symbols in the event; this can be smth like {comment} | |
1822 free_render_context(); | |
19638
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
1823 return 1; |
18937 | 1824 } |
1825 | |
1826 // depends on glyph x coordinates being monotonous, so it should be done before line wrap | |
1827 process_karaoke_effects(); | |
1828 | |
1829 // alignments | |
1830 alignment = render_context.alignment; | |
1831 halign = alignment & 3; | |
1832 valign = alignment & 12; | |
1833 | |
19649 | 1834 MarginL = (event->MarginL) ? event->MarginL : render_context.style->MarginL; |
1835 MarginR = (event->MarginR) ? event->MarginR : render_context.style->MarginR; | |
1836 MarginV = (event->MarginV) ? event->MarginV : render_context.style->MarginV; | |
19556 | 1837 |
1838 if (render_context.evt_type != EVENT_HSCROLL) { | |
19931
399bb1fcdc94
Move variable declaration to a more deeply nested block. It is not used outside of it.
eugeni
parents:
19919
diff
changeset
|
1839 int max_text_width; |
399bb1fcdc94
Move variable declaration to a more deeply nested block. It is not used outside of it.
eugeni
parents:
19919
diff
changeset
|
1840 |
19557 | 1841 // calculate max length of a line |
1842 max_text_width = x2scr(frame_context.track->PlayResX - MarginR) - x2scr(MarginL); | |
19556 | 1843 |
19557 | 1844 // rearrange text in several lines |
1845 wrap_lines_smart(max_text_width); | |
19556 | 1846 |
19557 | 1847 // align text |
1848 last_break = -1; | |
1849 for (i = 1; i < text_info.length + 1; ++i) { // (text_info.length + 1) is the end of the last line | |
1850 if ((i == text_info.length) || text_info.glyphs[i].linebreak) { | |
22456
bfab3ee300ab
Text alignment should not use bounding boxes of individual glyphs.
eugeni
parents:
22455
diff
changeset
|
1851 int width, shift = 0; |
19557 | 1852 glyph_info_t* first_glyph = text_info.glyphs + last_break + 1; |
1853 glyph_info_t* last_glyph = text_info.glyphs + i - 1; | |
18937 | 1854 |
20226
42140caaf210
Fix crash because of last_glyph < first_glyph, probably caused by first line
reimar
parents:
20202
diff
changeset
|
1855 while ((last_glyph > first_glyph) && ((last_glyph->symbol == '\n') || (last_glyph->symbol == 0))) |
19557 | 1856 last_glyph --; |
18937 | 1857 |
22456
bfab3ee300ab
Text alignment should not use bounding boxes of individual glyphs.
eugeni
parents:
22455
diff
changeset
|
1858 width = last_glyph->pos.x + d6_to_int(last_glyph->advance.x) - first_glyph->pos.x; |
19557 | 1859 if (halign == HALIGN_LEFT) { // left aligned, no action |
22456
bfab3ee300ab
Text alignment should not use bounding boxes of individual glyphs.
eugeni
parents:
22455
diff
changeset
|
1860 shift = 0; |
19557 | 1861 } else if (halign == HALIGN_RIGHT) { // right aligned |
1862 shift = max_text_width - width; | |
1863 } else if (halign == HALIGN_CENTER) { // centered | |
1864 shift = (max_text_width - width) / 2; | |
1865 } | |
1866 for (j = last_break + 1; j < i; ++j) { | |
1867 text_info.glyphs[j].pos.x += shift; | |
1868 } | |
1869 last_break = i - 1; | |
18937 | 1870 } |
1871 } | |
19932
0b5b9cbbc74e
Move calculation of text parameters (number of lines, height, etc.) from
eugeni
parents:
19931
diff
changeset
|
1872 } else { // render_context.evt_type == EVENT_HSCROLL |
0b5b9cbbc74e
Move calculation of text parameters (number of lines, height, etc.) from
eugeni
parents:
19931
diff
changeset
|
1873 measure_text(); |
18937 | 1874 } |
1875 | |
1876 // determing text bounding box | |
1877 compute_string_bbox(&text_info, &bbox); | |
1878 | |
1879 // determine device coordinates for text | |
19556 | 1880 |
1881 // x coordinate for everything except positioned events | |
1882 if (render_context.evt_type == EVENT_NORMAL || | |
1883 render_context.evt_type == EVENT_VSCROLL) { | |
1884 device_x = x2scr(MarginL); | |
1885 } else if (render_context.evt_type == EVENT_HSCROLL) { | |
1886 if (render_context.scroll_direction == SCROLL_RL) | |
1887 device_x = x2scr(frame_context.track->PlayResX - render_context.scroll_shift); | |
1888 else if (render_context.scroll_direction == SCROLL_LR) | |
1889 device_x = x2scr(render_context.scroll_shift) - (bbox.xMax - bbox.xMin); | |
1890 } | |
18937 | 1891 |
19556 | 1892 // y coordinate for everything except positioned events |
1893 if (render_context.evt_type == EVENT_NORMAL || | |
1894 render_context.evt_type == EVENT_HSCROLL) { | |
18937 | 1895 if (valign == VALIGN_TOP) { // toptitle |
22213
66abe12ad374
Move conversions between 16.16, 26.6 fixed point and int, double to separate
eugeni
parents:
22209
diff
changeset
|
1896 device_y = y2scr_top(MarginV) + d6_to_int(text_info.lines[0].asc); |
18937 | 1897 } else if (valign == VALIGN_CENTER) { // midtitle |
1898 int scr_y = y2scr(frame_context.track->PlayResY / 2); | |
1899 device_y = scr_y - (bbox.yMax - bbox.yMin) / 2; | |
1900 } else { // subtitle | |
1901 int scr_y; | |
1902 if (valign != VALIGN_SUB) | |
20629
e8885ec63928
Introduce MSGT_ASS, use it for all libass messages.
eugeni
parents:
20503
diff
changeset
|
1903 mp_msg(MSGT_ASS, MSGL_V, "Invalid valign, supposing 0 (subtitle)\n"); |
18937 | 1904 scr_y = y2scr_sub(frame_context.track->PlayResY - MarginV); |
1905 device_y = scr_y; | |
22213
66abe12ad374
Move conversions between 16.16, 26.6 fixed point and int, double to separate
eugeni
parents:
22209
diff
changeset
|
1906 device_y -= d6_to_int(text_info.height); |
66abe12ad374
Move conversions between 16.16, 26.6 fixed point and int, double to separate
eugeni
parents:
22209
diff
changeset
|
1907 device_y += d6_to_int(text_info.lines[0].asc); |
18937 | 1908 } |
19556 | 1909 } else if (render_context.evt_type == EVENT_VSCROLL) { |
1910 if (render_context.scroll_direction == SCROLL_TB) | |
1911 device_y = y2scr(render_context.clip_y0 + render_context.scroll_shift) - (bbox.yMax - bbox.yMin); | |
1912 else if (render_context.scroll_direction == SCROLL_BT) | |
1913 device_y = y2scr(render_context.clip_y1 - render_context.scroll_shift); | |
1914 } | |
1915 | |
1916 // positioned events are totally different | |
1917 if (render_context.evt_type == EVENT_POSITIONED) { | |
20294
4d7c8478e523
Move base point calculation to a separate function. Will be reused soon.
eugeni
parents:
20293
diff
changeset
|
1918 int base_x = 0; |
4d7c8478e523
Move base point calculation to a separate function. Will be reused soon.
eugeni
parents:
20293
diff
changeset
|
1919 int base_y = 0; |
20629
e8885ec63928
Introduce MSGT_ASS, use it for all libass messages.
eugeni
parents:
20503
diff
changeset
|
1920 mp_msg(MSGT_ASS, MSGL_DBG2, "positioned event at %d, %d\n", render_context.pos_x, render_context.pos_y); |
20294
4d7c8478e523
Move base point calculation to a separate function. Will be reused soon.
eugeni
parents:
20293
diff
changeset
|
1921 get_base_point(bbox, alignment, &base_x, &base_y); |
4d7c8478e523
Move base point calculation to a separate function. Will be reused soon.
eugeni
parents:
20293
diff
changeset
|
1922 device_x = x2scr(render_context.pos_x) - base_x; |
4d7c8478e523
Move base point calculation to a separate function. Will be reused soon.
eugeni
parents:
20293
diff
changeset
|
1923 device_y = y2scr(render_context.pos_y) - base_y; |
18937 | 1924 } |
1925 | |
1926 // fix clip coordinates (they depend on alignment) | |
1927 render_context.clip_x0 = x2scr(render_context.clip_x0); | |
1928 render_context.clip_x1 = x2scr(render_context.clip_x1); | |
19556 | 1929 if (render_context.evt_type == EVENT_NORMAL || |
1930 render_context.evt_type == EVENT_HSCROLL || | |
1931 render_context.evt_type == EVENT_VSCROLL) { | |
18937 | 1932 if (valign == VALIGN_TOP) { |
1933 render_context.clip_y0 = y2scr_top(render_context.clip_y0); | |
1934 render_context.clip_y1 = y2scr_top(render_context.clip_y1); | |
1935 } else if (valign == VALIGN_CENTER) { | |
1936 render_context.clip_y0 = y2scr(render_context.clip_y0); | |
1937 render_context.clip_y1 = y2scr(render_context.clip_y1); | |
1938 } else if (valign == VALIGN_SUB) { | |
1939 render_context.clip_y0 = y2scr_sub(render_context.clip_y0); | |
1940 render_context.clip_y1 = y2scr_sub(render_context.clip_y1); | |
1941 } | |
1942 } else if (render_context.evt_type == EVENT_POSITIONED) { | |
1943 render_context.clip_y0 = y2scr(render_context.clip_y0); | |
1944 render_context.clip_y1 = y2scr(render_context.clip_y1); | |
1945 } | |
1946 | |
23179 | 1947 // calculate rotation parameters |
20295 | 1948 { |
18937 | 1949 FT_Vector center; |
1950 | |
22207 | 1951 if (render_context.have_origin) { |
22396 | 1952 center.x = x2scr(render_context.org_x); |
22397 | 1953 center.y = y2scr(render_context.org_y); |
18937 | 1954 } else { |
20296 | 1955 int bx, by; |
20302
2f7c26c86574
Fix center of rotation calculation. It was overly complex and
eugeni
parents:
20296
diff
changeset
|
1956 get_base_point(bbox, alignment, &bx, &by); |
2f7c26c86574
Fix center of rotation calculation. It was overly complex and
eugeni
parents:
20296
diff
changeset
|
1957 center.x = device_x + bx; |
2f7c26c86574
Fix center of rotation calculation. It was overly complex and
eugeni
parents:
20296
diff
changeset
|
1958 center.y = device_y + by; |
18937 | 1959 } |
1960 | |
1961 for (i = 0; i < text_info.length; ++i) { | |
1962 glyph_info_t* info = text_info.glyphs + i; | |
1963 | |
23028
57f56d8e182e
Add shift_[xy] (vector that is added to the glyph before transformation) to
eugeni
parents:
23027
diff
changeset
|
1964 if (info->hash_key.frx || info->hash_key.fry || info->hash_key.frz) { |
57f56d8e182e
Add shift_[xy] (vector that is added to the glyph before transformation) to
eugeni
parents:
23027
diff
changeset
|
1965 info->hash_key.shift_x = info->pos.x + device_x - center.x; |
57f56d8e182e
Add shift_[xy] (vector that is added to the glyph before transformation) to
eugeni
parents:
23027
diff
changeset
|
1966 info->hash_key.shift_y = - (info->pos.y + device_y - center.y); |
57f56d8e182e
Add shift_[xy] (vector that is added to the glyph before transformation) to
eugeni
parents:
23027
diff
changeset
|
1967 } else { |
57f56d8e182e
Add shift_[xy] (vector that is added to the glyph before transformation) to
eugeni
parents:
23027
diff
changeset
|
1968 info->hash_key.shift_x = 0; |
57f56d8e182e
Add shift_[xy] (vector that is added to the glyph before transformation) to
eugeni
parents:
23027
diff
changeset
|
1969 info->hash_key.shift_y = 0; |
57f56d8e182e
Add shift_[xy] (vector that is added to the glyph before transformation) to
eugeni
parents:
23027
diff
changeset
|
1970 } |
18937 | 1971 } |
1972 } | |
1973 | |
23179 | 1974 // convert glyphs to bitmaps |
23174 | 1975 for (i = 0; i < text_info.length; ++i) |
1976 get_bitmap_glyph(text_info.glyphs + i); | |
1977 | |
22213
66abe12ad374
Move conversions between 16.16, 26.6 fixed point and int, double to separate
eugeni
parents:
22209
diff
changeset
|
1978 event_images->top = device_y - d6_to_int(text_info.lines[0].asc); |
66abe12ad374
Move conversions between 16.16, 26.6 fixed point and int, double to separate
eugeni
parents:
22209
diff
changeset
|
1979 event_images->height = d6_to_int(text_info.height); |
19638
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
1980 event_images->detect_collisions = render_context.detect_collisions; |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
1981 event_images->shift_direction = (valign == VALIGN_TOP) ? 1 : -1; |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
1982 event_images->event = event; |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
1983 event_images->imgs = render_text(&text_info, device_x, device_y); |
18937 | 1984 |
1985 free_render_context(); | |
1986 | |
1987 return 0; | |
1988 } | |
1989 | |
21506
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
1990 /** |
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
1991 * \brief deallocate image list |
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
1992 * \param img list pointer |
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
1993 */ |
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
1994 void ass_free_images(ass_image_t* img) |
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
1995 { |
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
1996 while (img) { |
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
1997 ass_image_t* next = img->next; |
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
1998 free(img); |
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
1999 img = next; |
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
2000 } |
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
2001 } |
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
2002 |
20477 | 2003 static void ass_reconfigure(ass_renderer_t* priv) |
20446
e8adc3778348
Split ass_configure() into several smaller functions.
eugeni
parents:
20320
diff
changeset
|
2004 { |
e8adc3778348
Split ass_configure() into several smaller functions.
eugeni
parents:
20320
diff
changeset
|
2005 priv->render_id = ++last_render_id; |
23034
82697eb7803d
Reset outline glyph cache when configuration changes.
eugeni
parents:
23033
diff
changeset
|
2006 ass_glyph_cache_reset(); |
23017 | 2007 ass_bitmap_cache_reset(); |
21506
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
2008 ass_free_images(priv->prev_images_root); |
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
2009 priv->prev_images_root = 0; |
20446
e8adc3778348
Split ass_configure() into several smaller functions.
eugeni
parents:
20320
diff
changeset
|
2010 } |
e8adc3778348
Split ass_configure() into several smaller functions.
eugeni
parents:
20320
diff
changeset
|
2011 |
20477 | 2012 void ass_set_frame_size(ass_renderer_t* priv, int w, int h) |
20446
e8adc3778348
Split ass_configure() into several smaller functions.
eugeni
parents:
20320
diff
changeset
|
2013 { |
e8adc3778348
Split ass_configure() into several smaller functions.
eugeni
parents:
20320
diff
changeset
|
2014 if (priv->settings.frame_width != w || priv->settings.frame_height != h) { |
e8adc3778348
Split ass_configure() into several smaller functions.
eugeni
parents:
20320
diff
changeset
|
2015 priv->settings.frame_width = w; |
e8adc3778348
Split ass_configure() into several smaller functions.
eugeni
parents:
20320
diff
changeset
|
2016 priv->settings.frame_height = h; |
e8adc3778348
Split ass_configure() into several smaller functions.
eugeni
parents:
20320
diff
changeset
|
2017 if (priv->settings.aspect == 0.) |
e8adc3778348
Split ass_configure() into several smaller functions.
eugeni
parents:
20320
diff
changeset
|
2018 priv->settings.aspect = ((double)w) / h; |
e8adc3778348
Split ass_configure() into several smaller functions.
eugeni
parents:
20320
diff
changeset
|
2019 ass_reconfigure(priv); |
e8adc3778348
Split ass_configure() into several smaller functions.
eugeni
parents:
20320
diff
changeset
|
2020 } |
e8adc3778348
Split ass_configure() into several smaller functions.
eugeni
parents:
20320
diff
changeset
|
2021 } |
e8adc3778348
Split ass_configure() into several smaller functions.
eugeni
parents:
20320
diff
changeset
|
2022 |
20477 | 2023 void ass_set_margins(ass_renderer_t* priv, int t, int b, int l, int r) |
20446
e8adc3778348
Split ass_configure() into several smaller functions.
eugeni
parents:
20320
diff
changeset
|
2024 { |
e8adc3778348
Split ass_configure() into several smaller functions.
eugeni
parents:
20320
diff
changeset
|
2025 if (priv->settings.left_margin != l || |
e8adc3778348
Split ass_configure() into several smaller functions.
eugeni
parents:
20320
diff
changeset
|
2026 priv->settings.right_margin != r || |
e8adc3778348
Split ass_configure() into several smaller functions.
eugeni
parents:
20320
diff
changeset
|
2027 priv->settings.top_margin != t || |
e8adc3778348
Split ass_configure() into several smaller functions.
eugeni
parents:
20320
diff
changeset
|
2028 priv->settings.bottom_margin != b) { |
e8adc3778348
Split ass_configure() into several smaller functions.
eugeni
parents:
20320
diff
changeset
|
2029 priv->settings.left_margin = l; |
e8adc3778348
Split ass_configure() into several smaller functions.
eugeni
parents:
20320
diff
changeset
|
2030 priv->settings.right_margin = r; |
e8adc3778348
Split ass_configure() into several smaller functions.
eugeni
parents:
20320
diff
changeset
|
2031 priv->settings.top_margin = t; |
e8adc3778348
Split ass_configure() into several smaller functions.
eugeni
parents:
20320
diff
changeset
|
2032 priv->settings.bottom_margin = b; |
e8adc3778348
Split ass_configure() into several smaller functions.
eugeni
parents:
20320
diff
changeset
|
2033 ass_reconfigure(priv); |
e8adc3778348
Split ass_configure() into several smaller functions.
eugeni
parents:
20320
diff
changeset
|
2034 } |
e8adc3778348
Split ass_configure() into several smaller functions.
eugeni
parents:
20320
diff
changeset
|
2035 } |
e8adc3778348
Split ass_configure() into several smaller functions.
eugeni
parents:
20320
diff
changeset
|
2036 |
20477 | 2037 void ass_set_use_margins(ass_renderer_t* priv, int use) |
18937 | 2038 { |
20446
e8adc3778348
Split ass_configure() into several smaller functions.
eugeni
parents:
20320
diff
changeset
|
2039 priv->settings.use_margins = use; |
e8adc3778348
Split ass_configure() into several smaller functions.
eugeni
parents:
20320
diff
changeset
|
2040 } |
e8adc3778348
Split ass_configure() into several smaller functions.
eugeni
parents:
20320
diff
changeset
|
2041 |
20477 | 2042 void ass_set_aspect_ratio(ass_renderer_t* priv, double ar) |
20446
e8adc3778348
Split ass_configure() into several smaller functions.
eugeni
parents:
20320
diff
changeset
|
2043 { |
e8adc3778348
Split ass_configure() into several smaller functions.
eugeni
parents:
20320
diff
changeset
|
2044 if (priv->settings.aspect != ar) { |
e8adc3778348
Split ass_configure() into several smaller functions.
eugeni
parents:
20320
diff
changeset
|
2045 priv->settings.aspect = ar; |
e8adc3778348
Split ass_configure() into several smaller functions.
eugeni
parents:
20320
diff
changeset
|
2046 ass_reconfigure(priv); |
e8adc3778348
Split ass_configure() into several smaller functions.
eugeni
parents:
20320
diff
changeset
|
2047 } |
e8adc3778348
Split ass_configure() into several smaller functions.
eugeni
parents:
20320
diff
changeset
|
2048 } |
19638
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2049 |
20477 | 2050 void ass_set_font_scale(ass_renderer_t* priv, double font_scale) |
20446
e8adc3778348
Split ass_configure() into several smaller functions.
eugeni
parents:
20320
diff
changeset
|
2051 { |
e8adc3778348
Split ass_configure() into several smaller functions.
eugeni
parents:
20320
diff
changeset
|
2052 if (priv->settings.font_size_coeff != font_scale) { |
e8adc3778348
Split ass_configure() into several smaller functions.
eugeni
parents:
20320
diff
changeset
|
2053 priv->settings.font_size_coeff = font_scale; |
e8adc3778348
Split ass_configure() into several smaller functions.
eugeni
parents:
20320
diff
changeset
|
2054 ass_reconfigure(priv); |
19539 | 2055 } |
18937 | 2056 } |
2057 | |
23134
1de2a46a0987
Add -ass-hinting option for setting font hinting method.
eugeni
parents:
23133
diff
changeset
|
2058 void ass_set_hinting(ass_renderer_t* priv, ass_hinting_t ht) |
1de2a46a0987
Add -ass-hinting option for setting font hinting method.
eugeni
parents:
23133
diff
changeset
|
2059 { |
1de2a46a0987
Add -ass-hinting option for setting font hinting method.
eugeni
parents:
23133
diff
changeset
|
2060 if (priv->settings.hinting != ht) { |
1de2a46a0987
Add -ass-hinting option for setting font hinting method.
eugeni
parents:
23133
diff
changeset
|
2061 priv->settings.hinting = ht; |
1de2a46a0987
Add -ass-hinting option for setting font hinting method.
eugeni
parents:
23133
diff
changeset
|
2062 ass_reconfigure(priv); |
1de2a46a0987
Add -ass-hinting option for setting font hinting method.
eugeni
parents:
23133
diff
changeset
|
2063 } |
1de2a46a0987
Add -ass-hinting option for setting font hinting method.
eugeni
parents:
23133
diff
changeset
|
2064 } |
1de2a46a0987
Add -ass-hinting option for setting font hinting method.
eugeni
parents:
23133
diff
changeset
|
2065 |
20477 | 2066 int ass_set_fonts(ass_renderer_t* priv, const char* default_font, const char* default_family) |
20446
e8adc3778348
Split ass_configure() into several smaller functions.
eugeni
parents:
20320
diff
changeset
|
2067 { |
e8adc3778348
Split ass_configure() into several smaller functions.
eugeni
parents:
20320
diff
changeset
|
2068 if (priv->settings.default_font) |
e8adc3778348
Split ass_configure() into several smaller functions.
eugeni
parents:
20320
diff
changeset
|
2069 free(priv->settings.default_font); |
e8adc3778348
Split ass_configure() into several smaller functions.
eugeni
parents:
20320
diff
changeset
|
2070 if (priv->settings.default_family) |
e8adc3778348
Split ass_configure() into several smaller functions.
eugeni
parents:
20320
diff
changeset
|
2071 free(priv->settings.default_family); |
e8adc3778348
Split ass_configure() into several smaller functions.
eugeni
parents:
20320
diff
changeset
|
2072 |
e8adc3778348
Split ass_configure() into several smaller functions.
eugeni
parents:
20320
diff
changeset
|
2073 priv->settings.default_font = default_font ? strdup(default_font) : 0; |
e8adc3778348
Split ass_configure() into several smaller functions.
eugeni
parents:
20320
diff
changeset
|
2074 priv->settings.default_family = default_family ? strdup(default_family) : 0; |
e8adc3778348
Split ass_configure() into several smaller functions.
eugeni
parents:
20320
diff
changeset
|
2075 |
20451 | 2076 if (priv->fontconfig_priv) |
2077 fontconfig_done(priv->fontconfig_priv); | |
21460 | 2078 priv->fontconfig_priv = fontconfig_init(priv->library, priv->ftlibrary, default_family, default_font); |
20446
e8adc3778348
Split ass_configure() into several smaller functions.
eugeni
parents:
20320
diff
changeset
|
2079 |
e8adc3778348
Split ass_configure() into several smaller functions.
eugeni
parents:
20320
diff
changeset
|
2080 return !!priv->fontconfig_priv; |
e8adc3778348
Split ass_configure() into several smaller functions.
eugeni
parents:
20320
diff
changeset
|
2081 } |
e8adc3778348
Split ass_configure() into several smaller functions.
eugeni
parents:
20320
diff
changeset
|
2082 |
18937 | 2083 /** |
2084 * \brief Start a new frame | |
2085 */ | |
20477 | 2086 static int ass_start_frame(ass_renderer_t *priv, ass_track_t* track, long long now) |
18937 | 2087 { |
20477 | 2088 ass_renderer = priv; |
18937 | 2089 global_settings = &priv->settings; |
2090 | |
2091 if (!priv->settings.frame_width && !priv->settings.frame_height) | |
2092 return 1; // library not initialized | |
2093 | |
2094 frame_context.ass_priv = priv; | |
2095 frame_context.width = global_settings->frame_width; | |
2096 frame_context.height = global_settings->frame_height; | |
19538 | 2097 frame_context.orig_width = global_settings->frame_width - global_settings->left_margin - global_settings->right_margin; |
18937 | 2098 frame_context.orig_height = global_settings->frame_height - global_settings->top_margin - global_settings->bottom_margin; |
2099 frame_context.track = track; | |
2100 frame_context.time = now; | |
2101 | |
2102 ass_lazy_track_init(); | |
2103 | |
23328 | 2104 frame_context.font_scale = global_settings->font_size_coeff * |
19825
f351a3fc3e42
Make font outline width proportional to movie resolution.
eugeni
parents:
19716
diff
changeset
|
2105 frame_context.orig_height / frame_context.track->PlayResY; |
19917
6a31849e2b80
In r19831, font size multiplier was mistakenly applied to border width.
eugeni
parents:
19906
diff
changeset
|
2106 frame_context.border_scale = ((double)frame_context.orig_height) / frame_context.track->PlayResY; |
19825
f351a3fc3e42
Make font outline width proportional to movie resolution.
eugeni
parents:
19716
diff
changeset
|
2107 |
20497 | 2108 if (frame_context.orig_width * track->PlayResY == frame_context.orig_height * track->PlayResX) |
18937 | 2109 frame_context.font_scale_x = 1.; |
2110 else | |
19566 | 2111 frame_context.font_scale_x = ((double)(frame_context.orig_width * track->PlayResY)) / (frame_context.orig_height * track->PlayResX); |
18937 | 2112 |
21506
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
2113 priv->prev_images_root = priv->images_root; |
19638
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2114 priv->images_root = 0; |
18937 | 2115 |
2116 return 0; | |
2117 } | |
2118 | |
19638
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2119 static int cmp_event_layer(const void* p1, const void* p2) |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2120 { |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2121 ass_event_t* e1 = ((event_images_t*)p1)->event; |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2122 ass_event_t* e2 = ((event_images_t*)p2)->event; |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2123 if (e1->Layer < e2->Layer) |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2124 return -1; |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2125 if (e1->Layer > e2->Layer) |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2126 return 1; |
19906
f72c694ee566
Sort events by ReadOrder (if both layer and start time are equal).
eugeni
parents:
19904
diff
changeset
|
2127 if (e1->ReadOrder < e2->ReadOrder) |
f72c694ee566
Sort events by ReadOrder (if both layer and start time are equal).
eugeni
parents:
19904
diff
changeset
|
2128 return -1; |
f72c694ee566
Sort events by ReadOrder (if both layer and start time are equal).
eugeni
parents:
19904
diff
changeset
|
2129 if (e1->ReadOrder > e2->ReadOrder) |
f72c694ee566
Sort events by ReadOrder (if both layer and start time are equal).
eugeni
parents:
19904
diff
changeset
|
2130 return 1; |
19638
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2131 return 0; |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2132 } |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2133 |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2134 #define MAX_EVENTS 100 |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2135 |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2136 static render_priv_t* get_render_priv(ass_event_t* event) |
18937 | 2137 { |
19638
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2138 if (!event->render_priv) |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2139 event->render_priv = calloc(1, sizeof(render_priv_t)); |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2140 // FIXME: check render_id |
20477 | 2141 if (ass_renderer->render_id != event->render_priv->render_id) { |
19638
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2142 memset(event->render_priv, 0, sizeof(render_priv_t)); |
20477 | 2143 event->render_priv->render_id = ass_renderer->render_id; |
19638
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2144 } |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2145 return event->render_priv; |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2146 } |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2147 |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2148 typedef struct segment_s { |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2149 int a, b; // top and height |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2150 } segment_t; |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2151 |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2152 static int overlap(segment_t* s1, segment_t* s2) |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2153 { |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2154 if (s1->a >= s2->b || s2->a >= s1->b) |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2155 return 0; |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2156 return 1; |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2157 } |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2158 |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2159 static int cmp_segment(const void* p1, const void* p2) |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2160 { |
20291 | 2161 return ((segment_t*)p1)->a - ((segment_t*)p2)->a; |
19638
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2162 } |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2163 |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2164 static void shift_event(event_images_t* ei, int shift) |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2165 { |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2166 ass_image_t* cur = ei->imgs; |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2167 while (cur) { |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2168 cur->dst_y += shift; |
19664
f6badf921e82
Add vertical clipping for subtitles that were moved because of a collision.
eugeni
parents:
19663
diff
changeset
|
2169 // clip top and bottom |
f6badf921e82
Add vertical clipping for subtitles that were moved because of a collision.
eugeni
parents:
19663
diff
changeset
|
2170 if (cur->dst_y < 0) { |
f6badf921e82
Add vertical clipping for subtitles that were moved because of a collision.
eugeni
parents:
19663
diff
changeset
|
2171 int clip = - cur->dst_y; |
f6badf921e82
Add vertical clipping for subtitles that were moved because of a collision.
eugeni
parents:
19663
diff
changeset
|
2172 cur->h -= clip; |
f6badf921e82
Add vertical clipping for subtitles that were moved because of a collision.
eugeni
parents:
19663
diff
changeset
|
2173 cur->bitmap += clip * cur->stride; |
f6badf921e82
Add vertical clipping for subtitles that were moved because of a collision.
eugeni
parents:
19663
diff
changeset
|
2174 cur->dst_y = 0; |
f6badf921e82
Add vertical clipping for subtitles that were moved because of a collision.
eugeni
parents:
19663
diff
changeset
|
2175 } |
f6badf921e82
Add vertical clipping for subtitles that were moved because of a collision.
eugeni
parents:
19663
diff
changeset
|
2176 if (cur->dst_y + cur->h >= frame_context.height) { |
f6badf921e82
Add vertical clipping for subtitles that were moved because of a collision.
eugeni
parents:
19663
diff
changeset
|
2177 int clip = cur->dst_y + cur->h - frame_context.height; |
f6badf921e82
Add vertical clipping for subtitles that were moved because of a collision.
eugeni
parents:
19663
diff
changeset
|
2178 cur->h -= clip; |
f6badf921e82
Add vertical clipping for subtitles that were moved because of a collision.
eugeni
parents:
19663
diff
changeset
|
2179 } |
f6badf921e82
Add vertical clipping for subtitles that were moved because of a collision.
eugeni
parents:
19663
diff
changeset
|
2180 if (cur->h <= 0) { |
f6badf921e82
Add vertical clipping for subtitles that were moved because of a collision.
eugeni
parents:
19663
diff
changeset
|
2181 cur->h = 0; |
f6badf921e82
Add vertical clipping for subtitles that were moved because of a collision.
eugeni
parents:
19663
diff
changeset
|
2182 cur->dst_y = 0; |
f6badf921e82
Add vertical clipping for subtitles that were moved because of a collision.
eugeni
parents:
19663
diff
changeset
|
2183 } |
19638
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2184 cur = cur->next; |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2185 } |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2186 ei->top += shift; |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2187 } |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2188 |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2189 // dir: 1 - move down |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2190 // -1 - move up |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2191 static int fit_segment(segment_t* s, segment_t* fixed, int* cnt, int dir) |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2192 { |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2193 int i; |
21097
77316737de63
Fix collision detection. The old method tried to avoid gaps between subtitles
eugeni
parents:
21066
diff
changeset
|
2194 int shift = 0; |
19638
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2195 |
21098 | 2196 if (dir == 1) // move down |
19638
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2197 for (i = 0; i < *cnt; ++i) { |
21097
77316737de63
Fix collision detection. The old method tried to avoid gaps between subtitles
eugeni
parents:
21066
diff
changeset
|
2198 if (s->b + shift <= fixed[i].a || s->a + shift >= fixed[i].b) |
77316737de63
Fix collision detection. The old method tried to avoid gaps between subtitles
eugeni
parents:
21066
diff
changeset
|
2199 continue; |
19638
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2200 shift = fixed[i].b - s->a; |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2201 } |
21098 | 2202 else // dir == -1, move up |
19638
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2203 for (i = *cnt-1; i >= 0; --i) { |
21097
77316737de63
Fix collision detection. The old method tried to avoid gaps between subtitles
eugeni
parents:
21066
diff
changeset
|
2204 if (s->b + shift <= fixed[i].a || s->a + shift >= fixed[i].b) |
77316737de63
Fix collision detection. The old method tried to avoid gaps between subtitles
eugeni
parents:
21066
diff
changeset
|
2205 continue; |
19638
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2206 shift = fixed[i].a - s->b; |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2207 } |
21097
77316737de63
Fix collision detection. The old method tried to avoid gaps between subtitles
eugeni
parents:
21066
diff
changeset
|
2208 |
77316737de63
Fix collision detection. The old method tried to avoid gaps between subtitles
eugeni
parents:
21066
diff
changeset
|
2209 fixed[*cnt].a = s->a + shift; |
77316737de63
Fix collision detection. The old method tried to avoid gaps between subtitles
eugeni
parents:
21066
diff
changeset
|
2210 fixed[*cnt].b = s->b + shift; |
77316737de63
Fix collision detection. The old method tried to avoid gaps between subtitles
eugeni
parents:
21066
diff
changeset
|
2211 (*cnt)++; |
77316737de63
Fix collision detection. The old method tried to avoid gaps between subtitles
eugeni
parents:
21066
diff
changeset
|
2212 qsort(fixed, *cnt, sizeof(segment_t), cmp_segment); |
77316737de63
Fix collision detection. The old method tried to avoid gaps between subtitles
eugeni
parents:
21066
diff
changeset
|
2213 |
77316737de63
Fix collision detection. The old method tried to avoid gaps between subtitles
eugeni
parents:
21066
diff
changeset
|
2214 return shift; |
18937 | 2215 } |
19638
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2216 |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2217 static void fix_collisions(event_images_t* imgs, int cnt) |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2218 { |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2219 segment_t used[MAX_EVENTS]; |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2220 int cnt_used = 0; |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2221 int i, j; |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2222 |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2223 // fill used[] with fixed events |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2224 for (i = 0; i < cnt; ++i) { |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2225 render_priv_t* priv; |
20779
1721569b4d7d
s/break/continue/. A crazy mistake, somehow unnoticed for more that 2 months.
eugeni
parents:
20718
diff
changeset
|
2226 if (!imgs[i].detect_collisions) continue; |
19638
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2227 priv = get_render_priv(imgs[i].event); |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2228 if (priv->height > 0) { // it's a fixed event |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2229 segment_t s; |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2230 s.a = priv->top; |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2231 s.b = priv->top + priv->height; |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2232 if (priv->height != imgs[i].height) { // no, it's not |
21066 | 2233 mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_EventHeightHasChanged); |
19638
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2234 priv->top = 0; |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2235 priv->height = 0; |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2236 } |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2237 for (j = 0; j < cnt_used; ++j) |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2238 if (overlap(&s, used + j)) { // no, it's not |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2239 priv->top = 0; |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2240 priv->height = 0; |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2241 } |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2242 if (priv->height > 0) { // still a fixed event |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2243 used[cnt_used].a = priv->top; |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2244 used[cnt_used].b = priv->top + priv->height; |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2245 cnt_used ++; |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2246 shift_event(imgs + i, priv->top - imgs[i].top); |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2247 } |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2248 } |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2249 } |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2250 qsort(used, cnt_used, sizeof(segment_t), cmp_segment); |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2251 |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2252 // try to fit other events in free spaces |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2253 for (i = 0; i < cnt; ++i) { |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2254 render_priv_t* priv; |
20779
1721569b4d7d
s/break/continue/. A crazy mistake, somehow unnoticed for more that 2 months.
eugeni
parents:
20718
diff
changeset
|
2255 if (!imgs[i].detect_collisions) continue; |
19638
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2256 priv = get_render_priv(imgs[i].event); |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2257 if (priv->height == 0) { // not a fixed event |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2258 int shift; |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2259 segment_t s; |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2260 s.a = imgs[i].top; |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2261 s.b = imgs[i].top + imgs[i].height; |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2262 shift = fit_segment(&s, used, &cnt_used, imgs[i].shift_direction); |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2263 if (shift) shift_event(imgs + i, shift); |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2264 // make it fixed |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2265 priv->top = imgs[i].top; |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2266 priv->height = imgs[i].height; |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2267 } |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2268 |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2269 } |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2270 } |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2271 |
18937 | 2272 /** |
21506
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
2273 * \brief compare two images |
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
2274 * \param i1 first image |
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
2275 * \param i2 second image |
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
2276 * \return 0 if identical, 1 if different positions, 2 if different content |
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
2277 */ |
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
2278 int ass_image_compare(ass_image_t *i1, ass_image_t *i2) |
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
2279 { |
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
2280 if (i1->w != i2->w) return 2; |
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
2281 if (i1->h != i2->h) return 2; |
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
2282 if (i1->stride != i2->stride) return 2; |
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
2283 if (i1->color != i2->color) return 2; |
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
2284 if (i1->bitmap != i2->bitmap) |
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
2285 return 2; |
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
2286 if (i1->dst_x != i2->dst_x) return 1; |
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
2287 if (i1->dst_y != i2->dst_y) return 1; |
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
2288 return 0; |
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
2289 } |
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
2290 |
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
2291 /** |
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
2292 * \brief compare current and previous image list |
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
2293 * \param priv library handle |
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
2294 * \return 0 if identical, 1 if different positions, 2 if different content |
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
2295 */ |
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
2296 int ass_detect_change(ass_renderer_t *priv) |
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
2297 { |
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
2298 ass_image_t* img, *img2; |
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
2299 int diff; |
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
2300 |
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
2301 img = priv->prev_images_root; |
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
2302 img2 = priv->images_root; |
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
2303 diff = 0; |
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
2304 while (img && diff < 2) { |
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
2305 ass_image_t* next, *next2; |
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
2306 next = img->next; |
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
2307 if (img2) { |
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
2308 int d = ass_image_compare(img, img2); |
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
2309 if (d > diff) diff = d; |
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
2310 next2 = img2->next; |
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
2311 } else { |
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
2312 // previous list is shorter |
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
2313 diff = 2; |
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
2314 break; |
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
2315 } |
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
2316 img = next; |
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
2317 img2 = next2; |
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
2318 } |
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
2319 |
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
2320 // is the previous list longer? |
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
2321 if (img2) |
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
2322 diff = 2; |
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
2323 |
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
2324 return diff; |
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
2325 } |
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
2326 |
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
2327 /** |
18937 | 2328 * \brief render a frame |
2329 * \param priv library handle | |
2330 * \param track track | |
2331 * \param now current video timestamp (ms) | |
21506
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
2332 * \param detect_change a value describing how the new images differ from the previous ones will be written here: |
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
2333 * 0 if identical, 1 if different positions, 2 if different content. |
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
2334 * Can be NULL, in that case no detection is performed. |
18937 | 2335 */ |
21506
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
2336 ass_image_t* ass_render_frame(ass_renderer_t *priv, ass_track_t* track, long long now, int* detect_change) |
18937 | 2337 { |
19638
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2338 int i, cnt, rc; |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2339 event_images_t* last; |
19891 | 2340 ass_image_t** tail; |
18937 | 2341 |
19638
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2342 // init frame |
18937 | 2343 rc = ass_start_frame(priv, track, now); |
19638
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2344 if (rc != 0) |
18937 | 2345 return 0; |
19638
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2346 |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2347 // render events separately |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2348 cnt = 0; |
18937 | 2349 for (i = 0; i < track->n_events; ++i) { |
2350 ass_event_t* event = track->events + i; | |
2351 if ( (event->Start <= now) && (now < (event->Start + event->Duration)) ) { | |
22258
9c1160622400
Reallocate event_images_t, removing limit on simultanious events count.
eugeni
parents:
22221
diff
changeset
|
2352 if (cnt >= priv->eimg_size) { |
9c1160622400
Reallocate event_images_t, removing limit on simultanious events count.
eugeni
parents:
22221
diff
changeset
|
2353 priv->eimg_size += 100; |
9c1160622400
Reallocate event_images_t, removing limit on simultanious events count.
eugeni
parents:
22221
diff
changeset
|
2354 priv->eimg = realloc(priv->eimg, priv->eimg_size * sizeof(event_images_t)); |
19638
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2355 } |
22258
9c1160622400
Reallocate event_images_t, removing limit on simultanious events count.
eugeni
parents:
22221
diff
changeset
|
2356 rc = ass_render_event(event, priv->eimg + cnt); |
9c1160622400
Reallocate event_images_t, removing limit on simultanious events count.
eugeni
parents:
22221
diff
changeset
|
2357 if (!rc) ++cnt; |
18937 | 2358 } |
2359 } | |
19638
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2360 |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2361 // sort by layer |
22258
9c1160622400
Reallocate event_images_t, removing limit on simultanious events count.
eugeni
parents:
22221
diff
changeset
|
2362 qsort(priv->eimg, cnt, sizeof(event_images_t), cmp_event_layer); |
19638
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2363 |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2364 // call fix_collisions for each group of events with the same layer |
22258
9c1160622400
Reallocate event_images_t, removing limit on simultanious events count.
eugeni
parents:
22221
diff
changeset
|
2365 last = priv->eimg; |
19638
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2366 for (i = 1; i < cnt; ++i) |
22258
9c1160622400
Reallocate event_images_t, removing limit on simultanious events count.
eugeni
parents:
22221
diff
changeset
|
2367 if (last->event->Layer != priv->eimg[i].event->Layer) { |
9c1160622400
Reallocate event_images_t, removing limit on simultanious events count.
eugeni
parents:
22221
diff
changeset
|
2368 fix_collisions(last, priv->eimg + i - last); |
9c1160622400
Reallocate event_images_t, removing limit on simultanious events count.
eugeni
parents:
22221
diff
changeset
|
2369 last = priv->eimg + i; |
19638
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2370 } |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2371 if (cnt > 0) |
22258
9c1160622400
Reallocate event_images_t, removing limit on simultanious events count.
eugeni
parents:
22221
diff
changeset
|
2372 fix_collisions(last, priv->eimg + cnt - last); |
19638
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2373 |
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2374 // concat lists |
20477 | 2375 tail = &ass_renderer->images_root; |
19891 | 2376 for (i = 0; i < cnt; ++i) { |
22258
9c1160622400
Reallocate event_images_t, removing limit on simultanious events count.
eugeni
parents:
22221
diff
changeset
|
2377 ass_image_t* cur = priv->eimg[i].imgs; |
19891 | 2378 while (cur) { |
2379 *tail = cur; | |
2380 tail = &cur->next; | |
2381 cur = cur->next; | |
2382 } | |
19638
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2383 } |
21506
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
2384 |
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
2385 if (detect_change) |
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
2386 *detect_change = ass_detect_change(priv); |
19638
a3473d990fed
Better collision detection algorithm. The idea is to keep a subtitle in place
eugeni
parents:
19636
diff
changeset
|
2387 |
21506
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
2388 // free the previous image list |
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
2389 ass_free_images(priv->prev_images_root); |
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
2390 priv->prev_images_root = 0; |
8174acbf0633
Speed up ASS subtitles display by detecting changes between two consecutive
eugeni
parents:
21460
diff
changeset
|
2391 |
20477 | 2392 return ass_renderer->images_root; |
18937 | 2393 } |
2394 |