From 2e1a7a7ac7389ed185c2fb05ba746df21b225989 Mon Sep 17 00:00:00 2001 From: Shubham Thakral Date: Wed, 25 May 2022 10:31:33 +0530 Subject: [PATCH 01/28] Temporary (non generic) fix for FillUseElement --- svgnative/src/SVGDocumentImpl.cpp | 10 ++++ svgnative/src/SVGDocumentImpl.h | 88 +++++++++++++++++++++++++++++++ 2 files changed, 98 insertions(+) diff --git a/svgnative/src/SVGDocumentImpl.cpp b/svgnative/src/SVGDocumentImpl.cpp index 1e4b632e..6e0e400f 100644 --- a/svgnative/src/SVGDocumentImpl.cpp +++ b/svgnative/src/SVGDocumentImpl.cpp @@ -1222,6 +1222,7 @@ void SVGDocumentImpl::TraverseTree(const ColorMap& colorMap, const Element& elem // are deprecated, we are not going to fix this nor is this expected by // (still existing) clients. auto graphicStyle = element.graphicStyle; + static const Element* pRefElement = nullptr; FillStyleImpl fillStyle{}; StrokeStyleImpl strokeStyle{}; // Do not draw element if an applied clipPath has no content. @@ -1243,7 +1244,9 @@ void SVGDocumentImpl::TraverseTree(const ColorMap& colorMap, const Element& elem { ApplyCSSStyle(reference.classNames, graphicStyle, fillStyle, strokeStyle); auto saveRestore = SaveRestoreHelper{mRenderer, reference.graphicStyle}; + pRefElement = &element; TraverseTree(colorMap, *(refIt->second)); + pRefElement = nullptr; } // Done processing current element. @@ -1252,6 +1255,13 @@ void SVGDocumentImpl::TraverseTree(const ColorMap& colorMap, const Element& elem } case ElementType::kGraphic: { + if (pRefElement) + { + Graphic& graphic = static_cast(const_cast(element)); + Reference& reference = static_cast(const_cast(*pRefElement)); + // it will call assignment operator and transfer fillStyle & strokeStyle properties + graphic = reference; + } const auto& graphic = static_cast(element); // TODO: Since we keep the original fill, stroke and color property values // we should be able to do w/o a copy. diff --git a/svgnative/src/SVGDocumentImpl.h b/svgnative/src/SVGDocumentImpl.h index af2964a1..ded136a8 100644 --- a/svgnative/src/SVGDocumentImpl.h +++ b/svgnative/src/SVGDocumentImpl.h @@ -170,6 +170,94 @@ class SVGDocumentImpl ElementType Type() const override { return ElementType::kReference; } }; + ElementType Type() const override { return ElementType::kGraphic; } + Graphic& operator= (const Reference& refObj) + { + PaintImpl internalPaint = Color{{0.0f, 0.0f, 0.0f, 1.0f}}; + if (refObj.fillStyle.internalPaint.type() == typeid(Color)) + { + if (boost::get(internalPaint) != boost::get(refObj.fillStyle.internalPaint)) + { + // default value of hasFill is true + this->fillStyle.hasFill = refObj.fillStyle.hasFill; + this->fillStyle.internalPaint = refObj.fillStyle.internalPaint; + } + } + else + { + this->fillStyle.hasFill = refObj.fillStyle.hasFill; + this->fillStyle.internalPaint = refObj.fillStyle.internalPaint; + } + + if (refObj.fillStyle.fillRule != WindingRule::kNonZero) + this->fillStyle.fillRule = refObj.fillStyle.fillRule; + + if (refObj.fillStyle.fillOpacity != 1.0f) + this->fillStyle.fillOpacity = refObj.fillStyle.fillOpacity; + + Paint paint = Color{{0, 0, 0, 1.0}}; + if (refObj.fillStyle.paint.type() == typeid(Color)) + { + if (boost::get(paint) != boost::get(refObj.fillStyle.paint)) + this->fillStyle.paint = refObj.fillStyle.paint; + } + else + this->fillStyle.paint = refObj.fillStyle.paint; + + if (refObj.fillStyle.visibility != true) + this->fillStyle.visibility = refObj.fillStyle.visibility; + + ColorImpl color = Color{{0.0f, 0.0f, 0.0f, 1.0f}}; + if (refObj.fillStyle.color.type() == typeid(Color)) + { + if (boost::get(color) != boost::get(refObj.fillStyle.color)) + this->fillStyle.color = refObj.fillStyle.color; + } + else + this->fillStyle.color = refObj.fillStyle.color; + + if (refObj.fillStyle.clipRule != WindingRule::kNonZero) + this->fillStyle.clipRule = refObj.fillStyle.clipRule; + + if (refObj.strokeStyle.hasStroke) + { + //default value of hasStroke is false + this->strokeStyle.hasStroke = refObj.strokeStyle.hasStroke; + this->strokeStyle.internalPaint = refObj.strokeStyle.internalPaint; + } + if (refObj.strokeStyle.strokeOpacity != 1.0f) + this->strokeStyle.strokeOpacity = refObj.strokeStyle.strokeOpacity; + + if (refObj.strokeStyle.lineWidth != 1.0f) + this->strokeStyle.lineWidth = refObj.strokeStyle.lineWidth; + + if (refObj.strokeStyle.lineCap != LineCap::kButt) + this->strokeStyle.lineCap = refObj.strokeStyle.lineCap; + + if (refObj.strokeStyle.lineJoin != LineJoin::kMiter) + this->strokeStyle.lineJoin = refObj.strokeStyle.lineJoin; + + if (refObj.strokeStyle.dashArray.size() != 0) + this->strokeStyle.dashArray = refObj.strokeStyle.dashArray; + + if (refObj.strokeStyle.miterLimit != 4.0f) + this->strokeStyle.miterLimit = refObj.strokeStyle.miterLimit; + + if (refObj.strokeStyle.dashOffset != 4.0f) + this->strokeStyle.dashOffset = refObj.strokeStyle.dashOffset; + + if (refObj.strokeStyle.paint.type() == typeid(Color)) + { + if (boost::get(paint) != boost::get(refObj.strokeStyle.paint)) + this->strokeStyle.paint = refObj.strokeStyle.paint; + } + else + this->strokeStyle.paint = refObj.strokeStyle.paint; + + return *this; + } + }; + SVGDocumentImpl(std::shared_ptr renderer); ~SVGDocumentImpl() {} From b5b67e03532c1db609fa8d88ee0e692e5d21c659 Mon Sep 17 00:00:00 2001 From: Shubham Thakral Date: Fri, 27 May 2022 07:20:50 +0530 Subject: [PATCH 02/28] viewBox translation temporary (non generic fix) --- svgnative/src/SVGDocumentImpl.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/svgnative/src/SVGDocumentImpl.cpp b/svgnative/src/SVGDocumentImpl.cpp index 6e0e400f..873e0ccf 100644 --- a/svgnative/src/SVGDocumentImpl.cpp +++ b/svgnative/src/SVGDocumentImpl.cpp @@ -964,7 +964,7 @@ void SVGDocumentImpl::RenderElement(const Element& element, const ColorMap& colo GraphicStyleImpl graphicStyle{}; graphicStyle.transform = mRenderer->CreateTransform(); - graphicStyle.transform->Translate(-1 * mViewBox[0], -1 * mViewBox[1]); + // graphicStyle.transform->Translate(-1 * mViewBox[0], -1 * mViewBox[1]); graphicStyle.transform->Scale(scale, scale); auto saveRestore = SaveRestoreHelper{mRenderer, graphicStyle}; @@ -981,6 +981,7 @@ bool SVGDocumentImpl::GetBoundingBox(Rect& bound) GraphicStyleImpl graphicStyle{}; graphicStyle.transform = mRenderer->CreateTransform(); + /*Not making a change here right now as this API is not called by us currently, it was newly added*/ graphicStyle.transform->Translate(-1 * mViewBox[0], -1 * mViewBox[1]); auto saveRestore = SaveRestoreHelper{mRenderer, graphicStyle}; ExtractBounds(*mGroup); @@ -1007,6 +1008,7 @@ bool SVGDocumentImpl::GetBoundingBox(const char* id, Rect& bound) // figure out a way to supply width/height for this I guess? GraphicStyleImpl graphicStyle{}; graphicStyle.transform = mRenderer->CreateTransform(); + /*Not making a change here right now as this API is not called by us currently, it was newly added*/ graphicStyle.transform->Translate(-1 * mViewBox[0], -1 * mViewBox[1]); auto saveRestore = SaveRestoreHelper{mRenderer, graphicStyle}; const auto elementIter = mIdToElementMap.find(id); @@ -1034,6 +1036,7 @@ bool GetSubBoundingBoxes(std::vector& bounds); return false; GraphicStyleImpl graphicStyle{}; graphicStyle.transform = mRenderer->CreateTransform(); + /*Not making a change here right now as this API is not called by us currently, it was newly added*/ graphicStyle.transform->Translate(-1 * mViewBox[0], -1 * mViewBox[1]); auto saveRestore = SaveRestoreHelper{mRenderer, graphicStyle}; ExtractBounds(*mGroup); @@ -1049,6 +1052,7 @@ bool GetSubBoundingBoxes(const char* id, std::vector& bounds); return false; GraphicStyleImpl graphicStyle{}; graphicStyle.transform = mRenderer->CreateTransform(); + /*Not making a change here right now as this API is not called by us currently, it was newly added*/ graphicStyle.transform->Translate(-1 * mViewBox[0], -1 * mViewBox[1]); auto saveRestore = SaveRestoreHelper{mRenderer, graphicStyle}; const auto elementIter = mIdToElementMap.find(id); From 798d7df5ee9b582c66de919f99f1326ba53b2e69 Mon Sep 17 00:00:00 2001 From: Shubham Thakral Date: Fri, 27 May 2022 08:28:18 +0530 Subject: [PATCH 03/28] Temporary fix for pixelisation issue --- svgnative/include/svgnative/SVGRenderer.h | 4 ++++ svgnative/src/SVGDocument.cpp | 6 ++++++ svgnative/src/SVGDocumentImpl.cpp | 1 + svgnative/src/SVGDocumentImpl.h | 1 + 4 files changed, 12 insertions(+) diff --git a/svgnative/include/svgnative/SVGRenderer.h b/svgnative/include/svgnative/SVGRenderer.h index aa09bb44..46122a9d 100644 --- a/svgnative/include/svgnative/SVGRenderer.h +++ b/svgnative/include/svgnative/SVGRenderer.h @@ -250,6 +250,10 @@ class SVGRenderer throw "Bound calculation functionality not implemented in this port"; return Rect{0, 0, 0, 0}; } + virtual void UpdateWidthAndHeight(float& width,float& height) + { + // reason for being empty function is "no need to define same function in skia unless it requires" + } }; class SaveRestoreHelper diff --git a/svgnative/src/SVGDocument.cpp b/svgnative/src/SVGDocument.cpp index b850b6f6..4c302f66 100644 --- a/svgnative/src/SVGDocument.cpp +++ b/svgnative/src/SVGDocument.cpp @@ -66,6 +66,12 @@ void SVGDocument::Render() ColorMap colorMap; mDocument->Render(colorMap, mDocument->mViewBox[2], mDocument->mViewBox[3]); + // to update width and height in doc if view box is not present in svg file + // so that no problem in transformation matrix + if (mDocument->mViewBoxAttrFound == false) + { + mDocument->mRenderer->UpdateWidthAndHeight(mDocument->mViewBox[2], mDocument->mViewBox[3]); + } } void SVGDocument::Render(float width, float height) diff --git a/svgnative/src/SVGDocumentImpl.cpp b/svgnative/src/SVGDocumentImpl.cpp index 873e0ccf..14c890a5 100644 --- a/svgnative/src/SVGDocumentImpl.cpp +++ b/svgnative/src/SVGDocumentImpl.cpp @@ -85,6 +85,7 @@ void SVGDocumentImpl::TraverseSVGTree(XMLNode* rootNode) } else { + mViewBoxAttrFound = true; std::vector numberList; if (SVGStringParser::ParseListOfNumbers(viewBoxAttr.value, numberList) && numberList.size() == 4) mViewBox = {{numberList[0], numberList[1], numberList[2], numberList[3]}}; diff --git a/svgnative/src/SVGDocumentImpl.h b/svgnative/src/SVGDocumentImpl.h index ded136a8..c49d3e99 100644 --- a/svgnative/src/SVGDocumentImpl.h +++ b/svgnative/src/SVGDocumentImpl.h @@ -294,6 +294,7 @@ class SVGDocumentImpl std::array mViewBox; std::shared_ptr mRenderer; + bool mViewBoxAttrFound {false}; private: float ParseLengthFromAttr(const xml::XMLNode* child, const char* attrName, LengthType lengthType = LengthType::kHorizontal, float fallback = 0); From 141a913b44a6140ddd7179e6ca99de4ab71af6c0 Mon Sep 17 00:00:00 2001 From: Shubham Thakral Date: Fri, 27 May 2022 08:34:47 +0530 Subject: [PATCH 04/28] Temporarily added parsing of height and width for image elements till I add support for image elements correctly as currently its non generic --- svgnative/src/SVGDocumentImpl.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/svgnative/src/SVGDocumentImpl.cpp b/svgnative/src/SVGDocumentImpl.cpp index 14c890a5..8d9058bf 100644 --- a/svgnative/src/SVGDocumentImpl.cpp +++ b/svgnative/src/SVGDocumentImpl.cpp @@ -226,8 +226,8 @@ void SVGDocumentImpl::ParseChild(XMLNode* child) if (imageData) { - const float imageWidth = imageData->Width(); - const float imageHeight = imageData->Height(); + const float imageWidth = ParseLengthFromAttr(child, kWidthAttr, LengthType::kHorizontal); + const float imageHeight = ParseLengthFromAttr(child, kHeightAttr, LengthType::kVertical); Rect clipArea{ParseLengthFromAttr(child, kXAttr, LengthType::kHorizontal), ParseLengthFromAttr(child, kYAttr, LengthType::kVertical), From 833bbb6a1859f9e0a9e4203d50a280823f2c9afa Mon Sep 17 00:00:00 2001 From: Shubham Thakral Date: Mon, 30 May 2022 12:25:17 +0530 Subject: [PATCH 05/28] Revert "Temporary (non generic) fix for FillUseElement" Revering because Tushar will fix this properly, and I need to take some older commits too to make this run, so removing. This reverts commit 2e1a7a7ac7389ed185c2fb05ba746df21b225989. --- svgnative/src/SVGDocumentImpl.cpp | 10 ---- svgnative/src/SVGDocumentImpl.h | 88 ------------------------------- 2 files changed, 98 deletions(-) diff --git a/svgnative/src/SVGDocumentImpl.cpp b/svgnative/src/SVGDocumentImpl.cpp index 8d9058bf..ce831aad 100644 --- a/svgnative/src/SVGDocumentImpl.cpp +++ b/svgnative/src/SVGDocumentImpl.cpp @@ -1227,7 +1227,6 @@ void SVGDocumentImpl::TraverseTree(const ColorMap& colorMap, const Element& elem // are deprecated, we are not going to fix this nor is this expected by // (still existing) clients. auto graphicStyle = element.graphicStyle; - static const Element* pRefElement = nullptr; FillStyleImpl fillStyle{}; StrokeStyleImpl strokeStyle{}; // Do not draw element if an applied clipPath has no content. @@ -1249,9 +1248,7 @@ void SVGDocumentImpl::TraverseTree(const ColorMap& colorMap, const Element& elem { ApplyCSSStyle(reference.classNames, graphicStyle, fillStyle, strokeStyle); auto saveRestore = SaveRestoreHelper{mRenderer, reference.graphicStyle}; - pRefElement = &element; TraverseTree(colorMap, *(refIt->second)); - pRefElement = nullptr; } // Done processing current element. @@ -1260,13 +1257,6 @@ void SVGDocumentImpl::TraverseTree(const ColorMap& colorMap, const Element& elem } case ElementType::kGraphic: { - if (pRefElement) - { - Graphic& graphic = static_cast(const_cast(element)); - Reference& reference = static_cast(const_cast(*pRefElement)); - // it will call assignment operator and transfer fillStyle & strokeStyle properties - graphic = reference; - } const auto& graphic = static_cast(element); // TODO: Since we keep the original fill, stroke and color property values // we should be able to do w/o a copy. diff --git a/svgnative/src/SVGDocumentImpl.h b/svgnative/src/SVGDocumentImpl.h index c49d3e99..853eb7cf 100644 --- a/svgnative/src/SVGDocumentImpl.h +++ b/svgnative/src/SVGDocumentImpl.h @@ -170,94 +170,6 @@ class SVGDocumentImpl ElementType Type() const override { return ElementType::kReference; } }; - ElementType Type() const override { return ElementType::kGraphic; } - Graphic& operator= (const Reference& refObj) - { - PaintImpl internalPaint = Color{{0.0f, 0.0f, 0.0f, 1.0f}}; - if (refObj.fillStyle.internalPaint.type() == typeid(Color)) - { - if (boost::get(internalPaint) != boost::get(refObj.fillStyle.internalPaint)) - { - // default value of hasFill is true - this->fillStyle.hasFill = refObj.fillStyle.hasFill; - this->fillStyle.internalPaint = refObj.fillStyle.internalPaint; - } - } - else - { - this->fillStyle.hasFill = refObj.fillStyle.hasFill; - this->fillStyle.internalPaint = refObj.fillStyle.internalPaint; - } - - if (refObj.fillStyle.fillRule != WindingRule::kNonZero) - this->fillStyle.fillRule = refObj.fillStyle.fillRule; - - if (refObj.fillStyle.fillOpacity != 1.0f) - this->fillStyle.fillOpacity = refObj.fillStyle.fillOpacity; - - Paint paint = Color{{0, 0, 0, 1.0}}; - if (refObj.fillStyle.paint.type() == typeid(Color)) - { - if (boost::get(paint) != boost::get(refObj.fillStyle.paint)) - this->fillStyle.paint = refObj.fillStyle.paint; - } - else - this->fillStyle.paint = refObj.fillStyle.paint; - - if (refObj.fillStyle.visibility != true) - this->fillStyle.visibility = refObj.fillStyle.visibility; - - ColorImpl color = Color{{0.0f, 0.0f, 0.0f, 1.0f}}; - if (refObj.fillStyle.color.type() == typeid(Color)) - { - if (boost::get(color) != boost::get(refObj.fillStyle.color)) - this->fillStyle.color = refObj.fillStyle.color; - } - else - this->fillStyle.color = refObj.fillStyle.color; - - if (refObj.fillStyle.clipRule != WindingRule::kNonZero) - this->fillStyle.clipRule = refObj.fillStyle.clipRule; - - if (refObj.strokeStyle.hasStroke) - { - //default value of hasStroke is false - this->strokeStyle.hasStroke = refObj.strokeStyle.hasStroke; - this->strokeStyle.internalPaint = refObj.strokeStyle.internalPaint; - } - if (refObj.strokeStyle.strokeOpacity != 1.0f) - this->strokeStyle.strokeOpacity = refObj.strokeStyle.strokeOpacity; - - if (refObj.strokeStyle.lineWidth != 1.0f) - this->strokeStyle.lineWidth = refObj.strokeStyle.lineWidth; - - if (refObj.strokeStyle.lineCap != LineCap::kButt) - this->strokeStyle.lineCap = refObj.strokeStyle.lineCap; - - if (refObj.strokeStyle.lineJoin != LineJoin::kMiter) - this->strokeStyle.lineJoin = refObj.strokeStyle.lineJoin; - - if (refObj.strokeStyle.dashArray.size() != 0) - this->strokeStyle.dashArray = refObj.strokeStyle.dashArray; - - if (refObj.strokeStyle.miterLimit != 4.0f) - this->strokeStyle.miterLimit = refObj.strokeStyle.miterLimit; - - if (refObj.strokeStyle.dashOffset != 4.0f) - this->strokeStyle.dashOffset = refObj.strokeStyle.dashOffset; - - if (refObj.strokeStyle.paint.type() == typeid(Color)) - { - if (boost::get(paint) != boost::get(refObj.strokeStyle.paint)) - this->strokeStyle.paint = refObj.strokeStyle.paint; - } - else - this->strokeStyle.paint = refObj.strokeStyle.paint; - - return *this; - } - }; - SVGDocumentImpl(std::shared_ptr renderer); ~SVGDocumentImpl() {} From 957ef6ea110beec4ffed9ec306b006aa21266020 Mon Sep 17 00:00:00 2001 From: Shubham Thakral Date: Tue, 31 May 2022 14:19:45 +0530 Subject: [PATCH 06/28] Use element/fill issue related temporary fix Taken from commit https://github.com/adobe/svg-native-viewer/commit/4a4bed19c742a87b9d1839f421e3f678c56c06e0 and https://github.com/adobe/svg-native-viewer/commit/3fd71c3943d0ba42471366fef2554a865aa79577 --- svgnative/src/SVGDocumentImpl.cpp | 18 ++++++++++ svgnative/src/SVGDocumentImpl.h | 58 +++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+) diff --git a/svgnative/src/SVGDocumentImpl.cpp b/svgnative/src/SVGDocumentImpl.cpp index ce831aad..2a489b83 100644 --- a/svgnative/src/SVGDocumentImpl.cpp +++ b/svgnative/src/SVGDocumentImpl.cpp @@ -1248,6 +1248,24 @@ void SVGDocumentImpl::TraverseTree(const ColorMap& colorMap, const Element& elem { ApplyCSSStyle(reference.classNames, graphicStyle, fillStyle, strokeStyle); auto saveRestore = SaveRestoreHelper{mRenderer, reference.graphicStyle}; + if ((*(refIt->second)).Type() == ElementType::kGraphic) + { + Graphic& graphic = static_cast(*(refIt->second)); + // it will call assignment operator and pass fillStyle from reference to graphic + graphic = reference; + } + else if((*(refIt->second)).Type() == ElementType::kGroup) + { + Group& group = static_cast(*(refIt->second)); + for (auto& child : group.children) + { + if ((*child).Type() == ElementType::kGraphic) + { + Graphic& graphic = static_cast(*child); + graphic = reference; + } + } + } TraverseTree(colorMap, *(refIt->second)); } diff --git a/svgnative/src/SVGDocumentImpl.h b/svgnative/src/SVGDocumentImpl.h index 853eb7cf..2c8feef5 100644 --- a/svgnative/src/SVGDocumentImpl.h +++ b/svgnative/src/SVGDocumentImpl.h @@ -150,6 +150,64 @@ class SVGDocumentImpl std::shared_ptr path; ElementType Type() const override { return ElementType::kGraphic; } + Graphic& operator= (const Reference& refObj) + { + if (refObj.fillStyle.hasFill) + { + this->fillStyle.hasFill = refObj.fillStyle.hasFill; + this->fillStyle.internalPaint = refObj.fillStyle.internalPaint; + } + if (refObj.fillStyle.fillRule != WindingRule::kNonZero) + this->fillStyle.fillRule = refObj.fillStyle.fillRule; + + if (refObj.fillStyle.fillOpacity != 1.0f) + this->fillStyle.fillOpacity = refObj.fillStyle.fillOpacity; + + Color paint = Color{{0, 0, 0, 1.0}}; + if (paint != boost::get(refObj.fillStyle.paint)) + this->fillStyle.paint = refObj.fillStyle.paint; + + if (refObj.fillStyle.visibility != true) + this->fillStyle.visibility = refObj.fillStyle.visibility; + + ColorImpl color = Color{{0.0f, 0.0f, 0.0f, 1.0f}}; + if (refObj.fillStyle.color != color) + this->fillStyle.color = refObj.fillStyle.color; + + if (refObj.fillStyle.clipRule != WindingRule::kNonZero) + this->fillStyle.clipRule = refObj.fillStyle.clipRule; + + if (refObj.strokeStyle.hasStroke) + { + this->strokeStyle.hasStroke = refObj.strokeStyle.hasStroke; + this->strokeStyle.internalPaint = refObj.strokeStyle.internalPaint; + } + if (refObj.strokeStyle.strokeOpacity != 1.0f) + this->strokeStyle.strokeOpacity = refObj.strokeStyle.strokeOpacity; + + if (refObj.strokeStyle.lineWidth != 1.0f) + this->strokeStyle.lineWidth = refObj.strokeStyle.lineWidth; + + if (refObj.strokeStyle.lineCap != LineCap::kButt) + this->strokeStyle.lineCap = refObj.strokeStyle.lineCap; + + if (refObj.strokeStyle.lineJoin != LineJoin::kMiter) + this->strokeStyle.lineJoin = refObj.strokeStyle.lineJoin; + + if (refObj.strokeStyle.dashArray.size() != 0) + this->strokeStyle.dashArray = refObj.strokeStyle.dashArray; + + if (refObj.strokeStyle.miterLimit != 4.0f) + this->strokeStyle.miterLimit = refObj.strokeStyle.miterLimit; + + if (refObj.strokeStyle.dashOffset != 4.0f) + this->strokeStyle.dashOffset = refObj.strokeStyle.dashOffset; + + if (paint != boost::get(refObj.strokeStyle.paint)) + this->strokeStyle.paint = refObj.strokeStyle.paint; + + return *this; + } }; struct Reference : public Element From 233ea9fb7735e23747aa9c87acfc385ab665dd8b Mon Sep 17 00:00:00 2001 From: Shubham Thakral Date: Tue, 31 May 2022 14:59:52 +0530 Subject: [PATCH 07/28] FillUseElement temporary (non generic) fix --- svgnative/src/SVGDocumentImpl.cpp | 29 +++++++++---------------- svgnative/src/SVGDocumentImpl.h | 36 ++++++++++++++++++++++++++----- 2 files changed, 41 insertions(+), 24 deletions(-) diff --git a/svgnative/src/SVGDocumentImpl.cpp b/svgnative/src/SVGDocumentImpl.cpp index 2a489b83..f7e656a7 100644 --- a/svgnative/src/SVGDocumentImpl.cpp +++ b/svgnative/src/SVGDocumentImpl.cpp @@ -1248,25 +1248,9 @@ void SVGDocumentImpl::TraverseTree(const ColorMap& colorMap, const Element& elem { ApplyCSSStyle(reference.classNames, graphicStyle, fillStyle, strokeStyle); auto saveRestore = SaveRestoreHelper{mRenderer, reference.graphicStyle}; - if ((*(refIt->second)).Type() == ElementType::kGraphic) - { - Graphic& graphic = static_cast(*(refIt->second)); - // it will call assignment operator and pass fillStyle from reference to graphic - graphic = reference; - } - else if((*(refIt->second)).Type() == ElementType::kGroup) - { - Group& group = static_cast(*(refIt->second)); - for (auto& child : group.children) - { - if ((*child).Type() == ElementType::kGraphic) - { - Graphic& graphic = static_cast(*child); - graphic = reference; - } - } - } + pRefElement = &element; TraverseTree(colorMap, *(refIt->second)); + pRefElement = nullptr; } // Done processing current element. @@ -1274,7 +1258,14 @@ void SVGDocumentImpl::TraverseTree(const ColorMap& colorMap, const Element& elem break; } case ElementType::kGraphic: - { + { + if (pRefElement) + { + Graphic& graphic = static_cast(const_cast(element)); + Reference& reference = static_cast(const_cast(*pRefElement)); + // it will call assignment operator and transfer fillStyle & strokeStyle properties + graphic = reference; + } const auto& graphic = static_cast(element); // TODO: Since we keep the original fill, stroke and color property values // we should be able to do w/o a copy. diff --git a/svgnative/src/SVGDocumentImpl.h b/svgnative/src/SVGDocumentImpl.h index 2c8feef5..63524814 100644 --- a/svgnative/src/SVGDocumentImpl.h +++ b/svgnative/src/SVGDocumentImpl.h @@ -152,7 +152,17 @@ class SVGDocumentImpl ElementType Type() const override { return ElementType::kGraphic; } Graphic& operator= (const Reference& refObj) { - if (refObj.fillStyle.hasFill) + PaintImpl internalPaint = Color{{0.0f, 0.0f, 0.0f, 1.0f}}; + if (refObj.fillStyle.internalPaint.type() == typeid(Color)) + { + if (boost::get(internalPaint) != boost::get(refObj.fillStyle.internalPaint)) + { + // default value of hasFill is true + this->fillStyle.hasFill = refObj.fillStyle.hasFill; + this->fillStyle.internalPaint = refObj.fillStyle.internalPaint; + } + } + else { this->fillStyle.hasFill = refObj.fillStyle.hasFill; this->fillStyle.internalPaint = refObj.fillStyle.internalPaint; @@ -163,15 +173,25 @@ class SVGDocumentImpl if (refObj.fillStyle.fillOpacity != 1.0f) this->fillStyle.fillOpacity = refObj.fillStyle.fillOpacity; - Color paint = Color{{0, 0, 0, 1.0}}; - if (paint != boost::get(refObj.fillStyle.paint)) + Paint paint = Color{{0, 0, 0, 1.0}}; + if (refObj.fillStyle.paint.type() == typeid(Color)) + { + if (boost::get(paint) != boost::get(refObj.fillStyle.paint)) + this->fillStyle.paint = refObj.fillStyle.paint; + } + else this->fillStyle.paint = refObj.fillStyle.paint; if (refObj.fillStyle.visibility != true) this->fillStyle.visibility = refObj.fillStyle.visibility; ColorImpl color = Color{{0.0f, 0.0f, 0.0f, 1.0f}}; - if (refObj.fillStyle.color != color) + if (refObj.fillStyle.color.type() == typeid(Color)) + { + if (boost::get(color) != boost::get(refObj.fillStyle.color)) + this->fillStyle.color = refObj.fillStyle.color; + } + else this->fillStyle.color = refObj.fillStyle.color; if (refObj.fillStyle.clipRule != WindingRule::kNonZero) @@ -179,6 +199,7 @@ class SVGDocumentImpl if (refObj.strokeStyle.hasStroke) { + //default value of hasStroke is false this->strokeStyle.hasStroke = refObj.strokeStyle.hasStroke; this->strokeStyle.internalPaint = refObj.strokeStyle.internalPaint; } @@ -203,7 +224,12 @@ class SVGDocumentImpl if (refObj.strokeStyle.dashOffset != 4.0f) this->strokeStyle.dashOffset = refObj.strokeStyle.dashOffset; - if (paint != boost::get(refObj.strokeStyle.paint)) + if (refObj.strokeStyle.paint.type() == typeid(Color)) + { + if (boost::get(paint) != boost::get(refObj.strokeStyle.paint)) + this->strokeStyle.paint = refObj.strokeStyle.paint; + } + else this->strokeStyle.paint = refObj.strokeStyle.paint; return *this; From cd61de8126dfb0e44313c851915bb70d3c777b36 Mon Sep 17 00:00:00 2001 From: Shubham Thakral Date: Tue, 31 May 2022 19:43:02 +0530 Subject: [PATCH 08/28] Adding definition of pRefElement --- svgnative/src/SVGDocumentImpl.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/svgnative/src/SVGDocumentImpl.cpp b/svgnative/src/SVGDocumentImpl.cpp index f7e656a7..8d4079f5 100644 --- a/svgnative/src/SVGDocumentImpl.cpp +++ b/svgnative/src/SVGDocumentImpl.cpp @@ -1227,6 +1227,7 @@ void SVGDocumentImpl::TraverseTree(const ColorMap& colorMap, const Element& elem // are deprecated, we are not going to fix this nor is this expected by // (still existing) clients. auto graphicStyle = element.graphicStyle; + static const Element* pRefElement = nullptr; FillStyleImpl fillStyle{}; StrokeStyleImpl strokeStyle{}; // Do not draw element if an applied clipPath has no content. From 06cf6eeb87786b55f0e5864ebef2c552f637c9de Mon Sep 17 00:00:00 2001 From: Shubham Thakral Date: Tue, 31 May 2022 19:48:10 +0530 Subject: [PATCH 09/28] Changes for struct forward declaration --- svgnative/src/SVGDocumentImpl.cpp | 85 ++++++++++++++++++++++++++++++ svgnative/src/SVGDocumentImpl.h | 87 ++----------------------------- 2 files changed, 88 insertions(+), 84 deletions(-) diff --git a/svgnative/src/SVGDocumentImpl.cpp b/svgnative/src/SVGDocumentImpl.cpp index 8d4079f5..d95f1f81 100644 --- a/svgnative/src/SVGDocumentImpl.cpp +++ b/svgnative/src/SVGDocumentImpl.cpp @@ -1303,6 +1303,91 @@ void SVGDocumentImpl::TraverseTree(const ColorMap& colorMap, const Element& elem } } +SVGDocumentImpl::Graphic& SVGDocumentImpl::Graphic::operator=(const Reference& refObj) +{ + PaintImpl internalPaint = Color{{0.0f, 0.0f, 0.0f, 1.0f}}; + if (refObj.fillStyle.internalPaint.type() == typeid(Color)) + { + if (boost::get(internalPaint) != boost::get(refObj.fillStyle.internalPaint)) + { + // default value of hasFill is true + this->fillStyle.hasFill = refObj.fillStyle.hasFill; + this->fillStyle.internalPaint = refObj.fillStyle.internalPaint; + } + } + else + { + this->fillStyle.hasFill = refObj.fillStyle.hasFill; + this->fillStyle.internalPaint = refObj.fillStyle.internalPaint; + } + if (refObj.fillStyle.fillRule != WindingRule::kNonZero) + this->fillStyle.fillRule = refObj.fillStyle.fillRule; + + if (refObj.fillStyle.fillOpacity != 1.0f) + this->fillStyle.fillOpacity = refObj.fillStyle.fillOpacity; + + Paint paint = Color{{0, 0, 0, 1.0}}; + if (refObj.fillStyle.paint.type() == typeid(Color)) + { + if (boost::get(paint) != boost::get(refObj.fillStyle.paint)) + this->fillStyle.paint = refObj.fillStyle.paint; + } + else + this->fillStyle.paint = refObj.fillStyle.paint; + + if (refObj.fillStyle.visibility != true) + this->fillStyle.visibility = refObj.fillStyle.visibility; + + ColorImpl color = Color{{0.0f, 0.0f, 0.0f, 1.0f}}; + if (refObj.fillStyle.color.type() == typeid(Color)) + { + if (boost::get(color) != boost::get(refObj.fillStyle.color)) + this->fillStyle.color = refObj.fillStyle.color; + } + else + this->fillStyle.color = refObj.fillStyle.color; + + if (refObj.fillStyle.clipRule != WindingRule::kNonZero) + this->fillStyle.clipRule = refObj.fillStyle.clipRule; + + if (refObj.strokeStyle.hasStroke) + { + //default value of hasStroke is false + this->strokeStyle.hasStroke = refObj.strokeStyle.hasStroke; + this->strokeStyle.internalPaint = refObj.strokeStyle.internalPaint; + } + if (refObj.strokeStyle.strokeOpacity != 1.0f) + this->strokeStyle.strokeOpacity = refObj.strokeStyle.strokeOpacity; + + if (refObj.strokeStyle.lineWidth != 1.0f) + this->strokeStyle.lineWidth = refObj.strokeStyle.lineWidth; + + if (refObj.strokeStyle.lineCap != LineCap::kButt) + this->strokeStyle.lineCap = refObj.strokeStyle.lineCap; + + if (refObj.strokeStyle.lineJoin != LineJoin::kMiter) + this->strokeStyle.lineJoin = refObj.strokeStyle.lineJoin; + + if (refObj.strokeStyle.dashArray.size() != 0) + this->strokeStyle.dashArray = refObj.strokeStyle.dashArray; + + if (refObj.strokeStyle.miterLimit != 4.0f) + this->strokeStyle.miterLimit = refObj.strokeStyle.miterLimit; + + if (refObj.strokeStyle.dashOffset != 4.0f) + this->strokeStyle.dashOffset = refObj.strokeStyle.dashOffset; + + if (refObj.strokeStyle.paint.type() == typeid(Color)) + { + if (boost::get(paint) != boost::get(refObj.strokeStyle.paint)) + this->strokeStyle.paint = refObj.strokeStyle.paint; + } + else + this->strokeStyle.paint = refObj.strokeStyle.paint; + + return *this; +} + #ifndef STYLE_SUPPORT // Deprecated style support void SVGDocumentImpl::ApplyCSSStyle( diff --git a/svgnative/src/SVGDocumentImpl.h b/svgnative/src/SVGDocumentImpl.h index 63524814..d7314f2b 100644 --- a/svgnative/src/SVGDocumentImpl.h +++ b/svgnative/src/SVGDocumentImpl.h @@ -134,6 +134,8 @@ class SVGDocumentImpl ElementType Type() const override { return ElementType::kGroup; } }; + struct Reference; + struct Graphic : public Element { Graphic(GraphicStyleImpl& aGraphicStyle, std::set& aClasses, FillStyleImpl& aFillStyle, StrokeStyleImpl& aStrokeStyle, @@ -150,90 +152,7 @@ class SVGDocumentImpl std::shared_ptr path; ElementType Type() const override { return ElementType::kGraphic; } - Graphic& operator= (const Reference& refObj) - { - PaintImpl internalPaint = Color{{0.0f, 0.0f, 0.0f, 1.0f}}; - if (refObj.fillStyle.internalPaint.type() == typeid(Color)) - { - if (boost::get(internalPaint) != boost::get(refObj.fillStyle.internalPaint)) - { - // default value of hasFill is true - this->fillStyle.hasFill = refObj.fillStyle.hasFill; - this->fillStyle.internalPaint = refObj.fillStyle.internalPaint; - } - } - else - { - this->fillStyle.hasFill = refObj.fillStyle.hasFill; - this->fillStyle.internalPaint = refObj.fillStyle.internalPaint; - } - if (refObj.fillStyle.fillRule != WindingRule::kNonZero) - this->fillStyle.fillRule = refObj.fillStyle.fillRule; - - if (refObj.fillStyle.fillOpacity != 1.0f) - this->fillStyle.fillOpacity = refObj.fillStyle.fillOpacity; - - Paint paint = Color{{0, 0, 0, 1.0}}; - if (refObj.fillStyle.paint.type() == typeid(Color)) - { - if (boost::get(paint) != boost::get(refObj.fillStyle.paint)) - this->fillStyle.paint = refObj.fillStyle.paint; - } - else - this->fillStyle.paint = refObj.fillStyle.paint; - - if (refObj.fillStyle.visibility != true) - this->fillStyle.visibility = refObj.fillStyle.visibility; - - ColorImpl color = Color{{0.0f, 0.0f, 0.0f, 1.0f}}; - if (refObj.fillStyle.color.type() == typeid(Color)) - { - if (boost::get(color) != boost::get(refObj.fillStyle.color)) - this->fillStyle.color = refObj.fillStyle.color; - } - else - this->fillStyle.color = refObj.fillStyle.color; - - if (refObj.fillStyle.clipRule != WindingRule::kNonZero) - this->fillStyle.clipRule = refObj.fillStyle.clipRule; - - if (refObj.strokeStyle.hasStroke) - { - //default value of hasStroke is false - this->strokeStyle.hasStroke = refObj.strokeStyle.hasStroke; - this->strokeStyle.internalPaint = refObj.strokeStyle.internalPaint; - } - if (refObj.strokeStyle.strokeOpacity != 1.0f) - this->strokeStyle.strokeOpacity = refObj.strokeStyle.strokeOpacity; - - if (refObj.strokeStyle.lineWidth != 1.0f) - this->strokeStyle.lineWidth = refObj.strokeStyle.lineWidth; - - if (refObj.strokeStyle.lineCap != LineCap::kButt) - this->strokeStyle.lineCap = refObj.strokeStyle.lineCap; - - if (refObj.strokeStyle.lineJoin != LineJoin::kMiter) - this->strokeStyle.lineJoin = refObj.strokeStyle.lineJoin; - - if (refObj.strokeStyle.dashArray.size() != 0) - this->strokeStyle.dashArray = refObj.strokeStyle.dashArray; - - if (refObj.strokeStyle.miterLimit != 4.0f) - this->strokeStyle.miterLimit = refObj.strokeStyle.miterLimit; - - if (refObj.strokeStyle.dashOffset != 4.0f) - this->strokeStyle.dashOffset = refObj.strokeStyle.dashOffset; - - if (refObj.strokeStyle.paint.type() == typeid(Color)) - { - if (boost::get(paint) != boost::get(refObj.strokeStyle.paint)) - this->strokeStyle.paint = refObj.strokeStyle.paint; - } - else - this->strokeStyle.paint = refObj.strokeStyle.paint; - - return *this; - } + Graphic& operator= (const Reference& refObj); }; struct Reference : public Element From c247f827e2b5244995f28d897d6a83e239eb86d1 Mon Sep 17 00:00:00 2001 From: Tushar Jindal <90841856+tjindal@users.noreply.github.com> Date: Thu, 9 Jun 2022 04:48:14 +0000 Subject: [PATCH 10/28] support of tight bounding boxes for images or handling some glyphs which crops in output (#173) --- svgnative/example/testSkia/TestSkia.cpp | 11 +++++++++++ svgnative/src/SVGDocument.cpp | 5 ++++- svgnative/src/SVGDocumentImpl.cpp | 7 +++++++ svgnative/src/SVGDocumentImpl.h | 2 +- 4 files changed, 23 insertions(+), 2 deletions(-) diff --git a/svgnative/example/testSkia/TestSkia.cpp b/svgnative/example/testSkia/TestSkia.cpp index d5d63a4e..5766306b 100644 --- a/svgnative/example/testSkia/TestSkia.cpp +++ b/svgnative/example/testSkia/TestSkia.cpp @@ -45,6 +45,17 @@ int main(int argc, char* const argv[]) auto doc = std::unique_ptr(SVGNative::SVGDocument::CreateSVGDocument(svgInput.c_str(), renderer)); + { + // make initially default canvas and compute the bounds , after computation make + // new canvas again of actual bounds. + auto skRasterSurface = SkSurface::MakeRasterN32Premul(doc->Width(), doc->Height()); + auto skRasterCanvas = skRasterSurface->getCanvas(); + + renderer->SetSkCanvas(skRasterCanvas); + SVGNative::Rect bounds {0,0,0,0}; + doc->GetBoundingBox(bounds); + } + auto skRasterSurface = SkSurface::MakeRasterN32Premul(doc->Width(), doc->Height()); auto skRasterCanvas = skRasterSurface->getCanvas(); diff --git a/svgnative/src/SVGDocument.cpp b/svgnative/src/SVGDocument.cpp index 4c302f66..0fada524 100644 --- a/svgnative/src/SVGDocument.cpp +++ b/svgnative/src/SVGDocument.cpp @@ -136,7 +136,10 @@ bool SVGDocument::GetBoundingBox(Rect& bounds) { if (!mDocument) return false; - return mDocument->GetBoundingBox(bounds); + bool bStatus = mDocument->GetBoundingBox(bounds); + if (bStatus && bounds.IsEmpty()== false) + mDocument->UpdateViewBox(bounds); + return bStatus; } bool SVGDocument::GetBoundingBox(const char *id, Rect& bounds) diff --git a/svgnative/src/SVGDocumentImpl.cpp b/svgnative/src/SVGDocumentImpl.cpp index d95f1f81..47f5d361 100644 --- a/svgnative/src/SVGDocumentImpl.cpp +++ b/svgnative/src/SVGDocumentImpl.cpp @@ -1028,6 +1028,13 @@ bool SVGDocumentImpl::GetBoundingBox(const char* id, Rect& bound) return true; } +void SVGDocumentImpl::UpdateViewBox(Rect& bounds) +{ + mViewBox[0] = bounds.x; + mViewBox[1] = bounds.y; + mViewBox[2] = bounds.width; + mViewBox[3] = bounds.height; +} #ifdef DEBUG_API bool GetSubBoundingBoxes(std::vector& bounds); diff --git a/svgnative/src/SVGDocumentImpl.h b/svgnative/src/SVGDocumentImpl.h index d7314f2b..3a2db1ca 100644 --- a/svgnative/src/SVGDocumentImpl.h +++ b/svgnative/src/SVGDocumentImpl.h @@ -201,7 +201,7 @@ class SVGDocumentImpl bool GetBoundingBox(Rect& bounds); bool GetBoundingBox(const char* id, Rect& bounds); - + void UpdateViewBox(Rect& bounds); #ifdef DEBUG_API bool GetSubBoundingBoxes(std::vector& bounds); bool GetSubBoundingBoxes(const char* id, std::vector& bounds); From 074e357f01e61af4ecbe15692cf34050b8abee64 Mon Sep 17 00:00:00 2001 From: Tushar Jindal <90841856+tjindal@users.noreply.github.com> Date: Thu, 9 Jun 2022 06:47:51 +0000 Subject: [PATCH 11/28] support number or percentage values for offset/opacity values (#176) * fix testcases for offset/opacity as a percentage * support of percentage when specified in opacity,offset for stroke/fill properties * Revert "support of percentage when specified in opacity,offset for stroke/fill properties" This reverts commit 79c63ccee99721d68ffab547431a802891edc62e. * Adding a new function name ParseAlphaValue for values between 0-1 * minor change in last commit --- svgnative/src/SVGDocumentImpl.cpp | 10 +++++----- svgnative/src/SVGStringParser.cpp | 17 +++++++++++++++++ svgnative/src/SVGStringParser.h | 1 + svgnative/test/properties.svg | 6 +++--- svgnative/test/properties.txt | 6 +++--- 5 files changed, 29 insertions(+), 11 deletions(-) diff --git a/svgnative/src/SVGDocumentImpl.cpp b/svgnative/src/SVGDocumentImpl.cpp index 47f5d361..91ef3b29 100644 --- a/svgnative/src/SVGDocumentImpl.cpp +++ b/svgnative/src/SVGDocumentImpl.cpp @@ -612,7 +612,7 @@ void SVGDocumentImpl::ParseFillProperties(FillStyleImpl& fillStyle, const Proper if (prop != iterEnd) { float opacity{}; - if (SVGStringParser::ParseNumber(prop->second, opacity)) + if (SVGStringParser::ParseAlphaValue(prop->second, opacity)) fillStyle.fillOpacity = std::max(0.0, std::min(1.0, opacity)); } @@ -745,7 +745,7 @@ void SVGDocumentImpl::ParseStrokeProperties(StrokeStyleImpl& strokeStyle, const if (prop != iterEnd) { float opacity{}; - if (SVGStringParser::ParseNumber(prop->second, opacity)) + if (SVGStringParser::ParseAlphaValue(prop->second, opacity)) strokeStyle.strokeOpacity = std::max(0.0, std::min(1.0, opacity)); } } @@ -757,7 +757,7 @@ void SVGDocumentImpl::ParseGraphicsProperties(GraphicStyleImpl& graphicStyle, co if (prop != iterEnd) { float opacity{}; - if (SVGStringParser::ParseNumber(prop->second, opacity)) + if (SVGStringParser::ParseAlphaValue(prop->second, opacity)) graphicStyle.opacity = std::max(0.0, std::min(1.0, opacity)); } @@ -784,7 +784,7 @@ void SVGDocumentImpl::ParseGraphicsProperties(GraphicStyleImpl& graphicStyle, co if (prop != iterEnd) { float opacity{}; - if (SVGStringParser::ParseNumber(prop->second, opacity)) + if (SVGStringParser::ParseAlphaValue(prop->second, opacity)) graphicStyle.stopOpacity = std::max(0.0, std::min(1.0, opacity)); } @@ -811,7 +811,7 @@ float SVGDocumentImpl::ParseColorStop(const XMLNode* node, std::vectorGetAttribute(kOffsetAttr); - offset = (attr.found && SVGStringParser::ParseNumber(attr.value, offset)) ? offset : lastOffset; + offset = (attr.found && SVGStringParser::ParseAlphaValue(attr.value, offset)) ? offset : lastOffset; offset = std::max(lastOffset, offset); offset = std::min(1.0, std::max(0.0, offset)); diff --git a/svgnative/src/SVGStringParser.cpp b/svgnative/src/SVGStringParser.cpp index 955f51a0..060eaeb2 100644 --- a/svgnative/src/SVGStringParser.cpp +++ b/svgnative/src/SVGStringParser.cpp @@ -412,6 +412,23 @@ bool ParseNumber(const std::string& numberString, float& number) return !SkipOptWsp(pos, end); } +bool ParseAlphaValue(const std::string& numberString, float& number) +{ + auto pos = numberString.begin(); + auto end = numberString.end(); + + if (!SkipOptWsp(pos, end)) + return false; + if (!ParseScientificNumber(pos, end, number)) + return false; + if (pos < end && *pos == '%') + { + number = number/100.0f; + pos++; + } + return !SkipOptWsp(pos, end); +} + bool ParseListOfNumbers(const std::string& numberListString, std::vector& numberList, bool isAllOptional /*= true*/) { auto pos = numberListString.begin(); diff --git a/svgnative/src/SVGStringParser.h b/svgnative/src/SVGStringParser.h index c89f6aa8..aaac01fe 100644 --- a/svgnative/src/SVGStringParser.h +++ b/svgnative/src/SVGStringParser.h @@ -22,6 +22,7 @@ namespace SVGStringParser { bool ParseTransform(const std::string& transformString, Transform& matrix); bool ParseNumber(const std::string& numberString, float& number); +bool ParseAlphaValue(const std::string& numberString, float& number); bool ParseListOfNumbers(const std::string& numberListString, std::vector& numberList, bool isAllOptional = true); bool ParseListOfLengthOrPercentage( const std::string& lengthOrPercentageListString, float relDimensionLength, std::vector& numberList, bool isAllOptional = true); diff --git a/svgnative/test/properties.svg b/svgnative/test/properties.svg index c94dec85..9e26187e 100644 --- a/svgnative/test/properties.svg +++ b/svgnative/test/properties.svg @@ -24,9 +24,9 @@ + - @@ -39,9 +39,9 @@ + - @@ -54,9 +54,9 @@ + - diff --git a/svgnative/test/properties.txt b/svgnative/test/properties.txt index d060219f..9c6da280 100644 --- a/svgnative/test/properties.txt +++ b/svgnative/test/properties.txt @@ -57,7 +57,7 @@ stroke: {hasStroke: true width: 1 opacity: 0.2 cap: butt join: miter miter: 4 dashOffset: 0 paint: rgba(0,0,0,1)}] [path M5,22 L145,22 fill: {hasFill: true winding: nonzero paint: rgba(0,0,0,1)} - stroke: {hasStroke: true width: 1 cap: butt join: miter miter: 4 dashOffset: 0 paint: rgba(0,0,0,1)}] + stroke: {hasStroke: true width: 1 opacity: 0.2 cap: butt join: miter miter: 4 dashOffset: 0 paint: rgba(0,0,0,1)}] [path M5,22 L145,22 fill: {hasFill: true winding: nonzero paint: rgba(0,0,0,1)} stroke: {hasStroke: true width: 1 cap: butt join: miter miter: 4 dashOffset: 0 paint: rgba(0,0,0,1)}] @@ -85,7 +85,7 @@ [path Rect(5,39,140,2) opacity: 0.2 fill: {hasFill: true winding: nonzero paint: rgba(0,0,0,1)} stroke: {hasStroke: false width: 1 cap: butt join: miter miter: 4 dashOffset: 0 paint: rgba(0,0,0,1)}] - [path Rect(5,40,140,2) + [path Rect(5,40,140,2) opacity: 0.2 fill: {hasFill: true winding: nonzero paint: rgba(0,0,0,1)} stroke: {hasStroke: false width: 1 cap: butt join: miter miter: 4 dashOffset: 0 paint: rgba(0,0,0,1)}] [path Rect(5,40,140,2) @@ -116,7 +116,7 @@ fill: {hasFill: true winding: nonzero opacity: 0.2 paint: rgba(0,0,0,1)} stroke: {hasStroke: false width: 1 cap: butt join: miter miter: 4 dashOffset: 0 paint: rgba(0,0,0,1)}] [path Rect(5,42,140,2) - fill: {hasFill: true winding: nonzero paint: rgba(0,0,0,1)} + fill: {hasFill: true winding: nonzero opacity: 0.2 paint: rgba(0,0,0,1)} stroke: {hasStroke: false width: 1 cap: butt join: miter miter: 4 dashOffset: 0 paint: rgba(0,0,0,1)}] [path Rect(5,42,140,2) fill: {hasFill: true winding: nonzero paint: rgba(0,0,0,1)} From 3b717b2caf54fcaeac6755d63112bc3158d500a8 Mon Sep 17 00:00:00 2001 From: tushar Date: Wed, 15 Jun 2022 15:40:36 +0530 Subject: [PATCH 12/28] Revert "viewBox translation temporary (non generic fix)" This reverts commit b5b67e03532c1db609fa8d88ee0e692e5d21c659. --- svgnative/src/SVGDocumentImpl.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/svgnative/src/SVGDocumentImpl.cpp b/svgnative/src/SVGDocumentImpl.cpp index 91ef3b29..e7fd7ae2 100644 --- a/svgnative/src/SVGDocumentImpl.cpp +++ b/svgnative/src/SVGDocumentImpl.cpp @@ -965,7 +965,7 @@ void SVGDocumentImpl::RenderElement(const Element& element, const ColorMap& colo GraphicStyleImpl graphicStyle{}; graphicStyle.transform = mRenderer->CreateTransform(); - // graphicStyle.transform->Translate(-1 * mViewBox[0], -1 * mViewBox[1]); + graphicStyle.transform->Translate(-1 * mViewBox[0], -1 * mViewBox[1]); graphicStyle.transform->Scale(scale, scale); auto saveRestore = SaveRestoreHelper{mRenderer, graphicStyle}; @@ -982,7 +982,6 @@ bool SVGDocumentImpl::GetBoundingBox(Rect& bound) GraphicStyleImpl graphicStyle{}; graphicStyle.transform = mRenderer->CreateTransform(); - /*Not making a change here right now as this API is not called by us currently, it was newly added*/ graphicStyle.transform->Translate(-1 * mViewBox[0], -1 * mViewBox[1]); auto saveRestore = SaveRestoreHelper{mRenderer, graphicStyle}; ExtractBounds(*mGroup); @@ -1009,7 +1008,6 @@ bool SVGDocumentImpl::GetBoundingBox(const char* id, Rect& bound) // figure out a way to supply width/height for this I guess? GraphicStyleImpl graphicStyle{}; graphicStyle.transform = mRenderer->CreateTransform(); - /*Not making a change here right now as this API is not called by us currently, it was newly added*/ graphicStyle.transform->Translate(-1 * mViewBox[0], -1 * mViewBox[1]); auto saveRestore = SaveRestoreHelper{mRenderer, graphicStyle}; const auto elementIter = mIdToElementMap.find(id); @@ -1044,7 +1042,6 @@ bool GetSubBoundingBoxes(std::vector& bounds); return false; GraphicStyleImpl graphicStyle{}; graphicStyle.transform = mRenderer->CreateTransform(); - /*Not making a change here right now as this API is not called by us currently, it was newly added*/ graphicStyle.transform->Translate(-1 * mViewBox[0], -1 * mViewBox[1]); auto saveRestore = SaveRestoreHelper{mRenderer, graphicStyle}; ExtractBounds(*mGroup); @@ -1060,7 +1057,6 @@ bool GetSubBoundingBoxes(const char* id, std::vector& bounds); return false; GraphicStyleImpl graphicStyle{}; graphicStyle.transform = mRenderer->CreateTransform(); - /*Not making a change here right now as this API is not called by us currently, it was newly added*/ graphicStyle.transform->Translate(-1 * mViewBox[0], -1 * mViewBox[1]); auto saveRestore = SaveRestoreHelper{mRenderer, graphicStyle}; const auto elementIter = mIdToElementMap.find(id); From 6766faee20fa17339da3b89ef603d5076c69caf7 Mon Sep 17 00:00:00 2001 From: tushar Date: Wed, 15 Jun 2022 15:41:41 +0530 Subject: [PATCH 13/28] Revert "Temporary fix for pixelisation issue" This reverts commit 798d7df5ee9b582c66de919f99f1326ba53b2e69. --- svgnative/include/svgnative/SVGRenderer.h | 4 ---- svgnative/src/SVGDocument.cpp | 6 ------ svgnative/src/SVGDocumentImpl.cpp | 1 - svgnative/src/SVGDocumentImpl.h | 1 - 4 files changed, 12 deletions(-) diff --git a/svgnative/include/svgnative/SVGRenderer.h b/svgnative/include/svgnative/SVGRenderer.h index 46122a9d..aa09bb44 100644 --- a/svgnative/include/svgnative/SVGRenderer.h +++ b/svgnative/include/svgnative/SVGRenderer.h @@ -250,10 +250,6 @@ class SVGRenderer throw "Bound calculation functionality not implemented in this port"; return Rect{0, 0, 0, 0}; } - virtual void UpdateWidthAndHeight(float& width,float& height) - { - // reason for being empty function is "no need to define same function in skia unless it requires" - } }; class SaveRestoreHelper diff --git a/svgnative/src/SVGDocument.cpp b/svgnative/src/SVGDocument.cpp index 0fada524..7c946590 100644 --- a/svgnative/src/SVGDocument.cpp +++ b/svgnative/src/SVGDocument.cpp @@ -66,12 +66,6 @@ void SVGDocument::Render() ColorMap colorMap; mDocument->Render(colorMap, mDocument->mViewBox[2], mDocument->mViewBox[3]); - // to update width and height in doc if view box is not present in svg file - // so that no problem in transformation matrix - if (mDocument->mViewBoxAttrFound == false) - { - mDocument->mRenderer->UpdateWidthAndHeight(mDocument->mViewBox[2], mDocument->mViewBox[3]); - } } void SVGDocument::Render(float width, float height) diff --git a/svgnative/src/SVGDocumentImpl.cpp b/svgnative/src/SVGDocumentImpl.cpp index e7fd7ae2..d9cfad5a 100644 --- a/svgnative/src/SVGDocumentImpl.cpp +++ b/svgnative/src/SVGDocumentImpl.cpp @@ -85,7 +85,6 @@ void SVGDocumentImpl::TraverseSVGTree(XMLNode* rootNode) } else { - mViewBoxAttrFound = true; std::vector numberList; if (SVGStringParser::ParseListOfNumbers(viewBoxAttr.value, numberList) && numberList.size() == 4) mViewBox = {{numberList[0], numberList[1], numberList[2], numberList[3]}}; diff --git a/svgnative/src/SVGDocumentImpl.h b/svgnative/src/SVGDocumentImpl.h index 3a2db1ca..8a82621e 100644 --- a/svgnative/src/SVGDocumentImpl.h +++ b/svgnative/src/SVGDocumentImpl.h @@ -209,7 +209,6 @@ class SVGDocumentImpl std::array mViewBox; std::shared_ptr mRenderer; - bool mViewBoxAttrFound {false}; private: float ParseLengthFromAttr(const xml::XMLNode* child, const char* attrName, LengthType lengthType = LengthType::kHorizontal, float fallback = 0); From cb64d5a8669f957805d82a057de58ab17681df30 Mon Sep 17 00:00:00 2001 From: Milind Anand Date: Fri, 16 Sep 2022 10:09:25 +0530 Subject: [PATCH 14/28] Fix Bounding Box Issue --- svgnative/include/svgnative/SVGDocument.h | 4 ++++ svgnative/src/SVGDocument.cpp | 13 +++++++++++++ svgnative/src/SVGDocumentImpl.cpp | 10 +++++++--- svgnative/src/SVGDocumentImpl.h | 2 ++ 4 files changed, 26 insertions(+), 3 deletions(-) diff --git a/svgnative/include/svgnative/SVGDocument.h b/svgnative/include/svgnative/SVGDocument.h index db4ca0c9..8ae529a1 100644 --- a/svgnative/include/svgnative/SVGDocument.h +++ b/svgnative/include/svgnative/SVGDocument.h @@ -192,6 +192,10 @@ class SVG_IMP_EXP SVGDocument * set, otherwise an assertion will fire. */ bool GetBoundingBox(const char* id, Rect& bounds); + + void GetViewBox(Rect& viewBox); + + std::shared_ptr GetRootNodeTransform(); private: SVGDocument(); diff --git a/svgnative/src/SVGDocument.cpp b/svgnative/src/SVGDocument.cpp index 7c946590..83a587b5 100644 --- a/svgnative/src/SVGDocument.cpp +++ b/svgnative/src/SVGDocument.cpp @@ -143,6 +143,14 @@ bool SVGDocument::GetBoundingBox(const char *id, Rect& bounds) return mDocument->GetBoundingBox(id, bounds); } +void SVGDocument::GetViewBox(Rect& viewBox) +{ + viewBox.x = mDocument->mViewBox[0]; + viewBox.y = mDocument->mViewBox[1]; + viewBox.width = mDocument->mViewBox[2]; + viewBox.height = mDocument->mViewBox[3]; +} + #ifdef DEBUG_API bool GetSubBoundingBoxes(std::vector& bounds) { @@ -175,6 +183,11 @@ SVGRenderer* SVGDocument::Renderer() const return mDocument->mRenderer.get(); } +std::shared_ptr SVGDocument::GetRootNodeTransform() +{ + return mDocument->mRootNodeTransform; +} + #ifdef STYLE_SUPPORT void SVGDocument::AddCustomCSS(const StyleSheet::CssDocument* cssDocument) { diff --git a/svgnative/src/SVGDocumentImpl.cpp b/svgnative/src/SVGDocumentImpl.cpp index d9cfad5a..4b964e8c 100644 --- a/svgnative/src/SVGDocumentImpl.cpp +++ b/svgnative/src/SVGDocumentImpl.cpp @@ -571,7 +571,13 @@ GraphicStyleImpl SVGDocumentImpl::ParseGraphic( if (!SVGStringParser::ParseTransform(transformAttr.value, *graphicStyle.transform)) graphicStyle.transform.reset(); } - + else if (transformAttr.found && node == mRootNode) + { + SVG_ASSERT(mRenderer != nullptr); + mRootNodeTransform = mRenderer->CreateTransform(); + if (!SVGStringParser::ParseTransform(transformAttr.value, *mRootNodeTransform)) + mRootNodeTransform.reset(); + } return graphicStyle; } @@ -1029,8 +1035,6 @@ void SVGDocumentImpl::UpdateViewBox(Rect& bounds) { mViewBox[0] = bounds.x; mViewBox[1] = bounds.y; - mViewBox[2] = bounds.width; - mViewBox[3] = bounds.height; } #ifdef DEBUG_API diff --git a/svgnative/src/SVGDocumentImpl.h b/svgnative/src/SVGDocumentImpl.h index 8a82621e..2a1d4e6b 100644 --- a/svgnative/src/SVGDocumentImpl.h +++ b/svgnative/src/SVGDocumentImpl.h @@ -209,6 +209,8 @@ class SVGDocumentImpl std::array mViewBox; std::shared_ptr mRenderer; + bool mViewBoxAttrFound {false}; + std::shared_ptr mRootNodeTransform; private: float ParseLengthFromAttr(const xml::XMLNode* child, const char* attrName, LengthType lengthType = LengthType::kHorizontal, float fallback = 0); From bd32ab8d569a050eee76d38565b160e4d8a27191 Mon Sep 17 00:00:00 2001 From: Milind Anand Date: Thu, 22 Sep 2022 11:54:17 +0530 Subject: [PATCH 15/28] Revert "Fix Bounding Box Issue" This reverts commit cb64d5a8669f957805d82a057de58ab17681df30. --- svgnative/include/svgnative/SVGDocument.h | 4 ---- svgnative/src/SVGDocument.cpp | 13 ------------- svgnative/src/SVGDocumentImpl.cpp | 10 +++------- svgnative/src/SVGDocumentImpl.h | 2 -- 4 files changed, 3 insertions(+), 26 deletions(-) diff --git a/svgnative/include/svgnative/SVGDocument.h b/svgnative/include/svgnative/SVGDocument.h index 8ae529a1..db4ca0c9 100644 --- a/svgnative/include/svgnative/SVGDocument.h +++ b/svgnative/include/svgnative/SVGDocument.h @@ -192,10 +192,6 @@ class SVG_IMP_EXP SVGDocument * set, otherwise an assertion will fire. */ bool GetBoundingBox(const char* id, Rect& bounds); - - void GetViewBox(Rect& viewBox); - - std::shared_ptr GetRootNodeTransform(); private: SVGDocument(); diff --git a/svgnative/src/SVGDocument.cpp b/svgnative/src/SVGDocument.cpp index 83a587b5..7c946590 100644 --- a/svgnative/src/SVGDocument.cpp +++ b/svgnative/src/SVGDocument.cpp @@ -143,14 +143,6 @@ bool SVGDocument::GetBoundingBox(const char *id, Rect& bounds) return mDocument->GetBoundingBox(id, bounds); } -void SVGDocument::GetViewBox(Rect& viewBox) -{ - viewBox.x = mDocument->mViewBox[0]; - viewBox.y = mDocument->mViewBox[1]; - viewBox.width = mDocument->mViewBox[2]; - viewBox.height = mDocument->mViewBox[3]; -} - #ifdef DEBUG_API bool GetSubBoundingBoxes(std::vector& bounds) { @@ -183,11 +175,6 @@ SVGRenderer* SVGDocument::Renderer() const return mDocument->mRenderer.get(); } -std::shared_ptr SVGDocument::GetRootNodeTransform() -{ - return mDocument->mRootNodeTransform; -} - #ifdef STYLE_SUPPORT void SVGDocument::AddCustomCSS(const StyleSheet::CssDocument* cssDocument) { diff --git a/svgnative/src/SVGDocumentImpl.cpp b/svgnative/src/SVGDocumentImpl.cpp index 4b964e8c..d9cfad5a 100644 --- a/svgnative/src/SVGDocumentImpl.cpp +++ b/svgnative/src/SVGDocumentImpl.cpp @@ -571,13 +571,7 @@ GraphicStyleImpl SVGDocumentImpl::ParseGraphic( if (!SVGStringParser::ParseTransform(transformAttr.value, *graphicStyle.transform)) graphicStyle.transform.reset(); } - else if (transformAttr.found && node == mRootNode) - { - SVG_ASSERT(mRenderer != nullptr); - mRootNodeTransform = mRenderer->CreateTransform(); - if (!SVGStringParser::ParseTransform(transformAttr.value, *mRootNodeTransform)) - mRootNodeTransform.reset(); - } + return graphicStyle; } @@ -1035,6 +1029,8 @@ void SVGDocumentImpl::UpdateViewBox(Rect& bounds) { mViewBox[0] = bounds.x; mViewBox[1] = bounds.y; + mViewBox[2] = bounds.width; + mViewBox[3] = bounds.height; } #ifdef DEBUG_API diff --git a/svgnative/src/SVGDocumentImpl.h b/svgnative/src/SVGDocumentImpl.h index 2a1d4e6b..8a82621e 100644 --- a/svgnative/src/SVGDocumentImpl.h +++ b/svgnative/src/SVGDocumentImpl.h @@ -209,8 +209,6 @@ class SVGDocumentImpl std::array mViewBox; std::shared_ptr mRenderer; - bool mViewBoxAttrFound {false}; - std::shared_ptr mRootNodeTransform; private: float ParseLengthFromAttr(const xml::XMLNode* child, const char* attrName, LengthType lengthType = LengthType::kHorizontal, float fallback = 0); From 7c8084644ba322baf1990fe4f47dd61c2d4c9478 Mon Sep 17 00:00:00 2001 From: Milind Anand Date: Thu, 22 Sep 2022 13:10:42 +0530 Subject: [PATCH 16/28] Add GetViewBox() to retrieve viewBox dimensions * Part of changes required to support the fix for the bounding box issue. ViewBox dimensions will be used to shift the glyph. * Also removed UpdateViewBox() as it was not needed anymore. --- svgnative/include/svgnative/SVGDocument.h | 4 +++- svgnative/src/SVGDocument.cpp | 13 +++++++++---- svgnative/src/SVGDocumentImpl.cpp | 8 -------- svgnative/src/SVGDocumentImpl.h | 1 - 4 files changed, 12 insertions(+), 14 deletions(-) diff --git a/svgnative/include/svgnative/SVGDocument.h b/svgnative/include/svgnative/SVGDocument.h index db4ca0c9..3dc9c958 100644 --- a/svgnative/include/svgnative/SVGDocument.h +++ b/svgnative/include/svgnative/SVGDocument.h @@ -192,7 +192,9 @@ class SVG_IMP_EXP SVGDocument * set, otherwise an assertion will fire. */ bool GetBoundingBox(const char* id, Rect& bounds); - + + void GetViewBox(Rect& viewBox); + private: SVGDocument(); diff --git a/svgnative/src/SVGDocument.cpp b/svgnative/src/SVGDocument.cpp index 7c946590..ca3b67ec 100644 --- a/svgnative/src/SVGDocument.cpp +++ b/svgnative/src/SVGDocument.cpp @@ -130,10 +130,7 @@ bool SVGDocument::GetBoundingBox(Rect& bounds) { if (!mDocument) return false; - bool bStatus = mDocument->GetBoundingBox(bounds); - if (bStatus && bounds.IsEmpty()== false) - mDocument->UpdateViewBox(bounds); - return bStatus; + return mDocument->GetBoundingBox(bounds); } bool SVGDocument::GetBoundingBox(const char *id, Rect& bounds) @@ -143,6 +140,14 @@ bool SVGDocument::GetBoundingBox(const char *id, Rect& bounds) return mDocument->GetBoundingBox(id, bounds); } +void SVGDocument::GetViewBox(Rect& viewBox) +{ + viewBox.x = mDocument->mViewBox[0]; + viewBox.y = mDocument->mViewBox[1]; + viewBox.width = mDocument->mViewBox[2]; + viewBox.height = mDocument->mViewBox[3]; +} + #ifdef DEBUG_API bool GetSubBoundingBoxes(std::vector& bounds) { diff --git a/svgnative/src/SVGDocumentImpl.cpp b/svgnative/src/SVGDocumentImpl.cpp index d9cfad5a..f0172298 100644 --- a/svgnative/src/SVGDocumentImpl.cpp +++ b/svgnative/src/SVGDocumentImpl.cpp @@ -1025,14 +1025,6 @@ bool SVGDocumentImpl::GetBoundingBox(const char* id, Rect& bound) return true; } -void SVGDocumentImpl::UpdateViewBox(Rect& bounds) -{ - mViewBox[0] = bounds.x; - mViewBox[1] = bounds.y; - mViewBox[2] = bounds.width; - mViewBox[3] = bounds.height; -} - #ifdef DEBUG_API bool GetSubBoundingBoxes(std::vector& bounds); { diff --git a/svgnative/src/SVGDocumentImpl.h b/svgnative/src/SVGDocumentImpl.h index 8a82621e..e2f2015a 100644 --- a/svgnative/src/SVGDocumentImpl.h +++ b/svgnative/src/SVGDocumentImpl.h @@ -201,7 +201,6 @@ class SVGDocumentImpl bool GetBoundingBox(Rect& bounds); bool GetBoundingBox(const char* id, Rect& bounds); - void UpdateViewBox(Rect& bounds); #ifdef DEBUG_API bool GetSubBoundingBoxes(std::vector& bounds); bool GetSubBoundingBoxes(const char* id, std::vector& bounds); From be71d0db1066a58b333ee482e35010feb67ded0c Mon Sep 17 00:00:00 2001 From: Milind Anand Date: Fri, 23 Sep 2022 20:49:11 +0530 Subject: [PATCH 17/28] Dummy commit From bb6c449c41e34d7d9cdf6e4d6c0bf830504dbb6a Mon Sep 17 00:00:00 2001 From: Milind Anand Date: Fri, 30 Sep 2022 18:43:02 +0530 Subject: [PATCH 18/28] Update baseline for image.svg * Changed the baseline for image.svg as the old one was using default values of width and height which are now being obtained after parsing the image data --- svgnative/test/image.txt | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/svgnative/test/image.txt b/svgnative/test/image.txt index 6d949e43..19d50130 100644 --- a/svgnative/test/image.txt +++ b/svgnative/test/image.txt @@ -2,7 +2,7 @@ [group [group [group transform: matrix(1,0,0,1,20,40) - [image clip(0, 0, 30, 40) fill(0, 9.69, 30, 20.6) (PNG) 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] + [image clip(0, 0, 30, 40) fill(0, 0, 30, 40) (PNG) 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] ] [group transform: matrix(1,0,0,1,10,120) [path Rect(0.5,0.5,49,29) @@ -16,19 +16,19 @@ ] [group transform: matrix(1,0,0,1,100,60) [group - [image clip(0, 0, 50, 30) fill(0, 0, 43.6, 30) (PNG) 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] + [image clip(0, 0, 50, 30) fill(0, 0, 50, 30) (PNG) iVBORw0KGgoAAAANSUhEUgAAAH0AAACoCAYAAADNc+G5AAAACXBIWXMAAC4jAAAuIwF4pT92AAAHn0lEQVR4Xu2bQXLkOBAD2RF6zz5mPrxP0xzGjm631QIgsgoUybms0xYqWYXzPvb9/72UUkp5lFJK2b/o+e/o9+zvor6tzSvf1uaVb2vz3LePfS/7vj/Kvn//4VEYLuVR9v2M+VmII2dnurw3e/LGDsFD+azKka5eikBZlc9md1m69ziZLj6rcpPSvcfJdPFZlSNdys1W6amz+3DdpHQ+i9i7Rx+uitL5ByFWHlzL87g+f/uxdO+DR3XxWcQ1e6zShSxi7x68q9PS+Sxi7x59uoTS+QchrnmwyvO4+OwqXZiFOHJ2S9f2/OX7kOtDEXtdfFblSFfLm3VSOp9VOdLlvdl110np/BCVI10tj4PY6+Kz75xSuvc4mS4+q3JL1yq9gnNnt3NNUDqfRezdo53LVDqfRRx5nFFdG/ORypEPntfFZxGv0gXOnR3nGrB0PovYu0ecK6l0PqtypCuziEzX7UrPPI7XxWdVblK69ziZLj6rcqTrffYApfNZlSNdzpsFlc5nVY50OYvIdHVfuvM4uS4+q3KT0r3HGdXFZxGjPVbppy4+i9i7x0++Yel8FrF3D5+rUel8FjF6sDIL8Tyun99SpXsfPKqLzyJW91ilp83ux3WD0vmsypEu783OXRdL5x+kcqRLPU4Ne13nWXvp3uNkuvisyqrrsHTvcTJdfFblSFftzTosnc+qHOny3kxzkaXzD1I50lV7HIW9Lj6774bSvccZ1cVn9/2rdO+DR3XxWcSt95isdD6L2LtHnauD0vksYu8e93F9KF0bkvng5dKyR7xKv8i5s9u6Bi+dz6oc6Yq+maF0PqtypCu6iEzXxnxUw60ffD57VBefZbh56d7jZLr4rMqRrlKGK53Pqhzpyr5ZQul8VuVIV3YRma5blZ59nFFd1aVnP3gOF59FfLTHKp128VnE3j1uXzqfRezdI9cVUDqfRew+zpiuopfuffCoLj6LmNljlZ4wO9PF3OxmpfNZlSNd3pv9djUonc+qHOlijsPOQux1/f62q9K9x8l08VmVGRcs3XucTBefVTnSdeVmnZfOZ1WOdHlvhl3TlO7doy/XhdL5ByG+8uCrPI8LZ3+V7n3wqC4+i7jFHhOXzmcRe/fQXZ2VzmcRe/fo20WUjoew3OLBLM/j4rPfvEpvwJGzI1yb9ziZLj6rcqQr4mZf/39626H8AnxW5UhXRBGZroPScegqt3gwP3tUF5/9xKGle4+T6eKzKke4Bi6dz6oc6cq42SqdYO8e7V3JpfNZxBnHGdW1vQ5kQ84Hz+fis4i/Z2+vH6AQYu9xMl18FrFjj4FK57OIvXvEu4JL57OIHccZ1bVK787FZ1VuUrr3OJkuPqtypOvTzW5cOp9VOdLlvdk/blw6n1U50tVDEUxW5U+zuy3de5xMF59VuUnp3uOM6uKziNk9Vunps/2uG5XOZxF79/C7KkvnH4SYfXALnsd1/O1p6d4Hj+ris4iv7rFKF7OIvXtwro5L57OIvXv05xJL5x+kcqTr6nGusNfFZW2le4+T6eKzKl91bT9/+T7k2lCGvS4+q3Kkq9XNOiqdz6oc6fLe7JoLlM4NucKRrlbHYdjr4rOvnFa69zijuvjsK6/SKzl3dhvXJKXzWcTePdq4jKXzWcRRxxnVtTEfXeGoB8/t4rNnvEoXOXd2jGvQ0vmsypGurJslls5nVY50ZRWR6bpl6VnH8bv4rMLNSvceJ9PFZ1WOdL3OHqR0PqtypMt1s8DS+azKkS5XEZmuW5TuOs6orsulux48tovPIj7bY5UOXXwWsXePJ9+0dD6L2LuHx9WwdD6LuJfjoKzKXtfzZ7p074NHdfFZxMoeq/TA2Zku5WY3KZ3Pqhzp8t7ss6uidP5BKke6lOPUstf1+dsuSvceJ9PFZ1VWXB9L9x4n08VnVY501dys09L5rMqRLu/NeNfwpXv36NMllM4/CHHNg1Wex8Vnt+cvnQ8e1cVnEbfcY8LS+Sxi7x7XXZ2UzmcRe/e4h+ukdH4I4pYPRjyPi8++8yq9giNnR7omKJ3PqhzpiryZqXQ+q3KkK7KITNfGfFTLLR+MZ4/q4rOIQ0r3HifTxWdVjnQNWDqfVTnSlXmzVbo0ewxXUul8FnHmcUZ1NSk988HzuPgs4vfZq3TJxWcRO/cYoHQ+i9i7R54rqHQ+i9h5nFFdq/RuXHxW5Sale4+T6eKzKke60M1uWDqfVTnS5b3ZT25UOp9VOdKFjqPMQux1/fy2u9K9x8l08VmVkYsq3XucTBefVTnSpd5slZ42ux/XDUrns4i9e/Tjulg6/yDE6oNreB7XefawdO+DR3XxWcS1e0xeOp9F7N1Dc3VYOp9F7N2jXxdZOv8glSNdtcdR2Ovis/tuKN17nEwXn1W51rUdD6kbqj0408VnVY50tb5ZB6XzWZUjXd6b1bk+lK4NUTjS1fo4/br47BGHl+49zqguPnvEq/SLnDu7rWvw0vksYu8ebV2G0vks4ujjjOramI8Ujn7wnC4+i7iUVTrNubNjXYOVzmcRe/eIdSWUzmdVjnRlF5HnKmX78+e/su+llPL9x98///vv68/o2+t/V77l/q58W/t35dvavyvfPsrrv78x98C7+TTMeAAAAABJRU5ErkJggg==] [path Rect(0.5,0.5,49,29) fill: {hasFill: false winding: nonzero paint: rgba(0,0,0,0)} stroke: {hasStroke: true width: 1 cap: butt join: miter miter: 4 dashOffset: 0 paint: rgba(0,0,0,1)}] ] [group transform: matrix(1,0,0,1,70,0) - [image clip(0, 0, 50, 30) fill(3.18, 0, 43.6, 30) (PNG) iVBORw0KGgoAAAANSUhEUgAAAH0AAACoCAYAAADNc+G5AAAACXBIWXMAAC4jAAAuIwF4pT92AAAHn0lEQVR4Xu2bQXLkOBAD2RF6zz5mPrxP0xzGjm631QIgsgoUybms0xYqWYXzPvb9/72UUkp5lFJK2b/o+e/o9+zvor6tzSvf1uaVb2vz3LePfS/7vj/Kvn//4VEYLuVR9v2M+VmII2dnurw3e/LGDsFD+azKka5eikBZlc9md1m69ziZLj6rcpPSvcfJdPFZlSNdys1W6amz+3DdpHQ+i9i7Rx+uitL5ByFWHlzL87g+f/uxdO+DR3XxWcQ1e6zShSxi7x68q9PS+Sxi7x59uoTS+QchrnmwyvO4+OwqXZiFOHJ2S9f2/OX7kOtDEXtdfFblSFfLm3VSOp9VOdLlvdl110np/BCVI10tj4PY6+Kz75xSuvc4mS4+q3JL1yq9gnNnt3NNUDqfRezdo53LVDqfRRx5nFFdG/ORypEPntfFZxGv0gXOnR3nGrB0PovYu0ecK6l0PqtypCuziEzX7UrPPI7XxWdVblK69ziZLj6rcqTrffYApfNZlSNdzpsFlc5nVY50OYvIdHVfuvM4uS4+q3KT0r3HGdXFZxGjPVbppy4+i9i7x0++Yel8FrF3D5+rUel8FjF6sDIL8Tyun99SpXsfPKqLzyJW91ilp83ux3WD0vmsypEu783OXRdL5x+kcqRLPU4Ne13nWXvp3uNkuvisyqrrsHTvcTJdfFblSFftzTosnc+qHOny3kxzkaXzD1I50lV7HIW9Lj6774bSvccZ1cVn9/2rdO+DR3XxWcSt95isdD6L2LtHnauD0vksYu8e93F9KF0bkvng5dKyR7xKv8i5s9u6Bi+dz6oc6Yq+maF0PqtypCu6iEzXxnxUw60ffD57VBefZbh56d7jZLr4rMqRrlKGK53Pqhzpyr5ZQul8VuVIV3YRma5blZ59nFFd1aVnP3gOF59FfLTHKp128VnE3j1uXzqfRezdI9cVUDqfRew+zpiuopfuffCoLj6LmNljlZ4wO9PF3OxmpfNZlSNd3pv9djUonc+qHOlijsPOQux1/f62q9K9x8l08VmVGRcs3XucTBefVTnSdeVmnZfOZ1WOdHlvhl3TlO7doy/XhdL5ByG+8uCrPI8LZ3+V7n3wqC4+i7jFHhOXzmcRe/fQXZ2VzmcRe/fo20WUjoew3OLBLM/j4rPfvEpvwJGzI1yb9ziZLj6rcqQr4mZf/39626H8AnxW5UhXRBGZroPScegqt3gwP3tUF5/9xKGle4+T6eKzKke4Bi6dz6oc6cq42SqdYO8e7V3JpfNZxBnHGdW1vQ5kQ84Hz+fis4i/Z2+vH6AQYu9xMl18FrFjj4FK57OIvXvEu4JL57OIHccZ1bVK787FZ1VuUrr3OJkuPqtypOvTzW5cOp9VOdLlvdk/blw6n1U50tVDEUxW5U+zuy3de5xMF59VuUnp3uOM6uKziNk9Vunps/2uG5XOZxF79/C7KkvnH4SYfXALnsd1/O1p6d4Hj+ris4iv7rFKF7OIvXtwro5L57OIvXv05xJL5x+kcqTr6nGusNfFZW2le4+T6eKzKl91bT9/+T7k2lCGvS4+q3Kkq9XNOiqdz6oc6fLe7JoLlM4NucKRrlbHYdjr4rOvnFa69zijuvjsK6/SKzl3dhvXJKXzWcTePdq4jKXzWcRRxxnVtTEfXeGoB8/t4rNnvEoXOXd2jGvQ0vmsypGurJslls5nVY50ZRWR6bpl6VnH8bv4rMLNSvceJ9PFZ1WOdL3OHqR0PqtypMt1s8DS+azKkS5XEZmuW5TuOs6orsulux48tovPIj7bY5UOXXwWsXePJ9+0dD6L2LuHx9WwdD6LuJfjoKzKXtfzZ7p074NHdfFZxMoeq/TA2Zku5WY3KZ3Pqhzp8t7ss6uidP5BKke6lOPUstf1+dsuSvceJ9PFZ1VWXB9L9x4n08VnVY501dys09L5rMqRLu/NeNfwpXv36NMllM4/CHHNg1Wex8Vnt+cvnQ8e1cVnEbfcY8LS+Sxi7x7XXZ2UzmcRe/e4h+ukdH4I4pYPRjyPi8++8yq9giNnR7omKJ3PqhzpiryZqXQ+q3KkK7KITNfGfFTLLR+MZ4/q4rOIQ0r3HifTxWdVjnQNWDqfVTnSlXmzVbo0ewxXUul8FnHmcUZ1NSk988HzuPgs4vfZq3TJxWcRO/cYoHQ+i9i7R54rqHQ+i9h5nFFdq/RuXHxW5Sale4+T6eKzKke60M1uWDqfVTnS5b3ZT25UOp9VOdKFjqPMQux1/fy2u9K9x8l08VmVkYsq3XucTBefVTnSpd5slZ42ux/XDUrns4i9e/Tjulg6/yDE6oNreB7XefawdO+DR3XxWcS1e0xeOp9F7N1Dc3VYOp9F7N2jXxdZOv8glSNdtcdR2Ovis/tuKN17nEwXn1W51rUdD6kbqj0408VnVY50tb5ZB6XzWZUjXd6b1bk+lK4NUTjS1fo4/br47BGHl+49zqguPnvEq/SLnDu7rWvw0vksYu8ebV2G0vks4ujjjOramI8Ujn7wnC4+i7iUVTrNubNjXYOVzmcRe/eIdSWUzmdVjnRlF5HnKmX78+e/su+llPL9x98///vv68/o2+t/V77l/q58W/t35dvavyvfPsrrv78x98C7+TTMeAAAAABJRU5ErkJggg==] + [image clip(0, 0, 50, 30) fill(0, 0, 50, 30) (PNG) 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] [path Rect(0.5,0.5,49,29) fill: {hasFill: false winding: nonzero paint: rgba(0,0,0,0)} stroke: {hasStroke: true width: 1 cap: butt join: miter miter: 4 dashOffset: 0 paint: rgba(0,0,0,1)}] ] [group transform: matrix(1,0,0,1,0,70) - [image clip(0, 0, 50, 30) fill(6.36, 0, 43.6, 30) (PNG) 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] + [image clip(0, 0, 50, 30) fill(0, 0, 50, 30) (PNG) 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] [path Rect(0.5,0.5,49,29) fill: {hasFill: false winding: nonzero paint: rgba(0,0,0,0)} stroke: {hasStroke: true width: 1 cap: butt join: miter miter: 4 dashOffset: 0 paint: rgba(0,0,0,1)}] @@ -36,19 +36,19 @@ ] [group transform: matrix(1,0,0,1,250,60) [group - [image clip(0, 0, 30, 60) fill(0, 0, 30, 20.6) (PNG) iVBORw0KGgoAAAANSUhEUgAAAH0AAACoCAYAAADNc+G5AAAACXBIWXMAAC4jAAAuIwF4pT92AAAHn0lEQVR4Xu2bQXLkOBAD2RF6zz5mPrxP0xzGjm631QIgsgoUybms0xYqWYXzPvb9/72UUkp5lFJK2b/o+e/o9+zvor6tzSvf1uaVb2vz3LePfS/7vj/Kvn//4VEYLuVR9v2M+VmII2dnurw3e/LGDsFD+azKka5eikBZlc9md1m69ziZLj6rcpPSvcfJdPFZlSNdys1W6amz+3DdpHQ+i9i7Rx+uitL5ByFWHlzL87g+f/uxdO+DR3XxWcQ1e6zShSxi7x68q9PS+Sxi7x59uoTS+QchrnmwyvO4+OwqXZiFOHJ2S9f2/OX7kOtDEXtdfFblSFfLm3VSOp9VOdLlvdl110np/BCVI10tj4PY6+Kz75xSuvc4mS4+q3JL1yq9gnNnt3NNUDqfRezdo53LVDqfRRx5nFFdG/ORypEPntfFZxGv0gXOnR3nGrB0PovYu0ecK6l0PqtypCuziEzX7UrPPI7XxWdVblK69ziZLj6rcqTrffYApfNZlSNdzpsFlc5nVY50OYvIdHVfuvM4uS4+q3KT0r3HGdXFZxGjPVbppy4+i9i7x0++Yel8FrF3D5+rUel8FjF6sDIL8Tyun99SpXsfPKqLzyJW91ilp83ux3WD0vmsypEu783OXRdL5x+kcqRLPU4Ne13nWXvp3uNkuvisyqrrsHTvcTJdfFblSFftzTosnc+qHOny3kxzkaXzD1I50lV7HIW9Lj6774bSvccZ1cVn9/2rdO+DR3XxWcSt95isdD6L2LtHnauD0vksYu8e93F9KF0bkvng5dKyR7xKv8i5s9u6Bi+dz6oc6Yq+maF0PqtypCu6iEzXxnxUw60ffD57VBefZbh56d7jZLr4rMqRrlKGK53Pqhzpyr5ZQul8VuVIV3YRma5blZ59nFFd1aVnP3gOF59FfLTHKp128VnE3j1uXzqfRezdI9cVUDqfRew+zpiuopfuffCoLj6LmNljlZ4wO9PF3OxmpfNZlSNd3pv9djUonc+qHOlijsPOQux1/f62q9K9x8l08VmVGRcs3XucTBefVTnSdeVmnZfOZ1WOdHlvhl3TlO7doy/XhdL5ByG+8uCrPI8LZ3+V7n3wqC4+i7jFHhOXzmcRe/fQXZ2VzmcRe/fo20WUjoew3OLBLM/j4rPfvEpvwJGzI1yb9ziZLj6rcqQr4mZf/39626H8AnxW5UhXRBGZroPScegqt3gwP3tUF5/9xKGle4+T6eKzKke4Bi6dz6oc6cq42SqdYO8e7V3JpfNZxBnHGdW1vQ5kQ84Hz+fis4i/Z2+vH6AQYu9xMl18FrFjj4FK57OIvXvEu4JL57OIHccZ1bVK787FZ1VuUrr3OJkuPqtypOvTzW5cOp9VOdLlvdk/blw6n1U50tVDEUxW5U+zuy3de5xMF59VuUnp3uOM6uKziNk9Vunps/2uG5XOZxF79/C7KkvnH4SYfXALnsd1/O1p6d4Hj+ris4iv7rFKF7OIvXtwro5L57OIvXv05xJL5x+kcqTr6nGusNfFZW2le4+T6eKzKl91bT9/+T7k2lCGvS4+q3Kkq9XNOiqdz6oc6fLe7JoLlM4NucKRrlbHYdjr4rOvnFa69zijuvjsK6/SKzl3dhvXJKXzWcTePdq4jKXzWcRRxxnVtTEfXeGoB8/t4rNnvEoXOXd2jGvQ0vmsypGurJslls5nVY50ZRWR6bpl6VnH8bv4rMLNSvceJ9PFZ1WOdL3OHqR0PqtypMt1s8DS+azKkS5XEZmuW5TuOs6orsulux48tovPIj7bY5UOXXwWsXePJ9+0dD6L2LuHx9WwdD6LuJfjoKzKXtfzZ7p074NHdfFZxMoeq/TA2Zku5WY3KZ3Pqhzp8t7ss6uidP5BKke6lOPUstf1+dsuSvceJ9PFZ1VWXB9L9x4n08VnVY501dys09L5rMqRLu/NeNfwpXv36NMllM4/CHHNg1Wex8Vnt+cvnQ8e1cVnEbfcY8LS+Sxi7x7XXZ2UzmcRe/e4h+ukdH4I4pYPRjyPi8++8yq9giNnR7omKJ3PqhzpiryZqXQ+q3KkK7KITNfGfFTLLR+MZ4/q4rOIQ0r3HifTxWdVjnQNWDqfVTnSlXmzVbo0ewxXUul8FnHmcUZ1NSk988HzuPgs4vfZq3TJxWcRO/cYoHQ+i9i7R54rqHQ+i9h5nFFdq/RuXHxW5Sale4+T6eKzKke60M1uWDqfVTnS5b3ZT25UOp9VOdKFjqPMQux1/fy2u9K9x8l08VmVkYsq3XucTBefVTnSpd5slZ42ux/XDUrns4i9e/Tjulg6/yDE6oNreB7XefawdO+DR3XxWcS1e0xeOp9F7N1Dc3VYOp9F7N2jXxdZOv8glSNdtcdR2Ovis/tuKN17nEwXn1W51rUdD6kbqj0408VnVY50tb5ZB6XzWZUjXd6b1bk+lK4NUTjS1fo4/br47BGHl+49zqguPnvEq/SLnDu7rWvw0vksYu8ebV2G0vks4ujjjOramI8Ujn7wnC4+i7iUVTrNubNjXYOVzmcRe/eIdSWUzmdVjnRlF5HnKmX78+e/su+llPL9x98///vv68/o2+t/V77l/q58W/t35dvavyvfPsrrv78x98C7+TTMeAAAAABJRU5ErkJggg==] + [image clip(0, 0, 30, 60) fill(0, 0, 30, 60) (PNG) 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] [path Rect(0.5,0.5,29,59) fill: {hasFill: false winding: nonzero paint: rgba(0,0,0,0)} stroke: {hasStroke: true width: 1 cap: butt join: miter miter: 4 dashOffset: 0 paint: rgba(0,0,0,1)}] ] [group transform: matrix(1,0,0,1,50,0) - [image clip(0, 0, 30, 60) fill(0, 19.7, 30, 20.6) (PNG) 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] + [image clip(0, 0, 30, 60) fill(0, 0, 30, 60) (PNG) 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] [path Rect(0.5,0.5,29,59) fill: {hasFill: false winding: nonzero paint: rgba(0,0,0,0)} stroke: {hasStroke: true width: 1 cap: butt join: miter miter: 4 dashOffset: 0 paint: rgba(0,0,0,1)}] ] [group transform: matrix(1,0,0,1,100,0) - [image clip(0, 0, 30, 60) fill(0, 39.4, 30, 20.6) (PNG) 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] + [image clip(0, 0, 30, 60) fill(0, 0, 30, 60) (PNG) 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] [path Rect(0.5,0.5,29,59) fill: {hasFill: false winding: nonzero paint: rgba(0,0,0,0)} stroke: {hasStroke: true width: 1 cap: butt join: miter miter: 4 dashOffset: 0 paint: rgba(0,0,0,1)}] @@ -56,19 +56,19 @@ ] [group transform: matrix(1,0,0,1,100,220) [group - [image clip(0, 0, 30, 60) fill(0, 0, 87.3, 60) (PNG) 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] + [image clip(0, 0, 30, 60) fill(0, 0, 30, 60) (PNG) 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] [path Rect(0.5,0.5,29,59) fill: {hasFill: false winding: nonzero paint: rgba(0,0,0,0)} stroke: {hasStroke: true width: 1 cap: butt join: miter miter: 4 dashOffset: 0 paint: rgba(0,0,0,1)}] ] [group transform: matrix(1,0,0,1,50,0) - [image clip(0, 0, 30, 60) fill(-28.6, 0, 87.3, 60) (PNG) iVBORw0KGgoAAAANSUhEUgAAAH0AAACoCAYAAADNc+G5AAAACXBIWXMAAC4jAAAuIwF4pT92AAAHn0lEQVR4Xu2bQXLkOBAD2RF6zz5mPrxP0xzGjm631QIgsgoUybms0xYqWYXzPvb9/72UUkp5lFJK2b/o+e/o9+zvor6tzSvf1uaVb2vz3LePfS/7vj/Kvn//4VEYLuVR9v2M+VmII2dnurw3e/LGDsFD+azKka5eikBZlc9md1m69ziZLj6rcpPSvcfJdPFZlSNdys1W6amz+3DdpHQ+i9i7Rx+uitL5ByFWHlzL87g+f/uxdO+DR3XxWcQ1e6zShSxi7x68q9PS+Sxi7x59uoTS+QchrnmwyvO4+OwqXZiFOHJ2S9f2/OX7kOtDEXtdfFblSFfLm3VSOp9VOdLlvdl110np/BCVI10tj4PY6+Kz75xSuvc4mS4+q3JL1yq9gnNnt3NNUDqfRezdo53LVDqfRRx5nFFdG/ORypEPntfFZxGv0gXOnR3nGrB0PovYu0ecK6l0PqtypCuziEzX7UrPPI7XxWdVblK69ziZLj6rcqTrffYApfNZlSNdzpsFlc5nVY50OYvIdHVfuvM4uS4+q3KT0r3HGdXFZxGjPVbppy4+i9i7x0++Yel8FrF3D5+rUel8FjF6sDIL8Tyun99SpXsfPKqLzyJW91ilp83ux3WD0vmsypEu783OXRdL5x+kcqRLPU4Ne13nWXvp3uNkuvisyqrrsHTvcTJdfFblSFftzTosnc+qHOny3kxzkaXzD1I50lV7HIW9Lj6774bSvccZ1cVn9/2rdO+DR3XxWcSt95isdD6L2LtHnauD0vksYu8e93F9KF0bkvng5dKyR7xKv8i5s9u6Bi+dz6oc6Yq+maF0PqtypCu6iEzXxnxUw60ffD57VBefZbh56d7jZLr4rMqRrlKGK53Pqhzpyr5ZQul8VuVIV3YRma5blZ59nFFd1aVnP3gOF59FfLTHKp128VnE3j1uXzqfRezdI9cVUDqfRew+zpiuopfuffCoLj6LmNljlZ4wO9PF3OxmpfNZlSNd3pv9djUonc+qHOlijsPOQux1/f62q9K9x8l08VmVGRcs3XucTBefVTnSdeVmnZfOZ1WOdHlvhl3TlO7doy/XhdL5ByG+8uCrPI8LZ3+V7n3wqC4+i7jFHhOXzmcRe/fQXZ2VzmcRe/fo20WUjoew3OLBLM/j4rPfvEpvwJGzI1yb9ziZLj6rcqQr4mZf/39626H8AnxW5UhXRBGZroPScegqt3gwP3tUF5/9xKGle4+T6eKzKke4Bi6dz6oc6cq42SqdYO8e7V3JpfNZxBnHGdW1vQ5kQ84Hz+fis4i/Z2+vH6AQYu9xMl18FrFjj4FK57OIvXvEu4JL57OIHccZ1bVK787FZ1VuUrr3OJkuPqtypOvTzW5cOp9VOdLlvdk/blw6n1U50tVDEUxW5U+zuy3de5xMF59VuUnp3uOM6uKziNk9Vunps/2uG5XOZxF79/C7KkvnH4SYfXALnsd1/O1p6d4Hj+ris4iv7rFKF7OIvXtwro5L57OIvXv05xJL5x+kcqTr6nGusNfFZW2le4+T6eKzKl91bT9/+T7k2lCGvS4+q3Kkq9XNOiqdz6oc6fLe7JoLlM4NucKRrlbHYdjr4rOvnFa69zijuvjsK6/SKzl3dhvXJKXzWcTePdq4jKXzWcRRxxnVtTEfXeGoB8/t4rNnvEoXOXd2jGvQ0vmsypGurJslls5nVY50ZRWR6bpl6VnH8bv4rMLNSvceJ9PFZ1WOdL3OHqR0PqtypMt1s8DS+azKkS5XEZmuW5TuOs6orsulux48tovPIj7bY5UOXXwWsXePJ9+0dD6L2LuHx9WwdD6LuJfjoKzKXtfzZ7p074NHdfFZxMoeq/TA2Zku5WY3KZ3Pqhzp8t7ss6uidP5BKke6lOPUstf1+dsuSvceJ9PFZ1VWXB9L9x4n08VnVY501dys09L5rMqRLu/NeNfwpXv36NMllM4/CHHNg1Wex8Vnt+cvnQ8e1cVnEbfcY8LS+Sxi7x7XXZ2UzmcRe/e4h+ukdH4I4pYPRjyPi8++8yq9giNnR7omKJ3PqhzpiryZqXQ+q3KkK7KITNfGfFTLLR+MZ4/q4rOIQ0r3HifTxWdVjnQNWDqfVTnSlXmzVbo0ewxXUul8FnHmcUZ1NSk988HzuPgs4vfZq3TJxWcRO/cYoHQ+i9i7R54rqHQ+i9h5nFFdq/RuXHxW5Sale4+T6eKzKke60M1uWDqfVTnS5b3ZT25UOp9VOdKFjqPMQux1/fy2u9K9x8l08VmVkYsq3XucTBefVTnSpd5slZ42ux/XDUrns4i9e/Tjulg6/yDE6oNreB7XefawdO+DR3XxWcS1e0xeOp9F7N1Dc3VYOp9F7N2jXxdZOv8glSNdtcdR2Ovis/tuKN17nEwXn1W51rUdD6kbqj0408VnVY50tb5ZB6XzWZUjXd6b1bk+lK4NUTjS1fo4/br47BGHl+49zqguPnvEq/SLnDu7rWvw0vksYu8ebV2G0vks4ujjjOramI8Ujn7wnC4+i7iUVTrNubNjXYOVzmcRe/eIdSWUzmdVjnRlF5HnKmX78+e/su+llPL9x98///vv68/o2+t/V77l/q58W/t35dvavyvfPsrrv78x98C7+TTMeAAAAABJRU5ErkJggg==] + [image clip(0, 0, 30, 60) fill(0, 0, 30, 60) (PNG) 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] [path Rect(0.5,0.5,29,59) fill: {hasFill: false winding: nonzero paint: rgba(0,0,0,0)} stroke: {hasStroke: true width: 1 cap: butt join: miter miter: 4 dashOffset: 0 paint: rgba(0,0,0,1)}] ] [group transform: matrix(1,0,0,1,100,0) - [image clip(0, 0, 30, 60) fill(-57.3, 0, 87.3, 60) (PNG) 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] + [image clip(0, 0, 30, 60) fill(0, 0, 30, 60) (PNG) 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] [path Rect(0.5,0.5,29,59) fill: {hasFill: false winding: nonzero paint: rgba(0,0,0,0)} stroke: {hasStroke: true width: 1 cap: butt join: miter miter: 4 dashOffset: 0 paint: rgba(0,0,0,1)}] @@ -76,19 +76,19 @@ ] [group transform: matrix(1,0,0,1,250,220) [group - [image clip(0, 0, 50, 30) fill(0, 0, 50, 34.4) (PNG) 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] + [image clip(0, 0, 50, 30) fill(0, 0, 50, 30) (PNG) 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] [path Rect(0.5,0.5,49,29) fill: {hasFill: false winding: nonzero paint: rgba(0,0,0,0)} stroke: {hasStroke: true width: 1 cap: butt join: miter miter: 4 dashOffset: 0 paint: rgba(0,0,0,1)}] ] [group transform: matrix(1,0,0,1,70,0) - [image clip(0, 0, 50, 30) fill(0, -2.19, 50, 34.4) (PNG) iVBORw0KGgoAAAANSUhEUgAAAH0AAACoCAYAAADNc+G5AAAACXBIWXMAAC4jAAAuIwF4pT92AAAHn0lEQVR4Xu2bQXLkOBAD2RF6zz5mPrxP0xzGjm631QIgsgoUybms0xYqWYXzPvb9/72UUkp5lFJK2b/o+e/o9+zvor6tzSvf1uaVb2vz3LePfS/7vj/Kvn//4VEYLuVR9v2M+VmII2dnurw3e/LGDsFD+azKka5eikBZlc9md1m69ziZLj6rcpPSvcfJdPFZlSNdys1W6amz+3DdpHQ+i9i7Rx+uitL5ByFWHlzL87g+f/uxdO+DR3XxWcQ1e6zShSxi7x68q9PS+Sxi7x59uoTS+QchrnmwyvO4+OwqXZiFOHJ2S9f2/OX7kOtDEXtdfFblSFfLm3VSOp9VOdLlvdl110np/BCVI10tj4PY6+Kz75xSuvc4mS4+q3JL1yq9gnNnt3NNUDqfRezdo53LVDqfRRx5nFFdG/ORypEPntfFZxGv0gXOnR3nGrB0PovYu0ecK6l0PqtypCuziEzX7UrPPI7XxWdVblK69ziZLj6rcqTrffYApfNZlSNdzpsFlc5nVY50OYvIdHVfuvM4uS4+q3KT0r3HGdXFZxGjPVbppy4+i9i7x0++Yel8FrF3D5+rUel8FjF6sDIL8Tyun99SpXsfPKqLzyJW91ilp83ux3WD0vmsypEu783OXRdL5x+kcqRLPU4Ne13nWXvp3uNkuvisyqrrsHTvcTJdfFblSFftzTosnc+qHOny3kxzkaXzD1I50lV7HIW9Lj6774bSvccZ1cVn9/2rdO+DR3XxWcSt95isdD6L2LtHnauD0vksYu8e93F9KF0bkvng5dKyR7xKv8i5s9u6Bi+dz6oc6Yq+maF0PqtypCu6iEzXxnxUw60ffD57VBefZbh56d7jZLr4rMqRrlKGK53Pqhzpyr5ZQul8VuVIV3YRma5blZ59nFFd1aVnP3gOF59FfLTHKp128VnE3j1uXzqfRezdI9cVUDqfRew+zpiuopfuffCoLj6LmNljlZ4wO9PF3OxmpfNZlSNd3pv9djUonc+qHOlijsPOQux1/f62q9K9x8l08VmVGRcs3XucTBefVTnSdeVmnZfOZ1WOdHlvhl3TlO7doy/XhdL5ByG+8uCrPI8LZ3+V7n3wqC4+i7jFHhOXzmcRe/fQXZ2VzmcRe/fo20WUjoew3OLBLM/j4rPfvEpvwJGzI1yb9ziZLj6rcqQr4mZf/39626H8AnxW5UhXRBGZroPScegqt3gwP3tUF5/9xKGle4+T6eKzKke4Bi6dz6oc6cq42SqdYO8e7V3JpfNZxBnHGdW1vQ5kQ84Hz+fis4i/Z2+vH6AQYu9xMl18FrFjj4FK57OIvXvEu4JL57OIHccZ1bVK787FZ1VuUrr3OJkuPqtypOvTzW5cOp9VOdLlvdk/blw6n1U50tVDEUxW5U+zuy3de5xMF59VuUnp3uOM6uKziNk9Vunps/2uG5XOZxF79/C7KkvnH4SYfXALnsd1/O1p6d4Hj+ris4iv7rFKF7OIvXtwro5L57OIvXv05xJL5x+kcqTr6nGusNfFZW2le4+T6eKzKl91bT9/+T7k2lCGvS4+q3Kkq9XNOiqdz6oc6fLe7JoLlM4NucKRrlbHYdjr4rOvnFa69zijuvjsK6/SKzl3dhvXJKXzWcTePdq4jKXzWcRRxxnVtTEfXeGoB8/t4rNnvEoXOXd2jGvQ0vmsypGurJslls5nVY50ZRWR6bpl6VnH8bv4rMLNSvceJ9PFZ1WOdL3OHqR0PqtypMt1s8DS+azKkS5XEZmuW5TuOs6orsulux48tovPIj7bY5UOXXwWsXePJ9+0dD6L2LuHx9WwdD6LuJfjoKzKXtfzZ7p074NHdfFZxMoeq/TA2Zku5WY3KZ3Pqhzp8t7ss6uidP5BKke6lOPUstf1+dsuSvceJ9PFZ1VWXB9L9x4n08VnVY501dys09L5rMqRLu/NeNfwpXv36NMllM4/CHHNg1Wex8Vnt+cvnQ8e1cVnEbfcY8LS+Sxi7x7XXZ2UzmcRe/e4h+ukdH4I4pYPRjyPi8++8yq9giNnR7omKJ3PqhzpiryZqXQ+q3KkK7KITNfGfFTLLR+MZ4/q4rOIQ0r3HifTxWdVjnQNWDqfVTnSlXmzVbo0ewxXUul8FnHmcUZ1NSk988HzuPgs4vfZq3TJxWcRO/cYoHQ+i9i7R54rqHQ+i9h5nFFdq/RuXHxW5Sale4+T6eKzKke60M1uWDqfVTnS5b3ZT25UOp9VOdKFjqPMQux1/fy2u9K9x8l08VmVkYsq3XucTBefVTnSpd5slZ42ux/XDUrns4i9e/Tjulg6/yDE6oNreB7XefawdO+DR3XxWcS1e0xeOp9F7N1Dc3VYOp9F7N2jXxdZOv8glSNdtcdR2Ovis/tuKN17nEwXn1W51rUdD6kbqj0408VnVY50tb5ZB6XzWZUjXd6b1bk+lK4NUTjS1fo4/br47BGHl+49zqguPnvEq/SLnDu7rWvw0vksYu8ebV2G0vks4ujjjOramI8Ujn7wnC4+i7iUVTrNubNjXYOVzmcRe/eIdSWUzmdVjnRlF5HnKmX78+e/su+llPL9x98///vv68/o2+t/V77l/q58W/t35dvavyvfPsrrv78x98C7+TTMeAAAAABJRU5ErkJggg==] + [image clip(0, 0, 50, 30) fill(0, 0, 50, 30) (PNG) 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] [path Rect(0.5,0.5,49,29) fill: {hasFill: false winding: nonzero paint: rgba(0,0,0,0)} stroke: {hasStroke: true width: 1 cap: butt join: miter miter: 4 dashOffset: 0 paint: rgba(0,0,0,1)}] ] [group transform: matrix(1,0,0,1,140,0) - [image clip(0, 0, 50, 30) fill(0, -4.38, 50, 34.4) (PNG) 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] + [image clip(0, 0, 50, 30) fill(0, 0, 50, 30) (PNG) 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] [path Rect(0.5,0.5,49,29) fill: {hasFill: false winding: nonzero paint: rgba(0,0,0,0)} stroke: {hasStroke: true width: 1 cap: butt join: miter miter: 4 dashOffset: 0 paint: rgba(0,0,0,1)}] From 8ce60fbdd29f2180bdf7d56ccc5c2d6f69434ba0 Mon Sep 17 00:00:00 2001 From: Milind Anand <113413597+anand-milind@users.noreply.github.com> Date: Fri, 7 Oct 2022 12:50:04 +0530 Subject: [PATCH 19/28] Updated config.yml --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 817e1c18..48b85363 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -84,7 +84,7 @@ jobs: command: 'cd svgnative && cmake --build build/linux' build_with_cocoa: macos: - xcode: "10.3.0" + xcode: "12.5.1" steps: - checkout - run: git submodule sync From 44b94a46c4ebb6219b03ccd3508279021d2d16cb Mon Sep 17 00:00:00 2001 From: Milind Anand Date: Fri, 7 Oct 2022 13:05:15 +0530 Subject: [PATCH 20/28] Remove unnecessary whitespace --- svgnative/src/SVGDocumentImpl.h | 1 - 1 file changed, 1 deletion(-) diff --git a/svgnative/src/SVGDocumentImpl.h b/svgnative/src/SVGDocumentImpl.h index f4692759..e2f2015a 100644 --- a/svgnative/src/SVGDocumentImpl.h +++ b/svgnative/src/SVGDocumentImpl.h @@ -201,7 +201,6 @@ class SVGDocumentImpl bool GetBoundingBox(Rect& bounds); bool GetBoundingBox(const char* id, Rect& bounds); - #ifdef DEBUG_API bool GetSubBoundingBoxes(std::vector& bounds); bool GetSubBoundingBoxes(const char* id, std::vector& bounds); From ca7a86462b86b636ddb2e439b22b1a3e2a40d0c4 Mon Sep 17 00:00:00 2001 From: Milind Anand Date: Fri, 7 Oct 2022 13:08:46 +0530 Subject: [PATCH 21/28] Fix error introduced during merging --- svgnative/src/SVGDocument.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/svgnative/src/SVGDocument.cpp b/svgnative/src/SVGDocument.cpp index 9d07ef6b..ca3b67ec 100644 --- a/svgnative/src/SVGDocument.cpp +++ b/svgnative/src/SVGDocument.cpp @@ -130,10 +130,7 @@ bool SVGDocument::GetBoundingBox(Rect& bounds) { if (!mDocument) return false; - bool bStatus = mDocument->GetBoundingBox(bounds); - if (bStatus && bounds.IsEmpty()== false) - mDocument->UpdateViewBox(bounds); - return bStatus; + return mDocument->GetBoundingBox(bounds); } bool SVGDocument::GetBoundingBox(const char *id, Rect& bounds) From f577dd518f31575639d6def6130e11cf4f72dc0b Mon Sep 17 00:00:00 2001 From: tushar Date: Thu, 23 Mar 2023 11:38:40 +0530 Subject: [PATCH 22/28] upgrade boost module version --- .gitmodules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitmodules b/.gitmodules index 2a99629e..5d91fe77 100644 --- a/.gitmodules +++ b/.gitmodules @@ -8,4 +8,4 @@ [submodule "third_party/boost_variant_property_tree"] path = third_party/boost_variant_property_tree url = https://github.com/dirkschulze/boost_variant_property_tree.git - branch = v1_65_1 + branch = v1_81_0 From 6103410b01a20507a56aef44587418451a1b3f3b Mon Sep 17 00:00:00 2001 From: tushar Date: Thu, 23 Mar 2023 16:46:45 +0530 Subject: [PATCH 23/28] update thirdparty submodules boost and cpp-base64 --- third_party/boost_variant_property_tree | 2 +- third_party/cpp-base64 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/third_party/boost_variant_property_tree b/third_party/boost_variant_property_tree index 1debcf72..da1b7bdf 160000 --- a/third_party/boost_variant_property_tree +++ b/third_party/boost_variant_property_tree @@ -1 +1 @@ -Subproject commit 1debcf72a5766cc5809463e231959107759f72a9 +Subproject commit da1b7bdfc3c50a127b7388e0d2271a359718739d diff --git a/third_party/cpp-base64 b/third_party/cpp-base64 index 6420804f..82147d6d 160000 --- a/third_party/cpp-base64 +++ b/third_party/cpp-base64 @@ -1 +1 @@ -Subproject commit 6420804f7ba10e8c3049c6e3b59ec88c88d808a6 +Subproject commit 82147d6d89636217b870f54ec07ddd3e544d5f69 From 18f4ca8246c03e269f901a36d96cd4b4f75d9aa8 Mon Sep 17 00:00:00 2001 From: tushar Date: Thu, 23 Mar 2023 17:01:51 +0530 Subject: [PATCH 24/28] Revert "update thirdparty submodules boost and cpp-base64" This reverts commit 6103410b01a20507a56aef44587418451a1b3f3b. --- third_party/boost_variant_property_tree | 2 +- third_party/cpp-base64 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/third_party/boost_variant_property_tree b/third_party/boost_variant_property_tree index da1b7bdf..1debcf72 160000 --- a/third_party/boost_variant_property_tree +++ b/third_party/boost_variant_property_tree @@ -1 +1 @@ -Subproject commit da1b7bdfc3c50a127b7388e0d2271a359718739d +Subproject commit 1debcf72a5766cc5809463e231959107759f72a9 diff --git a/third_party/cpp-base64 b/third_party/cpp-base64 index 82147d6d..6420804f 160000 --- a/third_party/cpp-base64 +++ b/third_party/cpp-base64 @@ -1 +1 @@ -Subproject commit 82147d6d89636217b870f54ec07ddd3e544d5f69 +Subproject commit 6420804f7ba10e8c3049c6e3b59ec88c88d808a6 From 71ea75a4f7119b044416778eeddc2f77f81e3c3d Mon Sep 17 00:00:00 2001 From: tushar Date: Thu, 23 Mar 2023 17:07:26 +0530 Subject: [PATCH 25/28] update only boost submodule --- third_party/boost_variant_property_tree | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/third_party/boost_variant_property_tree b/third_party/boost_variant_property_tree index 1debcf72..da1b7bdf 160000 --- a/third_party/boost_variant_property_tree +++ b/third_party/boost_variant_property_tree @@ -1 +1 @@ -Subproject commit 1debcf72a5766cc5809463e231959107759f72a9 +Subproject commit da1b7bdfc3c50a127b7388e0d2271a359718739d From 17bec6cd95d5502d7549d4828d4da57c5b0b9bc3 Mon Sep 17 00:00:00 2001 From: Tushar Jindal <90841856+tjindal@users.noreply.github.com> Date: Thu, 23 Mar 2023 18:52:54 +0530 Subject: [PATCH 26/28] fix in circleCi testcase (#184) * fix in circleCi testcase * minor fix in circleCi testcase --- svgnative/src/Rect.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/svgnative/src/Rect.cpp b/svgnative/src/Rect.cpp index 40949416..b2d8d30c 100644 --- a/svgnative/src/Rect.cpp +++ b/svgnative/src/Rect.cpp @@ -72,7 +72,9 @@ namespace SVGNative float topRightDiff = std::sqrt(std::pow(Right() - other.Right(), 2) + std::pow(Top() - other.Top(), 2)); float bottomLeftDiff = std::sqrt(std::pow(Left() - other.Left(), 2) + std::pow(Bottom() - other.Bottom(), 2)); float bottomRightDiff = std::sqrt(std::pow(Right() - other.Right(), 2) + std::pow(Bottom() - other.Bottom(), 2)); - return std::max({topLeftDiff, topRightDiff, bottomLeftDiff, bottomRightDiff}); + float max1 = std::max(topLeftDiff, topRightDiff); + float max2 = std::max(bottomLeftDiff, bottomRightDiff); + return std::max(max1,max2); } IntervalPair Rect::Intervals() const { return IntervalPair(Interval(x, x + width), Interval(y, y + height)); } From 09cc3ab8913d401acf08778fd165f0887bb37b25 Mon Sep 17 00:00:00 2001 From: Dirk Schulze Date: Mon, 8 Jan 2024 16:52:31 +0100 Subject: [PATCH 27/28] Add C++17 compatibility in addition to C++11 (#194) * Make code compatible to C++17 using std::variant * revert CMake changes * C++17 fix: remove cassert.h * Fix build issues with GDI+ * Use variadic macros for variant * Test C++17 on MSVS * potential build fix * Try using/templates * build fix * Revert CMakeFile changes --- README.md | 1 + svgnative/include/svgnative/Config.h | 3 ++ svgnative/include/svgnative/Rect.h | 1 - svgnative/include/svgnative/SVGRenderer.h | 31 +++++++++++++++-- svgnative/src/SVGDocumentImpl.cpp | 34 +++++++++---------- svgnative/src/SVGDocumentImpl.h | 4 +-- svgnative/src/SVGStringParser.cpp | 22 +++++++++--- .../src/ports/cairo/CairoSVGRenderer.cpp | 8 ++--- svgnative/src/ports/cg/CGSVGRenderer.cpp | 16 ++++----- svgnative/src/ports/d2d/D2DSVGRenderer.cpp | 9 ++--- .../src/ports/gdiplus/GDIPlusSVGRenderer.cpp | 16 ++++----- svgnative/src/ports/skia/SkiaSVGRenderer.cpp | 8 ++--- .../src/ports/string/StringSVGRenderer.cpp | 8 ++--- 13 files changed, 102 insertions(+), 59 deletions(-) diff --git a/README.md b/README.md index 9f1f7c7d..33c21511 100644 --- a/README.md +++ b/README.md @@ -207,6 +207,7 @@ options `ON` or `OFF`: * `GDIPLUS` adds the _GDI+_ port to the library. Default `OFF`. * `D2D` adds the _Direct2D_ port to the library. Default `OFF`. * `CAIRO` adds the _Cairo Graphics_ port to the library. Default `OFF`. +* `TESTING` enables automated testing using Google Tests. Default `ON`. To enable the deprecated CSS styling support: * `STYLE` adds limited, deprecated support for `