• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "core/components/image/render_image.h"
17 
18 #include "base/log/dump_log.h"
19 #include "base/log/log.h"
20 #include "base/utils/utils.h"
21 #include "core/common/ace_engine_ext.h"
22 #include "core/common/clipboard/clipboard_proxy.h"
23 #include "core/components/container_modal/container_modal_constants.h"
24 #include "core/components/image/image_component.h"
25 #include "core/components/image/image_event.h"
26 #include "core/components/positioned/positioned_component.h"
27 #include "core/components/stack/stack_element.h"
28 #include "core/components/text_overlay/text_overlay_component.h"
29 #include "core/components/theme/icon_theme.h"
30 #include "core/event/ace_event_helper.h"
31 
32 namespace OHOS::Ace {
33 namespace {
34 
35 constexpr double RESIZE_AGAIN_THRESHOLD = 1.2;
36 
37 } // namespace
38 
~RenderImage()39 RenderImage::~RenderImage()
40 {
41     auto textOverlayManager = GetTextOverlayManager(context_);
42     if (textOverlayManager) {
43         auto textOverlayBase = textOverlayManager->GetTextOverlayBase();
44         if (textOverlayBase) {
45             auto targetNode = textOverlayManager->GetTargetNode();
46             if (targetNode == this) {
47                 textOverlayManager->PopTextOverlay();
48                 textOverlayBase->MarkIsOverlayShowed(false);
49                 targetNode->MarkNeedRender();
50             }
51         }
52     }
53 }
54 
Update(const RefPtr<Component> & component)55 void RenderImage::Update(const RefPtr<Component>& component)
56 {
57     const RefPtr<ImageComponent> image = AceType::DynamicCast<ImageComponent>(component);
58     if (!image) {
59         LOGE("image component is null!");
60         return;
61     }
62     auto context = context_.Upgrade();
63     if (!context) {
64         return;
65     }
66     if (!clipboard_ && context) {
67         clipboard_ = ClipboardProxy::GetInstance()->GetClipboard(context->GetTaskExecutor());
68     }
69     currentSrcRect_ = srcRect_;
70     currentDstRect_ = dstRect_;
71     currentDstRectList_ = rectList_;
72     colorfilter_ = image->GetColorFilterMatrix();
73     blurRadius_ = image->GetBlurRadius();
74     width_ = image->GetWidth();
75     syncMode_ = image->GetSyncMode();
76     height_ = image->GetHeight();
77     alignment_ = image->GetAlignment();
78     imageObjectPosition_ = image->GetImageObjectPosition();
79     fitMaxSize_ = image->GetFitMaxSize();
80     hasObjectPosition_ = image->GetHasObjectPosition();
81     color_ = image->GetColor();
82     previousLayoutSize_ = Size();
83     SetTextDirection(image->GetTextDirection());
84     matchTextDirection_ = image->IsMatchTextDirection();
85     SetRadius(image->GetBorder());
86     if (context && context->GetIsDeclarative()) {
87         loadImgSuccessEvent_ = AceAsyncEvent<void(const std::shared_ptr<BaseEventInfo>&)>::Create(
88             image->GetLoadSuccessEvent(), context_);
89         loadImgFailEvent_ = AceAsyncEvent<void(const std::shared_ptr<BaseEventInfo>&)>::Create(
90             image->GetLoadFailEvent(), context_);
91     } else {
92         loadSuccessEvent_ =
93             AceAsyncEvent<void(const std::string&)>::Create(image->GetLoadSuccessEvent(), context_);
94         loadFailEvent_ = AceAsyncEvent<void(const std::string&)>::Create(image->GetLoadFailEvent(), context_);
95     }
96     svgAnimatorFinishEvent_ = image->GetSvgAnimatorFinishEvent();
97     imageFit_ = image->GetImageFit();
98     imageInterpolation_ = image->GetImageInterpolation();
99     imageRenderMode_ = image->GetImageRenderMode();
100     imageRepeat_ = image->GetImageRepeat();
101 
102     useSkiaSvg_ = image->GetUseSkiaSvg();
103     autoResize_ = image->GetAutoResize();
104     imageAlt_ = image->GetAlt();
105     auto inComingSrc = image->GetSrc();
106     ImageSourceInfo inComingSource(
107         inComingSrc,
108         image->GetImageSourceSize().first,
109         image->GetImageSourceSize().second,
110         inComingSrc.empty() ? image->GetResourceId() : InternalResource::ResourceId::NO_ID,
111         image->GetPixmap());
112     UpdateThemeIcon(inComingSource);
113     auto fillColor = image->GetImageFill();
114     if (fillColor.has_value()) {
115         inComingSource.SetFillColor(fillColor.value());
116     }
117     border_ = image->GetBorder();
118 
119     onDragStart_ = image->GetOnDragStartId();
120     onDragEnter_ = image->GetOnDragEnterId();
121     onDragMove_ = image->GetOnDragMoveId();
122     onDragLeave_ = image->GetOnDragLeaveId();
123     onDrop_ = image->GetOnDropId();
124     if (onDragStart_) {
125         CreateDragDropRecognizer(context_);
126     }
127 
128     copyOption_ = image->GetCopyOption();
129 
130     // this value is used for update frequency with same image source info.
131     LOGD("sourceInfo %{public}s", sourceInfo_.ToString().c_str());
132     LOGD("inComingSource %{public}s", inComingSource.ToString().c_str());
133     LOGD("imageLoadingStatus_: %{public}d", static_cast<int32_t>(imageLoadingStatus_));
134     proceedPreviousLoading_ = sourceInfo_.IsValid() && sourceInfo_ == inComingSource;
135     // perform layout only if loading new image
136     if (!proceedPreviousLoading_) {
137         sourceInfo_ = inComingSource;
138         MarkNeedLayout(sourceInfo_.IsSvg());
139     }
140 }
141 
UpdateThemeIcon(ImageSourceInfo & sourceInfo)142 void RenderImage::UpdateThemeIcon(ImageSourceInfo& sourceInfo)
143 {
144     if (sourceInfo.IsInternalResource()) {
145         auto iconTheme = GetTheme<IconTheme>();
146         if (!iconTheme) {
147             LOGW("icon theme is null.");
148             return;
149         }
150         auto iconPath = iconTheme->GetIconPath(sourceInfo.GetResourceId());
151         if (!iconPath.empty()) {
152             sourceInfo.SetSrc(iconPath);
153         }
154     }
155 }
156 
OnPaintFinish()157 void RenderImage::OnPaintFinish()
158 {
159     UpdateOverlay();
160 }
161 
OnTouchTestHit(const Offset & coordinateOffset,const TouchRestrict & touchRestrict,TouchTestResult & result)162 void RenderImage::OnTouchTestHit(
163     const Offset& coordinateOffset, const TouchRestrict& touchRestrict, TouchTestResult& result)
164 {
165     if (dragDropGesture_) {
166         result.emplace_back(dragDropGesture_);
167     }
168 
169     if (copyOption_ != CopyOptions::None && imageLoadingStatus_ == ImageLoadingStatus::LOAD_SUCCESS
170         && !sourceInfo_.IsSvg()) {
171         if (!textOverlayRecognizer_) {
172             textOverlayRecognizer_ = AceType::MakeRefPtr<LongPressRecognizer>(context_);
173             textOverlayRecognizer_->SetOnLongPress([weak = WeakClaim(this)](const LongPressInfo& info) {
174                 auto client = weak.Upgrade();
175                 if (client) {
176                     client->OnLongPress(info);
177                 }
178             });
179         }
180         textOverlayRecognizer_->SetCoordinateOffset(coordinateOffset);
181         textOverlayRecognizer_->SetTouchRestrict(touchRestrict);
182         textOverlayRecognizer_->SetUseCatchMode(false);
183         result.emplace_back(textOverlayRecognizer_);
184     }
185 }
186 
OnLongPress(const LongPressInfo & longPressInfo)187 void RenderImage::OnLongPress(const LongPressInfo& longPressInfo)
188 {
189     auto textOverlayManager = GetTextOverlayManager(context_);
190     if (textOverlayManager) {
191         auto textOverlayBase = textOverlayManager->GetTextOverlayBase();
192         if (textOverlayBase) {
193             auto targetNode = textOverlayManager->GetTargetNode();
194             if (targetNode) {
195                 textOverlayManager->PopTextOverlay();
196                 textOverlayBase->MarkIsOverlayShowed(false);
197                 targetNode->MarkNeedRender();
198             }
199         }
200         textOverlayManager->SetTextOverlayBase(AceType::WeakClaim(this));
201     }
202 
203     Offset longPressPosition = longPressInfo.GetGlobalLocation();
204     ShowTextOverlay(longPressPosition);
205 }
206 
HandleMouseEvent(const MouseEvent & event)207 bool RenderImage::HandleMouseEvent(const MouseEvent& event)
208 {
209     if (copyOption_ == CopyOptions::None || imageLoadingStatus_ != ImageLoadingStatus::LOAD_SUCCESS
210         || sourceInfo_.IsSvg()) {
211         return false;
212     }
213     if (event.button == MouseButton::RIGHT_BUTTON && event.action == MouseAction::PRESS) {
214         Offset rightClickOffset = event.GetOffset();
215         auto textOverlayManager = GetTextOverlayManager(context_);
216         if (textOverlayManager) {
217             auto textOverlayBase = textOverlayManager->GetTextOverlayBase();
218             if (textOverlayBase) {
219                 auto targetNode = textOverlayManager->GetTargetNode();
220                 if (targetNode) {
221                     textOverlayManager->PopTextOverlay();
222                     textOverlayBase->MarkIsOverlayShowed(false);
223                     targetNode->MarkNeedRender();
224                 }
225             }
226             textOverlayManager->SetTextOverlayBase(AceType::WeakClaim(this));
227         }
228         ShowTextOverlay(rightClickOffset);
229         return true;
230     }
231     return false;
232 }
233 
HandleKeyEvent(const KeyEvent & event)234 bool RenderImage::HandleKeyEvent(const KeyEvent& event)
235 {
236     if (event.action != KeyAction::DOWN) {
237         return false;
238     }
239     if (event.IsCtrlWith(KeyCode::KEY_C) && copyOption_ != CopyOptions::None) {
240         HandleOnCopy();
241         return true;
242     }
243     return false;
244 }
245 
ShowTextOverlay(const Offset & showOffset)246 void RenderImage::ShowTextOverlay(const Offset& showOffset)
247 {
248     popOverlayOffset_ = showOffset;
249     Offset startHandleOffset = popOverlayOffset_;
250     Offset endHandleOffset = popOverlayOffset_;
251     if (isOverlayShowed_ && updateHandlePosition_) {
252         OverlayShowOption option { .showMenu = isOverlayShowed_,
253             .updateOverlayType = UpdateOverlayType::LONG_PRESS,
254             .startHandleOffset = startHandleOffset,
255             .endHandleOffset = endHandleOffset};
256         updateHandlePosition_(option);
257         if (!animator_) {
258             LOGE("Show textOverlay error, animator is nullptr");
259             return;
260         }
261         if (!animator_->IsStopped()) {
262             animator_->Stop();
263         }
264         animator_->Play();
265         return;
266     }
267 
268     textOverlay_ =
269         AceType::MakeRefPtr<TextOverlayComponent>(GetThemeManager(), context_.Upgrade()->GetAccessibilityManager());
270     textOverlay_->SetWeakImage(WeakClaim(this));
271     textOverlay_->SetNeedCilpRect(false);
272     textOverlay_->SetStartHandleOffset(startHandleOffset);
273     textOverlay_->SetEndHandleOffset(endHandleOffset);
274     textOverlay_->SetContext(context_);
275     InitAnimation(context_);
276     RegisterCallbacksToOverlay();
277     MarkNeedRender();
278 }
279 
RegisterCallbacksToOverlay()280 void RenderImage::RegisterCallbacksToOverlay()
281 {
282     if (!textOverlay_) {
283         return;
284     }
285 
286     textOverlay_->SetOnCopy([weak = AceType::WeakClaim(this)] {
287         auto image = weak.Upgrade();
288         if (image) {
289             image->HandleOnCopy();
290         }
291     });
292 
293     auto callback = [weak = WeakClaim(this), pipelineContext = context_, textOverlay = textOverlay_](
294                         const RefPtr<PixelMap>& pixmap) {
295         auto context = pipelineContext.Upgrade();
296         if (!context) {
297             return;
298         }
299         auto textOverlayManager = context->GetTextOverlayManager();
300         if (!textOverlayManager) {
301             return;
302         }
303         textOverlayManager->PushTextOverlayToStack(textOverlay, pipelineContext);
304 
305         auto image = weak.Upgrade();
306         if (!image) {
307             return;
308         }
309         image->UpdateOverlay();
310         image->MarkIsOverlayShowed(true);
311     };
312     if (clipboard_) {
313         clipboard_->GetPixelMapData(callback);
314     }
315 }
316 
UpdateOverlay()317 void RenderImage::UpdateOverlay()
318 {
319     if (isOverlayShowed_ && updateHandlePosition_) {
320         OverlayShowOption option { .showMenu = isOverlayShowed_,
321             .updateOverlayType = UpdateOverlayType::LONG_PRESS,
322             .startHandleOffset = popOverlayOffset_,
323             .endHandleOffset = popOverlayOffset_ };
324         updateHandlePosition_(option);
325     }
326 }
327 
HandleOnCopy()328 void RenderImage::HandleOnCopy()
329 {
330     if (!clipboard_) {
331         return;
332     }
333     auto renderImage = AceType::Claim(this);
334     auto type = sourceInfo_.GetSrcType();
335     switch (type) {
336         case SrcType::PIXMAP: {
337             clipboard_->SetPixelMapData(sourceInfo_.GetPixmap(), copyOption_);
338             break;
339         }
340         case SrcType::BASE64: {
341             clipboard_->SetData(sourceInfo_.GetSrc(), copyOption_);
342             break;
343         }
344         case SrcType::DATA_ABILITY_DECODED:
345         case SrcType::DATA_ABILITY: {
346             clipboard_->SetData(sourceInfo_.GetSrc(), copyOption_);
347             break;
348         }
349         default: {
350             clipboard_->SetPixelMapData(renderImage->GetPixmapFromSkImage(), copyOption_);
351             break;
352         }
353     }
354 
355     auto textOverlayManager = GetTextOverlayManager(context_);
356     if (textOverlayManager) {
357         textOverlayManager->PopTextOverlay();
358     }
359     isOverlayShowed_ = false;
360     MarkNeedRender();
361 }
362 
PerformLayout()363 void RenderImage::PerformLayout()
364 {
365     if (background_) {
366         PerformLayoutBgImage();
367         if (imageRenderFunc_) {
368             imageRenderFunc_();
369         }
370         return;
371     }
372 
373     auto context = context_.Upgrade();
374     if (!context) {
375         return;
376     }
377     scale_ = context->GetViewScale();
378     if (LessOrEqual(scale_, 0)) {
379         scale_ = 1.0;
380     }
381     if (width_.IsValid() && height_.IsValid()) {
382         imageComponentSize_ = Size(NormalizeToPx(width_), NormalizeToPx(height_));
383         isImageSizeSet_ = true;
384     }
385     // Divided by the true pixel ratio to apply image fit.
386     Size pictureSize = Measure() * (1.0 / scale_);
387     auto maxSize = GetLayoutParam().GetMaxSize();
388     if (fitMaxSize_ && (!imageComponentSize_.IsValid() || (!isImageSizeSet_ && maxSize != formerMaxSize_))) {
389         imageComponentSize_ = maxSize;
390         formerMaxSize_ = imageComponentSize_;
391     }
392     SetLayoutSize(GetLayoutParam().Constrain(imageComponentSize_.IsValid() && !imageComponentSize_.IsInfinite()
393                                                  ? imageComponentSize_
394                                                  : CalculateBackupImageSize(pictureSize)));
395     if (rawImageSizeUpdated_) {
396         previousLayoutSize_ = GetLayoutSize();
397     }
398     srcRect_.SetRect(Offset(), pictureSize);
399     dstRect_.SetRect(Offset(), GetLayoutSize());
400     ApplyImageFit(srcRect_, dstRect_);
401     // Restore image size.
402     srcRect_.ApplyScale(scale_);
403     if (!imageComponentSize_.IsValid()) {
404         SetLayoutSize(dstRect_.GetSize());
405     }
406     decltype(imageLayoutCallbacks_) imageLayoutCallbacks(std::move(imageLayoutCallbacks_));
407     std::for_each(
408         imageLayoutCallbacks.begin(), imageLayoutCallbacks.end(), [](std::function<void()> callback) { callback(); });
409     LayoutImageObject();
410     if (renderAltImage_) {
411         LayoutParam altLayoutParam;
412         altLayoutParam.SetFixedSize(GetLayoutSize());
413         renderAltImage_->Layout(altLayoutParam);
414     }
415 
416     CalculateResizeTarget();
417     if (hasObjectPosition_) {
418         ApplyObjectPosition();
419     }
420 }
421 
CalculateBackupImageSize(const Size & pictureSize)422 Size RenderImage::CalculateBackupImageSize(const Size& pictureSize)
423 {
424     // Since the return value of this function is used to determine the layout size of Image Component, it is essential
425     // to guarantee that there is no infinite edge to avoid thread stuck that may occur.
426     //
427     // Generally speaking, the size of the picture will not be infinite, but the size of the svg picture is equal to the
428     // maximum value of the layout parameters, so there is the possibility of infinity.
429     //
430     // Note that [pictureSize] has been scaled by [scale_], so we need to obtain the original picture size via
431     // [Measure()] to verify whether or not it has infinite edge.
432     auto rawPicSize = Measure();
433     if (!rawPicSize.IsValid() || rawPicSize.IsInfinite()) {
434         return Size();
435     }
436     uint8_t infiniteStatus = (static_cast<uint8_t>(imageComponentSize_.IsWidthInfinite()) << 1) |
437                              static_cast<uint8_t>(imageComponentSize_.IsHeightInfinite());
438     double pictureSizeRatio = pictureSize.Width() / pictureSize.Height();
439     Size backupImageSize = imageComponentSize_;
440     switch (infiniteStatus) {
441         case 0b00: // both width and height are infinite
442             backupImageSize = pictureSize;
443             break;
444         case 0b01: // only height is infinite
445             backupImageSize.SetHeight(imageComponentSize_.Width() / pictureSizeRatio);
446             break;
447         case 0b10: // only width is infinite
448             backupImageSize.SetWidth(imageComponentSize_.Height() * pictureSizeRatio);
449             break;
450         default:
451             backupImageSize = imageComponentSize_;
452             break;
453     }
454     return backupImageSize;
455 }
456 
NeedResize() const457 bool RenderImage::NeedResize() const
458 {
459     if (!resizeTarget_.IsValid()) {
460         return false;
461     }
462     if (!previousResizeTarget_.IsValid()) {
463         return true;
464     }
465     if (resizeTarget_ < previousResizeTarget_) {
466         return false;
467     }
468     double widthEnlargedBy = resizeTarget_.Width() / previousResizeTarget_.Width();
469     double heightEnlargedBy = resizeTarget_.Height() / previousResizeTarget_.Height();
470     if (widthEnlargedBy > RESIZE_AGAIN_THRESHOLD || heightEnlargedBy > RESIZE_AGAIN_THRESHOLD) {
471         return true;
472     }
473     return false;
474 }
475 
CalculateResizeTarget()476 void RenderImage::CalculateResizeTarget()
477 {
478     if (!srcRect_.IsValid()) {
479         return;
480     }
481     if (!autoResize_) {
482         resizeTarget_ = rawImageSize_;
483         resizeScale_ = Size(1.0, 1.0);
484         return;
485     }
486     double widthScale = dstRect_.Width() / srcRect_.Width() * scale_;
487     double heightScale = dstRect_.Height() / srcRect_.Height() * scale_;
488     if (widthScale < 1.0 && heightScale < 1.0) {
489         resizeScale_ = Size(widthScale, heightScale);
490     } else {
491         resizeScale_ = Size(1.0, 1.0);
492     }
493     resizeTarget_ = Size(rawImageSize_.Width() * resizeScale_.Width(), rawImageSize_.Height() * resizeScale_.Height());
494 }
495 
ApplyImageFit(Rect & srcRect,Rect & dstRect)496 void RenderImage::ApplyImageFit(Rect& srcRect, Rect& dstRect)
497 {
498     Size rawPicSize = srcRect.GetSize();
499     Size layoutSize = GetLayoutSize();
500     switch (imageFit_) {
501         case ImageFit::FILL:
502             break;
503         case ImageFit::NONE:
504             ApplyNone(srcRect, dstRect, rawPicSize, layoutSize);
505             break;
506         case ImageFit::COVER:
507             ApplyCover(srcRect, dstRect, rawPicSize, layoutSize);
508             break;
509         case ImageFit::FITWIDTH:
510             ApplyFitWidth(srcRect, dstRect, rawPicSize, layoutSize);
511             break;
512         case ImageFit::FITHEIGHT:
513             ApplyFitHeight(srcRect, dstRect, rawPicSize, layoutSize);
514             break;
515         case ImageFit::SCALE_DOWN:
516             if (srcRect.GetSize() < dstRect.GetSize()) {
517                 ApplyNone(srcRect, dstRect, rawPicSize, layoutSize);
518             } else {
519                 ApplyContain(srcRect, dstRect, rawPicSize, layoutSize);
520             }
521             break;
522         case ImageFit::CONTAIN:
523             ApplyContain(srcRect, dstRect, rawPicSize, layoutSize);
524             break;
525         default:
526             ApplyContain(srcRect, dstRect, rawPicSize, layoutSize);
527             break;
528     }
529 }
530 
ApplyContain(Rect & srcRect,Rect & dstRect,const Size & rawPicSize,const Size & layoutSize)531 void RenderImage::ApplyContain(Rect& srcRect, Rect& dstRect, const Size& rawPicSize, const Size& layoutSize)
532 {
533     if (!rawPicSize.IsValid()) {
534         return;
535     }
536     if (Size::CalcRatio(srcRect) > Size::CalcRatio(dstRect)) {
537         dstRect.SetSize(rawPicSize * (layoutSize.Width() / rawPicSize.Width()));
538     } else {
539         dstRect.SetSize(rawPicSize * (layoutSize.Height() / rawPicSize.Height()));
540     }
541     dstRect.SetOffset(Alignment::GetAlignPosition(layoutSize, dstRect.GetSize(), alignment_));
542 }
543 
ApplyCover(Rect & srcRect,Rect & dstRect,const Size & rawPicSize,const Size & layoutSize)544 void RenderImage::ApplyCover(Rect& srcRect, Rect& dstRect, const Size& rawPicSize, const Size& layoutSize)
545 {
546     if (Size::CalcRatio(srcRect) > Size::CalcRatio(dstRect)) {
547         srcRect.SetSize(layoutSize * (rawPicSize.Height() / layoutSize.Height()));
548     } else {
549         srcRect.SetSize(layoutSize * (rawPicSize.Width() / layoutSize.Width()));
550     }
551     srcRect.SetOffset(Alignment::GetAlignPosition(rawPicSize, srcRect.GetSize(), alignment_));
552 }
553 
ApplyFitWidth(Rect & srcRect,Rect & dstRect,const Size & rawPicSize,const Size & layoutSize)554 void RenderImage::ApplyFitWidth(Rect& srcRect, Rect& dstRect, const Size& rawPicSize, const Size& layoutSize)
555 {
556     if (Size::CalcRatio(srcRect) > Size::CalcRatio(dstRect)) {
557         dstRect.SetSize(rawPicSize * (layoutSize.Width() / rawPicSize.Width()));
558         dstRect.SetOffset(Alignment::GetAlignPosition(layoutSize, dstRect.GetSize(), alignment_));
559     } else {
560         srcRect.SetSize(layoutSize * (rawPicSize.Width() / layoutSize.Width()));
561         srcRect.SetOffset(Alignment::GetAlignPosition(rawPicSize, srcRect.GetSize(), alignment_));
562     }
563 }
564 
ApplyFitHeight(Rect & srcRect,Rect & dstRect,const Size & rawPicSize,const Size & layoutSize)565 void RenderImage::ApplyFitHeight(Rect& srcRect, Rect& dstRect, const Size& rawPicSize, const Size& layoutSize)
566 {
567     if (Size::CalcRatio(srcRect) > Size::CalcRatio(dstRect)) {
568         srcRect.SetSize(layoutSize * (rawPicSize.Height() / layoutSize.Height()));
569         srcRect.SetOffset(Alignment::GetAlignPosition(rawPicSize, srcRect.GetSize(), alignment_));
570     } else {
571         dstRect.SetSize(rawPicSize * (layoutSize.Height() / rawPicSize.Height()));
572         dstRect.SetOffset(Alignment::GetAlignPosition(layoutSize, dstRect.GetSize(), alignment_));
573     }
574 }
575 
ApplyNone(Rect & srcRect,Rect & dstRect,const Size & rawPicSize,const Size & layoutSize)576 void RenderImage::ApplyNone(Rect& srcRect, Rect& dstRect, const Size& rawPicSize, const Size& layoutSize)
577 {
578     Size srcSize =
579         Size(std::min(layoutSize.Width(), rawPicSize.Width()), std::min(layoutSize.Height(), rawPicSize.Height()));
580     dstRect.SetRect(Alignment::GetAlignPosition(layoutSize, srcSize, alignment_), srcSize);
581     srcRect.SetRect(Alignment::GetAlignPosition(rawPicSize, srcSize, alignment_), srcSize);
582 }
583 
FireLoadEvent(const Size & picSize,const std::string & errorMsg) const584 void RenderImage::FireLoadEvent(const Size& picSize, const std::string& errorMsg) const
585 {
586     auto context = context_.Upgrade();
587     if (context && context->GetIsDeclarative()) {
588         if (loadImgSuccessEvent_ && (imageLoadingStatus_ == ImageLoadingStatus::LOAD_SUCCESS)) {
589             // here the last param of [loadImgSuccessEvent_] is [1],
590             // which means the callback is triggered by [OnLoadSuccess]
591             loadImgSuccessEvent_(std::make_shared<LoadImageSuccessEvent>(
592                 picSize.Width(), picSize.Height(), GetLayoutSize().Width(), GetLayoutSize().Height(), 1));
593         }
594         if (loadImgFailEvent_ && (imageLoadingStatus_ == ImageLoadingStatus::LOAD_FAIL)) {
595             loadImgFailEvent_(
596                 std::make_shared<LoadImageFailEvent>(GetLayoutSize().Width(), GetLayoutSize().Height(), errorMsg));
597         }
598         return;
599     }
600     std::string param;
601     if (loadSuccessEvent_ && (imageLoadingStatus_ == ImageLoadingStatus::LOAD_SUCCESS)) {
602         param = std::string("\"complete\",{\"width\":")
603                     .append(std::to_string(picSize.Width()))
604                     .append(",\"height\":")
605                     .append(std::to_string(picSize.Height()))
606                     .append("}");
607         loadSuccessEvent_(param);
608     }
609     if (loadFailEvent_ && (imageLoadingStatus_ == ImageLoadingStatus::LOAD_FAIL)) {
610         param = std::string("\"error\",{\"width\":")
611                     .append(std::to_string(picSize.Width()))
612                     .append(",\"height\":")
613                     .append(std::to_string(picSize.Height()))
614                     .append("}");
615         loadFailEvent_(param);
616     }
617     if (loadFailCallback_ && (imageLoadingStatus_ == ImageLoadingStatus::LOAD_FAIL)) {
618         loadFailCallback_();
619         loadFailCallback_ = nullptr;
620     }
621 }
622 
SetRadius(const Border & border)623 void RenderImage::SetRadius(const Border& border)
624 {
625     auto leftEdgeWidth = border.Left().GetWidth();
626     auto topEdgeWidth = border.Top().GetWidth();
627     auto rightEdgeWidth = border.Right().GetWidth();
628     auto bottomEdgeWidth = border.Bottom().GetWidth();
629     topLeftRadius_ = Radius(border.TopLeftRadius() - Radius(topEdgeWidth, leftEdgeWidth));
630     topRightRadius_ = Radius(border.TopRightRadius() - Radius(topEdgeWidth, rightEdgeWidth));
631     bottomLeftRadius_ = Radius(border.BottomLeftRadius() - Radius(bottomEdgeWidth, leftEdgeWidth));
632     bottomRightRadius_ = Radius(border.BottomRightRadius() - Radius(bottomEdgeWidth, rightEdgeWidth));
633 }
634 
IsSVG(const std::string & src,InternalResource::ResourceId resourceId)635 bool RenderImage::IsSVG(const std::string& src, InternalResource::ResourceId resourceId)
636 {
637     return ImageComponent::IsSvgSuffix(src) || (src.empty() && resourceId > InternalResource::ResourceId::SVG_START &&
638                                                    resourceId < InternalResource::ResourceId::SVG_END);
639 }
640 
PerformLayoutBgImage()641 void RenderImage::PerformLayoutBgImage()
642 {
643     if (!background_) {
644         return;
645     }
646     if (!rawImageSize_.IsValid()) {
647         return;
648     }
649 
650     GenerateImageRects(rawImageSize_, imageSize_, imageRepeat_, imagePosition_);
651     srcRect_.SetOffset(Offset());
652     srcRect_.SetSize(rawImageSize_);
653     dstRect_.SetOffset(Offset());
654     dstRect_.SetSize(imageRenderSize_);
655 }
656 
657 // objectPosition
ApplyObjectPosition()658 void RenderImage::ApplyObjectPosition()
659 {
660     Size layoutSize = GetLayoutSize();
661     Offset offset;
662     if (imageObjectPosition_.GetSizeTypeX() == BackgroundImagePositionType::PX) {
663         offset.SetX((layoutSize.Width() - dstRect_.Width()) / 2 - imageObjectPosition_.GetSizeValueX());
664     } else {
665         offset.SetX(
666             (layoutSize.Width() - dstRect_.Width()) / 2 - imageObjectPosition_.GetSizeValueX() *
667             (layoutSize.Width() - dstRect_.Width()) / PERCENT_TRANSLATE);
668     }
669 
670     if (imageObjectPosition_.GetSizeTypeY() == BackgroundImagePositionType::PX) {
671         offset.SetY((layoutSize.Height() - dstRect_.Height()) / 2 - imageObjectPosition_.GetSizeValueY());
672     } else {
673         offset.SetY(
674             (layoutSize.Height() - dstRect_.Height()) / 2 - imageObjectPosition_.GetSizeValueY() *
675             (layoutSize.Height() - dstRect_.Height()) / PERCENT_TRANSLATE);
676     }
677     imageRenderPosition_ = offset;
678 }
679 
GenerateImageRects(const Size & srcSize,const BackgroundImageSize & imageSize,ImageRepeat imageRepeat,const BackgroundImagePosition & imagePosition)680 void RenderImage::GenerateImageRects(const Size& srcSize, const BackgroundImageSize& imageSize, ImageRepeat imageRepeat,
681     const BackgroundImagePosition& imagePosition)
682 {
683     rectList_.clear();
684     if (NearEqual(boxPaintSize_.Width(), Size::INFINITE_SIZE) ||
685         NearEqual(boxPaintSize_.Height(), Size::INFINITE_SIZE)) {
686         boxPaintSize_ = viewPort_;
687     }
688 
689     // Different with Image Repeat
690     imageRenderSize_ = CalculateImageRenderSize(srcSize, imageSize);
691     if (NearZero(imageRenderSize_.Width()) || NearZero(imageRenderSize_.Height())) {
692         return;
693     }
694     // Ceil render size
695     imageRenderSize_ = Size(ceil(imageRenderSize_.Width()), ceil(imageRenderSize_.Height()));
696 
697     CalculateImageRenderPosition(imagePosition);
698 
699     int32_t minX = 0;
700     int32_t minY = 0;
701     int32_t maxX = 0;
702     int32_t maxY = 0;
703     if (imageRepeat == ImageRepeat::REPEAT || imageRepeat == ImageRepeat::REPEAT_X) {
704         if (LessOrEqual(imageRenderPosition_.GetX(), 0.0)) {
705             minX = 0;
706             maxX = std::ceil((boxPaintSize_.Width() - imageRenderPosition_.GetX()) / imageRenderSize_.Width());
707         } else {
708             minX = std::floor((-imageRenderPosition_.GetX()) / imageRenderSize_.Width());
709             maxX = std::ceil((boxPaintSize_.Width() - imageRenderPosition_.GetX()) / imageRenderSize_.Width());
710         }
711     }
712 
713     if (imageRepeat == ImageRepeat::REPEAT || imageRepeat == ImageRepeat::REPEAT_Y) {
714         if (LessOrEqual(imageRenderPosition_.GetY(), 0.0)) {
715             minY = 0;
716             maxY = std::ceil((boxPaintSize_.Height() - imageRenderPosition_.GetY()) / imageRenderSize_.Height());
717         } else {
718             minY = std::floor((-imageRenderPosition_.GetY()) / imageRenderSize_.Height());
719             maxY = std::ceil((boxPaintSize_.Height() - imageRenderPosition_.GetY()) / imageRenderSize_.Height());
720         }
721     }
722 
723     Rect imageCell = Rect(imageRenderPosition_, Size(imageRenderSize_.Width(), imageRenderSize_.Height()));
724     for (int32_t i = minY; i <= maxY; ++i) {
725         for (int32_t j = minX; j <= maxX; ++j) {
726             rectList_.emplace_back(imageCell + Offset(j * imageRenderSize_.Width(), i * imageRenderSize_.Height()));
727         }
728     }
729 
730     if (imageLoadingStatus_ == ImageLoadingStatus::LOAD_SUCCESS) {
731         currentDstRectList_ = rectList_;
732     }
733     LOGD("[BOX][Dep:%{public}d][IMAGE] Result: X:%{public}d-%{public}d, Y:%{public}d-%{public}d",
734         GetDepth(), minX, maxX, minY, maxY);
735 }
736 
CalculateImageRenderSize(const Size & srcSize,const BackgroundImageSize & imageSize) const737 Size RenderImage::CalculateImageRenderSize(const Size& srcSize, const BackgroundImageSize& imageSize) const
738 {
739     Size renderSize;
740     if (NearZero(srcSize.Width()) || NearZero(srcSize.Height()) || NearZero(boxPaintSize_.Width()) ||
741         NearZero(boxPaintSize_.Height())) {
742         return renderSize;
743     }
744 
745     if (!imageSize.IsValid()) {
746         return renderSize;
747     }
748 
749     if (imageSize.GetSizeTypeX() == BackgroundImageSizeType::CONTAIN ||
750         imageSize.GetSizeTypeX() == BackgroundImageSizeType::COVER) {
751         renderSize = CalculateImageRenderSizeWithSingleParam(srcSize, imageSize);
752     } else {
753         renderSize = CalculateImageRenderSizeWithDoubleParam(srcSize, imageSize);
754     }
755 
756     return renderSize;
757 }
758 
CalculateImageRenderSizeWithSingleParam(const Size & srcSize,const BackgroundImageSize & imageSize) const759 Size RenderImage::CalculateImageRenderSizeWithSingleParam(
760     const Size& srcSize, const BackgroundImageSize& imageSize) const
761 {
762     Size sizeRet;
763     if (NearZero(srcSize.Width()) || NearZero(srcSize.Height()) || NearZero(boxPaintSize_.Width()) ||
764         NearZero(boxPaintSize_.Height())) {
765         return sizeRet;
766     }
767     double renderSizeX = 0.0;
768     double renderSizeY = 0.0;
769     if (imageSize.GetSizeTypeX() == BackgroundImageSizeType::CONTAIN) {
770         double srcAspectRatio = srcSize.Width() / srcSize.Height();
771         double paintAspectRatio = boxPaintSize_.Width() / boxPaintSize_.Height();
772         renderSizeX = paintAspectRatio >= srcAspectRatio ? srcSize.Width() * (boxPaintSize_.Height() / srcSize.Height())
773                                                          : boxPaintSize_.Width();
774         renderSizeY = paintAspectRatio >= srcAspectRatio ? boxPaintSize_.Height()
775                                                          : srcSize.Height() * (boxPaintSize_.Width() / srcSize.Width());
776     } else if (imageSize.GetSizeTypeX() == BackgroundImageSizeType::COVER) {
777         double srcAspectRatio = srcSize.Width() / srcSize.Height();
778         double paintAspectRatio = boxPaintSize_.Width() / boxPaintSize_.Height();
779         renderSizeX = paintAspectRatio >= srcAspectRatio
780                           ? boxPaintSize_.Width()
781                           : srcSize.Width() * (boxPaintSize_.Height() / srcSize.Height());
782         renderSizeY = paintAspectRatio >= srcAspectRatio ? srcSize.Height() * (boxPaintSize_.Width() / srcSize.Width())
783                                                          : boxPaintSize_.Height();
784     }
785 
786     sizeRet.SetWidth(renderSizeX);
787     sizeRet.SetHeight(renderSizeY);
788     return sizeRet;
789 }
790 
CalculateImageRenderSizeWithDoubleParam(const Size & srcSize,const BackgroundImageSize & imageSize) const791 Size RenderImage::CalculateImageRenderSizeWithDoubleParam(
792     const Size& srcSize, const BackgroundImageSize& imageSize) const
793 {
794     Size sizeRet;
795     if (NearZero(srcSize.Width()) || NearZero(srcSize.Height()) || NearZero(boxPaintSize_.Width()) ||
796         NearZero(boxPaintSize_.Height())) {
797         return sizeRet;
798     }
799 
800     double renderSizeX = 0.0;
801     double renderSizeY = 0.0;
802     if (imageSize.GetSizeTypeX() == BackgroundImageSizeType::LENGTH) {
803         renderSizeX = imageSize.GetSizeValueX();
804     } else if (imageSize.GetSizeTypeX() == BackgroundImageSizeType::PERCENT) {
805         renderSizeX = boxPaintSize_.Width() * imageSize.GetSizeValueX() / PERCENT_TRANSLATE;
806     }
807 
808     if (imageSize.GetSizeTypeY() == BackgroundImageSizeType::LENGTH) {
809         renderSizeY = imageSize.GetSizeValueY();
810     } else if (imageSize.GetSizeTypeY() == BackgroundImageSizeType::PERCENT) {
811         renderSizeY = boxPaintSize_.Height() * imageSize.GetSizeValueY() / PERCENT_TRANSLATE;
812     }
813 
814     if (imageSize.GetSizeTypeX() == BackgroundImageSizeType::AUTO &&
815         imageSize.GetSizeTypeY() == BackgroundImageSizeType::AUTO) {
816         renderSizeX = srcSize.Width();
817         renderSizeY = srcSize.Height();
818     } else if (imageSize.GetSizeTypeX() == BackgroundImageSizeType::AUTO) {
819         renderSizeX = srcSize.Width() * (renderSizeY / srcSize.Height());
820     } else if (imageSize.GetSizeTypeY() == BackgroundImageSizeType::AUTO) {
821         renderSizeY = srcSize.Height() * (renderSizeX / srcSize.Width());
822     }
823 
824     sizeRet.SetWidth(renderSizeX);
825     sizeRet.SetHeight(renderSizeY);
826     if (!sizeRet.IsValid()) {
827         sizeRet = Size();
828     }
829     return sizeRet;
830 }
831 
CalculateImageRenderPosition(const BackgroundImagePosition & imagePosition)832 void RenderImage::CalculateImageRenderPosition(const BackgroundImagePosition& imagePosition)
833 {
834     Offset offset;
835 
836     if (imagePosition.GetSizeTypeX() == BackgroundImagePositionType::PX) {
837         offset.SetX(imagePosition.GetSizeValueX());
838     } else {
839         offset.SetX(
840             imagePosition.GetSizeValueX() * (boxPaintSize_.Width() - imageRenderSize_.Width()) / PERCENT_TRANSLATE);
841     }
842 
843     if (imagePosition.GetSizeTypeY() == BackgroundImagePositionType::PX) {
844         offset.SetY(imagePosition.GetSizeValueY());
845     } else {
846         offset.SetY(
847             imagePosition.GetSizeValueY() * (boxPaintSize_.Height() - imageRenderSize_.Height()) / PERCENT_TRANSLATE);
848     }
849 
850     imageRenderPosition_ = offset;
851 }
852 
ClearRenderObject()853 void RenderImage::ClearRenderObject()
854 {
855     RenderNode::ClearRenderObject();
856 
857     isImageSizeSet_ = false;
858     rawImageSizeUpdated_ = false;
859     matchTextDirection_ = false;
860     imageComponentSize_ = Size();
861     formerMaxSize_ = Size();
862     alignment_ = Alignment::CENTER;
863     imageLoadingStatus_ = ImageLoadingStatus::UNLOADED;
864 
865     imageFit_ = ImageFit::COVER;
866     imageRepeat_ = ImageRepeat::NO_REPEAT;
867     rectList_.clear();
868     color_.reset();
869     sourceInfo_.Reset();
870     singleWidth_ = 0.0;
871     displaySrcWidth_ = 0.0;
872     scale_ = 1.0;
873     horizontalRepeatNum_ = 1.0;
874     rotate_ = 0.0;
875     keepOffsetZero_ = false;
876     resizeCallLoadImage_ = false;
877     frameCount_ = 0;
878     topLeftRadius_ = Radius(0.0);
879     topRightRadius_ = Radius(0.0);
880     bottomLeftRadius_ = Radius(0.0);
881     bottomRightRadius_ = Radius(0.0);
882     resizeScale_ = Size();
883     resizeTarget_ = Size();
884     previousResizeTarget_ = Size();
885     currentResizeScale_ = Size();
886     width_ = Dimension();
887     height_ = Dimension();
888     rawImageSize_ = Size();
889     renderAltImage_ = nullptr;
890     proceedPreviousLoading_ = false;
891     imageUpdateFunc_ = nullptr;
892     imageRenderFunc_ = nullptr;
893     background_ = false;
894     boxPaintSize_ = Size();
895     boxMarginOffset_ = Offset();
896     imageSize_ = BackgroundImageSize();
897     imagePosition_ = BackgroundImagePosition();
898     imageObjectPosition_ = ImageObjectPosition();
899     imageRenderSize_ = Size();
900     imageRenderPosition_ = Offset();
901     forceResize_ = false;
902     forceReload_ = false;
903     imageSizeForEvent_ = { 0.0, 0.0 };
904     retryCnt_ = 0;
905 }
906 
PrintImageLog(const Size & srcSize,const BackgroundImageSize & imageSize,ImageRepeat imageRepeat,const BackgroundImagePosition & imagePosition) const907 void RenderImage::PrintImageLog(const Size& srcSize, const BackgroundImageSize& imageSize, ImageRepeat imageRepeat,
908     const BackgroundImagePosition& imagePosition) const
909 {
910     LOGD("[BOX][IMAGE][Dep:%{public}d] Param:Src W:%{public}.1lf, H:%{public}.1lf, Size:%{public}.1lf|%{public}d, "
911          "%{public}.1lf|%{public}d, Rep:%{public}u, Pos X:%{public}.1lf|%{public}d, Y:%{public}.1lf|%{public}d, "
912          "BoxPaint:%{public}.1lf * %{public}.1lf, MarginOffset: %{public}.1lf * %{public}.1lf",
913         GetDepth(), srcSize.Width(), srcSize.Height(), imageSize.GetSizeValueX(), imageSize.GetSizeTypeX(),
914         imageSize.GetSizeValueY(), imageSize.GetSizeTypeY(), imageRepeat, imagePosition.GetSizeValueX(),
915         imagePosition.GetSizeTypeX(), imagePosition.GetSizeValueY(), imagePosition.GetSizeTypeY(),
916         boxPaintSize_.Width(), boxPaintSize_.Height(), boxMarginOffset_.GetX(), boxMarginOffset_.GetY());
917     LOGD("[BOX][IMAGE][Dep:%{public}d] Result: Size:(%{public}.1lf*%{public}.1lf), Pos(%{public}.1lf,%{public}.1lf), "
918          "rect:%{public}s",
919         GetDepth(), imageRenderSize_.Width(), imageRenderSize_.Height(), imageRenderPosition_.GetX(),
920         imageRenderPosition_.GetY(), rectList_.front().ToString().c_str());
921 }
922 
Dump()923 void RenderImage::Dump()
924 {
925     DumpLog::GetInstance().AddDesc(std::string("UsingWideGamut: ").append(IsSourceWideGamut() ? "true" : "false"));
926 }
927 
GenerateDragItemInfo(const RefPtr<PipelineContext> & context,const GestureEvent & info)928 DragItemInfo RenderImage::GenerateDragItemInfo(const RefPtr<PipelineContext>& context, const GestureEvent& info)
929 {
930     RefPtr<DragEvent> event = AceType::MakeRefPtr<DragEvent>();
931     event->SetX(context->ConvertPxToVp(Dimension(info.GetGlobalPoint().GetX(), DimensionUnit::PX)));
932     event->SetY(context->ConvertPxToVp(Dimension(info.GetGlobalPoint().GetY(), DimensionUnit::PX)));
933     selectedItemSize_ = GetLayoutSize();
934     auto extraParams = JsonUtil::Create(true);
935 
936     return onDragStart_(event, extraParams->ToString());
937 }
938 
PanOnActionStart(const GestureEvent & info)939 void RenderImage::PanOnActionStart(const GestureEvent& info)
940 {
941     if (!onDragStart_) {
942         return;
943     }
944 
945     auto pipelineContext = context_.Upgrade();
946     if (!pipelineContext) {
947         LOGE("Context is null.");
948         return;
949     }
950 
951     GestureEvent newInfo = info;
952     Point newPoint = UpdatePoint(pipelineContext, startPoint_);
953     newInfo.SetGlobalPoint(newPoint);
954     auto dragItemInfo = GenerateDragItemInfo(pipelineContext, newInfo);
955 #if !defined(PREVIEW)
956     if (!dragItemInfo.pixelMap && !dragItemInfo.customComponent) {
957         auto initRenderNode = AceType::Claim(this);
958         isDragDropNode_ = true;
959         pipelineContext->SetInitRenderNode(initRenderNode);
960 
961         AddDataToClipboard(pipelineContext, dragItemInfo.extraInfo, "", GetImageSrc());
962         if (!dragWindow_) {
963             auto rect = pipelineContext->GetCurrentWindowRect();
964             dragWindow_ = DragWindow::CreateDragWindow("APP_DRAG_WINDOW",
965                 static_cast<int32_t>(info.GetGlobalPoint().GetX() + rect.Left()),
966                 static_cast<int32_t>(info.GetGlobalPoint().GetY() + rect.Top()),
967                 static_cast<uint32_t>(initRenderNode->GetPaintRect().Width()),
968                 static_cast<uint32_t>(initRenderNode->GetPaintRect().Height()));
969             dragWindow_->SetOffset(static_cast<int32_t>(rect.Left()), static_cast<int32_t>(rect.Top()));
970             auto image = initRenderNode->GetSkImage();
971             dragWindow_->DrawImage(image);
972         }
973         if (dragWindow_) {
974             AceEngineExt::GetInstance().DragStartExt();
975         }
976         return;
977     }
978 
979     if (dragItemInfo.pixelMap) {
980         auto initRenderNode = AceType::Claim(this);
981         isDragDropNode_ = true;
982         pipelineContext->SetInitRenderNode(initRenderNode);
983 
984         AddDataToClipboard(pipelineContext, dragItemInfo.extraInfo, "", GetImageSrc());
985         if (!dragWindow_) {
986             auto rect = pipelineContext->GetCurrentWindowRect();
987             dragWindow_ = DragWindow::CreateDragWindow("APP_DRAG_WINDOW",
988                 static_cast<int32_t>(info.GetGlobalPoint().GetX()) + rect.Left(),
989                 static_cast<int32_t>(info.GetGlobalPoint().GetY()) + rect.Top(), dragItemInfo.pixelMap->GetWidth(),
990                 dragItemInfo.pixelMap->GetHeight());
991             dragWindow_->SetOffset(rect.Left(), rect.Top());
992             dragWindow_->DrawPixelMap(dragItemInfo.pixelMap);
993         }
994         if (dragWindow_) {
995             AceEngineExt::GetInstance().DragStartExt();
996         }
997         return;
998     }
999 #endif
1000     if (!dragItemInfo.customComponent) {
1001         LOGW("the drag custom component is null");
1002         return;
1003     }
1004 
1005     hasDragItem_ = true;
1006     auto positionedComponent = AceType::MakeRefPtr<PositionedComponent>(dragItemInfo.customComponent);
1007     positionedComponent->SetTop(Dimension(GetGlobalOffset().GetY()));
1008     positionedComponent->SetLeft(Dimension(GetGlobalOffset().GetX()));
1009     SetLocalPoint(startPoint_ - GetGlobalOffset());
1010     auto updatePosition = [renderBox = AceType::Claim(this)](
1011                               const std::function<void(const Dimension&, const Dimension&)>& func) {
1012         if (!renderBox) {
1013             return;
1014         }
1015         renderBox->SetUpdateBuilderFuncId(func);
1016     };
1017     positionedComponent->SetUpdatePositionFuncId(updatePosition);
1018     auto stackElement = pipelineContext->GetLastStack();
1019     stackElement->PushComponent(positionedComponent);
1020 }
1021 
PanOnActionUpdate(const GestureEvent & info)1022 void RenderImage::PanOnActionUpdate(const GestureEvent& info)
1023 {
1024 #if !defined(PREVIEW)
1025     if (isDragDropNode_ && dragWindow_) {
1026         int32_t x = static_cast<int32_t>(info.GetGlobalPoint().GetX());
1027         int32_t y = static_cast<int32_t>(info.GetGlobalPoint().GetY());
1028         if (lastDragMoveOffset_ == Offset(x, y)) {
1029             return;
1030         }
1031         lastDragMoveOffset_ = Offset(x, y);
1032         if (dragWindow_) {
1033             dragWindow_->MoveTo(x, y);
1034         }
1035         return;
1036     }
1037 #endif
1038     auto pipelineContext = context_.Upgrade();
1039     if (!pipelineContext) {
1040         LOGE("Context is null.");
1041         return;
1042     }
1043 
1044     RefPtr<DragEvent> event = AceType::MakeRefPtr<DragEvent>();
1045     event->SetX(pipelineContext->ConvertPxToVp(Dimension(info.GetGlobalPoint().GetX(), DimensionUnit::PX)));
1046     event->SetY(pipelineContext->ConvertPxToVp(Dimension(info.GetGlobalPoint().GetY(), DimensionUnit::PX)));
1047 
1048     Offset offset = info.GetGlobalPoint() - GetLocalPoint();
1049     if (GetUpdateBuilderFuncId()) {
1050         GetUpdateBuilderFuncId()(Dimension(offset.GetX()), Dimension(offset.GetY()));
1051     }
1052 
1053     auto extraParams = JsonUtil::Create(true);
1054     auto targetDragDropNode = FindDragDropNode(pipelineContext, info);
1055     auto preDragDropNode = GetPreDragDropNode();
1056     if (preDragDropNode == targetDragDropNode) {
1057         if (targetDragDropNode && targetDragDropNode->GetOnDragMove()) {
1058             (targetDragDropNode->GetOnDragMove())(event, extraParams->ToString());
1059         }
1060         return;
1061     }
1062     if (preDragDropNode && preDragDropNode->GetOnDragLeave()) {
1063         (preDragDropNode->GetOnDragLeave())(event, extraParams->ToString());
1064     }
1065     if (targetDragDropNode && targetDragDropNode->GetOnDragEnter()) {
1066         (targetDragDropNode->GetOnDragEnter())(event, extraParams->ToString());
1067     }
1068     SetPreDragDropNode(targetDragDropNode);
1069 }
1070 
PanOnActionEnd(const GestureEvent & info)1071 void RenderImage::PanOnActionEnd(const GestureEvent& info)
1072 {
1073     auto pipelineContext = context_.Upgrade();
1074     if (!pipelineContext) {
1075         LOGE("Context is null.");
1076         return;
1077     }
1078 #if !defined(PREVIEW)
1079     if (isDragDropNode_) {
1080         isDragDropNode_ = false;
1081         RestoreCilpboardData(pipelineContext);
1082 
1083         if (GetOnDrop()) {
1084             RefPtr<DragEvent> event = AceType::MakeRefPtr<DragEvent>();
1085             RefPtr<PasteData> pasteData = AceType::MakeRefPtr<PasteData>();
1086             event->SetPasteData(pasteData);
1087             event->SetX(pipelineContext->ConvertPxToVp(Dimension(info.GetGlobalPoint().GetX(), DimensionUnit::PX)));
1088             event->SetY(pipelineContext->ConvertPxToVp(Dimension(info.GetGlobalPoint().GetY(), DimensionUnit::PX)));
1089 
1090             auto extraParams = JsonUtil::Create(true);
1091             (GetOnDrop())(event, extraParams->ToString());
1092             pipelineContext->SetInitRenderNode(nullptr);
1093         }
1094     }
1095 
1096     if (dragWindow_) {
1097         dragWindow_->Destroy();
1098         dragWindow_ = nullptr;
1099         return;
1100     }
1101 #endif
1102     RefPtr<DragEvent> event = AceType::MakeRefPtr<DragEvent>();
1103     RefPtr<PasteData> pasteData = AceType::MakeRefPtr<PasteData>();
1104     event->SetPasteData(pasteData);
1105     event->SetX(pipelineContext->ConvertPxToVp(Dimension(info.GetGlobalPoint().GetX(), DimensionUnit::PX)));
1106     event->SetY(pipelineContext->ConvertPxToVp(Dimension(info.GetGlobalPoint().GetY(), DimensionUnit::PX)));
1107 
1108     Offset offset = info.GetGlobalPoint() - GetLocalPoint();
1109     if (GetUpdateBuilderFuncId()) {
1110         GetUpdateBuilderFuncId()(Dimension(offset.GetX()), Dimension(offset.GetY()));
1111     }
1112     if (hasDragItem_) {
1113         auto stackElement = pipelineContext->GetLastStack();
1114         stackElement->PopComponent();
1115     }
1116     hasDragItem_ = false;
1117 
1118     ACE_DCHECK(GetPreDragDropNode() == FindTargetRenderNode<DragDropEvent>(pipelineContext, info));
1119     auto targetDragDropNode = GetPreDragDropNode();
1120     if (!targetDragDropNode) {
1121         return;
1122     }
1123     if (targetDragDropNode->GetOnDrop()) {
1124         auto extraParams = JsonUtil::Create(true);
1125         (targetDragDropNode->GetOnDrop())(event, extraParams->ToString());
1126     }
1127     SetPreDragDropNode(nullptr);
1128 }
1129 
PanOnActionCancel()1130 void RenderImage::PanOnActionCancel()
1131 {
1132     auto pipelineContext = context_.Upgrade();
1133     if (!pipelineContext) {
1134         LOGE("Context is null.");
1135         return;
1136     }
1137 
1138 #if !defined(PREVIEW)
1139     if (isDragDropNode_) {
1140         isDragDropNode_ = false;
1141         RestoreCilpboardData(pipelineContext);
1142     }
1143 
1144     if (dragWindow_) {
1145         dragWindow_->Destroy();
1146         dragWindow_ = nullptr;
1147     }
1148 #endif
1149     if (hasDragItem_) {
1150         auto stackElement = pipelineContext->GetLastStack();
1151         stackElement->PopComponent();
1152         hasDragItem_ = false;
1153     }
1154     SetPreDragDropNode(nullptr);
1155 }
1156 
1157 } // namespace OHOS::Ace
1158