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