Skip to content

Commit

Permalink
Merge pull request #3725 from rism-digital/develop-nc-refactoring
Browse files Browse the repository at this point in the history
Refactoring of the Nc drawing code into a data preparation functor
  • Loading branch information
lpugin authored Jul 3, 2024
2 parents 28145c1 + 6d300db commit 4cc080c
Show file tree
Hide file tree
Showing 10 changed files with 196 additions and 175 deletions.
4 changes: 3 additions & 1 deletion include/vrv/adjustneumexfunctor.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,10 @@ class AdjustNeumeXFunctor : public DocFunctor {
public:
//
private:
/** The minimu position of the next syl */
/** The minimum position of the next syl */
int m_minPos;
/** The minimum position of the next neume */
int m_neumeMinPos;
};

} // namespace vrv
Expand Down
1 change: 1 addition & 0 deletions include/vrv/calcligatureorneumeposfunctor.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ class CalcLigatureOrNeumePosFunctor : public DocFunctor {
*/
///@{
FunctorCode VisitLigature(Ligature *ligature) override;
FunctorCode VisitNeume(Neume *neume) override;
///@}

protected:
Expand Down
18 changes: 18 additions & 0 deletions include/vrv/nc.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,25 @@ class Nc : public LayerElement,
FunctorCode AcceptEnd(ConstFunctor &functor) const override;
///@}

/**
* A Structure holding a glyph paramter for the nc.
* One single nc might need more than one glyph (e.g., liquescent).
* Set in CalcLigatureOrNeumePosFunctor::VisitNeume
*/
struct DrawingGlyph {
wchar_t m_fontNo = 0;
float m_xOffset = 0.0;
float m_yOffset = 0.0;
};

private:
//
public:
/** Drawing glyphs */
std::vector<DrawingGlyph> m_drawingGlyphs;

private:
//
};

} // namespace vrv
Expand Down
1 change: 1 addition & 0 deletions include/vrv/resetfunctor.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ class ResetDataFunctor : public Functor {
FunctorCode VisitMeasure(Measure *measure) override;
FunctorCode VisitMRest(MRest *mRest) override;
FunctorCode VisitNote(Note *note) override;
FunctorCode VisitNc(Nc *nc) override;
FunctorCode VisitObject(Object *object) override;
FunctorCode VisitRepeatMark(RepeatMark *repeatMark) override;
FunctorCode VisitRest(Rest *rest) override;
Expand Down
1 change: 1 addition & 0 deletions include/vrv/view.h
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,7 @@ class View {
*/
///@{
void DrawNcAsNotehead(DeviceContext *dc, Nc *nc, Layer *layer, Staff *staff, Measure *measure);
void DrawNcGlyphs(DeviceContext *dc, Nc *nc, Staff *staff);
///@}

/**
Expand Down
20 changes: 20 additions & 0 deletions src/adjustneumexfunctor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

#include "doc.h"
#include "layer.h"
#include "neume.h"
#include "score.h"
#include "staff.h"
#include "syl.h"
Expand Down Expand Up @@ -54,6 +55,22 @@ FunctorCode AdjustNeumeXFunctor::VisitLayerEnd(Layer *layer)

FunctorCode AdjustNeumeXFunctor::VisitNeume(Neume *neume)
{
// It is 0 when we process the first neume of the syllable
if (m_neumeMinPos != VRV_UNSET) {
Alignment *alignment = neume->GetAlignment();

int selfLeft = neume->GetContentLeft();
if (selfLeft < m_neumeMinPos) {
const int adjust = m_neumeMinPos - selfLeft;
alignment->SetXRel(alignment->GetXRel() + adjust);
}
}

m_neumeMinPos = neume->GetContentRight() + m_doc->GetDrawingUnit(100);

// Check if the neume takes more space the the syllable text
if (m_neumeMinPos > m_minPos) m_minPos = m_neumeMinPos;

return FUNCTOR_CONTINUE;
}

Expand All @@ -68,6 +85,9 @@ FunctorCode AdjustNeumeXFunctor::VisitSyl(Syl *syl)
{
Alignment *alignment = syl->GetAlignment();

// Indicates that the neume will be the first of the syllable
m_neumeMinPos = VRV_UNSET;

int selfLeft = syl->GetContentLeft();
if (selfLeft < m_minPos) {
const int adjust = m_minPos - selfLeft;
Expand Down
2 changes: 1 addition & 1 deletion src/alignfunctor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -394,7 +394,7 @@ FunctorCode AlignHorizontallyFunctor::VisitMeasureEnd(Measure *measure)

if (m_hasMultipleLayer) measure->HasAlignmentRefWithMultipleLayers(true);

// measure->m_measureAligner.LogDebugTree(3);
measure->m_measureAligner.LogDebugTree(3);

return FUNCTOR_CONTINUE;
}
Expand Down
126 changes: 126 additions & 0 deletions src/calcligatureorneumeposfunctor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@

#include "doc.h"
#include "ligature.h"
#include "nc.h"
#include "neume.h"
#include "staff.h"

//----------------------------------------------------------------------------
Expand Down Expand Up @@ -223,4 +225,128 @@ FunctorCode CalcLigatureOrNeumePosFunctor::VisitLigature(Ligature *ligature)
return FUNCTOR_SIBLINGS;
}

FunctorCode CalcLigatureOrNeumePosFunctor::VisitNeume(Neume *neume)
{
if (m_doc->GetOptions()->m_neumeAsNote.GetValue()) return FUNCTOR_SIBLINGS;

ListOfObjects ncs = neume->FindAllDescendantsByType(NC);

int xRel = 0;

for (Object *object : ncs) {

Nc *nc = vrv_cast<Nc *>(object);
assert(nc);

const bool hasLiquescent = (nc->FindDescendantByType(LIQUESCENT));
const bool hasOriscus = (nc->FindDescendantByType(ORISCUS));
const bool hasQuilisma = (nc->FindDescendantByType(QUILISMA));

// Make sure we have at least one glyph
nc->m_drawingGlyphs.resize(1);

if (hasLiquescent) {
nc->m_drawingGlyphs.resize(3);
if (nc->GetCurve() == curvatureDirection_CURVE_c) {
nc->m_drawingGlyphs[0].m_fontNo = SMUFL_E995_chantAuctumDesc;
nc->m_drawingGlyphs[1].m_fontNo = SMUFL_E9BE_chantConnectingLineAsc3rd;
nc->m_drawingGlyphs[2].m_fontNo = SMUFL_E9BE_chantConnectingLineAsc3rd;
nc->m_drawingGlyphs[2].m_xOffset = 0.8;
nc->m_drawingGlyphs[1].m_yOffset = -1.5;
nc->m_drawingGlyphs[2].m_yOffset = -1.75;
}
else if (nc->GetCurve() == curvatureDirection_CURVE_a) {
nc->m_drawingGlyphs[0].m_fontNo = SMUFL_E994_chantAuctumAsc;
nc->m_drawingGlyphs[1].m_fontNo = SMUFL_E9BE_chantConnectingLineAsc3rd;
nc->m_drawingGlyphs[2].m_fontNo = SMUFL_E9BE_chantConnectingLineAsc3rd;
nc->m_drawingGlyphs[2].m_xOffset = 0.8;
nc->m_drawingGlyphs[1].m_yOffset = 0.5;
nc->m_drawingGlyphs[2].m_yOffset = 0.75;
}
else {
nc->m_drawingGlyphs[0].m_fontNo = SMUFL_E9A1_chantPunctumDeminutum;
}
}
else if (hasOriscus) {
nc->m_drawingGlyphs[0].m_fontNo = SMUFL_EA2A_medRenOriscusCMN;
}
else if (hasQuilisma) {
nc->m_drawingGlyphs[0].m_fontNo = SMUFL_E99B_chantQuilisma;
}
else {
nc->m_drawingGlyphs[0].m_fontNo = SMUFL_E990_chantPunctum;

Neume *neume = vrv_cast<Neume *>(nc->GetFirstAncestor(NEUME));
assert(neume);
int position = neume->GetChildIndex(nc);

// Check if nc is part of a ligature or is an inclinatum
if (nc->HasTilt() && nc->GetTilt() == COMPASSDIRECTION_se) {
nc->m_drawingGlyphs[0].m_fontNo = SMUFL_E991_chantPunctumInclinatum;
}
else if (nc->GetLigated() == BOOLEAN_true) {
int pitchDifference = 0;
bool isFirst;
int ligCount = neume->GetLigatureCount(position);

if (ligCount % 2 == 0) {
isFirst = false;
Nc *lastNc = dynamic_cast<Nc *>(neume->GetChild(position > 0 ? position - 1 : 0));
assert(lastNc);
pitchDifference = nc->PitchDifferenceTo(lastNc);
nc->m_drawingGlyphs[0].m_yOffset = -pitchDifference;
}
else {
isFirst = true;
Object *nextSibling = neume->GetChild(position + 1);
if (nextSibling != NULL) {
Nc *nextNc = dynamic_cast<Nc *>(nextSibling);
assert(nextNc);
pitchDifference = nextNc->PitchDifferenceTo(nc);
nc->m_drawingGlyphs[0].m_yOffset = pitchDifference;
}
}

// set the glyph
switch (pitchDifference) {
case -1:
nc->m_drawingGlyphs[0].m_fontNo
= isFirst ? SMUFL_E9B4_chantEntryLineAsc2nd : SMUFL_E9B9_chantLigaturaDesc2nd;
break;
case -2:
nc->m_drawingGlyphs[0].m_fontNo
= isFirst ? SMUFL_E9B5_chantEntryLineAsc3rd : SMUFL_E9BA_chantLigaturaDesc3rd;
break;
case -3:
nc->m_drawingGlyphs[0].m_fontNo
= isFirst ? SMUFL_E9B6_chantEntryLineAsc4th : SMUFL_E9BB_chantLigaturaDesc4th;
break;
case -4:
nc->m_drawingGlyphs[0].m_fontNo
= isFirst ? SMUFL_E9B7_chantEntryLineAsc5th : SMUFL_E9BC_chantLigaturaDesc5th;
break;
default: break;
}
}

// If the nc is supposed to be a virga and currently is being rendered as a punctum
// change it to a virga
if (nc->GetTilt() == COMPASSDIRECTION_s && nc->m_drawingGlyphs[0].m_fontNo == SMUFL_E990_chantPunctum) {
nc->m_drawingGlyphs[0].m_fontNo = SMUFL_E996_chantPunctumVirga;
}

else if (nc->GetTilt() == COMPASSDIRECTION_n
&& nc->m_drawingGlyphs[0].m_fontNo == SMUFL_E990_chantPunctum) {
nc->m_drawingGlyphs[0].m_fontNo = SMUFL_E997_chantPunctumVirgaReversed;
}
}

nc->SetDrawingXRel(xRel);
// The first glyph set the spacing
xRel += m_doc->GetGlyphWidth(nc->m_drawingGlyphs[0].m_fontNo, 100, false);
}

return FUNCTOR_SIBLINGS;
}

} // namespace vrv
13 changes: 13 additions & 0 deletions src/resetfunctor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "layer.h"
#include "ligature.h"
#include "mrest.h"
#include "nc.h"
#include "octave.h"
#include "page.h"
#include "repeatmark.h"
Expand Down Expand Up @@ -343,6 +344,18 @@ FunctorCode ResetDataFunctor::VisitNote(Note *note)
return FUNCTOR_CONTINUE;
}

FunctorCode ResetDataFunctor::VisitNc(Nc *nc)
{
// Call parent one too
this->VisitLayerElement(nc);

nc->m_drawingGlyphs.clear();

// We want the list of the ObjectListInterface to be regenerated
nc->Modify();
return FUNCTOR_CONTINUE;
}

FunctorCode ResetDataFunctor::VisitObject(Object *object)
{
return FUNCTOR_CONTINUE;
Expand Down
Loading

0 comments on commit 4cc080c

Please sign in to comment.