예제 #1
0
  def setUp(self):
    self.doc = model.ContentDocument()

    r1 = model.Region("r1", self.doc)
    r1.set_style(styles.StyleProperties.ShowBackground, styles.ShowBackgroundType.whenActive)
    self.doc.put_region(r1)

    b = model.Body(self.doc)
    b.set_region(r1)
    self.doc.set_body(b)

    div1 = model.Div(self.doc)
    b.push_child(div1)

    p1 = model.P(self.doc)
    p1.set_begin(1)
    p1.set_end(3)
    div1.push_child(p1)

    span1 = model.Span(self.doc)
    span1.push_child(model.Text(self.doc, "hello"))
    p1.push_child(span1)

    span2 = model.Span(self.doc)
    span2.set_begin(1)
    span2.push_child(model.Text(self.doc, "bye"))
    p1.push_child(span2)
예제 #2
0
    def test_push_child(self):

        s = model.Span()

        s.push_child(model.Br())

        s.push_child(model.Span())

        s.push_child(model.Text())

        with self.assertRaises(TypeError):
            s.push_child(model.P())
예제 #3
0
파일: elements.py 프로젝트: sandflow/ttconv
 def from_xml(
   parent_ctx: typing.Optional[TTMLElement.ParsingContext],
   xml_elem: et.Element
 ) -> typing.Optional[SpanElement.ParsingContext]:
   span_ctx = SpanElement.ParsingContext(SpanElement, parent_ctx, model.Span(parent_ctx.doc))
   span_ctx.process(parent_ctx, xml_elem)
   return span_ctx
예제 #4
0
  def test_default_region(self):

    doc = model.ContentDocument()

    b = model.Body(doc)
    doc.set_body(b)

    div1 = model.Div(doc)
    b.push_child(div1)

    p1 = model.P(doc)
    div1.push_child(p1)

    span1 = model.Span(doc)
    span1.push_child(model.Text(doc, "hello"))
    p1.push_child(span1)

    isd = ISD.from_model(doc, 0)

    self.assertEqual(len(isd), 1)

    regions = list(isd.iter_regions())

    self.assertEqual(regions[0].get_id(), ISD.DEFAULT_REGION_ID)

    p = regions[0][0][0][0]

    self.assertEqual(len(p), 1)

    self.assertEqual(p[0][0].get_text(), "hello")
예제 #5
0
    def test_tts_writing_extent_when_body_has_extents(self):

        doc = model.ContentDocument()
        body = model.Body(doc)
        div = model.Div(doc)

        div.set_style(
            styles.StyleProperties.Extent,
            get_extent_from_dimensions(123, 456, styles.LengthType.Units.px))

        p = model.P(doc)
        span = model.Span(doc)
        text = model.Text(doc)
        text.set_text("asdf")

        span.push_child(text)
        p.push_child(span)
        div.push_child(p)
        body.push_child(div)
        doc.set_body(body)

        r = model.Region("hello", doc)
        r.set_style(
            styles.StyleProperties.Extent,
            get_extent_from_dimensions(123, 456, styles.LengthType.Units.px))

        doc.put_region(r)

        tree_from_model = imsc_writer.from_model(doc)

        extent = tree_from_model.getroot().attrib.get(
            f"{{{imsc_styles.StyleProperties.Extent.ns}}}{imsc_styles.StyleProperties.Extent.local_name}"
        )

        self.assertEqual(extent, '1920px 1080px')
예제 #6
0
  def test_compute_style_property(self):
    doc = model.ContentDocument()

    r1 = model.Region("r1", doc)
    r1.set_style(styles.StyleProperties.FontSize, styles.LengthType(value=50, units=styles.LengthType.Units.pct))
    doc.put_region(r1)

    b = model.Body(doc)
    b.set_style(styles.StyleProperties.FontSize, styles.LengthType(value=50, units=styles.LengthType.Units.pct))
    b.set_region(r1)
    doc.set_body(b)

    div1 = model.Div(doc)
    b.push_child(div1)

    p1 = model.P(doc)
    div1.push_child(p1)

    span1 = model.Span(doc)
    p1.push_child(span1)

    t1 = model.Text(doc, "hello")
    span1.push_child(t1)

    isd = ISD.from_model(doc, 0)

    region = list(isd.iter_regions())[0]

    span = region[0][0][0][0]

    fs: styles.LengthType = span.get_style(styles.StyleProperties.FontSize)

    self.assertAlmostEqual(fs.value, 25 / doc.get_cell_resolution().rows)

    self.assertEqual(fs.units, styles.LengthType.Units.rh)
예제 #7
0
  def handle_starttag(self, tag, attrs):

    span = model.Span(self.parent.get_doc())
    self.parent.push_child(span)
    self.parent = span

    if tag.lower() in ("b", "bold"):
      span.set_style(styles.StyleProperties.FontWeight, styles.FontWeightType.bold)
    elif tag.lower() in ("i", "italic"):
      span.set_style(styles.StyleProperties.FontStyle, styles.FontStyleType.italic)
    elif tag.lower() in ("u", "underline"):
      span.set_style(styles.StyleProperties.TextDecoration, styles.TextDecorationType(underline=True))
    elif tag.lower() == "font":
      for attr in attrs:
        if attr[0] == "color":
          color = parse_color(attr[1])
          break
      else:
        LOGGER.warning("Font tag without a color attribute at line %s", self.line_num)
        return

      if color is None:
        LOGGER.warning("Unknown color %s at line %s", attrs["color"], self.line_num)
        return

      span.set_style(styles.StyleProperties.Color, color)

    else:
      LOGGER.warning("Unknown tag %s at line %s", tag, self.line_num)
      return
예제 #8
0
    def make_anonymous_span(doc, text):

        s = model.Span(doc)
        t = model.Text(doc, text)
        s.push_child(t)

        return s
예제 #9
0
  def handle_data(self, data):
    lines = data.split("\n")

    for i, line in enumerate(lines):
      if i > 0:
        self.parent.push_child(model.Br(self.parent.get_doc()))
      span = model.Span(self.parent.get_doc())
      span.push_child(model.Text(self.parent.get_doc(), line))
      self.parent.push_child(span)
예제 #10
0
    def test_push_child(self):

        p = model.P()

        p.push_child(model.Br())

        p.push_child(model.Span())

        p.push_child(model.Ruby())

        with self.assertRaises(TypeError):
            p.push_child(model.Text())
예제 #11
0
    def make_anonymous_span(document, model_element, span_text):
        '''Creates an anonymous span in the element `model_element` from the text contained in `span_text`
    '''
        if isinstance(model_element, model.Span):
            return model.Text(document, span_text)

        s = model.Span(document)
        s.set_space(model_element.get_space())
        s.set_lang(model_element.get_lang())

        s.push_child(model.Text(document, span_text))

        return s
예제 #12
0
  def test_text_decoration_inheritance(self):
    doc = model.ContentDocument()

    r1 = model.Region("r1", doc)
    r1.set_style(
      styles.StyleProperties.TextDecoration,
      styles.TextDecorationType(
        line_through=False,
        underline=True,
        overline=True
      )
    )
    doc.put_region(r1)

    b = model.Body(doc)
    b.set_style(
      styles.StyleProperties.TextDecoration,
      styles.TextDecorationType(
        overline=False
      )
    )
    b.set_region(r1)
    doc.set_body(b)

    div1 = model.Div(doc)
    b.push_child(div1)

    p1 = model.P(doc)
    div1.push_child(p1)

    span1 = model.Span(doc)
    p1.push_child(span1)

    t1 = model.Text(doc, "hello")
    span1.push_child(t1)

    isd = ISD.from_model(doc, 0)

    region = list(isd.iter_regions())[0]

    span = region[0][0][0][0]

    self.assertEqual(
      span.get_style(styles.StyleProperties.TextDecoration),
      styles.TextDecorationType(
        line_through=False,
        underline=True,
        overline=False
      )
    )
예제 #13
0
    def process(context, inherited_space, inherited_lang, ttml_element):

        element = model.Span(context.doc)

        # process attributes

        element.set_space(
            XMLSpaceAttribute.extract(ttml_element) or inherited_space)

        element.set_lang(
            XMLLangAttribute.extract(ttml_element) or inherited_lang)

        ContentElement.process_region_property(context, ttml_element, element)

        ContentElement.process_style_properties(context, ttml_element, element)

        # process head text node

        if ttml_element.text is not None:
            element.push_child(model.Text(context.doc, ttml_element.text))

        # process children elements

        for ttml_child_element in ttml_element:

            child_element = ContentElement.process(context,
                                                   element.get_space(),
                                                   element.get_lang(),
                                                   ttml_child_element)

            if child_element is not None:

                if not isinstance(child_element, (model.Span, model.Br)):

                    LOGGER.error(
                        "Children of p must be span or br or text instances")

                else:

                    element.push_child(child_element)

            # process tail text node

            if ttml_child_element.tail:
                element.push_child(
                    model.Text(context.doc, ttml_child_element.tail))

        return element
예제 #14
0
파일: tf.py 프로젝트: sandflow/ttconv
  def start_span(self):
    if self.span is None:
      self.span = model.Span(self.parent.get_doc())

      self.span.set_style(styles.StyleProperties.BackgroundColor, self.get_bg_color())

      self.span.set_style(styles.StyleProperties.Color, self.get_fg_color())

      if self.get_underline():
        self.span.set_style(
          styles.StyleProperties.TextDecoration,
          styles.TextDecorationType(underline=True)
        )

      if self.get_italic():
        self.span.set_style(
          styles.StyleProperties.FontStyle,
          styles.FontStyleType.italic
        )
