mirror of
https://github.com/thorvg/thorvg.git
synced 2025-07-26 08:09:14 +00:00
tvg_format: force to check for compatibility by version comparision.
tvg file stores the version info of thorvg when it's generated, in order to compare it with the runtime thorvg version when it's loaded. For this, thorvg builds up the current version of symbol on the initilaization step, that can be referred by the tvg loader.
This commit is contained in:
parent
19b11277a0
commit
a042e771e4
8 changed files with 97 additions and 65 deletions
|
@ -10,6 +10,8 @@ add_project_arguments('-DEXAMPLE_DIR="@0@/src/examples/images"'.format(meson.cur
|
||||||
'-DTEST_DIR="@0@/test/images"'.format(meson.current_source_dir()),
|
'-DTEST_DIR="@0@/test/images"'.format(meson.current_source_dir()),
|
||||||
language : 'cpp')
|
language : 'cpp')
|
||||||
|
|
||||||
|
config_h.set_quoted('THORVG_VERSION_STRING', meson.project_version())
|
||||||
|
|
||||||
if get_option('engines').contains('sw') == true
|
if get_option('engines').contains('sw') == true
|
||||||
config_h.set10('THORVG_SW_RASTER_SUPPORT', true)
|
config_h.set10('THORVG_SW_RASTER_SUPPORT', true)
|
||||||
endif
|
endif
|
||||||
|
|
|
@ -56,4 +56,6 @@ enum class FileType { Tvg = 0, Svg, Raw, Png, Jpg, Unknown };
|
||||||
#define TVGLOG(...)
|
#define TVGLOG(...)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
uint16_t THORVG_VERSION_NUMBER();
|
||||||
|
|
||||||
#endif //_TVG_COMMON_H_
|
#endif //_TVG_COMMON_H_
|
|
@ -37,6 +37,39 @@
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
|
||||||
static int _initCnt = 0;
|
static int _initCnt = 0;
|
||||||
|
static uint16_t _version = 0;
|
||||||
|
|
||||||
|
|
||||||
|
static bool _buildVersionInfo()
|
||||||
|
{
|
||||||
|
auto SRC = THORVG_VERSION_STRING; //ex) 0.3.99
|
||||||
|
auto p = SRC;
|
||||||
|
const char* x;
|
||||||
|
|
||||||
|
char major[3];
|
||||||
|
x = strchr(p, '.');
|
||||||
|
if (!x) return false;
|
||||||
|
strncpy(major, p, x - p);
|
||||||
|
p = x + 1;
|
||||||
|
|
||||||
|
char minor[3];
|
||||||
|
x = strchr(p, '.');
|
||||||
|
if (!x) return false;
|
||||||
|
strncpy(minor, p, x - p);
|
||||||
|
p = x + 1;
|
||||||
|
|
||||||
|
char micro[3];
|
||||||
|
x = SRC + strlen(THORVG_VERSION_STRING);
|
||||||
|
if (!x) return false;
|
||||||
|
strncpy(micro, p, x - p);
|
||||||
|
|
||||||
|
char sum[7];
|
||||||
|
snprintf(sum, sizeof(sum), "%s%s%s", major, minor, micro);
|
||||||
|
|
||||||
|
_version = atoi(sum);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
@ -65,6 +98,8 @@ Result Initializer::init(CanvasEngine engine, uint32_t threads) noexcept
|
||||||
|
|
||||||
if (_initCnt++ > 0) return Result::Success;
|
if (_initCnt++ > 0) return Result::Success;
|
||||||
|
|
||||||
|
if (!_buildVersionInfo()) return Result::Unknown;
|
||||||
|
|
||||||
if (!LoaderMgr::init()) return Result::Unknown;
|
if (!LoaderMgr::init()) return Result::Unknown;
|
||||||
|
|
||||||
TaskScheduler::init(threads);
|
TaskScheduler::init(threads);
|
||||||
|
@ -103,3 +138,9 @@ Result Initializer::term(CanvasEngine engine) noexcept
|
||||||
|
|
||||||
return Result::Success;
|
return Result::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint16_t THORVG_VERSION_NUMBER()
|
||||||
|
{
|
||||||
|
return _version;
|
||||||
|
}
|
||||||
|
|
|
@ -28,10 +28,6 @@
|
||||||
/* Internal Class Implementation */
|
/* Internal Class Implementation */
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
|
||||||
#define SIZE(A) sizeof(A)
|
|
||||||
#define READ_UI32(dst, src) memcpy(dst, (src), sizeof(uint32_t))
|
|
||||||
#define READ_FLOAT(dst, src) memcpy(dst, (src), sizeof(float))
|
|
||||||
|
|
||||||
struct TvgBinBlock
|
struct TvgBinBlock
|
||||||
{
|
{
|
||||||
TvgBinTag type;
|
TvgBinTag type;
|
||||||
|
@ -64,29 +60,6 @@ static TvgBinBlock _readBlock(const char *ptr)
|
||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool _readTvgHeader(const char **ptr, float* w, float* h)
|
|
||||||
{
|
|
||||||
if (!*ptr) return false;
|
|
||||||
|
|
||||||
//Sign phase, always TVG_HEADER_SIGNATURE is declared
|
|
||||||
if (memcmp(*ptr, TVG_HEADER_SIGNATURE, TVG_HEADER_SIGNATURE_LENGTH)) return false;
|
|
||||||
*ptr += TVG_HEADER_SIGNATURE_LENGTH;
|
|
||||||
|
|
||||||
//Version number, declared in TVG_HEADER_VERSION
|
|
||||||
if (memcmp(*ptr, TVG_HEADER_VERSION, TVG_HEADER_VERSION_LENGTH)) return false;
|
|
||||||
*ptr += TVG_HEADER_VERSION_LENGTH;
|
|
||||||
|
|
||||||
//View width
|
|
||||||
if (w) READ_FLOAT(w, *ptr);
|
|
||||||
*ptr += SIZE(float);
|
|
||||||
|
|
||||||
//View height
|
|
||||||
if (h) READ_FLOAT(h, *ptr);
|
|
||||||
*ptr += SIZE(float);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static bool _parseCmpTarget(const char *ptr, const char *end, Paint *paint)
|
static bool _parseCmpTarget(const char *ptr, const char *end, Paint *paint)
|
||||||
{
|
{
|
||||||
|
@ -492,22 +465,8 @@ static Paint* _parsePaint(TvgBinBlock baseBlock)
|
||||||
/* External Class Implementation */
|
/* External Class Implementation */
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
|
||||||
bool tvgValidateData(const char *ptr, uint32_t size, float* w, float* h)
|
unique_ptr<Scene> tvgLoadData(const char *ptr, const char* end)
|
||||||
{
|
{
|
||||||
auto end = ptr + size;
|
|
||||||
if (!_readTvgHeader(&ptr, w, h) || ptr >= end) return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
unique_ptr<Scene> tvgLoadData(const char *ptr, uint32_t size)
|
|
||||||
{
|
|
||||||
auto end = ptr + size;
|
|
||||||
|
|
||||||
if (!_readTvgHeader(&ptr, nullptr, nullptr) || ptr >= end) {
|
|
||||||
TVGLOG("TVG", "Invalid TVG Data!");
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto scene = Scene::gen();
|
auto scene = Scene::gen();
|
||||||
if (!scene) return nullptr;
|
if (!scene) return nullptr;
|
||||||
|
|
||||||
|
@ -519,4 +478,4 @@ unique_ptr<Scene> tvgLoadData(const char *ptr, uint32_t size)
|
||||||
}
|
}
|
||||||
|
|
||||||
return move(scene);
|
return move(scene);
|
||||||
}
|
}
|
|
@ -26,7 +26,10 @@
|
||||||
#include "tvgCommon.h"
|
#include "tvgCommon.h"
|
||||||
#include "tvgBinaryDesc.h"
|
#include "tvgBinaryDesc.h"
|
||||||
|
|
||||||
bool tvgValidateData(const char *ptr, uint32_t size, float* w, float* h);
|
#define SIZE(A) sizeof(A)
|
||||||
unique_ptr<Scene> tvgLoadData(const char *ptr, uint32_t size);
|
#define READ_UI32(dst, src) memcpy(dst, (src), sizeof(uint32_t))
|
||||||
|
#define READ_FLOAT(dst, src) memcpy(dst, (src), sizeof(float))
|
||||||
|
|
||||||
|
unique_ptr<Scene> tvgLoadData(const char* ptr, const char* end);
|
||||||
|
|
||||||
#endif //_TVG_TVG_LOAD_PARSER_H_
|
#endif //_TVG_TVG_LOAD_PARSER_H_
|
||||||
|
|
|
@ -34,13 +34,40 @@
|
||||||
void TvgLoader::clear()
|
void TvgLoader::clear()
|
||||||
{
|
{
|
||||||
if (copy) free((char*)data);
|
if (copy) free((char*)data);
|
||||||
data = nullptr;
|
ptr = data = nullptr;
|
||||||
pointer = nullptr;
|
|
||||||
size = 0;
|
size = 0;
|
||||||
copy = false;
|
copy = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* WARNING: Header format shall not change! */
|
||||||
|
bool TvgLoader::readHeader()
|
||||||
|
{
|
||||||
|
if (!ptr) return false;
|
||||||
|
|
||||||
|
//1. Signature
|
||||||
|
if (memcmp(ptr, TVG_HEADER_SIGNATURE, TVG_HEADER_SIGNATURE_LENGTH)) return false;
|
||||||
|
ptr += TVG_HEADER_SIGNATURE_LENGTH;
|
||||||
|
|
||||||
|
//2. Version
|
||||||
|
char version[TVG_HEADER_VERSION_LENGTH];
|
||||||
|
memcpy(version, ptr, TVG_HEADER_VERSION_LENGTH);
|
||||||
|
ptr += TVG_HEADER_VERSION_LENGTH;
|
||||||
|
this->version = atoi(version);
|
||||||
|
if (this->version > THORVG_VERSION_NUMBER()) {
|
||||||
|
TVGLOG("TVG", "This TVG file expects a higher version(%d) of ThorVG symbol!, Current ThorVG(%d)", this->version, THORVG_VERSION_NUMBER());
|
||||||
|
}
|
||||||
|
|
||||||
|
//3. View Size
|
||||||
|
READ_FLOAT(&w, ptr);
|
||||||
|
ptr += SIZE(float);
|
||||||
|
READ_FLOAT(&h, ptr);
|
||||||
|
ptr += SIZE(float);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
/* External Class Implementation */
|
/* External Class Implementation */
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
@ -80,9 +107,9 @@ bool TvgLoader::open(const string &path)
|
||||||
|
|
||||||
f.close();
|
f.close();
|
||||||
|
|
||||||
pointer = data;
|
ptr = data;
|
||||||
|
|
||||||
return tvgValidateData(pointer, size, &w, &h);
|
return readHeader();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -96,11 +123,11 @@ bool TvgLoader::open(const char *data, uint32_t size, bool copy)
|
||||||
memcpy((char*)this->data, data, size);
|
memcpy((char*)this->data, data, size);
|
||||||
} else this->data = data;
|
} else this->data = data;
|
||||||
|
|
||||||
this->pointer = this->data;
|
this->ptr = this->data;
|
||||||
this->size = size;
|
this->size = size;
|
||||||
this->copy = copy;
|
this->copy = copy;
|
||||||
|
|
||||||
return tvgValidateData(pointer, size, &w, &h);
|
return readHeader();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -129,7 +156,7 @@ bool TvgLoader::resize(Paint* paint, float w, float h)
|
||||||
|
|
||||||
bool TvgLoader::read()
|
bool TvgLoader::read()
|
||||||
{
|
{
|
||||||
if (!pointer || size == 0) return false;
|
if (!ptr || size == 0) return false;
|
||||||
|
|
||||||
TaskScheduler::request(this);
|
TaskScheduler::request(this);
|
||||||
|
|
||||||
|
@ -148,7 +175,7 @@ bool TvgLoader::close()
|
||||||
void TvgLoader::run(unsigned tid)
|
void TvgLoader::run(unsigned tid)
|
||||||
{
|
{
|
||||||
if (root) root.reset();
|
if (root) root.reset();
|
||||||
root = tvgLoadData(pointer, size);
|
root = tvgLoadData(ptr, data + size);
|
||||||
if (!root) clear();
|
if (!root) clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -158,4 +185,4 @@ unique_ptr<Paint> TvgLoader::paint()
|
||||||
this->done();
|
this->done();
|
||||||
if (root) return move(root);
|
if (root) return move(root);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,8 +29,9 @@ class TvgLoader : public LoadModule, public Task
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
const char* data = nullptr;
|
const char* data = nullptr;
|
||||||
const char* pointer = nullptr;
|
const char* ptr = nullptr;
|
||||||
uint32_t size = 0;
|
uint32_t size = 0;
|
||||||
|
uint16_t version = 0;
|
||||||
unique_ptr<Scene> root = nullptr;
|
unique_ptr<Scene> root = nullptr;
|
||||||
bool copy = false;
|
bool copy = false;
|
||||||
|
|
||||||
|
@ -45,6 +46,7 @@ public:
|
||||||
unique_ptr<Paint> paint() override;
|
unique_ptr<Paint> paint() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
bool readHeader();
|
||||||
void run(unsigned tid) override;
|
void run(unsigned tid) override;
|
||||||
void clear();
|
void clear();
|
||||||
};
|
};
|
||||||
|
|
|
@ -52,29 +52,26 @@ bool TvgSaver::flushTo(const std::string& path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* WARNING: Header format shall not changed! */
|
||||||
bool TvgSaver::writeHeader()
|
bool TvgSaver::writeHeader()
|
||||||
{
|
{
|
||||||
buffer.grow(TVG_HEADER_SIGNATURE_LENGTH + TVG_HEADER_VERSION_LENGTH);
|
buffer.grow(TVG_HEADER_SIGNATURE_LENGTH + TVG_HEADER_VERSION_LENGTH);
|
||||||
|
|
||||||
|
//1. Signature
|
||||||
auto ptr = buffer.ptr();
|
auto ptr = buffer.ptr();
|
||||||
memcpy(ptr, TVG_HEADER_SIGNATURE, TVG_HEADER_SIGNATURE_LENGTH);
|
memcpy(ptr, TVG_HEADER_SIGNATURE, TVG_HEADER_SIGNATURE_LENGTH);
|
||||||
ptr += TVG_HEADER_SIGNATURE_LENGTH;
|
ptr += TVG_HEADER_SIGNATURE_LENGTH;
|
||||||
|
|
||||||
|
//2. Version
|
||||||
memcpy(ptr, TVG_HEADER_VERSION, TVG_HEADER_VERSION_LENGTH);
|
memcpy(ptr, TVG_HEADER_VERSION, TVG_HEADER_VERSION_LENGTH);
|
||||||
ptr += TVG_HEADER_VERSION_LENGTH;
|
ptr += TVG_HEADER_VERSION_LENGTH;
|
||||||
|
|
||||||
buffer.count += (TVG_HEADER_SIGNATURE_LENGTH + TVG_HEADER_VERSION_LENGTH);
|
buffer.count += (TVG_HEADER_SIGNATURE_LENGTH + TVG_HEADER_VERSION_LENGTH);
|
||||||
|
|
||||||
return true;
|
//3. View Size
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool TvgSaver::writeViewSize()
|
|
||||||
{
|
|
||||||
float var[2];
|
float var[2];
|
||||||
paint->bounds(nullptr, nullptr, &var[0], &var[1]);
|
paint->bounds(nullptr, nullptr, &var[0], &var[1]);
|
||||||
|
if (var[0] <= FLT_EPSILON || var[1] <= FLT_EPSILON) return false;
|
||||||
if (var[0] <= 0.0f || var[1] <= 0.0f) return false;
|
|
||||||
|
|
||||||
writeData(var, SIZE(var));
|
writeData(var, SIZE(var));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -413,7 +410,6 @@ TvgBinCounter TvgSaver::serialize(const Paint* paint)
|
||||||
void TvgSaver::run(unsigned tid)
|
void TvgSaver::run(unsigned tid)
|
||||||
{
|
{
|
||||||
if (!writeHeader()) return;
|
if (!writeHeader()) return;
|
||||||
if (!writeViewSize()) return;
|
|
||||||
if (serialize(paint) == 0) return;
|
if (serialize(paint) == 0) return;
|
||||||
if (!flushTo(path)) return;
|
if (!flushTo(path)) return;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue