OLD | NEW |
---|---|
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/debug/trace_event.h" | 5 #include "base/debug/trace_event.h" |
6 #include "base/logging.h" | 6 #include "base/logging.h" |
7 #include "skia/ext/analysis_canvas.h" | 7 #include "skia/ext/analysis_canvas.h" |
8 #include "third_party/skia/include/core/SkDraw.h" | 8 #include "third_party/skia/include/core/SkDraw.h" |
9 #include "third_party/skia/include/core/SkRRect.h" | 9 #include "third_party/skia/include/core/SkRRect.h" |
10 #include "third_party/skia/include/core/SkShader.h" | 10 #include "third_party/skia/include/core/SkShader.h" |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
73 } | 73 } |
74 | 74 |
75 void AnalysisCanvas::SetForceNotTransparent(bool flag) { | 75 void AnalysisCanvas::SetForceNotTransparent(bool flag) { |
76 is_forced_not_transparent_ = flag; | 76 is_forced_not_transparent_ = flag; |
77 if (is_forced_not_transparent_) | 77 if (is_forced_not_transparent_) |
78 is_transparent_ = false; | 78 is_transparent_ = false; |
79 } | 79 } |
80 | 80 |
81 void AnalysisCanvas::clear(SkColor color) { | 81 void AnalysisCanvas::clear(SkColor color) { |
82 is_transparent_ = (!is_forced_not_transparent_ && SkColorGetA(color) == 0); | 82 is_transparent_ = (!is_forced_not_transparent_ && SkColorGetA(color) == 0); |
83 has_text_ = false; | |
84 | 83 |
85 if (!is_forced_not_solid_ && SkColorGetA(color) == 255) { | 84 if (!is_forced_not_solid_ && SkColorGetA(color) == 255) { |
86 is_solid_color_ = true; | 85 is_solid_color_ = true; |
87 color_ = color; | 86 color_ = color; |
88 } else { | 87 } else { |
89 is_solid_color_ = false; | 88 is_solid_color_ = false; |
90 } | 89 } |
91 } | 90 } |
92 | 91 |
93 void AnalysisCanvas::drawPaint(const SkPaint& paint) { | 92 void AnalysisCanvas::drawPaint(const SkPaint& paint) { |
94 // This check is in SkCanvas::drawPaint(), and some of our unittests rely on | 93 // This check is in SkCanvas::drawPaint(), and some of our unittests rely on |
95 // on this, so we reproduce it here. | 94 // on this, so we reproduce it here. |
96 if (isClipEmpty()) | 95 if (isClipEmpty()) |
97 return; | 96 return; |
98 | 97 |
99 is_solid_color_ = false; | 98 is_solid_color_ = false; |
100 is_transparent_ = false; | 99 is_transparent_ = false; |
100 ++draw_op_count_; | |
101 } | 101 } |
102 | 102 |
103 void AnalysisCanvas::drawPoints(SkCanvas::PointMode mode, | 103 void AnalysisCanvas::drawPoints(SkCanvas::PointMode mode, |
104 size_t count, | 104 size_t count, |
105 const SkPoint points[], | 105 const SkPoint points[], |
106 const SkPaint& paint) { | 106 const SkPaint& paint) { |
107 is_solid_color_ = false; | 107 is_solid_color_ = false; |
108 is_transparent_ = false; | 108 is_transparent_ = false; |
109 ++draw_op_count_; | |
109 } | 110 } |
110 | 111 |
111 void AnalysisCanvas::drawRect(const SkRect& rect, const SkPaint& paint) { | 112 void AnalysisCanvas::drawRect(const SkRect& rect, const SkPaint& paint) { |
112 // This recreates the early-exit logic in SkCanvas.cpp, which aborts early | 113 // This recreates the early-exit logic in SkCanvas.cpp, which aborts early |
113 // if the paint will "draw nothing". | 114 // if the paint will "draw nothing". |
114 if (paint.nothingToDraw()) | 115 if (paint.nothingToDraw()) |
115 return; | 116 return; |
116 | 117 |
117 bool does_cover_canvas = IsFullQuad(this, rect); | 118 bool does_cover_canvas = IsFullQuad(this, rect); |
118 | 119 |
119 SkXfermode::Mode xfermode; | 120 SkXfermode::Mode xfermode; |
120 SkXfermode::AsMode(paint.getXfermode(), &xfermode); | 121 SkXfermode::AsMode(paint.getXfermode(), &xfermode); |
121 | 122 |
122 // This canvas will become transparent if the following holds: | 123 // This canvas will become transparent if the following holds: |
123 // - The quad is a full tile quad | 124 // - The quad is a full tile quad |
124 // - We're not in "forced not transparent" mode | 125 // - We're not in "forced not transparent" mode |
125 // - Transfer mode is clear (0 color, 0 alpha) | 126 // - Transfer mode is clear (0 color, 0 alpha) |
126 // | 127 // |
127 // If the paint alpha is not 0, or if the transfrer mode is | 128 // If the paint alpha is not 0, or if the transfrer mode is |
128 // not src, then this canvas will not be transparent. | 129 // not src, then this canvas will not be transparent. |
129 // | 130 // |
130 // In all other cases, we keep the current transparent value | 131 // In all other cases, we keep the current transparent value |
131 if (does_cover_canvas && | 132 if (does_cover_canvas && |
132 !is_forced_not_transparent_ && | 133 !is_forced_not_transparent_ && |
133 xfermode == SkXfermode::kClear_Mode) { | 134 xfermode == SkXfermode::kClear_Mode) { |
134 is_transparent_ = true; | 135 is_transparent_ = true; |
135 has_text_ = false; | |
136 } else if (paint.getAlpha() != 0 || xfermode != SkXfermode::kSrc_Mode) { | 136 } else if (paint.getAlpha() != 0 || xfermode != SkXfermode::kSrc_Mode) { |
137 is_transparent_ = false; | 137 is_transparent_ = false; |
138 } | 138 } |
139 | 139 |
140 // This bitmap is solid if and only if the following holds. | 140 // This bitmap is solid if and only if the following holds. |
141 // Note that this might be overly conservative: | 141 // Note that this might be overly conservative: |
142 // - We're not in "forced not solid" mode | 142 // - We're not in "forced not solid" mode |
143 // - Paint is solid color | 143 // - Paint is solid color |
144 // - The quad is a full tile quad | 144 // - The quad is a full tile quad |
145 if (!is_forced_not_solid_ && IsSolidColorPaint(paint) && does_cover_canvas) { | 145 if (!is_forced_not_solid_ && IsSolidColorPaint(paint) && does_cover_canvas) { |
146 is_solid_color_ = true; | 146 is_solid_color_ = true; |
147 color_ = paint.getColor(); | 147 color_ = paint.getColor(); |
148 has_text_ = false; | |
149 } else { | 148 } else { |
150 is_solid_color_ = false; | 149 is_solid_color_ = false; |
151 } | 150 } |
151 ++draw_op_count_; | |
152 } | 152 } |
153 | 153 |
154 void AnalysisCanvas::drawOval(const SkRect& oval, const SkPaint& paint) { | 154 void AnalysisCanvas::drawOval(const SkRect& oval, const SkPaint& paint) { |
155 is_solid_color_ = false; | 155 is_solid_color_ = false; |
156 is_transparent_ = false; | 156 is_transparent_ = false; |
157 ++draw_op_count_; | |
157 } | 158 } |
158 | 159 |
159 void AnalysisCanvas::drawRRect(const SkRRect& rr, const SkPaint& paint) { | 160 void AnalysisCanvas::drawRRect(const SkRRect& rr, const SkPaint& paint) { |
160 // This should add the SkRRect to an SkPath, and call | 161 // This should add the SkRRect to an SkPath, and call |
161 // drawPath, but since drawPath ignores the SkPath, just | 162 // drawPath, but since drawPath ignores the SkPath, just |
162 // do the same work here. | 163 // do the same work here. |
163 is_solid_color_ = false; | 164 is_solid_color_ = false; |
164 is_transparent_ = false; | 165 is_transparent_ = false; |
166 ++draw_op_count_; | |
165 } | 167 } |
166 | 168 |
167 void AnalysisCanvas::drawPath(const SkPath& path, const SkPaint& paint) { | 169 void AnalysisCanvas::drawPath(const SkPath& path, const SkPaint& paint) { |
168 is_solid_color_ = false; | 170 is_solid_color_ = false; |
169 is_transparent_ = false; | 171 is_transparent_ = false; |
172 ++draw_op_count_; | |
170 } | 173 } |
171 | 174 |
172 void AnalysisCanvas::drawBitmap(const SkBitmap& bitmap, | 175 void AnalysisCanvas::drawBitmap(const SkBitmap& bitmap, |
173 SkScalar left, | 176 SkScalar left, |
174 SkScalar top, | 177 SkScalar top, |
175 const SkPaint*) { | 178 const SkPaint*) { |
176 is_solid_color_ = false; | 179 is_solid_color_ = false; |
177 is_transparent_ = false; | 180 is_transparent_ = false; |
181 ++draw_op_count_; | |
178 } | 182 } |
179 | 183 |
180 void AnalysisCanvas::drawBitmapRectToRect(const SkBitmap&, | 184 void AnalysisCanvas::drawBitmapRectToRect(const SkBitmap&, |
181 const SkRect* src, | 185 const SkRect* src, |
182 const SkRect& dst, | 186 const SkRect& dst, |
183 const SkPaint* paint, | 187 const SkPaint* paint, |
184 DrawBitmapRectFlags flags) { | 188 DrawBitmapRectFlags flags) { |
185 // Call drawRect to determine transparency, | 189 // Call drawRect to determine transparency, |
186 // but reset solid color to false. | 190 // but reset solid color to false. |
187 SkPaint tmpPaint; | 191 SkPaint tmpPaint; |
188 if (!paint) | 192 if (!paint) |
189 paint = &tmpPaint; | 193 paint = &tmpPaint; |
190 drawRect(dst, *paint); | 194 drawRect(dst, *paint); |
191 is_solid_color_ = false; | 195 is_solid_color_ = false; |
196 ++draw_op_count_; | |
192 } | 197 } |
193 | 198 |
194 void AnalysisCanvas::drawBitmapMatrix(const SkBitmap& bitmap, | 199 void AnalysisCanvas::drawBitmapMatrix(const SkBitmap& bitmap, |
195 const SkMatrix& matrix, | 200 const SkMatrix& matrix, |
196 const SkPaint* paint) { | 201 const SkPaint* paint) { |
197 is_solid_color_ = false; | 202 is_solid_color_ = false; |
198 is_transparent_ = false; | 203 is_transparent_ = false; |
204 ++draw_op_count_; | |
199 } | 205 } |
200 | 206 |
201 void AnalysisCanvas::drawBitmapNine(const SkBitmap& bitmap, | 207 void AnalysisCanvas::drawBitmapNine(const SkBitmap& bitmap, |
202 const SkIRect& center, | 208 const SkIRect& center, |
203 const SkRect& dst, | 209 const SkRect& dst, |
204 const SkPaint* paint) { | 210 const SkPaint* paint) { |
205 is_solid_color_ = false; | 211 is_solid_color_ = false; |
206 is_transparent_ = false; | 212 is_transparent_ = false; |
213 ++draw_op_count_; | |
207 } | 214 } |
208 | 215 |
209 void AnalysisCanvas::drawSprite(const SkBitmap& bitmap, | 216 void AnalysisCanvas::drawSprite(const SkBitmap& bitmap, |
210 int left, | 217 int left, |
211 int top, | 218 int top, |
212 const SkPaint* paint) { | 219 const SkPaint* paint) { |
213 is_solid_color_ = false; | 220 is_solid_color_ = false; |
214 is_transparent_ = false; | 221 is_transparent_ = false; |
222 ++draw_op_count_; | |
215 } | 223 } |
216 | 224 |
217 void AnalysisCanvas::onDrawText(const void* text, | 225 void AnalysisCanvas::onDrawText(const void* text, |
218 size_t len, | 226 size_t len, |
219 SkScalar x, | 227 SkScalar x, |
220 SkScalar y, | 228 SkScalar y, |
221 const SkPaint& paint) { | 229 const SkPaint& paint) { |
222 is_solid_color_ = false; | 230 is_solid_color_ = false; |
223 is_transparent_ = false; | 231 is_transparent_ = false; |
224 has_text_ = true; | 232 ++draw_op_count_; |
225 } | 233 } |
226 | 234 |
227 void AnalysisCanvas::onDrawPosText(const void* text, | 235 void AnalysisCanvas::onDrawPosText(const void* text, |
228 size_t byteLength, | 236 size_t byteLength, |
229 const SkPoint pos[], | 237 const SkPoint pos[], |
230 const SkPaint& paint) { | 238 const SkPaint& paint) { |
231 is_solid_color_ = false; | 239 is_solid_color_ = false; |
232 is_transparent_ = false; | 240 is_transparent_ = false; |
233 has_text_ = true; | 241 ++draw_op_count_; |
234 } | 242 } |
235 | 243 |
236 void AnalysisCanvas::onDrawPosTextH(const void* text, | 244 void AnalysisCanvas::onDrawPosTextH(const void* text, |
237 size_t byteLength, | 245 size_t byteLength, |
238 const SkScalar xpos[], | 246 const SkScalar xpos[], |
239 SkScalar constY, | 247 SkScalar constY, |
240 const SkPaint& paint) { | 248 const SkPaint& paint) { |
241 is_solid_color_ = false; | 249 is_solid_color_ = false; |
242 is_transparent_ = false; | 250 is_transparent_ = false; |
243 has_text_ = true; | 251 ++draw_op_count_; |
244 } | 252 } |
245 | 253 |
246 void AnalysisCanvas::onDrawTextOnPath(const void* text, | 254 void AnalysisCanvas::onDrawTextOnPath(const void* text, |
247 size_t len, | 255 size_t len, |
248 const SkPath& path, | 256 const SkPath& path, |
249 const SkMatrix* matrix, | 257 const SkMatrix* matrix, |
250 const SkPaint& paint) { | 258 const SkPaint& paint) { |
251 is_solid_color_ = false; | 259 is_solid_color_ = false; |
252 is_transparent_ = false; | 260 is_transparent_ = false; |
253 has_text_ = true; | 261 ++draw_op_count_; |
254 } | 262 } |
255 | 263 |
256 void AnalysisCanvas::onDrawDRRect(const SkRRect& outer, | 264 void AnalysisCanvas::onDrawDRRect(const SkRRect& outer, |
257 const SkRRect& inner, | 265 const SkRRect& inner, |
258 const SkPaint& paint) { | 266 const SkPaint& paint) { |
259 is_solid_color_ = false; | 267 is_solid_color_ = false; |
260 is_transparent_ = false; | 268 is_transparent_ = false; |
269 ++draw_op_count_; | |
261 } | 270 } |
262 | 271 |
263 void AnalysisCanvas::drawVertices(SkCanvas::VertexMode, | 272 void AnalysisCanvas::drawVertices(SkCanvas::VertexMode, |
264 int vertex_count, | 273 int vertex_count, |
265 const SkPoint verts[], | 274 const SkPoint verts[], |
266 const SkPoint texs[], | 275 const SkPoint texs[], |
267 const SkColor colors[], | 276 const SkColor colors[], |
268 SkXfermode* xmode, | 277 SkXfermode* xmode, |
269 const uint16_t indices[], | 278 const uint16_t indices[], |
270 int index_count, | 279 int index_count, |
271 const SkPaint& paint) { | 280 const SkPaint& paint) { |
272 is_solid_color_ = false; | 281 is_solid_color_ = false; |
273 is_transparent_ = false; | 282 is_transparent_ = false; |
283 ++draw_op_count_; | |
274 } | 284 } |
275 | 285 |
276 // Needed for now, since SkCanvas requires a bitmap, even if it is not backed | 286 // Needed for now, since SkCanvas requires a bitmap, even if it is not backed |
277 // by any pixels | 287 // by any pixels |
278 static SkBitmap MakeEmptyBitmap(int width, int height) { | 288 static SkBitmap MakeEmptyBitmap(int width, int height) { |
279 SkBitmap bitmap; | 289 SkBitmap bitmap; |
280 bitmap.setInfo(SkImageInfo::MakeUnknown(width, height)); | 290 bitmap.setInfo(SkImageInfo::MakeUnknown(width, height)); |
281 return bitmap; | 291 return bitmap; |
282 } | 292 } |
283 | 293 |
284 AnalysisCanvas::AnalysisCanvas(int width, int height) | 294 AnalysisCanvas::AnalysisCanvas(int width, int height) |
285 : INHERITED(MakeEmptyBitmap(width, height)), | 295 : INHERITED(MakeEmptyBitmap(width, height)), |
286 saved_stack_size_(0), | 296 saved_stack_size_(0), |
287 force_not_solid_stack_level_(kNoLayer), | 297 force_not_solid_stack_level_(kNoLayer), |
288 force_not_transparent_stack_level_(kNoLayer), | 298 force_not_transparent_stack_level_(kNoLayer), |
289 is_forced_not_solid_(false), | 299 is_forced_not_solid_(false), |
290 is_forced_not_transparent_(false), | 300 is_forced_not_transparent_(false), |
291 is_solid_color_(true), | 301 is_solid_color_(true), |
292 is_transparent_(true), | 302 is_transparent_(true), |
293 has_text_(false) {} | 303 draw_op_count_(0) {} |
294 | 304 |
295 AnalysisCanvas::~AnalysisCanvas() {} | 305 AnalysisCanvas::~AnalysisCanvas() {} |
296 | 306 |
297 bool AnalysisCanvas::GetColorIfSolid(SkColor* color) const { | 307 bool AnalysisCanvas::GetColorIfSolid(SkColor* color) const { |
298 if (is_transparent_) { | 308 if (is_transparent_) { |
299 *color = SK_ColorTRANSPARENT; | 309 *color = SK_ColorTRANSPARENT; |
300 return true; | 310 return true; |
301 } | 311 } |
302 if (is_solid_color_) { | 312 if (is_solid_color_) { |
303 *color = color_; | 313 *color = color_; |
304 return true; | 314 return true; |
305 } | 315 } |
306 return false; | 316 return false; |
307 } | 317 } |
308 | 318 |
309 bool AnalysisCanvas::HasText() const { return has_text_; } | |
310 | |
311 bool AnalysisCanvas::abortDrawing() { | 319 bool AnalysisCanvas::abortDrawing() { |
312 // Early out as soon as we have detected that the tile has text. | 320 // Early out as soon as we have more than one draw op. |
313 return HasText(); | 321 // TODO(vmpstr): Investigate if 1 is the correct metric here. We need to |
322 // balance the amount of time we spend analyzing vs how many tiles would be | |
323 // solid if the number was higher. | |
324 return draw_op_count_ > 1; | |
Justin Novosad
2014/07/24 20:16:15
Since this is an heuristic, it feels like the '1'
vmpstr
2014/07/24 21:03:03
Sounds good... For now I'd rather keep this hard c
| |
314 } | 325 } |
315 | 326 |
316 void AnalysisCanvas::onClipRect(const SkRect& rect, SkRegion::Op op, | 327 void AnalysisCanvas::onClipRect(const SkRect& rect, SkRegion::Op op, |
317 ClipEdgeStyle edge_style) { | 328 ClipEdgeStyle edge_style) { |
318 | 329 |
319 INHERITED::onClipRect(rect, op, edge_style); | 330 INHERITED::onClipRect(rect, op, edge_style); |
320 } | 331 } |
321 | 332 |
322 void AnalysisCanvas::onClipPath(const SkPath& path, SkRegion::Op op, | 333 void AnalysisCanvas::onClipPath(const SkPath& path, SkRegion::Op op, |
323 ClipEdgeStyle edge_style) { | 334 ClipEdgeStyle edge_style) { |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
413 force_not_transparent_stack_level_ = kNoLayer; | 424 force_not_transparent_stack_level_ = kNoLayer; |
414 } | 425 } |
415 } | 426 } |
416 | 427 |
417 INHERITED::willRestore(); | 428 INHERITED::willRestore(); |
418 } | 429 } |
419 | 430 |
420 } // namespace skia | 431 } // namespace skia |
421 | 432 |
422 | 433 |
OLD | NEW |