Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Develop tab glt positioning #3512

Merged
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion include/vrv/note.h
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,8 @@ class Note : public LayerElement,
* @name Return the smufl string to use for a note give the notation type
*/
///@{
std::u32string GetTabFretString(data_NOTATIONTYPE notationType, bool &overline) const;
std::u32string GetTabFretString(
data_NOTATIONTYPE notationType, const std::string &notationSubtype, int &overline, int &strike) const;
///@}

/**
Expand Down
3 changes: 2 additions & 1 deletion include/vrv/staffdef.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ class StaffDef : public ScoreDefElement,
public AttStaffDefLog,
public AttStaffDefVis,
public AttTimeBase,
public AttTransposition {
public AttTransposition,
public AttVerticalAlign {
public:
/**
* @name Constructors, destructors, and other standard methods
Expand Down
2 changes: 1 addition & 1 deletion include/vrv/tabdursym.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ namespace vrv {
/**
* This class models the MEI <tabDurSym> element.
*/
class TabDurSym : public LayerElement, public StemmedDrawingInterface, public AttNNumberLike {
class TabDurSym : public LayerElement, public StemmedDrawingInterface, public AttNNumberLike, public AttStaffLoc {
public:
/**
* @name Constructors, destructors, and other standard methods
Expand Down
8 changes: 6 additions & 2 deletions include/vrv/tuning.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,16 +42,20 @@ class Tuning : public Object, public AttCourseLog {
/**
* Return the line for a note according to tablature type.
* Guitar, french and italian tablature: the line is based on the course.
* German tablature: the line is based on the note's index in the note list.
* German tablature: the line is based on the note's index in the note list
* or by explicit @loc.
*
* @param[in] course
* @param[in] notationType
* @param[in] lines
* @param[in] listSize
* @param[in] index - 0 based from the bottom of the chord
* @param[in] loc - German tablature: note@loc if specified, 0 at the bottom
* @param[in] topAlign - German tablature: true => align at the top, false => align at the bottom
* @return position in staff half lines
*/
int CalcPitchPos(int course, data_NOTATIONTYPE notationType, int lines, int listSize, int index) const;
int CalcPitchPos(
int course, data_NOTATIONTYPE notationType, int lines, int listSize, int index, int loc, bool topAlign) const;

/**
* Calculate the MIDI note number for course/fret
Expand Down
4 changes: 3 additions & 1 deletion src/calcalignmentpitchposfunctor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,10 @@ FunctorCode CalcAlignmentPitchPosFunctor::VisitLayerElement(LayerElement *layerE
TabGrp *tabGrp = note->IsTabGrpNote();
if (tabGrp) {
assert(staffY->m_drawingTuning);
assert(staffY->m_drawingStaffDef);
loc = staffY->m_drawingTuning->CalcPitchPos(note->GetTabCourse(), staffY->m_drawingNotationType,
staffY->m_drawingLines, tabGrp->GetListSize(tabGrp), tabGrp->GetListIndex(note));
staffY->m_drawingLines, tabGrp->GetListSize(), tabGrp->GetListIndex(note), note->GetLoc(),
staffY->m_drawingStaffDef->GetValign() != VERTICALALIGNMENT_bottom);
}
else if ((note->HasPname() && note->HasOct()) || note->HasLoc()) {
loc = PitchInterface::CalcLoc(note, layerY, layerElementY);
Expand Down
4 changes: 4 additions & 0 deletions src/iomei.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1812,6 +1812,7 @@ void MEIOutput::WriteStaffDef(pugi::xml_node currentNode, StaffDef *staffDef)
staffDef->WriteStaffDefVis(currentNode);
staffDef->WriteTimeBase(currentNode);
staffDef->WriteTransposition(currentNode);
staffDef->WriteVerticalAlign(currentNode);
}

void MEIOutput::WriteInstrDef(pugi::xml_node currentNode, InstrDef *instrDef)
Expand Down Expand Up @@ -2791,6 +2792,7 @@ void MEIOutput::WriteTabDurSym(pugi::xml_node currentNode, TabDurSym *tabDurSym)

this->WriteLayerElement(currentNode, tabDurSym);
tabDurSym->WriteNNumberLike(currentNode);
tabDurSym->WriteStaffLoc(currentNode);
}

void MEIOutput::WriteTabGrp(pugi::xml_node currentNode, TabGrp *tabGrp)
Expand Down Expand Up @@ -5100,6 +5102,7 @@ bool MEIInput::ReadStaffDef(Object *parent, pugi::xml_node staffDef)
vrvStaffDef->ReadStaffDefVis(staffDef);
vrvStaffDef->ReadTimeBase(staffDef);
vrvStaffDef->ReadTransposition(staffDef);
vrvStaffDef->ReadVerticalAlign(staffDef);

if (!vrvStaffDef->HasN()) {
LogWarning("No @n on <staffDef> might yield unpredictable results");
Expand Down Expand Up @@ -6972,6 +6975,7 @@ bool MEIInput::ReadTabDurSym(Object *parent, pugi::xml_node tabRhyhtm)
this->ReadLayerElement(tabRhyhtm, vrvTabDurSym);

vrvTabDurSym->ReadNNumberLike(tabRhyhtm);
vrvTabDurSym->ReadStaffLoc(tabRhyhtm);

parent->AddChild(vrvTabDurSym);
this->ReadUnsupportedAttr(tabRhyhtm, vrvTabDurSym);
Expand Down
39 changes: 28 additions & 11 deletions src/note.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -267,9 +267,11 @@ const TabGrp *Note::IsTabGrpNote() const
return vrv_cast<const TabGrp *>(this->GetFirstAncestor(TABGRP, MAX_TABGRP_DEPTH));
}

std::u32string Note::GetTabFretString(data_NOTATIONTYPE notationType, bool &overline) const
std::u32string Note::GetTabFretString(
data_NOTATIONTYPE notationType, const std::string &notationSubtype, int &overline, int &strike) const
{
overline = false;
overline = 0;
strike = 0;

if (notationType == NOTATIONTYPE_tab_lute_italian) {
std::u32string fretStr;
Expand Down Expand Up @@ -350,23 +352,38 @@ std::u32string Note::GetTabFretString(data_NOTATIONTYPE notationType, bool &over
//
// However, some glyphs are missing:
//
// Digit 1 with an oblique stroke for the open 6th course.
// Digit 1 with a strike through for the open 6th course.
// Digit 1 with two strike throughs for the open 7th course.
// Digit 1 with three strike throughs for the open 8th course.
// "et" for 2nd course 5th fret.
// "con" for 1st course 5th fret.
// Gothic font digits 1-5 for the open courses <= 5.
// Second lowercase alphabet with an overline used for courses <= 5 frets 6 to 10.
//
// To overcome these omissions I've substituted missing glyphs from other
// parts of the SMuFL collection. Overlines are drawn separately.
// parts of the SMuFL collection. Overlines and strike throughs are drawn separately.

if (course == 6 && fret >= 0 && fret <= 13) {
if (fret == 0) {
fretStr = SMUFL_E595_ornamentLeftVerticalStrokeWithCross; // substitute for 1 with oblique stroke
}
else {
if (course >= 6 && fret >= 0 && fret <= 13) {
// TODO more GLT subtypes needed, is this subtype too specific?
if (notationSubtype == "judenkunig_1523") {
lpugin marked this conversation as resolved.
Show resolved Hide resolved
// A B C D ...
// The German tablature uppercase letters A-N are contiguous, correctly omitting J
static_assert(SMUFL_EC23_luteGermanNUpper == SMUFL_EC17_luteGermanAUpper + 13 - 1);
fretStr = SMUFL_EC17_luteGermanAUpper + fret - 1;
fretStr = SMUFL_EC17_luteGermanAUpper + fret;
overline = course - 6; // 6 course 0 overline, 7 course 1 overline, ...
}
else {
// + A B C D ...
if (fret == 0) {
fretStr = SMUFL_EA51_figbass1; // substitute for 1 with oblique stroke
strike = course - 5; // 6 course 1 strike, 7 course 2 strikes, ...
}
else {
// The German tablature uppercase letters A-N are contiguous, correctly omitting J
static_assert(SMUFL_EC23_luteGermanNUpper == SMUFL_EC17_luteGermanAUpper + 13 - 1);
fretStr = SMUFL_EC17_luteGermanAUpper + fret - 1;
overline = course - 6; // 6 course 0 overline, 7 course 1 overline, ...
}
}
}
else if (course >= 1 && course <= 5 && fret == 0) {
Expand Down Expand Up @@ -394,7 +411,7 @@ std::u32string Note::GetTabFretString(data_NOTATIONTYPE notationType, bool &over
}

// second alphabet needs an overline
overline = (fret >= 6);
overline = (fret >= 6) ? 1 : 0;
}
return fretStr;
}
Expand Down
3 changes: 3 additions & 0 deletions src/staffdef.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ StaffDef::StaffDef()
, AttStaffDefVis()
, AttTimeBase()
, AttTransposition()
, AttVerticalAlign()
{
this->RegisterAttClass(ATT_DISTANCES);
this->RegisterAttClass(ATT_LABELLED);
Expand All @@ -52,6 +53,7 @@ StaffDef::StaffDef()
this->RegisterAttClass(ATT_STAFFDEFVIS);
this->RegisterAttClass(ATT_TIMEBASE);
this->RegisterAttClass(ATT_TRANSPOSITION);
this->RegisterAttClass(ATT_VERTICALALIGN);

this->Reset();
}
Expand All @@ -71,6 +73,7 @@ void StaffDef::Reset()
this->ResetStaffDefVis();
this->ResetTimeBase();
this->ResetTransposition();
this->ResetVerticalAlign();

m_drawingVisibility = OPTIMIZATION_NONE;
}
Expand Down
5 changes: 4 additions & 1 deletion src/tabdursym.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,11 @@ namespace vrv {

static const ClassRegistrar<TabDurSym> s_factory("tabDurSym", TABDURSYM);

TabDurSym::TabDurSym() : LayerElement(TABDURSYM, "tabdursym-"), StemmedDrawingInterface(), AttNNumberLike()
TabDurSym::TabDurSym()
: LayerElement(TABDURSYM, "tabdursym-"), StemmedDrawingInterface(), AttNNumberLike(), AttStaffLoc()
{
this->RegisterAttClass(ATT_NNUMBERLIKE);
this->RegisterAttClass(ATT_STAFFLOC);

this->Reset();
}
Expand All @@ -45,6 +47,7 @@ void TabDurSym::Reset()
LayerElement::Reset();
StemmedDrawingInterface::Reset();
this->ResetNNumberLike();
this->ResetStaffLoc();
}

bool TabDurSym::IsSupportedChild(Object *child)
Expand Down
15 changes: 13 additions & 2 deletions src/tuning.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,25 @@ bool Tuning::IsSupportedChild(Object *child)
return true;
}

int Tuning::CalcPitchPos(int course, data_NOTATIONTYPE notationType, int lines, int listSize, int index) const
int Tuning::CalcPitchPos(
int course, data_NOTATIONTYPE notationType, int lines, int listSize, int index, int loc, bool topAlign) const
{
switch (notationType) {
case NOTATIONTYPE_tab_lute_french:
// all courses >= 7 are positioned above line 0
return (lines - std::min(course, 7)) * 2 + 1; // above the line
case NOTATIONTYPE_tab_lute_italian: return (course - 1) * 2;
case NOTATIONTYPE_tab_lute_german: return (lines - (listSize - index)) * 2;
case NOTATIONTYPE_tab_lute_german:
if (loc != MEI_UNSET) {
return loc;
}
else if (topAlign) {
return (lines - (listSize - index)) * 2;
}
else {
// bottom align
return index * 2;
}
case NOTATIONTYPE_tab_guitar: [[fallthrough]];
default: return abs(course - lines) * 2;
}
Expand Down
39 changes: 30 additions & 9 deletions src/view_tab.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "rend.h"
#include "smufl.h"
#include "staff.h"
#include "staffdef.h"
#include "stem.h"
#include "system.h"
#include "tabdursym.h"
Expand Down Expand Up @@ -105,11 +106,13 @@ void View::DrawTabNote(DeviceContext *dc, LayerElement *element, Layer *layer, S

int glyphSize = staff->GetDrawingStaffNotationSize();
bool drawingCueSize = false;
bool overline = false;
int overline = 0;
int strike = 0;

if (staff->m_drawingNotationType == NOTATIONTYPE_tab_guitar) {

std::u32string fret = note->GetTabFretString(staff->m_drawingNotationType, overline);
std::u32string fret = note->GetTabFretString(
staff->m_drawingNotationType, staff->m_drawingStaffDef->GetNotationsubtype(), overline, strike);

FontInfo fretTxt;
if (!dc->UseGlobalStyling()) {
Expand All @@ -135,7 +138,8 @@ void View::DrawTabNote(DeviceContext *dc, LayerElement *element, Layer *layer, S
}
else {

std::u32string fret = note->GetTabFretString(staff->m_drawingNotationType, overline);
std::u32string fret = note->GetTabFretString(
staff->m_drawingNotationType, staff->m_drawingStaffDef->GetNotationsubtype(), overline, strike);
// Center for italian tablature
if (staff->IsTabLuteItalian()) {
y -= (m_doc->GetGlyphHeight(SMUFL_EBE0_luteItalianFret0, glyphSize, drawingCueSize) / 2);
Expand All @@ -153,8 +157,8 @@ void View::DrawTabNote(DeviceContext *dc, LayerElement *element, Layer *layer, S
dc->SetFont(m_doc->GetDrawingSmuflFont(glyphSize, false));
this->DrawSmuflString(dc, x, y, fret, HORIZONTALALIGNMENT_center, glyphSize);

// Add overline if required
if (overline && !fret.empty()) {
// Add overlines or strikethoughs if required
if ((overline > 0 || strike > 0) && !fret.empty()) {
const int lineThickness
= m_options->m_lyricLineThickness.GetValue() * m_doc->GetDrawingUnit(staff->m_drawingStaffSize);
const int widthFront = m_doc->GetGlyphWidth(fret.front(), glyphSize, drawingCueSize);
Expand All @@ -165,13 +169,24 @@ void View::DrawTabNote(DeviceContext *dc, LayerElement *element, Layer *layer, S
const int x1 = x - widthFront / 2;
const int x2 = x + extend.m_width - widthBack * 3 / 10; // trim right hand overhang on last character

const int y1 = y + extend.m_ascent + lineThickness;
const int y2 = y1;

dc->SetPen(m_currentColor, lineThickness, AxSOLID);
dc->SetBrush(m_currentColor, AxSOLID);

dc->DrawLine(ToDeviceContextX(x1), ToDeviceContextY(y1), ToDeviceContextX(x2), ToDeviceContextY(y2));
// overlines
int y1 = y + extend.m_ascent + lineThickness;

for (int i = 0; i < overline; ++i) {
dc->DrawLine(ToDeviceContextX(x1), ToDeviceContextY(y1), ToDeviceContextX(x2), ToDeviceContextY(y1));
y1 += 2 * lineThickness;
}

// strikethroughs
y1 = y + extend.m_ascent / 2 - (strike - 1) * lineThickness;

for (int i = 0; i < strike; ++i) {
dc->DrawLine(ToDeviceContextX(x1), ToDeviceContextY(y1), ToDeviceContextX(x2), ToDeviceContextY(y1));
y1 += 2 * lineThickness;
}

dc->ResetPen();
dc->ResetBrush();
Expand Down Expand Up @@ -200,6 +215,12 @@ void View::DrawTabDurSym(DeviceContext *dc, LayerElement *element, Layer *layer,

dc->StartGraphic(tabDurSym, "", tabDurSym->GetID());

if (tabDurSym->HasLoc()) {
const int yRel = ((staff->m_drawingLines - 1) * 2 - tabDurSym->GetLoc())
* m_doc->GetDrawingUnit(staff->m_drawingStaffSize);
tabDurSym->SetDrawingYRel(-yRel);
}

int x = element->GetDrawingX();
int y = element->GetDrawingY();

Expand Down