diff --git a/src/main/python/ttconv/filters/doc/lcd.py b/src/main/python/ttconv/filters/doc/lcd.py index d591efd8..6f7b6697 100644 --- a/src/main/python/ttconv/filters/doc/lcd.py +++ b/src/main/python/ttconv/filters/doc/lcd.py @@ -23,8 +23,7 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -"""Least common denominator filter. Merges regions and removes all text -formatting but color.""" +"""Defines the Least common denominator (LCD) filter.""" from __future__ import annotations import logging @@ -63,8 +62,8 @@ def _safe_area_decoder(s): return safe_area @dataclass -class LCDFilterConfig(ModuleConfiguration): - """Configuration class for the Simplify Regions filter""" +class LCDDocFilterConfig(ModuleConfiguration): + """Configuration class for the Least common denominator (LCD) filter""" @classmethod def name(cls): @@ -82,14 +81,15 @@ def name(cls): # specifies the paragraph background color bg_color: typing.Optional[ColorType] = field(default=NamedColors.black.value, metadata={"decoder": ttconv.utils.parse_color}) -class LCDFilter(DocumentFilter): - """Filter that simplifies regions""" +class LCDDocFilter(DocumentFilter): + """Merges regions and removes all text formatting with the exception of color + and text alignment.""" @classmethod def get_config_class(cls) -> ModuleConfiguration: - return LCDFilterConfig + return LCDDocFilterConfig - def __init__(self, config: LCDFilterConfig): + def __init__(self, config: LCDDocFilterConfig): super().__init__(config) def process(self, doc: ContentDocument) -> ContentDocument: diff --git a/src/main/python/ttconv/filters/isd/__init__.py b/src/main/python/ttconv/filters/isd/__init__.py index cb3bee33..88851cf2 100644 --- a/src/main/python/ttconv/filters/isd/__init__.py +++ b/src/main/python/ttconv/filters/isd/__init__.py @@ -25,12 +25,5 @@ """Data model filter""" -from ttconv.isd import ISD -class Filter: - """Abstract base class for filters""" - - def process(self, isd: ISD): - """Process the specified ISD and returns it.""" - raise NotImplementedError diff --git a/src/main/python/ttconv/filters/isd/default_style_properties.py b/src/main/python/ttconv/filters/isd/default_style_properties.py index 1bc81b62..077b004e 100644 --- a/src/main/python/ttconv/filters/isd/default_style_properties.py +++ b/src/main/python/ttconv/filters/isd/default_style_properties.py @@ -28,7 +28,7 @@ import logging from typing import Dict, Type, Any -from ttconv.filters.isd import Filter +from ttconv.filters.isd_filter import ISDFilter from ttconv.isd import ISD from ttconv.model import ContentElement from ttconv.style_properties import StyleProperty @@ -36,7 +36,7 @@ LOGGER = logging.getLogger(__name__) -class DefaultStylePropertyValuesFilter(Filter): +class DefaultStylePropertyValuesISDFilter(ISDFilter): """Filter that remove default style properties""" def __init__(self, style_property_default_values: Dict[Type[StyleProperty], Any]): diff --git a/src/main/python/ttconv/filters/isd/merge_paragraphs.py b/src/main/python/ttconv/filters/isd/merge_paragraphs.py index cfe502f3..d3717b7c 100644 --- a/src/main/python/ttconv/filters/isd/merge_paragraphs.py +++ b/src/main/python/ttconv/filters/isd/merge_paragraphs.py @@ -27,14 +27,14 @@ import logging -from ttconv.filters.isd import Filter +from ttconv.filters.isd_filter import ISDFilter from ttconv.isd import ISD from ttconv.model import Div, P, Br, ContentElement LOGGER = logging.getLogger(__name__) -class ParagraphsMergingFilter(Filter): +class ParagraphsMergingISDFilter(ISDFilter): """Filter for merging ISD document paragraphs per region into a single paragraph""" def _get_paragraphs(self, element: ContentElement): diff --git a/src/main/python/ttconv/filters/isd/merge_regions.py b/src/main/python/ttconv/filters/isd/merge_regions.py index 5a18325f..fab59406 100644 --- a/src/main/python/ttconv/filters/isd/merge_regions.py +++ b/src/main/python/ttconv/filters/isd/merge_regions.py @@ -27,14 +27,14 @@ import logging -from ttconv.filters.isd import Filter +from ttconv.filters.isd_filter import ISDFilter from ttconv.isd import ISD from ttconv.model import Body LOGGER = logging.getLogger(__name__) -class RegionsMergingFilter(Filter): +class RegionsMergingISDFilter(ISDFilter): """Filter for merging ISD document regions into a single region""" def process(self, isd: ISD): diff --git a/src/main/python/ttconv/filters/isd/supported_style_properties.py b/src/main/python/ttconv/filters/isd/supported_style_properties.py index 060dd8f2..f1983515 100644 --- a/src/main/python/ttconv/filters/isd/supported_style_properties.py +++ b/src/main/python/ttconv/filters/isd/supported_style_properties.py @@ -28,41 +28,24 @@ import logging from typing import Dict, List, Type -from ttconv.filters.isd import Filter +from ttconv.filters.isd_filter import ISDFilter from ttconv.isd import ISD from ttconv.model import ContentElement from ttconv.style_properties import StyleProperty +import ttconv.filters.supported_style_properties LOGGER = logging.getLogger(__name__) -class SupportedStylePropertiesFilter(Filter): +class SupportedStylePropertiesISDFilter(ISDFilter): """Filter that remove unsupported style properties""" def __init__(self, supported_style_properties: Dict[Type[StyleProperty], List]): - self.supported_style_properties = supported_style_properties - - def _process_element(self, element: ContentElement): - """Filter ISD element style properties""" - - element_styles = list(element.iter_styles()) - for style_prop in element_styles: - - if style_prop in self.supported_style_properties.keys(): - value = element.get_style(style_prop) - supported_values = self.supported_style_properties[style_prop] - - if len(supported_values) == 0 or value in supported_values: - continue - - element.set_style(style_prop, None) - - for child in element: - self._process_element(child) + self.filter = ttconv.filters.supported_style_properties.SupportedStylePropertiesFilter(supported_style_properties) def process(self, isd: ISD): """Filter ISD document style properties""" LOGGER.debug("Filter default style properties from ISD.") for region in isd.iter_regions(): - self._process_element(region) + self.filter.process_element(region) diff --git a/src/main/python/ttconv/filters/isd_filter.py b/src/main/python/ttconv/filters/isd_filter.py new file mode 100644 index 00000000..75c99217 --- /dev/null +++ b/src/main/python/ttconv/filters/isd_filter.py @@ -0,0 +1,35 @@ +#!/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. + +"""Data model filter""" + +from ttconv.isd import ISD + +class ISDFilter: + """Abstract base class for filters""" + + def process(self, isd: ISD): + """Process the specified ISD and returns it.""" + raise NotImplementedError diff --git a/src/main/python/ttconv/filters/remove_animations.py b/src/main/python/ttconv/filters/remove_animations.py index f830c80f..29f1070f 100644 --- a/src/main/python/ttconv/filters/remove_animations.py +++ b/src/main/python/ttconv/filters/remove_animations.py @@ -31,9 +31,6 @@ from ttconv.model import ContentDocument, ContentElement from ttconv.style_properties import StyleProperty -LOGGER = logging.getLogger(__name__) - - class RemoveAnimationFilter: """Filter that remove animations""" diff --git a/src/main/python/ttconv/filters/supported_style_properties.py b/src/main/python/ttconv/filters/supported_style_properties.py index 0e890bc1..6f6c09a4 100644 --- a/src/main/python/ttconv/filters/supported_style_properties.py +++ b/src/main/python/ttconv/filters/supported_style_properties.py @@ -31,9 +31,6 @@ from ttconv.model import ContentDocument, ContentElement from ttconv.style_properties import StyleProperty -LOGGER = logging.getLogger(__name__) - - class SupportedStylePropertiesFilter: """Filter that remove unsupported style properties""" diff --git a/src/main/python/ttconv/srt/writer.py b/src/main/python/ttconv/srt/writer.py index 43c78cdb..fd43ac17 100644 --- a/src/main/python/ttconv/srt/writer.py +++ b/src/main/python/ttconv/srt/writer.py @@ -31,11 +31,11 @@ import ttconv.model as model import ttconv.srt.style as style -from ttconv.filters.isd import Filter -from ttconv.filters.isd.default_style_properties import DefaultStylePropertyValuesFilter -from ttconv.filters.isd.merge_paragraphs import ParagraphsMergingFilter -from ttconv.filters.isd.merge_regions import RegionsMergingFilter -from ttconv.filters.isd.supported_style_properties import SupportedStylePropertiesFilter +from ttconv.filters.isd_filter import ISDFilter +from ttconv.filters.isd.default_style_properties import DefaultStylePropertyValuesISDFilter +from ttconv.filters.isd.merge_paragraphs import ParagraphsMergingISDFilter +from ttconv.filters.isd.merge_regions import RegionsMergingISDFilter +from ttconv.filters.isd.supported_style_properties import SupportedStylePropertiesISDFilter from ttconv.isd import ISD from ttconv.srt.paragraph import SrtParagraph from ttconv.srt.config import SRTWriterConfiguration @@ -47,10 +47,10 @@ class SrtContext: """SRT writer context""" - filters: List[Filter] = ( - RegionsMergingFilter(), - ParagraphsMergingFilter(), - SupportedStylePropertiesFilter({ + filters: List[ISDFilter] = ( + RegionsMergingISDFilter(), + ParagraphsMergingISDFilter(), + SupportedStylePropertiesISDFilter({ StyleProperties.FontWeight: [ # Every values ], @@ -65,7 +65,7 @@ class SrtContext: # Every values ], }), - DefaultStylePropertyValuesFilter({ + DefaultStylePropertyValuesISDFilter({ StyleProperties.Color: NamedColors.white.value, StyleProperties.FontWeight: FontWeightType.normal, StyleProperties.FontStyle: FontStyleType.normal, diff --git a/src/main/python/ttconv/vtt/writer.py b/src/main/python/ttconv/vtt/writer.py index a39d2caa..2a079e61 100644 --- a/src/main/python/ttconv/vtt/writer.py +++ b/src/main/python/ttconv/vtt/writer.py @@ -32,10 +32,10 @@ import ttconv.model as model from ttconv.vtt.config import VTTWriterConfiguration import ttconv.vtt.style as style -from ttconv.filters.isd.default_style_properties import DefaultStylePropertyValuesFilter -from ttconv.filters.isd.merge_paragraphs import ParagraphsMergingFilter -from ttconv.filters.isd.merge_regions import RegionsMergingFilter -from ttconv.filters.isd.supported_style_properties import SupportedStylePropertiesFilter +from ttconv.filters.isd.default_style_properties import DefaultStylePropertyValuesISDFilter +from ttconv.filters.isd.merge_paragraphs import ParagraphsMergingISDFilter +from ttconv.filters.isd.merge_regions import RegionsMergingISDFilter +from ttconv.filters.isd.supported_style_properties import SupportedStylePropertiesISDFilter from ttconv.isd import ISD from ttconv.vtt.cue import VttCue from ttconv.vtt.css_class import CssClass @@ -61,9 +61,9 @@ def __init__(self, config: VTTWriterConfiguration): self._filters = [] if not self._config.line_position: - self._filters.append(RegionsMergingFilter()) + self._filters.append(RegionsMergingISDFilter()) - self._filters.append(ParagraphsMergingFilter()) + self._filters.append(ParagraphsMergingISDFilter()) supported_styles = { StyleProperties.FontWeight: [], @@ -92,10 +92,10 @@ def __init__(self, config: VTTWriterConfiguration): StyleProperties.Direction: [], }) - self._filters.append(SupportedStylePropertiesFilter(supported_styles)) + self._filters.append(SupportedStylePropertiesISDFilter(supported_styles)) self._filters.append( - DefaultStylePropertyValuesFilter({ + DefaultStylePropertyValuesISDFilter({ StyleProperties.Color: NamedColors.white.value, StyleProperties.BackgroundColor: NamedColors.transparent.value, StyleProperties.FontWeight: FontWeightType.normal, diff --git a/src/test/python/test_filter_default_style_properties.py b/src/test/python/test_filter_default_style_properties.py index 018a7e75..77c92651 100644 --- a/src/test/python/test_filter_default_style_properties.py +++ b/src/test/python/test_filter_default_style_properties.py @@ -29,7 +29,7 @@ from fractions import Fraction import unittest -from ttconv.filters.isd.default_style_properties import DefaultStylePropertyValuesFilter +from ttconv.filters.isd.default_style_properties import DefaultStylePropertyValuesISDFilter from ttconv.isd import ISD from ttconv.model import P, ContentDocument, Region, Body, Div, Span, Text from ttconv.style_properties import StyleProperties, NamedColors, FontStyleType, DirectionType @@ -38,7 +38,7 @@ class DefaultStylesFilterTest(unittest.TestCase): def test_process_element(self): - default_style_value_filter = DefaultStylePropertyValuesFilter({ + default_style_value_filter = DefaultStylePropertyValuesISDFilter({ StyleProperties.Color: StyleProperties.Color.make_initial_value() }) @@ -55,7 +55,7 @@ def test_process_element(self): self.assertEqual(len(StyleProperties.ALL) - 1, len(p._styles)) def test_process_isd(self): - default_style_value_filter = DefaultStylePropertyValuesFilter({ + default_style_value_filter = DefaultStylePropertyValuesISDFilter({ StyleProperties.BackgroundColor: NamedColors.red.value, StyleProperties.Direction: DirectionType.ltr }) diff --git a/src/test/python/test_filter_merge_paragraphs.py b/src/test/python/test_filter_merge_paragraphs.py index 1469d6ae..fb15ec59 100644 --- a/src/test/python/test_filter_merge_paragraphs.py +++ b/src/test/python/test_filter_merge_paragraphs.py @@ -30,7 +30,7 @@ from typing import List import unittest -from ttconv.filters.isd.merge_paragraphs import ParagraphsMergingFilter +from ttconv.filters.isd.merge_paragraphs import ParagraphsMergingISDFilter from ttconv.isd import ISD from ttconv.model import P, Body, Div, Span, Text, ContentElement, Br @@ -66,7 +66,7 @@ def _get_text_from_children(element: ContentElement) -> str: return ParagraphsMergingFilterTest._get_text_from_children(child) def test_merging_regions(self): - paragraphs_merging_filter = ParagraphsMergingFilter() + paragraphs_merging_filter = ParagraphsMergingISDFilter() isd = ISD(None) diff --git a/src/test/python/test_filter_merge_regions.py b/src/test/python/test_filter_merge_regions.py index a8e750ca..03d4e951 100644 --- a/src/test/python/test_filter_merge_regions.py +++ b/src/test/python/test_filter_merge_regions.py @@ -29,7 +29,7 @@ import unittest -from ttconv.filters.isd.merge_regions import RegionsMergingFilter +from ttconv.filters.isd.merge_regions import RegionsMergingISDFilter from ttconv.isd import ISD from ttconv.model import P, Body, Div, Span, Text, ContentElement @@ -62,7 +62,7 @@ def _get_text_from_children(element: ContentElement) -> str: return RegionsMergingFilterTest._get_text_from_children(child) def test_merging_regions(self): - regions_merging_filter = RegionsMergingFilter() + regions_merging_filter = RegionsMergingISDFilter() isd = ISD(None) diff --git a/src/test/python/test_filter_supported_style_properties.py b/src/test/python/test_filter_supported_style_properties.py index 765e45a4..bfbc0720 100644 --- a/src/test/python/test_filter_supported_style_properties.py +++ b/src/test/python/test_filter_supported_style_properties.py @@ -29,7 +29,8 @@ from fractions import Fraction import unittest -from ttconv.filters.isd.supported_style_properties import SupportedStylePropertiesFilter +from ttconv.filters.supported_style_properties import SupportedStylePropertiesFilter +from ttconv.filters.isd.supported_style_properties import SupportedStylePropertiesISDFilter as SupportedStylePropertiesFilterISD from ttconv.isd import ISD from ttconv.model import P, ContentDocument, Region, Body, Div, Span, Text from ttconv.style_properties import StyleProperties, NamedColors, FontStyleType, DirectionType, ExtentType, LengthType @@ -53,7 +54,7 @@ def test_process_element(self): self.assertEqual(StyleProperties.Color.make_initial_value(), p.get_style(StyleProperties.Color)) self.assertEqual(StyleProperties.Extent.make_initial_value(), p.get_style(StyleProperties.Extent)) - supported_style_properties._process_element(p) + supported_style_properties.process_element(p) self.assertIsNone(p.get_style(StyleProperties.Color)) self.assertEqual(StyleProperties.Extent.make_initial_value(), p.get_style(StyleProperties.Extent)) @@ -61,14 +62,14 @@ def test_process_element(self): p.set_style(StyleProperties.Color, NamedColors.red.value) - supported_style_properties._process_element(p) + supported_style_properties.process_element(p) self.assertEqual(2, len(p._styles)) self.assertEqual(NamedColors.red.value, p.get_style(StyleProperties.Color)) self.assertEqual(StyleProperties.Extent.make_initial_value(), p.get_style(StyleProperties.Extent)) def test_process_isd(self): - supported_style_properties = SupportedStylePropertiesFilter({ + supported_style_properties = SupportedStylePropertiesFilterISD({ StyleProperties.BackgroundColor: [ NamedColors.red.value ], diff --git a/src/test/python/test_lcd_filter.py b/src/test/python/test_lcd_filter.py index 0784a1ba..06597674 100644 --- a/src/test/python/test_lcd_filter.py +++ b/src/test/python/test_lcd_filter.py @@ -28,7 +28,7 @@ # pylint: disable=R0201,C0115,C0116 import unittest -from ttconv.filters.doc.lcd import LCDFilter, LCDFilterConfig +from ttconv.filters.doc.lcd import LCDDocFilter, LCDDocFilterConfig import ttconv.model as model import ttconv.style_properties as styles @@ -129,7 +129,7 @@ def test_region_merging(self): p5.set_region(r5) div.push_child(p5) - filter = LCDFilter(LCDFilterConfig()) + filter = LCDDocFilter(LCDDocFilterConfig()) self.assertIsNone(filter.process(doc)) @@ -254,7 +254,7 @@ def test_region_resizing(self): div.push_child(p4) # apply filter - filter = LCDFilter(LCDFilterConfig()) + filter = LCDDocFilter(LCDDocFilterConfig()) self.assertIsNone(filter.process(doc)) @@ -316,7 +316,7 @@ def test_text_align(self): div.push_child(p1) # apply filter - filter = LCDFilter(LCDFilterConfig()) + filter = LCDDocFilter(LCDDocFilterConfig()) self.assertIsNone(filter.process(doc))