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 : #include "segmentlayout.h"
23 :
24 : #include "dom/part.h"
25 : #include "dom/drumset.h"
26 : #include "dom/parenthesis.h"
27 : #include "dom/staff.h"
28 :
29 : #include "tlayout.h"
30 : #include "chordlayout.h"
31 : #include "horizontalspacing.h"
32 :
33 : using namespace mu::engraving::rendering::score;
34 :
35 134513 : void SegmentLayout::layoutMeasureIndependentElements(const Segment& segment, track_idx_t track, const LayoutContext& ctx)
36 : {
37 : LAYOUT_CALL() << segment.typeName() << "(" << segment.eid() << ")";
38 :
39 134513 : if (segment.isJustType(SegmentType::KeySig)) {
40 6699 : KeySig* ks = toKeySig(segment.element(track));
41 6699 : if (ks) {
42 6443 : TLayout::layoutKeySig(ks, ks->mutldata(), ctx.conf()); // LD_INDEPENDENT
43 : }
44 127814 : } else if (segment.isJustType(SegmentType::Clef)) {
45 378 : Clef* cl = item_cast<Clef*>(segment.element(track));
46 378 : if (cl) {
47 286 : cl->setSmall(true);
48 286 : TLayout::layoutClef(cl, cl->mutldata(), ctx.conf()); // LD_INDEPENDENT
49 : }
50 127436 : } else if (segment.isType(SegmentType::HeaderClef)) {
51 6270 : Clef* cl = item_cast<Clef*>(segment.element(track));
52 6270 : if (cl) {
53 6101 : TLayout::layoutClef(cl, cl->mutldata(), ctx.conf()); // LD_INDEPENDENT
54 : }
55 121166 : } else if (segment.isType(SegmentType::TimeSig)) {
56 6189 : TimeSig* ts = item_cast<TimeSig*>(segment.element(track));
57 6189 : if (ts) {
58 6043 : TLayout::layoutTimeSig(ts, ts->mutldata(), ctx); // LD_INDEPENDENT
59 : }
60 114977 : } else if (segment.isType(SegmentType::Ambitus)) {
61 2 : Ambitus* am = item_cast<Ambitus*>(segment.element(track));
62 2 : if (am) {
63 2 : TLayout::layoutAmbitus(am, am->mutldata(), ctx); // LD_INDEPENDENT
64 : }
65 114975 : } else if (segment.isType(SegmentType::BarLine)) {
66 24 : BarLine* bl = toBarLine(segment.element(track));
67 24 : if (bl) {
68 : // check conditions (see TLayout::layoutBarLine)
69 : {
70 24 : for (const EngravingItem* e : *bl->el()) {
71 0 : if (e->isType(ElementType::ARTICULATION)) {
72 0 : LD_CONDITION(item_cast<const Articulation*>(e)->ldata()->symId.has_value());
73 : }
74 : }
75 : }
76 24 : TLayout::layoutBarLine(bl, bl->mutldata(), ctx);
77 : }
78 : }
79 134513 : }
80 :
81 87846 : void SegmentLayout::setChordMag(const Staff* staff, const Segment& segment, track_idx_t startTrack, track_idx_t endTrack,
82 : const LayoutConfiguration& conf)
83 : {
84 : LAYOUT_CALL() << LAYOUT_ITEM_INFO(staff) << " " << segment.typeName() << "(" << segment.eid() << ")";
85 :
86 87846 : IF_ASSERT_FAILED(segment.isJustType(SegmentType::ChordRest)) {
87 0 : return;
88 : }
89 :
90 87846 : const double staffMag = staff->staffMag(&segment);
91 87846 : const double smallNoteMag = conf.styleD(Sid::smallNoteMag);
92 87846 : const double graceNoteMag = conf.styleD(Sid::graceNoteMag);
93 :
94 439230 : for (track_idx_t t = startTrack; t < endTrack; ++t) {
95 351384 : ChordRest* cr = segment.cr(t);
96 351384 : if (!cr) {
97 264283 : continue;
98 : }
99 :
100 87101 : double m = staffMag;
101 87101 : if (cr->isSmall()) {
102 308 : m *= smallNoteMag;
103 : }
104 :
105 87101 : if (cr->isChord()) {
106 48116 : double graceMag = m * graceNoteMag;
107 48116 : Chord* chord = toChord(cr);
108 49021 : for (Chord* c : chord->graceNotes()) {
109 905 : c->mutldata()->setMag(graceMag);
110 : }
111 : }
112 87101 : cr->mutldata()->setMag(m);
113 : }
114 : }
115 :
116 0 : void SegmentLayout::checkStaffMoveValidity(const Segment& segment, track_idx_t startTrack, track_idx_t endTrack)
117 : {
118 : LAYOUT_CALL() << segment.typeName() << "(" << segment.eid() << ")";
119 :
120 0 : IF_ASSERT_FAILED(segment.isJustType(SegmentType::ChordRest)) {
121 0 : return;
122 : }
123 :
124 0 : for (track_idx_t t = startTrack; t < endTrack; ++t) {
125 0 : ChordRest* cr = toChordRest(segment.element(t));
126 0 : if (cr) {
127 : // Check if requested cross-staff is possible
128 0 : if (cr->staffMove() || cr->storedStaffMove()) {
129 0 : cr->checkStaffMoveValidity();
130 : }
131 : }
132 : }
133 : }
134 :
135 87846 : void SegmentLayout::layoutChordDrumset(const Staff* staff, const Segment& segment, track_idx_t startTrack, track_idx_t endTrack,
136 : const LayoutConfiguration& conf)
137 : {
138 : LAYOUT_CALL() << LAYOUT_ITEM_INFO(staff) << " " << segment.typeName() << "(" << segment.eid() << ")";
139 :
140 87846 : IF_ASSERT_FAILED(segment.isJustType(SegmentType::ChordRest)) {
141 85853 : return;
142 : }
143 :
144 87846 : const Instrument* ins = staff->originPart(segment.tick())->instrument(segment.tick());
145 87846 : if (!ins->useDrumset()) {
146 85853 : return;
147 : }
148 :
149 1993 : const Drumset* drumset = ins->drumset();
150 1993 : IF_ASSERT_FAILED(drumset) {
151 0 : return;
152 : }
153 :
154 1993 : const StaffType* st = staff->staffTypeForElement(&segment);
155 :
156 1128 : auto layoutDrumset = [](Chord* c, const Drumset* drumset, const StaffType* st, double spatium)
157 : {
158 2305 : for (Note* note : c->notes()) {
159 1177 : int pitch = note->pitch();
160 1177 : if (!drumset->isValid(pitch)) {
161 : // LOGD("unmapped drum note %d", pitch);
162 1101 : } else if (!note->fixed()) {
163 1078 : note->undoChangeProperty(Pid::HEAD_GROUP, drumset->noteHead(pitch));
164 1078 : int line = drumset->line(pitch);
165 1078 : note->setLine(line);
166 :
167 1078 : int off = st->stepOffset();
168 1078 : double ld = st->lineDistance().val();
169 1078 : note->mutldata()->setPosY((line + off * 2.0) * spatium * .5 * ld);
170 : }
171 : }
172 1128 : };
173 :
174 1993 : double spatium = conf.spatium();
175 9965 : for (track_idx_t t = startTrack; t < endTrack; ++t) {
176 7972 : Chord* chord = item_cast<Chord*>(segment.element(t), CastMode::MAYBE_BAD); // maybe Rest
177 7972 : if (!chord) {
178 6856 : continue;
179 : }
180 :
181 1128 : for (Chord* c : chord->graceNotes()) {
182 12 : layoutDrumset(c, drumset, st, spatium);
183 : }
184 :
185 1116 : layoutDrumset(chord, drumset, st, spatium);
186 : }
187 : }
188 :
189 87846 : void SegmentLayout::computeChordsUp(const Segment& segment, track_idx_t startTrack, track_idx_t endTrack, const LayoutContext& ctx)
190 : {
191 87846 : IF_ASSERT_FAILED(segment.isJustType(SegmentType::ChordRest)) {
192 0 : return;
193 : }
194 :
195 439230 : for (track_idx_t t = startTrack; t < endTrack; ++t) {
196 351384 : ChordRest* cr = segment.cr(t);
197 351384 : if (!cr) {
198 264283 : continue;
199 : }
200 :
201 87101 : if (cr->isChord()) {
202 48116 : Chord* chord = toChord(cr);
203 :
204 49021 : for (Chord* c : chord->graceNotes()) {
205 905 : ChordLayout::computeUp(c, ctx);
206 : }
207 :
208 48116 : ChordLayout::computeUp(chord, ctx);
209 : }
210 : }
211 : }
212 :
213 87846 : void SegmentLayout::layoutChordsStem(const Segment& segment, track_idx_t startTrack, track_idx_t endTrack, const LayoutContext& ctx)
214 : {
215 87846 : IF_ASSERT_FAILED(segment.isJustType(SegmentType::ChordRest)) {
216 0 : return;
217 : }
218 :
219 439230 : for (track_idx_t t = startTrack; t < endTrack; ++t) {
220 351384 : ChordRest* cr = segment.cr(t);
221 351384 : if (!cr) {
222 264283 : continue;
223 : }
224 :
225 87101 : if (cr->isChord()) {
226 48116 : Chord* chord = toChord(cr);
227 :
228 49021 : for (Chord* c : chord->graceNotes()) {
229 905 : ChordLayout::layoutStem(c, ctx);
230 : }
231 :
232 48116 : ChordLayout::layoutStem(chord, ctx);
233 : // stem direction can change later during beam processing
234 : }
235 : }
236 : }
|