Skip to content

feat(layers): layer tree, annotation layers and saved default state (#377) - #775

Closed
oscar981-op wants to merge 1 commit into
OpenAEC-Foundation:mainfrom
oscar981-op:feat/layers-377
Closed

oscar981-op wants to merge 1 commit into
OpenAEC-Foundation:mainfrom
oscar981-op:feat/layers-377

Conversation

@oscar981-op

Copy link
Copy Markdown
Contributor

Fixes #377.

Already on main

  • A layers panel built from pdf.js, with checkboxes.
  • Desktop toggling through a temp view copy with an incremental /OCProperties /D update (laagstand.js + Rust set_layer_view).
  • Markup layers saved as /OC.

Added

  • Tree: the full /Order tree, including the "children nested under a layer" form, labels, /Locked (checkbox disabled) and radio groups (js/pdf/lagen-boom.js).
  • Layer field in the properties panel. A markup put on a drawing layer hides with it in the app and in other readers: on save it gets /OC pointing at the drawing's own OCG.
  • Default state: "Set as default" in the Layers panel. The next save writes /D /ON /OFF, keeping BaseState and /AS and leaving out own markup OCGs.
  • Render paths:
    • PDFium (main view, tiles, thumbnails): the view copy is rebuilt after each save, where it used to go stale.
    • Export and raster print: pass pdfjsLaagOpties.
    • Vector Save as PDF: the source gets the same /D update.
  • Adopted OCGs keep their place in /OCGs, /Order, /Locked and /RBGroups. When removed they are detached, not deleted.
  • 8 new strings in all 40 locales.

Tests

  • Tree parsing compared with pdf.js: nesting, labels, RBGroups, Locked, BaseState ON/OFF.
  • Pixel tests on a generated PDF with two OCG rectangles: pdf.js, the view copy and the saved default in MuPDF, and annotation /OC hiding.
  • Annotation /OC round-trip.
  • An opt-in real PDFium pixel test (OPDS_PDFIUM_WORKER), which passed locally against the release worker.
  • Full unit suite: 0 failures. vite build is clean.

Not yet checked in the running app / limits

  • Panel look, the Layer select, and the full toggle → re-render → save → rebuild cycle. Printing on a real printer.
  • A drawing layer that has markups assigned writes its visibility to /D on every save.
  • /Usage print states and /AS print events are not applied.

🤖 Generated with Claude Code

…oundation#377)

- Layers panel follows the /OCProperties /D tree read from the file:
  layers nested under a layer (unlabelled /Order arrays), labels,
  /Locked layers (checkbox disabled, lock icon) and /RBGroups (radio
  semantics via the pdf.js config). Hidden-by-default layers stay hidden.
- "Set as default" stores the toggled state; the next save writes it as
  /D /ON /OFF (BaseState kept), after which it is the file's start state
  and the view copy follows the new bytes.
- Toggled state now also applies to raster export/print (pdf.js path) and
  the vector "save as PDF" print (same /D update as the view copy).
- Properties panel "Layer" field: markup layers or document layers. A
  markup on a document layer gets /OC to that OCG on save, loads back on
  it, and hides/shows with the layer. Adopted OCGs keep their place in
  /OCGs, /Order, /Locked and /RBGroups and survive removal of the layer.
- Translations for all locales; tests for tree parsing, default state,
  saving the default, annotation /OC round-trip and pixel checks via
  pdf.js, MuPDF and (optionally) the real pdfium-worker.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@DutchSailor

Copy link
Copy Markdown
Collaborator

Thank you, @oscar981-op! This change is included in release 2026.44.1 through the release PR #841, as one squashed commit with you as the author, so this PR is closed rather than merged. During review we added the following on top, with regression tests: a drawing layer that a markup layer is placed on now keeps its place in /OCGs, /Order, /RBGroups and /Locked, its own /Name and its default state when the markup layer is deleted or renamed; toggling a layer only changes the view, and only "Set as default" changes the saved default.

philip-tam pushed a commit to philip-tam/open-pdf-studio that referenced this pull request Nov 1, 2026
…penAEC-Foundation#775)

The Layers panel follows the /OCProperties /D tree from the file: nested
layers, labels, /Locked layers (shown with a lock, checkbox disabled) and
/RBGroups (radio behaviour). "Set as default" stores the toggled state, and
the next save writes it as /D /ON /OFF. The toggled state also applies to
raster export, printing and the vector "save as PDF" print. The properties
panel gets a "Layer" field: a markup can be put on a markup layer or on a
layer of the drawing, in which case it gets /OC to that OCG on save, loads
back on it and hides and shows with it.

Fixes OpenAEC-Foundation#377

Review fixes on top:
- An adopted drawing layer whose markup layer was removed while other
  markup layers remained was dropped from /OCGs, /Order, /Locked,
  /RBGroups and /ON /OFF. Every adopted OCG known from the file now keeps
  its place; only the app's own keys are removed.
- The drawing layer's /Name is no longer overwritten by the markup layer
  name (for example a " (2)" suffix or a rename in the panel).
- Adopting a layer no longer turns the current view state into the file's
  default. Adopted layers keep their /D state; only "Set as default"
  changes it (laagstandZonderEigenLagen).
- Regression tests for all three cases (save, reopen, check /OCGs, /Order,
  /RBGroups, /Locked, name and default state).
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.

[Feature]: Layers (optional content groups): view, toggle and assign annotations

2 participants