1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "skia_shader_effect.h"
17
18 #include <vector>
19
20 #include "include/core/SkMatrix.h"
21 #include "include/core/SkTileMode.h"
22 #include "include/effects/SkGradientShader.h"
23 #if defined(USE_CANVASKIT0310_SKIA)
24 #include "include/core/SkSamplingOptions.h"
25 #endif
26
27 #include "skia_image.h"
28 #include "skia_matrix.h"
29 #include "skia_picture.h"
30
31 #include "effect/shader_effect.h"
32 #include "image/image.h"
33 #include "image/picture.h"
34 #include "utils/matrix.h"
35
36 namespace OHOS {
37 namespace Rosen {
38 namespace Drawing {
SkiaShaderEffect()39 SkiaShaderEffect::SkiaShaderEffect() noexcept : shader_(nullptr) {}
40
InitWithColor(ColorQuad color)41 void SkiaShaderEffect::InitWithColor(ColorQuad color)
42 {
43 shader_ = SkShaders::Color(color);
44 }
45
InitWithBlend(const ShaderEffect & s1,const ShaderEffect & s2,BlendMode mode)46 void SkiaShaderEffect::InitWithBlend(const ShaderEffect& s1, const ShaderEffect& s2, BlendMode mode)
47 {
48 auto dst = s1.GetImpl<SkiaShaderEffect>();
49 auto src = s2.GetImpl<SkiaShaderEffect>();
50 if (dst != nullptr && src != nullptr) {
51 shader_ = SkShaders::Blend(static_cast<SkBlendMode>(mode), dst->GetShader(), src->GetShader());
52 }
53 }
54
InitWithImage(const Image & image,TileMode tileX,TileMode tileY,const SamplingOptions & sampling,const Matrix & matrix)55 void SkiaShaderEffect::InitWithImage(
56 const Image& image, TileMode tileX, TileMode tileY, const SamplingOptions& sampling, const Matrix& matrix)
57 {
58 SkTileMode modeX = static_cast<SkTileMode>(tileX);
59 SkTileMode modeY = static_cast<SkTileMode>(tileY);
60
61 auto m = matrix.GetImpl<SkiaMatrix>();
62 auto i = image.GetImpl<SkiaImage>();
63 SkMatrix skiaMatrix;
64 sk_sp<SkImage> skiaImage;
65 if (m != nullptr && i != nullptr) {
66 skiaMatrix = m->ExportSkiaMatrix();
67 skiaImage = i->GetImage();
68 if (skiaImage != nullptr) {
69 #if defined(USE_CANVASKIT0310_SKIA)
70 SkSamplingOptions samplingOptions;
71 if (sampling.GetUseCubic()) {
72 samplingOptions = SkSamplingOptions({ sampling.GetCubicCoffB(), sampling.GetCubicCoffC() });
73 } else {
74 samplingOptions = SkSamplingOptions(static_cast<SkFilterMode>(sampling.GetFilterMode()),
75 static_cast<SkMipmapMode>(sampling.GetMipmapMode()));
76 }
77 shader_ = skiaImage->makeShader(modeX, modeY, samplingOptions, &skiaMatrix);
78 #else
79 shader_ = skiaImage->makeShader(modeX, modeY, &skiaMatrix);
80 #endif
81 }
82 }
83 }
84
InitWithPicture(const Picture & picture,TileMode tileX,TileMode tileY,FilterMode mode,const Matrix & matrix,const Rect & rect)85 void SkiaShaderEffect::InitWithPicture(
86 const Picture& picture, TileMode tileX, TileMode tileY, FilterMode mode, const Matrix& matrix, const Rect& rect)
87 {
88 SkTileMode modeX = static_cast<SkTileMode>(tileX);
89 SkTileMode modeY = static_cast<SkTileMode>(tileY);
90 SkRect r = SkRect::MakeLTRB(rect.GetLeft(), rect.GetTop(), rect.GetRight(), rect.GetBottom());
91
92 auto p = picture.GetImpl<SkiaPicture>();
93 auto m = matrix.GetImpl<SkiaMatrix>();
94 sk_sp<SkPicture> skiaPicture;
95 SkMatrix skiaMatrix;
96 if (p != nullptr && m != nullptr) {
97 skiaPicture = p->GetPicture();
98 skiaMatrix = m->ExportSkiaMatrix();
99 if (skiaPicture != nullptr) {
100 #if defined(USE_CANVASKIT0310_SKIA)
101 SkFilterMode m = static_cast<SkFilterMode>(mode);
102 shader_ = skiaPicture->makeShader(modeX, modeY, m, &skiaMatrix, &r);
103 #else
104 shader_ = skiaPicture->makeShader(modeX, modeY, &skiaMatrix, &r);
105 #endif
106 }
107 }
108 }
109
InitWithLinearGradient(const Point & startPt,const Point & endPt,const std::vector<ColorQuad> & colors,const std::vector<scalar> & pos,TileMode mode)110 void SkiaShaderEffect::InitWithLinearGradient(const Point& startPt, const Point& endPt,
111 const std::vector<ColorQuad>& colors, const std::vector<scalar>& pos, TileMode mode)
112 {
113 SkPoint pts[2];
114 pts[0].set(startPt.GetX(), startPt.GetY());
115 pts[1].set(endPt.GetX(), endPt.GetY());
116
117 size_t count = (colors.size() == pos.size()) ? colors.size() : 0;
118 if (count == 0) {
119 return;
120 }
121 std::vector<SkColor> c;
122 std::vector<SkScalar> p;
123 for (size_t i = 0; i < count; ++i) {
124 c.emplace_back(colors[i]);
125 p.emplace_back(pos[i]);
126 }
127 shader_ = SkGradientShader::MakeLinear(pts, &c[0], &p[0], count, static_cast<SkTileMode>(mode));
128 }
129
InitWithRadialGradient(const Point & centerPt,scalar radius,const std::vector<ColorQuad> & colors,const std::vector<scalar> & pos,TileMode mode)130 void SkiaShaderEffect::InitWithRadialGradient(const Point& centerPt, scalar radius,
131 const std::vector<ColorQuad>& colors, const std::vector<scalar>& pos, TileMode mode)
132 {
133 SkPoint center;
134 center.set(centerPt.GetX(), centerPt.GetY());
135
136 size_t count = (colors.size() == pos.size()) ? colors.size() : 0;
137 if (count == 0) {
138 return;
139 }
140 std::vector<SkColor> c;
141 std::vector<SkScalar> p;
142 for (size_t i = 0; i < count; ++i) {
143 c.emplace_back(colors[i]);
144 p.emplace_back(pos[i]);
145 }
146 shader_ = SkGradientShader::MakeRadial(center, radius, &c[0], &p[0], count, static_cast<SkTileMode>(mode));
147 }
148
InitWithTwoPointConical(const Point & startPt,scalar startRadius,const Point & endPt,scalar endRadius,const std::vector<ColorQuad> & colors,const std::vector<scalar> & pos,TileMode mode)149 void SkiaShaderEffect::InitWithTwoPointConical(const Point& startPt, scalar startRadius, const Point& endPt,
150 scalar endRadius, const std::vector<ColorQuad>& colors, const std::vector<scalar>& pos, TileMode mode)
151 {
152 SkPoint start;
153 SkPoint end;
154 start.set(startPt.GetX(), startPt.GetY());
155 end.set(endPt.GetX(), endPt.GetY());
156
157 size_t count = (colors.size() == pos.size()) ? colors.size() : 0;
158 if (count == 0) {
159 return;
160 }
161 std::vector<SkColor> c;
162 std::vector<SkScalar> p;
163 for (size_t i = 0; i < count; ++i) {
164 c.emplace_back(colors[i]);
165 p.emplace_back(pos[i]);
166 }
167 shader_ = SkGradientShader::MakeTwoPointConical(
168 start, startRadius, end, endRadius, &c[0], &p[0], count, static_cast<SkTileMode>(mode));
169 }
170
InitWithSweepGradient(const Point & centerPt,const std::vector<ColorQuad> & colors,const std::vector<scalar> & pos,TileMode mode,scalar startAngle,scalar endAngle)171 void SkiaShaderEffect::InitWithSweepGradient(const Point& centerPt, const std::vector<ColorQuad>& colors,
172 const std::vector<scalar>& pos, TileMode mode, scalar startAngle, scalar endAngle)
173 {
174 size_t count = (colors.size() == pos.size()) ? colors.size() : 0;
175 if (count == 0) {
176 return;
177 }
178 std::vector<SkColor> c;
179 std::vector<SkScalar> p;
180 for (size_t i = 0; i < count; ++i) {
181 c.emplace_back(colors[i]);
182 p.emplace_back(pos[i]);
183 }
184 shader_ = SkGradientShader::MakeSweep(centerPt.GetX(), centerPt.GetY(), &c[0], &p[0], count,
185 static_cast<SkTileMode>(mode), startAngle, endAngle, 0, nullptr);
186 }
187
GetShader() const188 sk_sp<SkShader> SkiaShaderEffect::GetShader() const
189 {
190 return shader_;
191 }
192 } // namespace Drawing
193 } // namespace Rosen
194 } // namespace OHOS