Line data Source code
1 : /*
2 : * SPDX-License-Identifier: GPL-3.0-only
3 : * MuseScore-Studio-CLA-applies
4 : *
5 : * MuseScore Studio
6 : * Music Composition & Notation
7 : *
8 : * Copyright (C) 2023 MuseScore Limited and others
9 : *
10 : * This program is free software: you can redistribute it and/or modify
11 : * it under the terms of the GNU General Public License version 3 as
12 : * published by the Free Software Foundation.
13 : *
14 : * This program is distributed in the hope that it will be useful,
15 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : * GNU General Public License for more details.
18 : *
19 : * You should have received a copy of the GNU General Public License
20 : * along with this program. If not, see <https://www.gnu.org/licenses/>.
21 : */
22 : #pragma once
23 :
24 : #include <vector>
25 :
26 : #include "layoutcontext.h"
27 :
28 : #include "../../dom/measure.h"
29 : #include "../../dom/segment.h"
30 : #include "../../dom/sharedpart.h"
31 : #include "../../types/types.h"
32 :
33 : namespace mu::engraving {
34 : class BarLine;
35 : class Bracket;
36 : class BracketItem;
37 : class Chord;
38 : class Dynamic;
39 : class Expression;
40 : class FiguredBass;
41 : class FretDiagram;
42 : class Harmony;
43 : class HarpPedalDiagram;
44 : class Image;
45 : class InstrumentChange;
46 : class Measure;
47 : class MeasureNumber;
48 : class MMRest;
49 : class MMRestRange;
50 : class Parenthesis;
51 : class RehearsalMark;
52 : class Score;
53 : class Segment;
54 : class SkylineLine;
55 : class Spanner;
56 : class StaffText;
57 : class Sticking;
58 : class System;
59 : class SystemText;
60 : class TempoText;
61 : class TimeSig;
62 : }
63 :
64 : namespace mu::engraving::rendering::score {
65 : class SystemLayout
66 : {
67 : public:
68 : static System* collectSystem(LayoutContext& ctx);
69 : static void layoutSystemElements(System* system, LayoutContext& ctx);
70 :
71 : static void layoutSystem(System* system, LayoutContext& ctx, double xo1);
72 :
73 : static void hideEmptyStaves(System* system, LayoutContext& ctx, bool isFirstSystem);
74 : static bool canChangeSysStaffVisibility(const System* system, const staff_idx_t staffIdx);
75 :
76 : static void layout2(System* system, LayoutContext& ctx);
77 : static void restoreLayout2(System* system, LayoutContext& ctx);
78 : static void setMeasureHeight(System* system, double height, const LayoutContext& ctx);
79 :
80 : static double minDistance(const System* top, const System* bottom, const LayoutContext& ctx);
81 :
82 : static void centerElementsBetweenStaves(const System* system);
83 : /* Centers the systems which were laid out during this layout but whose page was not
84 : * collected (e.g. the first system of the next page, re-laid out by a partial layout),
85 : * so centerElementsBetweenStaves has not been called for them yet. Call it after the
86 : * system/page collection loop, before any leftover systems are deleted. */
87 : static void centerPendingSystems(LayoutContext& ctx);
88 : static void centerBigTimeSigsAcrossStaves(const System* system);
89 :
90 : static void updateSkylineForElement(EngravingItem* element, const System* system, double yMove);
91 : static void removeElementFromSkyline(EngravingItem* element, const System* system);
92 :
93 : static void layoutSystemLockIndicators(System* system, LayoutContext& ctx);
94 : static void layoutPageLockIndicators(System* system);
95 :
96 : private:
97 : struct MeasureState
98 : {
99 : Measure* measure = nullptr;
100 : double measureWidth = 0.0;
101 : double measurePos = 0.0;
102 : std::map<EngravingItem*, PointF> elementPositions;
103 : std::map<EngravingItem*, double> elementWidths;
104 : std::map<SharedPart*, SharedTrackMap> sharedTrackMaps;
105 : bool curHeader = false;
106 : bool curTrailer = false;
107 :
108 : void clear();
109 :
110 : void restoreMeasure(LayoutContext& ctx);
111 : };
112 :
113 : struct ElementsToLayout
114 : {
115 : System* system;
116 : std::vector<Measure*> measures;
117 : std::vector<Segment*> segments;
118 :
119 : std::vector<ChordRest*> chordRests;
120 : std::vector<Chord*> chords;
121 : std::vector<BarLine*> barlines;
122 : std::vector<TimeSig*> timeSigAboveStaves;
123 :
124 : std::vector<MeasureNumber*> measureNumbers;
125 : std::vector<MMRestRange*> mmrRanges;
126 : std::vector<EngravingItem*> markersAndJumps;
127 :
128 : std::vector<Sticking*> stickings;
129 : std::vector<EngravingItem*> fermatasAndTremoloBars;
130 : std::vector<FiguredBass*> figuredBass;
131 : std::vector<Dynamic*> dynamics;
132 : std::vector<Expression*> expressions;
133 : std::vector<HarpPedalDiagram*> harpDiagrams;
134 : std::vector<FretDiagram*> fretDiagrams;
135 : std::vector<StaffTextBase*> staffText;
136 : std::vector<InstrumentChange*> instrChanges;
137 : std::vector<SystemText*> systemText;
138 : std::vector<EngravingItem*> playTechCapoStringTunTripletFeel;
139 : std::vector<RehearsalMark*> rehMarks;
140 : std::vector<TempoText*> tempoText;
141 : std::vector<Image*> images;
142 : std::vector<Parenthesis*> parenthesis;
143 : std::vector<Harmony*> harmonies;
144 : std::vector<PlayCountText*> playCountText;
145 :
146 : std::vector<Spanner*> slurs;
147 : std::vector<Spanner*> trills;
148 : std::vector<Spanner*> hairpins;
149 : std::vector<Spanner*> ottavas;
150 : std::vector<Spanner*> pedal;
151 : std::vector<Spanner*> voltas;
152 : std::vector<Spanner*> tempoChangeLines;
153 : std::vector<Spanner*> partialLyricsLines;
154 : std::vector<Spanner*> allOtherSpanners;
155 :
156 : std::vector<GuitarBend*> guitarBends;
157 :
158 7396 : ElementsToLayout(System* s)
159 7396 : : system(s) {}
160 : };
161 :
162 : static void collectElementsToLayout(Measure* measure, ElementsToLayout& elements, const LayoutContext& ctx);
163 : static void collectSpannersToLayout(ElementsToLayout& elements, const LayoutContext& ctx);
164 :
165 : static System* getNextSystem(LayoutContext& lc);
166 : static void createSkylines(const ElementsToLayout& elementsToLayout, LayoutContext& ctx);
167 : static void processLines(System* system, LayoutContext& ctx, const std::vector<Spanner*>& lines, bool align = false);
168 : static void layoutTies(Chord* ch, System* system, const Fraction& stick, LayoutContext& ctx);
169 : static void doLayoutTies(System* system, const std::vector<Segment*>& sl, const Fraction& stick, const Fraction& etick,
170 : LayoutContext& ctx);
171 : static void doLayoutNoteSpannersLinear(System* system, LayoutContext& ctx);
172 : static void layoutNoteAnchoredSpanners(System* system, Chord* chord);
173 : static void updateCrossBeams(System* system, LayoutContext& ctx);
174 : static bool measureHasCrossStuffOrModifiedBeams(const Measure* measure);
175 : static void restoreOldSystemLayout(System* system, LayoutContext& ctx);
176 : static void layoutTuplets(const std::vector<ChordRest*>& chordRests, LayoutContext& ctx);
177 :
178 : static void layoutTiesAndBends(const ElementsToLayout& elementsToLayout, LayoutContext& ctx);
179 :
180 : static double minVertSpaceForCrossStaffBeams(System* system, staff_idx_t staffIdx1, staff_idx_t staffIdx2, LayoutContext& ctx);
181 :
182 : struct CenterableItem {
183 : EngravingItem* item = nullptr;
184 : Shape shape; // x relative to the system, y relative to the upper staff of the item's gap
185 : bool isLyrics = false;
186 : bool onUpperGapStaff = false; // whether the item hangs below the upper staff of its gap or sits above the lower one
187 : };
188 :
189 : // The space between two vertically adjacent visible staves
190 : struct Gap {
191 : staff_idx_t upperStaffIdx = muse::nidx;
192 : staff_idx_t lowerStaffIdx = muse::nidx;
193 : double yStaffDiff = 0.0; // Inside a gap, everything is expressed relative to its upper staff, so we need the y diff between staves
194 : std::vector<CenterableItem> items;
195 : };
196 :
197 : static bool snapChainShouldBeCenteredBetweenStaves(EngravingItem* item, const System* system);
198 : static bool elementShouldBeCenteredBetweenStaves(const EngravingItem* item, const System* system, bool placeAbove);
199 : static bool mmRestShouldBeCenteredBetweenStaves(const MMRest* mmRest, const System* system);
200 : static bool whammyBarShouldBeCenteredBetweenStaves(const WhammyBarSegment* wbar, const System* system);
201 : static bool elementHasAnotherStackedOutside(const EngravingItem* element, const Shape& elementShape, const SkylineLine& skylineLine);
202 : static bool shapesStackVertically(const Shape& shape1, const Shape& shape2, double minHorizontalClearance);
203 : static void collectCenterableItems(const System* system, std::vector<Gap>& gaps, std::vector<MMRest*>& mmRestsToCenter);
204 : static std::vector<std::vector<const CenterableItem*> > groupItemsToCenterTogether(const std::vector<const CenterableItem*>& items,
205 : double minHorizontalClearance);
206 : static void centerItemsInGap(const Gap& gap, const System* system, double minHorizontalClearance);
207 : static double gapConvergeDistance(const std::vector<const CenterableItem*>& group, double yStaffDiff, double minHorizontalClearance);
208 : static double convergenceMoveFor(const CenterableItem* centerableItem, double convergeDistance);
209 : static void centerItemGroup(const std::vector<const CenterableItem*>& group, const System* system, const SkylineLine& upperSkyline,
210 : const SkylineLine& lowerSkyline, double yStaffDiff, double minHorizontalClearance);
211 : static void centerMMRestBetweenStaves(MMRest* mmRest, const System* system);
212 :
213 : static bool shouldBeJustified(System* system, double curSysWidth, double targetSystemWidth, LayoutContext& ctx);
214 :
215 : static void updateTimeSigAboveStavesXPos(System* system, LayoutContext& ctx);
216 : static void clearBigTimeSigNotShown(System* system, LayoutContext& ctx);
217 :
218 : static void layoutSticking(const std::vector<Sticking*> stickings, System* system, LayoutContext& ctx);
219 :
220 : static void layoutLyrics(const ElementsToLayout& elements, LayoutContext& ctx);
221 :
222 : static void layoutVoltas(const ElementsToLayout& elementsToLayout, LayoutContext& ctx);
223 :
224 : static void layoutDynamicExpressionAndHairpins(const ElementsToLayout& elementsToLayout, LayoutContext& ctx);
225 :
226 : static void layoutParenthesisAndBigTimeSigs(const ElementsToLayout& elementsToLayout);
227 :
228 : static void layoutHarmonies(const std::vector<Harmony*> harmonies, System* system, LayoutContext& ctx);
229 : static void layoutFretDiagrams(const ElementsToLayout& elements, System* system, LayoutContext& ctx);
230 :
231 : static void alignRests(const ElementsToLayout& elementsToLayout, LayoutContext& ctx);
232 : static void checkFullMeasureRestCollisions(const ElementsToLayout& elementsToLayout, LayoutContext& ctx);
233 : };
234 : }
|