diff --git a/src/common/meson.build b/src/common/meson.build index 6c2e37e5..8a764c0a 100644 --- a/src/common/meson.build +++ b/src/common/meson.build @@ -3,12 +3,10 @@ source_file = [ 'tvgCompressor.h', 'tvgFormat.h', 'tvgInlist.h', - 'tvgLines.h', 'tvgLock.h', 'tvgMath.h', 'tvgStr.h', 'tvgCompressor.cpp', - 'tvgLines.cpp', 'tvgMath.cpp', 'tvgStr.cpp' ] diff --git a/src/common/tvgLines.cpp b/src/common/tvgLines.cpp deleted file mode 100644 index 3c62b74e..00000000 --- a/src/common/tvgLines.cpp +++ /dev/null @@ -1,245 +0,0 @@ -/* - * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved. - - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "tvgMath.h" -#include "tvgLines.h" - -#define BEZIER_EPSILON 1e-2f - -/************************************************************************/ -/* Internal Class Implementation */ -/************************************************************************/ - -static float _lineLengthApprox(const Point& pt1, const Point& pt2) -{ - /* approximate sqrt(x*x + y*y) using alpha max plus beta min algorithm. - With alpha = 1, beta = 3/8, giving results with the largest error less - than 7% compared to the exact value. */ - Point diff = {pt2.x - pt1.x, pt2.y - pt1.y}; - if (diff.x < 0) diff.x = -diff.x; - if (diff.y < 0) diff.y = -diff.y; - return (diff.x > diff.y) ? (diff.x + diff.y * 0.375f) : (diff.y + diff.x * 0.375f); -} - - -static float _lineLength(const Point& pt1, const Point& pt2) -{ - Point diff = {pt2.x - pt1.x, pt2.y - pt1.y}; - return sqrtf(diff.x * diff.x + diff.y * diff.y); -} - - -template -float _bezLength(const Bezier& cur, LengthFunc lineLengthFunc) -{ - Bezier left, right; - auto len = lineLengthFunc(cur.start, cur.ctrl1) + lineLengthFunc(cur.ctrl1, cur.ctrl2) + lineLengthFunc(cur.ctrl2, cur.end); - auto chord = lineLengthFunc(cur.start, cur.end); - - if (fabsf(len - chord) > BEZIER_EPSILON) { - tvg::bezSplit(cur, left, right); - return _bezLength(left, lineLengthFunc) + _bezLength(right, lineLengthFunc); - } - return len; -} - - -template -float _bezAt(const Bezier& bz, float at, float length, LengthFunc lineLengthFunc) -{ - auto biggest = 1.0f; - auto smallest = 0.0f; - auto t = 0.5f; - - //just in case to prevent an infinite loop - if (at <= 0) return 0.0f; - if (at >= length) return 1.0f; - - while (true) { - auto right = bz; - Bezier left; - bezSplitLeft(right, t, left); - length = _bezLength(left, lineLengthFunc); - if (fabsf(length - at) < BEZIER_EPSILON || fabsf(smallest - biggest) < BEZIER_EPSILON) { - break; - } - if (length < at) { - smallest = t; - t = (t + biggest) * 0.5f; - } else { - biggest = t; - t = (smallest + t) * 0.5f; - } - } - return t; -} - - -/************************************************************************/ -/* External Class Implementation */ -/************************************************************************/ - -namespace tvg -{ - -float lineLength(const Point& pt1, const Point& pt2) -{ - return _lineLength(pt1, pt2); -} - - -void lineSplitAt(const Line& cur, float at, Line& left, Line& right) -{ - auto len = lineLength(cur.pt1, cur.pt2); - auto dx = ((cur.pt2.x - cur.pt1.x) / len) * at; - auto dy = ((cur.pt2.y - cur.pt1.y) / len) * at; - left.pt1 = cur.pt1; - left.pt2.x = left.pt1.x + dx; - left.pt2.y = left.pt1.y + dy; - right.pt1 = left.pt2; - right.pt2 = cur.pt2; -} - - -void bezSplit(const Bezier& cur, Bezier& left, Bezier& right) -{ - auto c = (cur.ctrl1.x + cur.ctrl2.x) * 0.5f; - left.ctrl1.x = (cur.start.x + cur.ctrl1.x) * 0.5f; - right.ctrl2.x = (cur.ctrl2.x + cur.end.x) * 0.5f; - left.start.x = cur.start.x; - right.end.x = cur.end.x; - left.ctrl2.x = (left.ctrl1.x + c) * 0.5f; - right.ctrl1.x = (right.ctrl2.x + c) * 0.5f; - left.end.x = right.start.x = (left.ctrl2.x + right.ctrl1.x) * 0.5f; - - c = (cur.ctrl1.y + cur.ctrl2.y) * 0.5f; - left.ctrl1.y = (cur.start.y + cur.ctrl1.y) * 0.5f; - right.ctrl2.y = (cur.ctrl2.y + cur.end.y) * 0.5f; - left.start.y = cur.start.y; - right.end.y = cur.end.y; - left.ctrl2.y = (left.ctrl1.y + c) * 0.5f; - right.ctrl1.y = (right.ctrl2.y + c) * 0.5f; - left.end.y = right.start.y = (left.ctrl2.y + right.ctrl1.y) * 0.5f; -} - - -float bezLength(const Bezier& cur) -{ - return _bezLength(cur, _lineLength); -} - - -float bezLengthApprox(const Bezier& cur) -{ - return _bezLength(cur, _lineLengthApprox); -} - - -void bezSplitLeft(Bezier& cur, float at, Bezier& left) -{ - left.start = cur.start; - - left.ctrl1.x = cur.start.x + at * (cur.ctrl1.x - cur.start.x); - left.ctrl1.y = cur.start.y + at * (cur.ctrl1.y - cur.start.y); - - left.ctrl2.x = cur.ctrl1.x + at * (cur.ctrl2.x - cur.ctrl1.x); //temporary holding spot - left.ctrl2.y = cur.ctrl1.y + at * (cur.ctrl2.y - cur.ctrl1.y); //temporary holding spot - - cur.ctrl2.x = cur.ctrl2.x + at * (cur.end.x - cur.ctrl2.x); - cur.ctrl2.y = cur.ctrl2.y + at * (cur.end.y - cur.ctrl2.y); - - cur.ctrl1.x = left.ctrl2.x + at * (cur.ctrl2.x - left.ctrl2.x); - cur.ctrl1.y = left.ctrl2.y + at * (cur.ctrl2.y - left.ctrl2.y); - - left.ctrl2.x = left.ctrl1.x + at * (left.ctrl2.x - left.ctrl1.x); - left.ctrl2.y = left.ctrl1.y + at * (left.ctrl2.y - left.ctrl1.y); - - left.end.x = cur.start.x = left.ctrl2.x + at * (cur.ctrl1.x - left.ctrl2.x); - left.end.y = cur.start.y = left.ctrl2.y + at * (cur.ctrl1.y - left.ctrl2.y); -} - - -float bezAt(const Bezier& bz, float at, float length) -{ - return _bezAt(bz, at, length, _lineLength); -} - - -float bezAtApprox(const Bezier& bz, float at, float length) -{ - return _bezAt(bz, at, length, _lineLengthApprox); -} - - -void bezSplitAt(const Bezier& cur, float at, Bezier& left, Bezier& right) -{ - right = cur; - auto t = bezAt(right, at, bezLength(right)); - bezSplitLeft(right, t, left); -} - - -Point bezPointAt(const Bezier& bz, float t) -{ - Point cur; - auto it = 1.0f - t; - - auto ax = bz.start.x * it + bz.ctrl1.x * t; - auto bx = bz.ctrl1.x * it + bz.ctrl2.x * t; - auto cx = bz.ctrl2.x * it + bz.end.x * t; - ax = ax * it + bx * t; - bx = bx * it + cx * t; - cur.x = ax * it + bx * t; - - float ay = bz.start.y * it + bz.ctrl1.y * t; - float by = bz.ctrl1.y * it + bz.ctrl2.y * t; - float cy = bz.ctrl2.y * it + bz.end.y * t; - ay = ay * it + by * t; - by = by * it + cy * t; - cur.y = ay * it + by * t; - - return cur; -} - - -float bezAngleAt(const Bezier& bz, float t) -{ - if (t < 0 || t > 1) return 0; - - //derivate - // p'(t) = 3 * (-(1-2t+t^2) * p0 + (1 - 4 * t + 3 * t^2) * p1 + (2 * t - 3 * - // t^2) * p2 + t^2 * p3) - float mt = 1.0f - t; - float d = t * t; - float a = -mt * mt; - float b = 1 - 4 * t + 3 * d; - float c = 2 * t - 3 * d; - - Point pt ={a * bz.start.x + b * bz.ctrl1.x + c * bz.ctrl2.x + d * bz.end.x, a * bz.start.y + b * bz.ctrl1.y + c * bz.ctrl2.y + d * bz.end.y}; - pt.x *= 3; - pt.y *= 3; - - return rad2deg(tvg::atan2(pt.y, pt.x)); -} - - -} \ No newline at end of file diff --git a/src/common/tvgLines.h b/src/common/tvgLines.h deleted file mode 100644 index d900782b..00000000 --- a/src/common/tvgLines.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2020 - 2024 the ThorVG project. All rights reserved. - - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef _TVG_LINES_H_ -#define _TVG_LINES_H_ - -#include "tvgCommon.h" - -namespace tvg -{ - -struct Line -{ - Point pt1; - Point pt2; -}; - -float lineLength(const Point& pt1, const Point& pt2); -void lineSplitAt(const Line& cur, float at, Line& left, Line& right); - - -struct Bezier -{ - Point start; - Point ctrl1; - Point ctrl2; - Point end; -}; - -void bezSplit(const Bezier&cur, Bezier& left, Bezier& right); -float bezLength(const Bezier& cur); -void bezSplitLeft(Bezier& cur, float at, Bezier& left); -float bezAt(const Bezier& bz, float at, float length); -void bezSplitAt(const Bezier& cur, float at, Bezier& left, Bezier& right); -Point bezPointAt(const Bezier& bz, float t); -float bezAngleAt(const Bezier& bz, float t); - -float bezLengthApprox(const Bezier& cur); -float bezAtApprox(const Bezier& bz, float at, float length); -} - -#endif //_TVG_LINES_H_ diff --git a/src/common/tvgMath.cpp b/src/common/tvgMath.cpp index 24af3d45..578d673e 100644 --- a/src/common/tvgMath.cpp +++ b/src/common/tvgMath.cpp @@ -22,8 +22,85 @@ #include "tvgMath.h" +#define BEZIER_EPSILON 1e-2f + + +/************************************************************************/ +/* Internal Class Implementation */ +/************************************************************************/ + +static float _lineLengthApprox(const Point& pt1, const Point& pt2) +{ + /* approximate sqrt(x*x + y*y) using alpha max plus beta min algorithm. + With alpha = 1, beta = 3/8, giving results with the largest error less + than 7% compared to the exact value. */ + Point diff = {pt2.x - pt1.x, pt2.y - pt1.y}; + if (diff.x < 0) diff.x = -diff.x; + if (diff.y < 0) diff.y = -diff.y; + return (diff.x > diff.y) ? (diff.x + diff.y * 0.375f) : (diff.y + diff.x * 0.375f); +} + + +static float _lineLength(const Point& pt1, const Point& pt2) +{ + Point diff = {pt2.x - pt1.x, pt2.y - pt1.y}; + return sqrtf(diff.x * diff.x + diff.y * diff.y); +} + + +template +float _bezLength(const Bezier& cur, LengthFunc lineLengthFunc) +{ + Bezier left, right; + auto len = lineLengthFunc(cur.start, cur.ctrl1) + lineLengthFunc(cur.ctrl1, cur.ctrl2) + lineLengthFunc(cur.ctrl2, cur.end); + auto chord = lineLengthFunc(cur.start, cur.end); + + if (fabsf(len - chord) > BEZIER_EPSILON) { + cur.split(left, right); + return _bezLength(left, lineLengthFunc) + _bezLength(right, lineLengthFunc); + } + return len; +} + + +template +float _bezAt(const Bezier& bz, float at, float length, LengthFunc lineLengthFunc) +{ + auto biggest = 1.0f; + auto smallest = 0.0f; + auto t = 0.5f; + + //just in case to prevent an infinite loop + if (at <= 0) return 0.0f; + if (at >= length) return 1.0f; + + while (true) { + auto right = bz; + Bezier left; + right.split(t, left); + length = _bezLength(left, lineLengthFunc); + if (fabsf(length - at) < BEZIER_EPSILON || fabsf(smallest - biggest) < BEZIER_EPSILON) { + break; + } + if (length < at) { + smallest = t; + t = (t + biggest) * 0.5f; + } else { + biggest = t; + t = (smallest + t) * 0.5f; + } + } + return t; +} + + +/************************************************************************/ +/* External Class Implementation */ +/************************************************************************/ + namespace tvg { +//https://en.wikipedia.org/wiki/Remez_algorithm float atan2(float y, float x) { auto a = std::min(fabsf(x), fabsf(y)) / std::max(fabsf(x), fabsf(y)); @@ -133,4 +210,145 @@ Point operator*(const Point& pt, const Matrix& m) return {tx, ty}; } + +float Line::length() const +{ + return _lineLength(pt1, pt2); +} + + +void Line::split(float at, Line& left, Line& right) const +{ + auto len = length(); + auto dx = ((pt2.x - pt1.x) / len) * at; + auto dy = ((pt2.y - pt1.y) / len) * at; + left.pt1 = pt1; + left.pt2.x = left.pt1.x + dx; + left.pt2.y = left.pt1.y + dy; + right.pt1 = left.pt2; + right.pt2 = pt2; +} + + +void Bezier::split(Bezier& left, Bezier& right) const +{ + auto c = (ctrl1.x + ctrl2.x) * 0.5f; + left.ctrl1.x = (start.x + ctrl1.x) * 0.5f; + right.ctrl2.x = (ctrl2.x + end.x) * 0.5f; + left.start.x = start.x; + right.end.x = end.x; + left.ctrl2.x = (left.ctrl1.x + c) * 0.5f; + right.ctrl1.x = (right.ctrl2.x + c) * 0.5f; + left.end.x = right.start.x = (left.ctrl2.x + right.ctrl1.x) * 0.5f; + + c = (ctrl1.y + ctrl2.y) * 0.5f; + left.ctrl1.y = (start.y + ctrl1.y) * 0.5f; + right.ctrl2.y = (ctrl2.y + end.y) * 0.5f; + left.start.y = start.y; + right.end.y = end.y; + left.ctrl2.y = (left.ctrl1.y + c) * 0.5f; + right.ctrl1.y = (right.ctrl2.y + c) * 0.5f; + left.end.y = right.start.y = (left.ctrl2.y + right.ctrl1.y) * 0.5f; +} + + +void Bezier::split(float at, Bezier& left, Bezier& right) const +{ + right = *this; + auto t = right.at(at, right.length()); + right.split(t, left); +} + + +float Bezier::length() const +{ + return _bezLength(*this, _lineLength); +} + + +float Bezier::lengthApprox() const +{ + return _bezLength(*this, _lineLengthApprox); +} + + +void Bezier::split(float at, Bezier& left) +{ + left.start = start; + + left.ctrl1.x = start.x + at * (ctrl1.x - start.x); + left.ctrl1.y = start.y + at * (ctrl1.y - start.y); + + left.ctrl2.x = ctrl1.x + at * (ctrl2.x - ctrl1.x); //temporary holding spot + left.ctrl2.y = ctrl1.y + at * (ctrl2.y - ctrl1.y); //temporary holding spot + + ctrl2.x = ctrl2.x + at * (end.x - ctrl2.x); + ctrl2.y = ctrl2.y + at * (end.y - ctrl2.y); + + ctrl1.x = left.ctrl2.x + at * (ctrl2.x - left.ctrl2.x); + ctrl1.y = left.ctrl2.y + at * (ctrl2.y - left.ctrl2.y); + + left.ctrl2.x = left.ctrl1.x + at * (left.ctrl2.x - left.ctrl1.x); + left.ctrl2.y = left.ctrl1.y + at * (left.ctrl2.y - left.ctrl1.y); + + left.end.x = start.x = left.ctrl2.x + at * (ctrl1.x - left.ctrl2.x); + left.end.y = start.y = left.ctrl2.y + at * (ctrl1.y - left.ctrl2.y); +} + + +float Bezier::at(float at, float length) const +{ + return _bezAt(*this, at, length, _lineLength); +} + + +float Bezier::atApprox(float at, float length) const +{ + return _bezAt(*this, at, length, _lineLengthApprox); +} + + +Point Bezier::at(float t) const +{ + Point cur; + auto it = 1.0f - t; + + auto ax = start.x * it + ctrl1.x * t; + auto bx = ctrl1.x * it + ctrl2.x * t; + auto cx = ctrl2.x * it + end.x * t; + ax = ax * it + bx * t; + bx = bx * it + cx * t; + cur.x = ax * it + bx * t; + + float ay = start.y * it + ctrl1.y * t; + float by = ctrl1.y * it + ctrl2.y * t; + float cy = ctrl2.y * it + end.y * t; + ay = ay * it + by * t; + by = by * it + cy * t; + cur.y = ay * it + by * t; + + return cur; +} + + +float Bezier::angle(float t) const +{ + if (t < 0 || t > 1) return 0; + + //derivate + // p'(t) = 3 * (-(1-2t+t^2) * p0 + (1 - 4 * t + 3 * t^2) * p1 + (2 * t - 3 * + // t^2) * p2 + t^2 * p3) + float mt = 1.0f - t; + float d = t * t; + float a = -mt * mt; + float b = 1 - 4 * t + 3 * d; + float c = 2 * t - 3 * d; + + Point pt ={a * start.x + b * ctrl1.x + c * ctrl2.x + d * end.x, a * start.y + b * ctrl1.y + c * ctrl2.y + d * end.y}; + pt.x *= 3; + pt.y *= 3; + + return rad2deg(tvg::atan2(pt.y, pt.x)); +} + } \ No newline at end of file diff --git a/src/common/tvgMath.h b/src/common/tvgMath.h index 68344fee..9f19817c 100644 --- a/src/common/tvgMath.h +++ b/src/common/tvgMath.h @@ -238,6 +238,44 @@ static inline void log(const Point& pt) TVGLOG("COMMON", "Point: [%f %f]", pt.x, pt.y); } + +/************************************************************************/ +/* Line functions */ +/************************************************************************/ + +struct Line +{ + Point pt1; + Point pt2; + + void split(float at, Line& left, Line& right) const; + float length() const; +}; + + +/************************************************************************/ +/* Bezier functions */ +/************************************************************************/ + +struct Bezier +{ + Point start; + Point ctrl1; + Point ctrl2; + Point end; + + void split(float at, Bezier& left); + void split(Bezier& left, Bezier& right) const; + void split(float at, Bezier& left, Bezier& right) const; + float length() const; + float lengthApprox() const; + float at(float at, float length) const; + float atApprox(float at, float length) const; + Point at(float t) const; + float angle(float t) const; +}; + + /************************************************************************/ /* Interpolation functions */ /************************************************************************/ diff --git a/src/loaders/lottie/tvgLottieProperty.h b/src/loaders/lottie/tvgLottieProperty.h index 13deb18f..92561bfa 100644 --- a/src/loaders/lottie/tvgLottieProperty.h +++ b/src/loaders/lottie/tvgLottieProperty.h @@ -27,7 +27,6 @@ #include "tvgCommon.h" #include "tvgArray.h" #include "tvgMath.h" -#include "tvgLines.h" #include "tvgLottieInterpolator.h" #include "tvgLottieExpressions.h" @@ -145,8 +144,7 @@ struct LottieVectorFrame if (hasTangent) { Bezier bz = {value, value + outTangent, next->value + inTangent, next->value}; - t = bezAtApprox(bz, t * length, length); - return bezPointAt(bz, t); + return bz.at(bz.atApprox(t * length, length)); } else { return lerp(value, next->value, t); } @@ -162,14 +160,14 @@ struct LottieVectorFrame auto t = (frameNo - no) / (next->no - no); if (interpolator) t = interpolator->progress(t); Bezier bz = {value, value + outTangent, next->value + inTangent, next->value}; - t = bezAtApprox(bz, t * length, length); - return bezAngleAt(bz, t >= 1.0f ? 0.99f : (t <= 0.0f ? 0.01f : t)); + t = bz.atApprox(t * length, length); + return bz.angle(t >= 1.0f ? 0.99f : (t <= 0.0f ? 0.01f : t)); } void prepare(LottieVectorFrame* next) { Bezier bz = {value, value + outTangent, next->value + inTangent, next->value}; - length = bezLengthApprox(bz); + length = bz.lengthApprox(); } }; diff --git a/src/renderer/gl_engine/tvgGlTessellator.cpp b/src/renderer/gl_engine/tvgGlTessellator.cpp index 92df1af2..4270f81e 100644 --- a/src/renderer/gl_engine/tvgGlTessellator.cpp +++ b/src/renderer/gl_engine/tvgGlTessellator.cpp @@ -774,7 +774,7 @@ static int32_t _bezierCurveCount(const Bezier &curve) Bezier left{}; Bezier right{}; - bezSplit(curve, left, right); + curve.split(left, right); return _bezierCurveCount(left) + _bezierCurveCount(right); } @@ -1024,7 +1024,7 @@ void Tessellator::visitShape(const PathCommand *cmds, uint32_t cmd_count, const float step = 1.f / stepCount; for (uint32_t s = 1; s < static_cast(stepCount); s++) { - last->append(pHeap->allocate(detail::_upScalePoint(bezPointAt(curve, step * s)))); + last->append(pHeap->allocate(detail::_upScalePoint(curve.at(step * s)))); } last->append(pHeap->allocate(detail::_upScalePoint(end))); @@ -1830,7 +1830,7 @@ void Stroker::strokeCubicTo(const GlPoint &cnt1, const GlPoint &cnt2, const GlPo float step = 1.f / count; for (int32_t i = 0; i <= count; i++) { - strokeLineTo(bezPointAt(curve, step * i)); + strokeLineTo(curve.at(step * i)); } } @@ -2140,7 +2140,7 @@ void DashStroke::dashCubicTo(const GlPoint &cnt1, const GlPoint &cnt2, const GlP cur.ctrl2 = Point{cnt2.x, cnt2.y}; cur.end = Point{end.x, end.y}; - auto len = bezLength(cur); + auto len = cur.length(); if (len < mCurrLen) { mCurrLen -= len; @@ -2154,7 +2154,7 @@ void DashStroke::dashCubicTo(const GlPoint &cnt1, const GlPoint &cnt2, const GlP Bezier left, right; - bezSplitAt(cur, mCurrLen, left, right); + cur.split(mCurrLen, left, right); if (mCurrIdx == 0) { this->moveTo(left.start); @@ -2260,7 +2260,7 @@ void BWTessellator::tessellate(const RenderShape *rshape, const Matrix& matrix) float step = 1.f / stepCount; for (uint32_t s = 1; s <= static_cast(stepCount); s++) { - auto pt = bezPointAt(curve, step * s); + auto pt = curve.at(step * s); auto currIndex = pushVertex(pt.x, pt.y); if (prevIndex == 0) { diff --git a/src/renderer/gl_engine/tvgGlTessellator.h b/src/renderer/gl_engine/tvgGlTessellator.h index 20cfe759..e5644638 100644 --- a/src/renderer/gl_engine/tvgGlTessellator.h +++ b/src/renderer/gl_engine/tvgGlTessellator.h @@ -26,7 +26,7 @@ #include #include "tvgGlGeometry.h" -#include "tvgLines.h" +#include "tvgMath.h" namespace tvg { diff --git a/src/renderer/sw_engine/tvgSwShape.cpp b/src/renderer/sw_engine/tvgSwShape.cpp index 87b99aa0..317504bc 100644 --- a/src/renderer/sw_engine/tvgSwShape.cpp +++ b/src/renderer/sw_engine/tvgSwShape.cpp @@ -22,7 +22,6 @@ #include "tvgSwCommon.h" #include "tvgMath.h" -#include "tvgLines.h" /************************************************************************/ /* Internal Class Implementation */ @@ -102,7 +101,7 @@ static bool _outlineClose(SwOutline& outline) static void _dashLineTo(SwDashStroke& dash, const Point* to, const Matrix* transform) { Line cur = {dash.ptCur, *to}; - auto len = lineLength(cur.pt1, cur.pt2); + auto len = cur.length(); if (tvg::zero(len)) { _outlineMoveTo(*dash.outline, &dash.ptCur, transform); @@ -122,7 +121,7 @@ static void _dashLineTo(SwDashStroke& dash, const Point* to, const Matrix* trans Line left, right; if (dash.curLen > 0) { len -= dash.curLen; - lineSplitAt(cur, dash.curLen, left, right); + cur.split(dash.curLen, left, right); if (!dash.curOpGap) { if (dash.move || dash.pattern[dash.curIdx] - dash.curLen < FLOAT_EPSILON) { _outlineMoveTo(*dash.outline, &left.pt1, transform); @@ -163,7 +162,7 @@ static void _dashLineTo(SwDashStroke& dash, const Point* to, const Matrix* trans static void _dashCubicTo(SwDashStroke& dash, const Point* ctrl1, const Point* ctrl2, const Point* to, const Matrix* transform) { Bezier cur = {dash.ptCur, *ctrl1, *ctrl2, *to}; - auto len = bezLength(cur); + auto len = cur.length(); //draw the current line fully if (tvg::zero(len)) { @@ -183,7 +182,7 @@ static void _dashCubicTo(SwDashStroke& dash, const Point* ctrl1, const Point* ct Bezier left, right; if (dash.curLen > 0) { len -= dash.curLen; - bezSplitAt(cur, dash.curLen, left, right); + cur.split(dash.curLen, left, right); if (!dash.curOpGap) { if (dash.move || dash.pattern[dash.curIdx] - dash.curLen < FLOAT_EPSILON) { _outlineMoveTo(*dash.outline, &left.start, transform); @@ -313,7 +312,7 @@ static float _outlineLength(const RenderShape* rshape, uint32_t shiftPts, uint32 break; } case PathCommand::CubicTo: { - len += bezLength({*(pts - 1), *pts, *(pts + 1), *(pts + 2)}); + len += Bezier{*(pts - 1), *pts, *(pts + 1), *(pts + 2)}.length(); pts += 3; break; }