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

Skip to content

Backends cleanup #8772

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 4 commits into from
Jul 9, 2017
Merged

Backends cleanup #8772

merged 4 commits into from
Jul 9, 2017

Conversation

anntzer
Copy link
Contributor

@anntzer anntzer commented Jun 18, 2017

This is the first part of #8771, split out for simpler review.

  1. general cleanup to the backends code
  2. unification of blitting and nonblitting code paths in Qt5Agg's paintEvent, similarly to how it is implemented by Gtk3Cairo: a default repaint is simply equivalent to a blitting of the whole canvas.
  3. removal of the unused Gtk3 _needs_redraw attribute (documented as "doesnt work").

def __init__(self, figure):
if DEBUG:
print('FigureCanvasQtAgg: ', figure)
FigureCanvasQT.__init__(self, figure)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this needs to be here or the MI does not work correctly (as pyqt5 made them cooperative, but they are not int pyqt4)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is further handled by the qtcairo commit, but in fact with the new MRO (specifically, due to FigureCanvasQT going after FigureCanvasAgg), this is not needed anymore, because the MRO FigureCanvasQT(4)Agg is

matplotlib.backends.backend_qt4agg.FigureCanvasQTAgg
matplotlib.backends.backend_qt5agg.FigureCanvasQTAggBase
matplotlib.backends.backend_agg.FigureCanvasAgg
matplotlib.backends.backend_qt4.FigureCanvasQT
matplotlib.backends.backend_qt5.FigureCanvasQT
PyQt4.QtGui.QWidget
PyQt4.QtCore.QObject
sip.wrapper
PyQt4.QtGui.QPaintDevice
sip.simplewrapper
matplotlib.backend_bases.FigureCanvasBase
builtins.object

and FigureCanvasAgg.__init__ is the same as FigureCanvasBase.__init__, which does not forward its arguments to the super class, so QWidget never sees the figure kwarg.

Or you can just test by yourself that it works :)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I was lost in the classes here. It looks like the calls out to the PyQt base classes happen in the FigureCanvasQt.__init__ not here.

🐑


class FigureCanvasQTAgg(FigureCanvasQTAggBase,
FigureCanvasQT, FigureCanvasAgg):
class FigureCanvasQTAgg(FigureCanvasQTAggBase, FigureCanvasQT):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think having the base class come in as the _ version of this is clearer (I had to think a bit for why this should work).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually this MRO chain will get even further simplified in #8771 (to class FigureCanvasQTAgg(FigureCanvasAgg, FigureCanvasQT), which seems as simple as one can do :-)), sorry for modifying the same thing twice.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am very much 👍 on simplifying the MRO.

# into argb format and is in a 4 byte unsigned int. Little endian
# system is LSB first and expects the bytes in reverse order
# (bgra).
if QtCore.QSysInfo.ByteOrder == QtCore.QSysInfo.LittleEndian:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why drop the little endian support?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm just reusing the blitting codepath for both cases, so either region.to_string_argb (which is a different method from renderer.tostring_argb...) was already doing the right thing wrt. endianness, or there has been a bug for a while on one of the two endiannesses that no one ever noticed.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fair. There are not many little-endian systems left in practice (and they tend to be big main frame type systems these days).

rect = qImage.rect()
p = QtGui.QPainter(self)
# reset the image area of the canvas to be the back-ground color
p.eraseRect(rect)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is important if users have alpha in the final rgba. If this is not here text appears to 'get thicker' over time as the alpha stacks up.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, restored the erase in the case where bbox_queue is empty.

@@ -244,14 +190,11 @@ def __init__(self, figure):
if DEBUG:
print('FigureCanvasQtAgg: ', figure)
super(FigureCanvasQTAgg, self).__init__(figure=figure)
self._drawRect = None
self.blitbox = []
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This going private needs to be documented and gracefully deprecated. Users who use blitting are extra clever and are likely abusing this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done (modulo comment below)

# Adjust the buf reference count to work around a memory
# leak bug in QImage under PySide on Python 3.
if QT_API == 'PySide' and six.PY3:
ctypes.c_long.from_address(id(buf)).value = 1
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am curious what the history on why we had this done two different ways was.

