def extract(cls, context: StyleParsingContext, xml_attrib: str): if xml_attrib == "auto": return styles.ExtentType( height=styles.LengthType(1, styles.LengthType.Units.rh), width=styles.LengthType(1, styles.LengthType.Units.rw)) s = xml_attrib.split(" ") if len(s) != 2: raise ValueError("Bad tts:extent syntax") return styles.ExtentType( height=StyleProperties.ttml_length_to_model(context, s[1]), width=StyleProperties.ttml_length_to_model(context, s[0]))
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 _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 test_style_property_extent_has_px(self): prop = styles.ExtentType( styles.LengthType(1, styles.LengthType.units.px), styles.LengthType(1, styles.LengthType.units.em)) self.assertEqual(imsc_styles.StyleProperties.Extent.has_px(prop), True) prop = styles.ExtentType( styles.LengthType(1, styles.LengthType.units.px), styles.LengthType(1, styles.LengthType.units.px)) self.assertEqual(imsc_styles.StyleProperties.Extent.has_px(prop), True) prop = styles.ExtentType( styles.LengthType(1, styles.LengthType.units.em), styles.LengthType(1, styles.LengthType.units.px)) self.assertEqual(imsc_styles.StyleProperties.Extent.has_px(prop), True) prop = styles.ExtentType( styles.LengthType(1, styles.LengthType.units.em), styles.LengthType(1, styles.LengthType.units.em)) self.assertEqual(imsc_styles.StyleProperties.Extent.has_px(prop), False)
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 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