LCOV - code coverage report
Current view: top level - src/engraving/dom - segment.h Coverage Total Hit
Test: filtered_coverage.info Lines: 94.1 % 68 64
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              : #include "engravingitem.h"
      26              : 
      27              : namespace mu::engraving {
      28              : class Factory;
      29              : class Measure;
      30              : class Segment;
      31              : class ChordRest;
      32              : class Spanner;
      33              : class System;
      34              : 
      35              : //-------------------------------------------------------------------
      36              : //   SegmentType
      37              : //
      38              : //    Type values determine the order of segments for a given tick
      39              : //-------------------------------------------------------------------
      40              : 
      41              : enum class SegmentType {
      42              :     ///.\{
      43              :     Invalid               = 0x0,
      44              :     BeginBarLine          = 0x1,
      45              :     HeaderClef            = 0x2,
      46              :     KeySig                = 0x4,
      47              :     Ambitus               = 0x8,
      48              :     Breath                = 0x10,
      49              :     TimeSig               = 0x20,
      50              :     StartRepeatBarLine    = 0x40,
      51              :     ClefStartRepeatAnnounce    = 0x80,
      52              :     KeySigStartRepeatAnnounce  = 0x100,
      53              :     TimeSigStartRepeatAnnounce = 0x200,
      54              :     Clef                  = 0x400,
      55              :     BarLine               = 0x800,
      56              :     //--
      57              :     TimeTick              = 0x1000,
      58              :     ChordRest             = 0x2000,
      59              :     //--
      60              :     ClefRepeatAnnounce    = 0x4000,
      61              :     KeySigRepeatAnnounce  = 0x8000,
      62              :     TimeSigRepeatAnnounce = 0x10000,
      63              :     //--
      64              :     EndBarLine            = 0x20000,
      65              :     KeySigAnnounce        = 0x40000,
      66              :     TimeSigAnnounce       = 0x80000,
      67              :     //--
      68              :     All                   = -1,   ///< Includes all barline types
      69              :     /// Alias for `BeginBarLine | StartRepeatBarLine | BarLine | EndBarLine`
      70              :     BarLineTypes           = BeginBarLine | StartRepeatBarLine | BarLine | EndBarLine,
      71              :     CourtesyTimeSigTypes   = TimeSigAnnounce | TimeSigRepeatAnnounce | TimeSigStartRepeatAnnounce,
      72              :     CourtesyKeySigTypes    = KeySigAnnounce | KeySigRepeatAnnounce | KeySigStartRepeatAnnounce,
      73              :     CourtesyClefTypes      = ClefRepeatAnnounce | ClefStartRepeatAnnounce,
      74              :     TimeSigTypes           = TimeSig | CourtesyTimeSigTypes,
      75              :     KeySigTypes            = KeySig | CourtesyKeySigTypes,
      76              :     ClefTypes              = Clef | HeaderClef | CourtesyClefTypes,
      77              :     // Only types with non-null duration
      78              :     Duration              = TimeTick | ChordRest,
      79              :     ///\}
      80              : };
      81              : 
      82      1272073 : constexpr SegmentType operator|(const SegmentType t1, const SegmentType t2)
      83              : {
      84      1272073 :     return static_cast<SegmentType>(static_cast<int>(t1) | static_cast<int>(t2));
      85              : }
      86              : 
      87      5744439 : constexpr bool operator&(const SegmentType t1, const SegmentType t2)
      88              : {
      89      5744439 :     return static_cast<int>(t1) & static_cast<int>(t2);
      90              : }
      91              : 
      92            0 : constexpr SegmentType operator ~(const SegmentType& t)
      93              : {
      94            0 :     return static_cast<SegmentType>(~static_cast<int>(t));
      95              : }
      96              : 
      97              : //------------------------------------------------------------------------
      98              : //   @@ Segment
      99              : //    A segment holds all vertical aligned staff elements.
     100              : //    Segments are typed and contain only Elements of the same type.
     101              : //
     102              : //    All Elements in a segment start at the same tick. The Segment can store one EngravingItem for
     103              : //    each voice in each staff in the score.
     104              : //    Some elements (Clef, KeySig, TimeSig etc.) are assumed to always have voice zero
     105              : //    and can be found in _elist[staffIdx * VOICES];
     106              : 
     107              : //    Segments are children of Measures and store Clefs, KeySigs, TimeSigs,
     108              : //    BarLines and ChordRests.
     109              : //
     110              : //   @P annotations     array[EngravingItem]    the list of annotations (read only)
     111              : //   @P next            Segment           the next segment in the whole score; null at last score segment (read-only)
     112              : //   @P nextInMeasure   Segment           the next segment in measure; null at last measure segment (read-only)
     113              : //   @P prev            Segment           the previous segment in the whole score; null at first score segment (read-only)
     114              : //   @P prevInMeasure   Segment           the previous segment in measure; null at first measure segment (read-only)
     115              : //   @P segmentType     enum (Segment.All, .Ambitus, .BarLine, .Breath, .ChordRest, .Clef, .EndBarLine, .Invalid, .KeySig, .KeySigAnnounce, .StartRepeatBarLine, .TimeSig, .TimeSigAnnounce)
     116              : //   @P tick            int               midi tick position (read only)
     117              : //------------------------------------------------------------------------
     118              : 
     119              : class Segment final : public EngravingItem
     120              : {
     121       131841 :     OBJECT_ALLOCATOR(engraving, Segment)
     122         1316 :     DECLARE_CLASSOF(ElementType::SEGMENT)
     123              : 
     124              : protected:
     125              :     EngravingItem* getElement(staff_idx_t staff) const;       //??
     126              : 
     127              : public:
     128              : 
     129              :     ~Segment();
     130              : 
     131              :     void setOwnershipParent(DummyParentOr<Measure> parent);
     132              : 
     133            0 :     Segment* clone() const override { return new Segment(*this); }
     134              : 
     135              :     void setScore(Score*) override;
     136              : 
     137       686985 :     inline bool isActive() const { return !isTimeTickType() && enabled() && visible(); }
     138              : 
     139     18694839 :     Segment* next() const { return m_next; }
     140              :     Segment* next(SegmentType) const;
     141              :     Segment* nextActive() const;
     142              :     Segment* nextEnabled() const;
     143              :     Segment* nextInStaff(staff_idx_t staffIdx, SegmentType t = SegmentType::ChordRest) const;
     144       136919 :     void setNext(Segment* e) { m_next = e; }
     145              : 
     146      4540394 :     Segment* prev() const { return m_prev; }
     147              :     Segment* prev(SegmentType) const;
     148              :     Segment* prevWithElementsOnTrack(track_idx_t trackIdx, SegmentType segType = SegmentType::ChordRest) const;
     149              :     Segment* prevActive() const;
     150              :     Segment* prevEnabled() const;
     151       120407 :     void setPrev(Segment* e) { m_prev = e; }
     152              : 
     153              :     // don’t stop at measure boundary:
     154              :     Segment* next1() const;
     155              :     Segment* next1enabled() const;
     156              :     Segment* next1MM() const;
     157              :     Segment* next1MMenabled() const;
     158              :     Segment* next1(SegmentType) const;
     159              :     Segment* next1WithElemsOnStaff(staff_idx_t staffIdx, SegmentType segType = SegmentType::ChordRest) const;
     160              :     Segment* next1WithElemsOnTrack(track_idx_t trackIdx, SegmentType segType = SegmentType::ChordRest) const;
     161              :     Segment* next1MM(SegmentType) const;
     162              : 
     163              :     Segment* prev1() const;
     164              :     Segment* prev1WithElemsOnStaff(staff_idx_t staffIdx, SegmentType segType = SegmentType::ChordRest) const;
     165              :     Segment* prev1WithElemsOnTrack(track_idx_t trackIdx, SegmentType segType = SegmentType::ChordRest) const;
     166              :     Segment* prev1enabled() const;
     167              :     Segment* prev1MM() const;
     168              :     Segment* prev1MMenabled() const;
     169              :     Segment* prev1(SegmentType) const;
     170              :     Segment* prev1MM(SegmentType) const;
     171              : 
     172              :     Segment* nextCR(track_idx_t track = muse::nidx, bool sameStaff = false) const;
     173              : 
     174              :     ChordRest* nextChordRest(track_idx_t track, bool backwards = false, bool stopAtMeasureBoundary = false) const;
     175              : 
     176              :     EngravingItem* element(track_idx_t track) const;
     177              : 
     178      2840690 :     const std::vector<EngravingItem*>& elist() const { return m_elist; }
     179       831480 :     std::vector<EngravingItem*>& elist() { return m_elist; }
     180              : 
     181              :     void removeElement(track_idx_t track);
     182              :     void setElement(track_idx_t track, EngravingItem* el);
     183              :     void scanElements(std::function<void(EngravingItem*)> func) override;
     184              : 
     185     15717397 :     Measure* measure() const { return toMeasure(ownershipParent()); }
     186              :     System* system() const;
     187       474208 :     double x() const override { return ldata()->pos().x(); }
     188              : 
     189              :     void insertStaff(staff_idx_t staff);
     190              :     void removeStaff(staff_idx_t staff);
     191              : 
     192              :     void add(EngravingItem*) override;
     193              :     void remove(EngravingItem*) override;
     194              :     void swapElements(track_idx_t i1, track_idx_t i2);
     195              : 
     196              :     void sortStaves(std::vector<staff_idx_t>& dst);
     197              :     const char* subTypeName() const;
     198              : 
     199              :     static const char* subTypeName(SegmentType);
     200              :     static SegmentType segmentType(ElementType type);
     201              : 
     202      7282686 :     SegmentType segmentType() const { return m_segmentType; }
     203              :     void setSegmentType(SegmentType t);
     204              : 
     205         6287 :     bool empty() const { return flag(ElementFlag::EMPTY); }
     206        38788 :     bool written() const { return flag(ElementFlag::WRITTEN); }
     207        73740 :     void setWritten(bool val) const { setFlag(ElementFlag::WRITTEN, val); }
     208        97075 :     bool endOfMeasureChange() const { return flag(ElementFlag::END_OF_MEASURE_CHANGE); }         // Key/time sigs which should be placed at the end of the measure
     209           16 :     void setEndOfMeasureChange(bool val) const { setFlag(ElementFlag::END_OF_MEASURE_CHANGE, val); }
     210              : 
     211              :     void fixStaffIdx();
     212              : 
     213        64021 :     double stretch() const { return m_stretch; }
     214       171215 :     void setStretch(double v) { m_stretch = v; }
     215              : 
     216      6455217 :     Fraction rtick() const override { return m_tick; }
     217        21391 :     void setRtick(const Fraction& v) { assert(v >= Fraction(0, 1)); m_tick = v; }
     218              :     Fraction tick() const override;
     219              : 
     220      1099692 :     Fraction ticks() const { return m_ticks; }
     221        97209 :     void setTicks(const Fraction& v) { m_ticks = v; }
     222              : 
     223              :     double widthInStaff(staff_idx_t staffIdx, SegmentType nextSegType = SegmentType::ChordRest) const;
     224              :     Fraction ticksInStaff(staff_idx_t staffIdx) const;
     225              : 
     226              :     bool splitsTuplet() const;
     227              : 
     228      1046658 :     const std::vector<EngravingItem*>& annotations() const { return m_annotations; }
     229              :     void clearAnnotations();
     230              :     void removeAnnotation(EngravingItem* e);
     231              :     bool hasAnnotationOrElement(ElementType type, track_idx_t minTrack, track_idx_t maxTrack) const;
     232              :     bool hasAnnotationOrElement(staff_idx_t staffIdx) const;
     233              :     EngravingItem* findAnnotation(ElementType type, track_idx_t minTrack, track_idx_t maxTrack) const;
     234              :     std::vector<EngravingItem*> findAnnotations(ElementType type, track_idx_t minTrack, track_idx_t maxTrack) const;
     235              :     bool hasElements() const;
     236              :     bool hasElements(track_idx_t minTrack, track_idx_t maxTrack) const;
     237              :     bool hasElements(staff_idx_t staffIdx) const;
     238              :     bool allElementsInvisible() const;
     239              : 
     240       488312 :     Spatium extraLeadingSpace() const { return m_extraLeadingSpace; }
     241            0 :     void setExtraLeadingSpace(Spatium v) { m_extraLeadingSpace = v; }
     242              : 
     243              :     PropertyValue getProperty(Pid propertyId) const override;
     244              :     bool setProperty(Pid propertyId, const PropertyValue&) override;
     245              :     PropertyValue propertyDefault(Pid) const override;
     246              : 
     247              :     bool operator<(const Segment&) const;
     248              :     bool operator>(const Segment&) const;
     249              : 
     250              :     String accessibleExtraInfo() const override;
     251              : 
     252              : #ifndef ENGRAVING_NO_ACCESSIBILITY
     253              :     AccessibleItemPtr createAccessible() override;
     254              : #endif
     255              : 
     256              :     EngravingItem* firstInNextSegments(staff_idx_t activeStaff) const;   //<
     257              :     EngravingItem* lastInPrevSegments(staff_idx_t activeStaff) const;     //<
     258              :     EngravingItem* firstElementForNavigation(staff_idx_t staff) const;          //<  These methods are used for navigation
     259              :     EngravingItem* lastElementForNavigation(staff_idx_t staff) const;           //<  for next-element and prev-element
     260              :     EngravingItem* firstElementOfSegment(staff_idx_t activeStaff) const;
     261              :     EngravingItem* nextElementOfSegment(EngravingItem* e, staff_idx_t activeStaff) const;
     262              :     EngravingItem* prevElementOfSegment(EngravingItem* e, staff_idx_t activeStaff) const;
     263              :     EngravingItem* lastElementOfSegment(staff_idx_t activeStaff) const;
     264              :     EngravingItem* nextAnnotation(EngravingItem* e) const;
     265              :     EngravingItem* prevAnnotation(EngravingItem* e) const;
     266              :     EngravingItem* firstAnnotation(staff_idx_t activeStaff) const;
     267              :     EngravingItem* lastAnnotation(staff_idx_t activeStaff) const;
     268              :     Spanner* firstSpanner(staff_idx_t activeStaff) const;
     269              :     Spanner* lastSpanner(staff_idx_t activeStaff) const;
     270              :     bool notChordRestType() const;
     271              :     using EngravingItem::nextElement;
     272              :     EngravingItem* nextElement(staff_idx_t activeStaff);
     273              :     using EngravingItem::prevElement;
     274              :     EngravingItem* prevElement(staff_idx_t activeStaff);
     275              : 
     276              :     EngravingItem* firstElement(staff_idx_t staffIdx) const;
     277              : 
     278       360099 :     std::vector<Shape> shapes() { return m_shapes; }
     279      1776906 :     const std::vector<Shape>& shapes() const { return m_shapes; }
     280      3211820 :     const Shape& staffShape(staff_idx_t staffIdx) const { return m_shapes[staffIdx]; }
     281        40149 :     Shape& staffShape(staff_idx_t staffIdx) { return m_shapes[staffIdx]; }
     282              :     void createShapes();
     283              :     void createShape(staff_idx_t staffIdx);
     284              :     double minRight() const;
     285              :     double minLeft() const;
     286              : 
     287       125340 :     double widthOffset() const { return m_widthOffset; }
     288       287865 :     void clearWidthOffset() { m_widthOffset = 0.0; }
     289         1762 :     void addWidthOffset(double w) { m_widthOffset += w; }
     290              :     void setWidthOffset(double w) { m_widthOffset = w; }
     291              : 
     292              :     double elementsTopOffsetFromSkyline(staff_idx_t staffIndex) const;
     293              :     double elementsBottomOffsetFromSkyline(staff_idx_t staffIndex) const;
     294              : 
     295              :     //! spacing is additional width of segment, for example accidental needs this spacing to avoid overlapping
     296              :     void setSpacing(double);
     297              :     double spacing() const;
     298              : 
     299              :     // some helper function
     300      6108387 :     ChordRest* cr(track_idx_t track) const { return toChordRest(m_elist[track]); }
     301      6027989 :     bool isType(const SegmentType t) const { return int(m_segmentType) & int(t); }
     302      1509598 :     bool isJustType(const SegmentType t) const { return m_segmentType == t; }
     303          883 :     bool isBeginBarLineType() const { return m_segmentType == SegmentType::BeginBarLine; }
     304      1331100 :     bool isClefType() const { return m_segmentType == SegmentType::Clef; }
     305       737053 :     bool isHeaderClefType() const { return m_segmentType == SegmentType::HeaderClef; }
     306       571426 :     bool isKeySigType() const { return m_segmentType == SegmentType::KeySig; }
     307              :     bool isAmbitusType() const { return m_segmentType == SegmentType::Ambitus; }
     308       642946 :     bool isTimeSigType() const { return m_segmentType == SegmentType::TimeSig; }
     309              :     bool hasTimeSigAboveStaves() const;
     310              :     bool makeSpaceForTimeSigAboveStaves() const;
     311              :     bool hasTimeSigAcrossStaves() const;
     312      1070774 :     bool isStartRepeatBarLineType() const { return m_segmentType == SegmentType::StartRepeatBarLine; }
     313            9 :     bool isBarLineType() const { return m_segmentType == SegmentType::BarLine; }
     314       866136 :     bool isBreathType() const { return m_segmentType == SegmentType::Breath; }
     315     16366832 :     bool isChordRestType() const { return m_segmentType == SegmentType::ChordRest; }
     316        33647 :     bool isClefRepeatAnnounceType() const { return m_segmentType == SegmentType::ClefRepeatAnnounce; }
     317        31723 :     bool isKeySigRepeatAnnounceType() const { return m_segmentType == SegmentType::KeySigRepeatAnnounce; }
     318        31698 :     bool isTimeSigRepeatAnnounceType() const { return m_segmentType == SegmentType::TimeSigRepeatAnnounce; }
     319       460258 :     bool isEndBarLineType() const { return m_segmentType == SegmentType::EndBarLine; }
     320        10257 :     bool isKeySigAnnounceType() const { return m_segmentType == SegmentType::KeySigAnnounce; }
     321        10465 :     bool isTimeSigAnnounceType() const { return m_segmentType == SegmentType::TimeSigAnnounce; }
     322        10511 :     bool isCourtesySegment() const
     323              :     {
     324        10511 :         return m_segmentType & (SegmentType::CourtesyTimeSigTypes | SegmentType::CourtesyKeySigTypes | SegmentType::CourtesyClefTypes);
     325              :     }
     326              : 
     327       979917 :     bool isTimeTickType() const { return m_segmentType == SegmentType::TimeTick; }
     328       757554 :     bool isRightAligned() const { return isClefType() || isBreathType(); }
     329       341064 :     bool isMMRestSegment() const { return isChordRestType() && m_elist.front() && m_elist.front()->isMMRest(); }
     330              : 
     331              :     bool canWriteSpannerStartEnd(track_idx_t track, const Spanner* spanner) const;
     332              : 
     333              :     Fraction shortestChordRest() const;
     334              : 
     335              :     bool hasAccidentals() const;
     336              : 
     337      3121540 :     EngravingItem* preAppendedItem(track_idx_t track) { return m_preAppendedItems[track]; }
     338         1028 :     void preAppend(EngravingItem* item, track_idx_t track) { m_preAppendedItems[track] = item; }
     339          531 :     void clearPreAppended(track_idx_t track) { m_preAppendedItems[track] = nullptr; }
     340              : 
     341              :     bool goesBefore(const Segment* nextSegment) const;
     342              : 
     343              :     void checkEmpty() const;
     344              : 
     345              :     double xPosInSystemCoords() const;
     346              :     void setXPosInSystemCoords(double x);
     347              : 
     348              :     bool isTupletSubdivisionOnStaff(staff_idx_t staffIdx) const;
     349              :     bool isInsideTupletOnStaff(staff_idx_t staffIdx) const;
     350              : 
     351              : private:
     352              : 
     353              :     void addArticulationsToShape(const Chord* chord, Shape& shape);
     354              : 
     355              :     friend class Factory;
     356              :     Segment(DummyParentOr<Measure> m);
     357              :     Segment(DummyParentOr<Measure>, SegmentType, const Fraction&);
     358              :     Segment(const Segment&);
     359              : 
     360              :     void init();
     361              :     void checkElement(EngravingItem*, track_idx_t track);
     362       110823 :     void setEmpty(bool val) const { setFlag(ElementFlag::EMPTY, val); }
     363              : 
     364              :     SegmentType m_segmentType = SegmentType::Invalid;
     365              :     Fraction m_tick;    // { Fraction(0, 1) };
     366              :     Fraction m_ticks;   // { Fraction(0, 1) };
     367              :     Spatium m_extraLeadingSpace;
     368              :     double m_stretch = 1.0;
     369              :     double m_widthOffset = 0.0; // part of the segment width that will not be stretched during system justification
     370              : 
     371              :     Segment* m_next = nullptr;                       // linked list of segments inside a measure
     372              :     Segment* m_prev = nullptr;
     373              : 
     374              :     std::vector<EngravingItem*> m_annotations;
     375              :     std::vector<EngravingItem*> m_elist;         // EngravingItem storage, size = staves * VOICES.
     376              :     std::vector<EngravingItem*> m_preAppendedItems; // Container for items appended to the left of this segment (example: grace notes), size = staves * VOICES.
     377              :     std::vector<Shape> m_shapes;           // size = staves
     378              :     double m_spacing = 0;
     379              : };
     380              : } // namespace mu::engraving
     381              : 
     382              : #ifndef NO_QT_SUPPORT
     383           16 : Q_DECLARE_METATYPE(mu::engraving::SegmentType)
     384              : #endif
        

Generated by: LCOV version 2.0-1