Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 641f097

Browse files
committed
WxCairo backend.
1 parent a3d1c46 commit 641f097

5 files changed

Lines changed: 164 additions & 127 deletions

File tree

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
Cairo rendering for Qt canvases
2-
-------------------------------
1+
Cairo rendering for Qt and WX canvases
2+
--------------------------------------
33

4-
The new ``Qt4Cairo`` and ``Qt5Cairo`` backends allow Qt canvases to use Cairo
5-
rendering instead of Agg.
4+
The new ``Qt4Cairo``, ``Qt5Cairo``, and ``WXCairo`` backends allow Qt and Wx
5+
canvases to use Cairo rendering instead of Agg.

lib/matplotlib/backends/backend_wx.py

Lines changed: 102 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -547,7 +547,7 @@ def get_wxcolour(self, color):
547547
alpha=int(a))
548548

549549

550-
class FigureCanvasWx(FigureCanvasBase, wx.Panel):
550+
class _FigureCanvasWxBase(FigureCanvasBase, wx.Panel):
551551
"""
552552
The FigureCanvas contains the figure and does event handling.
553553
@@ -708,23 +708,11 @@ def draw_idle(self):
708708
"""
709709
DEBUG_MSG("draw_idle()", 1, self)
710710
self._isDrawn = False # Force redraw
711-
712711
# Triggering a paint event is all that is needed to defer drawing
713712
# until later. The platform will send the event when it thinks it is
714713
# a good time (usually as soon as there are no other events pending).
715714
self.Refresh(eraseBackground=False)
716715

717-
def draw(self, drawDC=None):
718-
"""
719-
Render the figure using RendererWx instance renderer, or using a
720-
previously defined renderer if none is specified.
721-
"""
722-
DEBUG_MSG("draw()", 1, self)
723-
self.renderer = RendererWx(self.bitmap, self.figure.dpi)
724-
self.figure.draw(self.renderer)
725-
self._isDrawn = True
726-
self.gui_repaint(drawDC=drawDC)
727-
728716
def new_timer(self, *args, **kwargs):
729717
"""
730718
Creates a new backend-specific subclass of
@@ -837,95 +825,14 @@ def gui_repaint(self, drawDC=None, origin='WX'):
837825
filetypes['xpm'] = 'X pixmap'
838826

839827
def print_figure(self, filename, *args, **kwargs):
840-
# Use pure Agg renderer to draw
841-
FigureCanvasBase.print_figure(self, filename, *args, **kwargs)
842-
# Restore the current view; this is needed because the
843-
# artist contains methods rely on particular attributes
844-
# of the rendered figure for determining things like
845-
# bounding boxes.
828+
super(_FigureCanvasWxBase, self).print_figure(
829+
filename, *args, **kwargs)
830+
# Restore the current view; this is needed because the artist contains
831+
# methods rely on particular attributes of the rendered figure for
832+
# determining things like bounding boxes.
846833
if self._isDrawn:
847834
self.draw()
848835

849-
def print_bmp(self, filename, *args, **kwargs):
850-
return self._print_image(filename, wx.BITMAP_TYPE_BMP, *args, **kwargs)
851-
852-
if not _has_pil:
853-
def print_jpeg(self, filename, *args, **kwargs):
854-
return self._print_image(filename, wx.BITMAP_TYPE_JPEG,
855-
*args, **kwargs)
856-
print_jpg = print_jpeg
857-
858-
def print_pcx(self, filename, *args, **kwargs):
859-
return self._print_image(filename, wx.BITMAP_TYPE_PCX, *args, **kwargs)
860-
861-
def print_png(self, filename, *args, **kwargs):
862-
return self._print_image(filename, wx.BITMAP_TYPE_PNG, *args, **kwargs)
863-
864-
if not _has_pil:
865-
def print_tiff(self, filename, *args, **kwargs):
866-
return self._print_image(filename, wx.BITMAP_TYPE_TIF,
867-
*args, **kwargs)
868-
print_tif = print_tiff
869-
870-
def print_xpm(self, filename, *args, **kwargs):
871-
return self._print_image(filename, wx.BITMAP_TYPE_XPM, *args, **kwargs)
872-
873-
def _print_image(self, filename, filetype, *args, **kwargs):
874-
origBitmap = self.bitmap
875-
876-
l, b, width, height = self.figure.bbox.bounds
877-
width = int(math.ceil(width))
878-
height = int(math.ceil(height))
879-
880-
self.bitmap = wxc.EmptyBitmap(width, height)
881-
882-
renderer = RendererWx(self.bitmap, self.figure.dpi)
883-
884-
gc = renderer.new_gc()
885-
886-
self.figure.draw(renderer)
887-
888-
# image is the object that we call SaveFile on.
889-
image = self.bitmap
890-
# set the JPEG quality appropriately. Unfortunately, it is only
891-
# possible to set the quality on a wx.Image object. So if we
892-
# are saving a JPEG, convert the wx.Bitmap to a wx.Image,
893-
# and set the quality.
894-
if filetype == wx.BITMAP_TYPE_JPEG:
895-
jpeg_quality = kwargs.get('quality',
896-
rcParams['savefig.jpeg_quality'])
897-
image = self.bitmap.ConvertToImage()
898-
image.SetOption(wx.IMAGE_OPTION_QUALITY, str(jpeg_quality))
899-
900-
# Now that we have rendered into the bitmap, save it
901-
# to the appropriate file type and clean up
902-
if isinstance(filename, six.string_types):
903-
if not image.SaveFile(filename, filetype):
904-
DEBUG_MSG('print_figure() file save error', 4, self)
905-
raise RuntimeError(
906-
'Could not save figure to %s\n' %
907-
(filename))
908-
elif is_writable_file_like(filename):
909-
if not isinstance(image, wx.Image):
910-
image = image.ConvertToImage()
911-
if not image.SaveStream(filename, filetype):
912-
DEBUG_MSG('print_figure() file save error', 4, self)
913-
raise RuntimeError(
914-
'Could not save figure to %s\n' %
915-
(filename))
916-
917-
# Restore everything to normal
918-
self.bitmap = origBitmap
919-
920-
# Note: draw is required here since bits of state about the
921-
# last renderer are strewn about the artist draw methods. Do
922-
# not remove the draw without first verifying that these have
923-
# been cleaned up. The artist contains() methods will fail
924-
# otherwise.
925-
if self._isDrawn:
926-
self.draw()
927-
self.Refresh()
928-
929836
def _onPaint(self, evt):
930837
"""
931838
Called when wxPaintEvt is generated
@@ -1137,6 +1044,101 @@ def _onEnter(self, evt):
11371044
FigureCanvasBase.enter_notify_event(self, guiEvent=evt)
11381045

