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
|