Optional-content layers
Read and write optional-content groups, configurations and visibility in pdfspine 0.8.0.
Optional-content groups (OCGs) control visibility in both rendering and native text extraction. This page describes the published 0.8.0 behavior.
Attach content to a group
import pdfspine
doc = pdfspine.open()
page = doc.new_page()
layer = doc.add_ocg("Notes")
page.insert_text((40, 60), "Layered text", oc=layer)
print(doc.get_ocgs())
print(page.get_text())The oc= argument also applies to image/page placement, shape text and vector
writers. Text/vectors use marked content; image/form XObjects carry /OC.
get_oc(xref) reads an image/form association. Use an existing OCG or OCMD xref;
invalid values fail without writing the content.
Default, alternate and UI configurations
get_layer() / set_layer() access the default configuration. get_layers() lists
alternate configurations, excluding the default /D entry.
doc.add_layer("Only notes", on=[layer])
config = doc.get_layers()[0]["number"]
doc.switch_layer(config) # in-memory view for extraction/rendering
for row in doc.layer_ui_configs():
print(row)set_layer_ui_config(number, action=0) turns a selectable row on; action 1
toggles and 2 clears it. It also accepts row text. Label/locked rows are ignored;
radio siblings are mutually exclusive. These overrides are in-memory only.
switch_layer(config, as_default=True) instead rewrites /D from the selected
configuration and removes /Configs; save the document to persist that change.
Use this deliberately if you want to replace the default rather than just inspect a view.
Membership dictionaries
set_ocmd(xref=0, ocgs=[layer], policy="AnyOn") creates an optional-content
membership dictionary; supplying an existing xref fully replaces it.
get_ocmd(xref) returns xref, ocgs, policy and ve.
Policies are AnyOn, AllOn, AnyOff, AllOff; a supplied visibility expression
ve takes precedence. Hidden marked content and hidden image/form XObjects emit
no text or drawing operations in the selected view.
See the 0.8.0 layer API source
for full signatures. Later changes on main are outside this release description.