@@ -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-
13511335void BeamLayout::createBeamletSegment (Beam* item, const LayoutContext& ctx, ChordRest* cr, bool isBefore, int level)
13521336{
13531337 const double startX = BeamTremoloLayout::chordBeamAnchorX (item->ldata (), cr,
0 commit comments