mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-14 12:04:29 +00:00
loaders: Pass mimetype to picture::load
* loaders: Pass mimetype to picture::load Added mimetype attribute to enfaster loading using a proper loader. @Changed api: Picture::load(const char* data, uint32_t size, const std::string& mimeType, bool copy = false) @issue: #571
This commit is contained in:
parent
0e98809f15
commit
cff8815404
13 changed files with 81 additions and 31 deletions
22
inc/thorvg.h
22
inc/thorvg.h
|
@ -1012,11 +1012,29 @@ public:
|
|||
* @retval Result::NonSupport When trying to load a file with an unknown extension.
|
||||
* @retval Result::Unknown If an error occurs at a later stage.
|
||||
*
|
||||
* @note: This api supports only SVG format
|
||||
* @warning: you have responsibility to release the @p data memory if the @p copy is true
|
||||
*
|
||||
* @deprecated This method will go away next release.
|
||||
* @see load(data, size, mimeType, copy)
|
||||
*/
|
||||
Result load(const char* data, uint32_t size, bool copy = false) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Loads a picture data from a memory block of a given size.
|
||||
*
|
||||
* @param[in] data A pointer to a memory location where the content of the picture file is stored.
|
||||
* @param[in] size The size in bytes of the memory occupied by the @p data.
|
||||
* @param[in] mimetype Mimetype or extension of data such as "jpg", "jpeg", "svg", "svg+xml", "png", etc. If empty string or unknown, loaders will be tried one by one.
|
||||
* @param[in] copy Decides whether the data should be copied into the engine local buffer.
|
||||
*
|
||||
* @retval Result::Success When succeed.
|
||||
* @retval Result::InvalidArguments In case no data are provided or the @p size is zero or less.
|
||||
* @retval Result::NonSupport When trying to load a file with an unknown extension.
|
||||
* @retval Result::Unknown If an error occurs at a later stage.
|
||||
*
|
||||
* @warning: you have responsibility to release the @p data memory if the @p copy is true
|
||||
*/
|
||||
Result load(const char* data, uint32_t size, bool copy = false) noexcept;
|
||||
Result load(const char* data, uint32_t size, const std::string& mimeType, bool copy = false) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Resize the picture content with the given width and height.
|
||||
|
|
|
@ -1676,6 +1676,7 @@ TVG_EXPORT Tvg_Result tvg_picture_load_raw(Tvg_Paint* paint, uint32_t *data, uin
|
|||
* \param[in] paint Tvg_Paint pointer
|
||||
* \param[in] data raw data pointer
|
||||
* \param[in] size of data
|
||||
* \param[in] mimetype mimetype of data
|
||||
* \param[in] copy Decides whether the data should be copied into the local buffer
|
||||
*
|
||||
* \return Tvg_Result return value
|
||||
|
@ -1684,7 +1685,7 @@ TVG_EXPORT Tvg_Result tvg_picture_load_raw(Tvg_Paint* paint, uint32_t *data, uin
|
|||
*
|
||||
* \warning Please do not use it, this API is not official one. It can be modified in the next version.
|
||||
*/
|
||||
TVG_EXPORT Tvg_Result tvg_picture_load_data(Tvg_Paint* paint, const char *data, uint32_t size, bool copy);
|
||||
TVG_EXPORT Tvg_Result tvg_picture_load_data(Tvg_Paint* paint, const char *data, uint32_t size, const char *mimetype, bool copy);
|
||||
|
||||
|
||||
/*!
|
||||
|
|
|
@ -463,10 +463,10 @@ TVG_EXPORT Tvg_Result tvg_picture_load_raw(Tvg_Paint* paint, uint32_t *data, uin
|
|||
}
|
||||
|
||||
|
||||
TVG_EXPORT Tvg_Result tvg_picture_load_data(Tvg_Paint* paint, const char *data, uint32_t size, bool copy)
|
||||
TVG_EXPORT Tvg_Result tvg_picture_load_data(Tvg_Paint* paint, const char *data, uint32_t size, const char *mimetype, bool copy)
|
||||
{
|
||||
if (!paint) return TVG_RESULT_INVALID_ARGUMENT;
|
||||
return (Tvg_Result) reinterpret_cast<Picture*>(paint)->load(data, size, copy);
|
||||
return (Tvg_Result) reinterpret_cast<Picture*>(paint)->load(data, size, mimetype ? mimetype : "", copy);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -57,8 +57,8 @@ void tvgDrawCmds(tvg::Canvas* canvas)
|
|||
file.close();
|
||||
|
||||
auto picture = tvg::Picture::gen();
|
||||
if (picture->load(data, size, true) != tvg::Result::Success) {
|
||||
cout << "Couldnt load JPG file from data." << endl;
|
||||
if (picture->load(data, size, "jpg", true) != tvg::Result::Success) {
|
||||
cout << "Couldn't load JPG file from data." << endl;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -57,8 +57,8 @@ void tvgDrawCmds(tvg::Canvas* canvas)
|
|||
file.close();
|
||||
|
||||
auto picture = tvg::Picture::gen();
|
||||
if (picture->load(data, size, true) != tvg::Result::Success) {
|
||||
cout << "Couldnt load PNG file from data." << endl;
|
||||
if (picture->load(data, size, "png", true) != tvg::Result::Success) {
|
||||
cout << "Couldn't load PNG file from data." << endl;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ void tvgDrawCmds(tvg::Canvas* canvas)
|
|||
if (canvas->push(move(shape)) != tvg::Result::Success) return;
|
||||
|
||||
auto picture = tvg::Picture::gen();
|
||||
if (picture->load(svg, strlen(svg)) != tvg::Result::Success) return;
|
||||
if (picture->load(svg, strlen(svg), "svg") != tvg::Result::Success) return;
|
||||
|
||||
picture->size(WIDTH, HEIGHT);
|
||||
|
||||
|
|
|
@ -158,9 +158,33 @@ shared_ptr<LoadModule> LoaderMgr::loader(const string& path, bool* invalid)
|
|||
}
|
||||
|
||||
|
||||
shared_ptr<LoadModule> LoaderMgr::loader(const char* data, uint32_t size, bool copy)
|
||||
shared_ptr<LoadModule> LoaderMgr::loader(const char* data, uint32_t size, const string& mimeType, bool copy)
|
||||
{
|
||||
FileType filetype = FileType::Unknown;
|
||||
if (!mimeType.empty()) {
|
||||
if (mimeType == "tvg") filetype = FileType::Tvg;
|
||||
else if (mimeType == "svg") filetype = FileType::Svg;
|
||||
else if (mimeType == "svg+xml") filetype = FileType::Svg;
|
||||
else if (mimeType == "raw") filetype = FileType::Raw;
|
||||
else if (mimeType == "png") filetype = FileType::Png;
|
||||
else if (mimeType == "jpg") filetype = FileType::Jpg;
|
||||
else if (mimeType == "jpeg") filetype = FileType::Jpg;
|
||||
else TVGLOG("LOADER", "Provided unknown mimetype \"%s\".", mimeType.c_str());
|
||||
|
||||
if (filetype != FileType::Unknown) {
|
||||
auto loader = _find(static_cast<FileType>(filetype));
|
||||
if (loader) {
|
||||
if (loader->open(data, size, copy)) return shared_ptr<LoadModule>(loader);
|
||||
else {
|
||||
TVGLOG("LOADER", "Provided mimetype \"%s\" (filetype=%d) seems incorrect. Will try other types.", mimeType.c_str(), static_cast<int>(filetype));
|
||||
delete(loader);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < static_cast<int>(FileType::Unknown); i++) {
|
||||
if (static_cast<FileType>(i) == filetype) continue;
|
||||
auto loader = _find(static_cast<FileType>(i));
|
||||
if (loader) {
|
||||
if (loader->open(data, size, copy)) return shared_ptr<LoadModule>(loader);
|
||||
|
|
|
@ -29,7 +29,7 @@ struct LoaderMgr
|
|||
static bool init();
|
||||
static bool term();
|
||||
static shared_ptr<LoadModule> loader(const string& path, bool* invalid);
|
||||
static shared_ptr<LoadModule> loader(const char* data, uint32_t size, bool copy);
|
||||
static shared_ptr<LoadModule> loader(const char* data, uint32_t size, const string& mimeType, bool copy);
|
||||
static shared_ptr<LoadModule> loader(const uint32_t* data, uint32_t w, uint32_t h, bool copy);
|
||||
};
|
||||
|
||||
|
|
|
@ -53,11 +53,16 @@ Result Picture::load(const std::string& path) noexcept
|
|||
}
|
||||
|
||||
|
||||
Result Picture::load(const char* data, uint32_t size, bool copy) noexcept
|
||||
Result Picture::load(const char* data, uint32_t size, const string& mimeType, bool copy) noexcept
|
||||
{
|
||||
if (!data || size <= 0) return Result::InvalidArguments;
|
||||
|
||||
return pImpl->load(data, size, copy);
|
||||
return pImpl->load(data, size, mimeType, copy);
|
||||
}
|
||||
|
||||
Result Picture::load(const char* data, uint32_t size, bool copy) noexcept
|
||||
{
|
||||
return load(data, size, "", copy);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -173,10 +173,10 @@ struct Picture::Impl
|
|||
return Result::Success;
|
||||
}
|
||||
|
||||
Result load(const char* data, uint32_t size, bool copy)
|
||||
Result load(const char* data, uint32_t size, const string& mimeType, bool copy)
|
||||
{
|
||||
if (loader) loader->close();
|
||||
loader = LoaderMgr::loader(data, size, copy);
|
||||
loader = LoaderMgr::loader(data, size, mimeType, copy);
|
||||
if (!loader) return Result::NonSupport;
|
||||
if (!loader->read()) return Result::Unknown;
|
||||
w = loader->w;
|
||||
|
|
|
@ -396,7 +396,7 @@ static constexpr struct
|
|||
};
|
||||
|
||||
|
||||
static bool _isValidImageMimeTypeAndEncoding(const char** href, imageMimeTypeEncoding* encoding) {
|
||||
static bool _isValidImageMimeTypeAndEncoding(const char** href, const char** mimetype, imageMimeTypeEncoding* encoding) {
|
||||
if (strncmp(*href, "image/", sizeof("image/") - 1)) return false; //not allowed mime type
|
||||
*href += sizeof("image/") - 1;
|
||||
|
||||
|
@ -406,6 +406,7 @@ static bool _isValidImageMimeTypeAndEncoding(const char** href, imageMimeTypeEnc
|
|||
for (unsigned int i = 0; i < sizeof(imageMimeTypes) / sizeof(imageMimeTypes[0]); i++) {
|
||||
if (!strncmp(*href, imageMimeTypes[i].name, imageMimeTypes[i].sz - 1)) {
|
||||
*href += imageMimeTypes[i].sz - 1;
|
||||
*mimetype = imageMimeTypes[i].name;
|
||||
|
||||
while (**href && **href != ',') {
|
||||
while (**href && **href != ';') ++(*href);
|
||||
|
@ -448,14 +449,15 @@ static unique_ptr<Picture> _imageBuildHelper(SvgNode* node, float vx, float vy,
|
|||
const char* href = (*node->node.image.href).c_str();
|
||||
if (!strncmp(href, "data:", sizeof("data:") - 1)) {
|
||||
href += sizeof("data:") - 1;
|
||||
const char* mimetype;
|
||||
imageMimeTypeEncoding encoding;
|
||||
if (!_isValidImageMimeTypeAndEncoding(&href, &encoding)) return nullptr; //not allowed mime type or encoding
|
||||
if (!_isValidImageMimeTypeAndEncoding(&href, &mimetype, &encoding)) return nullptr; //not allowed mime type or encoding
|
||||
if (encoding == imageMimeTypeEncoding::base64) {
|
||||
string decoded = svgUtilBase64Decode(href);
|
||||
if (picture->load(decoded.c_str(), decoded.size(), true) != Result::Success) return nullptr;
|
||||
if (picture->load(decoded.c_str(), decoded.size(), mimetype, true) != Result::Success) return nullptr;
|
||||
} else {
|
||||
string decoded = svgUtilURLDecode(href);
|
||||
if (picture->load(decoded.c_str(), decoded.size(), true) != Result::Success) return nullptr;
|
||||
if (picture->load(decoded.c_str(), decoded.size(), mimetype, true) != Result::Success) return nullptr;
|
||||
}
|
||||
} else {
|
||||
if (!strncmp(href, "file://", sizeof("file://") - 1)) href += sizeof("file://") - 1;
|
||||
|
|
|
@ -53,12 +53,12 @@ TEST_CASE("Load Svg Data in Picture", "[capiPicture]")
|
|||
REQUIRE(picture);
|
||||
|
||||
//Negative
|
||||
REQUIRE(tvg_picture_load_data(nullptr, svg, strlen(svg), true) == TVG_RESULT_INVALID_ARGUMENT);
|
||||
REQUIRE(tvg_picture_load_data(picture, nullptr, strlen(svg), true) == TVG_RESULT_INVALID_ARGUMENT);
|
||||
REQUIRE(tvg_picture_load_data(picture, svg, 0, true) == TVG_RESULT_INVALID_ARGUMENT);
|
||||
REQUIRE(tvg_picture_load_data(nullptr, svg, strlen(svg), nullptr, true) == TVG_RESULT_INVALID_ARGUMENT);
|
||||
REQUIRE(tvg_picture_load_data(picture, nullptr, strlen(svg), "", true) == TVG_RESULT_INVALID_ARGUMENT);
|
||||
REQUIRE(tvg_picture_load_data(picture, svg, 0, "", true) == TVG_RESULT_INVALID_ARGUMENT);
|
||||
|
||||
//Positive
|
||||
REQUIRE(tvg_picture_load_data(picture, svg, strlen(svg), false) == TVG_RESULT_SUCCESS);
|
||||
REQUIRE(tvg_picture_load_data(picture, svg, strlen(svg), "svg", false) == TVG_RESULT_SUCCESS);
|
||||
|
||||
//Verify Size
|
||||
float w, h;
|
||||
|
|
|
@ -51,11 +51,11 @@ TEST_CASE("Load SVG Data", "[tvgPicture]")
|
|||
REQUIRE(picture);
|
||||
|
||||
//Negative cases
|
||||
REQUIRE(picture->load(nullptr, 100) == Result::InvalidArguments);
|
||||
REQUIRE(picture->load(svg, 0) == Result::InvalidArguments);
|
||||
REQUIRE(picture->load(nullptr, 100, "") == Result::InvalidArguments);
|
||||
REQUIRE(picture->load(svg, 0, "") == Result::InvalidArguments);
|
||||
|
||||
//Positive cases
|
||||
REQUIRE(picture->load(svg, strlen(svg)) == Result::Success);
|
||||
REQUIRE(picture->load(svg, strlen(svg), "svg") == Result::Success);
|
||||
|
||||
float w, h;
|
||||
REQUIRE(picture->size(&w, &h) == Result::Success);
|
||||
|
@ -125,8 +125,8 @@ TEST_CASE("Load PNG file from data", "[tvgPicture]")
|
|||
file.read(data, size);
|
||||
file.close();
|
||||
|
||||
REQUIRE(picture->load(data, size, false) == Result::Success);
|
||||
REQUIRE(picture->load(data, size, true) == Result::Success);
|
||||
REQUIRE(picture->load(data, size, "", false) == Result::Success);
|
||||
REQUIRE(picture->load(data, size, "png", true) == Result::Success);
|
||||
|
||||
float w, h;
|
||||
REQUIRE(picture->size(&w, &h) == Result::Success);
|
||||
|
@ -169,8 +169,8 @@ TEST_CASE("Load JPG file from data", "[tvgPicture]")
|
|||
file.read(data, size);
|
||||
file.close();
|
||||
|
||||
REQUIRE(picture->load(data, size, false) == Result::Success);
|
||||
REQUIRE(picture->load(data, size, true) == Result::Success);
|
||||
REQUIRE(picture->load(data, size, "", false) == Result::Success);
|
||||
REQUIRE(picture->load(data, size, "jpg", true) == Result::Success);
|
||||
|
||||
float w, h;
|
||||
REQUIRE(picture->size(&w, &h) == Result::Success);
|
||||
|
|
Loading…
Add table
Reference in a new issue