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