Make the chrome fit every window, and every colour - #30
Merged
Conversation
added 2 commits
August 27, 2026 01:53
The app has carried alpha end to end since the first build: the picker offers it, the file format keeps it, and the bucket has always meant "knock a hole in this". Every other tool disagreed, and disagreed silently. Source-over compositing with a fully transparent source is arithmetically out = dst, so the pencil, the brush, the shapes, the text and the eraser did precisely nothing and said nothing about it. The eraser is the one that mattered. It paints Colour 2, and a transparent Colour 2 is exactly what somebody loads when they want a hole, so the app's most obvious route to transparency was the one route that was dead. Five compositors take a destination-out branch now, not the two it first looked like: the brush stamp, the antialiased stroke that the shipping default round brush actually uses, the shape fill, the airbrush, and the text — which needs a blend mode, because Core Graphics cannot say "erase" with a colour. Scaling a premultiplied destination by the inverse of the brush's coverage IS destination-out, so a soft brush erases softly for nothing. The first version of the test pressed and released on one pixel, which only reaches beginStroke's direct stamp. It passed with the whole antialiased path still dead — a transparent colour rubbed out one dot under the press and then did nothing for the rest of the drag, which is worse than doing nothing at all because the first dot proves the feature works. It drags now, across three tools, and it was watched failing before it was trusted to pass.
Four reports, and each one turned out to be a thing the code claimed to do already. Tooltips cut their own text in half. The chip measured itself for one line and drew three, then clipped the rest away with its own rounded rectangle — because .fixedSize proposes a nil width, and under a nil proposal .frame(maxWidth:) let the text report the height of one unbroken line. The bug hid itself: every size assertion in TooltipRenderTests bounded the chip from above, so each line that went missing made the checks pass more comfortably. What replaced them is a check that a longer sentence makes a taller chip. There were also two tooltip layers with two rules, and the rail's was not really a rule — it offset the chip by a constant, so hovering the ninth tool put the answer up beside the first. One layer now, one rule: the chip's near edge sits on a fixed line beside the chrome it explains and slides along that line to follow the control. The header ran off the right edge. The window can be dragged to 560pt and the row needed 647pt to draw itself with no filename in it, so Share, Duplicate, the Guide and the zoom were outside the window with nothing to say they were there. Two numbers that had never been compared. HeaderFit steps down a ladder, and every rung drops a run whose commands have another door — which inverts the obvious answer, because cut/copy/paste have three chords every Mac already has and the drag-out handle has none. The filename also had a layout priority but no ceiling, and the centred cluster is not in its stack, so a long name was handed the whole row and drawn over the zoom controls. The rail hid its colour block. The whole rail sat in one scroller with its indicators off, so the loaded pair and the edge toggle went below the fold — in a file that has claimed since it was written that the colours are the part that must never be cut. That was a comment, not a behaviour. RailFit sheds palette columns first and then scrolls only the tool run, cut at a real cell boundary rather than an average pitch, which is right only until the fold crosses a group rule. The bottom bar had no shedding at all and ran 878pt of bar into a 548pt window. Six controls in the options panel were still a stock AppKit slider, in a panel whose every other control was drawn by hand — the giveaway Mark's own doc comment complains about. They are marks now, each naming itself on its caption line, and OptionSlider is gone. Two live bugs came with it: the accessibility step was max(range/100, 1), which is the entire range on any 0-to-1 fraction, so Ink, Opacity and Strength had two reachable values each; and t skipped its clamp on the linear path, so an out-of-range value painted past the end of its own trough. The colour popover is gone. It was a weaker copy of the system Colors panel, which has an opacity slider, an eyedropper, saved swatches and a recents row that survives quitting. What replaces it is visible chrome rather than a keystroke: a More colours button in the run the swap button used to hold alone, so the rail is not a point thicker and the palette does not lose a column to it. Chips draw the canvas's own checkerboard when their colour is not solid, and only then, because a texture that is always there is a texture people stop seeing. Geometry is asked of the shipping arithmetic now rather than of a copy of it, and the two new geometry suites render the real views and measure the picture. Both were watched failing against the old behaviour first.
Merged
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.
Four reports from driving the app, and each one turned out to be something the code already claimed to do.
Tooltips cut their own text in half. The chip measured itself for one line and drew three, then clipped the rest with its own rounded rectangle. The bug hid itself: every size assertion in
TooltipRenderTestsbounded the chip from above, so each line that went missing made the checks pass more comfortably. What replaced them is a check that a longer sentence makes a taller chip. There were also two tooltip layers with two rules, and the rail's was not really a rule — it offset the chip by a constant, so hovering the ninth tool put the answer beside the first.The header ran off the right edge. The window can be dragged to 560pt; the row needed 647pt with no filename in it. Share, Duplicate, the Guide and the zoom were outside the window with nothing to say they were there — two numbers that had never been compared.
HeaderFitsteps down a ladder, and every rung drops a run whose commands have another door, which inverts the obvious answer: cut/copy/paste go before the drag-out handle, because they have three chords every Mac already knows and it has none.The rail hid its colour block. The whole rail sat in one scroller with its indicators off — in a file that has claimed since it was written that the loaded colours must never be cut. That was a comment, not a behaviour. The bottom bar had no shedding at all and ran 878pt of bar into a 548pt window.
Six controls were still a stock AppKit slider, in a panel whose every other control is drawn by hand. Two live bugs came out with them: the accessibility step was the entire range on any 0-to-1 fraction, so Ink, Opacity and Strength had two reachable values each; and
tskipped its clamp on the linear path, so an out-of-range value painted past the end of its own trough.A transparent colour did nothing in twelve of thirteen tools — including the eraser, which paints Colour 2, so the most obvious route to transparency was the one that was dead. Five compositors take a destination-out branch now, not the two it first looked like. The colour popover is gone with it: the system Colors panel is better at every part of that job, and what replaces the keystroke is a visible More colours button in the run the swap button used to hold alone, so the rail is not a point thicker.
Checking
docs/CHECKS_THAT_MISS.md§1 — and this file's own previous height check had exactly that shape.CI is the judge on the actor-isolation changes: this was written on a beta Xcode, and a green local build is not evidence there.