mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-14 12:04:29 +00:00
Revert "sw_engine: Increasing accuracy for dashed curves"
This reverts commit a8c0030d80
.
This commit is contained in:
parent
d399ae922a
commit
c01c8338d7
4 changed files with 43 additions and 73 deletions
|
@ -29,7 +29,7 @@
|
||||||
/* Internal Class Implementation */
|
/* Internal Class Implementation */
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
|
||||||
static float _lineLengthApprox(const Point& pt1, const Point& pt2)
|
static float _lineLength(const Point& pt1, const Point& pt2)
|
||||||
{
|
{
|
||||||
/* approximate sqrt(x*x + y*y) using alpha max plus beta min algorithm.
|
/* 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
|
With alpha = 1, beta = 3/8, giving results with the largest error less
|
||||||
|
@ -41,59 +41,6 @@ static float _lineLengthApprox(const Point& pt1, const Point& pt2)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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<typename LengthFunc>
|
|
||||||
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<typename LengthFunc>
|
|
||||||
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 */
|
/* External Class Implementation */
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
@ -101,7 +48,7 @@ float _bezAt(const Bezier& bz, float at, float length, LengthFunc lineLengthFunc
|
||||||
namespace tvg
|
namespace tvg
|
||||||
{
|
{
|
||||||
|
|
||||||
void bezSplit(const Bezier& cur, Bezier& left, Bezier& right)
|
void bezSplit(const Bezier&cur, Bezier& left, Bezier& right)
|
||||||
{
|
{
|
||||||
auto c = (cur.ctrl1.x + cur.ctrl2.x) * 0.5f;
|
auto c = (cur.ctrl1.x + cur.ctrl2.x) * 0.5f;
|
||||||
left.ctrl1.x = (cur.start.x + cur.ctrl1.x) * 0.5f;
|
left.ctrl1.x = (cur.start.x + cur.ctrl1.x) * 0.5f;
|
||||||
|
@ -125,13 +72,15 @@ void bezSplit(const Bezier& cur, Bezier& left, Bezier& right)
|
||||||
|
|
||||||
float bezLength(const Bezier& cur)
|
float bezLength(const Bezier& cur)
|
||||||
{
|
{
|
||||||
return _bezLength(cur, _lineLength);
|
Bezier left, right;
|
||||||
}
|
auto len = _lineLength(cur.start, cur.ctrl1) + _lineLength(cur.ctrl1, cur.ctrl2) + _lineLength(cur.ctrl2, cur.end);
|
||||||
|
auto chord = _lineLength(cur.start, cur.end);
|
||||||
|
|
||||||
|
if (fabsf(len - chord) > BEZIER_EPSILON) {
|
||||||
float bezLengthApprox(const Bezier& cur)
|
bezSplit(cur, left, right);
|
||||||
{
|
return bezLength(left) + bezLength(right);
|
||||||
return _bezLength(cur, _lineLengthApprox);
|
}
|
||||||
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -161,13 +110,31 @@ void bezSplitLeft(Bezier& cur, float at, Bezier& left)
|
||||||
|
|
||||||
float bezAt(const Bezier& bz, float at, float length)
|
float bezAt(const Bezier& bz, float at, float length)
|
||||||
{
|
{
|
||||||
return _bezAt(bz, at, length, _lineLength);
|
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;
|
||||||
|
|
||||||
float bezAtApprox(const Bezier& bz, float at, float length)
|
while (true) {
|
||||||
{
|
auto right = bz;
|
||||||
return _bezAt(bz, at, length, _lineLengthApprox);
|
Bezier left;
|
||||||
|
bezSplitLeft(right, t, left);
|
||||||
|
length = bezLength(left);
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -44,8 +44,6 @@ void bezSplitAt(const Bezier& cur, float at, Bezier& left, Bezier& right);
|
||||||
Point bezPointAt(const Bezier& bz, float t);
|
Point bezPointAt(const Bezier& bz, float t);
|
||||||
float bezAngleAt(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_BEZIER_H_
|
#endif //_TVG_BEZIER_H_
|
||||||
|
|
|
@ -158,7 +158,7 @@ struct LottieVectorFrame
|
||||||
|
|
||||||
if (hasTangent) {
|
if (hasTangent) {
|
||||||
Bezier bz = {value, value + outTangent, next->value + inTangent, next->value};
|
Bezier bz = {value, value + outTangent, next->value + inTangent, next->value};
|
||||||
t = bezAtApprox(bz, t * length, length);
|
t = bezAt(bz, t * length, length);
|
||||||
return bezPointAt(bz, t);
|
return bezPointAt(bz, t);
|
||||||
} else {
|
} else {
|
||||||
return mathLerp(value, next->value, t);
|
return mathLerp(value, next->value, t);
|
||||||
|
@ -171,14 +171,14 @@ struct LottieVectorFrame
|
||||||
auto t = (frameNo - no) / (next->no - no);
|
auto t = (frameNo - no) / (next->no - no);
|
||||||
if (interpolator) t = interpolator->progress(t);
|
if (interpolator) t = interpolator->progress(t);
|
||||||
Bezier bz = {value, value + outTangent, next->value + inTangent, next->value};
|
Bezier bz = {value, value + outTangent, next->value + inTangent, next->value};
|
||||||
t = bezAtApprox(bz, t * length, length);
|
t = bezAt(bz, t * length, length);
|
||||||
return -bezAngleAt(bz, t);
|
return -bezAngleAt(bz, t);
|
||||||
}
|
}
|
||||||
|
|
||||||
void prepare(LottieVectorFrame* next)
|
void prepare(LottieVectorFrame* next)
|
||||||
{
|
{
|
||||||
Bezier bz = {value, value + outTangent, next->value + inTangent, next->value};
|
Bezier bz = {value, value + outTangent, next->value + inTangent, next->value};
|
||||||
length = bezLengthApprox(bz);
|
length = bezLength(bz);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -37,8 +37,13 @@ struct Line
|
||||||
|
|
||||||
static float _lineLength(const Point& pt1, const Point& pt2)
|
static float _lineLength(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};
|
Point diff = {pt2.x - pt1.x, pt2.y - pt1.y};
|
||||||
return sqrtf(diff.x * diff.x + diff.y * diff.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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -383,7 +388,7 @@ static float _outlineLength(const RenderShape* rshape)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case PathCommand::CubicTo: {
|
case PathCommand::CubicTo: {
|
||||||
length += bezLengthApprox({*(pts - 1), *pts, *(pts + 1), *(pts + 2)});
|
length += bezLength({*(pts - 1), *pts, *(pts + 1), *(pts + 2)});
|
||||||
pts += 3;
|
pts += 3;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue