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