LCOV - code coverage report
Current view: top level - src/engraving/dom - chordlist.h Coverage Total Hit
Test: filtered_coverage.info Lines: 85.3 % 102 87
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 <map>
      26              : 
      27              : #include "global/allocator.h"
      28              : #include "global/types/string.h"
      29              : 
      30              : #include "../types/types.h"
      31              : 
      32              : namespace muse::io {
      33              : class IODevice;
      34              : }
      35              : 
      36              : namespace mu::engraving::compat {
      37              : class ReadChordListHook;
      38              : }
      39              : 
      40              : namespace mu::engraving {
      41              : class ChordList;
      42              : class MStyle;
      43              : class XmlWriter;
      44              : class XmlReader;
      45              : 
      46              : //---------------------------------------------------------
      47              : //   class HDegree
      48              : //---------------------------------------------------------
      49              : 
      50              : enum class HDegreeType : char {
      51              :     UNDEF, ADD, ALTER, SUBTRACT
      52              : };
      53              : 
      54              : class HDegree
      55              : {
      56              : public:
      57              :     HDegree() = default;
      58        15946 :     HDegree(int v, int a, HDegreeType t) { m_value = v; m_alter = a; m_type = t; }
      59        31897 :     int value() const { return m_value; }
      60        15960 :     int alter() const { return m_alter; }
      61        25220 :     HDegreeType type() const { return m_type; }
      62              :     String text() const;
      63              : 
      64              : private:
      65              :     int m_value = 0;
      66              :     int m_alter = 0;         // -1, 0, 1  (b - - #)
      67              :     HDegreeType m_type = HDegreeType::UNDEF;
      68              : };
      69              : 
      70              : //---------------------------------------------------------
      71              : //   HChord
      72              : //---------------------------------------------------------
      73              : 
      74              : class HChord
      75              : {
      76              : public:
      77        22646 :     HChord() = default;
      78          349 :     HChord(int k) { m_keys = k; }
      79              :     HChord(int a, int b, int c=-1, int d=-1, int e=-1, int f=-1, int g=-1, int h=-1, int i=-1, int k=-1, int l=-1);
      80              :     HChord(const String&);
      81              : 
      82              :     void rotate(int semiTones);
      83              : 
      84        15008 :     bool contains(int key) const           // key in chord?
      85              :     {
      86        15008 :         return (1 << (key % 12)) & m_keys;
      87              :     }
      88              : 
      89       113939 :     HChord& operator+=(int key)
      90              :     {
      91       113939 :         m_keys |= (1 << (key % 12));
      92       113939 :         return *this;
      93              :     }
      94              : 
      95         9183 :     HChord& operator-=(int key)
      96              :     {
      97         9183 :         m_keys &= ~(1 << (key % 12));
      98         9183 :         return *this;
      99              :     }
     100              : 
     101            0 :     bool operator==(const HChord& o) const { return m_keys == o.m_keys; }
     102              :     bool operator!=(const HChord& o) const { return m_keys != o.m_keys; }
     103              : 
     104        16704 :     int getKeys() const { return m_keys; }
     105              :     void print() const;
     106              : 
     107              :     String name(int tpc) const;
     108              :     String voicing() const;
     109              :     void add(const std::vector<HDegree>& degreeList);
     110              : 
     111              : protected:
     112              :     int m_keys = 0;
     113              : 
     114              : private:
     115              :     String m_str;
     116              : };
     117              : 
     118              : //---------------------------------------------------------
     119              : //   RenderAction
     120              : //    Render commands to be passed to and executed by Harmony
     121              : //---------------------------------------------------------
     122              : 
     123              : struct RenderAction
     124              : {
     125              :     enum class RenderActionType : char {
     126              :         SET, MOVE, MOVEXHEIGHT, PUSH, POP, NOTE, ACCIDENTAL, STOPHALIGN, SCALE, PAREN
     127              :     };
     128              : 
     129              :     virtual RenderActionType actionType() const = 0;
     130              : 
     131            0 :     virtual void print() const { print(actionType(), u""); }
     132              : 
     133       271068 :     virtual ~RenderAction() {}
     134              : 
     135              : protected:
     136              :     void print(RenderActionType type, const String& info) const;
     137              : };
     138              : 
     139              : struct RenderActionMove : RenderAction
     140              : {
     141              :     RenderActionMove() {}
     142        41527 :     RenderActionMove(double movex, double movey)
     143        41527 :         : m_vec(PointF(movex, movey)) {}
     144              : 
     145         3233 :     RenderActionType actionType() const override { return RenderActionType::MOVE; }
     146              :     void print() const override;
     147              : 
     148            0 :     double x() const { return m_vec.x(); }
     149            0 :     double y() const { return m_vec.y(); }
     150         3233 :     PointF vec() const { return m_vec; }
     151         3233 :     bool scaled() const { return m_scaled; }
     152              : 
     153              : protected:
     154        20130 :     RenderActionMove(double movex, double movey, bool scaled)
     155        20130 :         : m_vec(PointF(movex, movey)), m_scaled(scaled) {}
     156              : 
     157              : private:
     158              :     PointF m_vec = PointF(0.0, 0.0);
     159              :     bool m_scaled = false;
     160              : };
     161              : 
     162              : struct RenderActionMoveScaled : RenderActionMove
     163              : {
     164        20130 :     RenderActionMoveScaled(double movex, double movey)
     165        20130 :         : RenderActionMove(movex, movey, true) {}
     166              : 
     167              :     void print() const override;
     168              : };
     169              : 
     170              : struct RenderActionMoveXHeight : RenderAction
     171              : {
     172        10003 :     RenderActionMoveXHeight(bool up)
     173        10003 :         : m_up(up) {}
     174           12 :     RenderActionType actionType() const override { return RenderActionType::MOVEXHEIGHT; }
     175              : 
     176           12 :     bool up() const { return m_up; }
     177           12 :     bool scaled() const { return m_scaled; }
     178              :     void print() const override;
     179              : 
     180              : protected:
     181          915 :     RenderActionMoveXHeight(bool up, bool scaled)
     182          915 :         : m_up(up), m_scaled(scaled) {}
     183              : 
     184              : private:
     185              :     bool m_up = true;
     186              :     bool m_scaled = false;
     187              : };
     188              : 
     189              : struct RenderActionMoveXHeightScaled : RenderActionMoveXHeight
     190              : {
     191          915 :     RenderActionMoveXHeightScaled(bool up)
     192          915 :         : RenderActionMoveXHeight(up, true) {}
     193              : };
     194              : 
     195              : struct RenderActionSet : RenderAction
     196              : {
     197              :     RenderActionSet() {}
     198       167514 :     RenderActionSet(String s)
     199       167514 :         : m_text(s) {}
     200              : 
     201         7099 :     RenderActionType actionType() const override { return RenderActionType::SET; }
     202              :     void print() const override;
     203              : 
     204         9340 :     const String& text() const { return m_text; }
     205         7099 :     bool renderText() const { return m_renderText; }
     206              : 
     207              : protected:
     208            0 :     RenderActionSet(String s, bool renderText)
     209            0 :         : m_text(s), m_renderText(renderText) {}
     210              : 
     211              : private:
     212              :     String m_text;
     213              :     bool m_renderText = true;
     214              : };
     215              : 
     216              : struct RenderActionMoveTextWidth : RenderActionSet
     217              : {
     218            0 :     RenderActionMoveTextWidth(String s)
     219            0 :         : RenderActionSet(s, false) {}
     220              : };
     221              : 
     222              : struct RenderActionPush : RenderAction
     223              : {
     224        15574 :     RenderActionPush() {}
     225           16 :     RenderActionType actionType() const override { return RenderActionType::PUSH; }
     226              : };
     227              : 
     228              : struct RenderActionPop : RenderAction
     229              : {
     230         1449 :     RenderActionPop() {}
     231              : 
     232           16 :     RenderActionType actionType() const override { return RenderActionType::POP; }
     233              :     void print() const override;
     234              : 
     235           16 :     double popX() const { return m_popx; }
     236           16 :     double popY() const { return m_popy; }
     237              : protected:
     238        12313 :     RenderActionPop(bool popx, bool popy)
     239        12313 :         : m_popx(popx), m_popy(popy) {}
     240              : private:
     241              :     bool m_popx = true, m_popy = true;
     242              : };
     243              : 
     244              : struct RenderActionPopX : RenderActionPop
     245              : {
     246         2310 :     RenderActionPopX()
     247         2310 :         : RenderActionPop(true, false) {}
     248              : };
     249              : 
     250              : struct RenderActionPopY : RenderActionPop
     251              : {
     252        10003 :     RenderActionPopY()
     253        10003 :         : RenderActionPop(false, true) {}
     254              : };
     255              : 
     256              : struct RenderActionNote : RenderAction
     257              : {
     258         5314 :     RenderActionNote() {}
     259         2897 :     RenderActionType actionType() const override { return RenderActionType::NOTE; }
     260              : };
     261              : 
     262              : struct RenderActionAccidental : RenderAction
     263              : {
     264         5314 :     RenderActionAccidental() {}
     265         2897 :     RenderActionType actionType() const override { return RenderActionType::ACCIDENTAL; }
     266              : };
     267              : 
     268              : struct RenderActionStopHAlign : RenderAction
     269              : {
     270            0 :     RenderActionStopHAlign() {}
     271            0 :     RenderActionType actionType() const override { return RenderActionType::STOPHALIGN; }
     272              : };
     273              : 
     274              : struct RenderActionScale : RenderAction
     275              : {
     276              :     RenderActionScale() {}
     277        20024 :     RenderActionScale(double scale)
     278        20024 :         : m_scale(scale) {}
     279           24 :     RenderActionType actionType() const override { return RenderActionType::SCALE; }
     280              : 
     281           24 :     double scale() const { return m_scale; }
     282              : 
     283              :     void print() const override;
     284              : 
     285              : private:
     286              :     double m_scale = 1.0;
     287              : };
     288              : 
     289              : struct RenderActionParen : RenderAction
     290              : {
     291              :     virtual DirectionH direction() const = 0;
     292           64 :     RenderActionType actionType() const override { return RenderActionType::PAREN; }
     293              : 
     294              :     void print() const override;
     295              : };
     296              : 
     297              : struct RenderActionParenLeft : RenderActionParen
     298              : {
     299          915 :     RenderActionParenLeft() {}
     300           32 :     DirectionH direction() const override { return DirectionH::LEFT; }
     301              : };
     302              : 
     303              : struct RenderActionParenRight : RenderActionParen
     304              : {
     305          915 :     RenderActionParenRight() {}
     306           32 :     DirectionH direction() const override { return DirectionH::RIGHT; }
     307              : };
     308              : 
     309              : using RenderActionPtr = std::shared_ptr<RenderAction>;
     310              : using RenderActionMovePtr = std::shared_ptr<RenderActionMove>;
     311              : using RenderActionMoveXHeightPtr = std::shared_ptr<RenderActionMoveXHeight>;
     312              : using RenderActionPopPtr = std::shared_ptr<RenderActionPop>;
     313              : using RenderActionScalePtr = std::shared_ptr<RenderActionScale>;
     314              : using RenderActionSetPtr = std::shared_ptr<RenderActionSet>;
     315              : using RenderActionParenPtr = std::shared_ptr<RenderActionParen>;
     316              : 
     317              : //---------------------------------------------------------
     318              : //   ChordToken
     319              : //    Reads/represents the <token> tag in chord XML files
     320              : //---------------------------------------------------------
     321              : 
     322              : enum class ChordTokenClass : char {
     323              :     ALL, QUALITY, EXTENSION, MODIFIER, TYPE, ACCIDENTAL
     324              : };
     325              : 
     326              : class ChordToken
     327              : {
     328              : public:
     329              :     ChordTokenClass tokenClass;
     330              :     StringList names;
     331              :     std::vector<RenderActionPtr > renderList;
     332              :     void read(XmlReader&, int mscVersion);
     333              :     void write(XmlWriter&) const;
     334          747 :     bool isValid() const { return !names.empty(); }
     335              : };
     336              : 
     337              : //---------------------------------------------------------
     338              : //   ParsedChord
     339              : //    Extracts quality, extension & modifiers from a string eg. "m7#11"
     340              : //    Generates a list of render instructions to lay this chord out
     341              : //---------------------------------------------------------
     342              : 
     343              : class ParsedChord
     344              : {
     345              : public:
     346        17096 :     ParsedChord() = default;
     347              : 
     348              :     bool parse(const String&, const ChordList*, bool syntaxOnly = false, bool preferMinor = false);
     349              :     String fromXml(const String&, const String&, const String&, const String&, const std::vector<HDegree>&, const ChordList*);
     350              :     const std::vector<RenderActionPtr >& renderList(const ChordList* cl, bool stacked);
     351           49 :     bool parseable() const { return m_parseable; }
     352           47 :     bool understandable() const { return m_understandable; }
     353          571 :     const String& name() const { return m_name; }
     354        10458 :     const String& quality() const { return m_quality; }
     355          500 :     const String& extension() const { return m_extension; }
     356            0 :     const String& modifiers() const { return m_modifiers; }
     357          492 :     const StringList& modifierList() const { return m_modifierList; }
     358          436 :     const String& xmlKind() const { return m_xmlKind; }
     359         9942 :     const String& xmlText() const { return m_xmlText; }
     360         9942 :     const String& xmlSymbols() const { return m_xmlSymbols; }
     361         9942 :     const String& xmlParens() const { return m_xmlParens; }
     362          436 :     const StringList& xmlDegrees() const { return m_xmlDegrees; }
     363         6702 :     int keys() const { return m_chord.getKeys(); }
     364            0 :     const String& handle() const { return m_handle; }
     365              :     operator String() const {
     366              :         return m_handle;
     367              :     }
     368            0 :     bool operator==(const ParsedChord& c) const { return this->m_handle == c.m_handle; }
     369              :     bool operator!=(const ParsedChord& c) const { return !(*this == c); }
     370              : 
     371              : private:
     372              :     void configure(const ChordList*);
     373              :     void correctXmlText(const String& s = String());
     374              :     void addToken(String, ChordTokenClass);
     375              : 
     376              :     String m_name;
     377              :     String m_handle;
     378              :     String m_quality;
     379              :     String m_extension;
     380              :     String m_modifiers;
     381              :     StringList m_modifierList;
     382              :     std::vector<ChordToken> m_tokenList;
     383              :     std::vector<RenderActionPtr > m_renderList;
     384              :     String m_xmlKind;
     385              :     String m_xmlText;
     386              :     String m_xmlSymbols;
     387              :     String m_xmlParens;
     388              :     StringList m_xmlDegrees;
     389              :     StringList m_major, m_minor, m_diminished, m_augmented, m_lower, m_raise, m_mod, m_symbols;
     390              :     HChord m_chord;
     391              :     bool m_parseable = false;
     392              :     bool m_understandable = false;
     393              : };
     394              : 
     395              : //---------------------------------------------------------
     396              : //   ChordDescription
     397              : //    Describes chord quality, extensions and modifiers. eg. m7#11
     398              : //---------------------------------------------------------
     399              : 
     400              : struct ChordDescription {
     401              :     int id = 0;               // Chord id number (Band In A Box Chord Number)
     402              :     StringList names;        // list of alternative chord names
     403              :                              // that will by recognized from keyboard entry (without root/base)
     404              :     std::vector<ParsedChord> parsedChords;
     405              :     // parsed forms of primary name (optionally also include parsed forms of other names)
     406              :     String xmlKind;          // MusicXML: kind
     407              :     String xmlText;          // MusicXML: kind text=
     408              :     String xmlSymbols;       // MusicXML: kind use-symbols=
     409              :     String xmlParens;        // MusicXML: kind parentheses-degrees=
     410              :     StringList xmlDegrees;   // MusicXML: list of degrees (if any)
     411              :     HChord chord;             // C based chord
     412              :     std::vector<RenderActionPtr > renderList;
     413              :     std::vector<RenderActionPtr > renderListStacked;
     414              :     bool generated = false;
     415              :     bool renderListGenerated = false;
     416              :     bool exportOk = false;
     417              : 
     418            0 :     ChordDescription() {}
     419              :     ChordDescription(int);
     420              :     ChordDescription(const String&);
     421            0 :     String quality() const { return m_quality; }
     422              :     void complete(ParsedChord* pc, const ChordList*);
     423              :     void read(XmlReader&, int mscVersion);
     424              :     void write(XmlWriter&) const;
     425              : 
     426              : private:
     427              :     String m_quality;
     428              : };
     429              : 
     430              : //---------------------------------------------------------
     431              : //   ChordSymbol
     432              : //    Represents the <sym> tag in chord XML files
     433              : //---------------------------------------------------------
     434              : 
     435              : struct ChordSymbol {
     436              :     int fontIdx = -1;
     437              :     String name;
     438              :     String value;
     439              :     Char code;
     440              : 
     441        24689 :     bool isValid() const { return fontIdx != -1; }
     442              : };
     443              : 
     444              : //---------------------------------------------------------
     445              : //   ChordFont
     446              : //    Represents the <font> tag in chord XML files
     447              : //---------------------------------------------------------
     448              : 
     449              : struct ChordFont {
     450              :     String family;
     451              :     String fontClass;
     452              :     double mag = 1.0;
     453              :     bool musicSymbolText = false;
     454              : };
     455              : 
     456              : //---------------------------------------------------------
     457              : //   ChordList
     458              : //    Reads chord XML files and stores the list of known chords
     459              : //---------------------------------------------------------
     460              : 
     461              : class ChordList : public std::map<int, ChordDescription>
     462              : {
     463              :     OBJECT_ALLOCATOR(engraving, ChordList)
     464              : 
     465              : public:
     466              :     std::vector<ChordFont> fonts;
     467              :     std::vector<RenderActionPtr > renderListRoot;
     468              :     std::vector<RenderActionPtr > renderListFunction;
     469              :     std::vector<RenderActionPtr > renderListBass;
     470              :     std::vector<RenderActionPtr > renderListBassOffset;
     471              :     std::vector<ChordToken> chordTokenList;
     472              :     static int privateID;
     473              : 
     474        10902 :     bool autoAdjust() const { return m_autoAdjust; }
     475          142 :     double nominalMag() const { return m_nmag; }
     476          162 :     double nominalAdjust() const { return m_nadjust; }
     477              :     bool stackModifiers() const { return m_stackModifiers; }
     478        29627 :     bool excludeModsHAlign() const { return m_excludeModsHAlign; }
     479        16364 :     double stackedModifierMag() const { return m_stackedmmag; }
     480         9133 :     const ChordStylePreset& chordPreset() const { return m_chordPreset; }
     481              :     void configureAutoAdjust(double emag = 1.0, double eadjust = 0.0, double mmag = 1.0, double madjust = 0.0, double stackedmmag = 0.0,
     482              :                              bool stackModifiers = false, bool excludeModsHAlign = false, String symbolFont = u"",
     483              :                              const ChordStylePreset& preset = ChordStylePreset::STANDARD);
     484              :     double position(const StringList& names, bool stackModifiers, bool superScript, ChordTokenClass ctc, size_t modifierIdx,
     485              :                     size_t nmodifiers) const;
     486              : 
     487              :     void checkChordList(const MStyle& style);
     488              :     bool read(const String& name);
     489              :     bool read(muse::io::IODevice* device);
     490              :     bool write(const String&) const;
     491              :     bool write(muse::io::IODevice* device) const;
     492              :     bool loaded() const;
     493              :     void unload();
     494              : 
     495              :     const ChordDescription* description(int id) const;
     496              :     ChordSymbol symbol(const String& s) const;
     497              :     ChordToken token(const String& s, ChordTokenClass) const;
     498              : 
     499          129 :     void setCustomChordList(bool t) { m_customChordList = t; }
     500            3 :     bool customChordList() const { return m_customChordList; }
     501              : 
     502              : private:
     503              : 
     504              :     friend class compat::ReadChordListHook;
     505              : 
     506              :     void read(XmlReader& xml, int mscVersion);
     507              :     void write(XmlWriter& xml) const;
     508              : 
     509              :     std::map<String, ChordSymbol> m_symbols;
     510              :     bool m_autoAdjust = false;
     511              :     bool m_stackModifiers = false;
     512              :     bool m_excludeModsHAlign = false;
     513              :     ChordStylePreset m_chordPreset = ChordStylePreset::STANDARD;
     514              :     double m_nmag = 1.0, m_nadjust = 0.0;   // adjust values are measured in percentage
     515              :     double m_emag = 1.0, m_eadjust = 0.0;   // (which is then applied to the height of the font)
     516              :     double m_mmag = 1.0, m_madjust = 0.0, m_stackedmmag = 0.0;
     517              :     String m_symbolTextFont = u"";
     518              : 
     519              :     bool m_customChordList = false;         // if true, chordlist will be saved as part of score
     520              : };
     521              : }
        

Generated by: LCOV version 2.0-1