1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2017 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "gm/gm.h" 9cb93a386Sopenharmony_ci#include "include/core/SkCanvas.h" 10cb93a386Sopenharmony_ci#include "include/core/SkColor.h" 11cb93a386Sopenharmony_ci#include "include/core/SkMatrix.h" 12cb93a386Sopenharmony_ci#include "include/core/SkPaint.h" 13cb93a386Sopenharmony_ci#include "include/core/SkPathBuilder.h" 14cb93a386Sopenharmony_ci#include "include/core/SkPoint.h" 15cb93a386Sopenharmony_ci#include "include/core/SkPoint3.h" 16cb93a386Sopenharmony_ci#include "include/core/SkRRect.h" 17cb93a386Sopenharmony_ci#include "include/core/SkRect.h" 18cb93a386Sopenharmony_ci#include "include/core/SkScalar.h" 19cb93a386Sopenharmony_ci#include "include/core/SkTypes.h" 20cb93a386Sopenharmony_ci#include "include/private/SkShadowFlags.h" 21cb93a386Sopenharmony_ci#include "include/private/SkTArray.h" 22cb93a386Sopenharmony_ci#include "include/private/SkTDArray.h" 23cb93a386Sopenharmony_ci#include "include/utils/SkShadowUtils.h" 24cb93a386Sopenharmony_ci 25cb93a386Sopenharmony_ci#include <initializer_list> 26cb93a386Sopenharmony_ci 27cb93a386Sopenharmony_civoid draw_shadow(SkCanvas* canvas, const SkPath& path, SkScalar height, SkColor color, 28cb93a386Sopenharmony_ci SkPoint3 lightPos, SkScalar lightR, bool isAmbient, uint32_t flags) { 29cb93a386Sopenharmony_ci SkScalar ambientAlpha = isAmbient ? .5f : 0.f; 30cb93a386Sopenharmony_ci SkScalar spotAlpha = isAmbient ? 0.f : .5f; 31cb93a386Sopenharmony_ci SkColor ambientColor = SkColorSetARGB(ambientAlpha*SkColorGetA(color), SkColorGetR(color), 32cb93a386Sopenharmony_ci SkColorGetG(color), SkColorGetB(color)); 33cb93a386Sopenharmony_ci SkColor spotColor = SkColorSetARGB(spotAlpha*SkColorGetA(color), SkColorGetR(color), 34cb93a386Sopenharmony_ci SkColorGetG(color), SkColorGetB(color)); 35cb93a386Sopenharmony_ci SkShadowUtils::DrawShadow(canvas, path, SkPoint3{ 0, 0, height}, lightPos, lightR, 36cb93a386Sopenharmony_ci ambientColor, spotColor, flags); 37cb93a386Sopenharmony_ci} 38cb93a386Sopenharmony_ci 39cb93a386Sopenharmony_cistatic constexpr int kW = 800; 40cb93a386Sopenharmony_cistatic constexpr int kH = 960; 41cb93a386Sopenharmony_ci 42cb93a386Sopenharmony_cienum ShadowMode { 43cb93a386Sopenharmony_ci kDebugColorNoOccluders, 44cb93a386Sopenharmony_ci kDebugColorOccluders, 45cb93a386Sopenharmony_ci kGrayscale 46cb93a386Sopenharmony_ci}; 47cb93a386Sopenharmony_ci 48cb93a386Sopenharmony_civoid draw_paths(SkCanvas* canvas, ShadowMode mode) { 49cb93a386Sopenharmony_ci SkTArray<SkPath> paths; 50cb93a386Sopenharmony_ci paths.push_back(SkPath::RRect(SkRect::MakeWH(50, 50), 10, 10.00002f)); 51cb93a386Sopenharmony_ci SkRRect oddRRect; 52cb93a386Sopenharmony_ci oddRRect.setNinePatch(SkRect::MakeWH(50, 50), 9, 13, 6, 16); 53cb93a386Sopenharmony_ci paths.push_back(SkPath::RRect(oddRRect)); 54cb93a386Sopenharmony_ci paths.push_back(SkPath::Rect(SkRect::MakeWH(50, 50))); 55cb93a386Sopenharmony_ci paths.push_back(SkPath::Circle(25, 25, 25)); 56cb93a386Sopenharmony_ci paths.push_back(SkPathBuilder().cubicTo(100, 50, 20, 100, 0, 0).detach()); 57cb93a386Sopenharmony_ci paths.push_back(SkPath::Oval(SkRect::MakeWH(20, 60))); 58cb93a386Sopenharmony_ci 59cb93a386Sopenharmony_ci // star 60cb93a386Sopenharmony_ci SkTArray<SkPath> concavePaths; 61cb93a386Sopenharmony_ci concavePaths.push_back().moveTo(0.0f, -33.3333f); 62cb93a386Sopenharmony_ci concavePaths.back().lineTo(9.62f, -16.6667f); 63cb93a386Sopenharmony_ci concavePaths.back().lineTo(28.867f, -16.6667f); 64cb93a386Sopenharmony_ci concavePaths.back().lineTo(19.24f, 0.0f); 65cb93a386Sopenharmony_ci concavePaths.back().lineTo(28.867f, 16.6667f); 66cb93a386Sopenharmony_ci concavePaths.back().lineTo(9.62f, 16.6667f); 67cb93a386Sopenharmony_ci concavePaths.back().lineTo(0.0f, 33.3333f); 68cb93a386Sopenharmony_ci concavePaths.back().lineTo(-9.62f, 16.6667f); 69cb93a386Sopenharmony_ci concavePaths.back().lineTo(-28.867f, 16.6667f); 70cb93a386Sopenharmony_ci concavePaths.back().lineTo(-19.24f, 0.0f); 71cb93a386Sopenharmony_ci concavePaths.back().lineTo(-28.867f, -16.6667f); 72cb93a386Sopenharmony_ci concavePaths.back().lineTo(-9.62f, -16.6667f); 73cb93a386Sopenharmony_ci concavePaths.back().close(); 74cb93a386Sopenharmony_ci 75cb93a386Sopenharmony_ci // dumbbell 76cb93a386Sopenharmony_ci concavePaths.push_back().moveTo(50, 0); 77cb93a386Sopenharmony_ci concavePaths.back().cubicTo(100, 25, 60, 50, 50, 0); 78cb93a386Sopenharmony_ci concavePaths.back().cubicTo(0, -25, 40, -50, 50, 0); 79cb93a386Sopenharmony_ci 80cb93a386Sopenharmony_ci static constexpr SkScalar kPad = 15.f; 81cb93a386Sopenharmony_ci static constexpr SkScalar kLightR = 100.f; 82cb93a386Sopenharmony_ci static constexpr SkScalar kHeight = 50.f; 83cb93a386Sopenharmony_ci 84cb93a386Sopenharmony_ci // transform light position relative to canvas to handle tiling 85cb93a386Sopenharmony_ci SkPoint lightXY = canvas->getTotalMatrix().mapXY(250, 400); 86cb93a386Sopenharmony_ci SkPoint3 lightPos = { lightXY.fX, lightXY.fY, 500 }; 87cb93a386Sopenharmony_ci 88cb93a386Sopenharmony_ci canvas->translate(3 * kPad, 3 * kPad); 89cb93a386Sopenharmony_ci canvas->save(); 90cb93a386Sopenharmony_ci SkScalar x = 0; 91cb93a386Sopenharmony_ci SkScalar dy = 0; 92cb93a386Sopenharmony_ci SkTDArray<SkMatrix> matrices; 93cb93a386Sopenharmony_ci matrices.push()->reset(); 94cb93a386Sopenharmony_ci matrices.push()->setRotate(33.f, 25.f, 25.f).postScale(1.2f, 0.8f, 25.f, 25.f); 95cb93a386Sopenharmony_ci for (auto& m : matrices) { 96cb93a386Sopenharmony_ci for (int flags : { kNone_ShadowFlag, kTransparentOccluder_ShadowFlag }) { 97cb93a386Sopenharmony_ci int pathCounter = 0; 98cb93a386Sopenharmony_ci for (const auto& path : paths) { 99cb93a386Sopenharmony_ci SkRect postMBounds = path.getBounds(); 100cb93a386Sopenharmony_ci m.mapRect(&postMBounds); 101cb93a386Sopenharmony_ci SkScalar w = postMBounds.width() + kHeight; 102cb93a386Sopenharmony_ci SkScalar dx = w + kPad; 103cb93a386Sopenharmony_ci if (x + dx > kW - 3 * kPad) { 104cb93a386Sopenharmony_ci canvas->restore(); 105cb93a386Sopenharmony_ci canvas->translate(0, dy); 106cb93a386Sopenharmony_ci canvas->save(); 107cb93a386Sopenharmony_ci x = 0; 108cb93a386Sopenharmony_ci dy = 0; 109cb93a386Sopenharmony_ci } 110cb93a386Sopenharmony_ci 111cb93a386Sopenharmony_ci canvas->save(); 112cb93a386Sopenharmony_ci canvas->concat(m); 113cb93a386Sopenharmony_ci 114cb93a386Sopenharmony_ci // flip a couple of paths to test 180° rotation 115cb93a386Sopenharmony_ci if (kTransparentOccluder_ShadowFlag == flags && 0 == pathCounter % 3) { 116cb93a386Sopenharmony_ci canvas->save(); 117cb93a386Sopenharmony_ci canvas->rotate(180, 25, 25); 118cb93a386Sopenharmony_ci } 119cb93a386Sopenharmony_ci if (kDebugColorNoOccluders == mode || kDebugColorOccluders == mode) { 120cb93a386Sopenharmony_ci draw_shadow(canvas, path, kHeight, SK_ColorRED, lightPos, kLightR, 121cb93a386Sopenharmony_ci true, flags); 122cb93a386Sopenharmony_ci draw_shadow(canvas, path, kHeight, SK_ColorBLUE, lightPos, kLightR, 123cb93a386Sopenharmony_ci false, flags); 124cb93a386Sopenharmony_ci } else if (kGrayscale == mode) { 125cb93a386Sopenharmony_ci SkColor ambientColor = SkColorSetARGB(0.1f * 255, 0, 0, 0); 126cb93a386Sopenharmony_ci SkColor spotColor = SkColorSetARGB(0.25f * 255, 0, 0, 0); 127cb93a386Sopenharmony_ci SkShadowUtils::DrawShadow(canvas, path, SkPoint3{0, 0, kHeight}, lightPos, 128cb93a386Sopenharmony_ci kLightR, ambientColor, spotColor, flags); 129cb93a386Sopenharmony_ci } 130cb93a386Sopenharmony_ci 131cb93a386Sopenharmony_ci SkPaint paint; 132cb93a386Sopenharmony_ci paint.setAntiAlias(true); 133cb93a386Sopenharmony_ci if (kDebugColorNoOccluders == mode) { 134cb93a386Sopenharmony_ci // Draw the path outline in green on top of the ambient and spot shadows. 135cb93a386Sopenharmony_ci if (SkToBool(flags & kTransparentOccluder_ShadowFlag)) { 136cb93a386Sopenharmony_ci paint.setColor(SK_ColorCYAN); 137cb93a386Sopenharmony_ci } else { 138cb93a386Sopenharmony_ci paint.setColor(SK_ColorGREEN); 139cb93a386Sopenharmony_ci } 140cb93a386Sopenharmony_ci paint.setStyle(SkPaint::kStroke_Style); 141cb93a386Sopenharmony_ci paint.setStrokeWidth(0); 142cb93a386Sopenharmony_ci } else { 143cb93a386Sopenharmony_ci paint.setColor(kDebugColorOccluders == mode ? SK_ColorLTGRAY : SK_ColorWHITE); 144cb93a386Sopenharmony_ci if (SkToBool(flags & kTransparentOccluder_ShadowFlag)) { 145cb93a386Sopenharmony_ci paint.setAlphaf(0.5f); 146cb93a386Sopenharmony_ci } 147cb93a386Sopenharmony_ci paint.setStyle(SkPaint::kFill_Style); 148cb93a386Sopenharmony_ci } 149cb93a386Sopenharmony_ci canvas->drawPath(path, paint); 150cb93a386Sopenharmony_ci if (kTransparentOccluder_ShadowFlag == flags && 0 == pathCounter % 3) { 151cb93a386Sopenharmony_ci canvas->restore(); 152cb93a386Sopenharmony_ci } 153cb93a386Sopenharmony_ci canvas->restore(); 154cb93a386Sopenharmony_ci 155cb93a386Sopenharmony_ci canvas->translate(dx, 0); 156cb93a386Sopenharmony_ci x += dx; 157cb93a386Sopenharmony_ci dy = std::max(dy, postMBounds.height() + kPad + kHeight); 158cb93a386Sopenharmony_ci ++pathCounter; 159cb93a386Sopenharmony_ci } 160cb93a386Sopenharmony_ci } 161cb93a386Sopenharmony_ci } 162cb93a386Sopenharmony_ci 163cb93a386Sopenharmony_ci // concave paths 164cb93a386Sopenharmony_ci canvas->restore(); 165cb93a386Sopenharmony_ci canvas->translate(kPad, dy); 166cb93a386Sopenharmony_ci canvas->save(); 167cb93a386Sopenharmony_ci x = kPad; 168cb93a386Sopenharmony_ci dy = 0; 169cb93a386Sopenharmony_ci for (auto& m : matrices) { 170cb93a386Sopenharmony_ci // for the concave paths we are not clipping, so transparent and opaque are the same 171cb93a386Sopenharmony_ci for (const auto& path : concavePaths) { 172cb93a386Sopenharmony_ci SkRect postMBounds = path.getBounds(); 173cb93a386Sopenharmony_ci m.mapRect(&postMBounds); 174cb93a386Sopenharmony_ci SkScalar w = postMBounds.width() + kHeight; 175cb93a386Sopenharmony_ci SkScalar dx = w + kPad; 176cb93a386Sopenharmony_ci 177cb93a386Sopenharmony_ci canvas->save(); 178cb93a386Sopenharmony_ci canvas->concat(m); 179cb93a386Sopenharmony_ci 180cb93a386Sopenharmony_ci if (kDebugColorNoOccluders == mode || kDebugColorOccluders == mode) { 181cb93a386Sopenharmony_ci draw_shadow(canvas, path, kHeight, SK_ColorRED, lightPos, kLightR, 182cb93a386Sopenharmony_ci true, kNone_ShadowFlag); 183cb93a386Sopenharmony_ci draw_shadow(canvas, path, kHeight, SK_ColorBLUE, lightPos, kLightR, 184cb93a386Sopenharmony_ci false, kNone_ShadowFlag); 185cb93a386Sopenharmony_ci } else if (kGrayscale == mode) { 186cb93a386Sopenharmony_ci SkColor ambientColor = SkColorSetARGB(0.1f * 255, 0, 0, 0); 187cb93a386Sopenharmony_ci SkColor spotColor = SkColorSetARGB(0.25f * 255, 0, 0, 0); 188cb93a386Sopenharmony_ci SkShadowUtils::DrawShadow(canvas, path, SkPoint3{ 0, 0, kHeight }, lightPos, 189cb93a386Sopenharmony_ci kLightR, ambientColor, spotColor, kNone_ShadowFlag); 190cb93a386Sopenharmony_ci } 191cb93a386Sopenharmony_ci 192cb93a386Sopenharmony_ci SkPaint paint; 193cb93a386Sopenharmony_ci paint.setAntiAlias(true); 194cb93a386Sopenharmony_ci if (kDebugColorNoOccluders == mode) { 195cb93a386Sopenharmony_ci // Draw the path outline in green on top of the ambient and spot shadows. 196cb93a386Sopenharmony_ci paint.setColor(SK_ColorGREEN); 197cb93a386Sopenharmony_ci paint.setStyle(SkPaint::kStroke_Style); 198cb93a386Sopenharmony_ci paint.setStrokeWidth(0); 199cb93a386Sopenharmony_ci } else { 200cb93a386Sopenharmony_ci paint.setColor(kDebugColorOccluders == mode ? SK_ColorLTGRAY : SK_ColorWHITE); 201cb93a386Sopenharmony_ci paint.setStyle(SkPaint::kFill_Style); 202cb93a386Sopenharmony_ci } 203cb93a386Sopenharmony_ci canvas->drawPath(path, paint); 204cb93a386Sopenharmony_ci canvas->restore(); 205cb93a386Sopenharmony_ci 206cb93a386Sopenharmony_ci canvas->translate(dx, 0); 207cb93a386Sopenharmony_ci x += dx; 208cb93a386Sopenharmony_ci dy = std::max(dy, postMBounds.height() + kPad + kHeight); 209cb93a386Sopenharmony_ci } 210cb93a386Sopenharmony_ci } 211cb93a386Sopenharmony_ci 212cb93a386Sopenharmony_ci // Show where the light is in x,y as a circle (specified in device space). 213cb93a386Sopenharmony_ci SkMatrix invCanvasM = canvas->getTotalMatrix(); 214cb93a386Sopenharmony_ci if (invCanvasM.invert(&invCanvasM)) { 215cb93a386Sopenharmony_ci canvas->save(); 216cb93a386Sopenharmony_ci canvas->concat(invCanvasM); 217cb93a386Sopenharmony_ci SkPaint paint; 218cb93a386Sopenharmony_ci paint.setColor(SK_ColorBLACK); 219cb93a386Sopenharmony_ci paint.setAntiAlias(true); 220cb93a386Sopenharmony_ci canvas->drawCircle(lightPos.fX, lightPos.fY, kLightR / 10.f, paint); 221cb93a386Sopenharmony_ci canvas->restore(); 222cb93a386Sopenharmony_ci } 223cb93a386Sopenharmony_ci} 224cb93a386Sopenharmony_ci 225cb93a386Sopenharmony_ciDEF_SIMPLE_GM(shadow_utils, canvas, kW, kH) { 226cb93a386Sopenharmony_ci draw_paths(canvas, kDebugColorNoOccluders); 227cb93a386Sopenharmony_ci} 228cb93a386Sopenharmony_ci 229cb93a386Sopenharmony_ciDEF_SIMPLE_GM(shadow_utils_occl, canvas, kW, kH) { 230cb93a386Sopenharmony_ci draw_paths(canvas, kDebugColorOccluders); 231cb93a386Sopenharmony_ci} 232cb93a386Sopenharmony_ci 233cb93a386Sopenharmony_ciDEF_SIMPLE_GM(shadow_utils_gray, canvas, kW, kH) { 234cb93a386Sopenharmony_ci draw_paths(canvas, kGrayscale); 235cb93a386Sopenharmony_ci} 236cb93a386Sopenharmony_ci 237cb93a386Sopenharmony_ci#include "include/effects/SkGradientShader.h" 238cb93a386Sopenharmony_ci#include "src/core/SkColorFilterPriv.h" 239cb93a386Sopenharmony_ci 240cb93a386Sopenharmony_ciDEF_SIMPLE_GM(shadow_utils_gaussian_colorfilter, canvas, 512, 256) { 241cb93a386Sopenharmony_ci const SkRect r = SkRect::MakeWH(256, 256); 242cb93a386Sopenharmony_ci 243cb93a386Sopenharmony_ci const SkColor colors[] = { 0, 0xFF000000 }; 244cb93a386Sopenharmony_ci auto sh = SkGradientShader::MakeRadial({r.centerX(), r.centerY()}, r.width(), 245cb93a386Sopenharmony_ci colors, nullptr, SK_ARRAY_COUNT(colors), 246cb93a386Sopenharmony_ci SkTileMode::kClamp); 247cb93a386Sopenharmony_ci 248cb93a386Sopenharmony_ci SkPaint redPaint; 249cb93a386Sopenharmony_ci redPaint.setColor(SK_ColorRED); 250cb93a386Sopenharmony_ci 251cb93a386Sopenharmony_ci SkPaint paint; 252cb93a386Sopenharmony_ci paint.setShader(sh); 253cb93a386Sopenharmony_ci canvas->drawRect(r, redPaint); 254cb93a386Sopenharmony_ci canvas->drawRect(r, paint); 255cb93a386Sopenharmony_ci 256cb93a386Sopenharmony_ci canvas->translate(256, 0); 257cb93a386Sopenharmony_ci paint.setColorFilter(SkColorFilterPriv::MakeGaussian()); 258cb93a386Sopenharmony_ci canvas->drawRect(r, redPaint); 259cb93a386Sopenharmony_ci canvas->drawRect(r, paint); 260cb93a386Sopenharmony_ci} 261cb93a386Sopenharmony_ci 262cb93a386Sopenharmony_ciDEF_SIMPLE_GM(shadow_utils_directional, canvas, 256, 384) { 263cb93a386Sopenharmony_ci static constexpr SkScalar kLightR = 1.f; 264cb93a386Sopenharmony_ci static constexpr SkScalar kHeight = 12.f; 265cb93a386Sopenharmony_ci 266cb93a386Sopenharmony_ci SkPath rrect(SkPath::RRect(SkRect::MakeLTRB(-25, -25, 25, 25), 10, 10)); 267cb93a386Sopenharmony_ci SkPoint3 lightPos = { -45, -45, 77.9422863406f }; 268cb93a386Sopenharmony_ci 269cb93a386Sopenharmony_ci SkColor ambientColor = SkColorSetARGB(0.02f * 255, 0, 0, 0); 270cb93a386Sopenharmony_ci SkColor spotColor = SkColorSetARGB(0.35f * 255, 0, 0, 0); 271cb93a386Sopenharmony_ci 272cb93a386Sopenharmony_ci SkPaint paint; 273cb93a386Sopenharmony_ci paint.setAntiAlias(true); 274cb93a386Sopenharmony_ci paint.setColor(SK_ColorWHITE); 275cb93a386Sopenharmony_ci paint.setStyle(SkPaint::kFill_Style); 276cb93a386Sopenharmony_ci 277cb93a386Sopenharmony_ci // translation 278cb93a386Sopenharmony_ci canvas->save(); 279cb93a386Sopenharmony_ci canvas->translate(35, 35); 280cb93a386Sopenharmony_ci for (int i = 0; i < 3; ++i) { 281cb93a386Sopenharmony_ci SkShadowUtils::DrawShadow(canvas, rrect, SkPoint3{ 0, 0, kHeight }, lightPos, 282cb93a386Sopenharmony_ci kLightR, ambientColor, spotColor, 283cb93a386Sopenharmony_ci kDirectionalLight_ShadowFlag); 284cb93a386Sopenharmony_ci canvas->drawPath(rrect, paint); 285cb93a386Sopenharmony_ci canvas->translate(80, 0); 286cb93a386Sopenharmony_ci } 287cb93a386Sopenharmony_ci canvas->restore(); 288cb93a386Sopenharmony_ci 289cb93a386Sopenharmony_ci // rotation 290cb93a386Sopenharmony_ci for (int i = 0; i < 3; ++i) { 291cb93a386Sopenharmony_ci canvas->save(); 292cb93a386Sopenharmony_ci canvas->translate(35 + 80*i, 105); 293cb93a386Sopenharmony_ci canvas->rotate(20.f*(i + 1)); 294cb93a386Sopenharmony_ci SkShadowUtils::DrawShadow(canvas, rrect, SkPoint3{ 0, 0, kHeight }, lightPos, 295cb93a386Sopenharmony_ci kLightR, ambientColor, spotColor, 296cb93a386Sopenharmony_ci kDirectionalLight_ShadowFlag); 297cb93a386Sopenharmony_ci 298cb93a386Sopenharmony_ci canvas->drawPath(rrect, paint); 299cb93a386Sopenharmony_ci canvas->restore(); 300cb93a386Sopenharmony_ci } 301cb93a386Sopenharmony_ci 302cb93a386Sopenharmony_ci // scale 303cb93a386Sopenharmony_ci for (int i = 0; i < 3; ++i) { 304cb93a386Sopenharmony_ci canvas->save(); 305cb93a386Sopenharmony_ci SkScalar scaleFactor = sk_float_pow(2.0, -i); 306cb93a386Sopenharmony_ci canvas->translate(35 + 80*i, 185); 307cb93a386Sopenharmony_ci canvas->scale(scaleFactor, scaleFactor); 308cb93a386Sopenharmony_ci SkShadowUtils::DrawShadow(canvas, rrect, SkPoint3{ 0, 0, kHeight }, lightPos, 309cb93a386Sopenharmony_ci kLightR, ambientColor, spotColor, 310cb93a386Sopenharmony_ci kDirectionalLight_ShadowFlag); 311cb93a386Sopenharmony_ci 312cb93a386Sopenharmony_ci canvas->drawPath(rrect, paint); 313cb93a386Sopenharmony_ci canvas->restore(); 314cb93a386Sopenharmony_ci } 315cb93a386Sopenharmony_ci 316cb93a386Sopenharmony_ci // perspective 317cb93a386Sopenharmony_ci for (int i = 0; i < 3; ++i) { 318cb93a386Sopenharmony_ci canvas->save(); 319cb93a386Sopenharmony_ci SkMatrix mat; 320cb93a386Sopenharmony_ci mat.reset(); 321cb93a386Sopenharmony_ci mat[SkMatrix::kMPersp1] = 0.005f; 322cb93a386Sopenharmony_ci mat[SkMatrix::kMPersp2] = 1.005f; 323cb93a386Sopenharmony_ci canvas->translate(35 + 80*i, 265); 324cb93a386Sopenharmony_ci canvas->concat(mat); 325cb93a386Sopenharmony_ci SkShadowUtils::DrawShadow(canvas, rrect, SkPoint3{ 0, 0, kHeight }, lightPos, 326cb93a386Sopenharmony_ci kLightR, ambientColor, spotColor, 327cb93a386Sopenharmony_ci kDirectionalLight_ShadowFlag); 328cb93a386Sopenharmony_ci 329cb93a386Sopenharmony_ci canvas->drawPath(rrect, paint); 330cb93a386Sopenharmony_ci canvas->restore(); 331cb93a386Sopenharmony_ci } 332cb93a386Sopenharmony_ci 333cb93a386Sopenharmony_ci} 334