LCOV - code coverage report
Current view: top level - src/engraving/dom - chord.h Coverage Total Hit
Test: filtered_coverage.info Lines: 91.0 % 78 71
Test Date: 2026-11-05 04:07:02

            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
        

Generated by: LCOV version 2.0-1