| 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; |
| 83 | 84 |
| 84 if (!is_forced_not_solid_ && SkColorGetA(color) == 255) { | 85 if (!is_forced_not_solid_ && SkColorGetA(color) == 255) { |
| 85 is_solid_color_ = true; | 86 is_solid_color_ = true; |
| 86 color_ = color; | 87 color_ = color; |
| 87 } else { | 88 } else { |
| 88 is_solid_color_ = false; | 89 is_solid_color_ = false; |
| 89 } | 90 } |
| 90 } | 91 } |
| 91 | 92 |
| 92 void AnalysisCanvas::drawPaint(const SkPaint& paint) { | 93 void AnalysisCanvas::drawPaint(const SkPaint& paint) { |
| 93 // This check is in SkCanvas::drawPaint(), and some of our unittests rely on | 94 // This check is in SkCanvas::drawPaint(), and some of our unittests rely on |
| 94 // on this, so we reproduce it here. | 95 // on this, so we reproduce it here. |
| 95 if (isClipEmpty()) | 96 if (isClipEmpty()) |
| 96 return; | 97 return; |
| 97 | 98 |
| 98 is_solid_color_ = false; | 99 is_solid_color_ = false; |
| 99 is_transparent_ = false; | 100 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_; | |
| 110 } | 109 } |
| 111 | 110 |
| 112 void AnalysisCanvas::drawRect(const SkRect& rect, const SkPaint& paint) { | 111 void AnalysisCanvas::drawRect(const SkRect& rect, const SkPaint& paint) { |
| 113 // This recreates the early-exit logic in SkCanvas.cpp, which aborts early | 112 // This recreates the early-exit logic in SkCanvas.cpp, which aborts early |
| 114 // if the paint will "draw nothing". | 113 // if the paint will "draw nothing". |
| 115 if (paint.nothingToDraw()) | 114 if (paint.nothingToDraw()) |
| 116 return; | 115 return; |
| 117 | 116 |
| 118 bool does_cover_canvas = IsFullQuad(this, rect); | 117 bool does_cover_canvas = IsFullQuad(this, rect); |
| 119 | 118 |
| 120 SkXfermode::Mode xfermode; | 119 SkXfermode::Mode xfermode; |
| 121 SkXfermode::AsMode(paint.getXfermode(), &xfermode); | 120 SkXfermode::AsMode(paint.getXfermode(), &xfermode); |
| 122 | 121 |
| 123 // This canvas will become transparent if the following holds: | 122 // This canvas will become transparent if the following holds: |
| 124 // - The quad is a full tile quad | 123 // - The quad is a full tile quad |
| 125 // - We're not in "forced not transparent" mode | 124 // - We're not in "forced not transparent" mode |
| 126 // - Transfer mode is clear (0 color, 0 alpha) | 125 // - Transfer mode is clear (0 color, 0 alpha) |
| 127 // | 126 // |
| 128 // If the paint alpha is not 0, or if the transfrer mode is | 127 // If the paint alpha is not 0, or if the transfrer mode is |
| 129 // not src, then this canvas will not be transparent. | 128 // not src, then this canvas will not be transparent. |
| 130 // | 129 // |
| 131 // In all other cases, we keep the current transparent value | 130 // In all other cases, we keep the current transparent value |
| 132 if (does_cover_canvas && | 131 if (does_cover_canvas && |
| 133 !is_forced_not_transparent_ && | 132 !is_forced_not_transparent_ && |
| 134 xfermode == SkXfermode::kClear_Mode) { | 133 xfermode == SkXfermode::kClear_Mode) { |
| 135 is_transparent_ = true; | 134 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; |
| 148 } else { | 149 } else { |
| 149 is_solid_color_ = false; | 150 is_solid_color_ = false; |
| 150 } | 151 } |
| 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_; | |
| 158 } | 157 } |
| 159 | 158 |
| 160 void AnalysisCanvas::drawRRect(const SkRRect& rr, const SkPaint& paint) { | 159 void AnalysisCanvas::drawRRect(const SkRRect& rr, const SkPaint& paint) { |
| 161 // This should add the SkRRect to an SkPath, and call | 160 // This should add the SkRRect to an SkPath, and call |
| 162 // drawPath, but since drawPath ignores the SkPath, just | 161 // drawPath, but since drawPath ignores the SkPath, just |
| 163 // do the same work here. | 162 // do the same work here. |
| 164 is_solid_color_ = false; | 163 is_solid_color_ = false; |
| 165 is_transparent_ = false; | 164 is_transparent_ = false; |
| 166 ++draw_op_count_; | |
| 167 } | 165 } |
| 168 | 166 |
| 169 void AnalysisCanvas::drawPath(const SkPath& path, const SkPaint& paint) { | 167 void AnalysisCanvas::drawPath(const SkPath& path, const SkPaint& paint) { |
| 170 is_solid_color_ = false; | 168 is_solid_color_ = false; |
| 171 is_transparent_ = false; | 169 is_transparent_ = false; |
| 172 ++draw_op_count_; | |
| 173 } | 170 } |
| 174 | 171 |
| 175 void AnalysisCanvas::drawBitmap(const SkBitmap& bitmap, | 172 void AnalysisCanvas::drawBitmap(const SkBitmap& bitmap, |
| 176 SkScalar left, | 173 SkScalar left, |
| 177 SkScalar top, | 174 SkScalar top, |
| 178 const SkPaint*) { | 175 const SkPaint*) { |
| 179 is_solid_color_ = false; | 176 is_solid_color_ = false; |
| 180 is_transparent_ = false; | 177 is_transparent_ = false; |
| 181 ++draw_op_count_; | |
| 182 } | 178 } |
| 183 | 179 |
| 184 void AnalysisCanvas::drawBitmapRectToRect(const SkBitmap&, | 180 void AnalysisCanvas::drawBitmapRectToRect(const SkBitmap&, |
| 185 const SkRect* src, | 181 const SkRect* src, |
| 186 const SkRect& dst, | 182 const SkRect& dst, |
| 187 const SkPaint* paint, | 183 const SkPaint* paint, |
| 188 DrawBitmapRectFlags flags) { | 184 DrawBitmapRectFlags flags) { |
| 189 // Call drawRect to determine transparency, | 185 // Call drawRect to determine transparency, |
| 190 // but reset solid color to false. | 186 // but reset solid color to false. |
| 191 SkPaint tmpPaint; | 187 SkPaint tmpPaint; |
| 192 if (!paint) | 188 if (!paint) |
| 193 paint = &tmpPaint; | 189 paint = &tmpPaint; |
| 194 drawRect(dst, *paint); | 190 drawRect(dst, *paint); |
| 195 is_solid_color_ = false; | 191 is_solid_color_ = false; |
| 196 ++draw_op_count_; | |
| 197 } | 192 } |
| 198 | 193 |
| 199 void AnalysisCanvas::drawBitmapMatrix(const SkBitmap& bitmap, | 194 void AnalysisCanvas::drawBitmapMatrix(const SkBitmap& bitmap, |
| 200 const SkMatrix& matrix, | 195 const SkMatrix& matrix, |
| 201 const SkPaint* paint) { | 196 const SkPaint* paint) { |
| 202 is_solid_color_ = false; | 197 is_solid_color_ = false; |
| 203 is_transparent_ = false; | 198 is_transparent_ = false; |
| 204 ++draw_op_count_; | |
| 205 } | 199 } |
| 206 | 200 |
| 207 void AnalysisCanvas::drawBitmapNine(const SkBitmap& bitmap, | 201 void AnalysisCanvas::drawBitmapNine(const SkBitmap& bitmap, |
| 208 const SkIRect& center, | 202 const SkIRect& center, |
| 209 const SkRect& dst, | 203 const SkRect& dst, |
| 210 const SkPaint* paint) { | 204 const SkPaint* paint) { |
| 211 is_solid_color_ = false; | 205 is_solid_color_ = false; |
| 212 is_transparent_ = false; | 206 is_transparent_ = false; |
| 213 ++draw_op_count_; | |
| 214 } | 207 } |
| 215 | 208 |
| 216 void AnalysisCanvas::drawSprite(const SkBitmap& bitmap, | 209 void AnalysisCanvas::drawSprite(const SkBitmap& bitmap, |
| 217 int left, | 210 int left, |
| 218 int top, | 211 int top, |
| 219 const SkPaint* paint) { | 212 const SkPaint* paint) { |
| 220 is_solid_color_ = false; | 213 is_solid_color_ = false; |
| 221 is_transparent_ = false; | 214 is_transparent_ = false; |
| 222 ++draw_op_count_; | |
| 223 } | 215 } |
| 224 | 216 |
| 225 void AnalysisCanvas::onDrawText(const void* text, | 217 void AnalysisCanvas::onDrawText(const void* text, |
| 226 size_t len, | 218 size_t len, |
| 227 SkScalar x, | 219 SkScalar x, |
| 228 SkScalar y, | 220 SkScalar y, |
| 229 const SkPaint& paint) { | 221 const SkPaint& paint) { |
| 230 is_solid_color_ = false; | 222 is_solid_color_ = false; |
| 231 is_transparent_ = false; | 223 is_transparent_ = false; |
| 232 ++draw_op_count_; | 224 has_text_ = true; |
| 233 } | 225 } |
| 234 | 226 |
| 235 void AnalysisCanvas::onDrawPosText(const void* text, | 227 void AnalysisCanvas::onDrawPosText(const void* text, |
| 236 size_t byteLength, | 228 size_t byteLength, |
| 237 const SkPoint pos[], | 229 const SkPoint pos[], |
| 238 const SkPaint& paint) { | 230 const SkPaint& paint) { |
| 239 is_solid_color_ = false; | 231 is_solid_color_ = false; |
| 240 is_transparent_ = false; | 232 is_transparent_ = false; |
| 241 ++draw_op_count_; | 233 has_text_ = true; |
| 242 } | 234 } |
| 243 | 235 |
| 244 void AnalysisCanvas::onDrawPosTextH(const void* text, | 236 void AnalysisCanvas::onDrawPosTextH(const void* text, |
| 245 size_t byteLength, | 237 size_t byteLength, |
| 246 const SkScalar xpos[], | 238 const SkScalar xpos[], |
| 247 SkScalar constY, | 239 SkScalar constY, |
| 248 const SkPaint& paint) { | 240 const SkPaint& paint) { |
| 249 is_solid_color_ = false; | 241 is_solid_color_ = false; |
| 250 is_transparent_ = false; | 242 is_transparent_ = false; |
| 251 ++draw_op_count_; | 243 has_text_ = true; |
| 252 } | 244 } |
| 253 | 245 |
| 254 void AnalysisCanvas::onDrawTextOnPath(const void* text, | 246 void AnalysisCanvas::onDrawTextOnPath(const void* text, |
| 255 size_t len, | 247 size_t len, |
| 256 const SkPath& path, | 248 const SkPath& path, |
| 257 const SkMatrix* matrix, | 249 const SkMatrix* matrix, |
| 258 const SkPaint& paint) { | 250 const SkPaint& paint) { |
| 259 is_solid_color_ = false; | 251 is_solid_color_ = false; |
| 260 is_transparent_ = false; | 252 is_transparent_ = false; |
| 261 ++draw_op_count_; | 253 has_text_ = true; |
| 262 } | 254 } |
| 263 | 255 |
| 264 void AnalysisCanvas::onDrawDRRect(const SkRRect& outer, | 256 void AnalysisCanvas::onDrawDRRect(const SkRRect& outer, |
| 265 const SkRRect& inner, | 257 const SkRRect& inner, |
| 266 const SkPaint& paint) { | 258 const SkPaint& paint) { |
| 267 is_solid_color_ = false; | 259 is_solid_color_ = false; |
| 268 is_transparent_ = false; | 260 is_transparent_ = false; |
| 269 ++draw_op_count_; | |
| 270 } | 261 } |
| 271 | 262 |
| 272 void AnalysisCanvas::drawVertices(SkCanvas::VertexMode, | 263 void AnalysisCanvas::drawVertices(SkCanvas::VertexMode, |
| 273 int vertex_count, | 264 int vertex_count, |
| 274 const SkPoint verts[], | 265 const SkPoint verts[], |
| 275 const SkPoint texs[], | 266 const SkPoint texs[], |
| 276 const SkColor colors[], | 267 const SkColor colors[], |
| 277 SkXfermode* xmode, | 268 SkXfermode* xmode, |
| 278 const uint16_t indices[], | 269 const uint16_t indices[], |
| 279 int index_count, | 270 int index_count, |
| 280 const SkPaint& paint) { | 271 const SkPaint& paint) { |
| 281 is_solid_color_ = false; | 272 is_solid_color_ = false; |
| 282 is_transparent_ = false; | 273 is_transparent_ = false; |
| 283 ++draw_op_count_; | |
| 284 } | 274 } |
| 285 | 275 |
| 286 // Needed for now, since SkCanvas requires a bitmap, even if it is not backed | 276 // Needed for now, since SkCanvas requires a bitmap, even if it is not backed |
| 287 // by any pixels | 277 // by any pixels |
| 288 static SkBitmap MakeEmptyBitmap(int width, int height) { | 278 static SkBitmap MakeEmptyBitmap(int width, int height) { |
| 289 SkBitmap bitmap; | 279 SkBitmap bitmap; |
| 290 bitmap.setInfo(SkImageInfo::MakeUnknown(width, height)); | 280 bitmap.setInfo(SkImageInfo::MakeUnknown(width, height)); |
| 291 return bitmap; | 281 return bitmap; |
| 292 } | 282 } |
| 293 | 283 |
| 294 AnalysisCanvas::AnalysisCanvas(int width, int height) | 284 AnalysisCanvas::AnalysisCanvas(int width, int height) |
| 295 : INHERITED(MakeEmptyBitmap(width, height)), | 285 : INHERITED(MakeEmptyBitmap(width, height)), |
| 296 saved_stack_size_(0), | 286 saved_stack_size_(0), |
| 297 force_not_solid_stack_level_(kNoLayer), | 287 force_not_solid_stack_level_(kNoLayer), |
| 298 force_not_transparent_stack_level_(kNoLayer), | 288 force_not_transparent_stack_level_(kNoLayer), |
| 299 is_forced_not_solid_(false), | 289 is_forced_not_solid_(false), |
| 300 is_forced_not_transparent_(false), | 290 is_forced_not_transparent_(false), |
| 301 is_solid_color_(true), | 291 is_solid_color_(true), |
| 302 is_transparent_(true), | 292 is_transparent_(true), |
| 303 draw_op_count_(0) {} | 293 has_text_(false) {} |
| 304 | 294 |
| 305 AnalysisCanvas::~AnalysisCanvas() {} | 295 AnalysisCanvas::~AnalysisCanvas() {} |
| 306 | 296 |
| 307 bool AnalysisCanvas::GetColorIfSolid(SkColor* color) const { | 297 bool AnalysisCanvas::GetColorIfSolid(SkColor* color) const { |
| 308 if (is_transparent_) { | 298 if (is_transparent_) { |
| 309 *color = SK_ColorTRANSPARENT; | 299 *color = SK_ColorTRANSPARENT; |
| 310 return true; | 300 return true; |
| 311 } | 301 } |
| 312 if (is_solid_color_) { | 302 if (is_solid_color_) { |
| 313 *color = color_; | 303 *color = color_; |
| 314 return true; | 304 return true; |
| 315 } | 305 } |
| 316 return false; | 306 return false; |
| 317 } | 307 } |
| 318 | 308 |
| 309 bool AnalysisCanvas::HasText() const { return has_text_; } |
| 310 |
| 319 bool AnalysisCanvas::abortDrawing() { | 311 bool AnalysisCanvas::abortDrawing() { |
| 320 // Early out as soon as we have more than one draw op. | 312 // Early out as soon as we have detected that the tile has text. |
| 321 // TODO(vmpstr): Investigate if 1 is the correct metric here. We need to | 313 return HasText(); |
| 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; | |
| 325 } | 314 } |
| 326 | 315 |
| 327 void AnalysisCanvas::onClipRect(const SkRect& rect, SkRegion::Op op, | 316 void AnalysisCanvas::onClipRect(const SkRect& rect, SkRegion::Op op, |
| 328 ClipEdgeStyle edge_style) { | 317 ClipEdgeStyle edge_style) { |
| 329 | 318 |
| 330 INHERITED::onClipRect(rect, op, edge_style); | 319 INHERITED::onClipRect(rect, op, edge_style); |
| 331 } | 320 } |
| 332 | 321 |
| 333 void AnalysisCanvas::onClipPath(const SkPath& path, SkRegion::Op op, | 322 void AnalysisCanvas::onClipPath(const SkPath& path, SkRegion::Op op, |
| 334 ClipEdgeStyle edge_style) { | 323 ClipEdgeStyle edge_style) { |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 424 force_not_transparent_stack_level_ = kNoLayer; | 413 force_not_transparent_stack_level_ = kNoLayer; |
| 425 } | 414 } |
| 426 } | 415 } |
| 427 | 416 |
| 428 INHERITED::willRestore(); | 417 INHERITED::willRestore(); |
| 429 } | 418 } |
| 430 | 419 |
| 431 } // namespace skia | 420 } // namespace skia |
| 432 | 421 |
| 433 | 422 |
| OLD | NEW |