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
Matplotlib-checkins@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-checkins

Reply via email to