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

Skip to content

WxCairo backend. #10395

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 11, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions doc/users/next_whats_new/more-cairo.rst
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
Cairo rendering for Qt canvases
-------------------------------
Cairo rendering for Qt and WX canvases
--------------------------------------

The new ``Qt4Cairo`` and ``Qt5Cairo`` backends allow Qt canvases to use Cairo
rendering instead of Agg.
The new ``Qt4Cairo``, ``Qt5Cairo``, and ``WXCairo`` backends allow Qt and Wx
canvases to use Cairo rendering instead of Agg.
202 changes: 102 additions & 100 deletions lib/matplotlib/backends/backend_wx.py
Original file line number Diff line number Diff line change
Expand Up @@ -547,7 +547,7 @@ def get_wxcolour(self, color):
alpha=int(a))


class FigureCanvasWx(FigureCanvasBase, wx.Panel):
class _FigureCanvasWxBase(FigureCanvasBase, wx.Panel):
"""
The FigureCanvas contains the figure and does event handling.

Expand Down Expand Up @@ -708,23 +708,11 @@ def draw_idle(self):
"""
DEBUG_MSG("draw_idle()", 1, self)
self._isDrawn = False # Force redraw

# Triggering a paint event is all that is needed to defer drawing
# until later. The platform will send the event when it thinks it is
# a good time (usually as soon as there are no other events pending).
self.Refresh(eraseBackground=False)

def draw(self, drawDC=None):
"""
Render the figure using RendererWx instance renderer, or using a
previously defined renderer if none is specified.
"""
DEBUG_MSG("draw()", 1, self)
self.renderer = RendererWx(self.bitmap, self.figure.dpi)
self.figure.draw(self.renderer)
self._isDrawn = True
self.gui_repaint(drawDC=drawDC)

def new_timer(self, *args, **kwargs):
"""
Creates a new backend-specific subclass of
Expand Down Expand Up @@ -837,95 +825,14 @@ def gui_repaint(self, drawDC=None, origin='WX'):
filetypes['xpm'] = 'X pixmap'

def print_figure(self, filename, *args, **kwargs):
# Use pure Agg renderer to draw
FigureCanvasBase.print_figure(self, filename, *args, **kwargs)
# Restore the current view; this is needed because the
# artist contains methods rely on particular attributes
# of the rendered figure for determining things like
# bounding boxes.
super(_FigureCanvasWxBase, self).print_figure(
filename, *args, **kwargs)
# Restore the current view; this is needed because the artist contains
# methods rely on particular attributes of the rendered figure for
# determining things like bounding boxes.
if self._isDrawn:
self.draw()

def print_bmp(self, filename, *args, **kwargs):
return self._print_image(filename, wx.BITMAP_TYPE_BMP, *args, **kwargs)

if not _has_pil:
def print_jpeg(self, filename, *args, **kwargs):
return self._print_image(filename, wx.BITMAP_TYPE_JPEG,
*args, **kwargs)
print_jpg = print_jpeg

def print_pcx(self, filename, *args, **kwargs):
return self._print_image(filename, wx.BITMAP_TYPE_PCX, *args, **kwargs)

def print_png(self, filename, *args, **kwargs):
return self._print_image(filename, wx.BITMAP_TYPE_PNG, *args, **kwargs)

if not _has_pil:
def print_tiff(self, filename, *args, **kwargs):
return self._print_image(filename, wx.BITMAP_TYPE_TIF,
*args, **kwargs)
print_tif = print_tiff

def print_xpm(self, filename, *args, **kwargs):
return self._print_image(filename, wx.BITMAP_TYPE_XPM, *args, **kwargs)

def _print_image(self, filename, filetype, *args, **kwargs):
origBitmap = self.bitmap

l, b, width, height = self.figure.bbox.bounds
width = int(math.ceil(width))
height = int(math.ceil(height))

self.bitmap = wxc.EmptyBitmap(width, height)

renderer = RendererWx(self.bitmap, self.figure.dpi)

gc = renderer.new_gc()

self.figure.draw(renderer)

# image is the object that we call SaveFile on.
image = self.bitmap
# set the JPEG quality appropriately. Unfortunately, it is only
# possible to set the quality on a wx.Image object. So if we
# are saving a JPEG, convert the wx.Bitmap to a wx.Image,
# and set the quality.
if filetype == wx.BITMAP_TYPE_JPEG:
jpeg_quality = kwargs.get('quality',
rcParams['savefig.jpeg_quality'])
image = self.bitmap.ConvertToImage()
image.SetOption(wx.IMAGE_OPTION_QUALITY, str(jpeg_quality))

# Now that we have rendered into the bitmap, save it
# to the appropriate file type and clean up
if isinstance(filename, six.string_types):
if not image.SaveFile(filename, filetype):
DEBUG_MSG('print_figure() file save error', 4, self)
raise RuntimeError(
'Could not save figure to %s\n' %
(filename))
elif is_writable_file_like(filename):
if not isinstance(image, wx.Image):
image = image.ConvertToImage()
if not image.SaveStream(filename, filetype):
DEBUG_MSG('print_figure() file save error', 4, self)
raise RuntimeError(
'Could not save figure to %s\n' %
(filename))

# Restore everything to normal
self.bitmap = origBitmap

# Note: draw is required here since bits of state about the
# last renderer are strewn about the artist draw methods. Do
# not remove the draw without first verifying that these have
# been cleaned up. The artist contains() methods will fail
# otherwise.
if self._isDrawn:
self.draw()
self.Refresh()

def _onPaint(self, evt):
"""
Called when wxPaintEvt is generated
Expand Down Expand Up @@ -1137,6 +1044,101 @@ def _onEnter(self, evt):
FigureCanvasBase.enter_notify_event(self, guiEvent=evt)


