Skip to content

Commit

Permalink
Correct horizontal spacing of big time signatures with hidden staves
Browse files Browse the repository at this point in the history
  • Loading branch information
mike-spa committed Feb 4, 2025
1 parent 97b0957 commit 53ef8fb
Show file tree
Hide file tree
Showing 9 changed files with 85 additions and 56 deletions.
3 changes: 3 additions & 0 deletions src/engraving/rendering/score/autoplace.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,9 @@ void Autoplace::autoplaceSegmentElement(const EngravingItem* item, EngravingItem
});

if (filteredSkyline.elements().empty()) {
if (add && item->addToSkyline()) {
staffSkyline.add(shape);
}
return;
}

Expand Down
45 changes: 1 addition & 44 deletions src/engraving/rendering/score/horizontalspacing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1033,8 +1033,6 @@ double HorizontalSpacing::minHorizontalDistance(const Segment* f, const Segment*
&& (ns->measure()->isFirstInSystem() || ns->measure()->prev()->isHBox())
&& (ns->isStartRepeatBarLineType() || ns->isChordRestType() || (ns->isClefType() && !ns->header()));

bool mustClearCollisionsOnAllStaves = ns->hasTimeSigAcrossStaves();

double ww = -DBL_MAX; // can remain negative
double d = 0.0;
Score* score = f->score();
Expand All @@ -1046,14 +1044,7 @@ double HorizontalSpacing::minHorizontalDistance(const Segment* f, const Segment*
const Shape& fshape = f->staffShape(staffIdx);
double sp = shapeSpatium(fshape);
d = minHorizontalDistance(fshape, ns->staffShape(staffIdx), sp, squeezeFactor);
if (mustClearCollisionsOnAllStaves) {
for (unsigned staffIdx2 = 0; staffIdx2 < f->shapes().size(); ++staffIdx2) {
if (score->staff(staffIdx2) && !score->staff(staffIdx2)->show()) {
continue;
}
d = std::max(d, minHorizontalDistance(fshape, ns->staffShape(staffIdx2), sp, squeezeFactor));
}
} else if (systemHeaderGap) {
if (systemHeaderGap) {
// first chordrest of a staff should clear the widest header for any staff
// so make sure segment is as wide as it needs to be
d = std::max(d, f->staffShape(staffIdx).right());
Expand Down Expand Up @@ -1321,40 +1312,6 @@ double HorizontalSpacing::computeVerticalClearance(const EngravingItem* item1, c
return 0.2 * spatium;
}

void HorizontalSpacing::centerTimeSigIfNeeded(System* system)
{
const MStyle& style = system->style();
if (!(style.styleV(Sid::timeSigPlacement).value<TimeSigPlacement>() == TimeSigPlacement::ABOVE_STAVES
&& style.styleB(Sid::timeSigCenterOnBarline))) {
return;
}

for (Measure* measure = system->firstMeasure(); measure; measure = measure->nextMeasure()) {
for (Segment& seg : measure->segments()) {
if (!seg.isType(SegmentType::TimeSig | SegmentType::TimeSigAnnounce)) {
continue;
}
Segment* prevBarlineSeg = nullptr;
for (Segment* prevSeg = seg.prev1(); prevSeg && prevSeg->tick() == seg.tick(); prevSeg = prevSeg->prev1()) {
if (prevSeg->isEndBarLineType()) {
prevBarlineSeg = prevSeg;
break;
}
}
if (prevBarlineSeg && prevBarlineSeg->system() == system) {
for (EngravingItem* timeSig : seg.elist()) {
if (!timeSig) {
continue;
}
RectF bbox = timeSig->ldata()->bbox();
timeSig->mutldata()->setPosX(-0.5 * (bbox.right() + bbox.left()));
}
seg.createShapes();
}
}
}
}

bool HorizontalSpacing::isSameVoiceKerningLimited(const EngravingItem* item)
{
ElementType type = item->type();
Expand Down
1 change: 0 additions & 1 deletion src/engraving/rendering/score/horizontalspacing.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ class HorizontalSpacing
static double computePadding(const EngravingItem* item1, const EngravingItem* item2);
static KerningType computeKerning(const EngravingItem* item1, const EngravingItem* item2);
static double computeVerticalClearance(const EngravingItem* item1, const EngravingItem* item2, double spatium);
static void centerTimeSigIfNeeded(System* system);

private:
struct HorizontalSpacingContext {
Expand Down
83 changes: 76 additions & 7 deletions src/engraving/rendering/score/systemlayout.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -353,7 +353,8 @@ System* SystemLayout::collectSystem(LayoutContext& ctx)
}
}

HorizontalSpacing::centerTimeSigIfNeeded(system);
updateBigTimeSigIfNeeded(system, ctx);

// Recompute spacing to account for the last changes (barlines, hidden staves, etc)
curSysWidth = HorizontalSpacing::computeSpacingForFullSystem(system);

Expand Down Expand Up @@ -598,6 +599,74 @@ void SystemLayout::hideEmptyStaves(System* system, LayoutContext& ctx, bool isFi
}
}

void SystemLayout::updateBigTimeSigIfNeeded(System* system, LayoutContext& ctx)
{
if (ctx.conf().styleV(Sid::timeSigPlacement).value<TimeSigPlacement>() != TimeSigPlacement::ABOVE_STAVES) {
return;
}

staff_idx_t nstaves = ctx.dom().nstaves();
bool centerOnBarline = ctx.conf().styleB(Sid::timeSigCenterOnBarline);

for (Measure* measure = system->firstMeasure(); measure; measure = measure->nextMeasure()) {
for (Segment& seg : measure->segments()) {
if (!seg.isType(SegmentType::TimeSig | SegmentType::TimeSigAnnounce)) {
continue;
}

std::set<TimeSig*> timeSigToKeep;
for (staff_idx_t staffIdx = 0; staffIdx < nstaves; ++staffIdx) {
TimeSig* timeSig = toTimeSig(seg.element(staff2track(staffIdx)));
if (!timeSig || !timeSig->showOnThisStaff()) {
continue;
}

timeSigToKeep.insert(timeSig);
if (system->staff(staffIdx)->show()) {
continue;
}

staff_idx_t nextVisStaff = system->nextVisibleStaff(staffIdx);
if (nextVisStaff == muse::nidx) {
continue;
}

TimeSig* nextVisTimeSig = toTimeSig(seg.element(staff2track(nextVisStaff)));
if (nextVisTimeSig) {
timeSigToKeep.insert(nextVisTimeSig);
}
}

Segment* prevBarlineSeg = nullptr;
if (centerOnBarline) {
for (Segment* prevSeg = seg.prev1(); prevSeg && prevSeg->tick() == seg.tick(); prevSeg = prevSeg->prev1()) {
if (prevSeg->isEndBarLineType()) {
prevBarlineSeg = prevSeg;
break;
}
}
}

for (staff_idx_t staffIdx = 0; staffIdx < nstaves; ++staffIdx) {
TimeSig* timeSig = toTimeSig(seg.element(staff2track(staffIdx)));
if (!timeSig) {
continue;
}
if (!muse::contains(timeSigToKeep, timeSig)) {
timeSig->mutldata()->reset(); // Eliminates the shape
continue;
}
if (prevBarlineSeg && prevBarlineSeg->system() == system) {
RectF bbox = timeSig->ldata()->bbox();
timeSig->mutldata()->setPosX(-0.5 * (bbox.right() + bbox.left()));
}
}

seg.createShapes();
}
}
}

void SystemLayout::layoutSystemElements(System* system, LayoutContext& ctx)
{
if (ctx.dom().nstaves() == 0) {
Expand Down Expand Up @@ -706,7 +775,7 @@ void SystemLayout::layoutSystemElements(System* system, LayoutContext& ctx)
}
} else if (s.isType(SegmentType::TimeSig | SegmentType::TimeSigAnnounce)) {
TimeSig* ts = toTimeSig(s.element(staffIdx * VOICES));
if (ts && ts->addToSkyline()) {
if (ts && ts->addToSkyline() && ts->showOnThisStaff()) {
TimeSigPlacement timeSigPlacement = ts->style().styleV(Sid::timeSigPlacement).value<TimeSigPlacement>();
if (timeSigPlacement != TimeSigPlacement::ACROSS_STAVES) {
skyline.add(ts->shape().translate(ts->pos() + p + ts->staffOffset()));
Expand Down Expand Up @@ -1301,7 +1370,7 @@ void SystemLayout::layoutSystemElements(System* system, LayoutContext& ctx)
for (Segment& s : toMeasure(mb)->segments()) {
if (s.isType(SegmentType::TimeSig | SegmentType::TimeSigAnnounce)) {
for (EngravingItem* timeSig : s.elist()) {
if (timeSig && timeSig->ldata()->isValid()) {
if (timeSig && toTimeSig(timeSig)->showOnThisStaff()) {
Autoplace::autoplaceSegmentElement(timeSig, timeSig->mutldata());
}
}
Expand Down Expand Up @@ -2676,15 +2745,15 @@ void SystemLayout::centerBigTimeSigsAcrossStaves(const System* system)
continue;
}
for (staff_idx_t staffIdx = 0; staffIdx < nstaves; ++staffIdx) {
EngravingItem* timeSig = segment.element(staff2track(staffIdx));
if (!timeSig || !timeSig->ldata()->isValid()) {
TimeSig* timeSig = toTimeSig(segment.element(staff2track(staffIdx)));
if (!timeSig || !timeSig->showOnThisStaff()) {
continue;
}
staff_idx_t thisStaffIdx = timeSig->staffIdxOrNextVisible();
staff_idx_t nextStaffIdx = thisStaffIdx;
for (staff_idx_t idx = thisStaffIdx + 1; idx < nstaves; ++idx) {
EngravingItem* nextTimeSig = segment.element(staff2track(idx));
if (nextTimeSig && nextTimeSig->ldata()->isValid()) {
TimeSig* nextTimeSig = toTimeSig(segment.element(staff2track(idx)));
if (nextTimeSig && nextTimeSig->showOnThisStaff()) {
staff_idx_t nextTimeSigStave = nextTimeSig->staffIdxOrNextVisible();
nextStaffIdx = system->prevVisibleStaff(nextTimeSigStave);
break;
Expand Down
2 changes: 2 additions & 0 deletions src/engraving/rendering/score/systemlayout.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,8 @@ class SystemLayout
static void centerMMRestBetweenStaves(MMRest* mmRest, const System* system);

static bool shouldBeJustified(System* system, double curSysWidth, double targetSystemWidth, LayoutContext& ctx);

static void updateBigTimeSigIfNeeded(System* system, LayoutContext& ctx);
};
}

Expand Down
3 changes: 3 additions & 0 deletions src/engraving/rendering/score/tdraw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3106,6 +3106,9 @@ void TDraw::draw(const TimeSig* item, Painter* painter)
if (item->staff() && !const_cast<const Staff*>(item->staff())->staffType(item->tick())->genTimesig()) {
return;
}
if (!item->showOnThisStaff()) {
return;
}
painter->setPen(item->curColor());

const TimeSig::LayoutData* ldata = item->ldata();
Expand Down
4 changes: 0 additions & 4 deletions src/engraving/rendering/score/tlayout.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6264,10 +6264,6 @@ void TLayout::layoutTimeSig(const TimeSig* item, TimeSig::LayoutData* ldata, con
ldata->pn = PointF();
ldata->pointLargeRightParen = PointF();

if (!item->showOnThisStaff()) {
return;
}

const MStyle& style = item->style();
TimeSigPlacement timeSigPlacement = style.styleV(Sid::timeSigPlacement).value<TimeSigPlacement>();
if (timeSigPlacement == TimeSigPlacement::NORMAL) {
Expand Down
Binary file added vtest/scores/bigTimeSig-5.mscz
Binary file not shown.
Binary file added vtest/scores/bigTimeSig-6.mscz
Binary file not shown.

0 comments on commit 53ef8fb

Please sign in to comment.