Repository navigation
Change an annotation's kind in place - #973
Merged
Merged
Conversation
An update with a new subtype turns a highlight, underline, squiggly line or strikeout into another of the four, and a rectangle into an ellipse and back: the kinds ISO 32000 describes with one table of entries, and that we declare with the same fields. It stays the same annotation: its ref, nm, place in the drawing order, replies, popup, group and author. The update takes the new kind's fields; any other subtype fails with InvalidArg, 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, so both writes are one step to undo. Today that is only a replacement's strikeout, which keeps its kind while it has its intent. In the headless docs, update() takes the subtype, the style panel has a subtype choice (none for a replacement's strikeout), selection.update gives it to the annotations that can take it, and changing a kind by hand needs both kinds in editable. Docs first: the engine still refuses a changed subtype.
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.
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.
withValues takes a sibling subtype when the record may change and the
annotation can become it (canChangeKind, from engine-core, the same
rule the resolver refuses by), so its patch and pending view are the
new kind's. setFields gives it only where people may change the new
kind by hand too, so selection.update({ subtype }) changes the members
that can and restyles the rest. changeBetween no longer pins a patch
to the old subtype. The plugin's restoring patch already comes out
right: annotationPatchBetween states the subtype.
selectionProperties leads a selection's properties with a subtype
choice when its kinds are siblings that can each change kind (not a
replacement's strikeout), offering the kinds people may change by
hand; each named as the comment list names it, under
annotation.style.kind. A tool's defaults panel keeps propertiesOf, so
it never offers a kind. The viewer's style panel renders no control
for subtype yet; that is the next step.
engine-core: fieldTheKindCannotHold and canChangeKind beside
siblingKindsOf; the resolver's refusal uses the first. The API reports
follow, and the conformance report catches up with a formatting-only
change from the previous commit.
The style panel's Type row shows the subtype choice selectionProperties
leads with: one toggle per kind the selection can become, each with
its tool's icon (KIND_ICON), as the alignment row does. Picking one
sends selection.update({ subtype }). annotation.style.kind ("Type") is
in all 15 viewer languages; the kinds reuse the comment list's names.
Acrobat, Preview and Foxit have no way to change a mark's kind (delete
and mark again); Zotero 7 converts highlight and underline from the
mark's context menu. The style panel is where a selected mark's other
properties are edited, so the kind sits there, first.
Checked in the dev viewer: a square becomes a circle in its turned box
(same object, stroke and rotation, written by the engine), Cmd+Z turns
it back; a new highlight becomes a squiggly line with its comment,
color and blend mode; a highlight and a circle selected together get
no Type row.
The viewer's annotations page says the style panel changes a mark's
kind, with a short section under Good to know.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
…nd-change # Conflicts: # api/embedpdf__angular/annotation.api.txt # api/embedpdf__angular/index.api.txt # api/embedpdf__core-annotation/index.api.txt # api/embedpdf__plugin-annotation/contract.api.txt # api/embedpdf__plugin-annotation/contract__host.api.txt # api/embedpdf__plugin-annotation/index.api.txt # api/embedpdf__react/annotation.api.txt # api/embedpdf__react/index.api.txt # api/embedpdf__svelte/annotation.api.txt # api/embedpdf__svelte/index.api.txt # api/embedpdf__vue/annotation.api.txt # api/embedpdf__vue/index.api.txt # packages/engine/core/src/annotation/resolve/resolveAnnotationPatch.ts
This branch had an error being deployed
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.
What changes
Switching a highlight to an underline (or squiggly, or strikethrough), or a square to a circle, took a delete and a create with every field copied by hand. That loses the annotation itself: its ref, its replies'
/IRT, its popup and group, its place in the drawing order, and its author, which a create stamps anew.update()refused a changedsubtype. (v2 looked as if it allowed it, but it never wrote/Subtype: the file kept a highlight, and a reload showed one.)Now an update changes the kind to a sibling and the annotation stays itself:
Siblings are the kinds ISO 32000-2 describes with one table of entries: highlight, underline, squiggly and strikeout (12.5.6.10), and square and circle (12.5.6.8). Our declarations give each group the same fields, and a test holds them to it (
siblings.ts).Any other subtype is refused with
InvalidArg(details.field: 'subtype'), 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, so it stays one undo step. Today that's only a replacement's strikeout and its
intent:By layer:
EPDFAnnot_SetSubtype(Change an annotation's kind in place runtime#103, Breaking changes introduced with new PATCH version #108). The bindings gain it, and Text Box Problems #104'sEPDFAnnot_SetNoColor. Pin the runtime to f2dd40897: shapes without a stroke, and ink drawn as Acrobat draws it #971 brought the same pin to main with ink's viewer half, and main is merged in, so the pin itself no longer shows as a change here.siblingKindsOf,canChangeKind,fieldTheKindCannotHold. The patch resolver and schema check run as the new kind. The prediction (applyAnnotationPatch) reads the new kind, andannotationPatchBetweenstates the subtype.AnnotationMutator.updatecallsEPDFAnnot_SetSubtypebefore writing the fields, and the appearance is drawn as the new kind. The undo fallback (annotation changed since) keeps the subtype.selection.update({ subtype })changes the members that can become that kind; the rest keep theirs. A locked annotation, a replacement's strikeout, or a kindeditabledoesn't allow by hand keep their kind.getProperties()leads with asubtypechoice (selectionProperties). A tool's defaults never offer one.Not in this PR: polygon ↔ polyline (more fields differ, and a measured polygon measures an area while a polyline measures a length). The wire shape and the contract's update operation don't change, so there's nothing for
api:sync.Testing
Fork (Change an annotation's kind in place runtime#103, released):
SetSubtypeChangesTheKindInPlaceandLayerSetSubtypeKeepsTheObjectAndAborts, native darwin-arm64, plus every*EPDFAnnot*test (170) and layer mode.Conformance on the local (wasm) and cloud engines (
runAnnotationMutationConformance, 4 new tests):nm, place in the order, reply and author;runAnnotationPredictionConformanceadds 4 kind changes, predicted as the engine writes them.Suites, after merging main (with Pin the runtime to f2dd40897: shapes without a stroke, and ink drawn as Acrobat draws it #971 and Write a dashed border's default pattern out; an empty pattern reads solid #972):
@embedpdf/engine1917 passed, none failing (the 4annotation-rectink cases that the pin alone failed now pass with Pin the runtime to f2dd40897: shapes without a stroke, and ink drawn as Acrobat draws it #971's ink half). engine-core 1033, core-annotation 663, plugin-annotation 280, and the cloud mutation and prediction suites 126 passed. Before the merge, the full@cloudpdf/enginesuite passed 1110.Checks: typecheck of the 93 packages that depend on core-annotation (websites aside),
api:check, anddocs:checkon both sites all pass.Viewer dev harness: