Revision: 4521
          http://matplotlib.svn.sourceforge.net/matplotlib/?rev=4521&view=rev
Author:   mdboom
Date:     2007-11-30 07:06:56 -0800 (Fri, 30 Nov 2007)

Log Message:
-----------
Get Gtk backend working.

Modified Paths:
--------------
    branches/transforms/lib/matplotlib/axis.py
    branches/transforms/lib/matplotlib/backends/backend_gdk.py
    branches/transforms/lib/matplotlib/path.py
    branches/transforms/src/_path.cpp

Modified: branches/transforms/lib/matplotlib/axis.py
===================================================================
--- branches/transforms/lib/matplotlib/axis.py  2007-11-30 14:43:11 UTC (rev 
4520)
+++ branches/transforms/lib/matplotlib/axis.py  2007-11-30 15:06:56 UTC (rev 
4521)
@@ -87,7 +87,7 @@
         self._size = size
 
         self._padPixels = self.figure.dpi * self._pad * (1/72.0)
-        
+
         self.tick1line = self._get_tick1line()
         self.tick2line = self._get_tick2line()
         self.gridline = self._get_gridline()
@@ -97,7 +97,7 @@
         self.label2 = self._get_text2()
 
         self.update_position(loc)
-        
+
         self.gridOn = gridOn
         self.tick1On = tick1On
         self.tick2On = tick2On
@@ -114,7 +114,7 @@
         #self.tick2line.set_clip_path(clippath, transform)
         self.gridline.set_clip_path(clippath, transform)
     set_clip_path.__doc__ = Artist.set_clip_path.__doc__
-    
+
     def contains(self, mouseevent):
         """Test whether the mouse event occured in the Tick marks.
 
@@ -189,7 +189,7 @@
         """
         self.label1.set_text(s)
     set_label = set_label1
-        
+
     def set_label2(self, s):
         """
         Set the text of ticklabel2
@@ -209,7 +209,7 @@
     def set_view_interval(self, vmin, vmax, ignore=False):
         raise NotImplementedError('Derived must override')
 
-    
+
 class XTick(Tick):
     """
     Contains all the Artists needed to make an x tick - the tick line,
@@ -223,7 +223,7 @@
         # x in data coords, y in axes coords
         #t =  Text(
         trans, vert, horiz = 
