File: figuredbass.h

package info (click to toggle)
musescore3 3.2.3%2Bdfsg2-11
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 210,672 kB
  • sloc: cpp: 291,093; xml: 200,238; sh: 3,779; ansic: 1,447; python: 393; makefile: 240; perl: 82; pascal: 79
file content (316 lines) | stat: -rw-r--r-- 16,320 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
//=============================================================================
//  MuseScore
//  Music Composition & Notation
//
//  Copyright (C) 2002-2011 Werner Schweer
//
//  This program is free software; you can redistribute it and/or modify
//  it under the terms of the GNU General Public License version 2
//  as published by the Free Software Foundation and appearing in
//  the file LICENCE.GPL
//=============================================================================

#ifndef __FIGUREDBASS_H__
#define __FIGUREDBASS_H__

#include "text.h"

namespace Ms {

class Segment;

/*---------------------------------------------------------
NOTE ON ARCHITECTURE

FiguredBass elements are stored in the annotations of a Segment (like for instance Harmony)

FiguredBass is rather simple: it contains only _ticks, telling the duration of the element,
and a list of FiguredBassItem elements which do most of the job. It also maintains a text with the
normalized (made uniform) version of the text, which is used during editing.

Normally, a FiguredBass element is assumed to be styled with an internally maintained text style
(based on the parameters of the general style "Figured Bass") FIGURED_BASS style and it is set
in this way upon creation and upon layout().
- - - -
FiguredBassItem contains the actually f.b. info; it is made of 4 parts (in this order):
1) prefix: one of [nothing, doubleflat, flat, natural, sharp, doublesharp, cross]
2) digit: one digit from 1 to 9
3) suffix: one of [nothing, doubleflat, flat, natural, sharp, doublesharp, cross, backslash, slash]
4) contLine: true if the item has a continuation line (whose length is determined by parent's _ticks)
and 5 parenthesis flags, one for each position before, between and after the four parts above:
each of them may contain one of [nothing, roundOpen, roundClosed, squaredOpen, squaredClosed].

There is a number of restrictions, implemented at the end of FiguredBassItem::parse().
Currently, no attempt is made to ensure that, if multiple parentheses are present, they are consistent
(matching open and closed parentheses is left to the user).

If an item cannot be parsed, the whole FiguredBass element is kept as entered, possibly un-styled.
If all items can be parsed, each item generates a display text from its properties,
lays it out so that it properly aligns under the chord, draws it at its proper location
and provides its FiguredBass parent with a normalized text for future editing.

FiguredBassItem has not use for formats (italics, bold, ...) and it is never edited directly;
more generally, it is never accessed directly, only via its FiguredBass parent;
so it is directly derived from Element and returns INVALID as type.

FiguredBass might require formatting (discouraged, but might be necessary for very uncommon cases)
and it is edited (via the normalized text); so it is derived from Text.
---------------------------------------------------------*/

#define FBIDigitNone    -1

//---------------------------------------------------------
//   @@ FiguredBassItem
///   One line of a figured bass indication
//
//   @P continuationLine   enum (FiguredBassItem.NONE, .SIMPLE, .EXTENDED)  whether item has continuation line or not, and of which type
//   @P digit              int                              main digit(s) (0 - 9)
//   @P displayText        string                           text displayed (depends on configured fonts) (read only)
//   @P normalizedText     string                           conventional textual representation of item properties (= text used during input) (read ony)
//   @P parenthesis1       enum (FiguredBassItem.NONE, .ROUNDOPEN, .ROUNDCLOSED, .SQUAREDOPEN, .SQUAREDCLOSED)  parentesis before the prefix
//   @P parenthesis2       enum (FiguredBassItem.NONE, .ROUNDOPEN, .ROUNDCLOSED, .SQUAREDOPEN, .SQUAREDCLOSED)  parentesis after the prefix / before the digit
//   @P parenthesis3       enum (FiguredBassItem.NONE, .ROUNDOPEN, .ROUNDCLOSED, .SQUAREDOPEN, .SQUAREDCLOSED)  parentesis after the digit / before the suffix
//   @P parenthesis4       enum (FiguredBassItem.NONE, .ROUNDOPEN, .ROUNDCLOSED, .SQUAREDOPEN, .SQUAREDCLOSED)  parentesis after the suffix / before the cont. line
//   @P parenthesis5       enum (FiguredBassItem.NONE, .ROUNDOPEN, .ROUNDCLOSED, .SQUAREDOPEN, .SQUAREDCLOSED)  parentesis after the cont. line
//   @P prefix             enum (FiguredBassItem.NONE, .DOUBLEFLAT, .FLAT, .NATURAL, .SHARP, .DOUBLESHARP, .PLUS, .BACKSLASH, .SLASH)  accidental before the digit
//   @P suffix             enum (FiguredBassItem.NONE, .DOUBLEFLAT, .FLAT, .NATURAL, .SHARP, .DOUBLESHARP, .PLUS, .BACKSLASH, .SLASH)  accidental/diacritic after the digit
//---------------------------------------------------------

class FiguredBass;

class FiguredBassItem final : public Element {
   public:
      enum class Modifier : char {
            NONE = 0,
            DOUBLEFLAT,
            FLAT,
            NATURAL,
            SHARP,
            DOUBLESHARP,
            CROSS,
            BACKSLASH,
            SLASH,
                  NUMOF
            };
      enum class Parenthesis : char {
            NONE = 0,
            ROUNDOPEN,
            ROUNDCLOSED,
            SQUAREDOPEN,
            SQUAREDCLOSED,
                  NUMOF
            };
      enum class ContLine : char {
            NONE = 0,
            SIMPLE,                     // cont. line stops at f.b. element end
            EXTENDED                    // cont. line joins with next element, if possible
            };

      enum class Style : char {
            MODERN = 0,
            HISTORIC,
                  NUMOF
            };
      enum class Combination : char {
            SIMPLE = 0,
            CROSSED,
            BACKSLASHED,
            SLASHED,
                  NUMOF
            };

   private:

      static const QChar normParenthToChar[int(Parenthesis::NUMOF)];

      QString           _displayText;           // the constructed display text (read-only)
      int               ord;                    // the line ordinal of this element in the FB stack
      // the parts making a FiguredBassItem up
      Modifier          _prefix;                // the accidental coming before the body
      int               _digit;                 // the main digit (if present)
      Modifier          _suffix;                // the accidental coming after the body
      ContLine          _contLine;              // whether the item has continuation line or not
      Parenthesis       parenth[5];             // each of the parenthesis: before, between and after parts
      qreal             textWidth;              // the text width (in raster units), set during layout()
                                                //    used by draw()
      // part parsing
      int               parseDigit(QString& str);
      int               parseParenthesis(QString& str, int parenthIdx);
      int               parsePrefixSuffix(QString& str, bool bPrefix);

      void              setDisplayText(const QString& s)    { _displayText = s;       }
      // read / write MusicXML support
      QString                   Modifier2MusicXML(FiguredBassItem::Modifier prefix) const;

   public:
      FiguredBassItem(Score * s = 0, int line = 0);
      FiguredBassItem(const FiguredBassItem&);
      ~FiguredBassItem();

      FiguredBassItem &operator=(const FiguredBassItem&) = delete;

      FiguredBassItem::Modifier MusicXML2Modifier(const QString prefix) const;

      // standard re-implemented virtual functions
      virtual FiguredBassItem*      clone() const override     { return new FiguredBassItem(*this); }
      virtual ElementType         type() const override      { return ElementType::INVALID; }
      virtual void      draw(QPainter* painter) const override;
      virtual void      layout() override;
      virtual void      read(XmlReader&) override;
      virtual void      write(XmlWriter& xml) const override;

      // read / write MusicXML
      void              writeMusicXML(XmlWriter& xml, bool isOriginalFigure, int crEndTick, int fbEndTick) const;
      bool              startsWithParenthesis() const;

      // specific API
      const FiguredBass *    figuredBass() const      { return (FiguredBass*)(parent()); }
      bool              parse(QString& text);

      // getters / setters
      Modifier          prefix() const                { return _prefix;       }
      void              setPrefix(const Modifier& v)  { _prefix = v;          }
      void              undoSetPrefix(Modifier pref);
      int               digit() const                 { return _digit;        }
      void              setDigit(int val)             { _digit = val;         }
      void              undoSetDigit(int digit);
      Modifier          suffix() const                { return _suffix;       }
      void              setSuffix(const Modifier& v)  { _suffix = v;          }
      void              undoSetSuffix(Modifier suff);
      ContLine          contLine() const              { return _contLine;     }
      void              setContLine(const ContLine& v){ _contLine = v;        }
      void              undoSetContLine(ContLine val);
      Parenthesis       parenth1()                    { return parenth[0];    }
      Parenthesis       parenth2()                    { return parenth[1];    }
      Parenthesis       parenth3()                    { return parenth[2];    }
      Parenthesis       parenth4()                    { return parenth[3];    }
      Parenthesis       parenth5()                    { return parenth[4];    }

      void              setParenth1(Parenthesis v)    { parenth[0] = v;    }
      void              setParenth2(Parenthesis v)    { parenth[1] = v;    }
      void              setParenth3(Parenthesis v)    { parenth[2] = v;    }
      void              setParenth4(Parenthesis v)    { parenth[3] = v;    }
      void              setParenth5(Parenthesis v)    { parenth[4] = v;    }

      void              undoSetParenth1(Parenthesis par);
      void              undoSetParenth2(Parenthesis par);
      void              undoSetParenth3(Parenthesis par);
      void              undoSetParenth4(Parenthesis par);
      void              undoSetParenth5(Parenthesis par);
      QString           normalizedText() const;
      QString           displayText() const           { return _displayText;  }

