Skip to content

Read and write an annotation's alt text in the structure tree - #119

Open
KleiKodesh wants to merge 5 commits into
embedpdf:embedpdf/mainfrom
KleiKodesh:feat/annot-alt-text
Open

KleiKodesh wants to merge 5 commits into
embedpdf:embedpdf/mainfrom
KleiKodesh:feat/annot-alt-text

Conversation

@KleiKodesh

Copy link
Copy Markdown

PDF.js keeps a stamp's alternate description in the structure tree, not in the annotation: a /Figure element with /Alt and an /OBJR to the stamp, the stamp's /StructParent, and a parent tree entry. An engine that wants to save alt text the way PDF.js reads it back had no API to write that.

New functions in epdf_annot.h:

  • EPDFAnnot_GetAltText(annot, buffer, buflen) reads the /Alt of the structure element that lists the annotation, found through its /StructParent and the parent tree (the same walk EPDFAnnot_GetStructurePosition() makes).
  • EPDFAnnot_SetAltText(annot, alt) writes it:
    • an annotation already in the tree: the element that lists it gets the /Alt (an empty or NULL text removes it);
    • otherwise a new /Figure element (/P, /Pg, /Alt, /K = the /OBJR), appended to the tree's /Document element when the root's one kid is one, else to the root; the annotation gets /StructParent = the next parent tree key (/ParentTreeNextKey, past every key in use), and the parent tree's /Nums gets the entry in key order;
    • the catalog's /StructTreeRoot and its /ParentTree are created when missing;
    • refused, with nothing written: a direct annotation dictionary, a parent tree with /Kids (only a flat /Nums is written), or a structure root or parent tree that isn't a dictionary.

Every write to an existing object goes through GetMutableIndirectObject() / GetMutableRoot(), so in a layer it promotes exactly the objects it changes.

Tests

  • New embedder test EPDFAnnotEmbedderTest.AltTextRoundTripsThroughTheStructureTree: two annotations get alt text on a document without a structure tree, read back, sit at root kids 0 and 1, a second write rewrites the element in place, and NULL removes it.
  • epdf_c_api_test.c lists the two new exports.
  • Not built or run locally (no emscripten/clang toolchain on the machine this was written on); CI hasn't run yet.

PDF.js writes a stamp's alternate description into the structure tree:
a /Figure element with /Alt and an object reference to the stamp, the
stamp's /StructParent, and a parent tree entry. There was no way to
write that, so an engine saving PDF.js-style alt text had nowhere to
put it.

- EPDFAnnot_GetAltText() reads the /Alt of the element that lists the
  annotation, found through its /StructParent.
- EPDFAnnot_SetAltText() writes it there. An annotation not yet in the
  tree gets a new /Figure element (under the tree's /Document element
  when that is the root's one kid), a /StructParent at the next parent
  tree key, and the catalog's /StructTreeRoot and /ParentTree when they
  are missing. An empty text removes the /Alt. A parent tree with /Kids
  is refused: only a flat /Nums is written.

Writes go through the document, so in a layer they promote exactly the
objects they change.
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