Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 847f0f5

Browse files
committed
Merge branch 'issue621' of https://github.com/jkseppan/matplotlib into jkseppan-issue621
Conflicts: CHANGELOG
2 parents 6a878de + 129750f commit 847f0f5

7 files changed

Lines changed: 215 additions & 35 deletions

File tree

CHANGELOG

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
1+
2011-12-29 ps and pdf markers are now stroked only if the line width
2+
is nonzero for consistency with agg, fixes issue #621. - JKS
3+
14
2011-12-27 Work around an EINTR bug in some versions of subprocess. - JKS
25

6+
37
2011-10-25 added support for \operatorname to mathtext,
48
including the ability to insert spaces, such as
59
$\operatorname{arg\,max}$ - PI

lib/matplotlib/backends/backend_pdf.py

Lines changed: 50 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# -*- coding: iso-8859-1 -*-
22

33
"""
4-
A PDF matplotlib backend (not yet complete)
4+
A PDF matplotlib backend
55
Author: Jouni K Seppänen <[email protected]>
66
"""
77
from __future__ import division, print_function
@@ -290,6 +290,29 @@ def pdfRepr(self):
290290
Op = Bunch(**dict([(name, Operator(value))
291291
for name, value in _pdfops.iteritems()]))
292292

293+
def _paint_path(closep, fillp, strokep):
294+
"""Return the PDF operator to paint a path in the following way:
295+
closep: close the path before painting
296+
fillp: fill the path with the fill color
297+
strokep: stroke the outline of the path with the line color"""
298+
if strokep:
299+
if closep:
300+
if fillp:
301+
return Op.close_fill_stroke
302+
else:
303+
return Op.close_stroke
304+
else:
305+
if fillp:
306+
return Op.fill_stroke
307+
else:
308+
return Op.stroke
309+
else:
310+
if fillp:
311+
return Op.fill
312+
else:
313+
return Op.endpath
314+
Op.paint_path = _paint_path
315+
293316
class Stream(object):
294317
"""PDF stream object.
295318
@@ -1190,10 +1213,22 @@ def writeImages(self):
11901213

11911214
img.flipud_out()
11921215

1193-
def markerObject(self, path, trans, fillp, lw):
1216+
def markerObject(self, path, trans, fillp, strokep, lw):
11941217
"""Return name of a marker XObject representing the given path."""
1218+
# self.markers used by markerObject, writeMarkers, close:
1219+
# mapping from (path operations, fill?, stroke?) to
1220+
# [name, object reference, bounding box, linewidth]
1221+
# This enables different draw_markers calls to share the XObject
1222+
# if the gc is sufficiently similar: colors etc can vary, but
1223+
# the choices of whether to fill and whether to stroke cannot.
1224+
# We need a bounding box enclosing all of the XObject path,
1225+
# but since line width may vary, we store the maximum of all
1226+
# occurring line widths in self.markers.
1227+
# close() is somewhat tightly coupled in that it expects the
1228+
# first two components of each value in self.markers to be the
1229+
# name and object reference.
11951230
pathops = self.pathOperations(path, trans, simplify=False)
1196-
key = (tuple(pathops), bool(fillp))
1231+
key = (tuple(pathops), bool(fillp), bool(strokep))
11971232
result = self.markers.get(key)
11981233
if result is None:
11991234
name = Name('M%d' % len(self.markers))
@@ -1207,17 +1242,15 @@ def markerObject(self, path, trans, fillp, lw):
12071242
return name
12081243

12091244
def writeMarkers(self):
1210-
for (pathops, fillp),(name, ob, bbox, lw) in self.markers.iteritems():
1245+
for ((pathops, fillp, strokep),
1246+
(name, ob, bbox, lw)) in self.markers.iteritems():
12111247
bbox = bbox.padded(lw * 0.5)
12121248
self.beginStream(
12131249
ob.id, None,
12141250
{'Type': Name('XObject'), 'Subtype': Name('Form'),
12151251
'BBox': list(bbox.extents) })
12161252
self.output(*pathops)
1217-
if fillp:
1218-
self.output(Op.fill_stroke)
1219-
else:
1220-
self.output(Op.stroke)
1253+
self.output(Op.paint_path(False, fillp, strokep))
12211254
self.endStream()
12221255

12231256
@staticmethod
@@ -1436,11 +1469,12 @@ def draw_markers(self, gc, marker_path, marker_trans, path, trans, rgbFace=None)
14361469
return
14371470

14381471
self.check_gc(gc, rgbFace)
1439-
fillp = rgbFace is not None
1472+
fillp = gc.fillp()
1473+
strokep = gc.strokep()
14401474

14411475
output = self.file.output
14421476
marker = self.file.markerObject(
1443-
marker_path, marker_trans, fillp, self.gc._linewidth)
1477+
marker_path, marker_trans, fillp, strokep, self.gc._linewidth)
14441478

14451479
output(Op.gsave)
14461480
lastx, lasty = 0, 0
@@ -1869,16 +1903,18 @@ def __repr__(self):
18691903
del d['parent']
18701904
return repr(d)
18711905

1872-
def _strokep(self):
1906+
def strokep(self):
18731907
"""
18741908
Predicate: does the path need to be stroked (its outline drawn)?
18751909
This tests for the various conditions that disable stroking
18761910
the path, in which case it would presumably be filled.
18771911
"""
1912+
# _linewidth > 0: in pdf a line of width 0 is drawn at minimum
1913+
# possible device width, but e.g. agg doesn't draw at all
18781914
return (self._linewidth > 0 and self._alpha > 0 and
18791915
(len(self._rgb) <= 3 or self._rgb[3] != 0.0))
18801916

1881-
def _fillp(self):
1917+
def fillp(self):
18821918
"""
18831919
Predicate: does the path need to be filled?
18841920
"""
@@ -1891,32 +1927,14 @@ def close_and_paint(self):
18911927
Return the appropriate pdf operator to close the path and
18921928
cause it to be stroked, filled, or both.
18931929
"""
1894-
if self._strokep():
1895-
if self._fillp():
1896-
return Op.close_fill_stroke
1897-
else:
1898-
return Op.close_stroke
1899-
else:
1900-
if self._fillp():
1901-
return Op.fill
1902-
else:
1903-
return Op.endpath
1930+
return Op.paint_path(True, self.fillp(), self.strokep())
19041931

