Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 20 additions & 1 deletion src/include/mx/api/CodaData.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,28 +6,47 @@

#include "mx/api/ApiCommon.h"
#include "mx/api/ColorData.h"
#include "mx/api/FontData.h"
#include "mx/api/PositionData.h"

#include <string>

namespace mx
{
namespace api
{
// The MusicXML <coda> element carries the empty-print-object-style-align attribute group plus the
// smufl glyph-name and optional-unique-id. positionData captures default/relative x-y plus the
// horizontal and vertical alignment; its placement member is unused here because <coda> has no
// placement attribute (placement lives on the parent <direction>).
class CodaData
{
public:
PositionData positionData;
FontData fontData;
bool isColorSpecified;
ColorData colorData;
bool isSmuflSpecified;
std::string smufl;
bool isIdSpecified;
std::string id;

CodaData() : positionData{}, isColorSpecified{false}, colorData{}
CodaData()
: positionData{}, fontData{}, isColorSpecified{false}, colorData{}, isSmuflSpecified{false}, smufl{},
isIdSpecified{false}, id{}
{
}
};

MXAPI_EQUALS_BEGIN(CodaData)
MXAPI_EQUALS_MEMBER(positionData)
MXAPI_EQUALS_MEMBER(fontData)
MXAPI_EQUALS_MEMBER(isColorSpecified)
MXAPI_EQUALS_MEMBER(colorData)
MXAPI_EQUALS_MEMBER(isSmuflSpecified)
MXAPI_EQUALS_MEMBER(smufl)
MXAPI_EQUALS_MEMBER(isIdSpecified)
MXAPI_EQUALS_MEMBER(id)
MXAPI_EQUALS_END;
MXAPI_NOT_EQUALS_AND_VECTORS(CodaData);
} // namespace api
Expand Down
21 changes: 20 additions & 1 deletion src/include/mx/api/SegnoData.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,28 +6,47 @@

#include "mx/api/ApiCommon.h"
#include "mx/api/ColorData.h"
#include "mx/api/FontData.h"
#include "mx/api/PositionData.h"

#include <string>

namespace mx
{
namespace api
{
// The MusicXML <segno> element carries the empty-print-object-style-align attribute group plus the
// smufl glyph-name and optional-unique-id. positionData captures default/relative x-y plus the
// horizontal and vertical alignment; its placement member is unused here because <segno> has no
// placement attribute (placement lives on the parent <direction>).
class SegnoData
{
public:
PositionData positionData;
FontData fontData;
bool isColorSpecified;
ColorData colorData;
bool isSmuflSpecified;
std::string smufl;
bool isIdSpecified;
std::string id;

SegnoData() : positionData{}, isColorSpecified{false}, colorData{}
SegnoData()
: positionData{}, fontData{}, isColorSpecified{false}, colorData{}, isSmuflSpecified{false}, smufl{},
isIdSpecified{false}, id{}
{
}
};

MXAPI_EQUALS_BEGIN(SegnoData)
MXAPI_EQUALS_MEMBER(positionData)
MXAPI_EQUALS_MEMBER(fontData)
MXAPI_EQUALS_MEMBER(isColorSpecified)
MXAPI_EQUALS_MEMBER(colorData)
MXAPI_EQUALS_MEMBER(isSmuflSpecified)
MXAPI_EQUALS_MEMBER(smufl)
MXAPI_EQUALS_MEMBER(isIdSpecified)
MXAPI_EQUALS_MEMBER(id)
MXAPI_EQUALS_END;
MXAPI_NOT_EQUALS_AND_VECTORS(SegnoData);
} // namespace api
Expand Down
34 changes: 32 additions & 2 deletions src/private/mx/impl/DirectionReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,22 @@ void DirectionReader::parseSegno(const core::DirectionType &directionType)
{
api::SegnoData outSegno;
outSegno.positionData = getPositionData(segno);
outSegno.colorData = getColor(segno);
outSegno.fontData = getFontData(segno);
outSegno.isColorSpecified = segno.color().has_value();
if (outSegno.isColorSpecified)
{
outSegno.colorData = getColor(segno);
}
if (segno.smufl().has_value())
{
outSegno.isSmuflSpecified = true;
outSegno.smufl = segno.smufl()->toString();
}
if (segno.id().has_value())
{
outSegno.isIdSpecified = true;
outSegno.id = segno.id()->value();
}
myOutDirectionData.segnos.emplace_back(std::move(outSegno));
appendOrderedComponent(api::DirectionComponentKind::segno,
static_cast<int>(myOutDirectionData.segnos.size()) - 1);
Expand Down Expand Up @@ -416,7 +431,22 @@ void DirectionReader::parseCoda(const core::DirectionType &directionType)
{
api::CodaData outCoda;
outCoda.positionData = getPositionData(coda);
outCoda.colorData = getColor(coda);
outCoda.fontData = getFontData(coda);
outCoda.isColorSpecified = coda.color().has_value();
if (outCoda.isColorSpecified)
{
outCoda.colorData = getColor(coda);
}
if (coda.smufl().has_value())
{
outCoda.isSmuflSpecified = true;
outCoda.smufl = coda.smufl()->toString();
}
if (coda.id().has_value())
{
outCoda.isIdSpecified = true;
outCoda.id = coda.id()->value();
}
myOutDirectionData.codas.emplace_back(std::move(outCoda));
appendOrderedComponent(api::DirectionComponentKind::coda,
static_cast<int>(myOutDirectionData.codas.size()) - 1);
Expand Down
46 changes: 46 additions & 0 deletions src/private/mx/impl/DirectionWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "mx/core/generated/BassStep.h"
#include "mx/core/generated/BeatUnitGroup.h"
#include "mx/core/generated/Bracket.h"
#include "mx/core/generated/Coda.h"
#include "mx/core/generated/Dashes.h"
#include "mx/core/generated/Degree.h"
#include "mx/core/generated/DegreeAlter.h"
Expand Down Expand Up @@ -43,6 +44,7 @@
#include "mx/core/generated/PerMinute.h"
#include "mx/core/generated/Root.h"
#include "mx/core/generated/RootStep.h"
#include "mx/core/generated/Segno.h"
#include "mx/core/generated/Semitones.h"
#include "mx/core/generated/StartStop.h"
#include "mx/core/generated/StartStopContinue.h"
Expand Down Expand Up @@ -391,6 +393,50 @@ std::vector<core::MusicDataChoice> DirectionWriter::getDirectionLikeThings()
}
}

for (const auto &item : myDirectionData.segnos)
{
core::Segno segno{};
setAttributesFromPositionData(item.positionData, segno);
setAttributesFromFontData(item.fontData, segno);
if (item.isColorSpecified)
{
setAttributesFromColorData(item.colorData, segno);
}
if (item.isSmuflSpecified)
{
segno.setSmufl(core::SmuflSegnoGlyphName::parse(item.smufl));
}
if (item.isIdSpecified)
{
segno.setID(core::Token{item.id});
}
core::DirectionType dt{};
dt.setChoice(core::DirectionTypeChoice::segno(core::OneOrMore<core::Segno>{std::move(segno)}));
addDirectionType(std::move(dt), direction);
}

for (const auto &item : myDirectionData.codas)
{
core::Coda coda{};
setAttributesFromPositionData(item.positionData, coda);
setAttributesFromFontData(item.fontData, coda);
if (item.isColorSpecified)
{
setAttributesFromColorData(item.colorData, coda);
}
if (item.isSmuflSpecified)
{
coda.setSmufl(core::SmuflCodaGlyphName::parse(item.smufl));
}
if (item.isIdSpecified)
{
coda.setID(core::Token{item.id});
}
core::DirectionType dt{};
dt.setChoice(core::DirectionTypeChoice::coda(core::OneOrMore<core::Coda>{std::move(coda)}));
addDirectionType(std::move(dt), direction);
}

if (myIsFirstDirectionTypeAdded)
{
output.push_back(core::MusicDataChoice::direction(direction));
Expand Down
72 changes: 72 additions & 0 deletions src/private/mxtest/impl/DirectionWriterTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "mx/core/generated/DirectionType.h"
#include "mx/core/generated/MusicDataChoice.h"
#include "mx/core/generated/OctaveShift.h"
#include "mx/impl/DirectionReader.h"
#include "mx/impl/DirectionWriter.h"

#include <memory>
Expand Down Expand Up @@ -45,4 +46,75 @@ TEST(ottavaStartStop, DirectionWriter)

T_END

// Build a segno and a coda carrying the full empty-print-object-style-align attribute set plus
// smufl and id, write them with DirectionWriter, read them back with DirectionReader, and confirm
// every field survives the api -> core -> api trip.
TEST(segnoAndCodaRoundTrip, DirectionWriter)
{
api::SegnoData segno;
segno.positionData.isDefaultXSpecified = true;
segno.positionData.defaultX = 1.0;
segno.positionData.isDefaultYSpecified = true;
segno.positionData.defaultY = 2.0;
segno.positionData.isRelativeXSpecified = true;
segno.positionData.relativeX = 3.0;
segno.positionData.isRelativeYSpecified = true;
segno.positionData.relativeY = 4.0;
segno.positionData.horizontalAlignmnet = api::HorizontalAlignment::left;
segno.positionData.verticalAlignment = api::VerticalAlignment::top;
segno.fontData.fontFamily = {"Maestro"};
segno.fontData.style = api::FontStyle::italic;
segno.fontData.weight = api::FontWeight::bold;
segno.fontData.sizeType = api::FontSizeType::point;
segno.fontData.sizePoint = 18.0;
segno.isColorSpecified = true;
segno.colorData.red = 0;
segno.colorData.green = 0;
segno.colorData.blue = 0;
segno.colorData.isAlphaSpecified = true;
segno.colorData.alpha = 255;
segno.isSmuflSpecified = true;
segno.smufl = "segno";
segno.isIdSpecified = true;
segno.id = "id3";

api::CodaData coda;
coda.positionData.isDefaultXSpecified = true;
coda.positionData.defaultX = 5.0;
coda.positionData.horizontalAlignmnet = api::HorizontalAlignment::center;
coda.positionData.verticalAlignment = api::VerticalAlignment::middle;
coda.fontData.fontFamily = {"Maestro"};
coda.fontData.style = api::FontStyle::normal;
coda.fontData.weight = api::FontWeight::normal;
coda.isColorSpecified = true;
coda.colorData.red = 12;
coda.colorData.green = 34;
coda.colorData.blue = 56;
coda.isSmuflSpecified = true;
coda.smufl = "coda";
coda.isIdSpecified = true;
coda.id = "id7";

api::DirectionData directionData;
directionData.segnos.push_back(segno);
directionData.codas.push_back(coda);

Cursor cursor{1, 100};
DirectionWriter writer{directionData, cursor};
const auto mdcSet = writer.getDirectionLikeThings();
REQUIRE(mdcSet.size() >= 1);
CHECK(mdcSet.front().isDirection());
const auto &direction = mdcSet.front().asDirection();

DirectionReader reader{direction, cursor};
const auto roundTripped = reader.getDirectionData();

REQUIRE(roundTripped.segnos.size() == 1);
REQUIRE(roundTripped.codas.size() == 1);
CHECK(segno == roundTripped.segnos.front());
CHECK(coda == roundTripped.codas.front());
}

T_END

#endif
Loading