|
19 | 19 | #include "expansion.h" |
20 | 20 | #include "lem.h" |
21 | 21 | #include "linkinginterface.h" |
| 22 | +#include "measure.h" |
22 | 23 | #include "plistinterface.h" |
23 | 24 | #include "rdg.h" |
| 25 | +#include "score.h" |
24 | 26 | #include "section.h" |
25 | 27 | #include "timeinterface.h" |
26 | 28 | #include "vrv.h" |
@@ -362,4 +364,111 @@ void ExpansionMap::ToJson(std::string &output) |
362 | 364 | output = expansionmap.json(); |
363 | 365 | } |
364 | 366 |
|
| 367 | +void ExpansionMap::GenerateExpansionFor(Score *score) |
| 368 | +{ |
| 369 | + if (score->FindDescendantByType(EXPANSION)) { |
| 370 | + LogWarning("An expansion cannot be generated if one is already encoded"); |
| 371 | + return; |
| 372 | + } |
| 373 | + |
| 374 | + if (score->HasEditorialContent()) { |
| 375 | + LogWarning("An expansion cannot be generated with editorial content"); |
| 376 | + return; |
| 377 | + } |
| 378 | + |
| 379 | + if (score->FindAllDescendantsByType(SECTION).size() > 1) { |
| 380 | + LogWarning("An expansion cannot be generated with more than one section"); |
| 381 | + return; |
| 382 | + } |
| 383 | + |
| 384 | + Section *section = vrv_cast<Section *>(score->FindDescendantByType(SECTION, 1)); |
| 385 | + assert(section); |
| 386 | + |
| 387 | + ArrayOfObjects childrenArray = section->GetChildrenForModification(); |
| 388 | + ListOfObjects children(childrenArray.begin(), childrenArray.end()); |
| 389 | + |
| 390 | + Expansion *expansion = new Expansion(); |
| 391 | + section->InsertChild(expansion, 0); |
| 392 | + |
| 393 | + ListOfObjects::iterator first = children.begin(); |
| 394 | + ListOfObjects::iterator last = children.begin(); |
| 395 | + |
| 396 | + bool isStartFromPrevious = false; |
| 397 | + |
| 398 | + for (auto current = children.begin(); current != children.end(); current++) { |
| 399 | + if ((*current)->Is(MEASURE)) { |
| 400 | + Measure *measure = vrv_cast<Measure *>(*current); |
| 401 | + // The current measure has a repeat end on its left |
| 402 | + if (ExpansionMap::IsPreviousRepeatEnd(measure)) { |
| 403 | + std::string ref = "#" + this->CreateSection(section, first, last); |
| 404 | + expansion->GetPlistInterface()->AddRefAllowDuplicate(ref); |
| 405 | + expansion->GetPlistInterface()->AddRefAllowDuplicate(ref); |
| 406 | + } |
| 407 | + if (isStartFromPrevious || ExpansionMap::IsRepeatStart(measure)) { |
| 408 | + first = current; |
| 409 | + } |
| 410 | + // The current measure has a repeat start on its right |
| 411 | + isStartFromPrevious = ExpansionMap::IsNextRepeatStart(measure); |
| 412 | + last = current; |
| 413 | + if (ExpansionMap::IsRepeatEnd(measure)) { |
| 414 | + std::string ref = "#" + this->CreateSection(section, first, last); |
| 415 | + expansion->GetPlistInterface()->AddRefAllowDuplicate(ref); |
| 416 | + expansion->GetPlistInterface()->AddRefAllowDuplicate(ref); |
| 417 | + } |
| 418 | + } |
| 419 | + } |
| 420 | +} |
| 421 | + |
| 422 | +std::string ExpansionMap::CreateSection( |
| 423 | + Section *section, const ListOfObjects::iterator &first, const ListOfObjects::iterator &last) |
| 424 | +{ |
| 425 | + Section *subSection = new Section(); |
| 426 | + section->InsertBefore(*first, subSection); |
| 427 | + for (auto sectionCurrent = first; sectionCurrent != std::next(last); sectionCurrent++) { |
| 428 | + section->DetachChild((*sectionCurrent)->GetIdx()); |
| 429 | + subSection->AddChild(*sectionCurrent); |
| 430 | + } |
| 431 | + return subSection->GetID(); |
| 432 | +} |
| 433 | + |
| 434 | +//---------------------------------------------------------------------------- |
| 435 | +// Static methods |
| 436 | +//---------------------------------------------------------------------------- |
| 437 | + |
| 438 | +bool ExpansionMap::IsRepeatStart(Measure *measure) |
| 439 | +{ |
| 440 | + static const std::vector<data_BARRENDITION> match{ BARRENDITION_rptboth, BARRENDITION_rptstart }; |
| 441 | + |
| 442 | + if (!measure->HasLeft()) return false; |
| 443 | + |
| 444 | + return (std::find(match.begin(), match.end(), measure->GetLeft()) != match.end()); |
| 445 | +} |
| 446 | + |
| 447 | +bool ExpansionMap::IsRepeatEnd(Measure *measure) |
| 448 | +{ |
| 449 | + static const std::vector<data_BARRENDITION> match{ BARRENDITION_rptboth, BARRENDITION_rptend }; |
| 450 | + |
| 451 | + if (!measure->HasRight()) return false; |
| 452 | + |
| 453 | + return (std::find(match.begin(), match.end(), measure->GetRight()) != match.end()); |
| 454 | +} |
| 455 | + |
| 456 | +bool ExpansionMap::IsNextRepeatStart(Measure *measure) |
| 457 | +{ |
| 458 | + static const std::vector<data_BARRENDITION> match{ BARRENDITION_rptboth, BARRENDITION_rptstart }; |
| 459 | + |
| 460 | + if (!measure->HasRight()) return false; |
| 461 | + |
| 462 | + return (std::find(match.begin(), match.end(), measure->GetRight()) != match.end()); |
| 463 | +} |
| 464 | + |
| 465 | +bool ExpansionMap::IsPreviousRepeatEnd(Measure *measure) |
| 466 | +{ |
| 467 | + static const std::vector<data_BARRENDITION> match{ BARRENDITION_rptboth, BARRENDITION_rptend }; |
| 468 | + |
| 469 | + if (!measure->HasLeft()) return false; |
| 470 | + |
| 471 | + return (std::find(match.begin(), match.end(), measure->GetLeft()) != match.end()); |
| 472 | +} |
| 473 | + |
365 | 474 | } // namespace vrv |
0 commit comments