class FigureCanvasWx(_FigureCanvasWxBase):
# Rendering to a Wx canvas using the deprecated Wx renderer.

def draw(self, drawDC=None):
"""
Render the figure using RendererWx instance renderer, or using a
previously defined renderer if none is specified.
"""
DEBUG_MSG("draw()", 1, self)
self.renderer = RendererWx(self.bitmap, self.figure.dpi)
self.figure.draw(self.renderer)
self._isDrawn = True
self.gui_repaint(drawDC=drawDC)

def print_bmp(self, filename, *args, **kwargs):
return self._print_image(filename, wx.BITMAP_TYPE_BMP, *args, **kwargs)

if not _has_pil:
def print_jpeg(self, filename, *args, **kwargs):
return self._print_image(filename, wx.BITMAP_TYPE_JPEG,
*args, **kwargs)
print_jpg = print_jpeg

def print_pcx(self, filename, *args, **kwargs):
return self._print_image(filename, wx.BITMAP_TYPE_PCX, *args, **kwargs)

def print_png(self, filename, *args, **kwargs):
return self._print_image(filename, wx.BITMAP_TYPE_PNG, *args, **kwargs)

if not _has_pil:
def print_tiff(self, filename, *args, **kwargs):
return self._print_image(filename, wx.BITMAP_TYPE_TIF,
*args, **kwargs)
print_tif = print_tiff

def print_xpm(self, filename, *args, **kwargs):
return self._print_image(filename, wx.BITMAP_TYPE_XPM, *args, **kwargs)

def _print_image(self, filename, filetype, *args, **kwargs):
origBitmap = self.bitmap

l, b, width, height = self.figure.bbox.bounds
width = int(math.ceil(width))
height = int(math.ceil(height))

self.bitmap = wxc.EmptyBitmap(width, height)

renderer = RendererWx(self.bitmap, self.figure.dpi)

gc = renderer.new_gc()

self.figure.draw(renderer)

# image is the object that we call SaveFile on.
image = self.bitmap
# set the JPEG quality appropriately. Unfortunately, it is only
# possible to set the quality on a wx.Image object. So if we
# are saving a JPEG, convert the wx.Bitmap to a wx.Image,
# and set the quality.
if filetype == wx.BITMAP_TYPE_JPEG:
jpeg_quality = kwargs.get('quality',
rcParams['savefig.jpeg_quality'])
image = self.bitmap.ConvertToImage()
image.SetOption(wx.IMAGE_OPTION_QUALITY, str(jpeg_quality))

# Now that we have rendered into the bitmap, save it
# to the appropriate file type and clean up
if isinstance(filename, six.string_types):
if not image.SaveFile(filename, filetype):
DEBUG_MSG('print_figure() file save error', 4, self)
raise RuntimeError(
'Could not save figure to %s\n' %
(filename))
elif is_writable_file_like(filename):
if not isinstance(image, wx.Image):
image = image.ConvertToImage()
if not image.SaveStream(filename, filetype):
DEBUG_MSG('print_figure() file save error', 4, self)
raise RuntimeError(
'Could not save figure to %s\n' %
(filename))

# Restore everything to normal
self.bitmap = origBitmap

# Note: draw is required here since bits of state about the
# last renderer are strewn about the artist draw methods. Do
# not remove the draw without first verifying that these have
# been cleaned up. The artist contains() methods will fail
# otherwise.
if self._isDrawn:
self.draw()
self.Refresh()


########################################################################
#
# The following functions and classes are for pylab compatibility
Expand Down Expand Up @@ -1213,7 +1215,7 @@ def _get_toolbar(self, statbar):
return toolbar

