1 //=============================================================================
2 //  MuseScore
3 //  Music Composition & Notation
4 //
5 //  Copyright (C) 2002-2011 Werner Schweer
6 //
7 //  This program is free software; you can redistribute it and/or modify
8 //  it under the terms of the GNU General Public License version 2
9 //  as published by the Free Software Foundation and appearing in
10 //  the file LICENCE.GPL
11 //=============================================================================
12 
13 #include "accidental.h"
14 #include "note.h"
15 #include "symbol.h"
16 #include "sym.h"
17 #include "score.h"
18 #include "icon.h"
19 #include "staff.h"
20 #include "undo.h"
21 #include "xml.h"
22 
23 namespace Ms {
24 
25 //---------------------------------------------------------
26 //   Acc
27 //---------------------------------------------------------
28 
29 struct Acc {
30       AccidentalVal offset;   // semitone offset
31       int centOffset;
32       SymId sym;
AccMs::Acc33       Acc(AccidentalVal o, int o2, SymId s) : offset(o), centOffset(o2), sym(s) {}
34       };
35 
36 // NOTE: keep this in sync with with AccidentalType enum in types.h, watch out for isMicrotonal()
37 static Acc accList[] = {
38       Acc(AccidentalVal::NATURAL,    0, SymId::noSym),                  // NONE
39       Acc(AccidentalVal::FLAT,       0, SymId::accidentalFlat),         // FLAT
40       Acc(AccidentalVal::NATURAL,    0, SymId::accidentalNatural),      // NATURAL
41       Acc(AccidentalVal::SHARP,      0, SymId::accidentalSharp),        // SHARP
42       Acc(AccidentalVal::SHARP2,     0, SymId::accidentalDoubleSharp),  // SHARP2
43       Acc(AccidentalVal::FLAT2,      0, SymId::accidentalDoubleFlat),   // FLAT2
44       Acc(AccidentalVal::SHARP3,     0, SymId::accidentalTripleSharp),  // SHARP3
45       Acc(AccidentalVal::FLAT3,      0, SymId::accidentalTripleFlat),   // FLAT3
46       Acc(AccidentalVal::FLAT,       0, SymId::accidentalNaturalFlat),  // NATURAL_FLAT
47       Acc(AccidentalVal::SHARP,      0, SymId::accidentalNaturalSharp), // NATURAL_SHARP
48       Acc(AccidentalVal::SHARP2,     0, SymId::accidentalSharpSharp),   // SHARP_SHARP
49 
50       // Gould arrow quartertone
51       Acc(AccidentalVal::NATURAL,   -50, SymId::accidentalQuarterToneFlatArrowUp),        // FLAT_ARROW_UP
52       Acc(AccidentalVal::NATURAL,  -150, SymId::accidentalThreeQuarterTonesFlatArrowDown),// FLAT_ARROW_DOWN
53       Acc(AccidentalVal::NATURAL,    50, SymId::accidentalQuarterToneSharpNaturalArrowUp),// NATURAL_ARROW_UP
54       Acc(AccidentalVal::NATURAL,   -50, SymId::accidentalQuarterToneFlatNaturalArrowDown), // NATURAL_ARROW_DOWN
55       Acc(AccidentalVal::NATURAL,   150, SymId::accidentalThreeQuarterTonesSharpArrowUp), // SHARP_ARROW_UP
56       Acc(AccidentalVal::NATURAL,    50, SymId::accidentalQuarterToneSharpArrowDown),     // SHARP_ARROW_DOWN
57       Acc(AccidentalVal::NATURAL,   250, SymId::accidentalFiveQuarterTonesSharpArrowUp),    // SHARP2_ARROW_UP
58       Acc(AccidentalVal::NATURAL,   150, SymId::accidentalThreeQuarterTonesSharpArrowDown), // SHARP2_ARROW_DOWN
59       Acc(AccidentalVal::NATURAL,  -250, SymId::accidentalThreeQuarterTonesFlatArrowUp),    // FLAT2_ARROW_UP
60       Acc(AccidentalVal::NATURAL,  -150, SymId::accidentalFiveQuarterTonesFlatArrowDown),   // FLAT2_ARROW_DOWN
61       Acc(AccidentalVal::NATURAL,   -50, SymId::accidentalArrowDown), // ARROW_DOWN
62       Acc(AccidentalVal::NATURAL,    50, SymId::accidentalArrowUp),   // ARROW_UP
63 
64       // Stein-Zimmermann
65       Acc(AccidentalVal::NATURAL,   -50, SymId::accidentalQuarterToneFlatStein), // MIRRORED_FLAT
66       Acc(AccidentalVal::NATURAL,  -150, SymId::accidentalThreeQuarterTonesFlatZimmermann), // MIRRORED_FLAT2
67       Acc(AccidentalVal::NATURAL,    50, SymId::accidentalQuarterToneSharpStein),       // SHARP_SLASH
68       Acc(AccidentalVal::NATURAL,   150, SymId::accidentalThreeQuarterTonesSharpStein), // SHARP_SLASH4
69 
70       // Arel-Ezgi-Uzdilek (AEU)
71       Acc(AccidentalVal::NATURAL,     0, SymId::accidentalBuyukMucennebFlat),  // FLAT_SLASH2
72       Acc(AccidentalVal::NATURAL,     0, SymId::accidentalBakiyeFlat),         // FLAT_SLASH
73       Acc(AccidentalVal::NATURAL,     0, SymId::accidentalKucukMucennebSharp), // SHARP_SLASH3
74       Acc(AccidentalVal::NATURAL,     0, SymId::accidentalBuyukMucennebSharp), // SHARP_SLASH2
75 
76       // Extended Helmholtz-Ellis accidentals (just intonation)
77       Acc(AccidentalVal::NATURAL,     0, SymId::accidentalDoubleFlatOneArrowDown),
78       Acc(AccidentalVal::NATURAL,     0, SymId::accidentalFlatOneArrowDown),
79       Acc(AccidentalVal::NATURAL,     0, SymId::accidentalNaturalOneArrowDown),
80       Acc(AccidentalVal::NATURAL,     0, SymId::accidentalSharpOneArrowDown),
81       Acc(AccidentalVal::NATURAL,     0, SymId::accidentalDoubleSharpOneArrowDown),
82       Acc(AccidentalVal::NATURAL,     0, SymId::accidentalDoubleFlatOneArrowUp),
83 
84       Acc(AccidentalVal::NATURAL,     0, SymId::accidentalFlatOneArrowUp),
85       Acc(AccidentalVal::NATURAL,     0, SymId::accidentalNaturalOneArrowUp),
86       Acc(AccidentalVal::NATURAL,     0, SymId::accidentalSharpOneArrowUp),
87       Acc(AccidentalVal::NATURAL,     0, SymId::accidentalDoubleSharpOneArrowUp),
88       Acc(AccidentalVal::NATURAL,     0, SymId::accidentalDoubleFlatTwoArrowsDown),
89       Acc(AccidentalVal::NATURAL,     0, SymId::accidentalFlatTwoArrowsDown),
90 
91       Acc(AccidentalVal::NATURAL,     0, SymId::accidentalNaturalTwoArrowsDown),
92       Acc(AccidentalVal::NATURAL,     0, SymId::accidentalSharpTwoArrowsDown),
93       Acc(AccidentalVal::NATURAL,     0, SymId::accidentalDoubleSharpTwoArrowsDown),
94       Acc(AccidentalVal::NATURAL,     0, SymId::accidentalDoubleFlatTwoArrowsUp),
95       Acc(AccidentalVal::NATURAL,     0, SymId::accidentalFlatTwoArrowsUp),
96       Acc(AccidentalVal::NATURAL,     0, SymId::accidentalNaturalTwoArrowsUp),
97 
98       Acc(AccidentalVal::NATURAL,     0, SymId::accidentalSharpTwoArrowsUp),
99       Acc(AccidentalVal::NATURAL,     0, SymId::accidentalDoubleSharpTwoArrowsUp),
100       Acc(AccidentalVal::NATURAL,     0, SymId::accidentalDoubleFlatThreeArrowsDown),
101       Acc(AccidentalVal::NATURAL,     0, SymId::accidentalFlatThreeArrowsDown),
102       Acc(AccidentalVal::NATURAL,     0, SymId::accidentalNaturalThreeArrowsDown),
103       Acc(AccidentalVal::NATURAL,     0, SymId::accidentalSharpThreeArrowsDown),
104 
105       Acc(AccidentalVal::NATURAL,     0, SymId::accidentalDoubleSharpThreeArrowsDown),
106       Acc(AccidentalVal::NATURAL,     0, SymId::accidentalDoubleFlatThreeArrowsUp),
107       Acc(AccidentalVal::NATURAL,     0, SymId::accidentalFlatThreeArrowsUp),
108       Acc(AccidentalVal::NATURAL,     0, SymId::accidentalNaturalThreeArrowsUp),
109       Acc(AccidentalVal::NATURAL,     0, SymId::accidentalSharpThreeArrowsUp),
110       Acc(AccidentalVal::NATURAL,     0, SymId::accidentalDoubleSharpThreeArrowsUp),
111 
112       Acc(AccidentalVal::NATURAL,     0, SymId::accidentalLowerOneSeptimalComma),
113       Acc(AccidentalVal::NATURAL,     0, SymId::accidentalRaiseOneSeptimalComma),
114       Acc(AccidentalVal::NATURAL,     0, SymId::accidentalLowerTwoSeptimalCommas),
115       Acc(AccidentalVal::NATURAL,     0, SymId::accidentalRaiseTwoSeptimalCommas),
116       Acc(AccidentalVal::NATURAL,     0, SymId::accidentalLowerOneUndecimalQuartertone),
117       Acc(AccidentalVal::NATURAL,     0, SymId::accidentalRaiseOneUndecimalQuartertone),
118 
119       Acc(AccidentalVal::NATURAL,     0, SymId::accidentalLowerOneTridecimalQuartertone),
120       Acc(AccidentalVal::NATURAL,     0, SymId::accidentalRaiseOneTridecimalQuartertone),
121 
122       Acc(AccidentalVal::NATURAL,     0, SymId::accidentalDoubleFlatEqualTempered),
123       Acc(AccidentalVal::NATURAL,     0, SymId::accidentalFlatEqualTempered),
124       Acc(AccidentalVal::NATURAL,     0, SymId::accidentalNaturalEqualTempered),
125       Acc(AccidentalVal::NATURAL,     0, SymId::accidentalSharpEqualTempered),
126       Acc(AccidentalVal::NATURAL,     0, SymId::accidentalDoubleSharpEqualTempered),
127       Acc(AccidentalVal::NATURAL,     0, SymId::accidentalQuarterFlatEqualTempered),
128       Acc(AccidentalVal::NATURAL,     0, SymId::accidentalQuarterSharpEqualTempered),
129 
130       Acc(AccidentalVal::NATURAL,  -6.8, SymId::accidentalCombiningLower17Schisma),
131       Acc(AccidentalVal::NATURAL,   6.8, SymId::accidentalCombiningRaise17Schisma),
132       Acc(AccidentalVal::NATURAL,  -3.4, SymId::accidentalCombiningLower19Schisma),
133       Acc(AccidentalVal::NATURAL,   3.4, SymId::accidentalCombiningRaise19Schisma),
134       Acc(AccidentalVal::NATURAL, -16.5, SymId::accidentalCombiningLower23Limit29LimitComma),
135       Acc(AccidentalVal::NATURAL,  16.5, SymId::accidentalCombiningRaise23Limit29LimitComma),
136       Acc(AccidentalVal::NATURAL,  -1.7, SymId::accidentalCombiningLower31Schisma),
137       Acc(AccidentalVal::NATURAL,   1.7, SymId::accidentalCombiningRaise31Schisma),
138       Acc(AccidentalVal::NATURAL, -10.9, SymId::accidentalCombiningLower53LimitComma),
139       Acc(AccidentalVal::NATURAL,  10.9, SymId::accidentalCombiningRaise53LimitComma),
140       //Acc(AccidentalVal::NATURAL,     0, SymId::accidentalEnharmonicAlmostEqualTo),
141       //Acc(AccidentalVal::NATURAL,     0, SymId::accidentalEnharmonicEquals),
142       //Acc(AccidentalVal::NATURAL,     0, SymId::accidentalEnharmonicTilde),
143 
144       // Persian
145       Acc(AccidentalVal::NATURAL,    33, SymId::accidentalSori),                          // SORI
146       Acc(AccidentalVal::NATURAL,   -67, SymId::accidentalKoron),                         // KORON
147 
148       // Wyschnegradsky
149       Acc(AccidentalVal::NATURAL,  -167, SymId::accidentalWyschnegradsky10TwelfthsFlat),
150       Acc(AccidentalVal::NATURAL,   167, SymId::accidentalWyschnegradsky10TwelfthsSharp),
151       Acc(AccidentalVal::NATURAL,  -183, SymId::accidentalWyschnegradsky11TwelfthsFlat),
152       Acc(AccidentalVal::NATURAL,   183, SymId::accidentalWyschnegradsky11TwelfthsSharp),
153       Acc(AccidentalVal::NATURAL,   -17, SymId::accidentalWyschnegradsky1TwelfthsFlat),
154       Acc(AccidentalVal::NATURAL,    17, SymId::accidentalWyschnegradsky1TwelfthsSharp),
155       Acc(AccidentalVal::NATURAL,   -33, SymId::accidentalWyschnegradsky2TwelfthsFlat),
156       Acc(AccidentalVal::NATURAL,    33, SymId::accidentalWyschnegradsky2TwelfthsSharp),
157       Acc(AccidentalVal::NATURAL,   -50, SymId::accidentalWyschnegradsky3TwelfthsFlat),
158       Acc(AccidentalVal::NATURAL,    50, SymId::accidentalWyschnegradsky3TwelfthsSharp),
159       Acc(AccidentalVal::NATURAL,   -67, SymId::accidentalWyschnegradsky4TwelfthsFlat),
160       Acc(AccidentalVal::NATURAL,    67, SymId::accidentalWyschnegradsky4TwelfthsSharp),
161       Acc(AccidentalVal::NATURAL,   -83, SymId::accidentalWyschnegradsky5TwelfthsFlat),
162       Acc(AccidentalVal::NATURAL,    83, SymId::accidentalWyschnegradsky5TwelfthsSharp),
163       Acc(AccidentalVal::FLAT,        0, SymId::accidentalWyschnegradsky6TwelfthsFlat),
164       Acc(AccidentalVal::SHARP,       0, SymId::accidentalWyschnegradsky6TwelfthsSharp),
165       Acc(AccidentalVal::NATURAL,  -116, SymId::accidentalWyschnegradsky7TwelfthsFlat),
166       Acc(AccidentalVal::NATURAL,   116, SymId::accidentalWyschnegradsky7TwelfthsSharp),
167       Acc(AccidentalVal::NATURAL,  -133, SymId::accidentalWyschnegradsky8TwelfthsFlat),
168       Acc(AccidentalVal::NATURAL,   133, SymId::accidentalWyschnegradsky8TwelfthsSharp),
169       Acc(AccidentalVal::NATURAL,  -150, SymId::accidentalWyschnegradsky9TwelfthsFlat),
170       Acc(AccidentalVal::NATURAL,   150, SymId::accidentalWyschnegradsky9TwelfthsSharp),
171 
172       // the most important (Spartan) Sagittal accidentals
173       Acc(AccidentalVal::NATURAL,  -5.8, SymId::accSagittal5v7KleismaDown),
174       Acc(AccidentalVal::NATURAL,   5.8, SymId::accSagittal5v7KleismaUp),
175       Acc(AccidentalVal::NATURAL, -21.5, SymId::accSagittal5CommaDown),
176       Acc(AccidentalVal::NATURAL,  21.5, SymId::accSagittal5CommaUp),
177       Acc(AccidentalVal::NATURAL, -27.3, SymId::accSagittal7CommaDown),
178       Acc(AccidentalVal::NATURAL,  27.3, SymId::accSagittal7CommaUp),
179       Acc(AccidentalVal::NATURAL, -43.0, SymId::accSagittal25SmallDiesisDown),
180       Acc(AccidentalVal::NATURAL,  43.0, SymId::accSagittal25SmallDiesisUp),
181       Acc(AccidentalVal::NATURAL, -48.8, SymId::accSagittal35MediumDiesisDown),
182       Acc(AccidentalVal::NATURAL,  48.8, SymId::accSagittal35MediumDiesisUp),
183       Acc(AccidentalVal::NATURAL, -53.3, SymId::accSagittal11MediumDiesisDown),
184       Acc(AccidentalVal::NATURAL,  53.3, SymId::accSagittal11MediumDiesisUp),
185       Acc(AccidentalVal::NATURAL, -60.4, SymId::accSagittal11LargeDiesisDown),
186       Acc(AccidentalVal::NATURAL,  60.4, SymId::accSagittal11LargeDiesisUp),
187       Acc(AccidentalVal::NATURAL, -64.9, SymId::accSagittal35LargeDiesisDown),
188       Acc(AccidentalVal::NATURAL,  64.9, SymId::accSagittal35LargeDiesisUp),
189       Acc(AccidentalVal::NATURAL, -70.7, SymId::accSagittalFlat25SUp),
190       Acc(AccidentalVal::NATURAL,  70.7, SymId::accSagittalSharp25SDown),
191       Acc(AccidentalVal::NATURAL, -86.4, SymId::accSagittalFlat7CUp),
192       Acc(AccidentalVal::NATURAL,  86.4, SymId::accSagittalSharp7CDown),
193       Acc(AccidentalVal::NATURAL, -92.2, SymId::accSagittalFlat5CUp),
194       Acc(AccidentalVal::NATURAL,  92.2, SymId::accSagittalSharp5CDown),
195       Acc(AccidentalVal::NATURAL,-107.9, SymId::accSagittalFlat5v7kUp),
196       Acc(AccidentalVal::NATURAL, 107.9, SymId::accSagittalSharp5v7kDown),
197       Acc(AccidentalVal::NATURAL,-113.7, SymId::accSagittalFlat),
198       Acc(AccidentalVal::NATURAL, 113.7, SymId::accSagittalSharp),
199       };
200 
201 //---------------------------------------------------------
202 //   sym2accidentalVal
203 //---------------------------------------------------------
204 
sym2accidentalVal(SymId id)205 AccidentalVal sym2accidentalVal(SymId id)
206       {
207       for (const Acc& a : accList) {
208             if (a.sym == id)
209                   return a.offset;
210             }
211       return AccidentalVal::NATURAL;
212       }
213 
214 //---------------------------------------------------------
215 //   Accidental
216 //---------------------------------------------------------
217 
Accidental(Score * s)218 Accidental::Accidental(Score* s)
219    : Element(s, ElementFlag::MOVABLE)
220       {
221       }
222 
223 //---------------------------------------------------------
224 //   read
225 //---------------------------------------------------------
226 
read(XmlReader & e)227 void Accidental::read(XmlReader& e)
228       {
229       while (e.readNextStartElement()) {
230             const QStringRef& tag(e.name());
231             if (tag == "bracket") {
232                   int i = e.readInt();
233                   if (i == 0 || i == 1 || i == 2)
234                         _bracket = AccidentalBracket(i);
235                   }
236             else if (tag == "subtype")
237                   setSubtype(e.readElementText());
238             else if (tag == "role") {
239                   AccidentalRole r = AccidentalRole(e.readInt());
240                   if (r == AccidentalRole::AUTO || r == AccidentalRole::USER)
241                         _role = r;
242                   }
243             else if (tag == "small")
244                   _small = e.readInt();
245             else if (Element::readProperties(e))
246                   ;
247             else
248                   e.unknown();
249             }
250       }
251 
252 //---------------------------------------------------------
253 //   write
254 //---------------------------------------------------------
255 
write(XmlWriter & xml) const256 void Accidental::write(XmlWriter& xml) const
257       {
258       xml.stag(this);
259       writeProperty(xml, Pid::ACCIDENTAL_BRACKET);
260       writeProperty(xml, Pid::ROLE);
261       writeProperty(xml, Pid::SMALL);
262       writeProperty(xml, Pid::ACCIDENTAL_TYPE);
263       Element::writeProperties(xml);
264       xml.etag();
265       }
266 
267 //---------------------------------------------------------
268 //   subTypeUserName
269 //---------------------------------------------------------
270 
subtypeUserName() const271 QString Accidental::subtypeUserName() const
272       {
273       return Sym::id2userName(symbol());
274       }
275 
276 //---------------------------------------------------------
277 //   symbol
278 //---------------------------------------------------------
279 
symbol() const280 SymId Accidental::symbol() const
281       {
282       return accList[int(accidentalType())].sym;
283       }
284 
285 //---------------------------------------------------------
286 //   subtype2value
287 //    returns the resulting pitch offset
288 //---------------------------------------------------------
289 
subtype2value(AccidentalType st)290 AccidentalVal Accidental::subtype2value(AccidentalType st)
291       {
292       return accList[int(st)].offset;
293       }
294 
295 //---------------------------------------------------------
296 //   subtype2name
297 //---------------------------------------------------------
298 
subtype2name(AccidentalType st)299 const char* Accidental::subtype2name(AccidentalType st)
300       {
301       return Sym::id2name(accList[int(st)].sym);
302       }
303 
304 //---------------------------------------------------------
305 //   subtype2symbol
306 //---------------------------------------------------------
307 
subtype2symbol(AccidentalType st)308 SymId Accidental::subtype2symbol(AccidentalType st)
309       {
310       return accList[int(st)].sym;
311       }
312 //---------------------------------------------------------
313 //   name2subtype
314 //---------------------------------------------------------
315 
name2subtype(const QString & tag)316 AccidentalType Accidental::name2subtype(const QString& tag)
317       {
318       SymId symId = Sym::name2id(tag);
319       if (symId == SymId::noSym)
320             ; // qDebug("no symbol found");
321       else {
322             int i = 0;
323             for (const Acc& acc : accList) {
324                   if (acc.sym == symId)
325                         return AccidentalType(i);
326                   ++i;
327                   }
328             }
329       return AccidentalType::NONE;
330       }
331 
332 //---------------------------------------------------------
333 //   setSubtype
334 //---------------------------------------------------------
335 
setSubtype(const QString & tag)336 void Accidental::setSubtype(const QString& tag)
337       {
338       setAccidentalType(name2subtype(tag));
339       }
340 
341 //---------------------------------------------------------
342 //   layout
343 //---------------------------------------------------------
344 
layout()345 void Accidental::layout()
346       {
347       el.clear();
348 
349       // TODO: remove Accidental in layout()
350       // don't show accidentals for tab or slash notation
351       if (onTabStaff() || (note() && note()->fixed())) {
352             setbbox(QRectF());
353             return;
354             }
355 
356       qreal m = parent() ? parent()->mag() : 1.0;
357       if (_small)
358             m *= score()->styleD(Sid::smallNoteMag);
359       setMag(m);
360 
361       // if the accidental is standard (doubleflat, flat, natural, sharp or double sharp)
362       // and it has either no bracket or parentheses, then we have glyphs straight from smufl.
363       if (_bracket == AccidentalBracket::NONE
364          || (_bracket == AccidentalBracket::PARENTHESIS
365           && (_accidentalType == AccidentalType::FLAT
366            || _accidentalType == AccidentalType::NATURAL
367            || _accidentalType == AccidentalType::SHARP
368            || _accidentalType == AccidentalType::SHARP2
369            || _accidentalType == AccidentalType::FLAT2))) {
370             layoutSingleGlyphAccidental();
371            }
372       else {
373             layoutMultiGlyphAccidental();
374             }
375       }
376 
layoutSingleGlyphAccidental()377 void Accidental::layoutSingleGlyphAccidental()
378       {
379       QRectF r;
380 
381       SymId s = symbol();
382       if (_bracket == AccidentalBracket::PARENTHESIS) {
383             switch (_accidentalType) {
384                   case AccidentalType::FLAT2:
385                         s = SymId::accidentalDoubleFlatParens;
386                         break;
387                   case AccidentalType::FLAT:
388                         s = SymId::accidentalFlatParens;
389                         break;
390                   case AccidentalType::NATURAL:
391                         s = SymId::accidentalNaturalParens;
392                         break;
393                   case AccidentalType::SHARP:
394                         s = SymId::accidentalSharpParens;
395                         break;
396                   case AccidentalType::SHARP2:
397                         s = SymId::accidentalDoubleSharpParens;
398                         break;
399                   default:
400                         break;
401                   }
402             if (!score()->scoreFont()->isValid(s)) {
403                   layoutMultiGlyphAccidental();
404                   return;
405                   }
406             }
407 
408       SymElement e(s, 0.0, 0.0);
409       el.append(e);
410       r |= symBbox(s);
411       setbbox(r);
412       }
413 
414 
layoutMultiGlyphAccidental()415 void Accidental::layoutMultiGlyphAccidental()
416       {
417       qreal margin = score()->styleP(Sid::bracketedAccidentalPadding);
418       QRectF r;
419       qreal x = 0.0;
420 
421       // should always be true
422       if (_bracket != AccidentalBracket::NONE) {
423             SymId id = SymId::noSym;
424             switch (_bracket) {
425                   case AccidentalBracket::PARENTHESIS:
426                         id = SymId::accidentalParensLeft;
427                         break;
428                   case AccidentalBracket::BRACKET:
429                         id = SymId::accidentalBracketLeft;
430                         break;
431                   case AccidentalBracket::BRACE:
432                         id = SymId::accidentalCombiningOpenCurlyBrace;
433                         break;
434                   case AccidentalBracket::NONE: // can't happen
435                         break;
436                   }
437             SymElement se(id, 0.0, _bracket == AccidentalBracket::BRACE ? spatium() * 0.4 : 0.0);
438             el.append(se);
439             r |= symBbox(id);
440             x += symAdvance(id) + margin;
441             }
442 
443       SymId s = symbol();
444       SymElement e(s, x, 0.0);
445       el.append(e);
446       r |= symBbox(s).translated(x, 0.0);
447 
448       // should always be true
449       if (_bracket != AccidentalBracket::NONE) {
450             x += symAdvance(s) + margin;
451             SymId id = SymId::noSym;
452             switch (_bracket) {
453                   case AccidentalBracket::PARENTHESIS:
454                         id = SymId::accidentalParensRight;
455                         break;
456                   case AccidentalBracket::BRACKET:
457                         id = SymId::accidentalBracketRight;
458                         break;
459                   case AccidentalBracket::BRACE:
460                         id = SymId::accidentalCombiningCloseCurlyBrace;
461                         break;
462                   case AccidentalBracket::NONE: // can't happen
463                         break;
464                   }
465             SymElement se(id, x, _bracket == AccidentalBracket::BRACE ? spatium() * 0.4 : 0.0);
466             el.append(se);
467             r |= symBbox(id).translated(x, 0.0);
468             }
469       setbbox(r);
470       }
471 
472 //---------------------------------------------------------
473 //   value2subtype
474 //---------------------------------------------------------
475 
value2subtype(AccidentalVal v)476 AccidentalType Accidental::value2subtype(AccidentalVal v)
477       {
478       switch(v) {
479             case AccidentalVal::NATURAL: return AccidentalType::NONE;
480             case AccidentalVal::SHARP:   return AccidentalType::SHARP;
481             case AccidentalVal::SHARP2:  return AccidentalType::SHARP2;
482             case AccidentalVal::SHARP3:  return AccidentalType::SHARP3;
483             case AccidentalVal::FLAT:    return AccidentalType::FLAT;
484             case AccidentalVal::FLAT2:   return AccidentalType::FLAT2;
485             case AccidentalVal::FLAT3:   return AccidentalType::FLAT3;
486             default:
487                   qFatal("value2subtype: illegal accidental val %d", int(v));
488             }
489       return AccidentalType::NONE;
490       }
491 
492 //---------------------------------------------------------
493 //   draw
494 //---------------------------------------------------------
495 
draw(QPainter * painter) const496 void Accidental::draw(QPainter* painter) const
497       {
498       // don't show accidentals for tab or slash notation
499       if (onTabStaff() || (note() && note()->fixed()))
500             return;
501       painter->setPen(curColor());
502       for (const SymElement& e : el)
503             score()->scoreFont()->draw(e.sym, painter, magS(), QPointF(e.x, e.y));
504       }
505 
506 //---------------------------------------------------------
507 //   acceptDrop
508 //---------------------------------------------------------
509 
acceptDrop(EditData & data) const510 bool Accidental::acceptDrop(EditData& data) const
511       {
512       Element* e = data.dropElement;
513       return e->isIcon() && (toIcon(e)->iconType() == IconType::BRACKETS || toIcon(e)->iconType() == IconType::PARENTHESES  || toIcon(e)->iconType() == IconType::BRACES);
514       }
515 
516 //---------------------------------------------------------
517 //   drop
518 //---------------------------------------------------------
519 
drop(EditData & data)520 Element* Accidental::drop(EditData& data)
521       {
522       Element* e = data.dropElement;
523       switch(e->type()) {
524             case ElementType::ICON :
525                   switch(toIcon(e)->iconType()) {
526                         case IconType::BRACKETS:
527                               undoChangeProperty(Pid::ACCIDENTAL_BRACKET, int(AccidentalBracket::BRACKET), PropertyFlags::NOSTYLE);
528                               break;
529                         case IconType::PARENTHESES:
530                               undoChangeProperty(Pid::ACCIDENTAL_BRACKET, int(AccidentalBracket::PARENTHESIS), PropertyFlags::NOSTYLE);
531                               break;
532                         case IconType::BRACES:
533                               undoChangeProperty(Pid::ACCIDENTAL_BRACKET, int(AccidentalBracket::BRACE), PropertyFlags::NOSTYLE);
534                               break;
535                         default:
536                               qDebug("unknown icon type");
537                               break;
538                         }
539                   break;
540             default:
541                   break;
542             }
543       delete e;
544       return 0;
545       }
546 
547 //---------------------------------------------------------
548 //   undoSetSmall
549 //---------------------------------------------------------
550 
undoSetSmall(bool val)551 void Accidental::undoSetSmall(bool val)
552       {
553       undoChangeProperty(Pid::SMALL, val);
554       }
555 
556 //---------------------------------------------------------
557 //   getProperty
558 //---------------------------------------------------------
559 
getProperty(Pid propertyId) const560 QVariant Accidental::getProperty(Pid propertyId) const
561       {
562       switch (propertyId) {
563             case Pid::ACCIDENTAL_TYPE:    return int(_accidentalType);
564             case Pid::SMALL:              return _small;
565             case Pid::ACCIDENTAL_BRACKET: return int(bracket());
566             case Pid::ROLE:               return int(role());
567             default:
568                   return Element::getProperty(propertyId);
569             }
570       }
571 
572 //---------------------------------------------------------
573 //   propertyDefault
574 //---------------------------------------------------------
575 
propertyDefault(Pid propertyId) const576 QVariant Accidental::propertyDefault(Pid propertyId) const
577       {
578       switch (propertyId) {
579             case Pid::ACCIDENTAL_TYPE:    return int(AccidentalType::NONE);
580             case Pid::SMALL:              return false;
581             case Pid::ACCIDENTAL_BRACKET: return int(AccidentalBracket::NONE);
582             case Pid::ROLE:               return int(AccidentalRole::AUTO);
583             default:
584                   return Element::propertyDefault(propertyId);
585             }
586       }
587 
588 //---------------------------------------------------------
589 //   setProperty
590 //---------------------------------------------------------
591 
setProperty(Pid propertyId,const QVariant & v)592 bool Accidental::setProperty(Pid propertyId, const QVariant& v)
593       {
594       switch (propertyId) {
595             case Pid::ACCIDENTAL_TYPE:
596                   setAccidentalType(AccidentalType(v.toInt()));
597                   break;
598             case Pid::SMALL:
599                   _small = v.toBool();
600                   break;
601             case Pid::ACCIDENTAL_BRACKET:
602                   _bracket = AccidentalBracket(v.toInt());
603                   break;
604             case Pid::ROLE:
605                   _role = v.value<AccidentalRole>();
606                   break;
607             default:
608                   return Element::setProperty(propertyId, v);
609             }
610       triggerLayout();
611       return true;
612       }
613 
614 //---------------------------------------------------------
615 //   propertyId
616 //---------------------------------------------------------
617 
propertyId(const QStringRef & xmlName) const618 Pid Accidental::propertyId(const QStringRef& xmlName) const
619       {
620       if (xmlName == propertyName(Pid::ACCIDENTAL_TYPE))
621             return Pid::ACCIDENTAL_TYPE;
622       return Element::propertyId(xmlName);
623       }
624 
625 //---------------------------------------------------------
626 //   propertyUserValue
627 //---------------------------------------------------------
628 
propertyUserValue(Pid pid) const629 QString Accidental::propertyUserValue(Pid pid) const
630       {
631       switch(pid) {
632             case Pid::ACCIDENTAL_TYPE:
633                   return subtypeUserName();
634             default:
635                   return Element::propertyUserValue(pid);
636             }
637       }
638 
639 //---------------------------------------------------------
640 //   accessibleInfo
641 //---------------------------------------------------------
642 
accessibleInfo() const643 QString Accidental::accessibleInfo() const
644       {
645       return QString("%1: %2").arg(Element::accessibleInfo(), Accidental::subtypeUserName());
646       }
647 
648 }
649