1 /*
2  * Copyright (c) 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 "recording/mask_cmd_list.h"
17 
18 #include "recording/cmd_list_helper.h"
19 #include "utils/log.h"
20 
21 namespace OHOS {
22 namespace Rosen {
23 namespace Drawing {
24 namespace {
25 Pen defaultPen;
26 }
27 
CreateFromData(const CmdListData & data,bool isCopy)28 std::shared_ptr<MaskCmdList> MaskCmdList::CreateFromData(const CmdListData& data, bool isCopy)
29 {
30     auto cmdList = std::make_shared<MaskCmdList>();
31     if (isCopy) {
32         cmdList->opAllocator_.BuildFromDataWithCopy(data.first, data.second);
33     } else {
34         cmdList->opAllocator_.BuildFromData(data.first, data.second);
35     }
36     return cmdList;
37 }
38 
Playback(MaskPlayer & player) const39 bool MaskCmdList::Playback(MaskPlayer &player) const
40 {
41     uint32_t offset = 0;
42     uint32_t count = 0;
43     size_t totalSize = opAllocator_.GetSize();
44     do {
45         count++;
46         if (totalSize < offset || totalSize - offset < sizeof(OpItem)) {
47             LOGD("MaskCmdList::Playback size error");
48             return false;
49         }
50         void* itemPtr = opAllocator_.OffsetToAddr(offset, sizeof(OpItem));
51         OpItem* curOpItemPtr = static_cast<OpItem*>(itemPtr);
52         if (curOpItemPtr != nullptr) {
53             if (!player.Playback(curOpItemPtr->GetType(), itemPtr, totalSize - offset)) {
54                 LOGD("MaskCmdList::Playback failed!");
55                 break;
56             }
57 
58             if (curOpItemPtr->GetNextOpItemOffset() < offset + sizeof(OpItem)) {
59                 break;
60             }
61             offset = curOpItemPtr->GetNextOpItemOffset();
62         } else {
63             LOGE("MaskCmdList::Playback failed, opItem is nullptr");
64             break;
65         }
66     } while (offset != 0 && count <= MAX_OPITEMSIZE);
67 
68     return true;
69 }
70 
Playback(std::shared_ptr<Path> & path,Brush & brush) const71 bool MaskCmdList::Playback(std::shared_ptr<Path>& path, Brush& brush) const
72 {
73     MaskPlayer player(path, brush, *this);
74     return Playback(player);
75 }
76 
Playback(std::shared_ptr<Path> & path,Pen & pen,Brush & brush) const77 bool MaskCmdList::Playback(std::shared_ptr<Path>& path, Pen& pen, Brush& brush) const
78 {
79     MaskPlayer player(path, brush, pen, *this);
80     return Playback(player);
81 }
82 
83 /* OpItem */
84 std::unordered_map<uint32_t, MaskPlayer::MaskPlaybackFunc> MaskPlayer::opPlaybackFuncLUT_ = {
85     { MaskOpItem::MASK_BRUSH_OPITEM,          MaskBrushOpItem::Playback },
86     { MaskOpItem::MASK_PATH_OPITEM,           MaskPathOpItem::Playback },
87     { MaskOpItem::MASK_PEN_OPITEM,           MaskPenOpItem::Playback },
88 };
89 
MaskPlayer(std::shared_ptr<Path> & path,Brush & brush,const CmdList & cmdList)90 MaskPlayer::MaskPlayer(std::shared_ptr<Path>& path, Brush& brush, const CmdList& cmdList)
91     : path_(path), brush_(brush), pen_(defaultPen), cmdList_(cmdList) {}
92 
MaskPlayer(std::shared_ptr<Path> & path,Brush & brush,Pen & pen,const CmdList & cmdList)93 MaskPlayer::MaskPlayer(std::shared_ptr<Path>& path, Brush& brush, Pen& pen, const CmdList& cmdList)
94     : path_(path), brush_(brush), pen_(pen), cmdList_(cmdList) {}
95 
Playback(uint32_t type,const void * opItem,size_t leftOpAllocatorSize)96 bool MaskPlayer::Playback(uint32_t type, const void* opItem, size_t leftOpAllocatorSize)
97 {
98     if (type == MaskOpItem::OPITEM_HEAD) {
99         return true;
100     }
101 
102     auto it = opPlaybackFuncLUT_.find(type);
103     if (it == opPlaybackFuncLUT_.end() || it->second == nullptr) {
104         return false;
105     }
106 
107     auto func = it->second;
108     (*func)(*this, opItem, leftOpAllocatorSize);
109 
110     return true;
111 }
112 
MaskBrushOpItem(const BrushHandle & brushHandle)113 MaskBrushOpItem::MaskBrushOpItem(const BrushHandle& brushHandle)
114     : MaskOpItem(MASK_BRUSH_OPITEM), brushHandle_(brushHandle) {}
115 
Playback(MaskPlayer & player,const void * opItem,size_t leftOpAllocatorSize)116 void MaskBrushOpItem::Playback(MaskPlayer& player, const void* opItem, size_t leftOpAllocatorSize)
117 {
118     if (opItem != nullptr && leftOpAllocatorSize >= sizeof(MaskBrushOpItem)) {
119         const auto* op = static_cast<const MaskBrushOpItem*>(opItem);
120         op->Playback(player.brush_, player.cmdList_);
121     }
122 }
123 
Playback(Brush & brush,const CmdList & cmdList) const124 void MaskBrushOpItem::Playback(Brush& brush, const CmdList& cmdList) const
125 {
126     auto colorSpace = CmdListHelper::GetColorSpaceFromCmdList(
127         cmdList, brushHandle_.colorSpaceHandle);
128     auto shaderEffect = CmdListHelper::GetShaderEffectFromCmdList(
129         cmdList, brushHandle_.shaderEffectHandle);
130     auto colorFilter = CmdListHelper::GetColorFilterFromCmdList(
131         cmdList, brushHandle_.colorFilterHandle);
132     auto imageFilter = CmdListHelper::GetImageFilterFromCmdList(
133         cmdList, brushHandle_.imageFilterHandle);
134     auto maskFilter = CmdListHelper::GetMaskFilterFromCmdList(
135         cmdList, brushHandle_.maskFilterHandle);
136 
137     Filter filter;
138     filter.SetColorFilter(colorFilter);
139     filter.SetImageFilter(imageFilter);
140     filter.SetMaskFilter(maskFilter);
141     filter.SetFilterQuality(brushHandle_.filterQuality);
142 
143     const Color4f color4f = { brushHandle_.color.GetRedF(), brushHandle_.color.GetGreenF(),
144         brushHandle_.color.GetBlueF(), brushHandle_.color.GetAlphaF() };
145 
146     brush.SetColor(color4f, colorSpace);
147     brush.SetShaderEffect(shaderEffect);
148     brush.SetBlendMode(brushHandle_.mode);
149     brush.SetAntiAlias(brushHandle_.isAntiAlias);
150     brush.SetFilter(filter);
151 }
152 
MaskPathOpItem(const OpDataHandle & pathHandle)153 MaskPathOpItem::MaskPathOpItem(const OpDataHandle& pathHandle)
154     : MaskOpItem(MASK_PATH_OPITEM), pathHandle_(pathHandle) {}
155 
Playback(MaskPlayer & player,const void * opItem,size_t leftOpAllocatorSize)156 void MaskPathOpItem::Playback(MaskPlayer& player, const void* opItem, size_t leftOpAllocatorSize)
157 {
158     if (opItem != nullptr && leftOpAllocatorSize >= sizeof(MaskPathOpItem)) {
159         const auto* op = static_cast<const MaskPathOpItem*>(opItem);
160         op->Playback(player.path_, player.cmdList_);
161     }
162 }
163 
Playback(std::shared_ptr<Path> & path,const CmdList & cmdList) const164 void MaskPathOpItem::Playback(std::shared_ptr<Path>& path, const CmdList& cmdList) const
165 {
166     auto readPath = CmdListHelper::GetPathFromCmdList(cmdList, pathHandle_);
167     path = readPath;
168 }
169 
MaskPenOpItem(const PenHandle & penHandle)170 MaskPenOpItem::MaskPenOpItem(const PenHandle& penHandle)
171     : MaskOpItem(MASK_PEN_OPITEM), penHandle_(penHandle) {}
172 
Playback(MaskPlayer & player,const void * opItem,size_t leftOpAllocatorSize)173 void MaskPenOpItem::Playback(MaskPlayer &player, const void *opItem, size_t leftOpAllocatorSize)
174 {
175     if (opItem != nullptr && leftOpAllocatorSize >= sizeof(MaskPenOpItem)) {
176         const auto* op = static_cast<const MaskPenOpItem*>(opItem);
177         op->Playback(player.pen_, player.cmdList_);
178     }
179 }
180 
Playback(Pen & pen,const CmdList & cmdList) const181 void MaskPenOpItem::Playback(Pen& pen, const CmdList& cmdList) const
182 {
183     pen.SetWidth(penHandle_.width);
184     pen.SetMiterLimit(penHandle_.miterLimit);
185     pen.SetJoinStyle(penHandle_.joinStyle);
186     pen.SetCapStyle(penHandle_.capStyle);
187 
188     auto pathEffect = CmdListHelper::GetPathEffectFromCmdList(cmdList, penHandle_.pathEffectHandle);
189     pen.SetPathEffect(pathEffect);
190     pen.SetColor(penHandle_.color);
191 }
192 } // namespace Drawing
193 } // namespace Rosen
194 } // namespace OHOS
195