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 #ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_RENDER_ADAPTER_BACKGROUND_MODIFIER_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_RENDER_ADAPTER_BACKGROUND_MODIFIER_H
18 
19 #include <functional>
20 #include <memory>
21 
22 #include "render_service_client/core/modifier/rs_extended_modifier.h"
23 
24 #include "core/components_ng/render/adapter/rosen_modifier_adapter.h"
25 
26 namespace OHOS::Ace::NG {
27 class BackgroundModifier : public Rosen::RSBackgroundStyleModifier {
28 public:
29     BackgroundModifier() = default;
30     ~BackgroundModifier() override = default;
31 
32 #ifndef USE_ROSEN_DRAWING
Draw(Rosen::RSDrawingContext & context)33     void Draw(Rosen::RSDrawingContext& context) const override
34     {
35         auto host = host_.Upgrade();
36         CHECK_NULL_VOID(host);
37         auto curSize = host->GetGeometryNode()->GetFrameSize();
38         auto curWidth = curSize.Width();
39         auto curHeight = curSize.Height();
40         CHECK_NULL_VOID(pixelMap_);
41         std::shared_ptr<Media::PixelMap> mediaPixelMap = pixelMap_->GetPixelMapSharedPtr();
42         CHECK_NULL_VOID(context.canvas);
43         std::shared_ptr<SkCanvas> skCanvas { context.canvas, [](SkCanvas* /* unused */) {} };
44         auto* recordingCanvas = static_cast<Rosen::RSRecordingCanvas*>(skCanvas.get());
45         SkSamplingOptions samplingOptions;
46         SkPaint paint;
47 
48         SizeF desSize(initialNodeWidth_, initialNodeHeight_);
49         SizeF srcSize(mediaPixelMap->GetWidth(), mediaPixelMap->GetHeight());
50         NG::OffsetF offset1 = Alignment::GetAlignPosition(srcSize, desSize, align_);
51         NG::OffsetF offset2 = Alignment::GetAlignPosition(desSize, srcSize, align_);
52         SkRect srcSKRect = SkRect::MakeXYWH(offset1.GetX(), offset1.GetY(), srcSize.Width(), srcSize.Height());
53         SkRect desSKRect = SkRect::MakeXYWH(offset2.GetX() * curWidth / initialNodeWidth_,
54             offset2.GetY() * curHeight / initialNodeHeight_, srcSize.Width() * curWidth / initialNodeWidth_,
55             srcSize.Height() * curHeight / initialNodeHeight_);
56         if (srcSize.Width() > desSize.Width()) {
57             srcSKRect.fRight = offset1.GetX() + desSize.Width();
58             desSKRect.fRight = curWidth;
59         }
60         if (srcSize.Height() > desSize.Height()) {
61             srcSKRect.fBottom = offset1.GetY() + desSize.Height();
62             desSKRect.fBottom = curHeight;
63         }
64         recordingCanvas->DrawPixelMapRect(mediaPixelMap, srcSKRect, desSKRect, samplingOptions, &paint);
65     }
66 #else
Draw(Rosen::RSDrawingContext & context)67     void Draw(Rosen::RSDrawingContext& context) const override
68     {
69         auto host = host_.Upgrade();
70         CHECK_NULL_VOID(host);
71         auto curSize = host->GetGeometryNode()->GetFrameSize();
72         auto curWidth = curSize.Width();
73         auto curHeight = curSize.Height();
74         CHECK_NULL_VOID(pixelMap_);
75         std::shared_ptr<Media::PixelMap> mediaPixelMap = pixelMap_->GetPixelMapSharedPtr();
76         CHECK_NULL_VOID(context.canvas);
77         auto& recordingCanvas = static_cast<Rosen::ExtendRecordingCanvas&>(*context.canvas);
78         RSSamplingOptions samplingOptions;
79         RSBrush brush;
80 
81         SizeF desSize(initialNodeWidth_, initialNodeHeight_);
82         SizeF srcSize(mediaPixelMap->GetWidth(), mediaPixelMap->GetHeight());
83         NG::OffsetF offset1 = Alignment::GetAlignPosition(srcSize, desSize, align_);
84         NG::OffsetF offset2 = Alignment::GetAlignPosition(desSize, srcSize, align_);
85         RSRect srcRSRect = RSRect(offset1.GetX(), offset1.GetY(), srcSize.Width() + offset1.GetX(),
86             srcSize.Height() + offset1.GetY());
87         RSRect desRSRect = RSRect(offset2.GetX() * curWidth / initialNodeWidth_,
88             offset2.GetY() * curHeight / initialNodeHeight_,
89             srcSize.Width() * curWidth / initialNodeWidth_ + offset2.GetX() * curWidth / initialNodeWidth_,
90             srcSize.Height() * curHeight / initialNodeHeight_ +
91             offset2.GetY() * curHeight / initialNodeHeight_);
92         if (srcSize.Width() > desSize.Width()) {
93             srcRSRect.SetRight(offset1.GetX() + desSize.Width());
94             desRSRect.SetRight(curWidth);
95         }
96         if (srcSize.Height() > desSize.Height()) {
97             srcRSRect.SetBottom(offset1.GetY() + desSize.Height());
98             desRSRect.SetBottom(curHeight);
99         }
100         recordingCanvas.AttachBrush(brush);
101         recordingCanvas.DrawPixelMapRect(mediaPixelMap, srcRSRect, desRSRect, samplingOptions);
102         recordingCanvas.DetachBrush();
103     }
104 #endif
105 
SetPixelMap(const RefPtr<PixelMap> & pixelMap)106     void SetPixelMap(const RefPtr<PixelMap>& pixelMap)
107     {
108         CHECK_NULL_VOID(pixelMap);
109         pixelMap_ = pixelMap;
110     }
111 
SetAlign(const Alignment & align)112     void SetAlign(const Alignment& align)
113     {
114         align_ = align;
115     }
116 
SetInitialNodeSize(const float width,const float height)117     void SetInitialNodeSize(const float width, const float height)
118     {
119         initialNodeWidth_ = width;
120         initialNodeHeight_ = height;
121     }
122 
Modify()123     void Modify()
124     {
125         if (!flag_) {
126             flag_ = std::make_shared<Rosen::RSProperty<bool>>(0);
127             AttachProperty(flag_);
128         } else {
129             flag_->Set(!flag_->Get());
130         }
131     }
132 
SetHostNode(RefPtr<FrameNode> host)133     void SetHostNode(RefPtr<FrameNode> host)
134     {
135         host_ = host;
136     }
137 
138 private:
139     RefPtr<PixelMap> pixelMap_;
140     Alignment align_;
141     float initialNodeWidth_ = 1.0f;
142     float initialNodeHeight_ = 1.0f;
143     std::shared_ptr<Rosen::RSProperty<bool>> flag_;
144     WeakPtr<FrameNode> host_;
145 };
146 } // namespace OHOS::Ace::NG
147 
148 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_RENDER_ADAPTER_BACKGROUND_MODIFIER_H
149