1 /*
2  * Copyright (c) 2021-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 "core/components/video/render_texture.h"
17 
18 #include "core/components/theme/theme_manager.h"
19 #include "core/components/video/video_component.h"
20 #include "core/components/video/video_theme.h"
21 
22 namespace OHOS::Ace {
23 
RenderTexture()24 RenderTexture::RenderTexture() : RenderNode(true) {}
25 
Update(const RefPtr<Component> & component)26 void RenderTexture::Update(const RefPtr<Component>& component)
27 {
28     const RefPtr<TextureComponent> texture = AceType::DynamicCast<TextureComponent>(component);
29     if (!texture) {
30         return;
31     }
32 
33     textureId_ = texture->GetTextureId();
34     auto sourceSize = Size(static_cast<double>(texture->GetSrcWidth()), static_cast<double>(texture->GetSrcHeight()));
35     if (sourceSize.IsValid()) {
36         sourceSize_ = sourceSize;
37     }
38     imageFit_ = texture->GetFit();
39     imagePosition_ = texture->GetImagePosition();
40     InitControlsHeight(component);
41 
42     MarkNeedLayout();
43 }
44 
InitControlsHeight(const RefPtr<Component> & component)45 void RenderTexture::InitControlsHeight(const RefPtr<Component>& component)
46 {
47     controlsHeight_ = 0.0;
48     auto context = context_.Upgrade();
49     if (!context) {
50         LOGE("context is null");
51         return;
52     }
53 
54     auto themeManager = context->GetThemeManager();
55     if (!themeManager) {
56         LOGE("theme manager is null");
57         return;
58     }
59 
60     auto videoTheme = themeManager->GetTheme<VideoTheme>();
61     if (!videoTheme) {
62         LOGE("video theme is null");
63         return;
64     }
65 
66     auto videoComponent = AceType::DynamicCast<VideoComponent>(component);
67     if (!videoComponent) {
68         LOGI("component is not video");
69         return;
70     }
71 
72     if (videoComponent->NeedControls()) {
73         controlsHeight_ += NormalizeToPx(Dimension(videoTheme->GetBtnSize().Height(), DimensionUnit::VP));
74         controlsHeight_ += NormalizeToPx(videoTheme->GetBtnEdge().Top());
75         controlsHeight_ += NormalizeToPx(videoTheme->GetBtnEdge().Bottom());
76     }
77 }
78 
SetHidden(bool hidden,bool inRecursion)79 void RenderTexture::SetHidden(bool hidden, bool inRecursion)
80 {
81     RenderNode::SetHidden(hidden, inRecursion);
82     if (hiddenChangeEvent_) {
83         hiddenChangeEvent_(hidden);
84     }
85 }
86 
PerformLayout()87 void RenderTexture::PerformLayout()
88 {
89     if (!NeedLayout()) {
90         return;
91     }
92     Measure();
93     SetNeedLayout(false);
94     if (textureSizeChangeEvent_) {
95         textureSizeChangeEvent_(textureId_, drawSize_.Width(), drawSize_.Height());
96     }
97     if (textureOffsetChangeEvent_) {
98         textureOffsetChangeEvent_(textureId_,
99             (int32_t)(alignmentX_ + GetGlobalOffset().GetX()), (int32_t)(alignmentY_ + GetGlobalOffset().GetY()));
100     }
101     MarkNeedRender();
102 }
103 
Measure()104 void RenderTexture::Measure()
105 {
106     double width = GetLayoutParam().GetMinSize().Width();
107     double height = GetLayoutParam().GetMinSize().Height();
108     for (const auto& item : GetChildren()) {
109         item->Layout(GetLayoutParam());
110         width = std::max(width, item->GetLayoutSize().Width());
111         height = std::max(height, item->GetLayoutSize().Height());
112     }
113 
114     if (!GetLayoutParam().GetMaxSize().IsInfinite()) {
115         SetLayoutSize(GetLayoutParam().GetMaxSize());
116     } else {
117         SetLayoutSize(Size(width, height));
118     }
119 
120     switch (imageFit_) {
121         case ImageFit::CONTAIN:
122             CalculateFitContain();
123             break;
124         case ImageFit::FILL:
125             CalculateFitFill();
126             break;
127         case ImageFit::COVER:
128             CalculateFitCover();
129             break;
130         case ImageFit::NONE:
131             CalculateFitNone();
132             break;
133         case ImageFit::SCALE_DOWN:
134             CalculateFitScaleDown();
135             break;
136         default:
137             CalculateFitContain();
138             break;
139     }
140 
141     ApplyObjectPosition();
142 }
143 
ApplyObjectPosition()144 void RenderTexture::ApplyObjectPosition()
145 {
146     const Size& layoutSize = GetLayoutSize();
147     if (imagePosition_.GetSizeTypeX() == BackgroundImagePositionType::PX) {
148         alignmentX_ = imagePosition_.GetSizeValueX();
149     } else {
150         alignmentX_ = imagePosition_.GetSizeValueX() * (layoutSize.Width() - drawSize_.Width()) / PERCENT_TRANSLATE;
151     }
152 
153     if (imagePosition_.GetSizeTypeY() == BackgroundImagePositionType::PX) {
154         alignmentY_ = imagePosition_.GetSizeValueY();
155     } else {
156         alignmentY_ = imagePosition_.GetSizeValueY() * (layoutSize.Height() - drawSize_.Height()) / PERCENT_TRANSLATE;
157     }
158 }
159 
CalculateFitContain()160 void RenderTexture::CalculateFitContain()
161 {
162     const Size& layoutSize = GetLayoutSize();
163     double layoutRatio = NearZero(layoutSize.Height()) ? 0.0 : layoutSize.Width() / layoutSize.Height();
164     double sourceRatio = NearZero(sourceSize_.Height()) ? layoutRatio : sourceSize_.Width() / sourceSize_.Height();
165     if (NearZero(layoutRatio) || NearZero(sourceRatio)) {
166         drawSize_ = layoutSize;
167     } else if (sourceRatio < layoutRatio) {
168         drawSize_ = Size(sourceRatio * layoutSize.Height(), layoutSize.Height());
169     } else {
170         drawSize_ = Size(layoutSize.Width(), layoutSize.Width() / sourceRatio);
171     }
172 }
173 
CalculateFitCover()174 void RenderTexture::CalculateFitCover()
175 {
176     const Size& layoutSize = GetLayoutSize();
177     double layoutRatio = NearZero(layoutSize.Height()) ? 0.0 : layoutSize.Width() / layoutSize.Height();
178     double sourceRatio = NearZero(sourceSize_.Height()) ? layoutRatio : sourceSize_.Width() / sourceSize_.Height();
179     if (NearZero(layoutRatio) || NearZero(sourceRatio)) {
180         drawSize_ = layoutSize;
181     } else if (sourceRatio < layoutRatio) {
182         drawSize_ = Size(layoutSize.Width(), layoutSize.Width() / sourceRatio);
183     } else {
184         drawSize_ = Size(layoutSize.Height() * sourceRatio, layoutSize.Height());
185     }
186 }
187 
CalculateFitFill()188 void RenderTexture::CalculateFitFill()
189 {
190     drawSize_ = GetLayoutSize();
191 }
192 
CalculateFitNone()193 void RenderTexture::CalculateFitNone()
194 {
195     drawSize_ = sourceSize_;
196 }
197 
CalculateFitScaleDown()198 void RenderTexture::CalculateFitScaleDown()
199 {
200     const Size& LayoutSize = GetLayoutSize();
201 
202     if (LayoutSize.Width() > sourceSize_.Width()) {
203         CalculateFitNone();
204     } else {
205         CalculateFitContain();
206     }
207 }
208 
209 } // namespace OHOS::Ace
210