def test_copy_to(self): src = model.Region("hello") src.set_begin(Fraction(1, 2)) src.set_end(Fraction(1, 3)) src.set_lang("fr") src.set_space(model.WhiteSpaceHandling.PRESERVE) src.add_animation_step( model.DiscreteAnimationStep(styles.StyleProperties.Color, 0, 1, styles.NamedColors.aqua.value)) src.set_style(styles.StyleProperties.Color, styles.NamedColors.green.value) dest = model.Region("hello") src.copy_to(dest) self.assertEqual(dest.get_begin(), src.get_begin()) self.assertEqual(dest.get_end(), src.get_end()) self.assertEqual(dest.get_lang(), src.get_lang()) self.assertEqual(dest.get_space(), src.get_space()) self.assertSequenceEqual(list(dest.iter_animation_steps()), list(src.iter_animation_steps())) self.assertSequenceEqual(list(dest.iter_styles()), list(src.iter_styles()))
def test_set_region(self): r1 = model.Region("hello") r2 = model.Region("blah") with self.assertRaises(RuntimeError): r1.set_region(r2)
def iter_region(self): d = model.Document() r1 = model.Region("hello1", d) r2 = model.Region("hello2", d) d.put_region(r1) d.put_region(r2) self.assertCountEqual(d.iter_regions(), [r1, r2])
def add_dup_region(self): d = model.Document() r1 = model.Region("hello", d) r2 = model.Region("hello", d) d.put_region(r1) d.put_region(r2) self.assertIs(d.get_region(r2.get_id()), r2)
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')
def add_detached_region(self): d = model.Document() r = model.Region("hello") with self.assertRaises(ValueError): d.put_region(r)
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)
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)
def test_compute_padding(self): doc = model.ContentDocument() r1 = model.Region("r1", doc) r1.set_style(styles.StyleProperties.ShowBackground, styles.ShowBackgroundType.always) r1.set_style( styles.StyleProperties.Extent, styles.ExtentType( width=styles.LengthType(50, styles.LengthType.Units.pct), height=styles.LengthType(25, styles.LengthType.Units.pct) ) ) r1.set_style( styles.StyleProperties.Padding, styles.PaddingType( before=styles.LengthType(5, styles.LengthType.Units.pct), after=styles.LengthType(10, styles.LengthType.Units.pct), start=styles.LengthType(15, styles.LengthType.Units.pct), end=styles.LengthType(20, styles.LengthType.Units.pct) ) ) doc.put_region(r1) isd = ISD.from_model(doc, 0) region = list(isd.iter_regions())[0] padding: styles.PaddingType = region.get_style(styles.StyleProperties.Padding) self.assertAlmostEqual(padding.before.value, 25 * 0.05) self.assertAlmostEqual(padding.after.value, 25 * 0.10) self.assertAlmostEqual(padding.start.value, 50 * 0.15) self.assertAlmostEqual(padding.end.value, 50 * 0.2)
def test_compute_extent_em(self): doc = model.ContentDocument() r1 = model.Region("r1", doc) r1.set_style(styles.StyleProperties.ShowBackground, styles.ShowBackgroundType.always) r1.set_style( styles.StyleProperties.Extent, styles.ExtentType( width=styles.LengthType(20, styles.LengthType.Units.em), height=styles.LengthType(3, styles.LengthType.Units.em) ) ) doc.put_region(r1) isd = ISD.from_model(doc, 0) region = list(isd.iter_regions())[0] extent: styles.ExtentType = region.get_style(styles.StyleProperties.Extent) self.assertAlmostEqual(extent.width.value, 100*20/doc.get_cell_resolution().rows) self.assertEqual(extent.width.units, styles.LengthType.Units.rh) self.assertAlmostEqual(extent.height.value, 100*3/doc.get_cell_resolution().rows) self.assertEqual(extent.height.units, styles.LengthType.Units.rh)
def test_compute_extent_pct(self): doc = model.ContentDocument() r1 = model.Region("r1", doc) r1.set_style(styles.StyleProperties.ShowBackground, styles.ShowBackgroundType.always) r1.set_style( styles.StyleProperties.Extent, styles.ExtentType( width=styles.LengthType(50, styles.LengthType.Units.pct), height=styles.LengthType(25, styles.LengthType.Units.pct) ) ) doc.put_region(r1) isd = ISD.from_model(doc, 0) region = list(isd.iter_regions())[0] extent: styles.ExtentType = region.get_style(styles.StyleProperties.Extent) self.assertEqual(extent.height.value, 25) self.assertEqual(extent.height.units, styles.LengthType.Units.rh) self.assertEqual(extent.width.value, 50) self.assertEqual(extent.width.units, styles.LengthType.Units.rw)
def add_region(self): d = model.Document() r = model.Region("hello", d) d.put_region(r) self.assertIs(d.get_region(r.get_id()), r)
def _get_region_from_model(doc: model.ContentDocument, x_origin: Number, y_origin: Number, width: Number, height: Number, display_align: styles.DisplayAlignType): """Returns a matching region from `doc` or creates one """ found_region = None regions = list(doc.iter_regions()) for r in regions: r_origin: styles.CoordinateType = r.get_style( styles.StyleProperties.Origin) assert r_origin is not None assert r_origin.x.units is styles.LengthType.Units.pct assert r_origin.y.units is styles.LengthType.Units.pct if r_origin.x.value != x_origin or r_origin.y.value != y_origin: continue r_extent: styles.ExtentType = r.get_style( styles.StyleProperties.Extent) assert r_extent is not None assert r_extent.height.units is styles.LengthType.Units.pct assert r_extent.width.units is styles.LengthType.Units.pct if r_extent.height.value != height or r_extent.width.value != width: continue r_display_align: styles.DisplayAlignType = r.get_style( styles.StyleProperties.DisplayAlign) assert r_display_align is not None if r_display_align != display_align: continue found_region = r break if found_region is None: found_region = model.Region(f"r{len(regions)}", doc) found_region.set_style( styles.StyleProperties.Extent, styles.ExtentType( height=styles.LengthType(height, styles.LengthType.Units.pct), width=styles.LengthType(width, styles.LengthType.Units.pct), )) found_region.set_style( styles.StyleProperties.Origin, styles.CoordinateType( x=styles.LengthType(x_origin, styles.LengthType.Units.pct), y=styles.LengthType(y_origin, styles.LengthType.Units.pct))) found_region.set_style(styles.StyleProperties.DisplayAlign, display_align) doc.put_region(found_region) return found_region
def from_xml(cls, parent_ctx: TTMLElement.ParsingContext, xml_elem) -> typing.Optional[RegionElement.ParsingContext]: rid = imsc_attr.XMLIDAttribute.extract(xml_elem) if rid is None: LOGGER.error("All regions must have an id") return None region_ctx = RegionElement.ParsingContext( RegionElement, parent_ctx, model.Region(rid, parent_ctx.doc)) region_ctx.process(parent_ctx, xml_elem) return region_ctx
def test_compute_extent_em(self): doc = model.ContentDocument() r1 = model.Region("r1", doc) r1.set_style(styles.StyleProperties.ShowBackground, styles.ShowBackgroundType.always) with self.assertRaises(ValueError) as _context: r1.set_style( styles.StyleProperties.Extent, styles.ExtentType( width=styles.LengthType(20, styles.LengthType.Units.em), height=styles.LengthType(3, styles.LengthType.Units.em)))
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 ) )
def remove_region(self): d = model.Document() r = model.Region("hello", d) d.put_region(r) self.assertIs(d.get_region(r.get_id()), r) d.remove_region(r.get_id()) self.assertFalse(d.has_region(r.get_id())) self.assertIsNone(d.get_region(r.get_id()))
def process(context, inherited_space, inherited_lang, ttml_element): rid = XMLIDAttribute.extract(ttml_element) if rid is None: LOGGER.error("All regions must have an id") return None r = model.Region(rid, context.doc) # process attributes r.set_space(XMLSpaceAttribute.extract(ttml_element) or inherited_space) r.set_lang(XMLLangAttribute.extract(ttml_element) or inherited_lang) ContentElement.process_style_properties(context, ttml_element, r) return r
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)
def test_set_id(self): r = model.Region("hello") with self.assertRaises(RuntimeError): r.set_id("blah")
def to_model(data_file: typing.IO, _config = None, progress_callback=lambda _: None): """Converts an SRT document to the data model""" doc = model.ContentDocument() region = model.Region(_DEFAULT_REGION_ID, doc) region.set_style( styles.StyleProperties.Origin, styles.CoordinateType( x=styles.LengthType(5, styles.LengthType.Units.pct), y=styles.LengthType(5, styles.LengthType.Units.pct) ) ) region.set_style( styles.StyleProperties.Extent, styles.ExtentType( height=styles.LengthType(90, styles.LengthType.Units.pct), width=styles.LengthType(90, styles.LengthType.Units.pct) ) ) region.set_style( styles.StyleProperties.DisplayAlign, styles.DisplayAlignType.after ) region.set_style( styles.StyleProperties.TextAlign, styles.TextAlignType.center ) region.set_style( styles.StyleProperties.LineHeight, _DEFAULT_LINE_HEIGHT ) region.set_style( styles.StyleProperties.FontFamily, _DEFAULT_FONT_STACK ) region.set_style( styles.StyleProperties.FontSize, _DEFAULT_FONT_SIZE ) region.set_style( styles.StyleProperties.Color, _DEFAULT_TEXT_COLOR ) region.set_style( styles.StyleProperties.TextOutline, styles.TextOutlineType( _DEFAULT_OUTLINE_THICKNESS, _DEFAULT_OUTLINE_COLOR ) ) doc.put_region(region) body = model.Body(doc) body.set_region(region) doc.set_body(body) div = model.Div(doc) body.push_child(div) lines : str = data_file.readlines() state = _State.COUNTER current_p = None for line_index, line in enumerate(_none_terminated(lines)): if state is _State.COUNTER: if line is None: break if _EMPTY_RE.fullmatch(line): continue if _COUNTER_RE.search(line) is None: LOGGER.fatal("Missing subtitle counter at line %s", line_index) return None progress_callback(line_index/len(lines)) state = _State.TC continue if state is _State.TC: if line is None: break m = _TIMECODE_RE.search(line) if m is None: LOGGER.fatal("Missing timecode at line %s", line_index) return None current_p = model.P(doc) current_p.set_begin( int(m.group('begin_h')) * 3600 + int(m.group('begin_m')) * 60 + int(m.group('begin_s')) + int(m.group('begin_ms')) / 1000 ) current_p.set_end( int(m.group('end_h')) * 3600 + int(m.group('end_m')) * 60 + int(m.group('end_s')) + int(m.group('end_ms')) / 1000 ) state = _State.TEXT continue if state in (_State.TEXT, _State.TEXT_MORE): if line is None or _EMPTY_RE.fullmatch(line): subtitle_text = subtitle_text.strip('\r\n')\ .replace(r"\n\r", "\n")\ .replace(r"{bold}", r"<bold>")\ .replace(r"{/bold}", r"</bold>")\ .replace(r"{italic}", r"<italic>")\ .replace(r"{/italic}", r"</italic>")\ .replace(r"{underline}", r"<underline>")\ .replace(r"{/underline}", r"</underline>") parser = _TextParser(current_p, line_index) parser.feed(subtitle_text) parser.close() state = _State.COUNTER continue if state is _State.TEXT: div.push_child(current_p) subtitle_text = "" if state is _State.TEXT_MORE: current_p.push_child(model.Br(current_p.get_doc())) subtitle_text += line state = _State.TEXT_MORE continue return doc
def test_push_child(self): r = model.Region("hello") with self.assertRaises(RuntimeError): r.push_child(model.P())