Skip to content

Maintenance 2026 - #85

Open
samizdatco wants to merge 133 commits into
mainfrom
maintenance-2026
Open

samizdatco wants to merge 133 commits into
mainfrom
maintenance-2026

Conversation

@samizdatco

@samizdatco samizdatco commented Jul 14, 2026 •

Copy link
Copy Markdown
Member

Misc. Improvements

  • Upgraded bundled Python to 3.14 in app
  • Added precompiled wheels for module installs (supporting Python 3.9–3.14)
  • No longer requires Xcode command line tools in order to install
  • Added support for running under uv
  • Editor now uses a WKWebKit-based view (replacing the deprecated WebKit framework)
  • Added new default editor theme
  • New app icon should avoid "squircle jail" on macOS 26+

Bugfixes

  • ordered() now works correctly and no longer causes the Advanced/Sorting.pv example to crash
  • Text.flow() will now invoke user-provided callbacks to determine layout of multi-column runs
  • Command line tool now parses {4}-style padded number blocks in exported filenames correctly
  • Silenced a console error by fixing super() use in command line tool
  • Restorable state in the app now uses the newer 'secure' api

Stacked PR

samizdatco added 30 commits July 9, 2026 13:05
- previously they would never interrupt CI, even with a failure
- also fixes local env detection in cli when run from repo
- allows the test suite to run in CI
- it was using map() which started being lazy in python3 and was failing to invoke the callback
- comparing to a tuple was always a non-match
- add missing dunder methods and drop otiose ones from MagicNumber (the base class for Dimension & Unit)
- add unit tests exercising numeric comparison ops
- fixes #67
- previously the vector would be rasterized at the width/height of the PDF or SVG, then that bitmap mask would be scaled
- now the vector image is scaled to the size it will occupy on the canvas *before* being rasterized, so the masking is still pixel-based, but will no longer be super-low res
- partially addresses #83 (though it doesn't provide the vector-based mask the user exptected)
- initial migration uses some runloop trickery in the EditorView.source getter to stay compatible with the synchronous file-saving api
- web inspector is now only enabled by default on dev builds (though it can be added to dist builds with a defaults write to `WebKitDeveloperExtras`)
- removed the need for the runloop trickery by keeping a cached copy of the document in _last_source (updated via the undo-manager callback)
- source file is app/art/PlotDevice-app.icon
- Assets.car can be rebuilt with `make.py icon`
- the Convert to CMYK checkbox is now a Colors popup listing available profiles
- View > Proof Colors affects the on-screen display and previews what an export with the corresponding profile would look like
- the press constants' values are now their names (gracol, swop, etc.)
set popup background via fixed selectors, not inline styles
- accept fill()-style gradient args in stroke()
- fill(), stroke(), and background() inherit color()'s mode, range, and space
- unknown color keywords raise instead of being dropped, as do extra arguments after an image
- the Colors pop-ups and Proof Colors include macOS's RGB spaces
- improve errors for unknown/invalid colors= values
- includes protanopia, deuteranopia, tritanopia, and their anomalous forms
- hovering the menu item previews its profile
- RGB profiles now keep transparency rather than a white matte
- rendered in P3 and then converted to requested primaries and matrix by AVFoundation
- move culling and layer-sizing state into FrameBounds, with each grob measuring its own _render_box()
- scaled-up text with effects no longer clips its glyphs' overhangs
- Text.flow() properly keeps the original size unit even if the canvas's changes before flowing
- FrameLayers collects the canvas's CA layers and tiles
- ViewTracker monitors the viewport's scale and position changes
- with export() only renders on a separate thread if the GIL is off
- ViewTracker applies zoom on its own, so it just needs the dpr
- if a nested render call occurred (e.g., for an embedded image/canvas), keep the lock until that completes
- each grob/frob now makes its own clone (isolated from ctx state for the rendering pass)
- if there aren't any variables referencing the grob, the copy is skipped
- stop using NSImage.lockFocus in favor of thread-friendly CGImage
- make sure ProRes frames are drawn in the movie's color space
- pass codec & colors as names rather than indices
- also switch to using NSApp() accessor rather than the global
- don't wildcard all of Foundation just to confirm PyObjC is present
- defer building the font family list until first use
- don't import all of CoreServices just to get the image type UTI strings
- use html.escape rather than pulling in xml.sax.saxutils (and transatively urllib.request)
- reduces `import plotdevice` from 950ms to 210ms
- now checks for exact family matches before switching to fuzzy (and avoids sending weight names to the family matcher)
- only construct the full family name list on the first fuzzy match request
- an image() can now be passed to stroke(), fill(), or background() and will be used as a repeating pattern
- the x/y/width/height values passed to image scale the tile and position it relative to the canvas origin
- svgs and canvas-backed patterns now remain vectors (though text fills still rasterize)
- requires pdf and eps exports to hold the render lock while CG reenters to draw the tiles
- previously the script's canvas reference could still affect a committed Frame's clip/mask shapes
- otherwise a canvas's default P3 space could be used for a pattern in a CMYK export
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