Skip to content

feat: accidental marks keep how they are drawn - #497

Merged
webern merged 3 commits into
m/mxdev-accmarkfrom
m/mxdev-accattr
Nov 7, 2026
Merged

webern merged 3 commits into
m/mxdev-accmarkfrom
m/mxdev-accattr

Conversation

@webern

@webern webern commented Nov 6, 2026 •

Copy link
Copy Markdown
Owner

AI Summary

An accidental-mark lost how it is drawn when read into mx::api and written back. Only its accidental value, position and placement were kept; its parentheses, bracket, size, SMuFL glyph, id, font and color were dropped on read and could not be authored. This applied both to a standalone accidental mark in notations and to an accidental that belongs to an ornament, such as the sharp over a trill.

What changes in mx::api:

  • A new SymbolSize enum in ApiCommon.h (unspecified, full, cue, graceCue, large) carries MusicXML's size attribute. unspecified leaves the size to the application.
  • MarkDataChoice gains an AccidentalMarkData alternative (Kind::accidentalMark, isAccidentalMark(), accidentalMark()) for the accidentalMark* mark types:
    • parentheses and bracket (Bool): yes draws the accidental in parentheses or square brackets, common ways to show an editorial accidental. unspecified leaves it to the application.
    • size (SymbolSize): how large the accidental is drawn.
    • smufl: a specific SMuFL accidental glyph, for example accidentalSharp. A name that is not a SMuFL accidental (one starting with acc, medRenFla, medRenNatura, medRenShar or kievanAccidental) is not written, and the write reports an error diagnostic with the dropped-data code.
    • id: the element's id.
      The accidental's font and color go in the existing MarkData::printData. A payload with every field at its default is stored as none, so a mark built from its MarkType alone still compares equal after a write and a read.
  • OrnamentAccidental gains the same five fields directly, plus PrintData for its font and color. An owned accidental has no MarkData around it, so its fields sit on the one struct a caller already reads.

One reader helper and one writer helper fill both shapes.

Behaviour change for callers reading files

Reading an accidental mark that sets any of parentheses, bracket, size, smufl or id now gives a choice holding AccidentalMarkData where it used to be none. Its MarkData::printData, and an OrnamentAccidental's printData, now holds the font and color from the file where it used to be left at its default. Code that builds accidental marks is unaffected, and nothing was removed or renamed, so this is labelled non-breaking.

Out of scope

  • MarkData::name is still filled in by the reader for an accidental mark (for example "sharp") but left empty by the MarkData constructor, as it already is for ornaments. The writer ignores name for these marks. Changing the constructor would change what existing callers build, so it is left alone here.
  • printObject on an accidental mark's PrintData, and the alignment fields of its PositionData, have no MusicXML attribute to go to and are not written. The headers say so. Other marks drop these the same way without a diagnostic, and adding one for every mark belongs in its own change.
  • A MarkDataChoice payload of another kind on an accidental mark is ignored, as on every other mark. An ornament payload on an accidental mark is still reported, as before.

Pinned files

  • synthetic/accidental-mark.3.0.xml
  • synthetic/accidental-mark.3.1.xml

Testing

  • MarkRoundTripTest: AccidentalMarkAttributes, AccidentalMarkSizes, AccidentalMarkDefaultsToNoPayload, OrnamentAccidentalAttributes, AccidentalMarkSmuflNotAnAccidental, AccidentalMarkChoiceAccessorsAndEquality (every new field's equality, both shapes)
  • NoteDataTest: readsSyntheticAccidentalMarkFixture reads every attribute of the trill's sharp from the 3.1 fixture; standaloneAccidentalMarkKeepsHowItIsDrawn reads a standalone accidental-mark's attributes, checks the written xml carries each one, and checks a bare one reads with no payload
  • make api-test: 6884 assertions in 806 test cases pass
  • make api-roundtrip: 460 of 460 pinned files pass, two more than before
  • make api-roundtrip-discover: 461 PASS, 380 FAIL; the PASS list is main's plus the two pinned files
  • make audit-test passes; make fmt-check passes
  • Unity build of target mx (CMAKE_UNITY_BUILD, batch size 0) succeeds

References

@webern
webern added this pull request to stack #498 November 6, 2026 01:12
@webern webern changed the title m/mxdev accattr feat: accidental marks keep how they are drawn Nov 6, 2026
@webern webern added feature new feature request non-breaking fixes or implementation that do not require breaking changes api Affects the mx::api layer impl Affects the mx::impl layer ai Issues opened by, or through, a coding agent. labels Nov 6, 2026
An accidental-mark kept only its value and position. Its parentheses,
bracket, size, SMuFL glyph, id, font and color were dropped on read and
never written.

A standalone accidental mark now carries these in a new AccidentalMarkData
alternative of MarkDataChoice, with its font and color in
MarkData::printData. A payload with nothing set is none, so a mark built
from its MarkType alone still compares equal after a write and a read. An
accidental that belongs to an ornament (OrnamentAccidental) gains the same
fields directly, plus PrintData. The new SymbolSize enum in ApiCommon.h
carries MusicXML's size attribute.

The reader and the writer each fill both shapes through one shared helper.
A smufl name that is not a SMuFL accidental glyph is not written and is
reported as dropped data.

Pins synthetic/accidental-mark.3.0.xml and accidental-mark.3.1.xml in the
round-trip baseline.
SymbolSize::unspecified leaves the size to the application rather than
promising the usual size, and cue and graceCue now follow MusicXML's
note-type defaults: cue is the size of a cue note or a grace note,
graceCue the size of a note that is both. AccidentalMarkData::size says
that a different size is, like parentheses and brackets, a common way to
show an editorial accidental, and the payload's comment says that
MarkData::printData's printObject is not used for an accidental mark.
Reads a standalone accidental-mark that sets parentheses, bracket, size,
font, color, smufl and id, checks each field, and checks the written xml
carries each attribute. A bare accidental-mark beside it reads with no
payload and default print data.

Corrects the comment on AccidentalMarkDefaultsToNoPayload: the mark reads
back equal in everything but name, which the reader fills in and the
MarkData constructor leaves empty for accidental marks.
@webern
webern marked this pull request as ready for review November 7, 2026 12:46
@webern
webern merged commit 222a402 into main Nov 7, 2026
9 of 18 checks passed
@webern
webern deleted the m/mxdev-accattr branch November 7, 2026 12:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai Issues opened by, or through, a coding agent. api Affects the mx::api layer feature new feature request impl Affects the mx::impl layer non-breaking fixes or implementation that do not require breaking changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant