def from_model_animation(model_element: model.ContentElement, xml_element): '''Write TTML set element from the model''' for a_step in model_element.iter_animation_steps(): set_element = SetElement.from_model(a_step) if set_element is not None: xml_element.append(set_element)
def append_element(self, element: model.ContentElement, begin: Fraction, end: Optional[Fraction]): """Converts model element to SRT content""" if isinstance(element, model.Div): for elem in list(element): self.append_element(elem, begin, end) if isinstance(element, model.P): self._captions_counter += 1 self._paragraphs.append(SrtParagraph(self._captions_counter)) self._paragraphs[-1].set_begin(begin) self._paragraphs[-1].set_end(end) for elem in list(element): self.append_element(elem, begin, end) self._paragraphs[-1].normalize_eol() if self._paragraphs[-1].is_only_whitespace(): LOGGER.debug("Removing empty paragraph.") self._paragraphs.pop() if isinstance(element, model.Span): is_bold = style.is_element_bold(element) is_italic = style.is_element_italic(element) is_underlined = style.is_element_underlined(element) font_color = style.get_font_color(element) if font_color is not None: self._paragraphs[-1].append_text( style.FONT_COLOR_TAG_IN.format(font_color)) if is_bold: self._paragraphs[-1].append_text(style.BOLD_TAG_IN) if is_italic: self._paragraphs[-1].append_text(style.ITALIC_TAG_IN) if is_underlined: self._paragraphs[-1].append_text(style.UNDERLINE_TAG_IN) for elem in list(element): self.append_element(elem, begin, end) if is_underlined: self._paragraphs[-1].append_text(style.UNDERLINE_TAG_OUT) if is_italic: self._paragraphs[-1].append_text(style.ITALIC_TAG_OUT) if is_bold: self._paragraphs[-1].append_text(style.BOLD_TAG_OUT) if font_color is not None: self._paragraphs[-1].append_text(style.FONT_COLOR_TAG_OUT) if isinstance(element, model.Br): self._paragraphs[-1].append_text("\n") if isinstance(element, model.Text): self._paragraphs[-1].append_text(element.get_text())
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)
def get_font_color(element: ContentElement) -> Optional[str]: """Returns the font color code if present""" font_color = element.get_style(StyleProperties.Color) if font_color is None: return None (r, g, b, a) = font_color.components return "#{:02x}{:02x}{:02x}{:02x}".format(r, g, b, a)
def get_background_color(element: ContentElement) -> Optional[str]: """Returns the background color hex code""" background_color = element.get_style(StyleProperties.BackgroundColor) if background_color is None: return None (r, g, b, a) = background_color.components return "#{:02x}{:02x}{:02x}{:02x}".format(r, g, b, a)
def append_element(self, element: model.ContentElement, offset: Fraction): """Converts model element to SRT content""" if isinstance(element, model.Div): for elem in list(element): self.append_element(elem, offset) if isinstance(element, model.P): if self._paragraphs: self._paragraphs[-1].set_end(offset) self._captions_counter += 1 self._paragraphs.append(SrtParagraph(self._captions_counter)) self._paragraphs[-1].set_begin(offset) for elem in list(element): self.append_element(elem, offset) if isinstance(element, model.Span): is_bold = style.is_element_bold(element) is_italic = style.is_element_italic(element) is_underlined = style.is_element_underlined(element) font_color = style.get_font_color(element) if font_color is not None: self._paragraphs[-1].append_text( style.FONT_COLOR_TAG_IN.format(font_color)) if is_bold: self._paragraphs[-1].append_text(style.BOLD_TAG_IN) if is_italic: self._paragraphs[-1].append_text(style.ITALIC_TAG_IN) if is_underlined: self._paragraphs[-1].append_text(style.UNDERLINE_TAG_IN) for elem in list(element): self.append_element(elem, offset) if is_underlined: self._paragraphs[-1].append_text(style.UNDERLINE_TAG_OUT) if is_italic: self._paragraphs[-1].append_text(style.ITALIC_TAG_OUT) if is_bold: self._paragraphs[-1].append_text(style.BOLD_TAG_OUT) if font_color is not None: self._paragraphs[-1].append_text(style.FONT_COLOR_TAG_OUT) if isinstance(element, model.Br): self._paragraphs[-1].append_text("\n") if isinstance(element, model.Text): self._paragraphs[-1].append_text(element.get_text())
def process_inline_element(self, element: model.ContentElement, begin: Fraction, end: Optional[Fraction]): """Converts inline element (span and br) to VTT content""" if isinstance(element, model.Span): is_bold = style.is_element_bold(element) is_italic = style.is_element_italic(element) is_underlined = style.is_element_underlined(element) color = style.get_color(element) bg_color = style.get_background_color(element) if color is not None: if self._colors_used.get(color) is None: color_classname = style.get_color_classname(color) self._colors_used[color] = color_classname self._css_classes.append(CssClass("color", color, color_classname)) else: color_classname = self._colors_used[color] self._paragraphs[-1].append_text(style.COLOR_TAG_IN.format(color_classname)) if bg_color is not None: if self._background_colors_used.get(bg_color) is None: bg_color_classname = style.get_background_color_classname(bg_color) self._background_colors_used[bg_color] = bg_color_classname self._css_classes.append(CssClass("background-color", bg_color, bg_color_classname)) else: bg_color_classname = self._background_colors_used[bg_color] self._paragraphs[-1].append_text(style.BG_COLOR_TAG_IN.format(bg_color_classname)) if is_bold: self._paragraphs[-1].append_text(style.BOLD_TAG_IN) if is_italic: self._paragraphs[-1].append_text(style.ITALIC_TAG_IN) if is_underlined: self._paragraphs[-1].append_text(style.UNDERLINE_TAG_IN) for elem in list(element): self.process_inline_element(elem, begin, end) if is_underlined: self._paragraphs[-1].append_text(style.UNDERLINE_TAG_OUT) if is_italic: self._paragraphs[-1].append_text(style.ITALIC_TAG_OUT) if is_bold: self._paragraphs[-1].append_text(style.BOLD_TAG_OUT) if color is not None: self._paragraphs[-1].append_text(style.COLOR_TAG_OUT) if bg_color is not None: self._paragraphs[-1].append_text(style.BG_COLOR_TAG_OUT) if isinstance(element, model.Br): self._paragraphs[-1].append_text("\n") if isinstance(element, model.Text): self._paragraphs[-1].append_text(element.get_text())
def _process_element(self, element: ContentElement): """Filter ISD element style properties""" element_styles = list(element.iter_styles()) for style_prop in element_styles: value = element.get_style(style_prop) default_value = self.style_property_default_values.get(style_prop) parent = element.parent() if parent is not None and style_prop.is_inherited: # If the parent style property value has not been removed, it means # the value is not set to default, and so that the child style property # value may have been "forced" to the default value, so let's skip it. parent_value = parent.get_style(style_prop) if parent_value is not None and parent_value is not value: continue # Remove the style property if its value is default (and if it is not inherited) if default_value is not None and value == default_value: element.set_style(style_prop, None) for child in element: self._process_element(child)
def check_element_style(self, elem: ContentElement, style_property: Type[StyleProperty], expected_value): self.assertEqual(expected_value, elem.get_style(style_property))
def is_element_underlined(element: ContentElement) -> bool: """Returns whether the element text is underlined""" text_decoration: Optional[TextDecorationType] = element.get_style( StyleProperties.TextDecoration) return text_decoration is not None and text_decoration.underline is True
def is_element_italic(element: ContentElement) -> bool: """Returns whether the element text is italic""" font_style: Optional[FontStyleType] = element.get_style( StyleProperties.FontStyle) return font_style is not None and font_style is FontStyleType.italic
def is_element_bold(element: ContentElement) -> bool: """Returns whether the element text is bold""" font_weight: Optional[FontWeightType] = element.get_style( StyleProperties.FontWeight) return font_weight is not None and font_weight is FontWeightType.bold
def from_model( model_element: model.ContentElement ) -> typing.Optional[ContentElement]: if isinstance(model_element, model.Body): imsc_class = BodyElement elif isinstance(model_element, model.Div): imsc_class = DivElement elif isinstance(model_element, model.P): imsc_class = PElement elif isinstance(model_element, model.Span): imsc_class = SpanElement elif isinstance(model_element, model.Br): imsc_class = BrElement elif isinstance(model_element, model.Ruby): imsc_class = RubyElement elif isinstance(model_element, model.Rb): imsc_class = RbElement elif isinstance(model_element, model.Rt): imsc_class = RtElement elif isinstance(model_element, model.Rbc): imsc_class = RbcElement elif isinstance(model_element, model.Rtc): imsc_class = RtcElement elif isinstance(model_element, model.Region): imsc_class = RegionElement else: return None xml_element = imsc_class.make_ttml_element() if imsc_class.has_region: if model_element.get_region() is not None: imsc_attr.RegionAttribute.set( xml_element, model_element.get_region().get_id()) if imsc_class.has_timing: if model_element.get_begin() is not None: imsc_attr.BeginAttribute.set(xml_element, model_element.get_begin()) if model_element.get_end() is not None: imsc_attr.EndAttribute.set(xml_element, model_element.get_end()) if model_element.get_id() is not None: imsc_attr.XMLIDAttribute.set(xml_element, model_element.get_id()) if imsc_class.has_styles: ContentElement.from_model_style_properties(model_element, xml_element) ContentElement.from_model_animation(model_element, xml_element) if imsc_class.has_children: last_child_element = None for child in iter(model_element): if isinstance(child, model.Text): if last_child_element is None: xml_element.text = child.get_text() else: last_child_element.tail = child.get_text() child_element = ContentElement.from_model(child) if child_element is not None: xml_element.append(child_element) last_child_element = child_element return xml_element
def from_model( ctx: TTMLElement.WritingContext, model_element: model.ContentElement ) -> typing.Optional[et.Element]: '''Returns the TTML element corresponding to the model element `model_element`. `ctx` contains state information used in the process. ''' if isinstance(model_element, model.Body): imsc_class = BodyElement elif isinstance(model_element, model.Div): imsc_class = DivElement elif isinstance(model_element, model.P): imsc_class = PElement elif isinstance(model_element, model.Span): imsc_class = SpanElement elif isinstance(model_element, model.Br): imsc_class = BrElement elif isinstance(model_element, model.Ruby): imsc_class = RubyElement elif isinstance(model_element, model.Rb): imsc_class = RbElement elif isinstance(model_element, model.Rt): imsc_class = RtElement elif isinstance(model_element, model.Rbc): imsc_class = RbcElement elif isinstance(model_element, model.Rtc): imsc_class = RtcElement elif isinstance(model_element, model.Region): imsc_class = RegionElement else: return None xml_element = imsc_class.make_ttml_element() if (model_element.parent() is None and model_element.get_space() is model.WhiteSpaceHandling.PRESERVE) or \ (model_element.parent() is not None and model_element.parent().get_space() != model_element.get_space()): imsc_attr.XMLSpaceAttribute.set(xml_element, model_element.get_space()) if imsc_class.has_region: if model_element.get_region() is not None: imsc_attr.RegionAttribute.set(xml_element, model_element.get_region().get_id()) if imsc_class.has_timing: if model_element.get_begin() is not None: imsc_attr.BeginAttribute.set(ctx.temporal_context, xml_element, model_element.get_begin()) if model_element.get_end() is not None: imsc_attr.EndAttribute.set(ctx.temporal_context, xml_element, model_element.get_end()) if model_element.get_id() is not None: imsc_attr.XMLIDAttribute.set(xml_element, model_element.get_id()) if imsc_class.has_styles: ContentElement.from_model_style_properties(model_element, xml_element) ContentElement.from_model_animation(ctx, model_element, xml_element) if imsc_class.has_children: last_child_element = None for child in iter(model_element): if isinstance(child, model.Text): if last_child_element is None: xml_element.text = child.get_text() else: last_child_element.tail = child.get_text() child_element = ContentElement.from_model(ctx, child) if child_element is not None: xml_element.append(child_element) last_child_element = child_element return xml_element
def _get_text_from_children(element: ContentElement) -> str: if isinstance(element, Text): return element.get_text() for child in element: return ParagraphsMergingFilterTest._get_text_from_children(child)
def to_model(element: model.ContentElement, is_teletext: bool, tti_cct: bytes, tti_tf: bytes): """Converts the EBU STL text field `tti_tf` to a sequence of span elements and appends them to the content element `element`. `is_teletext` indicates whether the text field is interpreted as teletext or open/undefined. `tti_cct` specifies the text field code page as signaled in the TTI CCT field. """ tf_iter = _TextFieldIterator(tti_tf) decode_func = _CHAR_DECODER_MAP.get(tti_cct) if decode_func is None: decode_func = iso6937.decode LOGGER.error("Unknown Text Field character set: %s", str(tti_cct)) context = _Context(element, is_teletext, decode_func) while True: c = tf_iter.cur() if _is_unused_space_code(c): break if _is_character_code(c): if _is_printable_code(c) or (_is_printable_code(tf_iter.peek_next()) and _is_printable_code(tf_iter.peek_prev())): context.append_character(c) elif _is_newline_code(c): if not _is_newline_code(tf_iter.peek_next()) and not _is_unused_space_code(tf_iter.peek_next()): context.end_span() element.push_child(model.Br(element.get_doc())) if is_teletext: context.reset_styles(is_teletext) elif _is_control_code(c): context.end_span() if c == 0x1C: context.set_bg_color(styles.NamedColors.black.value) elif c == 0x85: context.set_bg_color(styles.NamedColors.transparent.value) elif c == 0x1D: context.set_bg_color(context.get_fg_color()) elif c == 0x00: context.set_fg_color(styles.NamedColors.black.value) elif c == 0x01: context.set_fg_color(styles.NamedColors.red.value) elif c == 0x02: context.set_fg_color(styles.NamedColors.lime.value) elif c == 0x03: context.set_fg_color(styles.NamedColors.yellow.value) elif c == 0x04: context.set_fg_color(styles.NamedColors.blue.value) elif c == 0x05: context.set_fg_color(styles.NamedColors.magenta.value) elif c == 0x06: context.set_fg_color(styles.NamedColors.cyan.value) elif c == 0x07: context.set_fg_color(styles.NamedColors.white.value) elif c == 0x80: context.set_italic(True) elif c == 0x81: context.set_italic(False) elif c == 0x82: context.set_underline(True) elif c == 0x83: context.set_underline(False) if (_is_printable_code(tf_iter.peek_next()) and _is_printable_code(tf_iter.peek_prev())): context.append_character(0X20) next(tf_iter) context.end_span()