Skip to content

feat: polish freehand drawing, text halos, and fonts - #357

Merged
devmobasa merged 6 commits into
mainfrom
feat/drawing-polish
Aug 26, 2026
Merged

feat: polish freehand drawing, text halos, and fonts#357
devmobasa merged 6 commits into
mainfrom
feat/drawing-polish

Conversation

@devmobasa

Copy link
Copy Markdown
Owner

Summary

This PR adds three drawing and text improvements:

  • Smooth Pen and Marker strokes when drawing finishes. Smoothing is adjustable from 0–6, available in the toolbar and actions, remembered in sessions, and preserves tablet-pressure detail.
  • Make text halos contrast with the background behind the text instead of the text color. Halos can be disabled with [drawing] text_halo_enabled = false, independently of text background boxes.
  • Expand font controls with Shift+T cycling, an installed-font picker, configurator support, selected-text restyling, and toolbar controls for font family and Bold.

Additional polish

  • Load the system font catalog asynchronously after the first frame.
  • Add font search, filtering, wheel navigation, accelerated key repeat, responsive layout, and a scrollbar.
  • Keep modal wheel input, focus cleanup, preview damage, and narrow-toolbar behavior consistent.
  • Apply halo settings across canvas rendering, the text caret, thumbnails, PNG/region capture, and PDF export.
  • Document the new settings, actions, toolbar controls, and export limitations.

Run the configured binomial smoothing passes after a pen or marker stroke finishes, keeping both endpoints pinned so live input remains responsive and committed strokes lose pointer shake.

Smooth positions while preserving every tablet pressure sample and its thickness detail. Eraser paths remain raw because their geometry determines what is removed.

Store the resulting points on the committed shape and expose unbound step actions for adjusting the smoothing level.
Text is drawn with a contrasting outline so it reads over a busy desktop.
`text_outline_color` chose that outline from the colour of the *text*:
bright text took a black halo, dark text took a white one.

That reads the wrong input. A halo exists to separate the glyphs from what
is behind them, so what is behind them is what it has to contrast with.
Red has a weighted brightness of 0.30, so the rule called red dark and gave
it a white halo — on a whiteboard, a white halo on a white page. The
regression test measures the old behaviour at exactly zero dark pixels
around red glyphs on white.

The halo now comes from the luminance of what is already painted under the
label, sampled from the render target immediately before the glyphs go on.
Reading the target rather than the captured desktop image is what makes a
label over a blur, over a filled shape, or over a board colour all answer
correctly; none of them would if the probe looked at the raw screen capture.

The probe scales the region into a fixed 8x4 scratch surface, so it costs
one small paint per label per frame and does not grow with the size of the
text. It copies through a fresh context rather than borrowing the live
target's buffer, which is the same technique the spotlight magnifier uses.

A transparent board with no frozen or zoomed capture has nothing to sample:
the desktop shows through the compositor and those pixels were never ours.
The probe reports that it does not know, and the old text-colour rule stays
as the fallback, so behaviour there is unchanged. The guaranteed win is the
solid boards, where the background is always known.

The caret in the inline text editor asks the same question at its own
position, so a caret cannot disagree with the glyphs it sits among.
Changing the text font meant the toolbar or the config file. The toolbar's
two buttons cover Sans and Monospace; a third configured family had no
control at all and no key reached any of them.

Shift+T now steps the font through `[drawing] font_cycle`, a short list that
defaults to Sans, Monospace, Serif. `T` enters text mode, so its neighbour
is where the font that text will be written in belongs; omasnap #103 picked
the same chord for the same job.

The list is deliberately short rather than every installed font. A font
change mid-demo is a choice between two or three looks, not a font picker,
and a key that walks 400 families is a key nobody presses twice.

With text or a sticky note selected the step restyles that text and leaves
the tool setting alone, which is the idiom the shape and blur tools already
use for their variants. A mixed selection takes its step from the first
selected text shape, so it converges on one family rather than fanning out.
A family that is not in the list steps to the first entry: the list says
where the action can go, not where the font has been.

Blank and repeated entries are dropped at config load. A repeat would make
the key look like it skipped, and a blank name resolves to whatever the font
system falls back to. An empty list turns the action off and says so.

Wayscriber stays ahead of the PR this comes from: omasnap bundles three
fixed faces, while any installed family with any weight and style is already
valid here. Only the keyboard route was missing.
Add the system font picker, toolbar controls, configurator fields, and documentation for the new drawing settings.

Preserve smoothing state and preview damage, make text halos backdrop-aware on screen and in export, and harden modal input, focus teardown, and asynchronous font catalog loading.
@devmobasa devmobasa closed this Aug 26, 2026
@devmobasa devmobasa reopened this Aug 26, 2026
@devmobasa
devmobasa merged commit 14e504f into main Aug 26, 2026
2 checks passed
@devmobasa
devmobasa deleted the feat/drawing-polish branch August 26, 2026 19:46
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.

1 participant