Skip to content

Commit

Permalink
Fix cross-staff fingering layout and tidy up code
Browse files Browse the repository at this point in the history
  • Loading branch information
mike-spa committed Sep 18, 2024
1 parent de6e4d9 commit 023c08c
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 39 deletions.
113 changes: 74 additions & 39 deletions src/engraving/rendering/score/pagelayout.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -355,31 +355,6 @@ void PageLayout::collectPage(LayoutContext& ctx)
ChordLayout::computeUp(c2, ctx);
}
}
// Fingering and articulations on top of cross-staff beams must be laid out here
if (c->beam() && (c->beam()->cross() || c->staffMove() != 0)) {
ChordLayout::layoutArticulations(c, ctx);
ChordLayout::layoutArticulations2(c, ctx, true);

for (Note* note : c->notes()) {
for (EngravingItem* e : note->el()) {
if (!e || !e->isFingering()) {
continue;
}
Fingering* fingering = toFingering(e);
if (fingering->isOnCrossBeamSide()) {
TLayout::layoutFingering(fingering, fingering->mutldata());
if (fingering->addToSkyline()) {
const Note* n = fingering->note();
const RectF r
= fingering->ldata()->bbox().translated(
fingering->pos() + n->pos() + n->chord()->pos() + segment->pos()
+ segment->measure()->pos());
s->staff(fingering->note()->chord()->vStaffIdx())->skyline().add(r, fingering);
}
}
}
}
}
}
} else if (e2->isBarLine()) {
TLayout::layoutBarLine2(toBarLine(e2), ctx);
Expand Down Expand Up @@ -413,8 +388,17 @@ void PageLayout::collectPage(LayoutContext& ctx)
page->mutldata()->setBbox(0.0, 0.0, ctx.conf().loWidth(), height + ctx.state().page()->bm());
}

// HACK: we relayout here cross-staff slurs because only now the information
// about staff distances is fully available.
layoutCrossStaffElements(ctx, page);

for (const System* system : page->systems()) {
SystemLayout::centerElementsBetweenStaves(system);
}

page->invalidateBspTree();
}

void PageLayout::layoutCrossStaffElements(LayoutContext& ctx, Page* page)
{
for (System* system : page->systems()) {
if (!system->firstMeasure()) {
continue;
Expand All @@ -431,23 +415,74 @@ void PageLayout::collectPage(LayoutContext& ctx)
continue;
}

auto spanners = ctx.dom().spannerMap().findOverlapping(stick.ticks(), etick.ticks());
for (auto interval : spanners) {
Spanner* sp = interval.value;
if (!sp->isSlur() || sp->tick() == system->endTick()) {
layoutCrossStaffSlurs(ctx, system);

layoutArticAndFingeringOnCrossStaffBeams(ctx, system);
}
}

void PageLayout::layoutCrossStaffSlurs(LayoutContext& ctx, System* system)
{
Fraction stick = system->firstMeasure()->tick();
Fraction etick = system->endTick();

auto spanners = ctx.dom().spannerMap().findOverlapping(stick.ticks(), etick.ticks());
for (auto interval : spanners) {
Spanner* sp = interval.value;
if (!sp->isSlur() || sp->tick() == system->endTick()) {
continue;
}
if (toSlur(sp)->isCrossStaff()) {
SlurTieLayout::layoutSystem(toSlur(sp), system, ctx);
}
}
}

void PageLayout::layoutArticAndFingeringOnCrossStaffBeams(LayoutContext& ctx, System* system)
{
for (const MeasureBase* mb : system->measures()) {
if (!mb->isMeasure()) {
continue;
}
for (const Segment& segment : toMeasure(mb)->segments()) {
if (!segment.isChordRestType()) {
continue;
}
if (toSlur(sp)->isCrossStaff()) {
SlurTieLayout::layoutSystem(toSlur(sp), system, ctx);
for (EngravingItem* item : segment.elist()) {
if (!item || !item->isChord()) {
continue;
}

Chord* c = toChord(item);
bool hasCrossBeam = c->beam() && (c->beam()->cross() || c->staffMove() != 0);
if (!hasCrossBeam) {
continue;
}

ChordLayout::layoutArticulations(c, ctx);
ChordLayout::layoutArticulations2(c, ctx, true);

for (Note* note : c->notes()) {
for (EngravingItem* e : note->el()) {
if (!e || !e->isFingering()) {
continue;
}
Fingering* fingering = toFingering(e);
if (fingering->isOnCrossBeamSide()) {
TLayout::layoutFingering(fingering, fingering->mutldata());
if (fingering->addToSkyline()) {
const Note* n = fingering->note();
const RectF r = fingering->ldata()->bbox().translated(
fingering->pos() + n->pos() + n->chord()->pos() + segment.pos()
+ segment.measure()->pos());
system->staff(fingering->note()->chord()->vStaffIdx())->skyline().add(r, fingering);
}
}
}
}
}
}
}

for (const System* system : page->systems()) {
SystemLayout::centerElementsBetweenStaves(system);
}

page->invalidateBspTree();
}

//---------------------------------------------------------
Expand Down
4 changes: 4 additions & 0 deletions src/engraving/rendering/score/pagelayout.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ class PageLayout
static void layoutPage(LayoutContext& ctx, Page* page, double restHeight, double footerPadding);
static void checkDivider(LayoutContext& ctx, bool left, System* s, double yOffset, bool remove = false);
static void distributeStaves(LayoutContext& ctx, Page* page, double footerPadding);

static void layoutCrossStaffElements(LayoutContext& ctx, Page* page);
static void layoutCrossStaffSlurs(LayoutContext& ctx, System* system);
static void layoutArticAndFingeringOnCrossStaffBeams(LayoutContext& ctx, System* system);
};
}

Expand Down

0 comments on commit 023c08c

Please sign in to comment.