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) 2021 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 :
23 : #include "segmentlist.h"
24 : #include "segment.h"
25 : #include "score.h"
26 :
27 : #include "log.h"
28 :
29 : using namespace mu;
30 :
31 : namespace mu::engraving {
32 : //---------------------------------------------------------
33 : // clone
34 : //---------------------------------------------------------
35 :
36 0 : SegmentList SegmentList::clone() const
37 : {
38 0 : SegmentList dl;
39 0 : Segment* s = m_first;
40 0 : for (int i = 0; i < m_size; ++i) {
41 0 : Segment* ns = s->clone();
42 0 : dl.push_back(ns);
43 0 : s = s->next();
44 : }
45 0 : dl.check();
46 0 : return dl;
47 : }
48 :
49 0 : Segment* SegmentList::at(int index) const
50 : {
51 0 : Segment* s = m_first;
52 0 : for (int i = 0; i < m_size; ++i) {
53 0 : if (i == index) {
54 0 : return s;
55 : }
56 0 : s = s->next();
57 : }
58 0 : return nullptr;
59 : }
60 :
61 30515 : Segment* SegmentList::firstActive() const
62 : {
63 30515 : if (Segment* segment = m_first) {
64 30515 : return segment->isActive() ? segment : segment->nextActive();
65 : }
66 0 : return nullptr;
67 : }
68 :
69 : //---------------------------------------------------------
70 : // check
71 : //---------------------------------------------------------
72 :
73 : #ifndef NDEBUG
74 161786 : void SegmentList::check()
75 : {
76 161786 : int n = 0;
77 161786 : Segment* f = 0;
78 161786 : Segment* l = 0;
79 814127 : for (Segment* s = m_first; s; s = s->next()) {
80 652341 : if (f == 0) {
81 161786 : f = s;
82 : }
83 652341 : l = s;
84 652341 : ++n;
85 : }
86 814127 : for (Segment* s = m_first; s; s = s->next()) {
87 652341 : switch (s->segmentType()) {
88 652341 : case SegmentType::Invalid:
89 : case SegmentType::BeginBarLine:
90 : case SegmentType::HeaderClef:
91 : case SegmentType::Clef:
92 : case SegmentType::KeySig:
93 : case SegmentType::Ambitus:
94 : case SegmentType::TimeSig:
95 : case SegmentType::StartRepeatBarLine:
96 : case SegmentType::BarLine:
97 : case SegmentType::ChordRest:
98 : case SegmentType::Breath:
99 : case SegmentType::ClefRepeatAnnounce:
100 : case SegmentType::TimeSigRepeatAnnounce:
101 : case SegmentType::KeySigRepeatAnnounce:
102 : case SegmentType::ClefStartRepeatAnnounce:
103 : case SegmentType::TimeSigStartRepeatAnnounce:
104 : case SegmentType::KeySigStartRepeatAnnounce:
105 : case SegmentType::EndBarLine:
106 : case SegmentType::TimeSigAnnounce:
107 : case SegmentType::KeySigAnnounce:
108 : case SegmentType::TimeTick:
109 652341 : break;
110 0 : default:
111 0 : ASSERT_X(String(u"SegmentList::check: invalid segment type: %1").arg(int(s->segmentType())));
112 : break;
113 : }
114 652341 : Segment* ss = s->next();
115 2622346 : while (ss) {
116 1970005 : if (s == ss) {
117 0 : ASSERT_X("SegmentList::check: segment twice in list");
118 : }
119 1970005 : ss = ss->next();
120 : }
121 : }
122 161786 : if (f != m_first) {
123 0 : ASSERT_X("SegmentList::check: bad first");
124 : }
125 161786 : if (l != m_last) {
126 0 : ASSERT_X("SegmentList::check: bad last");
127 : }
128 161786 : if (f && f->prev()) {
129 0 : ASSERT_X("SegmentList::check: first has prev");
130 : }
131 161786 : if (l && l->next()) {
132 0 : ASSERT_X("SegmentList::check: last has next");
133 : }
134 161786 : if (n != m_size) {
135 0 : ASSERT_X(String(u"SegmentList::check: counted %1 but _size is %d2").arg(n, m_size));
136 : m_size = n;
137 : }
138 161786 : }
139 :
140 : #endif
141 :
142 : //---------------------------------------------------------
143 : // insert
144 : /// Insert Segment \a e before Segment \a el.
145 : //---------------------------------------------------------
146 :
147 81092 : void SegmentList::insert(Segment* e, Segment* el)
148 : {
149 81092 : if (el == 0) {
150 56079 : push_back(e);
151 25013 : } else if (el == first()) {
152 10183 : push_front(e);
153 : } else {
154 14830 : ++m_size;
155 14830 : e->setNext(el);
156 14830 : e->setPrev(el->prev());
157 14830 : el->prev()->setNext(e);
158 14830 : el->setPrev(e);
159 : }
160 81092 : check();
161 81092 : }
162 :
163 : //---------------------------------------------------------
164 : // remove
165 : //---------------------------------------------------------
166 :
167 14432 : void SegmentList::remove(Segment* e)
168 : {
169 : #ifndef NDEBUG
170 14432 : check();
171 14432 : bool found = false;
172 21943 : for (Segment* s = m_first; s; s = s->next()) {
173 21943 : if (e == s) {
174 14432 : found = true;
175 14432 : break;
176 : }
177 : }
178 14432 : if (!found) {
179 0 : ASSERT_X(String(u"segment %1 not in list").arg(String::fromAscii(e->subTypeName())));
180 : }
181 : #endif
182 14432 : --m_size;
183 14432 : if (e == m_first) {
184 12325 : m_first = m_first->next();
185 12325 : if (m_first) {
186 12292 : m_first->setPrev(0);
187 : }
188 12325 : if (e == m_last) {
189 33 : m_last = 0;
190 : }
191 2107 : } else if (e == m_last) {
192 97 : m_last = m_last->prev();
193 97 : if (m_last) {
194 97 : m_last->setNext(0);
195 : }
196 : } else {
197 2010 : e->prev()->setNext(e->next());
198 2010 : e->next()->setPrev(e->prev());
199 : }
200 14432 : }
201 :
202 : //---------------------------------------------------------
203 : // push_back
204 : //---------------------------------------------------------
205 :
206 56079 : void SegmentList::push_back(Segment* e)
207 : {
208 56079 : ++m_size;
209 56079 : e->setNext(0);
210 56079 : if (m_last) {
211 38890 : m_last->setNext(e);
212 : } else {
213 17189 : m_first = e;
214 : }
215 56079 : e->setPrev(m_last);
216 56079 : m_last = e;
217 56079 : check();
218 56079 : }
219 :
220 : //---------------------------------------------------------
221 : // push_front
222 : //---------------------------------------------------------
223 :
224 10183 : void SegmentList::push_front(Segment* e)
225 : {
226 10183 : ++m_size;
227 10183 : e->setPrev(0);
228 10183 : if (m_first) {
229 10183 : m_first->setPrev(e);
230 : } else {
231 0 : m_last = e;
232 : }
233 10183 : e->setNext(m_first);
234 10183 : m_first = e;
235 10183 : check();
236 10183 : }
237 :
238 : //---------------------------------------------------------
239 : // firstCRSegment
240 : //---------------------------------------------------------
241 :
242 10355 : Segment* SegmentList::firstCRSegment() const
243 : {
244 10355 : return first(SegmentType::ChordRest);
245 : }
246 :
247 : //---------------------------------------------------------
248 : // first
249 : //---------------------------------------------------------
250 :
251 834439 : Segment* SegmentList::first(SegmentType types) const
252 : {
253 1430404 : for (Segment* s = m_first; s; s = s->next()) {
254 1398968 : if (s->segmentType() & types) {
255 803003 : return s;
256 : }
257 : }
258 31436 : return 0;
259 : }
260 :
261 : //---------------------------------------------------------
262 : // first
263 : //---------------------------------------------------------
264 :
265 131313 : Segment* SegmentList::first(ElementFlag flags) const
266 : {
267 134467 : for (Segment* s = m_first; s; s = s->next()) {
268 134467 : if (s->flag(flags)) {
269 131313 : return s;
270 : }
271 : }
272 0 : return nullptr;
273 : }
274 :
275 : //---------------------------------------------------------
276 : // last
277 : //---------------------------------------------------------
278 :
279 4893 : Segment* SegmentList::last(ElementFlag flags) const
280 : {
281 4894 : for (Segment* s = m_last; s; s = s->prev()) {
282 4894 : if (s->flag(flags)) {
283 4893 : return s;
284 : }
285 : }
286 0 : return nullptr;
287 : }
288 :
289 1136 : Segment* SegmentList::last(SegmentType types) const
290 : {
291 1649 : for (Segment* s = m_last; s; s = s->prev()) {
292 1621 : if (s->segmentType() & types) {
293 1108 : return s;
294 : }
295 : }
296 28 : return nullptr;
297 : }
298 : }
|