Repository navigation
Change an annotation's kind in place - #103
Merged
Merged
Conversation
EPDFAnnot_SetSubtype writes /Subtype and nothing else. The annotation keeps its dictionary, object number, place in /Annots and every other entry, and its /AP until the caller draws the new kind. It is a mechanic: which kinds may become which is the caller's decision. ISO 32000-2 describes the four text markup subtypes with one table of entries, and Square and Circle with another. A widget belongs to its form field and a popup to its parent, so neither changes kind and nothing becomes one. A subtype the annotation API doesn't create is refused too. FPDFAnnot_GetSubtype() reads the subtype from the dictionary, and each render builds a new annotation list, so there is nothing to drop. A form-fill page view loaded before the change keeps the old subtype until the page is loaded again, as after FPDFPage_CreateAnnot(). Tests: on a new document, the refusals, the entries and drawing kept, a redraw that draws the new kind, and a save round trip; on a layer, an aborted transaction leaves the highlight, and a committed one keeps its object number and survives a reopen from the saved delta.
roanutil
pushed a commit
to roanutil/embed-pdf-viewer
that referenced
this pull request
Nov 4, 2026
The patch resolver takes a subtype the annotation can become: a highlight, underline, squiggly line or strikeout another of the four, a square a circle and back. ISO 32000-2 describes each group with one table of entries, and our declarations give them the same fields (siblings.ts; a test holds them to it: same owners, read-backs, colors and spaces, apart from a strikeout's intent). The patch is the new kind's, checked against its schema. Any other subtype is refused, naming the kinds it can become. A value the new kind has no field for is refused, never dropped: the caller clears it first, in the same change. The prediction makes the annotation the new kind, a field only it has reading null, and annotationPatchBetween states the subtype when the kind changed. Engine core only. The engines still keep /Subtype as it was until the fork's EPDFAnnot_SetSubtype (embedpdf/runtime#103) is released and pinned; the writer, undo and conformance follow with it.
roanutil
pushed a commit
to roanutil/embed-pdf-viewer
that referenced
this pull request
Nov 4, 2026
Pin the runtime to f2dd40897, which has EPDFAnnot_SetSubtype (embedpdf/runtime#103, #108); the bindings gain it and #104's EPDFAnnot_SetNoColor. An update whose resolved patch names a sibling kind calls EPDFAnnot_SetSubtype before writing the fields, so they are written as the new kind's and the appearance is drawn as one (appearanceImpactOf already answers regenerate for a changed subtype). The undo fallback keeps a changed subtype, so an undo after a later edit puts the old kind back by value; the usual undo restores the dictionaries. Conformance, on the local and the cloud engine: a highlight becomes a squiggly line with its ref, nm, place in the order, reply and author; a square becomes a circle with a new color and back; another family and a replacement's intent are refused, and clearing the intent first in the same change works; undo, redo, and undo after a restyle. The prediction suite predicts four kind changes as the engine writes them. The contract's update operation and the wire shape don't change, so there is nothing for api:sync.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds
EPDFAnnot_SetSubtype(): change an annotation's kind in place by writing its/Subtypeand nothing else. The annotation keeps its dictionary, object number, place in/Annotsand every other entry, so its replies (/IRT), popup, group and author stay with it./APis left as it is; the caller draws the new kind withEPDFAnnot_GenerateAppearance().Today the only way to turn a highlight into a squiggly line is delete and create, which loses all of that. ISO 32000-2 describes the four text markup subtypes with one table of entries (12.5.6.10), and Square and Circle with another (12.5.6.8), so within those a kind change is a new name and a new drawing.
FPDFAnnot_IsSupportedSubtype()refuses, and a widget or a popup either way. A widget belongs to its form field and a popup to its parent.FPDFAnnot_GetSubtype()reads the dictionary, and each render builds a new annotation list. A form-fill page view loaded before the change keeps the old subtype until the page loads again, as afterFPDFPage_CreateAnnot(); the engine opens no form-fill environment.Tests
SetSubtypeChangesTheKindInPlace: the refusals; the entries, index, color, contents and/APkept; a redraw draws the new kind; a save round trip.LayerSetSubtypeKeepsTheObjectAndAborts: an aborted transaction leaves the highlight; a committed one keeps the object number and survives a reopen from the saved delta.Run natively on darwin-arm64: both pass, and so do all 170
*EPDFAnnot*embedder tests.check-c-api.pyandcheck-fork-tags.py --strictpass.The engine side,
update()taking a siblingsubtype, is planned on embedpdf/embed-pdf-viewerfeature/annotation-kind-change(its docs are committed there). It needs this released and pinned.