Exemple #1
0
def check_temporary_storage(config):
    if config["directories"][
            "temporary_storage"] == "" and sys.platform == "win32":
        log.warning(
            "You may be using Windows platform and have not specified the path of"
            " `temporary_storage`, which may cause OSError. So it is recommended"
            " to specify the `temporary_storage` in the config file (.yml)")
Exemple #2
0
    def __init__(self, text, **kwargs):
        self.full2short(kwargs)
        digest_config(self, kwargs)
        if self.size:
            log.warning(
                "`self.size` has been deprecated and will "
                "be removed in future.", )
            self.font_size = self.size
        if self.lsh == -1:
            self.lsh = self.font_size + self.font_size * DEFAULT_LINE_SPACING_SCALE
        else:
            self.lsh = self.font_size + self.font_size * self.lsh
        text_without_tabs = text
        if text.find('\t') != -1:
            text_without_tabs = text.replace('\t', ' ' * self.tab_width)
        self.text = text_without_tabs
        file_name = self.text2svg()
        PangoUtils.remove_last_M(file_name)
        self.remove_empty_path(file_name)
        SVGMobject.__init__(self, file_name, **kwargs)
        self.text = text
        if self.disable_ligatures:
            self.apply_space_chars()
        if self.t2c:
            self.set_color_by_t2c()
        if self.gradient:
            self.set_color_by_gradient(*self.gradient)
        if self.t2g:
            self.set_color_by_t2g()

        # anti-aliasing
        if self.height is None:
            self.scale(TEXT_MOB_SCALE_FACTOR)
Exemple #3
0
    def on_key_press(self, symbol: int, modifiers: int) -> None:
        try:
            char = chr(symbol)
        except OverflowError:
            log.warning("The value of the pressed key is too large.")
            return

        event_data = {"symbol": symbol, "modifiers": modifiers}
        propagate_event = EVENT_DISPATCHER.dispatch(EventType.KeyPressEvent,
                                                    **event_data)
        if propagate_event is not None and propagate_event is False:
            return

        if char == RESET_FRAME_KEY:
            self.camera.frame.to_default_state()
        elif char == "z" and modifiers == COMMAND_MODIFIER:
            self.undo()
        elif char == "z" and modifiers == COMMAND_MODIFIER | SHIFT_MODIFIER:
            self.redo()
        # command + q
        elif char == QUIT_KEY and modifiers == COMMAND_MODIFIER:
            self.quit_interaction = True
        # Space or right arrow
        elif char == " " or symbol == ARROW_SYMBOLS[2]:
            self.hold_on_wait = False
Exemple #4
0
 def get_mobjects_from(self, svg: se.SVG) -> list[VMobject]:
     result = []
     for shape in svg.elements():
         if isinstance(shape, se.Group):
             continue
         elif isinstance(shape, se.Path):
             mob = self.path_to_mobject(shape)
         elif isinstance(shape, se.SimpleLine):
             mob = self.line_to_mobject(shape)
         elif isinstance(shape, se.Rect):
             mob = self.rect_to_mobject(shape)
         elif isinstance(shape, se.Circle):
             mob = self.circle_to_mobject(shape)
         elif isinstance(shape, se.Ellipse):
             mob = self.ellipse_to_mobject(shape)
         elif isinstance(shape, se.Polygon):
             mob = self.polygon_to_mobject(shape)
         elif isinstance(shape, se.Polyline):
             mob = self.polyline_to_mobject(shape)
         # elif isinstance(shape, se.Text):
         #     mob = self.text_to_mobject(shape)
         elif type(shape) == se.SVGElement:
             continue
         else:
             log.warning(f"Unsupported element type: {type(shape)}")
             continue
         if not mob.has_points():
             continue
         self.apply_style_to_mobject(mob, shape)
         if isinstance(shape, se.Transformable) and shape.apply:
             self.handle_transform(mob, shape.transform)
         result.append(mob)
     return result
Exemple #5
0
    def generate_mobject(self) -> None:
        super().generate_mobject()

        labels_count = len(self.labelled_spans)
        if not labels_count:
            for submob in self.submobjects:
                submob.label = -1
            return

        labelled_content = self.get_content(is_labelled=True)
        file_path = self.get_file_path_by_content(labelled_content)
        labelled_svg = SVGMobject(file_path)
        if len(self.submobjects) != len(labelled_svg.submobjects):
            log.warning("Cannot align submobjects of the labelled svg "
                        "to the original svg. Skip the labelling process.")
            for submob in self.submobjects:
                submob.label = -1
            return

        self.rearrange_submobjects_by_positions(labelled_svg)
        unrecognizable_colors = []
        for submob, labelled_svg_submob in zip(self.submobjects,
                                               labelled_svg.submobjects):
            color_int = self.hex_to_int(
                self.color_to_hex(labelled_svg_submob.get_fill_color()))
            if color_int > labels_count:
                unrecognizable_colors.append(color_int)
                color_int = 0
            submob.label = color_int - 1
        if unrecognizable_colors:
            log.warning(
                "Unrecognizable color labels detected (%s, etc). "
                "The result could be unexpected.",
                self.int_to_hex(unrecognizable_colors[0]))
