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