blob: 0c2c4d678d6068d30a3caace86268efe243a5012 [file] [log] [blame]
// 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