@@ -527,3 +527,64 @@ def test_svg_escape():
527527 fig .savefig (fd , format = 'svg' )
528528 buf = fd .getvalue ().decode ()
529529 assert '<'"&>"' in buf
530+
531+
532+ @pytest .mark .parametrize ("font_str" , [
533+ "'DejaVu Sans', 'WenQuanYi Zen Hei', 'Arial', sans-serif" ,
534+ "'DejaVu Serif', 'WenQuanYi Zen Hei', 'Times New Roman', serif" ,
535+ "'Arial', 'WenQuanYi Zen Hei', cursive" ,
536+ "'Impact', 'WenQuanYi Zen Hei', fantasy" ,
537+ "'DejaVu Sans Mono', 'WenQuanYi Zen Hei', 'Courier New', monospace" ,
538+ # These do not work because the logic to get the font metrics will not find
539+ # WenQuanYi as the fallback logic stops with the first fallback font:
540+ # "'DejaVu Sans Mono', 'Courier New', 'WenQuanYi Zen Hei', monospace",
541+ # "'DejaVu Sans', 'Arial', 'WenQuanYi Zen Hei', sans-serif",
542+ # "'DejaVu Serif', 'Times New Roman', 'WenQuanYi Zen Hei', serif",
543+ ])
544+ @pytest .mark .parametrize ("include_generic" , [True , False ])
545+ def test_svg_font_string (font_str , include_generic ):
546+ fp = fm .FontProperties (family = ["WenQuanYi Zen Hei" ])
547+ if Path (fm .findfont (fp )).name != "wqy-zenhei.ttc" :
548+ pytest .skip ("Font may be missing" )
549+
550+ explicit , * rest , generic = map (
551+ lambda x : x .strip ("'" ), font_str .split (", " )
552+ )
553+ size = len (generic )
554+ if include_generic :
555+ rest = rest + [generic ]
556+ plt .rcParams [f"font.{ generic } " ] = rest
557+ plt .rcParams ["font.size" ] = size
558+ plt .rcParams ["svg.fonttype" ] = "none"
559+
560+ fig , ax = plt .subplots ()
561+ if generic == "sans-serif" :
562+ generic_options = ["sans" , "sans-serif" , "sans serif" ]
563+ else :
564+ generic_options = [generic ]
565+
566+ for generic_name in generic_options :
567+ # test that fallback works
568+ ax .text (0.5 , 0.5 , "There are 几个汉字 in between!" ,
569+ family = [explicit , generic_name ], ha = "center" )
570+ # test deduplication works
571+ ax .text (0.5 , 0.1 , "There are 几个汉字 in between!" ,
572+ family = [explicit , * rest , generic_name ], ha = "center" )
573+ ax .axis ("off" )
574+
575+ with BytesIO () as fd :
576+ fig .savefig (fd , format = "svg" )
577+ buf = fd .getvalue ()
578+
579+ tree = xml .etree .ElementTree .fromstring (buf )
580+ ns = "http://www.w3.org/2000/svg"
581+ text_count = 0
582+ for text_element in tree .findall (f".//{{{ ns } }}text" ):
583+ text_count += 1
584+ font_info = dict (
585+ map (lambda x : x .strip (), _ .strip ().split (":" ))
586+ for _ in dict (text_element .items ())["style" ].split (";" )
587+ )["font" ]
588+
589+ assert font_info == f"{ size } px { font_str } "
590+ assert text_count == len (ax .texts )
0 commit comments