diff options
Diffstat (limited to 'src/gui/editors/guitar/NoteSymbols.cpp')
-rw-r--r-- | src/gui/editors/guitar/NoteSymbols.cpp | 486 |
1 files changed, 486 insertions, 0 deletions
diff --git a/src/gui/editors/guitar/NoteSymbols.cpp b/src/gui/editors/guitar/NoteSymbols.cpp new file mode 100644 index 0000000..14379de --- /dev/null +++ b/src/gui/editors/guitar/NoteSymbols.cpp @@ -0,0 +1,486 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Rosegarden + A MIDI and audio sequencer and musical notation editor. + + This program is Copyright 2000-2008 + Guillaume Laurent <[email protected]>, + Chris Cannam <[email protected]>, + Richard Bown <[email protected]> + + The moral rights of Guillaume Laurent, Chris Cannam, and Richard + Bown to claim authorship of this work have been asserted. + + This file contains code from + 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 "NoteSymbols.h" +#include "Fingering.h" +#include "misc/Debug.h" + +namespace Rosegarden +{ + +namespace Guitar +{ +NoteSymbols::posPair +NoteSymbols::getX ( int imgWidth, unsigned int stringNb, unsigned int nbOfStrings ) const +{ + /* + std::cout << "NoteSymbols::getX - input values" << std::endl + << " position: " << position << std::endl + << " string #: " << string_num << std::endl + << " scale: " << scale << std::endl; + */ + unsigned int lBorder = getLeftBorder( imgWidth ); + unsigned int guitarChordWidth = getGuitarChordWidth( imgWidth ); + unsigned int columnWidth = guitarChordWidth / nbOfStrings; + return std::make_pair( ( stringNb * columnWidth + lBorder ), columnWidth ); +} + +NoteSymbols::posPair +NoteSymbols::getY ( int imgHeight, unsigned int fretNb, unsigned int nbOfFrets ) const +{ + /* + std::cout << "NoteSymbols::getY - input values" << std::endl + << " position: " << fret_pos << std::endl + << " max frets: " << maxFretNum << std::endl + << " scale: " << scale << std::endl; + */ + unsigned int tBorder = getTopBorder( imgHeight ); + unsigned int guitarChordHeight = getGuitarChordHeight( imgHeight ); + unsigned int rowHeight = guitarChordHeight / nbOfFrets; + return std::make_pair( ( ( fretNb * rowHeight ) + tBorder ), rowHeight ); +} + +void +NoteSymbols::drawMuteSymbol ( QPainter* p, + unsigned int position ) const +{ + QRect v = p->viewport(); + + posPair x_pos = getX ( v.width(), position, m_nbOfStrings ); + unsigned int y_pos = getTopBorder( v.height() ) / 2; + double columnWidth = x_pos.second; + unsigned int width = static_cast<unsigned int>( columnWidth * 0.7 ); + unsigned int height = static_cast<unsigned int>( columnWidth * 0.7 ); + + //std::cout << "NoteSymbols::drawMuteSymbol - drawing Mute symbol at string #" << position + //<< std::endl; + + p->drawLine ( x_pos.first - ( width / 2 ), + y_pos - ( height / 2 ), + ( x_pos.first + ( width / 2 ) ), + y_pos + ( height / 2 ) ); + + p->drawLine( x_pos.first + ( width / 2 ), + y_pos - ( height / 2 ), + ( x_pos.first - ( width / 2 ) ), + y_pos + ( height / 2 ) ); +} + +void +NoteSymbols::drawOpenSymbol ( QPainter* p, + unsigned int position ) const +{ + QRect v = p->viewport(); + posPair x_pos = getX ( v.width(), position, m_nbOfStrings ); + unsigned int y_pos = getTopBorder( v.height() ) / 2; + double columnWidth = x_pos.second; + unsigned int radius = static_cast<unsigned int>( columnWidth * 0.7 ); + + //std::cout << "NoteSymbols::drawOpenSymbol - drawing Open symbol at string #" << position + //<< std::endl; + + p->setBrush( QBrush(p->brush().color(), Qt::NoBrush) ); + p->drawEllipse( x_pos.first - ( radius / 2 ), + y_pos - ( radius / 2 ), + radius, + radius ); +} + +void +NoteSymbols::drawNoteSymbol ( QPainter* p, + unsigned int stringNb, + int fretNb, + bool transient ) const +{ +// NOTATION_DEBUG << "NoteSymbols::drawNoteSymbol - string: " << stringNb << ", fret:" << fretNb << endl; + + QRect v = p->viewport(); + posPair x_pos = getX ( v.width(), stringNb, m_nbOfStrings ); + posPair y_pos = getY ( v.height(), fretNb, m_nbOfFrets ); + double columnWidth = x_pos.second; + unsigned int radius; + + if (transient) { + radius = static_cast<unsigned int>( columnWidth /* * 0.9 */ ); + p->setBrush( QBrush(p->brush().color(), Qt::NoBrush) ); + } else { + radius = static_cast<unsigned int>( columnWidth * 0.7 ); + p->setBrush( QBrush(p->brush().color(), Qt::SolidPattern) ); + } + + int x = x_pos.first - ( radius / 2 ), + y = y_pos.first + ( (y_pos.second - radius) / 2) - y_pos.second + TOP_GUITAR_CHORD_MARGIN; + +// y = y_pos.first - (radius / 2) - y_pos.second + TOP_GUITAR_CHORD_MARGIN; + +// RG_DEBUG << "NoteSymbols::drawNoteSymbol : rect = " << QRect(x,y, radius, radius) << endl; + + p->drawEllipse( x, + y, + radius, + radius ); + +// p->save(); +// p->setPen(Qt::red); +// p->drawRect( x, y, radius, radius ); +// p->restore(); +} + +void +NoteSymbols::drawBarreSymbol ( QPainter* p, + int fretNb, + unsigned int start, + unsigned int end ) const +{ + + //std::cout << "NoteSymbols::drawBarreSymbol - start: " << start << ", end:" << end << std::endl; + + drawNoteSymbol ( p, start, fretNb ); + + if ( ( end - start ) >= 1 ) { + QRect v = p->viewport(); + posPair startXPos = getX ( v.width(), start, m_nbOfStrings ); + posPair endXPos = getX ( v.width(), end, m_nbOfStrings ); + posPair y_pos = getY ( v.height(), fretNb, m_nbOfFrets ); + double columnWidth = startXPos.second; + unsigned int thickness = static_cast<unsigned int>( columnWidth * 0.7 ); + + p->drawRect( startXPos.first, + y_pos.first + ( y_pos.second / 4 ) + TOP_GUITAR_CHORD_MARGIN, + endXPos.first - startXPos.first, + thickness ); + } + + drawNoteSymbol ( p, end, fretNb ); +} + +void +NoteSymbols::drawFretNumber ( QPainter* p, + unsigned int fret_num ) const +{ + if ( fret_num > 1 ) { + QRect v = p->viewport(); + unsigned int imgWidth = v.width(); + unsigned int imgHeight = v.height(); + + p->save(); + QFont font; + font.setPixelSize(getFontPixelSize(v.width(), v.height())); + p->setFont(font); + + QString tmp; + tmp.setNum( fret_num ); + + // Use NoteSymbols to grab X and Y for first fret + posPair y_pos = getY( imgHeight, 0, m_nbOfFrets ); + + p->drawText( getLeftBorder( imgWidth ) / 4, + y_pos.first + ( y_pos.second / 2 ), + tmp ); + + p->restore(); + } +} + +void +NoteSymbols::drawFrets ( QPainter* p ) const +{ + /* + std::cout << "NoteSymbols::drawFretHorizontalLines" << std::endl + << " scale: " << scale << std::endl + << " frets: " << fretsDisplayed << std::endl + << " max string: " << maxStringNum << std::endl; + */ + + QRect v = p->viewport(); + unsigned int imgWidth = v.width(); + unsigned int imgHeight = v.height(); + //unsigned int endXPos = getGuitarChordWidth(imgWidth) + getLeftBorder(imgWidth); + posPair endXPos = getX ( imgWidth, m_nbOfStrings - 1, m_nbOfStrings ); + + unsigned int yGuitarChord = getGuitarChordHeight( imgHeight ); + unsigned int rowHeight = yGuitarChord / m_nbOfFrets; + + QPen pen(p->pen()); + pen.setWidth(imgHeight >= 100 ? FRET_PEN_WIDTH : FRET_PEN_WIDTH / 2); + p->save(); + p->setPen(pen); + unsigned int y_pos = (getY ( imgHeight, 0, m_nbOfFrets )).first + TOP_GUITAR_CHORD_MARGIN; + +// NOTATION_DEBUG << "NoteSymbols::drawFrets : " << m_nbOfFrets << endl; + + // Horizontal lines + for ( unsigned int i = 0; i <= m_nbOfFrets; ++i ) { + + /* This code borrowed from KGuitar 0.5 */ + p->drawLine( getLeftBorder( imgWidth ), + y_pos, + endXPos.first, + y_pos); +// NOTATION_DEBUG << "NoteSymbols::drawFrets : " << QPoint(getLeftBorder(imgWidth), y_pos) +// << " to " << QPoint(endXPos.first, y_pos) << endl; + + + y_pos += rowHeight; + } + + p->restore(); + +} + +void +NoteSymbols::drawStrings ( QPainter* p ) const +{ + // Vertical lines + QRect v = p->viewport(); + int imgHeight = v.height(); + int imgWidth = v.width(); + + unsigned int startPos = getTopBorder( imgHeight ) + TOP_GUITAR_CHORD_MARGIN; + unsigned int endPos = (getY ( imgHeight, m_nbOfFrets, m_nbOfFrets )).first + TOP_GUITAR_CHORD_MARGIN; + + unsigned int guitarChordWidth = getGuitarChordWidth( imgWidth ); + unsigned int columnWidth = guitarChordWidth / m_nbOfStrings; + + unsigned int x_pos = (getX ( imgWidth, 0, m_nbOfStrings )).first; + + QPen pen(p->pen()); + pen.setWidth(imgWidth >= 100 ? STRING_PEN_WIDTH : STRING_PEN_WIDTH / 2); + p->save(); + p->setPen(pen); + + for ( unsigned int i = 0; i < m_nbOfStrings; ++i ) { + + /* This code borrowed from KGuitar 0.5 */ + p->drawLine( x_pos, + startPos, + x_pos, + endPos ); + + x_pos += columnWidth; + } + + p->restore(); + +} + +QRect NoteSymbols::getTransientNoteSymbolRect(QSize guitarChordSize, + unsigned int stringNb, + int fretNb) const +{ + posPair x_pos = getX ( guitarChordSize.width(), stringNb, m_nbOfStrings ); + posPair y_pos = getY ( guitarChordSize.height(), fretNb, m_nbOfFrets ); + double columnWidth = x_pos.second; + unsigned int radius = static_cast<unsigned int>( columnWidth /* * 0.9 */ ); + + int x = x_pos.first - ( radius / 2 ), + y = y_pos.first + ( (y_pos.second - radius) / 2) - y_pos.second + TOP_GUITAR_CHORD_MARGIN; + + return QRect(x, y, radius, radius); +} + +unsigned int +NoteSymbols::getTopBorder ( unsigned int imgHeight ) const +{ + return static_cast<unsigned int>( TOP_BORDER_PERCENTAGE * imgHeight ); +} + +unsigned int +NoteSymbols::getBottomBorder ( unsigned int imgHeight ) const +{ + return static_cast<unsigned int>( imgHeight * BOTTOM_BORDER_PERCENTAGE ); +} + +unsigned int +NoteSymbols::getLeftBorder ( unsigned int imgWidth ) const +{ + unsigned int left = static_cast<unsigned int>( imgWidth * LEFT_BORDER_PERCENTAGE ); + if ( left < 15 ) { + left = 15; + } + return left; +} + +unsigned int +NoteSymbols::getRightBorder ( unsigned int imgWidth ) const +{ + return static_cast<unsigned int>( imgWidth * RIGHT_BORDER_PERCENTAGE ); +} + +unsigned int +NoteSymbols::getGuitarChordWidth ( int imgWidth ) const +{ + return static_cast<unsigned int>( imgWidth * GUITAR_CHORD_WIDTH_PERCENTAGE ); +} + +unsigned int +NoteSymbols::getGuitarChordHeight ( int imgHeight ) const +{ + return static_cast<unsigned int>( imgHeight * GUITAR_CHORD_HEIGHT_PERCENTAGE ); +} + +unsigned int +NoteSymbols::getFontPixelSize ( int imgWidth, int imgHeight ) const +{ + return std::max(8, imgHeight / 10); +} + +std::pair<bool, unsigned int> +NoteSymbols::getStringNumber ( int imgWidth, + unsigned int x_pos, + unsigned int maxStringNum ) const +{ + /* + std::cout << "NoteSymbols::getNumberOfStrings - input values" << std::endl + << " X position: " << x_pos << std::endl + << " string #: " << maxStringNum << std::endl + << " image width: " << imgWidth << std::endl; + */ + bool valueOk = false; + + posPair xPairPos; + unsigned int min = 0; + unsigned int max = 0; + unsigned int result = 0; + + for ( unsigned int i = 0; i < maxStringNum; ++i ) { + xPairPos = getX ( imgWidth, i, maxStringNum ); + + // If the counter equals zero then we are at the first + // string to the left + if ( i == 0 ) { + // Add 10 pixel buffer to range comparison + min = xPairPos.first - 10; + } else { + min = xPairPos.first - xPairPos.second / 2; + } + + // If the counter equals the maxString number -1 then we are at the last + // string to the right + if ( i == ( maxStringNum - 1 ) ) { + // Add 10 pixel buffer to range comparison + max = xPairPos.first + 10; + } else { + max = xPairPos.first + xPairPos.second / 2; + } + + if ( ( x_pos >= min ) && ( x_pos <= max ) ) { + result = i; + valueOk = true; + break; + } + } + + //std::cout << "NoteSymbols::getNumberOfStrings - string: #" << result << std::endl; + return std::make_pair( valueOk, result ); +} + +std::pair<bool, unsigned int> +NoteSymbols::getFretNumber ( int imgHeight, + unsigned int y_pos, + unsigned int maxFretNum ) const +{ + /* + std::cout << "NoteSymbols::getNumberOfFrets - input values" << std::endl + << " Y position: " << y_pos << std::endl + << " max frets: " << maxFretNum << std::endl + << " image height: " << imgHeight << std::endl; + */ + + bool valueOk = false; + unsigned int tBorder = getTopBorder( imgHeight ); + unsigned int result = 0; + + if ( y_pos < tBorder ) { + // User pressing above the guitar chord to mark line muted or opened + valueOk = true; + } else { + typedef std::pair<unsigned int, unsigned int> RangePair; + + posPair min_pos; + posPair max_pos; + + for ( unsigned int i = 0; i < maxFretNum; ++i ) { + min_pos = getY ( imgHeight, i, maxFretNum ); + max_pos = getY ( imgHeight, i + 1, maxFretNum ); + + if ( ( y_pos >= min_pos.first ) && y_pos <= max_pos.first - 1 ) { + result = i + 1; + valueOk = true; + break; + } + } + } + // std::cout << " fret #: " << result << std::endl; + return std::make_pair( valueOk, result ); +} + +void +NoteSymbols::drawFingeringPixmap(const Guitar::Fingering& fingering, const Guitar::NoteSymbols& noteSymbols, QPainter *p) +{ + unsigned int startFret = fingering.getStartFret(); + + noteSymbols.drawFretNumber(p, startFret); + noteSymbols.drawFrets(p); + noteSymbols.drawStrings(p); + + unsigned int stringNb = 0; + + for (Fingering::const_iterator pos = fingering.begin(); + pos != fingering.end(); + ++pos, ++stringNb) { + + switch (*pos) { + case Fingering::OPEN: + noteSymbols.drawOpenSymbol(p, stringNb); + break; + + case Fingering::MUTED: + noteSymbols.drawMuteSymbol(p, stringNb); + break; + + default: + noteSymbols.drawNoteSymbol(p, stringNb, *pos - (startFret - 1), false); + break; + } + } + +} + + +float const NoteSymbols::LEFT_BORDER_PERCENTAGE = 0.2; +float const NoteSymbols::RIGHT_BORDER_PERCENTAGE = 0.1; +float const NoteSymbols::GUITAR_CHORD_WIDTH_PERCENTAGE = 0.8; +float const NoteSymbols::TOP_BORDER_PERCENTAGE = 0.1; +float const NoteSymbols::BOTTOM_BORDER_PERCENTAGE = 0.1; +float const NoteSymbols::GUITAR_CHORD_HEIGHT_PERCENTAGE = 0.8; +int const NoteSymbols::TOP_GUITAR_CHORD_MARGIN = 5; +int const NoteSymbols::FRET_PEN_WIDTH = 2; +int const NoteSymbols::STRING_PEN_WIDTH = 2; + +} /* namespace Guitar */ + +} + |