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