Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitdd15dc0

Browse files
authored
Merge pull request#18370 from anntzer/unttps
Move PostScript Type3 subsetting to pure python.
2 parents825f518 +4438b25 commitdd15dc0

File tree

4 files changed

+226
-30
lines changed

4 files changed

+226
-30
lines changed

‎lib/matplotlib/backends/backend_ps.py

Lines changed: 107 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@
2525
_Backend,_check_savefig_extra_args,FigureCanvasBase,FigureManagerBase,
2626
GraphicsContextBase,RendererBase)
2727
frommatplotlib.cbookimportis_writable_file_like,file_requires_unicode
28-
frommatplotlib.font_managerimportis_opentype_cff_font,get_font
29-
frommatplotlib.ft2fontimportLOAD_NO_HINTING
28+
frommatplotlib.font_managerimportget_font
29+
frommatplotlib.ft2fontimportLOAD_NO_HINTING,LOAD_NO_SCALE
3030
frommatplotlib._ttconvimportconvert_ttf_to_ps
3131
frommatplotlib.mathtextimportMathTextParser
3232
frommatplotlib._mathtext_dataimportuni2type1
@@ -134,6 +134,86 @@ def _move_path_to_path_or_stream(src, dst):
134134
shutil.move(src,dst,copy_function=shutil.copyfile)
135135

136136