self.axes.get_xaxis_text1_transform(self._padPixels)
-        
+
         t =  TextWithDash(
             x=0, y=0,
             fontproperties=FontProperties(size=rcParams['xtick.labelsize']),
@@ -320,10 +320,10 @@
         else:
             Vmin, Vmax = self.get_view_interval()
             self.axes.viewLim.intervalx = min(vmin, Vmin), max(vmax, Vmax)
-    
+
     def get_minpos(self):
         return self.axes.dataLim.minposx
-    
+
     def get_data_interval(self):
         'return the Interval instance for this axis data limits'
         return self.axes.dataLim.intervalx
@@ -428,7 +428,7 @@
 
         self._loc = loc
 
-        
+
     def get_view_interval(self):
         'return the Interval instance for this axis view limits'
         return self.axes.viewLim.intervaly
@@ -439,10 +439,10 @@
         else:
             Vmin, Vmax = self.get_view_interval()
             self.axes.viewLim.intervaly = min(vmin, Vmin), max(vmax, Vmax)
-    
+
     def get_minpos(self):
         return self.axes.dataLim.minposy
-    
+
     def get_data_interval(self):
         'return the Interval instance for this axis data limits'
         return self.axes.dataLim.intervaly
@@ -465,7 +465,7 @@
     """
     LABELPAD = 5
     OFFSETTEXTPAD = 3
-    
+
     def __str__(self):
         return str(self.__class__).split('.')[-1] \
             + "(%d,%d)"%self.axes.transAxes.xy_tup((0,0))
@@ -493,23 +493,23 @@
         self.majorTicks = []
         self.minorTicks = []
         self.pickradius = pickradius
-        
+
         self.cla()
         self.set_scale('linear')
-        
+
     def get_transform(self):
         return self._scale.get_transform()
 
     def get_scale(self):
         return self._scale.name
-    
+
     def set_scale(self, value, **kwargs):
         self._scale = scale_factory(value, self, **kwargs)
         self._scale.set_default_locators_and_formatters(self)
 
     def limit_range_for_scale(self, vmin, vmax):
         return self._scale.limit_range_for_scale(vmin, vmax, self.get_minpos())
-        
+
     def get_children(self):
         children = [self.label]
         majorticks = self.get_major_ticks()
@@ -547,7 +547,7 @@
         self.minorTicks.extend([self._get_tick(major=False)])
         self._lastNumMajorTicks = 1
         self._lastNumMinorTicks = 1
-        
+
         self.converter = None
         self.units = None
         self.set_units(None)
@@ -555,17 +555,17 @@
     def set_clip_path(self, clippath, transform=None):
         Artist.set_clip_path(self, clippath, transform)
         majorticks = self.get_major_ticks()
-        minorticks = self.get_minor_ticks()        
+        minorticks = self.get_minor_ticks()
         for child in self.majorTicks + self.minorTicks:
             child.set_clip_path(clippath, transform)
-        
+
     def get_view_interval(self):
         'return the Interval instance for this axis view limits'
         raise NotImplementedError('Derived must override')
 
     def set_view_interval(self, vmin, vmax, ignore=False):
         raise NotImplementedError('Derived must override')
-    
+
     def get_data_interval(self):
         'return the Interval instance for this axis data limits'
         raise NotImplementedError('Derived must override')
@@ -573,7 +573,7 @@
     def set_data_interval(self):
         'Set the axis data limits'
         raise NotImplementedError('Derived must override')
-    
+
     def _set_artist_props(self, a):
         if a is None: return
         a.set_figure(self.figure)
@@ -774,7 +774,7 @@
             for i in range(numticks - len(self.majorTicks)):
                 tick = self._get_tick(major=True)
                 self.majorTicks.append(tick)
-            
+
         if self._lastNumMajorTicks < numticks:
             protoTick = self.majorTicks[0]
             for i in range(self._lastNumMajorTicks, len(self.majorTicks)):
@@ -798,7 +798,7 @@
             for i in range(numticks - len(self.minorTicks)):
                 tick = self._get_tick(major=False)
                 self.minorTicks.append(tick)
-            
+
         if self._lastNumMinorTicks < numticks:
             protoTick = self.minorTicks[0]
             for i in range(self._lastNumMinorTicks, len(self.minorTicks)):
@@ -1039,7 +1039,7 @@
 class XAxis(Axis):
     __name__ = 'xaxis'
     axis_name = 'x'
-            
+
     def contains(self,mouseevent):
         """Test whether the mouse event occured in the x axis.
         """
@@ -1120,7 +1120,7 @@
                 bbox = Bbox.union(bboxes)
                 bottom = bbox.y0
             self.label.set_position( (x, bottom - 
self.LABELPAD*self.figure.dpi / 72.0))
-            
+
         else:
             if not len(bboxes2):
                 top = self.axes.bbox.ymax
@@ -1141,7 +1141,7 @@
             bbox = Bbox.union(bboxes)
             bottom = bbox.y0
         self.offsetText.set_position((x, 
bottom-self.OFFSETTEXTPAD*self.figure.dpi/72.0))
-       
+
     def set_ticks_position(self, position):
         """
         Set the ticks position (top, bottom, both, default or none)
@@ -1224,10 +1224,10 @@
         else:
             Vmin, Vmax = self.get_view_interval()
             self.axes.viewLim.intervalx = min(vmin, Vmin), max(vmax, Vmax)
-    
+
     def get_minpos(self):
         return self.axes.dataLim.minposx
-    
+
     def get_data_interval(self):
         'return the Interval instance for this axis data limits'
         return self.axes.dataLim.intervalx
@@ -1244,7 +1244,7 @@
 class YAxis(Axis):
     __name__ = 'yaxis'
     axis_name = 'y'
-            
+
     def contains(self,mouseevent):
         """Test whether the mouse event occurred in the y axis.
 
@@ -1331,7 +1331,7 @@
                 left = bbox.x0
 
             self.label.set_position( (left-self.LABELPAD*self.figure.dpi/72.0, 
y))
-           
+
         else:
             if not len(bboxes2):
                 right = self.axes.bbox.xmax
@@ -1349,7 +1349,7 @@
         x,y = self.offsetText.get_position()
         top = self.axes.bbox.ymax
         self.offsetText.set_position((x, 
top+self.OFFSETTEXTPAD*self.figure.dpi/72.0))
-       
+
     def set_offset_position(self, position):
         assert position == 'left' or position == 'right'
 
@@ -1445,10 +1445,10 @@
         else:
             Vmin, Vmax = self.get_view_interval()
             self.axes.viewLim.intervaly = min(vmin, Vmin), max(vmax, Vmax)
-    
+
     def get_minpos(self):
         return self.axes.dataLim.minposy
-    
+
     def get_data_interval(self):
         'return the Interval instance for this axis data limits'
         return self.axes.dataLim.intervaly

Modified: branches/transforms/lib/matplotlib/backends/backend_gdk.py
===================================================================
--- branches/transforms/lib/matplotlib/backends/backend_gdk.py  2007-11-30 
14:43:11 UTC (rev 4520)
+++ branches/transforms/lib/matplotlib/backends/backend_gdk.py  2007-11-30 
15:06:56 UTC (rev 4521)
@@ -25,7 +25,7 @@
 from matplotlib.cbook import is_string_like, enumerate
 from matplotlib.figure import Figure
 from matplotlib.mathtext import MathTextParser
-
+from matplotlib.transforms import Affine2D
 from matplotlib.backends._backend_gdk import pixbuf_get_pixels_array
 
 
@@ -81,23 +81,25 @@
         """
         self.width, self.height = width, height
 
-    def draw_arc(self, gc, rgbFace, x, y, width, height, angle1, angle2, 
rotation):
-        x, y = int(x-0.5*width), self.height-int(y+0.5*height)
-        w, h = int(width)+1, int(height)+1
-        a1, a2 = int(angle1*64), int(angle2*64)
+    def draw_path(self, gc, path, transform, rgbFace=None):
+        transform = transform + Affine2D(). \
+            scale(1.0, -1.0).translate(0, self.height)
+        polygons = path.to_polygons(transform)
+        for polygon in polygons:
+            # draw_polygon won't take an arbitrary sequence -- it must be a 
list
+            # of tuples
+            polygon = [(int(round(x)), int(round(y))) for x, y in polygon]
+            if rgbFace is not None:
+                saveColor = gc.gdkGC.foreground
+                gc.gdkGC.foreground = gc.rgb_to_gdk_color(rgbFace)
+                self.gdkDrawable.draw_polygon(gc.gdkGC, True, polygon)
+                gc.gdkGC.foreground = saveColor
+            if gc.gdkGC.line_width > 0:
+                self.gdkDrawable.draw_lines(gc.gdkGC, polygon)
 
-        if rgbFace:
-            saveColor = gc.gdkGC.foreground
-            gc.gdkGC.foreground = gc.rgb_to_gdk_color(rgbFace)
-            self.gdkDrawable.draw_arc(gc.gdkGC, True, x, y, w, h, a1, a2)
-            gc.gdkGC.foreground = saveColor
-        if gc.gdkGC.line_width > 0:
-            self.gdkDrawable.draw_arc(gc.gdkGC, False, x, y, w, h, a1, a2)
-
-
-    def draw_image(self, x, y, im, bbox):
+    def draw_image(self, x, y, im, bbox, clippath=None, clippath_trans=None):
         if bbox != None:
-            l,b,w,h = bbox.get_bounds()
+            l,b,w,h = bbox.bounds
             #rectangle = (int(l), self.height-int(b+h),
             #             int(w), int(h))
             # set clip rect?
@@ -135,48 +137,6 @@
         im.flipud_out()
 
 
-    def draw_line(self, gc, x1, y1, x2, y2):
-        if gc.gdkGC.line_width > 0:
-            self.gdkDrawable.draw_line(gc.gdkGC, int(x1), self.height-int(y1),
-                                   int(x2), self.height-int(y2))
-
-
-    def draw_lines(self, gc, x, y, transform=None):
-        if gc.gdkGC.line_width > 0:
-            x = x.astype(npy.int16)
-            y = self.height - y.astype(npy.int16)
-            self.gdkDrawable.draw_lines(gc.gdkGC, zip(x,y))
-
-
-    def draw_point(self, gc, x, y):
-        self.gdkDrawable.draw_point(gc.gdkGC, int(x), self.height-int(y))
-
-
-    def draw_polygon(self, gc, rgbFace, points):
-        points = [(int(x), self.height-int(y)) for x,y in points]
-        if rgbFace:
-            saveColor = gc.gdkGC.foreground
-            gc.gdkGC.foreground = gc.rgb_to_gdk_color(rgbFace)
-            self.gdkDrawable.draw_polygon(gc.gdkGC, True, points)
-            gc.gdkGC.foreground = saveColor
-        if gc.gdkGC.line_width > 0:
-            self.gdkDrawable.draw_polygon(gc.gdkGC, False, points)
-
-
-    def draw_rectangle(self, gc, rgbFace, x, y, width, height):
-        x, y = int(x), self.height-int(y+height)
-        #x, y = int(x), self.height-int(math.ceil(y+height))
-        w, h = int(math.ceil(width)), int(math.ceil(height))
-
-        if rgbFace:
-            saveColor = gc.gdkGC.foreground
-            gc.gdkGC.foreground = gc.rgb_to_gdk_color(rgbFace)
-            self.gdkDrawable.draw_rectangle(gc.gdkGC, True, x, y, w, h)
-            gc.gdkGC.foreground = saveColor
-        if gc.gdkGC.line_width > 0:
-            self.gdkDrawable.draw_rectangle(gc.gdkGC, False, x, y, w, h)
-
-
     def draw_text(self, gc, x, y, s, prop, angle, ismath):
         x, y = int(x), int(y)
 
@@ -200,7 +160,7 @@
 
     def _draw_mathtext(self, gc, x, y, s, prop, angle):
         ox, oy, width, height, descent, font_image, used_characters = \
-            self.mathtext_parser.parse(s, self.dpi.get(), prop)
+            self.mathtext_parser.parse(s, self.dpi, prop)
 
         if angle==90:
             width, height = height, width
@@ -213,7 +173,7 @@
 
         # a numpixels by num fonts array
         Xall = npy.zeros((N,1), npy.uint8)
-        
+
         image_str = font_image.as_str()
         Xall[:,0] = npy.fromstring(image_str, npy.uint8)
 
@@ -310,12 +270,12 @@
         # two (not one) layouts are created for every text item s (then they
         # are cached) - why?
 
-        key = self.dpi.get(), s, hash(prop)
+        key = self.dpi, s, hash(prop)
         value = self.layoutd.get(key)
         if value != None:
             return value
 
-        size = prop.get_size_in_points() * self.dpi.get() / 96.0
+        size = prop.get_size_in_points() * self.dpi / 96.0
         size = round(size)
 
         font_str = '%s, %s %i' % (prop.get_name(), prop.get_style(), size,)
@@ -341,7 +301,7 @@
     def get_text_width_height_descent(self, s, prop, ismath):
         if ismath:
             ox, oy, width, height, descent, font_image, used_characters = \
-                self.mathtext_parser.parse(s, self.dpi.get(), prop)
+                self.mathtext_parser.parse(s, self.dpi, prop)
             return width, height, descent
 
         layout, inkRect, logicalRect = self._get_pango_layout(s, prop)
@@ -386,9 +346,9 @@
         return an allocated gtk.gdk.Color
         """
         try:
-            return self._cached[rgb]
+            return self._cached[tuple(rgb)]
         except KeyError:
-            color = self._cached[rgb] = \
+            color = self._cached[tuple(rgb)] = \
                     self._cmap.alloc_color(
                         int(rgb[0]*65535),int(rgb[1]*65535),int(rgb[2]*65535))
             return color
@@ -404,14 +364,15 @@
 
     def set_clip_rectangle(self, rectangle):
         GraphicsContextBase.set_clip_rectangle(self, rectangle)
-        l,b,w,h = rectangle
+        if rectangle is None:
+            return
+        l,b,w,h = rectangle.bounds
         rectangle = (int(l), self.renderer.height-int(b+h)+1,
                      int(w), int(h))
         #rectangle = (int(l), self.renderer.height-int(b+h),
         #             int(w+1), int(h+2))
         self.gdkGC.set_clip_rectangle(rectangle)
 
-
     def set_dashes(self, dash_offset, dash_list):
         GraphicsContextBase.set_dashes(self, dash_offset, dash_list)
 
@@ -486,7 +447,7 @@
 
     def print_png(self, filename, *args, **kwargs):
         return self._print_image(filename, 'png')
-    
+
     def _print_image(self, filename, format, *args, **kwargs):
         width, height = self.get_width_height()
         pixmap = gtk.gdk.Pixmap (None, width, height, depth=24)
@@ -500,4 +461,6 @@
                                  0, 0, 0, 0, width, height)
 
         pixbuf.save(filename, format)
-        
+
+    def get_default_filetype(self):
+        return 'png'

Modified: branches/transforms/lib/matplotlib/path.py
===================================================================
--- branches/transforms/lib/matplotlib/path.py  2007-11-30 14:43:11 UTC (rev 
4520)
+++ branches/transforms/lib/matplotlib/path.py  2007-11-30 15:06:56 UTC (rev 
4521)
@@ -12,7 +12,7 @@
 
 from matplotlib._path import point_in_path, get_path_extents, \
     point_in_path_collection, get_path_collection_extents, \
-    path_in_path, path_intersects_path
+    path_in_path, path_intersects_path, convert_path_to_polygons
 from matplotlib.cbook import simple_linear_interpolation
 
 KAPPA = 4.0 * (npy.sqrt(2) - 1) / 3.0
@@ -210,19 +210,17 @@
         If transform is not None, the path will be transformed before
         performing the test.
         """
-        if transform is None:
-            from transforms import IdentityTransform
-            transform = IdentityTransform()
-        return point_in_path(point[0], point[1], self, transform.frozen())
+        if transform is not None:
+            transform = transform.frozen()
+        return point_in_path(point[0], point[1], self, transform)
 
     def contains_path(self, path, transform=None):
         """
         Returns True if this path completely contains the given path.
         """
-        if transform is None:
-            from transforms import IdentityTransform
-            transform = IdentityTransform()
-        return path_in_path(self, IdentityTransform(), path, transform)
+        if transform is not None:
+            transform = transform.frozen()
+        return path_in_path(self, None, path, transform)
 
     def get_extents(self, transform=None):
         """
@@ -232,9 +230,9 @@
         algorithm will take into account the curves and deal with
         control points appropriately.
         """
-        from transforms import Affine2D, Bbox
-        if transform is None:
-            transform = Affine2D()
+        from transforms import Bbox
+        if transform is not None:
+            transform = transform.frozen()
         return Bbox(get_path_extents(self, transform))
 
     def intersects_path(self, other):
@@ -267,6 +265,23 @@
             new_codes = None
         return Path(vertices, new_codes)
 
+    def to_polygons(self, transform=None):
+        """
+        Convert this path to a list of polygons.  Each polygon is an
+        Nx2 array of vertices.  In other words, each polygon has no
+        "move to" instructions or curves.
+        """
+        if transform is not None:
+            transform = transform.frozen()
+        # Deal with the common and simple case
+        if self.codes is None:
+            if len(self.vertices):
+                return [transform.transform(self.vertices)]
+            return []
+        # Deal with the case where there are curves and/or multiple
+        # subpaths (using extension code)
+        return convert_path_to_polygons(self, transform)
+
     _unit_rectangle = None
     [EMAIL PROTECTED]
     def unit_rectangle(cls):

Modified: branches/transforms/src/_path.cpp
===================================================================
--- branches/transforms/src/_path.cpp   2007-11-30 14:43:11 UTC (rev 4520)
+++ branches/transforms/src/_path.cpp   2007-11-30 15:06:56 UTC (rev 4521)
@@ -48,6 +48,8 @@
                            "count_bboxes_overlapping_bbox(bbox, bboxes)");
         add_varargs_method("path_intersects_path", 
&_path_module::path_intersects_path,
                            "path_intersects_path(p1, p2)");
