diff --git a/src/common/tvgMath.h b/src/common/tvgMath.h index a0507866..6865a164 100644 --- a/src/common/tvgMath.h +++ b/src/common/tvgMath.h @@ -346,6 +346,17 @@ struct Bezier }; +/************************************************************************/ +/* Geometry functions */ +/************************************************************************/ + +struct BBox +{ + Point min, max; +}; + + + /************************************************************************/ /* Interpolation functions */ /************************************************************************/ diff --git a/src/loaders/svg/tvgSvgLoader.cpp b/src/loaders/svg/tvgSvgLoader.cpp index 636c47ff..5548425b 100644 --- a/src/loaders/svg/tvgSvgLoader.cpp +++ b/src/loaders/svg/tvgSvgLoader.cpp @@ -908,20 +908,20 @@ static bool _attrParseSvgNode(void* data, const char* key, const char* value) doc->viewFlag = (doc->viewFlag | SvgViewFlag::Height); } } else if (STR_AS(key, "viewBox")) { - if (_parseNumber(&value, nullptr, &doc->vx)) { - if (_parseNumber(&value, nullptr, &doc->vy)) { - if (_parseNumber(&value, nullptr, &doc->vw)) { - if (_parseNumber(&value, nullptr, &doc->vh)) { + if (_parseNumber(&value, nullptr, &doc->vbox.x)) { + if (_parseNumber(&value, nullptr, &doc->vbox.y)) { + if (_parseNumber(&value, nullptr, &doc->vbox.w)) { + if (_parseNumber(&value, nullptr, &doc->vbox.h)) { doc->viewFlag = (doc->viewFlag | SvgViewFlag::Viewbox); - loader->svgParse->global.h = doc->vh; + loader->svgParse->global.h = doc->vbox.h; } - loader->svgParse->global.w = doc->vw; + loader->svgParse->global.w = doc->vbox.w; } - loader->svgParse->global.y = doc->vy; + loader->svgParse->global.y = doc->vbox.y; } - loader->svgParse->global.x = doc->vx; + loader->svgParse->global.x = doc->vbox.x; } - if ((doc->viewFlag & SvgViewFlag::Viewbox) && (doc->vw < 0.0f || doc->vh < 0.0f)) { + if ((doc->viewFlag & SvgViewFlag::Viewbox) && (doc->vbox.w < 0.0f || doc->vbox.h < 0.0f)) { doc->viewFlag = (SvgViewFlag)((uint32_t)doc->viewFlag & ~(uint32_t)SvgViewFlag::Viewbox); TVGLOG("SVG", "Negative values of the width and/or height - the attribute invalidated."); } @@ -3900,7 +3900,7 @@ SvgLoader::~SvgLoader() void SvgLoader::run(unsigned tid) { //According to the SVG standard the value of the width/height of the viewbox set to 0 disables rendering - if ((viewFlag & SvgViewFlag::Viewbox) && (fabsf(vw) <= FLOAT_EPSILON || fabsf(vh) <= FLOAT_EPSILON)) { + if ((viewFlag & SvgViewFlag::Viewbox) && (fabsf(vbox.w) <= FLOAT_EPSILON || fabsf(vbox.h) <= FLOAT_EPSILON)) { TVGLOG("SVG", "The width and/or height set to 0 - rendering disabled."); root = Scene::gen(); return; @@ -3928,16 +3928,13 @@ void SvgLoader::run(unsigned tid) if (loaderData.gradients.count > 0) _updateGradient(&loaderData, loaderData.doc, &loaderData.gradients); if (defs) _updateGradient(&loaderData, loaderData.doc, &defs->node.defs.gradients); } - root = svgSceneBuild(loaderData, {vx, vy, vw, vh}, w, h, align, meetOrSlice, svgPath, viewFlag); + root = svgSceneBuild(loaderData, vbox, w, h, align, meetOrSlice, svgPath, viewFlag); //In case no viewbox and width/height data is provided the completion of loading //has to be forced, in order to establish this data based on the whole picture. if (!(viewFlag & SvgViewFlag::Viewbox)) { //Override viewbox & size again after svg loading. - vx = loaderData.doc->node.doc.vx; - vy = loaderData.doc->node.doc.vy; - vw = loaderData.doc->node.doc.vw; - vh = loaderData.doc->node.doc.vh; + vbox = loaderData.doc->node.doc.vbox; w = loaderData.doc->node.doc.w; h = loaderData.doc->node.doc.h; } @@ -3965,14 +3962,11 @@ bool SvgLoader::header() meetOrSlice = loaderData.doc->node.doc.meetOrSlice; if (viewFlag & SvgViewFlag::Viewbox) { - vx = loaderData.doc->node.doc.vx; - vy = loaderData.doc->node.doc.vy; - vw = loaderData.doc->node.doc.vw; - vh = loaderData.doc->node.doc.vh; + vbox = loaderData.doc->node.doc.vbox; if (viewFlag & SvgViewFlag::Width) w = loaderData.doc->node.doc.w; else { - w = loaderData.doc->node.doc.vw; + w = loaderData.doc->node.doc.vbox.w; if (viewFlag & SvgViewFlag::WidthInPercent) { w *= loaderData.doc->node.doc.w; viewFlag = (viewFlag ^ SvgViewFlag::WidthInPercent); @@ -3981,7 +3975,7 @@ bool SvgLoader::header() } if (viewFlag & SvgViewFlag::Height) h = loaderData.doc->node.doc.h; else { - h = loaderData.doc->node.doc.vh; + h = loaderData.doc->node.doc.vbox.h; if (viewFlag & SvgViewFlag::HeightInPercent) { h *= loaderData.doc->node.doc.h; viewFlag = (viewFlag ^ SvgViewFlag::HeightInPercent); @@ -3992,20 +3986,20 @@ bool SvgLoader::header() //has to be forced, in order to establish this data based on the whole picture. } else { //Before loading, set default viewbox & size if they are empty - vx = vy = 0.0f; + vbox.x = vbox.y = 0.0f; if (viewFlag & SvgViewFlag::Width) { - vw = w = loaderData.doc->node.doc.w; + vbox.w = w = loaderData.doc->node.doc.w; } else { - vw = 1.0f; + vbox.w = 1.0f; if (viewFlag & SvgViewFlag::WidthInPercent) { w = loaderData.doc->node.doc.w; } else w = 1.0f; } if (viewFlag & SvgViewFlag::Height) { - vh = h = loaderData.doc->node.doc.h; + vbox.h = h = loaderData.doc->node.doc.h; } else { - vh = 1.0f; + vbox.h = 1.0f; if (viewFlag & SvgViewFlag::HeightInPercent) { h = loaderData.doc->node.doc.h; } else h = 1.0f; diff --git a/src/loaders/svg/tvgSvgLoader.h b/src/loaders/svg/tvgSvgLoader.h index 2f11324a..11f8856f 100644 --- a/src/loaders/svg/tvgSvgLoader.h +++ b/src/loaders/svg/tvgSvgLoader.h @@ -54,10 +54,7 @@ private: SvgViewFlag viewFlag = SvgViewFlag::None; AspectRatioAlign align = AspectRatioAlign::XMidYMid; AspectRatioMeetOrSlice meetOrSlice = AspectRatioMeetOrSlice::Meet; - float vx = 0; - float vy = 0; - float vw = 0; - float vh = 0; + Box vbox{}; bool header(); void clear(bool all = true); diff --git a/src/loaders/svg/tvgSvgLoaderCommon.h b/src/loaders/svg/tvgSvgLoaderCommon.h index ec7614cf..51e44a3d 100644 --- a/src/loaders/svg/tvgSvgLoaderCommon.h +++ b/src/loaders/svg/tvgSvgLoaderCommon.h @@ -285,12 +285,8 @@ enum class AspectRatioMeetOrSlice struct SvgDocNode { - float w; //unit: point or in percentage see: SvgViewFlag - float h; //unit: point or in percentage see: SvgViewFlag - float vx; - float vy; - float vw; - float vh; + float w, h; //unit: point or in percentage see: SvgViewFlag + Box vbox; SvgViewFlag viewFlag; SvgNode* defs; SvgNode* style; @@ -558,10 +554,7 @@ struct SvgParser SvgStyleGradient* styleGrad; Fill::ColorStop gradStop; SvgStopStyleFlags flags; - struct - { - float x, y, w, h; - } global; + Box global; struct { bool parsedFx; diff --git a/src/loaders/svg/tvgSvgSceneBuilder.cpp b/src/loaders/svg/tvgSvgSceneBuilder.cpp index ae4894ff..971d7407 100644 --- a/src/loaders/svg/tvgSvgSceneBuilder.cpp +++ b/src/loaders/svg/tvgSvgSceneBuilder.cpp @@ -940,10 +940,7 @@ Scene* svgSceneBuild(SvgLoaderData& loaderData, Box vBox, float w, float h, Aspe clippingLayer->clip(viewBoxClip); clippingLayer->push(docNode); - loaderData.doc->node.doc.vx = vBox.x; - loaderData.doc->node.doc.vy = vBox.y; - loaderData.doc->node.doc.vw = vBox.w; - loaderData.doc->node.doc.vh = vBox.h; + loaderData.doc->node.doc.vbox = vBox; loaderData.doc->node.doc.w = w; loaderData.doc->node.doc.h = h; diff --git a/src/renderer/gl_engine/tvgGlTessellator.cpp b/src/renderer/gl_engine/tvgGlTessellator.cpp index 31bb8fac..b4968ea6 100644 --- a/src/renderer/gl_engine/tvgGlTessellator.cpp +++ b/src/renderer/gl_engine/tvgGlTessellator.cpp @@ -2502,10 +2502,10 @@ void BWTessellator::tessellate(const RenderShape *rshape, const Matrix& matrix) RenderRegion BWTessellator::bounds() const { return RenderRegion { - static_cast(floor(mLeftTop.x)), - static_cast(floor(mLeftTop.y)), - static_cast(ceil(mRightBottom.x - floor(mLeftTop.x))), - static_cast(ceil(mRightBottom.y - floor(mLeftTop.y))), + static_cast(floor(bbox.min.x)), + static_cast(floor(bbox.min.y)), + static_cast(ceil(bbox.max.x - floor(bbox.min.x))), + static_cast(ceil(bbox.max.y - floor(bbox.min.y))), }; } @@ -2515,13 +2515,10 @@ uint32_t BWTessellator::pushVertex(float x, float y) auto index = _pushVertex(mResPoints, x, y); if (index == 0) { - mRightBottom.x = mLeftTop.x = x; - mRightBottom.y = mLeftTop.y = y; + bbox.max = bbox.min = {x, y}; } else { - mLeftTop.x = std::min(mLeftTop.x, x); - mLeftTop.y = std::min(mLeftTop.y, y); - mRightBottom.x = std::max(mRightBottom.x, x); - mRightBottom.y = std::max(mRightBottom.y , y); + bbox.min = {std::min(bbox.min.x, x), std::min(bbox.min.y, y)}; + bbox.max = {std::max(bbox.max.x, x), std::max(bbox.max.y, y)}; } return index; diff --git a/src/renderer/gl_engine/tvgGlTessellator.h b/src/renderer/gl_engine/tvgGlTessellator.h index d047c5fa..01cb3f57 100644 --- a/src/renderer/gl_engine/tvgGlTessellator.h +++ b/src/renderer/gl_engine/tvgGlTessellator.h @@ -176,8 +176,7 @@ private: Array* mResPoints; Array* mResIndices; - Point mLeftTop = {0.0f, 0.0f}; - Point mRightBottom = {0.0f, 0.0f}; + BBox bbox = {{}, {}}; }; } // namespace tvg diff --git a/src/renderer/wg_engine/tvgWgRenderData.cpp b/src/renderer/wg_engine/tvgWgRenderData.cpp index 5eb012e4..918729fb 100755 --- a/src/renderer/wg_engine/tvgWgRenderData.cpp +++ b/src/renderer/wg_engine/tvgWgRenderData.cpp @@ -365,14 +365,12 @@ void WgRenderDataShape::updateBBox(Point pmin, Point pmax) void WgRenderDataShape::updateAABB(const Matrix& tr) { - Point p0 = Point{pMin.x, pMin.y} * tr; - Point p1 = Point{pMax.x, pMin.y} * tr; - Point p2 = Point{pMin.x, pMax.y} * tr; - Point p3 = Point{pMax.x, pMax.y} * tr; - aabb.pMin.x = std::min({p0.x, p1.x, p2.x, p3.x}); - aabb.pMin.y = std::min({p0.y, p1.y, p2.y, p3.y}); - aabb.pMax.x = std::max({p0.x, p1.x, p2.x, p3.x}); - aabb.pMax.y = std::max({p0.y, p1.y, p2.y, p3.y}); + auto p0 = Point{pMin.x, pMin.y} * tr; + auto p1 = Point{pMax.x, pMin.y} * tr; + auto p2 = Point{pMin.x, pMax.y} * tr; + auto p3 = Point{pMax.x, pMax.y} * tr; + aabb.min = {std::min({p0.x, p1.x, p2.x, p3.x}), std::min({p0.y, p1.y, p2.y, p3.y})}; + aabb.max = {std::max({p0.x, p1.x, p2.x, p3.x}), std::max({p0.y, p1.y, p2.y, p3.y})}; } diff --git a/src/renderer/wg_engine/tvgWgRenderData.h b/src/renderer/wg_engine/tvgWgRenderData.h index fdb1121f..cb0e8a02 100755 --- a/src/renderer/wg_engine/tvgWgRenderData.h +++ b/src/renderer/wg_engine/tvgWgRenderData.h @@ -26,11 +26,6 @@ #include "tvgWgPipelines.h" #include "tvgWgGeometry.h" -struct WgAabb { - Point pMin{}; - Point pMax{}; -}; - struct WgMeshData { WGPUBuffer bufferPosition{}; WGPUBuffer bufferTexCoord{}; @@ -104,7 +99,7 @@ struct WgRenderDataPaint WGPUBuffer bufferBlendSettings{}; WGPUBindGroup bindGroupPaint{}; RenderRegion viewport{}; - WgAabb aabb{}; + BBox aabb{{},{}}; float opacity{}; Array clips; diff --git a/src/renderer/wg_engine/tvgWgRenderer.cpp b/src/renderer/wg_engine/tvgWgRenderer.cpp index 678a01ef..dfc12209 100755 --- a/src/renderer/wg_engine/tvgWgRenderer.cpp +++ b/src/renderer/wg_engine/tvgWgRenderer.cpp @@ -203,8 +203,8 @@ RenderRegion WgRenderer::region(RenderData data) { auto renderData = (WgRenderDataPaint*)data; if (renderData->type() == Type::Shape) { - Point v1 = renderData->aabb.pMin; - Point v2 = renderData->aabb.pMax; + auto& v1 = renderData->aabb.min; + auto& v2 = renderData->aabb.max; RenderRegion renderRegion; renderRegion.x = static_cast(nearbyint(v1.x)); renderRegion.y = static_cast(nearbyint(v1.y));