11391046

1047+
class FigureCanvasWx(_FigureCanvasWxBase):
1048+
# Rendering to a Wx canvas using the deprecated Wx renderer.
1049+
1050+
def draw(self, drawDC=None):
1051+
"""
1052+
Render the figure using RendererWx instance renderer, or using a
1053+
previously defined renderer if none is specified.
1054+
"""
1055+
DEBUG_MSG("draw()", 1, self)
1056+
self.renderer = RendererWx(self.bitmap, self.figure.dpi)
1057+
self.figure.draw(self.renderer)
1058+
self._isDrawn = True
1059+
self.gui_repaint(drawDC=drawDC)
1060+
1061+
def print_bmp(self, filename, *args, **kwargs):
1062+
return self._print_image(filename, wx.BITMAP_TYPE_BMP, *args, **kwargs)
1063+
1064+
if not _has_pil:
1065+
def print_jpeg(self, filename, *args, **kwargs):
1066+
return self._print_image(filename, wx.BITMAP_TYPE_JPEG,
1067+
*args, **kwargs)
1068+
print_jpg = print_jpeg
1069+
1070+
def print_pcx(self, filename, *args, **kwargs):
1071+
return self._print_image(filename, wx.BITMAP_TYPE_PCX, *args, **kwargs)
1072+
1073+
def print_png(self, filename, *args, **kwargs):
1074+
return self._print_image(filename, wx.BITMAP_TYPE_PNG, *args, **kwargs)
1075+
1076+
if not _has_pil:
1077+
def print_tiff(self, filename, *args, **kwargs):
1078+
return self._print_image(filename, wx.BITMAP_TYPE_TIF,
1079+
*args, **kwargs)
1080+
print_tif = print_tiff
1081+
1082+
def print_xpm(self, filename, *args, **kwargs):
1083+
return self._print_image(filename, wx.BITMAP_TYPE_XPM, *args, **kwargs)
1084+
1085+
def _print_image(self, filename, filetype, *args, **kwargs):
1086+
origBitmap = self.bitmap
1087+
1088+
l, b, width, height = self.figure.bbox.bounds
1089+
width = int(math.ceil(width))
1090+
height = int(math.ceil(height))
1091+
1092+
self.bitmap = wxc.EmptyBitmap(width, height)
1093+
1094+
renderer = RendererWx(self.bitmap, self.figure.dpi)
1095+
1096+
gc = renderer.new_gc()
1097+
1098+
self.figure.draw(renderer)
1099+
1100+
# image is the object that we call SaveFile on.
1101+
image = self.bitmap
1102+
# set the JPEG quality appropriately. Unfortunately, it is only
1103+
# possible to set the quality on a wx.Image object. So if we
1104+
# are saving a JPEG, convert the wx.Bitmap to a wx.Image,
1105+
# and set the quality.
1106+
if filetype == wx.BITMAP_TYPE_JPEG:
1107+
jpeg_quality = kwargs.get('quality',
1108+
rcParams['savefig.jpeg_quality'])
1109+
image = self.bitmap.ConvertToImage()
1110+
image.SetOption(wx.IMAGE_OPTION_QUALITY, str(jpeg_quality))
1111+
1112+
# Now that we have rendered into the bitmap, save it
1113+
# to the appropriate file type and clean up
1114+
if isinstance(filename, six.string_types):
1115+
if not image.SaveFile(filename, filetype):
1116+
DEBUG_MSG('print_figure() file save error', 4, self)
1117+
raise RuntimeError(
1118+
'Could not save figure to %s\n' %
1119+
(filename))
1120+
elif is_writable_file_like(filename):
1121+
if not isinstance(image, wx.Image):
1122+
image = image.ConvertToImage()
1123+
if not image.SaveStream(filename, filetype):
1124+
DEBUG_MSG('print_figure() file save error', 4, self)
1125+
raise RuntimeError(
1126+
'Could not save figure to %s\n' %
1127+
(filename))
1128+
1129+
# Restore everything to normal
1130+
self.bitmap = origBitmap
1131+
1132+
# Note: draw is required here since bits of state about the
1133+
# last renderer are strewn about the artist draw methods. Do
1134+
# not remove the draw without first verifying that these have
1135+
# been cleaned up. The artist contains() methods will fail
1136+
# otherwise.
1137+
if self._isDrawn:
1138+
self.draw()
1139+
self.Refresh()
1140+
1141+
11401142
########################################################################
11411143
#
11421144
# The following functions and classes are for pylab compatibility
@@ -1213,7 +1215,7 @@ def _get_toolbar(self, statbar):
12131215
return toolbar
12141216