Exemple #6
0
    def get_mobjects_from(self, element, style):
        result = []
        if not isinstance(element, minidom.Element):
            return result
        style = cascade_element_style(element, style)

        if element.tagName == 'defs':
            self.update_ref_to_element(element, style)
        elif element.tagName == 'style':
            pass  # TODO, handle style
        elif element.tagName in ['g', 'svg', 'symbol']:
            result += it.chain(*(self.get_mobjects_from(child, style)
                                 for child in element.childNodes))
        elif element.tagName == 'path':
            result.append(
                self.path_string_to_mobject(element.getAttribute('d'), style))
        elif element.tagName == 'use':
            result += self.use_to_mobjects(element, style)
        elif element.tagName == 'rect':
            result.append(self.rect_to_mobject(element, style))
        elif element.tagName == 'circle':
            result.append(self.circle_to_mobject(element, style))
        elif element.tagName == 'ellipse':
            result.append(self.ellipse_to_mobject(element, style))
        elif element.tagName in ['polygon', 'polyline']:
            result.append(self.polygon_to_mobject(element, style))
        else:
            log.warning(f"Unsupported element type: {element.tagName}")
            pass  # TODO
        result = [m.insert_n_curves(0) for m in result if m is not None]
        self.handle_transforms(element, VGroup(*result))
        if len(result) > 1 and not self.unpack_groups:
            result = [VGroup(*result)]

        return result
Exemple #7
0
    def get_content_prefix_and_suffix(self,
                                      is_labelled: bool) -> tuple[str, str]:
        global_attr_dict = {
            "foreground": self.base_color_hex,
            "font_family": self.font,
            "font_style": self.slant,
            "font_weight": self.weight,
            "font_size": str(self.font_size * 1024),
        }
        global_attr_dict.update(self.global_config)
        # `line_height` attribute is supported since Pango 1.50.
        pango_version = manimpango.pango_version()
        if tuple(map(int, pango_version.split("."))) < (1, 50):
            if self.lsh is not None:
                log.warning(
                    "Pango version %s found (< 1.50), "
                    "unable to set `line_height` attribute", pango_version)
        else:
            line_spacing_scale = self.lsh or DEFAULT_LINE_SPACING_SCALE
            global_attr_dict["line_height"] = str(
                ((line_spacing_scale) + 1) * 0.6)

        return self.get_cmd_str_pair(
            global_attr_dict,
            label_hex=self.int_to_hex(0) if is_labelled else None)
Exemple #8
0
    def update_local_attr(self, span: tuple[int, int], key: str,
                          value: typing.Any) -> None:
        if span[0] >= span[1]:
            log.warning(f"Span {span} doesn't match any part of the string")
            return

        if span in self.local_attrs.keys():
            _TextParser.update_attr_dict(self.local_attrs[span], key, value)
            return

        span_triplets = []
        for sp, attr_dict in self.local_attrs.items():
            if sp[1] <= span[0] or span[1] <= sp[0]:
                continue
            span_to_become = (max(sp[0], span[0]), min(sp[1], span[1]))
            spans_to_add = []
            if sp[0] < span[0]:
                spans_to_add.append((sp[0], span[0]))
            if span[1] < sp[1]:
                spans_to_add.append((span[1], sp[1]))
            span_triplets.append((sp, span_to_become, spans_to_add))
        for span_to_remove, span_to_become, spans_to_add in span_triplets:
            attr_dict = self.local_attrs.pop(span_to_remove)
            for span_to_add in spans_to_add:
                self.local_attrs[span_to_add] = attr_dict.copy()
            self.local_attrs[span_to_become] = attr_dict
            _TextParser.update_attr_dict(self.local_attrs[span_to_become], key,
                                         value)
Exemple #9
0
 def play(self, *args, **kwargs) -> None:
     if len(args) == 0:
         log.warning("Called Scene.play with no animations")
         return
     animations = self.anims_from_play_args(*args, **kwargs)
     self.begin_animations(animations)
     self.progress_through_animations(animations)
     self.finish_animations(animations)
