50
static void change_font_size(ASS_Renderer *render_priv, double sz)
50
double ensure_font_size(ASS_Renderer *priv, double size)
52
double size = sz * render_priv->font_scale;
56
else if (size > render_priv->height * 2)
57
size = render_priv->height * 2;
59
ass_font_set_size(render_priv->state.font, size);
54
else if (size > priv->height * 2)
55
size = priv->height * 2;
60
static void change_font_size(ASS_Renderer *render_priv, double sz)
61
62
render_priv->state.font_size = sz;
194
196
} else if (now >= t4) {
196
} else if (now < t2) { // and > t1
198
} else if (now < t2 && t2 > t1) {
197
199
cf = ((double) (now - t1)) / (t2 - t1);
198
200
a = a1 * (1 - cf) + a2 * cf;
199
} else if (now > t3) {
201
} else if (now >= t3 && t4 > t3) {
200
202
cf = ((double) (now - t3)) / (t4 - t3);
201
203
a = a2 * (1 - cf) + a3 * cf;
202
} else { // t2 <= now <= t3
204
} else { // t2 <= now < t3
217
219
ASS_Drawing *drawing = render_priv->state.clip_drawing;
219
if (drawing && drawing->glyph)
220
FT_Done_Glyph((FT_Glyph) drawing->glyph);
221
221
ass_drawing_free(drawing);
222
render_priv->state.clip_drawing = ass_drawing_new(
223
render_priv->fontconfig_priv,
224
render_priv->state.font,
225
render_priv->ftlibrary);
222
render_priv->state.clip_drawing =
223
ass_drawing_new(render_priv->library, render_priv->ftlibrary);
226
224
drawing = render_priv->state.clip_drawing;
228
226
res = mystrtoi(&p, &scale);
359
361
render_priv->state.hspacing * (1 - pwr) + val * pwr;
361
363
render_priv->state.hspacing = render_priv->state.style->Spacing;
364
} else if (mystrcmp(&p, "fs+")) {
366
if (mystrtod(&p, &val)) {
367
val = render_priv->state.font_size + pwr * val;
369
val = render_priv->state.style->FontSize;
370
if (render_priv->state.font)
371
change_font_size(render_priv, val);
372
} else if (mystrcmp(&p, "fs-")) {
374
if (mystrtod(&p, &val))
375
val = render_priv->state.font_size - pwr * val;
377
val = render_priv->state.style->FontSize;
378
if (render_priv->state.font)
379
change_font_size(render_priv, val);
362
380
} else if (mystrcmp(&p, "fs")) {
364
382
if (mystrtod(&p, &val))
376
394
val = -1.; // reset to default
377
395
change_border(render_priv, val, val);
396
render_priv->state.bm_run_id++;
378
397
} else if (mystrcmp(&p, "move")) {
379
398
double x1, x2, y1, y2;
380
399
long long t1, t2, delta_t, t;
476
495
change_alpha(&render_priv->state.c[3],
477
496
render_priv->state.style->BackColour, pwr);
498
render_priv->state.bm_run_id++;
479
499
// FIXME: simplify
480
500
} else if (mystrcmp(&p, "an")) {
487
507
val = ((val - 1) % 3) + 1; // horizontal alignment
489
509
ass_msg(render_priv->library, MSGL_DBG2, "align %d", val);
490
render_priv->state.alignment = val;
510
if ((render_priv->state.parsed_tags & PARSED_A) == 0) {
511
render_priv->state.alignment = val;
512
render_priv->state.parsed_tags |= PARSED_A;
492
515
render_priv->state.alignment =
493
516
render_priv->state.style->Alignment;
494
517
} else if (mystrcmp(&p, "a")) {
496
if (mystrtoi(&p, &val) && val)
497
// take care of a vsfilter quirk: handle illegal \a8 like \a5
498
render_priv->state.alignment = (val == 8) ? 5 : val;
519
if (mystrtoi(&p, &val) && val) {
520
if ((render_priv->state.parsed_tags & PARSED_A) == 0) {
521
// take care of a vsfilter quirk: handle illegal \a8 like \a5
522
render_priv->state.alignment = (val == 8) ? 5 : val;
523
render_priv->state.parsed_tags |= PARSED_A;
500
526
render_priv->state.alignment =
501
527
render_priv->state.style->Alignment;
502
528
} else if (mystrcmp(&p, "pos")) {
550
576
mystrtoll(&p, &t4);
553
render_priv->state.fade =
554
interpolate_alpha(render_priv->time -
555
render_priv->state.event->Start, t1, t2,
579
if ((render_priv->state.parsed_tags & PARSED_FADE) == 0) {
580
render_priv->state.fade =
581
interpolate_alpha(render_priv->time -
582
render_priv->state.event->Start, t1, t2,
584
render_priv->state.parsed_tags |= PARSED_FADE;
557
586
} else if (mystrcmp(&p, "org")) {
657
686
val = render_priv->state.style->PrimaryColour;
658
687
ass_msg(render_priv->library, MSGL_DBG2, "color: %X", val);
659
688
change_color(&render_priv->state.c[0], val, pwr);
689
render_priv->state.bm_run_id++;
660
690
} else if ((*p >= '1') && (*p <= '4') && (++p)
661
691
&& (mystrcmp(&p, "c") || mystrcmp(&p, "a"))) {
662
692
char n = *(p - 2);
688
718
change_color(render_priv->state.c + cidx, val, pwr);
719
render_priv->state.bm_run_id++;
691
722
change_alpha(render_priv->state.c + cidx, val >> 24, pwr);
723
render_priv->state.bm_run_id++;
694
726
ass_msg(render_priv->library, MSGL_WARN, "Bad command: %c%c",
758
791
render_priv->state.shadow_x = render_priv->state.shadow_y = val;
792
render_priv->state.bm_run_id++;
759
793
} else if (mystrcmp(&p, "s")) {
761
795
if (mystrtoi(&p, &val) && val)
762
796
render_priv->state.flags |= DECO_STRIKETHROUGH;
764
798
render_priv->state.flags &= ~DECO_STRIKETHROUGH;
799
render_priv->state.bm_run_id++;
765
800
} else if (mystrcmp(&p, "u")) {
767
802
if (mystrtoi(&p, &val) && val)
768
803
render_priv->state.flags |= DECO_UNDERLINE;
770
805
render_priv->state.flags &= ~DECO_UNDERLINE;
806
render_priv->state.bm_run_id++;
771
807
} else if (mystrcmp(&p, "pbo")) {
773
809
if (mystrtod(&p, &val))
784
820
if (!mystrtoi(&p, &val))
785
821
val = render_priv->track->WrapStyle;
786
822
render_priv->state.wrap_style = val;
823
} else if (mystrcmp(&p, "fe")) {
825
if (!mystrtoi(&p, &val))
826
val = render_priv->state.style->Encoding;
827
render_priv->state.font_encoding = val;
909
* \brief determine karaoke effects
910
* Karaoke effects cannot be calculated during parse stage (get_next_char()),
911
* so they are done in a separate step.
912
* Parse stage: when karaoke style override is found, its parameters are stored in the next glyph's
913
* (the first glyph of the karaoke word)'s effect_type and effect_timing.
915
* 1. sets effect_type for all glyphs in the word (_karaoke_ word)
916
* 2. sets effect_timing for all glyphs to x coordinate of the border line between the left and right karaoke parts
917
* (left part is filled with PrimaryColour, right one - with SecondaryColour).
919
void process_karaoke_effects(ASS_Renderer *render_priv)
921
GlyphInfo *cur, *cur2;
922
GlyphInfo *s1, *e1; // start and end of the current word
923
GlyphInfo *s2; // start of the next word
925
int timing; // current timing
926
int tm_start, tm_end; // timings at start and end of the current word
932
tm_current = render_priv->time - render_priv->state.event->Start;
935
for (i = 0; i <= render_priv->text_info.length; ++i) {
936
cur = render_priv->text_info.glyphs + i;
937
if ((i == render_priv->text_info.length)
938
|| (cur->effect_type != EF_NONE)) {
943
tm_start = timing + s1->effect_skip_timing;
944
tm_end = tm_start + s1->effect_timing;
948
for (cur2 = s1; cur2 <= e1; ++cur2) {
949
x_start = FFMIN(x_start, d6_to_int(cur2->bbox.xMin + cur2->pos.x));
950
x_end = FFMAX(x_end, d6_to_int(cur2->bbox.xMax + cur2->pos.x));
953
dt = (tm_current - tm_start);
954
if ((s1->effect_type == EF_KARAOKE)
955
|| (s1->effect_type == EF_KARAOKE_KO)) {
960
} else if (s1->effect_type == EF_KARAOKE_KF) {
961
dt /= (tm_end - tm_start);
962
x = x_start + (x_end - x_start) * dt;
964
ass_msg(render_priv->library, MSGL_ERR,
965
"Unknown effect type");
969
for (cur2 = s1; cur2 <= e1; ++cur2) {
970
cur2->effect_type = s1->effect_type;
971
cur2->effect_timing = x - d6_to_int(cur2->pos.x);
868
980
* \brief Get next ucs4 char from string, parsing and executing style overrides
869
981
* \param str string pointer
870
982
* \return ucs4 code of the next char