8000 lottie: fix offsetting partially degenerated cubics by mgrudzinska · Pull Request #3523 · thorvg/thorvg · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

lottie: fix offsetting partially degenerated cubics #3523

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

mgrudzinska
Copy link
Collaborator

Until now, cases where a Bezier curve had start == ctrl1 or
ctrl2 == end were incorrectly treated as linear segments.
This led to incorrect rendering, for example when offsetting
a polystar with outer roundness > 0 and inner roundness == 0.
Now such cases handled as proper curves with full cubic behavior.

before:
Zrzut ekranu 2025-06-11 o 23 34 48

after:
Zrzut ekranu 2025-06-11 o 23 35 10

AE (even here visible some artefacts):
Zrzut ekranu 2025-06-11 o 23 37 05
Zrzut ekranu 2025-06-11 o 23 37 01

samples:
sample1.json
sample2.json

Introduce the _colinear function - checks if a Bezier curve
is degenerated to a line.
Until now, cases where a Bezier curve had `start == ctrl1` or
`ctrl2 == end` were incorrectly treated as linear segments.
This led to incorrect rendering, for example when offsetting
a polystar with outer roundness > 0 and inner roundness == 0.
Now such cases handled as proper curves with full cubic behavior.
@mgrudzinska mgrudzinska self-assigned this Jun 11, 2025
@mgrudzinska mgrudzinska added bug Something isn't working lottie Lottie animation labels Jun 11, 2025
@mgrudzinska
Copy link
Collaborator Author

is ready, but I want to test more (more complicated cases can be tested after modifiers chaining is applied - more combinations of lineTo/cubicTo possible)

@hermet hermet requested a review from Copilot June 12, 2025 02:02
Copy link
@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR improves how partially degenerated cubic Beziers (where start==ctrl1 or ctrl2==end) are detected and offset, fixing rendering artifacts for shapes like polystars with mixed roundness.

  • Introduces a _colinear helper to detect degenerate cubic segments.
  • Updates LottieRoundnessModifier to treat these as full cubics when rounding corners.
  • Enhances LottieOffsetModifier to maintain continuity across degenerate lines and compute proper intersections.
Comments suppressed due to low confidence (1)

src/loaders/lottie/tvgLottieModifier.cpp:30

  • [nitpick] Rename _colinear to _collinear to correct the spelling of 'collinear' and improve readability.
static bool _colinear(const Point* p)

@@ -328,6 +330,10 @@ bool LottieOffsetModifier::modifyPath(PathCommand* inCmds, uint32_t inCmdsCnt, P
auto offset = _clockwise(inPts, inPtsCnt) ? this->offset : -this->offset;
auto threshold = 1.0f / fabsf(offset) + 1.0f;

bool inside{};
Copy link
Preview
Copilot AI Jun 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The inside variable is declared but never used. Consider removing it or using it to validate intersection results.

Suggested change
bool inside{};

Copilot uses AI. Check for mistakes.

@@ -348,17 +354,27 @@ bool LottieOffsetModifier::modifyPath(PathCommand* inCmds, uint32_t inCmdsCnt, P
auto& bezier = stack.last();
auto len = tvg::length(bezier.start - bezier.ctrl1) + tvg::length(bezier.ctrl1 - bezier.ctrl2) + tvg::length(bezier.ctrl2 - bezier.end);

if (len > threshold * bezier.length()) {
if (len > threshold * bezier.length() && len > 1.0f) {
Copy link
Preview
Copilot AI Jun 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The literal 1.0f here is a magic number. Extract it into a named constant to clarify its purpose in the subdivision threshold check.

Suggested change
if (len > threshold * bezier.length() && len > 1.0f) {
if (len > threshold * bezier.length() && len > SUBDIVISION_THRESHOLD) {

Copilot uses AI. Check for mistakes.

Bezier next;
bezier.split(0.5f, next);
stack.push(next);
continue;
}
stack.pop();

auto line1 = _offset(bezier.start, bezier.ctrl1, offset);
degeneratedLine1 = _zero(bezier.start, bezier.ctrl1);
Copy link
Preview
Copilot AI Jun 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The _zero helper divides coordinates and may trigger division by zero if any component is zero. Prefer using tvg::zero or a safer comparison to avoid potential runtime errors.

Copilot uses AI. Check for mistakes.

@hermet hermet force-pushed the main branch 2 times, most recently from fcbdcc9 to e20562c Compare June 19, 2025 07:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working lottie Lottie animation
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant
0