MuseScore/libmscore/key.cpp

224 lines
6.4 KiB
C++
Raw Normal View History

2012-05-26 14:26:10 +02:00
//=============================================================================
// 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
//=============================================================================
#include "key.h"
#include "xml.h"
#include "utils.h"
#include "score.h"
#include "pitchspelling.h"
2014-06-03 15:28:10 +02:00
#include "keylist.h"
2012-05-26 14:26:10 +02:00
2013-05-13 18:49:17 +02:00
namespace Ms {
2012-05-26 14:26:10 +02:00
//---------------------------------------------------------
// KeySigEvent
//---------------------------------------------------------
2014-06-20 17:07:22 +02:00
KeySigEvent::KeySigEvent(Key k)
2012-05-26 14:26:10 +02:00
{
2014-06-20 17:07:22 +02:00
Q_ASSERT(int(k) >= -7 && int(k) <= 7);
_key = k;
2014-06-05 11:37:21 +02:00
_invalid = false;
2012-05-26 14:26:10 +02:00
}
//---------------------------------------------------------
2014-06-20 17:07:22 +02:00
// enforceLimits - ensure _key
2014-06-03 15:28:10 +02:00
// is within acceptable limits (-7 .. +7).
2012-05-26 14:26:10 +02:00
// see KeySig::layout()
//---------------------------------------------------------
void KeySigEvent::enforceLimits()
{
const char* msg = 0;
2014-06-20 17:07:22 +02:00
if (_key < Key::MIN) {
_key = Key::MIN;
msg = "key < -7";
2012-05-26 14:26:10 +02:00
}
2014-06-20 17:07:22 +02:00
else if (_key > Key::MAX) {
_key = Key::MAX;
msg = "key > 7";
2012-05-26 14:26:10 +02:00
}
if (msg)
qDebug("KeySigEvent: %s", msg);
2012-05-26 14:26:10 +02:00
}
//---------------------------------------------------------
// setCustomType
//---------------------------------------------------------
void KeySigEvent::setCustomType(int v)
{
2014-06-20 17:07:22 +02:00
_key = Key::C;
_customType = v;
_custom = true;
_invalid = false;
2012-05-26 14:26:10 +02:00
}
//---------------------------------------------------------
// print
//---------------------------------------------------------
void KeySigEvent::print() const
{
qDebug("<KeySigEvent: ");
if (_invalid)
qDebug("invalid>");
else {
if (_custom)
2014-06-03 15:28:10 +02:00
qDebug("custom %d>", _customType);
2012-05-26 14:26:10 +02:00
else
2014-06-20 17:07:22 +02:00
qDebug("accidental %d>", int(_key));
2012-05-26 14:26:10 +02:00
}
}
//---------------------------------------------------------
2014-06-20 17:07:22 +02:00
// setKey
2012-05-26 14:26:10 +02:00
//---------------------------------------------------------
2014-06-20 17:07:22 +02:00
void KeySigEvent::setKey(Key v)
2012-05-26 14:26:10 +02:00
{
2014-06-20 17:07:22 +02:00
_key = v;
_custom = false;
_invalid = false;
2012-05-26 14:26:10 +02:00
enforceLimits();
}
//---------------------------------------------------------
// KeySigEvent::operator==
//---------------------------------------------------------
bool KeySigEvent::operator==(const KeySigEvent& e) const
{
if ((e._invalid != _invalid) || (e._custom != _custom))
return false;
if (_custom)
return e._customType == _customType;
else
2014-06-20 17:07:22 +02:00
return e._key == _key;
2012-05-26 14:26:10 +02:00
}
//---------------------------------------------------------
// KeySigEvent::operator!=
//---------------------------------------------------------
bool KeySigEvent::operator!=(const KeySigEvent& e) const
{
if ((e._invalid != _invalid) || (e._custom != _custom))
return true;
if (_custom)
return e._customType != _customType;
else
2014-06-20 17:07:22 +02:00
return e._key != _key;
2012-05-26 14:26:10 +02:00
}
//---------------------------------------------------------
// initLineList
// preset lines list with accidentals for given key
//---------------------------------------------------------
2014-06-20 17:07:22 +02:00
void AccidentalState::init(Key key)
2012-05-26 14:26:10 +02:00
{
memset(state, 2, 74);
for (int octave = 0; octave < 11; ++octave) {
2014-06-05 11:37:21 +02:00
if (key > 0) {
2014-06-20 17:07:22 +02:00
for (int i = 0; i < int(key); ++i) {
2012-05-26 14:26:10 +02:00
int idx = tpc2step(20 + i) + octave * 7;
if (idx < 74)
state[idx] = 1 + 2;
}
}
else {
2014-06-20 17:07:22 +02:00
for (int i = 0; i > int(key); --i) {
2012-05-26 14:26:10 +02:00
int idx = tpc2step(12 + i) + octave * 7;
if (idx < 74)
state[idx] = -1 + 2;
}
}
}
}
//---------------------------------------------------------
// transposeKey
//---------------------------------------------------------
2014-06-20 17:07:22 +02:00
Key transposeKey(Key key, const Interval& interval)
{
2014-06-20 17:07:22 +02:00
int tpc = int(key) + 14;
tpc = transposeTpc(tpc, interval, false);
// check for valid key sigs
2014-06-20 17:07:22 +02:00
if (tpc > 21)
tpc -= 12; // no more than 7 sharps in keysig
if (tpc < 7)
tpc += 12; // no more than 7 flats in keysig
return Key(tpc - 14);
}
2012-05-26 14:26:10 +02:00
//---------------------------------------------------------
// initFromSubtype
// for backward compatibility
//---------------------------------------------------------
void KeySigEvent::initFromSubtype(int st)
{
union U {
int subtype;
struct {
2014-06-20 17:07:22 +02:00
int _key:4;
2012-05-26 14:26:10 +02:00
int _naturalType:4;
unsigned _customType:16;
bool _custom : 1;
bool _invalid : 1;
};
};
U a;
a.subtype = st;
2014-06-20 17:07:22 +02:00
_key = Key(a._key);
2012-05-26 14:26:10 +02:00
_customType = a._customType;
_custom = a._custom;
_invalid = a._invalid;
enforceLimits();
}
2014-06-20 17:07:22 +02:00
//---------------------------------------------------------
// accidentalVal
//---------------------------------------------------------
AccidentalVal AccidentalState::accidentalVal(int line) const
{
Q_ASSERT(line >= 0 && line < 75);
return AccidentalVal((state[line] & 0x0f) - 2);
}
//---------------------------------------------------------
// tieContext
//---------------------------------------------------------
bool AccidentalState::tieContext(int line) const
{
Q_ASSERT(line >= 0 && line < 75);
return state[line] & TIE_CONTEXT;
}
//---------------------------------------------------------
// setAccidentalVal
//---------------------------------------------------------
void AccidentalState::setAccidentalVal(int line, AccidentalVal val, bool tieContext)
{
Q_ASSERT(line >= 0 && line < 75);
2014-06-18 12:05:41 +02:00
// casts needed to work around a bug in Xcode 4.2 on Mac, see #25910
Q_ASSERT(int(val) >= int(AccidentalVal::FLAT2) && int(val) <= int(AccidentalVal::SHARP2));
2014-06-20 17:07:22 +02:00
state[line] = (int(val) + 2) | (tieContext ? TIE_CONTEXT : 0);
}
2013-05-13 18:49:17 +02:00
}