• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "core/components_ng/pattern/image/image_modifier.h"
17 
18 namespace OHOS::Ace::NG {
ImageModifier()19 ImageModifier::ImageModifier()
20 {
21     imageFit_ = AceType::MakeRefPtr<AnimatablePropertyFloat>(0.0f);
22     flag_ = AceType::MakeRefPtr<PropertyBool>(false);
23     AttachProperty(imageFit_);
24     AttachProperty(flag_);
25 }
26 
onDraw(DrawingContext & context)27 void ImageModifier::onDraw(DrawingContext& context)
28 {
29     auto canvas = canvasImage_.Upgrade();
30     CHECK_NULL_VOID(canvas);
31     if (isAltImage_) {
32         DrawImageWithoutAnimation(context);
33         return;
34     }
35     if (isFirst_) {
36         DrawImageWithoutAnimation(context);
37         isFirst_ = false;
38     } else {
39         auto&& config = canvas->GetPaintConfig();
40         if (config.isSvg_) {
41             DrawImageWithoutAnimation(context);
42         } else {
43             DrawImageWithAnimation(context);
44         }
45     }
46 }
47 
SetImageFit(ImageFit imagefit)48 void ImageModifier::SetImageFit(ImageFit imagefit)
49 {
50     if (imagefit != endImageFit_) {
51         startImageFit_ = endImageFit_;
52         endImageFit_ = imagefit;
53     } else {
54         imageFit_->Set(static_cast<float>(startImageFit_));
55     }
56     imageFit_->Set(static_cast<float>(imagefit));
57 }
58 
UpdateImageData(const WeakPtr<CanvasImage> & canvasImage,const OffsetF & offset,const SizeF & contentSize)59 void ImageModifier::UpdateImageData(const WeakPtr<CanvasImage>& canvasImage,
60     const OffsetF& offset, const SizeF& contentSize)
61 {
62     canvasImage_ = canvasImage;
63     offset_ = offset;
64     contentSize_ = contentSize;
65     auto canvas = canvasImage_.Upgrade();
66     CHECK_NULL_VOID(canvas);
67     auto&& config = canvas->GetPaintConfig();
68     // update srcRect
69     startSrcRect_ = endSrcRect_;
70     endSrcRect_ = config.srcRect_;
71     // update dstRect
72     startDstRect_ = endDstRect_;
73     endDstRect_ = config.dstRect_;
74 }
75 
Modify()76 void ImageModifier::Modify()
77 {
78     flag_->Set(!flag_->Get());
79 }
80 
SetIsAltImage(bool isAltImage)81 void ImageModifier::SetIsAltImage(bool isAltImage)
82 {
83     isAltImage_ = isAltImage;
84 }
85 
GetValue(float value) const86 float ImageModifier::GetValue(float value) const
87 {
88     return std::max(value, 0.0f);
89 }
90 
DrawImageWithAnimation(DrawingContext & context)91 void ImageModifier::DrawImageWithAnimation(DrawingContext& context)
92 {
93     float difference = static_cast<float>(endImageFit_) - static_cast<float>(startImageFit_);
94     float ratio = 1.0f;
95     if (!NearZero(difference)) {
96         // ratio goes from 0 to 1
97         ratio = abs((imageFit_->Get() - static_cast<float>(startImageFit_)) / difference);
98     }
99     UpdatePaintConfig(ratio);
100     auto canvas = canvasImage_.Upgrade();
101     CHECK_NULL_VOID(canvas);
102     canvas->SetIsDrawAnimate(!NearEqual(ANIMATION_END, ratio, EPSILON));
103     ImagePainter imagePainter(canvas);
104     imagePainter.DrawImage(context.canvas, offset_, contentSize_);
105 }
106 
DrawImageWithoutAnimation(DrawingContext & context) const107 void ImageModifier::DrawImageWithoutAnimation(DrawingContext& context) const
108 {
109     auto canvas = canvasImage_.Upgrade();
110     CHECK_NULL_VOID(canvas);
111     ImagePainter imagePainter(canvas);
112     imagePainter.DrawImage(context.canvas, offset_, contentSize_);
113 }
114 
UpdatePaintConfig(float ratio)115 void ImageModifier::UpdatePaintConfig(float ratio)
116 {
117     // use ratio to calculate new dstRect and srcRect
118     auto canvas = canvasImage_.Upgrade();
119     CHECK_NULL_VOID(canvas);
120     auto&& config = canvas->GetPaintConfig();
121     if (NearEqual(ANIMATION_END, ratio, EPSILON)) {
122         config.dstRect_.SetRect(endDstRect_.GetOffset(), endDstRect_.GetSize());
123         config.srcRect_.SetRect(endSrcRect_.GetOffset(), endSrcRect_.GetSize());
124     } else {
125         // calculate new dstRect
126         auto x = startDstRect_.GetX() + (endDstRect_.GetX() - startDstRect_.GetX()) * ratio;
127         auto y = startDstRect_.GetY() + (endDstRect_.GetY() - startDstRect_.GetY()) * ratio;
128         auto width = contentSize_.Width() - TWICE * x;
129         auto height = contentSize_.Height() - TWICE * y;
130         config.dstRect_.SetRect(GetValue(x), GetValue(y), GetValue(width), GetValue(height));
131         // calculate new srcRect
132         auto startImageWidth = TWICE * startSrcRect_.GetX() + startSrcRect_.Width();
133         auto startImageHeight = TWICE * startSrcRect_.GetY() + startSrcRect_.Height();
134         auto endImageWidth = TWICE * endSrcRect_.GetX() + endSrcRect_.Width();
135         auto endImageHeight = TWICE * endSrcRect_.GetY() + endSrcRect_.Height();
136 
137         x = endSrcRect_.GetX() * ratio +
138             (startSrcRect_.GetX() / (startImageWidth / endImageWidth)) * (ANIMATION_END - ratio);
139         y = endSrcRect_.GetY() * ratio +
140             (startSrcRect_.GetY() / (startImageHeight / endImageHeight)) * (ANIMATION_END - ratio);
141         // calculate new width & height
142         width = endImageWidth - TWICE * x;
143         height = endImageHeight - TWICE * y;
144         config.srcRect_.SetRect(GetValue(x), GetValue(y), GetValue(width), GetValue(height));
145     }
146 }
147 } // namespace OHOS::Ace::NG
148