Repository navigation
feat: ctxClip takes the fill rule ctxFill takes, so a ring clipped evenodd cuts a ring where it cut the square around it - #12
Merged
Conversation
…enodd cuts a ring where it cut the square around it ctxClip(surface, evenOdd) builds its geometry with D2D1_FILL_MODE_ALTERNATE when the flag is set and D2D1_FILL_MODE_WINDING otherwise, the same flag and default as ctxFill. canvas's clip(path, 'evenodd') is how ntk's SvgView cuts an element to a <clipPath> with clip-rule="evenodd" (sidorares/ntk#529), and react-x11's context hands it on now; CtxClip ignored a second argument and built every clip geometry winding. One rect still takes PushAxisAlignedClip under either rule: one figure wound once is cut alike by both.
sidorares
added a commit
to sidorares/react-x11
that referenced
this pull request
Oct 4, 2026
…a clip the context hands evenodd is cut evenodd on macOS and Windows, and the smoothing a perspective's tiles ask for reaches a Mac, where the ranges admitted neither bridge's verb neither bridge read it: an SVG ring clipped evenodd by ntk 8.22.0's SvgView, or an `<Html>` polygon cut evenodd, still came out the square around it. appkit 0.24.0 clips with CGContextEOClip for the flag (windowkit/appkit#111), win32 0.0.7 builds the clip geometry alternate (windowkit/win32#12). Both ranges were exact on 0.x. The appkit range also reaches 0.23.0's ctxSetImageSmoothing (windowkit/appkit#109). #861 feature-detects it, so a context made over an install that `^0.22.0` resolved kept every tile of a box in perspective at medium quality, resampling the whole surface for each. test/backend-context-clip-rule.test.js gains a layer over the real bridge, where it loads: a ring clipped evenodd, by the current path and by a path handed in, leaves its hole undrawn. It fails on 0.22.0 at the hole and passes on 0.24.0. docs/macos.md says what the rule does and where it came from, and the Windows verb table names the fill mode.
sidorares
added a commit
to sidorares/react-x11
that referenced
this pull request
Oct 4, 2026
…a clip the context hands evenodd is cut evenodd on macOS and Windows, and the smoothing a perspective's tiles ask for reaches a Mac, where the ranges admitted neither bridge's verb #864 hands the fill rule to `ctxClip` as the flag `ctxFill` takes, and neither bridge read it: an SVG ring clipped evenodd by ntk 8.22.0's SvgView, or an `<Html>` polygon cut evenodd, still came out the square around it. appkit 0.24.0 clips with CGContextEOClip for the flag (windowkit/appkit#111), win32 0.0.7 builds the clip geometry alternate (windowkit/win32#12). Both ranges were exact on 0.x. The appkit range also reaches 0.23.0's ctxSetImageSmoothing (windowkit/appkit#109). #861 feature-detects it, so a context made over an install that `^0.22.0` resolved kept every tile of a box in perspective at medium quality, resampling the whole surface for each. test/backend-context-clip-rule.test.js gains a layer over the real bridge, where it loads: a ring clipped evenodd, by the current path and by a path handed in, leaves its hole undrawn. It fails on 0.22.0 at the hole and passes on 0.24.0. docs/macos.md says what the rule does and where it came from, and the Windows verb table names the fill mode.
sidorares
added a commit
to sidorares/react-x11
that referenced
this pull request
Oct 4, 2026
…a clip the context hands evenodd is cut evenodd on macOS and Windows, and the smoothing a perspective's tiles ask for reaches a Mac, where the ranges admitted neither bridge's verb (#865) #864 hands the fill rule to `ctxClip` as the flag `ctxFill` takes, and neither bridge read it: an SVG ring clipped evenodd by ntk 8.22.0's SvgView, or an `<Html>` polygon cut evenodd, still came out the square around it. appkit 0.24.0 clips with CGContextEOClip for the flag (windowkit/appkit#111), win32 0.0.7 builds the clip geometry alternate (windowkit/win32#12). Both ranges were exact on 0.x. The appkit range also reaches 0.23.0's ctxSetImageSmoothing (windowkit/appkit#109). #861 feature-detects it, so a context made over an install that `^0.22.0` resolved kept every tile of a box in perspective at medium quality, resampling the whole surface for each. test/backend-context-clip-rule.test.js gains a layer over the real bridge, where it loads: a ring clipped evenodd, by the current path and by a path handed in, leaves its hole undrawn. It fails on 0.22.0 at the hole and passes on 0.24.0. docs/macos.md says what the rule does and where it came from, and the Windows verb table names the fill mode.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
ctxClipnow takes the booleanctxFilltakes, asctxClip(surface, evenOdd): the clip geometry is built withD2D1_FILL_MODE_ALTERNATEwhen it is set andD2D1_FILL_MODE_WINDINGwhen it is false or absent, so every existing caller clips as it did. The macOS half is windowkit/appkit#111.Why now. ntk 8.22.0's SvgView cuts an element to its
<clipPath>with canvas'sctx.clip(path, rule), the rule being the shape'sclip-rule(sidorares/ntk#529). react-x11's Windows context dropped the rule andCtxClipalways calledBuildPathwinding, so an SVG ring clippedevenoddcame out a filled square where X11 draws a ring. The react-x11 half hands the flag on; it is a no-op until this lands and core's range moves to the release.The rect fast path. One rect still takes
PushAxisAlignedClipwhatever the rule: one figure wound once is cut alike by both.Test.
test/clip-rule.js, intest:unit, the job that gates CI, fills a surface through a clip to a ring of two rects wound the same way:evenoddleaves the hole empty;false, fills it, as before;PushAxisAlignedCliproute, clips to the same pixels under both rules.Not built locally. This was written on a Mac, so CI here is the first build and the first run of the test. The same test against the appkit build fails before its change and passes after.