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 | 9 |
10 #include "SkColorPriv.h" | 10 #include "SkColorPriv.h" |
11 #include "SkDebugCanvas.h" | 11 #include "SkDebugCanvas.h" |
12 #include "SkDrawCommand.h" | 12 #include "SkDrawCommand.h" |
13 #include "SkDrawFilter.h" | |
14 #include "SkDevice.h" | 13 #include "SkDevice.h" |
14 #include "SkPaintFilterCanvas.h" | |
15 #include "SkXfermode.h" | 15 #include "SkXfermode.h" |
16 | 16 |
17 namespace { | |
18 | |
19 class OverdrawXfermode : public SkXfermode { | |
20 public: | |
21 SkPMColor xferColor(SkPMColor src, SkPMColor dst) const SK_OVERRIDE { | |
22 // This table encodes the color progression of the overdraw visualizatio n | |
23 static const SkPMColor gTable[] = { | |
24 SkPackARGB32(0x00, 0x00, 0x00, 0x00), | |
25 SkPackARGB32(0xFF, 128, 158, 255), | |
26 SkPackARGB32(0xFF, 170, 185, 212), | |
27 SkPackARGB32(0xFF, 213, 195, 170), | |
28 SkPackARGB32(0xFF, 255, 192, 127), | |
29 SkPackARGB32(0xFF, 255, 185, 85), | |
30 SkPackARGB32(0xFF, 255, 165, 42), | |
31 SkPackARGB32(0xFF, 255, 135, 0), | |
32 SkPackARGB32(0xFF, 255, 95, 0), | |
33 SkPackARGB32(0xFF, 255, 50, 0), | |
34 SkPackARGB32(0xFF, 255, 0, 0) | |
35 }; | |
36 | |
37 | |
38 int idx; | |
39 if (SkColorGetR(dst) < 64) { // 0 | |
40 idx = 0; | |
41 } else if (SkColorGetG(dst) < 25) { // 10 | |
42 idx = 9; // cap at 9 for upcoming increment | |
43 } else if ((SkColorGetB(dst)+21)/42 > 0) { // 1-6 | |
44 idx = 7 - (SkColorGetB(dst)+21)/42; | |
45 } else { // 7-9 | |
46 idx = 10 - (SkColorGetG(dst)+22)/45; | |
47 } | |
48 ++idx; | |
49 SkASSERT(idx < (int)SK_ARRAY_COUNT(gTable)); | |
50 | |
51 return gTable[idx]; | |
52 } | |
53 | |
54 Factory getFactory() const SK_OVERRIDE { return NULL; } | |
55 #ifndef SK_IGNORE_TO_STRING | |
56 virtual void toString(SkString* str) const SK_OVERRIDE { str->set("OverdrawX fermode"); } | |
57 #endif | |
58 }; | |
59 | |
60 class DebugPaintFilterCanvas : public SkPaintFilterCanvas { | |
61 public: | |
62 DebugPaintFilterCanvas(int width, int height, bool overdrawViz, bool overrid eFilterQuality, | |
63 SkFilterQuality quality) | |
64 : INHERITED(width, height) | |
65 , fOverdrawXfermode(overdrawViz ? SkNEW(OverdrawXfermode) : NULL) | |
66 , fOverrideFilterQuality(overrideFilterQuality) | |
67 , fFilterQuality(quality) { } | |
68 | |
69 protected: | |
70 void filterPaint(SkPaint* paint, Type) const override { | |
71 if (fOverdrawXfermode) { | |
tomhudson
2015/03/25 14:52:51
Is there some reasonable way to be more explicit i
f(malita)
2015/03/25 15:29:23
Done.
| |
72 paint->setAntiAlias(false); | |
73 paint->setXfermode(fOverdrawXfermode.get()); | |
74 } | |
75 | |
76 if (fOverrideFilterQuality) { | |
77 paint->setFilterQuality(fFilterQuality); | |
78 } | |
79 } | |
80 | |
81 void onDrawPicture(const SkPicture* picture, const SkMatrix* matrix, const S kPaint* paint) { | |
82 // We need to replay the picture onto this canvas in order to filter its internal paints. | |
83 this->SkCanvas::onDrawPicture(picture, matrix, paint); | |
84 } | |
85 | |
86 private: | |
87 SkAutoTUnref<SkXfermode> fOverdrawXfermode; | |
88 | |
89 bool fOverrideFilterQuality; | |
90 SkFilterQuality fFilterQuality; | |
91 | |
92 typedef SkPaintFilterCanvas INHERITED; | |
93 }; | |
94 | |
95 } | |
96 | |
17 SkDebugCanvas::SkDebugCanvas(int width, int height) | 97 SkDebugCanvas::SkDebugCanvas(int width, int height) |
18 : INHERITED(width, height) | 98 : INHERITED(width, height) |
19 , fPicture(NULL) | 99 , fPicture(NULL) |
20 , fFilter(false) | 100 , fFilter(false) |
21 , fMegaVizMode(false) | 101 , fMegaVizMode(false) |
22 , fOverdrawViz(false) | 102 , fOverdrawViz(false) |
23 , fOverdrawFilter(NULL) | 103 , fOverrideFilterQuality(false) |
24 , fOverrideTexFiltering(false) | 104 , fFilterQuality(kNone_SkFilterQuality) { |
25 , fTexOverrideFilter(NULL) { | |
26 fUserMatrix.reset(); | 105 fUserMatrix.reset(); |
27 | 106 |
28 // SkPicturePlayback uses the base-class' quickReject calls to cull clipped | 107 // SkPicturePlayback uses the base-class' quickReject calls to cull clipped |
29 // operations. This can lead to problems in the debugger which expects all | 108 // operations. This can lead to problems in the debugger which expects all |
30 // the operations in the captured skp to appear in the debug canvas. To | 109 // the operations in the captured skp to appear in the debug canvas. To |
31 // circumvent this we create a wide open clip here (an empty clip rect | 110 // circumvent this we create a wide open clip here (an empty clip rect |
32 // is not sufficient). | 111 // is not sufficient). |
33 // Internally, the SkRect passed to clipRect is converted to an SkIRect and | 112 // Internally, the SkRect passed to clipRect is converted to an SkIRect and |
34 // rounded out. The following code creates a nearly maximal rect that will | 113 // rounded out. The following code creates a nearly maximal rect that will |
35 // not get collapsed by the coming conversions (Due to precision loss the | 114 // not get collapsed by the coming conversions (Due to precision loss the |
36 // inset has to be surprisingly large). | 115 // inset has to be surprisingly large). |
37 SkIRect largeIRect = SkIRect::MakeLargest(); | 116 SkIRect largeIRect = SkIRect::MakeLargest(); |
38 largeIRect.inset(1024, 1024); | 117 largeIRect.inset(1024, 1024); |
39 SkRect large = SkRect::Make(largeIRect); | 118 SkRect large = SkRect::Make(largeIRect); |
40 #ifdef SK_DEBUG | 119 #ifdef SK_DEBUG |
41 SkASSERT(!large.roundOut().isEmpty()); | 120 SkASSERT(!large.roundOut().isEmpty()); |
42 #endif | 121 #endif |
43 // call the base class' version to avoid adding a draw command | 122 // call the base class' version to avoid adding a draw command |
44 this->INHERITED::onClipRect(large, SkRegion::kReplace_Op, kHard_ClipEdgeStyl e); | 123 this->INHERITED::onClipRect(large, SkRegion::kReplace_Op, kHard_ClipEdgeStyl e); |
45 } | 124 } |
46 | 125 |
47 SkDebugCanvas::~SkDebugCanvas() { | 126 SkDebugCanvas::~SkDebugCanvas() { |
48 fCommandVector.deleteAll(); | 127 fCommandVector.deleteAll(); |
49 SkSafeUnref(fOverdrawFilter); | |
50 SkSafeUnref(fTexOverrideFilter); | |
51 } | 128 } |
52 | 129 |
53 void SkDebugCanvas::addDrawCommand(SkDrawCommand* command) { | 130 void SkDebugCanvas::addDrawCommand(SkDrawCommand* command) { |
54 command->setOffset(this->getOpID()); | 131 command->setOffset(this->getOpID()); |
55 fCommandVector.push(command); | 132 fCommandVector.push(command); |
56 } | 133 } |
57 | 134 |
58 void SkDebugCanvas::draw(SkCanvas* canvas) { | 135 void SkDebugCanvas::draw(SkCanvas* canvas) { |
59 if (!fCommandVector.isEmpty()) { | 136 if (!fCommandVector.isEmpty()) { |
60 this->drawTo(canvas, fCommandVector.count() - 1); | 137 this->drawTo(canvas, fCommandVector.count() - 1); |
(...skipping 20 matching lines...) Expand all Loading... | |
81 fCommandVector[i]->execute(&canvas); | 158 fCommandVector[i]->execute(&canvas); |
82 } | 159 } |
83 if (prev != bitmap.getColor(0,0)) { | 160 if (prev != bitmap.getColor(0,0)) { |
84 layer = i; | 161 layer = i; |
85 } | 162 } |
86 prev = bitmap.getColor(0,0); | 163 prev = bitmap.getColor(0,0); |
87 } | 164 } |
88 return layer; | 165 return layer; |
89 } | 166 } |
90 | 167 |
91 class OverdrawXfermode : public SkXfermode { | |
92 public: | |
93 SkPMColor xferColor(SkPMColor src, SkPMColor dst) const SK_OVERRIDE { | |
94 // This table encodes the color progression of the overdraw visualizatio n | |
95 static const SkPMColor gTable[] = { | |
96 SkPackARGB32(0x00, 0x00, 0x00, 0x00), | |
97 SkPackARGB32(0xFF, 128, 158, 255), | |
98 SkPackARGB32(0xFF, 170, 185, 212), | |
99 SkPackARGB32(0xFF, 213, 195, 170), | |
100 SkPackARGB32(0xFF, 255, 192, 127), | |
101 SkPackARGB32(0xFF, 255, 185, 85), | |
102 SkPackARGB32(0xFF, 255, 165, 42), | |
103 SkPackARGB32(0xFF, 255, 135, 0), | |
104 SkPackARGB32(0xFF, 255, 95, 0), | |
105 SkPackARGB32(0xFF, 255, 50, 0), | |
106 SkPackARGB32(0xFF, 255, 0, 0) | |
107 }; | |
108 | |
109 | |
110 int idx; | |
111 if (SkColorGetR(dst) < 64) { // 0 | |
112 idx = 0; | |
113 } else if (SkColorGetG(dst) < 25) { // 10 | |
114 idx = 9; // cap at 9 for upcoming increment | |
115 } else if ((SkColorGetB(dst)+21)/42 > 0) { // 1-6 | |
116 idx = 7 - (SkColorGetB(dst)+21)/42; | |
117 } else { // 7-9 | |
118 idx = 10 - (SkColorGetG(dst)+22)/45; | |
119 } | |
120 ++idx; | |
121 SkASSERT(idx < (int)SK_ARRAY_COUNT(gTable)); | |
122 | |
123 return gTable[idx]; | |
124 } | |
125 | |
126 Factory getFactory() const SK_OVERRIDE { return NULL; } | |
127 #ifndef SK_IGNORE_TO_STRING | |
128 virtual void toString(SkString* str) const SK_OVERRIDE { str->set("OverdrawX fermode"); } | |
129 #endif | |
130 }; | |
131 | |
132 class SkOverdrawFilter : public SkDrawFilter { | |
133 public: | |
134 SkOverdrawFilter() { | |
135 fXferMode = SkNEW(OverdrawXfermode); | |
136 } | |
137 | |
138 virtual ~SkOverdrawFilter() { | |
139 delete fXferMode; | |
140 } | |
141 | |
142 bool filter(SkPaint* p, Type) SK_OVERRIDE { | |
143 p->setXfermode(fXferMode); | |
144 p->setAntiAlias(false); | |
145 return true; | |
146 } | |
147 | |
148 protected: | |
149 SkXfermode* fXferMode; | |
150 | |
151 private: | |
152 typedef SkDrawFilter INHERITED; | |
153 }; | |
154 | |
155 // SkTexOverrideFilter modifies every paint to use the specified | |
156 // texture filtering mode | |
157 class SkTexOverrideFilter : public SkDrawFilter { | |
158 public: | |
159 SkTexOverrideFilter() : fFilterQuality(kNone_SkFilterQuality) { | |
160 } | |
161 | |
162 void setFilterQuality(SkFilterQuality filterQuality) { | |
163 fFilterQuality = filterQuality; | |
164 } | |
165 | |
166 bool filter(SkPaint* p, Type) SK_OVERRIDE { | |
167 p->setFilterQuality(fFilterQuality); | |
168 return true; | |
169 } | |
170 | |
171 protected: | |
172 SkFilterQuality fFilterQuality; | |
173 | |
174 private: | |
175 typedef SkDrawFilter INHERITED; | |
176 }; | |
177 | |
178 class SkDebugClipVisitor : public SkCanvas::ClipVisitor { | 168 class SkDebugClipVisitor : public SkCanvas::ClipVisitor { |
179 public: | 169 public: |
180 SkDebugClipVisitor(SkCanvas* canvas) : fCanvas(canvas) {} | 170 SkDebugClipVisitor(SkCanvas* canvas) : fCanvas(canvas) {} |
181 | 171 |
182 void clipRect(const SkRect& r, SkRegion::Op, bool doAA) SK_OVERRIDE { | 172 void clipRect(const SkRect& r, SkRegion::Op, bool doAA) SK_OVERRIDE { |
183 SkPaint p; | 173 SkPaint p; |
184 p.setColor(SK_ColorRED); | 174 p.setColor(SK_ColorRED); |
185 p.setStyle(SkPaint::kStroke_Style); | 175 p.setStyle(SkPaint::kStroke_Style); |
186 p.setAntiAlias(doAA); | 176 p.setAntiAlias(doAA); |
187 fCanvas->drawRect(r, p); | 177 fCanvas->drawRect(r, p); |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
243 | 233 |
244 bool pathOpsMode = getAllowSimplifyClip(); | 234 bool pathOpsMode = getAllowSimplifyClip(); |
245 canvas->setAllowSimplifyClip(pathOpsMode); | 235 canvas->setAllowSimplifyClip(pathOpsMode); |
246 canvas->clear(SK_ColorTRANSPARENT); | 236 canvas->clear(SK_ColorTRANSPARENT); |
247 canvas->resetMatrix(); | 237 canvas->resetMatrix(); |
248 if (!windowRect.isEmpty()) { | 238 if (!windowRect.isEmpty()) { |
249 canvas->clipRect(windowRect, SkRegion::kReplace_Op); | 239 canvas->clipRect(windowRect, SkRegion::kReplace_Op); |
250 } | 240 } |
251 this->applyUserTransform(canvas); | 241 this->applyUserTransform(canvas); |
252 | 242 |
253 // The setting of the draw filter has to go here (rather than in | 243 if (fPaintFilterCanvas) { |
254 // SkRasterWidget) due to the canvas restores this class performs. | 244 fPaintFilterCanvas->addCanvas(canvas); |
255 // Since the draw filter is stored in the layer stack if we | 245 canvas = fPaintFilterCanvas.get(); |
256 // call setDrawFilter on anything but the root layer odd things happen. | |
257 if (fOverdrawViz) { | |
258 if (NULL == fOverdrawFilter) { | |
259 fOverdrawFilter = new SkOverdrawFilter; | |
260 } | |
261 | |
262 if (fOverdrawFilter != canvas->getDrawFilter()) { | |
263 canvas->setDrawFilter(fOverdrawFilter); | |
264 } | |
265 } else if (fOverrideTexFiltering) { | |
266 if (NULL == fTexOverrideFilter) { | |
267 fTexOverrideFilter = new SkTexOverrideFilter; | |
268 } | |
269 | |
270 if (fTexOverrideFilter != canvas->getDrawFilter()) { | |
271 canvas->setDrawFilter(fTexOverrideFilter); | |
272 } | |
273 } else { | |
274 canvas->setDrawFilter(NULL); | |
275 } | 246 } |
276 | 247 |
277 if (fMegaVizMode) { | 248 if (fMegaVizMode) { |
278 this->markActiveCommands(index); | 249 this->markActiveCommands(index); |
279 } | 250 } |
280 | 251 |
281 for (int i = 0; i <= index; i++) { | 252 for (int i = 0; i <= index; i++) { |
282 if (i == index && fFilter) { | 253 if (i == index && fFilter) { |
283 canvas->clear(0xAAFFFFFF); | 254 canvas->clear(0xAAFFFFFF); |
284 } | 255 } |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
335 } | 306 } |
336 } | 307 } |
337 this->lastClipStackData(devPath); | 308 this->lastClipStackData(devPath); |
338 } | 309 } |
339 fMatrix = canvas->getTotalMatrix(); | 310 fMatrix = canvas->getTotalMatrix(); |
340 if (!canvas->getClipDeviceBounds(&fClip)) { | 311 if (!canvas->getClipDeviceBounds(&fClip)) { |
341 fClip.setEmpty(); | 312 fClip.setEmpty(); |
342 } | 313 } |
343 | 314 |
344 canvas->restoreToCount(saveCount); | 315 canvas->restoreToCount(saveCount); |
316 | |
317 if (fPaintFilterCanvas) { | |
318 fPaintFilterCanvas->removeAll(); | |
319 } | |
345 } | 320 } |
346 | 321 |
347 void SkDebugCanvas::deleteDrawCommandAt(int index) { | 322 void SkDebugCanvas::deleteDrawCommandAt(int index) { |
348 SkASSERT(index < fCommandVector.count()); | 323 SkASSERT(index < fCommandVector.count()); |
349 delete fCommandVector[index]; | 324 delete fCommandVector[index]; |
350 fCommandVector.remove(index); | 325 fCommandVector.remove(index); |
351 } | 326 } |
352 | 327 |
353 SkDrawCommand* SkDebugCanvas::getDrawCommandAt(int index) { | 328 SkDrawCommand* SkDebugCanvas::getDrawCommandAt(int index) { |
354 SkASSERT(index < fCommandVector.count()); | 329 SkASSERT(index < fCommandVector.count()); |
(...skipping 17 matching lines...) Expand all Loading... | |
372 } | 347 } |
373 | 348 |
374 const SkTDArray <SkDrawCommand*>& SkDebugCanvas::getDrawCommands() const { | 349 const SkTDArray <SkDrawCommand*>& SkDebugCanvas::getDrawCommands() const { |
375 return fCommandVector; | 350 return fCommandVector; |
376 } | 351 } |
377 | 352 |
378 SkTDArray <SkDrawCommand*>& SkDebugCanvas::getDrawCommands() { | 353 SkTDArray <SkDrawCommand*>& SkDebugCanvas::getDrawCommands() { |
379 return fCommandVector; | 354 return fCommandVector; |
380 } | 355 } |
381 | 356 |
382 void SkDebugCanvas::overrideTexFiltering(bool overrideTexFiltering, SkFilterQual ity quality) { | 357 void SkDebugCanvas::updatePaintFilterCanvas() { |
383 if (NULL == fTexOverrideFilter) { | 358 if (!fOverdrawViz && !fOverrideFilterQuality) { |
384 fTexOverrideFilter = new SkTexOverrideFilter; | 359 fPaintFilterCanvas.reset(NULL); |
360 return; | |
385 } | 361 } |
386 | 362 |
387 fOverrideTexFiltering = overrideTexFiltering; | 363 const SkImageInfo info = this->imageInfo(); |
388 fTexOverrideFilter->setFilterQuality(quality); | 364 fPaintFilterCanvas.reset(SkNEW_ARGS(DebugPaintFilterCanvas, (info.width(), |
365 info.height(), | |
366 fOverdrawViz, | |
367 fOverrideFilter Quality, | |
368 fFilterQuality) )); | |
369 } | |
370 | |
371 void SkDebugCanvas::setOverdrawViz(bool overdrawViz) { | |
372 if (fOverdrawViz == overdrawViz) { | |
373 return; | |
374 } | |
375 | |
376 fOverdrawViz = overdrawViz; | |
robertphillips
2015/03/25 15:07:06
this->
f(malita)
2015/03/25 15:29:23
Done.
| |
377 updatePaintFilterCanvas(); | |
378 } | |
379 | |
380 void SkDebugCanvas::overrideTexFiltering(bool overrideTexFiltering, SkFilterQual ity quality) { | |
381 if (fOverrideFilterQuality == overrideTexFiltering && fFilterQuality == qual ity) { | |
382 return; | |
383 } | |
384 | |
385 fOverrideFilterQuality = overrideTexFiltering; | |
386 fFilterQuality = quality; | |
robertphillips
2015/03/25 15:07:06
this->
f(malita)
2015/03/25 15:29:23
Done.
| |
387 updatePaintFilterCanvas(); | |
389 } | 388 } |
390 | 389 |
391 void SkDebugCanvas::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyl e edgeStyle) { | 390 void SkDebugCanvas::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyl e edgeStyle) { |
392 this->addDrawCommand(new SkClipPathCommand(path, op, kSoft_ClipEdgeStyle == edgeStyle)); | 391 this->addDrawCommand(new SkClipPathCommand(path, op, kSoft_ClipEdgeStyle == edgeStyle)); |
393 } | 392 } |
394 | 393 |
395 void SkDebugCanvas::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyl e edgeStyle) { | 394 void SkDebugCanvas::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyl e edgeStyle) { |
396 this->addDrawCommand(new SkClipRectCommand(rect, op, kSoft_ClipEdgeStyle == edgeStyle)); | 395 this->addDrawCommand(new SkClipRectCommand(rect, op, kSoft_ClipEdgeStyle == edgeStyle)); |
397 } | 396 } |
398 | 397 |
(...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
673 } | 672 } |
674 | 673 |
675 bool SkDebugCanvas::lastClipStackData(const SkPath& devPath) { | 674 bool SkDebugCanvas::lastClipStackData(const SkPath& devPath) { |
676 if (fCalledAddStackData) { | 675 if (fCalledAddStackData) { |
677 fClipStackData.appendf("<br>"); | 676 fClipStackData.appendf("<br>"); |
678 addPathData(devPath, "pathOut"); | 677 addPathData(devPath, "pathOut"); |
679 return true; | 678 return true; |
680 } | 679 } |
681 return false; | 680 return false; |
682 } | 681 } |
OLD | NEW |