12151217
def get_canvas(self, fig):
1216-
return FigureCanvasWx(self, -1, fig)
1218+
return type(self.canvas)(self, -1, fig)
12171219

12181220
def get_figure_manager(self):
12191221
DEBUG_MSG("get_figure_manager()", 1, self)

lib/matplotlib/backends/backend_wxagg.py

Lines changed: 4 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -6,27 +6,19 @@
66
import wx
77

88
import matplotlib
9+
from .. import cbook
910
from . import wx_compat as wxc
10-
from . import backend_wx
1111
from .backend_agg import FigureCanvasAgg
1212
from .backend_wx import (
13-
_BackendWx, FigureCanvasWx, FigureFrameWx, NavigationToolbar2Wx, DEBUG_MSG)
13+
_BackendWx, _FigureCanvasWxBase, FigureFrameWx, NavigationToolbar2Wx)
1414

1515

1616
class FigureFrameWxAgg(FigureFrameWx):
1717
def get_canvas(self, fig):
1818
return FigureCanvasWxAgg(self, -1, fig)
1919

20-
def _get_toolbar(self, statbar):
21-
if matplotlib.rcParams['toolbar'] == 'toolbar2':
22-
toolbar = NavigationToolbar2WxAgg(self.canvas)
23-
toolbar.set_status_bar(statbar)
24-
else:
25-
toolbar = None
26-
return toolbar
2720

