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

Commitda4513e

Browse files
committed
Move PostScript Type3 subsetting to pure python.
... similarly to the change for pdf, but easier because there are nobaseline images for which we need to provide bug-level backcompat :-)Drop the FontInfo metadata (which is explicitly optional in thePostScript spec) to avoid having to figure out the correct encoding(which can be quite obscure).Replace the implementation of the `_sc` command from`7 -1 roll{setcachedevice}{pop pop pop pop pop pop}ifelse` to a plain`setcachedevice` (as I cannot see any case where the "other" branch istaken).Drop the splitting of long commands using `exec` (`_e`) -- this is onlyneeded for level-1 postscript, which has a small fixed stack size; weoutput level-2 postscript (per backend_version) and I guess level-1 israrely in use nowadays anyways (probably the feature could be added backif there's really demand for it, but let's not get ahead of ourselves).Previously, some composite characters would be output in a "compressed"form (e.g., accented characters would be recorded as "draw the accent,then run the charproc for the unaccented character"). This is lost, butI'd guess outputting .ps.gz is better if compression really matters.
1 parent71de09a commitda4513e

File tree

4 files changed

+181
-22
lines changed

4 files changed

+181
-22
lines changed

‎lib/matplotlib/backends/backend_ps.py

Lines changed: 84 additions & 17 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,77 @@ 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+
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+
forglyph_idinglyph_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+
forglyph_idinglyph_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+
returnpreamble+"\n".join(entries)+postamble
206+
207+
137208
classRendererPS(_backend_pdf_ps.RendererPDFPSBase):
138209
"""
139210
The renderer handles all the drawing primitives using a graphics
@@ -932,22 +1003,18 @@ def print_figure_impl(fh):
9321003
# Can't use more than 255 chars from a single Type 3 font.
9331004
iflen(glyph_ids)>255:
9341005
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-
ifis_opentype_cff_font(font_path):
939-
raiseRuntimeError(
940-
"OpenType CFF fonts can not be saved using "
941-
"the internal Postscript backend at this "
942-
"time; consider using the Cairo backend")
9431006
fh.flush()
944-
try:
945-
convert_ttf_to_ps(os.fsencode(font_path),
946-
fh,fonttype,glyph_ids)
947-
exceptRuntimeError:
948-
_log.warning("The PostScript backend does not "
949-
"currently support the selected font.")
950-
raise
1007+
iffonttype==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+
exceptRuntimeError:
1014+
_log.warning(
1015+
"The PostScript backend does not currently "
1016+
"support the selected font.")
1017+
raise
9511018
print("end",file=fh)
9521019
print("%%EndProlog",file=fh)
9531020

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
%!PS-Adobe-3.0 EPSF-3.0
2+
%%BeginProlog
3+
/mpldict8dictdef
4+
mpldictbegin
5+
/m {moveto }binddef
6+
/l {lineto }binddef
7+
/r {rlineto }binddef
8+
/c {curveto }binddef
9+
/cl {closepath }binddef
10+
/box {
11+
m
12+
1index0r
13+
0exchr
14+
neg0r
15+
cl
16+
}binddef
17+
/clipbox {
18+
box
19+
clip
20+
newpath
21+
}binddef
22+
23+
%!PS-Adobe-3.0 Resource-Font
24+
%%Creator:Converted from TrueType to Type 3 by Matplotlib.
25+
20dictbegin
26+
/_d {binddef}binddef
27+
/_m {moveto}_d
28+
/_l {lineto}_d
29+
/_ce {closepatheofill}_d
30+
/_c {curveto}_d
31+
/_sc {setcachedevice}_d
32+
/_e {exec}_d
33+
/FontName/DejaVuSansdef
34+
/PaintType0def
35+
/FontMatrix [0.00048828125000.0004882812500]def
36+
/FontBBox [-2090-94836732524]def
37+
/FontType3def
38+
/Encoding [/I]def
39+
/CharStrings2dictdupbegin
40+
/.notdef0def
41+
/I{604020104031493_sc
42+
2011493_m
43+
4031493_l
44+
4030_l
45+
2010_l
46+
2011493_l
47+
48+
_ce}_d
49+
endreadonlydef
50+
51+
/BuildGlyph {
52+
exchbegin
53+
CharStringsexch
54+
2copyknownnot {pop/.notdef}if
55+
true31rollgetexec
56+
end
57+
}_d
58+
59+
/BuildChar {
60+
1index/Encodinggetexchget
61+
1index/BuildGlyphgetexec
62+
}_d
63+
64+
FontNamecurrentdictenddefinefontpop
65+
end
66+
%%EndProlog
67+
mpldictbegin
68+
18180translate
69+
57643200clipbox
70+
gsave
71+
00m
72+
5760l
73+
576432l
74+
0432l
75+
cl
76+
1.000setgray
77+
fill
78+
grestore
79+
0.000setgray
80+
/DejaVuSansfindfont
81+
12.000scalefont
82+
setfont
83+
gsave
84+
288.000000216.000000translate
85+
0.000000rotate
86+
0.0000000m/Iglyphshow
87+
grestore
88+
89+
end
90+
showpage

‎lib/matplotlib/tests/test_backend_ps.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,3 +133,8 @@ def test_partial_usetex(caplog):
133133
plt.savefig(io.BytesIO(),format="ps")
134134
assertcaplog.recordsandall("as if usetex=False"inrecord.getMessage()
135135
forrecordincaplog.records)
136+
137+
138+
@image_comparison(["type3.eps"])
139+
deftest_type3_font():
140+
plt.figtext(.5,.5,"I")

‎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