@@ -53,18 +53,15 @@ def construct(self):
53
53
from xml .sax .saxutils import escape
54
54
55
55
import cairo
56
- import cairocffi
57
- import pangocairocffi
58
- import pangocffi
56
+ import manimpango
57
+ from manimpango import PangoUtils , TextSetting , MarkupUtils
59
58
60
59
from ... import config , logger
61
60
from ...constants import *
62
61
from ...mobject .geometry import Dot
63
62
from ...mobject .svg .svg_mobject import SVGMobject
64
63
from ...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
68
65
69
66
TEXT_MOB_SCALE_FACTOR = 0.05
70
67
@@ -103,68 +100,6 @@ def remove_invisible_chars(mobject):
103
100
return mobject_without_dots
104
101
105
102
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
-
168
103
class CairoText (SVGMobject ):
169
104
"""Display (non-LaTeX) text.
170
105
@@ -448,7 +383,7 @@ def text2svg(self):
448
383
offset_x = 0
449
384
last_line_num = 0
450
385
for setting in settings :
451
- font = setting .font
386
+ font = setting .font . decode ( "utf-8" )
452
387
slant = self .str2slant (setting .slant )
453
388
weight = self .str2weight (setting .weight )
454
389
text = self .text [setting .start : setting .end ].replace ("\n " , " " )
@@ -1012,45 +947,22 @@ def text2svg(self):
1012
947
file_name = os .path .join (dir_name , hash_name ) + ".svg"
1013
948
if os .path .exists (file_name ):
1014
949
return file_name
1015
- surface = cairocffi .SVGSurface (file_name , 600 , 400 )
1016
- context = cairocffi .Context (surface )
1017
- context .move_to (START_X , START_Y )
1018
950
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
+ )
1054
966
1055
967
1056
968
class MarkupText (SVGMobject ):
@@ -1360,32 +1272,22 @@ def text2svg(self):
1360
1272
file_name = os .path .join (dir_name , hash_name ) + ".svg"
1361
1273
if os .path .exists (file_name ):
1362
1274
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 )
1376
1275
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 )
1385
1276
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
+ )
1389
1291
1390
1292
def _count_real_chars (self , s ):
1391
1293
"""Counts characters that will be displayed.
0 commit comments