OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2014 Google Inc. | 2 * Copyright 2014 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkRecordDraw.h" | 8 #include "SkRecordDraw.h" |
9 #include "SkTSort.h" | 9 #include "SkTSort.h" |
10 | 10 |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
110 // To implement this, we keep a stack of active Save blocks. As we consume ops | 110 // To implement this, we keep a stack of active Save blocks. As we consume ops |
111 // inside the Save/Restore block, drawing ops are unioned with the bounds of | 111 // inside the Save/Restore block, drawing ops are unioned with the bounds of |
112 // the block, and control ops are stashed away for later. When we finish the | 112 // the block, and control ops are stashed away for later. When we finish the |
113 // block with a Restore, our bounds are complete, and we go back and fill them | 113 // block with a Restore, our bounds are complete, and we go back and fill them |
114 // in for all the control ops we stashed away. | 114 // in for all the control ops we stashed away. |
115 class FillBounds : SkNoncopyable { | 115 class FillBounds : SkNoncopyable { |
116 public: | 116 public: |
117 FillBounds(const SkRecord& record, SkBBoxHierarchy* bbh) : fBounds(record.co
unt()) { | 117 FillBounds(const SkRecord& record, SkBBoxHierarchy* bbh) : fBounds(record.co
unt()) { |
118 // Calculate bounds for all ops. This won't go quite in order, so we'll
need | 118 // Calculate bounds for all ops. This won't go quite in order, so we'll
need |
119 // to store the bounds separately then feed them in to the BBH later in
order. | 119 // to store the bounds separately then feed them in to the BBH later in
order. |
| 120 fCTM.setIdentity(); |
120 for (fCurrentOp = 0; fCurrentOp < record.count(); fCurrentOp++) { | 121 for (fCurrentOp = 0; fCurrentOp < record.count(); fCurrentOp++) { |
121 record.visit<void>(fCurrentOp, *this); | 122 record.visit<void>(fCurrentOp, *this); |
122 } | 123 } |
123 | 124 |
124 // If we have any lingering unpaired Saves, simulate restores to make | 125 // If we have any lingering unpaired Saves, simulate restores to make |
125 // sure all ops in those Save blocks have their bounds calculated. | 126 // sure all ops in those Save blocks have their bounds calculated. |
126 while (!fSaveStack.isEmpty()) { | 127 while (!fSaveStack.isEmpty()) { |
127 this->popSaveBlock(); | 128 this->popSaveBlock(); |
128 } | 129 } |
129 | 130 |
130 // Any control ops not part of any Save/Restore block draw everywhere. | 131 // Any control ops not part of any Save/Restore block draw everywhere. |
131 while (!fControlIndices.isEmpty()) { | 132 while (!fControlIndices.isEmpty()) { |
132 this->popControl(SkIRect::MakeLargest()); | 133 this->popControl(SkIRect::MakeLargest()); |
133 } | 134 } |
134 | 135 |
135 // Finally feed all stored bounds into the BBH. They'll be returned in
this order. | 136 // Finally feed all stored bounds into the BBH. They'll be returned in
this order. |
136 SkASSERT(NULL != bbh); | 137 SkASSERT(NULL != bbh); |
137 for (uintptr_t i = 0; i < record.count(); i++) { | 138 for (uintptr_t i = 0; i < record.count(); i++) { |
138 if (!fBounds[i].isEmpty()) { | 139 if (!fBounds[i].isEmpty()) { |
139 bbh->insert((void*)i, fBounds[i], true/*ok to defer*/); | 140 bbh->insert((void*)i, fBounds[i], true/*ok to defer*/); |
140 } | 141 } |
141 } | 142 } |
142 bbh->flushDeferredInserts(); | 143 bbh->flushDeferredInserts(); |
143 } | 144 } |
144 | 145 |
145 template <typename T> void operator()(const T& r) { | 146 template <typename T> void operator()(const T& r) { |
| 147 this->updateCTM(r); |
146 this->trackBounds(r); | 148 this->trackBounds(r); |
147 } | 149 } |
148 | 150 |
149 private: | 151 private: |
150 struct SaveBounds { | 152 struct SaveBounds { |
151 int controlOps; // Number of control ops in this Save block, including
the Save. | 153 int controlOps; // Number of control ops in this Save block, including
the Save. |
152 SkIRect bounds; // Bounds of everything in the block. | 154 SkIRect bounds; // Bounds of everything in the block. |
153 }; | 155 }; |
154 | 156 |
| 157 template <typename T> void updateCTM(const T&) { /* most ops don't change th
e CTM */ } |
| 158 void updateCTM(const Restore& r) { fCTM = r.matrix; } |
| 159 void updateCTM(const SetMatrix& r) { fCTM = r.matrix; } |
| 160 void updateCTM(const Concat& r) { fCTM.preConcat(r.matrix); } |
| 161 |
155 // The bounds of these ops must be calculated when we hit the Restore | 162 // The bounds of these ops must be calculated when we hit the Restore |
156 // from the bounds of the ops in the same Save block. | 163 // from the bounds of the ops in the same Save block. |
157 void trackBounds(const Save&) { this->pushSaveBlock(); } | 164 void trackBounds(const Save&) { this->pushSaveBlock(); } |
158 // TODO: bounds of SaveLayer may be more complicated? | 165 // TODO: bounds of SaveLayer may be more complicated? |
159 void trackBounds(const SaveLayer&) { this->pushSaveBlock(); } | 166 void trackBounds(const SaveLayer&) { this->pushSaveBlock(); } |
160 void trackBounds(const Restore&) { fBounds[fCurrentOp] = this->popSaveBlo
ck(); } | 167 void trackBounds(const Restore&) { fBounds[fCurrentOp] = this->popSaveBlo
ck(); } |
161 | 168 |
162 void trackBounds(const Concat&) { this->pushControl(); } | 169 void trackBounds(const Concat&) { this->pushControl(); } |
163 void trackBounds(const SetMatrix&) { this->pushControl(); } | 170 void trackBounds(const SetMatrix&) { this->pushControl(); } |
164 void trackBounds(const ClipRect&) { this->pushControl(); } | 171 void trackBounds(const ClipRect&) { this->pushControl(); } |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
212 void updateSaveBounds(const SkIRect& bounds) { | 219 void updateSaveBounds(const SkIRect& bounds) { |
213 // If we're in a Save block, expand its bounds to cover these bounds too
. | 220 // If we're in a Save block, expand its bounds to cover these bounds too
. |
214 if (!fSaveStack.isEmpty()) { | 221 if (!fSaveStack.isEmpty()) { |
215 fSaveStack.top().bounds.join(bounds); | 222 fSaveStack.top().bounds.join(bounds); |
216 } | 223 } |
217 } | 224 } |
218 | 225 |
219 SkIRect bounds(const NoOp&) { return SkIRect::MakeEmpty(); } // NoOps don't
draw anywhere. | 226 SkIRect bounds(const NoOp&) { return SkIRect::MakeEmpty(); } // NoOps don't
draw anywhere. |
220 | 227 |
221 SkAutoTMalloc<SkIRect> fBounds; // One for each op in the record. | 228 SkAutoTMalloc<SkIRect> fBounds; // One for each op in the record. |
| 229 SkMatrix fCTM; |
222 unsigned fCurrentOp; | 230 unsigned fCurrentOp; |
223 SkTDArray<SaveBounds> fSaveStack; | 231 SkTDArray<SaveBounds> fSaveStack; |
224 SkTDArray<unsigned> fControlIndices; | 232 SkTDArray<unsigned> fControlIndices; |
225 }; | 233 }; |
226 | 234 |
227 } // namespace SkRecords | 235 } // namespace SkRecords |
228 | 236 |
229 void SkRecordFillBounds(const SkRecord& record, SkBBoxHierarchy* bbh) { | 237 void SkRecordFillBounds(const SkRecord& record, SkBBoxHierarchy* bbh) { |
230 SkRecords::FillBounds(record, bbh); | 238 SkRecords::FillBounds(record, bbh); |
231 } | 239 } |
OLD | NEW |