Skip to content

Commit

Permalink
thorvg: Update to 0.14.8, and workaround Bezier precision regression
Browse files Browse the repository at this point in the history
  • Loading branch information
akien-mga committed Sep 2, 2024
1 parent 7f86ca0 commit 7375f9b
Show file tree
Hide file tree
Showing 19 changed files with 177 additions and 43 deletions.
2 changes: 1 addition & 1 deletion thirdparty/thorvg/inc/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,5 @@
// For internal debugging:
//#define THORVG_LOG_ENABLED

#define THORVG_VERSION_STRING "0.14.7"
#define THORVG_VERSION_STRING "0.14.8"
#endif
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
From ac7d208ed8e4651c93ce1b2384070fccac9b6cb6 Mon Sep 17 00:00:00 2001
From: Mira Grudzinska <[email protected]>
Date: Sun, 1 Sep 2024 22:36:18 +0200
Subject: [PATCH] sw_engine: handle small cubics

During the stroke's outline calculation, the function
handling small cubics set all angles to zero. Such cases
should be ignored, as further processing caused errors -
when the cubic was small but not zero, setting the angles
to zero resulted in incorrect outlines.

@Issue: https://github.com/godotengine/godot/issues/96262
---
src/renderer/sw_engine/tvgSwCommon.h | 3 ++-
src/renderer/sw_engine/tvgSwMath.cpp | 19 ++++++++++++-------
src/renderer/sw_engine/tvgSwStroke.cpp | 16 +++++++++++-----
3 files changed, 25 insertions(+), 13 deletions(-)

diff --git a/src/renderer/sw_engine/tvgSwCommon.h b/src/renderer/sw_engine/tvgSwCommon.h
index 893e9beca..158fe8ecd 100644
--- a/src/renderer/sw_engine/tvgSwCommon.h
+++ b/src/renderer/sw_engine/tvgSwCommon.h
@@ -491,7 +491,8 @@ SwFixed mathSin(SwFixed angle);
void mathSplitCubic(SwPoint* base);
SwFixed mathDiff(SwFixed angle1, SwFixed angle2);
SwFixed mathLength(const SwPoint& pt);
-bool mathSmallCubic(const SwPoint* base, SwFixed& angleIn, SwFixed& angleMid, SwFixed& angleOut);
+bool mathSmallCubic(const SwPoint* base);
+bool mathFlatCubic(const SwPoint* base, SwFixed& angleIn, SwFixed& angleMid, SwFixed& angleOut);
SwFixed mathMean(SwFixed angle1, SwFixed angle2);
SwPoint mathTransform(const Point* to, const Matrix& transform);
bool mathUpdateOutlineBBox(const SwOutline* outline, const SwBBox& clipRegion, SwBBox& renderRegion, bool fastTrack);
diff --git a/src/renderer/sw_engine/tvgSwMath.cpp b/src/renderer/sw_engine/tvgSwMath.cpp
index 1093edd62..b311be05f 100644
--- a/src/renderer/sw_engine/tvgSwMath.cpp
+++ b/src/renderer/sw_engine/tvgSwMath.cpp
@@ -44,7 +44,17 @@ SwFixed mathMean(SwFixed angle1, SwFixed angle2)
}


-bool mathSmallCubic(const SwPoint* base, SwFixed& angleIn, SwFixed& angleMid, SwFixed& angleOut)
+bool mathSmallCubic(const SwPoint* base)
+{
+ auto d1 = base[2] - base[3];
+ auto d2 = base[1] - base[2];
+ auto d3 = base[0] - base[1];
+
+ return d1.small() && d2.small() && d3.small();
+}
+
+
+bool mathFlatCubic(const SwPoint* base, SwFixed& angleIn, SwFixed& angleMid, SwFixed& angleOut)
{
auto d1 = base[2] - base[3];
auto d2 = base[1] - base[2];
@@ -52,12 +62,7 @@ bool mathSmallCubic(const SwPoint* base, SwFixed& angleIn, SwFixed& angleMid, Sw

if (d1.small()) {
if (d2.small()) {
- if (d3.small()) {
- angleIn = angleMid = angleOut = 0;
- return true;
- } else {
- angleIn = angleMid = angleOut = mathAtan(d3);
- }
+ angleIn = angleMid = angleOut = mathAtan(d3);
} else {
if (d3.small()) {
angleIn = angleMid = angleOut = mathAtan(d2);
diff --git a/src/renderer/sw_engine/tvgSwStroke.cpp b/src/renderer/sw_engine/tvgSwStroke.cpp
index 575d12951..4679b72cc 100644
--- a/src/renderer/sw_engine/tvgSwStroke.cpp
+++ b/src/renderer/sw_engine/tvgSwStroke.cpp
@@ -441,11 +441,17 @@ static void _cubicTo(SwStroke& stroke, const SwPoint& ctrl1, const SwPoint& ctrl
//initialize with current direction
angleIn = angleOut = angleMid = stroke.angleIn;

- if (arc < limit && !mathSmallCubic(arc, angleIn, angleMid, angleOut)) {
- if (stroke.firstPt) stroke.angleIn = angleIn;
- mathSplitCubic(arc);
- arc += 3;
- continue;
+ if (arc < limit) {
+ if (mathSmallCubic(arc)) {
+ arc -= 3;
+ continue;
+ }
+ if (!mathFlatCubic(arc, angleIn, angleMid, angleOut)) {
+ if (stroke.firstPt) stroke.angleIn = angleIn;
+ mathSplitCubic(arc);
+ arc += 3;
+ continue;
+ }
}

if (firstArc) {
8 changes: 8 additions & 0 deletions thirdparty/thorvg/src/common/tvgMath.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,3 +133,11 @@ Point operator*(const Point& pt, const Matrix& m)
auto ty = pt.x * m.e21 + pt.y * m.e22 + m.e23;
return {tx, ty};
}

uint8_t mathLerp(const uint8_t &start, const uint8_t &end, float t)
{
auto result = static_cast<int>(start + (end - start) * t);
if (result > 255) result = 255;
else if (result < 0) result = 0;
return static_cast<uint8_t>(result);
}
1 change: 1 addition & 0 deletions thirdparty/thorvg/src/common/tvgMath.h
Original file line number Diff line number Diff line change
Expand Up @@ -259,5 +259,6 @@ static inline T mathLerp(const T &start, const T &end, float t)
return static_cast<T>(start + (end - start) * t);
}

uint8_t mathLerp(const uint8_t &start, const uint8_t &end, float t);

#endif //_TVG_MATH_H_
6 changes: 5 additions & 1 deletion thirdparty/thorvg/src/loaders/svg/tvgSvgLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -588,6 +588,11 @@ static bool _hslToRgb(float hue, float saturation, float brightness, uint8_t* re
float _red = 0, _green = 0, _blue = 0;
uint32_t i = 0;

while (hue < 0) hue += 360.0f;
hue = fmod(hue, 360.0f);
saturation = saturation > 0 ? std::min(saturation, 1.0f) : 0.0f;
brightness = brightness > 0 ? std::min(brightness, 1.0f) : 0.0f;

if (mathZero(saturation)) _red = _green = _blue = brightness;
else {
if (mathEqual(hue, 360.0)) hue = 0.0f;
Expand Down Expand Up @@ -714,7 +719,6 @@ static bool _toColor(const char* str, uint8_t* r, uint8_t* g, uint8_t* b, char**
const char* hue = nullptr;
if (_parseNumber(&content, &hue, &th) && hue) {
const char* saturation = nullptr;
th = float(uint32_t(th) % 360);
hue = _skipSpace(hue, nullptr);
hue = (char*)_skipComma(hue);
hue = _skipSpace(hue, nullptr);
Expand Down
12 changes: 8 additions & 4 deletions thirdparty/thorvg/src/renderer/sw_engine/tvgSwCommon.h
Original file line number Diff line number Diff line change
Expand Up @@ -367,7 +367,7 @@ static inline uint32_t opBlendSrcOver(uint32_t s, TVG_UNUSED uint32_t d, TVG_UNU
}

//TODO: BlendMethod could remove the alpha parameter.
static inline uint32_t opBlendDifference(uint32_t s, uint32_t d, TVG_UNUSED uint8_t a)
static inline uint32_t opBlendDifference(uint32_t s, uint32_t d, uint8_t a)
{
//if (s > d) => s - d
//else => d - s
Expand Down Expand Up @@ -404,8 +404,7 @@ static inline uint32_t opBlendScreen(uint32_t s, uint32_t d, TVG_UNUSED uint8_t
return JOIN(255, c1, c2, c3);
}


static inline uint32_t opBlendMultiply(uint32_t s, uint32_t d, TVG_UNUSED uint8_t a)
static inline uint32_t opBlendDirectMultiply(uint32_t s, uint32_t d, uint8_t a)
{
// s * d
auto c1 = MULTIPLY(C1(s), C1(d));
Expand All @@ -414,6 +413,10 @@ static inline uint32_t opBlendMultiply(uint32_t s, uint32_t d, TVG_UNUSED uint8_
return JOIN(255, c1, c2, c3);
}

static inline uint32_t opBlendMultiply(uint32_t s, uint32_t d, uint8_t a)
{
return opBlendDirectMultiply(s, d, a) + ALPHA_BLEND(d, IA(s));
}

static inline uint32_t opBlendOverlay(uint32_t s, uint32_t d, TVG_UNUSED uint8_t a)
{
Expand Down Expand Up @@ -492,7 +495,8 @@ SwFixed mathSin(SwFixed angle);
void mathSplitCubic(SwPoint* base);
SwFixed mathDiff(SwFixed angle1, SwFixed angle2);
SwFixed mathLength(const SwPoint& pt);
bool mathSmallCubic(const SwPoint* base, SwFixed& angleIn, SwFixed& angleMid, SwFixed& angleOut);
bool mathSmallCubic(const SwPoint* base);
bool mathFlatCubic(const SwPoint* base, SwFixed& angleIn, SwFixed& angleMid, SwFixed& angleOut);
SwFixed mathMean(SwFixed angle1, SwFixed angle2);
SwPoint mathTransform(const Point* to, const Matrix& transform);
bool mathUpdateOutlineBBox(const SwOutline* outline, const SwBBox& clipRegion, SwBBox& renderRegion, bool fastTrack);
Expand Down
19 changes: 12 additions & 7 deletions thirdparty/thorvg/src/renderer/sw_engine/tvgSwMath.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,20 +44,25 @@ SwFixed mathMean(SwFixed angle1, SwFixed angle2)
}


bool mathSmallCubic(const SwPoint* base, SwFixed& angleIn, SwFixed& angleMid, SwFixed& angleOut)
bool mathSmallCubic(const SwPoint* base)
{
auto d1 = base[2] - base[3];
auto d2 = base[1] - base[2];
auto d3 = base[0] - base[1];

return d1.small() && d2.small() && d3.small();
}


bool mathFlatCubic(const SwPoint* base, SwFixed& angleIn, SwFixed& angleMid, SwFixed& angleOut)
{
auto d1 = base[2] - base[3];
auto d2 = base[1] - base[2];
auto d3 = base[0] - base[1];

if (d1.small()) {
if (d2.small()) {
if (d3.small()) {
angleIn = angleMid = angleOut = 0;
return true;
} else {
angleIn = angleMid = angleOut = mathAtan(d3);
}
angleIn = angleMid = angleOut = mathAtan(d3);
} else {
if (d3.small()) {
angleIn = angleMid = angleOut = mathAtan(d2);
Expand Down
2 changes: 1 addition & 1 deletion thirdparty/thorvg/src/renderer/sw_engine/tvgSwRaster.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1383,7 +1383,7 @@ static bool _rasterDirectBlendingImage(SwSurface* surface, const SwImage* image,
*dst = INTERPOLATE(tmp, *dst, A(*src));
}
} else {
for (auto x = region.min.x; x < region.max.x; ++x, ++dst, ++src) {
for (auto x = region.min.x; x < region.max.x; x++, dst++, src++) {
auto tmp = ALPHA_BLEND(*src, opacity);
auto tmp2 = surface->blender(tmp, *dst, 255);
*dst = INTERPOLATE(tmp2, *dst, A(tmp));
Expand Down
5 changes: 2 additions & 3 deletions thirdparty/thorvg/src/renderer/sw_engine/tvgSwRenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,6 @@ struct SwShapeTask : SwTask
return (width * sqrt(transform.e11 * transform.e11 + transform.e12 * transform.e12));
}


bool clip(SwRleData* target) override
{
if (shape.fastTrack) rleClipRect(target, &bbox);
Expand Down Expand Up @@ -447,7 +446,7 @@ bool SwRenderer::renderShape(RenderData data)
}


bool SwRenderer::blend(BlendMethod method)
bool SwRenderer::blend(BlendMethod method, bool direct)
{
if (surface->blendMethod == method) return true;
surface->blendMethod = method;
Expand All @@ -460,7 +459,7 @@ bool SwRenderer::blend(BlendMethod method)
surface->blender = opBlendScreen;
break;
case BlendMethod::Multiply:
surface->blender = opBlendMultiply;
surface->blender = direct ? opBlendDirectMultiply : opBlendMultiply;
break;
case BlendMethod::Overlay:
surface->blender = opBlendOverlay;
Expand Down
2 changes: 1 addition & 1 deletion thirdparty/thorvg/src/renderer/sw_engine/tvgSwRenderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ class SwRenderer : public RenderMethod
RenderRegion region(RenderData data) override;
RenderRegion viewport() override;
bool viewport(const RenderRegion& vp) override;
bool blend(BlendMethod method) override;
bool blend(BlendMethod method, bool direct) override;
ColorSpace colorSpace() override;
const Surface* mainSurface() override;

Expand Down
16 changes: 11 additions & 5 deletions thirdparty/thorvg/src/renderer/sw_engine/tvgSwStroke.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -441,11 +441,17 @@ static void _cubicTo(SwStroke& stroke, const SwPoint& ctrl1, const SwPoint& ctrl
//initialize with current direction
angleIn = angleOut = angleMid = stroke.angleIn;

if (arc < limit && !mathSmallCubic(arc, angleIn, angleMid, angleOut)) {
if (stroke.firstPt) stroke.angleIn = angleIn;
mathSplitCubic(arc);
arc += 3;
continue;
if (arc < limit) {
if (mathSmallCubic(arc)) {
arc -= 3;
continue;
}
if (!mathFlatCubic(arc, angleIn, angleMid, angleOut)) {
if (stroke.firstPt) stroke.angleIn = angleIn;
mathSplitCubic(arc);
arc += 3;
continue;
}
}

if (firstArc) {
Expand Down
3 changes: 2 additions & 1 deletion thirdparty/thorvg/src/renderer/tvgLoadModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,8 @@ struct FontLoader : LoadModule

FontLoader(FileType type) : LoadModule(type) {}

virtual bool request(Shape* shape, char* text, bool italic = false) = 0;
virtual bool request(Shape* shape, char* text) = 0;
virtual bool transform(Paint* paint, float fontSize, bool italic) = 0;
};

#endif //_TVG_LOAD_MODULE_H_
2 changes: 0 additions & 2 deletions thirdparty/thorvg/src/renderer/tvgPaint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -225,8 +225,6 @@ bool Paint::Impl::render(RenderMethod* renderer)

if (cmp) renderer->beginComposite(cmp, compData->method, compData->target->pImpl->opacity);

renderer->blend(blendMethod);

bool ret;
PAINT_METHOD(ret, render(renderer));

Expand Down
2 changes: 2 additions & 0 deletions thirdparty/thorvg/src/renderer/tvgPicture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ bool Picture::Impl::needComposition(uint8_t opacity)
bool Picture::Impl::render(RenderMethod* renderer)
{
bool ret = false;
renderer->blend(picture->blend(), true);

if (surface) return renderer->renderImage(rd);
else if (paint) {
Compositor* cmp = nullptr;
Expand Down
2 changes: 1 addition & 1 deletion thirdparty/thorvg/src/renderer/tvgRender.h
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ class RenderMethod
virtual RenderRegion region(RenderData data) = 0;
virtual RenderRegion viewport() = 0;
virtual bool viewport(const RenderRegion& vp) = 0;
virtual bool blend(BlendMethod method) = 0;
virtual bool blend(BlendMethod method, bool direct = false) = 0;
virtual ColorSpace colorSpace() = 0;
virtual const Surface* mainSurface() = 0;

Expand Down
2 changes: 2 additions & 0 deletions thirdparty/thorvg/src/renderer/tvgScene.h
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,8 @@ struct Scene::Impl
Compositor* cmp = nullptr;
auto ret = true;

renderer->blend(scene->blend());

if (needComp) {
cmp = renderer->target(bounds(renderer), renderer->colorSpace());
renderer->beginComposite(cmp, CompositeMethod::None, opacity);
Expand Down
3 changes: 3 additions & 0 deletions thirdparty/thorvg/src/renderer/tvgShape.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,13 @@ struct Shape::Impl
Compositor* cmp = nullptr;
bool ret;

renderer->blend(shape->blend(), !needComp);

if (needComp) {
cmp = renderer->target(bounds(renderer), renderer->colorSpace());
renderer->beginComposite(cmp, CompositeMethod::None, opacity);
}

ret = renderer->renderShape(rd);
if (cmp) renderer->endComposite(cmp);
return ret;
Expand Down
Loading

0 comments on commit 7375f9b

Please sign in to comment.