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