mirror of
https://github.com/thorvg/thorvg.git
synced 2025-07-25 07:39:02 +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()),
|
||||
language : 'cpp')
|
||||
|
||||
config_h.set_quoted('THORVG_VERSION_STRING', meson.project_version())
|
||||
|
||||
if get_option('engines').contains('sw') == true
|
||||
config_h.set10('THORVG_SW_RASTER_SUPPORT', true)
|
||||
endif
|
||||
|
|
|
@ -56,4 +56,6 @@ enum class FileType { Tvg = 0, Svg, Raw, Png, Jpg, Unknown };
|
|||
#define TVGLOG(...)
|
||||
#endif
|
||||
|
||||
uint16_t THORVG_VERSION_NUMBER();
|
||||
|
||||
#endif //_TVG_COMMON_H_
|
|
@ -37,6 +37,39 @@
|
|||
/************************************************************************/
|
||||
|
||||
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 (!_buildVersionInfo()) return Result::Unknown;
|
||||
|
||||
if (!LoaderMgr::init()) return Result::Unknown;
|
||||
|
||||
TaskScheduler::init(threads);
|
||||
|
@ -103,3 +138,9 @@ Result Initializer::term(CanvasEngine engine) noexcept
|
|||
|
||||
return Result::Success;
|
||||
}
|
||||
|
||||
|
||||
uint16_t THORVG_VERSION_NUMBER()
|
||||
{
|
||||
return _version;
|
||||
}
|
||||
|
|
|
@ -28,10 +28,6 @@
|
|||
/* 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
|
||||
{
|
||||
TvgBinTag type;
|
||||
|
@ -64,29 +60,6 @@ static TvgBinBlock _readBlock(const char *ptr)
|
|||
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)
|
||||
{
|
||||
|
@ -492,22 +465,8 @@ static Paint* _parsePaint(TvgBinBlock baseBlock)
|
|||
/* 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();
|
||||
if (!scene) return nullptr;
|
||||
|
||||
|
@ -519,4 +478,4 @@ unique_ptr<Scene> tvgLoadData(const char *ptr, uint32_t size)
|
|||
}
|
||||
|
||||
return move(scene);
|
||||
}
|
||||
}
|
|
@ -26,7 +26,10 @@
|
|||
#include "tvgCommon.h"
|
||||
#include "tvgBinaryDesc.h"
|
||||
|
||||
bool tvgValidateData(const char *ptr, uint32_t size, float* w, float* h);
|
||||
unique_ptr<Scene> tvgLoadData(const char *ptr, uint32_t size);
|
||||
#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))
|
||||
|
||||
unique_ptr<Scene> tvgLoadData(const char* ptr, const char* end);
|
||||
|
||||
#endif //_TVG_TVG_LOAD_PARSER_H_
|
||||
|
|
|
@ -34,13 +34,40 @@
|
|||
void TvgLoader::clear()
|
||||
{
|
||||
if (copy) free((char*)data);
|
||||
data = nullptr;
|
||||
pointer = nullptr;
|
||||
ptr = data = nullptr;
|
||||
size = 0;
|
||||
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 */
|
||||
/************************************************************************/
|
||||
|
@ -80,9 +107,9 @@ bool TvgLoader::open(const string &path)
|
|||
|
||||
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);
|
||||
} else this->data = data;
|
||||
|
||||
this->pointer = this->data;
|
||||
this->ptr = this->data;
|
||||
this->size = size;
|
||||
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()
|
||||
{
|
||||
if (!pointer || size == 0) return false;
|
||||
if (!ptr || size == 0) return false;
|
||||
|
||||
TaskScheduler::request(this);
|
||||
|
||||
|
@ -148,7 +175,7 @@ bool TvgLoader::close()
|
|||
void TvgLoader::run(unsigned tid)
|
||||
{
|
||||
if (root) root.reset();
|
||||
root = tvgLoadData(pointer, size);
|
||||
root = tvgLoadData(ptr, data + size);
|
||||
if (!root) clear();
|
||||
}
|
||||
|
||||
|
@ -158,4 +185,4 @@ unique_ptr<Paint> TvgLoader::paint()
|
|||
this->done();
|
||||
if (root) return move(root);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,8 +29,9 @@ class TvgLoader : public LoadModule, public Task
|
|||
{
|
||||
public:
|
||||
const char* data = nullptr;
|
||||
const char* pointer = nullptr;
|
||||
const char* ptr = nullptr;
|
||||
uint32_t size = 0;
|
||||
uint16_t version = 0;
|
||||
unique_ptr<Scene> root = nullptr;
|
||||
bool copy = false;
|
||||
|
||||
|
@ -45,6 +46,7 @@ public:
|
|||
unique_ptr<Paint> paint() override;
|
||||
|
||||
private:
|
||||
bool readHeader();
|
||||
void run(unsigned tid) override;
|
||||
void clear();
|
||||
};
|
||||
|
|
|
@ -52,29 +52,26 @@ bool TvgSaver::flushTo(const std::string& path)
|
|||
}
|
||||
|
||||
|
||||
/* WARNING: Header format shall not changed! */
|
||||
bool TvgSaver::writeHeader()
|
||||
{
|
||||
buffer.grow(TVG_HEADER_SIGNATURE_LENGTH + TVG_HEADER_VERSION_LENGTH);
|
||||
|
||||
//1. Signature
|
||||
auto ptr = buffer.ptr();
|
||||
memcpy(ptr, TVG_HEADER_SIGNATURE, TVG_HEADER_SIGNATURE_LENGTH);
|
||||
ptr += TVG_HEADER_SIGNATURE_LENGTH;
|
||||
|
||||
//2. Version
|
||||
memcpy(ptr, TVG_HEADER_VERSION, TVG_HEADER_VERSION_LENGTH);
|
||||
ptr += TVG_HEADER_VERSION_LENGTH;
|
||||
|
||||
buffer.count += (TVG_HEADER_SIGNATURE_LENGTH + TVG_HEADER_VERSION_LENGTH);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool TvgSaver::writeViewSize()
|
||||
{
|
||||
//3. View Size
|
||||
float var[2];
|
||||
paint->bounds(nullptr, nullptr, &var[0], &var[1]);
|
||||
|
||||
if (var[0] <= 0.0f || var[1] <= 0.0f) return false;
|
||||
|
||||
if (var[0] <= FLT_EPSILON || var[1] <= FLT_EPSILON) return false;
|
||||
writeData(var, SIZE(var));
|
||||
|
||||
return true;
|
||||
|
@ -413,7 +410,6 @@ TvgBinCounter TvgSaver::serialize(const Paint* paint)
|
|||
void TvgSaver::run(unsigned tid)
|
||||
{
|
||||
if (!writeHeader()) return;
|
||||
if (!writeViewSize()) return;
|
||||
if (serialize(paint) == 0) return;
|
||||
if (!flushTo(path)) return;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue