Skip to content
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

Context2D does not implement clip() correctly #3408

Open
andrewcmyers opened this issue Apr 9, 2022 · 3 comments
Open

Context2D does not implement clip() correctly #3408

andrewcmyers opened this issue Apr 9, 2022 · 3 comments

Comments

@andrewcmyers
Copy link
Contributor

clip() is supposed to take an argument to specify the clipping rule. Context2D drops this argument on the floor and implements the default clipping rule, I guess.

It can also be given two arguments where one argument is the path. This is also not implemented.

https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/clip

@HackbrettXXX
Copy link
Collaborator

Thanks. Pull requests welcome ;)

@andrewcmyers
Copy link
Contributor Author

I'm pretty confused by the code that is currently there so I'm going to leave this one alone.

@seanmiddleditch
Copy link

I believe arcs are the only problem. If I have no arcs in my clip path, everything is fine. If I add any arcs, it breaks.

A quick inspection leads me to believe that the problem is the handling of the drawArc internal helper function in context2d.js which is always calling the doClip function; doClip must only be called at the end of the complete path, as it (among other things) discards the remaining path.

doClip.call(this);

this.pdf.discardPath();

A very quick monkey patch that got me unblocked on my particular project:

    const clip = ctx.clip.bind(ctx)
    const pdfClip = (ctx as any).pdf.clip
    const pdfDiscardPath = (ctx as any).pdf.discardPath

    const patchClip = function (this: Context2d): jsPDF {
        const self = this as any

        // clip is recursive for some cases; disable recursion into ourselves
        ctx.clip = clip

        // disable the problem calls into the pdf backend
        self.pdf.clip = () => {}
        self.pdf.discardPath = () => {}

        // perform real clipping
        clip()

        // restore problem calls into the pdf backend
        self.pdf.clip = pdfClip
        self.pdf.discardPath = pdfDiscardPath

        // finalize the real clipping operation (was disabled)
        self.pdf.clip()
        self.pdf.discardPath()

        // restore patched clip
        ctx.clip = patchClip
        return self.pdf
    }
    ctx.clip = patchClip

A proper fix would likely just be to make the drawArc not automatically do the doClip function and require any callers to perform that operation, which would be correct for the general clipping case at least.

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

No branches or pull requests

3 participants