LCOV - code coverage report
Current view: top level - src/engraving/dom - lyrics.h Coverage Total Hit
Test: filtered_coverage.info Lines: 82.8 % 64 53
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 "../types/types.h"
      26              : #include "line.h"
      27              : #include "textbase.h"
      28              : 
      29              : namespace mu::engraving {
      30              : class Transaction;
      31              : 
      32              : //---------------------------------------------------------
      33              : //   Lyrics
      34              : //---------------------------------------------------------
      35              : 
      36              : class LyricsLine;
      37              : 
      38              : class Lyrics final : public TextBase
      39              : {
      40         6202 :     OBJECT_ALLOCATOR(engraving, Lyrics)
      41         1525 :     DECLARE_CLASSOF(ElementType::LYRICS)
      42              : 
      43              : public:
      44              : 
      45              :     // MELISMA FIRST UNDERSCORE:
      46              :     // used as_ticks value to mark a melisma for which only the first chord has been spanned so far
      47              :     // and to give the user a visible feedback that the underscore has been actually entered;
      48              :     // it should be cleared to 0 at some point, so that it will not be carried over
      49              :     // if the melisma is not extended beyond a single chord, but no suitable place to do this
      50              :     // has been identified yet.
      51              :     static constexpr Fraction TEMP_MELISMA_TICKS = Fraction::eps(); // THIS WAS A HORRIBLE HACK. At some point we must remove it and replace it with a proper solution. (M.S.)
      52              : 
      53              :     ~Lyrics();
      54              : 
      55         1329 :     Lyrics* clone() const override { return new Lyrics(*this); }
      56              :     bool acceptDrop(EditData&) const override;
      57              :     EngravingItem* drop(Transaction& tx, EditData&) override;
      58              : 
      59          845 :     Segment* segment() const { return toSegment(ownershipParent()->ownershipParent()); }
      60            2 :     Measure* measure() const { return toMeasure(ownershipParent()->ownershipParent()->ownershipParent()); }
      61        11286 :     ChordRest* chordRest() const { return toChordRest(ownershipParent()); }
      62              : 
      63         1306 :     int subtype() const override { return m_verse; }
      64              :     TranslatableString subtypeUserName() const override;
      65          529 :     void setVerse(int n) { m_verse = n; }
      66        26143 :     int verse() const { return m_verse; }
      67         1258 :     bool isEven() const { return m_verse % 2; }
      68          574 :     void setSyllabic(LyricsSyllabic s) { m_syllabic = s; }
      69        20671 :     LyricsSyllabic syllabic() const { return m_syllabic; }
      70              :     void add(EngravingItem*) override;
      71              :     void remove(EngravingItem*) override;
      72              :     bool isEditAllowed(EditData&) const override;
      73              :     void endEdit(EditData&) override;
      74              : 
      75         4940 :     bool positionRelativeToNoteheadRest() const override { return true; }
      76              : 
      77        14088 :     const Fraction& ticks() const { return m_ticks; }
      78           63 :     void setTicks(const Fraction& tick) { m_ticks = tick; }
      79              :     Fraction endTick() const;
      80              :     void removeFromScore();
      81              : 
      82              :     void adjustPrevious();
      83              : 
      84         2180 :     bool needRemoveInvalidSegments() const { return m_needRemoveInvalidSegments; }
      85              :     void setNeedRemoveInvalidSegments();
      86              :     void removeInvalidSegments();
      87              : 
      88        31931 :     LyricsLine* separator() const { return m_separator; }
      89          243 :     void setSeparator(LyricsLine* s) { m_separator = s; }
      90              : 
      91              :     bool isMelisma() const;
      92              : 
      93            0 :     bool allowTimeAnchor() const override { return false; }
      94              : 
      95              :     using EngravingObject::undoChangeProperty;
      96              :     void paste(const String& txt) override;
      97              : 
      98              :     PropertyValue getProperty(Pid propertyId) const override;
      99              :     bool setProperty(Pid propertyId, const PropertyValue&) override;
     100              :     PropertyValue propertyDefault(Pid id) const override;
     101              :     void undoChangeProperty(Pid id, const PropertyValue&, PropertyFlags ps) override;
     102              :     void reset() override;
     103              :     void triggerLayout() const override;
     104              : 
     105              :     double yRelativeToStaff() const;
     106              :     void setYRelativeToStaff(double y);
     107              : 
     108         4780 :     bool avoidBarlines() const { return m_avoidBarlines; }
     109              :     void setAvoidBarlines(bool v) { m_avoidBarlines = v; }
     110              : 
     111              : private:
     112              : 
     113              :     friend class Factory;
     114              :     Lyrics(DummyParentOr<ChordRest> parent);
     115              :     Lyrics(const Lyrics&);
     116              : 
     117              :     int m_verse = 0;              // row index
     118              :     Fraction m_ticks;          // if > 0 then draw an underline to tick() + _ticks (melisma)
     119              :     LyricsSyllabic m_syllabic = LyricsSyllabic::SINGLE;
     120              :     LyricsLine* m_separator = nullptr;
     121              :     bool m_needRemoveInvalidSegments = false;
     122              :     bool m_avoidBarlines = true;
     123              : };
     124              : 
     125              : //---------------------------------------------------------
     126              : //   LyricsLine
     127              : ///   \cond PLUGIN_API \private \endcond
     128              : //---------------------------------------------------------
     129              : 
     130              : class LyricsLine : public SLine
     131              : {
     132          483 :     OBJECT_ALLOCATOR(engraving, LyricsLine)
     133         2553 :     DECLARE_CLASSOF(ElementType::LYRICSLINE)
     134              : 
     135              : public:
     136              :     LyricsLine(DummyParentOr<EngravingItem> parent);
     137              :     LyricsLine(const LyricsLine&);
     138              : 
     139            0 :     LyricsLine* clone() const override { return new LyricsLine(*this); }
     140              : 
     141          752 :     Anchor anchor() const override { return Anchor::SEGMENT; }
     142              : 
     143              :     LineSegment* createLineSegment() override;
     144              :     void removeUnmanaged() override;
     145              : 
     146        19835 :     virtual Lyrics* lyrics() const { return toLyrics(ownershipParent()); }
     147          916 :     Lyrics* nextLyrics() const { return m_nextLyrics; }
     148          228 :     void setNextLyrics(Lyrics* l) { m_nextLyrics = l; }
     149         7203 :     virtual bool isEndMelisma() const { return lyrics() && lyrics()->ticks().isNotZero(); }
     150          328 :     bool isDash() const { return !isEndMelisma(); }
     151              : 
     152              :     bool setProperty(Pid propertyId, const PropertyValue& v) override;
     153              :     PropertyValue propertyDefault(Pid id) const override;
     154              :     Sid getPropertyStyle(Pid) const override;
     155              : 
     156              : protected:
     157           11 :     LyricsLine(const ElementType& type, DummyParentOr<EngravingItem> parent, ElementFlags = ElementFlag::NOTHING);
     158              : 
     159          767 :     bool isInSpannerMap() const override { return false; }
     160              : 
     161              :     Lyrics* m_nextLyrics = nullptr;
     162              : 
     163              :     void doComputeEndElement() override;
     164              : };
     165              : 
     166              : //---------------------------------------------------------
     167              : //   LyricsLineSegment
     168              : ///   \cond PLUGIN_API \private \endcond
     169              : //---------------------------------------------------------
     170              : 
     171              : class LyricsLineSegment : public LineSegment
     172              : {
     173          489 :     OBJECT_ALLOCATOR(engraving, LyricsLineSegment)
     174              :     DECLARE_CLASSOF(ElementType::LYRICSLINE_SEGMENT)
     175              : 
     176              : public:
     177              :     LyricsLineSegment(LyricsLine*);
     178              : 
     179            0 :     LyricsLineSegment* clone() const override { return new LyricsLineSegment(*this); }
     180              : 
     181         4912 :     LyricsLine* lyricsLine() const { return toLyricsLine(spanner()); }
     182         2825 :     virtual Lyrics* lyrics() const { return lyricsLine()->lyrics(); }
     183              : 
     184              :     virtual double baseLineShift() const;
     185              : 
     186          665 :     virtual int verse() const { return lyrics()->verse(); }
     187          524 :     virtual bool lyricsPlaceAbove() const { return lyrics()->placeAbove(); }
     188          678 :     virtual bool lyricsAddToSkyline() const { return lyrics()->addToSkyline(); }
     189          339 :     virtual double lineSpacing() const { return lyrics()->lineSpacing(); }
     190            0 :     Color color() const override { return lyrics()->color(); }
     191              : 
     192              :     PropertyValue getProperty(Pid propertyId) const override;
     193              :     bool setProperty(Pid propertyId, const PropertyValue&) override;
     194              :     PropertyValue propertyDefault(Pid propertyId) const override;
     195              :     EngravingObject* propertyDelegate(Pid propertyId) const override;
     196              : 
     197            0 :     bool allowTimeAnchor() const override { return false; }
     198              : 
     199            0 :     virtual bool isEditAllowed(EditData&) const override { return false; }
     200              : 
     201              :     struct LayoutData : public LineSegment::LayoutData {
     202              :     public:
     203            0 :         const std::vector<LineF>& dashes() const { return m_dashes; }
     204          348 :         void clearDashes() { m_dashes.clear(); }
     205          365 :         void addDash(const LineF& dash) { m_dashes.push_back(dash); }
     206              :     private:
     207              :         std::vector<LineF> m_dashes;
     208              :     };
     209         1674 :     DECLARE_LAYOUTDATA_METHODS(LyricsLineSegment)
     210              : 
     211              : protected:
     212              :     LyricsLineSegment(const ElementType& type, LyricsLine* sp, ElementFlags f = ElementFlag::NOTHING);
     213              :     void rebaseAnchors(EditData&, Grip) override;
     214              : };
     215              : 
     216              : class PartialLyricsLine final : public LyricsLine
     217              : {
     218           20 :     OBJECT_ALLOCATOR(engraving, PartialLyricsLine)
     219              :     DECLARE_CLASSOF(ElementType::PARTIAL_LYRICSLINE)
     220              : 
     221              : public:
     222              :     PartialLyricsLine(DummyParentOr<EngravingItem> parent);
     223              :     PartialLyricsLine(const PartialLyricsLine&);
     224            0 :     PartialLyricsLine* clone() const override { return new PartialLyricsLine(*this); }
     225              :     LineSegment* createLineSegment() override;
     226              : 
     227           15 :     Lyrics* lyrics() const override { return nullptr; }
     228              : 
     229            5 :     void setIsEndMelisma(bool val) { m_isEndMelisma = val; }
     230           60 :     bool isEndMelisma() const override { return m_isEndMelisma; }
     231              : 
     232            2 :     void setVerse(int val) { m_verse = val; }
     233           33 :     int verse() const { return m_verse; }
     234              : 
     235            4 :     void setCenterBetweenStaves(AutoOnOff v) { m_centerBetweenStaves = v; }
     236            9 :     AutoOnOff centerBetweenStaves() const { return m_centerBetweenStaves; }
     237              : 
     238              :     PropertyValue getProperty(Pid propertyId) const override;
     239              :     bool setProperty(Pid propertyId, const PropertyValue&) override;
     240              :     PropertyValue propertyDefault(Pid propertyId) const override;
     241              :     Sid getPropertyStyle(Pid propertyId) const override;
     242              :     void undoChangeProperty(Pid id, const PropertyValue&, PropertyFlags ps) override;
     243              :     void reset() override;
     244              : 
     245              :     Lyrics* findLyricsInPreviousRepeatSeg() const;
     246              :     Lyrics* findAdjacentLyricsOrDefault() const;
     247              : 
     248              : protected:
     249              :     void doComputeEndElement() override;
     250            4 :     bool isInSpannerMap() const override { return true; }
     251              : 
     252              : private:
     253              :     bool m_isEndMelisma = false;
     254              :     int m_verse = 0;
     255              :     AutoOnOff m_centerBetweenStaves = AutoOnOff::AUTO;
     256              : };
     257              : 
     258              : class PartialLyricsLineSegment final : public LyricsLineSegment
     259              : {
     260            4 :     OBJECT_ALLOCATOR(engraving, PartialLyricsLineSegment)
     261              :     DECLARE_CLASSOF(ElementType::PARTIAL_LYRICSLINE_SEGMENT)
     262              : 
     263              : public:
     264              :     PartialLyricsLineSegment(PartialLyricsLine*);
     265              : 
     266            0 :     LyricsLineSegment* clone() const override { return new PartialLyricsLineSegment(*this); }
     267              : 
     268           51 :     PartialLyricsLine* lyricsLine() const { return toPartialLyricsLine(spanner()); }
     269            0 :     Lyrics* lyrics() const override { return nullptr; }
     270              : 
     271           15 :     int verse() const override { return lyricsLine()->verse(); }
     272              :     double lineSpacing() const override;
     273            6 :     bool lyricsPlaceAbove() const override { return lyricsLine()->placeAbove(); }// Delegate?
     274           12 :     bool lyricsAddToSkyline() const override { return lyricsLine()->addToSkyline(); }
     275            0 :     Color color() const override { return lyricsLine()->color(); }
     276              :     double baseLineShift() const override;
     277              : 
     278              :     EngravingObject* propertyDelegate(Pid) const override;
     279              : };
     280              : } // namespace mu::engraving
        

Generated by: LCOV version 2.0-1