      virtual QVariant  getProperty(Pid propertyId) const override;
      virtual bool      setProperty(Pid propertyId, const QVariant&) override;
      virtual QVariant  propertyDefault(Pid) const override;
      };

//---------------------------------------------------------
//   FiguredBassFont
//---------------------------------------------------------

struct FiguredBassFont {
      QString           family;
      QString           displayName;
      qreal             defPitch;
      qreal             defLineHeight;
      QChar             displayAccidental[int(FiguredBassItem::Modifier::NUMOF)];
      QChar             displayParenthesis[int(FiguredBassItem::Parenthesis::NUMOF)];
      QChar             displayDigit[int(FiguredBassItem::Style::NUMOF)][10][int(FiguredBassItem::Combination::NUMOF)];

      bool read(XmlReader&);
      };

//---------------------------------------------------------
//   @@ FiguredBass
///    A complete figured bass indication
//
//   @P onNote  bool  whether it is placed on a note beginning or between notes (read only)
//   @P ticks   int   duration in ticks
//---------------------------------------------------------

class FiguredBass final : public TextBase {
      std::vector<FiguredBassItem*> items;      // the individual lines of the F.B.
      QVector<qreal>    _lineLengths;           // lengths of duration indicator lines (in raster units)
      bool              _onNote;                // true if this element is on a staff note | false if it is betweee notes
      Fraction          _ticks;                 // the duration (used for cont. lines and for multiple F.B.
                                                // under the same note)
      qreal             _printedLineLength;     // the length of lines actually printed (i.e. continuation lines)
      void              layoutLines();
      bool              hasParentheses() const; // read / write MusicXML support

      virtual Sid getPropertyStyle(Pid) const override;

   public:
      FiguredBass(Score* s = 0);
      FiguredBass(const FiguredBass&);
      ~FiguredBass();

      // a convenience static function to create/retrieve a new FiguredBass into/from its intended parent
      static FiguredBass* addFiguredBassToSegment(Segment* seg, int track, const Fraction& extTicks, bool *pNew);

      // static functions for font config files
      static bool       readConfigFile(const QString& fileName);
      static QList<QString>  fontNames();
      static bool       fontData(int nIdx, QString *pFamily, QString *pDisplayName,
                              qreal * pSize, qreal * pLineHeight);

      // standard re-implemented virtual functions
      virtual FiguredBass*    clone() const override   { return new FiguredBass(*this); }
      virtual ElementType   type() const override      { return ElementType::FIGURED_BASS; }
      virtual void      draw(QPainter* painter) const override;
      virtual void      endEdit(EditData&) override;
      virtual void      layout() override;
      virtual void      read(XmlReader&) override;
      virtual void      setSelected(bool f) override;
      virtual void      setVisible(bool f) override;
      virtual void      startEdit(EditData&) override;
      virtual void      write(XmlWriter& xml) const override;

      // read / write MusicXML
      void              writeMusicXML(XmlWriter& xml, bool isOriginalFigure, int crEndTick, int fbEndTick, bool writeDuration, int divisions) const;

//DEBUG
//Q_INVOKABLE Ms::FiguredBassItem* addItem();

      // getters / setters / properties
//      void qmlItemsAppend(QDeclarativeListProperty<FiguredBassItem> *list, FiguredBassItem * pItem)
//                                                {     list->append(pItem);
//                                                      items.append(&pItem);
//                                                }
//      QDeclarativeListProperty<FiguredBassItem> qmlItems()
//                                                {     QList<FiguredBassItem*> list;
//                                                      foreach(FiguredBassItem item, items)
//                                                            list.append(&item);
//                                                      return QDeclarativeListProperty<FiguredBassItem>(this, &items, qmlItemsAppend);
//                                                }
      qreal             lineLength(int idx) const     {   if(_lineLengths.size() > idx)
                                                            return _lineLengths.at(idx);
                                                          return 0;   }
      qreal             printedLineLength() const     { return _printedLineLength; }
      bool              onNote() const          { return _onNote; }
      size_t            numOfItems() const      { return items.size(); }
      void              setOnNote(bool val)     { _onNote = val;  }
      Segment *         segment() const         { return (Segment*)(parent()); }
      Fraction          ticks() const           { return _ticks;  }
      void              setTicks(const Fraction& v) { _ticks = v;   }

      qreal             additionalContLineX(qreal pagePosY) const;// returns the X coord (in page coord) of cont. line at pagePosY, if any
      FiguredBass *     nextFiguredBass() const;                  // returns next *adjacent* f.b. item, if any

      virtual QVariant  getProperty(Pid propertyId) const override;
      virtual bool      setProperty(Pid propertyId, const QVariant&) override;
      virtual QVariant  propertyDefault(Pid) const override;

      void appendItem(FiguredBassItem* item) {  items.push_back(item); }
      };


}     // namespace Ms

Q_DECLARE_METATYPE(Ms::FiguredBassItem::Modifier);
Q_DECLARE_METATYPE(Ms::FiguredBassItem::Parenthesis);
Q_DECLARE_METATYPE(Ms::FiguredBassItem::ContLine);

#endif