예제 #15
0
    def test_body_only(self):

        doc = model.ContentDocument()
        body = model.Body(doc)
        div = model.Div(doc)
        p = model.P(doc)
        span = model.Span(doc)
        text = model.Text(doc)
        text.set_text("asdf")

        span.push_child(text)
        p.push_child(span)
        div.push_child(p)
        body.push_child(div)
        doc.set_body(body)

        # write the document out to a file
        imsc_writer.from_model(doc).write('build/BodyElement.out.ttml',
                                          encoding='utf-8',
                                          xml_declaration=True)
예제 #16
0
    def test_tts_writing_no_extent_when_body_has_no_extents(self):

        doc = model.ContentDocument()
        body = model.Body(doc)
        div = model.Div(doc)
        p = model.P(doc)
        span = model.Span(doc)
        text = model.Text(doc)
        text.set_text("asdf")

        span.push_child(text)
        p.push_child(span)
        div.push_child(p)
        body.push_child(div)
        doc.set_body(body)

        tree_from_model = imsc_writer.from_model(doc)

        extent = tree_from_model.getroot().attrib.get(
            f"{{{imsc_styles.StyleProperties.Extent.ns}}}{imsc_styles.StyleProperties.Extent.local_name}"
        )

        self.assertEqual(extent, None)
예제 #17
0
    def process_tti_block(self, tti_block: bytes):
        """Processes a single TTI block
    """
        if tti_block is None:
            raise ValueError("tti_block should not be None")

        tti = _TTIBlock._make(struct.unpack('<BHBBBBBBBBBBBBB112s', tti_block))

        LOGGER.debug("Subtitle SN: %s", tti.SN)
        LOGGER.debug("  EBN: %s", tti.EBN)
        LOGGER.debug("  CS: %s", tti.CS)
        LOGGER.debug("  SGN: %s", tti.SGN)
        LOGGER.debug("  JC: %s", tti.JC)
        LOGGER.debug("  VP: %s", tti.VP)

        if 0xEF < tti.EBN < 0xFF:
            # skip user data and reserved blocks
            return

        if not self.is_in_extension:
            self.tti_tf = b''

        self.tti_tf += tti.TF.strip(b'\x8f')

        is_double_height_characters = tf.has_double_height_char(self.tti_tf)

        # continue accumulating if we have an extension block

        if tti.EBN != 0xFF:
            self.is_in_extension = True
            return

        self.is_in_extension = False

        # apply program offset

        try:
            tci = SmpteTimeCode(tti.TCIh, tti.TCIm, tti.TCIs, tti.TCIf,
                                self.get_fps())
            tco = SmpteTimeCode(tti.TCOh, tti.TCOm, tti.TCOs, tti.TCOf,
                                self.get_fps())
        except ValueError:
            LOGGER.error("Invalid TTI timecode")
            return

        begin_time = tci.to_temporal_offset() - self.start_offset
        if begin_time < 0:
            LOGGER.debug(
                "Skipping subtitle because TCI is less than start time")
            return
        LOGGER.debug("  Time in: %s", tci)

        end_time = tco.to_temporal_offset() - self.start_offset
        if end_time < begin_time:
            LOGGER.error("Subtitle TCO is less than TCI")
            return
        LOGGER.debug("  Time out: %s", tco)

        # create a new subtitle if SN changes and we are not in cumulative mode

        if tti.SN is not self.last_sn and tti.CS in (0x00, 0x01):

            self.last_sn = tti.SN

            # find the div to which the subtitle belongs, based on SGN

            div_element = self.sgn_to_div_map.get(tti.SGN)

            # create the div if it does not exist

            if div_element is None:
                div_element = model.Div(self.doc)
                self.body.push_child(div_element)
                self.sgn_to_div_map[tti.SGN] = div_element

            # create the p that will hold the subtitle

            self.cur_p_element = model.P(self.doc)

            if tti.JC == 0x01:
                self.cur_p_element.set_style(styles.StyleProperties.TextAlign,
                                             styles.TextAlignType.start)
            elif tti.JC == 0x03:
                self.cur_p_element.set_style(styles.StyleProperties.TextAlign,
                                             styles.TextAlignType.end)
            else:
                self.cur_p_element.set_style(styles.StyleProperties.TextAlign,
                                             styles.TextAlignType.center)

            self.cur_p_element.set_style(
                styles.StyleProperties.LineHeight,
                styles.LengthType(DEFAULT_LINE_HEIGHT_PCT,
                                  styles.LengthType.Units.pct))

            if self.is_teletext() and not is_double_height_characters:
                font_size = DEFAULT_SINGLE_HEIGHT_FONT_SIZE_PCT
            else:
                font_size = DEFAULT_DOUBLE_HEIGHT_FONT_SIZE_PCT

            self.cur_p_element.set_style(
                styles.StyleProperties.FontSize,
                styles.LengthType(font_size, styles.LengthType.Units.pct))

            safe_area_height = round(100 -
                                     DEFAULT_VERTICAL_SAFE_MARGIN_PCT * 2)
            safe_area_width = round(100 -
                                    DEFAULT_HORIZONTAL_SAFE_MARGIN_PCT * 2)

            # assume that VP < max number of rows/2 means bottom-aligned and otherwise top-aligned
            # probably should offer an option to override this

            if tti.VP < self.get_max_row_count() // 2:
                # top-aligned large region

                r_y = DEFAULT_VERTICAL_SAFE_MARGIN_PCT + (
                    (tti.VP - 1) / self.get_max_row_count()) * safe_area_height
                r_height = 100 - DEFAULT_VERTICAL_SAFE_MARGIN_PCT - r_y

                region = _get_region_from_model(
                    self.doc, round(DEFAULT_HORIZONTAL_SAFE_MARGIN_PCT), r_y,
                    safe_area_width, r_height, styles.DisplayAlignType.before)

            else:

                line_count = tf.line_count(self.tti_tf,
                                           is_double_height_characters)
                vp = tti.VP
                line_height = 2 if is_double_height_characters else 1

                r_y = DEFAULT_VERTICAL_SAFE_MARGIN_PCT
                r_height = ((vp + line_count * line_height - 1) /
                            self.get_max_row_count()) * safe_area_height

                region = _get_region_from_model(
                    self.doc, round(DEFAULT_HORIZONTAL_SAFE_MARGIN_PCT), r_y,
                    safe_area_width, r_height, styles.DisplayAlignType.after)

            self.cur_p_element.set_region(region)

            div_element.push_child(self.cur_p_element)

        if tti.CS in (0x01, 0x02, 0x03):
            # create a nested span if we are in cumulative mode
            sub_element = model.Span(self.doc)
            self.cur_p_element.push_child(sub_element)
        else:
            sub_element = self.cur_p_element

        sub_element.set_begin(begin_time)
        sub_element.set_end(end_time)

        LOGGER.debug("  TF: %s", self.tti_tf)

        tf.to_model(sub_element, self.is_teletext(), self.get_cct(),
                    self.tti_tf)

        if tti.CS in (0x01, 0x02):
            sub_element.push_child(model.Br(self.doc))