+        add_varargs_method("convert_path_to_polygons", 
&_path_module::convert_path_to_polygons,
+                           "convert_path_to_polygons(path, trans)");
 
         initialize("Helper functions for paths");
     }
@@ -66,6 +68,7 @@
     Py::Object affine_transform(const Py::Tuple& args);
     Py::Object count_bboxes_overlapping_bbox(const Py::Tuple& args);
     Py::Object path_intersects_path(const Py::Tuple& args);
+    Py::Object convert_path_to_polygons(const Py::Tuple& args);
 };
 
 //
@@ -137,7 +140,7 @@
             code = path.vertex(&x, &y);
 
             // The following cases denote the beginning on a new subpath
-            if (code == agg::path_cmd_stop || 
+            if (code == agg::path_cmd_stop ||
                (code & agg::path_cmd_end_poly) == agg::path_cmd_end_poly)
             {
                 x = sx;
@@ -234,7 +237,7 @@
     double x = Py::Float(args[0]);
     double y = Py::Float(args[1]);
     PathIterator path(args[2]);
-    agg::trans_affine trans = py_to_agg_transformation_matrix(args[3]);
+    agg::trans_affine trans = py_to_agg_transformation_matrix(args[3], false);
 
     if (::point_in_path(x, y, path, trans))
         return Py::Int(1);
@@ -623,9 +626,9 @@
     args.verify_length(4);
 
     PathIterator a(args[0]);
-    agg::trans_affine atrans = py_to_agg_transformation_matrix(args[1]);
+    agg::trans_affine atrans = py_to_agg_transformation_matrix(args[1], false);
     PathIterator b(args[2]);
-    agg::trans_affine btrans = py_to_agg_transformation_matrix(args[3]);
+    agg::trans_affine btrans = py_to_agg_transformation_matrix(args[3], false);
 
     return Py::Int(::path_in_path(a, atrans, b, btrans));
 }
@@ -1091,6 +1094,68 @@
     return Py::Int(1);
 }
 
