blob: 526050547453f1a425874a1084c67fb31dbb5bbb [file] [log] [blame]
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef FLUTTER_IMPELLER_AIKS_CANVAS_RECORDER_H_
#define FLUTTER_IMPELLER_AIKS_CANVAS_RECORDER_H_
#include <cstdint>
#include "impeller/aiks/canvas.h"
#define FLT_CANVAS_RECORDER_OP_ARG(name) \
CanvasRecorderOp::k##name, &Canvas::name
namespace impeller {
/// TODO(tbd): These are very similar to `flutter::DisplayListOpType`. When
/// golden tests can be written at a higher level, migrate these to
/// flutter::DisplayListOpType.
enum CanvasRecorderOp : uint16_t {
kNew,
kSave,
kSaveLayer,
kRestore,
kRestoreToCount,
kResetTransform,
kTransform,
kConcat,
kPreConcat,
kTranslate,
kScale2,
kScale3,
kSkew,
kRotate,
kDrawPath,
kDrawPaint,
kDrawLine,
kDrawRect,
kDrawOval,
kDrawRRect,
kDrawCircle,
kDrawPoints,
kDrawImage,
kDrawImageRect,
kClipPath,
kClipRect,
kClipOval,
kClipRRect,
kDrawTextFrame,
kDrawVertices,
kDrawAtlas,
};
// Canvas recorder should only be used when IMPELLER_TRACE_CANVAS is defined
// (never in production code).
#ifdef IMPELLER_TRACE_CANVAS
/// Static polymorphic replacement for impeller::Canvas that records methods
/// called on an impeller::Canvas and forwards it to a real instance.
/// TODO(https://github.com/flutter/flutter/issues/135718): Move this recorder
/// to the DisplayList level when golden tests can be written at the ui.Canvas
/// layer.
template <typename Serializer>
class CanvasRecorder {
public:
CanvasRecorder() : canvas_() { serializer_.Write(CanvasRecorderOp::kNew); }
explicit CanvasRecorder(Rect cull_rect) : canvas_(cull_rect) {
serializer_.Write(CanvasRecorderOp::kNew);
}
explicit CanvasRecorder(IRect cull_rect) : canvas_(cull_rect) {
serializer_.Write(CanvasRecorderOp::kNew);
}
~CanvasRecorder() {}
const Serializer& GetSerializer() const { return serializer_; }
template <typename ReturnType>
ReturnType ExecuteAndSerialize(CanvasRecorderOp op,
ReturnType (Canvas::*canvasMethod)()) {
serializer_.Write(op);
return (canvas_.*canvasMethod)();
}
template <typename FuncType, typename... Args>
auto ExecuteAndSerialize(CanvasRecorderOp op,
FuncType canvasMethod,
Args&&... args)
-> decltype((std::declval<Canvas>().*
canvasMethod)(std::forward<Args>(args)...)) {
// Serialize each argument
(serializer_.Write(std::forward<Args>(args)), ...);
serializer_.Write(op);
return (canvas_.*canvasMethod)(std::forward<Args>(args)...);
}
template <typename FuncType, typename... Args>
auto ExecuteAndSkipArgSerialize(CanvasRecorderOp op,
FuncType canvasMethod,
Args&&... args)
-> decltype((std::declval<Canvas>().*
canvasMethod)(std::forward<Args>(args)...)) {
serializer_.Write(op);
return (canvas_.*canvasMethod)(std::forward<Args>(args)...);
}
//////////////////////////////////////////////////////////////////////////////
// Canvas Static Polymorphism
// ////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
void Save() {
return ExecuteAndSerialize(CanvasRecorderOp::kSave, &Canvas::Save);
}
void SaveLayer(
const Paint& paint,
std::optional<Rect> bounds = std::nullopt,
const std::shared_ptr<ImageFilter>& backdrop_filter = nullptr,
ContentBoundsPromise bounds_promise = ContentBoundsPromise::kUnknown) {
return ExecuteAndSerialize(FLT_CANVAS_RECORDER_OP_ARG(SaveLayer), paint,
bounds, backdrop_filter, bounds_promise);
}
bool Restore() {
return ExecuteAndSerialize(FLT_CANVAS_RECORDER_OP_ARG(Restore));
}
size_t GetSaveCount() const { return canvas_.GetSaveCount(); }
void RestoreToCount(size_t count) {
return ExecuteAndSerialize(FLT_CANVAS_RECORDER_OP_ARG(RestoreToCount),
count);
}
const Matrix& GetCurrentTransform() const {
return canvas_.GetCurrentTransform();
}
const std::optional<Rect> GetCurrentLocalCullingBounds() const {
return canvas_.GetCurrentLocalCullingBounds();
}
void ResetTransform() {
return ExecuteAndSerialize(FLT_CANVAS_RECORDER_OP_ARG(ResetTransform));
}
void Transform(const Matrix& transform) {
return ExecuteAndSerialize(FLT_CANVAS_RECORDER_OP_ARG(Transform),
transform);
}
void Concat(const Matrix& transform) {
return ExecuteAndSerialize(FLT_CANVAS_RECORDER_OP_ARG(Concat), transform);
}
void PreConcat(const Matrix& transform) {
return ExecuteAndSerialize(FLT_CANVAS_RECORDER_OP_ARG(PreConcat),
transform);
}
void Translate(const Vector3& offset) {
return ExecuteAndSerialize(FLT_CANVAS_RECORDER_OP_ARG(Translate), offset);
}
void Scale(const Vector2& scale) {
return ExecuteAndSerialize(
CanvasRecorderOp::kScale2,
static_cast<void (Canvas::*)(const Vector2&)>(&Canvas::Scale), scale);
}
void Scale(const Vector3& scale) {
return ExecuteAndSerialize(
CanvasRecorderOp::kScale3,
static_cast<void (Canvas::*)(const Vector3&)>(&Canvas::Scale), scale);
}
void Skew(Scalar sx, Scalar sy) {
return ExecuteAndSerialize(FLT_CANVAS_RECORDER_OP_ARG(Skew), sx, sy);
}
void Rotate(Radians radians) {
return ExecuteAndSerialize(FLT_CANVAS_RECORDER_OP_ARG(Rotate), radians);
}
void DrawPath(Path path, const Paint& paint) {
serializer_.Write(path);
serializer_.Write(paint);
return ExecuteAndSkipArgSerialize(FLT_CANVAS_RECORDER_OP_ARG(DrawPath),
std::move(path), paint);
}
void DrawPaint(const Paint& paint) {
return ExecuteAndSerialize(FLT_CANVAS_RECORDER_OP_ARG(DrawPaint), paint);
}
void DrawLine(const Point& p0, const Point& p1, const Paint& paint) {
return ExecuteAndSerialize(FLT_CANVAS_RECORDER_OP_ARG(DrawLine), p0, p1,
paint);
}
void DrawRect(Rect rect, const Paint& paint) {
return ExecuteAndSerialize(FLT_CANVAS_RECORDER_OP_ARG(DrawRect), rect,
paint);
}
void DrawOval(const Rect& rect, const Paint& paint) {
return ExecuteAndSerialize(FLT_CANVAS_RECORDER_OP_ARG(DrawOval), rect,
paint);
}
void DrawRRect(const Rect& rect,
const Size& corner_radii,
const Paint& paint) {
return ExecuteAndSerialize(FLT_CANVAS_RECORDER_OP_ARG(DrawRRect), rect,
corner_radii, paint);
}
void DrawCircle(Point center, Scalar radius, const Paint& paint) {
return ExecuteAndSerialize(FLT_CANVAS_RECORDER_OP_ARG(DrawCircle), center,
radius, paint);
}
void DrawPoints(std::vector<Point> points,
Scalar radius,
const Paint& paint,
PointStyle point_style) {
return ExecuteAndSerialize(FLT_CANVAS_RECORDER_OP_ARG(DrawPoints), points,
radius, paint, point_style);
}
void DrawImage(const std::shared_ptr<Image>& image,
Point offset,
const Paint& paint,
SamplerDescriptor sampler = {}) {
return ExecuteAndSerialize(FLT_CANVAS_RECORDER_OP_ARG(DrawImage), image,
offset, paint, sampler);
}
void DrawImageRect(
const std::shared_ptr<Image>& image,
Rect source,
Rect dest,
const Paint& paint,
SamplerDescriptor sampler = {},
SourceRectConstraint src_rect_constraint = SourceRectConstraint::kFast) {
return ExecuteAndSerialize(FLT_CANVAS_RECORDER_OP_ARG(DrawImageRect), image,
source, dest, paint, sampler,
src_rect_constraint);
}
void ClipPath(
Path path,
Entity::ClipOperation clip_op = Entity::ClipOperation::kIntersect) {
serializer_.Write(path);
serializer_.Write(clip_op);
return ExecuteAndSkipArgSerialize(FLT_CANVAS_RECORDER_OP_ARG(ClipPath),
std::move(path), clip_op);
}
void ClipRect(
const Rect& rect,
Entity::ClipOperation clip_op = Entity::ClipOperation::kIntersect) {
return ExecuteAndSerialize(FLT_CANVAS_RECORDER_OP_ARG(ClipRect), rect,
clip_op);
}
void ClipOval(
const Rect& bounds,
Entity::ClipOperation clip_op = Entity::ClipOperation::kIntersect) {
return ExecuteAndSerialize(FLT_CANVAS_RECORDER_OP_ARG(ClipOval), bounds,
clip_op);
}
void ClipRRect(
const Rect& rect,
const Size& corner_radii,
Entity::ClipOperation clip_op = Entity::ClipOperation::kIntersect) {
return ExecuteAndSerialize(FLT_CANVAS_RECORDER_OP_ARG(ClipRRect), rect,
corner_radii, clip_op);
}
void DrawTextFrame(const std::shared_ptr<TextFrame>& text_frame,
Point position,
const Paint& paint) {
return ExecuteAndSerialize(FLT_CANVAS_RECORDER_OP_ARG(DrawTextFrame),
text_frame, position, paint);
}
void DrawVertices(const std::shared_ptr<VerticesGeometry>& vertices,
BlendMode blend_mode,
const Paint& paint) {
return ExecuteAndSerialize(FLT_CANVAS_RECORDER_OP_ARG(DrawVertices),
vertices, blend_mode, paint);
}
void DrawAtlas(const std::shared_ptr<Image>& atlas,
std::vector<Matrix> transforms,
std::vector<Rect> texture_coordinates,
std::vector<Color> colors,
BlendMode blend_mode,
SamplerDescriptor sampler,
std::optional<Rect> cull_rect,
const Paint& paint) {
return ExecuteAndSerialize(FLT_CANVAS_RECORDER_OP_ARG(DrawAtlas), //
atlas, //
transforms, //
texture_coordinates, //
colors, //
blend_mode, //
sampler, //
cull_rect, //
paint);
}
Picture EndRecordingAsPicture() { return canvas_.EndRecordingAsPicture(); }
private:
Canvas canvas_;
Serializer serializer_;
};
#endif
} // namespace impeller
#endif // FLUTTER_IMPELLER_AIKS_CANVAS_RECORDER_H_