예제 #18
0
  def setUp(self):
    self.doc = model.ContentDocument()

    a1 = model.DiscreteAnimationStep(
      style_property=styles.StyleProperties.Color,
      begin=None,
      end=None,
      value=styles.NamedColors.red.value
    )

    a2 = model.DiscreteAnimationStep(
      style_property=styles.StyleProperties.Color,
      begin=Fraction(1),
      end=None,
      value=styles.NamedColors.green.value
    )

    a3 = model.DiscreteAnimationStep(
      style_property=styles.StyleProperties.Color,
      begin=Fraction(2),
      end=None,
      value=styles.NamedColors.blue.value
    )

    r1 = model.Region("r1", self.doc)
    self.doc.put_region(r1)

    # r2: sig times = {2, 9}

    r2 = model.Region("r2", self.doc)
    r2.set_begin(Fraction(2))
    r2.set_end(Fraction(9))
    r2.add_animation_step(a1)
    self.doc.put_region(r2)

    # b: sig times = {1, 10}

    b = model.Body(self.doc)
    b.set_begin(Fraction(1))
    b.set_end(Fraction(10))
    self.doc.set_body(b)

    # div1: offset = 1, sig times = {2, 4}

    div1 = model.Div(self.doc)
    div1.add_animation_step(a2)
    div1.set_begin(Fraction(3))
    div1.set_region(r1)
    b.push_child(div1)

    # div2: offset = 1, sig times = {10}

    div2 = model.Div(self.doc)
    div2.set_end(Fraction(12))
    div2.set_region(r2)
    b.push_child(div2)

    # p1: offset = 1, sig times = {}

    p1 = model.P(self.doc)
    div2.push_child(p1)

    # span1: offset = 1, sig times = {3}
    span1 = model.Span(self.doc)
    span1.add_animation_step(a3)
    p1.push_child(span1)

    t1 = model.Text(self.doc, "hello")
    span1.push_child(t1)
예제 #19
0
    def test_push_child(self):

        t = model.Text()

        with self.assertRaises(RuntimeError):
            t.push_child(model.Span())