Skip to content

Commit fb3de67

Browse files
authored
Merge pull request #21606 from cbjeukendrup/french_beams_refactor
Refactor stem length adjustment calculations for beams
2 parents 47cb557 + f60bfa9 commit fb3de67

File tree

2 files changed

+39
-58
lines changed

2 files changed

+39
-58
lines changed

src/engraving/rendering/dev/beamlayout.cpp

Lines changed: 38 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -990,8 +990,7 @@ void BeamLayout::createBeamSegments(Beam* item, const LayoutContext& ctx, const
990990
int level = 0;
991991
constexpr size_t noLastChord = std::numeric_limits<size_t>::max();
992992
size_t numCr = chordRests.size();
993-
bool shortStems = ctx.conf().styleB(Sid::frenchStyleBeams);
994-
std::set<ChordRest*> stemShortenedCrs;
993+
bool frenchStyleBeams = ctx.conf().styleB(Sid::frenchStyleBeams);
995994
do {
996995
levelHasBeam = false;
997996
ChordRest* startCr = nullptr;
@@ -1064,11 +1063,7 @@ void BeamLayout::createBeamSegments(Beam* item, const LayoutContext& ctx, const
10641063
previousBreak32);
10651064
createBeamletSegment(item, ctx, toChord(startCr), isBeamletBefore, level);
10661065
} else {
1067-
createBeamSegment(item, startCr, endCr, level, shortStems, stemShortenedCrs);
1068-
if (shortStems) {
1069-
stemShortenedCrs.insert(startCr);
1070-
stemShortenedCrs.insert(endCr);
1071-
}
1066+
createBeamSegment(item, startCr, endCr, level, frenchStyleBeams);
10721067
}
10731068
}
10741069
bool setCr = chordRest && chordRest->isChord() && breakBeam && level < chordRest->beams();
@@ -1089,11 +1084,7 @@ void BeamLayout::createBeamSegments(Beam* item, const LayoutContext& ctx, const
10891084
bool isBefore = !(startCr == chordRests.front());
10901085
createBeamletSegment(item, ctx, toChord(startCr), isBefore, level);
10911086
} else {
1092-
createBeamSegment(item, startCr, endCr, level, shortStems, stemShortenedCrs);
1093-
if (shortStems) {
1094-
stemShortenedCrs.insert(startCr);
1095-
stemShortenedCrs.insert(endCr);
1096-
}
1087+
createBeamSegment(item, startCr, endCr, level, frenchStyleBeams);
10971088
}
10981089
}
10991090
level++;
@@ -1187,8 +1178,25 @@ bool BeamLayout::calcIsBeamletBefore(const Beam* item, Chord* chord, int i, int
11871178
return false;
11881179
}
11891180

1190-
void BeamLayout::createBeamSegment(Beam* item, ChordRest* startCr, ChordRest* endCr, int level, bool shortStems,
1191-
std::set<ChordRest*>& stemShortenedCrs)
1181+
static inline int computeStemLengthAdjustmentSteps(const ChordRest* cr, bool isStartOrEnd, bool isAbove, bool frenchStyleBeams,
1182+
int level, int beamsAbove, int beamsBelow)
1183+
{
1184+
if (isAbove == cr->up()) { // beam segment on opposite side
1185+
if (!frenchStyleBeams || isStartOrEnd) {
1186+
// lengthen
1187+
return level - (isAbove ? beamsBelow : beamsAbove);
1188+
}
1189+
} else { // beamlet on the note side
1190+
if (frenchStyleBeams && !isStartOrEnd) {
1191+
// shorten
1192+
return (isAbove ? beamsBelow : beamsAbove) - level;
1193+
}
1194+
}
1195+
1196+
return 0;
1197+
}
1198+
1199+
void BeamLayout::createBeamSegment(Beam* item, ChordRest* startCr, ChordRest* endCr, int level, bool frenchStyleBeams)
11921200
{
11931201
const bool isFirstSubgroup = startCr == item->elements().front();
11941202
const bool isLastSubgroup = endCr == item->elements().back();
@@ -1299,55 +1307,31 @@ void BeamLayout::createBeamSegment(Beam* item, ChordRest* startCr, ChordRest* en
12991307
continue;
13001308
}
13011309

1302-
double addition = 0.0;
1303-
1304-
if (level > 0) {
1305-
double grow = item->growLeft();
1306-
if (!RealIsEqual(item->growLeft(), item->growRight())) {
1307-
double anchorX = BeamTremoloLayout::chordBeamAnchorX(item->ldata(), chord, ChordBeamAnchorType::Middle);
1308-
double proportionAlongX = (anchorX - item->startAnchor().x()) / (item->endAnchor().x() - item->startAnchor().x());
1309-
grow = proportionAlongX * (item->growRight() - item->growLeft()) + item->growLeft();
1310-
}
1310+
if (level == 0) {
1311+
BeamTremoloLayout::extendStem(item->ldata(), chord, 0.0);
1312+
} else {
1313+
int stemLengthAdjustmentSteps = computeStemLengthAdjustmentSteps(cr, cr == startCr || cr == endCr, b->above, frenchStyleBeams,
1314+
level, beamsAbove, beamsBelow);
1315+
if (stemLengthAdjustmentSteps != 0) {
1316+
double grow = item->growLeft();
1317+
if (!RealIsEqual(item->growLeft(), item->growRight())) {
1318+
double anchorX = BeamTremoloLayout::chordBeamAnchorX(item->ldata(), chord, ChordBeamAnchorType::Middle);
1319+
double proportionAlongX = (anchorX - item->startAnchor().x()) / (item->endAnchor().x() - item->startAnchor().x());
1320+
grow = proportionAlongX * (item->growRight() - item->growLeft()) + item->growLeft();
1321+
}
13111322

1312-
int extraBeamAdjust = cr->up() ? beamsBelow : beamsAbove;
1313-
int stemShortenFactor = shortStems ? computeStemShortenAmount(cr, item, b, level, startCr, endCr, stemShortenedCrs) : 0;
1314-
addition = grow * (level - extraBeamAdjust - stemShortenFactor) * item->beamDist();
1315-
}
1323+
double stemLengthAdjustment = grow * stemLengthAdjustmentSteps * item->beamDist();
13161324

1317-
if (level == 0 || !RealIsEqual(addition, 0.0)) {
1318-
BeamTremoloLayout::extendStem(item->ldata(), chord, addition);
1325+
BeamTremoloLayout::extendStem(item->ldata(), chord, stemLengthAdjustment);
1326+
}
13191327
}
13201328

1321-
if (chord == endCr) {
1329+
if (cr == endCr) {
13221330
break;
13231331
}
13241332
}
13251333
}
13261334

1327-
int BeamLayout::computeStemShortenAmount(ChordRest* cr, const Beam* beam, const BeamSegment* beamSegment, int level,
1328-
const ChordRest* startCr, const ChordRest* endCr,
1329-
std::set<ChordRest*>& stemShortenedCrs)
1330-
{
1331-
if (cr == beam->elements().front() || cr == beam->elements().back()) {
1332-
// Don't shorten stems at the start or end of the beam.
1333-
return 0;
1334-
}
1335-
if (cr == startCr || cr == endCr) {
1336-
if (beamSegment->above == cr->up()) {
1337-
// When the BeamSegment and chord are on opposite sides of the base beam,
1338-
// draw the stem to the tip of the beam (don't shorten the stem).
1339-
return 0;
1340-
}
1341-
// Stems are progressively shortened as the level of the BeamSegment increases.
1342-
// Stems at the start or end of a BeamSegment shouldn't further be shortened.
1343-
if (!mu::contains(stemShortenedCrs, cr)) {
1344-
return level - 1;
1345-
}
1346-
return 0;
1347-
}
1348-
return level;
1349-
}
1350-
13511335
void BeamLayout::createBeamletSegment(Beam* item, const LayoutContext& ctx, ChordRest* cr, bool isBefore, int level)
13521336
{
13531337
const double startX = BeamTremoloLayout::chordBeamAnchorX(item->ldata(), cr,

src/engraving/rendering/dev/beamlayout.h

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,10 +68,7 @@ class BeamLayout
6868

6969
static void createBeamSegments(Beam* item, const LayoutContext& ctx, const std::vector<ChordRest*>& chordRests);
7070
static bool calcIsBeamletBefore(const Beam* item, Chord* chord, int i, int level, bool isAfter32Break, bool isAfter64Break);
71-
static void createBeamSegment(Beam* item, ChordRest* startChord, ChordRest* endChord, int level, bool shortStems,
72-
std::set<ChordRest*>& stemShortenedCrs);
73-
static int computeStemShortenAmount(ChordRest* cr, const Beam* beam, const BeamSegment* beamSegment, int level,
74-
const ChordRest* startCr, const ChordRest* endCr, std::set<ChordRest*>& stemShortenedCrs);
71+
static void createBeamSegment(Beam* item, ChordRest* startChord, ChordRest* endChord, int level, bool shortStems);
7572
static void createBeamletSegment(Beam* item, const LayoutContext& ctx, ChordRest* chord, bool isBefore, int level);
7673

7774
static bool computeUpForMovedCross(Beam* item);

0 commit comments

Comments
 (0)