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

canvas: Reimplement masking #7026

Merged
merged 2 commits into from
May 22, 2022
Merged

canvas: Reimplement masking #7026

merged 2 commits into from
May 22, 2022

Conversation

Herschel
Copy link
Member

@Herschel Herschel commented May 19, 2022

Reimplement masking on the canvas backend using the native CanvasRenderinContext2d.clip method.

When I first implemented masking in canvas, I didn't think clip could handle all of the nuances of Flash masking, so I ended up with a hacky+slow solution of drawing to off-screen canvases and using globalCompositeOperation to blend onto the main canvas. But I think we can handle nearly all of the cases natively using clip now:

  • clip(Path2D) is now supported in all major browsers.
  • Strokes aren't considered when masking. Originally I was worried that strokes could mask content as well, which would be impossible with clip. But Flash operates the same as canvas and omits strokes.
  • "Layered" art (multiple layers in a single Shape) is still a problem.
    • The layers should be unioned to generate the mask area, but with the canvas API, we can only really intersect using successive clip calls.
    • I settled on using a "non-zero" winding rule to handle this case, but this won't be completely correct in other cases (such as self-intersecting shapes).
    • But Flash IDE actively avoids exporting mask art in the above ways (multiple layers or self-intersecting), because the Flash Player itself doesn't handle these cases completely correctly either, sometimes producing artifacts. It's still possible to hit these cases using the drawing API + dynamic masks though. This should be rare, and hopefully the non-zero winding rule operates decently enough in these cases.

Fixes Gridlock drawing a blank screen in canvas backend (#6976).

@Herschel Herschel marked this pull request as draft May 19, 2022 18:39
@Herschel Herschel force-pushed the canvas-mask branch 2 times, most recently from ff29ff6 to ed77ebb Compare May 21, 2022 04:09
@Herschel Herschel marked this pull request as ready for review May 21, 2022 04:09
@Herschel Herschel changed the title [wip] canvas: Reimplement masking canvas: Reimplement masking May 21, 2022
@Herschel Herschel requested a review from Toad06 May 21, 2022 04:10
Herschel added 2 commits May 20, 2022 21:10
Use `CanvasRenderingContext2d.clip` for masking instead of using
intermediate canvases.
@Toad06
Copy link
Member

Toad06 commented May 21, 2022

This looks good to me, I'm also impressed about the performance improvement in almost all files. For instance, Ultimate Flash Sonic was running pretty smoothly when played in windowed mode on Newgrounds but was really too slow and so unplayable with larger dimensions or in fullscreen mode. Now it's always smooth. :)

While I'm at it, I'd like to mention that the issue I mentioned here showed up again. This is not related to this PR but one of the following commits: nightly-2022-05-18...nightly-2022-05-20 (likely #7029?). Firefox and Chrome on Windows are both affected (canvas render only). The issue is particularly noticeable in Super Mario 63, in the first / tutorial level.

@Herschel
Copy link
Member Author

Thanks! Will fix the bitmap issue in another PR.

This was referenced Apr 22, 2023
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.

2 participants