@@ -53,18 +53,15 @@ def construct(self):
5353from xml .sax .saxutils import escape
5454
5555import cairo
56- import cairocffi
57- import pangocairocffi
58- import pangocffi
56+ import manimpango
57+ from manimpango import PangoUtils , TextSetting , MarkupUtils
5958
6059from ... import config , logger
6160from ...constants import *
6261from ...mobject .geometry import Dot
6362from ...mobject .svg .svg_mobject import SVGMobject
6463from ...mobject .types .vectorized_mobject import VGroup
65- from ...utils .color import WHITE
66- from ...utils .color import Colors
67-
64+ from ...utils .color import WHITE , Colors
6865
6966TEXT_MOB_SCALE_FACTOR = 0.05
7067
@@ -103,68 +100,6 @@ def remove_invisible_chars(mobject):
103100 return mobject_without_dots
104101
105102
106- class PangoUtils :
107- @staticmethod
108- def str2style (string : str ) -> pangocffi .Style :
109- """Internally used function. Converts text to Pango Understandable Styles."""
110- if string == NORMAL :
111- return pangocffi .Style .NORMAL
112- elif string == ITALIC :
113- return pangocffi .Style .ITALIC
114- elif string == OBLIQUE :
115- return pangocffi .Style .OBLIQUE
116- else :
117- raise AttributeError ("There is no Style Called %s" % string )
118-
119- @staticmethod
120- def str2weight (string : str ) -> pangocffi .Weight :
121- """Internally used function. Convert text to Pango Understandable Weight"""
122- if string == NORMAL :
123- return pangocffi .Weight .NORMAL
124- elif string == BOLD :
125- return pangocffi .Weight .BOLD
126- elif string == THIN :
127- return pangocffi .Weight .THIN
128- elif string == ULTRALIGHT :
129- return pangocffi .Weight .ULTRALIGHT
130- elif string == LIGHT :
131- return pangocffi .Weight .LIGHT
132- elif string == SEMILIGHT :
133- return pangocffi .Weight .SEMILIGHT
134- elif string == BOOK :
135- return pangocffi .Weight .BOOK
136- elif string == MEDIUM :
137- return pangocffi .Weight .MEDIUM
138- elif string == SEMIBOLD :
139- return pangocffi .Weight .SEMIBOLD
140- elif string == ULTRABOLD :
141- return pangocffi .Weight .ULTRABOLD
142- elif string == HEAVY :
143- return pangocffi .Weight .HEAVY
144- elif string == ULTRAHEAVY :
145- return pangocffi .Weight .ULTRAHEAVY
146- else :
147- raise AttributeError ("There is no Font Weight Called %s" % string )
148-
149- @staticmethod
150- def remove_last_M (file_name : str ) -> None :
151- with open (file_name , "r" ) as fpr :
152- content = fpr .read ()
153- content = re .sub (r'Z M [^A-Za-z]*? "\/>' , 'Z "/>' , content )
154- with open (file_name , "w" ) as fpw :
155- fpw .write (content )
156-
157-
158- class TextSetting (object ):
159- def __init__ (self , start , end , font , slant , weight , line_num = - 1 ):
160- self .start = start
161- self .end = end
162- self .font = font
163- self .slant = slant
164- self .weight = weight
165- self .line_num = line_num
166-
167-
168103class CairoText (SVGMobject ):
169104 """Display (non-LaTeX) text.
170105
@@ -448,7 +383,7 @@ def text2svg(self):
448383 offset_x = 0
449384 last_line_num = 0
450385 for setting in settings :
451- font = setting .font
386+ font = setting .font . decode ( "utf-8" )
452387 slant = self .str2slant (setting .slant )
453388 weight = self .str2weight (setting .weight )
454389 text = self .text [setting .start : setting .end ].replace ("\n " , " " )
@@ -1012,45 +947,22 @@ def text2svg(self):
1012947 file_name = os .path .join (dir_name , hash_name ) + ".svg"
1013948 if os .path .exists (file_name ):
1014949 return file_name
1015- surface = cairocffi .SVGSurface (file_name , 600 , 400 )
1016- context = cairocffi .Context (surface )
1017- context .move_to (START_X , START_Y )
1018950 settings = self .text2settings ()
1019- offset_x = 0
1020- last_line_num = 0
1021- layout = pangocairocffi .create_layout (context )
1022- layout .set_width (pangocffi .units_from_double (600 ))
1023- for setting in settings :
1024- family = setting .font
1025- style = PangoUtils .str2style (setting .slant )
1026- weight = PangoUtils .str2weight (setting .weight )
1027- text = self .text [setting .start : setting .end ].replace ("\n " , " " )
1028- fontdesc = pangocffi .FontDescription ()
1029- fontdesc .set_size (pangocffi .units_from_double (size ))
1030- if family :
1031- fontdesc .set_family (family )
1032- fontdesc .set_style (style )
1033- fontdesc .set_weight (weight )
1034- layout .set_font_description (fontdesc )
1035- if setting .line_num != last_line_num :
1036- offset_x = 0
1037- last_line_num = setting .line_num
1038- context .move_to (
1039- START_X + offset_x , START_Y + line_spacing * setting .line_num
1040- )
1041- pangocairocffi .update_layout (context , layout )
1042- if disable_liga :
1043- text = escape (text )
1044- layout .set_markup (
1045- f"<span font_features='liga=0,dlig=0,clig=0,hlig=0'>{ text } </span>"
1046- )
1047- else :
1048- layout .set_text (text )
1049- logger .debug (f"Setting Text { text } " )
1050- pangocairocffi .show_layout (context , layout )
1051- offset_x += pangocffi .units_to_double (layout .get_size ()[0 ])
1052- surface .finish ()
1053- return file_name
951+ width = 600
952+ height = 400
953+
954+ return manimpango .text2svg (
955+ settings ,
956+ size ,
957+ line_spacing ,
958+ disable_liga ,
959+ file_name ,
960+ START_X ,
961+ START_Y ,
962+ width ,
963+ height ,
964+ self .text ,
965+ )
1054966
1055967
1056968class MarkupText (SVGMobject ):
@@ -1360,32 +1272,22 @@ def text2svg(self):
13601272 file_name = os .path .join (dir_name , hash_name ) + ".svg"
13611273 if os .path .exists (file_name ):
13621274 return file_name
1363- surface = cairocffi .SVGSurface (file_name , 600 , 400 )
1364- context = cairocffi .Context (surface )
1365- context .move_to (START_X , START_Y )
1366- layout = pangocairocffi .create_layout (context )
1367- layout .set_width (pangocffi .units_from_double (600 ))
1368-
1369- fontdesc = pangocffi .FontDescription ()
1370- fontdesc .set_size (pangocffi .units_from_double (size ))
1371- if self .font :
1372- fontdesc .set_family (self .font )
1373- fontdesc .set_style (PangoUtils .str2style (self .slant ))
1374- fontdesc .set_weight (PangoUtils .str2weight (self .weight ))
1375- layout .set_font_description (fontdesc )
13761275
1377- context .move_to (START_X , START_Y )
1378- pangocairocffi .update_layout (context , layout )
1379- if disable_liga :
1380- layout .set_markup (
1381- f"<span font_features='liga=0,dlig=0,clig=0,hlig=0'>{ self .text } </span>"
1382- )
1383- else :
1384- layout .set_markup (self .text )
13851276 logger .debug (f"Setting Text { self .text } " )
1386- pangocairocffi .show_layout (context , layout )
1387- surface .finish ()
1388- return file_name
1277+ return MarkupUtils .text2svg (
1278+ self .text ,
1279+ self .font ,
1280+ self .slant ,
1281+ self .weight ,
1282+ size ,
1283+ line_spacing ,
1284+ disable_liga ,
1285+ file_name ,
1286+ START_X ,
1287+ START_Y ,
1288+ 600 , # width
1289+ 400 , # height
1290+ )
13891291
13901292 def _count_real_chars (self , s ):
13911293 """Counts characters that will be displayed.
0 commit comments