8000 Simplify transforms invalidation system. · matplotlib/matplotlib@bc5bd1e · GitHub
[go: up one dir, main page]

Skip to content

Commit bc5bd1e

Browse files
committed
Simplify transforms invalidation system.
The INVALID_NON_AFFINE state is never used, except at init, but there it can be replaced by a fully invalid state (the difference is that calls to invalidate() will not be propagated, but that's OK because any (necessarily new) dependent of the new node will also already be in an invalid state as well). Thus, for clarity, replace the 4 possible values of `._invalid` (0-3) by only 3 values (0-2), and get rid of bit-twiddling in TransformedPath._revalidate. Also rename "value" to (invalidation) "level", invert the logic in _invalidate_internal (I find the new order easier to follow), and get rid of a seemingly incorrect statement about invalidation stickiness (as far as I can tell, once a node has been revalidated (`._invalid = 0`), it can again be invalidated as affine_only).
1 parent 70e0ba8 commit bc5bd1e

File tree

2 files changed

+29
-41
lines changed

2 files changed

+29
-41
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
``INVALID_NON_AFFINE``, ``INVALID_AFFINE``, ``INVALID`` attributes of ``TransformNode``
2+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3+
These attributes are deprecated.

lib/matplotlib/transforms.py

Lines changed: 26 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -92,9 +92,12 @@ class TransformNode:
9292
# Invalidation may affect only the affine part. If the
9393
# invalidation was "affine-only", the _invalid member is set to
9494
# INVALID_AFFINE_ONLY
95-
INVALID_NON_AFFINE = 1
96-
INVALID_AFFINE = 2
97-
INVALID = INVALID_NON_AFFINE | INVALID_AFFINE
95+
INVALID_NON_AFFINE = _api.deprecated("3.8")(_api.classproperty(lambda cls: 1))
96+
INVALID_AFFINE = _api.deprecated("3.8")(_api.classproperty(lambda cls: 2))
97+
INVALID = _api.deprecated("3.8")(_api.classproperty(lambda cls: 3))
98+
99+
# Possible values for the _invalid attribute.
100+
_VALID, _INVALID_AFFINE_ONLY, _INVALID_FULL = range(3)
98101

99102
# Some metadata about the transform, used to determine whether an
100103
# invalidation is affine-only
@@ -117,10 +120,8 @@ def __init__(self, shorthand_name=None):
117120
``str(transform)`` when DEBUG=True.
118121
"""
119122
self._parents = {}
120-
121-
# TransformNodes start out as invalid until their values are
122-
# computed for the first time.
123-
self._invalid = 1
123+
# Initially invalid, until first computation.
124+
self._invalid = self._INVALID_FULL
124125
self._shorthand_name = shorthand_name or ''
125126

126127
if DEBUG:
@@ -159,37 +160,24 @@ def invalidate(self):
159160
Invalidate this `TransformNode` and triggers an invalidation of its
160161
ancestors. Should be called any time the transform changes.
161162
"""
162-
value = self.INVALID
163-
if self.is_affine:
164-
value = self.INVALID_AFFINE
165-
return self._invalidate_internal(value, invalidating_node=self)
163+
return self._invalidate_internal(
164+
level=self._INVALID_AFFINE_ONLY if self.is_affine else self._INVALID_FULL,
165+
invalidating_node=self)
166166

167-
def _invalidate_internal(self, value, invalidating_node):
167+
def _invalidate_internal(self, level, invalidating_node):
168168
"""
169169
Called by :meth:`invalidate` and subsequently ascends the transform
170170
stack calling each TransformNode's _invalidate_internal method.
171171
"""
172-
# determine if this call will be an extension to the invalidation
173-
# status. If not, then a shortcut means that we needn't invoke an
174-
# invalidation up the transform stack as it will already have been
175-
# invalidated.
176-
177-
# N.B This makes the invalidation sticky, once a transform has been
178-
# invalidated as NON_AFFINE, then it will always be invalidated as
179-
# NON_AFFINE even when triggered with a AFFINE_ONLY invalidation.
180-
# In most cases this is not a problem (i.e. for interactive panning and
181-
# zooming) and the only side effect will be on performance.
182-
status_changed = self._invalid < value
183-
184-
if self.pass_through or status_changed:
185-
self._invalid = value
186-
187-
for parent in list(self._parents.values()):
188-
# Dereference the weak reference
189-
parent = parent()
190-
if parent is not None:
191-
parent._invalidate_internal(
192-
value=value, invalidating_node=self)
172+
# If we are already more invalid than the currently propagated invalidation,
173+
# then we don't need to do anything.
174+
if level <= self._invalid and not self.pass_through:
175+
return
176+
self._invalid = level
177+
for parent in list(self._parents.values()):
178+
parent = parent() # Dereference the weak reference.
179+
if parent is not None:
180+
parent._invalidate_internal(level=level, invalidating_node=self)
193181

194182
def set_children(self, *children):
195183
"""
@@ -2379,20 +2367,17 @@ def frozen(self):
23792367
return frozen.frozen()
23802368
return frozen
23812369

2382-
def _invalidate_internal(self, value, invalidating_node):
2370+
def _invalidate_internal(self, level, invalidating_node):
23832371
# In some cases for a composite transform, an invalidating call to
23842372
# AFFINE_ONLY needs to be extended to invalidate the NON_AFFINE part
23852373
# too. These cases are when the right hand transform is non-affine and
23862374
# either:
23872375
# (a) the left hand transform is non affine
23882376
# (b) it is the left hand node which has triggered the invalidation
2389-
if (value == Transform.INVALID_AFFINE and
2390-
not self._b.is_affine and
2377+
if (not self._b.is_affine and
23912378
(not self._a.is_affine or invalidating_node is self._a)):
2392-
value = Transform.INVALID
2393-
2394-
super()._invalidate_internal(value=value,
2395-
invalidating_node=invalidating_node)
2379+
level = Transform._INVALID_FULL
2380+
super()._invalidate_internal(level, invalidating_node)
23962381

23972382
def __eq__(self, other):
23982383
if isinstance(other, (CompositeGenericTransform, CompositeAffine2D)):
@@ -2757,7 +2742,7 @@ def __init__(self, path, transform):
27572742
def _revalidate(self):
27582743
# only recompute if the invalidation includes the non_affine part of
27592744
# the transform
2760-
if (self._invalid & self.INVALID_NON_AFFINE == self.INVALID_NON_AFFINE
2745+
if (self._invalid == self._INVALID_FULL
27612746
or self._transformed_path is None):
27622747
self._transformed_path = \
27632748
self._transform.transform_path_non_affine(self._path)

0 commit comments

Comments
 (0)
0