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