1- """
2- A fully functional, do-nothing backend intended as a template for backend
3- writers. It is fully functional in that you can select it as a backend e.g.
4- with ::
5-
6- import matplotlib
7- matplotlib.use("template")
1+ """Pygame Matplotlib Backend.
82
9- and your program will (should!) run without error, though no output is
10- produced. This provides a starting point for backend writers; you can
11- selectively implement drawing methods (`~.RendererTemplate.draw_path`,
12- `~.RendererTemplate.draw_image`, etc.) and slowly see your figure come to life
13- instead having to have a full blown implementation before getting any results.
14-
15- Copy this file to a directory outside of the Matplotlib source tree, somewhere
16- where Python can import it (by adding the directory to your ``sys.path`` or by
17- packaging it as a normal Python package); if the backend is importable as
18- ``import my.backend`` you can then select it using ::
3+ A functional backend for using matplotlib in pygame display.
4+ You can select it as a backend using
5+ with ::
196
207 import matplotlib
21- matplotlib.use("module://my.backend")
22-
23- If your backend implements support for saving figures (i.e. has a `print_xyz`
24- method), you can register it as the default handler for a given file type::
25-
26- from matplotlib.backend_bases import register_backend
27- register_backend('xyz', 'my_backend', 'XYZ File Format')
28- ...
29- plt.savefig("figure.xyz")
8+ matplotlib.use("'module://pygame_matplotlib.backend_pygame'")
309"""
3110import numpy as np
3211from matplotlib .transforms import Affine2D
3615 FigureCanvasBase , FigureManagerBase , GraphicsContextBase , RendererBase )
3716from matplotlib .figure import Figure
3817from matplotlib .path import Path
39- import math
4018
4119class FigureSurface (pygame .Surface , Figure ):
4220 def __init__ (self , * args , ** kwargs ):
@@ -45,13 +23,10 @@ def __init__(self, *args, **kwargs):
4523 pygame .Surface .__init__ (self , self .bbox .size )
4624 self .fill ('white' )
4725
48- class RendererTemplate (RendererBase ):
49- """
50- The renderer handles drawing/rendering operations.
26+ class RendererPygame (RendererBase ):
27+ """The renderer handles drawing/rendering operations.
5128
52- This is a minimal do-nothing class that can be used to get started when
53- writing a new backend. Refer to `backend_bases.RendererBase` for
54- documentation of the methods.
29+ The draw methods convert maptplotlib into pygame.draw .
5530 """
5631
5732 def __init__ (self , dpi ):
@@ -74,7 +49,9 @@ def draw_path(self, gc, path, transform, rgbFace=None):
7449
7550 transform += transfrom_to_pygame_axis
7651
77- draw_func = pygame .draw .aaline if gc .get_antialiased () else pygame .draw .line
52+ draw_func = ( # Select whether antialiased will be used in pygame
53+ pygame .draw .aaline if gc .get_antialiased () else pygame .draw .line
54+ )
7855
7956 previous_point = (0 , 0 )
8057 for point , code in path .iter_segments (transform ):
@@ -88,29 +65,7 @@ def draw_path(self, gc, path, transform, rgbFace=None):
8865 elif code == Path .CURVE3 :
8966 end_point = point [2 :]
9067 control_point = point [:2 ]
91- # Creates the bounding rectangle for the arc
92- # rect = pygame.Rect(
93- # x:=min(previous_point[0], end_point[0]),
94- # y:=min(previous_point[1], end_point[1]),
95- # w:=max(previous_point[0], end_point[0]) - x,
96- # h:=max(previous_point[1], end_point[1]) - y,
97- # )
98- # start_angle = math.atan(abs(
99- # (x - control_point[0])
100- # / (y- control_point[1])
101- # ))
102- # stop_angle = math.atan(abs(
103- # (x + w - control_point[0])
104- # / (y + h - control_point[1])
105- # ))
106- # Find the vectors to get the angle of the arc
107- #c_p = (control_point[0] - previous_point[0], control_point[1] - previous_point[1])
108- #c_e = (control_point[0] - end_point[0], control_point[1] - end_point[1])
109- #arc_angle = math.acos(
110- # ((c_p[0] * c_e[0]) + (c_p[1] * c_e[1]))
111- # / (math.hypot(*c_p) * math.hypot(*c_e))
112- #)
113- # The focals are at the intersection
68+ # TODO: use bezier arcs instead
11469 draw_func (
11570 self .surface , color , previous_point , end_point , linewidth
11671 )
@@ -144,10 +99,16 @@ def draw_path(self, gc, path, transform, rgbFace=None):
14499# pass
145100
146101 def draw_image (self , gc , x , y , im ):
147- print (type (im ))
148- print (x , y )
149- img_surf = pygame .image .frombuffer (np .ascontiguousarray (np .flip (im , axis = 0 )), (im .shape [1 ], im .shape [0 ]), 'RGBA' )
150- self .surface .blit (img_surf , (x , self .surface .get_height () - y - im .shape [0 ]))
102+ img_surf = pygame .image .frombuffer (
103+ # Need to flip the image as pygame starts top left
104+ np .ascontiguousarray (np .flip (im , axis = 0 )),
105+ (im .shape [1 ], im .shape [0 ]), 'RGBA'
106+ )
107+ self .surface .blit (
108+ img_surf ,
109+ # Image starts top left
110+ (x , self .surface .get_height () - y - im .shape [0 ])
111+ )
151112
152113 def draw_text (self , gc , x , y , s , prop , angle , ismath = False , mtext = None ):
153114 # make sure font module is initialized
@@ -161,7 +122,8 @@ def draw_text(self, gc, x, y, s, prop, angle, ismath=False, mtext=None):
161122 s , gc .get_antialiased (), [val * 255 for val in gc .get_rgb ()]
162123 )
163124 if mtext is not None :
164- # Reads the position of the mtext, but could use relative position to 0 instead
125+ # Reads the position of the mtext
126+ # but could use relative position to 0 instead
165127 x , y , _ , _ = mtext .get_window_extent ().bounds
166128 width , height = myfont .size (s )
167129 # Needs to resize to center
@@ -182,18 +144,18 @@ def get_text_width_height_descent(self, s, prop, ismath):
182144
183145 def new_gc (self ):
184146 # docstring inherited
185- return GraphicsContextTemplate ()
147+ return GraphicsContextPygame ()
186148
187149 def points_to_pixels (self , points ):
188- # if backend doesn't have dpi, e.g., postscript or svg
150+ # points are pixels in pygame
189151 return points
190152 # elif backend assumes a value for pixels_per_inch
191153 #return points/72.0 * self.dpi.get() * pixels_per_inch/72.0
192154 # else
193155 #return points/72.0 * self.dpi.get()
194156
195157
196- class GraphicsContextTemplate (GraphicsContextBase ):
158+ class GraphicsContextPygame (GraphicsContextBase ):
197159 """
198160 The graphics context provides the color, line styles, etc... See the cairo
199161 and postscript backends for examples of mapping the graphics context
@@ -258,14 +220,12 @@ def new_figure_manager(num, *args, FigureClass=FigureSurface, **kwargs):
258220
259221def new_figure_manager_given_figure (num , figure ):
260222 """Create a new figure manager instance for the given figure."""
261- canvas = FigureCanvasTemplate (figure )
262- manager = FigureManagerTemplate (canvas , num )
223+ canvas = FigureCanvasPygame (figure )
224+ manager = FigureManagerPygame (canvas , num )
263225 return manager
264226
265227
266-
267-
268- class FigureCanvasTemplate (FigureCanvasBase ):
228+ class FigureCanvasPygame (FigureCanvasBase ):
269229 """
270230 The canvas the figure renders into. Calls the draw and print fig
271231 methods, creates the renderers, etc.
@@ -294,7 +254,7 @@ def draw(self):
294254 deferred work (like computing limits auto-limits and tick
295255 values) that users may want access to before saving to disk.
296256 """
297- renderer = RendererTemplate (self .figure .dpi )
257+ renderer = RendererPygame (self .figure .dpi )
298258 renderer .surface = self .figure
299259 self .figure .draw (renderer )
300260
@@ -321,7 +281,7 @@ def get_default_filetype(self):
321281 return 'foo'
322282
323283
324- class FigureManagerTemplate (FigureManagerBase ):
284+ class FigureManagerPygame (FigureManagerBase ):
325285 """
326286 Helper class for pyplot mode, wraps everything up into a neat bundle.
327287
@@ -333,10 +293,9 @@ def show(self):
333293 pygame .init ()
334294 main_display = pygame .display .set_mode (
335295 self .canvas .figure .get_size (), # Size matches figure size
336- pygame .RESIZABLE # Allow resizing
337296 )
338297
339- FPS = 144
298+ FPS = 60
340299 FramePerSec = pygame .time .Clock ()
341300
342301 self .canvas .figure .canvas .draw ()
@@ -360,5 +319,5 @@ def show(self):
360319#
361320########################################################################
362321
363- FigureCanvas = FigureCanvasTemplate
364- FigureManager = FigureManagerTemplate
322+ FigureCanvas = FigureCanvasPygame
323+ FigureManager = FigureManagerPygame
0 commit comments