1 /*
2  * Copyright (c) 2022 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 "render/rs_mask.h"
17 
18 #include "include/core/SkPictureRecorder.h"
19 #include "recording/recording_handle.h"
20 #include "draw/pen.h"
21 
22 #include "recording/mask_cmd_list.h"
23 #include "recording/cmd_list_helper.h"
24 #include "effect/shader_effect.h"
25 #include "platform/common/rs_log.h"
26 #include "render/rs_pixel_map_util.h"
27 
28 namespace OHOS {
29 namespace Rosen {
CreateGradientMask(const Drawing::Brush & maskBrush)30 std::shared_ptr<RSMask> RSMask::CreateGradientMask(const Drawing::Brush& maskBrush)
31 {
32     auto mask = std::make_shared<RSMask>();
33     if (mask) {
34         mask->SetMaskBrush(maskBrush);
35         mask->SetMaskType(MaskType::GRADIENT);
36     }
37     return mask;
38 }
39 
CreatePathMask(const Drawing::Path & maskPath,const Drawing::Brush & maskBrush)40 std::shared_ptr<RSMask> RSMask::CreatePathMask(const Drawing::Path& maskPath, const Drawing::Brush& maskBrush)
41 {
42     auto mask = std::make_shared<RSMask>();
43     if (mask) {
44         mask->SetMaskPath(maskPath);
45         mask->SetMaskBrush(maskBrush);
46         mask->SetMaskType(MaskType::PATH);
47     }
48     return mask;
49 }
50 
CreatePathMask(const Drawing::Path & maskPath,const Drawing::Pen & maskPen,const Drawing::Brush & maskBrush)51 std::shared_ptr<RSMask> RSMask::CreatePathMask(
52     const Drawing::Path& maskPath, const Drawing::Pen& maskPen, const Drawing::Brush& maskBrush)
53 {
54     auto mask = std::make_shared<RSMask>();
55     if (mask) {
56         mask->SetMaskPath(maskPath);
57         mask->SetMaskPen(maskPen);
58         mask->SetMaskBrush(maskBrush);
59         mask->SetMaskType(MaskType::PATH);
60     }
61     return mask;
62 }
63 
CreateSVGMask(double x,double y,double scaleX,double scaleY,const sk_sp<SkSVGDOM> & svgDom)64 std::shared_ptr<RSMask> RSMask::CreateSVGMask(double x, double y, double scaleX, double scaleY,
65     const sk_sp<SkSVGDOM>& svgDom)
66 {
67     auto mask = std::make_shared<RSMask>();
68     if (mask) {
69         mask->SetSvgX(x);
70         mask->SetSvgY(y);
71         mask->SetScaleX(scaleX);
72         mask->SetScaleY(scaleY);
73         mask->SetSvgDom(svgDom);
74         mask->SetMaskType(MaskType::SVG);
75     }
76     return mask;
77 }
78 
CreatePixelMapMask(const std::shared_ptr<Media::PixelMap> pixelMap)79 std::shared_ptr<RSMask> RSMask::CreatePixelMapMask(const std::shared_ptr<Media::PixelMap> pixelMap)
80 {
81     auto mask = std::make_shared<RSMask>();
82     if (mask) {
83         mask->SetPixelMap(pixelMap);
84         mask->SetMaskType(MaskType::PIXEL_MAP);
85     }
86     return mask;
87 }
88 
RSMask()89 RSMask::RSMask()
90 {
91     maskPath_ = std::make_shared<Drawing::Path>();
92 }
93 
~RSMask()94 RSMask::~RSMask()
95 {
96 }
97 
SetSvgX(double x)98 void RSMask::SetSvgX(double x)
99 {
100     svgX_ = x;
101 }
102 
GetSvgX() const103 double RSMask::GetSvgX() const
104 {
105     return svgX_;
106 }
107 
SetSvgY(double y)108 void RSMask::SetSvgY(double y)
109 {
110     svgY_ = y;
111 }
112 
GetSvgY() const113 double RSMask::GetSvgY() const
114 {
115     return svgY_;
116 }
117 
SetScaleX(double scaleX)118 void RSMask::SetScaleX(double scaleX)
119 {
120     scaleX_ = scaleX;
121 }
122 
GetScaleX() const123 double RSMask::GetScaleX() const
124 {
125     return scaleX_;
126 }
127 
SetScaleY(double scaleY)128 void RSMask::SetScaleY(double scaleY)
129 {
130     scaleY_ = scaleY;
131 }
132 
GetScaleY() const133 double RSMask::GetScaleY() const
134 {
135     return scaleY_;
136 }
137 
SetMaskPath(const Drawing::Path & path)138 void RSMask::SetMaskPath(const Drawing::Path& path)
139 {
140     maskPath_ = std::make_shared<Drawing::Path>(path);
141 }
142 
GetMaskPath() const143 std::shared_ptr<Drawing::Path> RSMask::GetMaskPath() const
144 {
145     return maskPath_;
146 }
147 
SetMaskPen(const Drawing::Pen & pen)148 void RSMask::SetMaskPen(const Drawing::Pen& pen)
149 {
150     maskPen_ = pen;
151 }
152 
GetMaskPen() const153 Drawing::Pen RSMask::GetMaskPen() const
154 {
155     return maskPen_;
156 }
157 
SetMaskBrush(const Drawing::Brush & brush)158 void RSMask::SetMaskBrush(const Drawing::Brush& brush)
159 {
160     maskBrush_ = brush;
161 }
162 
GetMaskBrush() const163 Drawing::Brush RSMask::GetMaskBrush() const
164 {
165     return maskBrush_;
166 }
167 
SetSvgDom(const sk_sp<SkSVGDOM> & svgDom)168 void RSMask::SetSvgDom(const sk_sp<SkSVGDOM>& svgDom)
169 {
170     svgDom_ = svgDom;
171 }
172 
GetSvgDom() const173 sk_sp<SkSVGDOM> RSMask::GetSvgDom() const
174 {
175     return svgDom_;
176 }
177 
GetSvgPicture() const178 std::shared_ptr<Drawing::Picture> RSMask::GetSvgPicture() const
179 {
180     return svgPicture_;
181 }
182 
SetMaskType(MaskType type)183 void RSMask::SetMaskType(MaskType type)
184 {
185     type_ = type;
186 }
187 
SetPixelMap(const std::shared_ptr<Media::PixelMap> pixelMap)188 void RSMask::SetPixelMap(const std::shared_ptr<Media::PixelMap> pixelMap)
189 {
190     pixelMap_ = pixelMap;
191     image_ = RSPixelMapUtil::ExtractDrawingImage(pixelMap_);
192 }
193 
GetPixelMap() const194 std::shared_ptr<Media::PixelMap> RSMask::GetPixelMap() const
195 {
196     return pixelMap_;
197 }
198 
GetImage() const199 std::shared_ptr<Drawing::Image> RSMask::GetImage() const
200 {
201     return image_;
202 }
203 
IsSvgMask() const204 bool RSMask::IsSvgMask() const
205 {
206     return (type_ == MaskType::SVG);
207 }
208 
IsGradientMask() const209 bool RSMask::IsGradientMask() const
210 {
211     return (type_ == MaskType::GRADIENT);
212 }
213 
IsPixelMapMask() const214 bool RSMask::IsPixelMapMask() const
215 {
216     return (type_ == MaskType::PIXEL_MAP);
217 }
218 
IsPathMask() const219 bool RSMask::IsPathMask() const
220 {
221     return (type_ == MaskType::PATH);
222 }
223 
Dump(std::string & out) const224 void RSMask::Dump(std::string& out) const
225 {
226     out += "[maskType:" + std::to_string(static_cast<int>(type_));
227     out += " x:" + std::to_string(svgX_) + " y:" + std::to_string(svgY_);
228     out += " scaleX:" + std::to_string(scaleX_) + " scaleY:" + std::to_string(scaleY_);
229     out += " pen";
230     maskPen_.Dump(out);
231     out += " brush";
232     maskBrush_.Dump(out);
233     out += " path[";
234     if (maskPath_ != nullptr) {
235         out += "isValid:" + std::to_string(maskPath_->IsValid());
236         auto bounds = maskPath_->GetBounds();
237         out += " bounds[top:" + std::to_string(bounds.GetTop()) + " bottom:" + std::to_string(bounds.GetBottom());
238         out += " left:" + std::to_string(bounds.GetLeft()) + " right:" + std::to_string(bounds.GetRight()) + "]";
239         out += " drawingType:" + std::to_string(static_cast<int>(maskPath_->GetDrawingType()));
240     }
241     out += "] pixelMap[";
242     if (pixelMap_ != nullptr) {
243         out += "width:" + std::to_string(pixelMap_->GetWidth());
244         out += " height:" + std::to_string(pixelMap_->GetHeight());
245         out += " byteCount:" + std::to_string(pixelMap_->GetByteCount());
246     }
247     out += ']';
248     if (image_ != nullptr) {
249         out += " image";
250         image_->Dump(out);
251     }
252     out += ']';
253 }
254 
255 #ifdef ROSEN_OHOS
Marshalling(Parcel & parcel) const256 bool RSMask::Marshalling(Parcel& parcel) const
257 {
258     if (!(RSMarshallingHelper::Marshalling(parcel, type_) &&
259             RSMarshallingHelper::Marshalling(parcel, svgX_) &&
260             RSMarshallingHelper::Marshalling(parcel, svgY_) &&
261             RSMarshallingHelper::Marshalling(parcel, scaleX_) &&
262             RSMarshallingHelper::Marshalling(parcel, scaleY_))) {
263         ROSEN_LOGE("RSMask::Marshalling failed!");
264         return false;
265     }
266 
267     if (!MarshallingPathAndBrush(parcel)) {
268         ROSEN_LOGE("RSMask::Marshalling failed!");
269         return false;
270     }
271 
272     if (IsPixelMapMask() && !RSMarshallingHelper::Marshalling(parcel, pixelMap_)) {
273         ROSEN_LOGE("RSMask::Marshalling Pixelmap failed!");
274         return false;
275     }
276     return true;
277 }
278 
MarshallingPathAndBrush(Parcel & parcel) const279 bool RSMask::MarshallingPathAndBrush(Parcel& parcel) const
280 {
281     Drawing::CmdListData listData;
282     auto maskCmdList = Drawing::MaskCmdList::CreateFromData(listData, true);
283     Drawing::Filter filter = maskBrush_.GetFilter();
284     Drawing::BrushHandle brushHandle = {
285         maskBrush_.GetColor(),
286         maskBrush_.GetBlendMode(),
287         maskBrush_.IsAntiAlias(),
288         maskBrush_.GetBlenderEnabled(),
289         filter.GetFilterQuality(),
290         Drawing::CmdListHelper::AddColorSpaceToCmdList(*maskCmdList,
291             maskBrush_.GetColorSpace()),
292         Drawing::CmdListHelper::AddShaderEffectToCmdList(*maskCmdList,
293             maskBrush_.GetShaderEffect()),
294         Drawing::CmdListHelper::AddColorFilterToCmdList(*maskCmdList,
295             filter.GetColorFilter()),
296         Drawing::CmdListHelper::AddImageFilterToCmdList(*maskCmdList,
297             filter.GetImageFilter()),
298         Drawing::CmdListHelper::AddMaskFilterToCmdList(*maskCmdList,
299             filter.GetMaskFilter()),
300     };
301     maskCmdList->AddOp<Drawing::MaskBrushOpItem>(brushHandle);
302 
303     Drawing::PenHandle penHandle = {
304         maskPen_.GetWidth(),
305         maskPen_.GetMiterLimit(),
306         maskPen_.GetCapStyle(),
307         maskPen_.GetJoinStyle(),
308         Drawing::CmdListHelper::AddPathEffectToCmdList(*maskCmdList,
309             maskPen_.GetPathEffect()),
310         maskPen_.GetColor(),
311     };
312     maskCmdList->AddOp<Drawing::MaskPenOpItem>(penHandle);
313 
314     auto pathHandle = Drawing::CmdListHelper::AddPathToCmdList(*maskCmdList, *maskPath_);
315     maskCmdList->AddOp<Drawing::MaskPathOpItem>(pathHandle);
316 
317     if (!RSMarshallingHelper::Marshalling(parcel, maskCmdList)) {
318         ROSEN_LOGE("RSMask::MarshallingPathAndBrush failed!");
319         return false;
320     }
321     return true;
322 }
323 
Unmarshalling(Parcel & parcel)324 RSMask* RSMask::Unmarshalling(Parcel& parcel)
325 {
326     auto rsMask = std::make_unique<RSMask>();
327     if (!(RSMarshallingHelper::Unmarshalling(parcel, rsMask->type_) &&
328             RSMarshallingHelper::Unmarshalling(parcel, rsMask->svgX_) &&
329             RSMarshallingHelper::Unmarshalling(parcel, rsMask->svgY_) &&
330             RSMarshallingHelper::Unmarshalling(parcel, rsMask->scaleX_) &&
331             RSMarshallingHelper::Unmarshalling(parcel, rsMask->scaleY_))) {
332         ROSEN_LOGE("RSMask::Unmarshalling failed!");
333         return nullptr;
334     }
335 
336     std::shared_ptr<Drawing::MaskCmdList> maskCmdList = nullptr;
337     if (!RSMarshallingHelper::Unmarshalling(parcel, maskCmdList)) {
338         ROSEN_LOGE("RSMask::Unmarshalling failed!");
339         return nullptr;
340     }
341     if (maskCmdList) {
342         maskCmdList->Playback(rsMask->maskPath_, rsMask->maskPen_, rsMask->maskBrush_);
343     }
344 
345     if (rsMask->IsPixelMapMask() && !RSMarshallingHelper::Unmarshalling(parcel, rsMask->pixelMap_)) {
346         ROSEN_LOGE("RSMask::Unmarshalling pixelmap failed!");
347         return nullptr;
348     }
349 
350     if (!rsMask->image_ && rsMask->pixelMap_) {
351         rsMask->image_ = RSPixelMapUtil::ExtractDrawingImage(rsMask->pixelMap_);
352     }
353     return rsMask.release();
354 }
355 #endif
356 } // namespace Rosen
357 } // namespace OHOS