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:
Michal Maciola 2021-08-05 04:02:26 +02:00 committed by GitHub
parent 0e98809f15
commit cff8815404
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 81 additions and 31 deletions

View file

@ -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.

View file

@ -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);
/*!

View file

@ -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);
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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);

View file

@ -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);

View file

@ -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);
};

View file

@ -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);
}

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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);