Exemple #10
0
 def get_parts_by_text(self, word):
     if self.is_markup:
         log.warning("Slicing MarkupText via `get_parts_by_text`, "
                     "the result could be unexpected.")
     elif not self.apply_space_chars:
         log.warning(
             "Slicing Text via `get_parts_by_text` without applying spaces, "
             "the result could be unexpected.")
     return VGroup(*(self[i:j] for i, j in self.find_indexes(word)))
Exemple #11
0
 def play(self, *proto_animations, **animation_config) -> None:
     if len(proto_animations) == 0:
         log.warning("Called Scene.play with no animations")
         return
     animations = self.prepare_animations(proto_animations,
                                          animation_config)
     self.begin_animations(animations)
     self.progress_through_animations(animations)
     self.finish_animations(animations)
Exemple #12
0
 def use_to_mobjects(self, use_element, local_style):
     # Remove initial "#" character
     ref = use_element.getAttribute("xlink:href")[1:]
     if ref not in self.ref_to_element:
         log.warning(f"{ref} not recognized")
         return VGroup()
     def_element, def_style = self.ref_to_element[ref]
     style = local_style.copy()
     style.update(def_style)
     return self.get_mobjects_from(def_element, style)
Exemple #13
0
 def play(self, *args, **kwargs):
     if len(args) == 0:
         log.warning("Called Scene.play with no animations")
         return
     animations = self.anims_from_play_args(*args, **kwargs)
     self.lock_static_mobject_data(*animations)
     self.begin_animations(animations)
     self.progress_through_animations(animations)
     self.finish_animations(animations)
     self.unlock_mobject_data()
Exemple #14
0
    def combine_movie_files(self) -> None:
        kwargs = {
            "remove_non_integer_files": True,
            "extension": self.movie_file_extension,
        }
        if self.scene.start_at_animation_number is not None:
            kwargs["min_index"] = self.scene.start_at_animation_number
        if self.scene.end_at_animation_number is not None:
            kwargs["max_index"] = self.scene.end_at_animation_number
        else:
            kwargs["remove_indices_greater_than"] = self.scene.num_plays - 1
        partial_movie_files = get_sorted_integer_files(
            self.partial_movie_directory, **kwargs)
        if len(partial_movie_files) == 0:
            log.warning("No animations in this scene")
            return

        # Write a file partial_file_list.txt containing all
        # partial movie files
        file_list = os.path.join(self.partial_movie_directory,
                                 "partial_movie_file_list.txt")
        with open(file_list, 'w') as fp:
            for pf_path in partial_movie_files:
                if os.name == 'nt':
                    pf_path = pf_path.replace('\\', '/')
                fp.write(f"file \'{pf_path}\'\n")

        movie_file_path = self.get_movie_file_path()
        commands = [
            FFMPEG_BIN,
            '-y',  # overwrite output file if it exists
            '-f',
            'concat',
            '-safe',
            '0',
            '-i',
            file_list,
            '-loglevel',
            'error',
            '-c',
            'copy',
            movie_file_path
        ]
        if not self.includes_sound:
            commands.insert(-1, '-an')

        combine_process = sp.Popen(commands)
        combine_process.wait()
Exemple #15
0
    def break_up_by_scripts(self) -> None:
        # Match subscripts & superscripts.
        tex_string = self.tex_string
        whitespace_indices = self.whitespace_indices
        brace_indices_dict = self.brace_indices_dict
        script_spans = []
        for script_index in self.script_indices:
            script_char = tex_string[script_index]
            extended_begin = script_index
            while extended_begin - 1 in whitespace_indices:
                extended_begin -= 1
            script_begin = script_index + 1
            while script_begin in whitespace_indices:
                script_begin += 1
            if script_begin in brace_indices_dict.keys():
                script_end = brace_indices_dict[script_begin] + 1
            else:
                pattern = re.compile(r"[a-zA-Z0-9]|\\[a-zA-Z]+")
                match_obj = pattern.match(tex_string, pos=script_begin)
                if not match_obj:
                    script_name = {
                        "_": "subscript",
                        "^": "superscript"
                    }[script_char]
                    log.warning(
                        f"Unclear {script_name} detected while parsing. "
                        "Please use braces to clarify"
                    )
                    continue
                script_end = match_obj.end()
            tex_span = (script_begin, script_end)
            script_span = (extended_begin, script_end)
            script_spans.append(script_span)
            self.add_tex_span(tex_span)
            self.script_span_to_char_dict[script_span] = script_char
            self.script_span_to_tex_span_dict[script_span] = tex_span

        if not script_spans:
            return

        _, sorted_script_spans = zip(*sorted([
            (index, script_span)
            for script_span in script_spans
            for index in script_span
        ]))
        for span_0, span_1 in _get_neighbouring_pairs(sorted_script_spans):
            if span_0[1] == span_1[0]:
                self.neighbouring_script_span_pairs.append((span_0, span_1))
Exemple #16
0
    def on_key_press(self, symbol, modifiers):
        try:
            char = chr(symbol)
        except OverflowError:
            log.warning("The value of the pressed key is too large.")
            return

        event_data = {"symbol": symbol, "modifiers": modifiers}
        propagate_event = EVENT_DISPATCHER.dispatch(EventType.KeyPressEvent,
                                                    **event_data)
        if propagate_event is not None and propagate_event is False:
            return

        if char == "r":
            self.camera.frame.to_default_state()
        elif char == "q":
            self.quit_interaction = True
Exemple #17
0
    def get_full_markup_str(self):
        if self.t2g:
            log.warning(
                "Manim currently cannot parse gradient from svg. "
                "Please set gradient via `set_color_by_gradient`.", )

        config_style_dict = self.generate_config_style_dict()
        global_attr_dict = {
            "line_height":
            ((self.lsh or DEFAULT_LINE_SPACING_SCALE) + 1) * 0.6,
            "font_family":
            self.font or get_customization()["style"]["font"],
            "font_size":
            self.font_size * 1024,
            "font_style":
            self.slant,
            "font_weight":
            self.weight,
            # TODO, it seems this doesn't work
            "font_features":
            "liga=0,dlig=0,clig=0,hlig=0" if self.disable_ligatures else None,
            "foreground":
            config_style_dict.get("fill", None),
            "alpha":
            config_style_dict.get("fill-opacity", None)
        }
        global_attr_dict = {
            k: v
            for k, v in global_attr_dict.items() if v is not None
        }
        global_attr_dict.update(self.global_config)
        self.parser.update_global_attrs(global_attr_dict)

        local_attr_items = [(word_or_text_span, {
            key: value
        }) for t2x_dict, key in ((self.t2c, "foreground"), (self.t2f,
                                                            "font_family"),
                                 (self.t2s, "font_style"), (self.t2w,
                                                            "font_weight"))
                            for word_or_text_span, value in t2x_dict.items()]
        local_attr_items.extend(self.local_configs.items())
        for word_or_text_span, local_config in local_attr_items:
            for text_span in self.find_indexes(word_or_text_span):
                self.parser.update_local_attrs(text_span, local_config)

        return self.parser.get_markup_str_with_attrs()
Exemple #18
0
    def __init__(self, text: str, **kwargs):
        self.full2short(kwargs)
        digest_config(self, kwargs)

        if not self.font:
            self.font = get_customization()["style"]["font"]
        if self.is_markup:
            self.validate_markup_string(text)

        self.text = text
        super().__init__(text, **kwargs)

        if self.t2g:
            log.warning(
                "Manim currently cannot parse gradient from svg. "
                "Please set gradient via `set_color_by_gradient`.", )
        if self.gradient:
            self.set_color_by_gradient(*self.gradient)
        if self.height is None:
            self.scale(TEXT_MOB_SCALE_FACTOR)
Exemple #19
0
    def on_key_press(self, symbol: int, modifiers: int) -> None:
        try:
            char = chr(symbol)
        except OverflowError:
            log.warning("The value of the pressed key is too large.")
            return

        event_data = {"symbol": symbol, "modifiers": modifiers}
        propagate_event = EVENT_DISPATCHER.dispatch(EventType.KeyPressEvent,
                                                    **event_data)
        if propagate_event is not None and propagate_event is False:
            return

        if char == "r":
            self.camera.frame.to_default_state()
        elif char == "q":
            self.quit_interaction = True
        elif char == " " or symbol == 65363:  # Space or right arrow
            self.hold_on_wait = False
        elif char == "e" and modifiers == 3:  # ctrl + shift + e
            self.embed(close_scene_on_exit=False)
Exemple #20
0
    def get_mobject_from(self, shape: se.GraphicObject) -> VMobject | None:
        shape_class_to_func_map: dict[type, Callable[
            [se.GraphicObject], VMobject]] = {
                se.Path: self.path_to_mobject,
                se.SimpleLine: self.line_to_mobject,
                se.Rect: self.rect_to_mobject,
                se.Circle: self.circle_to_mobject,
                se.Ellipse: self.ellipse_to_mobject,
                se.Polygon: self.polygon_to_mobject,
                se.Polyline: self.polyline_to_mobject,
                # se.Text: self.text_to_mobject,  # TODO
            }
        for shape_class, func in shape_class_to_func_map.items():
            if isinstance(shape, shape_class):
                mob = func(shape)
                self.apply_style_to_mobject(mob, shape)
                return mob

        shape_class_name = shape.__class__.__name__
        if shape_class_name != "SVGElement":
            log.warning(f"Unsupported element type: {shape_class_name}")
        return None