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