28-
29-
class FigureCanvasWxAgg(FigureCanvasAgg, FigureCanvasWx):
21+
class FigureCanvasWxAgg(FigureCanvasAgg, _FigureCanvasWxBase):
3022
"""
3123
The FigureCanvas contains the figure and does event handling.
3224
@@ -41,7 +33,6 @@ def draw(self, drawDC=None):
4133
"""
4234
Render the figure using agg.
4335
"""
44-
DEBUG_MSG("draw()", 1, self)
4536
FigureCanvasAgg.draw(self)
4637

4738
self.bitmap = _convert_agg_to_wx_bitmap(self.get_renderer(), None)
@@ -79,17 +70,8 @@ def blit(self, bbox=None):
7970

8071
filetypes = FigureCanvasAgg.filetypes
8172

82-
def print_figure(self, filename, *args, **kwargs):
83-
# Use pure Agg renderer to draw
84-
FigureCanvasAgg.print_figure(self, filename, *args, **kwargs)
85-
# Restore the current view; this is needed because the
86-
# artist contains methods rely on particular attributes
87-
# of the rendered figure for determining things like
88-
# bounding boxes.
89-
if self._isDrawn:
90-
self.draw()
91-
9273

74+
@cbook.deprecated("2.2")
9375
class NavigationToolbar2WxAgg(NavigationToolbar2Wx):
9476
def get_canvas(self, frame, fig):
9577
return FigureCanvasWxAgg(frame, -1, fig)
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
from __future__ import (absolute_import, division, print_function,
2+
unicode_literals)
3+
4+
import six
5+
6+
import wx
7+
8+
from .backend_cairo import cairo, FigureCanvasCairo, RendererCairo
9+
from .backend_wx import (
10+
_BackendWx, _FigureCanvasWxBase, FigureFrameWx, NavigationToolbar2Wx)
11+
from . import wx_compat as wxc
12+
13+
14+
class FigureFrameWxCairo(FigureFrameWx):
15+
def get_canvas(self, fig):
16+
return FigureCanvasWxCairo(self, -1, fig)
17+
18+
19+
class FigureCanvasWxCairo(_FigureCanvasWxBase, FigureCanvasCairo):
20+
"""
21+
The FigureCanvas contains the figure and does event handling.
22+
23+
In the wxPython backend, it is derived from wxPanel, and (usually) lives
24+
inside a frame instantiated by a FigureManagerWx. The parent window
25+
probably implements a wxSizer to control the displayed control size - but
26+
we give a hint as to our preferred minimum size.
27+
"""
28+
29+
def __init__(self, parent, id, figure):
30+
# _FigureCanvasWxBase should be fixed to have the same signature as
31+
# every other FigureCanvas and use cooperative inheritance, but in the
32+
# meantime the following will make do.
33+
_FigureCanvasWxBase.__init__(self, parent, id, figure)
34+
FigureCanvasCairo.__init__(self, figure)
35+
self._renderer = RendererCairo(self.figure.dpi)
36+
37+
def draw(self, drawDC=None):
38+
width = int(self.figure.bbox.width)
39+
height = int(self.figure.bbox.height)
40+
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height)
41+
self._renderer.set_ctx_from_surface(surface)
42+
self._renderer.set_width_height(width, height)
43+
self.figure.draw(self._renderer)
44+
buf = surface.get_data()
45+
self.bitmap = wxc.BitmapFromBuffer(width, height, buf)
46+
self._isDrawn = True
47+
self.gui_repaint(drawDC=drawDC, origin='WXCairo')
48+
49+
50+
@_BackendWx.export
51+
class _BackendWxCairo(_BackendWx):
52+
FigureCanvas = FigureCanvasWxCairo
53+
_frame_class = FigureFrameWxCairo

lib/matplotlib/rcsetup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
'Qt4Agg', 'Qt4Cairo', 'Qt5Agg', 'Qt5Cairo',
4545
'TkAgg',
4646
'WebAgg',
47-
'WX', 'WXAgg']
47+
'WX', 'WXAgg', 'WXCairo']
4848
non_interactive_bk = ['agg', 'cairo', 'gdk',
4949
'pdf', 'pgf', 'ps', 'svg', 'template']
5050
all_backends = interactive_bk + non_interactive_bk

0 commit comments

Comments
 (0)