Skip to content

Removed AUTO joint/cap types, and made joint type non-nullable - #5012

Open
LinesThatConnect wants to merge 1 commit into
ManimCommunity:mainfrom
LinesThatConnect:fix-joints-and-caps
Open

LinesThatConnect wants to merge 1 commit into
ManimCommunity:mainfrom
LinesThatConnect:fix-joints-and-caps

Conversation

@LinesThatConnect

@LinesThatConnect LinesThatConnect commented Sep 12, 2026

Copy link
Copy Markdown

Overview: What does this pull request change?

Removes LineJointType.AUTO and CapStyleType.AUTO, and disallows None for the joint_type constructor argument in VMobject. This will may be a breaking change for anyone who explicitly sets the join/cap types to None or AUTO

Motivation and Explanation: Why and how do your changes improve the library?

Currently, if you set the joint or cap type of a VMobject to something other than AUTO, the joint/cap type is applied to all other VMobjects that are rendered after it. This is a bug (or at least it's highly unintuitive behavior). This has been noted in issue #3410.

The behavior of AUTO (apart from the bug noted above) matches MITER for joints and BUTT for caps, and the issue is resolved if we default to these values instead of AUTO.

Links to added or changed documentation pages

Further Information and Comments

I admit I don't know why the AUTO values exist. They don't serve an obvious purpose, so it's worth double-checking that I haven't missed some use-case for them. I've tested this on my projects and haven't seen any issues. If my removal of AUTO and None changes the contract too much, we could instead just change the defaults.

Reviewer Checklist

  • The PR title is descriptive enough for the changelog, and the PR is labeled correctly
  • If applicable: newly added non-private functions and classes have a docstring including a short summary and a PARAMETERS section
  • If applicable: newly added functions and classes are tested

@behackl

behackl commented Sep 12, 2026

Copy link
Copy Markdown
Member

I appreciate the honesty with your disclaimer, but don't really feel that we should get a solution not well understood merged, especially if it constitutes a breaking change.

I'm quite certain that there is a cleaner solution; the current behavior is likely because the miter type is a class and not a instance variable (or is it?) -- if you are willing to spend some more time figuring this out, then I'm happy to take a closer look at your proposal as well.

@LinesThatConnect

LinesThatConnect commented Sep 12, 2026

Copy link
Copy Markdown
Author

Understood! I'm hoping that this will be seen by someone with knowledge of the history that led to the current code. That said, I believe I understand the issue.

LineJointType and CapStyleType are simply enums. They are both mapped to Cairo constants in camera.py - see LINE_JOIN_MAP and CAP_STYLE_MAP. Both these dictionaries map the AUTO values to None. These dictionaries are only used in Camera.apply_stroke(), where they update the Cairo context:

ctx.set_line_join(LINE_JOIN_MAP[vmobject.joint_type])
ctx.set_line_cap(CAP_STYLE_MAP[vmobject.cap_style])

That is the problem. Cairo does not expect you to pass None into these methods (or at least the documentation doesn't mention that possibility), so this is undefined behavior. It seems to treat it as a no-op, which explains the behavior: Objects with AUTO don't update the Cairo context, so they take whatever joint and cap were set most recently.

If my analysis is correct, the current contract is overly loose, defining and defaulting to invalid enum values. Removing these values seems like the most reasonable option. I updated my disclaimer because it really overstated my doubts!

@nikolajmunk

Copy link
Copy Markdown
Contributor

We also discussed this subject in issue #4979 where I traced the problem to the same source, though without a good idea of the correct fix.

It looks like CapStyleType.AUTO and this behavior has existed since cap styles were introduced two years ago. However, I suspect that was just done to copy the existing behavior of LineJointType.AUTO which was implemented the year before by in #3016. Seems like the choice to make AUTO mean "do the same thing as before" was made by @behackl in commit 7c7d0b3.

@nikolajmunk

Copy link
Copy Markdown
Contributor

I think it would probably be fine to outright remove AUTO, though maybe in a future version with a notice about it in the release before it.

If we really want to keep AUTO, perhaps we could define a global or renderer-level default value for line joints and cap styles (probably defaulting to ROUND and BUTT) which any AUTO values then map to. That would let the user define their own auto values.

How do other graphics libraries handle this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants