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/SkDevice.h" | 8 #include "third_party/skia/include/core/SkDevice.h" |
| 9 #include "third_party/skia/include/core/SkDraw.h" | 9 #include "third_party/skia/include/core/SkDraw.h" |
| 10 #include "third_party/skia/include/core/SkRRect.h" | 10 #include "third_party/skia/include/core/SkRRect.h" |
| 11 #include "third_party/skia/include/core/SkShader.h" | 11 #include "third_party/skia/include/core/SkShader.h" |
| 12 #include "third_party/skia/src/core/SkRasterClip.h" | 12 #include "third_party/skia/src/core/SkRasterClip.h" |
| 13 #include "ui/gfx/rect_conversions.h" | 13 #include "ui/gfx/rect_conversions.h" |
| 14 #include "ui/gfx/skia_util.h" | |
| 14 | 15 |
| 15 namespace { | 16 namespace { |
| 16 | 17 |
| 17 const int kNoLayer = -1; | 18 const int kNoLayer = -1; |
| 18 | 19 |
| 19 bool IsSolidColorPaint(const SkPaint& paint) { | 20 bool IsSolidColorPaint(const SkPaint& paint) { |
| 20 SkXfermode::Mode xfermode; | 21 SkXfermode::Mode xfermode; |
| 21 | 22 |
| 22 // getXfermode can return a NULL, but that is handled | 23 // getXfermode can return a NULL, but that is handled |
| 23 // gracefully by AsMode (NULL turns into kSrcOver mode). | 24 // gracefully by AsMode (NULL turns into kSrcOver mode). |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 63 return draw.fRC->isRect() && | 64 return draw.fRC->isRect() && |
| 64 device_rect.contains(clip_rect) && | 65 device_rect.contains(clip_rect) && |
| 65 clip_rect.contains(canvas_rect) && | 66 clip_rect.contains(canvas_rect) && |
| 66 draw_bitmap_rect.contains(canvas_rect); | 67 draw_bitmap_rect.contains(canvas_rect); |
| 67 } | 68 } |
| 68 | 69 |
| 69 } // namespace | 70 } // namespace |
| 70 | 71 |
| 71 namespace skia { | 72 namespace skia { |
| 72 | 73 |
| 73 AnalysisDevice::AnalysisDevice(const SkBitmap& bitmap) | 74 AnalysisDevice::AnalysisDevice(const SkBitmap& bitmap, gfx::Rect analysis_rect) |
| 74 : INHERITED(bitmap), | 75 : INHERITED(bitmap), |
| 76 analysis_rect_(analysis_rect), | |
| 75 is_forced_not_solid_(false), | 77 is_forced_not_solid_(false), |
| 76 is_forced_not_transparent_(false), | 78 is_forced_not_transparent_(false), |
| 77 is_solid_color_(true), | 79 is_solid_color_(true), |
| 78 is_transparent_(true), | 80 is_transparent_(true), |
| 79 has_text_(false) {} | 81 has_text_(false) {} |
| 80 | 82 |
| 81 AnalysisDevice::~AnalysisDevice() {} | 83 AnalysisDevice::~AnalysisDevice() {} |
| 82 | 84 |
| 83 bool AnalysisDevice::GetColorIfSolid(SkColor* color) const { | 85 bool AnalysisDevice::GetColorIfSolid(SkColor* color) const { |
| 84 if (is_transparent_) { | 86 if (is_transparent_) { |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 114 | 116 |
| 115 if (!is_forced_not_solid_ && SkColorGetA(color) == 255) { | 117 if (!is_forced_not_solid_ && SkColorGetA(color) == 255) { |
| 116 is_solid_color_ = true; | 118 is_solid_color_ = true; |
| 117 color_ = color; | 119 color_ = color; |
| 118 } else { | 120 } else { |
| 119 is_solid_color_ = false; | 121 is_solid_color_ = false; |
| 120 } | 122 } |
| 121 } | 123 } |
| 122 | 124 |
| 123 void AnalysisDevice::drawPaint(const SkDraw& draw, const SkPaint& paint) { | 125 void AnalysisDevice::drawPaint(const SkDraw& draw, const SkPaint& paint) { |
| 126 INHERITED::drawPaint(draw, paint); | |
|
vangelis
2013/11/07 01:35:03
Do we see this method getting called for common we
enne (OOO)
2013/11/07 22:13:50
No. This is not called from Blink.
| |
| 124 is_solid_color_ = false; | 127 is_solid_color_ = false; |
| 125 is_transparent_ = false; | 128 is_transparent_ = false; |
| 126 } | 129 } |
| 127 | 130 |
| 128 void AnalysisDevice::drawPoints(const SkDraw& draw, | 131 void AnalysisDevice::drawPoints(const SkDraw& draw, |
| 129 SkCanvas::PointMode mode, | 132 SkCanvas::PointMode mode, |
| 130 size_t count, | 133 size_t count, |
| 131 const SkPoint points[], | 134 const SkPoint points[], |
| 132 const SkPaint& paint) { | 135 const SkPaint& paint) { |
| 136 INHERITED::drawPoints(draw, mode, count, points, paint); | |
| 133 is_solid_color_ = false; | 137 is_solid_color_ = false; |
| 134 is_transparent_ = false; | 138 is_transparent_ = false; |
| 135 } | 139 } |
| 136 | 140 |
| 137 void AnalysisDevice::drawRect(const SkDraw& draw, | 141 void AnalysisDevice::drawRect(const SkDraw& draw, |
| 138 const SkRect& rect, | 142 const SkRect& rect, |
| 139 const SkPaint& paint) { | 143 const SkPaint& paint) { |
| 140 bool does_cover_canvas = | 144 INHERITED::drawRect(draw, rect, paint); |
| 141 IsFullQuad(draw, SkRect::MakeWH(width(), height()), rect); | 145 AnalyzeDrawRect(draw, rect, paint); |
| 142 | |
| 143 SkXfermode::Mode xfermode; | |
| 144 SkXfermode::AsMode(paint.getXfermode(), &xfermode); | |
| 145 | |
| 146 // This canvas will become transparent if the following holds: | |
| 147 // - The quad is a full tile quad | |
| 148 // - We're not in "forced not transparent" mode | |
| 149 // - Transfer mode is clear (0 color, 0 alpha) | |
| 150 // | |
| 151 // If the paint alpha is not 0, or if the transfrer mode is | |
| 152 // not src, then this canvas will not be transparent. | |
| 153 // | |
| 154 // In all other cases, we keep the current transparent value | |
| 155 if (does_cover_canvas && | |
| 156 !is_forced_not_transparent_ && | |
| 157 xfermode == SkXfermode::kClear_Mode) { | |
| 158 is_transparent_ = true; | |
| 159 has_text_ = false; | |
| 160 } else if (paint.getAlpha() != 0 || xfermode != SkXfermode::kSrc_Mode) { | |
| 161 is_transparent_ = false; | |
| 162 } | |
| 163 | |
| 164 // This bitmap is solid if and only if the following holds. | |
| 165 // Note that this might be overly conservative: | |
| 166 // - We're not in "forced not solid" mode | |
| 167 // - Paint is solid color | |
| 168 // - The quad is a full tile quad | |
| 169 if (!is_forced_not_solid_ && IsSolidColorPaint(paint) && does_cover_canvas) { | |
| 170 is_solid_color_ = true; | |
| 171 color_ = paint.getColor(); | |
| 172 has_text_ = false; | |
| 173 } else { | |
| 174 is_solid_color_ = false; | |
| 175 } | |
| 176 } | 146 } |
| 177 | 147 |
| 178 void AnalysisDevice::drawOval(const SkDraw& draw, | 148 void AnalysisDevice::drawOval(const SkDraw& draw, |
| 179 const SkRect& oval, | 149 const SkRect& oval, |
| 180 const SkPaint& paint) { | 150 const SkPaint& paint) { |
| 151 INHERITED::drawOval(draw, oval, paint); | |
| 181 is_solid_color_ = false; | 152 is_solid_color_ = false; |
| 182 is_transparent_ = false; | 153 is_transparent_ = false; |
| 183 } | 154 } |
| 184 | 155 |
| 185 void AnalysisDevice::drawPath(const SkDraw& draw, | 156 void AnalysisDevice::drawPath(const SkDraw& draw, |
| 186 const SkPath& path, | 157 const SkPath& path, |
| 187 const SkPaint& paint, | 158 const SkPaint& paint, |
| 188 const SkMatrix* pre_path_matrix, | 159 const SkMatrix* pre_path_matrix, |
| 189 bool path_is_mutable) { | 160 bool path_is_mutable) { |
| 161 INHERITED::drawPath(draw, path, paint, pre_path_matrix, path_is_mutable); | |
| 190 is_solid_color_ = false; | 162 is_solid_color_ = false; |
| 191 is_transparent_ = false; | 163 is_transparent_ = false; |
| 192 } | 164 } |
| 193 | 165 |
| 194 void AnalysisDevice::drawBitmap(const SkDraw& draw, | 166 void AnalysisDevice::drawBitmap(const SkDraw& draw, |
| 195 const SkBitmap& bitmap, | 167 const SkBitmap& bitmap, |
| 196 const SkMatrix& matrix, | 168 const SkMatrix& matrix, |
| 197 const SkPaint& paint) { | 169 const SkPaint& paint) { |
| 170 INHERITED::drawBitmap(draw, bitmap, matrix, paint); | |
| 198 is_solid_color_ = false; | 171 is_solid_color_ = false; |
| 199 is_transparent_ = false; | 172 is_transparent_ = false; |
| 200 } | 173 } |
| 201 | 174 |
| 202 void AnalysisDevice::drawSprite(const SkDraw& draw, | 175 void AnalysisDevice::drawSprite(const SkDraw& draw, |
| 203 const SkBitmap& bitmap, | 176 const SkBitmap& bitmap, |
| 204 int x, | 177 int x, |
| 205 int y, | 178 int y, |
| 206 const SkPaint& paint) { | 179 const SkPaint& paint) { |
| 180 INHERITED::drawSprite(draw, bitmap, x, y, paint); | |
| 207 is_solid_color_ = false; | 181 is_solid_color_ = false; |
| 208 is_transparent_ = false; | 182 is_transparent_ = false; |
| 209 } | 183 } |
| 210 | 184 |
| 211 void AnalysisDevice::drawBitmapRect(const SkDraw& draw, | 185 void AnalysisDevice::drawBitmapRect(const SkDraw& draw, |
| 212 const SkBitmap& bitmap, | 186 const SkBitmap& bitmap, |
| 213 const SkRect* src_or_null, | 187 const SkRect* src_or_null, |
| 214 const SkRect& dst, | 188 const SkRect& rect, |
| 215 const SkPaint& paint, | 189 const SkPaint& paint, |
| 216 SkCanvas::DrawBitmapRectFlags flags) { | 190 SkCanvas::DrawBitmapRectFlags flags) { |
| 217 // Call drawRect to determine transparency, | 191 INHERITED::drawBitmapRect(draw, bitmap, src_or_null, rect, paint, flags); |
| 192 | |
| 193 // Call AnalyzeDrawRect to determine transparency, | |
| 218 // but reset solid color to false. | 194 // but reset solid color to false. |
| 219 drawRect(draw, dst, paint); | 195 AnalyzeDrawRect(draw, rect, paint); |
| 220 is_solid_color_ = false; | 196 is_solid_color_ = false; |
| 221 } | 197 } |
| 222 | 198 |
| 223 void AnalysisDevice::drawText(const SkDraw& draw, | 199 void AnalysisDevice::drawText(const SkDraw& draw, |
| 224 const void* text, | 200 const void* text, |
| 225 size_t len, | 201 size_t len, |
| 226 SkScalar x, | 202 SkScalar x, |
| 227 SkScalar y, | 203 SkScalar y, |
| 228 const SkPaint& paint) { | 204 const SkPaint& paint) { |
| 205 INHERITED::drawText(draw, text, len, x, y, paint); | |
| 229 is_solid_color_ = false; | 206 is_solid_color_ = false; |
| 230 is_transparent_ = false; | 207 is_transparent_ = false; |
| 231 has_text_ = true; | 208 has_text_ = true; |
| 232 } | 209 } |
| 233 | 210 |
| 234 void AnalysisDevice::drawPosText(const SkDraw& draw, | 211 void AnalysisDevice::drawPosText(const SkDraw& draw, |
| 235 const void* text, | 212 const void* text, |
| 236 size_t len, | 213 size_t len, |
| 237 const SkScalar pos[], | 214 const SkScalar pos[], |
| 238 SkScalar const_y, | 215 SkScalar const_y, |
| 239 int scalars_per_pos, | 216 int scalars_per_pos, |
| 240 const SkPaint& paint) { | 217 const SkPaint& paint) { |
| 218 INHERITED::drawPosText(draw, text, len, pos, const_y, scalars_per_pos, paint); | |
| 241 is_solid_color_ = false; | 219 is_solid_color_ = false; |
| 242 is_transparent_ = false; | 220 is_transparent_ = false; |
| 243 has_text_ = true; | 221 has_text_ = true; |
| 244 } | 222 } |
| 245 | 223 |
| 246 void AnalysisDevice::drawTextOnPath(const SkDraw& draw, | 224 void AnalysisDevice::drawTextOnPath(const SkDraw& draw, |
| 247 const void* text, | 225 const void* text, |
| 248 size_t len, | 226 size_t len, |
| 249 const SkPath& path, | 227 const SkPath& path, |
| 250 const SkMatrix* matrix, | 228 const SkMatrix* matrix, |
| 251 const SkPaint& paint) { | 229 const SkPaint& paint) { |
| 230 INHERITED::drawTextOnPath(draw, text, len, path, matrix, paint); | |
| 252 is_solid_color_ = false; | 231 is_solid_color_ = false; |
| 253 is_transparent_ = false; | 232 is_transparent_ = false; |
| 254 has_text_ = true; | 233 has_text_ = true; |
| 255 } | 234 } |
| 256 | 235 |
| 257 #ifdef SK_BUILD_FOR_ANDROID | 236 #ifdef SK_BUILD_FOR_ANDROID |
| 258 void AnalysisDevice::drawPosTextOnPath(const SkDraw& draw, | 237 void AnalysisDevice::drawPosTextOnPath(const SkDraw& draw, |
| 259 const void* text, | 238 const void* text, |
| 260 size_t len, | 239 size_t len, |
| 261 const SkPoint pos[], | 240 const SkPoint pos[], |
| 262 const SkPaint& paint, | 241 const SkPaint& paint, |
| 263 const SkPath& path, | 242 const SkPath& path, |
| 264 const SkMatrix* matrix) { | 243 const SkMatrix* matrix) { |
| 244 INHERITED::drawPosTextOnPath(draw, text, len, pos, paint, path, matrix); | |
| 265 is_solid_color_ = false; | 245 is_solid_color_ = false; |
| 266 is_transparent_ = false; | 246 is_transparent_ = false; |
| 267 has_text_ = true; | 247 has_text_ = true; |
| 268 } | 248 } |
| 269 #endif | 249 #endif |
| 270 | 250 |
| 271 void AnalysisDevice::drawVertices(const SkDraw& draw, | 251 void AnalysisDevice::drawVertices(const SkDraw& draw, |
| 272 SkCanvas::VertexMode, | 252 SkCanvas::VertexMode mode, |
| 273 int vertex_count, | 253 int vertex_count, |
| 274 const SkPoint verts[], | 254 const SkPoint verts[], |
| 275 const SkPoint texs[], | 255 const SkPoint texs[], |
| 276 const SkColor colors[], | 256 const SkColor colors[], |
| 277 SkXfermode* xmode, | 257 SkXfermode* xmode, |
| 278 const uint16_t indices[], | 258 const uint16_t indices[], |
| 279 int index_count, | 259 int index_count, |
| 280 const SkPaint& paint) { | 260 const SkPaint& paint) { |
| 261 INHERITED::drawVertices(draw, | |
| 262 mode, | |
| 263 vertex_count, | |
| 264 verts, | |
| 265 texs, | |
| 266 colors, | |
| 267 xmode, | |
| 268 indices, | |
| 269 index_count, | |
| 270 paint); | |
| 281 is_solid_color_ = false; | 271 is_solid_color_ = false; |
| 282 is_transparent_ = false; | 272 is_transparent_ = false; |
| 283 } | 273 } |
| 284 | 274 |
| 285 void AnalysisDevice::drawDevice(const SkDraw& draw, | 275 void AnalysisDevice::drawDevice(const SkDraw& draw, |
| 286 SkBaseDevice* device, | 276 SkBaseDevice* device, |
| 287 int x, | 277 int x, |
| 288 int y, | 278 int y, |
| 289 const SkPaint& paint) { | 279 const SkPaint& paint) { |
| 280 INHERITED::drawDevice(draw, device, x, y, paint); | |
| 290 is_solid_color_ = false; | 281 is_solid_color_ = false; |
| 291 is_transparent_ = false; | 282 is_transparent_ = false; |
| 292 } | 283 } |
| 293 | 284 |
| 294 AnalysisCanvas::AnalysisCanvas(AnalysisDevice* device) | 285 AnalysisCanvas::AnalysisCanvas(AnalysisDevice* device) |
| 295 : INHERITED(device), | 286 : INHERITED(device), |
| 296 saved_stack_size_(0), | 287 saved_stack_size_(0), |
| 297 force_not_solid_stack_level_(kNoLayer), | 288 force_not_solid_stack_level_(kNoLayer), |
| 298 force_not_transparent_stack_level_(kNoLayer) {} | 289 force_not_transparent_stack_level_(kNoLayer) {} |
| 299 | 290 |
| 300 AnalysisCanvas::~AnalysisCanvas() {} | 291 AnalysisCanvas::~AnalysisCanvas() {} |
| 301 | 292 |
| 302 bool AnalysisCanvas::GetColorIfSolid(SkColor* color) const { | 293 bool AnalysisCanvas::GetColorIfSolid(SkColor* color) const { |
| 303 return (static_cast<AnalysisDevice*>(getDevice()))->GetColorIfSolid(color); | 294 return (static_cast<AnalysisDevice*>(getDevice()))->GetColorIfSolid(color); |
| 304 } | 295 } |
| 305 | 296 |
| 306 bool AnalysisCanvas::HasText() const { | 297 bool AnalysisCanvas::HasText() const { |
| 307 return (static_cast<AnalysisDevice*>(getDevice()))->HasText(); | 298 return (static_cast<AnalysisDevice*>(getDevice()))->HasText(); |
| 308 } | 299 } |
| 309 | 300 |
| 310 bool AnalysisCanvas::abortDrawing() { | |
| 311 // Early out as soon as we have detected that the tile has text. | |
| 312 return HasText(); | |
| 313 } | |
| 314 | |
| 315 bool AnalysisCanvas::clipRect(const SkRect& rect, SkRegion::Op op, bool do_aa) { | 301 bool AnalysisCanvas::clipRect(const SkRect& rect, SkRegion::Op op, bool do_aa) { |
| 316 return INHERITED::clipRect(rect, op, do_aa); | 302 return INHERITED::clipRect(rect, op, do_aa); |
| 317 } | 303 } |
| 318 | 304 |
| 319 bool AnalysisCanvas::clipPath(const SkPath& path, SkRegion::Op op, bool do_aa) { | 305 bool AnalysisCanvas::clipPath(const SkPath& path, SkRegion::Op op, bool do_aa) { |
| 320 // clipPaths can make our calls to IsFullQuad invalid (ie have false | 306 // clipPaths can make our calls to IsFullQuad invalid (ie have false |
| 321 // positives). As a precaution, force the setting to be non-solid | 307 // positives). As a precaution, force the setting to be non-solid |
| 322 // and non-transparent until we pop this | 308 // and non-transparent until we pop this |
| 323 if (force_not_solid_stack_level_ == kNoLayer) { | 309 if (force_not_solid_stack_level_ == kNoLayer) { |
| 324 force_not_solid_stack_level_ = saved_stack_size_; | 310 force_not_solid_stack_level_ = saved_stack_size_; |
| 325 (static_cast<AnalysisDevice*>(getDevice()))->SetForceNotSolid(true); | 311 (static_cast<AnalysisDevice*>(getDevice()))->SetForceNotSolid(true); |
| 326 } | 312 } |
| 327 if (force_not_transparent_stack_level_ == kNoLayer) { | 313 if (force_not_transparent_stack_level_ == kNoLayer) { |
| 328 force_not_transparent_stack_level_ = saved_stack_size_; | 314 force_not_transparent_stack_level_ = saved_stack_size_; |
| 329 (static_cast<AnalysisDevice*>(getDevice()))->SetForceNotTransparent(true); | 315 (static_cast<AnalysisDevice*>(getDevice()))->SetForceNotTransparent(true); |
| 330 } | 316 } |
| 331 | 317 |
| 332 return INHERITED::clipRect(path.getBounds(), op, do_aa); | 318 return INHERITED::clipPath(path, op, do_aa); |
| 333 } | 319 } |
| 334 | 320 |
| 335 bool AnalysisCanvas::clipRRect(const SkRRect& rrect, | 321 bool AnalysisCanvas::clipRRect(const SkRRect& rrect, |
| 336 SkRegion::Op op, | 322 SkRegion::Op op, |
| 337 bool do_aa) { | 323 bool do_aa) { |
| 338 // clipRRect can make our calls to IsFullQuad invalid (ie have false | 324 // clipRRect can make our calls to IsFullQuad invalid (ie have false |
| 339 // positives). As a precaution, force the setting to be non-solid | 325 // positives). As a precaution, force the setting to be non-solid |
| 340 // and non-transparent until we pop this | 326 // and non-transparent until we pop this |
| 341 if (force_not_solid_stack_level_ == kNoLayer) { | 327 if (force_not_solid_stack_level_ == kNoLayer) { |
| 342 force_not_solid_stack_level_ = saved_stack_size_; | 328 force_not_solid_stack_level_ = saved_stack_size_; |
| 343 (static_cast<AnalysisDevice*>(getDevice()))->SetForceNotSolid(true); | 329 (static_cast<AnalysisDevice*>(getDevice()))->SetForceNotSolid(true); |
| 344 } | 330 } |
| 345 if (force_not_transparent_stack_level_ == kNoLayer) { | 331 if (force_not_transparent_stack_level_ == kNoLayer) { |
| 346 force_not_transparent_stack_level_ = saved_stack_size_; | 332 force_not_transparent_stack_level_ = saved_stack_size_; |
| 347 (static_cast<AnalysisDevice*>(getDevice()))->SetForceNotTransparent(true); | 333 (static_cast<AnalysisDevice*>(getDevice()))->SetForceNotTransparent(true); |
| 348 } | 334 } |
| 349 | 335 |
| 350 return INHERITED::clipRect(rrect.getBounds(), op, do_aa); | 336 return INHERITED::clipRRect(rrect, op, do_aa); |
| 351 } | 337 } |
| 352 | 338 |
| 353 int AnalysisCanvas::save(SkCanvas::SaveFlags flags) { | 339 int AnalysisCanvas::save(SkCanvas::SaveFlags flags) { |
| 354 ++saved_stack_size_; | 340 ++saved_stack_size_; |
| 355 return INHERITED::save(flags); | 341 return INHERITED::save(flags); |
| 356 } | 342 } |
| 357 | 343 |
| 358 int AnalysisCanvas::saveLayer(const SkRect* bounds, | 344 int AnalysisCanvas::saveLayer(const SkRect* bounds, |
| 359 const SkPaint* paint, | 345 const SkPaint* paint, |
| 360 SkCanvas::SaveFlags flags) { | 346 SkCanvas::SaveFlags flags) { |
| 361 ++saved_stack_size_; | 347 ++saved_stack_size_; |
| 362 | 348 |
| 363 // If after we draw to the saved layer, we have to blend with the current | 349 // If after we draw to the saved layer, we have to blend with the current |
| 364 // layer, then we can conservatively say that the canvas will not be of | 350 // layer, then we can conservatively say that the canvas will not be of |
| 365 // solid color. | 351 // solid color. |
| 352 gfx::Rect analysis_rect = | |
| 353 static_cast<AnalysisDevice*>(getDevice())->AnalysisRect(); | |
| 366 if ((paint && !IsSolidColorPaint(*paint)) || | 354 if ((paint && !IsSolidColorPaint(*paint)) || |
| 367 (bounds && !bounds->contains(SkRect::MakeWH(getDevice()->width(), | 355 (bounds && !bounds->contains(RectToSkRect(analysis_rect)))) { |
| 368 getDevice()->height())))) { | |
| 369 if (force_not_solid_stack_level_ == kNoLayer) { | 356 if (force_not_solid_stack_level_ == kNoLayer) { |
| 370 force_not_solid_stack_level_ = saved_stack_size_; | 357 force_not_solid_stack_level_ = saved_stack_size_; |
| 371 (static_cast<AnalysisDevice*>(getDevice()))->SetForceNotSolid(true); | 358 (static_cast<AnalysisDevice*>(getDevice()))->SetForceNotSolid(true); |
| 372 } | 359 } |
| 373 } | 360 } |
| 374 | 361 |
| 375 // If after we draw to the save layer, we have to blend with the current | 362 // If after we draw to the save layer, we have to blend with the current |
| 376 // layer using any part of the current layer's alpha, then we can | 363 // layer using any part of the current layer's alpha, then we can |
| 377 // conservatively say that the canvas will not be transparent. | 364 // conservatively say that the canvas will not be transparent. |
| 378 SkXfermode::Mode xfermode = SkXfermode::kSrc_Mode; | 365 SkXfermode::Mode xfermode = SkXfermode::kSrc_Mode; |
| 379 if (paint) | 366 if (paint) |
| 380 SkXfermode::AsMode(paint->getXfermode(), &xfermode); | 367 SkXfermode::AsMode(paint->getXfermode(), &xfermode); |
| 381 if (xfermode != SkXfermode::kSrc_Mode) { | 368 if (xfermode != SkXfermode::kSrc_Mode) { |
| 382 if (force_not_transparent_stack_level_ == kNoLayer) { | 369 if (force_not_transparent_stack_level_ == kNoLayer) { |
| 383 force_not_transparent_stack_level_ = saved_stack_size_; | 370 force_not_transparent_stack_level_ = saved_stack_size_; |
| 384 (static_cast<AnalysisDevice*>(getDevice()))->SetForceNotTransparent(true); | 371 (static_cast<AnalysisDevice*>(getDevice()))->SetForceNotTransparent(true); |
| 385 } | 372 } |
| 386 } | 373 } |
| 387 | 374 |
| 388 // Actually saving a layer here could cause a new bitmap to be created | 375 return INHERITED::saveLayer(bounds, paint, flags); |
| 389 // and real rendering to occur. | |
| 390 int count = INHERITED::save(flags); | |
| 391 if (bounds) { | |
| 392 INHERITED::clipRectBounds(bounds, flags, NULL); | |
| 393 } | |
| 394 return count; | |
| 395 } | 376 } |
| 396 | 377 |
| 397 void AnalysisCanvas::restore() { | 378 void AnalysisCanvas::restore() { |
| 398 INHERITED::restore(); | 379 INHERITED::restore(); |
| 399 | 380 |
| 400 DCHECK(saved_stack_size_); | 381 DCHECK(saved_stack_size_); |
| 401 if (saved_stack_size_) { | 382 if (saved_stack_size_) { |
| 402 --saved_stack_size_; | 383 --saved_stack_size_; |
| 403 if (saved_stack_size_ < force_not_solid_stack_level_) { | 384 if (saved_stack_size_ < force_not_solid_stack_level_) { |
| 404 (static_cast<AnalysisDevice*>(getDevice()))->SetForceNotSolid(false); | 385 (static_cast<AnalysisDevice*>(getDevice()))->SetForceNotSolid(false); |
| 405 force_not_solid_stack_level_ = kNoLayer; | 386 force_not_solid_stack_level_ = kNoLayer; |
| 406 } | 387 } |
| 407 if (saved_stack_size_ < force_not_transparent_stack_level_) { | 388 if (saved_stack_size_ < force_not_transparent_stack_level_) { |
| 408 (static_cast<AnalysisDevice*>(getDevice()))->SetForceNotTransparent( | 389 (static_cast<AnalysisDevice*>(getDevice()))->SetForceNotTransparent( |
| 409 false); | 390 false); |
| 410 force_not_transparent_stack_level_ = kNoLayer; | 391 force_not_transparent_stack_level_ = kNoLayer; |
| 411 } | 392 } |
| 412 } | 393 } |
| 413 } | 394 } |
| 414 | 395 |
| 396 void AnalysisDevice::AnalyzeDrawRect(const SkDraw& draw, | |
| 397 const SkRect& rect, | |
| 398 const SkPaint& paint) { | |
| 399 bool does_cover_canvas = | |
| 400 IsFullQuad(draw, RectToSkRect(analysis_rect_), rect); | |
| 401 | |
| 402 SkXfermode::Mode xfermode; | |
| 403 SkXfermode::AsMode(paint.getXfermode(), &xfermode); | |
| 404 | |
| 405 // This canvas will become transparent if the following holds: | |
| 406 // - The quad is a full tile quad | |
| 407 // - We're not in "forced not transparent" mode | |
| 408 // - Transfer mode is clear (0 color, 0 alpha) | |
|
Stephen White
2013/11/07 18:14:22
Nit: also not new to this patch, but is it possibl
enne (OOO)
2013/11/07 22:36:10
Such a helper function from the Skia side would be
| |
| 409 // | |
| 410 // If the paint alpha is not 0, or if the transfrer mode is | |
| 411 // not src, then this canvas will not be transparent. | |
| 412 // | |
| 413 // In all other cases, we keep the current transparent value | |
| 414 if (does_cover_canvas && | |
| 415 !is_forced_not_transparent_ && | |
| 416 xfermode == SkXfermode::kClear_Mode) { | |
| 417 is_transparent_ = true; | |
| 418 has_text_ = false; | |
| 419 } else if (paint.getAlpha() != 0 || xfermode != SkXfermode::kSrc_Mode) { | |
| 420 is_transparent_ = false; | |
| 421 } | |
| 422 | |
| 423 // This bitmap is solid if and only if the following holds. | |
| 424 // Note that this might be overly conservative: | |
| 425 // - We're not in "forced not solid" mode | |
| 426 // - Paint is solid color | |
| 427 // - The quad is a full tile quad | |
| 428 if (!is_forced_not_solid_ && IsSolidColorPaint(paint) && does_cover_canvas) { | |
| 429 is_solid_color_ = true; | |
| 430 color_ = paint.getColor(); | |
| 431 has_text_ = false; | |
| 432 } else { | |
| 433 is_solid_color_ = false; | |
| 434 } | |
| 435 } | |
| 436 | |
| 415 } // namespace skia | 437 } // namespace skia |
| 416 | |
| 417 | |
| OLD | NEW |