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