Skip to content

Commit 4dba019

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 4dba019

File tree

2 files changed

+28
-39
lines changed

2 files changed

+28
-39
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: 25 additions & 39 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,9 @@ def __init__(self, shorthand_name=None):
117120
``str(transform)`` when DEBUG=True.
118121
"""
119122
self._parents = {}
120-
121123
# TransformNodes start out as invalid until their values are
122124
# computed for the first time.
123-
self._invalid = 1
125+
self._invalid = self._INVALID_FULL
124126
self._shorthand_name = shorthand_name or ''
125127

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

167-
def _invalidate_internal(self, value, invalidating_node):
168+
def _invalidate_internal(self, level, invalidating_node):
168169
"""
169170
Called by :meth:`invalidate` and subsequently ascends the transform
170171
stack calling each TransformNode's _invalidate_internal method.
171172
"""
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)
173+
# If we are already more invalid than the currently propagated invalidation,
174+
# then we don't need to do anything.
175+
if level <= self._invalid and not self.pass_through:
176+
return
177+
self._invalid = level
178+
for parent in list(self._parents.values()):
179+
parent = parent() # Dereference the weak reference.
180+
if parent is not None:
181+
parent._invalidate_internal(level=level, invalidating_node=self)
193182

194183
def set_children(self, *children):
195184
"""
@@ -2379,20 +2368,17 @@ def frozen(self):
23792368
return frozen.frozen()
23802369
return frozen
23812370

2382-
def _invalidate_internal(self, value, invalidating_node):
2371+
def _invalidate_internal(self, level, invalidating_node):
23832372
# In some cases for a composite transform, an invalidating call to
23842373
# AFFINE_ONLY needs to be extended to invalidate the NON_AFFINE part
23852374
# too. These cases are when the right hand transform is non-affine and
23862375
# either:
23872376
# (a) the left hand transform is non affine
23882377
# (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
2378+
if (not self._b.is_affine and
23912379
(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)
2380+
level = Transform._INVALID_FULL
2381+
super()._invalidate_internal(level, invalidating_node)
23962382

23972383
def __eq__(self, other):
23982384
if isinstance(other, (CompositeGenericTransform, CompositeAffine2D)):
@@ -2757,7 +2743,7 @@ def __init__(self, path, transform):
27572743
def _revalidate(self):
27582744
# only recompute if the invalidation includes the non_affine part of
27592745
# the transform
2760-
if (self._invalid & self.INVALID_NON_AFFINE == self.INVALID_NON_AFFINE
2746+
if (self._invalid == self._INVALID_FULL
27612747
or self._transformed_path is None):
27622748
self._transformed_path = \
27632749
self._transform.transform_path_non_affine(self._path)

0 commit comments

Comments
 (0)