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 |
11 void SkRecordDraw(const SkRecord& record, | 11 void SkRecordDraw(const SkRecord& record, |
12 SkCanvas* canvas, | 12 SkCanvas* canvas, |
13 const SkBBoxHierarchy* bbh, | 13 const SkBBoxHierarchy* bbh, |
14 SkDrawPictureCallback* callback) { | 14 SkDrawPictureCallback* callback) { |
15 SkAutoCanvasRestore saveRestore(canvas, true /*save now, restore at exit*/); | 15 SkAutoCanvasRestore saveRestore(canvas, true /*save now, restore at exit*/); |
16 | 16 |
17 if (NULL != bbh) { | 17 if (NULL != bbh) { |
18 SkASSERT(bbh->getCount() == SkToInt(record.count())); | |
19 | |
20 // Draw only ops that affect pixels in the canvas's current clip. | 18 // Draw only ops that affect pixels in the canvas's current clip. |
21 SkIRect devBounds; | 19 SkIRect devBounds; |
22 canvas->getClipDeviceBounds(&devBounds); | 20 canvas->getClipDeviceBounds(&devBounds); |
23 SkTDArray<void*> ops; | 21 SkTDArray<void*> ops; |
24 bbh->search(devBounds, &ops); | 22 bbh->search(devBounds, &ops); |
25 | 23 |
26 // Until we start filling in real bounds, we should get every op back. | |
27 SkASSERT(ops.count() == SkToInt(record.count())); | |
28 | |
29 // FIXME: QuadTree doesn't send these back in the order we inserted them . :( | 24 // FIXME: QuadTree doesn't send these back in the order we inserted them . :( |
30 // Also remove the sort in SkPictureData::getActiveOps()? | 25 // Also remove the sort in SkPictureData::getActiveOps()? |
31 if (ops.count() > 0) { | 26 if (ops.count() > 0) { |
32 SkTQSort(ops.begin(), ops.end() - 1, SkTCompareLT<void*>()); | 27 SkTQSort(ops.begin(), ops.end() - 1, SkTCompareLT<void*>()); |
33 } | 28 } |
34 | 29 |
35 SkRecords::Draw draw(canvas); | 30 SkRecords::Draw draw(canvas); |
36 for (int i = 0; i < ops.count(); i++) { | 31 for (int i = 0; i < ops.count(); i++) { |
37 if (NULL != callback && callback->abortDrawing()) { | 32 if (NULL != callback && callback->abortDrawing()) { |
38 return; | 33 return; |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
92 DRAW(DrawRRect, drawRRect(r.rrect, r.paint)); | 87 DRAW(DrawRRect, drawRRect(r.rrect, r.paint)); |
93 DRAW(DrawRect, drawRect(r.rect, r.paint)); | 88 DRAW(DrawRect, drawRect(r.rect, r.paint)); |
94 DRAW(DrawSprite, drawSprite(shallow_copy(r.bitmap), r.left, r.top, r.paint)); | 89 DRAW(DrawSprite, drawSprite(shallow_copy(r.bitmap), r.left, r.top, r.paint)); |
95 DRAW(DrawText, drawText(r.text, r.byteLength, r.x, r.y, r.paint)); | 90 DRAW(DrawText, drawText(r.text, r.byteLength, r.x, r.y, r.paint)); |
96 DRAW(DrawTextOnPath, drawTextOnPath(r.text, r.byteLength, r.path, r.matrix, r.pa int)); | 91 DRAW(DrawTextOnPath, drawTextOnPath(r.text, r.byteLength, r.path, r.matrix, r.pa int)); |
97 DRAW(DrawVertices, drawVertices(r.vmode, r.vertexCount, r.vertices, r.texs, r.co lors, | 92 DRAW(DrawVertices, drawVertices(r.vmode, r.vertexCount, r.vertices, r.texs, r.co lors, |
98 r.xmode.get(), r.indices, r.indexCount, r.paint) ); | 93 r.xmode.get(), r.indices, r.indexCount, r.paint) ); |
99 #undef DRAW | 94 #undef DRAW |
100 | 95 |
101 | 96 |
102 // This is an SkRecord visitor that fills an SkBBoxHierarchy. | 97 // This is an SkRecord visitor that fills an SkBBoxHierarchy. |
robertphillips
2014/08/13 18:53:46
// Every operation (including save* and control op
| |
103 class FillBounds : SkNoncopyable { | 98 class FillBounds : SkNoncopyable { |
104 public: | 99 public: |
105 explicit FillBounds(SkBBoxHierarchy* bbh) : fBBH(bbh), fIndex(0) {} | 100 FillBounds(const SkRecord& record, SkBBoxHierarchy* bbh) : fBounds(record.co unt()) { |
106 ~FillBounds() { fBBH->flushDeferredInserts(); } | 101 // Calculate bounds for all ops. This won't go quite in order, so we'll need |
102 // to store the bounds separately then feed them in to the BBH later in order. | |
103 for (fI = 0; fI < record.count(); fI++) { | |
104 record.visit<void>(fI, *this); | |
105 } | |
107 | 106 |
108 uintptr_t index() const { return fIndex; } | 107 // If we have any lingering unpaired Saves, simulate restores to make |
109 void next() { ++fIndex; } | 108 // sure all ops in those Save blocks have their bounds calculated. |
109 while (!fSaves.isEmpty()) { | |
110 this->popSaveBlock(); | |
111 } | |
112 | |
113 // Any control ops not part of any Save/Restore block draw everywhere. | |
114 while (!fControls.isEmpty()) { | |
115 this->popControl(SkIRect::MakeLargest()); | |
116 } | |
117 | |
118 // Finally feed all stored bounds into the BBH. They'll be returned in this order. | |
119 SkASSERT(NULL != bbh); | |
120 for (uintptr_t i = 0; i < record.count(); i++) { | |
121 if (!fBounds[i].isEmpty()) { | |
122 bbh->insert((void*)i, fBounds[i], true/*ok to defer*/); | |
123 } | |
124 } | |
125 bbh->flushDeferredInserts(); | |
126 } | |
110 | 127 |
111 template <typename T> void operator()(const T& r) { | 128 template <typename T> void operator()(const T& r) { |
112 // MakeLargest() is a trivially safe default for ops that haven't been b ounded yet. | 129 this->trackBounds(r); |
113 this->insert(this->index(), SkIRect::MakeLargest()); | |
114 } | 130 } |
115 | 131 |
116 private: | 132 private: |
117 void insert(uintptr_t opIndex, const SkIRect& bounds) { | 133 struct SaveBounds { |
118 fBBH->insert((void*)opIndex, bounds, true/*ok to defer*/); | 134 int controlOps; // Number of control ops in this Save block, including the Save. |
135 SkIRect bounds; // Bounds of everything in the block. | |
136 }; | |
137 | |
138 // The bounds of these ops must be calculated when we hit the Restore | |
139 // from the bounds of the ops in the same Save block. | |
140 void trackBounds(const Save&) { this->pushSaveBlock(); } | |
141 // TODO: bounds of SaveLayer may be more complicated? | |
142 void trackBounds(const SaveLayer&) { this->pushSaveBlock(); } | |
143 void trackBounds(const Restore&) { fBounds[fI] = this->popSaveBlock(); } | |
144 | |
145 void trackBounds(const Concat&) { this->pushControl(); } | |
146 void trackBounds(const SetMatrix&) { this->pushControl(); } | |
147 void trackBounds(const ClipRect&) { this->pushControl(); } | |
148 void trackBounds(const ClipRRect&) { this->pushControl(); } | |
149 void trackBounds(const ClipPath&) { this->pushControl(); } | |
150 void trackBounds(const ClipRegion&) { this->pushControl(); } | |
151 | |
152 // For all other ops, we can calculate and store the bounds directly now. | |
153 template <typename T> void trackBounds(const T& op) { | |
154 fBounds[fI] = this->bounds(op); // Store our own bounds. | |
155 this->updateSaveBounds(fBounds[fI]); // If we're in a Save, expand its b ounds to contain us. | |
119 } | 156 } |
120 | 157 |
121 SkBBoxHierarchy* fBBH; // Unowned. The BBH is guaranteed to be ref'd for ou r lifetime. | 158 // TODO: remove this trivially-safe default when done bounding all ops |
122 uintptr_t fIndex; | 159 template <typename T> SkIRect bounds(const T&) { return SkIRect::MakeLargest (); } |
160 | |
161 void pushSaveBlock() { | |
162 // Starting a new Save block. Push a new entry to represent that. | |
163 SaveBounds sb = { 0, SkIRect::MakeEmpty() }; | |
164 fSaves.push(sb); | |
165 this->pushControl(); | |
166 } | |
167 | |
168 SkIRect popSaveBlock() { | |
robertphillips
2014/08/13 18:53:46
We're done _with_ ... ?
| |
169 // We're done the Save block. Apply the block's bounds to all control o ps inside it. | |
170 SaveBounds sb; | |
171 fSaves.pop(&sb); | |
172 while (sb.controlOps --> 0) { | |
173 this->popControl(sb.bounds); | |
174 } | |
175 | |
176 // This whole Save block may be part another Save block. | |
177 this->updateSaveBounds(sb.bounds); | |
178 | |
179 // If called from a real Restore (not a phony one for balance), it'll ne ed the bounds. | |
180 return sb.bounds; | |
181 } | |
182 | |
183 void pushControl() { | |
184 fControls.push(fI); | |
185 if (!fSaves.isEmpty()) { | |
186 fSaves.top().controlOps++; | |
187 } | |
188 } | |
189 | |
190 void popControl(const SkIRect& bounds) { | |
191 fBounds[fControls.top()] = bounds; | |
192 fControls.pop(); | |
193 } | |
194 | |
195 void updateSaveBounds(const SkIRect& bounds) { | |
196 // If we're in a Save block, expand its bounds to cover these bounds too . | |
197 if (!fSaves.isEmpty()) { | |
198 fSaves.top().bounds.join(bounds); | |
199 } | |
200 } | |
201 | |
202 SkIRect bounds(const NoOp&) { return SkIRect::MakeEmpty(); } // NoOps don't draw anywhere. | |
203 | |
204 SkAutoTMalloc<SkIRect> fBounds; // One for each op in the record. | |
robertphillips
2014/08/13 18:53:46
fI -> fCurOp, fCurBound, fCurOpIndex ?
| |
205 unsigned fI; | |
robertphillips
2014/08/13 18:53:46
// Contains both saves and saveLayers ?
fSaves ->
| |
206 SkTDArray<SaveBounds> fSaves; | |
robertphillips
2014/08/13 18:53:46
// A unified list of control operations encountere
| |
207 SkTDArray<unsigned> fControls; | |
123 }; | 208 }; |
124 | 209 |
125 } // namespace SkRecords | 210 } // namespace SkRecords |
126 | 211 |
127 void SkRecordFillBounds(const SkRecord& record, SkBBoxHierarchy* bbh) { | 212 void SkRecordFillBounds(const SkRecord& record, SkBBoxHierarchy* bbh) { |
128 SkASSERT(NULL != bbh); | 213 SkRecords::FillBounds(record, bbh); |
129 for(SkRecords::FillBounds fb(bbh); fb.index() < record.count(); fb.next()) { | |
130 record.visit<void>(fb.index(), fb); | |
131 } | |
132 } | 214 } |
OLD | NEW |