@@ -56,12 +59,6 @@
from matplotlib.transforms import Bbox, Affine2D
from matplotlib.font_manager import ttfFontProperty

# Image::color_conv(format) for draw_image()
Copy link
Member

@tacaswell tacaswell Jun 19, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This came in via 9cb48c1 and it's use was removed in #5718 and it's backports.

@@ -509,7 +476,7 @@ def print_svg(self, fobj, *args, **kwargs):
def print_svgz(self, fobj, *args, **kwargs):
return self._save(fobj, 'svgz', *args, **kwargs)

def _save (self, fo, format, **kwargs):
def _save(self, fo, fmt, **kwargs):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will grumble a bit about this, but it is OK. It is a private API and the change is to avoid shadowing a builtin.

@tacaswell tacaswell added this to the 2.1 (next point release) milestone Jun 19, 2017
@tacaswell
Copy link
Member

I think the biggest concern I have with this is the dropping of eraserect and the little endian support, the rest of it seems non-controversial on a first read.

@anntzer
Copy link
Contributor Author

anntzer commented Jun 19, 2017

You mean blitbox? I made it a deprecated property, do you want an API change there? (tbh I am not sure how that would help anyone, there is simply no replacement for it (other than calling .blit perhaps)) eraseRect was already private.

@anntzer anntzer force-pushed the backends-cleanup branch from 0194395 to 1f50a0f Compare June 19, 2017 05:11
@anntzer
Copy link
Contributor Author

anntzer commented Jun 19, 2017

New version pushed.

@anntzer anntzer force-pushed the backends-cleanup branch from 1f50a0f to 0fd5b04 Compare June 19, 2017 05:48
@@ -75,9 +63,14 @@ def drawRectangle(self, rect):
self._drawRect = None
self.update()

@property
@cbook.deprecated("2.0")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be 2.1?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, fixed

@anntzer anntzer force-pushed the backends-cleanup branch from 0fd5b04 to 6ce2f06 Compare June 20, 2017 00:04
@efiring
Copy link
Member

efiring commented Jun 20, 2017 via email

@anntzer anntzer force-pushed the backends-cleanup branch from 6ce2f06 to 22457f3 Compare June 27, 2017 09:13
@tacaswell tacaswell closed this Jul 1, 2017
@tacaswell tacaswell reopened this Jul 1, 2017
@tacaswell
Copy link
Member

power-cycled to retrigger CI.


if self._bbox_queue:
bbox_queue = self._bbox_queue
self._bbox_queue = []
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do not need this line, unconditionally reset below.

@@ -196,7 +141,7 @@ def __draw_idle_agg(self, *args):
self._agg_draw_pending = False
return
try:
FigureCanvasAgg.draw(self)
super(FigureCanvasQTAggBase, self).draw()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be simplified to self.draw()

self.ctx.set_line_width (self.renderer.points_to_pixels(w))


def new_figure_manager(num, *args, **kwargs): # called by backends/__init__.py
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this change leaked when you split the changes up?

Copy link
Member

@tacaswell tacaswell left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left 3 small comments, ok with this going in with out them being addressed.

@anntzer anntzer force-pushed the backends-cleanup branch from 22457f3 to f879b2b Compare July 1, 2017 22:50
@anntzer
Copy link
Contributor Author

anntzer commented Jul 1, 2017

Comments handled.

Follow a similar architecture to the Gtk3Agg backend: a default draw can
be implemented as a blitting of the entire canvas.

Also unify the Qt4Agg and Qt5Agg canvas classes a bit more.
anntzer added 3 commits July 8, 2017 20:31
The removed comment in backend_agg regarding rgb came in in 281b7b7, but
is now irrelevant.
@anntzer anntzer force-pushed the backends-cleanup branch from f879b2b to 79cfe14 Compare July 9, 2017 07:06
@anntzer
Copy link
Contributor Author

anntzer commented Jul 9, 2017

Last commit removes some old comments, rewords some docstrings, reformats a few lines.

@tacaswell tacaswell merged commit d412228 into matplotlib:master Jul 9, 2017
@anntzer anntzer deleted the backends-cleanup branch July 9, 2017 19:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants