blob: 86b1ac71f692416c0cfbac5d353f3e40e8c446ee [file] [log] [blame]
John Reck013127b2020-10-29 20:53:51 -04001/*
2 * Copyright (C) 2020 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#pragma once
18
19#include <SkAndroidFrameworkUtils.h>
20#include <SkCanvas.h>
21#include <SkPath.h>
Nader Jawadfb1e7f12020-11-06 22:49:42 -080022#include <SkRegion.h>
23#include <SkVertices.h>
Nader Jawadda9248c2020-11-09 17:27:36 -080024#include <SkImage.h>
25#include <SkPicture.h>
Derek Sollenbergerdf301aa2020-12-17 11:06:03 -050026#include <SkRuntimeEffect.h>
Nader Jawadda9248c2020-11-09 17:27:36 -080027#include <hwui/Bitmap.h>
John Reck013127b2020-10-29 20:53:51 -040028#include <log/log.h>
Nader Jawadde3ce842020-11-06 16:54:48 -080029#include "CanvasProperty.h"
Nader Jawad4285c8a2020-11-06 22:49:42 -080030#include "Points.h"
John Reck013127b2020-10-29 20:53:51 -040031
32#include "CanvasOpTypes.h"
Nader Jawad55f19762020-11-25 15:30:20 -080033#include "Layer.h"
John Reck013127b2020-10-29 20:53:51 -040034
35#include <experimental/type_traits>
Nader Jawadda9248c2020-11-09 17:27:36 -080036#include <utility>
John Reck013127b2020-10-29 20:53:51 -040037
38namespace android::uirenderer {
39
40template <CanvasOpType T>
41struct CanvasOp;
42
43struct CanvasOpTraits {
44 CanvasOpTraits() = delete;
45
46 template<class T>
47 using draw_t = decltype(std::integral_constant<void (T::*)(SkCanvas*) const, &T::draw>{});
48
49 template <class T>
50 static constexpr bool can_draw = std::experimental::is_detected_v<draw_t, T>;
51};
52
53#define ASSERT_DRAWABLE() private: constexpr void _check_drawable() \
54 { static_assert(CanvasOpTraits::can_draw<std::decay_t<decltype(*this)>>); }
55
56// ----------------------------------------------
57// State Ops
58// ---------------------------------------------
59
60template <>
61struct CanvasOp<CanvasOpType::Save> {
62 void draw(SkCanvas* canvas) const { canvas->save(); }
63 ASSERT_DRAWABLE()
64};
65
66template <>
67struct CanvasOp<CanvasOpType::SaveLayer> {
68 SkCanvas::SaveLayerRec saveLayerRec;
69 void draw(SkCanvas* canvas) const { canvas->saveLayer(saveLayerRec); }
70 ASSERT_DRAWABLE()
71};
72
73template <>
74struct CanvasOp<CanvasOpType::SaveBehind> {
75 SkRect bounds;
76 void draw(SkCanvas* canvas) const { SkAndroidFrameworkUtils::SaveBehind(canvas, &bounds); }
77 ASSERT_DRAWABLE()
78};
79
80template <>
81struct CanvasOp<CanvasOpType::Restore> {
82 void draw(SkCanvas* canvas) const { canvas->restore(); }
83 ASSERT_DRAWABLE()
84};
85
86template <>
87struct CanvasOp<CanvasOpType::BeginZ> {
88};
89template <>
90struct CanvasOp<CanvasOpType::EndZ> {};
91
92// ----------------------------------------------
93// Clip Ops
94// ---------------------------------------------
95
96template <>
97struct CanvasOp<CanvasOpType::ClipRect> {
98 SkRect rect;
99 SkClipOp clipOp;
100 void draw(SkCanvas* canvas) const { canvas->clipRect(rect, clipOp); }
101 ASSERT_DRAWABLE()
102};
103
104template <>
105struct CanvasOp<CanvasOpType::ClipPath> {
106 SkPath path;
107 SkClipOp op;
108 void draw(SkCanvas* canvas) const { canvas->clipPath(path, op, true); }
109 ASSERT_DRAWABLE()
110};
111
112// ----------------------------------------------
113// Drawing Ops
114// ---------------------------------------------
115
Nader Jawadde3ce842020-11-06 16:54:48 -0800116template<>
117struct CanvasOp<CanvasOpType::DrawRoundRectProperty> {
118 sp<uirenderer::CanvasPropertyPrimitive> left;
119 sp<uirenderer::CanvasPropertyPrimitive> top;
120 sp<uirenderer::CanvasPropertyPrimitive> right;
121 sp<uirenderer::CanvasPropertyPrimitive> bottom;
122 sp<uirenderer::CanvasPropertyPrimitive> rx;
123 sp<uirenderer::CanvasPropertyPrimitive> ry;
124 sp<uirenderer::CanvasPropertyPaint> paint;
125
126 void draw(SkCanvas* canvas) const {
127 SkRect rect = SkRect::MakeLTRB(left->value, top->value, right->value, bottom->value);
128 canvas->drawRoundRect(rect, rx->value, ry->value, paint->value);
129 }
130 ASSERT_DRAWABLE()
131};
132
133template<>
134struct CanvasOp<CanvasOpType::DrawCircleProperty> {
135 sp<uirenderer::CanvasPropertyPrimitive> x;
136 sp<uirenderer::CanvasPropertyPrimitive> y;
137 sp<uirenderer::CanvasPropertyPrimitive> radius;
138 sp<uirenderer::CanvasPropertyPaint> paint;
139
140 void draw(SkCanvas* canvas) const {
141 canvas->drawCircle(x->value, y->value, radius->value, paint->value);
142 }
143 ASSERT_DRAWABLE()
144};
145
Derek Sollenbergerdf301aa2020-12-17 11:06:03 -0500146template<>
147struct CanvasOp<CanvasOpType::DrawRippleProperty> {
148 sp<uirenderer::CanvasPropertyPrimitive> x;
149 sp<uirenderer::CanvasPropertyPrimitive> y;
150 sp<uirenderer::CanvasPropertyPrimitive> radius;
151 sp<uirenderer::CanvasPropertyPaint> paint;
152 sp<uirenderer::CanvasPropertyPrimitive> progress;
153 sk_sp<SkRuntimeEffect> effect;
154
155 void draw(SkCanvas* canvas) const {
156 SkRuntimeShaderBuilder runtimeEffectBuilder(effect);
157
158 SkRuntimeShaderBuilder::BuilderUniform center = runtimeEffectBuilder.uniform("in_origin");
159 if (center.fVar != nullptr) {
160 center = SkV2{x->value, y->value};
161 }
162
163 SkRuntimeShaderBuilder::BuilderUniform radiusU =
Derek Sollenberger783e5ae2021-01-11 15:44:46 -0500164 runtimeEffectBuilder.uniform("in_radius");
Derek Sollenbergerdf301aa2020-12-17 11:06:03 -0500165 if (radiusU.fVar != nullptr) {
166 radiusU = radius->value;
167 }
168
169 SkRuntimeShaderBuilder::BuilderUniform progressU =
170 runtimeEffectBuilder.uniform("in_progress");
171 if (progressU.fVar != nullptr) {
172 progressU = progress->value;
173 }
174
175 SkPaint paintMod = paint->value;
176 paintMod.setShader(runtimeEffectBuilder.makeShader(nullptr, false));
177 canvas->drawCircle(x->value, y->value, radius->value, paintMod);
178 }
179 ASSERT_DRAWABLE()
180};
181
John Reck013127b2020-10-29 20:53:51 -0400182template <>
183struct CanvasOp<CanvasOpType::DrawColor> {
184 SkColor4f color;
185 SkBlendMode mode;
186 void draw(SkCanvas* canvas) const { canvas->drawColor(color, mode); }
187 ASSERT_DRAWABLE()
188};
189
190template <>
Nader Jawadd5c2b6d2020-11-05 19:12:29 -0800191struct CanvasOp<CanvasOpType::DrawPaint> {
192 SkPaint paint;
193 void draw(SkCanvas* canvas) const { canvas->drawPaint(paint); }
194 ASSERT_DRAWABLE()
195};
196
197template <>
Nader Jawadfb1e7f12020-11-06 22:49:42 -0800198struct CanvasOp<CanvasOpType::DrawPoint> {
199 float x;
200 float y;
201 SkPaint paint;
202 void draw(SkCanvas* canvas) const { canvas->drawPoint(x, y, paint); }
203 ASSERT_DRAWABLE()
204};
205
206template <>
Nader Jawad4285c8a2020-11-06 22:49:42 -0800207struct CanvasOp<CanvasOpType::DrawPoints> {
208 size_t count;
209 SkPaint paint;
210 sk_sp<Points> points;
211 void draw(SkCanvas* canvas) const {
212 canvas->drawPoints(
213 SkCanvas::kPoints_PointMode,
214 count,
215 points->data(),
216 paint
217 );
218 }
219 ASSERT_DRAWABLE()
220};
221
222template <>
John Reck013127b2020-10-29 20:53:51 -0400223struct CanvasOp<CanvasOpType::DrawRect> {
224 SkRect rect;
225 SkPaint paint;
226 void draw(SkCanvas* canvas) const { canvas->drawRect(rect, paint); }
227 ASSERT_DRAWABLE()
228};
229
Nader Jawadfb1e7f12020-11-06 22:49:42 -0800230template <>
231struct CanvasOp<CanvasOpType::DrawRegion> {
232 SkRegion region;
233 SkPaint paint;
234 void draw(SkCanvas* canvas) const { canvas->drawRegion(region, paint); }
235 ASSERT_DRAWABLE()
236};
237
Nader Jawadd5c2b6d2020-11-05 19:12:29 -0800238template<>
239struct CanvasOp<CanvasOpType::DrawRoundRect> {
240 SkRect rect;
241 SkScalar rx;
242 SkScalar ry;
243 SkPaint paint;
244 void draw(SkCanvas* canvas) const {
245 canvas->drawRoundRect(rect, rx, ry, paint);
246 }
247 ASSERT_DRAWABLE()
248};
249
250template<>
Nader Jawadfb1e7f12020-11-06 22:49:42 -0800251struct CanvasOp<CanvasOpType::DrawDoubleRoundRect> {
252 SkRRect outer;
253 SkRRect inner;
254 SkPaint paint;
255 void draw(SkCanvas* canvas) const {
256 canvas->drawDRRect(outer, inner, paint);
257 }
258 ASSERT_DRAWABLE()
259};
260
261template<>
Nader Jawadd5c2b6d2020-11-05 19:12:29 -0800262struct CanvasOp<CanvasOpType::DrawCircle> {
263 SkScalar cx;
264 SkScalar cy;
265 SkScalar radius;
266 SkPaint paint;
267 void draw(SkCanvas* canvas) const {
268 canvas->drawCircle(cx, cy, radius, paint);
269 }
270 ASSERT_DRAWABLE()
271};
272
273template<>
274struct CanvasOp<CanvasOpType::DrawOval> {
275 SkRect oval;
276 SkPaint paint;
277 void draw(SkCanvas* canvas) const {
278 canvas->drawOval(oval, paint);
279 }
280 ASSERT_DRAWABLE()
281};
282
283template<>
284struct CanvasOp<CanvasOpType::DrawArc> {
285 SkRect oval;
286 SkScalar startAngle;
287 SkScalar sweepAngle;
288 bool useCenter;
289 SkPaint paint;
290
291 void draw(SkCanvas* canvas) const {
292 canvas->drawArc(oval, startAngle, sweepAngle, useCenter, paint);
293 }
294 ASSERT_DRAWABLE()
295};
John Reck013127b2020-10-29 20:53:51 -0400296
Nader Jawadfb1e7f12020-11-06 22:49:42 -0800297template<>
298struct CanvasOp<CanvasOpType::DrawPath> {
299 SkPath path;
300 SkPaint paint;
301
302 void draw(SkCanvas* canvas) const { canvas->drawPath(path, paint); }
303 ASSERT_DRAWABLE()
304};
305
306template<>
307struct CanvasOp<CanvasOpType::DrawLine> {
308 float startX;
309 float startY;
310 float endX;
311 float endY;
312 SkPaint paint;
313
314 void draw(SkCanvas* canvas) const {
315 canvas->drawLine(startX, startY, endX, endY, paint);
316 }
317 ASSERT_DRAWABLE()
318};
319
320template<>
Nader Jawad4285c8a2020-11-06 22:49:42 -0800321struct CanvasOp<CanvasOpType::DrawLines> {
322 size_t count;
323 SkPaint paint;
324 sk_sp<Points> points;
325 void draw(SkCanvas* canvas) const {
326 canvas->drawPoints(
327 SkCanvas::kLines_PointMode,
328 count,
329 points->data(),
330 paint
331 );
332 }
333 ASSERT_DRAWABLE()
334};
335
336template<>
Nader Jawadfb1e7f12020-11-06 22:49:42 -0800337struct CanvasOp<CanvasOpType::DrawVertices> {
338 sk_sp<SkVertices> vertices;
339 SkBlendMode mode;
340 SkPaint paint;
341 void draw(SkCanvas* canvas) const {
342 canvas->drawVertices(vertices, mode, paint);
343 }
344 ASSERT_DRAWABLE()
345};
346
Nader Jawadda9248c2020-11-09 17:27:36 -0800347template<>
348struct CanvasOp<CanvasOpType::DrawImage> {
349
John Reckb5eeb182020-12-09 13:45:39 -0500350 CanvasOp(
Nader Jawadda9248c2020-11-09 17:27:36 -0800351 const sk_sp<Bitmap>& bitmap,
352 float left,
353 float top,
Mike Reed7994a312021-01-28 18:06:26 -0500354 SkFilterMode filter,
Nader Jawadda9248c2020-11-09 17:27:36 -0800355 SkPaint paint
356 ) : left(left),
357 top(top),
Mike Reed7994a312021-01-28 18:06:26 -0500358 filter(filter),
Nader Jawadda9248c2020-11-09 17:27:36 -0800359 paint(std::move(paint)),
360 bitmap(bitmap),
361 image(bitmap->makeImage()) { }
362
363 float left;
364 float top;
Mike Reed7994a312021-01-28 18:06:26 -0500365 SkFilterMode filter;
Nader Jawadda9248c2020-11-09 17:27:36 -0800366 SkPaint paint;
367 sk_sp<Bitmap> bitmap;
368 sk_sp<SkImage> image;
369
370 void draw(SkCanvas* canvas) const {
Mike Reed7994a312021-01-28 18:06:26 -0500371 canvas->drawImage(image, left, top, SkSamplingOptions(filter), &paint);
Nader Jawadda9248c2020-11-09 17:27:36 -0800372 }
373 ASSERT_DRAWABLE()
374};
375
376template<>
377struct CanvasOp<CanvasOpType::DrawImageRect> {
378
John Reckb5eeb182020-12-09 13:45:39 -0500379 CanvasOp(
Nader Jawadda9248c2020-11-09 17:27:36 -0800380 const sk_sp<Bitmap>& bitmap,
381 SkRect src,
382 SkRect dst,
Mike Reed7994a312021-01-28 18:06:26 -0500383 SkFilterMode filter,
Nader Jawadda9248c2020-11-09 17:27:36 -0800384 SkPaint paint
385 ) : src(src),
386 dst(dst),
Mike Reed7994a312021-01-28 18:06:26 -0500387 filter(filter),
Nader Jawadda9248c2020-11-09 17:27:36 -0800388 paint(std::move(paint)),
389 bitmap(bitmap),
390 image(bitmap->makeImage()) { }
391
392 SkRect src;
393 SkRect dst;
Mike Reed7994a312021-01-28 18:06:26 -0500394 SkFilterMode filter;
Nader Jawadda9248c2020-11-09 17:27:36 -0800395 SkPaint paint;
396 sk_sp<Bitmap> bitmap;
397 sk_sp<SkImage> image;
398
399 void draw(SkCanvas* canvas) const {
400 canvas->drawImageRect(image,
401 src,
402 dst,
Mike Reed7994a312021-01-28 18:06:26 -0500403 SkSamplingOptions(filter),
Nader Jawadda9248c2020-11-09 17:27:36 -0800404 &paint,
405 SkCanvas::kFast_SrcRectConstraint
406 );
407 }
408 ASSERT_DRAWABLE()
409};
410
411template<>
412struct CanvasOp<CanvasOpType::DrawImageLattice> {
413
John Reckb5eeb182020-12-09 13:45:39 -0500414 CanvasOp(
Nader Jawadda9248c2020-11-09 17:27:36 -0800415 const sk_sp<Bitmap>& bitmap,
416 SkRect dst,
417 SkCanvas::Lattice lattice,
Mike Reed1b3dcfc2021-01-26 20:31:20 -0500418 SkFilterMode filter,
Nader Jawadda9248c2020-11-09 17:27:36 -0800419 SkPaint paint
420 ): dst(dst),
421 lattice(lattice),
Mike Reed1b3dcfc2021-01-26 20:31:20 -0500422 filter(filter),
Nader Jawadda9248c2020-11-09 17:27:36 -0800423 bitmap(bitmap),
424 image(bitmap->makeImage()),
425 paint(std::move(paint)) {}
426
427 SkRect dst;
428 SkCanvas::Lattice lattice;
Mike Reed1b3dcfc2021-01-26 20:31:20 -0500429 SkFilterMode filter;
Nader Jawadda9248c2020-11-09 17:27:36 -0800430 const sk_sp<Bitmap> bitmap;
431 const sk_sp<SkImage> image;
432
433 SkPaint paint;
434 void draw(SkCanvas* canvas) const {
Mike Reed1b3dcfc2021-01-26 20:31:20 -0500435 canvas->drawImageLattice(image.get(), lattice, dst, filter, &paint);
Nader Jawadda9248c2020-11-09 17:27:36 -0800436 }
437 ASSERT_DRAWABLE()
438};
439
440template<>
441struct CanvasOp<CanvasOpType::DrawPicture> {
442 sk_sp<SkPicture> picture;
443 void draw(SkCanvas* canvas) const {
444 picture->playback(canvas);
445 }
446};
447
Nader Jawad55f19762020-11-25 15:30:20 -0800448template<>
449struct CanvasOp<CanvasOpType::DrawLayer> {
450 sp<Layer> layer;
451};
452
John Reck013127b2020-10-29 20:53:51 -0400453// cleanup our macros
454#undef ASSERT_DRAWABLE
455
Nader Jawadfb1e7f12020-11-06 22:49:42 -0800456} // namespace android::uirenderer