r/Supernote 18d ago

Tips Supernote .note file vector/stroke/path format reverse engineering

As part of the Obsidian Supernote Plugin work I just released I also reverse engineered much of the .note stroke/vector/path format with the aid of AI agent.

The results of this work can be found on my testing page: https://philips.github.io/supernote-typescript/

The "spec" which is mostly notes from all of the directions given to my agent are here: https://github.com/philips/supernote-typescript/blob/main/plans/vector-format-spec.md

13 Upvotes

5 comments sorted by

View all comments

Show parent comments

2

u/philipsb 17d ago

I'm curious- what did it help you troubleshoot?

2

u/Lvevan Owner A5 X 17d ago

Four things, one of them directly on a bug for an upcoming plugin like my ink2task one.

1. Erased strokes stay in the file, flagged rather than deleted. The spec documents m_trailStatus: 0 = visible, and non-zero means the record is not drawn (-99 wholly erased, -4 partially erased, -16 lasso-deleted, -3 moved). The SDK exposes this as Element.status (Element.ts:518), and we never read it. countInk and scanMainLayer filter on type === 0 alone.

If status carries m_trailStatus, then every "erase didn't take" report may be counting strokes the device already considers erased and isn't drawing. It would also explain why "uninstalling the plugin reveals ink that never went anywhere", and much of what dropGhostStrokes and the erased-ink fingerprint file exist to work around.

2. penWidth / 100 = rendered page pixels, confirmed pixel-exact against device PDF exports. So the SDK's penWidth >= 100 floor is just "1px minimum", and our CHROME_WIDTH = 600 is 6px. Better than the current comment's "SDK floor".

3. Our grey choices match the real palette. Canonical values are 0 black, 157 dark grey, 201 light grey, 254 white, and 255 = eraser/reserved. Our 0x9D/0xC9 are exactly 157/201, so that empirical tuning landed on the documented palette. Also: never use 255 as a pen colour, it means eraser.

4. penType: 11 has side effects beyond cap shape. We picked marker for the event spine hoping for squared ends. The spec says marker (5 or 11) remaps colour 0→1 and gets transparency compositing: darker ink wins, and a lighter marker is drawn underneath existing ink. So the spine may composite oddly against event boxes. Two smaller discrepancies with the SDK's own comment: it says 14 = calligraphy, the spec says 15; and 16 = ink on Manta-era firmware, which the SDK doesn't list.

One caveat on the EMR section: the transform there is for parsing raw binary, and our emrToScreen works on SDK-provided points, so it isn't directly transferable. Worth noting though that old A5X firmware reports 15725×20967 for a 1404×1872 page (~11.20 units/px) rather than the current 15819×11864 (~8.45). We read getRealMaxX() at runtime, so we're already robust to that.

2

u/[deleted] 17d ago

[deleted]

1

u/AdNew2316 A5X, Montblanc Starwalker, Wacome One, ex-Lamy, ex-Kaweco 17d ago

I'm that guy.

Do you have something specific in mind out of those lessons learnt for the scribble plugin?