• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2023 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 #include "skia_helper.h"
18 
19 #include <vector>
20 
21 #include "include/core/SkMatrix.h"
22 #include "include/core/SkTileMode.h"
23 #include "include/effects/SkGradientShader.h"
24 #include "src/shaders/SkShaderBase.h"
25 #if defined(USE_CANVASKIT0310_SKIA) || defined(NEW_SKIA)
26 #include "include/core/SkSamplingOptions.h"
27 #endif
28 
29 #include "skia_image.h"
30 #include "skia_matrix.h"
31 #include "skia_picture.h"
32 
33 #include "effect/shader_effect.h"
34 #include "image/image.h"
35 #include "image/picture.h"
36 #include "utils/matrix.h"
37 #include "utils/data.h"
38 #include "utils/log.h"
39 
40 namespace OHOS {
41 namespace Rosen {
42 namespace Drawing {
SkiaShaderEffect()43 SkiaShaderEffect::SkiaShaderEffect() noexcept : shader_(nullptr) {}
44 
InitWithColor(ColorQuad color)45 void SkiaShaderEffect::InitWithColor(ColorQuad color)
46 {
47     shader_ = SkShaders::Color(color);
48 }
49 
InitWithBlend(const ShaderEffect & s1,const ShaderEffect & s2,BlendMode mode)50 void SkiaShaderEffect::InitWithBlend(const ShaderEffect& s1, const ShaderEffect& s2, BlendMode mode)
51 {
52     auto dst = s1.GetImpl<SkiaShaderEffect>();
53     auto src = s2.GetImpl<SkiaShaderEffect>();
54     if (dst != nullptr && src != nullptr) {
55         shader_ = SkShaders::Blend(static_cast<SkBlendMode>(mode), dst->GetShader(), src->GetShader());
56     }
57 }
58 
InitWithImage(const Image & image,TileMode tileX,TileMode tileY,const SamplingOptions & sampling,const Matrix & matrix)59 void SkiaShaderEffect::InitWithImage(
60     const Image& image, TileMode tileX, TileMode tileY, const SamplingOptions& sampling, const Matrix& matrix)
61 {
62     SkTileMode modeX = static_cast<SkTileMode>(tileX);
63     SkTileMode modeY = static_cast<SkTileMode>(tileY);
64 
65     auto m = matrix.GetImpl<SkiaMatrix>();
66     auto i = image.GetImpl<SkiaImage>();
67     SkMatrix skiaMatrix;
68     sk_sp<SkImage> skiaImage;
69     if (m != nullptr && i != nullptr) {
70         skiaMatrix = m->ExportSkiaMatrix();
71         skiaImage = i->GetImage();
72         if (skiaImage != nullptr) {
73 #if defined(USE_CANVASKIT0310_SKIA) || defined(NEW_SKIA)
74             SkSamplingOptions samplingOptions;
75             if (sampling.GetUseCubic()) {
76                 samplingOptions = SkSamplingOptions({ sampling.GetCubicCoffB(), sampling.GetCubicCoffC() });
77             } else {
78                 samplingOptions = SkSamplingOptions(static_cast<SkFilterMode>(sampling.GetFilterMode()),
79                     static_cast<SkMipmapMode>(sampling.GetMipmapMode()));
80             }
81             shader_ = skiaImage->makeShader(modeX, modeY, samplingOptions, &skiaMatrix);
82 #else
83             shader_ = skiaImage->makeShader(modeX, modeY, &skiaMatrix);
84 #endif
85         }
86     }
87 }
88 
InitWithPicture(const Picture & picture,TileMode tileX,TileMode tileY,FilterMode mode,const Matrix & matrix,const Rect & rect)89 void SkiaShaderEffect::InitWithPicture(
90     const Picture& picture, TileMode tileX, TileMode tileY, FilterMode mode, const Matrix& matrix, const Rect& rect)
91 {
92     SkTileMode modeX = static_cast<SkTileMode>(tileX);
93     SkTileMode modeY = static_cast<SkTileMode>(tileY);
94     SkRect r = SkRect::MakeLTRB(rect.GetLeft(), rect.GetTop(), rect.GetRight(), rect.GetBottom());
95 
96     auto p = picture.GetImpl<SkiaPicture>();
97     auto m = matrix.GetImpl<SkiaMatrix>();
98     sk_sp<SkPicture> skiaPicture;
99     SkMatrix skiaMatrix;
100     if (p != nullptr && m != nullptr) {
101         skiaPicture = p->GetPicture();
102         skiaMatrix = m->ExportSkiaMatrix();
103         if (skiaPicture != nullptr) {
104 #if defined(USE_CANVASKIT0310_SKIA) || defined(NEW_SKIA)
105             SkFilterMode skFilterMode = static_cast<SkFilterMode>(mode);
106             shader_ = skiaPicture->makeShader(modeX, modeY, skFilterMode, &skiaMatrix, &r);
107 #else
108             shader_ = skiaPicture->makeShader(modeX, modeY, &skiaMatrix, &r);
109 #endif
110         }
111     }
112 }
113 
InitWithLinearGradient(const Point & startPt,const Point & endPt,const std::vector<ColorQuad> & colors,const std::vector<scalar> & pos,TileMode mode)114 void SkiaShaderEffect::InitWithLinearGradient(const Point& startPt, const Point& endPt,
115     const std::vector<ColorQuad>& colors, const std::vector<scalar>& pos, TileMode mode)
116 {
117     SkPoint pts[2];
118     pts[0].set(startPt.GetX(), startPt.GetY());
119     pts[1].set(endPt.GetX(), endPt.GetY());
120 
121     size_t count = (colors.size() == pos.size()) ? colors.size() : 0;
122     if (count == 0) {
123         return;
124     }
125     std::vector<SkColor> c;
126     std::vector<SkScalar> p;
127     for (size_t i = 0; i < count; ++i) {
128         c.emplace_back(colors[i]);
129         p.emplace_back(pos[i]);
130     }
131     shader_ = SkGradientShader::MakeLinear(pts, &c[0], &p[0], count, static_cast<SkTileMode>(mode));
132 }
133 
InitWithRadialGradient(const Point & centerPt,scalar radius,const std::vector<ColorQuad> & colors,const std::vector<scalar> & pos,TileMode mode)134 void SkiaShaderEffect::InitWithRadialGradient(const Point& centerPt, scalar radius,
135     const std::vector<ColorQuad>& colors, const std::vector<scalar>& pos, TileMode mode)
136 {
137     SkPoint center;
138     center.set(centerPt.GetX(), centerPt.GetY());
139 
140     size_t count = (colors.size() == pos.size()) ? colors.size() : 0;
141     if (count == 0) {
142         return;
143     }
144     std::vector<SkColor> c;
145     std::vector<SkScalar> p;
146     for (size_t i = 0; i < count; ++i) {
147         c.emplace_back(colors[i]);
148         p.emplace_back(pos[i]);
149     }
150     shader_ = SkGradientShader::MakeRadial(center, radius, &c[0], &p[0], count, static_cast<SkTileMode>(mode));
151 }
152 
InitWithTwoPointConical(const Point & startPt,scalar startRadius,const Point & endPt,scalar endRadius,const std::vector<ColorQuad> & colors,const std::vector<scalar> & pos,TileMode mode,const Matrix * matrix)153 void SkiaShaderEffect::InitWithTwoPointConical(const Point& startPt, scalar startRadius, const Point& endPt,
154     scalar endRadius, const std::vector<ColorQuad>& colors, const std::vector<scalar>& pos, TileMode mode,
155     const Matrix *matrix)
156 {
157     SkPoint start;
158     SkPoint end;
159     start.set(startPt.GetX(), startPt.GetY());
160     end.set(endPt.GetX(), endPt.GetY());
161 
162     size_t count = (colors.size() == pos.size()) ? colors.size() : 0;
163     if (count == 0) {
164         return;
165     }
166     std::vector<SkColor> c;
167     std::vector<SkScalar> p;
168     for (size_t i = 0; i < count; ++i) {
169         c.emplace_back(colors[i]);
170         p.emplace_back(pos[i]);
171     }
172     const SkMatrix *skMatrix = nullptr;
173     if (matrix != nullptr) {
174         skMatrix = &matrix->GetImpl<SkiaMatrix>()->ExportSkiaMatrix();
175     }
176 
177     shader_ = SkGradientShader::MakeTwoPointConical(
178         start, startRadius, end, endRadius, &c[0], &p[0], count, static_cast<SkTileMode>(mode), 0, skMatrix);
179 }
180 
InitWithSweepGradient(const Point & centerPt,const std::vector<ColorQuad> & colors,const std::vector<scalar> & pos,TileMode mode,scalar startAngle,scalar endAngle,const Matrix * matrix)181 void SkiaShaderEffect::InitWithSweepGradient(const Point& centerPt, const std::vector<ColorQuad>& colors,
182     const std::vector<scalar>& pos, TileMode mode, scalar startAngle, scalar endAngle, const Matrix *matrix)
183 {
184     size_t count = (colors.size() == pos.size()) ? colors.size() : 0;
185     if (count == 0) {
186         return;
187     }
188     std::vector<SkColor> c;
189     std::vector<SkScalar> p;
190     for (size_t i = 0; i < count; ++i) {
191         c.emplace_back(colors[i]);
192         p.emplace_back(pos[i]);
193     }
194     const SkMatrix *skMatrix = nullptr;
195     if (matrix != nullptr) {
196         skMatrix = &matrix->GetImpl<SkiaMatrix>()->ExportSkiaMatrix();
197     }
198     shader_ = SkGradientShader::MakeSweep(centerPt.GetX(), centerPt.GetY(), &c[0], &p[0], count,
199         static_cast<SkTileMode>(mode), startAngle, endAngle, 0, skMatrix);
200 }
201 
GetShader() const202 sk_sp<SkShader> SkiaShaderEffect::GetShader() const
203 {
204     return shader_;
205 }
206 
SetSkShader(const sk_sp<SkShader> & skShader)207 void SkiaShaderEffect::SetSkShader(const sk_sp<SkShader>& skShader)
208 {
209     shader_ = skShader;
210 }
211 
Serialize() const212 std::shared_ptr<Data> SkiaShaderEffect::Serialize() const
213 {
214     if (shader_ == nullptr) {
215         LOGD("SkiaShaderEffect::Serialize, shader_ is nullptr!");
216         return nullptr;
217     }
218 
219     return SkiaHelper::FlattenableSerialize(shader_.get());
220 }
221 
Deserialize(std::shared_ptr<Data> data)222 bool SkiaShaderEffect::Deserialize(std::shared_ptr<Data> data)
223 {
224     if (data == nullptr) {
225         LOGD("SkiaShaderEffect::Deserialize, data is invalid!");
226         return false;
227     }
228 
229     shader_ = SkiaHelper::FlattenableDeserialize<SkShaderBase>(data);
230     return true;
231 }
232 
233 } // namespace Drawing
234 } // namespace Rosen
235 } // namespace OHOS