+void _add_polygon(Py::List& polygons, const std::vector<double>& polygon) {
+    if (polygon.size() == 0)
+       return;
+    npy_intp polygon_dims[] = { polygon.size() / 2, 2, 0 };
+    double* polygon_data = new double[polygon.size()];
+    memcpy(polygon_data, &polygon[0], polygon.size() * sizeof(double));
+    PyArrayObject* polygon_array = NULL;
+    polygon_array = (PyArrayObject*)PyArray_SimpleNewFromData
+       (2, polygon_dims, PyArray_DOUBLE, polygon_data);
+    if (!polygon_array)
+    {
+       delete[] polygon_data;
+       throw Py::RuntimeError("Error creating polygon array");
+    }
+    polygons.append(Py::Object((PyObject*)polygon_array));
+}
+
+Py::Object _path_module::convert_path_to_polygons(const Py::Tuple& args)
+{
+    typedef agg::conv_transform<PathIterator> transformed_path_t;
+    typedef agg::conv_curve<transformed_path_t> curve_t;
+
+    typedef std::vector<double> vertices_t;
+
+    args.verify_length(2);
+
+    PathIterator path(args[0]);
+    agg::trans_affine trans = py_to_agg_transformation_matrix(args[1], false);
+
+    transformed_path_t tpath(path, trans);
+    curve_t curve(tpath);
+
+    Py::List polygons;
+    vertices_t polygon;
+    double x, y;
+    unsigned code;
+
+    while ((code = curve.vertex(&x, &y)) != agg::path_cmd_stop)
+    {
+       if ((code & agg::path_cmd_end_poly) == agg::path_cmd_end_poly) {
+           if (polygon.size() >= 2)
+           {
+               polygon.push_back(polygon[0]);
+               polygon.push_back(polygon[1]);
+               _add_polygon(polygons, polygon);
+           }
+           polygon.clear();
+       } else {
+           if (code == agg::path_cmd_move_to) {
+               _add_polygon(polygons, polygon);
+               polygon.clear();
+           }
+           polygon.push_back(x);
+           polygon.push_back(y);
+       }
+    }
+
+    _add_polygon(polygons, polygon);
+
+    return polygons;
+}
+
 extern "C"
     DL_EXPORT(void)
     init_path(void)


This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.

-------------------------------------------------------------------------
SF.Net email is sponsored by: The Future of Linux Business White Paper
from Novell.  From the desktop to the data center, Linux is going
mainstream.  Let it simplify your IT future.
http://altfarm.mediaplex.com/ad/ck/8857-50307-18918-4
_______________________________________________
Matplotlib-checkins mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/matplotlib-checkins

Reply via email to