1 /* 2 * Copyright (C) 2016 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 <SkCanvas.h> 20 #include <SkDrawable.h> 21 #include <SkRuntimeEffect.h> 22 #include <math.h> 23 #include <utils/RefBase.h> 24 #include "CanvasProperty.h" 25 #include "CanvasTransform.h" 26 27 namespace android { 28 namespace uirenderer { 29 namespace skiapipeline { 30 31 class AnimatedRoundRect : public SkDrawable { 32 public: AnimatedRoundRect(uirenderer::CanvasPropertyPrimitive * left,uirenderer::CanvasPropertyPrimitive * top,uirenderer::CanvasPropertyPrimitive * right,uirenderer::CanvasPropertyPrimitive * bottom,uirenderer::CanvasPropertyPrimitive * rx,uirenderer::CanvasPropertyPrimitive * ry,uirenderer::CanvasPropertyPaint * p)33 AnimatedRoundRect(uirenderer::CanvasPropertyPrimitive* left, 34 uirenderer::CanvasPropertyPrimitive* top, 35 uirenderer::CanvasPropertyPrimitive* right, 36 uirenderer::CanvasPropertyPrimitive* bottom, 37 uirenderer::CanvasPropertyPrimitive* rx, 38 uirenderer::CanvasPropertyPrimitive* ry, uirenderer::CanvasPropertyPaint* p) 39 : mLeft(left), mTop(top), mRight(right), mBottom(bottom), mRx(rx), mRy(ry), mPaint(p) {} 40 41 protected: onGetBounds()42 virtual SkRect onGetBounds() override { 43 return SkRect::MakeLTRB(mLeft->value, mTop->value, mRight->value, mBottom->value); 44 } onDraw(SkCanvas * canvas)45 virtual void onDraw(SkCanvas* canvas) override { 46 SkRect rect = SkRect::MakeLTRB(mLeft->value, mTop->value, mRight->value, mBottom->value); 47 canvas->drawRoundRect(rect, mRx->value, mRy->value, mPaint->value); 48 } 49 50 private: 51 sp<uirenderer::CanvasPropertyPrimitive> mLeft; 52 sp<uirenderer::CanvasPropertyPrimitive> mTop; 53 sp<uirenderer::CanvasPropertyPrimitive> mRight; 54 sp<uirenderer::CanvasPropertyPrimitive> mBottom; 55 sp<uirenderer::CanvasPropertyPrimitive> mRx; 56 sp<uirenderer::CanvasPropertyPrimitive> mRy; 57 sp<uirenderer::CanvasPropertyPaint> mPaint; 58 }; 59 60 struct RippleDrawableParams { 61 sp<uirenderer::CanvasPropertyPrimitive> x; 62 sp<uirenderer::CanvasPropertyPrimitive> y; 63 sp<uirenderer::CanvasPropertyPrimitive> radius; 64 sp<uirenderer::CanvasPropertyPrimitive> progress; 65 sp<uirenderer::CanvasPropertyPrimitive> turbulencePhase; 66 SkColor color; 67 sp<uirenderer::CanvasPropertyPaint> paint; 68 SkRuntimeShaderBuilder effectBuilder; 69 }; 70 71 class AnimatedRippleDrawable { 72 public: draw(SkCanvas * canvas,const RippleDrawableParams & params)73 static void draw(SkCanvas* canvas, const RippleDrawableParams& params) { 74 auto& effectBuilder = const_cast<SkRuntimeShaderBuilder&>(params.effectBuilder); 75 76 setUniform2f(effectBuilder, "in_origin", params.x->value, params.y->value); 77 setUniform(effectBuilder, "in_radius", params.radius); 78 setUniform(effectBuilder, "in_progress", params.progress); 79 setUniform(effectBuilder, "in_turbulencePhase", params.turbulencePhase); 80 setUniform(effectBuilder, "in_noisePhase", params.turbulencePhase->value * 0.001); 81 82 SkRuntimeShaderBuilder::BuilderUniform uniform = effectBuilder.uniform("in_color"); 83 if (uniform.fVar != nullptr) { 84 uniform = SkV4{SkColorGetR(params.color) / 255.0f, SkColorGetG(params.color) / 255.0f, 85 SkColorGetB(params.color) / 255.0f, SkColorGetA(params.color) / 255.0f}; 86 } 87 88 const float CIRCLE_X_1 = 0.01 * cos(SCALE * 0.55); 89 const float CIRCLE_Y_1 = 0.01 * sin(SCALE * 0.55); 90 const float CIRCLE_X_2 = -0.0066 * cos(SCALE * 0.45); 91 const float CIRCLE_Y_2 = -0.0066 * sin(SCALE * 0.45); 92 const float CIRCLE_X_3 = -0.0066 * cos(SCALE * 0.35); 93 const float CIRCLE_Y_3 = -0.0066 * sin(SCALE * 0.35); 94 95 // 96 // Keep in sync with: 97 // frameworks/base/graphics/java/android/graphics/drawable/RippleShader.java 98 // 99 const float turbulencePhase = params.turbulencePhase->value; 100 setUniform2f(effectBuilder, "in_tCircle1", SCALE * 0.5 + (turbulencePhase * CIRCLE_X_1), 101 SCALE * 0.5 + (turbulencePhase * CIRCLE_Y_1)); 102 setUniform2f(effectBuilder, "in_tCircle2", SCALE * 0.2 + (turbulencePhase * CIRCLE_X_2), 103 SCALE * 0.2 + (turbulencePhase * CIRCLE_Y_2)); 104 setUniform2f(effectBuilder, "in_tCircle3", SCALE + (turbulencePhase * CIRCLE_X_3), 105 SCALE + (turbulencePhase * CIRCLE_Y_3)); 106 const float rotation1 = turbulencePhase * PI_ROTATE_RIGHT + 1.7 * PI; 107 setUniform2f(effectBuilder, "in_tRotation1", cos(rotation1), sin(rotation1)); 108 const float rotation2 = turbulencePhase * PI_ROTATE_LEFT + 2 * PI; 109 setUniform2f(effectBuilder, "in_tRotation2", cos(rotation2), sin(rotation2)); 110 const float rotation3 = turbulencePhase * PI_ROTATE_RIGHT + 2.75 * PI; 111 setUniform2f(effectBuilder, "in_tRotation3", cos(rotation3), sin(rotation3)); 112 113 params.paint->value.setShader(effectBuilder.makeShader(nullptr, false)); 114 canvas->drawCircle(params.x->value, params.y->value, params.radius->value, 115 params.paint->value); 116 } 117 118 private: 119 static constexpr float PI = 3.1415926535897932384626; 120 static constexpr float PI_ROTATE_RIGHT = PI * 0.0078125; 121 static constexpr float PI_ROTATE_LEFT = PI * -0.0078125; 122 static constexpr float SCALE = 1.5; 123 setUniform(SkRuntimeShaderBuilder & effectBuilder,const char * name,sp<uirenderer::CanvasPropertyPrimitive> property)124 static void setUniform(SkRuntimeShaderBuilder& effectBuilder, const char* name, 125 sp<uirenderer::CanvasPropertyPrimitive> property) { 126 SkRuntimeShaderBuilder::BuilderUniform uniform = effectBuilder.uniform(name); 127 if (uniform.fVar != nullptr) { 128 uniform = property->value; 129 } 130 } 131 setUniform(SkRuntimeShaderBuilder & effectBuilder,const char * name,float value)132 static void setUniform(SkRuntimeShaderBuilder& effectBuilder, const char* name, float value) { 133 SkRuntimeShaderBuilder::BuilderUniform uniform = effectBuilder.uniform(name); 134 if (uniform.fVar != nullptr) { 135 uniform = value; 136 } 137 } 138 setUniform2f(SkRuntimeShaderBuilder & effectBuilder,const char * name,float a,float b)139 static void setUniform2f(SkRuntimeShaderBuilder& effectBuilder, const char* name, float a, 140 float b) { 141 SkRuntimeShaderBuilder::BuilderUniform uniform = effectBuilder.uniform(name); 142 if (uniform.fVar != nullptr) { 143 uniform = SkV2{a, b}; 144 } 145 } 146 }; 147 148 class AnimatedCircle : public SkDrawable { 149 public: AnimatedCircle(uirenderer::CanvasPropertyPrimitive * x,uirenderer::CanvasPropertyPrimitive * y,uirenderer::CanvasPropertyPrimitive * radius,uirenderer::CanvasPropertyPaint * paint)150 AnimatedCircle(uirenderer::CanvasPropertyPrimitive* x, uirenderer::CanvasPropertyPrimitive* y, 151 uirenderer::CanvasPropertyPrimitive* radius, 152 uirenderer::CanvasPropertyPaint* paint) 153 : mX(x), mY(y), mRadius(radius), mPaint(paint) {} 154 155 protected: onGetBounds()156 virtual SkRect onGetBounds() override { 157 const float x = mX->value; 158 const float y = mY->value; 159 const float radius = mRadius->value; 160 return SkRect::MakeLTRB(x - radius, y - radius, x + radius, y + radius); 161 } onDraw(SkCanvas * canvas)162 virtual void onDraw(SkCanvas* canvas) override { 163 canvas->drawCircle(mX->value, mY->value, mRadius->value, mPaint->value); 164 } 165 166 private: 167 sp<uirenderer::CanvasPropertyPrimitive> mX; 168 sp<uirenderer::CanvasPropertyPrimitive> mY; 169 sp<uirenderer::CanvasPropertyPrimitive> mRadius; 170 sp<uirenderer::CanvasPropertyPaint> mPaint; 171 }; 172 173 } // namespace skiapipeline 174 } // namespace uirenderer 175 } // namespace android 176