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 : #pragma once
24 :
25 : /**
26 : \file
27 : Definition of classes Chord, HelpLine and NoteList.
28 : */
29 :
30 : #include <functional>
31 : #include <set>
32 : #include <vector>
33 :
34 : #include "articulation.h"
35 : #include "chordrest.h"
36 :
37 : #include "draw/types/color.h"
38 :
39 : namespace mu::engraving {
40 : class AccidentalState;
41 : class Arpeggio;
42 : class Chord;
43 : class Hook;
44 : class LedgerLine;
45 : class Note;
46 : class NoteEventList;
47 : class Stem;
48 : class StemSlash;
49 : class Transaction;
50 : class TremoloSingleChord;
51 : class TremoloTwoChord;
52 :
53 : enum class NoteType : unsigned char {
54 : ///.\{
55 : NORMAL = 0,
56 : ACCIACCATURA = 0x1,
57 : APPOGGIATURA = 0x2, // grace notes
58 : GRACE4 = 0x4,
59 : GRACE16 = 0x8,
60 : GRACE32 = 0x10,
61 : GRACE8_AFTER = 0x20,
62 : GRACE16_AFTER = 0x40,
63 : GRACE32_AFTER = 0x80,
64 : INVALID = 0xFF
65 : ///\}
66 : };
67 :
68 123754 : constexpr NoteType operator|(NoteType t1, NoteType t2)
69 : {
70 123754 : return static_cast<NoteType>(static_cast<unsigned char>(t1) | static_cast<unsigned char>(t2));
71 : }
72 :
73 45688 : constexpr bool operator&(NoteType t1, NoteType t2)
74 : {
75 45688 : return static_cast<unsigned char>(t1) & static_cast<unsigned char>(t2);
76 : }
77 :
78 : enum class PlayEventType : unsigned char {
79 : ///.\{
80 : Auto, ///< Play events for all notes are calculated by MuseScore.
81 : User, ///< Some play events are modified by user. Those events are written into the mscx file.
82 : ///.\}
83 : };
84 :
85 : class GraceNotesGroup final : public std::vector<Chord*>, public EngravingItem
86 : {
87 0 : OBJECT_ALLOCATOR(engraving, GraceNotesGroup)
88 : public:
89 0 : GraceNotesGroup* clone() const override { return new GraceNotesGroup(*this); }
90 : GraceNotesGroup(DummyParentOr<Chord> c);
91 :
92 5717 : Chord* parent() const { return _parent; }
93 :
94 : void setPos(double x, double y) override;
95 1016 : Segment* appendedSegment() const { return _appendedSegment; }
96 1028 : void setAppendedSegment(Segment* s) { _appendedSegment = s; }
97 : void addToShape();
98 :
99 : private:
100 : Chord* _parent = nullptr;
101 : Segment* _appendedSegment = nullptr; // the graceNoteGroup is appended to this segment
102 : };
103 :
104 : //---------------------------------------------------------
105 : // @@ Chord
106 : /// Graphic representation of a chord.
107 : /// Single notes are handled as degenerated chords.
108 : //
109 : // @P beam Beam the beam of the chord, if any (read only)
110 : // @P graceNotes array[Chord] the list of grace note chords (read only)
111 : // @P hook Hook the hook of the chord, if any (read only)
112 : // @P lyrics array[Lyrics] the list of lyrics (read only)
113 : // @P notes array[Note] the list of notes (read only)
114 : // @P stem Stem the stem of the chord, if any (read only)
115 : // @P stemSlash StemSlash the stem slash of the chord (acciaccatura), if any (read only)
116 : // @P stemDirection Direction the stem direction of the chord: AUTO, UP, DOWN (read only)
117 : //---------------------------------------------------------
118 :
119 : struct NoteParenthesisInfo {
120 : NoteParenthesisInfo (Parenthesis* lParen, Parenthesis* rParen, std::vector<Note*> nList);
121 : ~NoteParenthesisInfo();
122 2376 : Parenthesis* leftParen() const { return m_leftParen; }
123 1925 : Parenthesis* rightParen() const { return m_rightParen; }
124 1196 : const std::vector<Note*>& notes() const { return m_notes; }
125 :
126 : void insertNote(Note* note);
127 : void removeNote(Note* note);
128 :
129 : private:
130 : Parenthesis* m_leftParen = nullptr;
131 : Parenthesis* m_rightParen = nullptr;
132 : std::vector<Note*> m_notes;
133 : };
134 :
135 : using NoteParenthesisInfoList = std::vector<NoteParenthesisInfo*>;
136 :
137 : class Chord final : public ChordRest
138 : {
139 63972 : OBJECT_ALLOCATOR(engraving, Chord)
140 1866 : DECLARE_CLASSOF(ElementType::CHORD)
141 :
142 : public:
143 :
144 : ~Chord();
145 : Chord& operator=(const Chord&) = delete;
146 :
147 : void scanElements(std::function<void(EngravingItem*)> func) override;
148 :
149 1953 : Chord* clone() const override { return new Chord(*this, false); }
150 1014 : EngravingItem* linkedClone() override { return new Chord(*this, true); }
151 : void undoUnlink() override;
152 :
153 : void setScore(Score* s) override;
154 : double intrinsicMag() const override;
155 : double mag() const override;
156 : double noteHeadWidth() const;
157 :
158 : EngravingItem* drop(Transaction& tx, EditData&) override;
159 :
160 : void setColor(const Color& c) override;
161 : void setStemDirection(DirectionV d);
162 136153 : DirectionV stemDirection() const { return m_stemDirection; }
163 :
164 : Chord* prev() const;
165 : Chord* next() const;
166 :
167 86567 : bool isUiItem() const { return m_isUiItem; }
168 0 : void setIsUiItem(bool val) { m_isUiItem = val; }
169 :
170 257979 : const std::vector<LedgerLine*>& ledgerLines() const { return m_ledgerLines; }
171 306521 : std::vector<LedgerLine*>& ledgerLines() { return m_ledgerLines; }
172 : void resizeLedgerLinesTo(size_t newSize);
173 :
174 230852 : double defaultStemLength() const { return m_defaultStemLength; }
175 144130 : void setDefaultStemLength(double l) { m_defaultStemLength = l; }
176 : void setBeamExtension(double extension);
177 :
178 1417580 : std::vector<Note*>& notes() { return m_notes; }
179 583957 : const std::vector<Note*>& notes() const { return m_notes; }
180 :
181 335996 : const NoteParenthesisInfoList& noteParentheses() const { return m_noteParens; }
182 : const NoteParenthesisInfo* findNoteParenthesisInfo(const Note* note) const;
183 : NoteParenthesisInfo* findNoteParenthesisInfo(const Parenthesis* paren);
184 : void addNoteParenthesisInfo(NoteParenthesisInfo* noteParenInfo);
185 : void removeNoteParenthesisInfo(const NoteParenthesisInfo* noteParenInfo);
186 : void addNoteToParenthesisInfo(Note* note, const Parenthesis* paren);
187 : void removeNoteFromParenthesisInfo(Note* note, const Parenthesis* paren);
188 :
189 : bool isChordPlayable() const;
190 : void setIsChordPlayable(const bool isPlayable);
191 :
192 : // Chord has at least one Note
193 : Note* upNote() const;
194 : Note* downNote() const;
195 : int upString() const;
196 : int downString() const;
197 : std::vector<int> noteDistances() const;
198 :
199 : double maxHeadWidth() const;
200 :
201 : Note* findNote(int pitch, int skip = 0) const;
202 :
203 2035471 : Stem* stem() const { return m_stem; }
204 445955 : Arpeggio* arpeggio() const { return m_arpeggio; }
205 80 : void setArpeggio(Arpeggio* a) { m_arpeggio = a; }
206 :
207 409822 : Arpeggio* spanArpeggio() const { return m_spanArpeggio; }
208 461 : void setSpanArpeggio(Arpeggio* a) { m_spanArpeggio = a; }
209 : void undoChangeSpanArpeggio(Arpeggio* a);
210 :
211 : TremoloType tremoloType() const;
212 : TremoloTwoChord* tremoloTwoChord() const;
213 : TremoloSingleChord* tremoloSingleChord() const;
214 :
215 : void setTremoloTwoChord(TremoloTwoChord* tr, bool applyLogic = true);
216 : void setTremoloSingleChord(TremoloSingleChord* tr);
217 :
218 : ChordLine* chordLine() const;
219 53420 : bool endsNoteAnchoredLine() const { return m_endsNoteAnchoredLine; }
220 558 : void setEndsNoteAnchoredLine(bool val) { m_endsNoteAnchoredLine = val; }
221 : void updateEndsNoteAnchoredLine();
222 498015 : StemSlash* stemSlash() const { return m_stemSlash; }
223 152878 : bool showStemSlash() const { return m_showStemSlash; }
224 : void setShowStemSlashInAdvance();
225 : void requestShowStemSlash(bool show);
226 725 : void setShowStemSlash(bool show) { m_showStemSlash = show; }
227 : bool slash();
228 : void setSlash(bool flag, bool stemless);
229 : void removeMarkings(bool keepTremolo = false) override;
230 :
231 88507 : const std::vector<Chord*>& graceNotes() const { return m_graceNotes; }
232 1298533 : std::vector<Chord*>& graceNotes() { return m_graceNotes; }
233 : std::vector<Chord*> allGraceChordsOfMainChord();
234 3 : void removeAllGraceNotes() { m_graceNotes.clear(); }
235 :
236 : GraceNotesGroup& graceNotesBefore(bool filterUnplayable = false) const;
237 : GraceNotesGroup& graceNotesAfter(bool filterUnplayable = false) const;
238 :
239 785 : size_t graceIndex() const { return m_graceIndex; }
240 1429 : void setGraceIndex(size_t val) { m_graceIndex = val; }
241 :
242 : Chord* graceNoteAt(size_t idx) const;
243 :
244 : int line(bool up) const { return up ? upLine() : downLine(); }
245 86664 : int line() const { return ldata()->up ? upLine() : downLine(); }
246 : int upLine() const;
247 : int downLine() const;
248 : double rightEdge() const override;
249 :
250 : bool underBeam() const;
251 1583173 : Hook* hook() const { return m_hook; }
252 0 : void setHook(Hook* h) { m_hook = h; }
253 :
254 : void add(EngravingItem*) override;
255 : void remove(EngravingItem*) override;
256 :
257 : Note* selectedNote() const;
258 :
259 : PointF pagePos() const override; ///< position in page coordinates
260 : void cmdUpdateNotes(AccidentalState*, staff_idx_t staffIdx);
261 :
262 1670847 : NoteType noteType() const { return m_noteType; }
263 : void setNoteType(NoteType t);
264 733415 : bool isGrace() const { return m_noteType != NoteType::NORMAL; }
265 : void toGraceAfter();
266 :
267 : bool isPreBendOrGraceBendStart() const;
268 : bool isGraceBendEnd() const;
269 :
270 18944 : bool isTrillCueNote() const { return m_isTrillCueNote; }
271 : void setIsTrillCueNote(bool v);
272 :
273 : void setTrack(track_idx_t val) override;
274 :
275 1945 : double dotPosX() const { return m_dotPosX; }
276 50852 : void setDotPosX(double x) { m_dotPosX = x; }
277 :
278 24416 : bool noStem() const { return m_noStem; }
279 7085 : void setNoStem(bool val) { m_noStem = val; }
280 :
281 358 : double spaceLw() { return m_spaceLw; }
282 50781 : void setSpaceLw(double lw) { m_spaceLw = lw; }
283 204 : double spaceRw() { return m_spaceRw; }
284 50770 : void setSpaceRw(double rw) { m_spaceRw = rw; }
285 :
286 222467 : AutoOnOff combineVoice() const { return m_combineVoice; }
287 0 : void setCombineVoice(AutoOnOff v) { m_combineVoice = v; }
288 : bool shouldCombineVoice() const;
289 : static bool combineVoice(const Chord* chord1, const Chord* chord2);
290 :
291 23921 : PlayEventType playEventType() const { return m_playEventType; }
292 92 : void setPlayEventType(PlayEventType v) { m_playEventType = v; }
293 : std::vector<NoteEventList> getNoteEventLists();
294 : void setNoteEventLists(std::vector<NoteEventList>& nel);
295 :
296 : TremoloChordType tremoloChordType() const;
297 :
298 330982 : std::vector<Articulation*>& articulations() { return m_articulations; }
299 441153 : const std::vector<Articulation*>& articulations() const { return m_articulations; }
300 : std::set<SymId> articulationSymbolIds() const;
301 : Articulation* hasArticulation(const Articulation*);
302 : Tapping* tapping() const;
303 : bool hasSingleArticulation() const { return m_articulations.size() == 1; }
304 :
305 : void updateArticulations(const std::set<SymId>& newArticulationIds,
306 : ArticulationsUpdateMode replaceMode = ArticulationsUpdateMode::Insert);
307 :
308 : void localSpatiumChanged(double oldValue, double newValue) override;
309 : PropertyValue getProperty(Pid propertyId) const override;
310 : bool setProperty(Pid propertyId, const PropertyValue&) override;
311 : PropertyValue propertyDefault(Pid) const override;
312 : bool isUserModified() const override;
313 :
314 : void reset() override;
315 :
316 : Segment* segment() const override;
317 : Measure* measure() const override;
318 :
319 : void sortNotes();
320 :
321 : Chord* nextTiedChord(bool backwards = false, bool sameSize = true) const;
322 :
323 : Fraction endTickIncludingTied() const;
324 :
325 : EngravingItem* nextElement() override;
326 : EngravingItem* prevElement() override;
327 : EngravingItem* nextSegmentElement() override;
328 : EngravingItem* lastElementBeforeSegment();
329 : EngravingItem* prevSegmentElement() override;
330 :
331 : String accessibleExtraInfo() const override;
332 :
333 : Note* firstGraceOrNote();
334 :
335 : #ifndef ENGRAVING_NO_ACCESSIBILITY
336 : AccessibleItemPtr createAccessible() override;
337 : #endif
338 :
339 : void undoChangeProperty(Pid id, const PropertyValue& newValue);
340 : void undoChangeProperty(Pid id, const PropertyValue& newValue, PropertyFlags ps) override;
341 :
342 : void styleChanged() override;
343 :
344 349937 : bool allowKerningAbove() const { return m_allowKerningAbove; }
345 346219 : bool allowKerningBelow() const { return m_allowKerningBelow; }
346 : void computeKerningExceptions();
347 :
348 : Ornament* findOrnament(bool forPlayback = false) const;
349 :
350 98364 : const std::set<Spanner*>& startingSpanners() const { return m_startingSpanners; }
351 51681 : const std::set<Spanner*>& endingSpanners() const { return m_endingSpanners; }
352 3895 : void addStartingSpanner(Spanner* spanner) { m_startingSpanners.insert(spanner); }
353 3220 : void removeStartingSpanner(Spanner* spanner) { m_startingSpanners.erase(spanner); }
354 4225 : void addEndingSpanner(Spanner* spanner) { m_endingSpanners.insert(spanner); }
355 2650 : void removeEndingSpanner(Spanner* spanner) { m_endingSpanners.erase(spanner); }
356 :
357 : bool shouldHaveStem() const;
358 : bool shouldHaveHook() const;
359 : void createStem();
360 : void removeStem();
361 : void createHook();
362 :
363 : double upPos() const override;
364 : double downPos() const override;
365 :
366 : struct StartEndSlurs {
367 : bool startUp = false;
368 : bool startDown = false;
369 : bool endUp = false;
370 : bool endDown = false;
371 51681 : void reset()
372 : {
373 51681 : startUp = false;
374 51681 : startDown = false;
375 51681 : endUp = false;
376 51681 : endDown = false;
377 51681 : }
378 : };
379 :
380 53556 : StartEndSlurs& startEndSlurs() { return m_startEndSlurs; }
381 :
382 : bool allNotesTiedToNext() const;
383 : bool allElementsInvisible() const;
384 :
385 : private:
386 :
387 : friend class Factory;
388 :
389 : Chord(DummyParentOr<Segment> parent);
390 : Chord(const Chord&, bool link = false);
391 :
392 : // `includeTemporarySiblings`: whether items that are deleted & recreated during every layout should also be processed
393 : void processSiblings(std::function<void(EngravingItem*)> func, bool includeTemporarySiblings) const;
394 :
395 : std::vector<Note*> m_notes; // sorted to decreasing line step
396 : std::vector<LedgerLine*> m_ledgerLines;
397 : NoteParenthesisInfoList m_noteParens;
398 :
399 : Stem* m_stem = nullptr;
400 : Hook* m_hook = nullptr;
401 : StemSlash* m_stemSlash = nullptr; // for grace notes
402 : bool m_showStemSlash = false;
403 :
404 : Arpeggio* m_arpeggio = nullptr; // arpeggio which starts on the chord
405 : Arpeggio* m_spanArpeggio = nullptr; // arpeggio which spans over this chord
406 :
407 : TremoloTwoChord* m_tremoloTwoChord = nullptr;
408 : TremoloSingleChord* m_tremoloSingleChord = nullptr;
409 :
410 : bool m_endsNoteAnchoredLine = false; // true if this chord is the ending point of a glissando (needed for layout)
411 : std::vector<Chord*> m_graceNotes; // storage for all grace notes
412 : mutable GraceNotesGroup m_graceNotesBefore = GraceNotesGroup(this); // will store before-chord grace notes
413 : mutable GraceNotesGroup m_graceNotesAfter = GraceNotesGroup(this); // will store after-chord grace notes
414 : size_t m_graceIndex = 0; // if this is a grace note, index in parent list
415 :
416 : bool m_isTrillCueNote = false;
417 :
418 : DirectionV m_stemDirection = DirectionV::AUTO;
419 : NoteType m_noteType = NoteType::NORMAL; // mark grace notes: acciaccatura and appoggiatura
420 : bool m_noStem = false;
421 : PlayEventType m_playEventType = PlayEventType::Auto; // play events were modified by user
422 :
423 : double m_spaceLw = 0.0;
424 : double m_spaceRw = 0.0;
425 :
426 : double m_defaultStemLength = 0.0;
427 :
428 : bool m_isUiItem = false;
429 :
430 : double m_dotPosX = 0.0;
431 :
432 : StartEndSlurs m_startEndSlurs;
433 :
434 : std::set<Spanner*> m_startingSpanners; // spanners starting on this item
435 : std::set<Spanner*> m_endingSpanners; // spanners ending on this item
436 :
437 : bool m_allowKerningAbove = true;
438 : bool m_allowKerningBelow = true;
439 :
440 : AutoOnOff m_combineVoice = AutoOnOff::AUTO;
441 :
442 : std::vector<Articulation*> m_articulations;
443 : };
444 : } // namespace mu::engraving
445 :
446 : #ifndef NO_QT_SUPPORT
447 0 : Q_DECLARE_METATYPE(mu::engraving::NoteType)
448 0 : Q_DECLARE_METATYPE(mu::engraving::PlayEventType)
449 : #endif
|