diff --git a/adapter/ohos/osal/pixel_map_ohos.cpp b/adapter/ohos/osal/pixel_map_ohos.cpp index 9afdce5a..f254d34f 100644 --- a/adapter/ohos/osal/pixel_map_ohos.cpp +++ b/adapter/ohos/osal/pixel_map_ohos.cpp @@ -155,4 +155,20 @@ void* PixelMapOhos::GetRawPixelMapPtr() const return pixmap_.get(); } +std::string PixelMapOhos::GetId() +{ + if (pixmap_) { + return pixmap_->GetId(); + } + return std::string(); +} + +std::string PixelMapOhos::GetModifyId() +{ + if (pixmap_) { + return pixmap_->GetModifyId(); + } + return std::string(); +} + } // namespace OHOS::Ace \ No newline at end of file diff --git a/adapter/ohos/osal/pixel_map_ohos.h b/adapter/ohos/osal/pixel_map_ohos.h index abcc2f00..21c9914f 100644 --- a/adapter/ohos/osal/pixel_map_ohos.h +++ b/adapter/ohos/osal/pixel_map_ohos.h @@ -40,6 +40,8 @@ public: int32_t GetByteCount() const override; void* GetPixelManager() const override; void* GetRawPixelMapPtr() const override; + std::string GetId() override; + std::string GetModifyId() override; private: std::shared_ptr pixmap_; diff --git a/frameworks/base/image/pixel_map.h b/frameworks/base/image/pixel_map.h index 8bf1ad74..361e855d 100644 --- a/frameworks/base/image/pixel_map.h +++ b/frameworks/base/image/pixel_map.h @@ -55,6 +55,8 @@ public: virtual int32_t GetByteCount() const = 0; virtual void* GetPixelManager() const = 0; virtual void* GetRawPixelMapPtr() const = 0; + virtual std::string GetId() = 0; + virtual std::string GetModifyId() = 0; }; } // namespace OHOS::Ace diff --git a/frameworks/core/components/common/layout/constants.h b/frameworks/core/components/common/layout/constants.h index f7613a36..4994c6f1 100644 --- a/frameworks/core/components/common/layout/constants.h +++ b/frameworks/core/components/common/layout/constants.h @@ -301,9 +301,11 @@ enum class SrcType { NETWORK, MEMORY, BASE64, - INTERNAL, + INTERNAL, // internal cached file resource RESOURCE, DATA_ABILITY, + RESOURCE_ID, // default resource which src is internal resource id + PIXMAP, }; enum class WrapAlignment { diff --git a/frameworks/core/components/image/flutter_render_image.cpp b/frameworks/core/components/image/flutter_render_image.cpp index e4058047..01da8779 100644 --- a/frameworks/core/components/image/flutter_render_image.cpp +++ b/frameworks/core/components/image/flutter_render_image.cpp @@ -187,6 +187,7 @@ void FlutterRenderImage::ImageObjReady(const RefPtr& imageObj) } } else { LOGI("image is vectorgraph(svg) without absolute size, set svgDom_"); + image_ = nullptr; if (useSkiaSvg_) { skiaDom_ = AceType::DynamicCast(imageObj_)->GetSkiaDom(); } else { @@ -274,35 +275,21 @@ void FlutterRenderImage::CacheImageObject() } } -void FlutterRenderImage::UpdatePixmap() +void FlutterRenderImage::UpdatePixmap(const RefPtr& pixmap) { - if (pixmapRawPtr_ == DynamicCast(imageObj_)->GetRawPixelMapPtr()) { - LOGD("pixmapRawPtr_ not changed."); - imageObj_->ClearData(); - } else { - image_ = nullptr; - curSourceInfo_.Reset(); - rawImageSize_ = imageObj_->GetImageSize(); - rawImageSizeUpdated_ = true; - imageLoadingStatus_ = ImageLoadingStatus::LOAD_SUCCESS; - } + LOGD("update pixmap"); + imageObj_ = MakeRefPtr(pixmap); + image_ = nullptr; + curSourceInfo_.Reset(); + rawImageSize_ = imageObj_->GetImageSize(); + rawImageSizeUpdated_ = true; + imageLoadingStatus_ = ImageLoadingStatus::LOAD_SUCCESS; MarkNeedLayout(); } void FlutterRenderImage::Update(const RefPtr& component) { RenderImage::Update(component); - auto pixmap = AceType::DynamicCast(component)->GetPixmap(); - if (pixmap != nullptr) { - LOGD("pixmap not null!"); - sourceInfo_.Reset(); - imageObj_ = MakeRefPtr(pixmap); - UpdatePixmap(); - return; - } else { - LOGD("pixmap is null!"); - pixmapRawPtr_ = nullptr; - } // curImageSrc represents the picture currently shown and imageSrc represents next picture to be shown imageLoadingStatus_ = (sourceInfo_ != curSourceInfo_) ? ImageLoadingStatus::UPDATING : imageLoadingStatus_; UpdateRenderAltImage(component); @@ -340,25 +327,40 @@ void FlutterRenderImage::FetchImageObject() return; } rawImageSizeUpdated_ = false; - SrcType srcType = ImageLoader::ResolveURI(sourceInfo_.GetSrc()); - auto isNetworkSrc = (ImageLoader::ResolveURI(sourceInfo_.GetSrc()) == SrcType::NETWORK); - if (srcType != SrcType::MEMORY) { - bool syncMode = context->IsBuildingFirstPage() && frontend->GetType() == FrontendType::JS_CARD && !isNetworkSrc; - ImageProvider::FetchImageObject( - sourceInfo_, - imageObjSuccessCallback_, - uploadSuccessCallback_, - failedCallback_, - GetContext(), - syncMode, - useSkiaSvg_, - autoResize_, - renderTaskHolder_, - onPostBackgroundTask_); - return; + SrcType srcType = sourceInfo_.GetSrcType(); + switch (srcType) { + case SrcType::PIXMAP: { + UpdatePixmap(sourceInfo_.GetPixmap()); + break; + } + case SrcType::MEMORY: { + UpdateSharedMemoryImage(context); + break; + } + default: { + bool syncMode = context->IsBuildingFirstPage() && + frontend->GetType() == FrontendType::JS_CARD && + sourceInfo_.GetSrcType() != SrcType::NETWORK; + ImageProvider::FetchImageObject( + sourceInfo_, + imageObjSuccessCallback_, + uploadSuccessCallback_, + failedCallback_, + GetContext(), + syncMode, + useSkiaSvg_, + autoResize_, + renderTaskHolder_, + onPostBackgroundTask_); + break; + } } +} + +void FlutterRenderImage::UpdateSharedMemoryImage(const RefPtr& context) +{ auto sharedImageManager = context->GetSharedImageManager(); - if (sharedImageManager && srcType == SrcType::MEMORY) { + if (sharedImageManager) { if (sharedImageManager->IsResourceToReload(ImageLoader::RemovePathHead(sourceInfo_.GetSrc()))) { // This case means that the imageSrc to load is a memory image and its data is not ready. // If run [GetImageSize] here, there will be an unexpected [OnLoadFail] callback from [ImageProvider]. @@ -422,8 +424,6 @@ void FlutterRenderImage::ProcessPixmapForPaint() imageObj_->ClearData(); return; } - pixmapRawPtr_ = pixmap->GetRawPixelMapPtr(); - imageObj_->ClearData(); FireLoadEvent(rawImageSize_); renderAltImage_ = nullptr; } @@ -490,7 +490,7 @@ void FlutterRenderImage::Paint(RenderContext& context, const Offset& offset) renderAltImage_->SetDirectPaint(directPaint_); renderAltImage_->RenderWithContext(context, offset); } - if (sourceInfo_.IsValid()) { + if (sourceInfo_.GetSrcType() != SrcType::PIXMAP) { UpLoadImageDataForPaint(); } auto canvas = ScopedCanvas::Create(context); @@ -648,7 +648,9 @@ void FlutterRenderImage::CanvasDrawImageRect( bool isLoading = ((imageLoadingStatus_ == ImageLoadingStatus::LOADING) || (imageLoadingStatus_ == ImageLoadingStatus::UPDATING)); Rect scaledSrcRect = isLoading ? currentSrcRect_ : srcRect_; - if (sourceInfo_.IsValid() && imageObj_ && (imageObj_->GetFrameCount() == 1)) { + if (sourceInfo_.IsValid() && + imageObj_ && (imageObj_->GetFrameCount() == 1) && + sourceInfo_.GetSrcType() != SrcType::PIXMAP) { Size sourceSize = (image_ ? Size(image_->width(), image_->height()) : Size()); // calculate srcRect that matches the real image source size // note that gif doesn't do resize, so gif does not need to recalculate @@ -1165,8 +1167,9 @@ bool FlutterRenderImage::RetryLoading() sourceInfo_.ToString().c_str()); return false; } - auto isNetworkSrc = (ImageLoader::ResolveURI(sourceInfo_.GetSrc()) == SrcType::NETWORK); - bool syncMode = context->IsBuildingFirstPage() && frontend->GetType() == FrontendType::JS_CARD && !isNetworkSrc; + bool syncMode = context->IsBuildingFirstPage() && + frontend->GetType() == FrontendType::JS_CARD && + sourceInfo_.GetSrcType() != SrcType::NETWORK; ImageProvider::FetchImageObject( sourceInfo_, diff --git a/frameworks/core/components/image/flutter_render_image.h b/frameworks/core/components/image/flutter_render_image.h index 1553e744..e0fc3380 100644 --- a/frameworks/core/components/image/flutter_render_image.h +++ b/frameworks/core/components/image/flutter_render_image.h @@ -141,7 +141,8 @@ private: void PerformLayoutSvgCustom(); void CancelBackgroundTasks(); void CacheImageObject(); - void UpdatePixmap(); + void UpdatePixmap(const RefPtr& pixmap); + void UpdateSharedMemoryImage(const RefPtr& context); void ProcessPixmapForPaint(); sk_sp skiaDom_; diff --git a/frameworks/core/components/image/render_image.cpp b/frameworks/core/components/image/render_image.cpp index a2849c80..11d260a5 100644 --- a/frameworks/core/components/image/render_image.cpp +++ b/frameworks/core/components/image/render_image.cpp @@ -76,7 +76,8 @@ void RenderImage::Update(const RefPtr& component) inComingSrc, image->GetImageSourceSize().first, image->GetImageSourceSize().second, - inComingSrc.empty() ? image->GetResourceId() : InternalResource::ResourceId::NO_ID); + inComingSrc.empty() ? image->GetResourceId() : InternalResource::ResourceId::NO_ID, + image->GetPixmap()); auto fillColor = image->GetImageFill(); if (fillColor.has_value()) { inComingSource.SetFillColor(fillColor.value()); diff --git a/frameworks/core/components/image/rosen_render_image.cpp b/frameworks/core/components/image/rosen_render_image.cpp index 58c18511..f216f808 100644 --- a/frameworks/core/components/image/rosen_render_image.cpp +++ b/frameworks/core/components/image/rosen_render_image.cpp @@ -180,6 +180,7 @@ void RosenRenderImage::ImageObjReady(const RefPtr& imageObj) } } else { LOGI("image is vectorgraph(svg) without absolute size, set svgDom_"); + image_ = nullptr; if (useSkiaSvg_) { skiaDom_ = AceType::DynamicCast(imageObj_)->GetSkiaDom(); } else { @@ -266,35 +267,21 @@ void RosenRenderImage::CacheImageObject() } } -void RosenRenderImage::UpdatePixmap() +void RosenRenderImage::UpdatePixmap(const RefPtr& pixmap) { - if (pixmapRawPtr_ == DynamicCast(imageObj_)->GetRawPixelMapPtr()) { - LOGD("pixmapRawPtr_ not changed."); - imageObj_->ClearData(); - } else { - image_ = nullptr; - curSourceInfo_.Reset(); - rawImageSize_ = imageObj_->GetImageSize(); - rawImageSizeUpdated_ = true; - imageLoadingStatus_ = ImageLoadingStatus::LOAD_SUCCESS; - } + LOGD("update pixmap"); + imageObj_ = MakeRefPtr(pixmap); + image_ = nullptr; + curSourceInfo_.Reset(); + rawImageSize_ = imageObj_->GetImageSize(); + rawImageSizeUpdated_ = true; + imageLoadingStatus_ = ImageLoadingStatus::LOAD_SUCCESS; MarkNeedLayout(); } void RosenRenderImage::Update(const RefPtr& component) { RenderImage::Update(component); - auto pixmap = AceType::DynamicCast(component)->GetPixmap(); - if (pixmap != nullptr) { - LOGD("pixmap not null!"); - sourceInfo_.Reset(); - imageObj_ = MakeRefPtr(pixmap); - UpdatePixmap(); - return; - } else { - LOGD("pixmap is null!"); - pixmapRawPtr_ = nullptr; - } // curImageSrc represents the picture currently shown and imageSrc represents next picture to be shown imageLoadingStatus_ = (sourceInfo_ != curSourceInfo_) ? ImageLoadingStatus::UPDATING : imageLoadingStatus_; UpdateRenderAltImage(component); @@ -332,15 +319,40 @@ void RosenRenderImage::FetchImageObject() return; } rawImageSizeUpdated_ = false; - SrcType srcType = ImageLoader::ResolveURI(sourceInfo_.GetSrc()); - if (srcType != SrcType::MEMORY) { - bool syncMode = context->IsBuildingFirstPage() && frontend->GetType() == FrontendType::JS_CARD; - ImageProvider::FetchImageObject(sourceInfo_, imageObjSuccessCallback_, uploadSuccessCallback_, failedCallback_, - GetContext(), syncMode, useSkiaSvg_, autoResize_, renderTaskHolder_, onPostBackgroundTask_); - return; + SrcType srcType = sourceInfo_.GetSrcType(); + switch (srcType) { + case SrcType::PIXMAP: { + UpdatePixmap(sourceInfo_.GetPixmap()); + break; + } + case SrcType::MEMORY: { + UpdateSharedMemoryImage(context); + break; + } + default: { + bool syncMode = context->IsBuildingFirstPage() && + frontend->GetType() == FrontendType::JS_CARD && + sourceInfo_.GetSrcType() != SrcType::NETWORK; + ImageProvider::FetchImageObject( + sourceInfo_, + imageObjSuccessCallback_, + uploadSuccessCallback_, + failedCallback_, + GetContext(), + syncMode, + useSkiaSvg_, + autoResize_, + renderTaskHolder_, + onPostBackgroundTask_); + break; + } } +} + +void RosenRenderImage::UpdateSharedMemoryImage(const RefPtr& context) +{ auto sharedImageManager = context->GetSharedImageManager(); - if (sharedImageManager && srcType == SrcType::MEMORY) { + if (sharedImageManager) { if (sharedImageManager->IsResourceToReload(ImageLoader::RemovePathHead(sourceInfo_.GetSrc()))) { // This case means that the imageSrc to load is a memory image and its data is not ready. // If run [GetImageSize] here, there will be an unexpected [OnLoadFail] callback from [ImageProvider]. @@ -396,8 +408,6 @@ void RosenRenderImage::ProcessPixmapForPaint() imageObj_->ClearData(); return; } - pixmapRawPtr_ = pixmap->GetRawPixelMapPtr(); - imageObj_->ClearData(); FireLoadEvent(rawImageSize_); renderAltImage_ = nullptr; } @@ -464,7 +474,7 @@ void RosenRenderImage::Paint(RenderContext& context, const Offset& offset) renderAltImage_->SetDirectPaint(directPaint_); renderAltImage_->RenderWithContext(context, offset); } - if (sourceInfo_.IsValid()) { + if (sourceInfo_.GetSrcType() != SrcType::PIXMAP) { UpLoadImageDataForPaint(); } auto canvas = static_cast(&context)->GetCanvas(); @@ -1011,7 +1021,9 @@ bool RosenRenderImage::RetryLoading() sourceInfo_.ToString().c_str()); return false; } - bool syncMode = context->IsBuildingFirstPage() && frontend->GetType() == FrontendType::JS_CARD; + bool syncMode = context->IsBuildingFirstPage() && + frontend->GetType() == FrontendType::JS_CARD && + sourceInfo_.GetSrcType() != SrcType::NETWORK; ImageProvider::FetchImageObject(sourceInfo_, imageObjSuccessCallback_, uploadSuccessCallback_, failedCallback_, GetContext(), syncMode, useSkiaSvg_, autoResize_, renderTaskHolder_, onPostBackgroundTask_); LOGW("Retry loading time: %{public}d, triggered by GetImageSize fail, imageSrc: %{private}s", retryCnt_, diff --git a/frameworks/core/components/image/rosen_render_image.h b/frameworks/core/components/image/rosen_render_image.h index e7ff2898..8994bc46 100644 --- a/frameworks/core/components/image/rosen_render_image.h +++ b/frameworks/core/components/image/rosen_render_image.h @@ -110,7 +110,8 @@ private: void PerformLayoutSvgCustom(); void CancelBackgroundTasks(); void CacheImageObject(); - void UpdatePixmap(); + void UpdatePixmap(const RefPtr& pixmap); + void UpdateSharedMemoryImage(const RefPtr& context); void ProcessPixmapForPaint(); sk_sp skiaDom_; diff --git a/frameworks/core/image/flutter_image_cache.cpp b/frameworks/core/image/flutter_image_cache.cpp index b98609b2..b9e43ea5 100644 --- a/frameworks/core/image/flutter_image_cache.cpp +++ b/frameworks/core/image/flutter_image_cache.cpp @@ -43,7 +43,7 @@ RefPtr FlutterImageCache::GetDataFromCacheFile(const std::strin LOGD("file : %{public}s cached found", filePath.c_str()); } auto cacheFileLoader = AceType::MakeRefPtr(); - auto data = cacheFileLoader->LoadImageData(std::string("file:/").append(filePath)); + auto data = cacheFileLoader->LoadImageData(ImageSourceInfo(std::string("file:/").append(filePath))); return data ? AceType::MakeRefPtr(data) : nullptr; } diff --git a/frameworks/core/image/image_loader.cpp b/frameworks/core/image/image_loader.cpp index 4ed9b914..8c341d53 100644 --- a/frameworks/core/image/image_loader.cpp +++ b/frameworks/core/image/image_loader.cpp @@ -51,18 +51,6 @@ char* realpath(const char* path, char* resolved_path) } #endif -bool IsValidBase64Head(const std::string& uri, const std::string& pattern) -{ - auto iter = uri.find_first_of(','); - if (iter == std::string::npos) { - LOGE("wrong base64 head format."); - return false; - } - std::string base64Head = uri.substr(0, iter); - std::regex regular(pattern); - return std::regex_match(base64Head, regular); -} - } // namespace void ImageLoader::CacheResizedImage(const sk_sp& image, const std::string& key) @@ -94,46 +82,9 @@ std::string ImageLoader::RemovePathHead(const std::string& uri) return std::string(); } -SrcType ImageLoader::ResolveURI(const std::string& uri) -{ - if (uri.empty()) { - return SrcType::UNSUPPORTED; - } - auto iter = uri.find_first_of(':'); - if (iter == std::string::npos) { - return SrcType::ASSET; - } - std::string head = uri.substr(0, iter); - std::transform(head.begin(), head.end(), head.begin(), [](unsigned char c) { return std::tolower(c); }); - if (head == "http" or head == "https") { - return SrcType::NETWORK; - } else if (head == "file") { - return SrcType::FILE; - } else if (head == "internal") { - return SrcType::INTERNAL; - } else if (head == "data") { - static constexpr char BASE64_PATTERN[] = "^data:image/(jpeg|jpg|png|ico|gif|bmp|webp);base64$"; - if (IsValidBase64Head(uri, BASE64_PATTERN)) { - return SrcType::BASE64; - } - return SrcType::UNSUPPORTED; - } else if (head == "memory") { - return SrcType::MEMORY; - } else if (head == "resource") { - return SrcType::RESOURCE; - } else if (head == "dataability") { - return SrcType::DATA_ABILITY; - } else { - return SrcType::UNSUPPORTED; - } -} - RefPtr ImageLoader::CreateImageLoader(const ImageSourceInfo& imageSourceInfo) { - if (imageSourceInfo.IsInternalResource()) { - return MakeRefPtr(imageSourceInfo.GetResourceId()); - } - SrcType srcType = ResolveURI(imageSourceInfo.GetSrc()); + SrcType srcType = imageSourceInfo.GetSrcType(); switch (srcType) { case SrcType::INTERNAL: case SrcType::FILE: { @@ -158,6 +109,9 @@ RefPtr ImageLoader::CreateImageLoader(const ImageSourceInfo& imageS LOGE("Image source type: shared memory. image data is not come from image loader."); return nullptr; } + case SrcType::RESOURCE_ID: { + return MakeRefPtr(); + } default: { LOGE("Image source type not supported!"); return nullptr; @@ -189,12 +143,13 @@ sk_sp ImageLoader::LoadDataFromCachedFile(const std::string& uri) return nullptr; } -sk_sp FileImageLoader::LoadImageData(const std::string& src, const WeakPtr context) +sk_sp FileImageLoader::LoadImageData( + const ImageSourceInfo& imageSourceInfo, const WeakPtr context) { LOGD("File Image!"); - bool isInternal = (ResolveURI(src) == SrcType::INTERNAL); + auto src = imageSourceInfo.GetSrc(); std::string filePath = RemovePathHead(src); - if (isInternal) { + if (imageSourceInfo.GetSrcType() == SrcType::INTERNAL) { // the internal source uri format is like "internal://app/imagename.png", the absolute path of which is like // "/data/data/{bundleName}/files/imagename.png" auto bundleName = AceApplicationInfo::GetInstance().GetPackageName(); @@ -210,7 +165,7 @@ sk_sp FileImageLoader::LoadImageData(const std::string& src, const WeakP .append(bundleName) .append("/files/") // infix of absolute path .append(filePath.substr(4)); // 4 is the length of "app/" from "internal://app/" - } + }\ if (filePath.length() > PATH_MAX) { LOGE("src path is too long"); return nullptr; @@ -229,8 +184,10 @@ sk_sp FileImageLoader::LoadImageData(const std::string& src, const WeakP return SkData::MakeFromFILE(file.get()); } -sk_sp DataProviderImageLoader::LoadImageData(const std::string& src, const WeakPtr context) +sk_sp DataProviderImageLoader::LoadImageData( + const ImageSourceInfo& imageSourceInfo, const WeakPtr context) { + auto src = imageSourceInfo.GetSrc(); auto skData = ImageLoader::LoadDataFromCachedFile(src); if (skData) { return skData; @@ -255,8 +212,10 @@ sk_sp DataProviderImageLoader::LoadImageData(const std::string& src, con return SkData::MakeWithCopy(imageData.data(), imageData.size()); } -sk_sp AssetImageLoader::LoadImageData(const std::string& src, const WeakPtr context) +sk_sp AssetImageLoader::LoadImageData( + const ImageSourceInfo& imageSourceInfo, const WeakPtr context) { + auto src = imageSourceInfo.GetSrc(); if (src.empty()) { LOGE("image src is empty"); return nullptr; @@ -319,8 +278,10 @@ std::string AssetImageLoader::LoadJsonData(const std::string& src, const WeakPtr return std::string((char *)assetData->GetData(), assetData->GetSize()); } -sk_sp NetworkImageLoader::LoadImageData(const std::string& uri, const WeakPtr context) +sk_sp NetworkImageLoader::LoadImageData( + const ImageSourceInfo& imageSourceInfo, const WeakPtr context) { + auto uri = imageSourceInfo.GetSrc(); // 1. find in cache file path. LOGD("Network Image!"); auto skData = ImageLoader::LoadDataFromCachedFile(uri); @@ -339,10 +300,12 @@ sk_sp NetworkImageLoader::LoadImageData(const std::string& uri, const We return SkData::MakeWithCopy(imageData.data(), imageData.size()); } -sk_sp InternalImageLoader::LoadImageData(const std::string& uri, const WeakPtr context) +sk_sp InternalImageLoader::LoadImageData( + const ImageSourceInfo& imageSourceInfo, const WeakPtr context) { size_t imageSize = 0; - const uint8_t* internalData = InternalResource::GetInstance().GetResource(resourceId_, imageSize); + const uint8_t* internalData = + InternalResource::GetInstance().GetResource(imageSourceInfo.GetResourceId(), imageSize); if (internalData == nullptr) { LOGE("data null, the resource id may be wrong."); return nullptr; @@ -350,11 +313,12 @@ sk_sp InternalImageLoader::LoadImageData(const std::string& uri, const W return SkData::MakeWithCopy(internalData, imageSize); } -sk_sp Base64ImageLoader::LoadImageData(const std::string& uri, const WeakPtr context) +sk_sp Base64ImageLoader::LoadImageData( + const ImageSourceInfo& imageSourceInfo, const WeakPtr context) { SkBase64 base64Decoder; size_t imageSize = 0; - std::string base64Code = GetBase64ImageCode(uri, imageSize); + std::string base64Code = GetBase64ImageCode(imageSourceInfo.GetSrc(), imageSize); SkBase64::Error error = base64Decoder.decode(base64Code.c_str(), base64Code.size()); if (error != SkBase64::kNoError) { LOGE("error base64 image code!"); @@ -431,8 +395,10 @@ bool ResourceImageLoader::GetResourceId(const std::string& uri, const RefPtr ResourceImageLoader::LoadImageData(const std::string& uri, const WeakPtr context) +sk_sp ResourceImageLoader::LoadImageData( + const ImageSourceInfo& imageSourceInfo, const WeakPtr context) { + auto uri = imageSourceInfo.GetSrc(); auto pipelineContext = context.Upgrade(); if (!pipelineContext) { LOGE("invalid pipeline context"); diff --git a/frameworks/core/image/image_loader.h b/frameworks/core/image/image_loader.h index f96358cf..32b16793 100644 --- a/frameworks/core/image/image_loader.h +++ b/frameworks/core/image/image_loader.h @@ -35,8 +35,9 @@ class ImageLoader : public virtual AceType { DECLARE_ACE_TYPE(ImageLoader, AceType); public: - virtual sk_sp LoadImageData(const std::string& src, const WeakPtr context = nullptr) = 0; - static SrcType ResolveURI(const std::string& uri); + virtual sk_sp LoadImageData( + const ImageSourceInfo& imageSourceInfo, const WeakPtr context = nullptr) = 0; + static std::string RemovePathHead(const std::string& uri); static RefPtr CreateImageLoader(const ImageSourceInfo& imageSourceInfo); static void CacheResizedImage(const sk_sp& image, const std::string& key); @@ -48,7 +49,8 @@ class FileImageLoader : public ImageLoader { public: FileImageLoader() = default; ~FileImageLoader() override = default; - sk_sp LoadImageData(const std::string& src, const WeakPtr context = nullptr) override; + sk_sp LoadImageData( + const ImageSourceInfo& imageSourceInfo, const WeakPtr context = nullptr) override; }; // data provider image loader. @@ -56,14 +58,16 @@ class DataProviderImageLoader : public ImageLoader { public: DataProviderImageLoader() = default; ~DataProviderImageLoader() override = default; - sk_sp LoadImageData(const std::string& src, const WeakPtr context = nullptr) override; + sk_sp LoadImageData( + const ImageSourceInfo& imageSourceInfo, const WeakPtr context = nullptr) override; }; class AssetImageLoader final : public ImageLoader { public: - explicit AssetImageLoader() = default; + AssetImageLoader() = default; ~AssetImageLoader() override = default; - sk_sp LoadImageData(const std::string& src, const WeakPtr context = nullptr) override; + sk_sp LoadImageData( + const ImageSourceInfo& imageSourceInfo, const WeakPtr context = nullptr) override; std::string LoadJsonData(const std::string& src, const WeakPtr context = nullptr); }; @@ -72,17 +76,16 @@ class NetworkImageLoader final : public ImageLoader { public: NetworkImageLoader() = default; ~NetworkImageLoader() override = default; - sk_sp LoadImageData(const std::string& uri, const WeakPtr context = nullptr) override; + sk_sp LoadImageData( + const ImageSourceInfo& imageSourceInfo, const WeakPtr context = nullptr) override; }; class InternalImageLoader final : public ImageLoader { public: - explicit InternalImageLoader(InternalResource::ResourceId resourceId) : resourceId_(resourceId) {} + InternalImageLoader() = default; ~InternalImageLoader() override = default; - sk_sp LoadImageData(const std::string& uri, const WeakPtr context = nullptr) override; - -private: - InternalResource::ResourceId resourceId_; + sk_sp LoadImageData( + const ImageSourceInfo& imageSourceInfo, const WeakPtr context = nullptr) override; }; class Base64ImageLoader final : public ImageLoader { @@ -91,26 +94,22 @@ public: ~Base64ImageLoader() override = default; static std::string GetBase64ImageCode(const std::string& uri, size_t& imagSize); static size_t GetBase64ImageSize(const std::string& code); - sk_sp LoadImageData(const std::string& uri, const WeakPtr context = nullptr) override; + sk_sp LoadImageData( + const ImageSourceInfo& imageSourceInfo, const WeakPtr context = nullptr) override; }; class ResourceImageLoader final : public ImageLoader { public: ResourceImageLoader() = default; ~ResourceImageLoader() override = default; - sk_sp LoadImageData(const std::string& src, const WeakPtr context = nullptr) override; + sk_sp LoadImageData( + const ImageSourceInfo& imageSourceInfo, const WeakPtr context = nullptr) override; private: bool GetResourceId(const std::string& uri, const RefPtr& themeContants, uint32_t& resId) const; bool GetResourceId(const std::string& uri, const RefPtr& themeContants, std::string& path) const; }; -class FileCacheImageLoader final : public FileImageLoader { -public: - FileCacheImageLoader() = default; - ~FileCacheImageLoader() override = default; -}; - } // namespace OHOS::Ace #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_IMAGE_IMAGE_LOADER_H \ No newline at end of file diff --git a/frameworks/core/image/image_provider.cpp b/frameworks/core/image/image_provider.cpp index 094ae058..60434bde 100644 --- a/frameworks/core/image/image_provider.cpp +++ b/frameworks/core/image/image_provider.cpp @@ -145,7 +145,7 @@ sk_sp ImageProvider::LoadImageRawData( LOGE("imageLoader create failed. imageInfo: %{private}s", imageInfo.ToString().c_str()); return nullptr; } - auto data = imageLoader->LoadImageData(imageInfo.GetSrc(), context); + auto data = imageLoader->LoadImageData(imageInfo, context); if (data && imageCache) { // cache sk data. imageCache->CacheImageData(imageInfo.GetSrc(), AceType::MakeRefPtr(data)); @@ -171,12 +171,13 @@ void ImageProvider::GetSVGImageDOMAsyncFromSrc( if (!taskExecutor) { return; } - auto imageLoader = ImageLoader::CreateImageLoader(ImageSourceInfo(src)); + ImageSourceInfo info(src); + auto imageLoader = ImageLoader::CreateImageLoader(info); if (!imageLoader) { LOGE("load image failed when create image loader. src: %{private}s", src.c_str()); return; } - auto imageData = imageLoader->LoadImageData(src, context); + auto imageData = imageLoader->LoadImageData(info, context); if (imageData) { const auto svgStream = std::make_unique(std::move(imageData)); if (svgStream) { @@ -376,8 +377,9 @@ sk_sp ImageProvider::GetSkImage( const WeakPtr context, Size targetSize) { - auto imageLoader = ImageLoader::CreateImageLoader(ImageSourceInfo(src)); - auto imageSkData = imageLoader->LoadImageData(src, context); + ImageSourceInfo info(src); + auto imageLoader = ImageLoader::CreateImageLoader(info); + auto imageSkData = imageLoader->LoadImageData(info, context); if (!imageSkData) { LOGE("fetch data failed. src: %{private}s", src.c_str()); return nullptr; diff --git a/frameworks/core/image/image_source_info.cpp b/frameworks/core/image/image_source_info.cpp index f57756c0..98d729af 100644 --- a/frameworks/core/image/image_source_info.cpp +++ b/frameworks/core/image/image_source_info.cpp @@ -15,6 +15,9 @@ #include "core/image/image_source_info.h" +#include +#include "base/log/log.h" + namespace OHOS::Ace { bool ImageSourceInfo::IsSVGSource(const std::string& src, InternalResource::ResourceId resourceId) @@ -25,9 +28,99 @@ bool ImageSourceInfo::IsSVGSource(const std::string& src, InternalResource::Reso resourceId < InternalResource::ResourceId::SVG_END); } +bool ImageSourceInfo::IsValidBase64Head(const std::string& uri, const std::string& pattern) +{ + auto iter = uri.find_first_of(','); + if (iter == std::string::npos) { + LOGE("wrong base64 head format."); + return false; + } + std::string base64Head = uri.substr(0, iter); + std::regex regular(pattern); + return std::regex_match(base64Head, regular); +} + +SrcType ImageSourceInfo::ResolveURIType(const std::string& uri) +{ + if (uri.empty()) { + return SrcType::UNSUPPORTED; + } + auto iter = uri.find_first_of(':'); + if (iter == std::string::npos) { + return SrcType::ASSET; + } + std::string head = uri.substr(0, iter); + std::transform(head.begin(), head.end(), head.begin(), [](unsigned char c) { return std::tolower(c); }); + if (head == "http" || head == "https") { + return SrcType::NETWORK; + } else if (head == "file") { + return SrcType::FILE; + } else if (head == "internal") { + return SrcType::INTERNAL; + } else if (head == "data") { + static constexpr char BASE64_PATTERN[] = "^data:image/(jpeg|jpg|png|ico|gif|bmp|webp);base64$"; + if (IsValidBase64Head(uri, BASE64_PATTERN)) { + return SrcType::BASE64; + } + return SrcType::UNSUPPORTED; + } else if (head == "memory") { + return SrcType::MEMORY; + } else if (head == "resource") { + return SrcType::RESOURCE; + } else if (head == "dataability") { + return SrcType::DATA_ABILITY; + } else { + return SrcType::UNSUPPORTED; + } +} + +ImageSourceInfo::ImageSourceInfo( + const std::string& imageSrc, + Dimension width, + Dimension height, + InternalResource::ResourceId resourceId, + const RefPtr& pixmap) + : src_(imageSrc), + sourceWidth_(width), + sourceHeight_(height), + resourceId_(resourceId), + pixmap_(pixmap), + isSvg_(IsSVGSource(src_, resourceId_)), + srcType_(ResolveSrcType()) +{ + // count how many source set. + int32_t count = 0; + if (!src_.empty()) { + ++count; + } + if (resourceId_ != InternalResource::ResourceId::NO_ID) { + ++count; + } + if (pixmap != nullptr) { + ++count; + } + if (count > 1) { + LOGW("multi image source set, only one will be load."); + } +} + +SrcType ImageSourceInfo::ResolveSrcType() const +{ + if (pixmap_) { + return SrcType::PIXMAP; + } + if (!src_.empty()) { + return ResolveURIType(src_); + } + if (resourceId_ != InternalResource::ResourceId::NO_ID) { + return SrcType::RESOURCE_ID; + } + return SrcType::UNSUPPORTED; +} + void ImageSourceInfo::SetFillColor(const Color& color) { fillColor_.emplace(color.GetValue()); } -} // namespace OHOS::Ace \ No newline at end of file +} // namespace OHOS::Ace diff --git a/frameworks/core/image/image_source_info.h b/frameworks/core/image/image_source_info.h index bda1b2d2..cb507330 100644 --- a/frameworks/core/image/image_source_info.h +++ b/frameworks/core/image/image_source_info.h @@ -20,31 +20,33 @@ #include "base/geometry/dimension.h" #include "base/geometry/size.h" +#include "base/image/pixel_map.h" #include "base/resource/internal_resource.h" +#include "core/components/common/layout/constants.h" #include "core/components/common/properties/color.h" namespace OHOS::Ace { - class ImageSourceInfo { public: static bool IsSVGSource(const std::string& imageSrc, InternalResource::ResourceId resourceId); - ImageSourceInfo() = default; + static SrcType ResolveURIType(const std::string& uri); + static bool IsValidBase64Head(const std::string& uri, const std::string& pattern); + explicit ImageSourceInfo( const std::string& imageSrc, Dimension width = Dimension(-1), Dimension height = Dimension(-1), - InternalResource::ResourceId resourceId = InternalResource::ResourceId::NO_ID) - : src_(imageSrc), - sourceWidth_(width), - sourceHeight_(height), - resourceId_(resourceId), - isSvg_(IsSVGSource(src_, resourceId_)) - {} + InternalResource::ResourceId resourceId = InternalResource::ResourceId::NO_ID, + const RefPtr& pixmap = nullptr); + + ImageSourceInfo() = default; ~ImageSourceInfo() = default; bool operator==(const ImageSourceInfo& info) const { - return src_ == info.src_ && + return ((!pixmap_ && !info.pixmap_) || + (pixmap_ && info.pixmap_ && pixmap_->GetModifyId() == info.pixmap_->GetModifyId())) && + src_ == info.src_ && resourceId_ == info.resourceId_ && sourceWidth_ == info.sourceWidth_ && sourceHeight_ == info.sourceHeight_ && @@ -53,7 +55,10 @@ public: bool operator!=(const ImageSourceInfo& info) const { - return src_ != info.src_ || + return (!pixmap_ && info.pixmap_) || + (pixmap_ && !info.pixmap_) || + (pixmap_ && info.pixmap_ && pixmap_->GetModifyId() != info.pixmap_->GetModifyId()) || + src_ != info.src_ || resourceId_ != info.resourceId_ || sourceWidth_ != info.sourceWidth_ || sourceHeight_ != info.sourceHeight_ || @@ -66,6 +71,7 @@ public: resourceId_ = InternalResource::ResourceId::NO_ID; isSvg_ = IsSVGSource(src_, resourceId_); fillColor_ = fillColor; + pixmap_ = nullptr; } const std::string& GetSrc() const @@ -73,12 +79,13 @@ public: return src_; } - void SetResourceId(InternalResource::ResourceId id) + void SetResourceId(InternalResource::ResourceId id, std::optional fillColor = std::nullopt) { resourceId_ = id; src_.clear(); isSvg_ = IsSVGSource(src_, resourceId_); - fillColor_.reset(); + fillColor_ = fillColor; + pixmap_ = nullptr; } InternalResource::ResourceId GetResourceId() const @@ -88,13 +95,14 @@ public: bool IsInternalResource() const { - return src_.empty() && resourceId_ != InternalResource::ResourceId::NO_ID; + return src_.empty() && resourceId_ != InternalResource::ResourceId::NO_ID && !pixmap_; } bool IsValid() const { return (src_.empty() && resourceId_ != InternalResource::ResourceId::NO_ID) || - (!src_.empty() && resourceId_ == InternalResource::ResourceId::NO_ID); + (!src_.empty() && resourceId_ == InternalResource::ResourceId::NO_ID) || + pixmap_; } bool IsSvg() const @@ -102,6 +110,16 @@ public: return isSvg_; } + bool IsPixmap() const + { + return pixmap_ != nullptr; + } + + SrcType GetSrcType() const + { + return srcType_; + } + std::string ToString() const { if (!src_.empty()) { @@ -109,6 +127,9 @@ public: std::string("h") + std::to_string(sourceHeight_.Value()); } else if (resourceId_ != InternalResource::ResourceId::NO_ID) { return std::string("internal resource id: ") + std::to_string(static_cast(resourceId_)); + } else if (pixmap_) { + return std::string("pixmapID: ") + pixmap_->GetId() + + std::string(" -> modifyID: ") + pixmap_->GetModifyId(); } else { return std::string("empty source"); } @@ -138,6 +159,7 @@ public: resourceId_ = InternalResource::ResourceId::NO_ID; isSvg_ = false; fillColor_.reset(); + pixmap_ = nullptr; } void SetFillColor(const Color& color); @@ -147,15 +169,26 @@ public: return fillColor_; } + const RefPtr& GetPixmap() const + { + return pixmap_; + } + private: + SrcType ResolveSrcType() const; + std::string src_; Dimension sourceWidth_ = Dimension(-1); Dimension sourceHeight_ = Dimension(-1); InternalResource::ResourceId resourceId_ = InternalResource::ResourceId::NO_ID; + RefPtr pixmap_; bool isSvg_ = false; // only Svg will set it. std::optional fillColor_; + + // image source type for example:FILE, ASSET, NETWORK, MEMORY, BASE64, INTERNAL, RESOURCE or DATA_ABILITY, + SrcType srcType_ = SrcType::UNSUPPORTED; }; } // namespace OHOS::Ace