You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
484 lines
13 KiB
484 lines
13 KiB
/*
|
|
Rosegarden
|
|
A MIDI and audio sequencer and musical notation editor.
|
|
|
|
This program is Copyright 2000-2008
|
|
Guillaume Laurent <glaurent@telegraph-road.org>,
|
|
Chris Cannam <cannam@all-day-breakfast.com>,
|
|
Richard Bown <richard.bown@ferventsoftware.com>
|
|
|
|
The moral rights of Guillaume Laurent, Chris Cannam, and Richard
|
|
Bown to claim authorship of this work have been asserted.
|
|
|
|
Other copyrights also apply to some parts of this work. Please
|
|
see the AUTHORS file and individual file headers for details.
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License as
|
|
published by the Free Software Foundation; either version 2 of the
|
|
License, or (at your option) any later version. See the file
|
|
COPYING included with this distribution for more information.
|
|
*/
|
|
|
|
|
|
#include "NoteStyle.h"
|
|
|
|
#include "base/NotationTypes.h"
|
|
#include "base/PropertyName.h"
|
|
#include "NoteCharacterNames.h"
|
|
#include "NoteStyleFactory.h"
|
|
|
|
|
|
namespace Rosegarden
|
|
{
|
|
|
|
NoteStyle::~NoteStyle()
|
|
{
|
|
// nothing
|
|
}
|
|
|
|
const NoteStyle::NoteHeadShape NoteStyle::AngledOval = "angled oval";
|
|
|
|
const NoteStyle::NoteHeadShape NoteStyle::LevelOval = "level oval";
|
|
|
|
const NoteStyle::NoteHeadShape NoteStyle::Breve = "breve";
|
|
|
|
const NoteStyle::NoteHeadShape NoteStyle::Cross = "cross";
|
|
|
|
const NoteStyle::NoteHeadShape NoteStyle::TriangleUp = "triangle up";
|
|
|
|
const NoteStyle::NoteHeadShape NoteStyle::TriangleDown = "triangle down";
|
|
|
|
const NoteStyle::NoteHeadShape NoteStyle::Diamond = "diamond";
|
|
|
|
const NoteStyle::NoteHeadShape NoteStyle::Rectangle = "rectangle";
|
|
|
|
const NoteStyle::NoteHeadShape NoteStyle::Number = "number";
|
|
|
|
const NoteStyle::NoteHeadShape NoteStyle::CustomCharName = "custom character";
|
|
|
|
|
|
|
|
NoteStyle::NoteHeadShape
|
|
|
|
NoteStyle::getShape(Note::Type type)
|
|
{
|
|
NoteDescriptionMap::iterator i = m_notes.find(type);
|
|
if (i == m_notes.end()) {
|
|
if (m_baseStyle)
|
|
return m_baseStyle->getShape(type);
|
|
std::cerr
|
|
<< "WARNING: NoteStyle::getShape: No shape defined for note type "
|
|
<< type << ", defaulting to AngledOval" << std::endl;
|
|
return AngledOval;
|
|
}
|
|
|
|
return i->second.shape;
|
|
}
|
|
|
|
bool
|
|
NoteStyle::isFilled(Note::Type type)
|
|
{
|
|
NoteDescriptionMap::iterator i = m_notes.find(type);
|
|
if (i == m_notes.end()) {
|
|
if (m_baseStyle)
|
|
return m_baseStyle->isFilled(type);
|
|
std::cerr
|
|
<< "WARNING: NoteStyle::isFilled: No definition for note type "
|
|
<< type << ", defaulting to true" << std::endl;
|
|
return true;
|
|
}
|
|
|
|
return i->second.filled;
|
|
}
|
|
|
|
bool
|
|
NoteStyle::hasStem(Note::Type type)
|
|
{
|
|
NoteDescriptionMap::iterator i = m_notes.find(type);
|
|
if (i == m_notes.end()) {
|
|
if (m_baseStyle)
|
|
return m_baseStyle->hasStem(type);
|
|
std::cerr
|
|
<< "WARNING: NoteStyle::hasStem: No definition for note type "
|
|
<< type << ", defaulting to true" << std::endl;
|
|
return true;
|
|
}
|
|
|
|
return i->second.stem;
|
|
}
|
|
|
|
int
|
|
NoteStyle::getFlagCount(Note::Type type)
|
|
{
|
|
NoteDescriptionMap::iterator i = m_notes.find(type);
|
|
if (i == m_notes.end()) {
|
|
if (m_baseStyle)
|
|
return m_baseStyle->getFlagCount(type);
|
|
std::cerr
|
|
<< "WARNING: NoteStyle::getFlagCount: No definition for note type "
|
|
<< type << ", defaulting to 0" << std::endl;
|
|
return 0;
|
|
}
|
|
|
|
return i->second.flags;
|
|
}
|
|
|
|
int
|
|
NoteStyle::getSlashCount(Note::Type type)
|
|
{
|
|
NoteDescriptionMap::iterator i = m_notes.find(type);
|
|
if (i == m_notes.end()) {
|
|
if (m_baseStyle)
|
|
return m_baseStyle->getSlashCount(type);
|
|
std::cerr
|
|
<< "WARNING: NoteStyle::getSlashCount: No definition for note type "
|
|
<< type << ", defaulting to 0" << std::endl;
|
|
return 0;
|
|
}
|
|
|
|
return i->second.slashes;
|
|
}
|
|
|
|
void
|
|
NoteStyle::getStemFixPoints(Note::Type type,
|
|
HFixPoint &hfix, VFixPoint &vfix)
|
|
{
|
|
NoteDescriptionMap::iterator i = m_notes.find(type);
|
|
if (i == m_notes.end()) {
|
|
if (m_baseStyle) {
|
|
m_baseStyle->getStemFixPoints(type, hfix, vfix);
|
|
return ;
|
|
}
|
|
std::cerr
|
|
<< "WARNING: NoteStyle::getStemFixPoints: "
|
|
<< "No definition for note type " << type
|
|
<< ", defaulting to (Normal,Middle)" << std::endl;
|
|
hfix = Normal;
|
|
vfix = Middle;
|
|
return ;
|
|
}
|
|
|
|
hfix = i->second.hfix;
|
|
vfix = i->second.vfix;
|
|
}
|
|
|
|
NoteStyle::CharNameRec
|
|
|
|
NoteStyle::getNoteHeadCharName(Note::Type type)
|
|
{
|
|
NoteDescriptionMap::iterator i = m_notes.find(type);
|
|
if (i == m_notes.end()) {
|
|
if (m_baseStyle)
|
|
return m_baseStyle->getNoteHeadCharName(type);
|
|
std::cerr
|
|
<< "WARNING: NoteStyle::getNoteHeadCharName: No definition for note type "
|
|
<< type << ", defaulting to NOTEHEAD_BLACK" << std::endl;
|
|
return CharNameRec(NoteCharacterNames::NOTEHEAD_BLACK, false);
|
|
}
|
|
|
|
const NoteDescription &desc(i->second);
|
|
CharName name = NoteCharacterNames::UNKNOWN;
|
|
bool inverted = false;
|
|
|
|
if (desc.shape == AngledOval) {
|
|
|
|
name = desc.filled ? NoteCharacterNames::NOTEHEAD_BLACK
|
|
: NoteCharacterNames::VOID_NOTEHEAD;
|
|
|
|
} else if (desc.shape == LevelOval) {
|
|
|
|
if (desc.filled) {
|
|
std::cerr << "WARNING: NoteStyle::getNoteHeadCharName: No filled level oval head" << std::endl;
|
|
}
|
|
name = NoteCharacterNames::WHOLE_NOTE;
|
|
|
|
} else if (desc.shape == Breve) {
|
|
|
|
if (desc.filled) {
|
|
std::cerr << "WARNING: NoteStyle::getNoteHeadCharName: No filled breve head" << std::endl;
|
|
}
|
|
name = NoteCharacterNames::BREVE;
|
|
|
|
} else if (desc.shape == Cross) {
|
|
|
|
name = desc.filled ? NoteCharacterNames::X_NOTEHEAD
|
|
: NoteCharacterNames::CIRCLE_X_NOTEHEAD;
|
|
|
|
} else if (desc.shape == TriangleUp) {
|
|
|
|
name = desc.filled ? NoteCharacterNames::TRIANGLE_NOTEHEAD_UP_BLACK
|
|
: NoteCharacterNames::TRIANGLE_NOTEHEAD_UP_WHITE;
|
|
|
|
} else if (desc.shape == TriangleDown) {
|
|
|
|
name = desc.filled ? NoteCharacterNames::TRIANGLE_NOTEHEAD_UP_BLACK
|
|
: NoteCharacterNames::TRIANGLE_NOTEHEAD_UP_WHITE;
|
|
inverted = true;
|
|
|
|
} else if (desc.shape == Diamond) {
|
|
|
|
name = desc.filled ? NoteCharacterNames::SEMIBREVIS_BLACK
|
|
: NoteCharacterNames::SEMIBREVIS_WHITE;
|
|
|
|
} else if (desc.shape == Rectangle) {
|
|
|
|
name = desc.filled ? NoteCharacterNames::SQUARE_NOTEHEAD_BLACK
|
|
: NoteCharacterNames::SQUARE_NOTEHEAD_WHITE;
|
|
|
|
} else if (desc.shape == Number) {
|
|
|
|
std::cerr << "WARNING: NoteStyle::getNoteHeadCharName: Number not yet implemented" << std::endl;
|
|
name = NoteCharacterNames::UNKNOWN; //!!!
|
|
|
|
} else if (desc.shape == CustomCharName) {
|
|
|
|
name = desc.charName;
|
|
|
|
} else {
|
|
|
|
name = NoteCharacterNames::UNKNOWN;
|
|
}
|
|
|
|
return CharNameRec(name, inverted);
|
|
}
|
|
|
|
CharName
|
|
NoteStyle::getAccidentalCharName(const Accidental &a)
|
|
{
|
|
if (a == Accidentals::Sharp)
|
|
return NoteCharacterNames::SHARP;
|
|
else if (a == Accidentals::Flat)
|
|
return NoteCharacterNames::FLAT;
|
|
else if (a == Accidentals::Natural)
|
|
return NoteCharacterNames::NATURAL;
|
|
else if (a == Accidentals::DoubleSharp)
|
|
return NoteCharacterNames::DOUBLE_SHARP;
|
|
else if (a == Accidentals::DoubleFlat)
|
|
return NoteCharacterNames::DOUBLE_FLAT;
|
|
return NoteCharacterNames::UNKNOWN;
|
|
}
|
|
|
|
CharName
|
|
NoteStyle::getMarkCharName(const Mark &mark)
|
|
{
|
|
if (mark == Marks::Accent)
|
|
return NoteCharacterNames::ACCENT;
|
|
else if (mark == Marks::Tenuto)
|
|
return NoteCharacterNames::TENUTO;
|
|
else if (mark == Marks::Staccato)
|
|
return NoteCharacterNames::STACCATO;
|
|
else if (mark == Marks::Staccatissimo)
|
|
return NoteCharacterNames::STACCATISSIMO;
|
|
else if (mark == Marks::Marcato)
|
|
return NoteCharacterNames::MARCATO;
|
|
else if (mark == Marks::Trill)
|
|
return NoteCharacterNames::TRILL;
|
|
else if (mark == Marks::LongTrill)
|
|
return NoteCharacterNames::TRILL;
|
|
else if (mark == Marks::TrillLine)
|
|
return NoteCharacterNames::TRILL_LINE;
|
|
else if (mark == Marks::Turn)
|
|
return NoteCharacterNames::TURN;
|
|
else if (mark == Marks::Pause)
|
|
return NoteCharacterNames::FERMATA;
|
|
else if (mark == Marks::UpBow)
|
|
return NoteCharacterNames::UP_BOW;
|
|
else if (mark == Marks::DownBow)
|
|
return NoteCharacterNames::DOWN_BOW;
|
|
else if (mark == Marks::Mordent)
|
|
return NoteCharacterNames::MORDENT;
|
|
else if (mark == Marks::MordentInverted)
|
|
return NoteCharacterNames::MORDENT_INVERTED;
|
|
else if (mark == Marks::MordentLong)
|
|
return NoteCharacterNames::MORDENT_LONG;
|
|
else if (mark == Marks::MordentLongInverted)
|
|
return NoteCharacterNames::MORDENT_LONG_INVERTED;
|
|
// Things like "sf" and "rf" are generated from text fonts
|
|
return NoteCharacterNames::UNKNOWN;
|
|
}
|
|
|
|
CharName
|
|
NoteStyle::getClefCharName(const Clef &clef)
|
|
{
|
|
std::string clefType(clef.getClefType());
|
|
|
|
if (clefType == Clef::Bass || clefType == Clef::Varbaritone || clefType == Clef::Subbass) {
|
|
return NoteCharacterNames::F_CLEF;
|
|
} else if (clefType == Clef::Treble || clefType == Clef::French) {
|
|
return NoteCharacterNames::G_CLEF;
|
|
} else {
|
|
return NoteCharacterNames::C_CLEF;
|
|
}
|
|
}
|
|
|
|
CharName
|
|
NoteStyle::getRestCharName(Note::Type type, bool restOutsideStave)
|
|
{
|
|
switch (type) {
|
|
case Note::Hemidemisemiquaver:
|
|
return NoteCharacterNames::SIXTY_FOURTH_REST;
|
|
case Note::Demisemiquaver:
|
|
return NoteCharacterNames::THIRTY_SECOND_REST;
|
|
case Note::Semiquaver:
|
|
return NoteCharacterNames::SIXTEENTH_REST;
|
|
case Note::Quaver:
|
|
return NoteCharacterNames::EIGHTH_REST;
|
|
case Note::Crotchet:
|
|
return NoteCharacterNames::QUARTER_REST;
|
|
case Note::Minim:
|
|
return restOutsideStave ?
|
|
NoteCharacterNames::HALF_REST
|
|
: NoteCharacterNames::HALF_REST_ON_STAFF;
|
|
case Note::Semibreve:
|
|
return restOutsideStave ?
|
|
NoteCharacterNames::WHOLE_REST
|
|
: NoteCharacterNames::WHOLE_REST_ON_STAFF;
|
|
case Note::Breve:
|
|
return restOutsideStave ?
|
|
NoteCharacterNames::MULTI_REST
|
|
: NoteCharacterNames::MULTI_REST_ON_STAFF;
|
|
default:
|
|
return NoteCharacterNames::UNKNOWN;
|
|
}
|
|
}
|
|
|
|
CharName
|
|
NoteStyle::getPartialFlagCharName(bool final)
|
|
{
|
|
if (final)
|
|
return NoteCharacterNames::FLAG_PARTIAL_FINAL;
|
|
else
|
|
return NoteCharacterNames::FLAG_PARTIAL;
|
|
}
|
|
|
|
CharName
|
|
NoteStyle::getFlagCharName(int flagCount)
|
|
{
|
|
switch (flagCount) {
|
|
case 1:
|
|
return NoteCharacterNames::FLAG_1;
|
|
case 2:
|
|
return NoteCharacterNames::FLAG_2;
|
|
case 3:
|
|
return NoteCharacterNames::FLAG_3;
|
|
case 4:
|
|
return NoteCharacterNames::FLAG_4;
|
|
default:
|
|
return NoteCharacterNames::UNKNOWN;
|
|
}
|
|
}
|
|
|
|
CharName
|
|
NoteStyle::getTimeSignatureDigitName(int digit)
|
|
{
|
|
switch (digit) {
|
|
case 0:
|
|
return NoteCharacterNames::DIGIT_ZERO;
|
|
case 1:
|
|
return NoteCharacterNames::DIGIT_ONE;
|
|
case 2:
|
|
return NoteCharacterNames::DIGIT_TWO;
|
|
case 3:
|
|
return NoteCharacterNames::DIGIT_THREE;
|
|
case 4:
|
|
return NoteCharacterNames::DIGIT_FOUR;
|
|
case 5:
|
|
return NoteCharacterNames::DIGIT_FIVE;
|
|
case 6:
|
|
return NoteCharacterNames::DIGIT_SIX;
|
|
case 7:
|
|
return NoteCharacterNames::DIGIT_SEVEN;
|
|
case 8:
|
|
return NoteCharacterNames::DIGIT_EIGHT;
|
|
case 9:
|
|
return NoteCharacterNames::DIGIT_NINE;
|
|
default:
|
|
return NoteCharacterNames::UNKNOWN;
|
|
}
|
|
}
|
|
|
|
void
|
|
NoteStyle::setBaseStyle(NoteStyleName name)
|
|
{
|
|
try {
|
|
m_baseStyle = NoteStyleFactory::getStyle(name);
|
|
if (m_baseStyle == this)
|
|
m_baseStyle = 0;
|
|
} catch (NoteStyleFactory::StyleUnavailable u) {
|
|
if (name != NoteStyleFactory::DefaultStyle) {
|
|
std::cerr
|
|
<< "NoteStyle::setBaseStyle: Base style "
|
|
<< name << " not available, defaulting to "
|
|
<< NoteStyleFactory::DefaultStyle << std::endl;
|
|
setBaseStyle(NoteStyleFactory::DefaultStyle);
|
|
} else {
|
|
std::cerr
|
|
<< "NoteStyle::setBaseStyle: Base style "
|
|
<< name << " not available" << std::endl;
|
|
m_baseStyle = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
NoteStyle::checkDescription(Note::Type note)
|
|
{
|
|
if (m_baseStyle && (m_notes.find(note) == m_notes.end())) {
|
|
m_baseStyle->checkDescription(note);
|
|
m_notes[note] = m_baseStyle->m_notes[note];
|
|
}
|
|
}
|
|
|
|
void
|
|
NoteStyle::setShape(Note::Type note, NoteHeadShape shape)
|
|
{
|
|
checkDescription(note);
|
|
m_notes[note].shape = shape;
|
|
}
|
|
|
|
void
|
|
NoteStyle::setCharName(Note::Type note, CharName charName)
|
|
{
|
|
checkDescription(note);
|
|
m_notes[note].charName = charName;
|
|
}
|
|
|
|
void
|
|
NoteStyle::setFilled(Note::Type note, bool filled)
|
|
{
|
|
checkDescription(note);
|
|
m_notes[note].filled = filled;
|
|
}
|
|
|
|
void
|
|
NoteStyle::setStem(Note::Type note, bool stem)
|
|
{
|
|
checkDescription(note);
|
|
m_notes[note].stem = stem;
|
|
}
|
|
|
|
void
|
|
NoteStyle::setFlagCount(Note::Type note, int flags)
|
|
{
|
|
checkDescription(note);
|
|
m_notes[note].flags = flags;
|
|
}
|
|
|
|
void
|
|
NoteStyle::setSlashCount(Note::Type note, int slashes)
|
|
{
|
|
checkDescription(note);
|
|
m_notes[note].slashes = slashes;
|
|
}
|
|
|
|
void
|
|
NoteStyle::setStemFixPoints(Note::Type note, HFixPoint hfix, VFixPoint vfix)
|
|
{
|
|
checkDescription(note);
|
|
m_notes[note].hfix = hfix;
|
|
m_notes[note].vfix = vfix;
|
|
}
|
|
|
|
}
|