From 16e96903ac6f8b489078553da94d1c77c51268eb Mon Sep 17 00:00:00 2001 From: Michele Spagnolo Date: Thu, 6 Feb 2025 14:11:57 +0100 Subject: [PATCH 1/6] Fix code error --- src/engraving/rendering/score/horizontalspacing.cpp | 2 +- src/engraving/rendering/score/horizontalspacing.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/engraving/rendering/score/horizontalspacing.cpp b/src/engraving/rendering/score/horizontalspacing.cpp index f87eb5dbd2666..c78cb9e63613a 100644 --- a/src/engraving/rendering/score/horizontalspacing.cpp +++ b/src/engraving/rendering/score/horizontalspacing.cpp @@ -239,7 +239,7 @@ void HorizontalSpacing::spaceMeasureGroup(const std::vector& measureGr ctx.xCur = lastMeas->x() + lastMeas->width(); } -std::vector HorizontalSpacing::spaceSegments(const std::vector segList, int startSegIdx, +std::vector HorizontalSpacing::spaceSegments(const std::vector& segList, int startSegIdx, HorizontalSpacingContext& ctx) { std::vector placedSegments; diff --git a/src/engraving/rendering/score/horizontalspacing.h b/src/engraving/rendering/score/horizontalspacing.h index c9743ac7ec345..2077fca2ccf91 100644 --- a/src/engraving/rendering/score/horizontalspacing.h +++ b/src/engraving/rendering/score/horizontalspacing.h @@ -99,7 +99,7 @@ class HorizontalSpacing static void spaceMeasureGroup(const std::vector& measureGroup, HorizontalSpacingContext& ctx); static double getFirstSegmentXPos(Segment* segment, HorizontalSpacingContext& ctx); - static std::vector spaceSegments(const std::vector segList, int startSegIdx, HorizontalSpacingContext& ctx); + static std::vector spaceSegments(const std::vector& segList, int startSegIdx, HorizontalSpacingContext& ctx); static bool ignoreSegmentForSpacing(const Segment* segment); static bool ignoreAllSegmentsForSpacing(const std::vector& segmentPositions); static void spaceAgainstPreviousSegments(Segment* segment, std::vector& prevSegPositions, From a3740a9f5ed612131894977cfff296c99465bc7d Mon Sep 17 00:00:00 2001 From: Michele Spagnolo Date: Thu, 6 Feb 2025 11:25:42 +0100 Subject: [PATCH 2/6] Ignore full measure rests --- .../rendering/score/horizontalspacing.cpp | 14 ++++++++++++++ src/engraving/rendering/score/horizontalspacing.h | 1 + 2 files changed, 15 insertions(+) diff --git a/src/engraving/rendering/score/horizontalspacing.cpp b/src/engraving/rendering/score/horizontalspacing.cpp index c78cb9e63613a..6d940256451c5 100644 --- a/src/engraving/rendering/score/horizontalspacing.cpp +++ b/src/engraving/rendering/score/horizontalspacing.cpp @@ -1354,6 +1354,10 @@ void HorizontalSpacing::computeLyricsPadding(const Lyrics* lyrics1, const Engrav KerningType HorizontalSpacing::computeKerning(const EngravingItem* item1, const EngravingItem* item2) { + if (ignoreItems(item1, item2)) { + return KerningType::ALLOW_COLLISION; + } + if (isSameVoiceKerningLimited(item1) && isSameVoiceKerningLimited(item2) && item1->track() == item2->track()) { return KerningType::NON_KERNING; } @@ -1420,6 +1424,16 @@ bool HorizontalSpacing::isAlwaysKernable(const EngravingItem* item) return item->isTextBase() || item->isChordLine() || item->isParenthesis(); } +bool HorizontalSpacing::ignoreItems(const EngravingItem* item1, const EngravingItem* item2) +{ + if (item1->isRest() && toRest(item1)->isFullMeasureRest()) { + // Full-measure rest must ignore cross-stave notes + return item1->staffIdx() != item2->staffIdx(); + } + + return false; +} + KerningType HorizontalSpacing::doComputeKerningType(const EngravingItem* item1, const EngravingItem* item2) { ElementType type1 = item1->type(); diff --git a/src/engraving/rendering/score/horizontalspacing.h b/src/engraving/rendering/score/horizontalspacing.h index 2077fca2ccf91..f8f57049cd487 100644 --- a/src/engraving/rendering/score/horizontalspacing.h +++ b/src/engraving/rendering/score/horizontalspacing.h @@ -137,6 +137,7 @@ class HorizontalSpacing static bool isSameVoiceKerningLimited(const EngravingItem* item); static bool isNeverKernable(const EngravingItem* item); static bool isAlwaysKernable(const EngravingItem* item); + static bool ignoreItems(const EngravingItem* item1, const EngravingItem* item2); static KerningType doComputeKerningType(const EngravingItem* item1, const EngravingItem* item2); static KerningType computeNoteKerningType(const Note* note, const EngravingItem* item2); From 257e8b531d58156eb43945c52c1243ecc7d2b80f Mon Sep 17 00:00:00 2001 From: Michele Spagnolo Date: Thu, 6 Feb 2025 17:26:20 +0100 Subject: [PATCH 3/6] Improved spacing of cross-staff beams in narrow situations --- .../rendering/score/horizontalspacing.cpp | 61 +++++++++++++++---- .../rendering/score/horizontalspacing.h | 13 ++-- 2 files changed, 54 insertions(+), 20 deletions(-) diff --git a/src/engraving/rendering/score/horizontalspacing.cpp b/src/engraving/rendering/score/horizontalspacing.cpp index 6d940256451c5..f204947d61bf9 100644 --- a/src/engraving/rendering/score/horizontalspacing.cpp +++ b/src/engraving/rendering/score/horizontalspacing.cpp @@ -725,37 +725,76 @@ bool HorizontalSpacing::needsCueSizeSpacing(const Segment* segment) void HorizontalSpacing::applyCrossBeamSpacingCorrection(Segment* thisSeg, Segment* nextSeg, double& width) { - Measure* m = thisSeg->measure(); - CrossBeamType crossBeamType = computeCrossBeamType(thisSeg, nextSeg); + CrossBeamSpacing crossBeamSpacing = computeCrossBeamSpacing(thisSeg, nextSeg); - double displacement = m->score()->noteHeadWidth() - m->score()->style().styleMM(Sid::stemWidth); - if (crossBeamType.upDown && crossBeamType.canBeAdjusted) { + const Score* score = thisSeg->score(); + const PaddingTable& paddingTable = score->paddingTable(); + const MStyle& style = score->style(); + + double displacement = score->noteHeadWidth() - style.styleMM(Sid::stemWidth); + + if (crossBeamSpacing.upDown && crossBeamSpacing.canBeAdjusted) { thisSeg->addWidthOffset(displacement); width += displacement; - } else if (crossBeamType.downUp && crossBeamType.canBeAdjusted) { + } else if (crossBeamSpacing.downUp && crossBeamSpacing.canBeAdjusted) { thisSeg->addWidthOffset(-displacement); width -= displacement; } - if (crossBeamType.upDown) { - if (crossBeamType.hasOpposingBeamlets) { - double minBeamletClearance = m->style().styleMM(Sid::beamMinLen) * 2.0 - + m->score()->paddingTable().at(ElementType::BEAM).at(ElementType::BEAM); + if (crossBeamSpacing.upDown) { + if (crossBeamSpacing.hasOpposingBeamlets) { + double minBeamletClearance = style.styleMM(Sid::beamMinLen) * 2.0 + paddingTable.at(ElementType::BEAM).at(ElementType::BEAM); width = std::max(width, displacement + minBeamletClearance); } else { width = std::max(width, 2 * displacement); } } + + if (crossBeamSpacing.preventCrossStaffKerning) { + double padding = crossBeamSpacing.ensureMinStemDistance ? paddingTable.at(ElementType::STEM).at(ElementType::STEM) + : style.styleMM(Sid::minNoteDistance); + width = std::max(width, score->noteHeadWidth() + padding); + } else if (crossBeamSpacing.ensureMinStemDistance) { + width = std::max(width, score->paddingTable().at(ElementType::STEM).at(ElementType::STEM)); + } } -HorizontalSpacing::CrossBeamType HorizontalSpacing::computeCrossBeamType(Segment* thisSeg, Segment* nextSeg) +HorizontalSpacing::CrossBeamSpacing HorizontalSpacing::computeCrossBeamSpacing(Segment* thisSeg, Segment* nextSeg) { - CrossBeamType crossBeamType; + CrossBeamSpacing crossBeamType; if (!thisSeg->isChordRestType() || !nextSeg || !nextSeg->isChordRestType()) { return crossBeamType; } + bool preventCrossStaffKerning = false; + bool ensureMinStemDistance = false; + for (EngravingItem* e : thisSeg->elist()) { + if (!e || !e->isChord() || !e->visible() || !e->staff()->visible()) { + continue; + } + + Chord* thisChord = toChord(e); + ChordRest* nextCR = toChordRest(nextSeg->element(thisChord->track())); + Chord* nextChord = nextCR && nextCR->isChord() ? toChord(nextCR) : nullptr; + if (!nextChord) { + continue; + } + + int thisStaffMove = thisChord->staffMove(); + int nextStaffMove = nextChord->staffMove(); + if (thisStaffMove == nextStaffMove) { + continue; + } + + preventCrossStaffKerning = thisStaffMove > nextStaffMove; + ensureMinStemDistance = (thisStaffMove > nextStaffMove && thisChord->up() && !nextChord->up()) + || (thisStaffMove < nextStaffMove && thisChord->up() == nextChord->up()); + } + + crossBeamType.preventCrossStaffKerning = preventCrossStaffKerning; + crossBeamType.ensureMinStemDistance = ensureMinStemDistance; + bool upDown = false; bool downUp = false; bool canBeAdjusted = true; diff --git a/src/engraving/rendering/score/horizontalspacing.h b/src/engraving/rendering/score/horizontalspacing.h index f8f57049cd487..dda5990b784e6 100644 --- a/src/engraving/rendering/score/horizontalspacing.h +++ b/src/engraving/rendering/score/horizontalspacing.h @@ -82,19 +82,14 @@ class HorizontalSpacing : segment(s), xPosInSystemCoords(x) {} }; - struct CrossBeamType + struct CrossBeamSpacing { bool upDown = false; bool downUp = false; bool canBeAdjusted = true; bool hasOpposingBeamlets = false; - void reset() - { - upDown = false; - downUp = false; - canBeAdjusted = true; - hasOpposingBeamlets = false; - } + bool preventCrossStaffKerning = false; + bool ensureMinStemDistance = false; }; static void spaceMeasureGroup(const std::vector& measureGroup, HorizontalSpacingContext& ctx); @@ -118,7 +113,7 @@ class HorizontalSpacing static bool needsCueSizeSpacing(const Segment* segment); static void applyCrossBeamSpacingCorrection(Segment* thisSeg, Segment* nextSeg, double& width); - static CrossBeamType computeCrossBeamType(Segment* thisSeg, Segment* nextSeg); + static CrossBeamSpacing computeCrossBeamSpacing(Segment* thisSeg, Segment* nextSeg); static void enforceMinimumMeasureWidths(const std::vector measureGroup); static double computeMinMeasureWidth(Measure* m); From 56de4011ddee892ac8cd9c828ff64ffe12ac7b19 Mon Sep 17 00:00:00 2001 From: Michele Spagnolo Date: Thu, 6 Feb 2025 19:09:50 +0100 Subject: [PATCH 4/6] Improve collision checks on cross-staff stems --- .../rendering/score/horizontalspacing.cpp | 52 +++++++++++++++++++ .../rendering/score/horizontalspacing.h | 2 + 2 files changed, 54 insertions(+) diff --git a/src/engraving/rendering/score/horizontalspacing.cpp b/src/engraving/rendering/score/horizontalspacing.cpp index f204947d61bf9..294a47a874ec4 100644 --- a/src/engraving/rendering/score/horizontalspacing.cpp +++ b/src/engraving/rendering/score/horizontalspacing.cpp @@ -24,6 +24,7 @@ #include "horizontalspacing.h" #include "dom/barline.h" +#include "dom/beam.h" #include "dom/chord.h" #include "dom/engravingitem.h" #include "dom/glissando.h" @@ -33,6 +34,7 @@ #include "dom/score.h" #include "dom/stemslash.h" #include "dom/staff.h" +#include "dom/stem.h" #include "dom/system.h" #include "dom/tie.h" #include "dom/timesig.h" @@ -614,6 +616,52 @@ void HorizontalSpacing::moveRightAlignedSegments(std::vector& p } } +void HorizontalSpacing::checkCollisionsWithCrossStaffStems(const Segment* thisSeg, const Segment* nextSeg, staff_idx_t staffIdx, + double& curMinDist) +{ + std::vector itemsToCheck; + itemsToCheck.reserve(VOICES); + + for (EngravingItem* el : nextSeg->elist()) { + if (el && el->vStaffIdx() == staffIdx) { + ChordRest* cr = toChordRest(el); + if (cr->beam() && cr->beam()->cross()) { + itemsToCheck.push_back(toChordRest(el)); + } + } + } + + for (ChordRest* cr : itemsToCheck) { + Chord* potentialCollidingChord = nullptr; + for (ChordRest* beamElement : cr->beam()->elements()) { + if (beamElement->isChord() && beamElement->parent() == thisSeg) { + potentialCollidingChord = toChord(beamElement); + break; + } + } + + if (!potentialCollidingChord || potentialCollidingChord->up() != cr->up() || !potentialCollidingChord->stem()) { + return; + } + + bool checkStemCollision = (cr->up() && potentialCollidingChord->vStaffIdx() > cr->vStaffIdx()) + || (!cr->up() && potentialCollidingChord->vStaffIdx() < cr->vStaffIdx()); + if (!checkStemCollision) { + return; + } + + Stem* stem = potentialCollidingChord->stem(); + Shape prevStemShape = stem->shape().translated(stem->pos() + potentialCollidingChord->pos()); + prevStemShape.adjust(0.0, -10000, 0.0, 10000); + + const Shape& staffShape = nextSeg->staffShape(staffIdx); + + double minDist = minHorizontalDistance(prevStemShape, staffShape, stem->spatium()); + + curMinDist = std::max(curMinDist, minDist); + } +} + double HorizontalSpacing::chordRestSegmentNaturalWidth(Segment* segment, HorizontalSpacingContext& ctx) { double durationStretch = computeSegmentDurationStretch(segment, segment->prev(SegmentType::ChordRest)); @@ -1154,6 +1202,10 @@ double HorizontalSpacing::minHorizontalDistance(const Segment* f, const Segment* d = std::max(d, f->staffShape(staffIdx).right()); } + if (f->isChordRestType() && ns->isChordRestType()) { + checkCollisionsWithCrossStaffStems(f, ns, staffIdx, d); + } + ww = std::max(ww, d); } double w = std::max(ww, 0.0); // non-negative diff --git a/src/engraving/rendering/score/horizontalspacing.h b/src/engraving/rendering/score/horizontalspacing.h index dda5990b784e6..ba47f48d87c3e 100644 --- a/src/engraving/rendering/score/horizontalspacing.h +++ b/src/engraving/rendering/score/horizontalspacing.h @@ -105,6 +105,8 @@ class HorizontalSpacing static double spaceLyricsAgainstBarlines(Segment* firstSeg, Segment* secondSeg, const HorizontalSpacingContext& ctx); static void checkLargeTimeSigAgainstRightMargin(std::vector& segPositions); static void moveRightAlignedSegments(std::vector& placedSegments, const HorizontalSpacingContext& ctx); + static void checkCollisionsWithCrossStaffStems(const Segment* thisSeg, const Segment* nextSeg, staff_idx_t staffIdx, + double& curMinDist); static double chordRestSegmentNaturalWidth(Segment* segment, HorizontalSpacingContext& ctx); static double computeSegmentDurationStretch(const Segment* curSeg, const Segment* prevSeg); From 7689ad28602103e6da37b8379838644119dabe91 Mon Sep 17 00:00:00 2001 From: Michele Spagnolo Date: Fri, 7 Feb 2025 08:46:07 +0100 Subject: [PATCH 5/6] add vtest --- vtest/scores/cross-12.mscz | Bin 0 -> 23553 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 vtest/scores/cross-12.mscz diff --git a/vtest/scores/cross-12.mscz b/vtest/scores/cross-12.mscz new file mode 100644 index 0000000000000000000000000000000000000000..3cd857485c037d7ba539d7fcc0881179839a8930 GIT binary patch literal 23553 zcmZ6yb8uzN7d9H(oJ?%nwr$(CZQFKE?3~z6CZ3oRXTph{FYoW(?~i+{cCB93^>m-E zy>>m_>*;lrWWgaYKtNz%KzhU_b>3OIPY)PDK&W^@L6AW}KwM27UCa$#-MsD08SGtM z%l&m7HzzV4-d-?;nSS_z%kg%-hDiGwb@S%$k>wM4oVW@47twDVi=nZnrH!1dBA*Xc z`)jL{_#2?vUbb<>j_Qwg-8}?;Y0(?{(dOE#Hv|T73;gW$Q?9@ME8Z6H{BlId=@`J{ z|FU}$=-a#DIDOvTMNR7I!A982_q7>|-O%8vIDISLS?O`Kf0Eg4VW`v7W)~BAOSo+E z-p%Ejvbbz*I8|&@ii!z6 z8J*IrW8dC7tfT!c)?r7<^{be-H$jfv=FZw&@%6mIo`7;D5r4x#O|=-*znjfg$(-)J zw7H6-Lt$moVv7=G{c4wi=iRsO&sJBMpf0U8z4qYl>h+%e*fqBYA0NOioNE-%l>PHn zpLK%_Ud>9bqz&R&y(61WJQC<|N;Sy?G1Q?8;zBKd$?%rlu=8-fUR@S)q0O5+c`pvv|S4JWv>P zN=_B<<|EY35e@Km<01B*$gbNF6PLX3L!;{=+cP`lBiVtBLpFm+QM3>CQKj$B69l?} z^4#85Rb2rKGe-5TLzejXV3|#Ndpqj-(-{Na-<#_e3j+dPmJW|-r90^|AD*PL;l?7T ze(Nxkbj!l&N$K&UsZ*e_Ig3Rpn$0BrS_lZ`szb#lDWcylOXbT}X3`J?d35L2`FD zrilUmcAVaQs@VjtAR?uSA3x8Sx<9$=JG9#uG}JAR(nH`zD2 z;}9^KgIMc!=Q^R>E0!2#;d=gB$g_ajCwCOZEx&J&@BPrbsNU!isG|E>dHCA&=}>!p z)lirrtGXPZw>f_2`?eF4T>uE?a~@~3usS2U?+FB$JQOQdk>l~J)IfJM8)jyqwD`bZz z@68O)>$NmbQ?Zhfwtnrte!(Av$jYbUjZ?P}MMtSY$qK}&TL)oFOW3A>Zr^wvHDVx4 z`I1gV*pXF+ofRE1VFWd*b5N-T)6yxCiD>RAu`qdsIw;-mXd=H=*wyS@u0Wnu>j>lr zHtN4l*Q_=)>RW%^;+L3KJjc4HMg?;&Gzv#w47Ve0pe~8&NsDyQ{CeWPfS)?nu?o$e zr3~tI42`bWq!n^HRrI5ZwfA+##sdI(2ZXT9cRw@pNC)aA+lg9V zw(gIxGGQId^!fRTkw)dYkVEK%#_cvXO4nYnUl<>*y0$Rltv_pfX+%*79I9tl_;`@Q z`uvu-J00MweJ4Pc?~&h*>Nn_Q1xbfnbYM!dWg$GhOY9LRu45tD1 z4+GE$hW#p)fpImPHtoAA6p?uLnsqW~_g=5B>0{lmmd?u+m)A$Bz0q70VTk{*!j0YB z{$8hZ84#8Y|C8AR^*2Bi#dMoA3S`zCNk}Tv@I4x#~@BG!{nhw3`uc9ghk#=u%o) z7t?Ls%91qLCyAr4f3|&2py@-=M?(z)8c2(oJFRr#INSPLZzW##92l;0HrNPb9FH93 zdv~+oNED3}0@`s-bO=e%t6;6KV$5Im-{u&{84dYz0u9Nvug|+1$Xd!FCjxdiDd0PC z62K=7W8Sd=>!=c5fDtf^ZGVLee}zMTiIfg`qVVUo-b*qBl%Z={dKcd z&Z}=3I{Kp96L-rKx9Ss)_N_!X%7t*riw=8uodOm%Dgw5|ErmxX@*_0hSbl;}4#xSSF~0*o$f} z|ChBG#^PyuylDM&1&uuwT-efvf%Dxx;M&oC&N7*SZsJX_diwxSV$FKgwAJ-zif@p+ zYI6so7m_uOmxFo~YPY5KDW2u?)zlKo^rvqj^pD~i*FZ;~g<=Q~)>72_QmCW-VtZfJ z>g-IE%EJin#Iv*%^_L!luBN>ytm4m|WS)Jjtyy0mHGlR!Om2o% ztVdA@Oovgwcv3-d=?;5nJ|1p72$sqE$ymdjZT0PS5HL!F18`(_H8}FP!nUvP4 zOzz2?!bmJk&3llH@D;3;fkX4{vfe{-u&dXsTlW~X4NwhNRF-o zXmn7j@{e6tw*Jx#dYG0A34ZPLAC57hTp0K$--&L|0>O7(YW1GK5aImoHob)&ibdD# z=ubs*32HqQ!jLkv81u2n!Qx;(>p1g{{?{koQZohA)0U(n}n`ayCzQeqzHNSmZ&81-((u?yxXFO(5R&k%#gI;$%m}(x&ADA{EN1p8d4Z zS{fe7hGOr0O2ffK%wZ&5_nc)><*NnCI$QqXy<1g|`!q6oH=OD=(o(CL06_Ues%F%l zeRWR1L-#8%mD-Beb?yaD(3;fI!*X!6KQ!yypp}>cb-7G)sF%DTLug(dMpKbh`!z$h>it-vbtLts72WOU zdUkv?TkW>#WxUH|6;<%S3o>Z4+`m=0v_tQ}&R|F~@OFfw%rRVrm$?i;8$0Q`9JrpE zO_8}J#7$BuCb$1kbQ2OIN~<_OK&^7%RcOwBuj{gp(VwZWU{aXr1tpQ>c#tkF(_TIY zaK`J3?&%ca!I4fo<_jY-$Zo;M5bg*;`vN?;d6*!Q@n1RvYOg#W$F>$>!@;_GCB;3d zy0tTU;aq=L7+{`%AFi5F8BOhOhPN+m&voCTK13`%^2_4MXB0qs8a&2$y|EB9z;q*7 z80-bQEnBWL79k9R-s8e%nBN>ag=jydf52Dk{Y%Ww9I#Hwa-O^uEL0Gl;YvrQyw+@a zGan4MOB2G)2p6DYvx>KBER&0l4L+V0Rv1!WB^iXG|NA0Pfwm^L0FflLp*0v07R9cg zvJ#fXW`+g~V`8&K%LuFWB$cFwZgaQ7nH76A=UHS_O%BLTxSw__GqfQ6XqGH9{ho^x zD-=-V6z`)R#0Ljm4J#z;vX|E4gj zJ{pZ&6Mf8{Xrd7P9FaNnpRE!QzEf!(KVTk1^TKNCb;kc&pk5^eR5wKs#G=vo_xd1x z7jsZjjTG0=hEOhGWkpta*V0{-8e>-yYS&ed%ecb)rl8VEZdh0D!-b!pip%jm!ilUy z7Yh{SD~+s!@bV0FC{lo}Y3Xrz#FrsyiLKo9$mL}Aa-gqkdbo6PMuldmYE-3vZXh~B035{H$JH`bq8nd#uk zZoRB6K;3TB$oDu1R<}m}Cu%3b)4Izp+g!oYLA$d?_fS?3LGD3J1zVUWDyQuEdXpdc z`STEWuO+h9WQAjgwtvSfSZw*aBI$~mc#M}_=tP5ZParIGsbxQ2 zA|N;vmPI;x$e&L6IbYlGvremE{3v+{L@eO#K}%|_-p-;^i{bLGdwVUK?)yg;InY8m ztjgOi+boJQdp&+mv3p$I{X}**x2y9i>X8PTdv;lLX~pQm2Z5N(bwFB==A2WD7=Gz} z#rv+rdfo}X)7SSmbpHnkYR#bWq^7!M0@Sn=VPOZrmaMn!|v$BM>5KPU?hZn=#?q1a|D# zdUqWU3S|n%Y0X=;U8QdfXtfiA5o6`1hfvF#+T|4ied^~UBSuT&ih_HVdM@X#t!jvOx2Z^u@JA~4_Pd~4d}sh5p6+>Y05 zE1A1CKadJ&xC^`vsYKz5)Tqjq1CirjMBJsCAx8rz@hXM*vxy^j{`UbdN>O;M%BC^PqbQQV+V;g#Z7TA=XYe`W^B;<( z8c6hR9omLw8b3C!(jg$1C62ov<(s@bcRh->3c|wZE#4c>#WRUq!|*~$&P6e`QkzU6 zshR_-JiA?l$CSv|++Agy)ngzMIw-`!B=wbzin*Ot)Bn+NJ@P8;V4XkKJqcwQUnVg@ zNViKqx0|@I*;9vxB@=UYjImw+im7ByUdo#H+uae_VP<=*Gtw!my`xk_r&95SExg_M zX+cnH37i5!1A8}ib04~Z*l>sf`%}E#;x$&j3l`ycZ`*Cmllz9OgKnRFdcb1apIM7T z7#8HDfBKpFL#cioD3$X1l;I}b_gk@TXvE@xwark2DwE*A90fVDv<31!UC({lFL5MI zI8Ju(03K=0zkXd5c0-+;EO6W5R{o1@G*CWIZw&xOlM0$@be5KM*WUK~g${p4y_g)c zL5M|@)o`IW{_YICc5HnkztlYW@({<-jQN-CO{9&uwc@{&}pO!1Ub5w1!mzCr3n-S3SDv2 zL7al&RfJ4J7z7WC1l121CyTm}2C?e3uFpP!I0ZYUZ0I}BsPQ#Mwu8OmuitCkKwpo{NUD66y^vR&Mo>YXnrW6A)ulrJG^ZW*+H zhE+UZRXtvM(xkKLQh2P{hEyR@%jO6DW8^oifqsItU`>?Rux}UERVg~>XpW$Oca_g@EV`nF2h6Fl2^RjXGvc;t9Vho_*6j{sT+U8J|&5y zIRSkjJ;*H|qk5wFu8c|ia@(IINB9GfuM6cazz)9o>F8)ZrG5_J<=sR;Q3*?CI43l| zS->MLHyW#GlOUVc86Gz4cw}=rBB~P=?P%T&F*$bKRw@^4=wY#>#m85SLU73)$TAXl|5&crS z0=&B5ig;$b=9F#Wc#RaqoT11tO>3<;5NWrn2D8PpX? zm5dZD_mQ?V^mTmkT)Rar5L@hwk~0cWhXey;5;B~}7Xh`k3{j%l`&s;foA=>##NuX* zWNnOfF_t7b6%cRIer+c zE7Fhq!N!w65>0dKdabowkW5YklRJz;YxuS1w;xO7#XVmGa#zpAy;dL0D7JFOu5!Cx zRC23H>1NMG50C@{Xmcy?C0^FU>8x{P#{R!L@dw z*^8PKpsuN6h8f_RN-4<|M^0*z)R_mVp%N2jqNiB`i>L$>I2KH#vGEh~{u7f^9kHfs zTT*gFE%I{pFo2m47sin%Yc}%~X-62p*`iQpUx1Rz^>K`SCm0LrZYu$qPP! z!0$qxC3fk3E}(5P;i4|)m{uTyQX~Be#bmuKqmd-Ci6)x4!b%fdjTegkJWreVR0kf; z^moDBa?2!M559v5lOh;B72J}V23wM_td#M5V@2f6Y7xZ~k{8WSj5C8Qhh5f?nKrLd z2s5+5zjw`EM4U205|5I*3x<6t8r|kqKA8v@Vz{@du*M60<%4FcDkh7?ao4C1`KOvt zzCQ-`VTvF8qj4C{u{Ihhnf{n}*(~7cfPj^>59q+*C9~~FC^eR~9JS-6{a#~0`DRT= zREWvO-o8^+6IYRD`@xl$nj-SOz8biAn$6zJhwv3|%hWu}iHJ z{zUzt7+=#mGDt8MM;zjB6>TNy`_%%2*x*h-botfTFZ>dH+N#=L@$kZJefZYpLh@)8 z*}$2ckV1HEp&5p>{oxJ|`y%bUyWoxAaC*Ob>O8xBFc}At=^g@0c zIQGTc0m9)SapA1PnOk}dvV+6^y_=IO)EgDIeWZWM6Q zO|%P7E;`RcZ>}YOaU;41Y~&<8)y0=3aCmg7q!5*(&C=YrvQwU@`(>oKiqd`{5TB6r zL9ra?g?=(ZQ4y}ZCo`B(w?e<%g{@;hosAJ(?{djD$FLPT`Hq7M-njjHjNsq*RLeGAllPh;h z^&_`Ga!LB}(6<_EYhDr6le<9B7|ZCvr#1bT)-sVmBI^A13=5MoQeK2e8c-6WAPIJ{ zlHPc}QJKm?X;F+4)fM>>ncGNCd@guFmOebD9?heV#}UtMbJpd4HOuX<%E>9;w3CAh z`X*hLmv3-t(eLoJy_jybwkMV--qKXK@={Jiu;H63&TOqXJsF9OE>VkV&T2WUhZm67 z1dZG+S6gr{I$hR8`)*B&_4K(yoH-Z+l8P2x;rP3inG~xq{udLA!dfI*>SG-Et@UIX zJ1OB!lXMZm^Ro06vA(lZ#k-u!P!`IG;Ln_m)e5)w_KBbcG^Y*v0XL1Kj+`Bk@x zjU@(^W%UpjBKl67bCjnbTlGyLk&VguBFe=PXlvDxU-1J!VbGAc2HBNk+y`)~lbKF} zNcCBb$3QuUZK=-wc(-BvTP&?0vHKT(fk%7*;m^w(*ua0zP$IQz2>ZQ3RIVcbGvZ}G zj;y1$&Z`}yC`$$Rmo~jEv5LB8qCI0kxFVO6TJxlfj^4{6Fe0+Iz{{k}jejMVlO`s- zmfcK6I+Ze<%E1_C?o0b7CBZI0+c1w}qI-*MW?>pPH4-_Md8iDxO%kwzF>VaWXMPcB z7)E3Ys@%W3M=v}EtxU+>0!6AUKck|Ip8jYU8AoIT5`%< z-z)s;@Z2bH6B2yNZ>AXi2fjzGtFrNxx~Icy$Ira(Hj>dOtG9GO;sNVYuQ!Hdw1-D; zHn$!e>(C_`nz!XS0|d1E1FRt*S|sEB9Q_Gl*4K!y9Tdf2zsiL&GJ5$RWlwKb*(mX4 z2y)1GvJ-|Up~BKhp_QNwq%e}8;lY3Fa`13joHQwHwrJbQK@n`P zmy#2!4iKB%0IX^z89Z6HK?n)D^l-K8#yD&(^MMlM@JyIO-LUn9KbZUGl_^9C3?NWEw-ASAxH}+~MNbG7 z1D2TJLXi4MfiR&)0BHXG`1wUdB{55K+}xzNG#fLa6r~c>IEY?Z)=Wg2=?l>Yp1;Y= z#1|FwO`uU~#8PW2tD)h4P^gb;&*doSgjU|xQRF`-AO__M2#2Hm8hoZ8!VJZ%M=6N> za{L^3>7SvQkq1g5|0Vfi6d+A=U6`Y_C$U zOV)1x6D+;z4uIu#H%4_vFdQl|tDXX*pn_Y*3~B;d=7gqNQ?9f{sVDO%v`{na|2^bA zN$Le7|C?#PNX&3e>jwwb!e*M(D(ynX4`mI64?3;3ASb#%>LNo?<*htH6m+rbpln9U zUp7K8h03sg5&6wwGwpLTF-PW2HR?6sT1jMa>fl({tjMaWwrZ`A()&{w zh_ZcpiC~B~BvzO*1)$quZImDxA%m1TgBpcwvZ#T^!g?}jlsn~$-P6EB9Qg!G{NlIY zhBaXn4oKIQWb$c+OFkA8V;~zkf<2OKMqgg)CX~ z1fS)Ra%mL9<0LV9N)x`zMi7~qV_rnE(Lg;H4X%fth-!rRiJN2-y_aK7bB}}JNQ0rd zwYMTri2$HKk1hlvP5|W+^v$WKQAvGU;Pu0U#M&Yo(z~V1K^PiP)+QUuK$v0NQgQ}G zuDviqU6-hDX664yHpjh3Mc|xbiRZNRwU?R}X^H)};_Y@QSf$Pz+OOE94i<+pI|Y$D za?!QO?qo7DuXGXd2M*_4R8SGW)&L~yLA57pqGu+}L6Gx=d~=%V2C-+fOM+CS-e5`s zRU{sNO|2{TFp>{bhir*v3T!_DfJW5A*JD0e-OiCBoDzmQQ;`rWjh#Uv+KOM zv*2BBL5MT#jLQ^*?dTYd(8BjAu^ca9TtrFs4y2pSyEejkXf#Ioi74@)yn(Ggm6jUr zX@Tt<;x?(JgIEu-C_|Nj#zJL;P~oj<(%$=UBEgybc>89)ssi=k6`(kGmbol$IoD$x zTyMrqNblxwxIvnP(2$H`ai`i1fow5$vAEK`6dB!F?YMG~xFsq%e+(EMN9<`3f#|A1MK{>w=zkt%OsA7;3rPro?}RQVcGhSF1G`UT+zgjH|ApI$1I=BXhBon z==WM^D`^mCe2)15p73s(esj#0I+V}yeA6N*#Z-PY31%Crq?G!?{Y1jxSXHF^PSwn7P}Ht#zoxi>wQ&IIGpRWzEmkOK8h zndXT9Q6|TKl(~cQA7$cwQ>F`DhE*pxRB_`jZA*UwOupYJol$W$7EDPmea_5_nhHHl z10x}u&scR12o^DFI^;+&nFcmYM*FK)U^}fnB&lOf>VF$?VM(KI_VjC=S_9)HLCP0+)EFq_v8J=z|PmG zGgR@e7d5u-YAuN_w-VUJQNqpJnSjpL^dvCy?8DuxThN|_u zEBQ--Vuy~$&2#P+S0e$$x+gzaHI;7HGDs2YlAVR3TiA#|77cRb$Q-yRw6}tA>&fRN zGn10TU&NUV{H+Y%y234~G+V{&KqMd~t&RO_tE0&GM;$&aCWWLAF>Pi6{;yh5BMtHkKZQBq^hod=OMN zg3q4dE_ z){3OOQJ7`&{j32Icl(zwX(qz*ST1QVgmzmeiAXva)WEN@KCpyKh?d(P3@JT?KoLZ4 z2*JuR5IcbWvjyR_Lf1Idi2BqYY7cxq$qN)q;S#qw?65<)8xezyS7RiNhv;V9qO`p9OfFL=D0X?6>YN%9O&Zx z2`$#!opcyAbSjZ2zkTy1~|M<~cg+lOOjsDf9a|Dc_OR^xsy4~@TR-&Vra%$FO_6os zNDc~1uTPEY)J0t(NacsAiwWt(|t&DleqGuxblm* z@`JeYEB|M|ojtDn!+i|g@~p8lh|x1Mp<@N5JO#5ngH&sAB%lemi)8CA~b8Qj8_8{1UEwq=_x+ zn5C+?C2Ii%0FMHINdZ8k0H9I;a47(y|A!dj%Kyui|80>Hm(K3?-6ZziDE8eV_T8ZN z-75ZPznzE!w~Sa-yEK!Z09Fh@3urd4s54KhGtcz+ncVmp!q}PI=o!NIGk!*g`X7Sz z2Y?m-Kil%hna9^4Z&o^QRy=Q3Id4`tZ&v+(_SBr4|-gmUp~ zIQt;%-~SjnV@_B)_Sh-ohV+3~ZcgeB7-fN`4t4LacBSNMj<{I82g zA<;OG06B5#;AHd+HhKvi6+lU)peU4AP|3v)>g)rye-AN!Ce5JGq#R?NS5U;okCW8- zAHpoJ;PBx7J20?uOX!&Y8|0K%K=uv)p69y@A3({ZpcpZJHhH&ypEhz<6}9voG60c+ zqIzCI2p2!3vro*yJsUP)jcSxlK~Xuc;5%mjAy^a?@0@+A5AHF>&Z=VmH;79?5&av! z|G%z;CDk7Q!0^HSy|=TE#Qwe9$Qe$|5-SS8l15?fd)>iY{KL*Z|2J%wR0?xYW>^0q zZ~&GsT>MMUK2Qhu-*Nk|3lCr!&BZVJ|8$L?;lwR{2hQiQhYLUPROm}8;XZLs=?iA0 z8vMoR3r6hRD=gwoGWy@Avc~|SZh9W#OQO=R1W8eeYDuTxfn^aNlF(xxl16)hVUnMc zKBs|UCaa}BH-TwU298O?U!*_!369Z0NPi3x5O6>;`B)&dOwzFHh68H${4lc`Ls&JO zrfAqL(+gX9xNIRS>TY_Li=t`yT+0FVNHhAylQkn3m|1;8cbZkOwTB2;1w%5wjEkjf zN9a~uE1C+p6WJ@!wN1HG*&|f7P1!QpS5m*5Ty}{i?Sm1&6)xW5^hO%)SYs{#I{`}- zdqj(lDSI8e08;}y6uPb{Ukm$+s;((lJG+9ML%eFsx7*7;cBgB~G{`>2s&`;1=Nw666sC|oaFzP`z<3w7n7MDfvn&HegbAAsOBb|s-Q(}(iuQj`#>^wY3 zc3`YLy1Qje3hFhvztNX%b1}j%M-CDrB^dl|E~b5_2A)kU>4Y%(uVR*qeDE$)*Ls;O ze>IO2?FVQ0gj>_lK1~#nmmS(_Es3uGC+abLsNLu7f1Udnmn&VwR$s=P%fN^WuW6XamV>I#qomZ+65nWuaN6!-qD!E&;r_HuOzpqByBB3C;RRd8J zn!$<{!&iuYLL+A`6K@P*mS71tVvYDf6uth-3*>oq8X=5EK+#FGLP;8BKrjL&0fLME z5fbt+q{5hozUU#U4$h6qQ~6B=;}P=Ktc}?XR=bLy9DbinZmN>{9J9TCt_kuKQq9X- zaD@$0S(;0~I+)o_iiWR`aEqu6U~v8FwCxBV&705T`Qy_&*CCpFw#goI(7$)Z<-y)>2CyO^w% zl1p6?d2XNfmAN&t$|TyqOJyQ`Iu{au7UdB5ga6(&qUCf_XZRIO_vohp3c3GXo_BZO zv<1|sB@U`!xM@Ax{(!Vz>Y(DAfIDLXuE7v&LMZ)0y(ZZF!IV4fKv2`&aPHFmF#Zl6 z+EDORv%D1f0sODlTd`)-r?c1L%Wc_b>ezPpqkbogW4qye-$R?hPMwN5F#Wb~jnQ+H z(Y%GdogKGLn@ZU5t+Vgw<@wai!^34`#fQM@ShHAj3FHqV80J{s( z_)Wy-&m7e*#vd7ibYgtb_wPXq{K(N20)G!_g1(kW|09IUC4GVkA zfM!j29a}u`1F~%yXr1R;VSgeZtxlmmnW^20;kNo2O@C)z`W*acEwCReaHxSXhMv3G z*fy~L7X23b^HuSqAqNw3O3TIXXejoRZn)v0-@w48{@SX~NIo&mN8}lHwJ3L;b}YG> z8OhbM;!bYLU5m0;rXEwY-gTM9bk2tr3?~R_tF%G`z+_~rB*W{{7PoXsRY2!QfFB)v zWk=1Mk0xJkP%C^*$spHr`5J)_r)jsUiY>vipar|*rBDi=jpaAf7|P>U){mHokWjOB zmLIu$kX9ZxBsOnwAvU|)5ONI6MsOi1?msp1xglD<#tV9zAuNjGK5AqD| z(+G_G5kZSBT=C!M72A9cvRzm_cE4;K;Duf2J1#ioZF%>8qMqZY{G{g#DKlR+zkvSH zU1T(7=pkxeccmSE;D_yVc^>73*IQBOJ6c)p?IXuZCb}WZVZR~1;bJ zfhH^l^}|$XR^7qG=16k`V+o^_Ejfb9GYL5k{O3SpdK2xMqiV6k+RT$3VOmX%1qO|F zbsh!Y!X&9|MUq&iS@4`T7_o=mcGKNRln4q}LjEY~dhkJH^b6Z=^cFnCAgvqX7HqlP zZ?xKwy>p@^d_mQvB{3U8PVD3n@&ZEvN!M?v~>ALnvEfn=7JhYcsam2&&&^ zp>$wwkas>1&t$xR2UeO&!DfOn4lfhq?ttt~Q_Uwf2wSXJbcM&9N#Q2(1>iNQd!VGW zoIBZmHaV-l6LL0*+u*g6Vt_Iwr=qfT+;ebi$*tL}_@g&$(yi-4)=3E3+dmoa?#7o! zQ+40{v=5B6j;0|paGNgspWlQhe_?HYcI;$MBvC2O^9o*kV(<8X> z?tlm;eBJI0CjvvQ6u52VL_Xl%ol;Zb7%J;#Im#mZ+3D;R}GT+6VqWm&CNJeR8RPf?nb#q-VX(KLf0!lBx9^ z>%omnvl7h0y2T31{%|MOYqyqBX8nNGS$09>LEhn(|E@=^>BF2TCX${MLz|&Lc@V5o zq4CeA=`R+?`ShpX8Zi!(g{{4PlL?E#|42ZB&e&BSLVM?PCE5)UOJYlX!=s zdB7{+W0>D?vyf_jMeVvPVp#c$Y}Nd_=Jt9<>@>ul_Lz5P33P2*f~i!D^O>g`a7JB) z9?xSf5s`OTF}$}eLnyXF^w$&{q1=47YJalY!KRf2A~`UBc5#@U(ke=db5B?Nrxlwe z_u!ZoXJ<`nJE@g*`m;h^nJgjh#>4M#T@GIKr?yc|2Rz?Y1;BR~pEMsg8royBiF_0p zUHMFSWBHUH_ujcq$0q6G!P>2r=8kJe`IU%lwS-PH%Xn)}N05oFB7wXJ&`&5;#}h!* z=CC}e#oN?vam^>DHEEE^jAnHBT^7SH8*2c;WWX%7(++~sVs|@58tzLa)Lj|gn zc+L@#3Q2}X-qzhrw2g&=!1}MSH5W~qx*vKP#4J`cB(;7l#jHUxRMGN`vv(c%nI-9& z%|{Xqi`0(uK$%ASH=d&Ema=BP`~wee@){$Xj+fB30rhXZ`mXJoXKs;mhJva&22=Hh zVLC@$G{dpyk>W`0&yqzDK4?tC(dmQ9c4!l>IiZjm01bFHkwjglf{=A zr#&KGXZpcZ*%&@3$3ezE-C`RF739G&{zP~(C_2B{u&)jp;#FW89Hod|Ynf<~uEF4U zgU*r1Ir=PaTBazA-?(zjOdp#&L&S>VPw97A%#Bs`$rmHd6o<`}YO@a@^Q@($85GC!OyX7joY#jOL00&QMFvy zm9Ye|`n*fz@n~5De{JEd?qu@Pi&eI2;t8F?F1W?8CePZ5^`ZCK2Pzl)8ZaTe7ICuH zz-(g{Q~YbigWh)QVn3~L{47i4kP>fh2OlqF8%!G5j*lgoQN9i!{K)Qoeu+V){ZKz_ zDw3Lml%?l1rCHkUpTGcb-~7q$>q=_{9$~N9gc)xX5I{7+DgMG7T!eGc=v=3KQykAYi~&c{uIy@f?v^+>bC1P^bYiXC~Z= zg*~BmB`xxn=t@_{M^MSN;$W>GG%LB(OT4zjF&(n|S8Ju7Y-6dC?Zp>l`J(AjS@R@d~tI~x|DnN+LE7!`PCEB3oO`Ei>Le0lVy2@vSDtxr%1cy2C= za|Qd4_5rOoB~s3)a87q7fOdA6g+MdD?eTnVYxEHTu^{Qq)SOnDxu^zbUkRAf;a&VA z-p@)g%wO!x+wL$#H~Ue9=)er`ET6Eu`V&F&J=zjUdyNeTUJGH_oUl}j<;sh~of~lz z&a@1EOh@G+*lS;S|KYZzlirHYvYhn<9-1RJl#M?FJw0l}VC1eo$GL5}i$~`%I87i= z&UVZh3j$FdISGh-cA@;u8QOo?n(_v$V3{bUAFWK<>EFExA4lc~Z2tYEWU?oMoB}J4 zs0=pmg?!bRi@*j&?3~8B_6TBPQRf(ocD|7&e~t>ncN=F4X@_<`?FHV4coZWSBF}P+B1F8*w;qP0Qd1&J-8`@e6e~^X;_x}xu4qjFDp*|+%}eJ z#>9L9x{jl+X!y#E)C?Q3|M+E&3g}}nI3{JLpgv$is}^VPt{2Zb$J;mIGM{BGhe1RC zK{2m^xLfH4n>-h|{D?5ldAQ(a=ahz+YET0^nAJd~%ooi-982-9ebdkUR+pE~c@%l1i^)z{V)Y+QESL95i7$VQ z&AGD@mDP(u*tFv`;UL?m6F;*8%OH#+Sk8q=trQD89B_+Ff(>gBwzswgnHv+ZCfp}E zRq#V^;1BAW+haZer9+9wUx(grD5@@)RV2c6r_-gV*N)T~{a>9AU*~tg8LQp;xS|Yk zuqvgIGED7~=_kQezrS~V@F4RqUw?lW-Syv9eLejD@;C-5Ai?7g5Rj>#ARyljh?>N!`OT&Y zL_}gPD0D@Wn=AoM(|x$pcUNzWet}-~mi4yBJ(jcFtS3EJZvphHV%F8P%BoDNLMUSK zY8vxkoA5V&kfdM@qc()cgAsV;c2N;U&=p?=nOPwigCXn4RYWxh>1_p<@g@2^V>vZ` z;j(2qA3a;kkG_#={25tvw={CF%heXTaitU!{4{mabXTGV70`JH%}+% z{9Gzvb;g^hnF}`=-eO)2)uANxBY}BJ;%IKqec#p6YL~Yr8mh>1&73ZT|5Mm5uYZx4 z(=Ept|EFF3i6m^XrhbZI#xqT!may#ROf!r9EzXba-DK$vn6M$zl;0S=Ky=UUd(GhC zM)kb4YgVGqE6Dwi`ZVyglesE|!U>ofF$pH=AojFbU0pLQ9rYM+dUiUm-@RgZy!}KY zyYw-gbr^fyR9DyBhMu@Izn@Ta~a&E?LfKtV?4^*Na^#n~A( zP28$qlbmsNX;o2H*0jUp61Jptt0N;Mg(ZzsKb^Am!QF$Sjdzo+&TZ$hOk&Zm%7YmP z2ZzgWNkm+Hbj+fO^A7ZKxu)K#HKpinatDqeR|vtoHW6@m+zc&8X9!Qb@W))%%ZPKp zoUL^W=>06D)=GKOBsN)Anl-(4;)Ikn7rKGH=9Q-!$cN>4a{4ThT~k>((Xq1Lx^Qr{ zJ?E<(HZ~^lUML6v#ZG-V&FpV33DAoDQC<1|tK-SV-5&9Rn);5kcJ-D_()gceeE-;| z-n_|8KNs&vdPHPo=(V)+aWjhSO_KWKV?bIEdp)q%Wp&4Xw#`6KPp@I?G-vkym)zcp zovkU-;NajNbH%P3Sf2THZ}37Qdh)Ff(iug<((i)BRZnLiPGvGM@a$@=Sg|EFHI>b{ zRxu%%`s(d-qtZKcGrvByqoYIjCwGd&bVuq(+jog`zm`VZ|Ec4wW8z@eHNIGJ*A{7U zcln^SxVtPYUZB`wi@O(>;;^_waf(w|CTBtxvKKM^;v5inr$*H8pi!n~8ToWXSbks$vUii6WMT zQRNlC(Av>Bw&?HnHWz{nt0mihB?YgNF7KSQ1sL!}1({mztU*B;`Qq~8 z!r?~>!~wBpVqlx%Egf?%eO<0*M9k82Mh~{?veHs! z5`%tfgATuCpxCEGzT!!Zr1{xiSx35@JP!w3GZyCF&6Zzgs zd)v6WUfwR{fGdVnN*BbMQ7w-CNdEY1@_8T$^wT;S#TfOe@?q0o8piP{aoeevf zL{>5+FKLcrwA{`SjRJUJqKZ4t${hIxRR2Sh-%BxSDGBztz2Oi~U1jrRF-^1@8Y;Gg zp+C#zs&cXgBh56f&D5TMsaEPZ^WnN)I`ptaU{p7XHM+|^&#S7khd@+Ak@5(A=+MNO zRj)ffxd-OlI z@*qTs(kTgf|7bbP>&CS-0X8g0s%Br!u*Jkt`TK|gm+3)bE&4C4UsY7@d;Rd}IN+?newJ*Q zdXfc6!o4jOtZ6C7N3knh^m4s77T4mz&GGguD=SN~rYI+fOn%mrjAu9S+)Q2?#V0o| zdbYhduZ-n;-rXSS#hw~75uXrPLx|;6TRn=X9=_NFS={+0mo0~4%tcI0o_jrxs~dVS z9p&C@LvaM};G`?6Y4b;%OT0i|YG~hG7H(PVv`m_lAo;Q0wxz^f(iDkO``e9!gKRcr zCrz0YH4L#w&Gy4S$EvN!iN(=czVaPcfh`?rt!;CsCA^(ZH4G$Ta^v9+wl^*tKR+|H z;D1VdCtdpVhfd0Nr&C}G!BoDl5+G+j_zcs z+TILe?%-~TYOJHCrnb)~{=6kV7NZ(|tQyJ$K(H^W!rsr&2fZe85slmwMcfxOl)8=) zrl!zf97F+d>Y?$^l4N_ggC3aMXD!z18X~inDdl9|Rla1MWqyOI0mlPp6_t^Vjg6Zd z!EdB=pREK*d}DBf1Tt_-)^+I}yx^Fn9DQ~uqCPiV!oH2G5&cOQB=}({gAQ`?$`Gmv zHFeltePIC!myPMvX23E47daXO=k06CBIe?d_<+eNXS)78_)3W#p~$nr3e1^NFcrZ8 z*%Ej45MsSm6T)T zQ1U|_pR#D$u)k@L!#_<9cx7p$kH)+wMBubA-QiEYp6_peshKBRhgYt|=Ky23q3fW% zeN()P+jGmon6^aCcmQ=ish_BM1J)G?*r6&z5|!s=8Vg zOP+F=pd-SP`98Ww^lZua){&``;FCIa&3j6pygpo(=lVY4IC1!T7hC1TUW6+HLosqc z<(%wV#=(i)#qI9tuhIG(?VRnU`uh4U!+rf6+I%7&9v+2elNim(^>xuLHDg(MHsjyZ+-0QIOA2dQnU^zcP7o9sw~ijPg=agsim<|;0+KLNOpsEzs`3KkmRicQ*bZ^i_{aNTmjrD zC)C{>bdaoRbAp6~p>y-|;|5UYRK2y)hbde*U9#vkA`#zA@(jiZP(VD+G>0G(?x9u?|N#^rr^A@*Y4 z1Lefj681{w6!J@4`S#>C`+r%SSobi0o6y-lb3tZ;q@`xvkIDqTyXCs8u8@|){SSJ9t9eUDg~LN>UBZpq(UyqoiPD z-Fe zJ?HNnhm%9{q(#{-aSwVNbzmMJ-+wr3Dcy_{cl72*D6xrma z%mASGC?Lp6vae4!VGYX6Sv1g5@S#J6FeDME>&oa@Uif<;6-gAN^UZx zO*1j^0aWl4HNB||M?WMa1fut-E)ge&p_&blPqaf(zI{7%_Cbvy@FZM%d1j|)V|@Ph z6qTEd`gAfY${gwAa^4*>oC9Y{@)V2j>$wMk4YL^Cs!+niw)_euE1cz&&}Q#ua@Fe}lC3 z?OY({U79VE$(-M_Vop+II@m1dyW%-NEmS5aB4AsL+G#K{=WD(Wza(;Sj0WYOa&<;V zM%#A(kT2%#y4uW)kB0h*v)gYNu{Q%A=ds$}QFv0g@Ib@tq@rPh8{oL6*m_0)XN9>VM0!;`f)!tFaj>NlzUXF3VL^waMr z5+?e&xj8)X{GloCEb8Tq4!=^+Yqd+|AT@x_(!t+C1id%4TSg@^qz&5bdV=sre zD`m5*u9<=Y+FUHzQ1h;wmp7q4Uo>3PdEK zS=~IN=;Y)SnO*VpI2h#GSns=;O6X9#HsNH;JG~-Oa@H&_E>3-{Qr#RJOfBkbE7zX_ zn%vz58@0J?emlOqd8B1%_z=v5c}nc&)|pgtRu9y_ZSul8+rDrS!h3Ezj5=`I8@p3B zaFSn}r1?-3=PB#75X#bSU&CVN*fQ1`>YWLMhN5ot3LV0y2OODm*LY{&3R*6^ zlOfRd4h{-O5n3|1rdfOB)5Ih2-$FPzd4DYI?#BuUKc*wD1JcjqAiE5{(HA|;ZxXn9 zdGC)qo^73*f#%n8!6d9=0wagsfZDk>ZTq(;%%cr694N9bCWkgMp`qV!=-r9jwiEef zLc`L&^=a$YMnpu2mkUSU&Kzb5Ox|vy$oJ9f&M#KyFNqU5JN>wKPiNPqj5v5TF5K(Q zjZ`R}CbhC41B3Emtip2aH4^p)+PMGd|baq zYBO)uWMaT+tGNdix-NKWD)yehNPjd{3*H>>Us?6%{gpm(J;9)XgYSlA6g0??dR6JZ z<%oKf(aCPE&e3}C$Z^w33CWNOUopHwFVJxK=A!;JT|tSgf4*ba4@Z{mOPlZ&-c19{ z1D?wJx`&vmmMb|%?$7!&Yn@&Wo+`fmR9eHw1by3-qQ**1BPtv$s!v zK8ab#pTD&MI7L~K+}Yd15ZBD9WUkAsl#tun%Y@(Tr|tpvMU6ipO<_PE$54K%;HuZ5 zple8}5pwYX442Ym*L54WFGO2WhY?56mF1JpPlftZV|@;-?O?eyb4rMhRrk2KN?Ia$ z7pM-|7<_NU_?hG+1Uc)hJrlkS)_$CxDPGnGh?|Yk`;sXduK`eStM zMR;jyhl9*!z|jP8@p&lS4I6K;;1!om`hI%37Z4C|-tXno@%o!V{#nL9kcwck%^D>1 z7X6;p6}=8_=zYKSd^iTL2Euc6nYQmKqNrM7?UA^{H(MhY!kqP@;$o8S%*Z|(3K`aP zn7iHA%ri05?e$G|c^r`MBZcLfk7ICh_NLE4Lr-V98kdB)JUZfKo$OlAh$i;zR2)r+ zR3Dv~OTq&*ppI~osOZ9vRlVqVpK2?H%6<6{Ox`6YW)tC$(~CiO-Cq!8Yw+0CADFh0 zdbs^F%K5q>{wO4?&Ff2oH$=LpTSHUh*R-XS*)gog&aN;h%M!H#df?6JA1HE`!lwxW z$riXj7m11`{Vb0oKoO0|v-CY!e?_rV4G#~p=q&qK51P&rgoRFn`Lyp}ByC+n@$yzGj!AZ)z zm%N*TjZ_Q*0zU|T$SjqG|8U)Raw8WT{uKEUlRdE-J(&Mj#Zfh?iFpll`5KZu**#nL zI3VU95Vfo$xX0kV$%L@;6}~G#5`;X#GdT%iWFbGxLgnF_Ji9slJma7`9ymTOM|CN$v?5KKPM=adkZTEUf=96{hZw0S%bD<`AcV{?F{0ag_j7M7P|Mk6B6Ulf7@6-6_ziiCPg(9?yZ%mSc4w>qvX z1_DGk!S_l$sOajf;dsuRyuh9+GZt3XQG4&`~ZeExq}&*;Luom;0ffLdDP+9oa% zE6D{m)@5ZTLHhElQD)#evHnTF1dDdhdpFlb%wWdho&E;jxAKiYs9EDjMn)XIg9ll- zK-$-Da3uP0P_RYBEshZk^Tw?Vly+S$EWE^dW!1L~;4ydC$DUXLv-tSaNRjCnMN4Y-IR|oge-Y9hR;Ug+uUS3JOy;#4ysaDZ%VUkzZs*9fu z8U8U^52iU*w;h?;&PD?cI`|+$<#R^H0hj{7^I1uWhd>?>fhXT8$vHmzgGWIMU|%S^ zdq2?eTZ*nz<<$@`2GpLzSoOqeqRU?OtN&5rU`B~LoPCp%J`A8|NXl?M4>wucE6BIfi#E!Xyis8j1wB41@&_`VJ<^ zC<&4Hj4j<~f1Pdasg>$%y*DAG?He7fb>!jZ-}JAwB%Qo{jl7fE@`RdM!GiL>?N7pF z9<5RIb6lIvf?7=H#zbn6cJxqMEtFA3ySOtALxRG`$6Q%CVPfK7CgJl})SthYnL(9@ zIRMPgp5d5{9}9x?(;XVBI8`CP(IDKhDqLGCz>!m3_Lw(H;jtjIy;dJ@#%9KI@tguE zvf{&9{;=d^UX`0^Z4+^hLj1Q#~kK_9l`!+ETlM~k@r*S`_jdLB)BiD;q7CghB zpVyzAzdInnyxnH5-&;QkAXD`*?qLu+jY>YD{-@`S-%l_e6A=KI!2$pXUTP&Ku4Z6} zv$=~4*xu5a!`c~Qf2eI}v&co{J6etA#nA&c8S-9SAij#TABrs?nr~O>G3%EDcxD4|L&pJPE3@=cp;fi`mj?jaoGlYc5^~!t8Q8|EIQ^IuWlT^rO;_JrHj%(Hh zmQTv)3`=syRzIyRF?0~m#wQlf!eusaI;k#~yQA)24E=x3NQSmGas|?C-q@Wm@w{an zpmaPxu6dPMM~iSXzd>1ahF-x8q*D;i`Thb~14DoNMv@W{KEmJX`{ zWpb`y{P%+;5q%aHP)u`qZ5y?lo^@+v(4AK5>3m^1SHTD_?$pyAHfahmYtLqHdSlHY zjZlZugC5&N6dlYXr`;QKn^1u7#*1{tg{Hx#c^BvB8viXJ9P{~dCugSM&6rgY7^FH~ z*w4tMJPEe2y0(BrmhFG*Fyf zUPXrUGsND-1Z;2a#NlCQ>pS)xCx{F0)yi^-)sM-@M9IKm#-H<3PGZU}w6LI?t2N`G z2$NRP+ox4gO?F8R3YxO^^WMuyU literal 0 HcmV?d00001 From b2ac8be904277d0c17d99bd36f92e82cb8a7b0b8 Mon Sep 17 00:00:00 2001 From: Michele Spagnolo Date: Mon, 10 Feb 2025 09:30:43 +0100 Subject: [PATCH 6/6] Add comment --- src/engraving/rendering/score/horizontalspacing.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/engraving/rendering/score/horizontalspacing.cpp b/src/engraving/rendering/score/horizontalspacing.cpp index 294a47a874ec4..19922ae08584a 100644 --- a/src/engraving/rendering/score/horizontalspacing.cpp +++ b/src/engraving/rendering/score/horizontalspacing.cpp @@ -652,7 +652,9 @@ void HorizontalSpacing::checkCollisionsWithCrossStaffStems(const Segment* thisSe Stem* stem = potentialCollidingChord->stem(); Shape prevStemShape = stem->shape().translated(stem->pos() + potentialCollidingChord->pos()); - prevStemShape.adjust(0.0, -10000, 0.0, 10000); + // We don't know where this stem is vertically, but we know from the beam arrangement that + // it's going to be crossed anyway, so we can space to it as if it had infinite height. + prevStemShape.adjust(0.0, -100000, 0.0, 100000); const Shape& staffShape = nextSeg->staffShape(staffIdx);