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