diff --git a/meson.build b/meson.build index 239ce518..9658bc3f 100644 --- a/meson.build +++ b/meson.build @@ -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 diff --git a/src/lib/tvgCommon.h b/src/lib/tvgCommon.h index e8dd0b80..9389156a 100644 --- a/src/lib/tvgCommon.h +++ b/src/lib/tvgCommon.h @@ -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_ \ No newline at end of file diff --git a/src/lib/tvgInitializer.cpp b/src/lib/tvgInitializer.cpp index e5d7750b..0b63cf3a 100644 --- a/src/lib/tvgInitializer.cpp +++ b/src/lib/tvgInitializer.cpp @@ -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; +} diff --git a/src/loaders/tvg/tvgTvgLoadParser.cpp b/src/loaders/tvg/tvgTvgLoadParser.cpp index 7979fb2f..62250b59 100644 --- a/src/loaders/tvg/tvgTvgLoadParser.cpp +++ b/src/loaders/tvg/tvgTvgLoadParser.cpp @@ -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 tvgLoadData(const char *ptr, const char* end) { - auto end = ptr + size; - if (!_readTvgHeader(&ptr, w, h) || ptr >= end) return false; - return true; -} - -unique_ptr 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 tvgLoadData(const char *ptr, uint32_t size) } return move(scene); -} +} \ No newline at end of file diff --git a/src/loaders/tvg/tvgTvgLoadParser.h b/src/loaders/tvg/tvgTvgLoadParser.h index 437670eb..3e2daf7c 100644 --- a/src/loaders/tvg/tvgTvgLoadParser.h +++ b/src/loaders/tvg/tvgTvgLoadParser.h @@ -26,7 +26,10 @@ #include "tvgCommon.h" #include "tvgBinaryDesc.h" -bool tvgValidateData(const char *ptr, uint32_t size, float* w, float* h); -unique_ptr 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 tvgLoadData(const char* ptr, const char* end); #endif //_TVG_TVG_LOAD_PARSER_H_ diff --git a/src/loaders/tvg/tvgTvgLoader.cpp b/src/loaders/tvg/tvgTvgLoader.cpp index 593187eb..00c31a81 100644 --- a/src/loaders/tvg/tvgTvgLoader.cpp +++ b/src/loaders/tvg/tvgTvgLoader.cpp @@ -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 TvgLoader::paint() this->done(); if (root) return move(root); return nullptr; -} \ No newline at end of file +} diff --git a/src/loaders/tvg/tvgTvgLoader.h b/src/loaders/tvg/tvgTvgLoader.h index c138ced4..d48e13be 100644 --- a/src/loaders/tvg/tvgTvgLoader.h +++ b/src/loaders/tvg/tvgTvgLoader.h @@ -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 root = nullptr; bool copy = false; @@ -45,6 +46,7 @@ public: unique_ptr paint() override; private: + bool readHeader(); void run(unsigned tid) override; void clear(); }; diff --git a/src/savers/tvg/tvgTvgSaver.cpp b/src/savers/tvg/tvgTvgSaver.cpp index e8e1a241..52de8d92 100644 --- a/src/savers/tvg/tvgTvgSaver.cpp +++ b/src/savers/tvg/tvgTvgSaver.cpp @@ -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; }