8000 Single commit of necessary transform changes. · matplotlib/matplotlib@753c9a2 · GitHub
[go: up one dir, main page]

Skip to content

Commit 753c9a2

Browse files
Phil Elsonpelson
authored andcommitted
Single commit of necessary transform changes.
1 parent 2441135 commit 753c9a2

File tree

1 file changed

+39
-20
lines changed

1 file changed

+39
-20
lines changed

lib/matplotlib/transforms.py

Lines changed: 39 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -99,30 +99,32 @@ def __copy__(self, *args):
9999

100100
def invalidate(self):
101101
"""
102-
Invalidate this :class:`TransformNode` and all of its
103-
ancestors. Should be called any time the transform changes.
102+
Invalidate this :class:`TransformNode` and triggers an
103+
invalidation of its ancestors. Should be called any
104+
time the transform changes.
104105
"""
105-
# If we are an affine transform being changed, we can set the
106-
# flag to INVALID_AFFINE_ONLY
107-
value = (self.is_affine) and self.INVALID_AFFINE or self.INVALID
106+
value = self.INVALID
107+
if self.is_affine:
108+
value = self.INVALID_AFFINE
109+
return self._invalidate_internal(value, invalidating_node=self)
108110

109-
# Shortcut: If self is already invalid, that means its parents
110-
# are as well, so we don't need to do anything.
111-
if self._invalid == value:
112-
return
111+
def _invalidate_internal(self, value, invalidating_node):
112+
"""
113+
Called by :meth:`invalidate` and subsequently ascends the transform
114+
stack calling each TransformNode's _invalidate_internal method.
115+
"""
116+
# determine if this call will be an extension to the invalidation status
117+
# if not, then a shortcut means that we needn't invoke an invalidation
118+
# up the transform stack
119+
# XXX This makes the invalidation sticky, once a transform has been invalidated as NON_AFFINE
120+
# too, then it is always NON_AFFINE invalid, even when triggered with a AFFINE_ONLY invalidation.
121+
status_changed = self._invalid < value
113122

114-
if not len(self._parents):
123+
if self.pass_through or status_changed:
115124
self._invalid = value
116-
return
117125

118-
# Invalidate all ancestors of self using pseudo-recursion.
119-
stack = [self]
120-
while len(stack):
121-
root = stack.pop()
122-
# Stop at subtrees that have already been invalidated
123-
if root._invalid != value or root.pass_through:
124-
root._invalid = self.INVALID
125-
stack.extend(root._parents.iterkeys())
126+
for parent in self._parents.iterkeys():
127+
parent._invalidate_internal(value=value, invalidating_node=self)
126128

127129
def set_children(self, *children):
128130
"""
@@ -1251,7 +1253,6 @@ class TransformWrapper(Transform):
12511253
of the same dimensions.
12521254
"""
12531255
pass_through = True
1254-
is_affine = False
12551256

12561257
def __init__(self, child):
12571258
"""
@@ -1286,6 +1287,7 @@ def _set(self, child):
12861287
self.transform_path_non_affine = child.transform_path_non_affine
12871288
self.get_affine = child.get_affine
12881289
self.inverted = child.inverted
1290+
self.is_affine = child.is_affine
12891291

12901292
def set(self, child):
12911293
"""
@@ -1890,6 +1892,8 @@ def __init__(self, a, b):
18901892
self._b = b
18911893
self.set_children(a, b)
18921894

1895+
is_affine = property(lambda self: self._a.is_affine and self._b.is_affine)
1896+
18931897
def frozen(self):
18941898
self._invalid = 0
18951899
frozen = composite_transform_factory(self._a.frozen(), self._b.frozen())
@@ -1898,6 +1902,20 @@ def frozen(self):
18981902
return frozen
18991903
frozen.__doc__ = Transform.frozen.__doc__
19001904

1905+
def _invalidate_internal(self, value, invalidating_node):
1906+
# In some cases for a composite transform, an invalidating call to AFFINE_ONLY needs
1907+
# to be extended to invalidate the NON_AFFINE part too. These cases are when the right
1908+
# hand transform is non-affine and either:
1909+
# (a) the left hand transform is non affine
1910+
# (b) it is the left hand node which has triggered the invalidation
1911+
if value == Transform.INVALID_AFFINE \
1912+
and not self._b.is_affine \
1913+
and (not self._a.is_affine or invalidating_node is self._a): # note use of is will break when using TransformWrapper
1914+
1915+
value = Transform.INVALID
1916+
1917+
Transform._invalidate_internal(self, value=value, invalidating_node=invalidating_node)
1918+
19011919
def _get_is_affine(self):
19021920
return self._a.is_affine and self._b.is_affine
19031921
is_affine = property(_get_is_affine)
@@ -2229,6 +2247,7 @@ def __init__(self, path, transform):
22292247
self._transformed_points = None
22302248

22312249
def _revalidate(self):
2250+
# only recompute if the invalidation includes the non_affine part of the transform
22322251
if ((self._invalid & self.INVALID_NON_AFFINE == self.INVALID_NON_AFFINE)
22332252
or self._transformed_path is None):
22342253
self._transformed_path = \

0 commit comments

Comments
 (0)
0