• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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/image/render_image.h"
17 
18 #include "base/log/dump_log.h"
19 #include "base/log/log.h"
20 #include "base/utils/utils.h"
21 #include "core/components/image/image_component.h"
22 #include "core/components/image/image_event.h"
23 #include "core/event/ace_event_helper.h"
24 
25 namespace OHOS::Ace {
26 namespace {
27 
28 constexpr double RESIZE_AGAIN_THRESHOLD = 1.2;
29 
30 } // namespace
31 
Update(const RefPtr<Component> & component)32 void RenderImage::Update(const RefPtr<Component>& component)
33 {
34     const RefPtr<ImageComponent> image = AceType::DynamicCast<ImageComponent>(component);
35     if (!image) {
36         LOGE("image component is null!");
37         return;
38     }
39     currentSrcRect_ = srcRect_;
40     currentDstRect_ = dstRect_;
41     currentDstRectList_ = rectList_;
42 
43     width_ = image->GetWidth();
44     syncMode_ = image->GetSyncMode();
45     height_ = image->GetHeight();
46     alignment_ = image->GetAlignment();
47     imageObjectPosition_ = image->GetImageObjectPosition();
48     fitMaxSize_ = image->GetFitMaxSize();
49     hasObjectPosition_ = image->GetHasObjectPosition();
50     color_ = image->GetColor();
51     previousLayoutSize_ = Size();
52     SetTextDirection(image->GetTextDirection());
53     matchTextDirection_ = image->IsMatchTextDirection();
54     SetRadius(image->GetBorder());
55     auto context = context_.Upgrade();
56     if (context && context->GetIsDeclarative()) {
57         loadImgSuccessEvent_ = AceAsyncEvent<void(const std::shared_ptr<BaseEventInfo>&)>::Create(
58             image->GetLoadSuccessEvent(), context_);
59         loadImgFailEvent_ = AceAsyncEvent<void(const std::shared_ptr<BaseEventInfo>&)>::Create(
60             image->GetLoadFailEvent(), context_);
61     } else {
62         loadSuccessEvent_ =
63             AceAsyncEvent<void(const std::string&)>::Create(image->GetLoadSuccessEvent(), context_);
64         loadFailEvent_ = AceAsyncEvent<void(const std::string&)>::Create(image->GetLoadFailEvent(), context_);
65     }
66     svgAnimatorFinishEvent_ = image->GetSvgAnimatorFinishEvent();
67     imageFit_ = image->GetImageFit();
68     imageInterpolation_ = image->GetImageInterpolation();
69     imageRenderMode_ = image->GetImageRenderMode();
70     imageRepeat_ = image->GetImageRepeat();
71 
72     useSkiaSvg_ = image->GetUseSkiaSvg();
73     autoResize_ = image->GetAutoResize();
74     imageAlt_ = image->GetAlt();
75     auto inComingSrc = image->GetSrc();
76     ImageSourceInfo inComingSource(
77         inComingSrc,
78         image->GetImageSourceSize().first,
79         image->GetImageSourceSize().second,
80         inComingSrc.empty() ? image->GetResourceId() : InternalResource::ResourceId::NO_ID,
81         image->GetPixmap());
82     auto fillColor = image->GetImageFill();
83     if (fillColor.has_value()) {
84         inComingSource.SetFillColor(fillColor.value());
85     }
86     border_ = image->GetBorder();
87     // this value is used for update frequency with same image source info.
88     LOGD("sourceInfo %{public}s", sourceInfo_.ToString().c_str());
89     LOGD("inComingSource %{public}s", inComingSource.ToString().c_str());
90     LOGD("imageLoadingStatus_: %{public}d", static_cast<int32_t>(imageLoadingStatus_));
91     proceedPreviousLoading_ = sourceInfo_.IsValid() && sourceInfo_ == inComingSource;
92     sourceInfo_ = inComingSource;
93     MarkNeedLayout(sourceInfo_.IsSvg());
94 }
95 
PerformLayout()96 void RenderImage::PerformLayout()
97 {
98     if (background_) {
99         PerformLayoutBgImage();
100         if (imageRenderFunc_) {
101             imageRenderFunc_();
102         }
103         return;
104     }
105 
106     auto context = context_.Upgrade();
107     if (!context) {
108         return;
109     }
110     scale_ = context->GetViewScale();
111     if (LessOrEqual(scale_, 0)) {
112         scale_ = 1.0;
113     }
114     if (width_.IsValid() && height_.IsValid()) {
115         imageComponentSize_ = Size(NormalizeToPx(width_), NormalizeToPx(height_));
116         isImageSizeSet_ = true;
117     }
118     // Divided by the true pixel ratio to apply image fit.
119     Size pictureSize = Measure() * (1.0 / scale_);
120     auto maxSize = GetLayoutParam().GetMaxSize();
121     if (fitMaxSize_ && (!imageComponentSize_.IsValid() || (!isImageSizeSet_ && maxSize != formerMaxSize_))) {
122         imageComponentSize_ = maxSize;
123         formerMaxSize_ = imageComponentSize_;
124     }
125     SetLayoutSize(GetLayoutParam().Constrain(imageComponentSize_.IsValid() && !imageComponentSize_.IsInfinite() ?
126         imageComponentSize_ : CalculateBackupImageSize(pictureSize)));
127     if (rawImageSizeUpdated_) {
128         previousLayoutSize_ = GetLayoutSize();
129     }
130     srcRect_.SetRect(Offset(), pictureSize);
131     dstRect_.SetRect(Offset(), GetLayoutSize());
132     ApplyImageFit(srcRect_, dstRect_);
133     // Restore image size.
134     srcRect_.ApplyScale(scale_);
135     if (!imageComponentSize_.IsValid()) {
136         SetLayoutSize(dstRect_.GetSize());
137     }
138     decltype(imageLayoutCallbacks_) imageLayoutCallbacks(std::move(imageLayoutCallbacks_));
139     std::for_each(
140         imageLayoutCallbacks.begin(), imageLayoutCallbacks.end(), [](std::function<void()> callback) { callback(); });
141     LayoutImageObject();
142     if (renderAltImage_) {
143         LayoutParam altLayoutParam;
144         altLayoutParam.SetFixedSize(GetLayoutSize());
145         renderAltImage_->Layout(altLayoutParam);
146     }
147 
148     CalculateResizeTarget();
149     if (hasObjectPosition_) {
150         ApplyObjectPosition();
151     }
152 }
153 
CalculateBackupImageSize(const Size & pictureSize)154 Size RenderImage::CalculateBackupImageSize(const Size& pictureSize)
155 {
156     // Since the return value of this function is used to determine the layout size of Image Component, it is essential
157     // to guarantee that there is no infinite edge to avoid thread stuck that may occur.
158     //
159     // Generally speaking, the size of the picture will not be infinite, but the size of the svg picture is equal to the
160     // maximum value of the layout parameters, so there is the possibility of infinity.
161     //
162     // Note that [pictureSize] has been scaled by [scale_], so we need to obtain the original picture size via
163     // [Measure()] to verify whether or not it has infinite edge.
164     auto rawPicSize = Measure();
165     if (!rawPicSize.IsValid() || rawPicSize.IsInfinite()) {
166         return Size();
167     }
168     uint8_t infiniteStatus = (static_cast<uint8_t>(imageComponentSize_.IsWidthInfinite()) << 1) |
169                              static_cast<uint8_t>(imageComponentSize_.IsHeightInfinite());
170     double pictureSizeRatio = pictureSize.Width() / pictureSize.Height();
171     Size backupImageSize = imageComponentSize_;
172     switch (infiniteStatus) {
173         case 0b00: // both width and height are infinite
174             backupImageSize = pictureSize;
175             break;
176         case 0b01: // only height is infinite
177             backupImageSize.SetHeight(imageComponentSize_.Width() / pictureSizeRatio);
178             break;
179         case 0b10: // only width is infinite
180             backupImageSize.SetWidth(imageComponentSize_.Height() * pictureSizeRatio);
181             break;
182         default:
183             backupImageSize = imageComponentSize_;
184             break;
185     }
186     return backupImageSize;
187 }
188 
NeedResize() const189 bool RenderImage::NeedResize() const
190 {
191     if (!resizeTarget_.IsValid()) {
192         return false;
193     }
194     if (!previousResizeTarget_.IsValid()) {
195         return true;
196     }
197     if (resizeTarget_ < previousResizeTarget_) {
198         return false;
199     }
200     double widthEnlargedBy = resizeTarget_.Width() / previousResizeTarget_.Width();
201     double heightEnlargedBy = resizeTarget_.Height() / previousResizeTarget_.Height();
202     if (widthEnlargedBy > RESIZE_AGAIN_THRESHOLD || heightEnlargedBy > RESIZE_AGAIN_THRESHOLD) {
203         return true;
204     }
205     return false;
206 }
207 
CalculateResizeTarget()208 void RenderImage::CalculateResizeTarget()
209 {
210     if (!srcRect_.IsValid()) {
211         return;
212     }
213     if (!autoResize_) {
214         resizeTarget_ = rawImageSize_;
215         resizeScale_ = Size(1.0, 1.0);
216         return;
217     }
218     double widthScale = dstRect_.Width() / srcRect_.Width() * scale_;
219     double heightScale = dstRect_.Height() / srcRect_.Height() * scale_;
220     if (widthScale < 1.0 && heightScale < 1.0) {
221         resizeScale_ = Size(widthScale, heightScale);
222     } else {
223         resizeScale_ = Size(1.0, 1.0);
224     }
225     resizeTarget_ = Size(rawImageSize_.Width() * resizeScale_.Width(), rawImageSize_.Height() * resizeScale_.Height());
226 }
227 
ApplyImageFit(Rect & srcRect,Rect & dstRect)228 void RenderImage::ApplyImageFit(Rect& srcRect, Rect& dstRect)
229 {
230     Size rawPicSize = srcRect.GetSize();
231     Size layoutSize = GetLayoutSize();
232     switch (imageFit_) {
233         case ImageFit::FILL:
234             break;
235         case ImageFit::NONE:
236             ApplyNone(srcRect, dstRect, rawPicSize, layoutSize);
237             break;
238         case ImageFit::COVER:
239             ApplyCover(srcRect, dstRect, rawPicSize, layoutSize);
240             break;
241         case ImageFit::FITWIDTH:
242             ApplyFitWidth(srcRect, dstRect, rawPicSize, layoutSize);
243             break;
244         case ImageFit::FITHEIGHT:
245             ApplyFitHeight(srcRect, dstRect, rawPicSize, layoutSize);
246             break;
247         case ImageFit::SCALEDOWN:
248             if (srcRect.GetSize() < dstRect.GetSize()) {
249                 ApplyNone(srcRect, dstRect, rawPicSize, layoutSize);
250             } else {
251                 ApplyContain(srcRect, dstRect, rawPicSize, layoutSize);
252             }
253             break;
254         case ImageFit::CONTAIN:
255             ApplyContain(srcRect, dstRect, rawPicSize, layoutSize);
256             break;
257         default:
258             ApplyContain(srcRect, dstRect, rawPicSize, layoutSize);
259             break;
260     }
261 }
262 
ApplyContain(Rect & srcRect,Rect & dstRect,const Size & rawPicSize,const Size & layoutSize)263 void RenderImage::ApplyContain(Rect& srcRect, Rect& dstRect, const Size& rawPicSize, const Size& layoutSize)
264 {
265     if (!rawPicSize.IsValid()) {
266         return;
267     }
268     if (Size::CalcRatio(srcRect) > Size::CalcRatio(dstRect)) {
269         dstRect.SetSize(rawPicSize * (layoutSize.Width() / rawPicSize.Width()));
270     } else {
271         dstRect.SetSize(rawPicSize * (layoutSize.Height() / rawPicSize.Height()));
272     }
273     dstRect.SetOffset(Alignment::GetAlignPosition(layoutSize, dstRect.GetSize(), alignment_));
274 }
275 
ApplyCover(Rect & srcRect,Rect & dstRect,const Size & rawPicSize,const Size & layoutSize)276 void RenderImage::ApplyCover(Rect& srcRect, Rect& dstRect, const Size& rawPicSize, const Size& layoutSize)
277 {
278     if (Size::CalcRatio(srcRect) > Size::CalcRatio(dstRect)) {
279         srcRect.SetSize(layoutSize * (rawPicSize.Height() / layoutSize.Height()));
280     } else {
281         srcRect.SetSize(layoutSize * (rawPicSize.Width() / layoutSize.Width()));
282     }
283     srcRect.SetOffset(Alignment::GetAlignPosition(rawPicSize, srcRect.GetSize(), alignment_));
284 }
285 
ApplyFitWidth(Rect & srcRect,Rect & dstRect,const Size & rawPicSize,const Size & layoutSize)286 void RenderImage::ApplyFitWidth(Rect& srcRect, Rect& dstRect, const Size& rawPicSize, const Size& layoutSize)
287 {
288     if (Size::CalcRatio(srcRect) > Size::CalcRatio(dstRect)) {
289         dstRect.SetSize(rawPicSize * (layoutSize.Width() / rawPicSize.Width()));
290         dstRect.SetOffset(Alignment::GetAlignPosition(layoutSize, dstRect.GetSize(), alignment_));
291     } else {
292         srcRect.SetSize(layoutSize * (rawPicSize.Width() / layoutSize.Width()));
293         srcRect.SetOffset(Alignment::GetAlignPosition(rawPicSize, srcRect.GetSize(), alignment_));
294     }
295 }
296 
ApplyFitHeight(Rect & srcRect,Rect & dstRect,const Size & rawPicSize,const Size & layoutSize)297 void RenderImage::ApplyFitHeight(Rect& srcRect, Rect& dstRect, const Size& rawPicSize, const Size& layoutSize)
298 {
299     if (Size::CalcRatio(srcRect) > Size::CalcRatio(dstRect)) {
300         srcRect.SetSize(layoutSize * (rawPicSize.Height() / layoutSize.Height()));
301         srcRect.SetOffset(Alignment::GetAlignPosition(rawPicSize, srcRect.GetSize(), alignment_));
302     } else {
303         dstRect.SetSize(rawPicSize * (layoutSize.Height() / rawPicSize.Height()));
304         dstRect.SetOffset(Alignment::GetAlignPosition(layoutSize, dstRect.GetSize(), alignment_));
305     }
306 }
307 
ApplyNone(Rect & srcRect,Rect & dstRect,const Size & rawPicSize,const Size & layoutSize)308 void RenderImage::ApplyNone(Rect& srcRect, Rect& dstRect, const Size& rawPicSize, const Size& layoutSize)
309 {
310     Size srcSize =
311         Size(std::min(layoutSize.Width(), rawPicSize.Width()), std::min(layoutSize.Height(), rawPicSize.Height()));
312     dstRect.SetRect(Alignment::GetAlignPosition(layoutSize, srcSize, alignment_), srcSize);
313     srcRect.SetRect(Alignment::GetAlignPosition(rawPicSize, srcSize, alignment_), srcSize);
314 }
315 
FireLoadEvent(const Size & picSize) const316 void RenderImage::FireLoadEvent(const Size& picSize) const
317 {
318     auto context = context_.Upgrade();
319     if (context && context->GetIsDeclarative()) {
320         if (loadImgSuccessEvent_ && (imageLoadingStatus_ == ImageLoadingStatus::LOAD_SUCCESS)) {
321             // here the last param of [loadImgSuccessEvent_] is [1],
322             // which means the callback is triggered by [OnLoadSuccess]
323             loadImgSuccessEvent_(std::make_shared<LoadImageSuccessEvent>(picSize.Width(), picSize.Height(),
324                 GetLayoutSize().Width(), GetLayoutSize().Height(), 1));
325         }
326         if (loadImgFailEvent_ && (imageLoadingStatus_ == ImageLoadingStatus::LOAD_FAIL)) {
327             loadImgFailEvent_(std::make_shared<LoadImageFailEvent>(GetLayoutSize().Width(), GetLayoutSize().Height()));
328         }
329         return;
330     }
331     std::string param;
332     if (loadSuccessEvent_ && (imageLoadingStatus_ == ImageLoadingStatus::LOAD_SUCCESS)) {
333         param = std::string("\"complete\",{\"width\":")
334                     .append(std::to_string(picSize.Width()))
335                     .append(",\"height\":")
336                     .append(std::to_string(picSize.Height()))
337                     .append("}");
338         loadSuccessEvent_(param);
339     }
340     if (loadFailEvent_ && (imageLoadingStatus_ == ImageLoadingStatus::LOAD_FAIL)) {
341         param = std::string("\"error\",{\"width\":")
342                     .append(std::to_string(picSize.Width()))
343                     .append(",\"height\":")
344                     .append(std::to_string(picSize.Height()))
345                     .append("}");
346         loadFailEvent_(param);
347     }
348     if (loadFailCallback_ && (imageLoadingStatus_ == ImageLoadingStatus::LOAD_FAIL)) {
349         loadFailCallback_();
350         loadFailCallback_ = nullptr;
351     }
352 }
353 
SetRadius(const Border & border)354 void RenderImage::SetRadius(const Border& border)
355 {
356     auto leftEdgeWidth = border.Left().GetWidth();
357     auto topEdgeWidth = border.Top().GetWidth();
358     auto rightEdgeWidth = border.Right().GetWidth();
359     auto bottomEdgeWidth = border.Bottom().GetWidth();
360     topLeftRadius_ = Radius(border.TopLeftRadius() - Radius(topEdgeWidth, leftEdgeWidth));
361     topRightRadius_ = Radius(border.TopRightRadius() - Radius(topEdgeWidth, rightEdgeWidth));
362     bottomLeftRadius_ = Radius(border.BottomLeftRadius() - Radius(bottomEdgeWidth, leftEdgeWidth));
363     bottomRightRadius_ = Radius(border.BottomRightRadius() - Radius(bottomEdgeWidth, rightEdgeWidth));
364 }
365 
IsSVG(const std::string & src,InternalResource::ResourceId resourceId)366 bool RenderImage::IsSVG(const std::string& src, InternalResource::ResourceId resourceId)
367 {
368     return ImageComponent::IsSvgSuffix(src) ||
369            (src.empty() && resourceId > InternalResource::ResourceId::SVG_START &&
370                resourceId < InternalResource::ResourceId::SVG_END);
371 }
372 
PerformLayoutBgImage()373 void RenderImage::PerformLayoutBgImage()
374 {
375     if (!background_) {
376         return;
377     }
378     if (!rawImageSize_.IsValid()) {
379         return;
380     }
381 
382     GenerateImageRects(rawImageSize_, imageSize_, imageRepeat_, imagePosition_);
383     srcRect_.SetOffset(Offset());
384     srcRect_.SetSize(rawImageSize_);
385     dstRect_.SetOffset(Offset());
386     dstRect_.SetSize(imageRenderSize_);
387 }
388 
389 // objectPosition
ApplyObjectPosition()390 void RenderImage::ApplyObjectPosition()
391 {
392     Size layoutSize = GetLayoutSize();
393     Offset offset;
394     if (imageObjectPosition_.GetSizeTypeX() == BackgroundImagePositionType::PX) {
395         offset.SetX((layoutSize.Width() - dstRect_.Width()) / 2 - imageObjectPosition_.GetSizeValueX());
396     } else {
397         offset.SetX(
398             (layoutSize.Width() - dstRect_.Width()) / 2 - imageObjectPosition_.GetSizeValueX() *
399             (layoutSize.Width() - dstRect_.Width()) / PERCENT_TRANSLATE);
400     }
401 
402     if (imageObjectPosition_.GetSizeTypeY() == BackgroundImagePositionType::PX) {
403         offset.SetY((layoutSize.Height() - dstRect_.Height()) / 2 - imageObjectPosition_.GetSizeValueY());
404     } else {
405         offset.SetY(
406             (layoutSize.Height() - dstRect_.Height()) / 2 - imageObjectPosition_.GetSizeValueY() *
407             (layoutSize.Height() - dstRect_.Height()) / PERCENT_TRANSLATE);
408     }
409     imageRenderPosition_ = offset;
410 }
411 
GenerateImageRects(const Size & srcSize,const BackgroundImageSize & imageSize,ImageRepeat imageRepeat,const BackgroundImagePosition & imagePosition)412 void RenderImage::GenerateImageRects(const Size& srcSize, const BackgroundImageSize& imageSize, ImageRepeat imageRepeat,
413     const BackgroundImagePosition& imagePosition)
414 {
415     rectList_.clear();
416     if (NearEqual(boxPaintSize_.Width(), Size::INFINITE_SIZE) ||
417         NearEqual(boxPaintSize_.Height(), Size::INFINITE_SIZE)) {
418         boxPaintSize_ = viewPort_;
419     }
420 
421     // Different with Image Repeat
422     imageRenderSize_ = CalculateImageRenderSize(srcSize, imageSize);
423     if (NearZero(imageRenderSize_.Width()) || NearZero(imageRenderSize_.Height())) {
424         return;
425     }
426     // Ceil render size
427     imageRenderSize_ = Size(ceil(imageRenderSize_.Width()), ceil(imageRenderSize_.Height()));
428 
429     CalculateImageRenderPosition(imagePosition);
430 
431     int32_t minX = 0;
432     int32_t minY = 0;
433     int32_t maxX = 0;
434     int32_t maxY = 0;
435     if (imageRepeat == ImageRepeat::REPEAT || imageRepeat == ImageRepeat::REPEATX) {
436         if (LessOrEqual(imageRenderPosition_.GetX(), 0.0)) {
437             minX = 0;
438             maxX = std::ceil((boxPaintSize_.Width() - imageRenderPosition_.GetX()) / imageRenderSize_.Width());
439         } else {
440             minX = std::floor((-imageRenderPosition_.GetX()) / imageRenderSize_.Width());
441             maxX = std::ceil((boxPaintSize_.Width() - imageRenderPosition_.GetX()) / imageRenderSize_.Width());
442         }
443     }
444 
445     if (imageRepeat == ImageRepeat::REPEAT || imageRepeat == ImageRepeat::REPEATY) {
446         if (LessOrEqual(imageRenderPosition_.GetY(), 0.0)) {
447             minY = 0;
448             maxY = std::ceil((boxPaintSize_.Height() - imageRenderPosition_.GetY()) / imageRenderSize_.Height());
449         } else {
450             minY = std::floor((-imageRenderPosition_.GetY()) / imageRenderSize_.Height());
451             maxY = std::ceil((boxPaintSize_.Height() - imageRenderPosition_.GetY()) / imageRenderSize_.Height());
452         }
453     }
454 
455     Rect imageCell = Rect(imageRenderPosition_, Size(imageRenderSize_.Width(), imageRenderSize_.Height()));
456     for (int32_t i = minY; i <= maxY; ++i) {
457         for (int32_t j = minX; j <= maxX; ++j) {
458             rectList_.emplace_back(imageCell + Offset(j * imageRenderSize_.Width(), i * imageRenderSize_.Height()));
459         }
460     }
461 
462     if (imageLoadingStatus_ == ImageLoadingStatus::LOAD_SUCCESS) {
463         currentDstRectList_ = rectList_;
464     }
465     LOGD("[BOX][Dep:%{public}d][%{public}p][IMAGE] Result: X:%{public}d-%{public}d, Y:%{public}d-%{public}d",
466         GetDepth(), this, minX, maxX, minY, maxY);
467 }
468 
CalculateImageRenderSize(const Size & srcSize,const BackgroundImageSize & imageSize) const469 Size RenderImage::CalculateImageRenderSize(const Size& srcSize, const BackgroundImageSize& imageSize) const
470 {
471     Size renderSize;
472     if (NearZero(srcSize.Width()) || NearZero(srcSize.Height()) || NearZero(boxPaintSize_.Width()) ||
473         NearZero(boxPaintSize_.Height())) {
474         return renderSize;
475     }
476 
477     if (!imageSize.IsValid()) {
478         return renderSize;
479     }
480 
481     if (imageSize.GetSizeTypeX() == BackgroundImageSizeType::CONTAIN ||
482         imageSize.GetSizeTypeX() == BackgroundImageSizeType::COVER) {
483         renderSize = CalculateImageRenderSizeWithSingleParam(srcSize, imageSize);
484     } else {
485         renderSize = CalculateImageRenderSizeWithDoubleParam(srcSize, imageSize);
486     }
487 
488     return renderSize;
489 }
490 
CalculateImageRenderSizeWithSingleParam(const Size & srcSize,const BackgroundImageSize & imageSize) const491 Size RenderImage::CalculateImageRenderSizeWithSingleParam(
492     const Size& srcSize, const BackgroundImageSize& imageSize) const
493 {
494     Size sizeRet;
495     if (NearZero(srcSize.Width()) || NearZero(srcSize.Height()) || NearZero(boxPaintSize_.Width()) ||
496         NearZero(boxPaintSize_.Height())) {
497         return sizeRet;
498     }
499     double renderSizeX = 0.0;
500     double renderSizeY = 0.0;
501     if (imageSize.GetSizeTypeX() == BackgroundImageSizeType::CONTAIN) {
502         double srcAspectRatio = srcSize.Width() / srcSize.Height();
503         double paintAspectRatio = boxPaintSize_.Width() / boxPaintSize_.Height();
504         renderSizeX = paintAspectRatio >= srcAspectRatio ? srcSize.Width() * (boxPaintSize_.Height() / srcSize.Height())
505                                                          : boxPaintSize_.Width();
506         renderSizeY = paintAspectRatio >= srcAspectRatio ? boxPaintSize_.Height()
507                                                          : srcSize.Height() * (boxPaintSize_.Width() / srcSize.Width());
508     } else if (imageSize.GetSizeTypeX() == BackgroundImageSizeType::COVER) {
509         double srcAspectRatio = srcSize.Width() / srcSize.Height();
510         double paintAspectRatio = boxPaintSize_.Width() / boxPaintSize_.Height();
511         renderSizeX = paintAspectRatio >= srcAspectRatio
512                           ? boxPaintSize_.Width()
513                           : srcSize.Width() * (boxPaintSize_.Height() / srcSize.Height());
514         renderSizeY = paintAspectRatio >= srcAspectRatio ? srcSize.Height() * (boxPaintSize_.Width() / srcSize.Width())
515                                                          : boxPaintSize_.Height();
516     }
517 
518     sizeRet.SetWidth(renderSizeX);
519     sizeRet.SetHeight(renderSizeY);
520     return sizeRet;
521 }
522 
CalculateImageRenderSizeWithDoubleParam(const Size & srcSize,const BackgroundImageSize & imageSize) const523 Size RenderImage::CalculateImageRenderSizeWithDoubleParam(
524     const Size& srcSize, const BackgroundImageSize& imageSize) const
525 {
526     Size sizeRet;
527     if (NearZero(srcSize.Width()) || NearZero(srcSize.Height()) || NearZero(boxPaintSize_.Width()) ||
528         NearZero(boxPaintSize_.Height())) {
529         return sizeRet;
530     }
531 
532     double renderSizeX = 0.0;
533     double renderSizeY = 0.0;
534     if (imageSize.GetSizeTypeX() == BackgroundImageSizeType::LENGTH) {
535         renderSizeX = imageSize.GetSizeValueX();
536     } else if (imageSize.GetSizeTypeX() == BackgroundImageSizeType::PERCENT) {
537         renderSizeX = boxPaintSize_.Width() * imageSize.GetSizeValueX() / PERCENT_TRANSLATE;
538     }
539 
540     if (imageSize.GetSizeTypeY() == BackgroundImageSizeType::LENGTH) {
541         renderSizeY = imageSize.GetSizeValueY();
542     } else if (imageSize.GetSizeTypeY() == BackgroundImageSizeType::PERCENT) {
543         renderSizeY = boxPaintSize_.Height() * imageSize.GetSizeValueY() / PERCENT_TRANSLATE;
544     }
545 
546     if (imageSize.GetSizeTypeX() == BackgroundImageSizeType::AUTO &&
547         imageSize.GetSizeTypeY() == BackgroundImageSizeType::AUTO) {
548         renderSizeX = srcSize.Width();
549         renderSizeY = srcSize.Height();
550     } else if (imageSize.GetSizeTypeX() == BackgroundImageSizeType::AUTO) {
551         renderSizeX = srcSize.Width() * (renderSizeY / srcSize.Height());
552     } else if (imageSize.GetSizeTypeY() == BackgroundImageSizeType::AUTO) {
553         renderSizeY = srcSize.Height() * (renderSizeX / srcSize.Width());
554     }
555 
556     sizeRet.SetWidth(renderSizeX);
557     sizeRet.SetHeight(renderSizeY);
558     if (!sizeRet.IsValid()) {
559         sizeRet = Size();
560     }
561     return sizeRet;
562 }
563 
CalculateImageRenderPosition(const BackgroundImagePosition & imagePosition)564 void RenderImage::CalculateImageRenderPosition(const BackgroundImagePosition& imagePosition)
565 {
566     Offset offset;
567 
568     if (imagePosition.GetSizeTypeX() == BackgroundImagePositionType::PX) {
569         offset.SetX(imagePosition.GetSizeValueX());
570     } else {
571         offset.SetX(
572             imagePosition.GetSizeValueX() * (boxPaintSize_.Width() - imageRenderSize_.Width()) / PERCENT_TRANSLATE);
573     }
574 
575     if (imagePosition.GetSizeTypeY() == BackgroundImagePositionType::PX) {
576         offset.SetY(imagePosition.GetSizeValueY());
577     } else {
578         offset.SetY(
579             imagePosition.GetSizeValueY() * (boxPaintSize_.Height() - imageRenderSize_.Height()) / PERCENT_TRANSLATE);
580     }
581 
582     imageRenderPosition_ = offset;
583 }
584 
ClearRenderObject()585 void RenderImage::ClearRenderObject()
586 {
587     RenderNode::ClearRenderObject();
588 
589     isImageSizeSet_ = false;
590     rawImageSizeUpdated_ = false;
591     matchTextDirection_ = false;
592     imageComponentSize_ = Size();
593     formerMaxSize_ = Size();
594     alignment_ = Alignment::CENTER;
595     imageLoadingStatus_ = ImageLoadingStatus::UNLOADED;
596 
597     imageFit_ = ImageFit::COVER;
598     imageRepeat_ = ImageRepeat::NOREPEAT;
599     rectList_.clear();
600     color_.reset();
601     sourceInfo_.Reset();
602     singleWidth_ = 0.0;
603     displaySrcWidth_ = 0.0;
604     scale_ = 1.0;
605     horizontalRepeatNum_ = 1.0;
606     rotate_ = 0.0;
607     keepOffsetZero_ = false;
608     resizeCallLoadImage_ = false;
609     frameCount_ = 0;
610     topLeftRadius_ = Radius(0.0);
611     topRightRadius_ = Radius(0.0);
612     bottomLeftRadius_ = Radius(0.0);
613     bottomRightRadius_ = Radius(0.0);
614     resizeScale_ = Size();
615     resizeTarget_ = Size();
616     previousResizeTarget_ = Size();
617     currentResizeScale_ = Size();
618     width_ = Dimension();
619     height_ = Dimension();
620     rawImageSize_ = Size();
621     renderAltImage_ = nullptr;
622     proceedPreviousLoading_ = false;
623     imageUpdateFunc_ = nullptr;
624     imageRenderFunc_ = nullptr;
625     background_ = false;
626     boxPaintSize_ = Size();
627     boxMarginOffset_ = Offset();
628     imageSize_ = BackgroundImageSize();
629     imagePosition_ = BackgroundImagePosition();
630     imageObjectPosition_ = ImageObjectPosition();
631     imageRenderSize_ = Size();
632     imageRenderPosition_ = Offset();
633     forceResize_ = false;
634     forceReload_ = false;
635     imageSizeForEvent_ =  { 0.0, 0.0 };
636     retryCnt_ = 0;
637 }
638 
PrintImageLog(const Size & srcSize,const BackgroundImageSize & imageSize,ImageRepeat imageRepeat,const BackgroundImagePosition & imagePosition) const639 void RenderImage::PrintImageLog(const Size& srcSize, const BackgroundImageSize& imageSize, ImageRepeat imageRepeat,
640     const BackgroundImagePosition& imagePosition) const
641 {
642     LOGD("[BOX][IMAGE][Dep:%{public}d] Param:Src W:%{public}.1lf, H:%{public}.1lf, Size:%{public}.1lf|%{public}d, "
643          "%{public}.1lf|%{public}d, Rep:%{public}u, Pos X:%{public}.1lf|%{public}d, Y:%{public}.1lf|%{public}d, "
644          "BoxPaint:%{public}.1lf * %{public}.1lf, MarginOffset: %{public}.1lf * %{public}.1lf",
645         GetDepth(), srcSize.Width(), srcSize.Height(), imageSize.GetSizeValueX(), imageSize.GetSizeTypeX(),
646         imageSize.GetSizeValueY(), imageSize.GetSizeTypeY(), imageRepeat, imagePosition.GetSizeValueX(),
647         imagePosition.GetSizeTypeX(), imagePosition.GetSizeValueY(), imagePosition.GetSizeTypeY(),
648         boxPaintSize_.Width(), boxPaintSize_.Height(), boxMarginOffset_.GetX(), boxMarginOffset_.GetY());
649     LOGD("[BOX][IMAGE][Dep:%{public}d] Result: Size:(%{public}.1lf*%{public}.1lf), Pos(%{public}.1lf,%{public}.1lf), "
650          "rect:%{public}s",
651         GetDepth(), imageRenderSize_.Width(), imageRenderSize_.Height(), imageRenderPosition_.GetX(),
652         imageRenderPosition_.GetY(), rectList_.front().ToString().c_str());
653 }
654 
Dump()655 void RenderImage::Dump()
656 {
657     DumpLog::GetInstance().AddDesc(std::string("UsingWideGamut: ").append(IsSourceWideGamut() ? "true" : "false"));
658 }
659 
660 } // namespace OHOS::Ace
661