summaryrefslogtreecommitdiffstats
path: root/libass/ass_parse.c
Commit message (Collapse)AuthorAgeFilesLines
* Fix Scroll effects with rectangle \clip/\iclipOleg Oshmyan2020-10-181-2/+2
|
* Disable collision detection for Banner effect eventsOleg Oshmyan2020-10-181-0/+1
| | | | This matches VSFilter.
* Don't special-case Scroll effect with bigger coordinate = 0Oleg Oshmyan2020-10-181-2/+0
| | | | VSFilter does no such thing.
* Support Banner/Scroll effects with \pos/\moveOleg Oshmyan2020-10-181-6/+6
|
* Default Banner effect to right-to-leftOleg Oshmyan2020-10-181-3/+3
| | | | That's what VSFilter does.
* Support line breaks with Banner effectOleg Oshmyan2020-10-181-0/+1
| | | | | | | | | Make Banner default to \q2, but allow explicit line breaks and \q overrides. Justify the lines according to \a etc., and wrap lines as usual if \q is overridden, but make sure to keep the left/right edge of the whole event flush with the edge of the screen at the event's start time as required by Banner. This is what VSFilter does.
* mult_alpha: round the productOleg Oshmyan2020-10-181-1/+1
| | | | | | For what it's worth, VSFilter does this too, and our mult_alpha now gives the same results as the corresponding code in VSFilter for all possible inputs.
* Fix mult_alpha of large argumentOleg Oshmyan2020-10-181-2/+3
| | | | | | | | | | | | This function is passed alpha values from \fade, which are restricted to nonnegative values but have no upper limit. Given a large value, the subtraction and the multiply-divide could wrap around or even overflow (in case of integer promotion to signed int). Overflow is undesirable due to undefined behavior, and wraparound is also undesirable due to VSFilter compatibility. Rewrite the expression as a simpler equivalent that does not need to deal with negative numbers and works correctly regardless of integer promotion.
* parse_tag: handle timestamps w/o overflow & like VSFilterOleg Oshmyan2020-10-181-32/+31
| | | | | | | | | | | | | | | | | | | | | | | | | | | We generally support 64-bit timestamps. However, for better VSFilter compatibility and to avoid overflow, when handling \t, \move and \fad(e), parse timestamps with 32 bits like VSFilter does and perform wraparound 32-bit subtraction. To match VSFilter results when the parsed arguments are large but the video/event durations are short, clip the current frame time and event duration to 32 bits during this. Note: we generally handle large event and video timestamps differently from VSFilter (which uses 32 bits throughout) regardless of this commit, so in a sense, this commit actually breaks our saner rendering of long- duration events while it remains VSFilter-incompatible. (It does not break large event/video timestamps per se as long as each individual event's duration fits in 31 bits.) The gain is VSFilter-compatible rendering when all video/event timestamps fit in 31 bits but override tags have values that don't (or whose differences don't) fit. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=542. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=602. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=624. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2721. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=3880. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=11632. Closes https://github.com/libass/libass/pull/337.
* Fix integer overflow while parsing \fad(arg, large negative number)Oleg Oshmyan2020-10-181-1/+6
| | | | | | | | | | | If t3 is initially negative, it should be set to a value larger than the duration of the event. This triggers the `now < t3` branch in interpolate_alpha (if none of the earlier branches are taken). The same effect can be achieved by setting t3 to the duration itself. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=531. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=3905. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=11736.
* Factor out & improve UB-less double -> int32_t conversionOleg Oshmyan2020-10-181-7/+12
| | | | | | | | | The value may be bigger than INT32_MAX as long as its *integral part* isn't. Furthermore, make sure to avoid UB on odd platforms where int32_t limits aren't exactly representable in double, as this isn't too hard. Do assume that they're representable at all though. We won't necessarily match x86 values on such platforms, but we will avoid the undefined behavior.
* ass_parse: avoid UB and match vsfilter on negative-accel color animationrcombs2020-09-191-4/+25
| | | | | | | | | | | | | | | | | | | | Providing a negative acceleration to \t could result in undefined behavior due to overflow in float->int conversion. This codifies the same behavior we currently have on x86, which matches vsfilter's, without actually invoking UB. Additionally, vsfilter color animations work subtly differently than ours did. We used to lerp each individual color component's byte value, while vsfilter performs the lerp on the component _in place within a larger int_. This didn't result in major issues for most cases, but could probably result in subtle rounding errors, and gave vastly different results for \t with negative acceleration. Negative \t acceleration is probably completely useless, but our behavior was wacky in a different way from vsfilter's, and I'd rather have portable wackiness than libass-specific wackiness. It might still be possible to invoke UB in negative-acceleration \t using tags other than colors; we should fix those cases as well.
* Skip fully parsing \t if there is no backslashOleg Oshmyan2020-09-191-2/+10
| | | | | | | | | | | | | | | | | | | | | | | | | | The assertion in commit 66cef6774386d558e1e39096db926d677dad6882 fires on the following ASS code: \t(\t(foobar,) (where "foobar" is any nonblank sequence that does not contain a backslash) The outer \t is parsed as having a single argument "\t(foobar," including the comma. The inner \t is parsed as having a single argument "foobar" *excluding* the comma. As a result, in the inner parse_tags, args[cnt].end == end - 1 && nested, and the assert fires. This is because arguments that contain backslashes are parsed differently from arguments that do not. But if the argument to \t contains no backslashes, why bother parsing it at all? It clearly has no override tags and affects nothing. Rather than try to make the assert more clever (and more convoluted), this commit skips parsing the last \t argument if it has no backslash. The assert is now valid. This probably does not significantly affect parsing speed in either direction. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=25796.
* Assert finite parse_tags recursionOleg Oshmyan2020-09-081-0/+1
| | | | | | | | | | | | | | | | | | Before commit 6835731c2fe4164a0c50bc91d12c43b2a2b4e799, parse_tags used to recurse for each nested \t(). The depth of this recursion was not limited, and each \t in \t(\t(\t(... added another level. This could lead to stack overflow. Since that commit, parse_tags still recurses, but at most once: it is called with nested=false at the top level and recurses with nested=true for the outermost \t() (except rare cases in which even this one level of recursion is avoided). Parsing stops at the closing ) both for the outermost \t() and for any inner \t() nested inside it, so the inner recursive call cannot recurse further. This was not immediately obvious when reading the code, and therefore it was not obvious that stack overflow is avoided. Make it so by adding an assertion.
* ass_parse: improve performance of tag name comparisonsrcombs2020-08-301-5/+7
| | | | | | | | | | Yes, this actually makes a major difference on some tag-heavy scripts. This lets the whole function get inlined, rather than making a call out to the libc's strcmp implementation. The libc's version is likely much faster on longer strings, but we're only ever comparing against strings that are a few characters long, so that doesn't really matter. It also avoids making an extra pass for the strlen.
* parse: fix setting font size when no font is loaded; fixes #365rcombs2020-01-061-10/+1
|
* parse_tags: fix case where t==t1==t2Rodger Combs2019-11-071-1/+1
| | | | | This previously gave the pre-transition value; VSFilter's behavior is to give the post-transition value.
* cache: construct cache values only from corresponding keysDr.Smile2019-05-191-4/+1
| | | | | | | | | | | | | | | | | | | | This commit forces construction of cache values using only data available in its companion keys. That ensures logical correctness: keys are guaranteed to have all the necessary data, and prevents accidental collisions. Most fixes of cache logic correspond to minor problem when rendering is done with double parameter but cache key stores its approximate fixed-point representation. The only serious problem is missing scale of clip drawing. Also this commit removes unused scale parameters from glyph metrics cache key. Due to missing scale clip shapes that differed only in scale treated by cache system as identical. That can lead to incorrect reuse of cached bitmap of different scale instead of correct one. The only hack left is in glyph metrics cache with its unicode >= VERTICAL_LOWER_BOUND check.
* drawing: separate drawing text reading from outline constructionDr.Smile2019-05-191-20/+11
| | | | Purpose of this commit is to simplify logic behind drawing handling.
* parse_tags: handle argumentless \t inside \t() like VSFilterOleg Oshmyan2018-01-081-5/+10
| | | | | | | | | | | | | | | | | | | | | | | | | | \t with no parantheses inside \t() resets the animation parameters of the \t() for subsequent tags, so they are animated as if the \t() was the single-argument version regardless of the actual number of arguments the \t() has. Equivalently, you could say parentheses are implied for \t inside \t(). For example, \t(20,60,\frx0\t\fry0\frz0) animates \frx from 20 to 60 ms and animates \fry and \frz for the whole duration of the line, just like \t(20,60,\frx0)\t(\fry0\frz0) or \t(20,60,\frx0\t(\fry0\frz0)). Technically, VSFilter simply resets the animation parameters for any \t it encounters but parses the embedded tags only if the \t has the right number of arguments. However, top-level animation parameters don't matter because top-level tags are not animated, while any nested \t that has parentheses terminates the containing \t because they share the closing parenthesis, so the fact that a nested \t with empty parentheses or with at least four arguments changes the animation parameters also doesn't matter because the containing \t immediately ends and the changed parameters have nothing to apply to. Thus the only situation where this has a visible effect is a nested \t without parentheses. Closes https://github.com/libass/libass/pull/296.
* parse_tags: don't recurse for nested \t()Oleg Oshmyan2018-01-081-1/+11
| | | | | | | | | | | | | This fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=4892 (stack overflow on deeply nested \t()). This is possible because parentheses do not nest and the first ')' terminates the whole tag. Thus something like \t(\t(\t(\t(\t() can be read in a simple loop with no recursion required. Recursion is also not required if the ')' is missing entirely and the outermost \t(... never ends. See https://github.com/libass/libass/pull/296 for more backstory.
* Move parse_tag loop into parse_tag itself, now called parse_tagsOleg Oshmyan2018-01-051-586/+586
| | | | This commit is mostly transparent to `git blame -w`.
* Replace FreeType types with libass native typesDr.Smile2017-09-171-4/+3
| | | | | | FT_Vector and FT_BBox types are based on FT_Pos, which is alias of long. FreeType treats it as 32-bit integer, but on some platforms long can be 64-bit. That leads to wasted memory and suboptimal performance.
* stroker: implement fast two-outline strokerDr.Smile2017-07-311-35/+0
|
* Reuse numpad2align in parse_tagOleg Oshmyan2017-02-141-8/+3
|
* parse_tag: don't consume *end == ')' when called recursivelyOleg Oshmyan2016-12-291-1/+1
| | | | | This did not cause any problems, but it's nicer to guarantee that the return value is <= end.
* Fix buffer overread in parse_tag when end points to a spaceOleg Oshmyan2016-12-291-3/+6
| | | | | | | | | | | | | | | | | | | | | | | | | | | When parse_tag is invoked recursively to handle the animated tags inside a \t tag, the `end` argument is taken from the `end` field of a struct arg in the enclosing parse_tag. When struct arg is filled by push_arg, this field is always right-trimmed using rskip_spaces. Ultimately, the inner parse_tag invokation sees its `end` argument point not to the ')' or '}' of the \t as it expects but rather to the spaces preceding the ')' or '}'. At this point, when parse_tag calls skip_spaces, which is ignorant of the end pointer, it happily skips over the spaces preceding the ')', moving the pointer past `end`. Subsequent `pointer != end` comparisons in parse_tag fail (as in fact `pointer > end`), and parse_tag thinks it is still inside the substring to be parsed. This is harmless in many cases, but given either of the following inputs, parse_tag reads past the end of the actual buffer that stores the string: {\t(\ } {\t(\ )(} After this commit, parse_tag knows that `end` can point to a sequence of spaces and avoids calling skip_spaces on `end`, thus avoiding the overread. Discovered by OSS-Fuzz. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=194.
* cache: keep ref_count of all active objects nonzeroDr.Smile2016-06-301-1/+1
|
* Fully fix compilation with MSVC/ICLOleg Oshmyan2015-09-171-0/+1
| | | | | | | | | As before, this does not add any build system support: a config.h file and a project must still be manually created (or the compiler can be run manually instead of using a project). Signed-off-by: Grigori Goronzy <greg@kinoho.net> Signed-off-by: Oleg Oshmyan <chortos@inbox.lv>
* ass_parse: add check against ass_drawing_new() failurewm42015-09-071-8/+9
| | | | | Also move the argument parsing part to the top of the function. IT's easier to read this way.
* fontselect: fix oblique/italic mixupGrigori Goronzy2015-07-101-1/+1
| | | | The constants were swapped. In some cases this lead to incorrect matching.
* Use TrueType font weight scaleGrigori Goronzy2015-07-101-3/+3
| | | | | | | | | | fontconfig uses an unusual scale from 0-215 for the font weight. It looks like it is somewhat derived from the typographic scale some font families use, but is still rather nonstandard. Nowadays the TrueType scale from 100-900 seems to be standard. CSS uses it, for example. However, most importantly, VSFilter also uses the TrueType scale. So let's use it in libass, too.
* Custom font matching and font sourcesGrigori Goronzy2015-07-101-2/+1
| | | | | | | Implement a simple font sorter (FontSelector) and an interface to deal with multiple font sources (FontProvider). Unfinished business, but works for the most part. Currently the only implemented FontProvider uses fontconfig.
* Simplify change_alpha and change_colorOleg Oshmyan2015-05-251-6/+4
|
* Apply fade only when the fade alpha is positive (like VSFilter)Oleg Oshmyan2015-05-251-3/+3
|
* parse_tag: split \[1-4][ac]Oleg Oshmyan2015-05-251-47/+49
|
* Parse and animate all colors and alpha values like VSFilterOleg Oshmyan2015-05-251-26/+24
| | | | | | | | | | | | | | | | | | | | | | | | | | | | * Allow exactly one of these prefixes in header values: 0x, 0X, &h, &H. Note that "0x0xFFFFFF" is a correct value, as the first 0x is consumed by the parser and the second by the string-to-number conversion following strtol semantics. * Allow arbitrary numbers of leading & and H (and not h) in any order in override tag values. * Reduce header values modulo 2**32 instead of saturating them to LLONG_MIN/MAX. * Saturate override tag values to INT32_MIN/MAX rather than to LLONG_MIN/MAX. * Don't fiddle with bytes in alpha override tag values. (They can be outside of the 0..255 range.) Also change the byte swapping code to be more sensible. Fixes #80. Fixes #145. Fixes #178. Also fixes our behavior in the case described in https://code.google.com/p/xy-vsfilter/issues/detail?id=80.
* Refine list of tags that prevent selective style overrideswm42015-03-061-4/+7
| | | | | | | Somewhat stolen from: https://github.com/Cyberbeing/xy-VSFilter/blob/xy_sub_filter_rc3/src/subtitles/RTS.cpp#L2004 (xy-VSFilter started work on this in commit 014da6d9766417d7886eb867c9f2c14038f2a226)
* More malloc checkingwm42014-11-171-3/+1
| | | | | | | | | | Use strndup() instead of malloc+copy. Make all code deal with the possibility that ASS_Drawing.text can be NULL (which can happen on allocation failure). Skip fix_collisions() on malloc failure - the lines will overlap, but at least libass won't crash.
* Fix \fade(7-argument version) parseMaks Naumov2014-08-231-2/+2
|
* ass_parse: remove 2 unused variableswm42014-06-091-2/+0
| | | | Fallout from the previous commits.
* Simplify drawing text assignmentOleg Oshmyan2014-06-061-1/+1
|
* parse_tag: remove unnecessary mallocOleg Oshmyan2014-06-061-8/+2
|
* Require closing '}' for override tagsOleg Oshmyan2014-06-061-12/+9
| | | | | | | | Like VSFilter. '{' without a following '}' is just text, though in vector drawing mode it still delimits individual drawings. This also lets us nicely avoid '\0' hacks in the \t override tag handler in parse_tag.
* Introduce ass_drawing_add_chars for adding a whole string at onceOleg Oshmyan2014-06-061-4/+3
|
* Parse override tag arguments exactly like VSFilter 2.38Oleg Oshmyan2014-06-061-236/+308
| | | | | Also replace strtocolor in ass_utils with string2color from ass.c, because that is more useful everywhere now.
* parse_tag: merge \fs+, \fs-, \fsOleg Oshmyan2014-06-061-18/+7
|
* parse_tag: split \fscx, \fscy, \fscOleg Oshmyan2014-06-061-23/+20
|
* Add a mechanism for selective style overrideswm42014-06-051-0/+26
| | | | | | | | | | | | | | | This adds 2 new API functions: ass_set_selective_style_override() ass_set_selective_style_override_enabled() They can be used to force dialog text to use a specific ASS_Style. It uses a fuzzy heuristic for that, and the quality of results may vary. It does style overriding selectively and tries not to override things that need explicit styling. The heuristic for that isn't set in stone either, and can change with future libass versions. Closes libass#88.
* Fix \1a, \2a, \3a, \4a with invalid argumentOleg Oshmyan2014-05-121-0/+2
| | | | Reset to the initial color's alpha component, not red.
* Reset clipping mode on every rectangle \clipOleg Oshmyan2014-05-121-0/+1
| | | | | | | | Prior to this fix, both of the following: \iclip(0,0,9999,9999)\clip(0,0,9999,9999) \iclip(0,0,0,0)\clip(0,0,9999,9999) hid the whole picture in libass. The correct behavior in both cases is to display the whole picture.
* Make \be animatableOleg Oshmyan2014-05-121-2/+5
| | | | | | | VSFilter has supported this since version 2.39. Use the raw floating-point value of the \be argument in the animation formula, like xy-VSFilter has done since version 3.0.0.45 (404301a3).
* Fix corner case: \move with identical start and end timesOleg Oshmyan2014-05-121-2/+2
|
* Parser: don't increment render_priv->state.bm_run_id (unnecessary)11rcombs2014-01-251-14/+0
|
* Combine bitmaps before applying blur and shadow11rcombs2014-01-251-0/+1
|
* Start \k, \ko at exact start time, not right after itOleg Oshmyan2014-01-241-1/+1
|
* Remove some ass_msg() callswm42014-01-241-12/+0
| | | | | | | These aren't very useful for debugging due to the high volume of the log output in problem cases. In fact, all they do is making the code slower (the message callback can easily appear in the profiler output, even if the callback doesn't actually print the messages).
* Fix \fade corner casesOleg Oshmyan2014-01-151-9/+14
| | | | | | | | Times in \fade(,,,-1,fadein,fadeout,-1) are interpreted as in \fad(fadein,fadeout). Make sure we check the times in the same order as VSFilter in case they are not sorted.
* Fix \t corner casesOleg Oshmyan2014-01-151-20/+17
| | | | | The end time is reset to line duration if and only if it is zero. Negative accelerations are allowed (and can cause overflow later).
* Do not reset \pbo and \p values after each drawingOleg Oshmyan2014-01-081-4/+3
| | | | Confirmed with VSFilter. This complements the previous commit.
* A whole bunch of parsing and default value fixesOleg Oshmyan2014-01-071-116/+111
| | | | Obtained by reading the xy-VSFilter source code.
* Fix \fs+ and \fs-Oleg Oshmyan2014-01-071-2/+2
| | | | The argument is a relative amount. The unit is: \fs+1 = +10%.
* Stop animating \b and \iOleg Oshmyan2014-01-071-12/+8
| | | | Unlike what the cc635086 message says, VSFilter does not animate them.