Revision: 3955
http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3955&view=rev
Author: mdboom
Date: 2007-10-16 07:17:53 -0700 (Tue, 16 Oct 2007)
Log Message:
-----------
First pass at PS backend updates.
Modified Paths:
--------------
branches/transforms/lib/matplotlib/backend_bases.py
branches/transforms/lib/matplotlib/backends/backend_ps.py
branches/transforms/lib/matplotlib/cbook.py
branches/transforms/lib/matplotlib/collections.py
branches/transforms/lib/matplotlib/lines.py
branches/transforms/lib/matplotlib/path.py
branches/transforms/lib/matplotlib/transforms.py
Modified: branches/transforms/lib/matplotlib/backend_bases.py
===================================================================
--- branches/transforms/lib/matplotlib/backend_bases.py 2007-10-16 13:45:59 UTC
(rev 3954)
+++ branches/transforms/lib/matplotlib/backend_bases.py 2007-10-16 14:17:53 UTC
(rev 3955)
@@ -49,7 +49,62 @@
trans is an affine transform applied to the path.
"""
raise NotImplementedError
-
+
+ def draw_path_collection(self, master_transform, cliprect, clippath,
+ clippath_trans, paths, all_transforms, offsets,
+ offsetTrans, facecolors, edgecolors, linewidths,
+ linestyles, antialiaseds):
+ """
+ MGDTODO: Document me. Explain that often the backend will not
+ want to override this.
+ """
+ Npaths = len(paths)
+ Noffsets = len(offsets)
+ N = max(Npaths, Noffsets)
+ Ntransforms = min(len(all_transforms), N)
+ Nfacecolors = len(facecolors)
+ Nedgecolors = len(edgecolors)
+ Nlinewidths = len(linewidths)
+ Nlinestyles = len(linestyles)
+ Naa = len(antialiaseds)
+
+ if (Nfacecolors == 0 and Nedgecolors == 0) or N == 0:
+ return
+
+ ttransforms = []
+ for i in range(Ntransforms):
+ transform = all_transforms[i]
+ if transform is None:
+ transform = transforms.IdentityTransform()
+ ttransforms.append((transform + master_transform).frozen())
+
+ toffsets = offsetTrans.transform(offsets)
+
+ gc = self.new_gc()
+ gc.set_clip_rectangle(cliprect)
+ if clippath is not None:
+ clippath = transforms.TransformedPath(clippath, clippath_trans)
+ gc.set_clippath(clippath)
+
+ if Nfacecolors == 0:
+ rgbFace = None
+
+ print linewidths, edgecolors
+
+ for i in xrange(N):
+ path = paths[i % Npaths]
+ xo, yo = toffsets[i % Noffsets]
+ transform = ttransforms[i % Ntransforms].frozen().translate(xo, yo)
+ if Nfacecolors:
+ rgbFace = facecolors[i % Nfacecolors]
+ if Nedgecolors:
+ gc.set_foreground(edgecolors[i % Nedgecolors])
+ gc.set_linewidth(linewidths[i % Nlinewidths])
+ gc.set_dashes(*linestyles[i % Nlinestyles])
+ gc.set_antialiased(antialiaseds[i % Naa])
+
+ self.draw_path(gc, path, transform, rgbFace)
+
def get_image_magnification(self):
"""
Get the factor by which to magnify images passed to draw_image.
@@ -78,328 +133,6 @@
"""
return False
- ######################################################################
- ## OLD API IS BELOW
- ## These functions no longer need to be implemented in the backends --
- ## they now perform all of their functions in terms of the new API.
-
-# def draw_arc(self, gc, rgbFace, x, y, width, height, angle1, angle2,
-# rotation):
-# """
-# Draw an arc using GraphicsContext instance gcEdge, centered at x,y,
-# with width and height and angles from 0.0 to 360.0
-# 0 degrees is at 3-o'clock
-# positive angles are anti-clockwise
-# draw rotated 'rotation' degrees anti-clockwise about x,y
-
-# If the color rgbFace is not None, fill the arc with it.
-# """
-# raise NotImplementedError
-
-# def draw_line_collection(self, segments, transform, clipbox,
-# colors, linewidths, linestyle, antialiaseds,
-# offsets, transOffset):
-# """
-# This is a function for optimized line drawing. If you need to draw
-# many line segments with similar properties, it is faster to avoid the
-# overhead of all the object creation etc. The lack of total
-# configurability is compensated for with efficiency. Hence we don't
use
-# a GC and many of the line props it supports. See
-# matplotlib.collections for more details.
-
-# segments is a sequence of ( line0, line1, line2), where linen =
-# is an Mx2 array with columns x, y. Each line can be a
-# different length
-
-# transform is used to Transform the lines
-
-# clipbox is a xmin, ymin, width, height clip rect
-
-# colors is a tuple of RGBA tuples
-
-# linewidths is a tuple of linewidths
-# *** really should be called 'dashes' not 'linestyle', since
-# we call gc.set_dashes() not gc.set_linestyle() ***
-
-# linestyle is an (offset, onoffseq) tuple or None,None for solid
-
-# antialiseds is a tuple of ones or zeros indicating whether the
-# segment should be aa or not
-
-# offsets, if not None, is an Nx2 array of x,y offsets to
-# translate the lines by after transform is used to transform
-# the offset coords
-
-# This function could be overridden in the backend to possibly
implement
-# faster drawing, but it is already much faster than using draw_lines()
-# by itself.
-# """
-
-# newstyle = getattr(self, 'draw_markers', None) is not None
-# identity = transforms.identity_transform()
-# gc = self.new_gc()
-# if clipbox is not None:
-# gc.set_clip_rectangle(clipbox.get_bounds())
-# gc.set_dashes(*linestyle)
-
-# Nc = len(colors)
-# Nlw = len(linewidths)
-# Naa = len(antialiaseds)
-# Nsegments = len(segments)
-
-# usingOffsets = offsets is not None
-# Noffsets = 0
-# if usingOffsets:
-# Noffsets = offsets.shape[0]
-# offsets = transOffset.numerix_xy(offsets)
-
-# for i in xrange(max(Noffsets, Nsegments)):
-# color = colors[i % Nc]
-# rgb = color[0], color[1], color[2]
-# alpha = color[-1]
-
-# gc.set_foreground(rgb, isRGB=True)
-# gc.set_alpha( alpha )
-# gc.set_linewidth( linewidths[i % Nlw] )
-# gc.set_antialiased( antialiaseds[i % Naa] )
-# seg = segments[i % Nsegments]
-# if not len(seg): continue
-# xy = transform.numerix_xy(seg)
-# if usingOffsets:
-# xy = xy + offsets[i % Noffsets]
-
-# if newstyle: self.draw_lines(gc, xy[:,0], xy[:,1], identity)
-# else: self.draw_lines(gc, xy[:,0], xy[:,1])
-
-# def draw_line(self, gc, x1, y1, x2, y2):
-# """
-# Draw a single line from x1,y1 to x2,y2
-# """
-# raise NotImplementedError
-
-# def draw_lines(self, gc, x, y, transform=None):
-# """
-# x and y are equal length arrays, draw lines connecting each
-# point in x, y
-# """
-# raise NotImplementedError
-
-# def draw_point(self, gc, x, y):
-# """
-# Draw a single point at x,y
-# Where 'point' is a device-unit point (or pixel), not a matplotlib
point
-# """
-# raise NotImplementedError
-
-# def draw_quad_mesh(self, meshWidth, meshHeight, colors,
-# xCoords, yCoords, clipbox,
-# transform, offsets, transOffset, showedges):
-# """
-# Draw a quadrilateral mesh
-# See documentation in QuadMesh class in collections.py for details
-# """
-# # print "draw_quad_mesh not found, using function in backend_bases"
-# verts = npy.zeros(((meshWidth * meshHeight), 4, 2), npy.float32)
-# indices = npy.arange((meshWidth + 1) * (meshHeight + 1))
-# indices = npy.compress((indices + 1) % (meshWidth + 1), indices)
-# indices = indices[:(meshWidth * meshHeight)]
-# verts[:, 0, 0] = npy.take(xCoords, indices)
-# verts[:, 0, 1] = npy.take(yCoords, indices)
-# verts[:, 1, 0] = npy.take(xCoords, (indices + 1))
-# verts[:, 1, 1] = npy.take(yCoords, (indices + 1))
-# verts[:, 2, 0] = npy.take(xCoords, (indices + meshWidth + 2))
-# verts[:, 2, 1] = npy.take(yCoords, (indices + meshWidth + 2))
-# verts[:, 3, 0] = npy.take(xCoords, (indices + meshWidth + 1))
-# verts[:, 3, 1] = npy.take(yCoords, (indices + meshWidth + 1))
-# if (showedges):
-# edgecolors = colors
-# else:
-# edgecolors = (0, 0, 0, 0),
-# self.draw_poly_collection(verts, transform,
-# clipbox, colors, edgecolors,
-# (0.25,), (0,), offsets, transOffset)
-
-# def draw_poly_collection(
-# self, verts, transform, clipbox, facecolors, edgecolors,
-# linewidths, antialiaseds, offsets, transOffset):
-# """
-# Draw a polygon collection
-
-# verts are a sequence of polygon vectors, where each polygon
-# vector is a sequence of x,y tuples of vertices
-
-# facecolors and edgecolors are a sequence of RGBA tuples
-# linewidths are a sequence of linewidths
-# antialiaseds are a sequence of 0,1 integers whether to use aa
-
-# If a linewidth is zero or an edgecolor alpha is zero, the
-# line will be omitted; similarly, the fill will be omitted
-# if the facecolor alpha is zero.
-# """
-# ## line and/or fill OK
-# Nface = len(facecolors)
-# Nedge = len(edgecolors)
-# Nlw = len(linewidths)
-# Naa = len(antialiaseds)
-
-# usingOffsets = offsets is not None
-# Noffsets = 0
-# Nverts = len(verts)
-# if usingOffsets:
-# Noffsets = len(offsets)
-
-# N = max(Noffsets, Nverts)
-
-# gc = self.new_gc()
-# if clipbox is not None:
-# gc.set_clip_rectangle(clipbox.get_bounds())
-
-
-# for i in xrange(N):
-# polyverts = ma.filled(verts[i % Nverts], npy.nan)
-# if npy.any(npy.isnan(polyverts)):
-# continue
-# linewidth = linewidths[i % Nlw]
-# rf,gf,bf,af = facecolors[i % Nface]
-# re,ge,be,ae = edgecolors[i % Nedge]
-# if af==0:
-# if ae==0 or linewidth == 0:
-# continue
-# rgbFace = None
-# alpha = ae
-# else:
-# rgbFace = rf,gf,bf
-# if ae==0:
-# alpha = af
-# gc.set_linewidth(0)
-# else:
-# # the draw_poly interface can't handle separate alphas for
-# # edge and face so we'll just use the maximum
-# alpha = max(af,ae)
-# gc.set_foreground( (re,ge,be), isRGB=True)
-# gc.set_linewidth( linewidths[i % Nlw] )
-# #print 'verts', zip(thisxverts, thisyverts)
-
-# gc.set_antialiased( antialiaseds[i % Naa] ) # Used for fill
only?
-# gc.set_alpha( alpha )
-# tverts = transform.seq_xy_tups(polyverts)
-# if usingOffsets:
-# xo,yo = transOffset.xy_tup(offsets[i % Noffsets])
-# tverts = [(x+xo,y+yo) for x,y in tverts]
-
-# self.draw_polygon(gc, rgbFace, tverts)
-
-# def draw_polygon(self, gc, rgbFace, points):
-# """
-# Draw a polygon using the GraphicsContext instance gc.
-# points is a len vertices tuple, each element
-# giving the x,y coords a vertex
-
-# If the color rgbFace is not None, fill the polygon with it
-# """
-# raise NotImplementedError
-
-# def draw_rectangle(self, gcEdge, rgbFace, x, y, width, height):
-# """
-# Draw a non-filled rectangle using the GraphicsContext instance
gcEdge,
-# with lower left at x,y with width and height.
-
-# If rgbFace is not None, fill the rectangle with it.
-# """
-# warnings.warn("draw_rectangle called",
warnings.PendingDeprecationWarning)
-# transform = transforms.Affine2D().scale(width, height).translate(x, y)
-# self.draw_path(gcEdge, Path.unit_rectangle(), transform, rgbFace)
-
-# def draw_regpoly_collection(
-# self, clipbox, offsets, transOffset, verts, sizes,
-# facecolors, edgecolors, linewidths, antialiaseds):
-# """
-# Draw a regular poly collection
-
-# offsets - is a sequence is x,y tuples
-# transOffset - maps this to display coords
-
-# verts - are the vertices of the regular polygon at the origin
-
-# sizes are the area of the circle that circumscribes the
-# polygon in points^2
-
-# facecolors and edgecolors are a sequence of RGBA tuples
-# linewidths are a sequence of linewidths
-# antialiaseds are a sequence of 0,1 integers whether to use aa
-# """
-# ## line and/or fill OK
-# gc = self.new_gc()
-# if clipbox is not None:
-# gc.set_clip_rectangle(clipbox.get_bounds())
-
-# xverts, yverts = zip(*verts)
-# xverts = npy.asarray(xverts)
-# yverts = npy.asarray(yverts)
-
-# Nface = len(facecolors)
-# Nedge = len(edgecolors)
-# Nlw = len(linewidths)
-# Naa = len(antialiaseds)
-# Nsizes = len(sizes)
-
-# for i, loc in enumerate(offsets):
-# xo,yo = transOffset.xy_tup(loc)
-# #print 'xo, yo', loc, (xo, yo)
-# scale = sizes[i % Nsizes]
-
-# thisxverts = scale*xverts + xo
-# thisyverts = scale*yverts + yo
-# #print 'xverts', xverts
-
-# linewidth = linewidths[i % Nlw]
-# rf,gf,bf,af = facecolors[i % Nface]
-# re,ge,be,ae = edgecolors[i % Nedge]
-# if af==0:
-# if ae==0 or linewidth == 0:
-# continue
-# rgbFace = None
-# alpha = ae
-# else:
-# rgbFace = rf,gf,bf
-# if ae==0:
-# alpha = af
-# gc.set_linewidth(0)
-# else:
-# # the draw_poly interface can't handle separate alphas for
-# # edge and face so we'll just use the maximum
-# alpha = max(af,ae)
-# gc.set_foreground( (re,ge,be), isRGB=True)
-# gc.set_linewidth( linewidths[i % Nlw] )
-# #print 'verts', zip(thisxverts, thisyverts)
-
-# gc.set_antialiased( antialiaseds[i % Naa] ) # Used for fill
only?
-# gc.set_alpha( alpha )
-# #print 'verts', zip(thisxverts, thisyverts)
-# self.draw_polygon(gc, rgbFace, zip(thisxverts, thisyverts))
-
-
-# def draw_tex(self, gc, x, y, s, prop, angle, ismath='TeX!'):
-# raise NotImplementedError
-
-# def draw_text(self, gc, x, y, s, prop, angle, ismath=False):
-# """
-# Draw the text.Text instance s at x,y (display coords) with font
-# properties instance prop at angle in degrees, using GraphicsContext
gc
-
-# **backend implementers note**
-
-# When you are trying to determine if you have gotten your bounding box
-# right (which is what enables the text layout/alignment to work
-# properly), it helps to change the line in text.py
-
-# if 0: bbox_artist(self, renderer)
-
-# to if 1, and then the actual bounding box will be blotted along with
-# your text.
-# """
-# raise NotImplementedError
-
def flipy(self):
"""return true if y small numbers are top for renderer
Is used for drawing text (text.py) and images (image.py) only
@@ -416,12 +149,6 @@
self._texmanager = TexManager()
return self._texmanager
- def get_text_extent(self, text): # is not used, can be removed?
- """
- Get the text extent in window coords
- """
- return transforms.lbwh_to_bbox(0,0,1,1) # your values here
-
def get_text_width_height_descent(self, s, prop, ismath):
"""
get the width and height, and the offset from the bottom to the
Modified: branches/transforms/lib/matplotlib/backends/backend_ps.py
===================================================================
--- branches/transforms/lib/matplotlib/backends/backend_ps.py 2007-10-16
13:45:59 UTC (rev 3954)
+++ branches/transforms/lib/matplotlib/backends/backend_ps.py 2007-10-16
14:17:53 UTC (rev 3955)
@@ -24,9 +24,9 @@
from matplotlib.mathtext import MathTextParser
from matplotlib._mathtext_data import uni2type1
from matplotlib.text import Text
+from matplotlib.path import Path
+from matplotlib.transforms import IdentityTransform
-from matplotlib.transforms import get_vec6_scales
-
import numpy as npy
import binascii
import re
@@ -141,7 +141,9 @@
self.fontsize = None
self.hatch = None
self.image_magnification = dpi/72.0
-
+ self._clip_paths = {}
+ self._path_collection_id = 0
+
self.fontd = {}
self.afmfontd = {}
self.used_characters = {}
@@ -247,7 +249,7 @@
hatchl cvi hatchgap idiv hatchgap mul
hatchgap
hatchr cvi hatchgap idiv hatchgap mul
- {hatcht moveto 0 hatchb hatcht sub rlineto}
+ {hatcht m 0 hatchb hatcht sub r }
for
stroke
grestore
@@ -330,18 +332,6 @@
font.set_size(size, 72.0)
return font
- def draw_arc(self, gc, rgbFace, x, y, width, height, angle1, angle2,
rotation):
- """
- Draw an arc centered at x,y with width and height and angles
- from 0.0 to 360.0
-
- If gcFace is not None, fill the arc slice with it. gcEdge
- is a GraphicsContext instance
- """
- ps = '%f %f translate\n%f rotate\n%f %f translate\n%s ellipse' % \
- (x, y, rotation, -x, -y, _nums_to_str(angle1, angle2, 0.5*width,
0.5*height, x, y))
- self._draw_ps(ps, gc, rgbFace, "arc")
-
def _rgba(self, im):
return im.as_rgba_str()
@@ -428,14 +418,47 @@
# unflip
im.flipud_out()
- def draw_line(self, gc, x0, y0, x1, y1):
+ def _convert_path(self, path, transform):
+ path = transform.transform_path(path)
+
+ ps = []
+ for points, code in path.iter_segments():
+ if code == Path.MOVETO:
+ ps.append("%g %g m" % tuple(points))
+ elif code == Path.LINETO:
+ ps.append("%g %g l" % tuple(points))
+ elif code == Path.CURVE3:
+ ps.append("%g %g %g %g %g %g c" %
+ (points[0], points[1],
+ points[0], points[1],
+ points[2], points[3]))
+ elif code == Path.CURVE4:
+ ps.append("%g %g %g %g %g %g c" % tuple(points))
+ elif code == Path.CLOSEPOLY:
+ ps.append("cl")
+ ps = "\n".join(ps)
+
+ return ps
+
+ def _get_clip_path(self, clippath, clippath_transform):
+ id = self._clip_paths.get((clippath, clippath_transform))
+ if id is None:
+ id = 'c%x' % len(self._clip_paths)
+ ps_cmd = ['/%s {' % id]
+ ps_cmd.append(self._convert_path(clippath, clippath_transform))
+ ps_cmd.extend(['clip', 'newpath', '} bind def\n'])
+ self._pswriter.write('\n'.join(ps_cmd))
+ self._clip_paths[(clippath, clippath_transform)] = id
+ return id
+
+ def draw_path(self, gc, path, transform, rgbFace=None):
"""
- Draw a single line from x0,y0 to x1,y1
- """
- ps = '%1.4g %1.4g m %1.4g %1.4g l'%(x0, y0, x1, y1)
- self._draw_ps(ps, gc, None, "line")
+ Draws a Path instance using the given affine transform.
+ """
+ ps = self._convert_path(path, transform)
+ self._draw_ps(ps, gc, rgbFace)
- def draw_markers(self, gc, path, rgbFace, x, y, transform):
+ def draw_markers(self, gc, marker_path, marker_trans, path, trans,
rgbFace=None):
"""
Draw the markers defined by path at each of the positions in x
and y. path coordinates are points, x and y coords will be
@@ -452,216 +475,82 @@
ps_color = '%1.3f %1.3f %1.3f setrgbcolor' % rgbFace
# construct the generic marker command:
- ps_cmd = ['gsave'] # dont want the translate to be global
- ps_cmd.append('newpath')
- ps_cmd.append('translate')
- while 1:
- code, xp, yp = path.vertex()
- if code == agg.path_cmd_stop:
- ps_cmd.append('closepath') # Hack, path_cmd_end_poly not found
- break
- elif code == agg.path_cmd_move_to:
- ps_cmd.append('%g %g m' % (xp,yp))
- elif code == agg.path_cmd_line_to:
- ps_cmd.append('%g %g l' % (xp,yp))
- elif code == agg.path_cmd_curve3:
- pass
- elif code == agg.path_cmd_curve4:
- pass
- elif code == agg.path_cmd_end_poly:
- pass
- ps_cmd.append('closepath')
- elif code == agg.path_cmd_mask:
- pass
- else:
- pass
- #print code
+ ps_cmd = ['/o {', 'gsave', 'newpath', 'translate'] # dont want the
translate to be global
+ ps_cmd.append(self._convert_path(marker_path, marker_trans))
if rgbFace:
- ps_cmd.append('gsave')
- ps_cmd.append(ps_color)
- ps_cmd.append('fill')
- ps_cmd.append('grestore')
+ ps_cmd.extend(['gsave', ps_color, 'fill', 'grestore'])
- ps_cmd.append('stroke')
- ps_cmd.append('grestore') # undo translate()
- ps_cmd = '\n'.join(ps_cmd)
+ ps_cmd.extend(['stroke', 'grestore', '} bind def'])
+
+ tpath = trans.transform_path(path)
+ for x, y in tpath.vertices:
+ ps_cmd.append("%1.3g %1.3g o" % (x, y))
- self.push_gc(gc, store=1)
+ ps = '\n'.join(ps_cmd)
+ self._draw_ps(ps, gc, rgbFace, fill=False, stroke=False)
- def drawone(x, y):
- try:
- xt, yt = transform.xy_tup((x, y))
- ret = '%g %g o' % (xt, yt)
- except ValueError:
- pass
- else:
- return ret
-
- step = 500
- start = 0
- end = step
-
- mask = npy.where(npy.isnan(x) + npy.isnan(y), 0, 1)
-
- cliprect = gc.get_clip_rectangle()
- if cliprect:
- write('gsave\n')
- xc,yc,wc,hc=cliprect
- write('%g %g %g %g clipbox\n' % (wc,hc,xc,yc))
- write(' '.join(['/o {', ps_cmd, '} bind def\n']))
- # Now evaluate the marker command at each marker location:
- while start < len(x):
- todraw = izip(x[start:end+1], y[start:end+1], mask[start:end+1])
- ps = [i for i in [drawone(xi,yi) for xi,yi,mi in todraw if mi] if
i]
- write('\n'.join(ps)+'\n')
- start = end
- end += step
- if cliprect: write('grestore\n')
-
- def draw_path(self,gc,rgbFace,path,trans):
- pass
-
- def draw_lines(self, gc, x, y, transform):
- """
- x and y are npy.equal length arrays, draw lines connecting each
- point in x, y
- """
- if debugPS: self._pswriter.write('% draw_lines \n')
-
+ def draw_path_collection(self, master_transform, cliprect, clippath,
+ clippath_trans, paths, all_transforms, offsets,
+ offsetTrans, facecolors, edgecolors, linewidths,
+ linestyles, antialiaseds):
write = self._pswriter.write
+
+ Npaths = len(paths)
+ Noffsets = len(offsets)
+ N = max(Npaths, Noffsets)
+ Ntransforms = min(len(all_transforms), N)
+ Ntpaths = max(Npaths, Ntransforms)
+ Nfacecolors = len(facecolors)
+ Nedgecolors = len(edgecolors)
+ Nlinewidths = len(linewidths)
+ Nlinestyles = len(linestyles)
+ Naa = len(antialiaseds)
- def drawone(x, y, skip):
- try:
- if skip: raise(ValueError)
- xt, yt = transform.xy_tup((x, y))
- ret = '%g %g %c' % (xt, yt, drawone.state)
- except ValueError:
- drawone.state = 'm'
- else:
- drawone.state = 'l'
- return ret
+ if (Nfacecolors == 0 and Nedgecolors == 0) or N == 0:
+ return
+
+ for i in range(Ntpaths):
+ path = paths[i % Npaths]
+ transform = all_transforms[i % Ntransforms]
+ if transform is None:
+ transform = IdentityTransform()
+ transform += master_transform
- step = 100000
- start = 0
- end = step
+ ps_cmd = ['/p%x_%x {' % (self._path_collection_id, i),
+ 'newpath', 'translate']
+ ps_cmd.append(self._convert_path(path, transform))
+ ps_cmd.extend(['} bind def\n'])
+ write('\n'.join(ps_cmd))
+
+ toffsets = offsetTrans.transform(offsets)
+
+ gc = self.new_gc()
- skip = npy.where(npy.isnan(x) + npy.isnan(y), 1, 0)
- points = zip(x,y,skip)
+ gc.set_clip_rectangle(cliprect)
+ if clippath is not None:
+ clippath = transforms.TransformedPath(clippath, clippath_trans)
+ gc.set_clippath(clippath)
+
+ if Nfacecolors == 0:
+ rgbFace = None
- self.push_gc(gc, store=1)
- cliprect = gc.get_clip_rectangle()
- if cliprect:
- write('gsave\n')
- xc,yc,wc,hc=cliprect
- write('%g %g %g %g clipbox\n' % (wc,hc,xc,yc))
- while start < len(points):
- drawone.state = 'm'
- ps = [i for i in [drawone(x,y,s) for x,y,s in points[start:end+1]]\
- if i]
- ps.append('stroke')
- write('\n'.join(ps)+'\n')
- start = end
- end += step
- if cliprect: write('grestore\n')
+ for i in xrange(N):
+ path_id = i % Ntpaths
+ xo, yo = toffsets[i % Noffsets]
+ if Nfacecolors:
+ rgbFace = facecolors[i % Nfacecolors]
+ if Nedgecolors:
+ gc.set_foreground(edgecolors[i % Nedgecolors])
+ gc.set_linewidth(linewidths[i % Nlinewidths])
+ gc.set_dashes(*linestyles[i % Nlinestyles])
+ gc.set_antialiased(antialiaseds[i % Naa])
+ ps = "%g %g p%x_%x" % (xo, yo, self._path_collection_id, path_id)
+ self._draw_ps(ps, gc, rgbFace)
- def draw_lines_old(self, gc, x, y, transform=None):
- """
- x and y are npy.equal length arrays, draw lines connecting each
- point in x, y
- """
- if debugPS: self._pswriter.write('% draw_lines \n')
-
- write = self._pswriter.write
-
- mask = npy.where(npy.isnan(x) + npy.isnan(y), 0, 1)
- if transform: # this won't be called if draw_markers is hidden
- if transform.need_nonlinear():
- x,y,mask = transform.nonlinear_only_numerix(x, y, returnMask=1)
-
- # a,b,c,d,tx,ty affine which transforms x and y into ps coordinates
- a,b,c,d,tx,ty = transform.as_vec6_val()
-
- xo = a*x+c*y+tx
- yo = b*x+d*y+ty
- x,y = xo,yo
-
- self.push_gc(gc, store=1)
-
- cliprect = gc.get_clip_rectangle()
- if cliprect:
- write('gsave\n')
- xc,yc,wc,hc=cliprect
- write('%g %g %g %g clipbox\n' % (wc,hc,xc,yc))
-
- steps = 50
- start = 0
- end = steps
- points = zip(x,y)
-
- while start < len(x):
- # npy.put moveto on all the bad data and on the first good
- # point after the bad data
- codes = [('m','l')[int(i)] for i in mask]
- ind = npy.nonzero(mask[start:end+1]==0)+1
- if len(ind):
- if ind[-1]>=len(codes):
- ind = ind[:-1]
- for i in ind:
- codes[i] = 'm'
- # npy.put a moveto on the first point, regardless
- codes[0] = 'm'
-
- thisx = x[start:end+1]
- thisy = y[start:end+1]
- to_draw = izip(thisx, thisy, codes, mask)
- if not to_draw:
- break
-
- ps = ["%g %g %c" % (xp, yp, c) for xp, yp, c, m in to_draw if m]
- if transform:
- ps.append('stroke')
- write('\n'.join(ps)+'\n')
- else:
- self._draw_ps("\n".join(ps)+'\n', gc, None)
- start = end
- end += steps
- if transform:
- if cliprect: write("grestore\n")
-
- def draw_point(self, gc, x, y):
- """
- Draw a single point at x,y
- """
- # TODO: is there a better way to draw points in postscript?
- # (use a small circle?)
- self.draw_line(gc, x, y, x+1, y+1)
-
- def draw_polygon(self, gc, rgbFace, points):
- """
- Draw a polygon. points is a len vertices tuple, each element
- giving the x,y coords a vertex
-
- If rgbFace is not None, fill the poly with it. gc
- is a GraphicsContext instance
- """
- ps = ["%s m\n" % _nums_to_str(*points[0])]
- ps.extend([ "%s l\n" % _nums_to_str(x, y) for x,y in points[1:] ])
- ps.append("closepath")
- self._draw_ps(''.join(ps), gc, rgbFace, "polygon")
-
- def draw_rectangle(self, gc, rgbFace, x, y, width, height):
- """
- Draw a rectangle with lower left at x,y with width and height.
-
- If gcFace is not None, fill the rectangle with it. gcEdge
- is a GraphicsContext instance
- """
- # TODO: use rectstroke
- ps = '%s box' % _nums_to_str(width, height, x, y)
- self._draw_ps(ps, gc, rgbFace, "rectangle")
-
+ self._path_collection_id += 1
+
def draw_tex(self, gc, x, y, s, prop, angle, ismath='TeX!'):
"""
draw a Text instance
@@ -853,7 +742,6 @@
""" % locals()
self._pswriter.write(ps)
-
def draw_mathtext(self, gc,
x, y, s, prop, angle):
"""
@@ -875,68 +763,57 @@
""" % locals()
self._pswriter.write(ps)
- def _draw_ps(self, ps, gc, rgbFace, command=None):
+ def _draw_ps(self, ps, gc, rgbFace, fill=True, stroke=True, command=None):
"""
Emit the PostScript sniplet 'ps' with all the attributes from 'gc'
applied. 'ps' must consist of PostScript commands to construct a path.
"""
# local variable eliminates all repeated attribute lookups
write = self._pswriter.write
- write('gsave\n')
+ # write('gsave\n')
if debugPS and command:
write("% "+command+"\n")
- cliprect = gc.get_clip_rectangle()
- self.set_color(*gc.get_rgb())
self.set_linewidth(gc.get_linewidth())
jint = gc.get_joinstyle()
self.set_linejoin(jint)
cint = gc.get_capstyle()
self.set_linecap(cint)
self.set_linedash(*gc.get_dashes())
-
+
+ cliprect = gc.get_clip_rectangle()
if cliprect:
- x,y,w,h=cliprect
+ x,y,w,h=cliprect.bounds
write('gsave\n%1.4g %1.4g %1.4g %1.4g clipbox\n' % (w,h,x,y))
+ clippath, clippath_trans = gc.get_clip_path()
+ if clippath:
+ id = self._get_clip_path(clippath, clippath_trans)
+ write('gsave\n%s\n' % id)
+
# Jochen, is the strip necessary? - this could be a honking big string
write(ps.strip())
write("\n")
- if rgbFace:
+
+ if rgbFace is not None and fill:
#print 'rgbface', rgbFace
write("gsave\n")
- self.set_color(store=0, *rgbFace)
+ self.set_color(store=0, *rgbFace[:3])
write("fill\ngrestore\n")
hatch = gc.get_hatch()
if (hatch):
self.set_hatch(hatch)
- if self.linewidth > 0:
+ if self.linewidth > 0 and stroke:
+ self.set_color(*gc.get_rgb()[:3])
write("stroke\n")
+ if clippath:
+ write("grestore\n")
if cliprect:
write("grestore\n")
- write('grestore\n')
- def push_gc(self, gc, store=1):
- """
- Push the current onto stack, with the exception of the clip box, which
- must be isolated in a gsave/grestore pair.
- """
- # local variable eliminates all repeated attribute lookups
- write = self._pswriter.write
+ #write('grestore\n')
- self.set_color(store=store, *gc.get_rgb())
- self.set_linewidth(gc.get_linewidth(), store=store)
- self.set_linejoin(gc.get_joinstyle(), store=store)
- self.set_linecap(gc.get_capstyle(), store=store)
- self.set_linedash(store=store, *gc.get_dashes())
-
-## cliprect = gc.get_clip_rectangle()
-## if cliprect:
-## x,y,w,h=cliprect
-## write('%1.3f %1.3f %1.3f %1.3f clipbox\n' % (w,h,x,y))
-
-## write("\n")
-
+
class GraphicsContextPS(GraphicsContextBase):
def get_capstyle(self):
return {'butt':0,
@@ -1044,7 +921,7 @@
xo = 72*0.5*(paperWidth - width)
yo = 72*0.5*(paperHeight - height)
- l, b, w, h = self.figure.bbox.get_bounds()
+ l, b, w, h = self.figure.bbox.bounds
llx = xo
lly = yo
urx = llx + w
@@ -1521,33 +1398,6 @@
# http://www.mactech.com/articles/mactech/Vol.09/09.04/PostscriptTutorial/
# http://www.math.ubc.ca/people/faculty/cass/graphics/text/www/
#
-# Some comments about the implementation:
-#
-# Drawing ellipses:
-#
-# ellipse adds a counter-clockwise segment of an elliptical arc to the
-# current path. The ellipse procedure takes six operands: the x and y
-# coordinates of the center of the ellipse (the center is defined as
-# the point of intersection of the major and minor axes), the
-# ``radius'' of the ellipse in the x direction, the ``radius'' of the
-# ellipse in the y direction, the starting angle of the elliptical arc
-# and the ending angle of the elliptical arc.
-#
-# The basic strategy used in drawing the ellipse is to translate to
-# the center of the ellipse, scale the user coordinate system by the x
-# and y radius values, and then add a circular arc, centered at the
-# origin with a 1 unit radius to the current path. We will be
-# transforming the user coordinate system with the translate and
-# rotate operators to add the elliptical arc segment but we don't want
-# these transformations to affect other parts of the program. In other
-# words, we would like to localize the effect of the transformations.
-# Usually the gsave and grestore operators would be ideal candidates
-# for this task. Unfortunately gsave and grestore are inappropriate
-# for this situation because we cannot save the arc segment that we
-# have added to the path. Instead we will localize the effect of the
-# transformations by saving the current transformation matrix and
-# restoring it explicitly after we have added the elliptical arc to
-# the path.
# The usage comments use the notation of the operator summary
# in the PostScript Language reference manual.
@@ -1558,28 +1408,22 @@
"/l { lineto } bind def",
# x y *r* -
"/r { rlineto } bind def",
+ # x1 y1 x2 y2 x y *c* -
+ "/c { curveto } bind def",
+ # *closepath* -
+ "/cl { closepath } bind def",
# w h x y *box* -
"""/box {
m
1 index 0 r
0 exch r
neg 0 r
- closepath
+ cl
} bind def""",
# w h x y *clipbox* -
"""/clipbox {
box
clip
newpath
- } bind def""",
- # angle1 angle2 rx ry x y *ellipse* -
- """/ellipse {
- newpath
- matrix currentmatrix 7 1 roll
- translate
- scale
- 0 0 1 5 3 roll arc
- setmatrix
- closepath
} bind def"""
]
Modified: branches/transforms/lib/matplotlib/cbook.py
===================================================================
--- branches/transforms/lib/matplotlib/cbook.py 2007-10-16 13:45:59 UTC (rev
3954)
+++ branches/transforms/lib/matplotlib/cbook.py 2007-10-16 14:17:53 UTC (rev
3955)
@@ -174,6 +174,7 @@
def __str__(self):
return '<a list of %d %s objects>' % (len(self), self.type)
+# MGDTODO: This is very incomplete
def strip_math(s):
'remove latex formatting from mathtext'
remove = (r'\rm', '\cal', '\tt', '\it', '\\', '{', '}')
Modified: branches/transforms/lib/matplotlib/collections.py
===================================================================
--- branches/transforms/lib/matplotlib/collections.py 2007-10-16 13:45:59 UTC
(rev 3954)
+++ branches/transforms/lib/matplotlib/collections.py 2007-10-16 14:17:53 UTC
(rev 3955)
@@ -167,7 +167,9 @@
self.update_scalarmappable()
clippath, clippath_trans = self.get_transformed_clip_path_and_affine()
-
+ if clippath_trans is not None:
+ clippath_trans = clippath_trans.frozen()
+
# MGDTODO: This may benefit from using TransformedPath
if not transform.is_affine:
paths = [transform.transform_path_non_affine(path) for path in
paths]
@@ -175,9 +177,9 @@
if not transOffset.is_affine:
offsets = transOffset.transform_non_affine(offsets)
transOffset = transOffset.get_affine()
-
+
renderer.draw_path_collection(
- transform, self.clipbox, clippath, clippath_trans,
+ transform.frozen(), self.clipbox, clippath, clippath_trans,
paths, self.get_transforms(),
npy.asarray(offsets, npy.float_), transOffset,
self._facecolors, self._edgecolors, self._linewidths,
Modified: branches/transforms/lib/matplotlib/lines.py
===================================================================
--- branches/transforms/lib/matplotlib/lines.py 2007-10-16 13:45:59 UTC (rev
3954)
+++ branches/transforms/lib/matplotlib/lines.py 2007-10-16 14:17:53 UTC (rev
3955)
@@ -458,7 +458,7 @@
if funcname != '_draw_nothing':
tpath, affine =
self._transformed_path.get_transformed_path_and_affine()
lineFunc = getattr(self, funcname)
- lineFunc(renderer, gc, tpath, affine)
+ lineFunc(renderer, gc, tpath, affine.frozen())
if self._marker is not None:
gc = renderer.new_gc()
@@ -470,7 +470,7 @@
if funcname != '_draw_nothing':
tpath, affine =
self._transformed_path.get_transformed_path_and_affine()
markerFunc = getattr(self, funcname)
- markerFunc(renderer, gc, tpath, affine)
+ markerFunc(renderer, gc, tpath, affine.frozen())
renderer.close_group('line2d')
Modified: branches/transforms/lib/matplotlib/path.py
===================================================================
--- branches/transforms/lib/matplotlib/path.py 2007-10-16 13:45:59 UTC (rev
3954)
+++ branches/transforms/lib/matplotlib/path.py 2007-10-16 14:17:53 UTC (rev
3955)
@@ -142,7 +142,7 @@
return self._vertices
vertices = property(_get_vertices)
- def iter_endpoints(self):
+ def iter_segments(self):
"""
Iterates over all of the endpoints in the path. Unlike
iterating directly over the vertices array, curve control
@@ -151,15 +151,20 @@
i = 0
NUM_VERTICES = self.NUM_VERTICES
vertices = self.vertices
- for code in self.codes:
+ codes = self.codes
+
+ while i < len(vertices):
+ code = codes[i]
if code == self.CLOSEPOLY:
+ yield [], code
i += 1
+ elif code == self.STOP:
+ return
else:
num_vertices = NUM_VERTICES[code]
- i += num_vertices - 1
- yield vertices[i]
- i += 1
-
+ yield vertices[i:i+num_vertices].flatten(), code
+ i += num_vertices
+
def transformed(self, transform):
"""
Return a transformed copy of the path.
Modified: branches/transforms/lib/matplotlib/transforms.py
===================================================================
--- branches/transforms/lib/matplotlib/transforms.py 2007-10-16 13:45:59 UTC
(rev 3954)
+++ branches/transforms/lib/matplotlib/transforms.py 2007-10-16 14:17:53 UTC
(rev 3955)
@@ -822,6 +822,12 @@
raise TypeError(
"Can not add Transform to object of type '%s'" % type(other))
+ def __array__(self):
+ """
+ Used by C/C++ -based backends to get at the array matrix data.
+ """
+ return self.frozen().__array__()
+
def transform(self, values):
"""
Performs the transformation on the given array of values.
This was sent by the SourceForge.net collaborative development platform, the
world's largest Open Source development site.
-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems? Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
_______________________________________________
Matplotlib-checkins mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/matplotlib-checkins