137+
def_font_to_ps_type3(font_path,glyph_ids):
138+
"""
139+
Subset *glyph_ids* from the font at *font_path* into a Type 3 font.
140+
141+
Parameters
142+
----------
143+
font_path : path-like
144+
Path to the font to be subsetted.
145+
glyph_ids : list of int
146+
The glyph indices to include in the subsetted font.
147+
148+
Returns
149+
-------
150+
str
151+
The string representation of a Type 3 font, which can be included
152+
verbatim into a PostScript file.
153+
"""
154+
font=get_font(font_path,hinting_factor=1)
155+
156+
preamble="""\
157+
%!PS-Adobe-3.0 Resource-Font
158+
%%Creator: Converted from TrueType to Type 3 by Matplotlib.
159+
10 dict begin
160+
/FontName /{font_name} def
161+
/PaintType 0 def
162+
/FontMatrix [{inv_units_per_em} 0 0 {inv_units_per_em} 0 0] def
163+
/FontBBox [{bbox}] def
164+
/FontType 3 def
165+
/Encoding [{encoding}] def
166+
/CharStrings {num_glyphs} dict dup begin
167+
/.notdef 0 def
168+
""".format(font_name=font.postscript_name,
169+
inv_units_per_em=1/font.units_per_EM,
170+
bbox=" ".join(map(str,font.bbox)),
171+
encoding=" ".join("/{}".format(font.get_glyph_name(glyph_id))
172+
forglyph_idinglyph_ids),
173+
num_glyphs=len(glyph_ids)+1)
174+
postamble="""
175+
end readonly def
176+
177+
/BuildGlyph {
178+
exch begin
179+
CharStrings exch
180+
2 copy known not {pop /.notdef} if
181+
true 3 1 roll get exec
182+
end
183+
} d
184+
185+
/BuildChar {
186+
1 index /Encoding get exch get
187+
1 index /BuildGlyph get exec
188+
} d
189+
190+
FontName currentdict end definefont pop
191+
"""
192+
193+
entries= []
194+
forglyph_idinglyph_ids:
195+
g=font.load_glyph(glyph_id,LOAD_NO_SCALE)
196+
v,c=font.get_path()
197+
entries.append(
198+
"/%(name)s{%(bbox)s sc\n"% {
199+
"name":font.get_glyph_name(glyph_id),
200+
"bbox":" ".join(map(str, [g.horiAdvance,0,*g.bbox])),
201+
}
202+
+_path.convert_to_string(
203+
# Convert back to TrueType's internal units (1/64's).
204+
# (Other dimensions are already in these units.)
205+
Path(v*64,c),None,None,False,None,0,
206+
# No code for quad Beziers triggers auto-conversion to cubics.
207+
# Drop intermediate closepolys (relying on the outline
208+
# decomposer always explicitly moving to the closing point
209+
# first).
210+
[b"m",b"l",b"",b"c",b""],True).decode("ascii")
211+
+"ce} d"
212+
)
213+
214+
returnpreamble+"\n".join(entries)+postamble
215+
216+
137217
classRendererPS(_backend_pdf_ps.RendererPDFPSBase):
138218
"""
139219
The renderer handles all the drawing primitives using a graphics
@@ -922,22 +1002,18 @@ def print_figure_impl(fh):
9221002
# Can't use more than 255 chars from a single Type 3 font.
9231003
iflen(glyph_ids)>255:
9241004
fonttype=42
925-
# The ttf to ps (subsetting) support doesn't work for
926-
# OpenType fonts that are Postscript inside (like the STIX
927-
# fonts). This will simply turn that off to avoid errors.
928-
ifis_opentype_cff_font(font_path):
929-
raiseRuntimeError(
930-
"OpenType CFF fonts can not be saved using "
931-
"the internal Postscript backend at this "
932-
"time; consider using the Cairo backend")
9331005
fh.flush()
934-
try:
935-
convert_ttf_to_ps(os.fsencode(font_path),
936-
fh,fonttype,glyph_ids)
937-
exceptRuntimeError:
938-
_log.warning("The PostScript backend does not "
939-
"currently support the selected font.")
940-
raise
1006+
iffonttype==3:
1007+
fh.write(_font_to_ps_type3(font_path,glyph_ids))
1008+
else:
1009+
try:
1010+
convert_ttf_to_ps(os.fsencode(font_path),
1011+
fh,fonttype,glyph_ids)
1012+
exceptRuntimeError:
1013+
_log.warning(
1014+
"The PostScript backend does not currently "
1015+
"support the selected font.")
1016+
raise
9411017
print("end",file=fh)
9421018
print("%%EndProlog",file=fh)
9431019

@@ -1312,30 +1388,36 @@ def pstoeps(tmpfile, bbox=None, rotated=False):
13121388
# The usage comments use the notation of the operator summary
13131389
# in the PostScript Language reference manual.
13141390
psDefs= [
1391+
# name proc *d* -
1392+
"/d { bind def } bind def",
13151393
# x y *m* -
1316-
"/m { moveto }bind def",
1394+
"/m { moveto }d",
13171395
# x y *l* -
1318-
"/l { lineto }bind def",
1396+
"/l { lineto }d",
13191397
# x y *r* -
1320-
"/r { rlineto }bind def",
1398+
"/r { rlineto }d",
13211399
# x1 y1 x2 y2 x y *c* -
1322-
"/c { curveto } bind def",
1323-
# *closepath* -
1324-
"/cl { closepath } bind def",
1400+
"/c { curveto } d",
1401+
# *cl* -
1402+
"/cl { closepath } d",
1403+
# *ce* -
1404+
"/ce { closepath eofill } d",
13251405
# w h x y *box* -
13261406
"""/box {
13271407
m
13281408
1 index 0 r
13291409
0 exch r
13301410
neg 0 r
13311411
cl
1332-
}bind def""",
1412+
}d""",
13331413
# w h x y *clipbox* -
13341414
"""/clipbox {
13351415
box
13361416
clip
13371417
newpath
1338-
} bind def""",
1418+
} d""",
1419+
# wx wy llx lly urx ury *setcachedevice* -
1420+
"/sc { setcachedevice } d",
13391421
]
13401422

13411423

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
%!PS-Adobe-3.0 EPSF-3.0
2+
%%Orientation:portrait
3+
%%BoundingBox:18.0 180.0 594.0 612.0
4+
%%EndComments
5+
%%BeginProlog
6+
/mpldict11dictdef
7+
mpldictbegin
8+
/d {binddef }binddef
9+
/m {moveto }d
10+
/l {lineto }d
11+
/r {rlineto }d
12+
/c {curveto }d
13+
/cl {closepath }d
14+
/ce {closepatheofill }d
15+
/box {
16+
m
17+
1index0r
18+
0exchr
19+
neg0r
20+
cl
21+
}d
22+
/clipbox {
23+
box
24+
clip
25+
newpath
26+
}d
27+
/sc {setcachedevice }d
28+
%!PS-Adobe-3.0 Resource-Font
29+
%%Creator:Converted from TrueType to Type 3 by Matplotlib.
30+
10dictbegin
31+
/FontName/DejaVuSansdef
32+
/PaintType0def
33+
/FontMatrix [0.00048828125000.0004882812500]def
34+
/FontBBox [-2090-94836732524]def
35+
/FontType3def
36+
/Encoding [/I/J/slash]def
37+
/CharStrings4dictdupbegin
38+
/.notdef0def
39+
/I{604020104031493sc
40+
2011493m
41+
4031493l
42+
4030l
43+
2010l
44+
2011493l
45+
46+
ce}d
47+
/J{6040-106-4104031493sc
48+
2011493m
49+
4031493l
50+
403104l
51+
403-76369-207300-288c
52+
232-369122-410-29-410c
53+
-106-410l
54+
-106-240l
55+
-43-240l
56+
46-240109-215146-165c
57+
183-115201-25201104c
58+
2011493l
59+
60+
ce}d
61+
/slash{69000-1906901493sc
62+
5201493m
63+
6901493l
64+
170-190l
65+
0-190l
66+
5201493l
67+
68+
ce}d
69+
endreadonlydef
70+
71+
/BuildGlyph {
72+
exchbegin
73+
CharStringsexch
74+
2copyknownnot {pop/.notdef}if
75+
true31rollgetexec
76+
end
77+
}d
78+
79+
/BuildChar {
80+
1index/Encodinggetexchget
81+
1index/BuildGlyphgetexec
82+
}d
83+
84+
FontNamecurrentdictenddefinefontpop
85+
end
86+
%%EndProlog
87+
mpldictbegin
88+
18180translate
89+
57643200clipbox
90+
gsave
91+
00m
92+
5760l
93+
576432l
94+
0432l
95+
cl
96+
1.000setgray
97+
fill
98+
grestore
99+
0.000setgray
100+
/DejaVuSansfindfont
101+
12.000scalefont
102+
setfont
103+
gsave
104+
288.000000216.000000translate
105+
0.000000rotate
106+
0.0000000m/Iglyphshow
107+
3.5390620m/slashglyphshow
108+
7.5820310m/Jglyphshow
109+
grestore
110+
111+
end
112+
showpage

‎lib/matplotlib/tests/test_backend_ps.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,3 +157,8 @@ def test_useafm():
157157
ax.set_axis_off()
158158
ax.axhline(.5)
159159
ax.text(.5,.5,"qk")
160+
161+
162+
@image_comparison(["type3.eps"])
163+
deftest_type3_font():
164+
plt.figtext(.5,.5,"I/J")

‎lib/matplotlib/tests/test_font_manager.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -120,11 +120,8 @@ def test_find_ttc():
120120

121121
fig,ax=plt.subplots()
122122
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-
withpytest.raises(RuntimeError):
127-
fig.savefig(BytesIO(),format="ps")
123+
forfmtin ["raw","svg","pdf","ps"]:
124+
fig.savefig(BytesIO(),format=fmt)
128125

129126

130127
deftest_find_invalid(tmpdir):

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp