• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2025 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 #define NAPI_VERSION 8
17 
18 #include "core/components_ng/pattern/image/image_pattern.h"
19 
20 #include "base/utils/multi_thread.h"
21 #include "base/image/image_perf.h"
22 #include "base/log/dump_log.h"
23 #include "base/network/download_manager.h"
24 #include "core/common/ace_engine_ext.h"
25 #include "core/common/ai/image_analyzer_manager.h"
26 #include "core/common/udmf/udmf_client.h"
27 #include "core/components/common/layout/constants.h"
28 #include "core/components/image/image_theme.h"
29 #include "core/components/text/text_theme.h"
30 #include "core/components/theme/icon_theme.h"
31 #include "core/components_ng/image_provider/image_utils.h"
32 #include "core/components_ng/pattern/image/image_content_modifier.h"
33 #include "core/components_ng/pattern/image/image_dfx.h"
34 #include "core/components_ng/pattern/image/image_layout_property.h"
35 #include "core/components_ng/pattern/image/image_paint_method.h"
36 #include "core/components_ng/property/border_property.h"
37 #include "core/components_ng/render/drawing.h"
38 #include "core/pipeline_ng/pipeline_context.h"
39 
40 namespace OHOS::Ace::NG {
41 namespace {
42 constexpr int32_t DEFAULT_DURATION = 1000; // ms
43 constexpr uint32_t CRITICAL_TIME = 50;     // ms. If show time of image is less than this, use more cacheImages.
44 constexpr int64_t MICROSEC_TO_MILLISEC = 1000;
45 constexpr int32_t DEFAULT_ITERATIONS = 1;
46 constexpr int32_t MEMORY_LEVEL_CRITICAL_STATUS = 2;
47 constexpr size_t URL_SAVE_LENGTH = 15;
48 constexpr size_t URL_KEEP_TOTAL_LENGTH = 30;
49 constexpr int32_t NEED_MASK_INDEX = 3;
50 constexpr int32_t KERNEL_MAX_LENGTH_EXCEPT_OTHER = 245;
51 constexpr size_t NEED_MASK_START_OFFSET = 2;
52 
GetImageInterpolation(ImageInterpolation interpolation)53 std::string GetImageInterpolation(ImageInterpolation interpolation)
54 {
55     switch (interpolation) {
56         case ImageInterpolation::LOW:
57             return "LOW";
58         case ImageInterpolation::MEDIUM:
59             return "MEDIUM";
60         case ImageInterpolation::HIGH:
61             return "HIGH";
62         default:
63             return "NONE";
64     }
65 }
66 
GetDynamicModeString(DynamicRangeMode dynamicMode)67 std::string GetDynamicModeString(DynamicRangeMode dynamicMode)
68 {
69     switch (dynamicMode) {
70         case DynamicRangeMode::HIGH:
71             return "HIGH";
72         case DynamicRangeMode::CONSTRAINT:
73             return "CONSTRAINT";
74         case DynamicRangeMode::STANDARD:
75             return "STANDARD";
76         default:
77             return "STANDARD";
78     }
79 }
80 
ConvertOrientationToString(ImageRotateOrientation orientation)81 std::string ConvertOrientationToString(ImageRotateOrientation orientation)
82 {
83     switch (orientation) {
84         case ImageRotateOrientation::UP:
85             return "UP";
86         case ImageRotateOrientation::RIGHT:
87             return "RIGHT";
88         case ImageRotateOrientation::DOWN:
89             return "DOWN";
90         case ImageRotateOrientation::LEFT:
91             return "LEFT";
92         case ImageRotateOrientation::UP_MIRRORED:
93             return "UP_MIRRORED";
94         case ImageRotateOrientation::RIGHT_MIRRORED:
95             return "RIGHT_MIRRORED";
96         case ImageRotateOrientation::DOWN_MIRRORED:
97             return "DOWN_MIRRORED";
98         case ImageRotateOrientation::LEFT_MIRRORED:
99             return "LEFT_MIRRORED";
100         case ImageRotateOrientation::AUTO:
101             return "AUTO";
102         default:
103             return "UP";
104     }
105 }
106 } // namespace
107 
108 constexpr float BOX_EPSILON = 0.5f;
109 constexpr float IMAGE_SENSITIVE_RADIUS = 80.0f;
110 constexpr double IMAGE_SENSITIVE_SATURATION = 1.0;
111 constexpr double IMAGE_SENSITIVE_BRIGHTNESS = 1.08;
112 constexpr uint32_t MAX_SRC_LENGTH = 120; // prevent the Base64 image format from too long.
113 constexpr int32_t IMAGE_LOAD_FAIL = 0;
114 constexpr int32_t IMAGE_LOAD_SUCCESS = 1;
115 
ImagePattern()116 ImagePattern::ImagePattern()
117 {
118     InitDefaultValue();
119     ImageAnimatorPattern();
120 }
121 
~ImagePattern()122 ImagePattern::~ImagePattern()
123 {
124     if (isEnableAnalyzer_) {
125         ReleaseImageAnalyzer();
126     }
127 }
128 
CreateDataReadyCallback()129 DataReadyNotifyTask ImagePattern::CreateDataReadyCallback()
130 {
131     return [weak = WeakClaim(this)](const ImageSourceInfo& sourceInfo) {
132         auto pattern = weak.Upgrade();
133         CHECK_NULL_VOID(pattern);
134         auto imageLayoutProperty = pattern->GetLayoutProperty<ImageLayoutProperty>();
135         CHECK_NULL_VOID(imageLayoutProperty);
136         auto currentSourceInfo = imageLayoutProperty->GetImageSourceInfo().value_or(ImageSourceInfo(""));
137         if (currentSourceInfo != sourceInfo) {
138             TAG_LOGW(AceLogTag::ACE_IMAGE, "src not match, %{public}s: %{private}s - %{private}s",
139                 pattern->imageDfxConfig_.ToStringWithoutSrc().c_str(), currentSourceInfo.ToString().c_str(),
140                 sourceInfo.ToString().c_str());
141             return;
142         }
143         pattern->OnImageDataReady();
144     };
145 }
146 
CreateLoadSuccessCallback()147 LoadSuccessNotifyTask ImagePattern::CreateLoadSuccessCallback()
148 {
149     return [weak = WeakClaim(this)](const ImageSourceInfo& sourceInfo) {
150         auto pattern = weak.Upgrade();
151         CHECK_NULL_VOID(pattern);
152         auto imageLayoutProperty = pattern->GetLayoutProperty<ImageLayoutProperty>();
153         CHECK_NULL_VOID(imageLayoutProperty);
154         auto currentSourceInfo = imageLayoutProperty->GetImageSourceInfo().value_or(ImageSourceInfo(""));
155         if (currentSourceInfo != sourceInfo) {
156             TAG_LOGW(AceLogTag::ACE_IMAGE, "src not match, %{public}s: %{private}s - %{private}s",
157                 pattern->imageDfxConfig_.ToStringWithoutSrc().c_str(), currentSourceInfo.ToString().c_str(),
158                 sourceInfo.ToString().c_str());
159             return;
160         }
161         pattern->OnImageLoadSuccess();
162     };
163 }
164 
CreateLoadFailCallback()165 LoadFailNotifyTask ImagePattern::CreateLoadFailCallback()
166 {
167     return [weak = WeakClaim(this)](
168                const ImageSourceInfo& sourceInfo, const std::string& errorMsg, const ImageErrorInfo& errorInfo) {
169         auto pattern = weak.Upgrade();
170         CHECK_NULL_VOID(pattern);
171         auto imageLayoutProperty = pattern->GetLayoutProperty<ImageLayoutProperty>();
172         CHECK_NULL_VOID(imageLayoutProperty);
173         auto currentSourceInfo = imageLayoutProperty->GetImageSourceInfo().value_or(ImageSourceInfo(""));
174         if (currentSourceInfo != sourceInfo) {
175             TAG_LOGW(AceLogTag::ACE_IMAGE, "src not match, %{public}s: %{private}s - %{private}s",
176                 pattern->imageDfxConfig_.ToStringWithoutSrc().c_str(), currentSourceInfo.ToString().c_str(),
177                 sourceInfo.ToString().c_str());
178             return;
179         }
180         if (!currentSourceInfo.IsFromReset()) {
181             pattern->OnImageLoadFail(errorMsg, errorInfo);
182         }
183     };
184 }
185 
CreateCompleteCallBackInDataReady()186 OnCompleteInDataReadyNotifyTask ImagePattern::CreateCompleteCallBackInDataReady()
187 {
188     return [weak = WeakClaim(this)](const ImageSourceInfo& sourceInfo) {
189         auto pattern = weak.Upgrade();
190         CHECK_NULL_VOID(pattern);
191         auto imageLayoutProperty = pattern->GetLayoutProperty<ImageLayoutProperty>();
192         CHECK_NULL_VOID(imageLayoutProperty);
193         auto currentSourceInfo = imageLayoutProperty->GetImageSourceInfo().value_or(ImageSourceInfo(""));
194         if (currentSourceInfo != sourceInfo) {
195             TAG_LOGW(AceLogTag::ACE_IMAGE, "src not match, %{public}s: %{private}s - %{private}s",
196                 pattern->imageDfxConfig_.ToStringWithoutSrc().c_str(), currentSourceInfo.ToString().c_str(),
197                 sourceInfo.ToString().c_str());
198             return;
199         }
200         pattern->OnCompleteInDataReady();
201     };
202 }
203 
OnCompleteInDataReady()204 void ImagePattern::OnCompleteInDataReady()
205 {
206     auto host = GetHost();
207     CHECK_NULL_VOID(host);
208     const auto& geometryNode = host->GetGeometryNode();
209     CHECK_NULL_VOID(geometryNode);
210     auto imageEventHub = GetOrCreateEventHub<ImageEventHub>();
211     CHECK_NULL_VOID(imageEventHub);
212     CHECK_NULL_VOID(loadingCtx_);
213     LoadImageSuccessEvent event(loadingCtx_->GetImageSize().Width(), loadingCtx_->GetImageSize().Height(),
214         geometryNode->GetFrameSize().Width(), geometryNode->GetFrameSize().Height(), 0,
215         geometryNode->GetContentSize().Width(), geometryNode->GetContentSize().Height(),
216         geometryNode->GetContentOffset().GetX(), geometryNode->GetContentOffset().GetY());
217     imageEventHub->FireCompleteEvent(event);
218 }
219 
TriggerFirstVisibleAreaChange()220 void ImagePattern::TriggerFirstVisibleAreaChange()
221 {
222     if (isComponentSnapshotNode_ || isImageAnimator_) {
223         OnVisibleAreaChange(true);
224         return;
225     }
226     OnVisibleAreaChange(previousVisibility_);
227 }
228 
PrepareAnimation(const RefPtr<CanvasImage> & image)229 void ImagePattern::PrepareAnimation(const RefPtr<CanvasImage>& image)
230 {
231     if (image->IsStatic()) {
232         return;
233     }
234     SetRedrawCallback(image);
235     SetOnFinishCallback(image);
236     RegisterVisibleAreaChange();
237     TriggerFirstVisibleAreaChange();
238 }
239 
SetOnFinishCallback(const RefPtr<CanvasImage> & image)240 void ImagePattern::SetOnFinishCallback(const RefPtr<CanvasImage>& image)
241 {
242     CHECK_NULL_VOID(image);
243     image->SetOnFinishCallback([weak = WeakPtr(GetHost())] {
244         auto imageNode = weak.Upgrade();
245         CHECK_NULL_VOID(imageNode);
246         auto eventHub = imageNode->GetOrCreateEventHub<ImageEventHub>();
247         if (eventHub) {
248             eventHub->FireFinishEvent();
249         }
250     });
251 }
252 
SetRedrawCallback(const RefPtr<CanvasImage> & image)253 void ImagePattern::SetRedrawCallback(const RefPtr<CanvasImage>& image)
254 {
255     CHECK_NULL_VOID(image);
256     // set animation flush function for svg / gif
257     image->SetRedrawCallback([weak = WeakPtr(GetHost())] {
258         auto imageNode = weak.Upgrade();
259         CHECK_NULL_VOID(imageNode);
260         imageNode->MarkNeedRenderOnly();
261     });
262 }
263 
RegisterVisibleAreaChange(bool isCalcClip)264 void ImagePattern::RegisterVisibleAreaChange(bool isCalcClip)
265 {
266     auto pipeline = GetContext();
267     // register to onVisibleAreaChange
268     CHECK_NULL_VOID(pipeline);
269     auto callback = [weak = WeakClaim(this)](bool visible, double ratio) {
270         auto self = weak.Upgrade();
271         CHECK_NULL_VOID(self);
272         self->OnVisibleAreaChange(visible, ratio);
273     };
274     auto host = GetHost();
275     CHECK_NULL_VOID(host);
276     // add visibleAreaChangeNode(inner callback)
277     std::vector<double> ratioList = { 0.0 };
278     pipeline->AddVisibleAreaChangeNode(host, ratioList, callback, false, isCalcClip);
279 }
280 
CheckHandles(SelectHandleInfo & handleInfo)281 void ImagePattern::CheckHandles(SelectHandleInfo& handleInfo)
282 {
283     auto host = GetHost();
284     CHECK_NULL_VOID(host);
285     auto renderContext = host->GetRenderContext();
286     CHECK_NULL_VOID(renderContext);
287     if (!renderContext->GetClipEdge().value_or(true)) {
288         return;
289     }
290     // use global offset.
291     const auto& geometryNode = host->GetGeometryNode();
292     auto contentRect = geometryNode->GetContentRect();
293     RectF visibleContentRect(contentRect.GetOffset() + parentGlobalOffset_, contentRect.GetSize());
294     auto parent = host->GetAncestorNodeOfFrame(true);
295     visibleContentRect = GetVisibleContentRect(parent, visibleContentRect);
296     auto paintRect = handleInfo.paintRect;
297     PointF bottomPoint = { paintRect.Left(), paintRect.Bottom() - BOX_EPSILON };
298     PointF topPoint = { paintRect.Left(), paintRect.Top() + BOX_EPSILON };
299     handleInfo.isShow = visibleContentRect.IsInRegion(bottomPoint) && visibleContentRect.IsInRegion(topPoint);
300 }
301 
CalAndUpdateSelectOverlay()302 void ImagePattern::CalAndUpdateSelectOverlay()
303 {
304     auto host = GetHost();
305     CHECK_NULL_VOID(host);
306     auto rect = host->GetTransformRectRelativeToWindow();
307     SelectOverlayInfo info;
308     const auto& geometryNode = host->GetGeometryNode();
309     CHECK_NULL_VOID(geometryNode);
310     SizeF handleSize = { SelectHandleInfo::GetDefaultLineWidth().ConvertToPx(),
311         geometryNode->GetContentSize().Height() };
312     info.firstHandle.paintRect = RectF(rect.GetOffset(), handleSize);
313     CheckHandles(info.firstHandle);
314     OffsetF offset(rect.Width() - handleSize.Width(), rect.Height() - handleSize.Height());
315     info.secondHandle.paintRect = RectF(rect.GetOffset() + offset, handleSize);
316     CheckHandles(info.secondHandle);
317     selectOverlay_->UpdateFirstAndSecondHandleInfo(info.firstHandle, info.secondHandle);
318 }
319 
GetParentGlobalOffset() const320 OffsetF ImagePattern::GetParentGlobalOffset() const
321 {
322     auto host = GetHost();
323     CHECK_NULL_RETURN(host, {});
324     auto pipeline = host->GetContext();
325     CHECK_NULL_RETURN(pipeline, {});
326     auto rootOffset = pipeline->GetRootRect().GetOffset();
327     return host->GetPaintRectOffset(false, true) - rootOffset;
328 }
329 
OnAreaChangedInner()330 void ImagePattern::OnAreaChangedInner()
331 {
332     if (selectOverlay_ && !selectOverlay_->IsClosed()) {
333         auto parentGlobalOffset = GetParentGlobalOffset();
334         if (parentGlobalOffset != parentGlobalOffset_) {
335             parentGlobalOffset_ = parentGlobalOffset;
336             CalAndUpdateSelectOverlay();
337         }
338     }
339 }
340 
RemoveAreaChangeInner()341 void ImagePattern::RemoveAreaChangeInner()
342 {
343     auto pipeline = GetContext();
344     CHECK_NULL_VOID(pipeline);
345     auto host = GetHost();
346     CHECK_NULL_VOID(host);
347     auto eventHub = host->GetOrCreateEventHub<ImageEventHub>();
348     CHECK_NULL_VOID(eventHub);
349     if (eventHub->HasOnAreaChanged()) {
350         return;
351     }
352     pipeline->RemoveOnAreaChangeNode(host->GetId());
353 }
354 
CalcImageContentPaintSize(const RefPtr<GeometryNode> & geometryNode)355 RectF ImagePattern::CalcImageContentPaintSize(const RefPtr<GeometryNode>& geometryNode)
356 {
357     RectF paintSize;
358     auto imageRenderProperty = GetPaintProperty<ImageRenderProperty>();
359     CHECK_NULL_RETURN(imageRenderProperty, paintSize);
360     ImageRepeat repeat = imageRenderProperty->GetImageRepeat().value_or(ImageRepeat::NO_REPEAT);
361     bool imageRepeatX = repeat == ImageRepeat::REPEAT || repeat == ImageRepeat::REPEAT_X;
362     bool imageRepeatY = repeat == ImageRepeat::REPEAT || repeat == ImageRepeat::REPEAT_Y;
363 
364     if (loadingCtx_->GetSourceInfo().IsSvg()) {
365         const float invalidValue = -1;
366         paintSize.SetWidth(dstRect_.IsValid() ? dstRect_.Width() : invalidValue);
367         paintSize.SetHeight(dstRect_.IsValid() ? dstRect_.Height() : invalidValue);
368         paintSize.SetLeft(
369             dstRect_.IsValid() ? dstRect_.GetX() + geometryNode->GetContentOffset().GetX() : invalidValue);
370         paintSize.SetTop(dstRect_.IsValid() ? dstRect_.GetY() + geometryNode->GetContentOffset().GetY() : invalidValue);
371     } else {
372         paintSize.SetWidth(imageRepeatX ? geometryNode->GetContentSize().Width() : dstRect_.Width());
373         paintSize.SetHeight(imageRepeatY ? geometryNode->GetContentSize().Height() : dstRect_.Height());
374         paintSize.SetLeft((imageRepeatX ? 0 : dstRect_.GetX()) + geometryNode->GetContentOffset().GetX());
375         paintSize.SetTop((imageRepeatY ? 0 : dstRect_.GetY()) + geometryNode->GetContentOffset().GetY());
376     }
377     return paintSize;
378 }
379 
ClearAltData()380 void ImagePattern::ClearAltData()
381 {
382     altLoadingCtx_ = nullptr;
383     altImage_ = nullptr;
384     altDstRect_.reset();
385     altSrcRect_.reset();
386 }
387 
ApplyAIModificationsToImage()388 void ImagePattern::ApplyAIModificationsToImage()
389 {
390     auto host = GetHost();
391     CHECK_NULL_VOID(host);
392     const auto& geometryNode = host->GetGeometryNode();
393     CHECK_NULL_VOID(geometryNode);
394     if (IsSupportImageAnalyzerFeature()) {
395         if (isPixelMapChanged_) {
396             UpdateAnalyzerOverlay();
397         }
398         UpdateAnalyzerUIConfig(geometryNode);
399         auto context = host->GetContext();
400         CHECK_NULL_VOID(context);
401         auto uiTaskExecutor = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::UI);
402         uiTaskExecutor.PostTask(
403             [weak = WeakClaim(this)] {
404                 auto pattern = weak.Upgrade();
405                 CHECK_NULL_VOID(pattern);
406                 ContainerScope scope(pattern->GetHostInstanceId());
407                 pattern->CreateAnalyzerOverlay();
408             },
409             "ArkUIImageCreateAnalyzerOverlay");
410     }
411 }
412 
ReportPerfData(const RefPtr<NG::FrameNode> & host,int32_t state)413 void ImagePattern::ReportPerfData(const RefPtr<NG::FrameNode>& host, int32_t state)
414 {
415     auto accessibilityId = host->GetAccessibilityId();
416     auto geometryNode = host->GetGeometryNode();
417     CHECK_NULL_VOID(geometryNode);
418     auto type = loadingCtx_->GetSourceInfo().GetSrcType();
419     std::string srcType = GetSrcTypeToString(type);
420     std::pair<int32_t, int32_t> size(geometryNode->GetFrameSize().Width(), geometryNode->GetFrameSize().Height());
421     ImagePerf::GetPerfMonitor()->EndRecordImageLoadStat(accessibilityId, srcType, size, state);
422 }
423 
OnImageLoadSuccess()424 void ImagePattern::OnImageLoadSuccess()
425 {
426     CHECK_NULL_VOID(loadingCtx_);
427     auto host = GetHost();
428     CHECK_NULL_VOID(host);
429     const auto& geometryNode = host->GetGeometryNode();
430     CHECK_NULL_VOID(geometryNode);
431 
432     image_ = loadingCtx_->MoveCanvasImage();
433     if (!image_) {
434         TAG_LOGW(AceLogTag::ACE_IMAGE, "%{public}s, %{private}s image is null.",
435             imageDfxConfig_.ToStringWithoutSrc().c_str(), imageDfxConfig_.GetImageSrc().c_str());
436         return;
437     }
438     srcRect_ = loadingCtx_->GetSrcRect();
439     dstRect_ = loadingCtx_->GetDstRect();
440     auto srcInfo = loadingCtx_->GetSourceInfo();
441     auto frameCount = loadingCtx_->GetFrameCount();
442     imageDfxConfig_.SetFrameSize(geometryNode->GetFrameSize().Width(), geometryNode->GetFrameSize().Height());
443 
444     image_->SetImageDfxConfig(imageDfxConfig_);
445 
446     SetImagePaintConfig(image_, srcRect_, dstRect_, srcInfo, frameCount);
447     if (srcInfo.IsSvg()) {
448         UpdateSvgSmoothEdgeValue();
449     }
450     PrepareAnimation(image_);
451     if (enableDrag_) {
452         EnableDrag();
453     }
454     ClearAltData();
455 
456     ApplyAIModificationsToImage();
457 
458     ACE_SCOPED_TRACE("OnImageLoadSuccess %s", imageDfxConfig_.ToStringWithSrc().c_str());
459     if (SystemProperties::GetDebugEnabled()) {
460         TAG_LOGI(AceLogTag::ACE_IMAGE, "ImageLoadSuccess %{public}s", imageDfxConfig_.ToStringWithSrc().c_str());
461     }
462     auto context = host->GetRenderContext();
463     auto pixelMap = image_->GetPixelMap();
464     if (pixelMap) {
465         SetPixelMapMemoryName(pixelMap);
466     }
467     if (context && pixelMap) {
468         context->SetColorGamut(pixelMap->GetInnerColorGamut());
469     }
470     ReportPerfData(host, IMAGE_LOAD_SUCCESS);
471     /*
472     * Trigger the completion callback. Since the callback is executed externally and its behavior
473     * is not controlled here, it may lead to object mutation or destruction. Therefore, avoid
474     * accessing internal member pointers or state after this call to prevent use-after-free
475     * issues or crashes.
476     */
477     RectF paintRect = CalcImageContentPaintSize(geometryNode);
478     LoadImageSuccessEvent event(loadingCtx_->GetImageSize().Width(), loadingCtx_->GetImageSize().Height(),
479         geometryNode->GetFrameSize().Width(), geometryNode->GetFrameSize().Height(), 1, paintRect.Width(),
480         paintRect.Height(), paintRect.GetX(), paintRect.GetY());
481     auto eventHub = GetOrCreateEventHub<ImageEventHub>();
482     if (eventHub) {
483         eventHub->FireCompleteEvent(event);
484     }
485     host->MarkNeedRenderOnly();
486 }
487 
SetPixelMapMemoryName(RefPtr<PixelMap> & pixelMap)488 bool ImagePattern::SetPixelMapMemoryName(RefPtr<PixelMap>& pixelMap)
489 {
490     auto host = GetHost();
491     CHECK_NULL_RETURN(host, false);
492     auto id = host->GetInspectorId();
493     if (id.has_value()) {
494         std::string result = std::string("id:") + id.value();
495         pixelMap->SetMemoryName(result);
496         hasSetPixelMapMemoryName_ = true;
497         return true;
498     }
499     auto imageLayoutProperty = GetLayoutProperty<ImageLayoutProperty>();
500     CHECK_NULL_RETURN(imageLayoutProperty, false);
501     auto imageSourceInfo = imageLayoutProperty->GetImageSourceInfo();
502     if (imageSourceInfo.has_value() && !imageSourceInfo->GetPixmap()) {
503         pixelMap->SetMemoryName(HandleSrcForMemoryName(imageSourceInfo->GetSrc()));
504     }
505     return false;
506 }
507 
HandleSrcForMemoryName(std::string url)508 std::string ImagePattern::HandleSrcForMemoryName(std::string url)
509 {
510     auto imageObj = loadingCtx_->GetImageObject();
511     CHECK_NULL_RETURN(imageObj, "");
512     auto width = imageObj->GetImageSize().Width();
513     auto height = imageObj->GetImageSize().Height();
514     if (url.length() > KERNEL_MAX_LENGTH_EXCEPT_OTHER) {
515         url = url.substr(url.size() - KERNEL_MAX_LENGTH_EXCEPT_OTHER);
516     }
517     std::string result = std::to_string(static_cast<int>(width)) + std::string("x") +
518         std::to_string(static_cast<int>(height)) + std::string("-") + MaskUrl(url);
519     return result;
520 }
521 
MaskUrl(std::string url)522 std::string ImagePattern::MaskUrl(std::string url)
523 {
524     const size_t urlLength = url.length();
525     if (urlLength < URL_KEEP_TOTAL_LENGTH) {
526         for (size_t i = NEED_MASK_START_OFFSET; i < urlLength; i += NEED_MASK_INDEX) {
527             url[i] = '*';
528         }
529         return url;
530     }
531 
532     // Long URL: keep head and tail, mask middle fully, and partially mask tail
533     std::string result;
534     // Pre-allocate memory to avoid multiple reallocations during string appends, improving performance
535     result.reserve(urlLength);
536     // 1. prefix: keep first URL_SAVE_LENGTH characters
537     result.append(url.substr(0, URL_SAVE_LENGTH));
538     // 2. middle: replace with stars
539     const size_t middleLength = urlLength - URL_KEEP_TOTAL_LENGTH;
540     result.append(middleLength, '*');
541     // 3. suffix: apply masked pattern on the last URL_SAVE_LENGTH chars
542     size_t suffixStart = urlLength - URL_SAVE_LENGTH;
543     for (size_t i = 0; i < URL_SAVE_LENGTH; ++i) {
544         if (i % NEED_MASK_INDEX == NEED_MASK_START_OFFSET) {
545             result += '*';
546         } else {
547             result += url[suffixStart + i];
548         }
549     }
550     return result;
551 }
552 
CheckIfNeedLayout()553 bool ImagePattern::CheckIfNeedLayout()
554 {
555     auto host = GetHost();
556     CHECK_NULL_RETURN(host, true);
557     CHECK_NULL_RETURN(host->GetGeometryNode()->GetContent(), true);
558     const auto& props = DynamicCast<ImageLayoutProperty>(host->GetLayoutProperty());
559     CHECK_NULL_RETURN(props, true);
560     const auto& layoutConstraint = props->GetCalcLayoutConstraint();
561     CHECK_NULL_RETURN(layoutConstraint, true);
562     return !(layoutConstraint->selfIdealSize && layoutConstraint->selfIdealSize->IsValid());
563 }
564 
OnImageDataReady()565 void ImagePattern::OnImageDataReady()
566 {
567     CHECK_NULL_VOID(loadingCtx_);
568     auto host = GetHost();
569     CHECK_NULL_VOID(host);
570     const auto& geometryNode = host->GetGeometryNode();
571     CHECK_NULL_VOID(geometryNode);
572     // update rotate orientation before decoding
573     UpdateOrientation();
574 
575     if (CheckIfNeedLayout()) {
576         host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
577         return;
578     }
579 
580     // 1. If PropertyChangeFlag contains PROPERTY_UPDATE_MEASURE,
581     //    the image will be decoded after layout.
582     // 2. The image node in imageAnimator will not be decoded after layout, decode directly.
583     auto layoutProp = host->GetLayoutProperty<ImageLayoutProperty>();
584     CHECK_NULL_VOID(layoutProp);
585     if (!((layoutProp->GetPropertyChangeFlag() & PROPERTY_UPDATE_MEASURE) == PROPERTY_UPDATE_MEASURE) ||
586         isImageAnimator_) {
587         StartDecoding(geometryNode->GetContentSize());
588     }
589 }
590 
591 // Update the necessary rotate orientation for drawing and measuring.
UpdateOrientation()592 void ImagePattern::UpdateOrientation()
593 {
594     auto imageObj = loadingCtx_->GetImageObject();
595     CHECK_NULL_VOID(imageObj);
596     if (imageObj->GetFrameCount() > 1) {
597         imageObj->SetOrientation(ImageRotateOrientation::UP);
598         return;
599     }
600     imageObj->SetUserOrientation(userOrientation_);
601     selfOrientation_ = imageObj->GetOrientation();
602     if (userOrientation_ == ImageRotateOrientation::UP) {
603         joinOrientation_ = ImageRotateOrientation::UP;
604         return;
605     }
606     if (userOrientation_ == ImageRotateOrientation::AUTO) {
607         joinOrientation_ = selfOrientation_;
608     } else {
609         joinOrientation_ = userOrientation_;
610     }
611     // update image object orientation before decoding
612     imageObj->SetOrientation(joinOrientation_);
613 }
614 
OnImageLoadFail(const std::string & errorMsg,const ImageErrorInfo & errorInfo)615 void ImagePattern::OnImageLoadFail(const std::string& errorMsg, const ImageErrorInfo& errorInfo)
616 {
617     auto host = GetHost();
618     CHECK_NULL_VOID(host);
619     const auto& geometryNode = host->GetGeometryNode();
620     auto imageEventHub = GetOrCreateEventHub<ImageEventHub>();
621     CHECK_NULL_VOID(imageEventHub);
622     LoadImageFailEvent event(
623         geometryNode->GetFrameSize().Width(), geometryNode->GetFrameSize().Height(), errorMsg, errorInfo);
624     ReportPerfData(host, IMAGE_LOAD_FAIL);
625     imageEventHub->FireErrorEvent(event);
626 }
627 
SetExternalDecodeFormat(PixelFormat externalDecodeFormat)628 void ImagePattern::SetExternalDecodeFormat(PixelFormat externalDecodeFormat)
629 {
630     isImageReloadNeeded_ = isImageReloadNeeded_ | (externalDecodeFormat_ != externalDecodeFormat);
631     switch (externalDecodeFormat) {
632         case PixelFormat::NV21:
633         case PixelFormat::RGBA_8888:
634         case PixelFormat::RGBA_1010102:
635         case PixelFormat::YCBCR_P010:
636         case PixelFormat::YCRCB_P010:
637             externalDecodeFormat_ = externalDecodeFormat;
638             break;
639         default:
640             externalDecodeFormat_ = PixelFormat::UNKNOWN;
641     }
642 }
643 
StartDecoding(const SizeF & dstSize)644 void ImagePattern::StartDecoding(const SizeF& dstSize)
645 {
646     // if layout size has not decided yet, resize target can not be calculated
647     auto host = GetHost();
648     CHECK_NULL_VOID(host);
649     if (!host->GetGeometryNode()->GetContent()) {
650         return;
651     }
652 
653     ACE_SCOPED_TRACE("StartDecoding imageInfo: [%s]", imageDfxConfig_.ToStringWithSrc().c_str());
654 
655     const auto& props = DynamicCast<ImageLayoutProperty>(host->GetLayoutProperty());
656     CHECK_NULL_VOID(props);
657     bool autoResize = props->GetAutoResize().value_or(autoResizeDefault_);
658 
659     ImageFit imageFit = props->GetImageFit().value_or(ImageFit::COVER);
660     const std::optional<SizeF>& sourceSize = props->GetSourceSize();
661     auto renderProp = host->GetPaintProperty<ImageRenderProperty>();
662     bool hasValidSlice = renderProp && (renderProp->HasImageResizableSlice() || renderProp->HasImageResizableLattice());
663     bool isHdrDecoderNeed = renderProp && (renderProp->HasDynamicMode() || renderProp->HasHdrBrightness());
664 
665     if (loadingCtx_) {
666         loadingCtx_->SetIsHdrDecoderNeed(isHdrDecoderNeed);
667         loadingCtx_->SetImageQuality(GetImageQuality());
668         loadingCtx_->SetPhotoDecodeFormat(GetExternalDecodeFormat());
669         loadingCtx_->MakeCanvasImageIfNeed(dstSize, autoResize, imageFit, sourceSize, hasValidSlice);
670     }
671     if (altLoadingCtx_) {
672         altLoadingCtx_->SetIsHdrDecoderNeed(isHdrDecoderNeed);
673         altLoadingCtx_->SetImageQuality(GetImageQuality());
674         altLoadingCtx_->SetPhotoDecodeFormat(GetExternalDecodeFormat());
675         altLoadingCtx_->MakeCanvasImageIfNeed(dstSize, autoResize, imageFit, sourceSize, hasValidSlice);
676     }
677 }
678 
UpdateSvgSmoothEdgeValue()679 void ImagePattern::UpdateSvgSmoothEdgeValue()
680 {
681     auto renderProp = GetPaintProperty<ImageRenderProperty>();
682     CHECK_NULL_VOID(renderProp);
683     renderProp->UpdateSmoothEdge(std::max(smoothEdge_, renderProp->GetSmoothEdge().value_or(0.0f)));
684 }
685 
SetImagePaintConfig(const RefPtr<CanvasImage> & canvasImage,const RectF & srcRect,const RectF & dstRect,const ImageSourceInfo & sourceInfo,int32_t frameCount)686 void ImagePattern::SetImagePaintConfig(const RefPtr<CanvasImage>& canvasImage, const RectF& srcRect,
687     const RectF& dstRect, const ImageSourceInfo& sourceInfo, int32_t frameCount)
688 {
689     auto layoutProps = GetLayoutProperty<ImageLayoutProperty>();
690     CHECK_NULL_VOID(layoutProps);
691 
692     ImagePaintConfig config {
693         .srcRect_ = srcRect,
694         .dstRect_ = dstRect,
695     };
696     config.imageFit_ = layoutProps->GetImageFit().value_or(ImageFit::COVER);
697     config.isSvg_ = sourceInfo.IsSvg();
698     config.frameCount_ = frameCount;
699     if (GreatNotEqual(frameCount, 1)) {
700         config.orientation_ = ImageRotateOrientation::UP;
701     } else {
702         config.orientation_ = joinOrientation_;
703     }
704     canvasImage->SetPaintConfig(config);
705 }
706 
CreateNodePaintMethod()707 RefPtr<NodePaintMethod> ImagePattern::CreateNodePaintMethod()
708 {
709     CreateModifier();
710     bool sensitive = false;
711     if (isSensitive_) {
712         auto host = GetHost();
713         CHECK_NULL_RETURN(host, nullptr);
714         sensitive = host->IsPrivacySensitive();
715     }
716     ImagePaintMethodConfig imagePaintMethodConfig { .sensitive = sensitive,
717         .selected = isSelected_,
718         .imageOverlayModifier = overlayMod_,
719         .imageContentModifier = contentMod_,
720         .interpolation = interpolationDefault_ };
721     // Callback function executed after the graphics rendering is complete.
722     auto drawCompleteCallback = [weakPattern = WeakClaim(this)](const RenderedImageInfo& renderedImageInfo) {
723         auto pattern = weakPattern.Upgrade();
724         CHECK_NULL_VOID(pattern);
725         // Mark the rendering as successful on the instance.
726         pattern->SetRenderedImageInfo(std::move(renderedImageInfo));
727     };
728     if (image_) {
729         image_->SetDrawCompleteCallback(std::move(drawCompleteCallback));
730         imagePaintMethod_->UpdatePaintMethod(image_, imagePaintMethodConfig);
731         return imagePaintMethod_;
732     }
733     if (altImage_ && altDstRect_ && altSrcRect_) {
734         altImage_->SetDrawCompleteCallback(std::move(drawCompleteCallback));
735         imagePaintMethod_->UpdatePaintMethod(altImage_, imagePaintMethodConfig);
736         return imagePaintMethod_;
737     }
738     CreateObscuredImage();
739     if (obscuredImage_) {
740         obscuredImage_->SetDrawCompleteCallback(std::move(drawCompleteCallback));
741         imagePaintMethod_->UpdatePaintMethod(obscuredImage_, imagePaintMethodConfig);
742         return imagePaintMethod_;
743     }
744     imagePaintMethodConfig.imageContentModifier = nullptr;
745     imagePaintMethodConfig.imageOverlayModifier = nullptr;
746     imagePaintMethod_->UpdatePaintMethod(nullptr, imagePaintMethodConfig);
747     return imagePaintMethod_;
748 }
749 
InitFromThemeIfNeed()750 void ImagePattern::InitFromThemeIfNeed()
751 {
752     if (isFullyInitializedFromTheme_) {
753         return;
754     }
755     isFullyInitializedFromTheme_ = true;
756 
757     auto host = GetHost();
758     CHECK_NULL_VOID(host);
759     auto pipeline = host->GetContext();
760     CHECK_NULL_VOID(pipeline);
761 
762     auto textTheme = pipeline->GetTheme<TextTheme>();
763     CHECK_NULL_VOID(textTheme);
764     selectedColor_ = textTheme->GetSelectedColor();
765 
766     auto imageTheme = pipeline->GetTheme<ImageTheme>();
767     CHECK_NULL_VOID(imageTheme);
768     smoothEdge_ = imageTheme->GetMinEdgeAntialiasing();
769 }
770 
CreateModifier()771 void ImagePattern::CreateModifier()
772 {
773     InitFromThemeIfNeed();
774     if (!contentMod_) {
775         contentMod_ = MakeRefPtr<ImageContentModifier>(WeakClaim(this));
776     }
777     if (!overlayMod_) {
778         overlayMod_ = MakeRefPtr<ImageOverlayModifier>(selectedColor_);
779     }
780     if (!imagePaintMethod_) {
781         imagePaintMethod_ = MakeRefPtr<ImagePaintMethod>(nullptr);
782     }
783 }
784 
OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper> & dirty,const DirtySwapConfig & config)785 bool ImagePattern::OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& config)
786 {
787     if (!isLayouted_ && GetIsAnimation()) {
788         isLayouted_ = true;
789         if (images_.size()) {
790             int32_t nextIndex = GetNextIndex(nowImageIndex_);
791             for (auto& cacheImage : cacheImages_) {
792                 UpdateCacheImageInfo(cacheImage, nextIndex);
793                 nextIndex = GetNextIndex(nextIndex);
794             }
795         }
796         return false;
797     }
798 
799     if (config.skipMeasure || dirty->SkipMeasureContent()) {
800         return false;
801     }
802 
803     if (imageType_ == ImageType::PIXELMAP_DRAWABLE) {
804         return true;
805     }
806 
807     const auto& dstSize = dirty->GetGeometryNode()->GetContentSize();
808     StartDecoding(dstSize);
809     if (loadingCtx_) {
810         auto renderProp = GetPaintProperty<ImageRenderProperty>();
811         if (renderProp && (renderProp->HasImageResizableSlice() || renderProp->HasImageResizableLattice()) && image_) {
812             loadingCtx_->ResizableCalcDstSize();
813             SetImagePaintConfig(image_, loadingCtx_->GetSrcRect(), loadingCtx_->GetDstRect(), loadingCtx_->GetSrc(),
814                 loadingCtx_->GetFrameCount());
815         }
816     }
817 
818     if (altLoadingCtx_) {
819         auto renderProp = GetPaintProperty<ImageRenderProperty>();
820         if (renderProp && (renderProp->HasImageResizableSlice() || renderProp->HasImageResizableLattice()) &&
821             altImage_) {
822             altLoadingCtx_->ResizableCalcDstSize();
823             SetImagePaintConfig(altImage_, altLoadingCtx_->GetSrcRect(), altLoadingCtx_->GetDstRect(),
824                 altLoadingCtx_->GetSrc(), altLoadingCtx_->GetFrameCount());
825         }
826     }
827 
828     if (IsSupportImageAnalyzerFeature()) {
829         UpdateAnalyzerUIConfig(dirty->GetGeometryNode());
830     }
831 
832     return image_ || altImage_;
833 }
834 
CreateObscuredImage()835 void ImagePattern::CreateObscuredImage()
836 {
837     auto props = GetLayoutProperty<ImageLayoutProperty>();
838     CHECK_NULL_VOID(props);
839     auto layoutConstraint = props->GetLayoutConstraint();
840     CHECK_NULL_VOID(layoutConstraint);
841     auto host = GetHost();
842     CHECK_NULL_VOID(host);
843     auto sourceInfo = props->GetImageSourceInfo().value_or(ImageSourceInfo(""));
844     auto reasons = host->GetRenderContext()->GetObscured().value_or(std::vector<ObscuredReasons>());
845     if (reasons.size() && layoutConstraint->selfIdealSize.IsValid()) {
846         if (!obscuredImage_) {
847             obscuredImage_ = MakeRefPtr<ObscuredImage>();
848             SetImagePaintConfig(obscuredImage_, srcRect_, dstRect_, sourceInfo);
849         }
850     }
851 }
852 
CreateImageDfxConfig(const ImageSourceInfo & src)853 ImageDfxConfig ImagePattern::CreateImageDfxConfig(const ImageSourceInfo& src)
854 {
855     auto host = GetHost();
856     CHECK_NULL_RETURN(host, ImageDfxConfig());
857     auto renderContext = host->GetRenderContext();
858     CHECK_NULL_RETURN(renderContext, ImageDfxConfig());
859     return {
860         { host->GetId(), host->GetAccessibilityId(), renderContext->GetNodeId() },
861         static_cast<int32_t>(src.GetSrcType()),
862         src.ToString().substr(0, MAX_SRC_LENGTH),
863         host->IsTrimMemRecycle(),
864     };
865 }
866 
ClearReloadFlagsAfterLoad()867 void ImagePattern::ClearReloadFlagsAfterLoad()
868 {
869     // Reset the reload flag before loading the image to ensure a fresh state.
870     isImageReloadNeeded_ = false;
871     isOrientationChange_ = false;
872     // Before loading new image data, reset the render success status to `false`.
873     renderedImageInfo_.renderSuccess = false;
874 }
875 
LoadImage(const ImageSourceInfo & src,bool needLayout)876 void ImagePattern::LoadImage(const ImageSourceInfo& src, bool needLayout)
877 {
878     if (loadingCtx_) {
879         auto srcKey = src.GetKey();
880         auto loadKey = loadingCtx_->GetSourceInfo().GetKey();
881         isPixelMapChanged_ = srcKey != loadKey;
882     }
883     LoadNotifier loadNotifier(CreateDataReadyCallback(), CreateLoadSuccessCallback(), CreateLoadFailCallback());
884     loadNotifier.onDataReadyComplete_ = CreateCompleteCallBackInDataReady();
885 
886     imageDfxConfig_ = CreateImageDfxConfig(src);
887 
888     loadingCtx_ = AceType::MakeRefPtr<ImageLoadingContext>(
889         src, std::move(loadNotifier), syncLoad_, isSceneBoardWindow_, imageDfxConfig_);
890 
891     if (SystemProperties::GetDebugEnabled()) {
892         TAG_LOGI(AceLogTag::ACE_IMAGE, "load image, %{private}s", imageDfxConfig_.ToStringWithSrc().c_str());
893     }
894 
895     if (onProgressCallback_) {
896         loadingCtx_->SetOnProgressCallback(std::move(onProgressCallback_));
897     }
898     if (!needLayout) {
899         loadingCtx_->FinishMeasure();
900     }
901     ClearReloadFlagsAfterLoad();
902     ImagePerf::GetPerfMonitor()->StartRecordImageLoadStat(imageDfxConfig_.GetAccessibilityId());
903     loadingCtx_->LoadImageData();
904 }
905 
LoadAltImage(const ImageSourceInfo & altImageSourceInfo)906 void ImagePattern::LoadAltImage(const ImageSourceInfo& altImageSourceInfo)
907 {
908     CHECK_NULL_VOID(GetNeedLoadAlt());
909     LoadNotifier altLoadNotifier(CreateDataReadyCallbackForAlt(), CreateLoadSuccessCallbackForAlt(), nullptr);
910     if (!altLoadingCtx_ || altLoadingCtx_->GetSourceInfo() != altImageSourceInfo ||
911         (altLoadingCtx_ && altImageSourceInfo.IsSvg())) {
912         auto host = GetHost();
913 
914         altImageDfxConfig_ = CreateImageDfxConfig(altImageSourceInfo);
915         altLoadingCtx_ = AceType::MakeRefPtr<ImageLoadingContext>(
916             altImageSourceInfo, std::move(altLoadNotifier), false, isSceneBoardWindow_, altImageDfxConfig_);
917         altLoadingCtx_->LoadImageData();
918     }
919 }
920 
LoadImageDataIfNeed()921 void ImagePattern::LoadImageDataIfNeed()
922 {
923     auto imageLayoutProperty = GetLayoutProperty<ImageLayoutProperty>();
924     CHECK_NULL_VOID(imageLayoutProperty);
925     auto host = GetHost();
926     CHECK_NULL_VOID(host);
927     auto src = imageLayoutProperty->GetImageSourceInfo().value_or(ImageSourceInfo(""));
928     UpdateInternalResource(src);
929 
930     if (!loadingCtx_ || loadingCtx_->GetSourceInfo() != src || isImageReloadNeeded_ || isOrientationChange_) {
931         bool needLayout = host->CheckNeedForceMeasureAndLayout() &&
932                           imageLayoutProperty->GetVisibility().value_or(VisibleType::VISIBLE) != VisibleType::GONE;
933         LoadImage(src, needLayout);
934     } else if (IsSupportImageAnalyzerFeature()) {
935         auto context = host->GetContext();
936         CHECK_NULL_VOID(context);
937         auto uiTaskExecutor = SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::UI);
938         uiTaskExecutor.PostTask(
939             [weak = WeakClaim(this)] {
940                 auto pattern = weak.Upgrade();
941                 CHECK_NULL_VOID(pattern);
942                 ContainerScope scope(pattern->GetHostInstanceId());
943                 pattern->CreateAnalyzerOverlay();
944                 auto host = pattern->GetHost();
945                 pattern->UpdateAnalyzerUIConfig(host->GetGeometryNode());
946             },
947             "ArkUIImageUpdateAnalyzerUIConfig");
948     }
949     if (loadingCtx_->NeedAlt() && imageLayoutProperty->GetAlt()) {
950         auto altImageSourceInfo = imageLayoutProperty->GetAlt().value_or(ImageSourceInfo(""));
951         LoadAltImage(altImageSourceInfo);
952     }
953 }
954 
UpdateGestureAndDragWhenModify()955 void ImagePattern::UpdateGestureAndDragWhenModify()
956 {
957     // remove long press and mouse events
958     auto host = GetHost();
959     CHECK_NULL_VOID(host);
960 
961     auto gestureHub = host->GetOrCreateGestureEventHub();
962     if (longPressEvent_) {
963         gestureHub->SetLongPressEvent(nullptr);
964         longPressEvent_ = nullptr;
965     }
966 
967     if (clickEvent_) {
968         gestureHub->RemoveClickEvent(clickEvent_);
969         clickEvent_ = nullptr;
970     }
971 
972     if (mouseEvent_) {
973         auto inputHub = host->GetOrCreateInputEventHub();
974         inputHub->RemoveOnMouseEvent(mouseEvent_);
975         mouseEvent_ = nullptr;
976     }
977 
978     enableDrag_ = host->IsDraggable();
979 
980     if (host->IsDraggable()) {
981         EnableDrag();
982     }
983 }
984 
OnModifyDone()985 void ImagePattern::OnModifyDone()
986 {
987     switch (imageType_) {
988         case ImageType::BASE:
989             OnImageModifyDone();
990             break;
991         case ImageType::ANIMATED_DRAWABLE:
992             OnAnimatedModifyDone();
993             break;
994         case ImageType::PIXELMAP_DRAWABLE:
995             OnPixelMapDrawableModifyDone();
996             break;
997         default:
998             break;
999     }
1000 
1001     InitOnKeyEvent();
1002 }
1003 
InitOnKeyEvent()1004 void ImagePattern::InitOnKeyEvent()
1005 {
1006     if (Container::LessThanAPITargetVersion(PlatformVersion::VERSION_FOURTEEN) || keyEventCallback_) {
1007         return;
1008     }
1009 
1010     auto host = GetHost();
1011     CHECK_NULL_VOID(host);
1012     auto hub = host->GetOrCreateEventHub<EventHub>();
1013     CHECK_NULL_VOID(hub);
1014     auto focusHub = hub->GetOrCreateFocusHub();
1015     CHECK_NULL_VOID(focusHub);
1016     keyEventCallback_ = [weak = WeakClaim(this)](const KeyEvent& event) -> bool {
1017         auto pattern = weak.Upgrade();
1018         CHECK_NULL_RETURN(pattern, false);
1019         pattern->OnKeyEvent(event);
1020         return false;
1021     };
1022     focusHub->SetOnKeyEventInternal(std::move(keyEventCallback_));
1023 }
1024 
OnKeyEvent(const KeyEvent & event)1025 void ImagePattern::OnKeyEvent(const KeyEvent& event)
1026 {
1027     if (imageAnalyzerManager_) {
1028         auto imageLayoutProperty = GetLayoutProperty<ImageLayoutProperty>();
1029         CHECK_NULL_VOID(imageLayoutProperty);
1030         auto imageInfo = imageLayoutProperty->GetImageSourceInfo().value_or(ImageSourceInfo(""));
1031         if (!imageInfo.IsSvg()) {
1032             imageAnalyzerManager_->UpdateKeyEvent(event);
1033         }
1034     }
1035     auto host = GetHost();
1036     CHECK_NULL_VOID(host);
1037     auto focusHub = host->GetFocusHub();
1038     CHECK_NULL_VOID(focusHub);
1039     focusHub->PaintFocusState(true);
1040     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
1041 }
1042 
OnAnimatedModifyDone()1043 void ImagePattern::OnAnimatedModifyDone()
1044 {
1045     auto host = GetHost();
1046     CHECK_NULL_VOID(host);
1047     Pattern::OnModifyDone();
1048     auto size = static_cast<int32_t>(images_.size());
1049     if (size <= 0) {
1050         TAG_LOGW(AceLogTag::ACE_IMAGE, "image size is less than 0.");
1051         return;
1052     }
1053     GenerateCachedImages();
1054     auto index = nowImageIndex_;
1055     if ((status_ == AnimatorStatus::IDLE || status_ == AnimatorStatus::STOPPED) && !firstUpdateEvent_) {
1056         index = 0;
1057     }
1058 
1059     if (imagesChangedFlag_) {
1060         animator_->ClearInterpolators();
1061         animator_->AddInterpolator(CreatePictureAnimation(size));
1062         AdaptSelfSize();
1063         imagesChangedFlag_ = false;
1064     }
1065     if (firstUpdateEvent_) {
1066         firstUpdateEvent_ = false;
1067         auto imageFrameNode = AceType::DynamicCast<FrameNode>(host->GetChildren().front());
1068         AddImageLoadSuccessEvent(imageFrameNode);
1069     }
1070     UpdateFormDurationByRemainder();
1071     SetObscured();
1072     if (isSrcUndefined_) {
1073         return;
1074     }
1075     ControlAnimation(index);
1076 }
1077 
ControlAnimation(int32_t index)1078 void ImagePattern::ControlAnimation(int32_t index)
1079 {
1080     auto host = GetHost();
1081     CHECK_NULL_VOID(host);
1082     if (!host->IsOnMainTree()) {
1083         return;
1084     }
1085     if (!animator_->HasScheduler()) {
1086         auto context = host->GetContextRefPtr();
1087         if (context) {
1088             animator_->AttachScheduler(context);
1089         } else {
1090             TAG_LOGW(AceLogTag::ACE_IMAGE, "pipeline is null.");
1091         }
1092     }
1093     switch (status_) {
1094         case AnimatorStatus::IDLE:
1095             animator_->Cancel();
1096             ResetFormAnimationFlag();
1097             SetShowingIndex(index);
1098             break;
1099         case AnimatorStatus::PAUSED:
1100             animator_->Pause();
1101             ResetFormAnimationFlag();
1102             break;
1103         case AnimatorStatus::STOPPED:
1104             animator_->Finish();
1105             ResetFormAnimationFlag();
1106             break;
1107         default:
1108             ResetFormAnimationStartTime();
1109             if (isFormAnimationEnd_) {
1110                 ResetFormAnimationFlag();
1111                 return;
1112             }
1113             if (host->IsVisible()) {
1114                 animator_->Forward();
1115             } else {
1116                 animator_->Pause();
1117             }
1118     }
1119 }
1120 
OnImageModifyDone()1121 void ImagePattern::OnImageModifyDone()
1122 {
1123     Pattern::OnModifyDone();
1124     LoadImageDataIfNeed();
1125     UpdateGestureAndDragWhenModify();
1126     CHECK_EQUAL_VOID(CheckImagePrivacyForCopyOption(), true);
1127     CloseSelectOverlay();
1128     UpdateOffsetForImageAnalyzerOverlay();
1129     SetFrameOffsetForOverlayNode();
1130 }
1131 
OnPixelMapDrawableModifyDone()1132 void ImagePattern::OnPixelMapDrawableModifyDone()
1133 {
1134     Pattern::OnModifyDone();
1135     UpdateGestureAndDragWhenModify();
1136     CHECK_EQUAL_VOID(CheckImagePrivacyForCopyOption(), true);
1137     CloseSelectOverlay();
1138     UpdateOffsetForImageAnalyzerOverlay();
1139     SetFrameOffsetForOverlayNode();
1140     // Data loading is not managed by image. Therefore, during component
1141     // attribute initilizationm, the dirty node mark of image needs to
1142     // be registered withe Drawable. Drawable triggers drawing again after
1143     // data loading is complete.
1144     RegisterDrawableRedrawCallback();
1145 }
1146 
RegisterDrawableRedrawCallback()1147 void ImagePattern::RegisterDrawableRedrawCallback()
1148 {
1149     if (isRegisterRedrawCallback_) {
1150         return;
1151     }
1152     CHECK_NULL_VOID(drawable_);
1153     drawable_->RegisterRedrawCallback([weak = WeakClaim(this)] {
1154         auto pattern = weak.Upgrade();
1155         CHECK_NULL_VOID(pattern);
1156         auto context = pattern->GetContext();
1157         CHECK_NULL_VOID(context);
1158         auto taskExecutor = context->GetTaskExecutor();
1159         CHECK_NULL_VOID(taskExecutor);
1160         taskExecutor->PostTask(
1161             [weak = weak] {
1162                 auto pattern = weak.Upgrade();
1163                 CHECK_NULL_VOID(pattern);
1164                 pattern->Validate();
1165             },
1166             TaskExecutor::TaskType::UI, "ArkUIImageDrawableMarkRender");
1167     });
1168     isRegisterRedrawCallback_ = true;
1169 }
1170 
Validate()1171 void ImagePattern::Validate()
1172 {
1173     auto host = GetHost();
1174     CHECK_NULL_VOID(host);
1175     ACE_SCOPED_TRACE("[Drawable][%d] validate callback", host->GetId());
1176     // first mark dirty render
1177     host->MarkNeedRenderOnly();
1178     CHECK_NULL_VOID(contentMod_);
1179     // because drawable is not a drawing attribute of the
1180     // content modifier, redrawing cannot be trigged when
1181     // drawable validates the content modifier. Therefore
1182     // count attribute in the modifier needs to be used to
1183     // forcibly refresh the content modifier.
1184     contentMod_->SetContentChange();
1185 }
1186 
CreatePaintConfig()1187 ImagePaintConfig ImagePattern::CreatePaintConfig()
1188 {
1189     ImagePaintConfig config;
1190     auto lp = GetLayoutProperty<ImageLayoutProperty>();
1191     CHECK_NULL_RETURN(lp, config);
1192     config.imageFit_ = lp->GetImageFit().value_or(ImageFit::COVER);
1193     return config;
1194 }
1195 
DrawDrawable(RSCanvas & canvas)1196 void ImagePattern::DrawDrawable(RSCanvas& canvas)
1197 {
1198     auto host = GetHost();
1199     CHECK_NULL_VOID(host);
1200     ACE_SCOPED_TRACE("[Drawable][%d] draw to canvas", host->GetId());
1201     CHECK_NULL_VOID(drawable_);
1202     auto config = CreatePaintConfig();
1203     drawable_->Draw(canvas, config);
1204 }
1205 
GetImageSizeForMeasure()1206 std::optional<SizeF> ImagePattern::GetImageSizeForMeasure()
1207 {
1208     if ((!loadingCtx_ || !loadingCtx_->GetImageSize().IsPositive()) &&
1209         (!altLoadingCtx_ || !altLoadingCtx_->GetImageSize().IsPositive())) {
1210         return std::nullopt;
1211     }
1212     auto rawImageSize = SizeF(-1.0, -1.0);
1213     if (loadingCtx_) {
1214         rawImageSize = loadingCtx_->GetImageSize();
1215     }
1216     if (rawImageSize.IsNegative() && altLoadingCtx_) {
1217         rawImageSize = altLoadingCtx_->GetImageSize();
1218     }
1219     return std::make_optional<SizeF>(rawImageSize.Width(), rawImageSize.Height());
1220 }
1221 
FinishMeasureForOnComplete()1222 void ImagePattern::FinishMeasureForOnComplete()
1223 {
1224     CHECK_NULL_VOID(loadingCtx_);
1225     loadingCtx_->FinishMeasure();
1226     loadingCtx_->CallbackAfterMeasureIfNeed();
1227 }
1228 
CheckImagePrivacyForCopyOption()1229 bool ImagePattern::CheckImagePrivacyForCopyOption()
1230 {
1231     if (copyOption_ == CopyOptions::None) {
1232         return false;
1233     }
1234     auto host = GetHost();
1235     CHECK_NULL_RETURN(host, false);
1236     bool hasObscured = false;
1237     if (host->GetRenderContext()->GetObscured().has_value()) {
1238         auto obscuredReasons = host->GetRenderContext()->GetObscured().value();
1239         hasObscured = std::any_of(obscuredReasons.begin(), obscuredReasons.end(),
1240             [](const auto& reason) { return reason == ObscuredReasons::PLACEHOLDER; });
1241     }
1242     if (!hasObscured) {
1243         InitCopy();
1244         return true;
1245     }
1246     return false;
1247 }
1248 
UpdateOffsetForImageAnalyzerOverlay()1249 void ImagePattern::UpdateOffsetForImageAnalyzerOverlay()
1250 {
1251     if (imageAnalyzerManager_ && imageAnalyzerManager_->IsOverlayCreated()) {
1252         if (!IsSupportImageAnalyzerFeature()) {
1253             DestroyAnalyzerOverlay();
1254         } else {
1255             UpdateAnalyzerOverlayLayout();
1256         }
1257     }
1258 }
1259 
1260 // SetUsingContentRectForRenderFrame is set for image paint
SetFrameOffsetForOverlayNode()1261 void ImagePattern::SetFrameOffsetForOverlayNode()
1262 {
1263     auto host = GetHost();
1264     CHECK_NULL_VOID(host);
1265     auto overlayNode = host->GetOverlayNode();
1266     if (overlayNode) {
1267         auto layoutProperty = host->GetLayoutProperty();
1268         CHECK_NULL_VOID(layoutProperty);
1269         auto padding = layoutProperty->CreatePaddingAndBorder();
1270         auto renderContext = overlayNode->GetRenderContext();
1271         if (renderContext) {
1272             renderContext->SetRenderFrameOffset({ -padding.Offset().GetX(), -padding.Offset().GetY() });
1273         }
1274     }
1275 }
1276 
CreateDataReadyCallbackForAlt()1277 DataReadyNotifyTask ImagePattern::CreateDataReadyCallbackForAlt()
1278 {
1279     return [weak = WeakClaim(this)](const ImageSourceInfo& sourceInfo) {
1280         auto pattern = weak.Upgrade();
1281         CHECK_NULL_VOID(pattern);
1282         CHECK_NULL_VOID(pattern->altLoadingCtx_);
1283         auto imageLayoutProperty = pattern->GetLayoutProperty<ImageLayoutProperty>();
1284         CHECK_NULL_VOID(imageLayoutProperty);
1285         auto currentAltSourceInfo = imageLayoutProperty->GetAlt().value_or(ImageSourceInfo(""));
1286         if (currentAltSourceInfo != sourceInfo) {
1287             TAG_LOGW(AceLogTag::ACE_IMAGE, "alt src not match, %{public}s: %{private}s - %{private}s",
1288                 pattern->imageDfxConfig_.ToStringWithoutSrc().c_str(), currentAltSourceInfo.ToString().c_str(),
1289                 sourceInfo.ToString().c_str());
1290             return;
1291         }
1292         auto host = pattern->GetHost();
1293         CHECK_NULL_VOID(host);
1294         if (!host->IsActive()) {
1295             return;
1296         }
1297         const auto& geometryNode = host->GetGeometryNode();
1298         CHECK_NULL_VOID(geometryNode);
1299         if (!geometryNode->GetContent()) {
1300             host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1301             return;
1302         }
1303 
1304         // calculate params for [altLoadingCtx] to do [MakeCanvasImage] if component size is already settled
1305         pattern->altLoadingCtx_->MakeCanvasImageIfNeed(
1306             geometryNode->GetContentSize(), true, imageLayoutProperty->GetImageFit().value_or(ImageFit::COVER));
1307     };
1308 }
1309 
CreateLoadSuccessCallbackForAlt()1310 LoadSuccessNotifyTask ImagePattern::CreateLoadSuccessCallbackForAlt()
1311 {
1312     return [weak = WeakClaim(this)](const ImageSourceInfo& sourceInfo) {
1313         auto pattern = weak.Upgrade();
1314         CHECK_NULL_VOID(pattern);
1315         CHECK_NULL_VOID(pattern->altLoadingCtx_);
1316         auto layoutProps = pattern->GetLayoutProperty<ImageLayoutProperty>();
1317         CHECK_NULL_VOID(layoutProps);
1318         auto currentAltSrc = layoutProps->GetAlt().value_or(ImageSourceInfo(""));
1319         if (currentAltSrc != sourceInfo) {
1320             TAG_LOGW(AceLogTag::ACE_IMAGE, "alt src not match, %{public}s: %{private}s - %{private}s",
1321                 pattern->imageDfxConfig_.ToStringWithoutSrc().c_str(), currentAltSrc.ToString().c_str(),
1322                 sourceInfo.ToString().c_str());
1323             return;
1324         }
1325         pattern->altImage_ = pattern->altLoadingCtx_->MoveCanvasImage();
1326         CHECK_NULL_VOID(pattern->altImage_);
1327         pattern->altImage_->SetImageDfxConfig(pattern->altImageDfxConfig_);
1328         pattern->altSrcRect_ = std::make_unique<RectF>(pattern->altLoadingCtx_->GetSrcRect());
1329         pattern->altDstRect_ = std::make_unique<RectF>(pattern->altLoadingCtx_->GetDstRect());
1330         pattern->SetImagePaintConfig(pattern->altImage_, *pattern->altSrcRect_, *pattern->altDstRect_,
1331             pattern->altLoadingCtx_->GetSourceInfo(), pattern->altLoadingCtx_->GetFrameCount());
1332 
1333         pattern->PrepareAnimation(pattern->altImage_);
1334 
1335         auto host = pattern->GetHost();
1336         CHECK_NULL_VOID(host);
1337         host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
1338     };
1339 }
1340 
UpdateInternalResource(ImageSourceInfo & sourceInfo)1341 void ImagePattern::UpdateInternalResource(ImageSourceInfo& sourceInfo)
1342 {
1343     if (!sourceInfo.IsInternalResource()) {
1344         return;
1345     }
1346 
1347     auto pipeline = GetHost()->GetContext();
1348     CHECK_NULL_VOID(pipeline);
1349     auto iconTheme = pipeline->GetTheme<IconTheme>();
1350     CHECK_NULL_VOID(iconTheme);
1351     auto iconPath = iconTheme->GetIconPath(sourceInfo.GetResourceId());
1352     if (!iconPath.empty()) {
1353         sourceInfo.SetSrc(iconPath, sourceInfo.GetFillColor());
1354         auto imageLayoutProperty = GetLayoutProperty<ImageLayoutProperty>();
1355         CHECK_NULL_VOID(imageLayoutProperty);
1356         imageLayoutProperty->UpdateImageSourceInfo(sourceInfo);
1357     }
1358 }
1359 
RecycleImageData()1360 bool ImagePattern::RecycleImageData()
1361 {
1362     // when image component is [onShow] , [no cache], do not clean image data
1363     bool isDataNoCache = (!loadingCtx_ || (loadingCtx_->GetSourceInfo().GetSrcType() == SrcType::NETWORK &&
1364                                               SystemProperties::GetDownloadByNetworkEnabled() &&
1365                                               DownloadManager::GetInstance()->IsContains(
1366                                                   loadingCtx_->GetSourceInfo().GetSrc()) == false));
1367     if (isShow_ || isDataNoCache) {
1368         return false;
1369     }
1370     auto frameNode = GetHost();
1371     if (!frameNode) {
1372         return false;
1373     }
1374     frameNode->SetTrimMemRecycle(true);
1375     loadingCtx_ = nullptr;
1376     auto rsRenderContext = frameNode->GetRenderContext();
1377     if (!rsRenderContext) {
1378         return false;
1379     }
1380     TAG_LOGI(AceLogTag::ACE_IMAGE, "%{public}s, %{private}s recycleImageData.",
1381         imageDfxConfig_.ToStringWithoutSrc().c_str(), imageDfxConfig_.GetImageSrc().c_str());
1382     rsRenderContext->RemoveContentModifier(contentMod_);
1383     contentMod_ = nullptr;
1384     image_ = nullptr;
1385     altLoadingCtx_ = nullptr;
1386     altImage_ = nullptr;
1387     ACE_SCOPED_TRACE("OnRecycleImageData imageInfo: [%s]", imageDfxConfig_.ToStringWithSrc().c_str());
1388     return true;
1389 }
1390 
OnNotifyMemoryLevel(int32_t level)1391 void ImagePattern::OnNotifyMemoryLevel(int32_t level)
1392 {
1393     // when image component is [onShow], do not clean image data
1394     if (isShow_ || level < MEMORY_LEVEL_CRITICAL_STATUS) {
1395         return;
1396     }
1397     auto frameNode = GetHost();
1398     CHECK_NULL_VOID(frameNode);
1399     frameNode->SetTrimMemRecycle(false);
1400     auto rsRenderContext = frameNode->GetRenderContext();
1401     CHECK_NULL_VOID(rsRenderContext);
1402     TAG_LOGD(AceLogTag::ACE_IMAGE, "%{public}s, %{private}s OnNotifyMemoryLevel %{public}d.",
1403         imageDfxConfig_.ToStringWithoutSrc().c_str(), imageDfxConfig_.GetImageSrc().c_str(), level);
1404     rsRenderContext->RemoveContentModifier(contentMod_);
1405     contentMod_ = nullptr;
1406     loadingCtx_ = nullptr;
1407     image_ = nullptr;
1408     altLoadingCtx_ = nullptr;
1409     altImage_ = nullptr;
1410 }
1411 
1412 // when recycle image component, release the pixelmap resource
OnRecycle()1413 void ImagePattern::OnRecycle()
1414 {
1415     TAG_LOGD(AceLogTag::ACE_IMAGE, "OnRecycle. %{public}s", imageDfxConfig_.ToStringWithoutSrc().c_str());
1416     loadingCtx_ = nullptr;
1417     image_ = nullptr;
1418     altLoadingCtx_ = nullptr;
1419     altImage_ = nullptr;
1420 
1421     auto frameNode = GetHost();
1422     CHECK_NULL_VOID(frameNode);
1423     auto rsRenderContext = frameNode->GetRenderContext();
1424     CHECK_NULL_VOID(rsRenderContext);
1425     rsRenderContext->RemoveContentModifier(contentMod_);
1426     contentMod_ = nullptr;
1427     UnregisterWindowStateChangedCallback();
1428     frameNode->SetTrimMemRecycle(false);
1429 }
1430 
OnReuse()1431 void ImagePattern::OnReuse()
1432 {
1433     RegisterWindowStateChangedCallback();
1434     auto renderProp = GetPaintProperty<ImageRenderProperty>();
1435     CHECK_NULL_VOID(renderProp);
1436     renderProp->UpdateNeedBorderRadius(needBorderRadius_);
1437     auto imageLayoutProperty = GetLayoutProperty<ImageLayoutProperty>();
1438     CHECK_NULL_VOID(imageLayoutProperty);
1439     LoadImageDataIfNeed();
1440 }
1441 
RegisterWindowStateChangedCallback()1442 void ImagePattern::RegisterWindowStateChangedCallback()
1443 {
1444     auto host = GetHost();
1445     CHECK_NULL_VOID(host);
1446     auto pipeline = host->GetContext();
1447     CHECK_NULL_VOID(pipeline);
1448     pipeline->AddWindowStateChangedCallback(host->GetId());
1449 }
1450 
UnregisterWindowStateChangedCallback()1451 void ImagePattern::UnregisterWindowStateChangedCallback()
1452 {
1453     auto host = GetHost();
1454     CHECK_NULL_VOID(host);
1455     auto pipeline = host->GetContext();
1456     CHECK_NULL_VOID(pipeline);
1457     pipeline->RemoveWindowStateChangedCallback(host->GetId());
1458 }
1459 
OnWindowHide()1460 void ImagePattern::OnWindowHide()
1461 {
1462     isShow_ = false;
1463 }
1464 
OnWindowShow()1465 void ImagePattern::OnWindowShow()
1466 {
1467     TAG_LOGD(AceLogTag::ACE_IMAGE, "OnWindowShow. %{public}s, isImageReloadNeeded_ = %{public}d",
1468         imageDfxConfig_.ToStringWithoutSrc().c_str(), isImageReloadNeeded_);
1469     isShow_ = true;
1470     auto host = GetHost();
1471     CHECK_NULL_VOID(host);
1472     if (!host->IsTrimMemRecycle()) {
1473         LoadImageDataIfNeed();
1474     }
1475 }
1476 
OnVisibleChange(bool visible)1477 void ImagePattern::OnVisibleChange(bool visible)
1478 {
1479     if (!visible) {
1480         TAG_LOGD(AceLogTag::ACE_IMAGE, "OnInVisible. %{public}s", imageDfxConfig_.ToStringWithoutSrc().c_str());
1481         CloseSelectOverlay();
1482     }
1483 }
1484 
OnVisibleAreaChange(bool visible,double ratio)1485 void ImagePattern::OnVisibleAreaChange(bool visible, double ratio)
1486 {
1487     ACE_SCOPED_TRACE(
1488         "OnVisibleAreaChange visible: [%d], imageInfo: %s", visible, imageDfxConfig_.ToStringWithSrc().c_str());
1489     if (SystemProperties::GetDebugEnabled()) {
1490         TAG_LOGI(AceLogTag::ACE_IMAGE, "OnVisibleAreaChange visible:%{public}d, %{public}s", visible,
1491             imageDfxConfig_.ToStringWithoutSrc().c_str());
1492     }
1493     previousVisibility_ = visible;
1494     if (!visible) {
1495         CloseSelectOverlay();
1496     }
1497     // control pixelMap List
1498     if (GetIsAnimation() && !animator_->IsStopped() && animator_->HasScheduler()) {
1499         if (visible) {
1500             animator_->Forward();
1501         } else {
1502             animator_->Pause();
1503         }
1504     }
1505     // control svg / gif animation
1506     if (image_) {
1507         image_->ControlAnimation(visible);
1508     } else if (altImage_) {
1509         altImage_->ControlAnimation(visible);
1510     }
1511 
1512     if (isEnableAnalyzer_) {
1513         auto host = GetHost();
1514         CHECK_NULL_VOID(host);
1515         auto overlayNode = host->GetOverlayNode();
1516         CHECK_NULL_VOID(overlayNode);
1517         TriggerVisibleAreaChangeForChild(overlayNode, visible, ratio);
1518     }
1519 }
1520 
OnAttachToFrameNode()1521 void ImagePattern::OnAttachToFrameNode()
1522 {
1523     auto host = GetHost();
1524     CHECK_NULL_VOID(host);
1525     THREAD_SAFE_NODE_CHECK(host, OnAttachToFrameNode);
1526     auto renderCtx = host->GetRenderContext();
1527     CHECK_NULL_VOID(renderCtx);
1528     auto pipeline = host->GetContext();
1529     CHECK_NULL_VOID(pipeline);
1530     if (GetIsAnimation()) {
1531         renderCtx->SetClipToFrame(true);
1532     } else {
1533         renderCtx->SetClipToBounds(false);
1534         renderCtx->SetUsingContentRectForRenderFrame(true);
1535 
1536         // register image frame node to pipeline context to receive memory level notification and window state change
1537         // notification
1538         pipeline->AddNodesToNotifyMemoryLevel(host->GetId());
1539         pipeline->AddWindowStateChangedCallback(host->GetId());
1540     }
1541 }
1542 
OnDetachFromFrameNode(FrameNode * frameNode)1543 void ImagePattern::OnDetachFromFrameNode(FrameNode* frameNode)
1544 {
1545     THREAD_SAFE_NODE_CHECK(frameNode, OnDetachFromFrameNode, frameNode);
1546     CloseSelectOverlay();
1547 
1548     auto id = frameNode->GetId();
1549     auto pipeline = AceType::DynamicCast<PipelineContext>(PipelineBase::GetCurrentContext());
1550     CHECK_NULL_VOID(pipeline);
1551     pipeline->RemoveWindowStateChangedCallback(id);
1552     pipeline->RemoveNodesToNotifyMemoryLevel(id);
1553 }
1554 
OnAttachToMainTree()1555 void ImagePattern::OnAttachToMainTree()
1556 {
1557     auto host = GetHost();
1558     CHECK_NULL_VOID(host);
1559     THREAD_SAFE_NODE_CHECK(host, OnAttachToMainTree);
1560 }
1561 
OnDetachFromMainTree()1562 void ImagePattern::OnDetachFromMainTree()
1563 {
1564     auto host = GetHost();
1565     CHECK_NULL_VOID(host);
1566     THREAD_SAFE_NODE_CHECK(host, OnAttachToFrameNode);
1567     if (isNeedReset_) {
1568         ResetImageAndAlt();
1569         isNeedReset_ = false;
1570     }
1571     if (GetIsAnimation() && !animator_->IsStopped() && animator_->HasScheduler()) {
1572         animator_->Stop();
1573     }
1574 }
1575 
EnableDrag()1576 void ImagePattern::EnableDrag()
1577 {
1578     auto host = GetHost();
1579     CHECK_NULL_VOID(host);
1580     auto dragStart = [weak = WeakClaim(this)](const RefPtr<OHOS::Ace::DragEvent>& event, const std::string&
1581                          /* extraParams */) -> DragDropInfo {
1582         DragDropInfo info;
1583         auto imagePattern = weak.Upgrade();
1584         CHECK_NULL_RETURN(imagePattern && imagePattern->loadingCtx_, info);
1585         AceEngineExt::GetInstance().DragStartExt();
1586         imagePattern->UpdateDragEvent(event);
1587         info.extraInfo = imagePattern->loadingCtx_->GetSourceInfo().GetSrc();
1588         return info;
1589     };
1590     auto eventHub = host->GetOrCreateEventHub<EventHub>();
1591     CHECK_NULL_VOID(eventHub);
1592     eventHub->SetDefaultOnDragStart(std::move(dragStart));
1593 }
1594 
BetweenSelectedPosition(const Offset & globalOffset)1595 bool ImagePattern::BetweenSelectedPosition(const Offset& globalOffset)
1596 {
1597     auto host = GetHost();
1598     CHECK_NULL_RETURN(host, false);
1599     auto globalRect = host->GetTransformRectRelativeToWindow();
1600     return globalRect.IsInRegion(PointF { globalOffset.GetX(), globalOffset.GetY() });
1601 }
1602 
BeforeCreatePaintWrapper()1603 void ImagePattern::BeforeCreatePaintWrapper()
1604 {
1605     auto host = GetHost();
1606     CHECK_NULL_VOID(host);
1607     host->GetRenderContext()->MarkContentChanged(true);
1608 }
1609 
InitCopy()1610 void ImagePattern::InitCopy()
1611 {
1612     if (longPressEvent_ && mouseEvent_ && clickEvent_) {
1613         return;
1614     }
1615     auto longPressTask = [weak = WeakClaim(this)](GestureEvent& info) {
1616         auto pattern = weak.Upgrade();
1617         CHECK_NULL_VOID(pattern);
1618         pattern->OpenSelectOverlay();
1619     };
1620     longPressEvent_ = MakeRefPtr<LongPressEvent>(std::move(longPressTask));
1621 
1622     auto host = GetHost();
1623     CHECK_NULL_VOID(host);
1624     auto gestureHub = host->GetOrCreateGestureEventHub();
1625     gestureHub->SetLongPressEvent(longPressEvent_);
1626 
1627     auto mouseTask = [weak = WeakClaim(this)](MouseInfo& info) {
1628         if (info.GetButton() == MouseButton::RIGHT_BUTTON && info.GetAction() == MouseAction::PRESS) {
1629             auto pattern = weak.Upgrade();
1630             CHECK_NULL_VOID(pattern);
1631             pattern->OpenSelectOverlay();
1632         }
1633     };
1634     mouseEvent_ = MakeRefPtr<InputEvent>(std::move(mouseTask));
1635     auto inputHub = host->GetOrCreateInputEventHub();
1636     CHECK_NULL_VOID(inputHub);
1637     inputHub->AddOnMouseEvent(mouseEvent_);
1638 
1639     // close overlay on click
1640     clickEvent_ = MakeRefPtr<ClickEvent>([weak = WeakClaim(this)](GestureEvent& callback) {
1641         auto pattern = weak.Upgrade();
1642         CHECK_NULL_VOID(pattern);
1643         pattern->CloseSelectOverlay();
1644     });
1645     gestureHub->AddClickEvent(clickEvent_);
1646 }
1647 
OpenSelectOverlay()1648 void ImagePattern::OpenSelectOverlay()
1649 {
1650     auto host = GetHost();
1651     CHECK_NULL_VOID(host);
1652     const auto& geometryNode = host->GetGeometryNode();
1653     CHECK_NULL_VOID(geometryNode);
1654     auto rect = host->GetTransformRectRelativeToWindow();
1655     SelectOverlayInfo info;
1656     SizeF handleSize = { SelectHandleInfo::GetDefaultLineWidth().ConvertToPx(),
1657         geometryNode->GetContentSize().Height() };
1658     info.firstHandle.paintRect = RectF(rect.GetOffset(), handleSize);
1659     OffsetF offset(rect.Width() - handleSize.Width(), rect.Height() - handleSize.Height());
1660     info.secondHandle.paintRect = RectF(rect.GetOffset() + offset, handleSize);
1661     info.menuInfo.menuIsShow = true;
1662     info.menuInfo.showCut = false;
1663     info.menuInfo.showPaste = false;
1664     info.menuCallback.onCopy = [weak = WeakClaim(this)]() {
1665         auto pattern = weak.Upgrade();
1666         CHECK_NULL_VOID(pattern);
1667         pattern->HandleCopy();
1668         pattern->CloseSelectOverlay();
1669     };
1670     info.onHandleMoveDone = [weak = WeakClaim(this)](const RectF&, bool isFirst) {
1671         // reset handle position
1672         auto pattern = weak.Upgrade();
1673         CHECK_NULL_VOID(pattern && pattern->selectOverlay_);
1674         pattern->HandleMoveDone(isFirst);
1675     };
1676     info.onClose = [weak = WeakClaim(this)](bool closedByGlobalEvent) {
1677         if (closedByGlobalEvent) {
1678             auto pattern = weak.Upgrade();
1679             CHECK_NULL_VOID(pattern);
1680             pattern->CloseSelectOverlay();
1681         }
1682     };
1683 
1684     auto pipeline = host->GetContext();
1685     CHECK_NULL_VOID(pipeline);
1686     selectOverlay_ = pipeline->GetSelectOverlayManager()->CreateAndShowSelectOverlay(info, WeakClaim(this));
1687     isSelected_ = true;
1688     CHECK_NULL_VOID(selectOverlay_);
1689     pipeline->AddOnAreaChangeNode(host->GetId());
1690     // paint selected mask effect
1691     host->MarkNeedRenderOnly();
1692 }
1693 
HandleMoveDone(bool isFirst)1694 void ImagePattern::HandleMoveDone(bool isFirst)
1695 {
1696     auto host = GetHost();
1697     CHECK_NULL_VOID(host);
1698     auto rect = host->GetTransformRectRelativeToWindow();
1699     const auto& geometryNode = host->GetGeometryNode();
1700     CHECK_NULL_VOID(geometryNode);
1701     SizeF handleSize = { SelectHandleInfo::GetDefaultLineWidth().ConvertToPx(),
1702         geometryNode->GetContentSize().Height() };
1703     SelectHandleInfo info;
1704     if (isFirst) {
1705         info.paintRect = RectF(rect.GetOffset(), handleSize);
1706         selectOverlay_->UpdateFirstSelectHandleInfo(info);
1707     } else {
1708         OffsetF offset(rect.Width() - handleSize.Width(), rect.Height() - handleSize.Height());
1709         info.paintRect = RectF(rect.GetOffset() + offset, handleSize);
1710         selectOverlay_->UpdateSecondSelectHandleInfo(info);
1711     }
1712 }
1713 
CloseSelectOverlay()1714 void ImagePattern::CloseSelectOverlay()
1715 {
1716     if (!selectOverlay_) {
1717         return;
1718     }
1719     if (!selectOverlay_->IsClosed()) {
1720         selectOverlay_->Close();
1721     }
1722     isSelected_ = false;
1723     // remove selected mask effect
1724     auto host = GetHost();
1725     CHECK_NULL_VOID(host);
1726     RemoveAreaChangeInner();
1727     host->MarkNeedRenderOnly();
1728 }
1729 
HandleCopy()1730 void ImagePattern::HandleCopy()
1731 {
1732     CHECK_NULL_VOID(image_);
1733     if (!clipboard_) {
1734         auto host = GetHost();
1735         CHECK_NULL_VOID(host);
1736         auto pipeline = host->GetContext();
1737         CHECK_NULL_VOID(pipeline);
1738         clipboard_ = ClipboardProxy::GetInstance()->GetClipboard(pipeline->GetTaskExecutor());
1739     }
1740     auto pixmap = image_->GetPixelMap();
1741     if (pixmap) {
1742         clipboard_->SetPixelMapData(pixmap, copyOption_);
1743     } else {
1744         auto host = GetHost();
1745         CHECK_NULL_VOID(host);
1746         clipboard_->SetData(loadingCtx_->GetSourceInfo().GetSrc());
1747     }
1748 }
1749 
ToJsonValue(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter) const1750 void ImagePattern::ToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
1751 {
1752     /* no fixed attr below, just return */
1753     if (filter.IsFastFilter()) {
1754         return;
1755     }
1756     static const char* COPY_OPTIONS[] = { "CopyOptions.None", "CopyOptions.InApp", "CopyOptions.Local",
1757         "CopyOptions.Distributed" };
1758     json->PutExtAttr("copyOption", COPY_OPTIONS[static_cast<int32_t>(copyOption_)], filter);
1759 
1760     json->PutExtAttr("syncLoad", syncLoad_ ? "true" : "false", filter);
1761     json->PutExtAttr("draggable", enableDrag_ ? "true" : "false", filter);
1762     json->PutExtAttr("enableAnalyzer", isEnableAnalyzer_ ? "true" : "false", filter);
1763     auto renderProp = GetPaintProperty<ImageRenderProperty>();
1764     CHECK_NULL_VOID(renderProp);
1765     DynamicRangeMode dynamicMode = DynamicRangeMode::STANDARD;
1766     if (renderProp->HasDynamicMode()) {
1767         dynamicMode = renderProp->GetDynamicMode().value_or(DynamicRangeMode::STANDARD);
1768     }
1769     json->PutExtAttr("dynamicRangeMode", GetDynamicModeString(dynamicMode).c_str(), filter);
1770     json->PutExtAttr("orientation", std::to_string(static_cast<int>(userOrientation_)).c_str(), filter);
1771     Matrix4 defaultMatrixValue = Matrix4(1.0f, 0, 0, 0, 0, 1.0f, 0, 0, 0, 0, 1.0f, 0, 0, 0, 0, 1.0f);
1772     Matrix4 matrixValue = renderProp->HasImageMatrix() ? renderProp->GetImageMatrixValue() : defaultMatrixValue;
1773     json->PutExtAttr("imageMatrix", matrixValue.ToString().c_str(), filter);
1774     if (loadingCtx_) {
1775         json->PutExtAttr("imageWidth", std::to_string(loadingCtx_->GetOriginImageSize().Width()).c_str(), filter);
1776         json->PutExtAttr("imageHeight", std::to_string(loadingCtx_->GetOriginImageSize().Height()).c_str(), filter);
1777     }
1778 }
1779 
DumpLayoutInfo()1780 void ImagePattern::DumpLayoutInfo()
1781 {
1782     DumpLog::GetInstance().AddDesc("---- Image Component Layout Dump ----");
1783     auto layoutProp = GetLayoutProperty<ImageLayoutProperty>();
1784     CHECK_NULL_VOID(layoutProp);
1785 
1786     DumpImageSourceInfo(layoutProp);
1787     DumpAltSourceInfo(layoutProp);
1788     DumpImageFit(layoutProp);
1789     DumpFitOriginalSize(layoutProp);
1790     DumpSourceSize(layoutProp);
1791     DumpAutoResize(layoutProp);
1792 }
1793 
DumpImageSourceInfo(const RefPtr<OHOS::Ace::NG::ImageLayoutProperty> & layoutProp)1794 void ImagePattern::DumpImageSourceInfo(const RefPtr<OHOS::Ace::NG::ImageLayoutProperty>& layoutProp)
1795 {
1796     auto src = layoutProp->GetImageSourceInfo().value_or(ImageSourceInfo(""));
1797     DumpLog::GetInstance().AddDesc(std::string("url: ").append(src.ToString()));
1798     DumpLog::GetInstance().AddDesc(
1799         std::string("SrcType: ").append(std::to_string(static_cast<int32_t>(src.GetSrcType()))));
1800     DumpLog::GetInstance().AddDesc(
1801         std::string("AbilityName: ").append(std::to_string(static_cast<int32_t>(Container::CurrentColorMode()))));
1802     DumpLog::GetInstance().AddDesc(std::string("BundleName: ").append(src.GetBundleName()));
1803     DumpLog::GetInstance().AddDesc(std::string("ModuleName: ").append(src.GetModuleName()));
1804     DumpLog::GetInstance().AddDesc(
1805         std::string("ColorMode: ").append(std::to_string(static_cast<int32_t>(Container::CurrentColorMode()))));
1806     DumpLog::GetInstance().AddDesc(
1807         std::string("LocalColorMode: ").append(std::to_string(static_cast<int32_t>(src.GetLocalColorMode()))));
1808 }
1809 
DumpAltSourceInfo(const RefPtr<OHOS::Ace::NG::ImageLayoutProperty> & layoutProp)1810 inline void ImagePattern::DumpAltSourceInfo(const RefPtr<OHOS::Ace::NG::ImageLayoutProperty>& layoutProp)
1811 {
1812     auto altSrc = layoutProp->GetAlt().value_or(ImageSourceInfo(""));
1813     DumpLog::GetInstance().AddDesc(std::string("altUrl: ").append(altSrc.ToString()));
1814 }
1815 
DumpImageFit(const RefPtr<OHOS::Ace::NG::ImageLayoutProperty> & layoutProp)1816 inline void ImagePattern::DumpImageFit(const RefPtr<OHOS::Ace::NG::ImageLayoutProperty>& layoutProp)
1817 {
1818     auto imageFit = layoutProp->GetImageFit().value_or(ImageFit::COVER);
1819     DumpLog::GetInstance().AddDesc(std::string("objectFit: ").append(GetImageFitStr(imageFit)));
1820 }
1821 
DumpFitOriginalSize(const RefPtr<OHOS::Ace::NG::ImageLayoutProperty> & layoutProp)1822 inline void ImagePattern::DumpFitOriginalSize(const RefPtr<OHOS::Ace::NG::ImageLayoutProperty>& layoutProp)
1823 {
1824     auto fitOriginalSize = layoutProp->GetFitOriginalSize().value_or(false);
1825     DumpLog::GetInstance().AddDesc(std::string("fitOriginalSize: ").append(fitOriginalSize ? "true" : "false"));
1826 }
1827 
DumpSourceSize(const RefPtr<OHOS::Ace::NG::ImageLayoutProperty> & layoutProp)1828 inline void ImagePattern::DumpSourceSize(const RefPtr<OHOS::Ace::NG::ImageLayoutProperty>& layoutProp)
1829 {
1830     const std::optional<SizeF>& sourceSize = layoutProp->GetSourceSize();
1831     if (sourceSize.has_value()) {
1832         DumpLog::GetInstance().AddDesc(std::string("sourceSize: ").append(sourceSize.value().ToString()));
1833     }
1834 }
1835 
DumpAutoResize(const RefPtr<OHOS::Ace::NG::ImageLayoutProperty> & layoutProp)1836 inline void ImagePattern::DumpAutoResize(const RefPtr<OHOS::Ace::NG::ImageLayoutProperty>& layoutProp)
1837 {
1838     bool autoResize = layoutProp->GetAutoResize().value_or(autoResizeDefault_);
1839     autoResize ? DumpLog::GetInstance().AddDesc("autoResize:true") : DumpLog::GetInstance().AddDesc("autoResize:false");
1840 }
1841 
DumpRenderInfo()1842 void ImagePattern::DumpRenderInfo()
1843 {
1844     DumpLog::GetInstance().AddDesc("---- Image Component Render Dump ----");
1845     auto renderProp = GetPaintProperty<ImageRenderProperty>();
1846     CHECK_NULL_VOID(renderProp);
1847 
1848     DumpRenderMode(renderProp);
1849     DumpImageRepeat(renderProp);
1850     DumpImageColorFilter(renderProp);
1851     DumpFillColor(renderProp);
1852     DumpDynamicRangeMode(renderProp);
1853     DumpMatchTextDirection(renderProp);
1854     DumpSmoothEdge(renderProp);
1855     DumpBorderRadiusProperties(renderProp);
1856     DumpResizable(renderProp);
1857     DumpHdrBrightness(renderProp);
1858 }
1859 
DumpHdrBrightness(const RefPtr<OHOS::Ace::NG::ImageRenderProperty> & renderProp)1860 inline void ImagePattern::DumpHdrBrightness(const RefPtr<OHOS::Ace::NG::ImageRenderProperty>& renderProp)
1861 {
1862     if (renderProp->HasHdrBrightness()) {
1863         auto hdrBrightness = renderProp->GetHdrBrightness().value();
1864         DumpLog::GetInstance().AddDesc(std::string("hdrBrightness: ").append(std::to_string(hdrBrightness)));
1865     }
1866 }
1867 
DumpRenderMode(const RefPtr<OHOS::Ace::NG::ImageRenderProperty> & renderProp)1868 inline void ImagePattern::DumpRenderMode(const RefPtr<OHOS::Ace::NG::ImageRenderProperty>& renderProp)
1869 {
1870     auto imageRenderMode = renderProp->GetImageRenderMode().value_or(ImageRenderMode::ORIGINAL);
1871     DumpLog::GetInstance().AddDesc(
1872         std::string("renderMode: ").append((imageRenderMode == ImageRenderMode::ORIGINAL) ? "Original" : "Template"));
1873 }
1874 
DumpImageRepeat(const RefPtr<OHOS::Ace::NG::ImageRenderProperty> & renderProp)1875 inline void ImagePattern::DumpImageRepeat(const RefPtr<OHOS::Ace::NG::ImageRenderProperty>& renderProp)
1876 {
1877     auto imageRepeat = renderProp->GetImageRepeat().value_or(ImageRepeat::NO_REPEAT);
1878     DumpLog::GetInstance().AddDesc(std::string("objectRepeat: ").append(GetImageRepeatStr(imageRepeat)));
1879 }
1880 
DumpImageColorFilter(const RefPtr<OHOS::Ace::NG::ImageRenderProperty> & renderProp)1881 inline void ImagePattern::DumpImageColorFilter(const RefPtr<OHOS::Ace::NG::ImageRenderProperty>& renderProp)
1882 {
1883     auto imageColorFilter = renderProp->GetColorFilter();
1884     if (imageColorFilter.has_value()) {
1885         auto colorFilter = imageColorFilter.value();
1886         DumpLog::GetInstance().AddDesc(std::string("colorFilter: ").append(GetImageColorFilterStr(colorFilter)));
1887     }
1888 }
1889 
DumpFillColor(const RefPtr<OHOS::Ace::NG::ImageRenderProperty> & renderProp)1890 inline void ImagePattern::DumpFillColor(const RefPtr<OHOS::Ace::NG::ImageRenderProperty>& renderProp)
1891 {
1892     auto fillColor = renderProp->GetSvgFillColor();
1893     if (fillColor.has_value()) {
1894         auto color = fillColor.value();
1895         DumpLog::GetInstance().AddDesc(std::string("fillColor_value: ").append(color.ToSvgFillColorKey()));
1896     }
1897 }
1898 
DumpDynamicRangeMode(const RefPtr<OHOS::Ace::NG::ImageRenderProperty> & renderProp)1899 inline void ImagePattern::DumpDynamicRangeMode(const RefPtr<OHOS::Ace::NG::ImageRenderProperty>& renderProp)
1900 {
1901     DynamicRangeMode dynamicMode = DynamicRangeMode::STANDARD;
1902     if (renderProp->HasDynamicMode()) {
1903         dynamicMode = renderProp->GetDynamicMode().value_or(DynamicRangeMode::STANDARD);
1904         DumpLog::GetInstance().AddDesc(std::string("dynamicRangeMode: ").append(GetDynamicModeString(dynamicMode)));
1905     }
1906 }
1907 
DumpMatchTextDirection(const RefPtr<OHOS::Ace::NG::ImageRenderProperty> & renderProp)1908 inline void ImagePattern::DumpMatchTextDirection(const RefPtr<OHOS::Ace::NG::ImageRenderProperty>& renderProp)
1909 {
1910     auto matchTextDirection = renderProp->GetMatchTextDirection().value_or(false);
1911     matchTextDirection ? DumpLog::GetInstance().AddDesc("matchTextDirection:true")
1912                        : DumpLog::GetInstance().AddDesc("matchTextDirection:false");
1913 }
1914 
DumpSmoothEdge(const RefPtr<OHOS::Ace::NG::ImageRenderProperty> & renderProp)1915 inline void ImagePattern::DumpSmoothEdge(const RefPtr<OHOS::Ace::NG::ImageRenderProperty>& renderProp)
1916 {
1917     auto smoothEdge = renderProp->GetSmoothEdge();
1918     if (smoothEdge.has_value()) {
1919         DumpLog::GetInstance().AddDesc(std::string("edgeAntialiasing: ").append(std::to_string(smoothEdge.value())));
1920     }
1921 }
1922 
DumpResizable(const RefPtr<OHOS::Ace::NG::ImageRenderProperty> & renderProp)1923 inline void ImagePattern::DumpResizable(const RefPtr<OHOS::Ace::NG::ImageRenderProperty>& renderProp)
1924 {
1925     if (renderProp->HasImageResizableSlice() && renderProp->GetImageResizableSliceValue({}).Valid()) {
1926         DumpLog::GetInstance().AddDesc(
1927             std::string("resizable slice: ").append(renderProp->GetImageResizableSliceValue({}).ToString()));
1928     } else {
1929         DumpLog::GetInstance().AddDesc(std::string("resizableSlice: Slice is null"));
1930     }
1931 
1932     auto resizableLattice = renderProp->GetImageResizableLatticeValue(nullptr);
1933     DumpLog::GetInstance().AddDesc(
1934         "resizableLattice:" + (resizableLattice ? resizableLattice->DumpToString() : "Lattice is null"));
1935 }
1936 
DumpBorderRadiusProperties(const RefPtr<OHOS::Ace::NG::ImageRenderProperty> & renderProp)1937 void ImagePattern::DumpBorderRadiusProperties(const RefPtr<OHOS::Ace::NG::ImageRenderProperty>& renderProp)
1938 {
1939     auto needBorderRadius = renderProp->GetNeedBorderRadius().value_or(false);
1940     needBorderRadius ? DumpLog::GetInstance().AddDesc("needBorderRadius:true")
1941                      : DumpLog::GetInstance().AddDesc("needBorderRadius:false");
1942 
1943     auto borderRadius = renderProp->GetBorderRadius().value_or(BorderRadiusProperty());
1944     DumpLog::GetInstance().AddDesc("ImageBorderRadius:" + borderRadius.ToString());
1945 
1946     auto host = GetHost();
1947     CHECK_NULL_VOID(host);
1948     auto renderContext = host->GetRenderContext();
1949     CHECK_NULL_VOID(renderContext);
1950     if (renderContext->HasBorderRadius()) {
1951         DumpLog::GetInstance().AddDesc(
1952             "borderRadius:" + renderContext->GetBorderRadiusValue(BorderRadiusProperty()).ToString());
1953     } else {
1954         DumpLog::GetInstance().AddDesc("borderRadius: null");
1955     }
1956 }
1957 
DumpInterpolation(const RefPtr<OHOS::Ace::NG::ImageRenderProperty> & renderProp)1958 void ImagePattern::DumpInterpolation(const RefPtr<OHOS::Ace::NG::ImageRenderProperty>& renderProp)
1959 {
1960     auto imageInterpolation = renderProp->GetImageInterpolation().value_or(interpolationDefault_);
1961     DumpLog::GetInstance().AddDesc("imageInterpolation:" + GetImageInterpolation(imageInterpolation));
1962 }
1963 
DumpSvgInfo()1964 void ImagePattern::DumpSvgInfo()
1965 {
1966     DumpLog::GetInstance().AddDesc("---- SVG Related Dump ----");
1967     DumpLog::GetInstance().AddDesc("Your SVG related log description here");
1968     auto imageLayoutProperty = GetLayoutProperty<ImageLayoutProperty>();
1969     CHECK_NULL_VOID(imageLayoutProperty);
1970     auto imageSourceInfo = imageLayoutProperty->GetImageSourceInfo();
1971     CHECK_NULL_VOID(imageSourceInfo);
1972     if (!imageSourceInfo->IsSvg() || !loadingCtx_) {
1973         return;
1974     }
1975     auto imageObject = loadingCtx_->GetImageObject();
1976     CHECK_NULL_VOID(imageObject);
1977     DumpLog::GetInstance().AddDesc(std::string("Svg:").append(imageObject->GetDumpInfo()));
1978 }
1979 
DumpOtherInfo()1980 void ImagePattern::DumpOtherInfo()
1981 {
1982     DumpLog::GetInstance().AddDesc("---- Image Component (Excluding Layout and Drawing) Other Info Dump ----");
1983     DumpLog::GetInstance().AddDesc(renderedImageInfo_.ToString());
1984     syncLoad_ ? DumpLog::GetInstance().AddDesc("syncLoad:true") : DumpLog::GetInstance().AddDesc("syncLoad:false");
1985 
1986     if (loadingCtx_) {
1987         auto currentLoadImageState = loadingCtx_->GetCurrentLoadingState();
1988         DumpLog::GetInstance().AddDesc(std::string("currentLoadImageState : ").append(currentLoadImageState));
1989         DumpLog::GetInstance().AddDesc(
1990             std::string("rawImageSize: ").append(loadingCtx_->GetOriginImageSize().ToString()));
1991         DumpLog::GetInstance().AddDesc(std::string("LoadErrorMsg: ").append(loadingCtx_->GetErrorMsg()));
1992         DumpLog::GetInstance().AddDesc(
1993             std::string("ImageDataSizeInfo: ").append(loadingCtx_->GetImageSizeInfo()));
1994     } else {
1995         DumpLog::GetInstance().AddDesc(std::string("imageLoadingContext: null"));
1996     }
1997 
1998     enableDrag_ ? DumpLog::GetInstance().AddDesc("draggable:true") : DumpLog::GetInstance().AddDesc("draggable:false");
1999     DumpLog::GetInstance().AddDesc(
2000         std::string("userOrientation: ").append(ConvertOrientationToString(userOrientation_)));
2001     DumpLog::GetInstance().AddDesc(
2002         std::string("selfOrientation: ").append(ConvertOrientationToString(selfOrientation_)));
2003     DumpLog::GetInstance().AddDesc(std::string("enableAnalyzer: ").append(isEnableAnalyzer_ ? "true" : "false"));
2004     DumpMenmoryNameId();
2005 }
2006 
DumpMenmoryNameId()2007 void ImagePattern::DumpMenmoryNameId()
2008 {
2009     auto host = GetHost();
2010     CHECK_NULL_VOID(host);
2011     auto id = host->GetInspectorId();
2012     if (id.has_value() && hasSetPixelMapMemoryName_) {
2013         DumpLog::GetInstance().AddDesc(std::string("PixelMapMemoryName id : ").append(id.value()));
2014     }
2015 }
2016 
DumpInfo()2017 void ImagePattern::DumpInfo()
2018 {
2019     DumpLayoutInfo();
2020     DumpRenderInfo();
2021     DumpSvgInfo();
2022     DumpOtherInfo();
2023 }
2024 
DumpAdvanceInfo()2025 void ImagePattern::DumpAdvanceInfo()
2026 {
2027     auto layoutProp = GetLayoutProperty<ImageLayoutProperty>();
2028     CHECK_NULL_VOID(layoutProp);
2029     auto src = layoutProp->GetImageSourceInfo().value_or(ImageSourceInfo(""));
2030     DumpLog::GetInstance().AddDesc(std::string("url: ").append(src.ToString()));
2031     syncLoad_ ? DumpLog::GetInstance().AddDesc("syncLoad:true") : DumpLog::GetInstance().AddDesc("syncLoad:false");
2032     if (loadingCtx_) {
2033         auto currentLoadImageState = loadingCtx_->GetCurrentLoadingState();
2034         DumpLog::GetInstance().AddDesc(std::string("currentLoadImageState : ").append(currentLoadImageState));
2035     }
2036 }
2037 
UpdateDragEvent(const RefPtr<OHOS::Ace::DragEvent> & event)2038 void ImagePattern::UpdateDragEvent(const RefPtr<OHOS::Ace::DragEvent>& event)
2039 {
2040     RefPtr<UnifiedData> unifiedData = UdmfClient::GetInstance()->CreateUnifiedData();
2041     if (loadingCtx_ && image_ && loadingCtx_->GetSourceInfo().IsPixmap()) {
2042         auto pixelMap = image_->GetPixelMap();
2043         CHECK_NULL_VOID(pixelMap);
2044         std::vector<uint8_t> data;
2045         if (!pixelMap->GetPixelsVec(data)) {
2046             return;
2047         }
2048         PixelMapRecordDetails details = { pixelMap->GetWidth(), pixelMap->GetHeight(), pixelMap->GetPixelFormat(),
2049             pixelMap->GetAlphaType() };
2050         UdmfClient::GetInstance()->AddPixelMapRecord(unifiedData, data, details);
2051     } else if (loadingCtx_) {
2052         UdmfClient::GetInstance()->AddImageRecord(unifiedData, loadingCtx_->GetSourceInfo().GetSrc());
2053     }
2054     event->SetData(unifiedData);
2055 }
2056 
OnLanguageConfigurationUpdate()2057 void ImagePattern::OnLanguageConfigurationUpdate()
2058 {
2059     CHECK_NULL_VOID(loadingCtx_);
2060     auto&& src = loadingCtx_->GetSourceInfo();
2061     // Resource image needs to reload when Language changes
2062     if (src.GetSrcType() == SrcType::RESOURCE) {
2063         loadingCtx_.Reset();
2064     }
2065     OnConfigurationUpdate();
2066 }
2067 
OnColorConfigurationUpdate()2068 void ImagePattern::OnColorConfigurationUpdate()
2069 {
2070     OnConfigurationUpdate();
2071     if (!SystemProperties::ConfigChangePerform()) {
2072         return;
2073     }
2074     auto host = GetHost();
2075     CHECK_NULL_VOID(host);
2076     auto pipeline = host->GetContext();
2077     CHECK_NULL_VOID(pipeline);
2078     auto theme = pipeline->GetTheme<ImageTheme>();
2079     CHECK_NULL_VOID(theme);
2080     auto layoutProperty = host->GetLayoutProperty<ImageLayoutProperty>();
2081     CHECK_NULL_VOID(layoutProperty);
2082     if (layoutProperty->GetImageFillSetByUserValue(false)) {
2083         if (Container::LessThanAPITargetVersion(PlatformVersion::VERSION_ELEVEN)) {
2084             return;
2085         }
2086         CHECK_NULL_VOID(theme);
2087         auto color = theme->GetFillColor();
2088         UpdateImageFill(color);
2089     }
2090 }
2091 
OnDirectionConfigurationUpdate()2092 void ImagePattern::OnDirectionConfigurationUpdate()
2093 {
2094     OnConfigurationUpdate();
2095 }
2096 
OnIconConfigurationUpdate()2097 void ImagePattern::OnIconConfigurationUpdate()
2098 {
2099     OnConfigurationUpdate();
2100 }
2101 
OnConfigurationUpdate()2102 void ImagePattern::OnConfigurationUpdate()
2103 {
2104     isFullyInitializedFromTheme_ = false;
2105     TAG_LOGD(AceLogTag::ACE_IMAGE, "OnConfigurationUpdate, %{public}s-%{public}d",
2106         imageDfxConfig_.ToStringWithoutSrc().c_str(), loadingCtx_ ? 1 : 0);
2107     CHECK_NULL_VOID(loadingCtx_);
2108     auto imageLayoutProperty = GetLayoutProperty<ImageLayoutProperty>();
2109     auto host = GetHost();
2110     CHECK_NULL_VOID(host);
2111     auto src = imageLayoutProperty->GetImageSourceInfo().value_or(ImageSourceInfo(""));
2112     UpdateInternalResource(src);
2113     bool needLayout = host->CheckNeedForceMeasureAndLayout() &&
2114                           imageLayoutProperty->GetVisibility().value_or(VisibleType::VISIBLE) != VisibleType::GONE;
2115     LoadImage(src, needLayout);
2116     if (loadingCtx_->NeedAlt() && imageLayoutProperty->GetAlt()) {
2117         auto altImageSourceInfo = imageLayoutProperty->GetAlt().value_or(ImageSourceInfo(""));
2118         if (altLoadingCtx_ && altLoadingCtx_->GetSourceInfo() == altImageSourceInfo) {
2119             altLoadingCtx_.Reset();
2120         }
2121         LoadAltImage(altImageSourceInfo);
2122     }
2123 }
2124 
GetImageFitStr(ImageFit value)2125 std::string ImagePattern::GetImageFitStr(ImageFit value)
2126 {
2127     switch (value) {
2128         case ImageFit::CONTAIN:
2129             return "CONTAIN";
2130         case ImageFit::COVER:
2131             return "COVER";
2132         case ImageFit::FILL:
2133             return "FILL";
2134         case ImageFit::FITWIDTH:
2135             return "FITWIDTH";
2136         case ImageFit::FITHEIGHT:
2137             return "FITHEIGHT";
2138         case ImageFit::NONE:
2139             return "NONE";
2140         case ImageFit::SCALE_DOWN:
2141             return "SCALE_DOWN";
2142         case ImageFit::TOP_LEFT:
2143             return "TOP_LEFT";
2144         default:
2145             return "COVER";
2146     }
2147 }
2148 
GetImageRepeatStr(ImageRepeat value)2149 std::string ImagePattern::GetImageRepeatStr(ImageRepeat value)
2150 {
2151     switch (value) {
2152         case ImageRepeat::NO_REPEAT:
2153             return "NO_REPEAT";
2154         case ImageRepeat::REPEAT:
2155             return "REPEAT_XY";
2156         case ImageRepeat::REPEAT_X:
2157             return "REPEAT_X";
2158         case ImageRepeat::REPEAT_Y:
2159             return "REPEAT_Y";
2160         default:
2161             return "NO_REPEAT";
2162     }
2163 }
2164 
GetImageColorFilterStr(const std::vector<float> & colorFilter)2165 std::string ImagePattern::GetImageColorFilterStr(const std::vector<float>& colorFilter)
2166 {
2167     if (colorFilter.empty()) {
2168         return "";
2169     }
2170     std::string result = "[" + std::to_string(colorFilter[0]);
2171     for (uint32_t idx = 1; idx < colorFilter.size(); ++idx) {
2172         result += ", " + std::to_string(colorFilter[idx]);
2173     }
2174     return result + "]";
2175 }
2176 
GetSrcTypeToString(SrcType srcType)2177 std::string ImagePattern::GetSrcTypeToString(SrcType srcType)
2178 {
2179     static const std::unordered_map<SrcType, std::string> typeMap = { { SrcType::UNSUPPORTED, "unsupported" },
2180         { SrcType::FILE, "file" }, { SrcType::ASSET, "asset" }, { SrcType::NETWORK, "network" },
2181         { SrcType::MEMORY, "memory" }, { SrcType::BASE64, "base64" }, { SrcType::INTERNAL, "internal" },
2182         { SrcType::RESOURCE, "resource" }, { SrcType::DATA_ABILITY, "dataAbility" },
2183         { SrcType::DATA_ABILITY_DECODED, "dataAbilityDecoded" }, { SrcType::RESOURCE_ID, "resourceId" },
2184         { SrcType::PIXMAP, "pixmap" }, { SrcType::ASTC, "astc" } };
2185 
2186     auto iter = typeMap.find(srcType);
2187     if (iter != typeMap.end()) {
2188         return iter->second;
2189     }
2190 
2191     return "";
2192 }
2193 
EnableAnalyzer(bool value)2194 void ImagePattern::EnableAnalyzer(bool value)
2195 {
2196     isEnableAnalyzer_ = value;
2197     if (!isEnableAnalyzer_) {
2198         DestroyAnalyzerOverlay();
2199         return;
2200     }
2201 
2202     if (!imageAnalyzerManager_) {
2203         imageAnalyzerManager_ = std::make_shared<ImageAnalyzerManager>(GetHost(), ImageAnalyzerHolder::IMAGE);
2204     }
2205     RegisterVisibleAreaChange(true);
2206 }
2207 
IsEnableAnalyzer() const2208 bool ImagePattern::IsEnableAnalyzer() const
2209 {
2210     return isEnableAnalyzer_;
2211 }
2212 
2213 // As an example
SetImageAnalyzerConfig(const ImageAnalyzerConfig & config)2214 void ImagePattern::SetImageAnalyzerConfig(const ImageAnalyzerConfig& config)
2215 {
2216     if (!isEnableAnalyzer_) {
2217         return;
2218     }
2219 }
2220 
SetImageAnalyzerConfig(void * config)2221 void ImagePattern::SetImageAnalyzerConfig(void* config)
2222 {
2223     if (isEnableAnalyzer_) {
2224         CHECK_NULL_VOID(imageAnalyzerManager_);
2225         imageAnalyzerManager_->SetImageAnalyzerConfig(config);
2226     }
2227 }
2228 
SetImageAIOptions(void * options)2229 void ImagePattern::SetImageAIOptions(void* options)
2230 {
2231     if (!imageAnalyzerManager_) {
2232         imageAnalyzerManager_ = std::make_shared<ImageAnalyzerManager>(GetHost(), ImageAnalyzerHolder::IMAGE);
2233     }
2234     CHECK_NULL_VOID(imageAnalyzerManager_);
2235     imageAnalyzerManager_->SetImageAIOptions(options);
2236 }
2237 
IsSupportImageAnalyzerFeature()2238 bool ImagePattern::IsSupportImageAnalyzerFeature()
2239 {
2240     CHECK_NULL_RETURN(imageAnalyzerManager_, false);
2241     return isEnableAnalyzer_ && image_ && !loadingCtx_->GetSourceInfo().IsSvg() && loadingCtx_->GetFrameCount() <= 1 &&
2242            imageAnalyzerManager_->IsSupportImageAnalyzerFeature();
2243 }
2244 
CreateAnalyzerOverlay()2245 void ImagePattern::CreateAnalyzerOverlay()
2246 {
2247     CHECK_NULL_VOID(imageAnalyzerManager_);
2248     if (imageAnalyzerManager_->IsOverlayCreated()) {
2249         return;
2250     }
2251 
2252     CHECK_NULL_VOID(image_);
2253     auto pixelMap = image_->GetPixelMap();
2254     CHECK_NULL_VOID(pixelMap);
2255     imageAnalyzerManager_->CreateAnalyzerOverlay(pixelMap);
2256 }
2257 
UpdateAnalyzerOverlay()2258 void ImagePattern::UpdateAnalyzerOverlay()
2259 {
2260     CHECK_NULL_VOID(imageAnalyzerManager_);
2261     if (!IsSupportImageAnalyzerFeature() || !imageAnalyzerManager_->IsOverlayCreated()) {
2262         return;
2263     }
2264 
2265     CHECK_NULL_VOID(image_);
2266     auto pixelMap = image_->GetPixelMap();
2267     CHECK_NULL_VOID(pixelMap);
2268     imageAnalyzerManager_->UpdateAnalyzerOverlay(pixelMap);
2269 }
2270 
UpdateAnalyzerOverlayLayout()2271 void ImagePattern::UpdateAnalyzerOverlayLayout()
2272 {
2273     CHECK_NULL_VOID(imageAnalyzerManager_);
2274     imageAnalyzerManager_->UpdateAnalyzerOverlayLayout();
2275 }
2276 
DestroyAnalyzerOverlay()2277 void ImagePattern::DestroyAnalyzerOverlay()
2278 {
2279     CHECK_NULL_VOID(imageAnalyzerManager_);
2280     imageAnalyzerManager_->DestroyAnalyzerOverlay();
2281 }
2282 
ReleaseImageAnalyzer()2283 void ImagePattern::ReleaseImageAnalyzer()
2284 {
2285     CHECK_NULL_VOID(imageAnalyzerManager_);
2286     imageAnalyzerManager_->ReleaseImageAnalyzer();
2287 }
2288 
UpdateAnalyzerUIConfig(const RefPtr<NG::GeometryNode> & geometryNode)2289 void ImagePattern::UpdateAnalyzerUIConfig(const RefPtr<NG::GeometryNode>& geometryNode)
2290 {
2291     CHECK_NULL_VOID(imageAnalyzerManager_);
2292     imageAnalyzerManager_->UpdateAnalyzerUIConfig(geometryNode);
2293 }
2294 
AllowVisibleAreaCheck() const2295 bool ImagePattern::AllowVisibleAreaCheck() const
2296 {
2297     auto frameNode = GetHost();
2298     CHECK_NULL_RETURN(frameNode, false);
2299     RefPtr<FrameNode> parentUi = frameNode->GetAncestorNodeOfFrame(true);
2300     while (parentUi) {
2301         auto layoutProperty = parentUi->GetLayoutProperty();
2302         if (layoutProperty && layoutProperty->IsOverlayNode()) {
2303             return true;
2304         }
2305         parentUi = parentUi->GetAncestorNodeOfFrame(true);
2306     }
2307     return false;
2308 }
2309 
InitDefaultValue()2310 void ImagePattern::InitDefaultValue()
2311 {
2312     // add API version protection
2313     if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
2314         autoResizeDefault_ = false;
2315         interpolationDefault_ = ImageInterpolation::LOW;
2316     }
2317     auto container = Container::Current();
2318     // If the default value is set to false, the SceneBoard memory increases.
2319     // Therefore the default value is different in the SceneBoard.
2320     if (container && container->IsSceneBoardWindow()) {
2321         isSceneBoardWindow_ = true;
2322         autoResizeDefault_ = true;
2323         interpolationDefault_ = ImageInterpolation::NONE;
2324     }
2325 }
2326 
hasSceneChanged()2327 bool ImagePattern::hasSceneChanged()
2328 {
2329     auto imageLayoutProperty = GetLayoutProperty<ImageLayoutProperty>();
2330     CHECK_NULL_RETURN(imageLayoutProperty, false);
2331     auto src = imageLayoutProperty->GetImageSourceInfo().value_or(ImageSourceInfo(""));
2332     UpdateInternalResource(src);
2333     return true;
2334 }
2335 
ImageAnimatorPattern()2336 void ImagePattern::ImageAnimatorPattern()
2337 {
2338     animator_ = CREATE_ANIMATOR();
2339     animator_->SetFillMode(FillMode::BACKWARDS);
2340     animator_->SetDuration(DEFAULT_DURATION);
2341     ResetFormAnimationFlag();
2342 }
2343 
CreatePictureAnimation(int32_t size)2344 RefPtr<PictureAnimation<int32_t>> ImagePattern::CreatePictureAnimation(int32_t size)
2345 {
2346     auto pictureAnimation = MakeRefPtr<PictureAnimation<int32_t>>();
2347     if (durationTotal_ > 0) {
2348         for (int32_t index = 0; index < size; ++index) {
2349             pictureAnimation->AddPicture(images_[index].duration / static_cast<float>(durationTotal_), index);
2350         }
2351         animator_->SetDuration(durationTotal_);
2352     } else {
2353         for (int32_t index = 0; index < size; ++index) {
2354             pictureAnimation->AddPicture(NORMALIZED_DURATION_MAX / static_cast<float>(size), index);
2355         }
2356     }
2357 
2358     pictureAnimation->AddListener([weak = WeakClaim(this)](int32_t index) {
2359         auto imageAnimator = weak.Upgrade();
2360         CHECK_NULL_VOID(imageAnimator);
2361         imageAnimator->SetShowingIndex(index);
2362     });
2363     return pictureAnimation;
2364 }
2365 
SetShowingIndex(int32_t index)2366 void ImagePattern::SetShowingIndex(int32_t index)
2367 {
2368     auto host = GetHost();
2369     CHECK_NULL_VOID(host);
2370     auto imageFrameNode = AceType::DynamicCast<FrameNode>(host->GetChildren().front());
2371     CHECK_NULL_VOID(imageFrameNode);
2372     auto imageLayoutProperty = imageFrameNode->GetLayoutProperty<ImageLayoutProperty>();
2373     CHECK_NULL_VOID(imageLayoutProperty);
2374     if (index >= static_cast<int32_t>(images_.size())) {
2375         TAG_LOGW(AceLogTag::ACE_IMAGE, "ImageAnimator InvalidIndex-%{public}d-%{public}zu", index, images_.size());
2376         return;
2377     }
2378     CHECK_NULL_VOID(images_[index].pixelMap);
2379     nowImageIndex_ = index;
2380     auto cacheImageIter = FindCacheImageNode(images_[index].pixelMap);
2381     if (IsShowingSrc(imageFrameNode, images_[index].pixelMap)) {
2382         ACE_SCOPED_TRACE("ImageAnimator same src %s, index %d", "PixelMap", index);
2383         UpdateShowingImageInfo(imageFrameNode, index);
2384     } else if (cacheImageIter == cacheImages_.end()) {
2385         ACE_SCOPED_TRACE("ImageAnimator no cache found, src %s, index %d", "PixelMap", index);
2386         UpdateShowingImageInfo(imageFrameNode, index);
2387     } else if (cacheImageIter->isLoaded) {
2388         ACE_SCOPED_TRACE("ImageAnimator useCache src %s, index %d", "PixelMap", index);
2389         auto cacheImageNode = cacheImageIter->imageNode;
2390         host->RemoveChild(imageFrameNode);
2391         host->AddChild(cacheImageNode, DEFAULT_NODE_SLOT, true);
2392         host->RebuildRenderContextTree();
2393         cacheImages_.erase(cacheImageIter);
2394         CacheImageStruct newCacheImageStruct(imageFrameNode);
2395         newCacheImageStruct.isLoaded = true;
2396         cacheImages_.emplace_back(newCacheImageStruct);
2397         UpdateShowingImageInfo(cacheImageNode, index);
2398     } else {
2399         UpdateShowingImageInfo(imageFrameNode, index);
2400         // wait for cache image loading
2401         ACE_SCOPED_TRACE("ImageAnimator waitForCache src %s, index %d", "PixelMap", index);
2402     }
2403     // update cache images
2404     CHECK_NULL_VOID(cacheImages_.size());
2405     int32_t nextIndex = GetNextIndex(index);
2406     for (auto& cacheImage : cacheImages_) {
2407         UpdateCacheImageInfo(cacheImage, nextIndex);
2408         nextIndex = GetNextIndex(nextIndex);
2409     }
2410     host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
2411 }
2412 
UpdateShowingImageInfo(const RefPtr<FrameNode> & imageFrameNode,int32_t index)2413 void ImagePattern::UpdateShowingImageInfo(const RefPtr<FrameNode>& imageFrameNode, int32_t index)
2414 {
2415     auto host = GetHost();
2416     CHECK_NULL_VOID(host);
2417     auto layoutProperty = host->GetLayoutProperty<ImageLayoutProperty>();
2418     CHECK_NULL_VOID(layoutProperty);
2419     auto imageLayoutProperty = imageFrameNode->GetLayoutProperty<ImageLayoutProperty>();
2420     CHECK_NULL_VOID(imageLayoutProperty);
2421 
2422     imageLayoutProperty->UpdateImageSourceInfo(ImageSourceInfo(images_[index].pixelMap));
2423     SetColorFilter(imageFrameNode);
2424     SetImageFit(imageFrameNode);
2425     // use the size of first pixelmap when no size is set
2426     auto&& layoutConstraint = layoutProperty->GetCalcLayoutConstraint();
2427     if (!layoutConstraint || !layoutConstraint->selfIdealSize.has_value()) {
2428         CalcSize realSize = { CalcLength(images_[0].pixelMap->GetWidth()),
2429             CalcLength(images_[0].pixelMap->GetHeight()) };
2430         imageLayoutProperty->UpdateUserDefinedIdealSize(realSize);
2431         imageLayoutProperty->UpdateMeasureType(MeasureType::MATCH_CONTENT);
2432         imageFrameNode->MarkModifyDone();
2433         imageFrameNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
2434         return;
2435     }
2436     MarginProperty margin;
2437     margin.SetEdges(CalcLength(0.0));
2438     imageLayoutProperty->UpdateMargin(margin);
2439     imageLayoutProperty->ClearUserDefinedIdealSize(true, true);
2440     imageLayoutProperty->UpdateMeasureType(MeasureType::MATCH_PARENT);
2441     imageFrameNode->MarkModifyDone();
2442     imageFrameNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
2443 }
2444 
UpdateCacheImageInfo(CacheImageStruct & cacheImage,int32_t index)2445 void ImagePattern::UpdateCacheImageInfo(CacheImageStruct& cacheImage, int32_t index)
2446 {
2447     if (index >= static_cast<int32_t>(images_.size())) {
2448         TAG_LOGW(AceLogTag::ACE_IMAGE, "index error: %{public}d-%{public}zu", index, images_.size());
2449         return;
2450     }
2451     auto host = GetHost();
2452     CHECK_NULL_VOID(host);
2453     auto layoutProperty = host->GetLayoutProperty<ImageLayoutProperty>();
2454     CHECK_NULL_VOID(layoutProperty);
2455     auto imageLayoutProperty = cacheImage.imageNode->GetLayoutProperty<ImageLayoutProperty>();
2456     CHECK_NULL_VOID(imageLayoutProperty);
2457     CHECK_NULL_VOID(images_[index].pixelMap);
2458     // pixelmap
2459     if (imageLayoutProperty->HasImageSourceInfo()) {
2460         auto preSrc = imageLayoutProperty->GetImageSourceInfoValue().GetPixmap();
2461         if (preSrc != images_[index].pixelMap) {
2462             // need to cache newImage
2463             imageLayoutProperty->UpdateImageSourceInfo(ImageSourceInfo(images_[index].pixelMap));
2464             cacheImage.index = index;
2465             cacheImage.isLoaded = false;
2466         }
2467     }
2468     SetColorFilter(cacheImage.imageNode);
2469     SetImageFit(cacheImage.imageNode);
2470     // use the size of first pixelmap when no size is set
2471     auto&& layoutConstraint = layoutProperty->GetCalcLayoutConstraint();
2472     if (!layoutConstraint || !layoutConstraint->selfIdealSize.has_value()) {
2473         CalcSize realSize = { CalcLength(images_[0].pixelMap->GetWidth()),
2474             CalcLength(images_[0].pixelMap->GetHeight()) };
2475         imageLayoutProperty->UpdateUserDefinedIdealSize(realSize);
2476         cacheImage.imageNode->MarkModifyDone();
2477         return;
2478     }
2479     auto hostSize = host->GetGeometryNode()->GetPaddingSize();
2480     if (!hostSize.IsPositive()) {
2481         // if imageNode size is nonPositive, no pixelMap will be generated. Wait for size.
2482         return;
2483     }
2484     imageLayoutProperty->UpdateUserDefinedIdealSize(
2485         CalcSize(CalcLength(hostSize.Width()), CalcLength(hostSize.Height())));
2486     cacheImage.imageNode->MarkModifyDone();
2487 }
2488 
FindCacheImageNode(const RefPtr<PixelMap> & src)2489 std::list<ImagePattern::CacheImageStruct>::iterator ImagePattern::FindCacheImageNode(const RefPtr<PixelMap>& src)
2490 {
2491     for (auto iter = cacheImages_.begin(); iter != cacheImages_.end(); ++iter) {
2492         if (IsShowingSrc(iter->imageNode, src)) {
2493             return iter;
2494         }
2495     }
2496     return cacheImages_.end();
2497 }
2498 
GenerateCachedImages()2499 void ImagePattern::GenerateCachedImages()
2500 {
2501     CHECK_NULL_VOID(images_.size());
2502     auto averageShowTime = static_cast<uint32_t>(animator_->GetDuration()) / images_.size();
2503     size_t cacheImageNum = averageShowTime >= CRITICAL_TIME ? 1 : 2;
2504     cacheImageNum = std::min(images_.size() - 1, cacheImageNum);
2505     if (cacheImages_.size() > cacheImageNum) {
2506         cacheImages_.resize(cacheImageNum);
2507         return;
2508     }
2509     while (cacheImages_.size() < cacheImageNum) {
2510         auto imageNode = FrameNode::CreateFrameNode(V2::IMAGE_ETS_TAG, -1, AceType::MakeRefPtr<ImagePattern>());
2511         auto imageLayoutProperty = imageNode->GetLayoutProperty();
2512         imageLayoutProperty->UpdateMeasureType(MeasureType::MATCH_PARENT);
2513         imageLayoutProperty->UpdateAlignment(Alignment::TOP_LEFT);
2514         AddImageLoadSuccessEvent(imageNode);
2515         cacheImages_.emplace_back(CacheImageStruct(imageNode));
2516     }
2517 }
2518 
AdaptSelfSize()2519 void ImagePattern::AdaptSelfSize()
2520 {
2521     auto host = GetHost();
2522     CHECK_NULL_VOID(host);
2523     const auto& layoutProperty = host->GetLayoutProperty();
2524     CHECK_NULL_VOID(layoutProperty);
2525     if (layoutProperty->GetCalcLayoutConstraint() && layoutProperty->GetCalcLayoutConstraint()->selfIdealSize &&
2526         layoutProperty->GetCalcLayoutConstraint()->selfIdealSize->IsValid()) {
2527         return;
2528     }
2529     if (images_.empty()) {
2530         return;
2531     }
2532     CHECK_NULL_VOID(images_[0].pixelMap);
2533     hasSizeChanged = true;
2534     CalcSize realSize = { CalcLength(images_[0].pixelMap->GetWidth()), CalcLength(images_[0].pixelMap->GetHeight()) };
2535 
2536     const auto& layoutConstraint = layoutProperty->GetCalcLayoutConstraint();
2537     if (!layoutConstraint || !layoutConstraint->selfIdealSize) {
2538         layoutProperty->UpdateUserDefinedIdealSize(realSize);
2539         return;
2540     }
2541     if (!layoutConstraint->selfIdealSize->Width()) {
2542         layoutProperty->UpdateUserDefinedIdealSize(CalcSize(CalcLength(images_[0].pixelMap->GetWidth()), std::nullopt));
2543         return;
2544     }
2545     layoutProperty->UpdateUserDefinedIdealSize(CalcSize(std::nullopt, CalcLength(images_[0].pixelMap->GetHeight())));
2546 }
2547 
GetNextIndex(int32_t preIndex)2548 int32_t ImagePattern::GetNextIndex(int32_t preIndex)
2549 {
2550     return (preIndex + 1) % static_cast<int32_t>(images_.size());
2551 }
2552 
AddImageLoadSuccessEvent(const RefPtr<FrameNode> & imageFrameNode)2553 void ImagePattern::AddImageLoadSuccessEvent(const RefPtr<FrameNode>& imageFrameNode)
2554 {
2555     CHECK_NULL_VOID(imageFrameNode);
2556     auto eventHub = imageFrameNode->GetOrCreateEventHub<ImageEventHub>();
2557     eventHub->SetOnComplete(
2558         [weakImage = WeakPtr<FrameNode>(imageFrameNode), weak = WeakClaim(this)](const LoadImageSuccessEvent& info) {
2559             if (info.GetLoadingStatus() != 1) {
2560                 // status 1 means load success. Only need loadSuccess event.
2561                 return;
2562             }
2563             auto pattern = weak.Upgrade();
2564             CHECK_NULL_VOID(pattern);
2565             auto cacheImageNode = weakImage.Upgrade();
2566             CHECK_NULL_VOID(cacheImageNode);
2567             auto imageAnimator = pattern->GetHost();
2568             CHECK_NULL_VOID(imageAnimator);
2569             auto cacheLayoutProperty = cacheImageNode->GetLayoutProperty<ImageLayoutProperty>();
2570             auto cacheSrc = cacheLayoutProperty->GetImageSourceInfoValue(ImageSourceInfo()).GetSrc();
2571             ACE_SCOPED_TRACE("ImageAnimator cache succeed. src %s", cacheSrc.c_str());
2572             auto iter = std::find_if(pattern->cacheImages_.begin(), pattern->cacheImages_.end(),
2573                 [&cacheImageNode](const CacheImageStruct& other) { return other.imageNode == cacheImageNode; });
2574             if (iter == pattern->cacheImages_.end()) {
2575                 return;
2576             }
2577             iter->isLoaded = true;
2578             if (pattern->nowImageIndex_ >= static_cast<int32_t>(pattern->images_.size())) {
2579                 TAG_LOGW(AceLogTag::ACE_IMAGE, "index is invalid");
2580                 return;
2581             }
2582             if (pattern->nowImageIndex_ == iter->index &&
2583                 IsShowingSrc(cacheImageNode, pattern->images_[pattern->nowImageIndex_].pixelMap)) {
2584                 pattern->SetShowingIndex(pattern->nowImageIndex_);
2585             }
2586         });
2587 }
2588 
IsShowingSrc(const RefPtr<FrameNode> & imageFrameNode,const RefPtr<PixelMap> & src)2589 bool ImagePattern::IsShowingSrc(const RefPtr<FrameNode>& imageFrameNode, const RefPtr<PixelMap>& src)
2590 {
2591     auto imageLayoutProperty = imageFrameNode->GetLayoutProperty<ImageLayoutProperty>();
2592     return imageLayoutProperty->HasImageSourceInfo() &&
2593            imageLayoutProperty->GetImageSourceInfoValue().GetPixmap() == src;
2594 }
2595 
IsFormRender()2596 bool ImagePattern::IsFormRender()
2597 {
2598     auto pipeline = PipelineBase::GetCurrentContext();
2599     CHECK_NULL_RETURN(pipeline, false);
2600     return pipeline->IsFormRenderExceptDynamicComponent();
2601 }
2602 
UpdateFormDurationByRemainder()2603 void ImagePattern::UpdateFormDurationByRemainder()
2604 {
2605     if (IsFormRender()) {
2606         if (!isFormAnimationStart_) {
2607             formAnimationRemainder_ =
2608                 DEFAULT_DURATION - (GetMicroTickCount() - formAnimationStartTime_) / MICROSEC_TO_MILLISEC;
2609         }
2610         if ((formAnimationRemainder_ > 0) && (animator_->GetDuration() > formAnimationRemainder_)) {
2611             animator_->SetDuration(formAnimationRemainder_);
2612         }
2613         if (formAnimationRemainder_ <= 0) {
2614             isFormAnimationEnd_ = true;
2615         }
2616     }
2617 }
2618 
ResetFormAnimationStartTime()2619 void ImagePattern::ResetFormAnimationStartTime()
2620 {
2621     if (isFormAnimationStart_) {
2622         isFormAnimationStart_ = false;
2623         formAnimationStartTime_ = GetMicroTickCount();
2624     }
2625 }
2626 
ResetFormAnimationFlag()2627 void ImagePattern::ResetFormAnimationFlag()
2628 {
2629     if (IsFormRender()) {
2630         formAnimationRemainder_ = DEFAULT_DURATION;
2631         isFormAnimationStart_ = true;
2632         isFormAnimationEnd_ = false;
2633     }
2634 }
2635 
SetIteration(int32_t iteration)2636 void ImagePattern::SetIteration(int32_t iteration)
2637 {
2638     if (iteration < -1) {
2639         return;
2640     }
2641     if (IsFormRender()) {
2642         iteration = DEFAULT_ITERATIONS;
2643     }
2644     animator_->SetIteration(iteration);
2645 }
2646 
SetDuration(int32_t duration)2647 void ImagePattern::SetDuration(int32_t duration)
2648 {
2649     if (duration < 0) {
2650         return;
2651     }
2652     int32_t finalDuration = durationTotal_ > 0 ? durationTotal_ : duration;
2653     if (IsFormRender()) {
2654         finalDuration = finalDuration < DEFAULT_DURATION ? finalDuration : DEFAULT_DURATION;
2655     }
2656     if (animator_->GetDuration() == finalDuration) {
2657         animator_->RemoveRepeatListener(repeatCallbackId_);
2658         return;
2659     }
2660     if (animator_->GetStatus() == Animator::Status::IDLE || animator_->GetStatus() == Animator::Status::STOPPED) {
2661         animator_->SetDuration(finalDuration);
2662         animator_->RemoveRepeatListener(repeatCallbackId_);
2663         return;
2664     }
2665     // if animator is running or paused, duration will work next time
2666     animator_->RemoveRepeatListener(repeatCallbackId_);
2667     repeatCallbackId_ = animator_->AddRepeatListener([weak = WeakClaim(this), finalDuration]() {
2668         auto imageAnimator = weak.Upgrade();
2669         CHECK_NULL_VOID(imageAnimator);
2670         imageAnimator->animator_->SetDuration(finalDuration);
2671     });
2672 }
2673 
SetOnProgressCallback(std::function<void (const uint32_t & dlNow,const uint32_t & dlTotal)> && onProgress)2674 void ImagePattern::SetOnProgressCallback(
2675     std::function<void(const uint32_t& dlNow, const uint32_t& dlTotal)>&& onProgress)
2676 {
2677     onProgressCallback_ = onProgress;
2678 }
2679 
OnSensitiveStyleChange(bool isSensitive)2680 void ImagePattern::OnSensitiveStyleChange(bool isSensitive)
2681 {
2682     auto host = GetHost();
2683     CHECK_NULL_VOID(host);
2684     auto privacySensitive = host->IsPrivacySensitive();
2685     if (isSensitive && privacySensitive) {
2686         isSensitive_ = true;
2687         auto renderContext = host->GetRenderContext();
2688         CHECK_NULL_VOID(renderContext);
2689         CalcDimension radius;
2690         radius.SetValue(IMAGE_SENSITIVE_RADIUS);
2691         Color color = Color::FromARGB(13, 255, 255, 255);
2692         EffectOption option = { radius, IMAGE_SENSITIVE_SATURATION, IMAGE_SENSITIVE_BRIGHTNESS, color };
2693         if (renderContext->GetBackBlurRadius().has_value()) {
2694             renderContext->UpdateBackBlurRadius(Dimension());
2695         }
2696         if (renderContext->GetBackBlurStyle().has_value()) {
2697             renderContext->UpdateBackBlurStyle(std::nullopt);
2698         }
2699         renderContext->UpdateBackgroundEffect(option);
2700     } else {
2701         isSensitive_ = false;
2702     }
2703     host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
2704 }
2705 
ResetImageProperties()2706 void ImagePattern::ResetImageProperties()
2707 {
2708     SetCopyOption(CopyOptions::None);
2709     OnImageModifyDone();
2710 }
2711 
ResetImage()2712 void ImagePattern::ResetImage()
2713 {
2714     image_ = nullptr;
2715     imageQuality_ = AIImageQuality::NONE;
2716     isImageReloadNeeded_ = false;
2717     loadingCtx_.Reset();
2718     auto host = GetHost();
2719     CHECK_NULL_VOID(host);
2720     if (!altImage_) {
2721         auto rsRenderContext = host->GetRenderContext();
2722         CHECK_NULL_VOID(rsRenderContext);
2723         TAG_LOGI(AceLogTag::ACE_IMAGE, "%{public}s, %{private}s ResetImage.",
2724             imageDfxConfig_.ToStringWithoutSrc().c_str(), imageDfxConfig_.GetImageSrc().c_str());
2725         rsRenderContext->RemoveContentModifier(contentMod_);
2726         contentMod_ = nullptr;
2727     }
2728     host->SetTrimMemRecycle(false);
2729 }
2730 
ResetAltImage()2731 void ImagePattern::ResetAltImage()
2732 {
2733     altImage_ = nullptr;
2734     altLoadingCtx_.Reset();
2735     if (!image_) {
2736         auto host = GetHost();
2737         CHECK_NULL_VOID(host);
2738         auto rsRenderContext = host->GetRenderContext();
2739         CHECK_NULL_VOID(rsRenderContext);
2740         TAG_LOGI(AceLogTag::ACE_IMAGE, "%{public}s-%{private}s ResetAltImage",
2741             imageDfxConfig_.ToStringWithoutSrc().c_str(), imageDfxConfig_.GetImageSrc().c_str());
2742         rsRenderContext->RemoveContentModifier(contentMod_);
2743         contentMod_ = nullptr;
2744     }
2745 }
2746 
ResetImageAndAlt()2747 void ImagePattern::ResetImageAndAlt()
2748 {
2749     TAG_LOGD(AceLogTag::ACE_IMAGE, "%{public}s-%{private}s ResetImageAlt", imageDfxConfig_.ToStringWithoutSrc().c_str(),
2750         imageDfxConfig_.GetImageSrc().c_str());
2751     auto frameNode = GetHost();
2752     CHECK_NULL_VOID(frameNode);
2753     if (frameNode->IsInDestroying() && frameNode->IsOnMainTree()) {
2754         isNeedReset_ = true;
2755         return;
2756     }
2757     image_ = nullptr;
2758     loadingCtx_ = nullptr;
2759     srcRect_.Reset();
2760     dstRect_.Reset();
2761     altLoadingCtx_ = nullptr;
2762     altImage_ = nullptr;
2763     altDstRect_.reset();
2764     altSrcRect_.reset();
2765     auto rsRenderContext = frameNode->GetRenderContext();
2766     CHECK_NULL_VOID(rsRenderContext);
2767     rsRenderContext->RemoveContentModifier(contentMod_);
2768     contentMod_ = nullptr;
2769     CloseSelectOverlay();
2770     DestroyAnalyzerOverlay();
2771     frameNode->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
2772     frameNode->SetTrimMemRecycle(false);
2773 }
2774 
ResetPictureSize()2775 void ImagePattern::ResetPictureSize()
2776 {
2777     auto host = GetHost();
2778     CHECK_NULL_VOID(host);
2779     const auto& layoutProperty = host->GetLayoutProperty();
2780     CHECK_NULL_VOID(layoutProperty);
2781     layoutProperty->ClearUserDefinedIdealSize(true, true);
2782     hasSizeChanged = false;
2783 }
2784 
SetColorFilter(const RefPtr<FrameNode> & imageFrameNode)2785 void ImagePattern::SetColorFilter(const RefPtr<FrameNode>& imageFrameNode)
2786 {
2787     auto host = GetHost();
2788     CHECK_NULL_VOID(host);
2789     auto renderProperty = host->GetPaintProperty<ImageRenderProperty>();
2790     CHECK_NULL_VOID(renderProperty);
2791     auto imageRenderProperty = imageFrameNode->GetPaintProperty<ImageRenderProperty>();
2792     CHECK_NULL_VOID(imageRenderProperty);
2793     if (renderProperty->HasColorFilter()) {
2794         imageRenderProperty->UpdateColorFilter(renderProperty->GetColorFilter().value());
2795     }
2796     if (renderProperty->HasDrawingColorFilter()) {
2797         imageRenderProperty->UpdateDrawingColorFilter(renderProperty->GetDrawingColorFilter().value());
2798     }
2799 }
2800 
SetImageFit(const RefPtr<FrameNode> & imageFrameNode)2801 void ImagePattern::SetImageFit(const RefPtr<FrameNode>& imageFrameNode)
2802 {
2803     auto host = GetHost();
2804     CHECK_NULL_VOID(host);
2805     auto layoutProperty = host->GetLayoutProperty<ImageLayoutProperty>();
2806     CHECK_NULL_VOID(layoutProperty);
2807     auto renderProperty = host->GetPaintProperty<ImageRenderProperty>();
2808     CHECK_NULL_VOID(renderProperty);
2809     auto imageLayoutProperty = imageFrameNode->GetLayoutProperty<ImageLayoutProperty>();
2810     CHECK_NULL_VOID(imageLayoutProperty);
2811     auto imageRenderProperty = imageFrameNode->GetPaintProperty<ImageRenderProperty>();
2812     CHECK_NULL_VOID(imageRenderProperty);
2813     if (renderProperty->HasImageFit()) {
2814         imageRenderProperty->UpdateImageFit(renderProperty->GetImageFit().value());
2815     }
2816     if (layoutProperty->HasImageFit()) {
2817         imageLayoutProperty->UpdateImageFit(layoutProperty->GetImageFit().value());
2818     }
2819 }
2820 
SetObscured()2821 void ImagePattern::SetObscured()
2822 {
2823     auto host = GetHost();
2824     CHECK_NULL_VOID(host);
2825     auto imageFrameNode = AceType::DynamicCast<FrameNode>(host->GetChildren().front());
2826     CHECK_NULL_VOID(imageFrameNode);
2827     auto obscuredReasons = host->GetRenderContext()->GetObscured().value_or(std::vector<ObscuredReasons>());
2828     const auto& castRenderContext = imageFrameNode->GetRenderContext();
2829     if (castRenderContext) {
2830         castRenderContext->UpdateObscured(obscuredReasons);
2831     }
2832     imageFrameNode->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
2833     host->GetRenderContext()->ResetObscured();
2834     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
2835 }
2836 
TriggerVisibleAreaChangeForChild(const RefPtr<UINode> & node,bool visible,double ratio)2837 void ImagePattern::TriggerVisibleAreaChangeForChild(const RefPtr<UINode>& node, bool visible, double ratio)
2838 {
2839     for (const auto& childNode : node->GetChildren()) {
2840         if (AceType::InstanceOf<FrameNode>(childNode)) {
2841             auto frame = AceType::DynamicCast<FrameNode>(childNode);
2842             if (!frame || !frame->GetOrCreateEventHub<EventHub>()) {
2843                 continue;
2844             }
2845             auto callback = frame->GetOrCreateEventHub<EventHub>()->GetVisibleAreaCallback(true).callback;
2846             if (callback) {
2847                 callback(visible, ratio);
2848             }
2849         }
2850         TriggerVisibleAreaChangeForChild(childNode, visible, ratio);
2851     }
2852 }
2853 
DumpInfo(std::unique_ptr<JsonValue> & json)2854 void ImagePattern::DumpInfo(std::unique_ptr<JsonValue>& json)
2855 {
2856     DumpLayoutInfo(json);
2857     DumpRenderInfo(json);
2858     json->Put("syncLoad", syncLoad_);
2859     if (loadingCtx_) {
2860         auto currentLoadImageState = loadingCtx_->GetCurrentLoadingState();
2861         json->Put("currentLoadImageState", currentLoadImageState.c_str());
2862         json->Put("rawImageSize", loadingCtx_->GetImageSize().ToString().c_str());
2863         json->Put("LoadErrorMsg", loadingCtx_->GetErrorMsg().c_str());
2864     } else {
2865         json->Put("imageLoadingContext", "null");
2866     }
2867 
2868     json->Put("draggable", enableDrag_);
2869     json->Put("enableAnalyzer", isEnableAnalyzer_);
2870 }
2871 
DumpLayoutInfo(std::unique_ptr<JsonValue> & json)2872 void ImagePattern::DumpLayoutInfo(std::unique_ptr<JsonValue>& json)
2873 {
2874     auto layoutProp = GetLayoutProperty<ImageLayoutProperty>();
2875     CHECK_NULL_VOID(layoutProp);
2876     auto src = layoutProp->GetImageSourceInfo().value_or(ImageSourceInfo(""));
2877     json->Put("url", src.ToString().c_str());
2878     auto altSrc = layoutProp->GetAlt().value_or(ImageSourceInfo(""));
2879     json->Put("altUrl", altSrc.ToString().c_str());
2880     auto imageFit = layoutProp->GetImageFit().value_or(ImageFit::COVER);
2881     json->Put("objectFit", GetImageFitStr(imageFit).c_str());
2882     auto fitOriginalSize = layoutProp->GetFitOriginalSize().value_or(false);
2883     json->Put("fitOriginalSize", fitOriginalSize);
2884     const std::optional<SizeF>& sourceSize = layoutProp->GetSourceSize();
2885     if (sourceSize.has_value()) {
2886         json->Put("sourceSize", sourceSize.value().ToString().c_str());
2887     }
2888     bool autoResize = layoutProp->GetAutoResize().value_or(autoResizeDefault_);
2889     json->Put("autoResize", autoResize);
2890 }
2891 
DumpRenderInfo(std::unique_ptr<JsonValue> & json)2892 void ImagePattern::DumpRenderInfo(std::unique_ptr<JsonValue>& json)
2893 {
2894     auto renderProp = GetPaintProperty<ImageRenderProperty>();
2895     CHECK_NULL_VOID(renderProp);
2896     auto imageRenderMode = renderProp->GetImageRenderMode().value_or(ImageRenderMode::ORIGINAL);
2897     json->Put("renderMode", (imageRenderMode == ImageRenderMode::ORIGINAL) ? "Original" : "Template");
2898     auto imageRepeat = renderProp->GetImageRepeat().value_or(ImageRepeat::NO_REPEAT);
2899     json->Put("objectRepeat", GetImageRepeatStr(imageRepeat).c_str());
2900     auto imageColorFilter = renderProp->GetColorFilter();
2901     if (imageColorFilter.has_value()) {
2902         auto colorFilter = imageColorFilter.value();
2903         json->Put("colorFilter", GetImageColorFilterStr(colorFilter).c_str());
2904     }
2905     auto fillColor = renderProp->GetSvgFillColor();
2906     if (fillColor.has_value()) {
2907         auto color = fillColor.value();
2908         json->Put("fillColor", color.ColorToString().c_str());
2909     }
2910     DynamicRangeMode dynamicMode = DynamicRangeMode::STANDARD;
2911     if (renderProp->HasDynamicMode()) {
2912         dynamicMode = renderProp->GetDynamicMode().value_or(DynamicRangeMode::STANDARD);
2913         json->Put("dynamicRangeMode", GetDynamicModeString(dynamicMode).c_str());
2914     }
2915     auto matchTextDirection = renderProp->GetMatchTextDirection().value_or(false);
2916     json->Put("matchTextDirection", matchTextDirection);
2917     auto smoothEdge = renderProp->GetSmoothEdge();
2918     if (smoothEdge.has_value()) {
2919         json->Put("edgeAntialiasing", smoothEdge.value());
2920     }
2921     auto needBorderRadius = renderProp->GetNeedBorderRadius().value_or(false);
2922     json->Put("needBorderRadius", needBorderRadius);
2923     if (renderProp && renderProp->HasImageResizableSlice() && renderProp->GetImageResizableSliceValue({}).Valid()) {
2924         json->Put("resizable slice", renderProp->GetImageResizableSliceValue({}).ToString().c_str());
2925     }
2926     auto imageInterpolation = renderProp->GetImageInterpolation().value_or(interpolationDefault_);
2927     json->Put("imageInterpolation", GetImageInterpolation(imageInterpolation).c_str());
2928 }
2929 
DumpAdvanceInfo(std::unique_ptr<JsonValue> & json)2930 void ImagePattern::DumpAdvanceInfo(std::unique_ptr<JsonValue>& json)
2931 {
2932     auto layoutProp = GetLayoutProperty<ImageLayoutProperty>();
2933     CHECK_NULL_VOID(layoutProp);
2934     auto src = layoutProp->GetImageSourceInfo().value_or(ImageSourceInfo(""));
2935     json->Put("url", src.ToString().c_str());
2936     json->Put("syncLoad", syncLoad_);
2937     if (loadingCtx_) {
2938         auto currentLoadImageState = loadingCtx_->GetCurrentLoadingState();
2939         json->Put("currentLoadImageState", currentLoadImageState.c_str());
2940     }
2941 }
2942 
AddPixelMapToUiManager()2943 void ImagePattern::AddPixelMapToUiManager()
2944 {
2945     CHECK_NULL_VOID(image_);
2946     auto pixmap = image_->GetPixelMap();
2947     CHECK_NULL_VOID(pixmap);
2948     auto host = GetHost();
2949     CHECK_NULL_VOID(host);
2950     auto pipeline = host->GetContext();
2951     CHECK_NULL_VOID(pipeline);
2952     pipeline->AddPixelMap(host->GetId(), pixmap);
2953 }
2954 
GetFocusPattern() const2955 FocusPattern ImagePattern::GetFocusPattern() const
2956 {
2957     if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_FOURTEEN)) {
2958         return { FocusType::NODE, false, FocusStyleType::OUTER_BORDER };
2959     } else {
2960         return { FocusType::NODE, false };
2961     }
2962 }
2963 
OnActive()2964 void ImagePattern::OnActive()
2965 {
2966     if (status_ == AnimatorStatus::RUNNING && animator_->GetStatus() != Animator::Status::RUNNING) {
2967         auto host = GetHost();
2968         CHECK_NULL_VOID(host);
2969         if (!animator_->HasScheduler()) {
2970             auto context = host->GetContextRefPtr();
2971             if (context) {
2972                 animator_->AttachScheduler(context);
2973             } else {
2974                 TAG_LOGW(AceLogTag::ACE_IMAGE, "pipeline is null.");
2975             }
2976         }
2977         animator_->Forward();
2978     }
2979 }
2980 
OnInActive()2981 void ImagePattern::OnInActive()
2982 {
2983     if (status_ == AnimatorStatus::RUNNING) {
2984         animator_->Pause();
2985     }
2986 }
2987 
UpdateImageSourceinfo(const ImageSourceInfo & sourceInfo)2988 void ImagePattern::UpdateImageSourceinfo(const ImageSourceInfo& sourceInfo)
2989 {
2990     auto host = GetHost();
2991     CHECK_NULL_VOID(host);
2992     auto pipelineContext = host->GetContext();
2993     CHECK_NULL_VOID(pipelineContext);
2994     if (pipelineContext->IsSystmColorChange()) {
2995         auto imageLayoutProperty = GetLayoutProperty<ImageLayoutProperty>();
2996         CHECK_NULL_VOID(imageLayoutProperty);
2997         imageLayoutProperty->UpdateImageSourceInfo(sourceInfo);
2998     }
2999 }
3000 
UpdateImageFill(const Color & color)3001 void ImagePattern::UpdateImageFill(const Color& color)
3002 {
3003     auto host = GetHost();
3004     CHECK_NULL_VOID(host);
3005     auto pipelineContext = host->GetContext();
3006     CHECK_NULL_VOID(pipelineContext);
3007     if (pipelineContext->IsSystmColorChange()) {
3008         auto renderProperty = GetPaintProperty<ImageRenderProperty>();
3009         CHECK_NULL_VOID(renderProperty);
3010         renderProperty->UpdateSvgFillColor(color);
3011         auto renderContext = host->GetRenderContext();
3012         CHECK_NULL_VOID(renderContext);
3013         renderContext->UpdateForegroundColor(color);
3014         host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
3015     }
3016 }
3017 
UpdateImageAlt(const ImageSourceInfo & sourceInfo)3018 void ImagePattern::UpdateImageAlt(const ImageSourceInfo& sourceInfo)
3019 {
3020     auto host = GetHost();
3021     CHECK_NULL_VOID(host);
3022     auto pipelineContext = host->GetContext();
3023     CHECK_NULL_VOID(pipelineContext);
3024     if (pipelineContext->IsSystmColorChange()) {
3025         auto imageLayoutProperty = GetLayoutProperty<ImageLayoutProperty>();
3026         CHECK_NULL_VOID(imageLayoutProperty);
3027         imageLayoutProperty->UpdateAlt(sourceInfo);
3028     }
3029 }
3030 
OnColorModeChange(uint32_t colorMode)3031 void ImagePattern::OnColorModeChange(uint32_t colorMode)
3032 {
3033     Pattern::OnColorModeChange(colorMode);
3034     auto host = GetHost();
3035     CHECK_NULL_VOID(host);
3036     auto pipelineContext = host->GetContext();
3037     CHECK_NULL_VOID(pipelineContext);
3038     if (host->GetRerenderable()) {
3039         host->MarkModifyDone();
3040         host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
3041     }
3042 }
3043 } // namespace OHOS::Ace::NG
3044