image source info optimise

Signed-off-by: sunfei <sunfei.sun@huawei.com>
Change-Id:  If0cea31f5415c2162b8af01218becc2e0bb601d6
This commit is contained in:
lushi
2021-11-27 15:17:22 +08:00
committed by sunfei
parent b1cdd65251
commit e316545cc3
15 changed files with 319 additions and 186 deletions
+16
View File
@@ -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
+2
View File
@@ -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<Media::PixelMap> pixmap_;
+2
View File
@@ -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
@@ -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 {
@@ -187,6 +187,7 @@ void FlutterRenderImage::ImageObjReady(const RefPtr<ImageObject>& imageObj)
}
} else {
LOGI("image is vectorgraph(svg) without absolute size, set svgDom_");
image_ = nullptr;
if (useSkiaSvg_) {
skiaDom_ = AceType::DynamicCast<SvgSkiaImageObject>(imageObj_)->GetSkiaDom();
} else {
@@ -274,35 +275,21 @@ void FlutterRenderImage::CacheImageObject()
}
}
void FlutterRenderImage::UpdatePixmap()
void FlutterRenderImage::UpdatePixmap(const RefPtr<PixelMap>& pixmap)
{
if (pixmapRawPtr_ == DynamicCast<PixelMapImageObject>(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<PixelMapImageObject>(pixmap);
image_ = nullptr;
curSourceInfo_.Reset();
rawImageSize_ = imageObj_->GetImageSize();
rawImageSizeUpdated_ = true;
imageLoadingStatus_ = ImageLoadingStatus::LOAD_SUCCESS;
MarkNeedLayout();
}
void FlutterRenderImage::Update(const RefPtr<Component>& component)
{
RenderImage::Update(component);
auto pixmap = AceType::DynamicCast<ImageComponent>(component)->GetPixmap();
if (pixmap != nullptr) {
LOGD("pixmap not null!");
sourceInfo_.Reset();
imageObj_ = MakeRefPtr<PixelMapImageObject>(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<PipelineContext>& 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_,
@@ -141,7 +141,8 @@ private:
void PerformLayoutSvgCustom();
void CancelBackgroundTasks();
void CacheImageObject();
void UpdatePixmap();
void UpdatePixmap(const RefPtr<PixelMap>& pixmap);
void UpdateSharedMemoryImage(const RefPtr<PipelineContext>& context);
void ProcessPixmapForPaint();
sk_sp<SkSVGDOM> skiaDom_;
@@ -76,7 +76,8 @@ void RenderImage::Update(const RefPtr<Component>& 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());
@@ -180,6 +180,7 @@ void RosenRenderImage::ImageObjReady(const RefPtr<ImageObject>& imageObj)
}
} else {
LOGI("image is vectorgraph(svg) without absolute size, set svgDom_");
image_ = nullptr;
if (useSkiaSvg_) {
skiaDom_ = AceType::DynamicCast<SvgSkiaImageObject>(imageObj_)->GetSkiaDom();
} else {
@@ -266,35 +267,21 @@ void RosenRenderImage::CacheImageObject()
}
}
void RosenRenderImage::UpdatePixmap()
void RosenRenderImage::UpdatePixmap(const RefPtr<PixelMap>& pixmap)
{
if (pixmapRawPtr_ == DynamicCast<PixelMapImageObject>(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<PixelMapImageObject>(pixmap);
image_ = nullptr;
curSourceInfo_.Reset();
rawImageSize_ = imageObj_->GetImageSize();
rawImageSizeUpdated_ = true;
imageLoadingStatus_ = ImageLoadingStatus::LOAD_SUCCESS;
MarkNeedLayout();
}
void RosenRenderImage::Update(const RefPtr<Component>& component)
{
RenderImage::Update(component);
auto pixmap = AceType::DynamicCast<ImageComponent>(component)->GetPixmap();
if (pixmap != nullptr) {
LOGD("pixmap not null!");
sourceInfo_.Reset();
imageObj_ = MakeRefPtr<PixelMapImageObject>(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<PipelineContext>& 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<RosenRenderContext*>(&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_,
@@ -110,7 +110,8 @@ private:
void PerformLayoutSvgCustom();
void CancelBackgroundTasks();
void CacheImageObject();
void UpdatePixmap();
void UpdatePixmap(const RefPtr<PixelMap>& pixmap);
void UpdateSharedMemoryImage(const RefPtr<PipelineContext>& context);
void ProcessPixmapForPaint();
sk_sp<SkSVGDOM> skiaDom_;
@@ -43,7 +43,7 @@ RefPtr<CachedImageData> FlutterImageCache::GetDataFromCacheFile(const std::strin
LOGD("file : %{public}s cached found", filePath.c_str());
}
auto cacheFileLoader = AceType::MakeRefPtr<FileImageLoader>();
auto data = cacheFileLoader->LoadImageData(std::string("file:/").append(filePath));
auto data = cacheFileLoader->LoadImageData(ImageSourceInfo(std::string("file:/").append(filePath)));
return data ? AceType::MakeRefPtr<SkiaCachedImageData>(data) : nullptr;
}
+28 -62
View File
@@ -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<SkImage>& 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> ImageLoader::CreateImageLoader(const ImageSourceInfo& imageSourceInfo)
{
if (imageSourceInfo.IsInternalResource()) {
return MakeRefPtr<InternalImageLoader>(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> 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<InternalImageLoader>();
}
default: {
LOGE("Image source type not supported!");
return nullptr;
@@ -189,12 +143,13 @@ sk_sp<SkData> ImageLoader::LoadDataFromCachedFile(const std::string& uri)
return nullptr;
}
sk_sp<SkData> FileImageLoader::LoadImageData(const std::string& src, const WeakPtr<PipelineContext> context)
sk_sp<SkData> FileImageLoader::LoadImageData(
const ImageSourceInfo& imageSourceInfo, const WeakPtr<PipelineContext> 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<SkData> 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<SkData> FileImageLoader::LoadImageData(const std::string& src, const WeakP
return SkData::MakeFromFILE(file.get());
}
sk_sp<SkData> DataProviderImageLoader::LoadImageData(const std::string& src, const WeakPtr<PipelineContext> context)
sk_sp<SkData> DataProviderImageLoader::LoadImageData(
const ImageSourceInfo& imageSourceInfo, const WeakPtr<PipelineContext> context)
{
auto src = imageSourceInfo.GetSrc();
auto skData = ImageLoader::LoadDataFromCachedFile(src);
if (skData) {
return skData;
@@ -255,8 +212,10 @@ sk_sp<SkData> DataProviderImageLoader::LoadImageData(const std::string& src, con
return SkData::MakeWithCopy(imageData.data(), imageData.size());
}
sk_sp<SkData> AssetImageLoader::LoadImageData(const std::string& src, const WeakPtr<PipelineContext> context)
sk_sp<SkData> AssetImageLoader::LoadImageData(
const ImageSourceInfo& imageSourceInfo, const WeakPtr<PipelineContext> 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<SkData> NetworkImageLoader::LoadImageData(const std::string& uri, const WeakPtr<PipelineContext> context)
sk_sp<SkData> NetworkImageLoader::LoadImageData(
const ImageSourceInfo& imageSourceInfo, const WeakPtr<PipelineContext> 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<SkData> NetworkImageLoader::LoadImageData(const std::string& uri, const We
return SkData::MakeWithCopy(imageData.data(), imageData.size());
}
sk_sp<SkData> InternalImageLoader::LoadImageData(const std::string& uri, const WeakPtr<PipelineContext> context)
sk_sp<SkData> InternalImageLoader::LoadImageData(
const ImageSourceInfo& imageSourceInfo, const WeakPtr<PipelineContext> 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<SkData> InternalImageLoader::LoadImageData(const std::string& uri, const W
return SkData::MakeWithCopy(internalData, imageSize);
}
sk_sp<SkData> Base64ImageLoader::LoadImageData(const std::string& uri, const WeakPtr<PipelineContext> context)
sk_sp<SkData> Base64ImageLoader::LoadImageData(
const ImageSourceInfo& imageSourceInfo, const WeakPtr<PipelineContext> 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<The
return false;
}
sk_sp<SkData> ResourceImageLoader::LoadImageData(const std::string& uri, const WeakPtr<PipelineContext> context)
sk_sp<SkData> ResourceImageLoader::LoadImageData(
const ImageSourceInfo& imageSourceInfo, const WeakPtr<PipelineContext> context)
{
auto uri = imageSourceInfo.GetSrc();
auto pipelineContext = context.Upgrade();
if (!pipelineContext) {
LOGE("invalid pipeline context");
+19 -20
View File
@@ -35,8 +35,9 @@ class ImageLoader : public virtual AceType {
DECLARE_ACE_TYPE(ImageLoader, AceType);
public:
virtual sk_sp<SkData> LoadImageData(const std::string& src, const WeakPtr<PipelineContext> context = nullptr) = 0;
static SrcType ResolveURI(const std::string& uri);
virtual sk_sp<SkData> LoadImageData(
const ImageSourceInfo& imageSourceInfo, const WeakPtr<PipelineContext> context = nullptr) = 0;
static std::string RemovePathHead(const std::string& uri);
static RefPtr<ImageLoader> CreateImageLoader(const ImageSourceInfo& imageSourceInfo);
static void CacheResizedImage(const sk_sp<SkImage>& image, const std::string& key);
@@ -48,7 +49,8 @@ class FileImageLoader : public ImageLoader {
public:
FileImageLoader() = default;
~FileImageLoader() override = default;
sk_sp<SkData> LoadImageData(const std::string& src, const WeakPtr<PipelineContext> context = nullptr) override;
sk_sp<SkData> LoadImageData(
const ImageSourceInfo& imageSourceInfo, const WeakPtr<PipelineContext> context = nullptr) override;
};
// data provider image loader.
@@ -56,14 +58,16 @@ class DataProviderImageLoader : public ImageLoader {
public:
DataProviderImageLoader() = default;
~DataProviderImageLoader() override = default;
sk_sp<SkData> LoadImageData(const std::string& src, const WeakPtr<PipelineContext> context = nullptr) override;
sk_sp<SkData> LoadImageData(
const ImageSourceInfo& imageSourceInfo, const WeakPtr<PipelineContext> context = nullptr) override;
};
class AssetImageLoader final : public ImageLoader {
public:
explicit AssetImageLoader() = default;
AssetImageLoader() = default;
~AssetImageLoader() override = default;
sk_sp<SkData> LoadImageData(const std::string& src, const WeakPtr<PipelineContext> context = nullptr) override;
sk_sp<SkData> LoadImageData(
const ImageSourceInfo& imageSourceInfo, const WeakPtr<PipelineContext> context = nullptr) override;
std::string LoadJsonData(const std::string& src, const WeakPtr<PipelineContext> context = nullptr);
};
@@ -72,17 +76,16 @@ class NetworkImageLoader final : public ImageLoader {
public:
NetworkImageLoader() = default;
~NetworkImageLoader() override = default;
sk_sp<SkData> LoadImageData(const std::string& uri, const WeakPtr<PipelineContext> context = nullptr) override;
sk_sp<SkData> LoadImageData(
const ImageSourceInfo& imageSourceInfo, const WeakPtr<PipelineContext> context = nullptr) override;
};
class InternalImageLoader final : public ImageLoader {
public:
explicit InternalImageLoader(InternalResource::ResourceId resourceId) : resourceId_(resourceId) {}
InternalImageLoader() = default;
~InternalImageLoader() override = default;
sk_sp<SkData> LoadImageData(const std::string& uri, const WeakPtr<PipelineContext> context = nullptr) override;
private:
InternalResource::ResourceId resourceId_;
sk_sp<SkData> LoadImageData(
const ImageSourceInfo& imageSourceInfo, const WeakPtr<PipelineContext> 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<SkData> LoadImageData(const std::string& uri, const WeakPtr<PipelineContext> context = nullptr) override;
sk_sp<SkData> LoadImageData(
const ImageSourceInfo& imageSourceInfo, const WeakPtr<PipelineContext> context = nullptr) override;
};
class ResourceImageLoader final : public ImageLoader {
public:
ResourceImageLoader() = default;
~ResourceImageLoader() override = default;
sk_sp<SkData> LoadImageData(const std::string& src, const WeakPtr<PipelineContext> context = nullptr) override;
sk_sp<SkData> LoadImageData(
const ImageSourceInfo& imageSourceInfo, const WeakPtr<PipelineContext> context = nullptr) override;
private:
bool GetResourceId(const std::string& uri, const RefPtr<ThemeConstants>& themeContants, uint32_t& resId) const;
bool GetResourceId(const std::string& uri, const RefPtr<ThemeConstants>& 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
+7 -5
View File
@@ -145,7 +145,7 @@ sk_sp<SkData> 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<SkiaCachedImageData>(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<SkMemoryStream>(std::move(imageData));
if (svgStream) {
@@ -376,8 +377,9 @@ sk_sp<SkImage> ImageProvider::GetSkImage(
const WeakPtr<PipelineContext> 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;
+94 -1
View File
@@ -15,6 +15,9 @@
#include "core/image/image_source_info.h"
#include <regex>
#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<PixelMap>& 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
} // namespace OHOS::Ace
+48 -15
View File
@@ -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<PixelMap>& 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<Color> 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<int32_t>(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<PixelMap>& 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<PixelMap> pixmap_;
bool isSvg_ = false;
// only Svg will set it.
std::optional<Color> fillColor_;
// image source type for example:FILE, ASSET, NETWORK, MEMORY, BASE64, INTERNAL, RESOURCE or DATA_ABILITY,
SrcType srcType_ = SrcType::UNSUPPORTED;
};
} // namespace OHOS::Ace