From 775850dbc3705eaa2cc735f67cbdc955003cb315 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Tue, 20 Jul 2021 15:48:15 +0900 Subject: [PATCH 01/16] tvg format: code refactoring #7 remove return type values. --- src/loaders/tvg/tvgTvgLoadParser.cpp | 133 ++++++++++++++++------------------- 1 file changed, 62 insertions(+), 71 deletions(-) diff --git a/src/loaders/tvg/tvgTvgLoadParser.cpp b/src/loaders/tvg/tvgTvgLoadParser.cpp index 0767b33..d6dc042 100644 --- a/src/loaders/tvg/tvgTvgLoadParser.cpp +++ b/src/loaders/tvg/tvgTvgLoadParser.cpp @@ -39,11 +39,8 @@ struct TvgBinBlock #define _read_tvg_ui32(dst, src) memcpy(dst, (src), sizeof(uint32_t)) #define _read_tvg_float(dst, src) memcpy(dst, (src), sizeof(float)) -enum class LoaderResult { Success = 0, InvalidType, SizeCorruption, MemoryCorruption, LogicalCorruption }; - static Paint* _parsePaint(TvgBinBlock block); - static bool _paintProperty(TvgBinBlock block) { switch (block.type) { @@ -82,13 +79,13 @@ static bool _readTvgHeader(const char **ptr) } -static LoaderResult _parseCmpTarget(const char *ptr, const char *end, Paint *paint) +static bool _parseCmpTarget(const char *ptr, const char *end, Paint *paint) { auto block = _readBlock(ptr); - if (block.end > end) return LoaderResult::SizeCorruption; + if (block.end > end) return false; - if (block.type != TVG_PAINT_CMP_METHOD_INDICATOR) return LoaderResult::LogicalCorruption; - if (block.length != sizeof(TvgFlag)) return LoaderResult::SizeCorruption; + if (block.type != TVG_PAINT_CMP_METHOD_INDICATOR) return false; + if (block.length != sizeof(TvgFlag)) return false; CompositeMethod cmpMethod; @@ -105,55 +102,55 @@ static LoaderResult _parseCmpTarget(const char *ptr, const char *end, Paint *pai cmpMethod = CompositeMethod::InvAlphaMask; break; } - default: return LoaderResult::LogicalCorruption; + default: return false; } ptr = block.end; auto cmpBlock = _readBlock(ptr); - if (cmpBlock.end > end) return LoaderResult::SizeCorruption; + if (cmpBlock.end > end) return false; paint->composite(unique_ptr(_parsePaint(cmpBlock)), cmpMethod); - return LoaderResult::Success; + return true; } -static LoaderResult _parsePaintProperty(TvgBinBlock block, Paint *paint) +static bool _parsePaintProperty(TvgBinBlock block, Paint *paint) { switch (block.type) { case TVG_PAINT_OPACITY_INDICATOR: { - if (block.length != sizeof(uint8_t)) return LoaderResult::SizeCorruption; + if (block.length != sizeof(uint8_t)) return false; paint->opacity(*block.data); - return LoaderResult::Success; + return true; } case TVG_PAINT_TRANSFORM_MATRIX_INDICATOR: { - if (block.length != sizeof(Matrix)) return LoaderResult::SizeCorruption; + if (block.length != sizeof(Matrix)) return false; Matrix matrix; memcpy(&matrix, block.data, sizeof(Matrix)); - if (paint->transform(matrix) != Result::Success) return LoaderResult::MemoryCorruption; - return LoaderResult::Success; + if (paint->transform(matrix) != Result::Success) return false; + return true; } case TVG_PAINT_CMP_TARGET_INDICATOR: { - if (block.length < TVG_INDICATOR_SIZE + BYTE_COUNTER_SIZE) return LoaderResult::SizeCorruption; + if (block.length < TVG_INDICATOR_SIZE + BYTE_COUNTER_SIZE) return false; return _parseCmpTarget(block.data, block.end, paint); } } - return LoaderResult::InvalidType; + return false; } -static LoaderResult _parseScene(TvgBinBlock block, Paint *paint) +static bool _parseScene(TvgBinBlock block, Paint *paint) { auto scene = static_cast(paint); switch (block.type) { case TVG_SCENE_FLAG_RESERVEDCNT: { - if (block.length != sizeof(uint32_t)) return LoaderResult::SizeCorruption; + if (block.length != sizeof(uint32_t)) return false; uint32_t reservedCnt; _read_tvg_ui32(&reservedCnt, block.data); scene->reserve(reservedCnt); - return LoaderResult::Success; + return true; } } @@ -161,14 +158,14 @@ static LoaderResult _parseScene(TvgBinBlock block, Paint *paint) if (auto paint = _parsePaint(block)) { scene->push(unique_ptr(paint)); - return LoaderResult::Success; + return true; } - return LoaderResult::InvalidType; + return false; } -static LoaderResult _parseShapePath(const char *ptr, const char *end, Shape *shape) +static bool _parseShapePath(const char *ptr, const char *end, Shape *shape) { //Shape Path uint32_t cmdCnt, ptsCnt; @@ -182,24 +179,24 @@ static LoaderResult _parseShapePath(const char *ptr, const char *end, Shape *sha const Point* pts = (Point*) ptr; ptr += sizeof(Point) * ptsCnt; - if (ptr > end) return LoaderResult::SizeCorruption; + if (ptr > end) return false; shape->appendPath(cmds, cmdCnt, pts, ptsCnt); - return LoaderResult::Success; + return true; } -static LoaderResult _parseShapeFill(const char *ptr, const char *end, Fill **fillOutside) +static bool _parseShapeFill(const char *ptr, const char *end, Fill **fillOutside) { unique_ptr fillGrad; while (ptr < end) { auto block = _readBlock(ptr); - if (block.end > end) return LoaderResult::SizeCorruption; + if (block.end > end) return false; switch (block.type) { case TVG_FILL_RADIAL_GRADIENT_INDICATOR: { - if (block.length != 3 * sizeof(float)) return LoaderResult::SizeCorruption; + if (block.length != 3 * sizeof(float)) return false; auto ptr = block.data; float x, y, radius; @@ -216,7 +213,7 @@ static LoaderResult _parseShapeFill(const char *ptr, const char *end, Fill **fil break; } case TVG_FILL_LINEAR_GRADIENT_INDICATOR: { - if (block.length != 4 * sizeof(float)) return LoaderResult::SizeCorruption; + if (block.length != 4 * sizeof(float)) return false; auto ptr = block.data; float x1, y1, x2, y2; @@ -235,8 +232,8 @@ static LoaderResult _parseShapeFill(const char *ptr, const char *end, Fill **fil break; } case TVG_FILL_FILLSPREAD_INDICATOR: { - if (!fillGrad) return LoaderResult::LogicalCorruption; - if (block.length != sizeof(TvgFlag)) return LoaderResult::SizeCorruption; + if (!fillGrad) return false; + if (block.length != sizeof(TvgFlag)) return false; switch (*block.data) { case TVG_FILL_FILLSPREAD_PAD_FLAG: { fillGrad->spread(FillSpread::Pad); @@ -254,10 +251,10 @@ static LoaderResult _parseShapeFill(const char *ptr, const char *end, Fill **fil break; } case TVG_FILL_COLORSTOPS_INDICATOR: { - if (!fillGrad) return LoaderResult::LogicalCorruption; - if (block.length == 0 || block.length & 0x07) return LoaderResult::SizeCorruption; + if (!fillGrad) return false; + if (block.length == 0 || block.length & 0x07) return false; uint32_t stopsCnt = block.length >> 3; // 8 bytes per ColorStop - if (stopsCnt > 1023) return LoaderResult::SizeCorruption; + if (stopsCnt > 1023) return false; Fill::ColorStop stops[stopsCnt]; auto p = block.data; for (uint32_t i = 0; i < stopsCnt; i++, p += 8) { @@ -274,11 +271,11 @@ static LoaderResult _parseShapeFill(const char *ptr, const char *end, Fill **fil ptr = block.end; } *fillOutside = fillGrad.release(); - return LoaderResult::Success; + return true; } -static LoaderResult _parseShapeStrokeDashPattern(const char *ptr, const char *end, Shape *shape) +static bool _parseShapeStrokeDashPattern(const char *ptr, const char *end, Shape *shape) { uint32_t dashPatternCnt; _read_tvg_ui32(&dashPatternCnt, ptr); @@ -286,22 +283,22 @@ static LoaderResult _parseShapeStrokeDashPattern(const char *ptr, const char *en const float* dashPattern = (float*) ptr; ptr += sizeof(float) * dashPatternCnt; - if (ptr > end) return LoaderResult::SizeCorruption; + if (ptr > end) return false; shape->stroke(dashPattern, dashPatternCnt); - return LoaderResult::Success; + return true; } -static LoaderResult _parseShapeStroke(const char *ptr, const char *end, Shape *shape) +static bool _parseShapeStroke(const char *ptr, const char *end, Shape *shape) { while (ptr < end) { auto block = _readBlock(ptr); - if (block.end > end) return LoaderResult::SizeCorruption; + if (block.end > end) return false; switch (block.type) { case TVG_SHAPE_STROKE_CAP_INDICATOR: { - if (block.length != sizeof(TvgFlag)) return LoaderResult::SizeCorruption; + if (block.length != sizeof(TvgFlag)) return false; switch (*block.data) { case TVG_SHAPE_STROKE_CAP_SQUARE_FLAG: shape->stroke(StrokeCap::Square); @@ -316,7 +313,7 @@ static LoaderResult _parseShapeStroke(const char *ptr, const char *end, Shape *s break; } case TVG_SHAPE_STROKE_JOIN_INDICATOR: { - if (block.length != sizeof(TvgFlag)) return LoaderResult::SizeCorruption; + if (block.length != sizeof(TvgFlag)) return false; switch (*block.data) { case TVG_SHAPE_STROKE_JOIN_BEVEL_FLAG: shape->stroke(StrokeJoin::Bevel); @@ -331,65 +328,60 @@ static LoaderResult _parseShapeStroke(const char *ptr, const char *end, Shape *s break; } case TVG_SHAPE_STROKE_WIDTH_INDICATOR: { - if (block.length != sizeof(float)) return LoaderResult::SizeCorruption; + if (block.length != sizeof(float)) return false; float width; _read_tvg_float(&width, block.data); shape->stroke(width); break; } case TVG_SHAPE_STROKE_COLOR_INDICATOR: { - if (block.length != 4) return LoaderResult::SizeCorruption; + if (block.length != 4) return false; shape->stroke(block.data[0], block.data[1], block.data[2], block.data[3]); break; } case TVG_SHAPE_STROKE_FILL_INDICATOR: { Fill* fill; - auto result = _parseShapeFill(block.data, block.end, &fill); - if (result != LoaderResult::Success) return result; + if (!_parseShapeFill(block.data, block.end, &fill)) return false; shape->stroke(unique_ptr < Fill > (fill)); break; } case TVG_SHAPE_STROKE_DASHPTRN_INDICATOR: { - auto result = _parseShapeStrokeDashPattern(block.data, block.end, shape); - if (result != LoaderResult::Success) return result; + if (!_parseShapeStrokeDashPattern(block.data, block.end, shape)) return false; break; } } ptr = block.end; } - return LoaderResult::Success; + return true; } -static LoaderResult _parseShape(TvgBinBlock block, Paint* paint) +static bool _parseShape(TvgBinBlock block, Paint* paint) { auto shape = static_cast(paint); switch (block.type) { case TVG_SHAPE_PATH_INDICATOR: { - auto result = _parseShapePath(block.data, block.end, shape); - if (result != LoaderResult::Success) return result; + if (!_parseShapePath(block.data, block.end, shape)) return false; break; } case TVG_SHAPE_STROKE_INDICATOR: { - auto result = _parseShapeStroke(block.data, block.end, shape); - if (result != LoaderResult::Success) return result; + if (!_parseShapeStroke(block.data, block.end, shape)) return false; break; } case TVG_SHAPE_FILL_INDICATOR: { Fill* fill; - auto result = _parseShapeFill(block.data, block.end, &fill); - if (result != LoaderResult::Success) return result; + if (!_parseShapeFill(block.data, block.end, &fill)) return false; shape->fill(unique_ptr < Fill > (fill)); break; } case TVG_SHAPE_COLOR_INDICATOR: { - if (block.length != 4) return LoaderResult::SizeCorruption; + if (block.length != 4) return false; shape->fill(block.data[0], block.data[1], block.data[2], block.data[3]); break; } case TVG_SHAPE_FILLRULE_INDICATOR: { - if (block.length != sizeof(TvgFlag)) return LoaderResult::SizeCorruption; + if (block.length != sizeof(TvgFlag)) return false; switch (*block.data) { case TVG_SHAPE_FILLRULE_WINDING_FLAG: shape->fill(FillRule::Winding); @@ -402,17 +394,17 @@ static LoaderResult _parseShape(TvgBinBlock block, Paint* paint) } default: return _parsePaintProperty(block, shape); } - return LoaderResult::Success; + return true; } -static LoaderResult _parsePicture(TvgBinBlock block, Paint* paint) +static bool _parsePicture(TvgBinBlock block, Paint* paint) { auto picture = static_cast(paint); switch (block.type) { case TVG_RAW_IMAGE_BEGIN_INDICATOR: { - if (block.length < 2 * sizeof(uint32_t)) return LoaderResult::SizeCorruption; + if (block.length < 2 * sizeof(uint32_t)) return false; auto ptr = block.data; uint32_t w, h; @@ -423,11 +415,10 @@ static LoaderResult _parsePicture(TvgBinBlock block, Paint* paint) ptr += sizeof(uint32_t); auto size = w * h * sizeof(uint32_t); - if (block.length != 2 * sizeof(uint32_t) + size) return LoaderResult::SizeCorruption; + if (block.length != 2 * sizeof(uint32_t) + size) return false; - auto pixels = (uint32_t*) ptr; - picture->load(pixels, w, h, true); - return LoaderResult::Success; + picture->load((uint32_t*) ptr, w, h, true); + return true; } } @@ -435,16 +426,16 @@ static LoaderResult _parsePicture(TvgBinBlock block, Paint* paint) if (auto paint = _parsePaint(block)) { picture->paint(unique_ptr(paint)); - return LoaderResult::Success; + return true; } - return LoaderResult::InvalidType; + return false; } static Paint* _parsePaint(TvgBinBlock baseBlock) { - LoaderResult (*parser)(TvgBinBlock, Paint*); + bool (*parser)(TvgBinBlock, Paint*); Paint *paint = nullptr; switch (baseBlock.type) { @@ -471,8 +462,8 @@ static Paint* _parsePaint(TvgBinBlock baseBlock) while (ptr < baseBlock.end) { auto block = _readBlock(ptr); if (block.end > baseBlock.end) return paint; - auto result = parser(block, paint); - if (result != LoaderResult::Success && result != LoaderResult::InvalidType) return paint; + //TODO: Do we need to clarify an invalid type case from the parsing failure? + if (!parser(block, paint)) return paint; ptr = block.end; } return paint; -- 2.7.4 From da142bfb08ab6167a200df1cdba41a35a636a0eb Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Tue, 20 Jul 2021 20:03:45 +0900 Subject: [PATCH 02/16] tvg format: code refactoring #8 Hide iterator APIs, simplify it as much as it's necessary. --- inc/thorvg.h | 50 ++++-------------------------------------------- src/lib/tvgCommon.h | 3 ++- src/lib/tvgPaint.cpp | 43 +---------------------------------------- src/lib/tvgPaint.h | 35 ++++++++++++++------------------- src/lib/tvgPictureImpl.h | 26 ++++++++++++++++++------- src/lib/tvgSaverImpl.h | 9 ++++++--- src/lib/tvgScene.cpp | 4 ++-- src/lib/tvgSceneImpl.h | 39 ++++++++++++++++++------------------- src/lib/tvgShapeImpl.h | 7 +------ 9 files changed, 68 insertions(+), 148 deletions(-) diff --git a/inc/thorvg.h b/inc/thorvg.h index a411e63..308a109 100644 --- a/inc/thorvg.h +++ b/inc/thorvg.h @@ -43,7 +43,9 @@ protected: \ #define _TVG_DECLARE_ACCESSOR() \ friend Canvas; \ friend Scene; \ - friend Picture + friend Picture; \ + friend Saver; + #define _TVG_DECALRE_IDENTIFIER() \ auto id() const { return _id; } \ @@ -57,6 +59,7 @@ class RenderMethod; class Scene; class Picture; class Canvas; +class Saver; /** * @defgroup ThorVG ThorVG @@ -300,51 +303,6 @@ public: uint8_t opacity() const noexcept; /** - * @brief Const forward iterator-like class enabling the iteration over the children nodes of the given paint. - * - * For the Scene-type Paint the children nodes represent the paints pushed into the Scene - the order of the children nodes is the same as the order as they were pushed. For the Picture-type Paint the child node is the read image in one of the supported formats. The Shape-type Paint doesn't have any child nodes. - * - * @BETA_API - */ - class Iterator - { - const Paint* parent; - const Paint* child; - - public: - Iterator (Paint* p = nullptr, Paint* c = nullptr); - const Paint& operator*() const; - Iterator& operator++(); - Iterator operator++(int); - friend bool operator!=(const Iterator& it1, const Iterator& it2) - { - return it1.child != it2.child; - }; - friend bool operator==(const Iterator& it1, const Iterator& it2) - { - return it1.child == it2.child; - }; - }; - - /** - * @brief Gets the iterator to the first child node. - * - * @return The iterator pointing to the first element of the children nodes of the given paint object. - * - * @BETA_API - */ - Iterator begin() const noexcept; - - /** - * @brief Gets the iterator to the past-the end child node. - * - * @return The iterator referring to the past-the-end element of the children nodes of the given paint object. - * - * @BETA_API - */ - Iterator end() const noexcept; - - /** * @brief Gets the composition target object and the composition method. * * @param[out] target The paint of the target object. diff --git a/src/lib/tvgCommon.h b/src/lib/tvgCommon.h index 6ef28b3..2fed7b3 100644 --- a/src/lib/tvgCommon.h +++ b/src/lib/tvgCommon.h @@ -45,4 +45,5 @@ using namespace tvg; #define TVG_UNUSED __attribute__ ((__unused__)) #endif -#endif //_TVG_COMMON_H_ + +#endif //_TVG_COMMON_H_ \ No newline at end of file diff --git a/src/lib/tvgPaint.cpp b/src/lib/tvgPaint.cpp index fc5c741..7c539fc 100644 --- a/src/lib/tvgPaint.cpp +++ b/src/lib/tvgPaint.cpp @@ -330,45 +330,4 @@ Result Paint::opacity(uint8_t o) noexcept uint8_t Paint::opacity() const noexcept { return pImpl->opacity; -} - - -Paint::Iterator Paint::begin() const noexcept -{ - return pImpl->begin(); -} - - -Paint::Iterator Paint::end() const noexcept -{ - return Paint::Iterator(); -} - - -Paint::Iterator::Iterator(Paint* p, Paint* c) : parent{p}, child{c} -{ -} - - -const Paint& Paint::Iterator::operator*() const -{ - return *child; -} - - -Paint::Iterator& Paint::Iterator::operator++() //prefix -{ - const Paint* nextChild = nullptr; - if (parent) nextChild = parent->pImpl->next(child); - child = nextChild; - - return *this; -} - - -Paint::Iterator Paint::Iterator::operator++(int) //postfix -{ - Iterator tmp = *this; - ++*this; - return tmp; -} +} \ No newline at end of file diff --git a/src/lib/tvgPaint.h b/src/lib/tvgPaint.h index f0b5c6c..6ce5d1f 100644 --- a/src/lib/tvgPaint.h +++ b/src/lib/tvgPaint.h @@ -27,6 +27,12 @@ namespace tvg { + struct Iterator + { + virtual ~Iterator() {} + virtual const Paint* next() = 0; + }; + struct StrategyMethod { virtual ~StrategyMethod() {} @@ -37,8 +43,7 @@ namespace tvg virtual bool bounds(float* x, float* y, float* w, float* h) const = 0; virtual RenderRegion bounds(RenderMethod& renderer) const = 0; virtual Paint* duplicate() = 0; - virtual Paint::Iterator begin() = 0; - virtual const Paint* next(const Paint* p) = 0; + virtual Iterator* iterator() = 0; }; struct Paint::Impl @@ -98,6 +103,11 @@ namespace tvg return smethod->dispose(renderer); } + Iterator* iterator() + { + return smethod->iterator(); + } + bool composite(Paint* target, CompositeMethod method) { if ((!target && method != CompositeMethod::None) || (target && method == CompositeMethod::None)) return false; @@ -113,17 +123,6 @@ namespace tvg void* update(RenderMethod& renderer, const RenderTransform* pTransform, uint32_t opacity, Array& clips, uint32_t pFlag); bool render(RenderMethod& renderer); Paint* duplicate(); - - Paint::Iterator begin() - { - return smethod->begin(); - } - - const Paint* next(const Paint* p) - { - return smethod->next(p); - } - }; @@ -165,16 +164,10 @@ namespace tvg return inst->duplicate(); } - Paint::Iterator begin() override + Iterator* iterator() override { - return inst->begin(); + return inst->iterator(); } - - const Paint* next(const Paint* p) override - { - return inst->next(p); - } - }; } diff --git a/src/lib/tvgPictureImpl.h b/src/lib/tvgPictureImpl.h index 1178afb..40e48e9 100644 --- a/src/lib/tvgPictureImpl.h +++ b/src/lib/tvgPictureImpl.h @@ -30,6 +30,23 @@ /* Internal Class Implementation */ /************************************************************************/ +struct PictureIterator : Iterator +{ + Paint* paint = nullptr; + + PictureIterator(Paint* p) : paint(p) + { + } + + const Paint* next() override + { + auto ret = paint; + paint = nullptr; + return ret; + } +}; + + struct Picture::Impl { shared_ptr loader = nullptr; @@ -219,15 +236,10 @@ struct Picture::Impl return ret.release(); } - Paint::Iterator begin() + Iterator* iterator() { reload(); - return Paint::Iterator(picture, paint); - } - - const Paint* next(const Paint* p) - { - return nullptr; + return new PictureIterator(paint); } }; diff --git a/src/lib/tvgSaverImpl.h b/src/lib/tvgSaverImpl.h index eef0830..eafd19f 100644 --- a/src/lib/tvgSaverImpl.h +++ b/src/lib/tvgSaverImpl.h @@ -347,13 +347,16 @@ struct Saver::Impl ByteCounter serializeChildren(const Paint* paint) { - if (!paint) return 0; ByteCounter dataByteCnt = 0; - for (auto it = paint->begin(); it != paint->end(); ++it) { - dataByteCnt += serialize(&(*it)); + auto it = paint->pImpl->iterator(); + + while (auto p = it->next()) { + dataByteCnt += serialize(p); } + delete(it); + return dataByteCnt; } diff --git a/src/lib/tvgScene.cpp b/src/lib/tvgScene.cpp index 08cc743..798f164 100644 --- a/src/lib/tvgScene.cpp +++ b/src/lib/tvgScene.cpp @@ -25,7 +25,7 @@ /* External Class Implementation */ /************************************************************************/ -Scene::Scene() : pImpl(new Impl(this)) +Scene::Scene() : pImpl(new Impl()) { _id = TVG_CLASS_ID_SCENE; Paint::pImpl->method(new PaintMethod(pImpl)); @@ -67,4 +67,4 @@ Result Scene::clear(bool free) noexcept pImpl->clear(free); return Result::Success; -} +} \ No newline at end of file diff --git a/src/lib/tvgSceneImpl.h b/src/lib/tvgSceneImpl.h index eb062be..9b14db8 100644 --- a/src/lib/tvgSceneImpl.h +++ b/src/lib/tvgSceneImpl.h @@ -29,11 +29,26 @@ /* Internal Class Implementation */ /************************************************************************/ +struct SceneIterator : Iterator +{ + Array* paints; + uint32_t idx = 0; + + SceneIterator(Array* p) : paints(p) + { + } + + const Paint* next() override + { + if (idx >= paints->count) return nullptr; + return paints->data[idx++]; + } +}; + struct Scene::Impl { Array paints; - Scene* scene = nullptr; - uint8_t opacity; //for composition + uint8_t opacity; //for composition RenderMethod* renderer = nullptr; //keep it for explicit clear ~Impl() @@ -43,10 +58,6 @@ struct Scene::Impl } } - Impl(Scene* s) : scene(s) - { - } - bool dispose(RenderMethod& renderer) { for (auto paint = paints.data; paint < (paints.data + paints.count); ++paint) { @@ -187,21 +198,9 @@ struct Scene::Impl renderer = nullptr; } - Paint::Iterator begin() + Iterator* iterator() { - if (paints.count > 0) return Paint::Iterator(scene, *(paints.data)); - return Paint::Iterator(); - } - - const Paint* next(const Paint* p) - { - for (auto paint = paints.data; paint < (paints.data + paints.count); ++paint) { - auto tmp = paint; - if (*paint == p && ++tmp < (paints.data + paints.count)) { - return *tmp; - } - } - return nullptr; + return new SceneIterator(&paints); } }; diff --git a/src/lib/tvgShapeImpl.h b/src/lib/tvgShapeImpl.h index f0ea0c9..fca452b 100644 --- a/src/lib/tvgShapeImpl.h +++ b/src/lib/tvgShapeImpl.h @@ -391,12 +391,7 @@ struct Shape::Impl return ret.release(); } - Paint::Iterator begin() - { - return Paint::Iterator(); - } - - const Paint* next(const Paint* p) + Iterator* iterator() { return nullptr; } -- 2.7.4 From b7fae753685b032fccba72adf5e8c97e079331cf Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Wed, 21 Jul 2021 11:14:11 +0900 Subject: [PATCH 03/16] tvg format: code refactoring #9 revise format of the macro names, no logical changes. ++ comments for maintenence. --- src/lib/tvgBinaryDesc.h | 140 ++++++++++++++------------- src/lib/tvgSaverImpl.h | 178 ++++++++++++++++++----------------- src/loaders/tvg/tvgTvgLoadParser.cpp | 117 ++++++++++++----------- 3 files changed, 224 insertions(+), 211 deletions(-) diff --git a/src/lib/tvgBinaryDesc.h b/src/lib/tvgBinaryDesc.h index c3d7c4b..4c65d38 100644 --- a/src/lib/tvgBinaryDesc.h +++ b/src/lib/tvgBinaryDesc.h @@ -22,72 +22,80 @@ #ifndef _TVG_BINARY_DESC_H_ #define _TVG_BINARY_DESC_H_ +//TODO: Need to consider whether uin8_t is enough size for extension... + +/* Data types, do not change data types once Tvg Format is officially released, + That would occur the abi break. */ using TvgBinByte = uint8_t; -using TvgIndicator = uint8_t; -using ByteCounter = uint32_t; -using TvgFlag = uint8_t; - -#define TVG_INDICATOR_SIZE sizeof(TvgIndicator) -#define BYTE_COUNTER_SIZE sizeof(ByteCounter) -#define TVG_FLAG_SIZE sizeof(TvgFlag) - -// HEADER -#define TVG_BIN_HEADER_SIGNATURE "ThorVG" -#define TVG_BIN_HEADER_SIGNATURE_LENGTH 6 -#define TVG_BIN_HEADER_VERSION "000200" -#define TVG_BIN_HEADER_VERSION_LENGTH 6 - -#define TVG_PICTURE_BEGIN_INDICATOR (TvgIndicator)0xfc -#define TVG_SHAPE_BEGIN_INDICATOR (TvgIndicator)0xfd -#define TVG_SCENE_BEGIN_INDICATOR (TvgIndicator)0xfe - -// Paint -#define TVG_PAINT_OPACITY_INDICATOR (TvgIndicator)0x10 -#define TVG_PAINT_TRANSFORM_MATRIX_INDICATOR (TvgIndicator)0x11 -#define TVG_PAINT_CMP_TARGET_INDICATOR (TvgIndicator)0x1 - -#define TVG_PAINT_CMP_METHOD_INDICATOR (TvgIndicator)0x20 -#define TVG_PAINT_CMP_METHOD_CLIPPATH_FLAG (TvgFlag)0x01 -#define TVG_PAINT_CMP_METHOD_ALPHAMASK_FLAG (TvgFlag)0x02 -#define TVG_PAINT_CMP_METHOD_INV_ALPHAMASK_FLAG (TvgFlag)0x03 - -// Scene -#define TVG_SCENE_FLAG_RESERVEDCNT (TvgIndicator)0x30 - -// Shape -#define TVG_SHAPE_PATH_INDICATOR (TvgIndicator)0x40 -#define TVG_SHAPE_STROKE_INDICATOR (TvgIndicator)0x41 -#define TVG_SHAPE_FILL_INDICATOR (TvgIndicator)0x42 -#define TVG_SHAPE_COLOR_INDICATOR (TvgIndicator)0x43 - -#define TVG_SHAPE_FILLRULE_INDICATOR (TvgIndicator)0x44 -#define TVG_SHAPE_FILLRULE_WINDING_FLAG (TvgFlag)0x00 -#define TVG_SHAPE_FILLRULE_EVENODD_FLAG (TvgFlag)0x01 - -#define TVG_SHAPE_STROKE_CAP_INDICATOR (TvgIndicator)0x50 -#define TVG_SHAPE_STROKE_CAP_SQUARE_FLAG (TvgFlag)0x00 -#define TVG_SHAPE_STROKE_CAP_ROUND_FLAG (TvgFlag)0x01 -#define TVG_SHAPE_STROKE_CAP_BUTT_FLAG (TvgFlag)0x02 - -#define TVG_SHAPE_STROKE_JOIN_INDICATOR (TvgIndicator)0x51 -#define TVG_SHAPE_STROKE_JOIN_BEVEL_FLAG (TvgFlag)0x00 -#define TVG_SHAPE_STROKE_JOIN_ROUND_FLAG (TvgFlag)0x01 -#define TVG_SHAPE_STROKE_JOIN_MITER_FLAG (TvgFlag)0x02 - -#define TVG_SHAPE_STROKE_WIDTH_INDICATOR (TvgIndicator)0x52 -#define TVG_SHAPE_STROKE_COLOR_INDICATOR (TvgIndicator)0x53 -#define TVG_SHAPE_STROKE_FILL_INDICATOR (TvgIndicator)0x54 -#define TVG_SHAPE_STROKE_DASHPTRN_INDICATOR (TvgIndicator)0x55 - -#define TVG_FILL_LINEAR_GRADIENT_INDICATOR (TvgIndicator)0x60 -#define TVG_FILL_RADIAL_GRADIENT_INDICATOR (TvgIndicator)0x61 -#define TVG_FILL_COLORSTOPS_INDICATOR (TvgIndicator)0x62 -#define TVG_FILL_FILLSPREAD_INDICATOR (TvgIndicator)0x63 -#define TVG_FILL_FILLSPREAD_PAD_FLAG (TvgFlag)0x00 -#define TVG_FILL_FILLSPREAD_REFLECT_FLAG (TvgFlag)0x01 -#define TVG_FILL_FILLSPREAD_REPEAT_FLAG (TvgFlag)0x02 - -// Picture -#define TVG_RAW_IMAGE_BEGIN_INDICATOR (TvgIndicator)0x70 +using TvgBinTag = uint8_t; +using TvgBinCounter = uint32_t; +using TvgBinFlag = uint8_t; + +//Header +#define TVG_HEADER_SIGNATURE "ThorVG" +#define TVG_HEADER_SIGNATURE_LENGTH 6 +#define TVG_HEADER_VERSION "000400" //Major 00, Minor 04, Micro 00 +#define TVG_HEADER_VERSION_LENGTH 6 + + +//Paint Type +#define TVG_TAG_CLASS_PICTURE (TvgBinTag)0xfc +#define TVG_TAG_CLASS_SHAPE (TvgBinTag)0xfd +#define TVG_TAG_CLASS_SCENE (TvgBinTag)0xfe + + +//Paint +#define TVG_TAG_PAINT_OPACITY (TvgBinTag)0x10 +#define TVG_TAG_PAINT_TRANSFORM (TvgBinTag)0x11 +#define TVG_TAG_PAINT_CMP_TARGET (TvgBinTag)0x01 +//Composition +#define TVG_TAG_PAINT_CMP_METHOD (TvgBinTag)0x20 +#define TVG_FLAG_PAINT_CMP_METHOD_CLIPPATH (TvgBinFlag)0x01 +#define TVG_FLAG_PAINT_CMP_METHOD_ALPHAMASK (TvgBinFlag)0x02 +#define TVG_FLAG_PAINT_CMP_METHOD_IALPHAMASK (TvgBinFlag)0x03 + + +//Scene +#define TVG_FLAG_SCENE_RESERVEDCNT (TvgBinTag)0x30 + + +//Shape +#define TVG_TAG_SHAPE_PATH (TvgBinTag)0x40 +#define TVG_TAG_SHAPE_STROKE (TvgBinTag)0x41 +#define TVG_TAG_SHAPE_FILL (TvgBinTag)0x42 +#define TVG_TAG_SHAPE_COLOR (TvgBinTag)0x43 +//Fill Rule +#define TVG_TAG_SHAPE_FILLRULE (TvgBinTag)0x44 +#define TVG_FLAG_SHAPE_FILLRULE_WINDING (TvgBinFlag)0x00 +#define TVG_FLAG_SHAPE_FILLRULE_EVENODD (TvgBinFlag)0x01 +//Stroke Cap +#define TVG_TAG_SHAPE_STROKE_CAP (TvgBinTag)0x50 +#define TVG_FLAG_SHAPE_STROKE_CAP_SQUARE (TvgBinFlag)0x00 +#define TVG_FLAG_SHAPE_STROKE_CAP_ROUND (TvgBinFlag)0x01 +#define TVG_FLAG_SHAPE_STROKE_CAP_BUTT (TvgBinFlag)0x02 +//Stroke Join +#define TVG_TAG_SHAPE_STROKE_JOIN (TvgBinTag)0x51 +#define TVG_FLAG_SHAPE_STROKE_JOIN_BEVEL (TvgBinFlag)0x00 +#define TVG_FLAG_SHAPE_STROKE_JOIN_ROUND (TvgBinFlag)0x01 +#define TVG_FLAG_SHAPE_STROKE_JOIN_MITER (TvgBinFlag)0x02 +//Stroke +#define TVG_TAG_SHAPE_STROKE_WIDTH (TvgBinTag)0x52 +#define TVG_TAG_SHAPE_STROKE_COLOR (TvgBinTag)0x53 +#define TVG_TAG_SHAPE_STROKE_FILL (TvgBinTag)0x54 +#define TVG_TAG_SHAPE_STROKE_DASHPTRN (TvgBinTag)0x55 + + +//Fill +#define TVG_TAG_FILL_LINEAR_GRADIENT (TvgBinTag)0x60 +#define TVG_TAG_FILL_RADIAL_GRADIENT (TvgBinTag)0x61 +#define TVG_TAG_FILL_COLORSTOPS (TvgBinTag)0x62 +#define TVG_TAG_FILL_FILLSPREAD (TvgBinTag)0x63 +#define TVG_FLAG_FILL_FILLSPREAD_PAD (TvgBinFlag)0x00 +#define TVG_FLAG_FILL_FILLSPREAD_REFLECT (TvgBinFlag)0x01 +#define TVG_FLAG_FILL_FILLSPREAD_REPEAT (TvgBinFlag)0x02 + + +//Picture +#define TVG_TAG_PICTURE_RAW_IMAGE (TvgBinTag)0x70 #endif //_TVG_BINARY_DESC_H_ diff --git a/src/lib/tvgSaverImpl.h b/src/lib/tvgSaverImpl.h index eafd19f..7504cdd 100644 --- a/src/lib/tvgSaverImpl.h +++ b/src/lib/tvgSaverImpl.h @@ -28,6 +28,8 @@ #include "tvgPaint.h" #include "tvgBinaryDesc.h" +#define SIZE(A) sizeof(A) + struct Saver::Impl { @@ -62,45 +64,45 @@ struct Saver::Impl bool writeHeader() { - buffer.grow(TVG_BIN_HEADER_SIGNATURE_LENGTH + TVG_BIN_HEADER_VERSION_LENGTH); + buffer.grow(TVG_HEADER_SIGNATURE_LENGTH + TVG_HEADER_VERSION_LENGTH); auto ptr = buffer.ptr(); - memcpy(ptr, TVG_BIN_HEADER_SIGNATURE, TVG_BIN_HEADER_SIGNATURE_LENGTH); - ptr += TVG_BIN_HEADER_SIGNATURE_LENGTH; - memcpy(ptr, TVG_BIN_HEADER_VERSION, TVG_BIN_HEADER_VERSION_LENGTH); - ptr += TVG_BIN_HEADER_VERSION_LENGTH; + memcpy(ptr, TVG_HEADER_SIGNATURE, TVG_HEADER_SIGNATURE_LENGTH); + ptr += TVG_HEADER_SIGNATURE_LENGTH; + memcpy(ptr, TVG_HEADER_VERSION, TVG_HEADER_VERSION_LENGTH); + ptr += TVG_HEADER_VERSION_LENGTH; - buffer.count += (TVG_BIN_HEADER_SIGNATURE_LENGTH + TVG_BIN_HEADER_VERSION_LENGTH); + buffer.count += (TVG_HEADER_SIGNATURE_LENGTH + TVG_HEADER_VERSION_LENGTH); return true; } - void writeMemberIndicator(TvgIndicator ind) + void writeMemberIndicator(TvgBinTag ind) { - buffer.grow(TVG_INDICATOR_SIZE); - memcpy(buffer.ptr(), &ind, TVG_INDICATOR_SIZE); - buffer.count += TVG_INDICATOR_SIZE; + buffer.grow(SIZE(TvgBinTag)); + memcpy(buffer.ptr(), &ind, SIZE(TvgBinTag)); + buffer.count += SIZE(TvgBinTag); } - void writeMemberDataSize(ByteCounter byteCnt) + void writeMemberDataSize(TvgBinCounter byteCnt) { - buffer.grow(BYTE_COUNTER_SIZE); - memcpy(buffer.ptr(), &byteCnt, BYTE_COUNTER_SIZE); - buffer.count += BYTE_COUNTER_SIZE; + buffer.grow(SIZE(TvgBinCounter)); + memcpy(buffer.ptr(), &byteCnt, SIZE(TvgBinCounter)); + buffer.count += SIZE(TvgBinCounter); } - void writeMemberDataSizeAt(ByteCounter byteCnt) + void writeMemberDataSizeAt(TvgBinCounter byteCnt) { - memcpy(buffer.ptr() - byteCnt - BYTE_COUNTER_SIZE, &byteCnt, BYTE_COUNTER_SIZE); + memcpy(buffer.ptr() - byteCnt - SIZE(TvgBinCounter), &byteCnt, SIZE(TvgBinCounter)); } void skipInBufferMemberDataSize() { - buffer.grow(BYTE_COUNTER_SIZE); - buffer.count += BYTE_COUNTER_SIZE; + buffer.grow(SIZE(TvgBinCounter)); + buffer.count += SIZE(TvgBinCounter); } - ByteCounter writeMemberData(const void* data, ByteCounter byteCnt) + TvgBinCounter writeMemberData(const void* data, TvgBinCounter byteCnt) { buffer.grow(byteCnt); memcpy(buffer.ptr(), data, byteCnt); @@ -109,18 +111,18 @@ struct Saver::Impl return byteCnt; } - ByteCounter writeMember(TvgIndicator ind, ByteCounter byteCnt, const void* data) + TvgBinCounter writeMember(TvgBinTag ind, TvgBinCounter byteCnt, const void* data) { - ByteCounter blockByteCnt = TVG_INDICATOR_SIZE + BYTE_COUNTER_SIZE + byteCnt; + TvgBinCounter blockByteCnt = SIZE(TvgBinTag) + SIZE(TvgBinCounter) + byteCnt; buffer.grow(blockByteCnt); auto ptr = buffer.ptr(); - memcpy(ptr, &ind, TVG_INDICATOR_SIZE); - ptr += TVG_INDICATOR_SIZE; - memcpy(ptr, &byteCnt, BYTE_COUNTER_SIZE); - ptr += BYTE_COUNTER_SIZE; + memcpy(ptr, &ind, SIZE(TvgBinTag)); + ptr += SIZE(TvgBinTag); + memcpy(ptr, &byteCnt, SIZE(TvgBinCounter)); + ptr += SIZE(TvgBinCounter); memcpy(ptr, data, byteCnt); ptr += byteCnt; @@ -129,20 +131,20 @@ struct Saver::Impl return blockByteCnt; } - ByteCounter serializePaint(const Paint* paint) + TvgBinCounter serializePaint(const Paint* paint) { - ByteCounter paintDataByteCnt = 0; + TvgBinCounter paintDataByteCnt = 0; auto opacity = paint->opacity(); if (opacity < 255) { - paintDataByteCnt += writeMember(TVG_PAINT_OPACITY_INDICATOR, sizeof(opacity), &opacity); + paintDataByteCnt += writeMember(TVG_TAG_PAINT_OPACITY, sizeof(opacity), &opacity); } auto m = const_cast(paint)->transform(); if (fabs(m.e11 - 1) > FLT_EPSILON || fabs(m.e12) > FLT_EPSILON || fabs(m.e13) > FLT_EPSILON || fabs(m.e21) > FLT_EPSILON || fabs(m.e22 - 1) > FLT_EPSILON || fabs(m.e23) > FLT_EPSILON || fabs(m.e31) > FLT_EPSILON || fabs(m.e32) > FLT_EPSILON || fabs(m.e33 - 1) > FLT_EPSILON) { - paintDataByteCnt += writeMember(TVG_PAINT_TRANSFORM_MATRIX_INDICATOR, sizeof(m), &m); + paintDataByteCnt += writeMember(TVG_TAG_PAINT_TRANSFORM, sizeof(m), &m); } const Paint* cmpTarget = nullptr; @@ -154,9 +156,9 @@ struct Saver::Impl return paintDataByteCnt; } - ByteCounter serializeScene(const Scene* scene) + TvgBinCounter serialize(const Scene* scene) { - writeMemberIndicator(TVG_SCENE_BEGIN_INDICATOR); + writeMemberIndicator(TVG_TAG_CLASS_SCENE); skipInBufferMemberDataSize(); auto sceneDataByteCnt = serializeChildren(scene); @@ -164,85 +166,85 @@ struct Saver::Impl writeMemberDataSizeAt(sceneDataByteCnt); - return TVG_INDICATOR_SIZE + BYTE_COUNTER_SIZE + sceneDataByteCnt; + return SIZE(TvgBinTag) + SIZE(TvgBinCounter) + sceneDataByteCnt; } - ByteCounter serializeShapeFill(const Fill* f, TvgIndicator fillTvgFlag) + TvgBinCounter serializeShapeFill(const Fill* f, TvgBinTag fillTvgBinFlag) { - ByteCounter fillDataByteCnt = 0; + TvgBinCounter fillDataByteCnt = 0; const Fill::ColorStop* stops = nullptr; auto stopsCnt = f->colorStops(&stops); if (!stops || stopsCnt == 0) return 0; - writeMemberIndicator(fillTvgFlag); + writeMemberIndicator(fillTvgBinFlag); skipInBufferMemberDataSize(); if (f->id() == TVG_CLASS_ID_RADIAL) { float argRadial[3]; auto radGrad = static_cast(f); radGrad->radial(argRadial, argRadial + 1,argRadial + 2); - fillDataByteCnt += writeMember(TVG_FILL_RADIAL_GRADIENT_INDICATOR, sizeof(argRadial), argRadial); + fillDataByteCnt += writeMember(TVG_TAG_FILL_RADIAL_GRADIENT, sizeof(argRadial), argRadial); } else { float argLinear[4]; auto linGrad = static_cast(f); linGrad->linear(argLinear, argLinear + 1, argLinear + 2, argLinear + 3); - fillDataByteCnt += writeMember(TVG_FILL_LINEAR_GRADIENT_INDICATOR, sizeof(argLinear), argLinear); + fillDataByteCnt += writeMember(TVG_TAG_FILL_LINEAR_GRADIENT, sizeof(argLinear), argLinear); } - auto flag = static_cast(f->spread()); - fillDataByteCnt += writeMember(TVG_FILL_FILLSPREAD_INDICATOR, TVG_FLAG_SIZE, &flag); - fillDataByteCnt += writeMember(TVG_FILL_COLORSTOPS_INDICATOR, stopsCnt * sizeof(stops), stops); + auto flag = static_cast(f->spread()); + fillDataByteCnt += writeMember(TVG_TAG_FILL_FILLSPREAD, SIZE(TvgBinFlag), &flag); + fillDataByteCnt += writeMember(TVG_TAG_FILL_COLORSTOPS, stopsCnt * sizeof(stops), stops); writeMemberDataSizeAt(fillDataByteCnt); - return TVG_INDICATOR_SIZE + BYTE_COUNTER_SIZE + fillDataByteCnt; + return SIZE(TvgBinTag) + SIZE(TvgBinCounter) + fillDataByteCnt; } - ByteCounter serializeShapeStroke(const Shape* shape) + TvgBinCounter serializeShapeStroke(const Shape* shape) { - ByteCounter strokeDataByteCnt = 0; - TvgFlag flag; + TvgBinCounter strokeDataByteCnt = 0; + TvgBinFlag flag; - writeMemberIndicator(TVG_SHAPE_STROKE_INDICATOR); + writeMemberIndicator(TVG_TAG_SHAPE_STROKE); skipInBufferMemberDataSize(); - flag = static_cast(shape->strokeCap()); - strokeDataByteCnt += writeMember(TVG_SHAPE_STROKE_CAP_INDICATOR, TVG_FLAG_SIZE, &flag); + flag = static_cast(shape->strokeCap()); + strokeDataByteCnt += writeMember(TVG_TAG_SHAPE_STROKE_CAP, SIZE(TvgBinFlag), &flag); - flag = static_cast(shape->strokeJoin()); - strokeDataByteCnt += writeMember(TVG_SHAPE_STROKE_JOIN_INDICATOR, TVG_FLAG_SIZE, &flag); + flag = static_cast(shape->strokeJoin()); + strokeDataByteCnt += writeMember(TVG_TAG_SHAPE_STROKE_JOIN, SIZE(TvgBinFlag), &flag); float width = shape->strokeWidth(); - strokeDataByteCnt += writeMember(TVG_SHAPE_STROKE_WIDTH_INDICATOR, sizeof(width), &width); + strokeDataByteCnt += writeMember(TVG_TAG_SHAPE_STROKE_WIDTH, sizeof(width), &width); if (auto fill = shape->strokeFill()) { - strokeDataByteCnt += serializeShapeFill(fill, TVG_SHAPE_STROKE_FILL_INDICATOR); + strokeDataByteCnt += serializeShapeFill(fill, TVG_TAG_SHAPE_STROKE_FILL); } else { uint8_t color[4] = {0, 0, 0, 0}; shape->strokeColor(color, color + 1, color + 2, color + 3); - strokeDataByteCnt += writeMember(TVG_SHAPE_STROKE_COLOR_INDICATOR, sizeof(color), &color); + strokeDataByteCnt += writeMember(TVG_TAG_SHAPE_STROKE_COLOR, sizeof(color), &color); } const float* dashPattern = nullptr; uint32_t dashCnt = shape->strokeDash(&dashPattern); if (dashPattern && dashCnt > 0) { - ByteCounter dashCntByteCnt = sizeof(dashCnt); - ByteCounter dashPtrnByteCnt = dashCnt * sizeof(dashPattern[0]); + TvgBinCounter dashCntByteCnt = sizeof(dashCnt); + TvgBinCounter dashPtrnByteCnt = dashCnt * sizeof(dashPattern[0]); - writeMemberIndicator(TVG_SHAPE_STROKE_DASHPTRN_INDICATOR); + writeMemberIndicator(TVG_TAG_SHAPE_STROKE_DASHPTRN); writeMemberDataSize(dashCntByteCnt + dashPtrnByteCnt); strokeDataByteCnt += writeMemberData(&dashCnt, dashCntByteCnt); strokeDataByteCnt += writeMemberData(dashPattern, dashPtrnByteCnt); - strokeDataByteCnt += TVG_INDICATOR_SIZE + BYTE_COUNTER_SIZE; + strokeDataByteCnt += SIZE(TvgBinTag) + SIZE(TvgBinCounter); } writeMemberDataSizeAt(strokeDataByteCnt); - return TVG_INDICATOR_SIZE + BYTE_COUNTER_SIZE + strokeDataByteCnt; + return SIZE(TvgBinTag) + SIZE(TvgBinCounter) + strokeDataByteCnt; } - ByteCounter serializeShapePath(const Shape* shape) + TvgBinCounter serializeShapePath(const Shape* shape) { const PathCommand* cmds = nullptr; uint32_t cmdCnt = shape->pathCommands(&cmds); @@ -251,9 +253,9 @@ struct Saver::Impl if (!cmds || !pts || !cmdCnt || !ptsCnt) return 0; - ByteCounter pathDataByteCnt = 0; + TvgBinCounter pathDataByteCnt = 0; - writeMemberIndicator(TVG_SHAPE_PATH_INDICATOR); + writeMemberIndicator(TVG_TAG_SHAPE_PATH); skipInBufferMemberDataSize(); pathDataByteCnt += writeMemberData(&cmdCnt, sizeof(cmdCnt)); @@ -263,25 +265,25 @@ struct Saver::Impl writeMemberDataSizeAt(pathDataByteCnt); - return TVG_INDICATOR_SIZE + BYTE_COUNTER_SIZE + pathDataByteCnt; + return SIZE(TvgBinTag) + SIZE(TvgBinCounter) + pathDataByteCnt; } - ByteCounter serializeShape(const Shape* shape) + TvgBinCounter serialize(const Shape* shape) { - writeMemberIndicator(TVG_SHAPE_BEGIN_INDICATOR); + writeMemberIndicator(TVG_TAG_CLASS_SHAPE); skipInBufferMemberDataSize(); - auto ruleTvgFlag = (shape->fillRule() == FillRule::EvenOdd) ? TVG_SHAPE_FILLRULE_EVENODD_FLAG : TVG_SHAPE_FILLRULE_WINDING_FLAG; - auto shapeDataByteCnt = writeMember(TVG_SHAPE_FILLRULE_INDICATOR, TVG_FLAG_SIZE, &ruleTvgFlag); + auto ruleTvgBinFlag = (shape->fillRule() == FillRule::EvenOdd) ? TVG_FLAG_SHAPE_FILLRULE_EVENODD : TVG_FLAG_SHAPE_FILLRULE_WINDING; + auto shapeDataByteCnt = writeMember(TVG_TAG_SHAPE_FILLRULE, SIZE(TvgBinFlag), &ruleTvgBinFlag); if (shape->strokeWidth() > 0) shapeDataByteCnt += serializeShapeStroke(shape); if (auto fill = shape->fill()) { - shapeDataByteCnt += serializeShapeFill(fill, TVG_SHAPE_FILL_INDICATOR); + shapeDataByteCnt += serializeShapeFill(fill, TVG_TAG_SHAPE_FILL); } else { uint8_t color[4] = {0, 0, 0, 0}; shape->fillColor(color, color + 1, color + 2, color + 3); - shapeDataByteCnt += writeMember(TVG_SHAPE_COLOR_INDICATOR, sizeof(color), color); + shapeDataByteCnt += writeMember(TVG_TAG_SHAPE_COLOR, sizeof(color), color); } shapeDataByteCnt += serializeShapePath(shape); @@ -289,16 +291,16 @@ struct Saver::Impl writeMemberDataSizeAt(shapeDataByteCnt); - return TVG_INDICATOR_SIZE + BYTE_COUNTER_SIZE + shapeDataByteCnt; + return SIZE(TvgBinTag) + SIZE(TvgBinCounter) + shapeDataByteCnt; } - ByteCounter serializePicture(const Picture* picture) + TvgBinCounter serialize(const Picture* picture) { auto pixels = picture->data(); - ByteCounter pictureDataByteCnt = 0; + TvgBinCounter pictureDataByteCnt = 0; - writeMemberIndicator(TVG_PICTURE_BEGIN_INDICATOR); + writeMemberIndicator(TVG_TAG_CLASS_PICTURE); skipInBufferMemberDataSize(); if (pixels) { @@ -308,15 +310,15 @@ struct Saver::Impl uint32_t w = static_cast(vw); uint32_t h = static_cast(vh); - ByteCounter wByteCnt = sizeof(w); // same as h size - ByteCounter pixelsByteCnt = w * h * sizeof(pixels[0]); + TvgBinCounter wByteCnt = sizeof(w); // same as h size + TvgBinCounter pixelsByteCnt = w * h * sizeof(pixels[0]); - writeMemberIndicator(TVG_RAW_IMAGE_BEGIN_INDICATOR); + writeMemberIndicator(TVG_TAG_PICTURE_RAW_IMAGE); writeMemberDataSize(2 * wByteCnt + pixelsByteCnt); pictureDataByteCnt += writeMemberData(&w, wByteCnt); pictureDataByteCnt += writeMemberData(&h, wByteCnt); pictureDataByteCnt += writeMemberData(pixels, pixelsByteCnt); - pictureDataByteCnt += TVG_INDICATOR_SIZE + BYTE_COUNTER_SIZE; + pictureDataByteCnt += SIZE(TvgBinTag) + SIZE(TvgBinCounter); } else { pictureDataByteCnt += serializeChildren(picture); } @@ -325,29 +327,29 @@ struct Saver::Impl writeMemberDataSizeAt(pictureDataByteCnt); - return TVG_INDICATOR_SIZE + BYTE_COUNTER_SIZE + pictureDataByteCnt; + return SIZE(TvgBinTag) + SIZE(TvgBinCounter) + pictureDataByteCnt; } - ByteCounter serializeComposite(const Paint* cmpTarget, CompositeMethod cmpMethod) + TvgBinCounter serializeComposite(const Paint* cmpTarget, CompositeMethod cmpMethod) { - ByteCounter cmpDataByteCnt = 0; + TvgBinCounter cmpDataByteCnt = 0; - writeMemberIndicator(TVG_PAINT_CMP_TARGET_INDICATOR); + writeMemberIndicator(TVG_TAG_PAINT_CMP_TARGET); skipInBufferMemberDataSize(); - auto cmpMethodTvgFlag = static_cast(cmpMethod); - cmpDataByteCnt += writeMember(TVG_PAINT_CMP_METHOD_INDICATOR, TVG_FLAG_SIZE, &cmpMethodTvgFlag); + auto cmpMethodTvgBinFlag = static_cast(cmpMethod); + cmpDataByteCnt += writeMember(TVG_TAG_PAINT_CMP_METHOD, SIZE(TvgBinFlag), &cmpMethodTvgBinFlag); cmpDataByteCnt += serialize(cmpTarget); writeMemberDataSizeAt(cmpDataByteCnt); - return TVG_INDICATOR_SIZE + BYTE_COUNTER_SIZE + cmpDataByteCnt; + return SIZE(TvgBinTag) + SIZE(TvgBinCounter) + cmpDataByteCnt; } - ByteCounter serializeChildren(const Paint* paint) + TvgBinCounter serializeChildren(const Paint* paint) { - ByteCounter dataByteCnt = 0; + TvgBinCounter dataByteCnt = 0; auto it = paint->pImpl->iterator(); @@ -360,14 +362,14 @@ struct Saver::Impl return dataByteCnt; } - ByteCounter serialize(const Paint* paint) + TvgBinCounter serialize(const Paint* paint) { if (!paint) return 0; switch (paint->id()) { - case TVG_CLASS_ID_SHAPE: return serializeShape(static_cast(paint)); - case TVG_CLASS_ID_SCENE: return serializeScene(static_cast(paint)); - case TVG_CLASS_ID_PICTURE: return serializePicture(static_cast(paint)); + case TVG_CLASS_ID_SHAPE: return serialize(static_cast(paint)); + case TVG_CLASS_ID_SCENE: return serialize(static_cast(paint)); + case TVG_CLASS_ID_PICTURE: return serialize(static_cast(paint)); } return 0; diff --git a/src/loaders/tvg/tvgTvgLoadParser.cpp b/src/loaders/tvg/tvgTvgLoadParser.cpp index d6dc042..67de51c 100644 --- a/src/loaders/tvg/tvgTvgLoadParser.cpp +++ b/src/loaders/tvg/tvgTvgLoadParser.cpp @@ -28,10 +28,13 @@ /* Internal Class Implementation */ /************************************************************************/ +#define SIZE(A) sizeof(A) + + struct TvgBinBlock { - TvgIndicator type; - ByteCounter length; + TvgBinTag type; + TvgBinCounter length; const char* data; const char* end; }; @@ -44,9 +47,9 @@ static Paint* _parsePaint(TvgBinBlock block); static bool _paintProperty(TvgBinBlock block) { switch (block.type) { - case TVG_PAINT_OPACITY_INDICATOR: - case TVG_PAINT_TRANSFORM_MATRIX_INDICATOR: - case TVG_PAINT_CMP_TARGET_INDICATOR: + case TVG_TAG_PAINT_OPACITY: + case TVG_TAG_PAINT_TRANSFORM: + case TVG_TAG_PAINT_CMP_TARGET: return true; } return false; @@ -57,8 +60,8 @@ static TvgBinBlock _readBlock(const char *ptr) { TvgBinBlock block; block.type = *ptr; - _read_tvg_ui32(&block.length, ptr + TVG_INDICATOR_SIZE); - block.data = ptr + TVG_INDICATOR_SIZE + BYTE_COUNTER_SIZE; + _read_tvg_ui32(&block.length, ptr + SIZE(TvgBinTag)); + block.data = ptr + SIZE(TvgBinTag) + SIZE(TvgBinCounter); block.end = block.data + block.length; return block; } @@ -67,13 +70,13 @@ static bool _readTvgHeader(const char **ptr) { if (!*ptr) return false; - //Sign phase, always TVG_BIN_HEADER_SIGNATURE is declared - if (memcmp(*ptr, TVG_BIN_HEADER_SIGNATURE, TVG_BIN_HEADER_SIGNATURE_LENGTH)) return false; - *ptr += TVG_BIN_HEADER_SIGNATURE_LENGTH; + //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_BIN_HEADER_VERSION - if (memcmp(*ptr, TVG_BIN_HEADER_VERSION, TVG_BIN_HEADER_VERSION_LENGTH)) return false; - *ptr += TVG_BIN_HEADER_VERSION_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; return true; } @@ -84,21 +87,21 @@ static bool _parseCmpTarget(const char *ptr, const char *end, Paint *paint) auto block = _readBlock(ptr); if (block.end > end) return false; - if (block.type != TVG_PAINT_CMP_METHOD_INDICATOR) return false; - if (block.length != sizeof(TvgFlag)) return false; + if (block.type != TVG_TAG_PAINT_CMP_METHOD) return false; + if (block.length != sizeof(TvgBinFlag)) return false; CompositeMethod cmpMethod; switch (*block.data) { - case TVG_PAINT_CMP_METHOD_CLIPPATH_FLAG: { + case TVG_FLAG_PAINT_CMP_METHOD_CLIPPATH: { cmpMethod = CompositeMethod::ClipPath; break; } - case TVG_PAINT_CMP_METHOD_ALPHAMASK_FLAG: { + case TVG_FLAG_PAINT_CMP_METHOD_ALPHAMASK: { cmpMethod = CompositeMethod::AlphaMask; break; } - case TVG_PAINT_CMP_METHOD_INV_ALPHAMASK_FLAG: { + case TVG_FLAG_PAINT_CMP_METHOD_IALPHAMASK: { cmpMethod = CompositeMethod::InvAlphaMask; break; } @@ -119,20 +122,20 @@ static bool _parseCmpTarget(const char *ptr, const char *end, Paint *paint) static bool _parsePaintProperty(TvgBinBlock block, Paint *paint) { switch (block.type) { - case TVG_PAINT_OPACITY_INDICATOR: { + case TVG_TAG_PAINT_OPACITY: { if (block.length != sizeof(uint8_t)) return false; paint->opacity(*block.data); return true; } - case TVG_PAINT_TRANSFORM_MATRIX_INDICATOR: { + case TVG_TAG_PAINT_TRANSFORM: { if (block.length != sizeof(Matrix)) return false; Matrix matrix; memcpy(&matrix, block.data, sizeof(Matrix)); if (paint->transform(matrix) != Result::Success) return false; return true; } - case TVG_PAINT_CMP_TARGET_INDICATOR: { - if (block.length < TVG_INDICATOR_SIZE + BYTE_COUNTER_SIZE) return false; + case TVG_TAG_PAINT_CMP_TARGET: { + if (block.length < SIZE(TvgBinTag) + SIZE(TvgBinCounter)) return false; return _parseCmpTarget(block.data, block.end, paint); } } @@ -145,7 +148,7 @@ static bool _parseScene(TvgBinBlock block, Paint *paint) auto scene = static_cast(paint); switch (block.type) { - case TVG_SCENE_FLAG_RESERVEDCNT: { + case TVG_FLAG_SCENE_RESERVEDCNT: { if (block.length != sizeof(uint32_t)) return false; uint32_t reservedCnt; _read_tvg_ui32(&reservedCnt, block.data); @@ -195,7 +198,7 @@ static bool _parseShapeFill(const char *ptr, const char *end, Fill **fillOutside if (block.end > end) return false; switch (block.type) { - case TVG_FILL_RADIAL_GRADIENT_INDICATOR: { + case TVG_TAG_FILL_RADIAL_GRADIENT: { if (block.length != 3 * sizeof(float)) return false; auto ptr = block.data; @@ -212,7 +215,7 @@ static bool _parseShapeFill(const char *ptr, const char *end, Fill **fillOutside fillGrad = move(fillGradRadial); break; } - case TVG_FILL_LINEAR_GRADIENT_INDICATOR: { + case TVG_TAG_FILL_LINEAR_GRADIENT: { if (block.length != 4 * sizeof(float)) return false; auto ptr = block.data; @@ -231,26 +234,26 @@ static bool _parseShapeFill(const char *ptr, const char *end, Fill **fillOutside fillGrad = move(fillGradLinear); break; } - case TVG_FILL_FILLSPREAD_INDICATOR: { + case TVG_TAG_FILL_FILLSPREAD: { if (!fillGrad) return false; - if (block.length != sizeof(TvgFlag)) return false; + if (block.length != sizeof(TvgBinFlag)) return false; switch (*block.data) { - case TVG_FILL_FILLSPREAD_PAD_FLAG: { + case TVG_FLAG_FILL_FILLSPREAD_PAD: { fillGrad->spread(FillSpread::Pad); break; } - case TVG_FILL_FILLSPREAD_REFLECT_FLAG: { + case TVG_FLAG_FILL_FILLSPREAD_REFLECT: { fillGrad->spread(FillSpread::Reflect); break; } - case TVG_FILL_FILLSPREAD_REPEAT_FLAG: { + case TVG_FLAG_FILL_FILLSPREAD_REPEAT: { fillGrad->spread(FillSpread::Repeat); break; } } break; } - case TVG_FILL_COLORSTOPS_INDICATOR: { + case TVG_TAG_FILL_COLORSTOPS: { if (!fillGrad) return false; if (block.length == 0 || block.length & 0x07) return false; uint32_t stopsCnt = block.length >> 3; // 8 bytes per ColorStop @@ -297,55 +300,55 @@ static bool _parseShapeStroke(const char *ptr, const char *end, Shape *shape) if (block.end > end) return false; switch (block.type) { - case TVG_SHAPE_STROKE_CAP_INDICATOR: { - if (block.length != sizeof(TvgFlag)) return false; + case TVG_TAG_SHAPE_STROKE_CAP: { + if (block.length != sizeof(TvgBinFlag)) return false; switch (*block.data) { - case TVG_SHAPE_STROKE_CAP_SQUARE_FLAG: + case TVG_FLAG_SHAPE_STROKE_CAP_SQUARE: shape->stroke(StrokeCap::Square); break; - case TVG_SHAPE_STROKE_CAP_ROUND_FLAG: + case TVG_FLAG_SHAPE_STROKE_CAP_ROUND: shape->stroke(StrokeCap::Round); break; - case TVG_SHAPE_STROKE_CAP_BUTT_FLAG: + case TVG_FLAG_SHAPE_STROKE_CAP_BUTT: shape->stroke(StrokeCap::Butt); break; } break; } - case TVG_SHAPE_STROKE_JOIN_INDICATOR: { - if (block.length != sizeof(TvgFlag)) return false; + case TVG_TAG_SHAPE_STROKE_JOIN: { + if (block.length != sizeof(TvgBinFlag)) return false; switch (*block.data) { - case TVG_SHAPE_STROKE_JOIN_BEVEL_FLAG: + case TVG_FLAG_SHAPE_STROKE_JOIN_BEVEL: shape->stroke(StrokeJoin::Bevel); break; - case TVG_SHAPE_STROKE_JOIN_ROUND_FLAG: + case TVG_FLAG_SHAPE_STROKE_JOIN_ROUND: shape->stroke(StrokeJoin::Round); break; - case TVG_SHAPE_STROKE_JOIN_MITER_FLAG: + case TVG_FLAG_SHAPE_STROKE_JOIN_MITER: shape->stroke(StrokeJoin::Miter); break; } break; } - case TVG_SHAPE_STROKE_WIDTH_INDICATOR: { + case TVG_TAG_SHAPE_STROKE_WIDTH: { if (block.length != sizeof(float)) return false; float width; _read_tvg_float(&width, block.data); shape->stroke(width); break; } - case TVG_SHAPE_STROKE_COLOR_INDICATOR: { + case TVG_TAG_SHAPE_STROKE_COLOR: { if (block.length != 4) return false; shape->stroke(block.data[0], block.data[1], block.data[2], block.data[3]); break; } - case TVG_SHAPE_STROKE_FILL_INDICATOR: { + case TVG_TAG_SHAPE_STROKE_FILL: { Fill* fill; if (!_parseShapeFill(block.data, block.end, &fill)) return false; shape->stroke(unique_ptr < Fill > (fill)); break; } - case TVG_SHAPE_STROKE_DASHPTRN_INDICATOR: { + case TVG_TAG_SHAPE_STROKE_DASHPTRN: { if (!_parseShapeStrokeDashPattern(block.data, block.end, shape)) return false; break; } @@ -361,32 +364,32 @@ static bool _parseShape(TvgBinBlock block, Paint* paint) auto shape = static_cast(paint); switch (block.type) { - case TVG_SHAPE_PATH_INDICATOR: { + case TVG_TAG_SHAPE_PATH: { if (!_parseShapePath(block.data, block.end, shape)) return false; break; } - case TVG_SHAPE_STROKE_INDICATOR: { + case TVG_TAG_SHAPE_STROKE: { if (!_parseShapeStroke(block.data, block.end, shape)) return false; break; } - case TVG_SHAPE_FILL_INDICATOR: { + case TVG_TAG_SHAPE_FILL: { Fill* fill; if (!_parseShapeFill(block.data, block.end, &fill)) return false; shape->fill(unique_ptr < Fill > (fill)); break; } - case TVG_SHAPE_COLOR_INDICATOR: { + case TVG_TAG_SHAPE_COLOR: { if (block.length != 4) return false; shape->fill(block.data[0], block.data[1], block.data[2], block.data[3]); break; } - case TVG_SHAPE_FILLRULE_INDICATOR: { - if (block.length != sizeof(TvgFlag)) return false; + case TVG_TAG_SHAPE_FILLRULE: { + if (block.length != sizeof(TvgBinFlag)) return false; switch (*block.data) { - case TVG_SHAPE_FILLRULE_WINDING_FLAG: + case TVG_FLAG_SHAPE_FILLRULE_WINDING: shape->fill(FillRule::Winding); break; - case TVG_SHAPE_FILLRULE_EVENODD_FLAG: + case TVG_FLAG_SHAPE_FILLRULE_EVENODD: shape->fill(FillRule::EvenOdd); break; } @@ -403,7 +406,7 @@ static bool _parsePicture(TvgBinBlock block, Paint* paint) auto picture = static_cast(paint); switch (block.type) { - case TVG_RAW_IMAGE_BEGIN_INDICATOR: { + case TVG_TAG_PICTURE_RAW_IMAGE: { if (block.length < 2 * sizeof(uint32_t)) return false; auto ptr = block.data; @@ -439,17 +442,17 @@ static Paint* _parsePaint(TvgBinBlock baseBlock) Paint *paint = nullptr; switch (baseBlock.type) { - case TVG_SCENE_BEGIN_INDICATOR: { + case TVG_TAG_CLASS_SCENE: { paint = Scene::gen().release(); parser = _parseScene; break; } - case TVG_SHAPE_BEGIN_INDICATOR: { + case TVG_TAG_CLASS_SHAPE: { paint = Shape::gen().release(); parser = _parseShape; break; } - case TVG_PICTURE_BEGIN_INDICATOR: { + case TVG_TAG_CLASS_PICTURE: { paint = Picture::gen().release(); parser = _parsePicture; break; -- 2.7.4 From dcb91b2dc3ed98136bef1f67a5c70da74a453684 Mon Sep 17 00:00:00 2001 From: Michal Maciola <71131832+mmaciola@users.noreply.github.com> Date: Wed, 21 Jul 2021 05:12:09 +0200 Subject: [PATCH 04/16] svg_loader: allow both clipPath and mask together (#622) * svg_loader: allow both clipPath and mask together * svg_loader: allow both clipPath and mask together fix #1 Changed seperate functions _applyClipPathComposition and _applyMaskComposition into single function _applyComposition --- src/loaders/svg/tvgSvgLoader.cpp | 36 +++++++++---------- src/loaders/svg/tvgSvgLoaderCommon.h | 6 ++-- src/loaders/svg/tvgSvgSceneBuilder.cpp | 63 ++++++++++++++++++++++++---------- 3 files changed, 64 insertions(+), 41 deletions(-) diff --git a/src/loaders/svg/tvgSvgLoader.cpp b/src/loaders/svg/tvgSvgLoader.cpp index 6db74f8..6a04447 100644 --- a/src/loaders/svg/tvgSvgLoader.cpp +++ b/src/loaders/svg/tvgSvgLoader.cpp @@ -873,15 +873,10 @@ static void _handleTransformAttr(TVG_UNUSED SvgLoaderData* loader, SvgNode* node static void _handleClipPathAttr(TVG_UNUSED SvgLoaderData* loader, SvgNode* node, const char* value) { SvgStyleProperty* style = node->style; -#ifdef THORVG_LOG_ENABLED - if (style->comp.method != CompositeMethod::None) printf("SVG: Multiple Composition Tried!\n"); -#endif - style->comp.method = CompositeMethod::ClipPath; int len = strlen(value); if (len >= 3 && !strncmp(value, "url", 3)) { - //FIXME: Support multiple composition. - if (style->comp.url) delete(style->comp.url); - style->comp.url = _idFromUrl((const char*)(value + 3)); + if (style->clipPath.url) delete(style->clipPath.url); + style->clipPath.url = _idFromUrl((const char*)(value + 3)); } } @@ -889,15 +884,10 @@ static void _handleClipPathAttr(TVG_UNUSED SvgLoaderData* loader, SvgNode* node, static void _handleMaskAttr(TVG_UNUSED SvgLoaderData* loader, SvgNode* node, const char* value) { SvgStyleProperty* style = node->style; -#ifdef THORVG_LOG_ENABLED - if (style->comp.method != CompositeMethod::None) printf("SVG: Multiple Composition Tried!\n"); -#endif - style->comp.method = CompositeMethod::AlphaMask; int len = strlen(value); if (len >= 3 && !strncmp(value, "url", 3)) { - //FIXME: Support multiple composition. - if (style->comp.url) delete(style->comp.url); - style->comp.url = _idFromUrl((const char*)(value + 3)); + if (style->mask.url) delete(style->mask.url); + style->mask.url = _idFromUrl((const char*)(value + 3)); } } @@ -1707,7 +1697,8 @@ static void _copyAttr(SvgNode* to, const SvgNode* from) *to->style = *from->style; if (from->style->fill.paint.url) to->style->fill.paint.url = new string(from->style->fill.paint.url->c_str()); if (from->style->stroke.paint.url) to->style->stroke.paint.url = new string(from->style->stroke.paint.url->c_str()); - if (from->style->comp.url) to->style->comp.url = new string(from->style->comp.url->c_str()); + if (from->style->clipPath.url) to->style->clipPath.url = new string(from->style->clipPath.url->c_str()); + if (from->style->mask.url) to->style->mask.url = new string(from->style->mask.url->c_str()); //Copy node attribute switch (from->type) { @@ -2598,9 +2589,13 @@ static void _updateGradient(SvgNode* node, Array* gradients) static void _updateComposite(SvgNode* node, SvgNode* root) { - if (node->style->comp.url && !node->style->comp.node) { - SvgNode *findResult = _findNodeById(root, node->style->comp.url); - if (findResult) node->style->comp.node = findResult; + if (node->style->clipPath.url && !node->style->clipPath.node) { + SvgNode *findResult = _findNodeById(root, node->style->clipPath.url); + if (findResult) node->style->clipPath.node = findResult; + } + if (node->style->mask.url && !node->style->mask.node) { + SvgNode *findResult = _findNodeById(root, node->style->mask.url); + if (findResult) node->style->mask.node = findResult; } if (node->child.count > 0) { auto child = node->child.data; @@ -2615,8 +2610,9 @@ static void _freeNodeStyle(SvgStyleProperty* style) { if (!style) return; - //style->comp.node has only the addresses of node. Therefore, style->comp.node is released from _freeNode. - delete(style->comp.url); + //style->clipPath.node and style->mask.node has only the addresses of node. Therefore, node is released from _freeNode. + delete(style->clipPath.url); + delete(style->mask.url); if (style->fill.paint.gradient) delete(style->fill.paint.gradient); if (style->stroke.paint.gradient) delete(style->stroke.paint.gradient); diff --git a/src/loaders/svg/tvgSvgLoaderCommon.h b/src/loaders/svg/tvgSvgLoaderCommon.h index 35928ea..4a466f6 100644 --- a/src/loaders/svg/tvgSvgLoaderCommon.h +++ b/src/loaders/svg/tvgSvgLoaderCommon.h @@ -225,10 +225,9 @@ struct SvgRadialGradient struct SvgComposite { - CompositeMethod method; //TODO: Currently support either one method string *url; SvgNode* node; - bool applying; //flag for checking circualr dependency. + bool applying; //flag for checking circular dependency. }; struct SvgColor @@ -302,7 +301,8 @@ struct SvgStyleProperty { SvgStyleFill fill; SvgStyleStroke stroke; - SvgComposite comp; + SvgComposite clipPath; + SvgComposite mask; int opacity; SvgColor color; bool curColorSet; diff --git a/src/loaders/svg/tvgSvgSceneBuilder.cpp b/src/loaders/svg/tvgSvgSceneBuilder.cpp index c2d608d..0c47ad3 100644 --- a/src/loaders/svg/tvgSvgSceneBuilder.cpp +++ b/src/loaders/svg/tvgSvgSceneBuilder.cpp @@ -178,36 +178,63 @@ static bool _appendChildShape(SvgNode* node, Shape* shape, float vx, float vy, f static void _applyComposition(Paint* paint, const SvgNode* node, float vx, float vy, float vw, float vh) { - if (node->style->comp.method == CompositeMethod::None) return; - - /* Do not drop in Circular Dependency. + /* ClipPath */ + /* Do not drop in Circular Dependency for ClipPath. Composition can be applied recursively if its children nodes have composition target to this one. */ - if (node->style->comp.applying) { + if (node->style->clipPath.applying) { #ifdef THORVG_LOG_ENABLED printf("SVG: Multiple Composition Tried! Check out Circular dependency?\n"); #endif - return; - } + } else { + auto compNode = node->style->clipPath.node; + if (compNode && compNode->child.count > 0) { + node->style->clipPath.applying = true; - auto compNode = node->style->comp.node; - if (!compNode || compNode->child.count == 0) return; + auto comp = Shape::gen(); + comp->fill(255, 255, 255, 255); + if (node->transform) comp->transform(*node->transform); - node->style->comp.applying = true; + auto child = compNode->child.data; + auto valid = false; //Composite only when valid shapes are existed - auto comp = Shape::gen(); - comp->fill(255, 255, 255, 255); - if (node->transform) comp->transform(*node->transform); + for (uint32_t i = 0; i < compNode->child.count; ++i, ++child) { + if (_appendChildShape(*child, comp.get(), vx, vy, vw, vh)) valid = true; + } - auto child = compNode->child.data; - auto valid = false; //Composite only when valid shapes are existed + if (valid) paint->composite(move(comp), CompositeMethod::ClipPath); - for (uint32_t i = 0; i < compNode->child.count; ++i, ++child) { - if (_appendChildShape(*child, comp.get(), vx, vy, vw, vh)) valid = true; + node->style->clipPath.applying = false; + } } - if (valid) paint->composite(move(comp), node->style->comp.method); + /* Mask */ + /* Do not drop in Circular Dependency for Mask. + Composition can be applied recursively if its children nodes have composition target to this one. */ + if (node->style->mask.applying) { +#ifdef THORVG_LOG_ENABLED + printf("SVG: Multiple Composition Tried! Check out Circular dependency?\n"); +#endif + } else { + auto compNode = node->style->mask.node; + if (compNode && compNode->child.count > 0) { + node->style->mask.applying = true; + + auto comp = Shape::gen(); + comp->fill(255, 255, 255, 255); + if (node->transform) comp->transform(*node->transform); + + auto child = compNode->child.data; + auto valid = false; //Composite only when valid shapes are existed + + for (uint32_t i = 0; i < compNode->child.count; ++i, ++child) { + if (_appendChildShape(*child, comp.get(), vx, vy, vw, vh)) valid = true; + } + + if (valid) paint->composite(move(comp), CompositeMethod::AlphaMask); - node->style->comp.applying = false; + node->style->mask.applying = false; + } + } } -- 2.7.4 From 64fea7580d238cd976c3542d75b71b675bb29f26 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Wed, 21 Jul 2021 13:56:50 +0900 Subject: [PATCH 05/16] tvg format: code refactoring #10 keep neat & clean code, revise to tvg style naming convention. --- src/examples/images/test.tvg | Bin 317203 -> 317203 bytes src/lib/tvgBinaryDesc.h | 9 +- src/lib/tvgSaverImpl.h | 320 ++++++++++++++++++++++--------------------- 3 files changed, 173 insertions(+), 156 deletions(-) diff --git a/src/examples/images/test.tvg b/src/examples/images/test.tvg index d4c4ed0f033c7ec536c8770751a4e8688308503b..df8e13c3e8d1356bb3ef561e0ffc500ebcdc49bb 100644 GIT binary patch delta 33 ocmbQdPI&S-0|Nt-My^&a##Sz-RxakPTr8Z|0kyFSk^lez delta 33 ocmbQdPI&S-0|Nu2My^&a##Sz-RxakPTr8Z|0kw|_kN^Mx diff --git a/src/lib/tvgBinaryDesc.h b/src/lib/tvgBinaryDesc.h index 4c65d38..793d48f 100644 --- a/src/lib/tvgBinaryDesc.h +++ b/src/lib/tvgBinaryDesc.h @@ -22,14 +22,17 @@ #ifndef _TVG_BINARY_DESC_H_ #define _TVG_BINARY_DESC_H_ -//TODO: Need to consider whether uin8_t is enough size for extension... +/* TODO: Need to consider whether uin8_t is enough size for extension... + Rather than optimal data, we can use enough size and data compress? */ /* Data types, do not change data types once Tvg Format is officially released, That would occur the abi break. */ + using TvgBinByte = uint8_t; -using TvgBinTag = uint8_t; using TvgBinCounter = uint32_t; -using TvgBinFlag = uint8_t; +using TvgBinTag = TvgBinByte; +using TvgBinFlag = TvgBinByte; + //Header #define TVG_HEADER_SIGNATURE "ThorVG" diff --git a/src/lib/tvgSaverImpl.h b/src/lib/tvgSaverImpl.h index 7504cdd..9a83312 100644 --- a/src/lib/tvgSaverImpl.h +++ b/src/lib/tvgSaverImpl.h @@ -30,6 +30,14 @@ #define SIZE(A) sizeof(A) +/************************************************************************/ +/* Internal Class Implementation */ +/************************************************************************/ + +static inline TvgBinCounter SERIAL_DONE(TvgBinCounter cnt) +{ + return SIZE(TvgBinTag) + SIZE(TvgBinCounter) + cnt; +} struct Saver::Impl { @@ -50,7 +58,7 @@ struct Saver::Impl return true; } - bool bufferToFile(const std::string& path) + bool flushTo(const std::string& path) { FILE* fp = fopen(path.c_str(), "w+"); if (!fp) return false; @@ -77,289 +85,295 @@ struct Saver::Impl return true; } - void writeMemberIndicator(TvgBinTag ind) + void writeTag(TvgBinTag tag) { buffer.grow(SIZE(TvgBinTag)); - memcpy(buffer.ptr(), &ind, SIZE(TvgBinTag)); + memcpy(buffer.ptr(), &tag, SIZE(TvgBinTag)); buffer.count += SIZE(TvgBinTag); } - void writeMemberDataSize(TvgBinCounter byteCnt) + void writeCount(TvgBinCounter cnt) { buffer.grow(SIZE(TvgBinCounter)); - memcpy(buffer.ptr(), &byteCnt, SIZE(TvgBinCounter)); + memcpy(buffer.ptr(), &cnt, SIZE(TvgBinCounter)); buffer.count += SIZE(TvgBinCounter); } - void writeMemberDataSizeAt(TvgBinCounter byteCnt) + void writeReservedCount(TvgBinCounter cnt) { - memcpy(buffer.ptr() - byteCnt - SIZE(TvgBinCounter), &byteCnt, SIZE(TvgBinCounter)); + memcpy(buffer.ptr() - cnt - SIZE(TvgBinCounter), &cnt, SIZE(TvgBinCounter)); } - void skipInBufferMemberDataSize() + void reserveCount() { buffer.grow(SIZE(TvgBinCounter)); buffer.count += SIZE(TvgBinCounter); } - TvgBinCounter writeMemberData(const void* data, TvgBinCounter byteCnt) + TvgBinCounter writeData(const void* data, TvgBinCounter cnt) { - buffer.grow(byteCnt); - memcpy(buffer.ptr(), data, byteCnt); - buffer.count += byteCnt; + buffer.grow(cnt); + memcpy(buffer.ptr(), data, cnt); + buffer.count += cnt; - return byteCnt; + return cnt; } - TvgBinCounter writeMember(TvgBinTag ind, TvgBinCounter byteCnt, const void* data) + TvgBinCounter writeTagProperty(TvgBinTag tag, TvgBinCounter cnt, const void* data) { - TvgBinCounter blockByteCnt = SIZE(TvgBinTag) + SIZE(TvgBinCounter) + byteCnt; + TvgBinCounter growCnt = SERIAL_DONE(cnt); - buffer.grow(blockByteCnt); + buffer.grow(growCnt); auto ptr = buffer.ptr(); - memcpy(ptr, &ind, SIZE(TvgBinTag)); - ptr += SIZE(TvgBinTag); - memcpy(ptr, &byteCnt, SIZE(TvgBinCounter)); + *ptr = tag; + ++ptr; + + memcpy(ptr, &cnt, SIZE(TvgBinCounter)); ptr += SIZE(TvgBinCounter); - memcpy(ptr, data, byteCnt); - ptr += byteCnt; - buffer.count += blockByteCnt; + memcpy(ptr, data, cnt); + ptr += cnt; - return blockByteCnt; + buffer.count += growCnt; + + return growCnt; } TvgBinCounter serializePaint(const Paint* paint) { - TvgBinCounter paintDataByteCnt = 0; + TvgBinCounter cnt = 0; + //opacity auto opacity = paint->opacity(); if (opacity < 255) { - paintDataByteCnt += writeMember(TVG_TAG_PAINT_OPACITY, sizeof(opacity), &opacity); + cnt += writeTagProperty(TVG_TAG_PAINT_OPACITY, sizeof(opacity), &opacity); } + //transform auto m = const_cast(paint)->transform(); if (fabs(m.e11 - 1) > FLT_EPSILON || fabs(m.e12) > FLT_EPSILON || fabs(m.e13) > FLT_EPSILON || fabs(m.e21) > FLT_EPSILON || fabs(m.e22 - 1) > FLT_EPSILON || fabs(m.e23) > FLT_EPSILON || fabs(m.e31) > FLT_EPSILON || fabs(m.e32) > FLT_EPSILON || fabs(m.e33 - 1) > FLT_EPSILON) { - paintDataByteCnt += writeMember(TVG_TAG_PAINT_TRANSFORM, sizeof(m), &m); + cnt += writeTagProperty(TVG_TAG_PAINT_TRANSFORM, sizeof(m), &m); } + //composite const Paint* cmpTarget = nullptr; auto cmpMethod = paint->composite(&cmpTarget); if (cmpMethod != CompositeMethod::None && cmpTarget) { - paintDataByteCnt += serializeComposite(cmpTarget, cmpMethod); + cnt += serializeComposite(cmpTarget, cmpMethod); } - return paintDataByteCnt; + return cnt; } - TvgBinCounter serialize(const Scene* scene) + TvgBinCounter serializeScene(const Scene* scene) { - writeMemberIndicator(TVG_TAG_CLASS_SCENE); - skipInBufferMemberDataSize(); + writeTag(TVG_TAG_CLASS_SCENE); + reserveCount(); - auto sceneDataByteCnt = serializeChildren(scene); - sceneDataByteCnt += serializePaint(scene); + auto cnt = serializeChildren(scene) + serializePaint(scene); - writeMemberDataSizeAt(sceneDataByteCnt); + writeReservedCount(cnt); - return SIZE(TvgBinTag) + SIZE(TvgBinCounter) + sceneDataByteCnt; + return SERIAL_DONE(cnt); } - TvgBinCounter serializeShapeFill(const Fill* f, TvgBinTag fillTvgBinFlag) + TvgBinCounter serializeFill(const Fill* fill, TvgBinTag tag) { - TvgBinCounter fillDataByteCnt = 0; const Fill::ColorStop* stops = nullptr; - auto stopsCnt = f->colorStops(&stops); + auto stopsCnt = fill->colorStops(&stops); if (!stops || stopsCnt == 0) return 0; - writeMemberIndicator(fillTvgBinFlag); - skipInBufferMemberDataSize(); + writeTag(tag); + reserveCount(); - if (f->id() == TVG_CLASS_ID_RADIAL) { - float argRadial[3]; - auto radGrad = static_cast(f); - radGrad->radial(argRadial, argRadial + 1,argRadial + 2); - fillDataByteCnt += writeMember(TVG_TAG_FILL_RADIAL_GRADIENT, sizeof(argRadial), argRadial); - } - else { - float argLinear[4]; - auto linGrad = static_cast(f); - linGrad->linear(argLinear, argLinear + 1, argLinear + 2, argLinear + 3); - fillDataByteCnt += writeMember(TVG_TAG_FILL_LINEAR_GRADIENT, sizeof(argLinear), argLinear); + TvgBinCounter cnt = 0; + + //radial fill + if (fill->id() == TVG_CLASS_ID_RADIAL) { + float args[3]; + static_cast(fill)->radial(args, args + 1,args + 2); + cnt += writeTagProperty(TVG_TAG_FILL_RADIAL_GRADIENT, sizeof(args), args); + //linear fill + } else { + float args[4]; + static_cast(fill)->linear(args, args + 1, args + 2, args + 3); + cnt += writeTagProperty(TVG_TAG_FILL_LINEAR_GRADIENT, sizeof(args), args); } - auto flag = static_cast(f->spread()); - fillDataByteCnt += writeMember(TVG_TAG_FILL_FILLSPREAD, SIZE(TvgBinFlag), &flag); - fillDataByteCnt += writeMember(TVG_TAG_FILL_COLORSTOPS, stopsCnt * sizeof(stops), stops); + auto flag = static_cast(fill->spread()); + cnt += writeTagProperty(TVG_TAG_FILL_FILLSPREAD, SIZE(TvgBinFlag), &flag); + cnt += writeTagProperty(TVG_TAG_FILL_COLORSTOPS, stopsCnt * sizeof(stops), stops); - writeMemberDataSizeAt(fillDataByteCnt); + writeReservedCount(cnt); - return SIZE(TvgBinTag) + SIZE(TvgBinCounter) + fillDataByteCnt; + return SERIAL_DONE(cnt); } - TvgBinCounter serializeShapeStroke(const Shape* shape) + TvgBinCounter serializeStroke(const Shape* shape) { - TvgBinCounter strokeDataByteCnt = 0; - TvgBinFlag flag; + writeTag(TVG_TAG_SHAPE_STROKE); + reserveCount(); - writeMemberIndicator(TVG_TAG_SHAPE_STROKE); - skipInBufferMemberDataSize(); - - flag = static_cast(shape->strokeCap()); - strokeDataByteCnt += writeMember(TVG_TAG_SHAPE_STROKE_CAP, SIZE(TvgBinFlag), &flag); + //cap + auto flag = static_cast(shape->strokeCap()); + auto cnt = writeTagProperty(TVG_TAG_SHAPE_STROKE_CAP, SIZE(TvgBinFlag), &flag); + //join flag = static_cast(shape->strokeJoin()); - strokeDataByteCnt += writeMember(TVG_TAG_SHAPE_STROKE_JOIN, SIZE(TvgBinFlag), &flag); + cnt += writeTagProperty(TVG_TAG_SHAPE_STROKE_JOIN, SIZE(TvgBinFlag), &flag); - float width = shape->strokeWidth(); - strokeDataByteCnt += writeMember(TVG_TAG_SHAPE_STROKE_WIDTH, sizeof(width), &width); + //width + auto width = shape->strokeWidth(); + cnt += writeTagProperty(TVG_TAG_SHAPE_STROKE_WIDTH, sizeof(width), &width); + //fill if (auto fill = shape->strokeFill()) { - strokeDataByteCnt += serializeShapeFill(fill, TVG_TAG_SHAPE_STROKE_FILL); + cnt += serializeFill(fill, TVG_TAG_SHAPE_STROKE_FILL); } else { uint8_t color[4] = {0, 0, 0, 0}; shape->strokeColor(color, color + 1, color + 2, color + 3); - strokeDataByteCnt += writeMember(TVG_TAG_SHAPE_STROKE_COLOR, sizeof(color), &color); + cnt += writeTagProperty(TVG_TAG_SHAPE_STROKE_COLOR, sizeof(color), &color); } + //dash const float* dashPattern = nullptr; - uint32_t dashCnt = shape->strokeDash(&dashPattern); + auto dashCnt = shape->strokeDash(&dashPattern); if (dashPattern && dashCnt > 0) { - TvgBinCounter dashCntByteCnt = sizeof(dashCnt); - TvgBinCounter dashPtrnByteCnt = dashCnt * sizeof(dashPattern[0]); - - writeMemberIndicator(TVG_TAG_SHAPE_STROKE_DASHPTRN); - writeMemberDataSize(dashCntByteCnt + dashPtrnByteCnt); - strokeDataByteCnt += writeMemberData(&dashCnt, dashCntByteCnt); - strokeDataByteCnt += writeMemberData(dashPattern, dashPtrnByteCnt); - strokeDataByteCnt += SIZE(TvgBinTag) + SIZE(TvgBinCounter); + TvgBinCounter dashCntSize = sizeof(dashCnt); + TvgBinCounter dashPtrnSize = dashCnt * sizeof(dashPattern[0]); + + writeTag(TVG_TAG_SHAPE_STROKE_DASHPTRN); + writeCount(dashCntSize + dashPtrnSize); + cnt += writeData(&dashCnt, dashCntSize); + cnt += writeData(dashPattern, dashPtrnSize); + cnt += SIZE(TvgBinTag) + SIZE(TvgBinCounter); } - writeMemberDataSizeAt(strokeDataByteCnt); + writeReservedCount(cnt); - return SIZE(TvgBinTag) + SIZE(TvgBinCounter) + strokeDataByteCnt; + return SERIAL_DONE(cnt); } - TvgBinCounter serializeShapePath(const Shape* shape) + TvgBinCounter serializePath(const Shape* shape) { const PathCommand* cmds = nullptr; - uint32_t cmdCnt = shape->pathCommands(&cmds); + auto cmdCnt = shape->pathCommands(&cmds); const Point* pts = nullptr; - uint32_t ptsCnt = shape->pathCoords(&pts); - - if (!cmds || !pts || !cmdCnt || !ptsCnt) return 0; + auto ptsCnt = shape->pathCoords(&pts); - TvgBinCounter pathDataByteCnt = 0; + if (!cmds || !pts || cmdCnt == 0 || ptsCnt == 0) return 0; - writeMemberIndicator(TVG_TAG_SHAPE_PATH); - skipInBufferMemberDataSize(); + writeTag(TVG_TAG_SHAPE_PATH); + reserveCount(); - pathDataByteCnt += writeMemberData(&cmdCnt, sizeof(cmdCnt)); - pathDataByteCnt += writeMemberData(&ptsCnt, sizeof(ptsCnt)); - pathDataByteCnt += writeMemberData(cmds, cmdCnt * sizeof(cmds[0])); - pathDataByteCnt += writeMemberData(pts, ptsCnt * sizeof(pts[0])); + auto cnt = writeData(&cmdCnt, sizeof(cmdCnt)); + cnt += writeData(&ptsCnt, sizeof(ptsCnt)); + cnt += writeData(cmds, cmdCnt * sizeof(cmds[0])); + cnt += writeData(pts, ptsCnt * sizeof(pts[0])); - writeMemberDataSizeAt(pathDataByteCnt); + writeReservedCount(cnt); - return SIZE(TvgBinTag) + SIZE(TvgBinCounter) + pathDataByteCnt; + return SERIAL_DONE(cnt); } - TvgBinCounter serialize(const Shape* shape) + TvgBinCounter serializeShape(const Shape* shape) { - writeMemberIndicator(TVG_TAG_CLASS_SHAPE); - skipInBufferMemberDataSize(); + writeTag(TVG_TAG_CLASS_SHAPE); + reserveCount(); - auto ruleTvgBinFlag = (shape->fillRule() == FillRule::EvenOdd) ? TVG_FLAG_SHAPE_FILLRULE_EVENODD : TVG_FLAG_SHAPE_FILLRULE_WINDING; - auto shapeDataByteCnt = writeMember(TVG_TAG_SHAPE_FILLRULE, SIZE(TvgBinFlag), &ruleTvgBinFlag); + //fill rule + auto flag = (shape->fillRule() == FillRule::EvenOdd) ? TVG_FLAG_SHAPE_FILLRULE_EVENODD : TVG_FLAG_SHAPE_FILLRULE_WINDING; + auto cnt = writeTagProperty(TVG_TAG_SHAPE_FILLRULE, SIZE(TvgBinFlag), &flag); - if (shape->strokeWidth() > 0) shapeDataByteCnt += serializeShapeStroke(shape); + //stroke + if (shape->strokeWidth() > 0) cnt += serializeStroke(shape); + //fill if (auto fill = shape->fill()) { - shapeDataByteCnt += serializeShapeFill(fill, TVG_TAG_SHAPE_FILL); + cnt += serializeFill(fill, TVG_TAG_SHAPE_FILL); } else { uint8_t color[4] = {0, 0, 0, 0}; shape->fillColor(color, color + 1, color + 2, color + 3); - shapeDataByteCnt += writeMember(TVG_TAG_SHAPE_COLOR, sizeof(color), color); + cnt += writeTagProperty(TVG_TAG_SHAPE_COLOR, sizeof(color), color); } - shapeDataByteCnt += serializeShapePath(shape); - shapeDataByteCnt += serializePaint(shape); + cnt += serializePath(shape); + cnt += serializePaint(shape); - writeMemberDataSizeAt(shapeDataByteCnt); + writeReservedCount(cnt); - return SIZE(TvgBinTag) + SIZE(TvgBinCounter) + shapeDataByteCnt; + return SERIAL_DONE(cnt); } - TvgBinCounter serialize(const Picture* picture) + TvgBinCounter serializePicture(const Picture* picture) { - auto pixels = picture->data(); - - TvgBinCounter pictureDataByteCnt = 0; - - writeMemberIndicator(TVG_TAG_CLASS_PICTURE); - skipInBufferMemberDataSize(); - - if (pixels) { - //TODO - loader expects uints - float vw, vh; - picture->viewbox(nullptr, nullptr, &vw, &vh); - - uint32_t w = static_cast(vw); - uint32_t h = static_cast(vh); - TvgBinCounter wByteCnt = sizeof(w); // same as h size - TvgBinCounter pixelsByteCnt = w * h * sizeof(pixels[0]); - - writeMemberIndicator(TVG_TAG_PICTURE_RAW_IMAGE); - writeMemberDataSize(2 * wByteCnt + pixelsByteCnt); - pictureDataByteCnt += writeMemberData(&w, wByteCnt); - pictureDataByteCnt += writeMemberData(&h, wByteCnt); - pictureDataByteCnt += writeMemberData(pixels, pixelsByteCnt); - pictureDataByteCnt += SIZE(TvgBinTag) + SIZE(TvgBinCounter); + writeTag(TVG_TAG_CLASS_PICTURE); + reserveCount(); + + TvgBinCounter cnt = 0; + + //Bitmap Image + if (auto pixels = picture->data()) { + //TODO: Loader expects uints + float fw, fh; + picture->size(&fw, &fh); + + auto w = static_cast(fw); + auto h = static_cast(fh); + TvgBinCounter sizeCnt = sizeof(w); + TvgBinCounter imgSize = w * h * sizeof(pixels[0]); + + writeTag(TVG_TAG_PICTURE_RAW_IMAGE); + writeCount(2 * sizeCnt + imgSize); + + cnt += writeData(&w, sizeCnt); + cnt += writeData(&h, sizeCnt); + cnt += writeData(pixels, imgSize); + cnt += SIZE(TvgBinTag) + SIZE(TvgBinCounter); + //Vector Image } else { - pictureDataByteCnt += serializeChildren(picture); + cnt += serializeChildren(picture); } - pictureDataByteCnt += serializePaint(picture); + cnt += serializePaint(picture); - writeMemberDataSizeAt(pictureDataByteCnt); + writeReservedCount(cnt); - return SIZE(TvgBinTag) + SIZE(TvgBinCounter) + pictureDataByteCnt; + return SERIAL_DONE(cnt); } TvgBinCounter serializeComposite(const Paint* cmpTarget, CompositeMethod cmpMethod) { - TvgBinCounter cmpDataByteCnt = 0; + writeTag(TVG_TAG_PAINT_CMP_TARGET); + reserveCount(); - writeMemberIndicator(TVG_TAG_PAINT_CMP_TARGET); - skipInBufferMemberDataSize(); + auto flag = static_cast(cmpMethod); + auto cnt = writeTagProperty(TVG_TAG_PAINT_CMP_METHOD, SIZE(TvgBinFlag), &flag); - auto cmpMethodTvgBinFlag = static_cast(cmpMethod); - cmpDataByteCnt += writeMember(TVG_TAG_PAINT_CMP_METHOD, SIZE(TvgBinFlag), &cmpMethodTvgBinFlag); + cnt += serialize(cmpTarget); - cmpDataByteCnt += serialize(cmpTarget); + writeReservedCount(cnt); - writeMemberDataSizeAt(cmpDataByteCnt); - - return SIZE(TvgBinTag) + SIZE(TvgBinCounter) + cmpDataByteCnt; + return SERIAL_DONE(cnt); } TvgBinCounter serializeChildren(const Paint* paint) { - TvgBinCounter dataByteCnt = 0; - auto it = paint->pImpl->iterator(); + if (!it) return 0; - while (auto p = it->next()) { - dataByteCnt += serialize(p); - } + TvgBinCounter cnt = 0; + + while (auto p = it->next()) + cnt += serialize(p); delete(it); - return dataByteCnt; + return cnt; } TvgBinCounter serialize(const Paint* paint) @@ -367,9 +381,9 @@ struct Saver::Impl if (!paint) return 0; switch (paint->id()) { - case TVG_CLASS_ID_SHAPE: return serialize(static_cast(paint)); - case TVG_CLASS_ID_SCENE: return serialize(static_cast(paint)); - case TVG_CLASS_ID_PICTURE: return serialize(static_cast(paint)); + case TVG_CLASS_ID_SHAPE: return serializeShape(static_cast(paint)); + case TVG_CLASS_ID_SCENE: return serializeScene(static_cast(paint)); + case TVG_CLASS_ID_PICTURE: return serializePicture(static_cast(paint)); } return 0; @@ -386,7 +400,7 @@ struct Saver::Impl if (!writeHeader()) return false; if (serialize(paint) == 0) return false; - if (!bufferToFile(path)) return false; + if (!flushTo(path)) return false; return true; } -- 2.7.4 From b75c8ee506ca03eb59120069ea84b19928f67735 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Wed, 21 Jul 2021 17:31:42 +0900 Subject: [PATCH 06/16] tvg_saver: introduce a new module tvg saver tvg saver is a new module to export tvg files. In this patch, it also contains the infrastructure of saver module to expand other types of savers such as png, jpg, etc. To save the tvg file from a paint, you can use the Saver feature, for example: auto saver = tvg::Saver::gen(); saver->save(paint, "sample.tvg"); saver->sync(); Later, you can read the "sample.tvg" using Picture. auto picture = tvg::Picture::gen(); picture->load("sample.tvg"); ... The behavior of the saver will work on sync/async based on the threading setting of the initializer. Thus if you wish to have a benefit of it, you must call sync() after the save() in the proper delayed time. Otherwise, you can call sync() immediately. Note that, the asynchronous tasking is depent on the saver module implementation. Also, you need to enable tvg saver/loader modules from meson option. (yet this feature is under the beta) @API Addition: Result Saver::save(std::unique_ptr paint, const std::string& path) noexcept; Result Saver::sync() noexcept; @Examples: tvgSaver @Co-author: Mira Grudzinska --- inc/thorvg.h | 5 +- meson.build | 16 +- meson_options.txt | 6 + src/examples/TvgSaver.cpp | 8 +- src/lib/meson.build | 2 +- src/lib/tvgCommon.h | 2 + src/lib/tvgLoaderMgr.h | 2 - src/lib/tvgPaint.cpp | 2 + src/lib/tvgPaint.h | 1 + src/lib/tvgPictureImpl.h | 4 +- src/lib/tvgSaver.cpp | 85 +++++++- src/lib/tvgSaver.h | 47 +++++ src/lib/tvgSaverImpl.h | 409 -------------------------------------- src/loaders/meson.build | 1 - src/meson.build | 3 +- src/savers/meson.build | 10 + src/savers/tvg/meson.build | 9 + src/savers/tvg/tvgTvgSaver.cpp | 434 +++++++++++++++++++++++++++++++++++++++++ src/savers/tvg/tvgTvgSaver.h | 70 +++++++ 19 files changed, 679 insertions(+), 437 deletions(-) create mode 100644 src/lib/tvgSaver.h delete mode 100644 src/lib/tvgSaverImpl.h create mode 100644 src/savers/meson.build create mode 100644 src/savers/tvg/meson.build create mode 100644 src/savers/tvg/tvgTvgSaver.cpp create mode 100644 src/savers/tvg/tvgTvgSaver.h diff --git a/inc/thorvg.h b/inc/thorvg.h index 308a109..b48d0f6 100644 --- a/inc/thorvg.h +++ b/inc/thorvg.h @@ -44,7 +44,7 @@ protected: \ friend Canvas; \ friend Scene; \ friend Picture; \ - friend Saver; + friend SaveModule; \ #define _TVG_DECALRE_IDENTIFIER() \ @@ -56,10 +56,10 @@ namespace tvg { class RenderMethod; +class SaveModule; class Scene; class Picture; class Canvas; -class Saver; /** * @defgroup ThorVG ThorVG @@ -1370,7 +1370,6 @@ public: _TVG_DECLARE_PRIVATE(Saver); }; - /** @}*/ } //namespace diff --git a/meson.build b/meson.build index 9a3717c..5563fbc 100644 --- a/meson.build +++ b/meson.build @@ -34,6 +34,10 @@ if get_option('loaders').contains('jpg') == true config_h.set10('THORVG_JPG_LOADER_SUPPORT', true) endif +if get_option('savers').contains('tvg') == true + config_h.set10('THORVG_TVG_SAVER_SUPPORT', true) +endif + if get_option('vectors').contains('avx') == true config_h.set10('THORVG_AVX_VECTOR_SUPPORT', true) endif @@ -73,11 +77,12 @@ Summary: Loader (SVG): @7@ Loader (PNG): @8@ Loader (JPG): @9@ - CAPI Binding: @10@ - Log Message: @11@ - Tests: @12@ - Examples: @13@ - Tool (Svg2Png): @14@ + Saver (TVG): @10@ + CAPI Binding: @11@ + Log Message: @12@ + Tests: @13@ + Examples: @14@ + Tool (Svg2Png): @15@ '''.format( meson.project_version(), @@ -90,6 +95,7 @@ Summary: get_option('loaders').contains('svg'), get_option('loaders').contains('png'), get_option('loaders').contains('jpg'), + get_option('savers').contains('tvg'), get_option('bindings').contains('capi'), get_option('log'), get_option('tests'), diff --git a/meson_options.txt b/meson_options.txt index 3ae98c0..3d72baf 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -10,6 +10,12 @@ option('loaders', value: ['svg'], description: 'Enable File Loaders in thorvg') +option('savers', + type: 'array', + choices: ['', 'tvg'], + value: [''], + description: 'Enable File Savers in thorvg') + option('vectors', type: 'array', choices: ['', 'avx'], diff --git a/src/examples/TvgSaver.cpp b/src/examples/TvgSaver.cpp index 181b8e9..1274460 100644 --- a/src/examples/TvgSaver.cpp +++ b/src/examples/TvgSaver.cpp @@ -179,12 +179,12 @@ void exportTvg() //save the tvg file auto saver = tvg::Saver::gen(); - if (saver->save(move(scene), EXAMPLE_DIR"/test.tvg") != tvg::Result::Success) { - cout << "Problem with saving the test.tvg file." << endl; + if (saver->save(move(scene), EXAMPLE_DIR"/test.tvg") == tvg::Result::Success) { + saver->sync(); + cout << "Successfully exported to test.tvg, Please check the result using PictureTvg!" << endl; return; } - - cout << "Successfully exported to test.tvg, Please check the result using PictureTvg!" << endl; + cout << "Problem with saving the test.tvg file. Did you enable TVG Saver?" << endl; } diff --git a/src/lib/meson.build b/src/lib/meson.build index c535560..372fe2d 100644 --- a/src/lib/meson.build +++ b/src/lib/meson.build @@ -18,7 +18,7 @@ source_file = [ 'tvgLoaderMgr.h', 'tvgPictureImpl.h', 'tvgRender.h', - 'tvgSaverImpl.h', + 'tvgSaver.h', 'tvgSceneImpl.h', 'tvgShapeImpl.h', 'tvgTaskScheduler.h', diff --git a/src/lib/tvgCommon.h b/src/lib/tvgCommon.h index 2fed7b3..a61670e 100644 --- a/src/lib/tvgCommon.h +++ b/src/lib/tvgCommon.h @@ -36,6 +36,8 @@ using namespace tvg; #define TVG_CLASS_ID_LINEAR 4 #define TVG_CLASS_ID_RADIAL 5 +enum class FileType { Tvg = 0, Svg, Raw, Png, Jpg, Unknown }; + //for MSVC Compat #ifdef _MSC_VER #define TVG_UNUSED diff --git a/src/lib/tvgLoaderMgr.h b/src/lib/tvgLoaderMgr.h index 18a8e8a..fb5893d 100644 --- a/src/lib/tvgLoaderMgr.h +++ b/src/lib/tvgLoaderMgr.h @@ -24,8 +24,6 @@ #include "tvgLoader.h" -enum class FileType { Tvg = 0, Svg, Raw, Png, Jpg, Unknown }; - struct LoaderMgr { static bool init(); diff --git a/src/lib/tvgPaint.cpp b/src/lib/tvgPaint.cpp index 7c539fc..2dbcadd 100644 --- a/src/lib/tvgPaint.cpp +++ b/src/lib/tvgPaint.cpp @@ -27,6 +27,8 @@ /* Internal Class Implementation */ /************************************************************************/ + + static inline bool FLT_SAME(float a, float b) { return (fabsf(a - b) < FLT_EPSILON); diff --git a/src/lib/tvgPaint.h b/src/lib/tvgPaint.h index 6ce5d1f..d4a67f6 100644 --- a/src/lib/tvgPaint.h +++ b/src/lib/tvgPaint.h @@ -27,6 +27,7 @@ namespace tvg { + struct Iterator { virtual ~Iterator() {} diff --git a/src/lib/tvgPictureImpl.h b/src/lib/tvgPictureImpl.h index 40e48e9..9a195dc 100644 --- a/src/lib/tvgPictureImpl.h +++ b/src/lib/tvgPictureImpl.h @@ -34,9 +34,7 @@ struct PictureIterator : Iterator { Paint* paint = nullptr; - PictureIterator(Paint* p) : paint(p) - { - } + PictureIterator(Paint* p) : paint(p) {} const Paint* next() override { diff --git a/src/lib/tvgSaver.cpp b/src/lib/tvgSaver.cpp index 5f50807..212d996 100644 --- a/src/lib/tvgSaver.cpp +++ b/src/lib/tvgSaver.cpp @@ -19,13 +19,69 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#include "tvgSaverImpl.h" -#include +#include "tvgCommon.h" +#include "tvgSaver.h" + +#ifdef THORVG_TVG_SAVER_SUPPORT + #include "tvgTvgSaver.h" +#endif /************************************************************************/ /* Internal Class Implementation */ /************************************************************************/ +struct Saver::Impl +{ + SaveModule* saveModule = nullptr; + ~Impl() + { + if (saveModule) delete(saveModule); + } +}; + + +static SaveModule* _find(FileType type) +{ + switch(type) { + case FileType::Tvg: { +#ifdef THORVG_TVG_SAVER_SUPPORT + return new TvgSaver; +#endif + break; + } + default: { + break; + } + } + +#ifdef THORVG_LOG_ENABLED + const char *format; + switch(type) { + case FileType::Tvg: { + format = "TVG"; + break; + } + default: { + format = "???"; + break; + } + } + printf("SAVER: %s format is not supported\n", format); +#endif + return nullptr; +} + + +static SaveModule* _find(const string& path) +{ + auto ext = path.substr(path.find_last_of(".") + 1); + if (!ext.compare("tvg")) { + return _find(FileType::Tvg); + } + return nullptr; +} + + /************************************************************************/ /* External Class Implementation */ /************************************************************************/ @@ -41,21 +97,34 @@ Saver::~Saver() } -Result Saver::save(std::unique_ptr paint, const std::string& path) noexcept +Result Saver::save(std::unique_ptr paint, const string& path) noexcept { + //Already on saving an other resource. + if (pImpl->saveModule) return Result::InsufficientCondition; + auto p = paint.release(); if (!p) return Result::MemoryCorruption; - if (this->pImpl->save(p, path)) return Result::Success; - - return Result::Unknown; + if (auto saveModule = _find(path)) { + if (saveModule->save(p, path)) { + pImpl->saveModule = saveModule; + return Result::Success; + } else { + return Result::Unknown; + } + } + return Result::NonSupport; } Result Saver::sync() noexcept { - if (this->pImpl->sync()) return Result::Success; - return Result::Unknown; + if (!pImpl->saveModule) return Result::InsufficientCondition; + pImpl->saveModule->close(); + delete(pImpl->saveModule); + pImpl->saveModule = nullptr; + + return Result::Success; } diff --git a/src/lib/tvgSaver.h b/src/lib/tvgSaver.h new file mode 100644 index 0000000..3586442 --- /dev/null +++ b/src/lib/tvgSaver.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#ifndef _TVG_SAVER_H_ +#define _TVG_SAVER_H_ + +#include "tvgPaint.h" + +namespace tvg +{ + +class SaveModule +{ +public: + virtual ~SaveModule() {} + + virtual bool save(Paint* paint, const string& path) = 0; + virtual bool close() = 0; + + //Utility Method: Iterator Delegator + Iterator* iterator(const Paint* paint) + { + return paint->pImpl->iterator(); + } +}; + +} + +#endif //_TVG_SAVER_H_ \ No newline at end of file diff --git a/src/lib/tvgSaverImpl.h b/src/lib/tvgSaverImpl.h deleted file mode 100644 index 9a83312..0000000 --- a/src/lib/tvgSaverImpl.h +++ /dev/null @@ -1,409 +0,0 @@ -/* - * Copyright (c) 2021 Samsung Electronics Co., Ltd. All rights reserved. - - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#ifndef _TVG_SAVER_IMPL_H_ -#define _TVG_SAVER_IMPL_H_ - -#include -#include -#include -#include "tvgPaint.h" -#include "tvgBinaryDesc.h" - -#define SIZE(A) sizeof(A) - -/************************************************************************/ -/* Internal Class Implementation */ -/************************************************************************/ - -static inline TvgBinCounter SERIAL_DONE(TvgBinCounter cnt) -{ - return SIZE(TvgBinTag) + SIZE(TvgBinCounter) + cnt; -} - -struct Saver::Impl -{ - Paint* paint = nullptr; //TODO: replace with Array - Array buffer; - - ~Impl() - { - sync(); - } - - bool sync() - { - if (paint) delete(paint); - - buffer.reset(); - - return true; - } - - bool flushTo(const std::string& path) - { - FILE* fp = fopen(path.c_str(), "w+"); - if (!fp) return false; - - if (fwrite(buffer.data, sizeof(char), buffer.count, fp) == 0) return false; - - fclose(fp); - - return true; - } - - bool writeHeader() - { - buffer.grow(TVG_HEADER_SIGNATURE_LENGTH + TVG_HEADER_VERSION_LENGTH); - - auto ptr = buffer.ptr(); - memcpy(ptr, TVG_HEADER_SIGNATURE, TVG_HEADER_SIGNATURE_LENGTH); - ptr += TVG_HEADER_SIGNATURE_LENGTH; - 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; - } - - void writeTag(TvgBinTag tag) - { - buffer.grow(SIZE(TvgBinTag)); - memcpy(buffer.ptr(), &tag, SIZE(TvgBinTag)); - buffer.count += SIZE(TvgBinTag); - } - - void writeCount(TvgBinCounter cnt) - { - buffer.grow(SIZE(TvgBinCounter)); - memcpy(buffer.ptr(), &cnt, SIZE(TvgBinCounter)); - buffer.count += SIZE(TvgBinCounter); - } - - void writeReservedCount(TvgBinCounter cnt) - { - memcpy(buffer.ptr() - cnt - SIZE(TvgBinCounter), &cnt, SIZE(TvgBinCounter)); - } - - void reserveCount() - { - buffer.grow(SIZE(TvgBinCounter)); - buffer.count += SIZE(TvgBinCounter); - } - - TvgBinCounter writeData(const void* data, TvgBinCounter cnt) - { - buffer.grow(cnt); - memcpy(buffer.ptr(), data, cnt); - buffer.count += cnt; - - return cnt; - } - - TvgBinCounter writeTagProperty(TvgBinTag tag, TvgBinCounter cnt, const void* data) - { - TvgBinCounter growCnt = SERIAL_DONE(cnt); - - buffer.grow(growCnt); - - auto ptr = buffer.ptr(); - - *ptr = tag; - ++ptr; - - memcpy(ptr, &cnt, SIZE(TvgBinCounter)); - ptr += SIZE(TvgBinCounter); - - memcpy(ptr, data, cnt); - ptr += cnt; - - buffer.count += growCnt; - - return growCnt; - } - - TvgBinCounter serializePaint(const Paint* paint) - { - TvgBinCounter cnt = 0; - - //opacity - auto opacity = paint->opacity(); - if (opacity < 255) { - cnt += writeTagProperty(TVG_TAG_PAINT_OPACITY, sizeof(opacity), &opacity); - } - - //transform - auto m = const_cast(paint)->transform(); - if (fabs(m.e11 - 1) > FLT_EPSILON || fabs(m.e12) > FLT_EPSILON || fabs(m.e13) > FLT_EPSILON || - fabs(m.e21) > FLT_EPSILON || fabs(m.e22 - 1) > FLT_EPSILON || fabs(m.e23) > FLT_EPSILON || - fabs(m.e31) > FLT_EPSILON || fabs(m.e32) > FLT_EPSILON || fabs(m.e33 - 1) > FLT_EPSILON) { - cnt += writeTagProperty(TVG_TAG_PAINT_TRANSFORM, sizeof(m), &m); - } - - //composite - const Paint* cmpTarget = nullptr; - auto cmpMethod = paint->composite(&cmpTarget); - if (cmpMethod != CompositeMethod::None && cmpTarget) { - cnt += serializeComposite(cmpTarget, cmpMethod); - } - - return cnt; - } - - TvgBinCounter serializeScene(const Scene* scene) - { - writeTag(TVG_TAG_CLASS_SCENE); - reserveCount(); - - auto cnt = serializeChildren(scene) + serializePaint(scene); - - writeReservedCount(cnt); - - return SERIAL_DONE(cnt); - } - - TvgBinCounter serializeFill(const Fill* fill, TvgBinTag tag) - { - const Fill::ColorStop* stops = nullptr; - auto stopsCnt = fill->colorStops(&stops); - if (!stops || stopsCnt == 0) return 0; - - writeTag(tag); - reserveCount(); - - TvgBinCounter cnt = 0; - - //radial fill - if (fill->id() == TVG_CLASS_ID_RADIAL) { - float args[3]; - static_cast(fill)->radial(args, args + 1,args + 2); - cnt += writeTagProperty(TVG_TAG_FILL_RADIAL_GRADIENT, sizeof(args), args); - //linear fill - } else { - float args[4]; - static_cast(fill)->linear(args, args + 1, args + 2, args + 3); - cnt += writeTagProperty(TVG_TAG_FILL_LINEAR_GRADIENT, sizeof(args), args); - } - - auto flag = static_cast(fill->spread()); - cnt += writeTagProperty(TVG_TAG_FILL_FILLSPREAD, SIZE(TvgBinFlag), &flag); - cnt += writeTagProperty(TVG_TAG_FILL_COLORSTOPS, stopsCnt * sizeof(stops), stops); - - writeReservedCount(cnt); - - return SERIAL_DONE(cnt); - } - - TvgBinCounter serializeStroke(const Shape* shape) - { - writeTag(TVG_TAG_SHAPE_STROKE); - reserveCount(); - - //cap - auto flag = static_cast(shape->strokeCap()); - auto cnt = writeTagProperty(TVG_TAG_SHAPE_STROKE_CAP, SIZE(TvgBinFlag), &flag); - - //join - flag = static_cast(shape->strokeJoin()); - cnt += writeTagProperty(TVG_TAG_SHAPE_STROKE_JOIN, SIZE(TvgBinFlag), &flag); - - //width - auto width = shape->strokeWidth(); - cnt += writeTagProperty(TVG_TAG_SHAPE_STROKE_WIDTH, sizeof(width), &width); - - //fill - if (auto fill = shape->strokeFill()) { - cnt += serializeFill(fill, TVG_TAG_SHAPE_STROKE_FILL); - } else { - uint8_t color[4] = {0, 0, 0, 0}; - shape->strokeColor(color, color + 1, color + 2, color + 3); - cnt += writeTagProperty(TVG_TAG_SHAPE_STROKE_COLOR, sizeof(color), &color); - } - - //dash - const float* dashPattern = nullptr; - auto dashCnt = shape->strokeDash(&dashPattern); - if (dashPattern && dashCnt > 0) { - TvgBinCounter dashCntSize = sizeof(dashCnt); - TvgBinCounter dashPtrnSize = dashCnt * sizeof(dashPattern[0]); - - writeTag(TVG_TAG_SHAPE_STROKE_DASHPTRN); - writeCount(dashCntSize + dashPtrnSize); - cnt += writeData(&dashCnt, dashCntSize); - cnt += writeData(dashPattern, dashPtrnSize); - cnt += SIZE(TvgBinTag) + SIZE(TvgBinCounter); - } - - writeReservedCount(cnt); - - return SERIAL_DONE(cnt); - } - - TvgBinCounter serializePath(const Shape* shape) - { - const PathCommand* cmds = nullptr; - auto cmdCnt = shape->pathCommands(&cmds); - const Point* pts = nullptr; - auto ptsCnt = shape->pathCoords(&pts); - - if (!cmds || !pts || cmdCnt == 0 || ptsCnt == 0) return 0; - - writeTag(TVG_TAG_SHAPE_PATH); - reserveCount(); - - auto cnt = writeData(&cmdCnt, sizeof(cmdCnt)); - cnt += writeData(&ptsCnt, sizeof(ptsCnt)); - cnt += writeData(cmds, cmdCnt * sizeof(cmds[0])); - cnt += writeData(pts, ptsCnt * sizeof(pts[0])); - - writeReservedCount(cnt); - - return SERIAL_DONE(cnt); - } - - TvgBinCounter serializeShape(const Shape* shape) - { - writeTag(TVG_TAG_CLASS_SHAPE); - reserveCount(); - - //fill rule - auto flag = (shape->fillRule() == FillRule::EvenOdd) ? TVG_FLAG_SHAPE_FILLRULE_EVENODD : TVG_FLAG_SHAPE_FILLRULE_WINDING; - auto cnt = writeTagProperty(TVG_TAG_SHAPE_FILLRULE, SIZE(TvgBinFlag), &flag); - - //stroke - if (shape->strokeWidth() > 0) cnt += serializeStroke(shape); - - //fill - if (auto fill = shape->fill()) { - cnt += serializeFill(fill, TVG_TAG_SHAPE_FILL); - } else { - uint8_t color[4] = {0, 0, 0, 0}; - shape->fillColor(color, color + 1, color + 2, color + 3); - cnt += writeTagProperty(TVG_TAG_SHAPE_COLOR, sizeof(color), color); - } - - cnt += serializePath(shape); - cnt += serializePaint(shape); - - writeReservedCount(cnt); - - return SERIAL_DONE(cnt); - } - - TvgBinCounter serializePicture(const Picture* picture) - { - writeTag(TVG_TAG_CLASS_PICTURE); - reserveCount(); - - TvgBinCounter cnt = 0; - - //Bitmap Image - if (auto pixels = picture->data()) { - //TODO: Loader expects uints - float fw, fh; - picture->size(&fw, &fh); - - auto w = static_cast(fw); - auto h = static_cast(fh); - TvgBinCounter sizeCnt = sizeof(w); - TvgBinCounter imgSize = w * h * sizeof(pixels[0]); - - writeTag(TVG_TAG_PICTURE_RAW_IMAGE); - writeCount(2 * sizeCnt + imgSize); - - cnt += writeData(&w, sizeCnt); - cnt += writeData(&h, sizeCnt); - cnt += writeData(pixels, imgSize); - cnt += SIZE(TvgBinTag) + SIZE(TvgBinCounter); - //Vector Image - } else { - cnt += serializeChildren(picture); - } - - cnt += serializePaint(picture); - - writeReservedCount(cnt); - - return SERIAL_DONE(cnt); - } - - TvgBinCounter serializeComposite(const Paint* cmpTarget, CompositeMethod cmpMethod) - { - writeTag(TVG_TAG_PAINT_CMP_TARGET); - reserveCount(); - - auto flag = static_cast(cmpMethod); - auto cnt = writeTagProperty(TVG_TAG_PAINT_CMP_METHOD, SIZE(TvgBinFlag), &flag); - - cnt += serialize(cmpTarget); - - writeReservedCount(cnt); - - return SERIAL_DONE(cnt); - } - - TvgBinCounter serializeChildren(const Paint* paint) - { - auto it = paint->pImpl->iterator(); - if (!it) return 0; - - TvgBinCounter cnt = 0; - - while (auto p = it->next()) - cnt += serialize(p); - - delete(it); - - return cnt; - } - - TvgBinCounter serialize(const Paint* paint) - { - if (!paint) return 0; - - switch (paint->id()) { - case TVG_CLASS_ID_SHAPE: return serializeShape(static_cast(paint)); - case TVG_CLASS_ID_SCENE: return serializeScene(static_cast(paint)); - case TVG_CLASS_ID_PICTURE: return serializePicture(static_cast(paint)); - } - - return 0; - } - - bool save(Paint* paint, const std::string& path) - { - //FIXME: use Array and remove sync() here - sync(); - - //TODO: Validate path - - this->paint = paint; - - if (!writeHeader()) return false; - if (serialize(paint) == 0) return false; - if (!flushTo(path)) return false; - - return true; - } -}; - -#endif //_TVG_SAVER_IMPL_H_ diff --git a/src/loaders/meson.build b/src/loaders/meson.build index 0e580b9..24b6544 100644 --- a/src/loaders/meson.build +++ b/src/loaders/meson.build @@ -14,7 +14,6 @@ endif if get_option('loaders').contains('jpg') == true subdir('jpg') - message('Enable JPG Loader') endif subdir('raw') diff --git a/src/meson.build b/src/meson.build index 119dec2..3302e33 100644 --- a/src/meson.build +++ b/src/meson.build @@ -15,10 +15,11 @@ endif subdir('lib') subdir('loaders') +subdir('savers') subdir('bindings') thread_dep = meson.get_compiler('cpp').find_library('pthread') -thorvg_lib_dep = [common_dep, loader_dep, binding_dep, thread_dep] +thorvg_lib_dep = [common_dep, loader_dep, saver_dep, binding_dep, thread_dep] thorvg_lib = library( 'thorvg', diff --git a/src/savers/meson.build b/src/savers/meson.build new file mode 100644 index 0000000..2b35e38 --- /dev/null +++ b/src/savers/meson.build @@ -0,0 +1,10 @@ +subsaver_dep = [] + +if get_option('savers').contains('tvg') == true + subdir('tvg') +endif + +saver_dep = declare_dependency( + dependencies: subsaver_dep, + include_directories : include_directories('.'), +) diff --git a/src/savers/tvg/meson.build b/src/savers/tvg/meson.build new file mode 100644 index 0000000..87eb992 --- /dev/null +++ b/src/savers/tvg/meson.build @@ -0,0 +1,9 @@ +source_file = [ + 'tvgTvgSaver.h', + 'tvgTvgSaver.cpp', +] + +subsaver_dep += [declare_dependency( + include_directories : include_directories('.'), + sources : source_file +)] diff --git a/src/savers/tvg/tvgTvgSaver.cpp b/src/savers/tvg/tvgTvgSaver.cpp new file mode 100644 index 0000000..ba9abbe --- /dev/null +++ b/src/savers/tvg/tvgTvgSaver.cpp @@ -0,0 +1,434 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#include +#include +#include +#include "tvgSaver.h" +#include "tvgTvgSaver.h" + +#define SIZE(A) sizeof(A) + +/************************************************************************/ +/* Internal Class Implementation */ +/************************************************************************/ + +static inline TvgBinCounter SERIAL_DONE(TvgBinCounter cnt) +{ + return SIZE(TvgBinTag) + SIZE(TvgBinCounter) + cnt; +} + + +bool TvgSaver::flushTo(const std::string& path) +{ + FILE* fp = fopen(path.c_str(), "w+"); + if (!fp) return false; + + if (fwrite(buffer.data, sizeof(char), buffer.count, fp) == 0) return false; + + fclose(fp); + + return true; +} + + +bool TvgSaver::writeHeader() +{ + buffer.grow(TVG_HEADER_SIGNATURE_LENGTH + TVG_HEADER_VERSION_LENGTH); + + auto ptr = buffer.ptr(); + memcpy(ptr, TVG_HEADER_SIGNATURE, TVG_HEADER_SIGNATURE_LENGTH); + ptr += TVG_HEADER_SIGNATURE_LENGTH; + 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; +} + + +void TvgSaver::writeTag(TvgBinTag tag) +{ + buffer.grow(SIZE(TvgBinTag)); + memcpy(buffer.ptr(), &tag, SIZE(TvgBinTag)); + buffer.count += SIZE(TvgBinTag); +} + + +void TvgSaver::writeCount(TvgBinCounter cnt) +{ + buffer.grow(SIZE(TvgBinCounter)); + memcpy(buffer.ptr(), &cnt, SIZE(TvgBinCounter)); + buffer.count += SIZE(TvgBinCounter); +} + + +void TvgSaver::writeReservedCount(TvgBinCounter cnt) +{ + memcpy(buffer.ptr() - cnt - SIZE(TvgBinCounter), &cnt, SIZE(TvgBinCounter)); +} + + +void TvgSaver::reserveCount() +{ + buffer.grow(SIZE(TvgBinCounter)); + buffer.count += SIZE(TvgBinCounter); +} + + +TvgBinCounter TvgSaver::writeData(const void* data, TvgBinCounter cnt) +{ + buffer.grow(cnt); + memcpy(buffer.ptr(), data, cnt); + buffer.count += cnt; + + return cnt; +} + + +TvgBinCounter TvgSaver::writeTagProperty(TvgBinTag tag, TvgBinCounter cnt, const void* data) +{ + auto growCnt = SERIAL_DONE(cnt); + + buffer.grow(growCnt); + + auto ptr = buffer.ptr(); + + *ptr = tag; + ++ptr; + + memcpy(ptr, &cnt, SIZE(TvgBinCounter)); + ptr += SIZE(TvgBinCounter); + + memcpy(ptr, data, cnt); + ptr += cnt; + + buffer.count += growCnt; + + return growCnt; +} + + +TvgBinCounter TvgSaver::serializePaint(const Paint* paint) +{ + TvgBinCounter cnt = 0; + + //opacity + auto opacity = paint->opacity(); + if (opacity < 255) { + cnt += writeTagProperty(TVG_TAG_PAINT_OPACITY, sizeof(opacity), &opacity); + } + + //transform + auto m = const_cast(paint)->transform(); + if (fabs(m.e11 - 1) > FLT_EPSILON || fabs(m.e12) > FLT_EPSILON || fabs(m.e13) > FLT_EPSILON || + fabs(m.e21) > FLT_EPSILON || fabs(m.e22 - 1) > FLT_EPSILON || fabs(m.e23) > FLT_EPSILON || + fabs(m.e31) > FLT_EPSILON || fabs(m.e32) > FLT_EPSILON || fabs(m.e33 - 1) > FLT_EPSILON) { + cnt += writeTagProperty(TVG_TAG_PAINT_TRANSFORM, sizeof(m), &m); + } + + //composite + const Paint* cmpTarget = nullptr; + auto cmpMethod = paint->composite(&cmpTarget); + if (cmpMethod != CompositeMethod::None && cmpTarget) { + cnt += serializeComposite(cmpTarget, cmpMethod); + } + + return cnt; +} + + +TvgBinCounter TvgSaver::serializeScene(const Scene* scene) +{ + writeTag(TVG_TAG_CLASS_SCENE); + reserveCount(); + + auto cnt = serializeChildren(scene) + serializePaint(scene); + + writeReservedCount(cnt); + + return SERIAL_DONE(cnt); +} + + +TvgBinCounter TvgSaver::serializeFill(const Fill* fill, TvgBinTag tag) +{ + const Fill::ColorStop* stops = nullptr; + auto stopsCnt = fill->colorStops(&stops); + if (!stops || stopsCnt == 0) return 0; + + writeTag(tag); + reserveCount(); + + TvgBinCounter cnt = 0; + + //radial fill + if (fill->id() == TVG_CLASS_ID_RADIAL) { + float args[3]; + static_cast(fill)->radial(args, args + 1,args + 2); + cnt += writeTagProperty(TVG_TAG_FILL_RADIAL_GRADIENT, sizeof(args), args); + //linear fill + } else { + float args[4]; + static_cast(fill)->linear(args, args + 1, args + 2, args + 3); + cnt += writeTagProperty(TVG_TAG_FILL_LINEAR_GRADIENT, sizeof(args), args); + } + + auto flag = static_cast(fill->spread()); + cnt += writeTagProperty(TVG_TAG_FILL_FILLSPREAD, SIZE(TvgBinFlag), &flag); + cnt += writeTagProperty(TVG_TAG_FILL_COLORSTOPS, stopsCnt * sizeof(stops), stops); + + writeReservedCount(cnt); + + return SERIAL_DONE(cnt); +} + + +TvgBinCounter TvgSaver::serializeStroke(const Shape* shape) +{ + writeTag(TVG_TAG_SHAPE_STROKE); + reserveCount(); + + //cap + auto flag = static_cast(shape->strokeCap()); + auto cnt = writeTagProperty(TVG_TAG_SHAPE_STROKE_CAP, SIZE(TvgBinFlag), &flag); + + //join + flag = static_cast(shape->strokeJoin()); + cnt += writeTagProperty(TVG_TAG_SHAPE_STROKE_JOIN, SIZE(TvgBinFlag), &flag); + + //width + auto width = shape->strokeWidth(); + cnt += writeTagProperty(TVG_TAG_SHAPE_STROKE_WIDTH, sizeof(width), &width); + + //fill + if (auto fill = shape->strokeFill()) { + cnt += serializeFill(fill, TVG_TAG_SHAPE_STROKE_FILL); + } else { + uint8_t color[4] = {0, 0, 0, 0}; + shape->strokeColor(color, color + 1, color + 2, color + 3); + cnt += writeTagProperty(TVG_TAG_SHAPE_STROKE_COLOR, sizeof(color), &color); + } + + //dash + const float* dashPattern = nullptr; + auto dashCnt = shape->strokeDash(&dashPattern); + if (dashPattern && dashCnt > 0) { + TvgBinCounter dashCntSize = sizeof(dashCnt); + TvgBinCounter dashPtrnSize = dashCnt * sizeof(dashPattern[0]); + + writeTag(TVG_TAG_SHAPE_STROKE_DASHPTRN); + writeCount(dashCntSize + dashPtrnSize); + cnt += writeData(&dashCnt, dashCntSize); + cnt += writeData(dashPattern, dashPtrnSize); + cnt += SIZE(TvgBinTag) + SIZE(TvgBinCounter); + } + + writeReservedCount(cnt); + + return SERIAL_DONE(cnt); +} + + +TvgBinCounter TvgSaver::serializePath(const Shape* shape) +{ + const PathCommand* cmds = nullptr; + auto cmdCnt = shape->pathCommands(&cmds); + const Point* pts = nullptr; + auto ptsCnt = shape->pathCoords(&pts); + + if (!cmds || !pts || cmdCnt == 0 || ptsCnt == 0) return 0; + + writeTag(TVG_TAG_SHAPE_PATH); + reserveCount(); + + auto cnt = writeData(&cmdCnt, sizeof(cmdCnt)); + cnt += writeData(&ptsCnt, sizeof(ptsCnt)); + cnt += writeData(cmds, cmdCnt * sizeof(cmds[0])); + cnt += writeData(pts, ptsCnt * sizeof(pts[0])); + + writeReservedCount(cnt); + + return SERIAL_DONE(cnt); +} + + +TvgBinCounter TvgSaver::serializeShape(const Shape* shape) +{ + writeTag(TVG_TAG_CLASS_SHAPE); + reserveCount(); + + //fill rule + auto flag = (shape->fillRule() == FillRule::EvenOdd) ? TVG_FLAG_SHAPE_FILLRULE_EVENODD : TVG_FLAG_SHAPE_FILLRULE_WINDING; + auto cnt = writeTagProperty(TVG_TAG_SHAPE_FILLRULE, SIZE(TvgBinFlag), &flag); + + //stroke + if (shape->strokeWidth() > 0) cnt += serializeStroke(shape); + + //fill + if (auto fill = shape->fill()) { + cnt += serializeFill(fill, TVG_TAG_SHAPE_FILL); + } else { + uint8_t color[4] = {0, 0, 0, 0}; + shape->fillColor(color, color + 1, color + 2, color + 3); + cnt += writeTagProperty(TVG_TAG_SHAPE_COLOR, sizeof(color), color); + } + + cnt += serializePath(shape); + cnt += serializePaint(shape); + + writeReservedCount(cnt); + + return SERIAL_DONE(cnt); +} + + +TvgBinCounter TvgSaver::serializePicture(const Picture* picture) +{ + writeTag(TVG_TAG_CLASS_PICTURE); + reserveCount(); + + TvgBinCounter cnt = 0; + + //Bitmap Image + if (auto pixels = picture->data()) { + //TODO: Loader expects uints + float fw, fh; + picture->size(&fw, &fh); + + auto w = static_cast(fw); + auto h = static_cast(fh); + TvgBinCounter sizeCnt = sizeof(w); + TvgBinCounter imgSize = w * h * sizeof(pixels[0]); + + writeTag(TVG_TAG_PICTURE_RAW_IMAGE); + writeCount(2 * sizeCnt + imgSize); + + cnt += writeData(&w, sizeCnt); + cnt += writeData(&h, sizeCnt); + cnt += writeData(pixels, imgSize); + cnt += SIZE(TvgBinTag) + SIZE(TvgBinCounter); + //Vector Image + } else { + cnt += serializeChildren(picture); + } + + cnt += serializePaint(picture); + + writeReservedCount(cnt); + + return SERIAL_DONE(cnt); +} + + +TvgBinCounter TvgSaver::serializeComposite(const Paint* cmpTarget, CompositeMethod cmpMethod) +{ + writeTag(TVG_TAG_PAINT_CMP_TARGET); + reserveCount(); + + auto flag = static_cast(cmpMethod); + auto cnt = writeTagProperty(TVG_TAG_PAINT_CMP_METHOD, SIZE(TvgBinFlag), &flag); + + cnt += serialize(cmpTarget); + + writeReservedCount(cnt); + + return SERIAL_DONE(cnt); +} + + +TvgBinCounter TvgSaver::serializeChildren(const Paint* paint) +{ + auto it = this->iterator(paint); + if (!it) return 0; + + TvgBinCounter cnt = 0; + + while (auto p = it->next()) + cnt += serialize(p); + + delete(it); + + return cnt; +} + + +TvgBinCounter TvgSaver::serialize(const Paint* paint) +{ + if (!paint) return 0; + + switch (paint->id()) { + case TVG_CLASS_ID_SHAPE: return serializeShape(static_cast(paint)); + case TVG_CLASS_ID_SCENE: return serializeScene(static_cast(paint)); + case TVG_CLASS_ID_PICTURE: return serializePicture(static_cast(paint)); + } + + return 0; +} + +void TvgSaver::run(unsigned tid) +{ + if (!writeHeader()) return; + if (serialize(paint) == 0) return; + if (!flushTo(path)) return; +} + + +/************************************************************************/ +/* External Class Implementation */ +/************************************************************************/ + +TvgSaver::~TvgSaver() +{ + close(); +} + +bool TvgSaver::close() +{ + this->done(); + + if (paint) { + delete(paint); + paint = nullptr; + } + if (path) { + free(path); + path = nullptr; + } + buffer.reset(); + return true; +} + + +bool TvgSaver::save(Paint* paint, const string& path) +{ + close(); + + this->path = strdup(path.c_str()); + if (!this->path) return false; + + this->paint = paint; + + TaskScheduler::request(this); + + return true; +} \ No newline at end of file diff --git a/src/savers/tvg/tvgTvgSaver.h b/src/savers/tvg/tvgTvgSaver.h new file mode 100644 index 0000000..908d94f --- /dev/null +++ b/src/savers/tvg/tvgTvgSaver.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2021 Samsung Electronics Co., Ltd. All rights reserved. + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#ifndef _TVG_TVGSAVER_H_ +#define _TVG_TVGSAVER_H_ + +#include "tvgArray.h" +#include "tvgBinaryDesc.h" +#include "tvgTaskScheduler.h" + +namespace tvg +{ + +class TvgSaver : public SaveModule, public Task +{ +private: + Array buffer; + Paint* paint = nullptr; + char *path = nullptr; + + bool flushTo(const std::string& path); + void reserveCount(); + + bool writeHeader(); + void writeTag(TvgBinTag tag); + void writeCount(TvgBinCounter cnt); + void writeReservedCount(TvgBinCounter cnt); + TvgBinCounter writeData(const void* data, TvgBinCounter cnt); + TvgBinCounter writeTagProperty(TvgBinTag tag, TvgBinCounter cnt, const void* data); + + TvgBinCounter serialize(const Paint* paint); + TvgBinCounter serializePaint(const Paint* paint); + TvgBinCounter serializeScene(const Scene* scene); + TvgBinCounter serializeShape(const Shape* shape); + TvgBinCounter serializePicture(const Picture* picture); + TvgBinCounter serializeFill(const Fill* fill, TvgBinTag tag); + TvgBinCounter serializeStroke(const Shape* shape); + TvgBinCounter serializePath(const Shape* shape); + TvgBinCounter serializeComposite(const Paint* cmpTarget, CompositeMethod cmpMethod); + TvgBinCounter serializeChildren(const Paint* paint); + +public: + ~TvgSaver(); + + bool save(Paint* paint, const string& path) override; + bool close() override; + void run(unsigned tid) override; +}; + +} + +#endif //_TVG_SAVE_MODULE_H_ \ No newline at end of file -- 2.7.4 From 3f0c30d59f603437821c12694f8086d931202618 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Thu, 22 Jul 2021 11:54:49 +0900 Subject: [PATCH 07/16] infra: add tvg saver in build test --- .github/workflows/actions.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/actions.yml b/.github/workflows/actions.yml index 0093408..1460758 100644 --- a/.github/workflows/actions.yml +++ b/.github/workflows/actions.yml @@ -17,13 +17,13 @@ jobs: run: | sudo apt-get update sudo apt-get install ninja-build gcc-multilib g++-multilib meson - + - name: Install TurboJPEG library run: sudo apt-get install libturbojpeg0-dev libjpeg8-dev - name: Build run: | - meson . build -Dlog=true -Dloaders="svg, tvg, png, jpg" + meson . build -Dlog=true -Dloaders="svg, tvg, png, jpg" -Dsavers="tvg" cd build sudo ninja -C . install @@ -39,13 +39,13 @@ jobs: sudo add-apt-repository ppa:niko2040/e19 sudo apt-get install ninja-build gcc-multilib g++-multilib meson sudo apt-get install libefl-dev - + - name: Install TurboJPEG library run: sudo apt-get install libturbojpeg0-dev libjpeg8-dev - name: Build run: | - meson . build -Dexamples=true -Dloaders="svg, tvg, png, jpg" + meson . build -Dexamples=true -Dloaders="svg, tvg, png, jpg" -Dsavers="tvg" cd build sudo ninja -C . install @@ -60,13 +60,13 @@ jobs: run: | sudo apt-get update sudo apt-get install ninja-build gcc-multilib g++-multilib libgtest-dev meson cmake cmake-data - + - name: Install TurboJPEG library run: sudo apt-get install libturbojpeg0-dev libjpeg8-dev - + - name: Install-ThorVG run: | - meson . build -Dloaders="svg, tvg, png, jpg" -Dbindings="capi" + meson . build -Dloaders="svg, tvg, png, jpg" -Dsavers="tvg" -Dbindings="capi" cd build sudo ninja -C . install cd .. @@ -74,7 +74,7 @@ jobs: - name: Build run: | - meson . build -Dtests=true -Dloaders="svg, tvg, png, jpg" -Dbindings="capi" --errorlogs + meson . build -Dtests=true -Dloaders="svg, tvg, png, jpg" -Dsavers="tvg" -Dbindings="capi" --errorlogs cd build sudo ninja -C . install test -- 2.7.4 From ca34d7f96aa58f0f58ac73156b32c97d125eafdf Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Thu, 22 Jul 2021 14:19:12 +0900 Subject: [PATCH 08/16] examples: replace sprintf() with snprintf() snprintf() is more preferred to use in preventing buffer overflow. --- src/examples/MultiCanvas.cpp | 2 +- src/examples/Stress.cpp | 2 +- src/examples/Svg.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/examples/MultiCanvas.cpp b/src/examples/MultiCanvas.cpp index 1bd6150..1e06b87 100644 --- a/src/examples/MultiCanvas.cpp +++ b/src/examples/MultiCanvas.cpp @@ -51,7 +51,7 @@ void tvgDrawCmds(tvg::Canvas* canvas, const char* path, const char* name) auto picture = tvg::Picture::gen(); char buf[PATH_MAX]; - sprintf(buf,"%s/%s", path, name); + snprintf(buf, sizeof(buf), "%s/%s", path, name); if (picture->load(buf) != tvg::Result::Success) return; diff --git a/src/examples/Stress.cpp b/src/examples/Stress.cpp index 9085731..b9a3bde 100644 --- a/src/examples/Stress.cpp +++ b/src/examples/Stress.cpp @@ -45,7 +45,7 @@ void svgDirCallback(const char* name, const char* path, void* data) auto picture = tvg::Picture::gen(); char buf[PATH_MAX]; - sprintf(buf, "/%s/%s", path, name); + snprintf(buf, sizeof(buf), "/%s/%s", path, name); if (picture->load(buf) != tvg::Result::Success) return; diff --git a/src/examples/Svg.cpp b/src/examples/Svg.cpp index 33cb982..880a2e2 100644 --- a/src/examples/Svg.cpp +++ b/src/examples/Svg.cpp @@ -43,7 +43,7 @@ void svgDirCallback(const char* name, const char* path, void* data) auto picture = tvg::Picture::gen(); char buf[PATH_MAX]; - sprintf(buf, "/%s/%s", path, name); + snprintf(buf, sizeof(buf), "/%s/%s", path, name); if (picture->load(buf) != tvg::Result::Success) return; -- 2.7.4 From 99245c7864df2775a44765646c43dbf2c50b34cb Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Thu, 22 Jul 2021 17:19:22 +0900 Subject: [PATCH 09/16] common: code refactoring. renamed loader classes same to Saver classes tvgLoaderMgr -> tvgLoader (tvgSaver) tvgLoader -> tvgLoadModule (tvgSaveModule) --- src/lib/meson.build | 6 ++--- src/lib/tvgInitializer.cpp | 2 +- src/lib/{tvgLoaderMgr.h => tvgLoadModule.h} | 38 +++++++++++++++++++++-------- src/lib/{tvgLoaderMgr.cpp => tvgLoader.cpp} | 18 +++++++------- src/lib/tvgLoader.h | 32 ++++++------------------ src/lib/tvgPictureImpl.h | 4 +-- src/lib/{tvgSaver.h => tvgSaveModule.h} | 6 ++--- src/lib/tvgSaver.cpp | 2 +- src/loaders/jpg/tvgJpgLoader.cpp | 2 +- src/loaders/jpg/tvgJpgLoader.h | 4 +-- src/loaders/png/tvgPngLoader.cpp | 2 +- src/loaders/png/tvgPngLoader.h | 5 ++-- src/loaders/raw/tvgRawLoader.cpp | 2 +- src/loaders/raw/tvgRawLoader.h | 4 +-- src/loaders/svg/tvgSvgLoader.cpp | 2 +- src/loaders/svg/tvgSvgLoader.h | 4 +-- src/loaders/tvg/tvgTvgLoader.cpp | 2 +- src/loaders/tvg/tvgTvgLoader.h | 4 +-- src/savers/tvg/tvgTvgSaver.cpp | 2 +- 19 files changed, 70 insertions(+), 71 deletions(-) rename src/lib/{tvgLoaderMgr.h => tvgLoadModule.h} (56%) rename src/lib/{tvgLoaderMgr.cpp => tvgLoader.cpp} (90%) rename src/lib/{tvgSaver.h => tvgSaveModule.h} (94%) diff --git a/src/lib/meson.build b/src/lib/meson.build index 372fe2d..5a7b70c 100644 --- a/src/lib/meson.build +++ b/src/lib/meson.build @@ -15,10 +15,10 @@ source_file = [ 'tvgBinaryDesc.h', 'tvgFill.h', 'tvgLoader.h', - 'tvgLoaderMgr.h', + 'tvgLoadModule.h', 'tvgPictureImpl.h', 'tvgRender.h', - 'tvgSaver.h', + 'tvgSaveModule.h', 'tvgSceneImpl.h', 'tvgShapeImpl.h', 'tvgTaskScheduler.h', @@ -28,7 +28,7 @@ source_file = [ 'tvgGlCanvas.cpp', 'tvgInitializer.cpp', 'tvgLinearGradient.cpp', - 'tvgLoaderMgr.cpp', + 'tvgLoader.cpp', 'tvgPaint.cpp', 'tvgPicture.cpp', 'tvgRadialGradient.cpp', diff --git a/src/lib/tvgInitializer.cpp b/src/lib/tvgInitializer.cpp index c36b02f..e5d7750 100644 --- a/src/lib/tvgInitializer.cpp +++ b/src/lib/tvgInitializer.cpp @@ -21,7 +21,7 @@ */ #include "tvgCommon.h" #include "tvgTaskScheduler.h" -#include "tvgLoaderMgr.h" +#include "tvgLoader.h" #ifdef THORVG_SW_RASTER_SUPPORT #include "tvgSwRenderer.h" diff --git a/src/lib/tvgLoaderMgr.h b/src/lib/tvgLoadModule.h similarity index 56% rename from src/lib/tvgLoaderMgr.h rename to src/lib/tvgLoadModule.h index fb5893d..04b8a9d 100644 --- a/src/lib/tvgLoaderMgr.h +++ b/src/lib/tvgLoadModule.h @@ -19,18 +19,36 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#ifndef _TVG_LOADER_MGR_H_ -#define _TVG_LOADER_MGR_H_ +#ifndef _TVG_LOAD_MODULE_H_ +#define _TVG_LOAD_MODULE_H_ -#include "tvgLoader.h" +#include "tvgCommon.h" -struct LoaderMgr +namespace tvg { - static bool init(); - static bool term(); - static shared_ptr loader(const string& path, bool* invalid); - static shared_ptr loader(const char* data, uint32_t size, bool copy); - static shared_ptr loader(const uint32_t* data, uint32_t w, uint32_t h, bool copy); + +class LoadModule +{ +public: + //default view box, if any. + float vx = 0; + float vy = 0; + float vw = 0; + float vh = 0; + float w = 0, h = 0; //default image size + bool preserveAspect = true; //keep aspect ratio by default. + + virtual ~LoadModule() {} + + virtual bool open(const string& path) { /* Not supported */ return false; }; + virtual bool open(const char* data, uint32_t size, bool copy) { /* Not supported */ return false; }; + virtual bool open(const uint32_t* data, uint32_t w, uint32_t h, bool copy) { /* Not supported */ return false; }; + virtual bool read() = 0; + virtual bool close() = 0; + virtual const uint32_t* pixels() { return nullptr; }; + virtual unique_ptr scene() { return nullptr; }; }; -#endif //_TVG_LOADER_MGR_H_ +} + +#endif //_TVG_LOAD_MODULE_H_ diff --git a/src/lib/tvgLoaderMgr.cpp b/src/lib/tvgLoader.cpp similarity index 90% rename from src/lib/tvgLoaderMgr.cpp rename to src/lib/tvgLoader.cpp index 425f85d..baea00e 100644 --- a/src/lib/tvgLoaderMgr.cpp +++ b/src/lib/tvgLoader.cpp @@ -19,7 +19,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#include "tvgLoaderMgr.h" +#include "tvgLoader.h" #ifdef THORVG_SVG_LOADER_SUPPORT #include "tvgSvgLoader.h" @@ -43,7 +43,7 @@ /* Internal Class Implementation */ /************************************************************************/ -static Loader* _find(FileType type) +static LoadModule* _find(FileType type) { switch(type) { case FileType::Svg: { @@ -114,7 +114,7 @@ static Loader* _find(FileType type) } -static Loader* _find(const string& path) +static LoadModule* _find(const string& path) { auto ext = path.substr(path.find_last_of(".") + 1); if (!ext.compare("svg")) return _find(FileType::Svg); @@ -146,12 +146,12 @@ bool LoaderMgr::term() } -shared_ptr LoaderMgr::loader(const string& path, bool* invalid) +shared_ptr LoaderMgr::loader(const string& path, bool* invalid) { *invalid = false; if (auto loader = _find(path)) { - if (loader->open(path)) return shared_ptr(loader); + if (loader->open(path)) return shared_ptr(loader); else delete(loader); *invalid = true; } @@ -159,12 +159,12 @@ shared_ptr LoaderMgr::loader(const string& path, bool* invalid) } -shared_ptr LoaderMgr::loader(const char* data, uint32_t size, bool copy) +shared_ptr LoaderMgr::loader(const char* data, uint32_t size, bool copy) { for (int i = 0; i < static_cast(FileType::Unknown); i++) { auto loader = _find(static_cast(i)); if (loader) { - if (loader->open(data, size, copy)) return shared_ptr(loader); + if (loader->open(data, size, copy)) return shared_ptr(loader); else delete(loader); } } @@ -172,12 +172,12 @@ shared_ptr LoaderMgr::loader(const char* data, uint32_t size, bool copy) } -shared_ptr LoaderMgr::loader(const uint32_t *data, uint32_t w, uint32_t h, bool copy) +shared_ptr LoaderMgr::loader(const uint32_t *data, uint32_t w, uint32_t h, bool copy) { for (int i = 0; i < static_cast(FileType::Unknown); i++) { auto loader = _find(static_cast(i)); if (loader) { - if (loader->open(data, w, h, copy)) return shared_ptr(loader); + if (loader->open(data, w, h, copy)) return shared_ptr(loader); else delete(loader); } } diff --git a/src/lib/tvgLoader.h b/src/lib/tvgLoader.h index 8887e89..9072769 100644 --- a/src/lib/tvgLoader.h +++ b/src/lib/tvgLoader.h @@ -22,33 +22,15 @@ #ifndef _TVG_LOADER_H_ #define _TVG_LOADER_H_ -#include "tvgCommon.h" +#include "tvgLoadModule.h" -namespace tvg +struct LoaderMgr { - -class Loader -{ -public: - //default view box, if any. - float vx = 0; - float vy = 0; - float vw = 0; - float vh = 0; - float w = 0, h = 0; //default image size - bool preserveAspect = true; //keep aspect ratio by default. - - virtual ~Loader() {} - - virtual bool open(const string& path) { /* Not supported */ return false; }; - virtual bool open(const char* data, uint32_t size, bool copy) { /* Not supported */ return false; }; - virtual bool open(const uint32_t* data, uint32_t w, uint32_t h, bool copy) { /* Not supported */ return false; }; - virtual bool read() = 0; - virtual bool close() = 0; - virtual const uint32_t* pixels() { return nullptr; }; - virtual unique_ptr scene() { return nullptr; }; + static bool init(); + static bool term(); + static shared_ptr loader(const string& path, bool* invalid); + static shared_ptr loader(const char* data, uint32_t size, bool copy); + static shared_ptr loader(const uint32_t* data, uint32_t w, uint32_t h, bool copy); }; -} - #endif //_TVG_LOADER_H_ diff --git a/src/lib/tvgPictureImpl.h b/src/lib/tvgPictureImpl.h index 9a195dc..c47f371 100644 --- a/src/lib/tvgPictureImpl.h +++ b/src/lib/tvgPictureImpl.h @@ -24,7 +24,7 @@ #include #include "tvgPaint.h" -#include "tvgLoaderMgr.h" +#include "tvgLoader.h" /************************************************************************/ /* Internal Class Implementation */ @@ -47,7 +47,7 @@ struct PictureIterator : Iterator struct Picture::Impl { - shared_ptr loader = nullptr; + shared_ptr loader = nullptr; Paint* paint = nullptr; uint32_t *pixels = nullptr; Picture *picture = nullptr; diff --git a/src/lib/tvgSaver.h b/src/lib/tvgSaveModule.h similarity index 94% rename from src/lib/tvgSaver.h rename to src/lib/tvgSaveModule.h index 3586442..4521b38 100644 --- a/src/lib/tvgSaver.h +++ b/src/lib/tvgSaveModule.h @@ -19,8 +19,8 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -#ifndef _TVG_SAVER_H_ -#define _TVG_SAVER_H_ +#ifndef _TVG_SAVE_MODULE_H_ +#define _TVG_SAVE_MODULE_H_ #include "tvgPaint.h" @@ -44,4 +44,4 @@ public: } -#endif //_TVG_SAVER_H_ \ No newline at end of file +#endif //_TVG_SAVE_MODULE_H_ \ No newline at end of file diff --git a/src/lib/tvgSaver.cpp b/src/lib/tvgSaver.cpp index 212d996..696ef19 100644 --- a/src/lib/tvgSaver.cpp +++ b/src/lib/tvgSaver.cpp @@ -20,7 +20,7 @@ * SOFTWARE. */ #include "tvgCommon.h" -#include "tvgSaver.h" +#include "tvgSaveModule.h" #ifdef THORVG_TVG_SAVER_SUPPORT #include "tvgTvgSaver.h" diff --git a/src/loaders/jpg/tvgJpgLoader.cpp b/src/loaders/jpg/tvgJpgLoader.cpp index 4a2ce3f..03efad2 100644 --- a/src/loaders/jpg/tvgJpgLoader.cpp +++ b/src/loaders/jpg/tvgJpgLoader.cpp @@ -22,7 +22,7 @@ #include #include -#include "tvgLoaderMgr.h" +#include "tvgLoader.h" #include "tvgJpgLoader.h" /************************************************************************/ diff --git a/src/loaders/jpg/tvgJpgLoader.h b/src/loaders/jpg/tvgJpgLoader.h index 0063da2..1aeaa04 100644 --- a/src/loaders/jpg/tvgJpgLoader.h +++ b/src/loaders/jpg/tvgJpgLoader.h @@ -25,13 +25,13 @@ using tjhandle = void*; //TODO: Use Task? -class JpgLoader : public Loader +class JpgLoader : public LoadModule { public: JpgLoader(); ~JpgLoader(); - using Loader::open; + using LoadModule::open; bool open(const string& path) override; bool open(const char* data, uint32_t size, bool copy) override; bool read() override; diff --git a/src/loaders/png/tvgPngLoader.cpp b/src/loaders/png/tvgPngLoader.cpp index 43c2cb1..d7c71e5 100755 --- a/src/loaders/png/tvgPngLoader.cpp +++ b/src/loaders/png/tvgPngLoader.cpp @@ -20,7 +20,7 @@ * SOFTWARE. */ -#include "tvgLoaderMgr.h" +#include "tvgLoader.h" #include "tvgPngLoader.h" PngLoader::PngLoader() diff --git a/src/loaders/png/tvgPngLoader.h b/src/loaders/png/tvgPngLoader.h index c7f3d4e..ab2c816 100755 --- a/src/loaders/png/tvgPngLoader.h +++ b/src/loaders/png/tvgPngLoader.h @@ -24,14 +24,13 @@ #include -//OPTIMIZE ME: Use Task? -class PngLoader : public Loader +class PngLoader : public LoadModule { public: PngLoader(); ~PngLoader(); - using Loader::open; + using LoadModule::open; bool open(const string& path) override; bool open(const char* data, uint32_t size, bool copy) override; bool read() override; diff --git a/src/loaders/raw/tvgRawLoader.cpp b/src/loaders/raw/tvgRawLoader.cpp index 2acfc3b..b358fe8 100644 --- a/src/loaders/raw/tvgRawLoader.cpp +++ b/src/loaders/raw/tvgRawLoader.cpp @@ -21,7 +21,7 @@ */ #include #include -#include "tvgLoaderMgr.h" +#include "tvgLoader.h" #include "tvgRawLoader.h" /************************************************************************/ diff --git a/src/loaders/raw/tvgRawLoader.h b/src/loaders/raw/tvgRawLoader.h index 153ce24..f6eed20 100644 --- a/src/loaders/raw/tvgRawLoader.h +++ b/src/loaders/raw/tvgRawLoader.h @@ -22,7 +22,7 @@ #ifndef _TVG_RAW_LOADER_H_ #define _TVG_RAW_LOADER_H_ -class RawLoader : public Loader +class RawLoader : public LoadModule { public: const uint32_t* content = nullptr; @@ -30,7 +30,7 @@ public: ~RawLoader(); - using Loader::open; + using LoadModule::open; bool open(const uint32_t* data, uint32_t w, uint32_t h, bool copy) override; bool read() override; bool close() override; diff --git a/src/loaders/svg/tvgSvgLoader.cpp b/src/loaders/svg/tvgSvgLoader.cpp index 6a04447..456c833 100644 --- a/src/loaders/svg/tvgSvgLoader.cpp +++ b/src/loaders/svg/tvgSvgLoader.cpp @@ -25,7 +25,7 @@ #include #include #include -#include "tvgLoaderMgr.h" +#include "tvgLoader.h" #include "tvgXmlParser.h" #include "tvgSvgLoader.h" #include "tvgSvgSceneBuilder.h" diff --git a/src/loaders/svg/tvgSvgLoader.h b/src/loaders/svg/tvgSvgLoader.h index c213d66..886af40 100644 --- a/src/loaders/svg/tvgSvgLoader.h +++ b/src/loaders/svg/tvgSvgLoader.h @@ -25,7 +25,7 @@ #include "tvgTaskScheduler.h" #include "tvgSvgLoaderCommon.h" -class SvgLoader : public Loader, public Task +class SvgLoader : public LoadModule, public Task { public: string filePath; @@ -40,7 +40,7 @@ public: SvgLoader(); ~SvgLoader(); - using Loader::open; + using LoadModule::open; bool open(const string& path) override; bool open(const char* data, uint32_t size, bool copy) override; diff --git a/src/loaders/tvg/tvgTvgLoader.cpp b/src/loaders/tvg/tvgTvgLoader.cpp index 5e793ec..706372b 100644 --- a/src/loaders/tvg/tvgTvgLoader.cpp +++ b/src/loaders/tvg/tvgTvgLoader.cpp @@ -22,7 +22,7 @@ #include #include -#include "tvgLoaderMgr.h" +#include "tvgLoader.h" #include "tvgTvgLoader.h" #include "tvgTvgLoadParser.h" diff --git a/src/loaders/tvg/tvgTvgLoader.h b/src/loaders/tvg/tvgTvgLoader.h index 155365d..cc2c183 100644 --- a/src/loaders/tvg/tvgTvgLoader.h +++ b/src/loaders/tvg/tvgTvgLoader.h @@ -25,7 +25,7 @@ #include "tvgTaskScheduler.h" -class TvgLoader : public Loader, public Task +class TvgLoader : public LoadModule, public Task { public: const char* data = nullptr; @@ -38,7 +38,7 @@ public: ~TvgLoader(); - using Loader::open; + using LoadModule::open; bool open(const string &path) override; bool open(const char *data, uint32_t size, bool copy) override; bool read() override; diff --git a/src/savers/tvg/tvgTvgSaver.cpp b/src/savers/tvg/tvgTvgSaver.cpp index ba9abbe..91364cf 100644 --- a/src/savers/tvg/tvgTvgSaver.cpp +++ b/src/savers/tvg/tvgTvgSaver.cpp @@ -22,7 +22,7 @@ #include #include #include -#include "tvgSaver.h" +#include "tvgSaveModule.h" #include "tvgTvgSaver.h" #define SIZE(A) sizeof(A) -- 2.7.4 From e8235340d5929e176018c7a804be9f56087bef9a Mon Sep 17 00:00:00 2001 From: Michal Maciola <71131832+mmaciola@users.noreply.github.com> Date: Thu, 22 Jul 2021 13:35:26 +0200 Subject: [PATCH 10/16] common: style fixes (#644) --- src/lib/sw_engine/tvgSwCommon.h | 2 +- src/lib/sw_engine/tvgSwMath.cpp | 2 +- src/lib/sw_engine/tvgSwRaster.cpp | 2 +- src/lib/sw_engine/tvgSwRle.cpp | 6 +++--- src/lib/tvgBezier.cpp | 4 ++-- src/loaders/png/tvgPngLoader.cpp | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/lib/sw_engine/tvgSwCommon.h b/src/lib/sw_engine/tvgSwCommon.h index d3c89e3..fa3b27b 100644 --- a/src/lib/sw_engine/tvgSwCommon.h +++ b/src/lib/sw_engine/tvgSwCommon.h @@ -70,7 +70,7 @@ struct SwPoint return {x - rhs.x, y - rhs.y}; } - bool operator==(const SwPoint& rhs ) const + bool operator==(const SwPoint& rhs) const { return (x == rhs.x && y == rhs.y); } diff --git a/src/lib/sw_engine/tvgSwMath.cpp b/src/lib/sw_engine/tvgSwMath.cpp index 2787d34..e39eeb0 100644 --- a/src/lib/sw_engine/tvgSwMath.cpp +++ b/src/lib/sw_engine/tvgSwMath.cpp @@ -271,7 +271,7 @@ int64_t mathMultiply(int64_t a, int64_t b) b = -b; s = -s; } - int64_t c = (a * b + 0x8000L ) >> 16; + int64_t c = (a * b + 0x8000L) >> 16; return (s > 0) ? c : -c; } diff --git a/src/lib/sw_engine/tvgSwRaster.cpp b/src/lib/sw_engine/tvgSwRaster.cpp index 169da04..804f679 100644 --- a/src/lib/sw_engine/tvgSwRaster.cpp +++ b/src/lib/sw_engine/tvgSwRaster.cpp @@ -49,7 +49,7 @@ static uint32_t _argbJoin(uint8_t r, uint8_t g, uint8_t b, uint8_t a) static bool _inverse(const Matrix* transform, Matrix* invM) { - // computes the inverse of a matrix m + //computes the inverse of a matrix m auto det = transform->e11 * (transform->e22 * transform->e33 - transform->e32 * transform->e23) - transform->e12 * (transform->e21 * transform->e33 - transform->e23 * transform->e31) + transform->e13 * (transform->e21 * transform->e32 - transform->e22 * transform->e31); diff --git a/src/lib/sw_engine/tvgSwRle.cpp b/src/lib/sw_engine/tvgSwRle.cpp index 2d3308d..34a2133 100644 --- a/src/lib/sw_engine/tvgSwRle.cpp +++ b/src/lib/sw_engine/tvgSwRle.cpp @@ -614,7 +614,7 @@ SwSpan* _intersectSpansRegion(const SwRleData *clip, const SwRleData *targetRle, auto clipSpans = clip->spans; auto clipEnd = clip->spans + clip->size; - while (spanCnt > 0 && spans < end ) { + while (spanCnt > 0 && spans < end) { if (clipSpans == clipEnd) { spans = end; break; @@ -680,7 +680,7 @@ SwSpan* _intersectMaskRegion(const SwRleData *clip, const SwRleData *targetRle, clipSpans1++; } - while (spanCnt && spans < end ) { + while (spanCnt && spans < end) { if (clipSpans > clipEnd) { spans = end; break; @@ -737,7 +737,7 @@ SwSpan* _intersectSpansRect(const SwBBox *bbox, const SwRleData *targetRle, SwSp auto maxx = minx + static_cast(bbox->max.x - bbox->min.x) - 1; auto maxy = miny + static_cast(bbox->max.y - bbox->min.y) - 1; - while (spanCnt && spans < end ) { + while (spanCnt && spans < end) { if (spans->y > maxy) { spans = end; break; diff --git a/src/lib/tvgBezier.cpp b/src/lib/tvgBezier.cpp index c27fe79..3577ccd 100644 --- a/src/lib/tvgBezier.cpp +++ b/src/lib/tvgBezier.cpp @@ -89,8 +89,8 @@ void bezSplitLeft(Bezier& cur, float at, Bezier& left) left.ctrl1.x = cur.start.x + at * (cur.ctrl1.x - cur.start.x); left.ctrl1.y = cur.start.y + at * (cur.ctrl1.y - cur.start.y); - left.ctrl2.x = cur.ctrl1.x + at * (cur.ctrl2.x - cur.ctrl1.x); // temporary holding spot - left.ctrl2.y = cur.ctrl1.y + at * (cur.ctrl2.y - cur.ctrl1.y); // temporary holding spot + left.ctrl2.x = cur.ctrl1.x + at * (cur.ctrl2.x - cur.ctrl1.x); //temporary holding spot + left.ctrl2.y = cur.ctrl1.y + at * (cur.ctrl2.y - cur.ctrl1.y); //temporary holding spot cur.ctrl2.x = cur.ctrl2.x + at * (cur.end.x - cur.ctrl2.x); cur.ctrl2.y = cur.ctrl2.y + at * (cur.end.y - cur.ctrl2.y); diff --git a/src/loaders/png/tvgPngLoader.cpp b/src/loaders/png/tvgPngLoader.cpp index d7c71e5..5677129 100755 --- a/src/loaders/png/tvgPngLoader.cpp +++ b/src/loaders/png/tvgPngLoader.cpp @@ -69,7 +69,7 @@ bool PngLoader::read() image->format = PNG_FORMAT_BGRA; buffer = static_cast(malloc(PNG_IMAGE_SIZE((*image)))); if (!buffer) { - // out of memory, only time when libpng doesnt free its data + //out of memory, only time when libpng doesnt free its data png_image_free(image); return false; } -- 2.7.4 From 39d599e75e3ea18f312b77ce5b1e2ed0c019649b Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Thu, 22 Jul 2021 13:00:59 +0900 Subject: [PATCH 11/16] apis: promote beta apis to the official ones. 3 api candidates has been verified since it's tagged in beta, we confirm that they are useful for tvg usages. Here list shows the candidates apis: @API Addition: Matrix Paint::transform() noexcept; CompositeMethod Paint::composite(const Paint** target) const noexcept; Result SwCanvas::mempool(MempoolPolicy policy) noexcept; --- inc/thorvg.h | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/inc/thorvg.h b/inc/thorvg.h index b48d0f6..20ca52c 100644 --- a/inc/thorvg.h +++ b/inc/thorvg.h @@ -247,7 +247,7 @@ public: * * @retval The augmented transformation matrix. * - * @BETA_API + * @since 0.4 */ Matrix transform() noexcept; @@ -1186,8 +1186,7 @@ public: /** * @brief Enumeration specifying the methods of Memory Pool behavior policy. - * - * @BETA_API + * @since 0.4 */ enum MempoolPolicy { @@ -1237,7 +1236,7 @@ public: * * @warning It's not allowed after pushing any paints. * - * @BETA_API + * @since 0.4 */ Result mempool(MempoolPolicy policy) noexcept; -- 2.7.4 From 7ad6a7ae5cd645aa132c0849b08fd25d9a4ec276 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Thu, 22 Jul 2021 13:10:30 +0900 Subject: [PATCH 12/16] doc: improved Saver documentation. --- inc/thorvg.h | 49 ++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 42 insertions(+), 7 deletions(-) diff --git a/inc/thorvg.h b/inc/thorvg.h index 20ca52c..05aa3c0 100644 --- a/inc/thorvg.h +++ b/inc/thorvg.h @@ -1339,7 +1339,17 @@ public: /** * @class Saver * - * @brief A class enabling saving a paint in a binary format. + * @brief A class for exporting a paint object into a specified file, from which to recover the paint data later. + * + * ThorVG provides a feature for exporting & importing paint data, the Saver has a role to export it to a file. + * Basically, this feature is useful when you need to save the composed scene or image from a paint object and recreate it later. + * + * The file format is decided by the extension name(i.e. "*.tvg") while the supported formats depend on the TVG packaging environment. + * If it doesn't support the file format, it will return the @c NonSuppport result by the save() method. + * + * Once you export a paint to the file successfully, you can recreate it using the Picture class. + * + * @see Picture::load() * * @BETA_API */ @@ -1349,21 +1359,46 @@ public: ~Saver(); /** - * @brief Saves all the paints from the tree in a binary format. + * @brief Export the given @p paint data to the given @p path * - * @param[in] paint The root paint to be saved with all its nodes. - * @param[in] path A path to the file, in which the data is to be saved. + * @param[in] paint The paint to be saved with all its associated properties. + * @param[in] path A path to the file, in which the paint data is to be saved. * * @retval Result::Success When succeed. - * @retval Result::InvalidArguments the @p path is invalid. - * @retval Result::FailedAllocation An internal error with a memory allocation for the Saver object. - * @retval Result::MemoryCorruption When casting in the internal function implementation failed. + * @retval Result::NonSupport When trying to save a file with an unknown extension nor non supported format. * @retval Result::Unknown Others. * + * @note Saving can be asynchronous if the assigned thread number is greater than zero. To guarantee the saving is done, call sync() afterwards. + * @see Saver::sync() + * + * @BETA_API */ Result save(std::unique_ptr paint, const std::string& path) noexcept; + + /** + * @brief Guarantees that the saving task is finished. + * + * The behavior of the saver will work on a sync/async basis, depending on the threading setting of the Initializer. + * Thus if you wish to have a benefit of it, you must call sync() after the save() in the proper delayed time. + * Otherwise, you can call sync() immediately. + * + * @return Result::Success when succeed. + * @return Result::InsufficientCondition otherwise. + * + * @note The asynchronous tasking is depend on the saver module implementation. + * @see Saver::save() + * + * @BETA_API + */ Result sync() noexcept; + /** + * @brief Creates a new Saver object. + * + * @return A new Saver object. + * + * @BETA_API + */ static std::unique_ptr gen() noexcept; _TVG_DECLARE_PRIVATE(Saver); -- 2.7.4 From 164ecdb87fc28a4a95752651bcd2238bd1a906c0 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Fri, 23 Jul 2021 14:46:31 +0900 Subject: [PATCH 13/16] svg_loader: code refactoring. clean up about logging before replacing it with TVGLOG() --- src/loaders/svg/tvgSvgLoader.cpp | 27 ++++----- src/loaders/svg/tvgSvgLoaderCommon.h | 1 + src/loaders/svg/tvgXmlParser.cpp | 107 ++++++++++++++++++++--------------- src/loaders/svg/tvgXmlParser.h | 6 +- 4 files changed, 76 insertions(+), 65 deletions(-) diff --git a/src/loaders/svg/tvgSvgLoader.cpp b/src/loaders/svg/tvgSvgLoader.cpp index 456c833..bd2b081 100644 --- a/src/loaders/svg/tvgSvgLoader.cpp +++ b/src/loaders/svg/tvgSvgLoader.cpp @@ -2484,49 +2484,50 @@ static void _styleInherit(SvgStyleProperty* child, const SvgStyleProperty* paren } +static void _inefficientNodeCheck(TVG_UNUSED SvgNode* node){ #ifdef THORVG_LOG_ENABLED -static void _inefficientNodeCheck(SvgNode* node){ - if (!node->display && node->type != SvgNodeType::ClipPath) printf("SVG: Inefficient elements used [Display is none][Node Type : %s]\n", simpleXmlNodeTypeToString(node->type).c_str()); - if (node->style->opacity == 0) printf("SVG: Inefficient elements used [Opacity is zero][Node Type : %s]\n", simpleXmlNodeTypeToString(node->type).c_str()); - if (node->style->fill.opacity == 0 && node->style->stroke.opacity == 0) printf("SVG: Inefficient elements used [Fill opacity and stroke opacity are zero][Node Type : %s]\n", simpleXmlNodeTypeToString(node->type).c_str()); + auto type = simpleXmlNodeTypeToString(node->type); + + if (!node->display && node->type != SvgNodeType::ClipPath) printf("SVG: Inefficient elements used [Display is none][Node Type : %s]\n", type); + if (node->style->opacity == 0) printf("SVG: Inefficient elements used [Opacity is zero][Node Type : %s]\n", type); + if (node->style->fill.opacity == 0 && node->style->stroke.opacity == 0) printf("SVG: Inefficient elements used [Fill opacity and stroke opacity are zero][Node Type : %s]\n", type); switch (node->type) { case SvgNodeType::Path: { - if (!node->node.path.path || node->node.path.path->empty()) printf("SVG: Inefficient elements used [Empty path][Node Type : %s]\n", simpleXmlNodeTypeToString(node->type).c_str()); + if (!node->node.path.path || node->node.path.path->empty()) printf("SVG: Inefficient elements used [Empty path][Node Type : %s]\n", type); break; } case SvgNodeType::Ellipse: { - if (node->node.ellipse.rx == 0 && node->node.ellipse.ry == 0) printf("SVG: Inefficient elements used [Size is zero][Node Type : %s]\n", simpleXmlNodeTypeToString(node->type).c_str()); + if (node->node.ellipse.rx == 0 && node->node.ellipse.ry == 0) printf("SVG: Inefficient elements used [Size is zero][Node Type : %s]\n", type); break; } case SvgNodeType::Polygon: case SvgNodeType::Polyline: { - if (node->node.polygon.pointsCount < 2) printf("SVG: Inefficient elements used [Invalid Polygon][Node Type : %s]\n", simpleXmlNodeTypeToString(node->type).c_str()); + if (node->node.polygon.pointsCount < 2) printf("SVG: Inefficient elements used [Invalid Polygon][Node Type : %s]\n", type); break; } case SvgNodeType::Circle: { - if (node->node.circle.r == 0) printf("SVG: Inefficient elements used [Size is zero][Node Type : %s]\n", simpleXmlNodeTypeToString(node->type).c_str()); + if (node->node.circle.r == 0) printf("SVG: Inefficient elements used [Size is zero][Node Type : %s]\n", type); break; } case SvgNodeType::Rect: { - if (node->node.rect.w == 0 && node->node.rect.h) printf("SVG: Inefficient elements used [Size is zero][Node Type : %s]\n", simpleXmlNodeTypeToString(node->type).c_str()); + if (node->node.rect.w == 0 && node->node.rect.h) printf("SVG: Inefficient elements used [Size is zero][Node Type : %s]\n", type); break; } case SvgNodeType::Line: { - if (node->node.line.x1 == node->node.line.x2 && node->node.line.y1 == node->node.line.y2) printf("SVG: Inefficient elements used [Size is zero][Node Type : %s]\n", simpleXmlNodeTypeToString(node->type).c_str()); + if (node->node.line.x1 == node->node.line.x2 && node->node.line.y1 == node->node.line.y2) printf("SVG: Inefficient elements used [Size is zero][Node Type : %s]\n", type); break; } default: break; } -} #endif +} + static void _updateStyle(SvgNode* node, SvgStyleProperty* parentStyle) { _styleInherit(node->style, parentStyle); -#ifdef THORVG_LOG_ENABLED _inefficientNodeCheck(node); -#endif auto child = node->child.data; for (uint32_t i = 0; i < node->child.count; ++i, ++child) { diff --git a/src/loaders/svg/tvgSvgLoaderCommon.h b/src/loaders/svg/tvgSvgLoaderCommon.h index 4a466f6..1854619 100644 --- a/src/loaders/svg/tvgSvgLoaderCommon.h +++ b/src/loaders/svg/tvgSvgLoaderCommon.h @@ -28,6 +28,7 @@ struct SvgNode; struct SvgStyleGradient; +//NOTE: Please update simpleXmlNodeTypeToString() as well. enum class SvgNodeType { Doc, diff --git a/src/loaders/svg/tvgXmlParser.cpp b/src/loaders/svg/tvgXmlParser.cpp index ed2a9b8..ce7cf4d 100644 --- a/src/loaders/svg/tvgXmlParser.cpp +++ b/src/loaders/svg/tvgXmlParser.cpp @@ -36,50 +36,6 @@ /************************************************************************/ #ifdef THORVG_LOG_ENABLED - -#include - -string simpleXmlNodeTypeToString(SvgNodeType type) -{ - switch (type) { - case SvgNodeType::Doc: return "Svg"; - case SvgNodeType::G: return "G"; - case SvgNodeType::Defs: return "Defs"; - case SvgNodeType::Animation: return "Animation"; - case SvgNodeType::Arc: return "Arc"; - case SvgNodeType::Circle: return "Circle"; - case SvgNodeType::Ellipse: return "Ellipse"; - case SvgNodeType::Image: return "Image"; - case SvgNodeType::Line: return "Line"; - case SvgNodeType::Path: return "Path"; - case SvgNodeType::Polygon: return "Polygon"; - case SvgNodeType::Polyline: return "Polyline"; - case SvgNodeType::Rect: return "Rect"; - case SvgNodeType::Text: return "Text"; - case SvgNodeType::TextArea: return "TextArea"; - case SvgNodeType::Tspan: return "Tspan"; - case SvgNodeType::Use: return "Use"; - case SvgNodeType::Video: return "Video"; - case SvgNodeType::ClipPath: return "ClipPath"; - case SvgNodeType::Mask: return "Mask"; - default: return "Unknown"; - } - return "Unknown"; -} - -bool isIgnoreUnsupportedLogElements(const char* tagName) -{ - const auto elementsNum = 1; - const char* const elements[] = { "title" }; - - for (unsigned int i = 0; i < elementsNum; ++i) { - if (!strncmp(tagName, elements[i], strlen(tagName))) { - return true; - } - } - return false; -} - bool _isIgnoreUnsupportedLogAttributes(const char* tagAttribute, const char* tagValue) { const auto attributesNum = 6; @@ -109,9 +65,9 @@ bool _isIgnoreUnsupportedLogAttributes(const char* tagAttribute, const char* tag } return false; } - #endif + static const char* _simpleXmlFindWhiteSpace(const char* itr, const char* itrEnd) { for (; itr < itrEnd; itr++) { @@ -253,6 +209,55 @@ static const char* _simpleXmlFindDoctypeChildEndTag(const char* itr, const char* /* External Class Implementation */ /************************************************************************/ +const char* simpleXmlNodeTypeToString(TVG_UNUSED SvgNodeType type) +{ +#ifdef THORVG_LOG_ENABLED + static const char* TYPE_NAMES[] = { + "Svg", + "G", + "Defs", + "Animation", + "Arc", + "Circle", + "Ellipse", + "Image", + "Line", + "Path", + "Polygon", + "Polyline", + "Rect", + "Text", + "TextArea", + "Tspan", + "Use", + "Video", + "ClipPath", + "Mask", + "Unknown", + }; + return TYPE_NAMES[(int) type]; +#endif + return nullptr; +} + + +bool isIgnoreUnsupportedLogElements(TVG_UNUSED const char* tagName) +{ +#ifdef THORVG_LOG_ENABLED + const auto elementsNum = 1; + const char* const elements[] = { "title" }; + + for (unsigned int i = 0; i < elementsNum; ++i) { + if (!strncmp(tagName, elements[i], strlen(tagName))) { + return true; + } + } + return false; +#else + return true; +#endif +} + bool simpleXmlParseAttributes(const char* buf, unsigned bufLength, simpleXMLAttributeCb func, const void* data) { @@ -313,7 +318,11 @@ bool simpleXmlParseAttributes(const char* buf, unsigned bufLength, simpleXMLAttr #ifdef THORVG_LOG_ENABLED if (!func((void*)data, tmpBuf, tval)) { - if (!_isIgnoreUnsupportedLogAttributes(tmpBuf, tval)) printf("SVG: Unsupported attributes used [Elements type: %s][Id : %s][Attribute: %s][Value: %s]\n", simpleXmlNodeTypeToString(((SvgLoaderData*)data)->svgParse->node->type).c_str(), ((SvgLoaderData*)data)->svgParse->node->id ? ((SvgLoaderData*)data)->svgParse->node->id->c_str() : "NO_ID", tmpBuf, tval ? tval : "NONE"); + if (!_isIgnoreUnsupportedLogAttributes(tmpBuf, tval)) { + auto type = simpleXmlNodeTypeToString(((SvgLoaderData*)data)->svgParse->node->type); + auto id = ((SvgLoaderData*)data)->svgParse->node->id ? ((SvgLoaderData*)data)->svgParse->node->id->c_str() : "NO_ID"; + printf("SVG: Unsupported attributes used [Elements type: %s][Id : %s][Attribute: %s][Value: %s]\n", type, id, tmpBuf, tval ? tval : "NONE"); + } } #else func((void*)data, tmpBuf, tval); @@ -510,7 +519,11 @@ bool simpleXmlParseW3CAttribute(const char* buf, simpleXMLAttributeCb func, cons #ifdef THORVG_LOG_ENABLED if (!func((void*)data, key, val)) { - if (!_isIgnoreUnsupportedLogAttributes(key, val)) printf("SVG: Unsupported attributes used [Elements type: %s][Id : %s][Attribute: %s][Value: %s]\n", simpleXmlNodeTypeToString(((SvgLoaderData*)data)->svgParse->node->type).c_str(), ((SvgLoaderData*)data)->svgParse->node->id ? ((SvgLoaderData*)data)->svgParse->node->id->c_str() : "NO_ID", key, val ? val : "NONE"); + if (!_isIgnoreUnsupportedLogAttributes(key, val)) { + auto type = simpleXmlNodeTypeToString(((SvgLoaderData*)data)->svgParse->node->type); + auto id = ((SvgLoaderData*)data)->svgParse->node->id ? ((SvgLoaderData*)data)->svgParse->node->id->c_str() : "NO_ID"; + printf("SVG: Unsupported attributes used [Elements type: %s][Id : %s][Attribute: %s][Value: %s]\n", type, id, key, val ? val : "NONE"); + } } #else func((void*)data, key, val); diff --git a/src/loaders/svg/tvgXmlParser.h b/src/loaders/svg/tvgXmlParser.h index f775819..86068af 100644 --- a/src/loaders/svg/tvgXmlParser.h +++ b/src/loaders/svg/tvgXmlParser.h @@ -51,11 +51,7 @@ bool simpleXmlParseAttributes(const char* buf, unsigned buflen, simpleXMLAttribu bool simpleXmlParse(const char* buf, unsigned buflen, bool strip, simpleXMLCb func, const void* data); bool simpleXmlParseW3CAttribute(const char* buf, simpleXMLAttributeCb func, const void* data); const char *simpleXmlFindAttributesTag(const char* buf, unsigned buflen); - -#ifdef THORVG_LOG_ENABLED -string simpleXmlNodeTypeToString(SvgNodeType type); - bool isIgnoreUnsupportedLogElements(const char* tagName); -#endif +const char* simpleXmlNodeTypeToString(SvgNodeType type); #endif //_TVG_SIMPLE_XML_PARSER_H_ -- 2.7.4 From 4d839028a3ca5875ad7224a8e81b607b59d8e63d Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Fri, 23 Jul 2021 12:05:53 +0900 Subject: [PATCH 14/16] common log: use the log macro to replace the print method easier. We can replace the system logger method by changing single line print source in common, This also helps to remove the THORVG_LOG_ENABLED macro from each use-cases. TVGLOG(): To print the hint & tip messages for users. TVGERR(): To print the error message for debugging. @Issues: https://github.com/Samsung/thorvg/issues/36 --- src/lib/gl_engine/tvgGlCommon.h | 4 ++-- src/lib/gl_engine/tvgGlProgram.cpp | 4 +--- src/lib/gl_engine/tvgGlRenderer.cpp | 4 ++-- src/lib/gl_engine/tvgGlShader.cpp | 6 +----- src/lib/sw_engine/tvgSwRaster.cpp | 36 ++++++++++++---------------------- src/lib/sw_engine/tvgSwRenderer.cpp | 4 +--- src/lib/sw_engine/tvgSwRle.cpp | 15 +++++--------- src/lib/tvgCommon.h | 22 ++++++++++++++------- src/lib/tvgLoader.cpp | 5 ++--- src/lib/tvgPaint.h | 1 - src/lib/tvgSaver.cpp | 4 ++-- src/loaders/svg/tvgSvgLoader.cpp | 34 +++++++++++++------------------- src/loaders/svg/tvgSvgSceneBuilder.cpp | 12 +++--------- src/loaders/svg/tvgXmlParser.cpp | 24 +++++++---------------- src/loaders/tvg/tvgTvgLoadParser.cpp | 6 ++---- 15 files changed, 69 insertions(+), 112 deletions(-) diff --git a/src/lib/gl_engine/tvgGlCommon.h b/src/lib/gl_engine/tvgGlCommon.h index fd8196e..c5bdbd6 100644 --- a/src/lib/gl_engine/tvgGlCommon.h +++ b/src/lib/gl_engine/tvgGlCommon.h @@ -34,7 +34,7 @@ do { \ GLenum glError = glGetError(); \ if(glError != GL_NO_ERROR) { \ - printf("glGetError() = %i (0x%.8x) at line %s : %i\n", glError, glError, __FILE__, __LINE__); \ + TVGERR("GL_ENGINE", "glGetError() = %i (0x%.8x)", glError, glError); \ assert(0); \ } \ } while(0) @@ -44,7 +44,7 @@ do { \ EGLint eglError = eglGetError(); \ if(eglError != EGL_SUCCESS) { \ - printf("eglGetError() = %i (0x%.8x) at line %s : %i\n", eglError, eglError, __FILE__, __LINE__); \ + TVGERR("GL_ENGINE", "eglGetError() = %i (0x%.8x)", eglError, eglError); \ assert(0); \ } \ } while(0) diff --git a/src/lib/gl_engine/tvgGlProgram.cpp b/src/lib/gl_engine/tvgGlProgram.cpp index b296568..e7a71b5 100644 --- a/src/lib/gl_engine/tvgGlProgram.cpp +++ b/src/lib/gl_engine/tvgGlProgram.cpp @@ -20,10 +20,8 @@ * SOFTWARE. */ -#include #include "tvgGlProgram.h" - /************************************************************************/ /* Internal Class Implementation */ /************************************************************************/ @@ -167,7 +165,7 @@ void GlProgram::linkProgram(std::shared_ptr shader) { char* infoLog = new char[infoLen]; glGetProgramInfoLog(progObj, infoLen, NULL, infoLog); - std::cout << "Error linking shader: " << infoLog << std::endl; + TVGERR("GL_ENGINE", "Error linking shader: %s", infoLog); delete[] infoLog; } diff --git a/src/lib/gl_engine/tvgGlRenderer.cpp b/src/lib/gl_engine/tvgGlRenderer.cpp index a5c0012..be2b752 100644 --- a/src/lib/gl_engine/tvgGlRenderer.cpp +++ b/src/lib/gl_engine/tvgGlRenderer.cpp @@ -332,7 +332,7 @@ void GlRenderer::drawPrimitive(GlShape& sdata, const Fill* fill, uint32_t primit auto matrix = sdata.geometry->getTransforMatrix(); switch (fill->id()) { - case FILL_ID_LINEAR: { + case TVG_CLASS_ID_LINEAR: { float x1, y1, x2, y2; GlLinearGradientRenderTask *renderTask = static_cast(mRenderTasks[GlRenderTask::RenderTypes::RT_LinGradient].get()); assert(renderTask); @@ -345,7 +345,7 @@ void GlRenderer::drawPrimitive(GlShape& sdata, const Fill* fill, uint32_t primit renderTask->setEndPosition(x2, y2); break; } - case FILL_ID_RADIAL: { + case TVG_CLASS_ID_RADIAL: { float x1, y1, r1; GlRadialGradientRenderTask *renderTask = static_cast(mRenderTasks[GlRenderTask::RenderTypes::RT_RadGradient].get()); assert(renderTask); diff --git a/src/lib/gl_engine/tvgGlShader.cpp b/src/lib/gl_engine/tvgGlShader.cpp index 42da89c..89c635f 100644 --- a/src/lib/gl_engine/tvgGlShader.cpp +++ b/src/lib/gl_engine/tvgGlShader.cpp @@ -20,10 +20,8 @@ * SOFTWARE. */ -#include #include "tvgGlShader.h" - /************************************************************************/ /* External Class Implementation */ /************************************************************************/ @@ -68,7 +66,6 @@ uint32_t GlShader::complileShader(uint32_t type, char* shaderSrc) // Create the shader object shader = glCreateShader(type); - assert(shader); // Load the shader source glShaderSource(shader, 1, &shaderSrc, NULL); @@ -89,11 +86,10 @@ uint32_t GlShader::complileShader(uint32_t type, char* shaderSrc) { char* infoLog = new char[infoLen]; glGetShaderInfoLog(shader, infoLen, NULL, infoLog); - std::cout << "Error compiling shader: " << infoLog << std::endl; + TVGERR("GL_ENGINE", "Error compiling shader: %s", infoLog); delete[] infoLog; } glDeleteShader(shader); - assert(0); } return shader; diff --git a/src/lib/sw_engine/tvgSwRaster.cpp b/src/lib/sw_engine/tvgSwRaster.cpp index 804f679..91a068d 100644 --- a/src/lib/sw_engine/tvgSwRaster.cpp +++ b/src/lib/sw_engine/tvgSwRaster.cpp @@ -121,9 +121,7 @@ static bool _translucentRectAlphaMask(SwSurface* surface, const SwBBox& region, auto h = static_cast(region.max.y - region.min.y); auto w = static_cast(region.max.x - region.min.x); -#ifdef THORVG_LOG_ENABLED - cout <<"SW_ENGINE: Rectangle Alpha Mask Composition" << endl; -#endif + TVGLOG("SW_ENGINE", "Rectangle Alpha Mask Composition"); auto cbuffer = surface->compositor->image.data + (region.min.y * surface->stride) + region.min.x; //compositor buffer @@ -145,9 +143,7 @@ static bool _translucentRectInvAlphaMask(SwSurface* surface, const SwBBox& regio auto h = static_cast(region.max.y - region.min.y); auto w = static_cast(region.max.x - region.min.x); -#ifdef THORVG_LOG_ENABLED - cout <<"SW_ENGINE: Rectangle Inverse Alpha Mask Composition" << endl; -#endif + TVGLOG("SW_ENGINE", "Rectangle Inverse Alpha Mask Composition"); auto cbuffer = surface->compositor->image.data + (region.min.y * surface->stride) + region.min.x; //compositor buffer @@ -216,9 +212,8 @@ static bool _translucentRle(SwSurface* surface, const SwRleData* rle, uint32_t c static bool _translucentRleAlphaMask(SwSurface* surface, const SwRleData* rle, uint32_t color) { -#ifdef THORVG_LOG_ENABLED - cout <<"SW_ENGINE: Rle Alpha Mask Composition" << endl; -#endif + TVGLOG("SW_ENGINE", "Rle Alpha Mask Composition"); + auto span = rle->spans; uint32_t src; auto cbuffer = surface->compositor->image.data; @@ -240,9 +235,8 @@ static bool _translucentRleAlphaMask(SwSurface* surface, const SwRleData* rle, u static bool _translucentRleInvAlphaMask(SwSurface* surface, SwRleData* rle, uint32_t color) { -#ifdef THORVG_LOG_ENABLED - cout <<"SW_ENGINE: Rle Inverse Alpha Mask Composition" << endl; -#endif + TVGLOG("SW_ENGINE", "Rle Inverse Alpha Mask Composition"); + auto span = rle->spans; uint32_t src; auto cbuffer = surface->compositor->image.data; @@ -402,9 +396,8 @@ static bool _translucentImage(SwSurface* surface, const uint32_t *img, uint32_t static bool _translucentImageAlphaMask(SwSurface* surface, const uint32_t *img, uint32_t w, TVG_UNUSED uint32_t h, uint32_t opacity, const SwBBox& region, const Matrix* invTransform) { -#ifdef THORVG_LOG_ENABLED - cout <<"SW_ENGINE: Transformed Image Alpha Mask Composition" << endl; -#endif + TVGLOG("SW_ENGINE", "Transformed Image Alpha Mask Composition"); + auto dbuffer = &surface->buffer[region.min.y * surface->stride + region.min.x]; auto cbuffer = &surface->compositor->image.data[region.min.y * surface->stride + region.min.x]; @@ -428,9 +421,8 @@ static bool _translucentImageAlphaMask(SwSurface* surface, const uint32_t *img, static bool _translucentImageInvAlphaMask(SwSurface* surface, const uint32_t *img, uint32_t w, uint32_t h, uint32_t opacity, const SwBBox& region, const Matrix* invTransform) { -#ifdef THORVG_LOG_ENABLED - cout <<"SW_ENGINE: Transformed Image Inverse Alpha Mask Composition" << endl; -#endif + TVGLOG("SW_ENGINE", "Transformed Image Inverse Alpha Mask Composition"); + auto dbuffer = &surface->buffer[region.min.y * surface->stride + region.min.x]; auto cbuffer = &surface->compositor->image.data[region.min.y * surface->stride + region.min.x]; @@ -491,9 +483,7 @@ static bool _translucentImageAlphaMask(SwSurface* surface, uint32_t *img, uint32 auto h2 = static_cast(region.max.y - region.min.y); auto w2 = static_cast(region.max.x - region.min.x); -#ifdef THORVG_LOG_ENABLED - cout <<"SW_ENGINE: Image Alpha Mask Composition" << endl; -#endif + TVGLOG("SW_ENGINE", "Image Alpha Mask Composition"); auto sbuffer = img + (region.min.y * w) + region.min.x; auto cbuffer = surface->compositor->image.data + (region.min.y * surface->stride) + region.min.x; //compositor buffer @@ -520,9 +510,7 @@ static bool _translucentImageInvAlphaMask(SwSurface* surface, uint32_t *img, uin auto h2 = static_cast(region.max.y - region.min.y); auto w2 = static_cast(region.max.x - region.min.x); -#ifdef THORVG_LOG_ENABLED - cout <<"SW_ENGINE: Image Inverse Alpha Mask Composition" << endl; -#endif + TVGLOG("SW_ENGINE", "Image Inverse Alpha Mask Composition"); auto sbuffer = img + (region.min.y * w) + region.min.x; auto cbuffer = surface->compositor->image.data + (region.min.y * surface->stride) + region.min.x; //compositor buffer diff --git a/src/lib/sw_engine/tvgSwRenderer.cpp b/src/lib/sw_engine/tvgSwRenderer.cpp index 2900ce4..b1b7a20 100644 --- a/src/lib/sw_engine/tvgSwRenderer.cpp +++ b/src/lib/sw_engine/tvgSwRenderer.cpp @@ -463,9 +463,7 @@ Compositor* SwRenderer::target(const RenderRegion& region) if (x + w > surface->w) w = (surface->w - x); if (y + h > surface->h) h = (surface->h - y); -#ifdef THORVG_LOG_ENABLED - printf("SW_ENGINE: Using intermediate composition [Region: %d %d %d %d]\n", x, y, w, h); -#endif + TVGLOG("SW_ENGINE", "Using intermediate composition [Region: %d %d %d %d]", x, y, w, h); cmp->compositor->recoverSfc = surface; cmp->compositor->recoverCmp = surface->compositor; diff --git a/src/lib/sw_engine/tvgSwRle.cpp b/src/lib/sw_engine/tvgSwRle.cpp index 34a2133..ca03be8 100644 --- a/src/lib/sw_engine/tvgSwRle.cpp +++ b/src/lib/sw_engine/tvgSwRle.cpp @@ -177,11 +177,11 @@ static void _horizLine(RleWorker& rw, SwCoord x, SwCoord y, SwCoord area, SwCoor //span has ushort coordinates. check limit overflow if (x >= SHRT_MAX) { - //LOG: x coordinate overflow! + TVGERR("SW_ENGINE", "X-coordiante overflow!"); x = SHRT_MAX; } if (y >= SHRT_MAX) { - //LOG: y coordinate overflow! + TVGERR("SW_ENGINE", "Y Coordiante overflow!"); y = SHRT_MAX; } @@ -589,7 +589,7 @@ static bool _decomposeOutline(RleWorker& rw) return true; invalid_outline: - //LOG: Invalid Outline! + TVGERR("SW_ENGINE", "Invalid Outline!"); return false; } @@ -927,9 +927,7 @@ void rleClipPath(SwRleData *rle, const SwRleData *clip) _replaceClipSpan(rle, spans, spansEnd - spans); -#ifdef THORVG_LOG_ENABLED - cout << "SW_ENGINE: Using ClipPath!" << endl; -#endif + TVGLOG("SW_ENGINE", "Using ClipPath!"); } @@ -942,9 +940,7 @@ void rleClipRect(SwRleData *rle, const SwBBox* clip) _replaceClipSpan(rle, spans, spansEnd - spans); -#ifdef THORVG_LOG_ENABLED - cout <<"SW_ENGINE: Using ClipRect!" << endl; -#endif + TVGLOG("SW_ENGINE", "Using ClipRect!"); } @@ -960,4 +956,3 @@ void rleAlphaMask(SwRleData *rle, const SwRleData *clip) _replaceClipSpan(rle, spans, spansEnd - spans); } - diff --git a/src/lib/tvgCommon.h b/src/lib/tvgCommon.h index a61670e..e8dd0b8 100644 --- a/src/lib/tvgCommon.h +++ b/src/lib/tvgCommon.h @@ -28,6 +28,16 @@ using namespace std; using namespace tvg; +//for MSVC Compat +#ifdef _MSC_VER + #define TVG_UNUSED + #define strncasecmp _strnicmp + #define strcasecmp _stricmp +#else + #define TVG_UNUSED __attribute__ ((__unused__)) +#endif + + //TVG class identifier values #define TVG_CLASS_ID_UNDEFINED 0 #define TVG_CLASS_ID_SHAPE 1 @@ -38,14 +48,12 @@ using namespace tvg; enum class FileType { Tvg = 0, Svg, Raw, Png, Jpg, Unknown }; -//for MSVC Compat -#ifdef _MSC_VER - #define TVG_UNUSED - #define strncasecmp _strnicmp - #define strcasecmp _stricmp +#ifdef THORVG_LOG_ENABLED + #define TVGLOG(tag, fmt, ...) fprintf(stdout, tag ": " fmt "\n", ##__VA_ARGS__) //Log Message for notifying user some useful info + #define TVGERR(tag, fmt, ...) fprintf(stderr, tag ": " fmt "\n", ##__VA_ARGS__) //Error Message for us to fix it #else - #define TVG_UNUSED __attribute__ ((__unused__)) + #define TVGERR(...) + #define TVGLOG(...) #endif - #endif //_TVG_COMMON_H_ \ No newline at end of file diff --git a/src/lib/tvgLoader.cpp b/src/lib/tvgLoader.cpp index baea00e..6073510 100644 --- a/src/lib/tvgLoader.cpp +++ b/src/lib/tvgLoader.cpp @@ -107,9 +107,8 @@ static LoadModule* _find(FileType type) break; } } - printf("LOADER: %s format is not supported\n", format); + TVGLOG("LOADER", "%s format is not supported", format); #endif - return nullptr; } @@ -182,4 +181,4 @@ shared_ptr LoaderMgr::loader(const uint32_t *data, uint32_t w, uint3 } } return nullptr; -} \ No newline at end of file +} diff --git a/src/lib/tvgPaint.h b/src/lib/tvgPaint.h index d4a67f6..6ce5d1f 100644 --- a/src/lib/tvgPaint.h +++ b/src/lib/tvgPaint.h @@ -27,7 +27,6 @@ namespace tvg { - struct Iterator { virtual ~Iterator() {} diff --git a/src/lib/tvgSaver.cpp b/src/lib/tvgSaver.cpp index 696ef19..1c5fafd 100644 --- a/src/lib/tvgSaver.cpp +++ b/src/lib/tvgSaver.cpp @@ -66,7 +66,7 @@ static SaveModule* _find(FileType type) break; } } - printf("SAVER: %s format is not supported\n", format); + TVGLOG("SAVER", "%s format is not supported", format); #endif return nullptr; } @@ -131,4 +131,4 @@ Result Saver::sync() noexcept unique_ptr Saver::gen() noexcept { return unique_ptr(new Saver); -} \ No newline at end of file +} diff --git a/src/loaders/svg/tvgSvgLoader.cpp b/src/loaders/svg/tvgSvgLoader.cpp index bd2b081..b547be4 100644 --- a/src/loaders/svg/tvgSvgLoader.cpp +++ b/src/loaders/svg/tvgSvgLoader.cpp @@ -760,7 +760,7 @@ static bool _attrParseSvgNode(void* data, const char* key, const char* value) } #ifdef THORVG_LOG_ENABLED else if (!strcmp(key, "x") || !strcmp(key, "y")) { - if (0.0f == _parseLength(value, &type)) printf("SVG: Unsupported attributes used [Elements type: Svg][Attribute: %s][Value: %s]\n", key, value); + if (0.0f == _parseLength(value, &type)) TVGLOG("SVG", "Unsupported attributes used [Elements type: Svg][Attribute: %s][Value: %s]", key, value); } #endif else { @@ -1340,7 +1340,6 @@ static bool _attrParsePolygonPoints(const char* str, float** points, int* ptCoun return true; error_alloc: - //LOG: allocation for point array failed. out of memory return false; } @@ -2378,21 +2377,16 @@ static void _svgLoaderParserXmlOpen(SvgLoaderData* loader, const char* content, loader->latestGradient = gradient; } else if (!strcmp(tagName, "stop")) { if (!loader->latestGradient) { -#ifdef THORVG_LOG_ENABLED - printf("SVG: Stop element is used outside of the Gradient element\n"); -#endif + TVGLOG("SVG", "Stop element is used outside of the Gradient element"); return; } /* default value for opacity */ loader->svgParse->gradStop = {0.0f, 0, 0, 0, 255}; simpleXmlParseAttributes(attrs, attrsLength, _attrParseStops, loader); loader->latestGradient->stops.push(loader->svgParse->gradStop); + } else if (!isIgnoreUnsupportedLogElements(tagName)) { + TVGLOG("SVG", "Unsupported elements used [Elements: %s]", tagName); } -#ifdef THORVG_LOG_ENABLED - else { - if (!isIgnoreUnsupportedLogElements(tagName)) printf("SVG: Unsupported elements used [Elements: %s]\n", tagName); - } -#endif } @@ -2488,34 +2482,34 @@ static void _inefficientNodeCheck(TVG_UNUSED SvgNode* node){ #ifdef THORVG_LOG_ENABLED auto type = simpleXmlNodeTypeToString(node->type); - if (!node->display && node->type != SvgNodeType::ClipPath) printf("SVG: Inefficient elements used [Display is none][Node Type : %s]\n", type); - if (node->style->opacity == 0) printf("SVG: Inefficient elements used [Opacity is zero][Node Type : %s]\n", type); - if (node->style->fill.opacity == 0 && node->style->stroke.opacity == 0) printf("SVG: Inefficient elements used [Fill opacity and stroke opacity are zero][Node Type : %s]\n", type); + if (!node->display && node->type != SvgNodeType::ClipPath) TVGLOG("SVG", "Inefficient elements used [Display is none][Node Type : %s]", type); + if (node->style->opacity == 0) TVGLOG("SVG", "Inefficient elements used [Opacity is zero][Node Type : %s]", type); + if (node->style->fill.opacity == 0 && node->style->stroke.opacity == 0) TVGLOG("SVG", "Inefficient elements used [Fill opacity and stroke opacity are zero][Node Type : %s]", type); switch (node->type) { case SvgNodeType::Path: { - if (!node->node.path.path || node->node.path.path->empty()) printf("SVG: Inefficient elements used [Empty path][Node Type : %s]\n", type); + if (!node->node.path.path || node->node.path.path->empty()) TVGLOG("SVG", "Inefficient elements used [Empty path][Node Type : %s]", type); break; } case SvgNodeType::Ellipse: { - if (node->node.ellipse.rx == 0 && node->node.ellipse.ry == 0) printf("SVG: Inefficient elements used [Size is zero][Node Type : %s]\n", type); + if (node->node.ellipse.rx == 0 && node->node.ellipse.ry == 0) TVGLOG("SVG", "Inefficient elements used [Size is zero][Node Type : %s]", type); break; } case SvgNodeType::Polygon: case SvgNodeType::Polyline: { - if (node->node.polygon.pointsCount < 2) printf("SVG: Inefficient elements used [Invalid Polygon][Node Type : %s]\n", type); + if (node->node.polygon.pointsCount < 2) TVGLOG("SVG", "Inefficient elements used [Invalid Polygon][Node Type : %s]", type); break; } case SvgNodeType::Circle: { - if (node->node.circle.r == 0) printf("SVG: Inefficient elements used [Size is zero][Node Type : %s]\n", type); + if (node->node.circle.r == 0) TVGLOG("SVG", "Inefficient elements used [Size is zero][Node Type : %s]", type); break; } case SvgNodeType::Rect: { - if (node->node.rect.w == 0 && node->node.rect.h) printf("SVG: Inefficient elements used [Size is zero][Node Type : %s]\n", type); + if (node->node.rect.w == 0 && node->node.rect.h) TVGLOG("SVG", "Inefficient elements used [Size is zero][Node Type : %s]", type); break; } case SvgNodeType::Line: { - if (node->node.line.x1 == node->node.line.x2 && node->node.line.y1 == node->node.line.y2) printf("SVG: Inefficient elements used [Size is zero][Node Type : %s]\n", type); + if (node->node.line.x1 == node->node.line.x2 && node->node.line.y1 == node->node.line.y2) TVGLOG("SVG", "Inefficient elements used [Size is zero][Node Type : %s]", type); break; } default: break; @@ -2810,7 +2804,7 @@ bool SvgLoader::header() preserveAspect = loaderData.doc->node.doc.preserveAspect; } else { - //LOG: No SVG File. There is no + TVGLOG("SVG", "No SVG File. There is no "); return false; } diff --git a/src/loaders/svg/tvgSvgSceneBuilder.cpp b/src/loaders/svg/tvgSvgSceneBuilder.cpp index 0c47ad3..aeea6a5 100644 --- a/src/loaders/svg/tvgSvgSceneBuilder.cpp +++ b/src/loaders/svg/tvgSvgSceneBuilder.cpp @@ -182,9 +182,7 @@ static void _applyComposition(Paint* paint, const SvgNode* node, float vx, float /* Do not drop in Circular Dependency for ClipPath. Composition can be applied recursively if its children nodes have composition target to this one. */ if (node->style->clipPath.applying) { -#ifdef THORVG_LOG_ENABLED - printf("SVG: Multiple Composition Tried! Check out Circular dependency?\n"); -#endif + TVGLOG("SVG", "Multiple Composition Tried! Check out Circular dependency?"); } else { auto compNode = node->style->clipPath.node; if (compNode && compNode->child.count > 0) { @@ -211,9 +209,7 @@ static void _applyComposition(Paint* paint, const SvgNode* node, float vx, float /* Do not drop in Circular Dependency for Mask. Composition can be applied recursively if its children nodes have composition target to this one. */ if (node->style->mask.applying) { -#ifdef THORVG_LOG_ENABLED - printf("SVG: Multiple Composition Tried! Check out Circular dependency?\n"); -#endif + TVGLOG("SVG", "Multiple Composition Tried! Check out Circular dependency?"); } else { auto compNode = node->style->mask.node; if (compNode && compNode->child.count > 0) { @@ -468,9 +464,7 @@ static unique_ptr _imageBuildHelper(SvgNode* node, float vx, float vy, //Temporarily disable embedded svg: const char *dot = strrchr(href, '.'); if (dot && !strcmp(dot, ".svg")) { -#ifdef THORVG_LOG_ENABLED - printf("SVG: Embedded svg file is disabled.\n"); -#endif + TVGLOG("SVG", "Embedded svg file is disabled."); return nullptr; } diff --git a/src/loaders/svg/tvgXmlParser.cpp b/src/loaders/svg/tvgXmlParser.cpp index ce7cf4d..01e4439 100644 --- a/src/loaders/svg/tvgXmlParser.cpp +++ b/src/loaders/svg/tvgXmlParser.cpp @@ -35,9 +35,9 @@ /* Internal Class Implementation */ /************************************************************************/ -#ifdef THORVG_LOG_ENABLED -bool _isIgnoreUnsupportedLogAttributes(const char* tagAttribute, const char* tagValue) +bool _isIgnoreUnsupportedLogAttributes(TVG_UNUSED const char* tagAttribute, TVG_UNUSED const char* tagValue) { +#ifdef THORVG_LOG_ENABLED const auto attributesNum = 6; const struct { @@ -64,8 +64,10 @@ bool _isIgnoreUnsupportedLogAttributes(const char* tagAttribute, const char* tag } } return false; -} #endif + return true; +} + static const char* _simpleXmlFindWhiteSpace(const char* itr, const char* itrEnd) @@ -316,17 +318,11 @@ bool simpleXmlParseAttributes(const char* buf, unsigned bufLength, simpleXMLAttr } tval[i] = '\0'; -#ifdef THORVG_LOG_ENABLED if (!func((void*)data, tmpBuf, tval)) { if (!_isIgnoreUnsupportedLogAttributes(tmpBuf, tval)) { - auto type = simpleXmlNodeTypeToString(((SvgLoaderData*)data)->svgParse->node->type); - auto id = ((SvgLoaderData*)data)->svgParse->node->id ? ((SvgLoaderData*)data)->svgParse->node->id->c_str() : "NO_ID"; - printf("SVG: Unsupported attributes used [Elements type: %s][Id : %s][Attribute: %s][Value: %s]\n", type, id, tmpBuf, tval ? tval : "NONE"); + TVGLOG("SVG", "Unsupported attributes used [Elements type: %s][Id : %s][Attribute: %s][Value: %s]", simpleXmlNodeTypeToString(((SvgLoaderData*)data)->svgParse->node->type), ((SvgLoaderData*)data)->svgParse->node->id ? ((SvgLoaderData*)data)->svgParse->node->id->c_str() : "NO_ID", tmpBuf, tval ? tval : "NONE"); } } -#else - func((void*)data, tmpBuf, tval); -#endif } return true; } @@ -517,17 +513,11 @@ bool simpleXmlParseW3CAttribute(const char* buf, simpleXMLAttributeCb func, cons val = const_cast(_simpleXmlSkipWhiteSpace(val, val + strlen(val))); val[_simpleXmlUnskipWhiteSpace(val + strlen(val) , val) - val] = '\0'; -#ifdef THORVG_LOG_ENABLED if (!func((void*)data, key, val)) { if (!_isIgnoreUnsupportedLogAttributes(key, val)) { - auto type = simpleXmlNodeTypeToString(((SvgLoaderData*)data)->svgParse->node->type); - auto id = ((SvgLoaderData*)data)->svgParse->node->id ? ((SvgLoaderData*)data)->svgParse->node->id->c_str() : "NO_ID"; - printf("SVG: Unsupported attributes used [Elements type: %s][Id : %s][Attribute: %s][Value: %s]\n", type, id, key, val ? val : "NONE"); + TVGLOG("SVG", "Unsupported attributes used [Elements type: %s][Id : %s][Attribute: %s][Value: %s]", simpleXmlNodeTypeToString(((SvgLoaderData*)data)->svgParse->node->type), ((SvgLoaderData*)data)->svgParse->node->id ? ((SvgLoaderData*)data)->svgParse->node->id->c_str() : "NO_ID", key, val ? val : "NONE"); } } -#else - func((void*)data, key, val); -#endif } buf = next + 1; diff --git a/src/loaders/tvg/tvgTvgLoadParser.cpp b/src/loaders/tvg/tvgTvgLoadParser.cpp index 67de51c..535cf21 100644 --- a/src/loaders/tvg/tvgTvgLoadParser.cpp +++ b/src/loaders/tvg/tvgTvgLoadParser.cpp @@ -489,9 +489,7 @@ unique_ptr tvgLoadData(const char *ptr, uint32_t size) auto end = ptr + size; if (!_readTvgHeader(&ptr) || ptr >= end) { -#ifdef THORVG_LOG_ENABLED - printf("TVG_LOADER: Invalid TVG Data!\n"); -#endif + TVGLOG("TVG", "Invalid TVG Data!"); return nullptr; } @@ -506,4 +504,4 @@ unique_ptr tvgLoadData(const char *ptr, uint32_t size) } return move(scene); -} \ No newline at end of file +} -- 2.7.4 From 6c4edee06b58cef1582ab6514cb478513ec8c6d7 Mon Sep 17 00:00:00 2001 From: Michal Maciola <71131832+mmaciola@users.noreply.github.com> Date: Fri, 23 Jul 2021 14:27:39 +0200 Subject: [PATCH 15/16] sw_engine: removed unused rleAlphaMask --- src/lib/sw_engine/tvgSwCommon.h | 1 - src/lib/sw_engine/tvgSwRle.cpp | 84 +---------------------------------------- 2 files changed, 1 insertion(+), 84 deletions(-) diff --git a/src/lib/sw_engine/tvgSwCommon.h b/src/lib/sw_engine/tvgSwCommon.h index fa3b27b..4349884 100644 --- a/src/lib/sw_engine/tvgSwCommon.h +++ b/src/lib/sw_engine/tvgSwCommon.h @@ -343,7 +343,6 @@ void rleFree(SwRleData* rle); void rleReset(SwRleData* rle); void rleClipPath(SwRleData *rle, const SwRleData *clip); void rleClipRect(SwRleData *rle, const SwBBox* clip); -void rleAlphaMask(SwRleData *rle, const SwRleData *clip); SwMpool* mpoolInit(uint32_t threads); bool mpoolTerm(SwMpool* mpool); diff --git a/src/lib/sw_engine/tvgSwRle.cpp b/src/lib/sw_engine/tvgSwRle.cpp index ca03be8..61a1c2c 100644 --- a/src/lib/sw_engine/tvgSwRle.cpp +++ b/src/lib/sw_engine/tvgSwRle.cpp @@ -658,74 +658,6 @@ SwSpan* _intersectSpansRegion(const SwRleData *clip, const SwRleData *targetRle, return out; } -SwSpan* _intersectMaskRegion(const SwRleData *clip, const SwRleData *targetRle, SwSpan *outSpans, uint32_t spanCnt) -{ - - auto out = outSpans; - auto spans = targetRle->spans; - auto end = targetRle->spans + targetRle->size; - auto clipSpans = clip->spans; - auto clipSpans1 = clip->spans; - auto clipEnd = clip->spans + clip->size; - - auto maskClipMin = clipSpans1->y; - auto maskClipMax = clipSpans1->y; - - while (clipSpans1->y) { - if (clipSpans1->y > maskClipMax) - maskClipMax = clipSpans1->y; - - if (clipSpans1->y < maskClipMax) - maskClipMin = clipSpans1->y; - clipSpans1++; - } - - while (spanCnt && spans < end) { - if (clipSpans > clipEnd) { - spans = end; - break; - } - - - if (spans->y < maskClipMin || spans->y > maskClipMax) { - out->x = spans->x; - out->y = spans->y; - out->len = spans->len; - out->coverage = spans->coverage; - ++out; - } - else { - while (clipSpans->y) { - auto sx1 = spans->x; - auto sx2 = sx1 + spans->len; - auto cx1 = clipSpans->x; - auto cx2 = cx1 + clipSpans->len; - auto x = sx1 > cx1 ? sx1 : cx1; - auto len = (sx2 < cx2 ? sx2 : cx2) - x; - - if (len > 1) { - out->x = sx1; - out->y = clipSpans->y; - out->len = cx1-sx1; - out->coverage = spans->coverage; - ++out; - - out->x = cx2; - out->y = clipSpans->y; - out->len = sx2 - cx2; - out->coverage = spans->coverage; - ++out; - } - clipSpans++; - } - } - --spanCnt; - ++spans; - } - - return out; -} - SwSpan* _intersectSpansRect(const SwBBox *bbox, const SwRleData *targetRle, SwSpan *outSpans, uint32_t spanCnt) { @@ -941,18 +873,4 @@ void rleClipRect(SwRleData *rle, const SwBBox* clip) _replaceClipSpan(rle, spans, spansEnd - spans); TVGLOG("SW_ENGINE", "Using ClipRect!"); -} - - -void rleAlphaMask(SwRleData *rle, const SwRleData *clip) -{ - if (rle->size == 0 || clip->size == 0) return; - auto spanCnt = rle->size + clip->size; - - auto spans = static_cast(malloc(sizeof(SwSpan) * (spanCnt))); - - if (!spans) return; - auto spansEnd = _intersectMaskRegion(clip, rle, spans, spanCnt); - - _replaceClipSpan(rle, spans, spansEnd - spans); -} +} \ No newline at end of file -- 2.7.4 From 201609517635b04d6a5c71f6338e36a4f1dcbd8d Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Mon, 26 Jul 2021 15:41:52 +0900 Subject: [PATCH 16/16] replace the logging system with dlog in tizen please turn on logging in meson_option when it's necessary. Change-Id: Ib2483184697c344f196fc1ff2253309c9215239f --- packaging/thorvg.spec | 1 + src/lib/tvgCommon.h | 12 +++++++++--- src/meson.build | 3 ++- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/packaging/thorvg.spec b/packaging/thorvg.spec index f30540e..5b3e517 100644 --- a/packaging/thorvg.spec +++ b/packaging/thorvg.spec @@ -10,6 +10,7 @@ Source0: %{name}-%{version}.tar.gz BuildRequires: pkgconfig BuildRequires: meson BuildRequires: ninja +BuildRequires: pkgconfig(dlog) Requires(post): /sbin/ldconfig Requires(postun): /sbin/ldconfig diff --git a/src/lib/tvgCommon.h b/src/lib/tvgCommon.h index e8dd0b8..95a1071 100644 --- a/src/lib/tvgCommon.h +++ b/src/lib/tvgCommon.h @@ -22,6 +22,7 @@ #ifndef _TVG_COMMON_H_ #define _TVG_COMMON_H_ +#include #include "config.h" #include "thorvg.h" @@ -37,6 +38,7 @@ using namespace tvg; #define TVG_UNUSED __attribute__ ((__unused__)) #endif +#define LOG_TAG "thorvg" //TVG class identifier values #define TVG_CLASS_ID_UNDEFINED 0 @@ -49,11 +51,15 @@ using namespace tvg; enum class FileType { Tvg = 0, Svg, Raw, Png, Jpg, Unknown }; #ifdef THORVG_LOG_ENABLED - #define TVGLOG(tag, fmt, ...) fprintf(stdout, tag ": " fmt "\n", ##__VA_ARGS__) //Log Message for notifying user some useful info - #define TVGERR(tag, fmt, ...) fprintf(stderr, tag ": " fmt "\n", ##__VA_ARGS__) //Error Message for us to fix it + //#define TVGLOG(tag, fmt, ...) fprintf(stdout, tag ": " fmt "\n", ##__VA_ARGS__) //Log Message for notifying user some useful info + //#define TVGERR(tag, fmt, ...) fprintf(stderr, tag ": " fmt "\n", ##__VA_ARGS__) //Error Message for us to fix it + + //Use dlog system in Tizen + #define TVGLOG(tag, fmt, ...) + #define TVGERR(tag, fmt, ...) dlog_print(DLOG_ERROR, LOG_TAG, tag ": " fmt "\n", ##__VA_ARGS__) #else #define TVGERR(...) #define TVGLOG(...) #endif -#endif //_TVG_COMMON_H_ \ No newline at end of file +#endif //_TVG_COMMON_H_ diff --git a/src/meson.build b/src/meson.build index 3302e33..4e2f4dc 100644 --- a/src/meson.build +++ b/src/meson.build @@ -19,7 +19,8 @@ subdir('savers') subdir('bindings') thread_dep = meson.get_compiler('cpp').find_library('pthread') -thorvg_lib_dep = [common_dep, loader_dep, saver_dep, binding_dep, thread_dep] +dlog_dep = dependency('dlog', required: false) +thorvg_lib_dep = [common_dep, loader_dep, saver_dep, binding_dep, thread_dep, dlog_dep] thorvg_lib = library( 'thorvg', -- 2.7.4