blob: 2dcbca8273e7bf9a99ae55b1d3fb0f70611beda3 [file] [log] [blame]
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <SkAndroidFrameworkUtils.h>
#include <SkBlendMode.h>
#include <SkCanvas.h>
#include <SkClipOp.h>
#include <SkImage.h>
#include <SkPaint.h>
#include <SkPath.h>
#include <SkPicture.h>
#include <SkRRect.h>
#include <SkRect.h>
#include <SkRegion.h>
#include <SkRuntimeEffect.h>
#include <SkSamplingOptions.h>
#include <SkVertices.h>
#include <log/log.h>
#include "hwui/Bitmap.h"
#include "CanvasProperty.h"
#include "CanvasOpTypes.h"
#include "Layer.h"
#include "Points.h"
#include "RenderNode.h"
#include <experimental/type_traits>
#include <utility>
namespace android::uirenderer {
template <CanvasOpType T>
struct CanvasOp;
struct CanvasOpTraits {
CanvasOpTraits() = delete;
template<class T>
using draw_t = decltype(std::integral_constant<void (T::*)(SkCanvas*) const, &T::draw>{});
template <class T>
static constexpr bool can_draw = std::experimental::is_detected_v<draw_t, T>;
};
#define ASSERT_DRAWABLE() private: constexpr void _check_drawable() \
{ static_assert(CanvasOpTraits::can_draw<std::decay_t<decltype(*this)>>); }
// ----------------------------------------------
// State Ops
// ---------------------------------------------
template <>
struct CanvasOp<CanvasOpType::Save> {
void draw(SkCanvas* canvas) const { canvas->save(); }
ASSERT_DRAWABLE()
};
template <>
struct CanvasOp<CanvasOpType::SaveLayer> {
SkCanvas::SaveLayerRec saveLayerRec;
void draw(SkCanvas* canvas) const { canvas->saveLayer(saveLayerRec); }
ASSERT_DRAWABLE()
};
template <>
struct CanvasOp<CanvasOpType::SaveBehind> {
SkRect bounds;
void draw(SkCanvas* canvas) const { SkAndroidFrameworkUtils::SaveBehind(canvas, &bounds); }
ASSERT_DRAWABLE()
};
template <>
struct CanvasOp<CanvasOpType::Restore> {
void draw(SkCanvas* canvas) const { canvas->restore(); }
ASSERT_DRAWABLE()
};
template <>
struct CanvasOp<CanvasOpType::BeginZ> {
};
template <>
struct CanvasOp<CanvasOpType::EndZ> {};
// ----------------------------------------------
// Clip Ops
// ---------------------------------------------
template <>
struct CanvasOp<CanvasOpType::ClipRect> {
SkRect rect;
SkClipOp clipOp;
void draw(SkCanvas* canvas) const { canvas->clipRect(rect, clipOp); }
ASSERT_DRAWABLE()
};
template <>
struct CanvasOp<CanvasOpType::ClipPath> {
SkPath path;
SkClipOp op;
void draw(SkCanvas* canvas) const { canvas->clipPath(path, op, true); }
ASSERT_DRAWABLE()
};
// ----------------------------------------------
// Drawing Ops
// ---------------------------------------------
template<>
struct CanvasOp<CanvasOpType::DrawRoundRectProperty> {
sp<uirenderer::CanvasPropertyPrimitive> left;
sp<uirenderer::CanvasPropertyPrimitive> top;
sp<uirenderer::CanvasPropertyPrimitive> right;
sp<uirenderer::CanvasPropertyPrimitive> bottom;
sp<uirenderer::CanvasPropertyPrimitive> rx;
sp<uirenderer::CanvasPropertyPrimitive> ry;
sp<uirenderer::CanvasPropertyPaint> paint;
void draw(SkCanvas* canvas) const {
SkRect rect = SkRect::MakeLTRB(left->value, top->value, right->value, bottom->value);
canvas->drawRoundRect(rect, rx->value, ry->value, paint->value);
}
ASSERT_DRAWABLE()
};
template<>
struct CanvasOp<CanvasOpType::DrawCircleProperty> {
sp<uirenderer::CanvasPropertyPrimitive> x;
sp<uirenderer::CanvasPropertyPrimitive> y;
sp<uirenderer::CanvasPropertyPrimitive> radius;
sp<uirenderer::CanvasPropertyPaint> paint;
void draw(SkCanvas* canvas) const {
canvas->drawCircle(x->value, y->value, radius->value, paint->value);
}
ASSERT_DRAWABLE()
};
template <>
struct CanvasOp<CanvasOpType::DrawRippleDrawable> {
skiapipeline::RippleDrawableParams params;
void draw(SkCanvas* canvas) const {
skiapipeline::AnimatedRippleDrawable::draw(canvas, params);
}
ASSERT_DRAWABLE()
};
template <>
struct CanvasOp<CanvasOpType::DrawColor> {
SkColor4f color;
SkBlendMode mode;
void draw(SkCanvas* canvas) const { canvas->drawColor(color, mode); }
ASSERT_DRAWABLE()
};
template <>
struct CanvasOp<CanvasOpType::DrawPaint> {
SkPaint paint;
void draw(SkCanvas* canvas) const { canvas->drawPaint(paint); }
ASSERT_DRAWABLE()
};
template <>
struct CanvasOp<CanvasOpType::DrawPoint> {
float x;
float y;
SkPaint paint;
void draw(SkCanvas* canvas) const { canvas->drawPoint(x, y, paint); }
ASSERT_DRAWABLE()
};
template <>
struct CanvasOp<CanvasOpType::DrawPoints> {
size_t count;
SkPaint paint;
sk_sp<Points> points;
void draw(SkCanvas* canvas) const {
canvas->drawPoints(
SkCanvas::kPoints_PointMode,
count,
points->data(),
paint
);
}
ASSERT_DRAWABLE()
};
template <>
struct CanvasOp<CanvasOpType::DrawRect> {
SkRect rect;
SkPaint paint;
void draw(SkCanvas* canvas) const { canvas->drawRect(rect, paint); }
ASSERT_DRAWABLE()
};
template <>
struct CanvasOp<CanvasOpType::DrawRegion> {
SkRegion region;
SkPaint paint;
void draw(SkCanvas* canvas) const { canvas->drawRegion(region, paint); }
ASSERT_DRAWABLE()
};
template<>
struct CanvasOp<CanvasOpType::DrawRoundRect> {
SkRect rect;
SkScalar rx;
SkScalar ry;
SkPaint paint;
void draw(SkCanvas* canvas) const {
canvas->drawRoundRect(rect, rx, ry, paint);
}
ASSERT_DRAWABLE()
};
template<>
struct CanvasOp<CanvasOpType::DrawDoubleRoundRect> {
SkRRect outer;
SkRRect inner;
SkPaint paint;
void draw(SkCanvas* canvas) const {
canvas->drawDRRect(outer, inner, paint);
}
ASSERT_DRAWABLE()
};
template<>
struct CanvasOp<CanvasOpType::DrawCircle> {
SkScalar cx;
SkScalar cy;
SkScalar radius;
SkPaint paint;
void draw(SkCanvas* canvas) const {
canvas->drawCircle(cx, cy, radius, paint);
}
ASSERT_DRAWABLE()
};
template<>
struct CanvasOp<CanvasOpType::DrawOval> {
SkRect oval;
SkPaint paint;
void draw(SkCanvas* canvas) const {
canvas->drawOval(oval, paint);
}
ASSERT_DRAWABLE()
};
template<>
struct CanvasOp<CanvasOpType::DrawArc> {
SkRect oval;
SkScalar startAngle;
SkScalar sweepAngle;
bool useCenter;
SkPaint paint;
void draw(SkCanvas* canvas) const {
canvas->drawArc(oval, startAngle, sweepAngle, useCenter, paint);
}
ASSERT_DRAWABLE()
};
template<>
struct CanvasOp<CanvasOpType::DrawPath> {
SkPath path;
SkPaint paint;
void draw(SkCanvas* canvas) const { canvas->drawPath(path, paint); }
ASSERT_DRAWABLE()
};
template<>
struct CanvasOp<CanvasOpType::DrawLine> {
float startX;
float startY;
float endX;
float endY;
SkPaint paint;
void draw(SkCanvas* canvas) const {
canvas->drawLine(startX, startY, endX, endY, paint);
}
ASSERT_DRAWABLE()
};
template<>
struct CanvasOp<CanvasOpType::DrawLines> {
size_t count;
SkPaint paint;
sk_sp<Points> points;
void draw(SkCanvas* canvas) const {
canvas->drawPoints(
SkCanvas::kLines_PointMode,
count,
points->data(),
paint
);
}
ASSERT_DRAWABLE()
};
template<>
struct CanvasOp<CanvasOpType::DrawVertices> {
sk_sp<SkVertices> vertices;
SkBlendMode mode;
SkPaint paint;
void draw(SkCanvas* canvas) const {
canvas->drawVertices(vertices, mode, paint);
}
ASSERT_DRAWABLE()
};
template<>
struct CanvasOp<CanvasOpType::DrawImage> {
CanvasOp(
const sk_sp<Bitmap>& bitmap,
float left,
float top,
SkFilterMode filter,
SkPaint paint
) : left(left),
top(top),
filter(filter),
paint(std::move(paint)),
bitmap(bitmap),
image(bitmap->makeImage()) { }
float left;
float top;
SkFilterMode filter;
SkPaint paint;
sk_sp<Bitmap> bitmap;
sk_sp<SkImage> image;
void draw(SkCanvas* canvas) const {
canvas->drawImage(image, left, top, SkSamplingOptions(filter), &paint);
}
ASSERT_DRAWABLE()
};
template<>
struct CanvasOp<CanvasOpType::DrawImageRect> {
CanvasOp(
const sk_sp<Bitmap>& bitmap,
SkRect src,
SkRect dst,
SkFilterMode filter,
SkPaint paint
) : src(src),
dst(dst),
filter(filter),
paint(std::move(paint)),
bitmap(bitmap),
image(bitmap->makeImage()) { }
SkRect src;
SkRect dst;
SkFilterMode filter;
SkPaint paint;
sk_sp<Bitmap> bitmap;
sk_sp<SkImage> image;
void draw(SkCanvas* canvas) const {
canvas->drawImageRect(image,
src,
dst,
SkSamplingOptions(filter),
&paint,
SkCanvas::kFast_SrcRectConstraint
);
}
ASSERT_DRAWABLE()
};
template<>
struct CanvasOp<CanvasOpType::DrawImageLattice> {
CanvasOp(
const sk_sp<Bitmap>& bitmap,
SkRect dst,
SkCanvas::Lattice lattice,
SkFilterMode filter,
SkPaint paint
): dst(dst),
lattice(lattice),
filter(filter),
bitmap(bitmap),
image(bitmap->makeImage()),
paint(std::move(paint)) {}
SkRect dst;
SkCanvas::Lattice lattice;
SkFilterMode filter;
const sk_sp<Bitmap> bitmap;
const sk_sp<SkImage> image;
SkPaint paint;
void draw(SkCanvas* canvas) const {
canvas->drawImageLattice(image.get(), lattice, dst, filter, &paint);
}
ASSERT_DRAWABLE()
};
template<>
struct CanvasOp<CanvasOpType::DrawPicture> {
sk_sp<SkPicture> picture;
void draw(SkCanvas* canvas) const {
picture->playback(canvas);
}
};
template<>
struct CanvasOp<CanvasOpType::DrawLayer> {
sp<Layer> layer;
};
template<>
struct CanvasOp<CanvasOpType::DrawRenderNode> {
sp<RenderNode> renderNode;
};
// cleanup our macros
#undef ASSERT_DRAWABLE
} // namespace android::uirenderer