From 3bc783e5a18f1b3437727bd8166c7d40ace7a6cd Mon Sep 17 00:00:00 2001 From: Pierre-Anthony Lemieux Date: Fri, 8 Dec 2023 13:03:49 -0800 Subject: [PATCH] Fix ISD cache ignoring regions with showBackground="always" https://github.com/sandflow/ttconv/issues/420 --- src/main/python/ttconv/isd.py | 33 +++++++++++-- src/test/python/test_isd_cache.py | 77 +++++++++++++++++++++++++++++++ 2 files changed, 106 insertions(+), 4 deletions(-) create mode 100644 src/test/python/test_isd_cache.py diff --git a/src/main/python/ttconv/isd.py b/src/main/python/ttconv/isd.py index 656c2dbf..77bde2c1 100644 --- a/src/main/python/ttconv/isd.py +++ b/src/main/python/ttconv/isd.py @@ -184,6 +184,30 @@ def _make_absolute( return (begin_time, end_time) + def _region_always_has_background(region: typing.Type[model.Region]) -> bool: + + if region.get_style(styles.StyleProperties.Opacity) == 0: + return False + + if region.get_style(styles.StyleProperties.Display) is styles.DisplayType.none: + return False + + if region.get_style(styles.StyleProperties.Visibility) is styles.VisibilityType.hidden: + return False + + if region.get_style(styles.StyleProperties.ShowBackground) is styles.ShowBackgroundType.whenActive: + return False + + bg_color: styles.ColorType = region.get_style(styles.StyleProperties.BackgroundColor) + if bg_color is not None: + if bg_color.ident is not styles.ColorType.Colorimetry.RGBA8: + raise RuntimeError(f"Unsupported colorimetry system: {bg_color.ident}") + + if bg_color.components[3] == 0: + return False + + return True + @staticmethod def significant_times(doc: model.ContentDocument) -> SignificantTimes: '''Returns a list of the temporal offsets at which the document `doc` changes, sorted in @@ -204,7 +228,8 @@ def compute_sig_times( interval_cache[element] = (begin_time, end_time) - if isinstance(element, (model.Br, model.Span)): + if isinstance(element, (model.Br, model.Span)) or \ + isinstance(element, (model.Region)) and ISD._region_always_has_background(element): content_interval[0] = begin_time if content_interval[0] is None else min(begin_time, content_interval[0]) content_interval[1] = None if end_time is None or content_interval[1] is None else max(end_time, content_interval[1]) @@ -249,15 +274,15 @@ def compute_sig_times( interval_cache = {} + content_interval = [None, 0] + # add significant times for regions for region in cached_doc.iter_regions(): - compute_sig_times(interval_cache, None, s_times, region, 0, None) + compute_sig_times(interval_cache, content_interval, s_times, region, 0, None) # add significant times for body and its descendents - content_interval = [None, 0] - if cached_doc.get_body() is not None: compute_sig_times(interval_cache, content_interval, s_times, cached_doc.get_body(), 0, None) diff --git a/src/test/python/test_isd_cache.py b/src/test/python/test_isd_cache.py new file mode 100644 index 00000000..ba6fa2d9 --- /dev/null +++ b/src/test/python/test_isd_cache.py @@ -0,0 +1,77 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- + +# Copyright (c) 2020, Sandflow Consulting LLC +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +'''Unit tests for ISD generation using caching''' + +# pylint: disable=R0201,C0115,C0116 + +import unittest +from ttconv.isd import ISD +import ttconv.model as model +import ttconv.style_properties as styles +import xml.etree.ElementTree as et +import ttconv.imsc.reader as imsc_reader + + +class ISDCacheTests(unittest.TestCase): + + def test_show_background(self): + ttml_doc = """ + + +