| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 71de09a commit da4513e
4 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -25,8 +25,8 @@ | |||
| 25 | 25 | _Backend, _check_savefig_extra_args, FigureCanvasBase, FigureManagerBase, | |
| 26 | 26 | GraphicsContextBase, RendererBase) | |
| 27 | 27 | from matplotlib.cbook import is_writable_file_like, file_requires_unicode | |
| 28 | - from matplotlib.font_manager import is_opentype_cff_font, get_font | ||
| 29 | - from matplotlib.ft2font import LOAD_NO_HINTING | ||
| 28 | + from matplotlib.font_manager import get_font | ||
| 29 | + from matplotlib.ft2font import LOAD_NO_HINTING, LOAD_NO_SCALE | ||
| 30 | 30 | from matplotlib._ttconv import convert_ttf_to_ps | |
| 31 | 31 | from matplotlib.mathtext import MathTextParser | |
| 32 | 32 | from matplotlib._mathtext_data import uni2type1 | |
@@ -134,6 +134,77 @@ def _move_path_to_path_or_stream(src, dst): | |||
| 134 | 134 | shutil.move(src, dst, copy_function=shutil.copyfile) | |
| 135 | 135 | ||
| 136 | 136 | ||
| 137 | + def _font_to_ps_type3(font_path, glyph_ids): | ||
| 138 | + font = get_font(font_path, hinting_factor=1) | ||
| 139 | + | ||
| 140 | + preamble = """ | ||
| 141 | + %!PS-Adobe-3.0 Resource-Font | ||
| 142 | + %%Creator: Converted from TrueType to Type 3 by Matplotlib. | ||
| 143 | + 20 dict begin | ||
| 144 | + /_d {{bind def}} bind def | ||
| 145 | + /_m {{moveto}} _d | ||
| 146 | + /_l {{lineto}} _d | ||
| 147 | + /_ce {{closepath eofill}} _d | ||
| 148 | + /_c {{curveto}} _d | ||
| 149 | + /_sc {{setcachedevice}} _d | ||
| 150 | + /_e {{exec}} _d | ||
| 151 | + /FontName /{font_name} def | ||
| 152 | + /PaintType 0 def | ||
| 153 | + /FontMatrix [{inv_units_per_em} 0 0 {inv_units_per_em} 0 0] def | ||
| 154 | + /FontBBox [{bbox}] def | ||
| 155 | + /FontType 3 def | ||
| 156 | + /Encoding [{encoding}] def | ||
| 157 | + /CharStrings {num_glyphs} dict dup begin | ||
| 158 | + /.notdef 0 def | ||
| 159 | + """.format(font_name=font.postscript_name, | ||
| 160 | + inv_units_per_em=1 / font.units_per_EM, | ||
| 161 | + bbox=" ".join(map(str, font.bbox)), | ||
| 162 | + encoding=" ".join("/{}".format(font.get_glyph_name(glyph_id)) | ||
| 163 | + for glyph_id in glyph_ids), | ||
| 164 | + num_glyphs=len(glyph_ids) + 1) | ||
| 165 | + postamble = """ | ||
| 166 | + end readonly def | ||
| 167 | + | ||
| 168 | + /BuildGlyph { | ||
| 169 | + exch begin | ||
| 170 | + CharStrings exch | ||
| 171 | + 2 copy known not {pop /.notdef} if | ||
| 172 | + true 3 1 roll get exec | ||
| 173 | + end | ||
| 174 | + }_d | ||
| 175 | + | ||
| 176 | + /BuildChar { | ||
| 177 | + 1 index /Encoding get exch get | ||
| 178 | + 1 index /BuildGlyph get exec | ||
| 179 | + }_d | ||
| 180 | + | ||
| 181 | + FontName currentdict end definefont pop | ||
| 182 | + """ | ||
| 183 | + | ||
| 184 | + entries = [] | ||
| 185 | + for glyph_id in glyph_ids: | ||
| 186 | + g = font.load_glyph(glyph_id, LOAD_NO_SCALE) | ||
| 187 | + v, c = font.get_path() | ||
| 188 | + entries.append( | ||
| 189 | + "/%(name)s{%(bbox)s _sc\n" % { | ||
| 190 | + "name": font.get_glyph_name(glyph_id), | ||
| 191 | + "bbox": " ".join(map(str, [g.horiAdvance, 0, *g.bbox])), | ||
| 192 | + } | ||
| 193 | + + _path.convert_to_string( | ||
| 194 | + # Convert back to TrueType's internal units (1/64's). | ||
| 195 | + # (Other dimensions are already in these units.) | ||
| 196 | + Path(v * 64, c), None, None, False, None, 0, | ||
| 197 | + # No code for quad Beziers triggers auto-conversion to cubics. | ||
| 198 | + # Drop intermediate closepolys (relying on the outline | ||
| 199 | + # decomposer always explicitly moving to the closing point | ||
| 200 | + # first). | ||
| 201 | + [b"_m", b"_l", b"", b"_c", b""], True).decode("ascii") | ||
| 202 | + + "_ce}_d" | ||
| 203 | + ) | ||
| 204 | + | ||
| 205 | + return preamble + "\n".join(entries) + postamble | ||
| 206 | + | ||
| 207 | + | ||
| 137 | 208 | class RendererPS(_backend_pdf_ps.RendererPDFPSBase): | |
| 138 | 209 | """ | |
| 139 | 210 | The renderer handles all the drawing primitives using a graphics | |
@@ -932,22 +1003,18 @@ def print_figure_impl(fh): | |||
| 932 | 1003 | # Can't use more than 255 chars from a single Type 3 font. | |
| 933 | 1004 | if len(glyph_ids) > 255: | |
| 934 | 1005 | fonttype = 42 | |
| 935 | - # The ttf to ps (subsetting) support doesn't work for | ||
| 936 | - # OpenType fonts that are Postscript inside (like the STIX | ||
| 937 | - # fonts). This will simply turn that off to avoid errors. | ||
| 938 | - if is_opentype_cff_font(font_path): | ||
| 939 | - raise RuntimeError( | ||
| 940 | - "OpenType CFF fonts can not be saved using " | ||
| 941 | - "the internal Postscript backend at this " | ||
| 942 | - "time; consider using the Cairo backend") | ||
| 943 | 1006 | fh.flush() | |
| 944 | - try: | ||
| 945 | - convert_ttf_to_ps(os.fsencode(font_path), | ||
| 946 | - fh, fonttype, glyph_ids) | ||
| 947 | - except RuntimeError: | ||
| 948 | - _log.warning("The PostScript backend does not " | ||
| 949 | - "currently support the selected font.") | ||
| 950 | - raise | ||
| 1007 | + if fonttype == 3: | ||
| 1008 | + fh.write(_font_to_ps_type3(font_path, glyph_ids)) | ||
| 1009 | + else: | ||
| 1010 | + try: | ||
| 1011 | + convert_ttf_to_ps(os.fsencode(font_path), | ||
| 1012 | + fh, fonttype, glyph_ids) | ||
| 1013 | + except RuntimeError: | ||
| 1014 | + _log.warning( | ||
| 1015 | + "The PostScript backend does not currently " | ||
| 1016 | + "support the selected font.") | ||
| 1017 | + raise | ||
| 951 | 1018 | print("end", file=fh) | |
| 952 | 1019 | print("%%EndProlog", file=fh) | |
| 953 | 1020 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,90 @@ | |||
| 1 | + %!PS-Adobe-3.0 EPSF-3.0 | ||
| 2 | + %%BeginProlog | ||
| 3 | + /mpldict 8 dict def | ||
| 4 | + mpldict begin | ||
| 5 | + /m { moveto } bind def | ||
| 6 | + /l { lineto } bind def | ||
| 7 | + /r { rlineto } bind def | ||
| 8 | + /c { curveto } bind def | ||
| 9 | + /cl { closepath } bind def | ||
| 10 | + /box { | ||
| 11 | + m | ||
| 12 | + 1 index 0 r | ||
| 13 | + 0 exch r | ||
| 14 | + neg 0 r | ||
| 15 | + cl | ||
| 16 | + } bind def | ||
| 17 | + /clipbox { | ||
| 18 | + box | ||
| 19 | + clip | ||
| 20 | + newpath | ||
| 21 | + } bind def | ||
| 22 | + | ||
| 23 | + %!PS-Adobe-3.0 Resource-Font | ||
| 24 | + %%Creator: Converted from TrueType to Type 3 by Matplotlib. | ||
| 25 | + 20 dict begin | ||
| 26 | + /_d {bind def} bind def | ||
| 27 | + /_m {moveto} _d | ||
| 28 | + /_l {lineto} _d | ||
| 29 | + /_ce {closepath eofill} _d | ||
| 30 | + /_c {curveto} _d | ||
| 31 | + /_sc {setcachedevice} _d | ||
| 32 | + /_e {exec} _d | ||
| 33 | + /FontName /DejaVuSans def | ||
| 34 | + /PaintType 0 def | ||
| 35 | + /FontMatrix [0.00048828125 0 0 0.00048828125 0 0] def | ||
| 36 | + /FontBBox [-2090 -948 3673 2524] def | ||
| 37 | + /FontType 3 def | ||
| 38 | + /Encoding [/I] def | ||
| 39 | + /CharStrings 2 dict dup begin | ||
| 40 | + /.notdef 0 def | ||
| 41 | + /I{604 0 201 0 403 1493 _sc | ||
| 42 | + 201 1493 _m | ||
| 43 | + 403 1493 _l | ||
| 44 | + 403 0 _l | ||
| 45 | + 201 0 _l | ||
| 46 | + 201 1493 _l | ||
| 47 | + | ||
| 48 | + _ce}_d | ||
| 49 | + end readonly def | ||
| 50 | + | ||
| 51 | + /BuildGlyph { | ||
| 52 | + exch begin | ||
| 53 | + CharStrings exch | ||
| 54 | + 2 copy known not {pop /.notdef} if | ||
| 55 | + true 3 1 roll get exec | ||
| 56 | + end | ||
| 57 | + }_d | ||
| 58 | + | ||
| 59 | + /BuildChar { | ||
| 60 | + 1 index /Encoding get exch get | ||
| 61 | + 1 index /BuildGlyph get exec | ||
| 62 | + }_d | ||
| 63 | + | ||
| 64 | + FontName currentdict end definefont pop | ||
| 65 | + end | ||
| 66 | + %%EndProlog | ||
| 67 | + mpldict begin | ||
| 68 | + 18 180 translate | ||
| 69 | + 576 432 0 0 clipbox | ||
| 70 | + gsave | ||
| 71 | + 0 0 m | ||
| 72 | + 576 0 l | ||
| 73 | + 576 432 l | ||
| 74 | + 0 432 l | ||
| 75 | + cl | ||
| 76 | + 1.000 setgray | ||
| 77 | + fill | ||
| 78 | + grestore | ||
| 79 | + 0.000 setgray | ||
| 80 | + /DejaVuSans findfont | ||
| 81 | + 12.000 scalefont | ||
| 82 | + setfont | ||
| 83 | + gsave | ||
| 84 | + 288.000000 216.000000 translate | ||
| 85 | + 0.000000 rotate | ||
| 86 | + 0.000000 0 m /I glyphshow | ||
| 87 | + grestore | ||
| 88 | + | ||
| 89 | + end | ||
| 90 | + showpage | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -133,3 +133,8 @@ def test_partial_usetex(caplog): | |||
| 133 | 133 | plt.savefig(io.BytesIO(), format="ps") | |
| 134 | 134 | assert caplog.records and all("as if usetex=False" in record.getMessage() | |
| 135 | 135 | for record in caplog.records) | |
| 136 | + | ||
| 137 | + | ||
| 138 | + @image_comparison(["type3.eps"]) | ||
| 139 | + def test_type3_font(): | ||
| 140 | + plt.figtext(.5, .5, "I") | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -120,11 +120,8 @@ def test_find_ttc(): | |||
| 120 | 120 | ||
| 121 | 121 | fig, ax = plt.subplots() | |
| 122 | 122 | ax.text(.5, .5, "\N{KANGXI RADICAL DRAGON}", fontproperties=fp) | |
| 123 | - fig.savefig(BytesIO(), format="raw") | ||
| 124 | - fig.savefig(BytesIO(), format="svg") | ||
| 125 | - fig.savefig(BytesIO(), format="pdf") | ||
| 126 | - with pytest.raises(RuntimeError): | ||
| 127 | - fig.savefig(BytesIO(), format="ps") | ||
| 123 | + for fmt in ["raw", "svg", "pdf", "ps"]: | ||
| 124 | + fig.savefig(BytesIO(), format=fmt) | ||
| 128 | 125 | ||
| 129 | 126 | ||
| 130 | 127 | def test_find_invalid(tmpdir): | |
| Back | FazBrowse Home | New Git URL |
0 commit comments