19051932
def paint(self):
19061933
"""
19071934
Return the appropriate pdf operator to cause the path to be
19081935
stroked, filled, or both.
19091936
"""
1910-
if self._strokep():
1911-
if self._fillp():
1912-
return Op.fill_stroke
1913-
else:
1914-
return Op.stroke
1915-
else:
1916-
if self._fillp():
1917-
return Op.fill
1918-
else:
1919-
return Op.endpath
1937+
return Op.paint_path(False, self.fillp(), self.strokep())
19201938

19211939
capstyles = { 'butt': 0, 'round': 1, 'projecting': 2 }
19221940
joinstyles = { 'miter': 0, 'round': 1, 'bevel': 2 }

lib/matplotlib/backends/backend_ps.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -593,8 +593,10 @@ def draw_markers(self, gc, marker_path, marker_trans, path, trans, rgbFace=None)
593593

594594
if rgbFace:
595595
ps_cmd.extend(['gsave', ps_color, 'fill', 'grestore'])
596+
if gc.shouldstroke():
597+
ps_cmd.append('stroke')
596598

597-
ps_cmd.extend(['stroke', 'grestore', '} bind def'])
599+
ps_cmd.extend(['grestore', '} bind def'])
598600

599601
for vertices, code in path.iter_segments(trans, simplify=False):
600602
if len(vertices):
@@ -855,8 +857,7 @@ def _draw_ps(self, ps, gc, rgbFace, fill=True, stroke=True, command=None):
855857
write = self._pswriter.write
856858
if debugPS and command:
857859
write("% "+command+"\n")
858-
mightstroke = (gc.get_linewidth() > 0.0 and
859-
(len(gc.get_rgb()) <= 3 or gc.get_rgb()[3] != 0.0))
860+
mightstroke = gc.shouldstroke()
860861
stroke = stroke and mightstroke
861862
fill = (fill and rgbFace is not None and
862863
(len(rgbFace) <= 3 or rgbFace[3] != 0.0))
@@ -917,6 +918,9 @@ def get_joinstyle(self):
917918
'round':1,
918919
'bevel':2}[GraphicsContextBase.get_joinstyle(self)]
919920

921+
def shouldstroke(self):
922+
return (self.get_linewidth() > 0.0 and
923+
(len(self.get_rgb()) <= 3 or self.get_rgb()[3] != 0.0))
920924

921925
def new_figure_manager(num, *args, **kwargs):
922926
FigureClass = kwargs.pop('FigureClass', Figure)
1.95 KB
Binary file not shown.
20.9 KB
Loading
Lines changed: 144 additions & 0 deletions
Loading

lib/matplotlib/tests/test_axes.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -636,6 +636,16 @@ def test_markevery_line():
636636
ax.plot(x, y, '-+', markevery=(5, 20), label='mark every 5 starting at 10')
637637
ax.legend()
638638

639+
@image_comparison(baseline_images=['marker_edges'])
640+
def test_marker_edges():
641+
x = np.linspace(0, 1, 10)
642+
fig = plt.figure()
643+
ax = fig.add_subplot(111)
644+
ax.plot(x, np.sin(x), 'y.', ms=30.0, mew=0, mec='r')
645+
ax.plot(x+0.1, np.sin(x), 'y.', ms=30.0, mew=1, mec='r')
646+
ax.plot(x+0.2, np.sin(x), 'y.', ms=30.0, mew=2, mec='b')
647+
ax.set_xticks([])
648+
ax.set_yticks([])
639649

640650
if __name__=='__main__':
641651
import nose

0 commit comments

Comments
 (0)