| // Copyright 2017 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "cc/paint/paint_record.h" |
| |
| #include <algorithm> |
| #include <utility> |
| |
| #include "base/no_destructor.h" |
| #include "cc/paint/paint_op_buffer_iterator.h" |
| #include "third_party/skia/include/core/SkMatrix.h" |
| #include "third_party/skia/include/core/SkPictureRecorder.h" |
| #include "third_party/skia/include/core/SkRect.h" |
| |
| namespace cc { |
| |
| PaintRecord::PaintRecord() { |
| static base::NoDestructor<sk_sp<PaintOpBuffer>> empty_buffer( |
| sk_make_sp<PaintOpBuffer>()); |
| buffer_ = *empty_buffer; |
| } |
| |
| PaintRecord::~PaintRecord() = default; |
| PaintRecord::PaintRecord(PaintRecord&&) = default; |
| PaintRecord& PaintRecord::operator=(PaintRecord&&) = default; |
| PaintRecord::PaintRecord(const PaintRecord&) = default; |
| PaintRecord& PaintRecord::operator=(const PaintRecord&) = default; |
| |
| PaintRecord::PaintRecord(sk_sp<PaintOpBuffer> buffer) |
| : buffer_(std::move(buffer)) { |
| DCHECK(buffer_); |
| } |
| |
| // static |
| SkRect PaintRecord::GetFixedScaleBounds(const SkMatrix& ctm, |
| const SkRect& bounds, |
| int max_texture_size) { |
| SkSize scale; |
| if (!ctm.decomposeScale(&scale)) { |
| // Decomposition failed, use an approximation. |
| scale.set(SkScalarSqrt(ctm.getScaleX() * ctm.getScaleX() + |
| ctm.getSkewX() * ctm.getSkewX()), |
| SkScalarSqrt(ctm.getScaleY() * ctm.getScaleY() + |
| ctm.getSkewY() * ctm.getSkewY())); |
| } |
| |
| SkScalar raster_width = bounds.width() * scale.width(); |
| SkScalar raster_height = bounds.height() * scale.height(); |
| SkScalar tile_area = raster_width * raster_height; |
| // Clamp the tile area to about 4M pixels, and per-dimension max texture size |
| // if it's provided. |
| static const SkScalar kMaxTileArea = 2048 * 2048; |
| SkScalar down_scale = 1.f; |
| if (tile_area > kMaxTileArea) { |
| down_scale = SkScalarSqrt(kMaxTileArea / tile_area); |
| } |
| if (max_texture_size > 0) { |
| // This only updates down_scale if the tile is larger than the texture size |
| // after ensuring its area is less than kMaxTileArea |
| down_scale = std::min( |
| down_scale, max_texture_size / std::max(raster_width, raster_height)); |
| } |
| |
| if (down_scale < 1.f) { |
| scale.set(down_scale * scale.width(), down_scale * scale.height()); |
| } |
| return SkRect::MakeXYWH( |
| bounds.fLeft * scale.width(), bounds.fTop * scale.height(), |
| SkScalarCeilToInt(SkScalarAbs(scale.width() * bounds.width())), |
| SkScalarCeilToInt(SkScalarAbs(scale.height() * bounds.height()))); |
| } |
| |
| sk_sp<SkPicture> PaintRecord::ToSkPicture( |
| const SkRect& bounds, |
| ImageProvider* image_provider, |
| PlaybackParams::CustomDataRasterCallback custom_callback, |
| PlaybackParams::ConvertOpCallback convert_op_callback) const { |
| SkPictureRecorder recorder; |
| SkCanvas* canvas = recorder.beginRecording(bounds); |
| PlaybackParams params(image_provider); |
| params.custom_callback = std::move(custom_callback); |
| params.convert_op_callback = std::move(convert_op_callback); |
| Playback(canvas, params); |
| return recorder.finishRecordingAsPicture(); |
| } |
| |
| PaintRecord::const_iterator PaintRecord::begin() const { |
| return const_iterator(buffer()); |
| } |
| |
| PaintRecord::const_iterator PaintRecord::end() const { |
| return const_iterator(buffer()).end(); |
| } |
| |
| } // namespace cc |