22import re
33from types import MethodType
44
5- from manimlib .constants import BLACK
5+ from manimlib .constants import WHITE
66from manimlib .mobject .svg .svg_mobject import SVGMobject
7- from manimlib .mobject .types .vectorized_mobject import VMobject
87from manimlib .mobject .types .vectorized_mobject import VGroup
98from manimlib .utils .color import color_to_int_rgb
9+ from manimlib .utils .config_ops import digest_config
1010from manimlib .utils .iterables import adjacent_pairs
1111from manimlib .utils .iterables import remove_list_redundancies
1212from manimlib .utils .tex_file_writing import tex_to_svg_file
1818SCALE_FACTOR_PER_FONT_POINT = 0.001
1919
2020
21- TEX_HASH_TO_MOB_MAP = {}
22-
23-
2421def _get_neighbouring_pairs (iterable ):
2522 return list (adjacent_pairs (iterable ))[:- 1 ]
2623
2724
28- class _TexSVG (SVGMobject ):
29- CONFIG = {
30- "color" : BLACK ,
31- "stroke_width" : 0 ,
32- "height" : None ,
33- "path_string_config" : {
34- "should_subdivide_sharp_curves" : True ,
35- "should_remove_null_curves" : True ,
36- },
37- }
38-
39-
4025class _TexParser (object ):
4126 def __init__ (self , tex_string , additional_substrings ):
4227 self .tex_string = tex_string
@@ -400,10 +385,21 @@ def get_isolated_substrings(self):
400385 ])
401386
402387
403- class MTex ( VMobject ):
388+ class _TexSVG ( SVGMobject ):
404389 CONFIG = {
390+ "height" : None ,
405391 "fill_opacity" : 1.0 ,
406392 "stroke_width" : 0 ,
393+ "path_string_config" : {
394+ "should_subdivide_sharp_curves" : True ,
395+ "should_remove_null_curves" : True ,
396+ },
397+ }
398+
399+
400+ class MTex (_TexSVG ):
401+ CONFIG = {
402+ "color" : WHITE ,
407403 "font_size" : 48 ,
408404 "alignment" : "\\ centering" ,
409405 "tex_environment" : "align*" ,
@@ -413,65 +409,49 @@ class MTex(VMobject):
413409 }
414410
415411 def __init__ (self , tex_string , ** kwargs ):
416- super (). __init__ ( ** kwargs )
412+ digest_config ( self , kwargs )
417413 tex_string = tex_string .strip ()
418414 # Prevent from passing an empty string.
419415 if not tex_string :
420416 tex_string = "\\ quad"
421417 self .tex_string = tex_string
422-
423- self .__parser = _TexParser (
418+ self .parser = _TexParser (
424419 self .tex_string ,
425420 [* self .tex_to_color_map .keys (), * self .isolate ]
426421 )
427- mob = self .generate_mobject ()
428- self .add (* mob .copy ())
429- self .init_colors ()
422+ super ().__init__ (** kwargs )
423+
430424 self .set_color_by_tex_to_color_map (self .tex_to_color_map )
431425 self .scale (SCALE_FACTOR_PER_FONT_POINT * self .font_size )
432426
433- @staticmethod
434- def color_to_label (color ):
435- r , g , b = color_to_int_rgb (color )
436- rg = r * 256 + g
437- return rg * 256 + b
438-
439- def generate_mobject (self ):
440- labelled_tex_string = self .__parser .get_labelled_tex_string ()
441- labelled_tex_content = self .get_tex_file_content (labelled_tex_string )
442- hash_val = hash ((labelled_tex_content , self .use_plain_tex ))
427+ @property
428+ def hash_seed (self ):
429+ return (
430+ self .__class__ .__name__ ,
431+ self .svg_default ,
432+ self .path_string_config ,
433+ self .tex_string ,
434+ self .parser .specified_substrings ,
435+ self .alignment ,
436+ self .tex_environment ,
437+ self .use_plain_tex
438+ )
443439
444- if hash_val in TEX_HASH_TO_MOB_MAP :
445- return TEX_HASH_TO_MOB_MAP [ hash_val ]
440+ def get_file_path ( self ) :
441+ return self . _get_file_path ( self . use_plain_tex )
446442
447- if not self .use_plain_tex :
448- with display_during_execution (f"Writing \" { self .tex_string } \" " ):
449- labelled_svg_glyphs = self .tex_content_to_glyphs (
450- labelled_tex_content
451- )
452- glyph_labels = [
453- self .color_to_label (labelled_glyph .get_fill_color ())
454- for labelled_glyph in labelled_svg_glyphs
455- ]
456- mob = self .build_mobject (labelled_svg_glyphs , glyph_labels )
457- TEX_HASH_TO_MOB_MAP [hash_val ] = mob
458- return mob
443+ def _get_file_path (self , use_plain_tex ):
444+ if use_plain_tex :
445+ tex_string = self .tex_string
446+ else :
447+ tex_string = self .parser .get_labelled_tex_string ()
459448
449+ full_tex = self .get_tex_file_body (tex_string )
460450 with display_during_execution (f"Writing \" { self .tex_string } \" " ):
461- labelled_svg_glyphs = self .tex_content_to_glyphs (
462- labelled_tex_content
463- )
464- tex_content = self .get_tex_file_content (self .tex_string )
465- svg_glyphs = self .tex_content_to_glyphs (tex_content )
466- glyph_labels = [
467- self .color_to_label (labelled_glyph .get_fill_color ())
468- for labelled_glyph in labelled_svg_glyphs
469- ]
470- mob = self .build_mobject (svg_glyphs , glyph_labels )
471- TEX_HASH_TO_MOB_MAP [hash_val ] = mob
472- return mob
451+ file_path = self .tex_to_svg_file_path (full_tex )
452+ return file_path
473453
474- def get_tex_file_content (self , tex_string ):
454+ def get_tex_file_body (self , tex_string ):
475455 if self .tex_environment :
476456 tex_string = "\n " .join ([
477457 f"\\ begin{{{ self .tex_environment } }}" ,
@@ -480,17 +460,38 @@ def get_tex_file_content(self, tex_string):
480460 ])
481461 if self .alignment :
482462 tex_string = "\n " .join ([self .alignment , tex_string ])
483- return tex_string
484-
485- @staticmethod
486- def tex_content_to_glyphs (tex_content ):
463+
487464 tex_config = get_tex_config ()
488- full_tex = tex_config ["tex_body" ].replace (
465+ return tex_config ["tex_body" ].replace (
489466 tex_config ["text_to_replace" ],
490- tex_content
467+ tex_string
491468 )
492- filename = tex_to_svg_file (full_tex )
493- return _TexSVG (filename )
469+
470+ @staticmethod
471+ def tex_to_svg_file_path (tex_file_content ):
472+ return tex_to_svg_file (tex_file_content )
473+
474+ def generate_mobject (self ):
475+ super ().generate_mobject ()
476+
477+ if not self .use_plain_tex :
478+ labelled_svg_glyphs = self
479+ else :
480+ file_path = self ._get_file_path (use_plain_tex = False )
481+ labelled_svg_glyphs = _TexSVG (file_path )
482+
483+ glyph_labels = [
484+ self .color_to_label (labelled_glyph .get_fill_color ())
485+ for labelled_glyph in labelled_svg_glyphs
486+ ]
487+ mob = self .build_mobject (self , glyph_labels )
488+ self .set_submobjects (mob .submobjects )
489+
490+ @staticmethod
491+ def color_to_label (color ):
492+ r , g , b = color_to_int_rgb (color )
493+ rg = r * 256 + g
494+ return rg * 256 + b
494495
495496 def build_mobject (self , svg_glyphs , glyph_labels ):
496497 if not svg_glyphs :
@@ -514,11 +515,11 @@ def build_mobject(self, svg_glyphs, glyph_labels):
514515 submob_labels .append (current_glyph_label )
515516 submobjects .append (submobject )
516517
517- indices = self .__parser .get_sorted_submob_indices (submob_labels )
518+ indices = self .parser .get_sorted_submob_indices (submob_labels )
518519 rearranged_submobjects = [submobjects [index ] for index in indices ]
519520 rearranged_labels = [submob_labels [index ] for index in indices ]
520521
521- submob_tex_strings = self .__parser .get_submob_tex_strings (
522+ submob_tex_strings = self .parser .get_submob_tex_strings (
522523 rearranged_labels
523524 )
524525 for submob , label , submob_tex in zip (
@@ -531,14 +532,14 @@ def build_mobject(self, svg_glyphs, glyph_labels):
531532 return VGroup (* rearranged_submobjects )
532533
533534 def get_part_by_tex_spans (self , tex_spans ):
534- labels = self .__parser .get_containing_labels_by_tex_spans (tex_spans )
535+ labels = self .parser .get_containing_labels_by_tex_spans (tex_spans )
535536 return VGroup (* filter (
536537 lambda submob : submob .submob_label in labels ,
537538 self .submobjects
538539 ))
539540
540541 def get_part_by_custom_span (self , custom_span ):
541- tex_spans = self .__parser .find_span_components_of_custom_span (
542+ tex_spans = self .parser .find_span_components_of_custom_span (
542543 custom_span
543544 )
544545 if tex_spans is None :
@@ -590,10 +591,10 @@ def get_submob_tex(self):
590591 ]
591592
592593 def get_specified_substrings (self ):
593- return self .__parser .get_specified_substrings ()
594+ return self .parser .get_specified_substrings ()
594595
595596 def get_isolated_substrings (self ):
596- return self .__parser .get_isolated_substrings ()
597+ return self .parser .get_isolated_substrings ()
597598
598599
599600class MTexText (MTex ):
0 commit comments