From e1c7af464bacd5cd82182573790547a10a5e2e65 Mon Sep 17 00:00:00 2001 From: Laurent Pugin Date: Fri, 27 Dec 2024 16:31:47 +0100 Subject: [PATCH 1/9] Make Verse member of AttPlacementRelStaff --- include/vrv/verse.h | 7 ++++++- src/iomei.cpp | 2 ++ src/verse.cpp | 2 ++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/include/vrv/verse.h b/include/vrv/verse.h index c67711eb1be..514e4a2edb5 100644 --- a/include/vrv/verse.h +++ b/include/vrv/verse.h @@ -20,7 +20,12 @@ class Syl; // Verse //---------------------------------------------------------------------------- -class Verse : public LayerElement, public AttColor, public AttLang, public AttNInteger, public AttTypography { +class Verse : public LayerElement, + public AttColor, + public AttLang, + public AttNInteger, + public AttPlacementRelStaff, + public AttTypography { public: /** * @name Constructors, destructors, and other standard methods diff --git a/src/iomei.cpp b/src/iomei.cpp index a6a4fe2b251..9ed20dc3a30 100644 --- a/src/iomei.cpp +++ b/src/iomei.cpp @@ -2870,6 +2870,7 @@ void MEIOutput::WriteVerse(pugi::xml_node currentNode, Verse *verse) verse->WriteColor(currentNode); verse->WriteLang(currentNode); verse->WriteNInteger(currentNode); + verse->WritePlacementRelStaff(currentNode); verse->WriteTypography(currentNode); } @@ -7163,6 +7164,7 @@ bool MEIInput::ReadVerse(Object *parent, pugi::xml_node verse) vrvVerse->ReadColor(verse); vrvVerse->ReadLang(verse); vrvVerse->ReadNInteger(verse); + vrvVerse->ReadPlacementRelStaff(verse); vrvVerse->ReadTypography(verse); parent->AddChild(vrvVerse); diff --git a/src/verse.cpp b/src/verse.cpp index 66013ee9261..cba1f9d2e9f 100644 --- a/src/verse.cpp +++ b/src/verse.cpp @@ -38,6 +38,7 @@ Verse::Verse() : LayerElement(VERSE, "verse-"), AttColor(), AttLang(), AttNInteg this->RegisterAttClass(ATT_COLOR); this->RegisterAttClass(ATT_LANG); this->RegisterAttClass(ATT_NINTEGER); + this->RegisterAttClass(ATT_PLACEMENTRELSTAFF); this->RegisterAttClass(ATT_TYPOGRAPHY); this->Reset(); @@ -51,6 +52,7 @@ void Verse::Reset() this->ResetColor(); this->ResetLang(); this->ResetNInteger(); + this->ResetPlacementRelStaff(); this->ResetTypography(); m_drawingLabelAbbr = NULL; From aae3bb5b4585f0ce947604f4b59d662deda4e4cb Mon Sep 17 00:00:00 2001 From: Laurent Pugin Date: Fri, 27 Dec 2024 16:48:25 +0100 Subject: [PATCH 2/9] Add support for lyrics above the staff --- include/vrv/syl.h | 4 +- include/vrv/verticalaligner.h | 12 ++++-- include/vrv/view.h | 2 +- src/adjustfloatingpositionerfunctor.cpp | 28 ++++++++---- src/alignfunctor.cpp | 18 +++++--- src/preparedatafunctor.cpp | 3 +- src/syl.cpp | 3 +- src/verticalaligner.cpp | 57 ++++++++++++++++++++----- src/view_control.cpp | 2 +- src/view_element.cpp | 29 ++++++++----- 10 files changed, 113 insertions(+), 45 deletions(-) diff --git a/include/vrv/syl.h b/include/vrv/syl.h index 47d0f654a23..23f4d629708 100644 --- a/include/vrv/syl.h +++ b/include/vrv/syl.h @@ -118,7 +118,9 @@ class Syl : public LayerElement, * The verse number with multiple verses * Value is 1 by default, set in PrepareLyrics */ - int m_drawingVerse; + int m_drawingVerseN; + /** The verse place (below by default) */ + data_STAFFREL m_drawingVersePlace; /** * A pointer to the next syllable of the word. diff --git a/include/vrv/verticalaligner.h b/include/vrv/verticalaligner.h index d5ce55c8644..cdabe209527 100644 --- a/include/vrv/verticalaligner.h +++ b/include/vrv/verticalaligner.h @@ -195,9 +195,12 @@ class StaffAlignment : public Object { * The position is calculated from the bottom. */ ///@{ - void AddVerseN(int verseN); + void AddVerseN(int verseN, data_STAFFREL place); int GetVerseCount(bool collapse) const; - int GetVersePosition(int verseN, bool collapse) const; + int GetVerseCountAbove(bool collapse) const; + int GetVerseCountBelow(bool collapse) const; + int GetVersePositionAbove(int verseN, bool collapse) const; + int GetVersePositionBelow(int verseN, bool collapse) const; ///@} /** @@ -402,9 +405,10 @@ class StaffAlignment : public Object { */ int m_yRel; /** - * Stores the verse@n of the staves attached to the aligner + * Stores the verse@n of the staves attached to the aligner (above and below */ - std::set m_verseNs; + std::set m_verseAboveNs; + std::set m_verseBelowNs; /** * @name values for storing the overflow and overlap diff --git a/include/vrv/view.h b/include/vrv/view.h index 56cdedebeec..a07a9742d27 100644 --- a/include/vrv/view.h +++ b/include/vrv/view.h @@ -624,7 +624,7 @@ class View { std::u32string IntToTimeSigFigures(unsigned short number); std::u32string IntToSmuflFigures(unsigned short number, int offset); int NestedTuplets(Object *object); - int GetSylYRel(int verseN, Staff *staff); + int GetSylYRel(int verseN, Staff *staff, data_STAFFREL place); int GetFYRel(F *f, Staff *staff); ///@} diff --git a/src/adjustfloatingpositionerfunctor.cpp b/src/adjustfloatingpositionerfunctor.cpp index 969ee0fc864..94fd8c7d946 100644 --- a/src/adjustfloatingpositionerfunctor.cpp +++ b/src/adjustfloatingpositionerfunctor.cpp @@ -40,14 +40,26 @@ FunctorCode AdjustFloatingPositionersFunctor::VisitStaffAlignment(StaffAlignment FontInfo *lyricFont = m_doc->GetDrawingLyricFont(staffAlignment->GetStaff()->m_drawingStaffSize); int descender = m_doc->GetTextGlyphDescender(L'q', lyricFont, false); int height = m_doc->GetTextGlyphHeight(L'I', lyricFont, false); - int margin = m_doc->GetBottomMargin(SYL) * drawingUnit; - int minMargin = std::max((int)(m_doc->GetOptions()->m_lyricTopMinMargin.GetValue() * drawingUnit), - staffAlignment->GetOverflowBelow()); - staffAlignment->SetOverflowBelow( - minMargin + staffAlignment->GetVerseCount(verseCollapse) * (height - descender + margin)); - // For now just clear the overflowBelow, which avoids the overlap to be calculated. We could also keep them - // and check if they are some lyrics in order to know if the overlap needs to be calculated or not. - staffAlignment->ClearBBoxesBelow(); + if (staffAlignment->GetVerseCountAbove(verseCollapse)) { + int margin = m_doc->GetTopMargin(SYL) * drawingUnit; + int minMargin = std::max((int)(m_doc->GetOptions()->m_lyricTopMinMargin.GetValue() * drawingUnit), + staffAlignment->GetOverflowAbove()); + staffAlignment->SetOverflowAbove( + minMargin + staffAlignment->GetVerseCountAbove(verseCollapse) * (height - descender + margin)); + // For now just clear the overflowBelow, which avoids the overlap to be calculated. We could also keep + // them and check if they are some lyrics in order to know if the overlap needs to be calculated or not. + staffAlignment->ClearBBoxesAbove(); + } + if (staffAlignment->GetVerseCountBelow(verseCollapse)) { + int margin = m_doc->GetBottomMargin(SYL) * drawingUnit; + int minMargin = std::max((int)(m_doc->GetOptions()->m_lyricTopMinMargin.GetValue() * drawingUnit), + staffAlignment->GetOverflowBelow()); + staffAlignment->SetOverflowBelow( + minMargin + staffAlignment->GetVerseCountBelow(verseCollapse) * (height - descender + margin)); + // For now just clear the overflowBelow, which avoids the overlap to be calculated. We could also keep + // them and check if they are some lyrics in order to know if the overlap needs to be calculated or not. + staffAlignment->ClearBBoxesBelow(); + } } return FUNCTOR_SIBLINGS; } diff --git a/src/alignfunctor.cpp b/src/alignfunctor.cpp index 25aa777e5f5..80c012544a3 100644 --- a/src/alignfunctor.cpp +++ b/src/alignfunctor.cpp @@ -640,9 +640,9 @@ FunctorCode AlignVerticallyFunctor::VisitStaff(Staff *staff) std::vector::const_iterator verseIterator = std::find_if( staff->m_timeSpanningElements.begin(), staff->m_timeSpanningElements.end(), ObjectComparison(VERSE)); if (verseIterator != staff->m_timeSpanningElements.end()) { - Verse *v = vrv_cast(*verseIterator); - assert(v); - alignment->AddVerseN(v->GetN()); + Verse *verse = vrv_cast(*verseIterator); + assert(verse); + alignment->AddVerseN(verse->GetN(), verse->GetPlace()); } // add verse number to alignment in case there are spanning SYL elements but there is no verse number already - this @@ -653,9 +653,13 @@ FunctorCode AlignVerticallyFunctor::VisitStaff(Staff *staff) Verse *verse = vrv_cast((*sylIterator)->GetFirstAncestor(VERSE)); if (verse) { const int verseNumber = verse->GetN(); + const data_STAFFREL versePlace = verse->GetPlace(); const bool verseCollapse = m_doc->GetOptions()->m_lyricVerseCollapse.GetValue(); - if (!alignment->GetVersePosition(verseNumber, verseCollapse)) { - alignment->AddVerseN(verseNumber); + if ((versePlace == STAFFREL_above) && !alignment->GetVersePositionAbove(verseNumber, verseCollapse)) { + alignment->AddVerseN(verseNumber, verse->GetPlace()); + } + if ((versePlace != STAFFREL_above) && !alignment->GetVersePositionBelow(verseNumber, verseCollapse)) { + alignment->AddVerseN(verseNumber, verse->GetPlace()); } } } @@ -685,7 +689,7 @@ FunctorCode AlignVerticallyFunctor::VisitSyllable(Syllable *syllable) StaffAlignment *alignment = m_systemAligner->GetStaffAlignmentForStaffN(m_staffN); if (!alignment) return FUNCTOR_CONTINUE; // Current limitation of only one syl (verse n) by syllable - alignment->AddVerseN(1); + alignment->AddVerseN(1, STAFFREL_below); return FUNCTOR_CONTINUE; } @@ -720,7 +724,7 @@ FunctorCode AlignVerticallyFunctor::VisitVerse(Verse *verse) if (!alignment) return FUNCTOR_CONTINUE; // Add the number count - alignment->AddVerseN(verse->GetN()); + alignment->AddVerseN(verse->GetN(), verse->GetPlace()); return FUNCTOR_CONTINUE; } diff --git a/src/preparedatafunctor.cpp b/src/preparedatafunctor.cpp index 49484e8b06e..636bfecf391 100644 --- a/src/preparedatafunctor.cpp +++ b/src/preparedatafunctor.cpp @@ -1041,7 +1041,8 @@ FunctorCode PrepareLyricsFunctor::VisitSyl(Syl *syl) { Verse *verse = vrv_cast(syl->GetFirstAncestor(VERSE, MAX_NOTE_DEPTH)); if (verse) { - syl->m_drawingVerse = std::max(verse->GetN(), 1); + syl->m_drawingVerseN = std::max(verse->GetN(), 1); + syl->m_drawingVersePlace = verse->GetPlace(); } syl->SetStart(vrv_cast(syl->GetFirstAncestor(NOTE, MAX_NOTE_DEPTH))); diff --git a/src/syl.cpp b/src/syl.cpp index 1e777512dab..03c35caf6fb 100644 --- a/src/syl.cpp +++ b/src/syl.cpp @@ -59,7 +59,8 @@ void Syl::Reset() this->ResetTypography(); this->ResetSylLog(); - m_drawingVerse = 1; + m_drawingVerseN = 1; + m_drawingVersePlace = STAFFREL_below; m_nextWordSyl = NULL; } diff --git a/src/verticalaligner.cpp b/src/verticalaligner.cpp index 2093b5d993a..86cf658fc8b 100644 --- a/src/verticalaligner.cpp +++ b/src/verticalaligner.cpp @@ -314,7 +314,8 @@ FunctorCode SystemAligner::AcceptEnd(ConstFunctor &functor) const StaffAlignment::StaffAlignment() : Object(STAFF_ALIGNMENT) { m_yRel = 0; - m_verseNs.clear(); + m_verseAboveNs.clear(); + m_verseBelowNs.clear(); m_staff = NULL; m_floatingPositionersSorted = true; @@ -436,39 +437,73 @@ void StaffAlignment::SetRequestedSpaceBelow(int space) } } -void StaffAlignment::AddVerseN(int verseN) +void StaffAlignment::AddVerseN(int verseN, data_STAFFREL place) { // if 0, then assume 1; verseN = std::max(verseN, 1); - m_verseNs.insert(verseN); + (place == STAFFREL_above) ? m_verseAboveNs.insert(verseN) : m_verseBelowNs.insert(verseN); } int StaffAlignment::GetVerseCount(bool collapse) const { - if (m_verseNs.empty()) { + return (this->GetVerseCountAbove(collapse) + this->GetVerseCountBelow(collapse)); +} + +int StaffAlignment::GetVerseCountAbove(bool collapse) const +{ + if (m_verseAboveNs.empty()) { + return 0; + } + else if (collapse) { + return (int)m_verseAboveNs.size(); + } + else { + return (*m_verseAboveNs.rbegin()); + } +} + +int StaffAlignment::GetVerseCountBelow(bool collapse) const +{ + if (m_verseBelowNs.empty()) { return 0; } else if (collapse) { - return (int)m_verseNs.size(); + return (int)m_verseBelowNs.size(); + } + else { + return (*m_verseBelowNs.rbegin()); + } +} + +int StaffAlignment::GetVersePositionAbove(int verseN, bool collapse) const +{ + if (m_verseAboveNs.empty()) { + // Syl in neumatic notation - since verse count will be 0, position is -1 + return -1; + } + else if (collapse) { + auto it = std::find(m_verseAboveNs.begin(), m_verseAboveNs.end(), verseN); + int pos = (int)std::distance(m_verseAboveNs.begin(), it); + return pos; } else { - return *m_verseNs.rbegin(); + return verseN - 1; } } -int StaffAlignment::GetVersePosition(int verseN, bool collapse) const +int StaffAlignment::GetVersePositionBelow(int verseN, bool collapse) const { - if (m_verseNs.empty()) { + if (m_verseBelowNs.empty()) { // Syl in neumatic notation - since verse count will be 0, position is -1 return -1; } else if (collapse) { - auto it = std::find(m_verseNs.rbegin(), m_verseNs.rend(), verseN); - int pos = (int)std::distance(m_verseNs.rbegin(), it); + auto it = std::find(m_verseBelowNs.rbegin(), m_verseBelowNs.rend(), verseN); + int pos = (int)std::distance(m_verseBelowNs.rbegin(), it); return pos; } else { - return (*m_verseNs.rbegin()) - verseN; + return (*m_verseBelowNs.rbegin()) - verseN; } } diff --git a/src/view_control.cpp b/src/view_control.cpp index 538acc581cf..b4d0736edb0 100644 --- a/src/view_control.cpp +++ b/src/view_control.cpp @@ -1245,7 +1245,7 @@ void View::DrawSylConnector( assert(syl->GetStart() && syl->GetEnd()); if (!syl->GetStart() || !syl->GetEnd()) return; - const int y = staff->GetDrawingY() + this->GetSylYRel(syl->m_drawingVerse, staff); + const int y = staff->GetDrawingY() + this->GetSylYRel(syl->m_drawingVerseN, staff, syl->m_drawingVersePlace); // Invalid bounding boxes might occur for empty syllables without text child if (!syl->HasContentHorizontalBB()) return; diff --git a/src/view_element.cpp b/src/view_element.cpp index cad7563ea2a..84455a7985e 100644 --- a/src/view_element.cpp +++ b/src/view_element.cpp @@ -1753,7 +1753,7 @@ void View::DrawSyl(DeviceContext *dc, LayerElement *element, Layer *layer, Staff } if (!m_doc->IsFacs() && !m_doc->IsTranscription() && !m_doc->IsNeumeLines()) { - syl->SetDrawingYRel(this->GetSylYRel(syl->m_drawingVerse, staff)); + syl->SetDrawingYRel(this->GetSylYRel(syl->m_drawingVerseN, staff, syl->m_drawingVersePlace)); } dc->StartGraphic(syl, "", syl->GetID()); @@ -1871,7 +1871,7 @@ void View::DrawVerse(DeviceContext *dc, LayerElement *element, Layer *layer, Sta TextDrawingParams params; params.m_x = verse->GetDrawingX() - m_doc->GetDrawingUnit(staff->m_drawingStaffSize); - params.m_y = staff->GetDrawingY() + this->GetSylYRel(std::max(1, verse->GetN()), staff); + params.m_y = staff->GetDrawingY() + this->GetSylYRel(std::max(1, verse->GetN()), staff, verse->GetPlace()); params.m_pointSize = labelTxt.GetPointSize(); dc->SetBrush(m_currentColor, AxSOLID); @@ -2098,22 +2098,31 @@ int View::GetFYRel(F *f, Staff *staff) return y; } -int View::GetSylYRel(int verseN, Staff *staff) +int View::GetSylYRel(int verseN, Staff *staff, data_STAFFREL place) { assert(staff); + StaffAlignment *alignment = staff->GetAlignment(); + if (!alignment) return 0; + const bool verseCollapse = m_options->m_lyricVerseCollapse.GetValue(); int y = 0; - StaffAlignment *alignment = staff->GetAlignment(); - if (alignment) { - FontInfo *lyricFont = m_doc->GetDrawingLyricFont(staff->m_drawingStaffSize); - int descender = -m_doc->GetTextGlyphDescender(L'q', lyricFont, false); - int height = m_doc->GetTextGlyphHeight(L'I', lyricFont, false); - int margin = m_doc->GetBottomMargin(SYL) * m_doc->GetDrawingUnit(staff->m_drawingStaffSize); + FontInfo *lyricFont = m_doc->GetDrawingLyricFont(staff->m_drawingStaffSize); + int descender = -m_doc->GetTextGlyphDescender(L'q', lyricFont, false); + int height = m_doc->GetTextGlyphHeight(L'I', lyricFont, false); + int margin = m_doc->GetBottomMargin(SYL) * m_doc->GetDrawingUnit(staff->m_drawingStaffSize); + + // above the staff + if (place == STAFFREL_above) { + y = alignment->GetOverflowAbove() + - (alignment->GetVersePositionAbove(verseN, verseCollapse)) * (height + descender + margin) - (height); + } + else { y = -alignment->GetStaffHeight() - alignment->GetOverflowBelow() - + alignment->GetVersePosition(verseN, verseCollapse) * (height + descender + margin) + (descender); + + alignment->GetVersePositionBelow(verseN, verseCollapse) * (height + descender + margin) + (descender); } + return y; } From b4d0d07732ec9c7636c6d7a4d0223301e025a07a Mon Sep 17 00:00:00 2001 From: Laurent Pugin Date: Fri, 27 Dec 2024 17:43:39 +0100 Subject: [PATCH 3/9] Add --lyric-height option --- include/vrv/options.h | 1 + src/adjustfloatingpositionerfunctor.cpp | 15 +++++++++------ src/options.cpp | 4 ++++ src/view_element.cpp | 17 +++++++++++++---- 4 files changed, 27 insertions(+), 10 deletions(-) diff --git a/include/vrv/options.h b/include/vrv/options.h index c81516b128b..fd3569203e1 100644 --- a/include/vrv/options.h +++ b/include/vrv/options.h @@ -714,6 +714,7 @@ class Options { OptionDbl m_ledgerLineThickness; OptionDbl m_ledgerLineExtension; OptionIntMap m_lyricElision; + OptionDbl m_lyricHeight; OptionDbl m_lyricLineThickness; OptionBool m_lyricNoStartHyphen; OptionDbl m_lyricSize; diff --git a/src/adjustfloatingpositionerfunctor.cpp b/src/adjustfloatingpositionerfunctor.cpp index 94fd8c7d946..e6b5ac655ed 100644 --- a/src/adjustfloatingpositionerfunctor.cpp +++ b/src/adjustfloatingpositionerfunctor.cpp @@ -34,18 +34,21 @@ FunctorCode AdjustFloatingPositionersFunctor::VisitStaffAlignment(StaffAlignment staffAlignment->SortPositioners(); - const bool verseCollapse = m_doc->GetOptions()->m_lyricVerseCollapse.GetValue(); if (m_classId == SYL) { + const bool verseCollapse = m_doc->GetOptions()->m_lyricVerseCollapse.GetValue(); if (staffAlignment->GetVerseCount(verseCollapse) > 0) { - FontInfo *lyricFont = m_doc->GetDrawingLyricFont(staffAlignment->GetStaff()->m_drawingStaffSize); - int descender = m_doc->GetTextGlyphDescender(L'q', lyricFont, false); - int height = m_doc->GetTextGlyphHeight(L'I', lyricFont, false); + int verseHeight = (int)m_doc->GetOptions()->m_lyricHeight.GetValue() * drawingUnit; + if (verseHeight == 0) { + FontInfo *lyricFont = m_doc->GetDrawingLyricFont(staffAlignment->GetStaff()->m_drawingStaffSize); + verseHeight -= m_doc->GetTextGlyphDescender(L'q', lyricFont, false); + verseHeight += m_doc->GetTextGlyphHeight(L'I', lyricFont, false); + } if (staffAlignment->GetVerseCountAbove(verseCollapse)) { int margin = m_doc->GetTopMargin(SYL) * drawingUnit; int minMargin = std::max((int)(m_doc->GetOptions()->m_lyricTopMinMargin.GetValue() * drawingUnit), staffAlignment->GetOverflowAbove()); staffAlignment->SetOverflowAbove( - minMargin + staffAlignment->GetVerseCountAbove(verseCollapse) * (height - descender + margin)); + minMargin + staffAlignment->GetVerseCountAbove(verseCollapse) * (verseHeight + margin)); // For now just clear the overflowBelow, which avoids the overlap to be calculated. We could also keep // them and check if they are some lyrics in order to know if the overlap needs to be calculated or not. staffAlignment->ClearBBoxesAbove(); @@ -55,7 +58,7 @@ FunctorCode AdjustFloatingPositionersFunctor::VisitStaffAlignment(StaffAlignment int minMargin = std::max((int)(m_doc->GetOptions()->m_lyricTopMinMargin.GetValue() * drawingUnit), staffAlignment->GetOverflowBelow()); staffAlignment->SetOverflowBelow( - minMargin + staffAlignment->GetVerseCountBelow(verseCollapse) * (height - descender + margin)); + minMargin + staffAlignment->GetVerseCountBelow(verseCollapse) * (verseHeight + margin)); // For now just clear the overflowBelow, which avoids the overlap to be calculated. We could also keep // them and check if they are some lyrics in order to know if the overlap needs to be calculated or not. staffAlignment->ClearBBoxesBelow(); diff --git a/src/options.cpp b/src/options.cpp index 1fcbb2c101c..3300e5885d0 100644 --- a/src/options.cpp +++ b/src/options.cpp @@ -1371,6 +1371,10 @@ Options::Options() m_lyricElision.Init(ELISION_regular, &Option::s_elision); this->Register(&m_lyricElision, "lyricElision", &m_generalLayout); + m_lyricHeight.SetInfo("Lyric height", "The lyric verse line height in MEI units (0.0 for the default text height)"); + m_lyricHeight.Init(0.0, 0.0, 20.0); + this->Register(&m_lyricHeight, "lyricHeight", &m_generalLayout); + m_lyricLineThickness.SetInfo("Lyric line thickness", "The lyric extender line thickness"); m_lyricLineThickness.Init(0.25, 0.10, 0.50); this->Register(&m_lyricLineThickness, "lyricLineThickness", &m_generalLayout); diff --git a/src/view_element.cpp b/src/view_element.cpp index 84455a7985e..4323be6c03e 100644 --- a/src/view_element.cpp +++ b/src/view_element.cpp @@ -2105,22 +2105,31 @@ int View::GetSylYRel(int verseN, Staff *staff, data_STAFFREL place) StaffAlignment *alignment = staff->GetAlignment(); if (!alignment) return 0; + const int drawingUnit = m_doc->GetDrawingUnit(staff->m_drawingStaffSize); + const bool verseCollapse = m_options->m_lyricVerseCollapse.GetValue(); int y = 0; FontInfo *lyricFont = m_doc->GetDrawingLyricFont(staff->m_drawingStaffSize); - int descender = -m_doc->GetTextGlyphDescender(L'q', lyricFont, false); - int height = m_doc->GetTextGlyphHeight(L'I', lyricFont, false); + const int descender = m_doc->GetTextGlyphDescender(L'q', lyricFont, false); + const int height = m_doc->GetTextGlyphHeight(L'I', lyricFont, false); + + int verseHeight = (int)m_doc->GetOptions()->m_lyricHeight.GetValue() * drawingUnit; + if (verseHeight == 0) { + verseHeight -= descender; + verseHeight += height; + } + int margin = m_doc->GetBottomMargin(SYL) * m_doc->GetDrawingUnit(staff->m_drawingStaffSize); // above the staff if (place == STAFFREL_above) { y = alignment->GetOverflowAbove() - - (alignment->GetVersePositionAbove(verseN, verseCollapse)) * (height + descender + margin) - (height); + - (alignment->GetVersePositionAbove(verseN, verseCollapse)) * (verseHeight + margin) - (height); } else { y = -alignment->GetStaffHeight() - alignment->GetOverflowBelow() - + alignment->GetVersePositionBelow(verseN, verseCollapse) * (height + descender + margin) + (descender); + + alignment->GetVersePositionBelow(verseN, verseCollapse) * (verseHeight + margin) + verseHeight - height; } return y; From 4cd183c7a789d3495f018826b4ab586a6e2a8ee4 Mon Sep 17 00:00:00 2001 From: Laurent Pugin Date: Mon, 6 Jan 2025 09:40:49 +0100 Subject: [PATCH 4/9] Change --lyric-height to --lyric-height-factor --- include/vrv/options.h | 2 +- src/adjustfloatingpositionerfunctor.cpp | 10 ++++------ src/options.cpp | 6 +++--- src/view_element.cpp | 10 ++-------- 4 files changed, 10 insertions(+), 18 deletions(-) diff --git a/include/vrv/options.h b/include/vrv/options.h index fd3569203e1..7bfb7f0d9fb 100644 --- a/include/vrv/options.h +++ b/include/vrv/options.h @@ -714,7 +714,7 @@ class Options { OptionDbl m_ledgerLineThickness; OptionDbl m_ledgerLineExtension; OptionIntMap m_lyricElision; - OptionDbl m_lyricHeight; + OptionDbl m_lyricHeightFactor; OptionDbl m_lyricLineThickness; OptionBool m_lyricNoStartHyphen; OptionDbl m_lyricSize; diff --git a/src/adjustfloatingpositionerfunctor.cpp b/src/adjustfloatingpositionerfunctor.cpp index e6b5ac655ed..3103958c152 100644 --- a/src/adjustfloatingpositionerfunctor.cpp +++ b/src/adjustfloatingpositionerfunctor.cpp @@ -37,12 +37,10 @@ FunctorCode AdjustFloatingPositionersFunctor::VisitStaffAlignment(StaffAlignment if (m_classId == SYL) { const bool verseCollapse = m_doc->GetOptions()->m_lyricVerseCollapse.GetValue(); if (staffAlignment->GetVerseCount(verseCollapse) > 0) { - int verseHeight = (int)m_doc->GetOptions()->m_lyricHeight.GetValue() * drawingUnit; - if (verseHeight == 0) { - FontInfo *lyricFont = m_doc->GetDrawingLyricFont(staffAlignment->GetStaff()->m_drawingStaffSize); - verseHeight -= m_doc->GetTextGlyphDescender(L'q', lyricFont, false); - verseHeight += m_doc->GetTextGlyphHeight(L'I', lyricFont, false); - } + FontInfo *lyricFont = m_doc->GetDrawingLyricFont(staffAlignment->GetStaff()->m_drawingStaffSize); + int verseHeight = m_doc->GetTextGlyphHeight(L'I', lyricFont, false) + - m_doc->GetTextGlyphDescender(L'q', lyricFont, false); + verseHeight *= m_doc->GetOptions()->m_lyricHeightFactor.GetValue(); if (staffAlignment->GetVerseCountAbove(verseCollapse)) { int margin = m_doc->GetTopMargin(SYL) * drawingUnit; int minMargin = std::max((int)(m_doc->GetOptions()->m_lyricTopMinMargin.GetValue() * drawingUnit), diff --git a/src/options.cpp b/src/options.cpp index 3300e5885d0..6caefe7cd7e 100644 --- a/src/options.cpp +++ b/src/options.cpp @@ -1371,9 +1371,9 @@ Options::Options() m_lyricElision.Init(ELISION_regular, &Option::s_elision); this->Register(&m_lyricElision, "lyricElision", &m_generalLayout); - m_lyricHeight.SetInfo("Lyric height", "The lyric verse line height in MEI units (0.0 for the default text height)"); - m_lyricHeight.Init(0.0, 0.0, 20.0); - this->Register(&m_lyricHeight, "lyricHeight", &m_generalLayout); + m_lyricHeightFactor.SetInfo("Lyric height factor", "The lyric verse line height factor"); + m_lyricHeightFactor.Init(1.0, 1.0, 20.0); + this->Register(&m_lyricHeightFactor, "lyricHeightFactor", &m_generalLayout); m_lyricLineThickness.SetInfo("Lyric line thickness", "The lyric extender line thickness"); m_lyricLineThickness.Init(0.25, 0.10, 0.50); diff --git a/src/view_element.cpp b/src/view_element.cpp index 4323be6c03e..e96180b7690 100644 --- a/src/view_element.cpp +++ b/src/view_element.cpp @@ -2105,8 +2105,6 @@ int View::GetSylYRel(int verseN, Staff *staff, data_STAFFREL place) StaffAlignment *alignment = staff->GetAlignment(); if (!alignment) return 0; - const int drawingUnit = m_doc->GetDrawingUnit(staff->m_drawingStaffSize); - const bool verseCollapse = m_options->m_lyricVerseCollapse.GetValue(); int y = 0; @@ -2114,12 +2112,8 @@ int View::GetSylYRel(int verseN, Staff *staff, data_STAFFREL place) const int descender = m_doc->GetTextGlyphDescender(L'q', lyricFont, false); const int height = m_doc->GetTextGlyphHeight(L'I', lyricFont, false); - int verseHeight = (int)m_doc->GetOptions()->m_lyricHeight.GetValue() * drawingUnit; - if (verseHeight == 0) { - verseHeight -= descender; - verseHeight += height; - } - + int verseHeight = height - descender; + verseHeight *= m_doc->GetOptions()->m_lyricHeightFactor.GetValue(); int margin = m_doc->GetBottomMargin(SYL) * m_doc->GetDrawingUnit(staff->m_drawingStaffSize); // above the staff From 87b521ce5c086daac3643000f60678599a144874 Mon Sep 17 00:00:00 2001 From: Laurent Pugin Date: Mon, 6 Jan 2025 10:18:24 +0100 Subject: [PATCH 5/9] Update src/adjustfloatingpositionerfunctor.cpp Co-authored-by: Andrew Hankinson --- src/adjustfloatingpositionerfunctor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/adjustfloatingpositionerfunctor.cpp b/src/adjustfloatingpositionerfunctor.cpp index 3103958c152..7e80ebe97f9 100644 --- a/src/adjustfloatingpositionerfunctor.cpp +++ b/src/adjustfloatingpositionerfunctor.cpp @@ -58,7 +58,7 @@ FunctorCode AdjustFloatingPositionersFunctor::VisitStaffAlignment(StaffAlignment staffAlignment->SetOverflowBelow( minMargin + staffAlignment->GetVerseCountBelow(verseCollapse) * (verseHeight + margin)); // For now just clear the overflowBelow, which avoids the overlap to be calculated. We could also keep - // them and check if they are some lyrics in order to know if the overlap needs to be calculated or not. + // them and check if there are some lyrics in order to know if the overlap needs to be calculated or not. staffAlignment->ClearBBoxesBelow(); } } From 7dea4400596ca4f0e53a25e73e741bba104b75f6 Mon Sep 17 00:00:00 2001 From: Laurent Pugin Date: Mon, 6 Jan 2025 10:18:34 +0100 Subject: [PATCH 6/9] Update include/vrv/verticalaligner.h Co-authored-by: Andrew Hankinson --- include/vrv/verticalaligner.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/vrv/verticalaligner.h b/include/vrv/verticalaligner.h index cdabe209527..8b09af337c7 100644 --- a/include/vrv/verticalaligner.h +++ b/include/vrv/verticalaligner.h @@ -405,7 +405,7 @@ class StaffAlignment : public Object { */ int m_yRel; /** - * Stores the verse@n of the staves attached to the aligner (above and below + * Stores the verse@n of the staves attached to the aligner (above and below) */ std::set m_verseAboveNs; std::set m_verseBelowNs; From 7bafbe8f11b1e9671fbef40ef932dedfe74f0017 Mon Sep 17 00:00:00 2001 From: Laurent Pugin Date: Mon, 6 Jan 2025 10:23:27 +0100 Subject: [PATCH 7/9] Remove duplicating if statement --- src/alignfunctor.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/alignfunctor.cpp b/src/alignfunctor.cpp index 80c012544a3..a87df5f8afa 100644 --- a/src/alignfunctor.cpp +++ b/src/alignfunctor.cpp @@ -655,11 +655,8 @@ FunctorCode AlignVerticallyFunctor::VisitStaff(Staff *staff) const int verseNumber = verse->GetN(); const data_STAFFREL versePlace = verse->GetPlace(); const bool verseCollapse = m_doc->GetOptions()->m_lyricVerseCollapse.GetValue(); - if ((versePlace == STAFFREL_above) && !alignment->GetVersePositionAbove(verseNumber, verseCollapse)) { - alignment->AddVerseN(verseNumber, verse->GetPlace()); - } - if ((versePlace != STAFFREL_above) && !alignment->GetVersePositionBelow(verseNumber, verseCollapse)) { - alignment->AddVerseN(verseNumber, verse->GetPlace()); + if (!alignment->GetVersePositionAbove(verseNumber, verseCollapse)) { + alignment->AddVerseN(verseNumber, versePlace); } } } From b0eafded74b512b95d16f8e908b85409da7db56e Mon Sep 17 00:00:00 2001 From: Laurent Pugin Date: Mon, 6 Jan 2025 10:28:41 +0100 Subject: [PATCH 8/9] Fix formatting --- src/adjustfloatingpositionerfunctor.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/adjustfloatingpositionerfunctor.cpp b/src/adjustfloatingpositionerfunctor.cpp index 7e80ebe97f9..2afc2983b6d 100644 --- a/src/adjustfloatingpositionerfunctor.cpp +++ b/src/adjustfloatingpositionerfunctor.cpp @@ -58,7 +58,8 @@ FunctorCode AdjustFloatingPositionersFunctor::VisitStaffAlignment(StaffAlignment staffAlignment->SetOverflowBelow( minMargin + staffAlignment->GetVerseCountBelow(verseCollapse) * (verseHeight + margin)); // For now just clear the overflowBelow, which avoids the overlap to be calculated. We could also keep - // them and check if there are some lyrics in order to know if the overlap needs to be calculated or not. + // them and check if there are some lyrics in order to know if the overlap needs to be calculated or + // not. staffAlignment->ClearBBoxesBelow(); } } From 8ed9ef4b3ca9150cbf595b10bf49ca87bfe8f7b1 Mon Sep 17 00:00:00 2001 From: Laurent Pugin Date: Mon, 6 Jan 2025 12:56:03 +0100 Subject: [PATCH 9/9] Revert "Remove duplicating if statement" This reverts commit 7bafbe8f11b1e9671fbef40ef932dedfe74f0017. --- src/alignfunctor.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/alignfunctor.cpp b/src/alignfunctor.cpp index a87df5f8afa..80c012544a3 100644 --- a/src/alignfunctor.cpp +++ b/src/alignfunctor.cpp @@ -655,8 +655,11 @@ FunctorCode AlignVerticallyFunctor::VisitStaff(Staff *staff) const int verseNumber = verse->GetN(); const data_STAFFREL versePlace = verse->GetPlace(); const bool verseCollapse = m_doc->GetOptions()->m_lyricVerseCollapse.GetValue(); - if (!alignment->GetVersePositionAbove(verseNumber, verseCollapse)) { - alignment->AddVerseN(verseNumber, versePlace); + if ((versePlace == STAFFREL_above) && !alignment->GetVersePositionAbove(verseNumber, verseCollapse)) { + alignment->AddVerseN(verseNumber, verse->GetPlace()); + } + if ((versePlace != STAFFREL_above) && !alignment->GetVersePositionBelow(verseNumber, verseCollapse)) { + alignment->AddVerseN(verseNumber, verse->GetPlace()); } } }