Skip to content

Commit

Permalink
Merge pull request #92 from mgavioli/TAB_half_note_stems
Browse files Browse the repository at this point in the history
Tab half note stems
  • Loading branch information
mgavioli committed Sep 22, 2012
2 parents 45b82d7 + 80afda1 commit ba582c2
Show file tree
Hide file tree
Showing 7 changed files with 163 additions and 50 deletions.
43 changes: 11 additions & 32 deletions libmscore/chord.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -298,17 +298,7 @@ void Chord::setStem(Stem* s)
QPointF Chord::stemPos() const
{
if (staff() && staff()->isTabStaff()) {
qreal sp = spatium();
StaffTypeTablature* tab = static_cast<StaffTypeTablature*>( staff()->staffType() );
qreal lineDist = tab->lineDistance().val();
qreal y;
if (tab->stemsDown())
y = tab->stemThrough() ? upString() * lineDist :
(tab->lines()-1)*lineDist + STAFFTYPE_TAB_DEFAULTSTEMPOSY_DN;
else
y = tab->stemThrough() ? downString()*lineDist : STAFFTYPE_TAB_DEFAULTSTEMPOSY_UP;

return QPointF(STAFFTYPE_TAB_DEFAULTSTEMPOSX*sp, y*sp) + pagePos();
return (static_cast<StaffTypeTablature*>(staff()->staffType())->chordStemPos(this) * spatium()) + pagePos();
}
return (_up ? downNote() : upNote())->stemPos(_up);
}
Expand All @@ -322,12 +312,7 @@ QPointF Chord::stemPos() const
QPointF Chord::stemPosBeam() const
{
if (staff() && staff()->isTabStaff()) {
qreal sp = spatium();
StaffTypeTablature* tab = static_cast<StaffTypeTablature*>( staff()->staffType() );
qreal y = ( tab->stemsDown() ?
downString() * tab->lineDistance().val() : STAFFTYPE_TAB_DEFAULTSTEMPOSY_UP);

return QPointF(STAFFTYPE_TAB_DEFAULTSTEMPOSX*sp, y*sp) + pagePos();
return (static_cast<StaffTypeTablature*>(staff()->staffType())->chordStemPosBeam(this) * spatium()) + pagePos();
}

return (_up ? upNote() : downNote())->stemPos(_up);
Expand Down Expand Up @@ -1121,18 +1106,9 @@ void Chord::layoutStem()
StaffTypeTablature* tab = (StaffTypeTablature*)staff()->staffType();
// require stems only if not stemless and this chord has a stem
if (!tab->slashStyle() && _stem) {
// process stems:
qreal lineDist = tab->lineDistance().val();
QPointF pos = stemPos() - pagePos();
qreal stemLen;
if (tab->stemThrough())
stemLen = tab->stemsDown() ?
STAFFTYPE_TAB_DEFAULTSTEMLEN_DN + STAFFTYPE_TAB_DEFAULTSTEMDIST_DN + (tab->lines()-1 - upString()) * lineDist :
STAFFTYPE_TAB_DEFAULTSTEMLEN_UP + STAFFTYPE_TAB_DEFAULTSTEMDIST_UP + downString() * lineDist;
else
stemLen = tab->stemsDown() ? STAFFTYPE_TAB_DEFAULTSTEMLEN_DN: STAFFTYPE_TAB_DEFAULTSTEMLEN_UP;
_stem->setPos(pos);
_stem->setLen(stemLen * spatium());
// process stem:
_stem->setPos(tab->chordStemPos(this) * spatium());
_stem->setLen(tab->chordStemLength(this) * spatium());
// process hook
int hookIdx = durationType().hooks();
if (tab->stemsDown())
Expand Down Expand Up @@ -1339,14 +1315,18 @@ void Chord::layout()
note->setPos(0.0, _spatium * tab->physStringToVisual(note->string()) * lineDist);
note->layout2();
}
// if tab type is stemless or duration longer than crochet
// if tab type is stemless or duration longer than half (if halves have stems) or duration longer than crochet
// remove stems
if (tab->slashStyle() || durationType().type() < TDuration::V_QUARTER) {
if (tab->slashStyle() || durationType().type() <
(tab->minimStyle() != TAB_MINIM_NONE ? TDuration::V_HALF : TDuration::V_QUARTER) ) {
delete _stem;
delete _hook;
_stem = 0;
_hook = 0;
}
// if stem is required but missing, add it
else if(/*durationType().hasStem() &&*/ _stem == 0)
setStem(new Stem(score()));
// unconditionally delete grace slashes
delete _stemSlash;
_stemSlash = 0;
Expand Down Expand Up @@ -1379,7 +1359,6 @@ void Chord::layout()
else
_tabDur->setDuration(durationType().type(), dots());
_tabDur->setParent(this);
// needed? _tabDur->setTrack(track());
_tabDur->layout();
}
else { // symbol not needed: if exists, delete
Expand Down
70 changes: 70 additions & 0 deletions libmscore/stafftype.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "staff.h"
#include "xml.h"
#include "mscore.h"
#include "chord.h"

#define TAB_DEFAULT_LINE_SP (1.5)
#define TAB_RESTSYMBDISPL 2.0
Expand Down Expand Up @@ -670,6 +671,75 @@ void StaffTypeTablature::setFretFontSize(qreal val)
_fretMetricsValid = false;
}

//---------------------------------------------------------
// chordStemPos / chordStemPosBeam / chordStemLength
//
// computes the stem data for the given chord, according to TAB settings
// NOTE: unit: spatium, position: relative to chord (DIFFERENT from Chord own functions)
//
// chordStemPos
// return position of note at other side of beam
//---------------------------------------------------------

QPointF StaffTypeTablature::chordStemPos(const Chord *chord) const
{
qreal y;
qreal delta = // displacement for half note stems (if used)
// if half notes have not a short stem OR not a half note => 0
(minimStyle() != TAB_MINIM_SHORTER || chord->durationType().type() != TDuration::V_HALF) ?
0.0 :
// if stems are up, displace of half stem length down (positive)
// if stems are down, displace of half stem length up (negative)
(stemsDown() ?
STAFFTYPE_TAB_DEFAULTSTEMLEN_DN : -STAFFTYPE_TAB_DEFAULTSTEMLEN_UP) * 0.5;

// if stems are through staff, stem goes from fartest note string
if (stemThrough())
y = (stemsDown() ? chord->upString() : chord->downString()) * _lineDistance.val();
else
// if stems beside staff, position are fixed, but take into account delta
y = (stemsDown() ? (_lines-1)*_lineDistance.val() + STAFFTYPE_TAB_DEFAULTSTEMPOSY_DN :
STAFFTYPE_TAB_DEFAULTSTEMPOSY_UP) + delta;

return QPointF(STAFFTYPE_TAB_DEFAULTSTEMPOSX, y);
}

//---------------------------------------------------------
// chordStemPosBeam
// return position of note at beam side of stem
//---------------------------------------------------------

QPointF StaffTypeTablature::chordStemPosBeam(const Chord *chord) const
{
qreal y = ( stemsDown() ? chord->downString() : chord->upString() ) * _lineDistance.val();

return QPointF(STAFFTYPE_TAB_DEFAULTSTEMPOSX, y);
}

//---------------------------------------------------------
// chordStemLength
// return length of stem
//---------------------------------------------------------

qreal StaffTypeTablature::chordStemLength(const Chord *chord) const
{
qreal stemLen;
// if stems are through staff, length is from fartest note to a fixed point aboe/below staff
if (stemThrough())
stemLen = stemsDown() ?
STAFFTYPE_TAB_DEFAULTSTEMLEN_DN + STAFFTYPE_TAB_DEFAULTSTEMDIST_DN
+ (_lines-1 - chord->upString()) * _lineDistance.val() :
STAFFTYPE_TAB_DEFAULTSTEMLEN_UP + STAFFTYPE_TAB_DEFAULTSTEMDIST_UP
+ chord->downString() * _lineDistance.val();
// if stems beside staff, length is fixed, but take into account shorter half note stems
else {
bool shrt = (minimStyle() == TAB_MINIM_SHORTER) && (chord->durationType().type() == TDuration::V_HALF);
stemLen = (stemsDown() ? STAFFTYPE_TAB_DEFAULTSTEMLEN_DN : STAFFTYPE_TAB_DEFAULTSTEMLEN_UP)
* (shrt ? 0.5 : 1.0);
}
return stemLen;
}

//---------------------------------------------------------
// fretString / durationString
//
Expand Down
22 changes: 19 additions & 3 deletions libmscore/stafftype.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "mscore.h"
#include "durationtype.h"

// all in spatium units
#define STAFFTYPE_TAB_DEFAULTSTEMLEN_UP 3.0
#define STAFFTYPE_TAB_DEFAULTSTEMDIST_UP 1.0
#define STAFFTYPE_TAB_DEFAULTSTEMPOSY_UP -STAFFTYPE_TAB_DEFAULTSTEMDIST_UP
Expand All @@ -28,6 +29,18 @@
#define STAFFTYPE_TAB_DEFAULTSTEMPOSX 0.75
#define STAFFTYPE_TAB_DEFAULTDOTDIST_X 0.75

#define STAFFTYPE_TAB_SLASH_WIDTH 1.2 /* X width of half note slash */
#define STAFFTYPE_TAB_SLASH_SLANTY 0.8 /* the Y coord of the slash slant */
#define STAFFTYPE_TAB_SLASH_THICK 0.4 /* slash thickness */
#define STAFFTYPE_TAB_SLASH_DISPL 0.8 /* the total displacement between one slash and the next */
// the total height of a double slash
#define STAFFTYPE_TAB_SLASH_2TOTHEIGHT (STAFFTYPE_TAB_SLASH_THICK+STAFFTYPE_TAB_SLASH_DISPL+STAFFTYPE_TAB_SLASH_SLANTY)
// the initial Y coord for a double shash on an UP stem = topmost corner of topmost slash
#define STAFFTYPE_TAB_SLASH_2STARTY_UP ((STAFFTYPE_TAB_DEFAULTSTEMLEN_UP-STAFFTYPE_TAB_SLASH_2TOTHEIGHT)*0.5)
// the initial Y coord for a double shash on an DN stem = topmost corner of topmost slash
#define STAFFTYPE_TAB_SLASH_2STARTY_DN ((STAFFTYPE_TAB_DEFAULTSTEMLEN_UP+STAFFTYPE_TAB_SLASH_2TOTHEIGHT)*0.5)

class Chord;
class Staff;
class Xml;
class QPainter;
Expand Down Expand Up @@ -273,8 +286,6 @@ class StaffTypeTablature : public StaffType {
setUseNumbers(useNumbers);
}

// internally managed variables

// re-implemented virtual functions
virtual StaffGroup group() const { return TAB_STAFF; }
virtual StaffTypeTablature* clone() const { return new StaffTypeTablature(*this); }
Expand All @@ -286,7 +297,7 @@ class StaffTypeTablature : public StaffType {

QString fretString(int fret, bool ghost) const; // returns a string with the text for fret
QString durationString(TDuration::DurationType type, int dots) const;
// functions to cope with tabulature visal order (top down or upside down)
// functions to cope with tabulature visual order (top down or upside down)
int physStringToVisual(int strg) const; // return the string in visual order from physical string
int VisualStringToPhys(int strg) const; // return the string in physical order from visual string

Expand Down Expand Up @@ -333,6 +344,11 @@ class StaffTypeTablature : public StaffType {
void setUpsideDown(bool val) { _upsideDown = val; }
void setUseNumbers(bool val) { _useNumbers = val; _fretMetricsValid = false; }

// utility functions for tab specially managed elements
QPointF chordStemPos(const Chord * chord) const;
QPointF chordStemPosBeam(const Chord * chord) const;
qreal chordStemLength(const Chord *chord) const;

// static functions for font config files
static bool readConfigFile(const QString& fileName);
static QList<QString> fontNames(bool bDuration);
Expand Down
40 changes: 35 additions & 5 deletions libmscore/stem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -156,14 +156,44 @@ void Stem::draw(QPainter* painter) const
painter->setPen(QPen(curColor(), lw, Qt::SolidLine, Qt::RoundCap));
painter->drawLine(line);

// NOT THE BEST PLACE FOR THIS?
// with tablatures, dots are not drawn near 'notes', but near stems
// TODO: adjust bounding rectangle in layout()
if (useTab) {
// TODO: adjust bounding rectangle in layout() for dots and for slash
StaffTypeTablature* stt = static_cast<StaffTypeTablature*>(st->staffType());
qreal sp = spatium();

// slashed half note stem
if(chord() && chord()->durationType().type() == TDuration::V_HALF
&& stt->minimStyle() == TAB_MINIM_SLASHED) {
qreal wdt = sp * STAFFTYPE_TAB_SLASH_WIDTH;
qreal sln = sp * STAFFTYPE_TAB_SLASH_SLANTY;
qreal thk = sp * STAFFTYPE_TAB_SLASH_THICK;
qreal displ = sp * STAFFTYPE_TAB_SLASH_DISPL;
QPainterPath path = QPainterPath();

qreal y = stt->stemsDown() ?
_len - STAFFTYPE_TAB_SLASH_2STARTY_DN*sp :
-_len + STAFFTYPE_TAB_SLASH_2STARTY_UP*sp;
int lines = 2;
for (int i = 0; i < lines; ++i) {
path.moveTo( wdt*0.5-lw, y); // top-right corner
path.lineTo( wdt*0.5-lw, y+thk); // bottom-right corner
path.lineTo(-wdt*0.5, y+thk+sln);// bottom-left corner
path.lineTo(-wdt*0.5, y+sln); // top-left corner
path.closeSubpath();
y += displ;
}
// setbbox(path.boundingRect());
painter->setBrush(QBrush(curColor()));
painter->setPen(Qt::NoPen);
painter->drawPath(path);
}

// dots
// NOT THE BEST PLACE FOR THIS?
// with tablatures, dots are not drawn near 'notes', but near stems
int nDots = chord()->dots();
if (nDots > 0) {
qreal sp = spatium();
qreal y = stemLen() - ( ((StaffTypeTablature*)st->staffType())->stemsDown() ?
qreal y = stemLen() - (stt->stemsDown() ?
(STAFFTYPE_TAB_DEFAULTSTEMLEN_DN - 0.75) * sp : 0.0 );
symbols[score()->symIdx()][dotSym].draw(painter, magS(),
QPointF(STAFFTYPE_TAB_DEFAULTDOTDIST_X * sp, y), nDots);
Expand Down
16 changes: 11 additions & 5 deletions mscore/editstafftype.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,13 @@ EditStaffType::EditStaffType(QWidget* parent, Staff* st)
}

// init tab presets
// clef bars stemless time durations size off genDur frets size off thru minim style onLin rests stmDn stmThr upsDn nums
_tabPresets[TAB_PRESET_GUITAR] = new StaffTypeTablature(QString(), 6, 1.5, true, true, false, false, QString("MuseScore Tab Modern"), 15, 0, false, QString("MuseScore Tab Modern"), 10, 0, false, TAB_MINIM_NONE,true, false, true, true, false, true);
_tabPresets[TAB_PRESET_BASS] = new StaffTypeTablature(QString(), 4, 1.5, true, true, false, false, QString("MuseScore Tab Modern"), 15, 0, false, QString("MuseScore Tab Modern"), 10, 0, false, TAB_MINIM_NONE,true, false, true, true, false, true);
_tabPresets[TAB_PRESET_ITALIAN] = new StaffTypeTablature(QString(), 6, 1.5, false, true, true, true, QString("MuseScore Tab Italian"),15, 0, true, QString("MuseScore Tab Renaiss"), 10, 0, true, TAB_MINIM_NONE,true, true, false, false, true, true);
_tabPresets[TAB_PRESET_FRENCH] = new StaffTypeTablature(QString(), 6, 1.5, false, true, true, true, QString("MuseScore Tab French"), 15, 0, true, QString("MuseScore Tab Renaiss"), 10, 0, true, TAB_MINIM_NONE,false, false, false, false, false, false);
// clef bars stemless time durations size off genDur frets size off thru minim style onLin rests stmDn stmThr upsDn nums
_tabPresets[TAB_PRESET_GUITAR] = new StaffTypeTablature(QString(), 6, 1.5, true, true, false, false, QString("MuseScore Tab Modern"), 15, 0, false, QString("MuseScore Tab Modern"), 10, 0, false, TAB_MINIM_NONE, true, false, true, true, false, true);
_tabPresets[TAB_PRESET_BASS] = new StaffTypeTablature(QString(), 4, 1.5, true, true, false, false, QString("MuseScore Tab Modern"), 15, 0, false, QString("MuseScore Tab Modern"), 10, 0, false, TAB_MINIM_NONE, true, false, true, true, false, true);
_tabPresets[TAB_PRESET_UKULELE] = new StaffTypeTablature(QString(), 4, 1.5, true, true, false, false, QString("MuseScore Tab Modern"), 15, 0, false, QString("MuseScore Tab Modern"), 10, 0, false, TAB_MINIM_SHORTER,true, true, true, false, false, true);
_tabPresets[TAB_PRESET_BANDURRIA]=new StaffTypeTablature(QString(), 6, 1.5, true, true, false, false, QString("MuseScore Tab Modern"), 15, 0, false, QString("MuseScore Tab Modern"), 10, 0, false, TAB_MINIM_SLASHED,true, true, true, true, false, true);
_tabPresets[TAB_PRESET_ITALIAN] = new StaffTypeTablature(QString(), 6, 1.5, false, true, true, true, QString("MuseScore Tab Italian"),15, 0, true, QString("MuseScore Tab Renaiss"), 10, 0, true, TAB_MINIM_NONE, true, true, false, false, true, true);
_tabPresets[TAB_PRESET_FRENCH] = new StaffTypeTablature(QString(), 6, 1.5, false, true, true, true, QString("MuseScore Tab French"), 15, 0, true, QString("MuseScore Tab Renaiss"), 10, 0, true, TAB_MINIM_NONE, false, false, false, false, false, false);
// tab page configuration
tabDetails->hide(); // start tabulature page in simple mode
QList<QString> fontNames = StaffTypeTablature::fontNames(false);
Expand Down Expand Up @@ -125,6 +127,10 @@ EditStaffType::~EditStaffType()
delete _tabPresets[TAB_PRESET_GUITAR];
if(_tabPresets[TAB_PRESET_BASS])
delete _tabPresets[TAB_PRESET_BASS];
if(_tabPresets[TAB_PRESET_UKULELE])
delete _tabPresets[TAB_PRESET_UKULELE];
if(_tabPresets[TAB_PRESET_BANDURRIA])
delete _tabPresets[TAB_PRESET_BANDURRIA];
if(_tabPresets[TAB_PRESET_ITALIAN])
delete _tabPresets[TAB_PRESET_ITALIAN];
if(_tabPresets[TAB_PRESET_FRENCH])
Expand Down
2 changes: 2 additions & 0 deletions mscore/editstafftype.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ class EditStaffType : public QDialog, private Ui::EditStaffType {
enum {
TAB_PRESET_GUITAR = 0,
TAB_PRESET_BASS,
TAB_PRESET_UKULELE,
TAB_PRESET_BANDURRIA,
TAB_PRESET_ITALIAN,
TAB_PRESET_FRENCH,
TAB_PRESET_CUSTOM, // custom preset has no effect
Expand Down
Loading

0 comments on commit ba582c2

Please sign in to comment.