Chromium Code Reviews| 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 |