summaryrefslogtreecommitdiffstats
path: root/libass
Commit message (Collapse)AuthorAgeFilesLines
* Handle track alloc failure in parse_memory safelyOneric2020-10-271-0/+2
|
* doc: clarify docs regarding track creation and freeingOneric2020-10-272-4/+7
|
* coretext: return full/PostScript name on fallbackOleg Oshmyan2020-10-231-9/+16
| | | | | | | | | CoreText's "family name" can use TT_NAME_ID_TYPOGRAPHIC_FAMILY names, which we ignore for compatibility with VSFilter. As a result, fallback returns a family name that we then fail to find, and fallback fails. Return a fuller name (fullname or postscriptname as appropriate) instead, which should be more reliable.
* ass_render: Replace Segment with RectOneric2020-10-222-39/+34
| | | | | | | | | Contrary to what the comments suggest Segment does not use one absolute reference point and relative offsets, but two absolute points, making it practically identical to the previously defined Rect with a <-> y0, b <-> y1, ha <-> x0, hb <-> x1 For simplicity replace Segment with Rect.
* ass_shaper: remove dependency on hb-ftrcombs2020-10-221-3/+40
|
* ass_shaper: handle harfbuzz allocation failuresrcombs2020-10-221-14/+22
| | | | | | | | | Edit by Oleg Oshmyan <chortos@inbox.lv>: Move the final ass_shaper_shape returns inside the switch. Add a default case in ass_shaper_shape to proactively placate static analysers that might decide the switch is not exhaustive and we therefore don't return a value. We know it is actually exhaustive as we validate the shaper selection in ass_set_shaper.
* Return bool from ass_shaper_shapeOleg Oshmyan2020-10-223-6/+6
|
* Make harfbuzz a hard dependency; closes #199rcombs2020-10-224-49/+0
|
* ass_shaper_find_runs: don't decrement pointer beyond array startOleg Oshmyan2020-10-191-3/+5
| | | | That triggers undefined behavior.
* shape_harfbuzz: don't attempt to shape drawingsOleg Oshmyan2020-10-191-0/+5
|
* shaper: ensure drawings are in separate shape runs from textOleg Oshmyan2020-10-191-6/+5
| | | | | | | Previously, drawings would get shape_run_id = 0 from calloc. Most of the time, this separated them from text shape runs, but drawings immediately following the very first shape run would get appended to it. Make sure this cannot happen.
* shaper: don't mingle run ID and bidi embedding levelOleg Oshmyan2020-10-191-9/+6
| | | | | | | | | | | | | | | | | | | A libass-chosen shaping run boundary can coincide with a bidi embedding level boundary such that the differences in shaper_run_id and emblevel cancel out. For example: English עבריתEnglish again (with parentheses) (with no space after the Hebrew) has ass_shaper_find_runs split runs after the Hebrew, adding 1 to shape_run_id, while the RTL embed also ends in the same place, removing 1 from emblevel. As a result, two shape runs that should be separate merge together. In this example, this leads to HarfBuzz thinking that "English again (with parentheses)" is still right-to-left, so it flips the parenthesis glyphs. To avoid this, don't attempt to add these numbers together. Just require explicitly that both numbers stay constant, rather than their sum.
* shaper: use FRIBIDI_LEVEL_IS_RTL macroOleg Oshmyan2020-10-191-1/+1
|
* shaper: honor/reuse starts_new_runOleg Oshmyan2020-10-191-27/+1
| | | | | | | | | This removes duplicated code (and a not-fully-correct comment). This also ensures shaping has breaks whenever the rest of the pipeline breaks runs (e. g. for bitmap combining). In particular, this adds missing breaks on karaoke changes, which the old code didn't actually honor despite the comment.
* shaper: handle U+FFFC characters that occur in textOleg Oshmyan2020-10-191-1/+1
| | | | | | | | | U+FFFC can not only come from drawings but also be actually contained in the source text. In that case, handle it like any other character. This doesn't distinguish source-text U+FFFC from drawings whose strdup failed. But the whole rest of the pipeline treats those drawings as plain U+FFFC characters, too.
* Split glyph runs earlyOleg Oshmyan2020-10-193-42/+47
| | | | | | | | | | | | | | | | | | The "bitmap runs" that are currently used only when combining bitmaps are also relevant at other stages, mainly for VSFilter compatibility. They are not currently used because this information is not available until bitmap combining (except during shaping, which has its own "shape runs" that duplicate a good chunk of the "bitmap run" logic). Move some code around to compute run boundaries as early as possible. This lays the foundation for future commits that will make use this information in more places where it can simplify code or improve VSFilter compatibility. For VSFilter compatibility, rather than break runs immediately upon line breaks, break runs after line-leading whitespace, even in the first line. These runs correspond to VSFilter's CWord instances.
* Ignore font substitution when splitting combined bitmapsOleg Oshmyan2020-10-181-2/+0
| | | | | | | | | | | Well, that was easy. font->desc.family is the raw family name from FontName/\fn, barring the leading @ for vertical fonts. So, for reference, even if the script requests two different font names and neither exists on the system and font fallback picks the same font for both, is_new_bm_run will treat them as distinct. This is indeed the desired behaviour that matches VSFilter.
* Fix Scroll effects with rectangle \clip/\iclipOleg Oshmyan2020-10-183-4/+13
|
* Disable collision detection for Banner effect eventsOleg Oshmyan2020-10-181-0/+1
| | | | This matches VSFilter.
* Fix Scroll effect coordinatesOleg Oshmyan2020-10-181-2/+3
| | | | | | | | The coordinate computed for the text's top edge was actually used for the baseline of the text's top line, causing the first line's ascender to protrude up and the whole text to be shifted up by that ascender. (Note: in this context, bbox.y_min == text_info->lines[0].asc.)
* 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-183-44/+43
|
* 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-182-12/+6
| | | | | | | | | 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.
* ass_render_event: simplify clip conversion to screen coordinatesOleg Oshmyan2020-10-181-53/+15
| | | | | | | | The "depends on alignment" block is useless: if use_margins, then the coordinates will be overridden, but if not, then all of the various x/y2scr... calls delegate to x/y2scr_pos... Rewrite several lines using FFMIN/FFMAX to keep them short.
* Prevent int overflow where unsigned wraparound is desiredOleg Oshmyan2020-10-182-5/+5
| | | | | | | | On exotic (or future) platforms, types such as size_t and uint32_t may be promoted to int, which allows multiplication, addition and left-shift operations on these types to overflow (and produce undefined behavior). To avoid this, make sure that the affected arithmetic operators convert any promoted operands to unsigned int by the usual arithmetic conversions.
* 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.
* ass_lazy_track_init: avoid integer overflow in multiply-divideOleg Oshmyan2020-10-181-2/+2
| | | | | | | | | | | | This is incompatible with VSFilter, so maybe we should later change this to use uint32_t instead. This fixes the multiply-divide if the result fits in int, but `PlayResX = PlayResY * 4LL / 3;` still overflows if PlayResY is close to INT_MAX. This should be addressed in a separate commit. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=533. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=603.
* 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.
* Scale everything from script resolution if storage size is unknownOleg Oshmyan2020-10-151-3/+1
| | | | | | | | | | | | | | | | | | | With this, our output can no longer change visually if display resolution is varied via ass_set_frame_size while everything else is kept constant, e. g. when a video player window is being resized, regardless of API (mis)use and script/track properties. In particular, this stops our \blur from affecting a varying portion of the screen and our 3D transforms involving \frx or \fry from moving around as display resolution is being changed. FWIW, this makes our blur and 3D transforms match MPC-HC's when storage size is unset. They already matched before this commit when ScaledBorderAndShadow was true, but now they also match when it is false. This also makes our borders and shadows scale with display resolution, effectively making ScaledBorderAndShadow a no-op (always true) if storage size is unset. FWIW, this does *not* agree with MPC-HC, but it just seems sensible™.
* outline: fix styleOneric2020-10-131-1/+1
|
* font: use library as a failure flagDr.Smile2020-10-111-2/+2
| | | | | | ass_font_clear() can now free family string even in a failure case. Fixes https://github.com/libass/libass/issues/414.
* outline: use labs() for FT_PosDr.Smile2020-10-101-1/+1
| | | | | | While FreeType uses FT_Pos for 32-bit values, the real underlying type is signed long, so labs() is more appropriate here.
* blur: fix styleDr.Smile2020-10-091-26/+26
|
* Simplify blur algorithmDr.Smile2020-10-095-1166/+470
| | | | | This commit removes prefilters altogether at the cost of enlarged main filter kernel.
* outline: fix overflows in outline processingDr.Smile2020-10-084-18/+65
| | | | | | | This commit enforces strict invariant on ASS_Outline to contain point coordinates into predetermined range. Fixes https://github.com/libass/libass/issues/431.
* Add more invisible characters to ass_shaper_skip_charactersOleg Oshmyan2020-09-191-1/+5
| | | | | | | | * Bidirectional isolates * Arabic letter mark * Invisible plus * Variation selectors * Mongolian control characters
* Ignore metrics of trimmable whitespace on nonblank linesOleg Oshmyan2020-09-192-8/+30
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Fixes https://github.com/libass/libass/issues/418. Fixes https://github.com/libass/libass/issues/427. Fixes https://github.com/mpv-player/mpv/issues/7712. A longstanding problem we had was that we ignored leading line breaks in events. We somewhat accidentally assigned line breaks zero height, and the code in `measure_text` that halved the height of empty lines explicitly ignored leading empty lines for some reason. #285 fixed both of these things: the former in e8d98dafb8d4d1fd80e9d398cfbef7db1e2ccb73, the latter in 5d03af99c6d8f43be973cb6dacb5d6dd0ada33b1. But life is not so simple! It turns out that VSFilter [discards metrics of the line break and leading/trailing spaces for lines that stay nonempty after whitespace trimming][1]. So we actually handled nonblank (trimmable-space-less) lines correctly *before* #285 and have been *mishandling* them since #285 landed, adding the line break's metrics when they should be ignored. This is not noticeable in plain text, but it affects cases when a line's contents have a different height from the line breaks: {\fs96}foo\N{\p1}m 0 0 l 0 1 1 1 1 0{\p0}\Nbar {\fs96}foo\N{\fs1}bar{\fs96}\Nbaz (the middle line should be 1px high, not 96px) [1]: https://github.com/Cyberbeing/xy-VSFilter/blob/3.0.0.306/src/subtitles/RTS.cpp#L1401-L1422 More complicated cases with trimmable spaces have never been handled correctly, but this is nevertheless a regression. To fix this: * move the `trim_whitespace` call before the `measure_text` call (they seem independent, so this is easy), * mark trimmed whitespace with a new dedicated flag in addition to `.skip` so it can be distinguished from invisible glyphs, * clear accumulated (line-leading-whitespace) metrics when each line's first non-trimmed-whitespace glyph is found, * skip trimmed-whitespace glyphs when the line is already proven nonblank, because they are certainly line-trailing whitespace. Note: line breaks themselves do have `.skip` and `.is_trimmed_whitespace`. Note: our `.linebreak` is set on the glyph *after* the line break. As a result, a nonblank line will include the metrics only of the glyphs that (would) remain after trimming leading and trailing whitespace (including the line break), while a blank line includes the metrics of all glyphs from its first in-line glyph up to and including the terminating line break (if any). At the same time, line height is only halved for lines that are truly empty and don't even contain any whitespace. (Before the halving, the line height comes from the line break glyph.) This matches VSFilter.
* Use bool and true/false assignments for GlyphInfo::skipOleg Oshmyan2020-09-193-10/+11
|
* Don't halve nonempty line height even if wholly invisibleOleg Oshmyan2020-09-191-1/+1
| | | | | VSFilter compatibility: VSFilter does no special handling of invisible control characters and sees the line as nonempty.
* Revert "fontselect: expose the freetype-provided family as well"rcombs2020-09-191-7/+9
| | | | | | | | This reverts commit 6c2120a7cb4a6fd648ef37ad8f0d961cbd60f500. This turned out never to actually be necessary, wasn't actually consistent with vsfilter, and could result in script authors relying on accidentally-introduced deviations from vsfilter font matching.
* 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.
* ass_fontconfig: use FcWeightToOpenTypeDoublercombs2020-09-191-6/+10
| | | | | This provides higher precision in reported weights when using the fontconfig font provider.
* 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.h: Mark deprecated declarations as deprecatedOneric2020-09-081-3/+19
| | | | GCC, Clang and MSVC now issue a warning when deprecated API is used.
* ass_utils: make ass_strtod/strtoll wrappers inlineablercombs2020-08-302-35/+31
| | | | | Also makes a measurable difference on float-parse-heavy scripts, and it's not like these had a reason to not be in the header.
* 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.
* render: match VSFilter's behavior when painting fill in shadow/borderrcombs2020-08-303-13/+33
| | | | | | | Some releases rely on this. See corresponding VSFilter code: https://github.com/Cyberbeing/xy-VSFilter/blob/cf8f5b27de77fe649341bfab0fdfd498e1ad2fa6/src/subtitles/RTS.cpp#L1270 https://github.com/Cyberbeing/xy-VSFilter/blob/cf8f5b27de77fe649341bfab0fdfd498e1ad2fa6/src/subtitles/RTS.cpp#L1291
* Disable bidi bracket matching unless enabled via ASS_FeatureOleg Oshmyan2020-07-146-16/+60
| | | | | | | | | | | | | | | | | | | | | Bracket matching is incompatible with VSFilter (even on modern Windows), so disable it by default. But as it's generally a good thing (and 100% more compliant with current Unicode), keep it available as an ASS_Feature. It can be toggled individually or enabled as part of the catch-all ASS_FEATURE_INCOMPATIBLE_EXTENSIONS feature. If libass is compiled against FriBidi older than 1.0, bracket matching is impossible. Signal this at runtime by failing to recognize the ASS_FEATURE_BIDI_BRACKETS feature. This way, clients who want to use bracket matching can set the feature without any compile-time checks for FriBidi and can be freely linked against libass that is itself compiled against any version of FriBidi; and yet they can detect at runtime whether the feature is actually enabled. Fixes https://github.com/libass/libass/issues/374.
* Extract struct parser_priv into separate header fileOleg Oshmyan2020-07-142-40/+65
|
* Take bool in ass_shaper_set_kerningOleg Oshmyan2020-07-142-3/+4
|
* shaper: drop prealloc parameter of ass_shaper_newOleg Oshmyan2020-07-123-7/+4
| | | | | | The only prealloc value actually used is 0, which is not useful and invokes implementation-defined (and potentially obsolescent as per C11 DR400) behavior.
* Ignore leading space of lines in parsingOneric2020-07-111-0/+1
| | | | | | This more forgiving behavi