Chromium Code Reviews| Index: cc/paint/paint_op_buffer.cc |
| diff --git a/cc/paint/paint_op_buffer.cc b/cc/paint/paint_op_buffer.cc |
| index 0a1897852f3e51ca3d91b67460b2d6e84dace61a..2617ba93047d318f49d364f1f23db13dbf049e89 100644 |
| --- a/cc/paint/paint_op_buffer.cc |
| +++ b/cc/paint/paint_op_buffer.cc |
| @@ -4,11 +4,37 @@ |
| #include "cc/paint/paint_op_buffer.h" |
| +#include "cc/paint/discardable_image_store.h" |
| #include "cc/paint/display_item_list.h" |
| #include "cc/paint/paint_record.h" |
| #include "third_party/skia/include/core/SkAnnotation.h" |
| namespace cc { |
| +namespace { |
| +// Currently this function only handles extracting images from SkImageShaders |
| +// embedded in SkPaints. Other embedded image cases, such as SkPictures, |
| +// are not yet handled. |
| +void AddImageFromFlags(DiscardableImageStore* image_store, |
|
vmpstr
2017/04/27 16:28:54
It feels like this should be a member on Discardab
Khushal
2017/04/27 22:06:02
Done.
|
| + const SkRect& rect, |
| + const PaintFlags& flags) { |
| + SkShader* shader = flags.getShader(); |
| + if (shader) { |
| + SkMatrix matrix; |
| + SkShader::TileMode xy[2]; |
| + SkImage* image = shader->isAImage(&matrix, xy); |
| + if (image) { |
| + PaintImage paint_image(sk_ref_sp(image), |
| + PaintImage::AnimationType::UNKNOWN, |
| + PaintImage::CompletionState::UNKNOWN); |
| + // TODO(ericrk): Handle cases where we only need a sub-rect from the |
| + // image. crbug.com/671821 |
| + image_store->AddImage(paint_image, SkRect::MakeFromIRect(image->bounds()), |
| + rect, &matrix, flags); |
| + } |
| + } |
| +} |
| + |
| +} // namespace |
| #define TYPES(M) \ |
| M(AnnotateOp) \ |
| @@ -574,6 +600,97 @@ void PaintOpBuffer::playback(SkCanvas* canvas, |
| } |
| } |
| +void PaintOpBuffer::GatherDiscardableImages( |
|
vmpstr
2017/04/27 16:28:54
hmmmmm. Have you considered flipping |this| and |i
Khushal
2017/04/27 22:06:02
Done.
|
| + DiscardableImageStore* image_store) const { |
| + if (!has_discardable_images_) |
| + return; |
| + |
| + SkCanvas* canvas = image_store->NoDrawCanvas(); |
| + SkMatrix original = canvas->getTotalMatrix(); |
| + canvas->save(); |
| + for (auto* op : Iterator(this)) { |
|
vmpstr
2017/04/27 16:28:54
I was hoping to implement a smarter iterator for t
Khushal
2017/04/27 22:06:02
Yeah. Its worth looking at in a follow up patch.
|
| + if (op->IsDrawOp()) { |
| + switch (op->GetType()) { |
| + case PaintOpType::DrawArc: { |
| + auto* arc_op = static_cast<DrawArcOp*>(op); |
| + AddImageFromFlags(image_store, arc_op->oval, arc_op->flags); |
| + } break; |
| + case PaintOpType::DrawCircle: { |
| + auto* circle_op = static_cast<DrawCircleOp*>(op); |
| + SkRect rect = |
| + SkRect::MakeXYWH(circle_op->cx - circle_op->radius, |
| + circle_op->cy - circle_op->radius, |
| + 2 * circle_op->radius, 2 * circle_op->radius); |
| + AddImageFromFlags(image_store, rect, circle_op->flags); |
| + } break; |
| + case PaintOpType::DrawDisplayItemList: { |
| + auto* list_op = static_cast<DrawDisplayItemListOp*>(op); |
| + list_op->list->GatherDiscardableImages(image_store); |
| + } break; |
| + case PaintOpType::DrawImage: { |
| + auto* image_op = static_cast<DrawImageOp*>(op); |
| + const SkImage* sk_image = image_op->image.sk_image().get(); |
| + image_store->AddImage( |
| + image_op->image, |
| + SkRect::MakeIWH(sk_image->width(), sk_image->height()), |
| + SkRect::MakeXYWH(image_op->left, image_op->top, sk_image->width(), |
| + sk_image->height()), |
| + nullptr, image_op->flags); |
| + } break; |
| + case PaintOpType::DrawImageRect: { |
| + auto* image_rect_op = static_cast<DrawImageRectOp*>(op); |
| + SkMatrix matrix; |
| + matrix.setRectToRect(image_rect_op->src, image_rect_op->dst, |
| + SkMatrix::kFill_ScaleToFit); |
| + image_store->AddImage(image_rect_op->image, image_rect_op->src, |
| + image_rect_op->dst, &matrix, |
| + image_rect_op->flags); |
| + } break; |
| + case PaintOpType::DrawIRect: { |
| + auto* rect_op = static_cast<DrawIRectOp*>(op); |
| + AddImageFromFlags(image_store, SkRect::Make(rect_op->rect), |
| + rect_op->flags); |
| + } break; |
| + case PaintOpType::DrawOval: { |
| + auto* oval_op = static_cast<DrawOvalOp*>(op); |
| + AddImageFromFlags(image_store, oval_op->oval, oval_op->flags); |
| + } break; |
| + case PaintOpType::DrawPath: { |
| + auto* path_op = static_cast<DrawPathOp*>(op); |
| + AddImageFromFlags(image_store, path_op->path.getBounds(), |
| + path_op->flags); |
| + } break; |
| + case PaintOpType::DrawRecord: { |
| + auto* record_op = static_cast<DrawRecordOp*>(op); |
| + record_op->record->GatherDiscardableImages(image_store); |
| + } break; |
| + case PaintOpType::DrawRect: { |
| + auto* rect_op = static_cast<DrawRectOp*>(op); |
| + AddImageFromFlags(image_store, rect_op->rect, rect_op->flags); |
| + } break; |
| + case PaintOpType::DrawRRect: { |
| + auto* rect_op = static_cast<DrawRRectOp*>(op); |
| + AddImageFromFlags(image_store, rect_op->rrect.rect(), rect_op->flags); |
| + } break; |
| + // TODO(khushalsagar): Check if we should be querying images from any of |
| + // the following ops. |
| + case PaintOpType::DrawPosText: |
| + case PaintOpType::DrawLine: |
| + case PaintOpType::DrawDRRect: |
| + case PaintOpType::DrawText: |
| + case PaintOpType::DrawTextBlob: |
| + case PaintOpType::DrawColor: |
| + break; |
| + default: |
| + NOTREACHED(); |
| + } |
| + } else { |
| + op->Raster(canvas, original); |
| + } |
| + } |
| + canvas->restore(); |
| +} |
| + |
| void PaintOpBuffer::ShrinkToFit() { |
| if (!used_ || used_ == reserved_) |
| return; |