/* Rosegarden A MIDI and audio sequencer and musical notation editor. This program is Copyright 2000-2008 Guillaume Laurent , Chris Cannam , Richard Bown 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 ( TQPainter* p, unsigned int position ) const { TQRect 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( columnWidth * 0.7 ); unsigned int height = static_cast( 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 ( TQPainter* p, unsigned int position ) const { TQRect 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( columnWidth * 0.7 ); //std::cout << "NoteSymbols::drawOpenSymbol - drawing Open symbol at string #" << position //<< std::endl; p->setBrush( TQBrush(p->brush().color(), TQt::NoBrush) ); p->drawEllipse( x_pos.first - ( radius / 2 ), y_pos - ( radius / 2 ), radius, radius ); } void NoteSymbols::drawNoteSymbol ( TQPainter* p, unsigned int stringNb, int fretNb, bool transient ) const { // NOTATION_DEBUG << "NoteSymbols::drawNoteSymbol - string: " << stringNb << ", fret:" << fretNb << endl; TQRect 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( columnWidth /* * 0.9 */ ); p->setBrush( TQBrush(p->brush().color(), TQt::NoBrush) ); } else { radius = static_cast( columnWidth * 0.7 ); p->setBrush( TQBrush(p->brush().color(), TQt::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 = " << TQRect(x,y, radius, radius) << endl; p->drawEllipse( x, y, radius, radius ); // p->save(); // p->setPen(TQt::red); // p->drawRect( x, y, radius, radius ); // p->restore(); } void NoteSymbols::drawBarreSymbol ( TQPainter* 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 ) { TQRect 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( 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 ( TQPainter* p, unsigned int fret_num ) const { if ( fret_num > 1 ) { TQRect v = p->viewport(); unsigned int imgWidth = v.width(); unsigned int imgHeight = v.height(); p->save(); TQFont font; font.setPixelSize(getFontPixelSize(v.width(), v.height())); p->setFont(font); TQString 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 ( TQPainter* p ) const { /* std::cout << "NoteSymbols::drawFretHorizontalLines" << std::endl << " scale: " << scale << std::endl << " frets: " << fretsDisplayed << std::endl << " max string: " << maxStringNum << std::endl; */ TQRect 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; TQPen 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 : " << TQPoint(getLeftBorder(imgWidth), y_pos) // << " to " << TQPoint(endXPos.first, y_pos) << endl; y_pos += rowHeight; } p->restore(); } void NoteSymbols::drawStrings ( TQPainter* p ) const { // Vertical lines TQRect 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; TQPen 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(); } TQRect NoteSymbols::getTransientNoteSymbolRect(TQSize 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( 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 TQRect(x, y, radius, radius); } unsigned int NoteSymbols::getTopBorder ( unsigned int imgHeight ) const { return static_cast( TOP_BORDER_PERCENTAGE * imgHeight ); } unsigned int NoteSymbols::getBottomBorder ( unsigned int imgHeight ) const { return static_cast( imgHeight * BOTTOM_BORDER_PERCENTAGE ); } unsigned int NoteSymbols::getLeftBorder ( unsigned int imgWidth ) const { unsigned int left = static_cast( imgWidth * LEFT_BORDER_PERCENTAGE ); if ( left < 15 ) { left = 15; } return left; } unsigned int NoteSymbols::getRightBorder ( unsigned int imgWidth ) const { return static_cast( imgWidth * RIGHT_BORDER_PERCENTAGE ); } unsigned int NoteSymbols::getGuitarChordWidth ( int imgWidth ) const { return static_cast( imgWidth * GUITAR_CHORD_WIDTH_PERCENTAGE ); } unsigned int NoteSymbols::getGuitarChordHeight ( int imgHeight ) const { return static_cast( imgHeight * GUITAR_CHORD_HEIGHT_PERCENTAGE ); } unsigned int NoteSymbols::getFontPixelSize ( int imgWidth, int imgHeight ) const { return std::max(8, imgHeight / 10); } std::pair 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 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 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, TQPainter *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 */ }