From 4a33d434b1136d74f4275db4ecc9912ceb88a307 Mon Sep 17 00:00:00 2001 From: Yinan Zhou Date: Thu, 21 Mar 2024 11:17:29 -0400 Subject: [PATCH] Refactor DrawCustos and Drag for custos --- include/vrv/editortoolkit_neume.h | 1 + src/editortoolkit_neume.cpp | 113 +++++++++++++++++++++++++----- src/view_element.cpp | 37 +--------- 3 files changed, 99 insertions(+), 52 deletions(-) diff --git a/include/vrv/editortoolkit_neume.h b/include/vrv/editortoolkit_neume.h index 5fcd380f836..049dffe7ebe 100644 --- a/include/vrv/editortoolkit_neume.h +++ b/include/vrv/editortoolkit_neume.h @@ -102,6 +102,7 @@ class EditorToolkitNeume : public EditorToolkit { ///@{ bool AdjustPitchFromPosition(Object *obj, Clef *clef = NULL); bool AdjustClefLineFromPosition(Clef *clef, Staff *staff = NULL); + bool AlignPositionFromPitch(Object *obj, Clef *clef = NULL); ///@} }; diff --git a/src/editortoolkit_neume.cpp b/src/editortoolkit_neume.cpp index e123883be09..97847be2121 100644 --- a/src/editortoolkit_neume.cpp +++ b/src/editortoolkit_neume.cpp @@ -518,8 +518,9 @@ bool EditorToolkitNeume::Drag(std::string elementId, int x, int y) assert(zone); zone->ShiftByXY(x, -y); - AdjustPitchFromPosition(element); ChangeStaff(elementId); + AdjustPitchFromPosition(element); + AlignPositionFromPitch(element); } else if (element->HasInterface(INTERFACE_PITCH) || element->Is(NEUME) || element->Is(SYLLABLE)) { Layer *layer = dynamic_cast(element->GetFirstAncestor(LAYER)); @@ -738,6 +739,11 @@ bool EditorToolkitNeume::Drag(std::string elementId, int x, int y) } Layer *layer = vrv_cast(element->GetFirstAncestor(LAYER)); layer->ReorderByXPos(); // Reflect position order of elements internally (and in the resulting output file) + + if (m_doc->IsTranscription() && m_doc->HasFacsimile()) { + m_doc->SyncFromFacsimileDoc(); + } + m_editInfo.import("status", status); m_editInfo.import("message", message); return true; @@ -4068,6 +4074,7 @@ bool EditorToolkitNeume::AdjustPitchFromPosition(Object *obj, Clef *clef) return false; } PitchInterface *pi = custos->GetPitchInterface(); + assert(pi); FacsimileInterface *fi = custos->GetFacsimileInterface(); // Check for facsimile @@ -4089,32 +4096,34 @@ bool EditorToolkitNeume::AdjustPitchFromPosition(Object *obj, Clef *clef) assert(clef); // Reset pitch to be "on clef" - if (clef->GetShape() == CLEFSHAPE_C) { - pi->SetPname(PITCHNAME_c); - } - else if (clef->GetShape() == CLEFSHAPE_F) { - pi->SetPname(PITCHNAME_f); - } - else if (clef->GetShape() == CLEFSHAPE_G) { - pi->SetPname(PITCHNAME_g); + switch (clef->GetShape()) { + case CLEFSHAPE_C: pi->SetPname(PITCHNAME_c); break; + case CLEFSHAPE_F: pi->SetPname(PITCHNAME_f); break; + case CLEFSHAPE_G: pi->SetPname(PITCHNAME_g); break; + default: + LogError("Clef %s does not have valid shape. Shape is %s", clef->GetID().c_str(), clef->GetShape()); + return false; } - else { - LogError("Clef %s does not have valid shape. Shape is %s", clef->GetID().c_str(), clef->GetShape()); - return false; + + int octave = 3; + if (clef->GetDis() && clef->GetDisPlace()) { + octave += (clef->GetDisPlace() == STAFFREL_basic_above ? 1 : -1) * (clef->GetDis() / 7); } - pi->SetOct(3); + pi->SetOct(octave); const int staffSize = m_doc->GetDrawingUnit(staff->m_drawingStaffSize); // Use the same pitchDifference equation for both syllables and custos const int pitchDifference - = round((double)(staff->GetDrawingY() + (2 * staffSize * (staff->m_drawingLines - clef->GetLine())) - - fi->GetZone()->GetUly() - - ((fi->GetZone()->GetUlx() - staff->GetZone()->GetUlx()) - * tan(-staff->GetDrawingRotate() * M_PI / 180.0))) + = round((double)(m_view->ToLogicalY(fi->GetZone()->GetUly()) - staff->GetDrawingY() + - (2 * staffSize * (staff->m_drawingLines - clef->GetLine())) + + staff->GetDrawingRotationOffsetFor(m_view->ToLogicalX(fi->GetZone()->GetUlx()))) / (double)(staffSize)); + LogError("pitch diff %d", pitchDifference); + LogError("before %d", pi->GetPname()); pi->AdjustPitchByOffset(pitchDifference); + LogError("after %d", pi->GetPname()); return true; } @@ -4218,4 +4227,74 @@ bool EditorToolkitNeume::AdjustClefLineFromPosition(Clef *clef, Staff *staff) return true; } +bool EditorToolkitNeume::AlignPositionFromPitch(Object *obj, Clef *clef) +{ + if (obj->Is(CUSTOS)) { + Custos *custos = dynamic_cast(obj); + Staff *staff = custos->GetAncestorStaff(); + + // Check interfaces + if ((custos->GetPitchInterface() == NULL) || (custos->GetFacsimileInterface() == NULL)) { + LogError("Element is lacking an interface which is required for pitch adjusting"); + return false; + } + PitchInterface *pi = custos->GetPitchInterface(); + assert(pi); + FacsimileInterface *fi = custos->GetFacsimileInterface(); + + // Check for facsimile + if (!fi->HasFacs() || !staff->HasFacs()) { + LogError("Could not adjust pitch: the element or staff lacks facsimile data"); + return false; + } + Zone *zone = fi->GetZone(); + assert(zone); + + int x = zone->GetUlx(); + int y = zone->GetUly(); + + if (clef == NULL) { + ClassIdComparison ac(CLEF); + clef = dynamic_cast(m_doc->GetDrawingPage()->FindPreviousChild(&ac, obj)); + if (clef == NULL) { + Layer *layer = vrv_cast(staff->FindDescendantByType(LAYER)); + assert(layer); + clef = layer->GetCurrentClef(); + } + } + assert(clef); + + data_PITCHNAME pname; + switch (clef->GetShape()) { + case CLEFSHAPE_C: pname = PITCHNAME_c; break; + case CLEFSHAPE_F: pname = PITCHNAME_f; break; + case CLEFSHAPE_G: pname = PITCHNAME_g; break; + default: + LogError("Clef %s does not have valid shape. Shape is %s", clef->GetID().c_str(), clef->GetShape()); + return false; + } + pi->SetPname(pname); + + int octave = 3; + if (clef->GetDis() && clef->GetDisPlace()) { + octave += (clef->GetDisPlace() == STAFFREL_basic_above ? 1 : -1) * (clef->GetDis() / 7); + } + pi->SetOct(octave); + + // Convert from lines & spaces from bottom to from top + int CClefOffsetFromTop = ((staff->m_drawingLines - 1) * 2) - clef->GetClefLocOffset(); + int custosOffsetFromTop = CClefOffsetFromTop + pi->PitchDifferenceTo(custos); + y += custosOffsetFromTop * m_doc->GetDrawingUnit(staff->m_drawingStaffSize); + + const int noteHeight = (int)(m_doc->GetDrawingDoubleUnit(staff->m_drawingStaffSize) / 2); + const int noteWidth = (int)(m_doc->GetDrawingDoubleUnit(staff->m_drawingStaffSize) / 1.4); + + zone->SetUly(y); + zone->SetLrx(x + noteWidth); + zone->SetLry(y - noteHeight); + + return true; + } +} + } // namespace vrv diff --git a/src/view_element.cpp b/src/view_element.cpp index bd7b0ee9879..f9e13cce2a6 100644 --- a/src/view_element.cpp +++ b/src/view_element.cpp @@ -761,24 +761,7 @@ void View::DrawCustos(DeviceContext *dc, LayerElement *element, Layer *layer, St // For neume notation we ignore the value set in CalcAlignmentPitchPosFunctor if (staff->m_drawingNotationType == NOTATIONTYPE_neume) { x = custos->GetDrawingX(); - // Recalculate y from pitch to prevent visual/meaning mismatch - Clef *clef = layer->GetClef(element); - y = staff->GetDrawingY(); - PitchInterface pi; - // Neume notation uses C3 for C clef rather than C4. - // Take this into account when determining location. - // However this doesn't affect the value for F clef. - pi.SetPname(PITCHNAME_c); - if (clef->GetShape() == CLEFSHAPE_C) { - pi.SetOct(3); - } - else { - pi.SetOct(4); - } - // Convert from lines & spaces from bottom to from top - int CClefOffsetFromTop = ((staff->m_drawingLines - 1) * 2) - clef->GetClefLocOffset(); - int custosOffsetFromTop = CClefOffsetFromTop + pi.PitchDifferenceTo(custos); - y -= custosOffsetFromTop * m_doc->GetDrawingUnit(staff->m_drawingStaffSize); + y = custos->GetDrawingY(); } else { x = element->GetDrawingX(); @@ -788,28 +771,12 @@ void View::DrawCustos(DeviceContext *dc, LayerElement *element, Layer *layer, St y -= m_doc->GetDrawingUnit(staff->m_drawingStaffSize); } - if (m_doc->IsFacs() && (staff->GetDrawingRotate() != 0)) { - double deg = staff->GetDrawingRotate(); - int xDiff = x - staff->GetDrawingX(); - y -= int(xDiff * tan(deg * M_PI / 180.0)); - } - else if (staff->HasDrawingRotation()) { + if (staff->HasDrawingRotation()) { y -= staff->GetDrawingRotationOffsetFor(x); } this->DrawSmuflCode(dc, x, y, sym, staff->m_drawingStaffSize, false, true); - if (m_doc->IsFacs() && element->HasFacs()) { - const int noteHeight = (int)(m_doc->GetDrawingDoubleUnit(staff->m_drawingStaffSize) / 2); - const int noteWidth = (int)(m_doc->GetDrawingDoubleUnit(staff->m_drawingStaffSize) / 1.4); - - FacsimileInterface *fi = element->GetFacsimileInterface(); - fi->GetZone()->SetUlx(x); - fi->GetZone()->SetUly(ToDeviceContextY(y)); - fi->GetZone()->SetLrx(x + noteWidth); - fi->GetZone()->SetLry(ToDeviceContextY(y - noteHeight)); - } - /************ Draw children (accidentals, etc) ************/ // Drawing the children should be done before ending the graphic. Otherwise the SVG tree will not match the MEI one this->DrawLayerChildren(dc, custos, layer, staff, measure);