OLD | NEW |
1 | 1 |
2 /* | 2 /* |
3 * Copyright 2012 Google Inc. | 3 * Copyright 2012 Google Inc. |
4 * | 4 * |
5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
7 */ | 7 */ |
8 | 8 |
9 #include "SkPictureStateTree.h" | 9 #include "SkPictureStateTree.h" |
10 #include "SkCanvas.h" | 10 #include "SkCanvas.h" |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
92 : fDraws(&draws) | 92 : fDraws(&draws) |
93 , fCanvas(canvas) | 93 , fCanvas(canvas) |
94 , fCurrentNode(root) | 94 , fCurrentNode(root) |
95 , fPlaybackMatrix(canvas->getTotalMatrix()) | 95 , fPlaybackMatrix(canvas->getTotalMatrix()) |
96 , fCurrentMatrix(NULL) | 96 , fCurrentMatrix(NULL) |
97 , fPlaybackIndex(0) | 97 , fPlaybackIndex(0) |
98 , fSave(false) | 98 , fSave(false) |
99 , fValid(true) { | 99 , fValid(true) { |
100 } | 100 } |
101 | 101 |
102 uint32_t SkPictureStateTree::Iterator::draw() { | 102 void SkPictureStateTree::Iterator::setCurrentMatrix(const SkMatrix* matrix) { |
| 103 SkASSERT(NULL != matrix); |
| 104 |
| 105 if (matrix == fCurrentMatrix) { |
| 106 return; |
| 107 } |
| 108 |
| 109 // The matrix is in recording space, but we also inherit |
| 110 // a playback matrix from out target canvas. |
| 111 SkMatrix m = *matrix; |
| 112 m.postConcat(fPlaybackMatrix); |
| 113 fCanvas->setMatrix(m); |
| 114 fCurrentMatrix = matrix; |
| 115 } |
| 116 |
| 117 uint32_t SkPictureStateTree::Iterator::nextDraw() { |
103 SkASSERT(this->isValid()); | 118 SkASSERT(this->isValid()); |
104 if (fPlaybackIndex >= fDraws->count()) { | 119 if (fPlaybackIndex >= fDraws->count()) { |
105 // restore back to where we started | |
106 fCanvas->setMatrix(fPlaybackMatrix); | |
107 if (fCurrentNode->fFlags & Node::kSaveLayer_Flag) { | 120 if (fCurrentNode->fFlags & Node::kSaveLayer_Flag) { |
108 fCanvas->restore(); | 121 fCanvas->restore(); |
109 } | 122 } |
110 fCurrentNode = fCurrentNode->fParent; | 123 |
111 while (NULL != fCurrentNode) { | 124 for (fCurrentNode = fCurrentNode->fParent; fCurrentNode; |
| 125 fCurrentNode = fCurrentNode->fParent) { |
| 126 // Note: we call restore() twice when both flags are set. |
112 if (fCurrentNode->fFlags & Node::kSave_Flag) { | 127 if (fCurrentNode->fFlags & Node::kSave_Flag) { |
113 fCanvas->restore(); | 128 fCanvas->restore(); |
114 } | 129 } |
115 if (fCurrentNode->fFlags & Node::kSaveLayer_Flag) { | 130 if (fCurrentNode->fFlags & Node::kSaveLayer_Flag) { |
116 fCanvas->restore(); | 131 fCanvas->restore(); |
117 } | 132 } |
118 fCurrentNode = fCurrentNode->fParent; | |
119 } | 133 } |
| 134 |
| 135 fCanvas->setMatrix(fPlaybackMatrix); |
| 136 fCurrentMatrix = NULL; |
120 return kDrawComplete; | 137 return kDrawComplete; |
121 } | 138 } |
122 | 139 |
123 Draw* draw = static_cast<Draw*>((*fDraws)[fPlaybackIndex]); | 140 Draw* draw = static_cast<Draw*>((*fDraws)[fPlaybackIndex]); |
124 Node* targetNode = draw->fNode; | 141 Node* targetNode = draw->fNode; |
125 | 142 |
126 if (fSave) { | 143 if (fSave) { |
127 // FIXME: the save below depends on soon-to-be-deprecated | 144 fCanvas->save(); |
128 // SaveFlags behavior: it relies on matrix changes persisting | |
129 // after restore. | |
130 fCanvas->save(SkCanvas::kClip_SaveFlag); | |
131 fSave = false; | 145 fSave = false; |
132 } | 146 } |
133 | 147 |
134 if (fCurrentNode != targetNode) { | 148 if (fCurrentNode != targetNode) { |
135 // If we're not at the target and we don't have a list of nodes to get t
here, we need to | 149 // If we're not at the target and we don't have a list of nodes to get t
here, we need to |
136 // figure out the path from our current node, to the target | 150 // figure out the path from our current node, to the target |
137 if (fNodes.count() == 0) { | 151 if (fNodes.count() == 0) { |
138 // Trace back up to a common ancestor, restoring to get our current
state to match that | 152 // Trace back up to a common ancestor, restoring to get our current
state to match that |
139 // of the ancestor, and saving a list of nodes whose state we need t
o apply to get to | 153 // of the ancestor, and saving a list of nodes whose state we need t
o apply to get to |
140 // the target (we can restore up to the ancestor immediately, but we
'll need to return | 154 // the target (we can restore up to the ancestor immediately, but we
'll need to return |
141 // an offset for each node on the way down to the target, to apply t
he desired clips and | 155 // an offset for each node on the way down to the target, to apply t
he desired clips and |
142 // saveLayers, so it may take several draw() calls before the next d
raw actually occurs) | 156 // saveLayers, so it may take several draw() calls before the next d
raw actually occurs) |
143 Node* tmp = fCurrentNode; | 157 Node* tmp = fCurrentNode; |
144 Node* ancestor = targetNode; | 158 Node* ancestor = targetNode; |
145 while (tmp != ancestor) { | 159 while (tmp != ancestor) { |
146 uint16_t currentLevel = tmp->fLevel; | 160 uint16_t currentLevel = tmp->fLevel; |
147 uint16_t targetLevel = ancestor->fLevel; | 161 uint16_t targetLevel = ancestor->fLevel; |
148 if (currentLevel >= targetLevel) { | 162 if (currentLevel >= targetLevel) { |
149 if (tmp != fCurrentNode && tmp->fFlags & Node::kSave_Flag) { | 163 if (tmp != fCurrentNode && tmp->fFlags & Node::kSave_Flag) { |
150 fCanvas->restore(); | 164 fCanvas->restore(); |
| 165 // restore() may change the matrix, so we need to reappl
y. |
| 166 fCurrentMatrix = NULL; |
151 } | 167 } |
152 if (tmp->fFlags & Node::kSaveLayer_Flag) { | 168 if (tmp->fFlags & Node::kSaveLayer_Flag) { |
153 fCanvas->restore(); | 169 fCanvas->restore(); |
| 170 // restore() may change the matrix, so we need to reappl
y. |
| 171 fCurrentMatrix = NULL; |
154 } | 172 } |
155 tmp = tmp->fParent; | 173 tmp = tmp->fParent; |
156 } | 174 } |
157 if (currentLevel <= targetLevel) { | 175 if (currentLevel <= targetLevel) { |
158 fNodes.push(ancestor); | 176 fNodes.push(ancestor); |
159 ancestor = ancestor->fParent; | 177 ancestor = ancestor->fParent; |
160 } | 178 } |
161 } | 179 } |
162 | 180 |
163 if (ancestor->fFlags & Node::kSave_Flag) { | 181 if (ancestor->fFlags & Node::kSave_Flag) { |
164 if (fCurrentNode != ancestor) { | 182 if (fCurrentNode != ancestor) { |
165 fCanvas->restore(); | 183 fCanvas->restore(); |
| 184 // restore() may change the matrix, so we need to reapply. |
| 185 fCurrentMatrix = NULL; |
166 } | 186 } |
167 if (targetNode != ancestor) { | 187 if (targetNode != ancestor) { |
168 // FIXME: the save below depends on soon-to-be-deprecated | 188 fCanvas->save(); |
169 // SaveFlags behavior: it relies on matrix changes persistin
g | |
170 // after restore. | |
171 fCanvas->save(SkCanvas::kClip_SaveFlag); | |
172 } | 189 } |
173 } | 190 } |
174 fCurrentNode = ancestor; | 191 fCurrentNode = ancestor; |
175 } | 192 } |
176 | 193 |
177 // If we're not at the target node yet, we'll need to return an offset t
o make the caller | 194 // If we're not at the target node yet, we'll need to return an offset t
o make the caller |
178 // apply the next clip or saveLayer. | 195 // apply the next clip or saveLayer. |
179 if (fCurrentNode != targetNode) { | 196 if (fCurrentNode != targetNode) { |
180 if (fCurrentMatrix != fNodes.top()->fMatrix) { | |
181 fCurrentMatrix = fNodes.top()->fMatrix; | |
182 SkMatrix tmp = *fNodes.top()->fMatrix; | |
183 tmp.postConcat(fPlaybackMatrix); | |
184 fCanvas->setMatrix(tmp); | |
185 } | |
186 uint32_t offset = fNodes.top()->fOffset; | 197 uint32_t offset = fNodes.top()->fOffset; |
187 fCurrentNode = fNodes.top(); | 198 fCurrentNode = fNodes.top(); |
188 fSave = fCurrentNode != targetNode && fCurrentNode->fFlags & Node::k
Save_Flag; | 199 fSave = fCurrentNode != targetNode && fCurrentNode->fFlags & Node::k
Save_Flag; |
189 fNodes.pop(); | 200 fNodes.pop(); |
| 201 this->setCurrentMatrix(fCurrentNode->fMatrix); |
190 return offset; | 202 return offset; |
191 } | 203 } |
192 } | 204 } |
193 | 205 |
194 // If we got this far, the clip/saveLayer state is all set, so we can procee
d to set the matrix | 206 // If we got this far, the clip/saveLayer state is all set, so we can procee
d to set the matrix |
195 // for the draw, and return its offset. | 207 // for the draw, and return its offset. |
196 | 208 this->setCurrentMatrix(draw->fMatrix); |
197 if (fCurrentMatrix != draw->fMatrix) { | |
198 SkMatrix tmp = *draw->fMatrix; | |
199 tmp.postConcat(fPlaybackMatrix); | |
200 fCanvas->setMatrix(tmp); | |
201 fCurrentMatrix = draw->fMatrix; | |
202 } | |
203 | 209 |
204 ++fPlaybackIndex; | 210 ++fPlaybackIndex; |
205 return draw->fOffset; | 211 return draw->fOffset; |
206 } | 212 } |
OLD | NEW |