diff --git a/README.md b/README.md index 50e804e3..cf686ee0 100644 --- a/README.md +++ b/README.md @@ -191,6 +191,14 @@ Default: `true` Default: `false` +#### text_align + +`"text_align" : true | false` + +`true` means that the VTT writer outputs text alignment cue settings + +Default: `false` + #### cue_id `"cue_id" : true | false` diff --git a/src/main/python/ttconv/vtt/config.py b/src/main/python/ttconv/vtt/config.py index 3e211693..6878d885 100644 --- a/src/main/python/ttconv/vtt/config.py +++ b/src/main/python/ttconv/vtt/config.py @@ -41,5 +41,8 @@ def name(cls): # outputs `line` and `line alignment` cue settings line_position: bool = field(default=False, metadata={"decoder": bool}) + # outputs `text alignment` cue settings + text_align: bool = field(default=False, metadata={"decoder": bool}) + # outputs cue identifier cue_id: bool = field(default=True, metadata={"decoder": bool}) diff --git a/src/main/python/ttconv/vtt/cue.py b/src/main/python/ttconv/vtt/cue.py index 3ff3c643..b2fd38f9 100644 --- a/src/main/python/ttconv/vtt/cue.py +++ b/src/main/python/ttconv/vtt/cue.py @@ -42,6 +42,12 @@ class LineAlignment(Enum): center = "center" end = "end" + class TextAlignment(Enum): + """WebVTT text alignment cue setting""" + left = "left" + center = "center" + right = "right" + _EOL_SEQ_RE = re.compile(r"\n{2,}") def __init__(self, identifier: Optional[int] = None): @@ -50,7 +56,8 @@ def __init__(self, identifier: Optional[int] = None): self._end: Optional[ClockTime] = None self._text: str = "" self._line: int = None - self._align: VttCue.LineAlignment = None + self._linealign: VttCue.LineAlignment = None + self._textalign: VttCue.TextAlignment = None def set_begin(self, offset: Fraction): """Sets the paragraph begin time code""" @@ -83,11 +90,15 @@ def get_line(self) -> Optional[int]: def set_align(self, align: LineAlignment): """Sets the WebVTT line alignment cue setting""" - self._align = align + self._linealign = align def get_align(self) -> Optional[LineAlignment]: """Return the WebVTT line alignment cue setting""" - return self._align + return self._linealign + + def set_textalign(self, textalign: TextAlignment): + """Sets the WebVTT text alignment cue setting""" + self._textalign = textalign def is_only_whitespace_or_empty(self): """Returns whether the paragraph text contains only whitespace or is empty""" @@ -123,12 +134,16 @@ def __str__(self) -> str: # cue timing t += f"{self._begin} --> {self._end}" + # cue text position + if self._textalign is not None: + t += f" align:{self._textalign.value}" + # cue line position if self._line is not None: t += f" line:{self._line}%" - if self._align is not None: - t += f",{self._align.value}" + if self._linealign is not None: + t += f",{self._linealign.value}" t += "\n" diff --git a/src/main/python/ttconv/vtt/writer.py b/src/main/python/ttconv/vtt/writer.py index 1859e2fb..5959f7c1 100644 --- a/src/main/python/ttconv/vtt/writer.py +++ b/src/main/python/ttconv/vtt/writer.py @@ -39,7 +39,8 @@ from ttconv.isd import ISD from ttconv.vtt.cue import VttCue from ttconv.vtt.css_class import CssClass -from ttconv.style_properties import ExtentType, PositionType, StyleProperties, FontStyleType, NamedColors, FontWeightType, TextDecorationType, DisplayAlignType +from ttconv.style_properties import DirectionType, ExtentType, PositionType, StyleProperties, FontStyleType, NamedColors, \ + FontWeightType, TextDecorationType, DisplayAlignType, TextAlignType LOGGER = logging.getLogger(__name__) @@ -84,7 +85,13 @@ def __init__(self, config: VTTWriterConfiguration): StyleProperties.DisplayAlign: [], StyleProperties.Extent: [], }) - + + if self._config.text_align: + supported_styles.update({ + StyleProperties.TextAlign: [], + StyleProperties.Direction: [], + }) + self._filters.append(SupportedStylePropertiesFilter(supported_styles)) self._filters.append( @@ -175,6 +182,16 @@ def process_p(self, region: ISD.Region, element: model.P, begin: Fraction, end: cue.set_line(round(position.v_offset.value + extent.height.value / 2)) cue.set_align(VttCue.LineAlignment.center) + if self._config.text_align: + direction = element.get_style(StyleProperties.Direction) + text_align = element.get_style(StyleProperties.TextAlign) + if text_align == TextAlignType.center: + cue.set_textalign(VttCue.TextAlignment.center) + elif text_align == TextAlignType.start: + cue.set_textalign(VttCue.TextAlignment.right if direction == DirectionType.rtl else VttCue.TextAlignment.left) + elif text_align == TextAlignType.end: + cue.set_textalign(VttCue.TextAlignment.left if direction == DirectionType.rtl else VttCue.TextAlignment.right) + self._paragraphs.append(cue) for elem in list(element): diff --git a/src/test/python/test_vtt_writer.py b/src/test/python/test_vtt_writer.py index 42f9f66a..9f07163d 100644 --- a/src/test/python/test_vtt_writer.py +++ b/src/test/python/test_vtt_writer.py @@ -150,6 +150,60 @@ def test_position(self): vtt_from_model = vtt_writer.from_model(model, config) self.assertEqual(expected_vtt, vtt_from_model) + def test_align(self): + ttml_doc_str = """ + + + +