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