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