def get_canvas(self, fig):
return FigureCanvasWx(self, -1, fig)
return type(self.canvas)(self, -1, fig)

def get_figure_manager(self):
DEBUG_MSG("get_figure_manager()", 1, self)
Expand Down
26 changes: 4 additions & 22 deletions lib/matplotlib/backends/backend_wxagg.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,27 +6,19 @@
import wx

import matplotlib
from .. import cbook
from . import wx_compat as wxc
from . import backend_wx
from .backend_agg import FigureCanvasAgg
from .backend_wx import (
_BackendWx, FigureCanvasWx, FigureFrameWx, NavigationToolbar2Wx, DEBUG_MSG)
_BackendWx, _FigureCanvasWxBase, FigureFrameWx, NavigationToolbar2Wx)


class FigureFrameWxAgg(FigureFrameWx):
def get_canvas(self, fig):
return FigureCanvasWxAgg(self, -1, fig)

def _get_toolbar(self, statbar):
if matplotlib.rcParams['toolbar'] == 'toolbar2':
toolbar = NavigationToolbar2WxAgg(self.canvas)
toolbar.set_status_bar(statbar)
else:
toolbar = None
return toolbar


class FigureCanvasWxAgg(FigureCanvasAgg, FigureCanvasWx):
class FigureCanvasWxAgg(FigureCanvasAgg, _FigureCanvasWxBase):
"""
The FigureCanvas contains the figure and does event handling.

Expand All @@ -41,7 +33,6 @@ def draw(self, drawDC=None):
"""
Render the figure using agg.
"""
DEBUG_MSG("draw()", 1, self)
FigureCanvasAgg.draw(self)

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

filetypes = FigureCanvasAgg.filetypes

def print_figure(self, filename, *args, **kwargs):
# Use pure Agg renderer to draw
FigureCanvasAgg.print_figure(self, filename, *args, **kwargs)
# Restore the current view; this is needed because the
# artist contains methods rely on particular attributes
# of the rendered figure for determining things like
# bounding boxes.
if self._isDrawn:
self.draw()


@cbook.deprecated("2.2")
class NavigationToolbar2WxAgg(NavigationToolbar2Wx):
def get_canvas(self, frame, fig):
return FigureCanvasWxAgg(frame, -1, fig)
Expand Down
53 changes: 53 additions & 0 deletions lib/matplotlib/backends/backend_wxcairo.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
from __future__ import (absolute_import, division, print_function,
unicode_literals)

import six

import wx

from .backend_cairo import cairo, FigureCanvasCairo, RendererCairo
from .backend_wx import (
_BackendWx, _FigureCanvasWxBase, FigureFrameWx, NavigationToolbar2Wx)
from . import wx_compat as wxc


class FigureFrameWxCairo(FigureFrameWx):
def get_canvas(self, fig):
return FigureCanvasWxCairo(self, -1, fig)


class FigureCanvasWxCairo(_FigureCanvasWxBase, FigureCanvasCairo):
"""
The FigureCanvas contains the figure and does event handling.

In the wxPython backend, it is derived from wxPanel, and (usually) lives
inside a frame instantiated by a FigureManagerWx. The parent window
probably implements a wxSizer to control the displayed control size - but
we give a hint as to our preferred minimum size.
"""

def __init__(self, parent, id, figure):
# _FigureCanvasWxBase should be fixed to have the same signature as
# every other FigureCanvas and use cooperative inheritance, but in the
# meantime the following will make do.
_FigureCanvasWxBase.__init__(self, parent, id, figure)
FigureCanvasCairo.__init__(self, figure)
self._renderer = RendererCairo(self.figure.dpi)

def draw(self, drawDC=None):
width = int(self.figure.bbox.width)
height = int(self.figure.bbox.height)
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height)
self._renderer.set_ctx_from_surface(surface)
self._renderer.set_width_height(width, height)
self.figure.draw(self._renderer)
buf = surface.get_data()
self.bitmap = wxc.BitmapFromBuffer(width, height, buf)
self._isDrawn = True
self.gui_repaint(drawDC=drawDC, origin='WXCairo')


@_BackendWx.export
class _BackendWxCairo(_BackendWx):
FigureCanvas = FigureCanvasWxCairo
_frame_class = FigureFrameWxCairo
2 changes: 1 addition & 1 deletion lib/matplotlib/rcsetup.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
'Qt4Agg', 'Qt4Cairo', 'Qt5Agg', 'Qt5Cairo',
'TkAgg',
'WebAgg',
'WX', 'WXAgg']
'WX', 'WXAgg', 'WXCairo']
non_interactive_bk = ['agg', 'cairo', 'gdk',
'pdf', 'pgf', 'ps', 'svg', 'template']
all_backends = interactive_bk + non_interactive_bk
Expand Down