pianobooster/src/Draw.cpp

936 lines
37 KiB
C++

/*********************************************************************************/
/*!
@file Draw.cpp
@author L. J. Barman
Copyright (c) 2008-2020, L. J. Barman and others, all rights reserved
This file is part of the PianoBooster application
PianoBooster 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 3 of the License, or
(at your option) any later version.
PianoBooster is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with PianoBooster. If not, see <http://www.gnu.org/licenses/>.
*/
/*********************************************************************************/
#include "Draw.h"
#include "Cfg.h"
#include "Settings.h"
#include "Notation.h"
#include <QGuiApplication>
#include <cstdlib>
#include <array>
typedef unsigned int guint;
typedef unsigned char guint8;
whichPart_t CDraw::m_displayHand;
int CDraw::m_forceCompileRedraw;
CDraw::CDraw(CSettings* settings)
#ifndef NO_USE_FTGL
:font(nullptr)
#endif
{
#ifndef NO_USE_FTGL
static const auto fontPaths = std::array<QString, 7>{
Util::dataDir(QStringLiteral("fonts")) + QStringLiteral("/DejaVuSans.ttf"),
QStringLiteral("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf"),
QStringLiteral("/usr/share/fonts/dejavu/DejaVuSans.ttf"),
QStringLiteral("/usr/share/fonts/TTF/dejavu/DejaVuSans.ttf"),
QStringLiteral("/usr/share/fonts/TTF/DejaVuSans.ttf"),
QStringLiteral("/usr/share/fonts/truetype/DejaVuSans.ttf"),
QStringLiteral("/usr/local/share/fonts/dejavu/DejaVuSans.ttf"),
};
for (const auto &path : fontPaths) {
if (QFile::exists(path)) {
font = new FTBitmapFont(path.toUtf8().data());
break;
}
}
if (!font) {
ppLogError("Font DejaVuSans.ttf was not found!");
exit(EXIT_FAILURE);
}
static const auto size = static_cast<unsigned int>(FONT_SIZE * qGuiApp->devicePixelRatio());
font->FaceSize(size, size);
#endif
m_settings = settings;
m_displayHand = PB_PART_both;
m_forceCompileRedraw = 1;
m_scrollProperties = &m_scrollPropertiesHorizontal;
}
void CDraw::oneLine(float x1, float y1, float x2, float y2)
{
glBegin(GL_LINES);
glVertex2f ((x1),(y1));
glVertex2f ((x2),(y2));
glEnd();
//ppLogTrace("oneLine %f %f %f %f", x1, y1, x2, y2);
}
void CDraw::drawStaveExtentsion(CSymbol symbol, float x, int noteWidth, bool playable)
{
int index;
index = symbol.getStavePos().getStaveIndex();
if (index < 6 && index > -6)
return;
index = index & ~1; // Force index to be even
whichPart_t hand = symbol.getStavePos().getHand();
if (playable)
drColor(Cfg::colorTheme().staveColor);
else
drColor(Cfg::colorTheme().staveColorDim);
glLineWidth (Cfg::staveThickness());
glBegin(GL_LINES);
while (index >= 6 || index <= -6)
{
glVertex2f (x - static_cast<float>(noteWidth)/2.0f - 4.0f, CStavePos(hand, index).getPosYRelative());
glVertex2f (x + static_cast<float>(noteWidth)/2.0f + 4.0f, CStavePos(hand, index).getPosYRelative());
// Move the index closer to the stave centre
if (index > 0)
index -= 2;
else
index += 2;
}
glEnd();
}
#define scaleGlVertex(xa, xb, ya, yb) glVertex2f( ((xa) * 1.2f) + (xb), ((ya) * 1.2f) + (yb))
#ifndef NO_USE_FTGL
void CDraw::renderText(float x, float y, const char* s)
{
const auto w = font->Advance(s);
const auto h = font->Descender();
glRasterPos2f(x - w/2, y - h);
font->Render(s);
}
#endif
void CDraw::drawNoteName(int midiNote, float x, float y, int type)
{
Q_UNUSED(type)
// Ignore note that are too high
if (midiNote > MIDI_TOP_C + 6)
return;
staveLookup_t item = CStavePos::midiNote2Name(midiNote);
drColor(Cfg::colorTheme().noteNameColor);
glLineWidth (1.0);
#ifdef NO_USE_FTGL
if (item.accidental != 0)
{
const float accidentalOffset = 10;
x += accidentalOffset/2;
if (item.accidental == 1)
{
glBegin(GL_LINES);
// letterSharp4
scaleGlVertex( -1.317895f, x, 5.794585f, y); // 1
scaleGlVertex( -1.265845f, x, -6.492455f, y); // 2
scaleGlVertex( 1.252305f, x, 6.492455f, y); // 3
scaleGlVertex( 1.322655f, x, -5.422335f, y); // 4
scaleGlVertex( -2.645765f, x, 1.967805f, y); // 5
scaleGlVertex( 2.648325f, x, 3.625485f, y); // 6
scaleGlVertex( -2.648325f, x, -3.306965f, y); // 7
scaleGlVertex( 2.596205f, x, -1.675765f, y); // 8
glEnd();
}
else
{
glBegin(GL_LINE_STRIP);
// letterFlat
scaleGlVertex( -2.52933f, x, 6.25291f, y); // 1
scaleGlVertex( -2.50344f, x, -6.25291f, y); // 2
scaleGlVertex( 0.76991f, x, -3.63422f, y); // 3
scaleGlVertex( 2.07925f, x, -1.67021f, y); // 4
scaleGlVertex( 2.52933f, x, 0.25288f, y); // 5
scaleGlVertex( 1.42458f, x, 1.07122f, y); // 6
scaleGlVertex( -0.53943f, x, 0.90755f, y); // 7
scaleGlVertex( -2.46252f, x, -1.01554f, y); // 8
scaleGlVertex( -2.50344f, x, -1.67021f, y); // 9
glEnd();
}
x -= accidentalOffset;
}
switch(item.pianoNote)
{
case 1:
glBegin(GL_LINE_STRIP);
// letterC
scaleGlVertex( 3.513445f, x, 2.17485f, y); // 1
scaleGlVertex( 1.880175f, x, 4.47041f, y); // 2
scaleGlVertex( -1.598825f, x, 4.4321f, y); // 3
scaleGlVertex( -3.692215f, x, 2.26571f, y); // 4
scaleGlVertex( -3.702055f, x, -1.88958f, y); // 5
scaleGlVertex( -1.630675f, x, -4.47041f, y); // 6
scaleGlVertex( 1.932545f, x, -4.44064f, y); // 7
scaleGlVertex( 3.702055f, x, -1.88554f, y); // 8
glEnd();
break;
case 2:
glBegin(GL_LINE_STRIP);
// letterD
scaleGlVertex( -3.30696f, x, 4.31878f, y); // 1
scaleGlVertex( -3.3428f, x, -4.31878f, y); // 2
scaleGlVertex( 0.9425f, x, -4.28164f, y); // 3
scaleGlVertex( 3.31415f, x, -1.42302f, y); // 4
scaleGlVertex( 3.3428f, x, 1.66626f, y); // 5
scaleGlVertex( 0.70825f, x, 4.31317f, y); // 6
scaleGlVertex( -3.22083f, x, 4.29495f, y); // 7
glEnd();
break;
case 3: // E
glBegin(GL_LINE_STRIP);
// letterE2
scaleGlVertex( 2.966065f, x, 4.416055f, y); // 1
scaleGlVertex( -3.007275f, x, 4.403495f, y); // 2
scaleGlVertex( -3.037615f, x, -4.416055f, y); // 3
scaleGlVertex( 3.037615f, x, -4.415435f, y); // 4
glEnd();
glBegin(GL_LINES);
scaleGlVertex( 3.011705f, x, 0.197675f, y); // 5
scaleGlVertex( -2.990845f, x, 0.196615f, y); // 6
glEnd();
break;
case 4: // F
glBegin(GL_LINE_STRIP);
// letterF2
scaleGlVertex( -2.55172f, x, -4.434285f, y); // 1
scaleGlVertex( -2.51956f, x, 4.433665f, y); // 2
scaleGlVertex( 2.39942f, x, 4.434285f, y); // 3
glEnd();
glBegin(GL_LINES);
scaleGlVertex( 2.58143f, x, 0.244465f, y); // 4
scaleGlVertex( -2.58143f, x, 0.243405f, y); // 5
glEnd();
break;
case 5:
glBegin(GL_LINE_STRIP);
// letterG
scaleGlVertex( 0.58123f, x, -0.34005f, y); // 1
scaleGlVertex( 3.66047f, x, -0.48722f, y); // 2
scaleGlVertex( 3.70461f, x, -3.23595f, y); // 3
scaleGlVertex( 1.96234f, x, -4.41694f, y); // 4
scaleGlVertex( -0.96712f, x, -4.57846f, y); // 5
scaleGlVertex( -3.70461f, x, -2.29011f, y); // 6
scaleGlVertex( -3.67245f, x, 2.14034f, y); // 7
scaleGlVertex( -1.25347f, x, 4.57846f, y); // 8
scaleGlVertex( 1.90018f, x, 4.55293f, y); // 9
scaleGlVertex( 3.54236f, x, 2.38612f, y); // 10
glEnd();
break;
case 6: // A
glBegin(GL_LINE_STRIP);
// letterA2
scaleGlVertex( -3.91146f, x, -4.907395f, y); // 1
scaleGlVertex( 0.06571f, x, 4.907395f, y); // 2
scaleGlVertex( 3.91146f, x, -4.803315f, y); // 3
glEnd();
glBegin(GL_LINES);
scaleGlVertex( 2.60111f, x, -1.400435f, y); // 4
scaleGlVertex( -2.56175f, x, -1.357305f, y); // 5
glEnd();
break;
case 7:
glBegin(GL_LINE_STRIP);
// letterB
scaleGlVertex( 1.038555f, x, 0.105285f, y); // 1
scaleGlVertex( -3.001935f, x, 0.121925f, y); // 2
scaleGlVertex( -3.027615f, x, 4.417905f, y); // 3
scaleGlVertex( 1.325925f, x, 4.451255f, y); // 4
scaleGlVertex( 2.737985f, x, 3.048615f, y); // 5
scaleGlVertex( 2.721765f, x, 1.366235f, y); // 6
scaleGlVertex( 1.022635f, x, 0.120235f, y); // 7
scaleGlVertex( 3.026015f, x, -1.282295f, y); // 8
scaleGlVertex( 3.027615f, x, -3.046285f, y); // 9
scaleGlVertex( 1.176815f, x, -4.451255f, y); // 10
scaleGlVertex( -2.981475f, x, -4.445735f, y); // 11
scaleGlVertex( -3.021355f, x, 0.176035f, y); // 12
glEnd();
break;
default:
glBegin(GL_LINES);
glVertex2f( 3.0f + x, -15.0f + y); // 1
glVertex2f( 3.0f + x, 8.0f + y); // 2
glVertex2f( -3.0f + x, -8.0f + y); // 3
glVertex2f( -3.0f + x, 15.0f + y); // 4
glVertex2f( 3.0f + x, 8.0f + y); // 5
glVertex2f( -3.0f + x, 2.0f + y); // 6
glVertex2f( 3.0f + x, -2.0f + y); // 7
glVertex2f( -3.0f + x, -8.0f + y); // 8
glEnd();
break;
}
#else
static const auto flat = QChar(u''), natural = QChar(u''), sharp = QChar(u'');
const auto n = std::array<QString, 7>{ tr("C"), tr("D"), tr("E"), tr("F"), tr("G"), tr("A"), tr("B") };
if (item.pianoNote > 0 && item.pianoNote < 8) {
auto note = n[static_cast<std::size_t>(item.pianoNote - 1)];
switch (item.accidental) {
case -1:
note += flat;
break;
case 1:
note += sharp;
break;
case 2:
note += natural;
break;
}
renderText(x, y, note.toUtf8().data());
}
#endif
}
void CDraw::drawStaveNoteName(CSymbol symbol, float x, float y)
{
if ( symbol.getNoteIndex() + 1 != symbol.getNoteTotal())
return;
if (m_settings->showNoteNames() == false)
return;
y += CStavePos::getVerticalNoteSpacing()*2 +3;
drawNoteName(symbol.getNote(), x, y, true);
}
void CDraw::checkAccidental(CSymbol symbol, float x, float y)
{
int accidental;
const int xGap = 16;
accidental = symbol.getStavePos().getAccidental();
if (symbol.getAccidentalModifer() == PB_ACCIDENTAL_MODIFER_suppress)
accidental = 0; // Suppress the accidental if it is the same bar
if (symbol.getAccidentalModifer() == PB_ACCIDENTAL_MODIFER_force)
{
// Force the display of an accidental including naturals if it is the same bar
accidental = CStavePos::midiNote2Name(symbol.getNote()).accidental;
if (accidental == 0)
accidental = 2;
}
if (accidental != 0)
{
//drColor (Cfg::colorTheme().lineColor);
if (accidental == 1)
drawSymbol(CSymbol(PB_SYMBOL_sharp, symbol.getStavePos()), x - xGap, y);
else if (accidental == -1)
drawSymbol(CSymbol(PB_SYMBOL_flat, symbol.getStavePos()), x - xGap, y);
else
drawSymbol(CSymbol(PB_SYMBOL_natural, symbol.getStavePos()), x - xGap, y);
}
}
bool CDraw::drawNote(CSymbol* symbol, float x, float y, CSlot* slot, CColor color, bool playable)
{
Q_UNUSED(slot)
const float stemLength = 34.0f;
float noteWidth = 6.0f;
//ppLogTrace("PB_SYMBOL_noteHead x %f y %f", x, y);
if (!CChord::isNotePlayable(symbol->getNote(), 0))
{
color = Cfg::colorTheme().noteColorDim;
playable = false;
}
drawStaveExtentsion(*symbol, x, 16, playable);
drColor(color);
const auto noteLength = symbol->getType();
auto solidNoteHead = false;
auto showNoteStem = false;
auto stemFlagCount = 0;
if (noteLength <= PB_SYMBOL_demisemiquaver)
stemFlagCount = 3;
else if (noteLength <= PB_SYMBOL_semiquaver)
stemFlagCount = 2;
else if (noteLength <= PB_SYMBOL_quaver)
stemFlagCount = 1;
if (noteLength <= PB_SYMBOL_crotchet)
solidNoteHead = true;
if (noteLength <= PB_SYMBOL_threequater)
showNoteStem = true;
if (showNoteStem) {
if (!solidNoteHead)
noteWidth += 1.0f;
glLineWidth(2.0f);
glBegin(GL_LINE_STRIP);
glVertex2f(noteWidth + x, 0.0f + y); // 1
glVertex2f(noteWidth + x, stemLength + y); // 2
glEnd();
}
float offset = stemLength;
while (stemFlagCount > 0) {
glLineWidth(2.0);
glBegin(GL_LINE_STRIP);
glVertex2f(noteWidth + x, offset + y); // 1
glVertex2f(noteWidth + 8.0f + x, offset - 16.0f + y); // 2
glEnd();
offset -= 8;
stemFlagCount--;
}
if (solidNoteHead) {
glBegin(GL_POLYGON);
glVertex2f(-7.0f + x, 2.0f + y); // 1
glVertex2f(-5.0f + x, 4.0f + y); // 2
glVertex2f(-1.0f + x, 6.0f + y); // 3
glVertex2f( 4.0f + x, 6.0f + y); // 4
glVertex2f( 7.0f + x, 4.0f + y); // 5
glVertex2f( 7.0f + x, 1.0f + y); // 6
glVertex2f( 6.0f + x, -2.0f + y); // 7
glVertex2f( 4.0f + x, -4.0f + y); // 8
glVertex2f( 0.0f + x, -6.0f + y); // 9
glVertex2f(-4.0f + x, -6.0f + y); // 10
glVertex2f(-8.0f + x, -3.0f + y); // 11
glVertex2f(-8.0f + x, -0.0f + y); // 12
glEnd();
} else {
glLineWidth(2.0);
glBegin(GL_LINE_STRIP);
glVertex2f(-7.0f + x, 2.0f + y); // 1
glVertex2f(-5.0f + x, 4.0f + y); // 2
glVertex2f(-1.0f + x, 6.0f + y); // 3
glVertex2f( 4.0f + x, 6.0f + y); // 4
glVertex2f( 7.0f + x, 4.0f + y); // 5
glVertex2f( 7.0f + x, 1.0f + y); // 6
glVertex2f( 6.0f + x, -2.0f + y); // 7
glVertex2f( 4.0f + x, -4.0f + y); // 8
glVertex2f( 0.0f + x, -6.0f + y); // 9
glVertex2f(-4.0f + x, -6.0f + y); // 10
glVertex2f(-8.0f + x, -3.0f + y); // 11
glVertex2f(-8.0f + x, -0.0f + y); // 12
glEnd();
}
// draw a circle after the half note to make it a three-quater note
const auto isDottedNote = (noteLength < PB_SYMBOL_breve) && ((noteLength - PB_SYMBOL_noteHead) % 2 == 0);
if (isDottedNote) {
static constexpr auto radius = 4.0f;
x += 15.0f;
glBegin(GL_POLYGON);
glVertex2f(1.0f * radius + x, 0.0f * radius + y);
glVertex2f(0.951057f * radius + x, 0.309017f * radius + y);
glVertex2f(0.809017f * radius + x, 0.587785f * radius + y);
glVertex2f(0.587785f * radius + x, 0.809017f * radius + y);
glVertex2f(0.309017f * radius + x, 0.951057f * radius + y);
glVertex2f(6.12323e-17f * radius + x, 1.0f * radius + y);
glVertex2f(-0.309017f * radius + x, 0.951056f * radius + y);
glVertex2f(-0.587785f * radius + x, 0.809017f * radius + y);
glVertex2f(-0.809017f * radius + x, 0.587785f * radius + y);
glVertex2f(-0.951057f * radius + x, 0.309017f * radius + y);
glVertex2f(-1.0f * radius + x, -3.74507e-07f * radius + y);
glVertex2f(-0.951056f * radius + x, -0.309017f * radius + y);
glVertex2f(-0.809017f * radius + x, -0.587786f * radius + y);
glVertex2f(-0.587785f * radius + x, -0.809017f * radius + y);
glVertex2f(-0.309016f * radius + x, -0.951057f * radius + y);
glVertex2f(7.49014e-07f * radius + x, -1.0f * radius + y);
glVertex2f(0.309018f * radius + x, -0.951056f * radius + y);
glVertex2f(0.587786f * radius + x, -0.809016f * radius + y);
glVertex2f(0.809018f * radius + x, -0.587784f * radius + y);
glVertex2f(0.951057f * radius + x, -0.309016f * radius + y);
glEnd();
}
checkAccidental(*symbol, x, y);
return playable;
}
void CDraw::drawSymbol(CSymbol symbol, float x, float y, CSlot* slot)
{
const auto &colorTheme = Cfg::colorTheme();
CColor color = symbol.getColor();
bool playable = true;
if (m_displayHand != symbol.getHand() && m_displayHand != PB_PART_both)
{
if (color == colorTheme.noteColor)
color = colorTheme.noteColorDim;
if (color == colorTheme.staveColor)
color = colorTheme.staveColorDim;
playable = false;
}
switch (symbol.getType())
{
case PB_SYMBOL_gClef: // The Treble Clef
y += 4;
drColor(color);
glLineWidth (3.0f);
glBegin(GL_LINE_STRIP);
glVertex2f( -0.011922f + x, -16.11494f + y); // 1
glVertex2f( -3.761922f + x, -12.48994f + y); // 2
glVertex2f( -4.859633f + x, -8.85196f + y); // 3
glVertex2f( -4.783288f + x, -5.42815f + y); // 4
glVertex2f( -0.606711f + x, -1.11108f + y); // 5
glVertex2f( 5.355545f + x, 0.48711f + y); // 6
glVertex2f( 10.641104f + x, -1.6473f + y); // 7
glVertex2f( 14.293812f + x, -6.18241f + y); // 8
glVertex2f( 14.675578f + x, -11.42744f + y); // 9
glVertex2f( 12.550578f + x, -17.30244f + y); // 10
glVertex2f( 7.912166f + x, -20.944f + y); // 11
glVertex2f( 3.049705f + x, -21.65755f + y); // 12
glVertex2f( -1.711005f + x, -21.36664f + y); // 13
glVertex2f( -6.283661f + x, -19.66739f + y); // 14
glVertex2f( -10.123329f + x, -16.79162f + y); // 15
glVertex2f( -13.363008f + x, -12.28184f + y); // 16
glVertex2f( -14.675578f + x, -5.79969f + y); // 17
glVertex2f( -13.66821f + x, 0.20179f + y); // 18
glVertex2f( -10.385341f + x, 6.27562f + y); // 19
glVertex2f( 5.539491f + x, 20.32671f + y); // 20
glVertex2f( 10.431588f + x, 28.20584f + y); // 21
glVertex2f( 11.00141f + x, 34.71585f + y); // 22
glVertex2f( 9.204915f + x, 39.62875f + y); // 23
glVertex2f( 7.854166f + x, 42.08262f + y); // 24
glVertex2f( 5.481415f + x, 42.66649f + y); // 25
glVertex2f( 3.57972f + x, 41.4147f + y); // 26
glVertex2f( 1.507889f + x, 37.35642f + y); // 27
glVertex2f( -0.381338f + x, 31.14317f + y); // 28
glVertex2f( -0.664306f + x, 25.51354f + y); // 29
glVertex2f( 8.296044f + x, -32.22694f + y); // 30
glVertex2f( 8.050507f + x, -36.6687f + y); // 31
glVertex2f( 6.496615f + x, -39.52999f + y); // 32
glVertex2f( 3.368583f + x, -41.7968f + y); // 33
glVertex2f( 0.253766f + x, -42.66649f + y); // 34
glVertex2f( -3.599633f + x, -42.23514f + y); // 35
glVertex2f( -8.098754f + x, -39.46637f + y); // 36
glVertex2f( -9.463279f + x, -35.49796f + y); // 37
glVertex2f( -7.08037f + x, -31.36512f + y); // 38
glVertex2f( -3.336421f + x, -31.14057f + y); // 39
glVertex2f( -1.360313f + x, -34.07738f + y); // 40
glVertex2f( -1.608342f + x, -37.11828f + y); // 41
glVertex2f( -5.729949f + x, -39.24759f + y); // 42
glVertex2f( -7.480646f + x, -36.2136f + y); // 43
glVertex2f( -6.826918f + x, -33.36919f + y); // 44
glVertex2f( -4.069083f + x, -32.9226f + y); // 45
glVertex2f( -3.040669f + x, -34.433f + y); // 46
glVertex2f( -3.737535f + x, -36.38759f + y); // 47
glVertex2f( -5.496558f + x, -36.97633f + y); // 48
glVertex2f( -5.295932f + x, -34.01951f + y); // 49
glEnd();
break;
case PB_SYMBOL_fClef: // The Base Clef
drColor(color);
glLineWidth (3.0f);
glBegin(GL_LINE_STRIP);
glVertex2f( -15.370325f + x, -17.42068f + y); // 1
glVertex2f( -7.171025f + x, -13.75432f + y); // 2
glVertex2f( -2.867225f + x, -10.66642f + y); // 3
glVertex2f( 0.925165f + x, -7.03249f + y); // 4
glVertex2f( 4.254425f + x, -0.65527f + y); // 5
glVertex2f( 4.762735f + x, 7.77848f + y); // 6
glVertex2f( 2.693395f + x, 13.92227f + y); // 7
glVertex2f( -1.207935f + x, 16.80317f + y); // 8
glVertex2f( -5.526425f + x, 17.42068f + y); // 9
glVertex2f( -10.228205f + x, 15.65609f + y); // 10
glVertex2f( -13.453995f + x, 10.7128f + y); // 11
glVertex2f( -13.133655f + x, 5.43731f + y); // 12
glVertex2f( -9.475575f + x, 3.00714f + y); // 13
glVertex2f( -5.846445f + x, 4.72159f + y); // 14
glVertex2f( -5.395545f + x, 9.72918f + y); // 15
glVertex2f( -8.850025f + x, 11.64372f + y); // 16
glVertex2f( -11.519385f + x, 10.35816f + y); // 17
glVertex2f( -11.706365f + x, 6.8704f + y); // 18
glVertex2f( -9.463505f + x, 5.01391f + y); // 19
glVertex2f( -7.172075f + x, 5.81649f + y); // 20
glVertex2f( -7.189565f + x, 8.62975f + y); // 21
glVertex2f( -9.175055f + x, 9.82019f + y); // 22
glVertex2f( -10.696425f + x, 8.08395f + y); // 23
glVertex2f( -8.843065f + x, 6.66726f + y); // 24
glVertex2f( -8.995775f + x, 8.71136f + y); // 25
glEnd();
glBegin(GL_POLYGON);
glVertex2f( 10.0f + x, 14.0f + y); // 26
glVertex2f( 14.0f + x, 14.0f + y); // 27
glVertex2f( 14.0f + x, 10.0f + y); // 28
glVertex2f( 10.0f + x, 10.0f + y); // 29
glVertex2f( 10.0f + x, 14.0f + y); // 30
glEnd();
glBegin(GL_POLYGON);
glVertex2f( 10.0f + x, 4.0f + y); // 31
glVertex2f( 14.0f + x, 4.0f + y); // 32
glVertex2f( 14.0f + x, 0.0f + y); // 33
glVertex2f( 10.0f + x, 0.0f + y); // 34
glVertex2f( 10.0f + x, 4.0f + y); // 35
glEnd();
break;
case PB_SYMBOL_noteHead:
//ppLogTrace("PB_SYMBOL_noteHead x %f y %f", x, y);
if (!CChord::isNotePlayable(symbol.getNote(), 0))
{
color = Cfg::colorTheme().noteColorDim;
playable = false;
}
drawStaveExtentsion(symbol, x, 16, playable);
// See forum post at link below from PianoBooster forum user Kory.
// http://piano-booster.2625608.n2.nabble.com/Pianobooster-port-to-arm-linux-or-Android-td7572459.html
// http://piano-booster.2625608.n2.nabble.com/Pianobooster-port-to-arm-linux-or-Android-td7572459.html#a7572676
if (m_settings->coloredNotes() && color == colorTheme.noteColor) //KORY added
{
int note = symbol.getNote() % MIDI_OCTAVE;
switch (note)
{
case 0: //note::PitchLabel::C:
color = CColor(1.0, 0.0, 0.0); //Red
break;
case 1: //note::PitchLabel::C♯:
color = CColor(1.0, 0.25, 0.0); //Red
break;
case 2: //note::PitchLabel::D:
color = CColor(1.0, 0.5, 0.0); //Orange
break;
case 3: //note::PitchLabel::D♯:
color = CColor(1.0, 0.75, 0.0); //Orange
break;
case 4: //note::PitchLabel::E:
color = CColor(1.0, 1.0, 0.0); //Yellow
break;
case 5: //note::PitchLabel::F:
color = CColor(0.0, 1.0, 0.0); //Green
break;
case 6: //note::PitchLabel::F♯:
color = CColor(0.0, 0.5, 0.5); //Green
break;
case 7: //note::PitchLabel::G:
color = CColor(0.0, 0.0, 1.0); //Blue
break;
case 8: //note::PitchLabel::G♯:
color = CColor(0.290, 0.0, 0.903); //Blue
break;
case 9: //note::PitchLabel::A:
color = CColor(0.580, 0.0, 0.827); //Dark Violet #9400D3
break;
case 10: //note::PitchLabel::A♯:
color = CColor(0.790, 0.0, 0.903); //Dark Violet #9400D3
break;
case 11: //note::PitchLabel::B:
color = CColor(1.0, 0.0, 1.0); //Magenta
break;
}
}
drColor(color);
glBegin(GL_POLYGON);
glVertex2f(-7.0f + x, 2.0f + y); // 1
glVertex2f(-5.0f + x, 4.0f + y); // 2
glVertex2f(-1.0f + x, 6.0f + y); // 3
glVertex2f( 4.0f + x, 6.0f + y); // 4
glVertex2f( 7.0f + x, 4.0f + y); // 5
glVertex2f( 7.0f + x, 1.0f + y); // 6
glVertex2f( 6.0f + x, -2.0f + y); // 7
glVertex2f( 4.0f + x, -4.0f + y); // 8
glVertex2f( 0.0f + x, -6.0f + y); // 9
glVertex2f(-4.0f + x, -6.0f + y); // 10
glVertex2f(-8.0f + x, -3.0f + y); // 11
glVertex2f(-8.0f + x, -0.0f + y); // 12
glEnd();
/*
// shows the MIDI Duration (but not very useful)
glLineWidth(4.0f);
drColor(CColor(0.3, 0.4, 0.4));
glBegin(GL_LINE_STRIP);
glVertex2f(x, y);
glVertex2f(x + CMidiFile::ppqnAdjust<float>(static_cast<float>(symbol.getMidiDuration())) * HORIZONTAL_SPACING_FACTOR, y);
glEnd();
drColor(color);
*/
checkAccidental(symbol, x, y);
break;
case PB_SYMBOL_drum:
if (!CChord::isNotePlayable(symbol.getNote(), 0))
color = colorTheme.noteColorDim;
drColor(color);
glLineWidth (3.0f);
glBegin(GL_LINES);
glVertex2f( 5.0f + x,-5.0f + y);
glVertex2f(-5.0f + x, 5.0f + y);
glVertex2f(-5.0f + x,-5.0f + y);
glVertex2f( 5.0f + x, 5.0f + y);
glEnd();
checkAccidental(symbol, x, y);
break;
case PB_SYMBOL_sharp:
glLineWidth (2.0f);
glBegin(GL_LINES);
glVertex2f(-2.0f + x, -14.0f + y);
glVertex2f(-2.0f + x, 14.0f + y);
glVertex2f( 2.0f + x, -13.0f + y);
glVertex2f( 2.0f + x, 15.0f + y);
glVertex2f(-5.0f + x, 4.0f + y);
glVertex2f( 5.0f + x, 7.0f + y);
glVertex2f(-5.0f + x, -6.0f + y);
glVertex2f( 5.0f + x, -3.0f + y);
glEnd();
break;
case PB_SYMBOL_flat:
glLineWidth (2.0f);
glBegin(GL_LINE_STRIP);
glVertex2f(-4.0f + x, 17.0f + y); // 1
glVertex2f(-4.0f + x, -6.0f + y); // 2
glVertex2f( 2.0f + x, -2.0f + y); // 3
glVertex2f( 5.0f + x, 2.0f + y); // 4
glVertex2f( 5.0f + x, 4.0f + y); // 5
glVertex2f( 3.0f + x, 5.0f + y); // 6
glVertex2f( 0.0f + x, 5.0f + y); // 7
glVertex2f(-4.0f + x, 2.0f + y); // 8
glEnd();
break;
case PB_SYMBOL_natural:
glLineWidth (2.0f);
glBegin(GL_LINES);
glVertex2f( 3.0f + x, -15.0f + y); // 1
glVertex2f( 3.0f + x, 8.0f + y); // 2
glVertex2f( -3.0f + x, -8.0f + y); // 3
glVertex2f( -3.0f + x, 15.0f + y); // 4
glVertex2f( 3.0f + x, 8.0f + y); // 5
glVertex2f( -3.0f + x, 2.0f + y); // 6
glVertex2f( 3.0f + x, -2.0f + y); // 7
glVertex2f( -3.0f + x, -8.0f + y); // 8
glEnd();
break;
case PB_SYMBOL_barLine:
x += BEAT_MARKER_OFFSET * HORIZONTAL_SPACING_FACTOR; // the beat markers where entered early so now move them correctly
glLineWidth (4.0f);
drColor ((m_displayHand == PB_PART_left) ? colorTheme.staveColorDim : colorTheme.staveColor);
oneLine(x, CStavePos(PB_PART_right, 4).getPosYRelative(), x, CStavePos(PB_PART_right, -4).getPosYRelative());
drColor ((m_displayHand == PB_PART_right) ? colorTheme.staveColorDim : colorTheme.staveColor);
oneLine(x, CStavePos(PB_PART_left, 4).getPosYRelative(), x, CStavePos(PB_PART_left, -4).getPosYRelative());
break;
case PB_SYMBOL_barMarker:
x += BEAT_MARKER_OFFSET * HORIZONTAL_SPACING_FACTOR; // the beat markers where entered early so now move them correctly
glLineWidth (5.0f);
drColor(colorTheme.barMarkerColor);
oneLine(x, CStavePos(PB_PART_right, m_beatMarkerHeight).getPosYRelative(), x, CStavePos(PB_PART_left, -m_beatMarkerHeight).getPosYRelative());
glDisable (GL_LINE_STIPPLE);
break;
case PB_SYMBOL_beatMarker:
x += BEAT_MARKER_OFFSET * HORIZONTAL_SPACING_FACTOR; // the beat markers where entered early so now move them correctly
glLineWidth (4.0);
drColor(colorTheme.beatMarkerColor);
oneLine(x, CStavePos(PB_PART_right, m_beatMarkerHeight).getPosYRelative(), x, CStavePos(PB_PART_left, -m_beatMarkerHeight).getPosYRelative());
glDisable (GL_LINE_STIPPLE);
break;
case PB_SYMBOL_playingZone:
{
float topY = CStavePos(PB_PART_right, m_beatMarkerHeight).getPosY();
float bottomY = CStavePos(PB_PART_left, -m_beatMarkerHeight).getPosY();
float early = static_cast<float>(Cfg::playZoneEarly()) * HORIZONTAL_SPACING_FACTOR;
float late = static_cast<float>(Cfg::playZoneLate()) * HORIZONTAL_SPACING_FACTOR;
drColor(colorTheme.playingZoneBg);
glRectf(x-late, topY, x + early, bottomY);
glLineWidth (2.0f);
drColor(colorTheme.playingZoneMiddle);
oneLine(x, topY, x, bottomY );
glLineWidth (1.0f);
glColor3f (1.0f, 0.0f, 0.6f);
drColor(colorTheme.playingZoneBorder);
oneLine(x-late, topY, x-late, bottomY );
oneLine(x+early, topY, x+early, bottomY );
}
break;
default:
if (symbol.getType() >= PB_SYMBOL_noteHead)
playable = drawNote(&symbol, x, y, slot, color, playable);
else
ppDEBUG(("ERROR drawSymbol unhandled symbol\n"));
break;
}
if (symbol.getType() >= PB_SYMBOL_noteHead)
{
if ( symbol.getPianistTiming() != NOT_USED)
{
auto pianistX = static_cast<float>(symbol.getPianistTiming());
pianistX = x + pianistX * HORIZONTAL_SPACING_FACTOR;
drColor(colorTheme.timingMarkerColor);
glLineWidth (2.0f);
glBegin(GL_LINES);
glVertex2f( 4.0f + pianistX, 4.0f + y);
glVertex2f(-5.0f + pianistX,-5.0f + y);
glVertex2f( 4.0f + pianistX,-4.0f + y); // draw pianist note timing markers
glVertex2f(-5.0f + pianistX, 5.0f + y);
glEnd();
}
if ( playable )
drawStaveNoteName(symbol, x, y);
}
}
void CDraw::drawSymbol(CSymbol symbol, float x)
{
drawSymbol(symbol, x, symbol.getStavePos().getPosY());
}
void CDraw::drawSlot(CSlot* slot)
{
CStavePos stavePos;
//int av8Left = slot->getAv8Left();
for (int i=0; i < slot->length(); i++)
{
whichPart_t hand = slot->getSymbol(i).getHand();
int clef = PB_SYMBOL_gClef;
if (hand == PB_PART_right) {
clef = m_settings->value("SidePanel/clefRight").toInt();
}
else if (hand == PB_PART_left) {
clef = m_settings->value("SidePanel/clefLeft").toInt();
}
CSymbol symbol = slot->getSymbol(i);
symbol.setClef(clef);
stavePos.notePos(hand, symbol.getNote(), clef);
//ppLogTrace ("compileSlot len %d id %2d next %2d time %2d type %2d note %2d", slot->length(), slot->m_displayListId,
//slot->m_nextDisplayListId, slot->getDeltaTime(), slot->getSymbol(i).getType(), slot->getSymbol(i).getNote());
drawSymbol(symbol, 0.0, stavePos.getPosYRelative()); // we add this back when drawing this symbol
}
}
void CDraw::drawStaves(float startX, float endX)
{
int i;
glLineWidth (Cfg::staveThickness());
/* select color for all lines */
const auto &colorTheme = Cfg::colorTheme();
drColor ((m_displayHand != PB_PART_left) ? colorTheme.staveColor : colorTheme.staveColorDim);
glBegin(GL_LINES);
for (i = -4; i <= 4; i+=2 )
{
CStavePos pos = CStavePos(PB_PART_right, i);
glVertex2f (startX, pos.getPosY());
glVertex2f (endX, pos.getPosY());
}
drColor ((m_displayHand != PB_PART_right) ? colorTheme.staveColor : colorTheme.staveColorDim);
for (i = -4; i <= 4; i+=2 )
{
CStavePos pos = CStavePos(PB_PART_left, i);
glVertex2f (startX, pos.getPosY());
glVertex2f (endX, pos.getPosY());
}
glEnd();
}
void CDraw::drawKeySignature(int key)
{
static constexpr int sharpLookUpRight[] = { 4, 1, 5, 2,-1, 3, 0};
static constexpr int sharpLookUpLeft[] = { 2,-1, 3, 0,-3, 1,-2};
static constexpr int flatLookUpRight[] = { 0, 3,-1, 2,-2, 1,-3};
static constexpr int flatLookUpLeft[] = {-2, 1,-3, 0,-4,-1,-5};
static constexpr float gapX = 11.0f;
const auto &colorTheme = Cfg::colorTheme();
CStavePos pos;
if (key == NOT_USED)
return;
int i = 0;
while (key != 0 )
{
if (key > 0)
{
if (i < arraySize(sharpLookUpRight))
{
drColor ((m_displayHand != PB_PART_left) ? colorTheme.noteColor : colorTheme.noteColorDim);
pos = CStavePos(PB_PART_right, sharpLookUpRight[i]);
drawSymbol( CSymbol(PB_SYMBOL_sharp, pos), Cfg::keySignatureX() + gapX * static_cast<float>(i) );
}
if (i < arraySize(sharpLookUpLeft))
{
drColor ((m_displayHand != PB_PART_right) ? colorTheme.noteColor : colorTheme.noteColorDim);
pos = CStavePos(PB_PART_left, sharpLookUpLeft[i]);
drawSymbol( CSymbol(PB_SYMBOL_sharp, pos), Cfg::keySignatureX() + gapX * static_cast<float>(i) );
}
key--;
}
else
{
if (i < arraySize(flatLookUpRight))
{
drColor ((m_displayHand != PB_PART_left) ? colorTheme.noteColor : colorTheme.noteColorDim);
pos = CStavePos(PB_PART_right, flatLookUpRight[i]);
drawSymbol( CSymbol(PB_SYMBOL_flat, pos), Cfg::keySignatureX() + gapX * static_cast<float>(i) );
}
if (i < arraySize(flatLookUpLeft))
{
drColor ((m_displayHand != PB_PART_right) ? colorTheme.noteColor : colorTheme.noteColorDim);
pos = CStavePos(PB_PART_left, flatLookUpLeft[i]);
drawSymbol( CSymbol(PB_SYMBOL_flat, pos), Cfg::keySignatureX() + gapX * static_cast<float>(i) );
}
key++;
}
i++;
}
}