Revision: 4185
          http://matplotlib.svn.sourceforge.net/matplotlib/?rev=4185&view=rev
Author:   mdboom
Date:     2007-11-09 08:35:15 -0800 (Fri, 09 Nov 2007)

Log Message:
-----------
Get wx backend working with wxGraphicsContext drawing.

Modified Paths:
--------------
    branches/transforms/lib/matplotlib/backend_bases.py
    branches/transforms/lib/matplotlib/backends/backend_wx.py

Modified: branches/transforms/lib/matplotlib/backend_bases.py
===================================================================
--- branches/transforms/lib/matplotlib/backend_bases.py 2007-11-09 16:33:58 UTC 
(rev 4184)
+++ branches/transforms/lib/matplotlib/backend_bases.py 2007-11-09 16:35:15 UTC 
(rev 4185)
@@ -67,8 +67,6 @@
         override this method in order to draw the marker only once and
         reuse it multiple times.
         """
-        ctx = gc.ctx
-        ctx.new_path()
         tpath = trans.transform_path(path)
         for x, y in tpath.vertices:
             self.draw_path(gc, marker_path,

Modified: branches/transforms/lib/matplotlib/backends/backend_wx.py
===================================================================
--- branches/transforms/lib/matplotlib/backends/backend_wx.py   2007-11-09 
16:33:58 UTC (rev 4184)
+++ branches/transforms/lib/matplotlib/backends/backend_wx.py   2007-11-09 
16:35:15 UTC (rev 4185)
@@ -94,7 +94,7 @@
 
 cvs_id = '$Id$'
 
-import sys, os, os.path, math, StringIO
+import sys, os, os.path, math, StringIO, weakref
 
 # Debugging settings here...
 # Debug level set here. If the debug level is less than 5, information
@@ -154,7 +154,9 @@
 from matplotlib.artist import Artist
 from matplotlib.cbook import exception_to_str
 from matplotlib.figure import Figure
+from matplotlib.path import Path
 from matplotlib.text import _process_text_args, Text
+from matplotlib.transforms import Affine2D
 from matplotlib.widgets import SubplotTool
 from matplotlib import rcParams
 
@@ -261,10 +263,14 @@
         #return 1, 1
         if ismath: s = self.strip_math(s)
 
-        if self.gc is None: gc = self.new_gc()
+        if self.gc is None:
+            gc = self.new_gc()
+        else:
+            gc = self.gc
+        gfx_ctx = gc.gfx_ctx
         font = self.get_wx_font(s, prop)
-        self.gc.SetFont(font)
-        w, h, descent, leading = self.gc.GetFullTextExtent(s)
+        gfx_ctx.SetFont(font, wx.BLACK)
+        w, h, descent, leading = gfx_ctx.GetFullTextExtent(s)
 
         return w, h, descent
 
@@ -272,97 +278,49 @@
         'return the canvas width and height in display coords'
         return self.width, self.height
 
-
-    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 rgbFace is present, fill the figure in this colour, otherwise
-        it is not filled.
-        """
+    def handle_clip_rectangle(self, gc):
+        new_bounds = gc.get_clip_rectangle()
+        if new_bounds is not None:
+            new_bounds = new_bounds.bounds
+        gfx_ctx = gc.gfx_ctx
+        if gfx_ctx._lastcliprect != new_bounds:
+            gfx_ctx._lastcliprect = new_bounds
+            if new_bounds is None:
+                gfx_ctx.ResetClip()
+            else:
+                gfx_ctx.Clip(*new_bounds)
+    
+    [EMAIL PROTECTED]
+    def convert_path(gfx_ctx, tpath):
+        wxpath = gfx_ctx.CreatePath()
+        for points, code in tpath.iter_segments():
+            if code == Path.MOVETO:
+                wxpath.MoveToPoint(*points)
+            elif code == Path.LINETO:
+                wxpath.AddLineToPoint(*points)
+            elif code == Path.CURVE3:
+                wxpath.AddQuadCurveToPoint(*points)
+            elif code == Path.CURVE4:
+                wxpath.AddCurveToPoint(*points)
+            elif code == Path.CLOSEPOLY:
+                wxpath.CloseSubpath()
+        return wxpath
+    convert_path = staticmethod(convert_path)
+        
+    def draw_path(self, gc, path, transform, rgbFace=None):
         gc.select()
-        assert gc.Ok(), "wxMemoryDC not OK to use"
-        # wxPython requires upper left corner of bounding rectange for ellipse
-        # Theoretically you don't need the int() below, but it seems to make
-        # rounding of arc centre point more accurate in screen co-ordinates
-        ulX = x - int(width/2)
-        ulY = self.height - int(y + (height/2))
+        self.handle_clip_rectangle(gc)
+        gfx_ctx = gc.gfx_ctx
+        transform = transform + Affine2D().scale(1.0, -1.0).translate(0.0, 
self.height)
+        tpath = transform.transform_path(path)
+        wxpath = self.convert_path(gfx_ctx, tpath)
         if rgbFace is not None:
-            r,g,b = self._to_wx_rgb(rgbFace)
-            new_brush =wx.Brush(wx.Colour(r,g,b), wx.SOLID)
-            gc.SetBrush(new_brush)
+            gfx_ctx.SetBrush(wx.Brush(gc.get_wxcolour(rgbFace)))
+            gfx_ctx.DrawPath(wxpath)
         else:
-            gc.SetBrush(wx.TRANSPARENT_BRUSH)
-        gc.DrawEllipticArc(int(ulX), int(ulY), int(width)+1, int(height)+1,
-                           int(angle1), int(angle2))
+            gfx_ctx.StrokePath(wxpath)
         gc.unselect()
 
-    def draw_line(self, gc, x1, y1, x2, y2):
-        """
-        Draw a single line from x1,y1 to x2,y2
-        """
-        DEBUG_MSG("draw_line()", 1, self)
-        gc.select()
-        gc.DrawLine(int(x1), self.height - int(y1),
-                    int(x2), self.height - int(y2))
-        gc.unselect()
-
-    def draw_lines(self, gc, x, y):
-        """
-        x and y are equal length arrays, draw lines connecting each
-        point in x, y
-        """
-        gc.select()
-        assert gc.Ok(), "wxMemoryDC not OK to use"
-        assert len(x) == len(y), "draw_lines() x and y must be of equal length"
-        gc.DrawLines([wx.Point(int(x[i]), self.height - int(y[i])) for i in 
range(len(x))])
-        gc.unselect()
-
-    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
-        """
-        gc.select()
-        assert gc.Ok(), "wxMemoryDC not OK to use"
-        points = [(int(x), self.height - int(y)) for x,y in points]
-        if rgbFace is not None:
-            r,g,b = self._to_wx_rgb(rgbFace)
-            new_brush =wx.Brush(wx.Colour(r,g,b), wx.SOLID)
-            gc.SetBrush(new_brush)
-        else:
-            gc.SetBrush(wx.TRANSPARENT_BRUSH)
-        gc.DrawPolygon(points)
-        gc.unselect()
-
-    def draw_rectangle(self, gc, rgbFace, x, y, width, height):
-        """
-        Draw a rectangle at lower left x,y with width and height
-        If filled=True, fill the rectangle with the gc foreground
-        gc is a GraphicsContext instance
-        """
-        # wxPython uses rectangle from TOP left!
-        gc.select()
-        assert gc.Ok(), "wxMemoryDC not OK to use"
-        if rgbFace is not None:
-            r,g,b = self._to_wx_rgb(rgbFace)
-            new_brush =wx.Brush(wx.Colour(r,g,b), wx.SOLID)
-            gc.SetBrush(new_brush)
-        else:
-            gc.SetBrush(wx.TRANSPARENT_BRUSH)
-        gc.DrawRectangle(int(x), self.height - int(height + y),
-                                 int(math.ceil(width)), int(math.ceil(height)))
-        gc.unselect()
-
-    def draw_point(self, gc, x, y):
-        """
-        Draw a single point at x,y
-        """
-        gc.select()
-        assert gc.Ok(), "wxMemoryDC not OK to use"
-        gc.DrawPoint(int(x), self.height - int(y))
-        gc.unselect()
-
     def draw_text(self, gc, x, y, s, prop, angle, ismath):
         """
         Render the matplotlib.text.Text instance
@@ -371,21 +329,23 @@
         if ismath: s = self.strip_math(s)
         DEBUG_MSG("draw_text()", 1, self)
         gc.select()
-
+        self.handle_clip_rectangle(gc)
+        gfx_ctx = gc.gfx_ctx
+        
         font = self.get_wx_font(s, prop)
-        gc.SetFont(font)
-        assert gc.Ok(), "wxMemoryDC not OK to use"
+        color = gc.get_wxcolour(gc.get_rgb())
+        gfx_ctx.SetFont(font, color)
 
         w, h, d = self.get_text_width_height_descent(s, prop, ismath)
         x = int(x)
         y = int(y-h)
 
-        if angle!=0:
-            try: gc.DrawRotatedText(s, x, y, angle)
-            except:
-                verbose.print_error(exception_to_str('WX rotated text failed'))
+        if angle == 0.0:
+            gfx_ctx.DrawText(s, x, y)
         else:
-            gc.DrawText(s, x, y)
+            angle = angle * (math.pi / 180.0)
+            gfx_ctx.DrawRotatedText(s, x, y, angle)
+            
         gc.unselect()
 
     def new_gc(self):
@@ -395,7 +355,6 @@
         DEBUG_MSG('new_gc()', 2, self)
         self.gc = GraphicsContextWx(self.bitmap, self)
         self.gc.select()
-        assert self.gc.Ok(), "wxMemoryDC not OK to use"
         self.gc.unselect()
         return self.gc
 
@@ -446,14 +405,7 @@
 
         return font
 
-    def _to_wx_rgb(self, rgb):
-        """Takes a colour value and returns a tuple (r,g,b) suitable
-        for instantiating a wx.Colour."""
-        r, g, b = rgb
-        return (int(r * 255), int(g * 255), int(b * 255))
 
-
-
     def points_to_pixels(self, points):
         """
         convert point measures to pixes using dpi and the pixels per
@@ -461,15 +413,15 @@
         """
         return points*(PIXELS_PER_INCH/72.0*self.dpi/72.0)
 
-class GraphicsContextWx(GraphicsContextBase, wx.MemoryDC):
+class GraphicsContextWx(GraphicsContextBase):
     """
     The graphics context provides the color, line styles, etc...
 
-    In wxPython this is done by wrapping a wxDC object and forwarding the
-    appropriate calls to it. Notice also that colour and line styles are
-    mapped on the wx.Pen() member of the wxDC. This means that we have some
-    rudimentary pen management here.
-
+    This class stores a reference to a wxMemoryDC, and a
+    wxGraphicsContext that draws to it.  Creating a wxGraphicsContext
+    seems to be fairly heavy, so these objects are cached based on the
+    bitmap object that is passed in.
+    
     The base GraphicsContext stores colors as a RGB tuple on the unit
     interval, eg, (0.5, 0.0, 1.0).  wxPython uses an int interval, but
     since wxPython colour management is rather simple, I have not chosen
@@ -487,26 +439,30 @@
                   'dashed':    wx.SHORT_DASH,
                   'dashdot':   wx.DOT_DASH,
                   'dotted':    wx.DOT }
-    _lastWxDC = None
-
+    _cache = weakref.WeakKeyDictionary()
+    
     def __init__(self, bitmap, renderer):
         GraphicsContextBase.__init__(self)
-        wx.MemoryDC.__init__(self)
         #assert self.Ok(), "wxMemoryDC not OK to use"
         DEBUG_MSG("__init__()", 1, self)
-        # Make sure (belt and braces!) that existing wxDC is not selected to
-        # to a bitmap.
-        if GraphicsContextWx._lastWxDC != None:
 
-            GraphicsContextWx._lastWxDC.SelectObject(wx.NullBitmap)
-
-        self.SelectObject(bitmap)
+        dc, gfx_ctx = self._cache.get(bitmap, (None, None))
+        if dc is None:
+            print "new dc"
+            dc = wx.MemoryDC()
+            dc.SelectObject(bitmap)
+            gfx_ctx = wx.GraphicsContext.Create(dc)
+            gfx_ctx._lastcliprect = None
+            self._cache[bitmap] = dc, gfx_ctx
+        
         self.bitmap = bitmap
-        self.SetPen(wx.Pen('BLACK', 1, wx.SOLID))
-        self._style=wx.SOLID
+        self.dc = dc
+        self.gfx_ctx = gfx_ctx
+        self._pen = wx.Pen('BLACK', 1, wx.SOLID)
+        gfx_ctx.SetPen(self._pen)
+        self._style = wx.SOLID
         self.renderer = renderer
-        GraphicsContextWx._lastWxDC = self
-
+        
     def select(self):
         """
         Select the current bitmap into this wxDC instance
@@ -524,23 +480,6 @@
             self.SelectObject(wx.NullBitmap)
             self.IsSelected = False
 
-    def set_clip_rectangle(self, rect):
-        """
-        Destroys previous clipping region and defines a new one.
-        """
-        DEBUG_MSG("set_clip_rectangle()", 1, self)
-        self.select()
-        l,b,w,h = rect
-        # this appears to be version dependent'
-        if hasattr(self, 'SetClippingRegionXY'):
-            clipfunc = getattr(self, 'SetClippingRegionXY')
-        else:
-            clipfunc = getattr(self, 'SetClippingRegion')
-
-        clipfunc(int(l), self.renderer.height - int(b+h),
-                 int(w), int(h))
-        self.unselect()
-
     def set_foreground(self, fg, isRGB=None):
         """
         Set the foreground color.  fg can be a matlab format string, a
@@ -556,12 +495,8 @@
         self.select()
         GraphicsContextBase.set_foreground(self, fg, isRGB)
 
-        pen = self.GetPen()
-        pen.SetColour(self.get_wxcolour())
-        self.SetPen(pen)
-        brush =wx.Brush(self.get_wxcolour(), wx.SOLID)
-        self.SetBrush(brush)
-        self.SetTextForeground(self.get_wxcolour())
+        self._pen.SetColour(self.get_wxcolour(self.get_rgb()))
+        self.gfx_ctx.SetPen(self._pen)
         self.unselect()
 
     def set_graylevel(self, frac):
@@ -573,11 +508,8 @@
         DEBUG_MSG("set_graylevel()", 1, self)
         self.select()
         GraphicsContextBase.set_graylevel(self, frac)
-        pen = self.GetPen()
-        pen.SetColour(self.get_wxcolour())
-        self.SetPen(pen)
-        brush =wx.Brush(self.get_wxcolour(), wx.SOLID)
-        self.SetBrush(brush)
+        self._pen.SetColour(self.get_wxcolour(self.get_rgb()))
+        self.gfx_ctx.SetPen(self._pen)
         self.unselect()
 
     def set_linewidth(self, w):
@@ -588,11 +520,10 @@
         self.select()
         if w>0 and w<1: w = 1
         GraphicsContextBase.set_linewidth(self, w)
-        pen = self.GetPen()
         lw = int(self.renderer.points_to_pixels(self._linewidth))
         if lw==0: lw = 1
-        pen.SetWidth(lw)
-        self.SetPen(pen)
+        self._pen.SetWidth(lw)
+        self.gfx_ctx.SetPen(self._pen)
         self.unselect()
 
     def set_capstyle(self, cs):
@@ -602,9 +533,8 @@
         DEBUG_MSG("set_capstyle()", 1, self)
         self.select()
         GraphicsContextBase.set_capstyle(self, cs)
-        pen = self.GetPen()
-        pen.SetCap(GraphicsContextWx._capd[self._capstyle])
-        self.SetPen(pen)
+        self._pen.SetCap(GraphicsContextWx._capd[self._capstyle])
+        self.gfx_ctx.SetPen(self._pen)
         self.unselect()
 
     def set_joinstyle(self, js):
@@ -614,9 +544,8 @@
         DEBUG_MSG("set_joinstyle()", 1, self)
         self.select()
         GraphicsContextBase.set_joinstyle(self, js)
-        pen = self.GetPen()
-        pen.SetJoin(GraphicsContextWx._joind[self._joinstyle])
-        self.SetPen(pen)
+        self._pen.SetJoin(GraphicsContextWx._joind[self._joinstyle])
+        self.gfx_ctx.SetPen(self._pen)
         self.unselect()
 
     def set_linestyle(self, ls):
@@ -629,25 +558,32 @@
         try:
             self._style = GraphicsContextWx._dashd_wx[ls]
         except KeyError:
-            self._style=wx.LONG_DASH# Style not used elsewhere...
+            self._style = wx.LONG_DASH# Style not used elsewhere...
 
         # On MS Windows platform, only line width of 1 allowed for dash lines
         if wx.Platform == '__WXMSW__':
             self.set_linewidth(1)
 
-        pen = self.GetPen()
-        pen.SetStyle(self._style)
-        self.SetPen(pen)
+        self._pen.SetStyle(self._style)
+        self.gfx_ctx.SetPen(self._pen)
         self.unselect()
 
-    def get_wxcolour(self):
+    def get_wxcolour(self, color):
         """return a wx.Colour from RGB format"""
         DEBUG_MSG("get_wx_color()", 1, self)
-        r, g, b = self.get_rgb()
-        r *= 255
-        g *= 255
-        b *= 255
-        return wx.Colour(red=int(r), green=int(g), blue=int(b))
+        if len(color) == 3:
+            r, g, b = color
+            r *= 255
+            g *= 255
+            b *= 255
+            return wx.Colour(red=int(r), green=int(g), blue=int(b))
+        else:
+            r, g, b, a = color
+            r *= 255
+            g *= 255
+            b *= 255
+            a *= 255
+            return wx.Colour(red=int(r), green=int(g), blue=int(b), 
alpha=int(a))
 
 class FigureCanvasWx(FigureCanvasBase, wx.Panel):
     """
@@ -783,7 +719,7 @@
         self.macros = {} # dict from wx id to seq of macros
 
         self.Printer_Init()
-
+        
     def Destroy(self, *args, **kwargs):
         wx.Panel.Destroy(self, *args, **kwargs)
 
@@ -938,6 +874,9 @@
         self.gui_repaint()
 
 
+    def draw_idle(self, *args, **kwargs):
+        pass
+        
     def draw(self, repaint=True):
         """
         Render the figure using RendererWx instance renderer, or using a
@@ -1016,7 +955,7 @@
     def _print_image(self, filename, filetype, *args, **kwargs):
         origBitmap   = self.bitmap
 
-        l,b,width,height = self.figure.bbox.get_bounds()
+        l,b,width,height = self.figure.bbox.bounds
         width = int(math.ceil(width))
         height = int(math.ceil(height))
 


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