LCOV - code coverage report
Current view: top level - src/engraving/dom - spanner.h Coverage Total Hit
Test: filtered_coverage.info Lines: 88.1 % 42 37
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 <deque>
      26              : 
      27              : #include "draw/types/color.h"
      28              : 
      29              : #include "../types/types.h"
      30              : 
      31              : #include "engravingitem.h"
      32              : 
      33              : namespace mu::engraving {
      34              : class Spanner;
      35              : 
      36              : //---------------------------------------------------------
      37              : //   @@ SpannerSegment
      38              : //!    parent: the Spanner it belongs to; placed on a System during layout
      39              : //---------------------------------------------------------
      40              : 
      41              : class SpannerSegment : public EngravingItem
      42              : {
      43            0 :     OBJECT_ALLOCATOR(engraving, SpannerSegment)
      44              : 
      45              : public:
      46              : 
      47              :     ~SpannerSegment() override;
      48              : 
      49              :     virtual double mag() const override;
      50              :     virtual Fraction tick() const override;
      51              : 
      52              :     //! The spanner that owns this segment - derived from the ownership parent,
      53              :     //! so that it can never go stale.
      54       470920 :     Spanner* spanner() const { return toSpanner(ownershipParent()); }
      55              :     void setSpanner(Spanner* val);
      56              : 
      57        13909 :     void setSpannerSegmentType(SpannerSegmentType s) { m_spannerSegmentType = s; }
      58        43683 :     SpannerSegmentType spannerSegmentType() const { return m_spannerSegmentType; }
      59        26499 :     bool isSingleType() const { return spannerSegmentType() == SpannerSegmentType::SINGLE; }
      60         2574 :     bool isBeginType() const { return spannerSegmentType() == SpannerSegmentType::BEGIN; }
      61        14463 :     bool isSingleBeginType() const { return isSingleType() || isBeginType(); }
      62         7571 :     bool isSingleEndType() const { return isSingleType() || isEndType(); }
      63           10 :     bool isMiddleType() const { return spannerSegmentType() == SpannerSegmentType::MIDDLE; }
      64         1072 :     bool isEndType() const { return spannerSegmentType() == SpannerSegmentType::END; }
      65              : 
      66              :     int subtype() const override;
      67              :     TranslatableString subtypeUserName() const override;
      68              : 
      69              :     //! The system this segment is currently laid out on; null if not placed.
      70        19519 :     System* system() const { return m_system; }
      71              :     //! Records the placement only. Reserved for System itself, which maintains its own
      72              :     //! segment list; everyone else must use moveToSystem(), so that a non-null system()
      73              :     //! always implies that the segment is in that system's segment list - otherwise the
      74              :     //! pointer is left dangling when the system is destroyed.
      75        11983 :     void setSystem(System* s) { m_system = s; }
      76              :     //! Detach from the current system's segment list and attach to the given one.
      77              :     void moveToSystem(System* s);
      78              :     EngravingItem* layoutParent() const override;
      79              :     EngravingItem* accessibleParentItem() const override;
      80              : 
      81              :     //! A segment is owned by its spanner; a system merely places it, see
      82              :     //! setSystem()/moveToSystem(). This overload hides EngravingItem::setOwnershipParent,
      83              :     //! so that no other parent can be set by accident.
      84              :     void setOwnershipParent(Spanner* spanner);
      85              : 
      86         1929 :     const PointF& userOff2() const { return m_offset2; }
      87           42 :     void setUserOff2(const PointF& o) { m_offset2 = o; }
      88            0 :     void setUserXoffset2(double x) { m_offset2.setX(x); }
      89         1252 :     void setUserYoffset2(double y) { m_offset2.setY(y); }
      90              :     real_t& rUserXoffset2() { return m_offset2.rx(); }
      91              :     real_t& rUserYoffset2() { return m_offset2.ry(); }
      92              : 
      93         5257 :     void setPos2(const PointF& p) { m_p2 = p; }
      94              :     //TODO: rename to spanSegPosWithUserOffset()
      95         9962 :     PointF pos2() const { return m_p2 + m_offset2; }
      96              :     //TODO: rename to spanSegPos()
      97         4602 :     const PointF& ipos2() const { return m_p2; }
      98              :     PointF& rpos2() { return m_p2; }
      99          137 :     real_t& rxpos2() { return m_p2.rx(); }
     100            2 :     real_t& rypos2() { return m_p2.ry(); }
     101              : 
     102            0 :     bool isEditable() const override { return true; }
     103              : 
     104              :     muse::ByteArray mimeData(const PointF& dragOffset) const override;
     105              : 
     106              :     void spatiumChanged(double ov, double nv) override;
     107              : 
     108              :     PropertyValue getProperty(Pid id) const override;
     109              :     bool setProperty(Pid id, const PropertyValue& v) override;
     110              :     PropertyValue propertyDefault(Pid id) const override;
     111              :     virtual EngravingObject* propertyDelegate(Pid) const override;
     112              :     void undoChangeProperty(Pid id, const PropertyValue&, PropertyFlags ps) override;
     113              :     using EngravingObject::undoChangeProperty;
     114              : 
     115              :     PointF defaultPos() const override;
     116              : 
     117              :     Sid getPropertyStyle(Pid id) const override;
     118              :     void resetProperty(Pid id) override;
     119              :     void styleChanged() override;
     120              :     void reset() override;
     121              : 
     122              :     void setSelected(bool f) override;
     123              :     void setVisible(bool f) override;
     124              :     void setColor(const Color& col) override;
     125              :     void setZ(int val) override;
     126              : 
     127              :     bool collectForDrawing() const override;
     128              : 
     129              :     EngravingItem* nextSegmentElement() override;
     130              :     EngravingItem* prevSegmentElement() override;
     131              :     String accessibleInfo() const override;
     132              :     void triggerLayout() const override;
     133              : 
     134              :     std::list<EngravingObject*> linkListForPropertyPropagation() const override;
     135              :     bool isPropertyLinkedToMaster(Pid id) const override;
     136              : 
     137              :     virtual bool isUserModified() const override;
     138              : 
     139              :     bool allowTimeAnchor() const override;
     140              : 
     141              : protected:
     142              : 
     143              :     SpannerSegment(const ElementType& type, Spanner*, ElementFlags f = ElementFlag::ON_STAFF | ElementFlag::MOVABLE);
     144              :     SpannerSegment(const SpannerSegment&);
     145              : 
     146              :     PointF m_p2;
     147              :     PointF m_offset2;
     148              : 
     149              : private:
     150              :     String formatBarsAndBeats() const override;
     151              :     String formatStartBarsAndBeats(const Segment* segment) const;
     152              :     String formatEndBarsAndBeats(const Segment* segment) const;
     153              : 
     154              :     System* m_system = nullptr;   // current layout placement; not owned, not copied
     155              :     SpannerSegmentType m_spannerSegmentType = SpannerSegmentType::SINGLE;
     156              : };
     157              : 
     158              : //----------------------------------------------------------------------------------
     159              : //   @@ Spanner
     160              : ///   Virtual base class for slurs, ties, lines etc.
     161              : //
     162              : //    @P anchor         enum (Spanner.CHORD, Spanner.MEASURE, Spanner.NOTE, Spanner.SEGMENT)
     163              : //    @P endElement     EngravingItem           the element the spanner end is anchored to (read-only)
     164              : //    @P startElement   EngravingItem           the element the spanner start is anchored to (read-only)
     165              : //    @P tick           int               tick start position
     166              : //    @P tick2          int               tick end position
     167              : //----------------------------------------------------------------------------------
     168              : 
     169              : class Spanner : public EngravingItem
     170              : {
     171            0 :     OBJECT_ALLOCATOR(engraving, Spanner)
     172              : public:
     173              :     enum class Anchor : unsigned char {
     174              :         SEGMENT, MEASURE, CHORDREST, NOTE
     175              :     };
     176              : 
     177              :     ~Spanner() override;
     178              : 
     179              :     virtual double mag() const override;
     180              : 
     181              :     virtual void setScore(Score* s) override;
     182              : 
     183       121912 :     virtual Fraction tick() const override { return m_tick; }
     184        50395 :     Fraction tick2() const { return m_tick + m_ticks; }
     185         4546 :     Fraction ticks() const { return m_ticks; }
     186              : 
     187              :     void setTick(const Fraction&);
     188              :     void setTick2(const Fraction&);
     189              :     void setTicks(const Fraction&);
     190              : 
     191              :     bool isVoiceSpecific() const;
     192              :     track_idx_t track2() const;
     193              :     void setTrack2(track_idx_t v);
     194              :     track_idx_t effectiveTrack2() const;
     195              : 
     196          905 :     bool playSpanner() const { return m_playSpanner; }
     197            1 :     void setPlaySpanner(bool p) { m_playSpanner = p; }
     198              : 
     199              :     virtual Anchor anchor() const = 0;
     200              : 
     201        22349 :     const std::vector<SpannerSegment*>& spannerSegments() const { return m_segments; }
     202              :     void setSpannerSegments(const std::vector<SpannerSegment*>& s) { m_segments = s; }
     203         4703 :     SpannerSegment* frontSegment() { return m_segments.front(); }
     204          130 :     const SpannerSegment* frontSegment() const { return m_segments.front(); }
     205         2089 :     SpannerSegment* backSegment() { return m_segments.back(); }
     206          105 :     const SpannerSegment* backSegment() const { return m_segments.back(); }
     207         6041 :     SpannerSegment* segmentAt(int n) { return m_segments[n]; }
     208              :     const SpannerSegment* segmentAt(int n) const { return m_segments[n]; }
     209         5912 :     size_t nsegments() const { return m_segments.size(); }
     210        10442 :     bool segmentsEmpty() const { return m_segments.empty(); }
     211              :     void eraseSpannerSegments();
     212              :     bool eitherEndVisible() const;
     213              : 
     214              :     virtual void triggerLayout() const override;
     215              :     virtual void add(EngravingItem*) override;
     216              :     virtual void remove(EngravingItem*) override;
     217              :     virtual void removed() override;
     218              :     EngravingItemList accessibleChildren() const override;
     219           77 :     virtual void scanElements(std::function<void(EngravingItem*)>) override {}
     220              :     bool removeSpannerBack();
     221              :     virtual void removeUnmanaged();
     222              :     virtual void insertTimeUnmanaged(const Fraction& tick, const Fraction& len);
     223              : 
     224              :     PropertyValue getProperty(Pid propertyId) const override;
     225              :     bool setProperty(Pid propertyId, const PropertyValue& v) override;
     226              :     PropertyValue propertyDefault(Pid propertyId) const override;
     227              : 
     228              :     virtual void computeStartElement();
     229              :     void computeEndElement();
     230              : 
     231              :     static Note* endElementFromSpanner(Spanner* sp, EngravingItem* newStart);
     232              :     static Note* startElementFromSpanner(Spanner* sp, EngravingItem* newEnd);
     233              :     void setNoteSpan(Note* startNote, Note* endNote);
     234              : 
     235       638307 :     EngravingItem* startElement() const { return m_startElement; }
     236       156786 :     EngravingItem* endElement() const { return m_endElement; }
     237              : 
     238              :     Measure* startMeasure() const;
     239              :     Measure* endMeasure() const;
     240              : 
     241              :     Measure* findStartMeasure() const;
     242              :     Measure* findEndMeasure() const;
     243              : 
     244              :     void setStartElement(EngravingItem* e);
     245              :     virtual void setEndElement(EngravingItem* e);
     246              : 
     247              :     ChordRest* startCR();
     248              :     ChordRest* endCR();
     249              : 
     250              :     Chord* startChord();
     251              :     Chord* endChord();
     252              : 
     253              :     ChordRest* findStartCR() const;
     254              :     ChordRest* findEndCR() const;
     255              : 
     256              :     Chord* findStartChord() const;
     257              :     Chord* findEndChord() const;
     258              : 
     259              :     Segment* startSegment() const;
     260              :     Segment* endSegment() const;
     261              : 
     262              :     bool elementAppliesToTrack(const track_idx_t refTrack) const override;
     263              : 
     264              :     virtual void setSelected(bool f) override;
     265              :     virtual void setVisible(bool f) override;
     266              :     virtual void setAutoplace(bool f) override;
     267              :     virtual void setColor(const Color& col) override;
     268              :     virtual void setZ(int val) override;
     269              :     Spanner* nextSpanner(EngravingItem* e, staff_idx_t activeStaff);
     270              :     Spanner* prevSpanner(EngravingItem* e, staff_idx_t activeStaff);
     271              :     virtual EngravingItem* nextSegmentElement() override;
     272              :     virtual EngravingItem* prevSegmentElement() override;
     273              : 
     274              :     using EngravingObject::undoChangeProperty;
     275              : 
     276              :     void pushUnusedSegment(SpannerSegment* seg);
     277              :     SpannerSegment* popUnusedSegment();
     278              :     void reuse(SpannerSegment* seg);              // called when segment from unusedSegments
     279              :                                                   // is added back to the spanner.
     280              :     int reuseSegments(int number);
     281              :     void fixupSegments(unsigned int targetNumber, std::function<SpannerSegment* ()> createSegment);
     282              : 
     283              :     bool isUserModified() const override;
     284              : 
     285            0 :     virtual bool allowTimeAnchor() const override { return false; }
     286              : 
     287              : protected:
     288              : 
     289         2358 :     Spanner(const ElementType& type, EngravingObject* parent, ElementFlags = ElementFlag::NOTHING);
     290              :     Spanner(const Spanner&);
     291              : 
     292              :     virtual void doComputeStartElement();
     293              :     virtual void doComputeEndElement();
     294              : 
     295         3025 :     virtual bool isInSpannerMap() const { return true; }
     296              : 
     297              : private:
     298              :     bool canBeCrossStaff() const;
     299              : 
     300              :     friend class SpannerSegment;
     301              : 
     302              :     EngravingItem* m_startElement = nullptr;
     303              :     EngravingItem* m_endElement = nullptr;
     304              : 
     305              :     bool m_playSpanner = true;
     306              : 
     307              :     Fraction m_tick = Fraction(-1, 1);
     308              :     Fraction m_ticks = Fraction(0, 1);
     309              :     track_idx_t m_track2 = muse::nidx;
     310              : 
     311              :     std::vector<SpannerSegment*> m_segments;
     312              :     std::deque<SpannerSegment*> m_unusedSegments;   // Currently unused segments which can be reused later.
     313              :                                                     // We cannot just delete them as they can be referenced
     314              :                                                     // in undo stack or other places already.
     315              : };
     316              : } // namespace mu::engraving
        

Generated by: LCOV version 2.0-1