def test_copy_to(self): src = model.ContentDocument() src.set_display_aspect_ratio(Fraction(16, 9)) src.set_active_area(model.ActiveAreaType(0.1, 0.15, 0.8, 0.7)) src.set_px_resolution(model.PixelResolutionType(height=480, width=640)) src.set_lang("fr") src.set_cell_resolution(model.CellResolutionType(rows=10, columns=20)) src.put_initial_value(styles.StyleProperties.Color, styles.ColorType((12, 23, 43, 56))) dest = model.ContentDocument() src.copy_to(dest) self.assertEqual(dest.get_display_aspect_ratio(), src.get_display_aspect_ratio()) self.assertEqual(dest.get_active_area(), src.get_active_area()) self.assertEqual(dest.get_px_resolution(), src.get_px_resolution()) self.assertEqual(dest.get_lang(), src.get_lang()) self.assertEqual(dest.get_cell_resolution(), src.get_cell_resolution()) self.assertSequenceEqual(list(dest.iter_initial_values()), list(src.iter_initial_values()))
def extract(ttml_element) -> model.ActiveAreaType: aa = ttml_element.attrib.get(ActiveAreaAttribute.qn) if aa is not None: s = aa.split(" ") if len(s) != 4: LOGGER.error("Syntax error in ittp:activeArea on <tt>") return None (left_offset, left_offset_units) = utils.parse_length(s[0]) (top_offset, top_offset_units) = utils.parse_length(s[1]) (w, w_units) = utils.parse_length(s[2]) (h, h_units) = utils.parse_length(s[3]) if w_units != "%" or h_units != "%" or left_offset_units != "%" or top_offset_units != "%": LOGGER.error("ittp:activeArea on <tt> must use % units") return None return model.ActiveAreaType(left_offset / 100, top_offset / 100, w / 100, h / 100) return None
def test_active_area(self): aa = model.ActiveAreaType(0.1, 0.15, 0.8, 0.7) self.assertEqual(aa.left_offset, 0.1) self.assertEqual(aa.top_offset, 0.15) self.assertEqual(aa.width, 0.8) self.assertEqual(aa.height, 0.7) with self.assertRaises(ValueError): model.ActiveAreaType(-0.1, 0.15, 0.8, 0.7) with self.assertRaises(ValueError): model.ActiveAreaType(0.1, 0.15, -0.8, 0.7)
def test_active_area_default(self): aa = model.ActiveAreaType() self.assertEqual(aa.left_offset, 0) self.assertEqual(aa.top_offset, 0) self.assertEqual(aa.height, 1) self.assertEqual(aa.width, 1)
def test_document_active_area(self): d = model.ContentDocument() aa = model.ActiveAreaType(0.1, 0.15, 0.8, 0.7) d.set_active_area(aa) self.assertEqual(d.get_active_area(), aa) d.set_active_area(None) self.assertIsNone(d.get_active_area())
def __init__(self, gsi_block: bytes, disable_fill_line_gap: bool = False, disable_line_padding: bool = False, start_tc: typing.Optional[str] = None, font_stack: typing.Tuple[typing.Union[ str, styles.GenericFontFamilyType]] = None, max_row_count: typing.Optional[typing.Union[int, str]] = None): self.gsi = _GSIBlock._make( struct.unpack( '3s8sc2s2s32s32s32s32s32s32s16s6s6s2s5s5s3s2s2s1s8s8s1s1s3s32s32s32s75x576s', gsi_block)) self.doc = model.ContentDocument() self.doc.set_cell_resolution( model.CellResolutionType( columns=round(100 * DEFAULT_TELETEXT_COLS / (100 - 2 * DEFAULT_HORIZONTAL_SAFE_MARGIN_PCT)), rows=round(100 * DEFAULT_TELETEXT_ROWS / (100 - 2 * DEFAULT_VERTICAL_SAFE_MARGIN_PCT)))) self.doc.set_active_area( model.ActiveAreaType( left_offset=DEFAULT_HORIZONTAL_SAFE_MARGIN_PCT / 100, top_offset=DEFAULT_VERTICAL_SAFE_MARGIN_PCT / 100, width=1 - 2 * DEFAULT_HORIZONTAL_SAFE_MARGIN_PCT / 100, height=1 - 2 * DEFAULT_VERTICAL_SAFE_MARGIN_PCT / 100)) self.body = model.Body(self.doc) if not disable_fill_line_gap: self.body.set_style(styles.StyleProperties.FillLineGap, True) if not disable_line_padding: self.body.set_style( styles.StyleProperties.LinePadding, styles.LengthType(LINE_PADDING_LENGTH_C, styles.LengthType.Units.c)) if font_stack is not None: self.body.set_style(styles.StyleProperties.FontFamily, font_stack) else: self.body.set_style(styles.StyleProperties.FontFamily, DEFAULT_FONT_STACK) self.doc.set_body(self.body) self.sgn_to_div_map = {} self.last_sn = None self.is_in_extension = False self.tti_tf = None self.fps = _DFC_FRACTION_MAP.get(self.gsi.DFC) if self.fps is None: LOGGER.error("Unknown GSI DFC value %s, defaulting to 25 fps", self.gsi.DFC) self.fps = Fraction(25) else: LOGGER.debug("GSI DFC: %s", self.gsi.DFC) self.cct = self.gsi.CCT LOGGER.debug("GSI CCT: %s", self.gsi.CCT) try: self.tti_count = int(self.gsi.TNB) LOGGER.debug("GSI TNB: %s", self.gsi.TNB) except ValueError: LOGGER.error("Invalid TNB field value: %s", self.gsi.TNB) self.tti_count = sys.maxsize self.language = _LC_BCP47_MAP.get(self.gsi.LC) if self.language is None: LOGGER.warning( "Unknown LC value: %s, defaulting to 'unspecified''", self.gsi.LC) self.language = "" else: LOGGER.debug("GSI LC: %s", self.gsi.LC) self.doc.set_lang(self.language) if start_tc is None: self.start_offset = 0 elif start_tc == "TCP": try: self.start_offset = SmpteTimeCode( int(self.gsi.TCP[0:2]), int(self.gsi.TCP[2:4]), int(self.gsi.TCP[4:6]), int(self.gsi.TCP[6:8]), self.get_fps()).to_temporal_offset() LOGGER.debug("GSI TCP: %s", self.gsi.TCP) except ValueError: LOGGER.error("Invalid TCP value: %s", self.gsi.tcp) self.start_offset = 0 else: try: self.start_offset = SmpteTimeCode.parse( start_tc, self.get_fps()).to_temporal_offset() except ValueError: LOGGER.error("Invalid start_tc value") raise if max_row_count is None or self.is_teletext(): self.max_row_count = DEFAULT_TELETEXT_ROWS elif isinstance(max_row_count, str) and max_row_count == "MNR": try: self.max_row_count = int(self.gsi.MNR) LOGGER.debug("GSI MNR: %s", self.gsi.MNR) except ValueError: LOGGER.error("Invalid MNR value: %s", self.gsi.MNR) self.start_offset = DEFAULT_TELETEXT_ROWS else: self.max_row_count = max_row_count # p_element for use across cumulative subtitles self.cur_p_element = None