diff --git a/frameworks/core/components_ng/image_provider/image_loading_context.cpp b/frameworks/core/components_ng/image_provider/image_loading_context.cpp index b30031f0f0c2a3914bf2aa4431b159a076edfba0..9fe0efb099000d2ee2920113af59a2046407fbeb 100644 --- a/frameworks/core/components_ng/image_provider/image_loading_context.cpp +++ b/frameworks/core/components_ng/image_provider/image_loading_context.cpp @@ -262,6 +262,25 @@ void ImageLoadingContext::OnMakeCanvasImage() imageObj_->MakeCanvasImage(Claim(this), targetSize, userDefinedSize.has_value(), syncLoad_); } +void ImageLoadingContext::ResizableCalcDstSize() +{ + auto userDefinedSize = GetSourceSize(); + if (userDefinedSize) { + ImagePainter::ApplyImageFit(imageFit_, *userDefinedSize, dstSize_, srcRect_, dstRect_); + return; + } + auto imageSize = GetImageSize(); + // calculate the srcRect based on original image size + ImagePainter::ApplyImageFit(imageFit_, imageSize, dstSize_, srcRect_, dstRect_); + + bool isPixelMapResource = (SrcType::DATA_ABILITY_DECODED == GetSourceInfo().GetSrcType()); + if (autoResize_ && !isPixelMapResource) { + SizeF targetSize = CalculateTargetSize(srcRect_.GetSize(), dstRect_.GetSize(), imageSize); + // calculate real srcRect used for paint based on resized image size + ImagePainter::ApplyImageFit(imageFit_, targetSize, dstSize_, srcRect_, dstRect_); + } +} + void ImageLoadingContext::DataReadyCallback(const RefPtr& imageObj) { CHECK_NULL_VOID(imageObj); @@ -314,8 +333,8 @@ int32_t ImageLoadingContext::RoundUp(int32_t value) return res; } -bool ImageLoadingContext::MakeCanvasImageIfNeed( - const SizeF& dstSize, bool autoResize, ImageFit imageFit, const std::optional& sourceSize) +bool ImageLoadingContext::MakeCanvasImageIfNeed(const SizeF& dstSize, bool autoResize, ImageFit imageFit, + const std::optional& sourceSize, bool hasValidSlice) { bool res = autoResize != autoResize_ || imageFit != imageFit_ || sourceSize != GetSourceSize(); @@ -327,6 +346,9 @@ bool ImageLoadingContext::MakeCanvasImageIfNeed( } else if (dstSize_ == SizeF()) { res |= dstSize.IsPositive(); } + if (!res && hasValidSlice) { + dstSize_ = dstSize; + } CHECK_NULL_RETURN(res, res); if (stateManager_->GetCurrentState() == ImageLoadingState::MAKE_CANVAS_IMAGE) { pendingMakeCanvasImageTask_ = [weak = AceType::WeakClaim(this), dstSize, autoResize, imageFit, sourceSize]() { diff --git a/frameworks/core/components_ng/image_provider/image_loading_context.h b/frameworks/core/components_ng/image_provider/image_loading_context.h index d44f63b05f6c2fead60201668c082eaa8002dc58..3e7851ebe13df8b9d8f170810ffe67d5ad1d89cc 100644 --- a/frameworks/core/components_ng/image_provider/image_loading_context.h +++ b/frameworks/core/components_ng/image_provider/image_loading_context.h @@ -38,7 +38,7 @@ public: // return true if calling MakeCanvasImage is necessary bool MakeCanvasImageIfNeed(const SizeF& dstSize, bool autoResize, ImageFit imageFit, - const std::optional& sourceSize = std::nullopt); + const std::optional& sourceSize = std::nullopt, bool hasValidSlice = false); /* interfaces to drive image loading */ void LoadImageData(); @@ -72,6 +72,7 @@ public: void SuccessCallback(const RefPtr& canvasImage); void FailCallback(const std::string& errorMsg); const std::string GetCurrentLoadingState(); + void ResizableCalcDstSize(); private: #define DEFINE_SET_NOTIFY_TASK(loadResult) \ diff --git a/frameworks/core/components_ng/pattern/image/image_layout_algorithm.cpp b/frameworks/core/components_ng/pattern/image/image_layout_algorithm.cpp index 219397f9de4a23066278bba2c161038655a03b76..1936a1784d3cb84fb60c13e2f29c687c95a7b112 100644 --- a/frameworks/core/components_ng/pattern/image/image_layout_algorithm.cpp +++ b/frameworks/core/components_ng/pattern/image/image_layout_algorithm.cpp @@ -20,6 +20,7 @@ #endif #include "core/components_ng/base/frame_node.h" #include "core/components_ng/pattern/image/image_layout_property.h" +#include "core/components_ng/pattern/image/image_render_property.h" #include "core/pipeline_ng/pipeline_context.h" namespace OHOS::Ace::NG { @@ -119,13 +120,18 @@ void ImageLayoutAlgorithm::Layout(LayoutWrapper* layoutWrapper) bool autoResize = props->GetAutoResize().value_or(true); ImageFit imageFit = props->GetImageFit().value_or(ImageFit::COVER); const std::optional& sourceSize = props->GetSourceSize(); + bool hasValidSlice = false; + if (layoutWrapper->GetHostNode()) { + auto renderProp = layoutWrapper->GetHostNode()->GetPaintProperty(); + hasValidSlice = renderProp && renderProp->HasImageResizableSlice(); + } auto loadingCtx = loadingCtx_.Upgrade(); if (loadingCtx) { - loadingCtx->MakeCanvasImageIfNeed(dstSize, autoResize, imageFit, sourceSize); + loadingCtx->MakeCanvasImageIfNeed(dstSize, autoResize, imageFit, sourceSize, hasValidSlice); } auto altLoadingCtx = altLoadingCtx_.Upgrade(); if (altLoadingCtx) { - altLoadingCtx->MakeCanvasImageIfNeed(dstSize, true, imageFit, sourceSize); + altLoadingCtx->MakeCanvasImageIfNeed(dstSize, true, imageFit, sourceSize, hasValidSlice); } } diff --git a/frameworks/core/components_ng/pattern/image/image_pattern.cpp b/frameworks/core/components_ng/pattern/image/image_pattern.cpp index 3c465b4862376a676fbcd466dafca2ba29b839b5..324fe11357a72d0b24713912de2f625f3a88bc66 100644 --- a/frameworks/core/components_ng/pattern/image/image_pattern.cpp +++ b/frameworks/core/components_ng/pattern/image/image_pattern.cpp @@ -298,7 +298,15 @@ bool ImagePattern::OnDirtyLayoutWrapperSwap(const RefPtr& dirty, if (config.skipMeasure || dirty->SkipMeasureContent()) { return false; } - + + if (loadingCtx_) { + auto renderProp = GetPaintProperty(); + if (renderProp && renderProp->HasImageResizableSlice() && image_) { + loadingCtx_->ResizableCalcDstSize(); + SetImagePaintConfig(image_, loadingCtx_->GetSrcRect(), loadingCtx_->GetDstRect(), false); + } + } + if (IsSupportImageAnalyzerFeature()) { UpdateAnalyzerUIConfig(dirty->GetGeometryNode()); } diff --git a/test/mock/core/image_provider/mock_image_loading_context.cpp b/test/mock/core/image_provider/mock_image_loading_context.cpp index 0d9cb8267da8217ddea9ec119b1519d2d7f2c9b2..e0cb0ffc1288d8ad9cb4b74c033573c3b7a7223e 100644 --- a/test/mock/core/image_provider/mock_image_loading_context.cpp +++ b/test/mock/core/image_provider/mock_image_loading_context.cpp @@ -13,9 +13,10 @@ * limitations under the License. */ -#include "core/components_ng/image_provider/image_loading_context.h" #include "test/mock/core/render/mock_canvas_image.h" +#include "core/components_ng/image_provider/image_loading_context.h" + namespace OHOS::Ace::NG { ImageLoadingContext::ImageLoadingContext(const ImageSourceInfo& src, LoadNotifier&& loadNotifier, bool syncLoad) : src_(src), notifiers_(loadNotifier), syncLoad_(syncLoad) @@ -80,8 +81,8 @@ RefPtr ImageLoadingContext::MoveCanvasImage() void ImageLoadingContext::LoadImageData() {} -bool ImageLoadingContext::MakeCanvasImageIfNeed( - const SizeF& dstSize, bool incomingNeedResize, ImageFit incomingImageFit, const std::optional& sourceSize) +bool ImageLoadingContext::MakeCanvasImageIfNeed(const SizeF& dstSize, bool incomingNeedResize, + ImageFit incomingImageFit, const std::optional& sourceSize, bool hasValidSlice) { dstSize_ = dstSize; imageFit_ = incomingImageFit; @@ -143,6 +144,7 @@ bool ImageLoadingContext::NeedAlt() const void ImageLoadingContext::ResetLoading() {} void ImageLoadingContext::ResumeLoading() {} void ImageLoadingContext::DownloadImage() {} +void ImageLoadingContext::ResizableCalcDstSize() {} const std::string ImageLoadingContext::GetCurrentLoadingState() {