Index: cc/playback/discardable_image_map.cc |
diff --git a/cc/playback/discardable_image_map.cc b/cc/playback/discardable_image_map.cc |
index e109e2be37599fbda7dd7a48553e2a8cb0ebab4b..f3c38c830adfc0b92f334f33d7e3e89adad3a645 100644 |
--- a/cc/playback/discardable_image_map.cc |
+++ b/cc/playback/discardable_image_map.cc |
@@ -7,6 +7,7 @@ |
#include <algorithm> |
#include <limits> |
+#include "base/containers/adapters.h" |
#include "cc/base/math_util.h" |
#include "cc/playback/display_item_list.h" |
#include "third_party/skia/include/utils/SkNWayCanvas.h" |
@@ -15,23 +16,47 @@ |
namespace cc { |
-namespace { |
- |
SkRect MapRect(const SkMatrix& matrix, const SkRect& src) { |
SkRect dst; |
matrix.mapRect(&dst, src); |
return dst; |
} |
-SkSize ExtractScale(const SkMatrix& matrix) { |
- SkSize scale = SkSize::Make(matrix.getScaleX(), matrix.getScaleY()); |
+bool ExtractScale(const SkMatrix& matrix, SkSize* scale) { |
+ *scale = SkSize::Make(matrix.getScaleX(), matrix.getScaleY()); |
if (matrix.getType() & SkMatrix::kAffine_Mask) { |
- if (!matrix.decomposeScale(&scale)) |
- scale.set(1, 1); |
+ if (!matrix.decomposeScale(scale)) { |
+ scale->set(1, 1); |
+ return false; |
+ } |
} |
- return scale; |
+ return true; |
} |
+bool ComputeRectBoundsFromPaint(const SkRect& rect, |
+ const SkPaint* current_paint, |
+ const std::vector<const SkPaint*>& saved_paints, |
+ SkRect* paint_bounds) { |
+ *paint_bounds = rect; |
+ if (current_paint) { |
+ if (!current_paint->canComputeFastBounds()) |
+ return false; |
+ *paint_bounds = |
+ current_paint->computeFastBounds(*paint_bounds, paint_bounds); |
+ } |
+ |
+ for (const auto* paint : base::Reversed(saved_paints)) { |
+ if (!paint) |
+ continue; |
+ if (!paint->canComputeFastBounds()) |
+ return false; |
+ *paint_bounds = paint->computeFastBounds(*paint_bounds, paint_bounds); |
+ } |
+ return true; |
+} |
+ |
+namespace { |
+ |
// We're using an NWay canvas with no added canvases, so in effect |
// non-overridden functions are no-ops. |
class DiscardableImagesMetadataCanvas : public SkNWayCanvas { |
@@ -57,10 +82,11 @@ class DiscardableImagesMetadataCanvas : public SkNWayCanvas { |
SkScalar x, |
SkScalar y, |
const SkPaint* paint) override { |
- const SkMatrix& ctm = this->getTotalMatrix(); |
- AddImage(image, MapRect(ctm, SkRect::MakeXYWH(x, y, image->width(), |
- image->height())), |
- ctm, paint); |
+ const SkMatrix& ctm = getTotalMatrix(); |
+ AddImage( |
+ image, SkRect::MakeIWH(image->width(), image->height()), |
+ MapRect(ctm, SkRect::MakeXYWH(x, y, image->width(), image->height())), |
+ ctm, paint); |
} |
void onDrawImageRect(const SkImage* image, |
@@ -68,7 +94,7 @@ class DiscardableImagesMetadataCanvas : public SkNWayCanvas { |
const SkRect& dst, |
const SkPaint* paint, |
SrcRectConstraint) override { |
- const SkMatrix& ctm = this->getTotalMatrix(); |
+ const SkMatrix& ctm = getTotalMatrix(); |
SkRect src_storage; |
if (!src) { |
src_storage = SkRect::MakeIWH(image->width(), image->height()); |
@@ -77,34 +103,78 @@ class DiscardableImagesMetadataCanvas : public SkNWayCanvas { |
SkMatrix matrix; |
matrix.setRectToRect(*src, dst, SkMatrix::kFill_ScaleToFit); |
matrix.postConcat(ctm); |
- AddImage(image, MapRect(ctm, dst), matrix, paint); |
+ AddImage(image, *src, MapRect(ctm, dst), matrix, paint); |
} |
void onDrawImageNine(const SkImage* image, |
const SkIRect& center, |
const SkRect& dst, |
const SkPaint* paint) override { |
- AddImage(image, dst, this->getTotalMatrix(), paint); |
+ // Blink doesn't issue image nine calls. |
enne (OOO)
2015/12/10 00:07:16
Blink doesn't issue => no cc embedder issues
...h
vmpstr
2015/12/10 00:47:03
Done.
|
+ NOTREACHED(); |
+ } |
+ |
+ SaveLayerStrategy willSaveLayer(const SkRect* rect, |
+ const SkPaint* paint, |
+ SaveFlags save_flags) override { |
+ saved_paints_.push_back(paint); |
+ return SkNWayCanvas::willSaveLayer(rect, paint, save_flags); |
+ } |
+ |
+ void willSave() override { |
+ saved_paints_.push_back(nullptr); |
+ return SkNWayCanvas::willSave(); |
+ } |
+ |
+ void willRestore() override { |
+ DCHECK_GT(saved_paints_.size(), 0u); |
+ saved_paints_.pop_back(); |
+ SkNWayCanvas::willRestore(); |
} |
private: |
void AddImage(const SkImage* image, |
+ const SkRect& src_rect, |
const SkRect& rect, |
const SkMatrix& matrix, |
const SkPaint* paint) { |
- if (rect.intersects(canvas_bounds_) && image->isLazyGenerated()) { |
- SkFilterQuality filter_quality = kNone_SkFilterQuality; |
- if (paint) { |
- filter_quality = paint->getFilterQuality(); |
- } |
- image_set_->push_back( |
- std::make_pair(DrawImage(image, ExtractScale(matrix), filter_quality), |
- gfx::ToEnclosingRect(gfx::SkRectToRectF(rect)))); |
+ if (!image->isLazyGenerated()) |
+ return; |
+ |
+ SkRect paint_rect; |
+ bool computed_paint_bounds = ComputePaintBounds(rect, paint, &paint_rect); |
+ if (!computed_paint_bounds) { |
+ // TODO(vmpstr): UMA this case. |
+ paint_rect = canvas_bounds_; |
} |
+ |
+ if (!paint_rect.intersects(canvas_bounds_)) |
+ return; |
+ |
+ SkFilterQuality filter_quality = kNone_SkFilterQuality; |
+ if (paint) { |
+ filter_quality = paint->getFilterQuality(); |
+ } |
+ |
+ SkIRect src_irect; |
+ src_rect.roundOut(&src_irect); |
+ SkSize scale; |
+ bool is_decomposable = ExtractScale(matrix, &scale); |
+ image_set_->push_back( |
+ std::make_pair(DrawImage(image, src_irect, scale, filter_quality, |
+ matrix.hasPerspective(), is_decomposable), |
+ gfx::ToEnclosingRect(gfx::SkRectToRectF(paint_rect)))); |
+ } |
+ |
+ bool ComputePaintBounds(const SkRect& rect, |
+ const SkPaint* paint, |
+ SkRect* paint_bounds) { |
+ return ComputeRectBoundsFromPaint(rect, paint, saved_paints_, paint_bounds); |
} |
std::vector<std::pair<DrawImage, gfx::Rect>>* image_set_; |
const SkRect canvas_bounds_; |
+ std::vector<const SkPaint*> saved_paints_; |
}; |
} // namespace |