From ec3865a0db9b790548dae95fbc632a32dda0dbc6 Mon Sep 17 00:00:00 2001 From: Laurent Pugin Date: Fri, 21 Feb 2025 11:48:12 +0100 Subject: [PATCH 1/8] Add method to draw bent parallelograms --- include/vrv/bboxdevicecontext.h | 1 + include/vrv/devicecontext.h | 1 + include/vrv/svgdevicecontext.h | 1 + src/bboxdevicecontext.cpp | 5 +++++ src/svgdevicecontext.cpp | 18 ++++++++++++++++++ 5 files changed, 26 insertions(+) diff --git a/include/vrv/bboxdevicecontext.h b/include/vrv/bboxdevicecontext.h index 9f0b369ba4..0ea40b19f6 100644 --- a/include/vrv/bboxdevicecontext.h +++ b/include/vrv/bboxdevicecontext.h @@ -72,6 +72,7 @@ class BBoxDeviceContext : public DeviceContext { void DrawQuadBezierPath(Point bezier[3]) override; void DrawCubicBezierPath(Point bezier[4]) override; void DrawCubicBezierPathFilled(Point bezier1[4], Point bezier2[4]) override; + void DrawBentParallelogramFilled(Point side1[3], Point side2[3]) override; void DrawCircle(int x, int y, int radius) override; void DrawEllipse(int x, int y, int width, int height) override; void DrawEllipticArc(int x, int y, int width, int height, double start, double end) override; diff --git a/include/vrv/devicecontext.h b/include/vrv/devicecontext.h index 565e32fb82..20f8eb4e1b 100644 --- a/include/vrv/devicecontext.h +++ b/include/vrv/devicecontext.h @@ -193,6 +193,7 @@ class DeviceContext { virtual void DrawQuadBezierPath(Point bezier[3]) = 0; virtual void DrawCubicBezierPath(Point bezier[4]) = 0; virtual void DrawCubicBezierPathFilled(Point bezier1[4], Point bezier2[4]) = 0; + virtual void DrawBentParallelogramFilled(Point side1[3], Point side2[3]) = 0; virtual void DrawCircle(int x, int y, int radius) = 0; virtual void DrawEllipse(int x, int y, int width, int height) = 0; virtual void DrawEllipticArc(int x, int y, int width, int height, double start, double end) = 0; diff --git a/include/vrv/svgdevicecontext.h b/include/vrv/svgdevicecontext.h index 80746b5fba..3d04637493 100644 --- a/include/vrv/svgdevicecontext.h +++ b/include/vrv/svgdevicecontext.h @@ -78,6 +78,7 @@ class SvgDeviceContext : public DeviceContext { void DrawQuadBezierPath(Point bezier[3]) override; void DrawCubicBezierPath(Point bezier[4]) override; void DrawCubicBezierPathFilled(Point bezier1[4], Point bezier2[4]) override; + void DrawBentParallelogramFilled(Point side1[3], Point side2[3]) override; void DrawCircle(int x, int y, int radius) override; void DrawEllipse(int x, int y, int width, int height) override; void DrawEllipticArc(int x, int y, int width, int height, double start, double end) override; diff --git a/src/bboxdevicecontext.cpp b/src/bboxdevicecontext.cpp index 3a444bd647..60ed2a96ae 100644 --- a/src/bboxdevicecontext.cpp +++ b/src/bboxdevicecontext.cpp @@ -169,6 +169,11 @@ void BBoxDeviceContext::DrawCubicBezierPathFilled(Point bezier1[4], Point bezier this->UpdateBB(pos.x, pos.y, pos.x + width, pos.y + height); } +void BBoxDeviceContext::DrawBentParallelogramFilled(Point side1[3], Point side2[3]) +{ + this->UpdateBB(side1[0].x, side1[0].y, side2[2].x, side2[2].y); +} + void BBoxDeviceContext::DrawCircle(int x, int y, int radius) { this->DrawEllipse(x - radius, y - radius, 2 * radius, 2 * radius); diff --git a/src/svgdevicecontext.cpp b/src/svgdevicecontext.cpp index bfb70d389e..bbd5f9523e 100644 --- a/src/svgdevicecontext.cpp +++ b/src/svgdevicecontext.cpp @@ -693,6 +693,24 @@ void SvgDeviceContext::DrawCubicBezierPathFilled(Point bezier1[4], Point bezier2 pathChild.append_attribute("stroke-width") = m_penStack.top().GetWidth(); } +void SvgDeviceContext::DrawBentParallelogramFilled(Point side1[3], Point side2[3]) +{ + pugi::xml_node pathChild = AddChild("path"); + pathChild.append_attribute("d") + = StringFormat("M%d,%d Q%d,%d %d,%d L%d,%d Q%d,%d %d,%d Z", side1[0].x, side1[0].y, // M command + side1[1].x, side1[1].y, side1[2].x, side1[2].y, side2[2].x, side2[2].y, side2[1].x, side2[1].y, side2[0].x, + side2[0].y // Second Bezier + ) + .c_str(); + // pathChild.append_attribute("fill") = "currentColor"; + // pathChild.append_attribute("fill-opacity") = "1"; + pathChild.append_attribute("stroke") = this->GetColor(m_penStack.top().GetColor()).c_str(); + pathChild.append_attribute("stroke-linecap") = "round"; + pathChild.append_attribute("stroke-linejoin") = "round"; + // pathChild.append_attribute("stroke-opacity") = "1"; + pathChild.append_attribute("stroke-width") = m_penStack.top().GetWidth(); +} + void SvgDeviceContext::DrawCircle(int x, int y, int radius) { this->DrawEllipse(x - radius, y - radius, 2 * radius, 2 * radius); From 5eeb077e71fb48b7dfcc0d1e7e92317960685649 Mon Sep 17 00:00:00 2001 From: Laurent Pugin Date: Fri, 21 Feb 2025 14:53:10 +0100 Subject: [PATCH 2/8] Refactor ligature drawing code (WIP) --- include/vrv/bboxdevicecontext.h | 2 +- include/vrv/devicecontext.h | 2 +- include/vrv/svgdevicecontext.h | 2 +- src/bboxdevicecontext.cpp | 2 +- src/svgdevicecontext.cpp | 2 +- src/view_mensural.cpp | 116 ++++++++++++++++++++++++++++++-- 6 files changed, 115 insertions(+), 11 deletions(-) diff --git a/include/vrv/bboxdevicecontext.h b/include/vrv/bboxdevicecontext.h index 0ea40b19f6..df600a9d5d 100644 --- a/include/vrv/bboxdevicecontext.h +++ b/include/vrv/bboxdevicecontext.h @@ -72,7 +72,7 @@ class BBoxDeviceContext : public DeviceContext { void DrawQuadBezierPath(Point bezier[3]) override; void DrawCubicBezierPath(Point bezier[4]) override; void DrawCubicBezierPathFilled(Point bezier1[4], Point bezier2[4]) override; - void DrawBentParallelogramFilled(Point side1[3], Point side2[3]) override; + void DrawBentParallelogramFilled(Point side1[4], Point side2[4]) override; void DrawCircle(int x, int y, int radius) override; void DrawEllipse(int x, int y, int width, int height) override; void DrawEllipticArc(int x, int y, int width, int height, double start, double end) override; diff --git a/include/vrv/devicecontext.h b/include/vrv/devicecontext.h index 20f8eb4e1b..7d3860a2a1 100644 --- a/include/vrv/devicecontext.h +++ b/include/vrv/devicecontext.h @@ -193,7 +193,7 @@ class DeviceContext { virtual void DrawQuadBezierPath(Point bezier[3]) = 0; virtual void DrawCubicBezierPath(Point bezier[4]) = 0; virtual void DrawCubicBezierPathFilled(Point bezier1[4], Point bezier2[4]) = 0; - virtual void DrawBentParallelogramFilled(Point side1[3], Point side2[3]) = 0; + virtual void DrawBentParallelogramFilled(Point side1[4], Point side2[4]) = 0; virtual void DrawCircle(int x, int y, int radius) = 0; virtual void DrawEllipse(int x, int y, int width, int height) = 0; virtual void DrawEllipticArc(int x, int y, int width, int height, double start, double end) = 0; diff --git a/include/vrv/svgdevicecontext.h b/include/vrv/svgdevicecontext.h index 3d04637493..c290952016 100644 --- a/include/vrv/svgdevicecontext.h +++ b/include/vrv/svgdevicecontext.h @@ -78,7 +78,7 @@ class SvgDeviceContext : public DeviceContext { void DrawQuadBezierPath(Point bezier[3]) override; void DrawCubicBezierPath(Point bezier[4]) override; void DrawCubicBezierPathFilled(Point bezier1[4], Point bezier2[4]) override; - void DrawBentParallelogramFilled(Point side1[3], Point side2[3]) override; + void DrawBentParallelogramFilled(Point side1[4], Point side2[4]) override; void DrawCircle(int x, int y, int radius) override; void DrawEllipse(int x, int y, int width, int height) override; void DrawEllipticArc(int x, int y, int width, int height, double start, double end) override; diff --git a/src/bboxdevicecontext.cpp b/src/bboxdevicecontext.cpp index 60ed2a96ae..d368f1443c 100644 --- a/src/bboxdevicecontext.cpp +++ b/src/bboxdevicecontext.cpp @@ -169,7 +169,7 @@ void BBoxDeviceContext::DrawCubicBezierPathFilled(Point bezier1[4], Point bezier this->UpdateBB(pos.x, pos.y, pos.x + width, pos.y + height); } -void BBoxDeviceContext::DrawBentParallelogramFilled(Point side1[3], Point side2[3]) +void BBoxDeviceContext::DrawBentParallelogramFilled(Point side1[4], Point side2[4]) { this->UpdateBB(side1[0].x, side1[0].y, side2[2].x, side2[2].y); } diff --git a/src/svgdevicecontext.cpp b/src/svgdevicecontext.cpp index bbd5f9523e..679cadb7b7 100644 --- a/src/svgdevicecontext.cpp +++ b/src/svgdevicecontext.cpp @@ -693,7 +693,7 @@ void SvgDeviceContext::DrawCubicBezierPathFilled(Point bezier1[4], Point bezier2 pathChild.append_attribute("stroke-width") = m_penStack.top().GetWidth(); } -void SvgDeviceContext::DrawBentParallelogramFilled(Point side1[3], Point side2[3]) +void SvgDeviceContext::DrawBentParallelogramFilled(Point side1[4], Point side2[4]) { pugi::xml_node pathChild = AddChild("path"); pathChild.append_attribute("d") diff --git a/src/view_mensural.cpp b/src/view_mensural.cpp index 2adc1cea7b..5848fd0116 100644 --- a/src/view_mensural.cpp +++ b/src/view_mensural.cpp @@ -389,7 +389,35 @@ void View::DrawLigatureNote(DeviceContext *dc, LayerElement *element, Layer *lay this->DrawObliquePolygon(dc, bottomLeft->x, bottomLeft->y, bottomRight->x, bottomRight->y, strokeWidth); } else { - this->DrawObliquePolygon(dc, topLeft->x, topLeft->y, topRight->x, topRight->y, bottomLeft->y - topLeft->y); + + /* + Point side1[4]; + Point side2[4]; + side1[0] = ToDeviceContext(*topLeft); + side1[2] = ToDeviceContext(*topRight); + // + side2[0] = ToDeviceContext(*bottomLeft); + side2[2] = ToDeviceContext(*bottomRight); + // + double ratio = (obliqueEnd) ? .5 : 0; + int width = (side1[2].x - side1[0].x); + int height = (side1[2].y - side1[0].y); + side1[1] = side1[2]; + side1[1].x -= width * ratio; + side2[1].y -= height * ratio; + side2[1] = side2[2]; + side2[1].x -= width * ratio; + //side2[1].y -= height * ratio; + + dc->DrawBentParallelogramFilled(side1, side2); + //} + // else { + // this->DrawObliquePolygon(dc, topLeft->x, topLeft->y, topRight->x, topRight->y, //bottomLeft->y - + // topLeft->y); + //} + */ + this->DrawObliquePolygon(dc, topLeft->x, topLeft->y, topRight->x, topRight->y, bottomLeft->y - + topLeft->y); } // Do not draw a left connector with obliques @@ -624,6 +652,9 @@ void View::CalcObliquePoints(Note *note1, Note *note2, Staff *staff, Point point assert(staff); const int stemWidth = m_doc->GetDrawingStemWidth(staff->m_drawingStaffSize); + const int noteDiff = note1->PitchDifferenceTo(note2); + + const int yAdjust = noteDiff * stemWidth / 10; Point *topLeft = &points[0]; Point *bottomLeft = &points[1]; @@ -648,25 +679,97 @@ void View::CalcObliquePoints(Note *note1, Note *note2, Staff *staff, Point point sides[3] = sides2[3]; // With oblique it is best visually to move them up / down - more with (white) ligatures with serif - double adjustmentFactor = (isMensuralBlack) ? 0.5 : 1.8; + //double adjustmentFactor = (isMensuralBlack) ? 2.5 : 1.8; double slope = 0.0; + if (bottomRight->x != bottomLeft->x) + slope = (double)(bottomRight->y - bottomLeft->y) / (double)(bottomRight->x - bottomLeft->x); + + int length = (bottomRight->x - bottomLeft->x) / 2; + slope *= 0.85; + + if (firstHalf) { + // make sure there are some pixels of overlap + length += 1; + bottomRight->x = bottomLeft->x + length; + topRight->x = bottomRight->x; + bottomRight->y = bottomLeft->y + (int)(length * slope); + topRight->y = topLeft->y + (int)(length * slope); + // + topLeft->y += yAdjust; + bottomLeft->y += yAdjust; + } + else { + bottomLeft->x = bottomLeft->x + length; + topLeft->x = bottomLeft->x; + bottomLeft->y = bottomLeft->y + (int)(length * slope); + topLeft->y = topLeft->y + (int)(length * slope); + // + topRight->y -= yAdjust; + bottomRight->y -= yAdjust; + } + +} + +/* +void View::CalcObliquePoints(Note *note1, Note *note2, Staff *staff, Point points[4], int sides[4], int shape, + bool isMensuralBlack, bool firstHalf) +{ + assert(note1); + assert(note2); + assert(staff); + + const int stemWidth = m_doc->GetDrawingStemWidth(staff->m_drawingStaffSize); + + Point *topLeft = &points[0]; + Point *bottomLeft = &points[1]; + Point *topRight = &points[2]; + Point *bottomRight = &points[3]; + + int sides1[4]; + CalcBrevisPoints(note1, staff, topLeft, bottomLeft, sides1, shape, isMensuralBlack); + // Correct the x of bottomLeft + bottomLeft->x = topLeft->x; + // Copy the left sides + sides[0] = sides1[0]; + sides[1] = sides1[1]; + + int sides2[4]; + // add OBLIQUE shape to make sure sides are shortened in mensural black + CalcBrevisPoints(note2, staff, topRight, bottomRight, sides2, LIGATURE_OBLIQUE, isMensuralBlack); + // Correct the x of topRight; + topRight->x = bottomRight->x; + // Copy the right sides + sides[2] = sides2[2]; + sides[3] = sides2[3]; + + // With oblique it is best visually to move them up / down - more with (white) ligatures with serif + double adjustmentFactor = (isMensuralBlack) ? 2.5 : 1.8; + double slope = 0.0; + slope *= 1.6; if (bottomRight->x != bottomLeft->x) slope = (double)(bottomRight->y - bottomLeft->y) / (double)(bottomRight->x - bottomLeft->x); int adjustment = (int)(slope * stemWidth) * adjustmentFactor; topLeft->y -= adjustment; - bottomLeft->y -= adjustment; - topRight->y += adjustment; - bottomRight->y += adjustment; + // bottomLeft->y -= adjustment; + if (firstHalf) { + topRight->y -= adjustment; + // bottomRight->y += adjustment; + } + else { + // topRight->y += adjustment; + // bottomRight->y -= adjustment; + } slope = 0.0; // recalculate slope after adjustment if (bottomRight->x != bottomLeft->x) slope = (double)(bottomRight->y - bottomLeft->y) / (double)(bottomRight->x - bottomLeft->x); int length = (bottomRight->x - bottomLeft->x) / 2; + slope *= 1.6; if (firstHalf) { // make sure there are some pixels of overlap - length += 10; + // length += 10; bottomRight->x = bottomLeft->x + length; topRight->x = bottomRight->x; bottomRight->y = bottomLeft->y + (int)(length * slope); @@ -679,6 +782,7 @@ void View::CalcObliquePoints(Note *note1, Note *note2, Staff *staff, Point point topLeft->y = topLeft->y + (int)(length * slope); } } +*/ data_STEMDIRECTION View::GetMensuralStemDir(Layer *layer, Note *note, int verticalCenter) { From 6ea87395e0012bb02bdb123bb6fb55c866989ab3 Mon Sep 17 00:00:00 2001 From: Laurent Pugin Date: Fri, 21 Feb 2025 16:02:02 +0100 Subject: [PATCH 3/8] Draw bent parallelograms (WIP) --- src/view_mensural.cpp | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/src/view_mensural.cpp b/src/view_mensural.cpp index 5848fd0116..726638d69b 100644 --- a/src/view_mensural.cpp +++ b/src/view_mensural.cpp @@ -389,8 +389,6 @@ void View::DrawLigatureNote(DeviceContext *dc, LayerElement *element, Layer *lay this->DrawObliquePolygon(dc, bottomLeft->x, bottomLeft->y, bottomRight->x, bottomRight->y, strokeWidth); } else { - - /* Point side1[4]; Point side2[4]; side1[0] = ToDeviceContext(*topLeft); @@ -399,25 +397,17 @@ void View::DrawLigatureNote(DeviceContext *dc, LayerElement *element, Layer *lay side2[0] = ToDeviceContext(*bottomLeft); side2[2] = ToDeviceContext(*bottomRight); // - double ratio = (obliqueEnd) ? .5 : 0; + double ratio = (obliqueEnd) ? .5 : 0.5; int width = (side1[2].x - side1[0].x); int height = (side1[2].y - side1[0].y); side1[1] = side1[2]; - side1[1].x -= width * ratio; - side2[1].y -= height * ratio; + side1[1].x -= (width * ratio); + side1[1].y -= (1.15 * height * ratio); side2[1] = side2[2]; side2[1].x -= width * ratio; - //side2[1].y -= height * ratio; + side2[1].y -= (1.15 * height * ratio); dc->DrawBentParallelogramFilled(side1, side2); - //} - // else { - // this->DrawObliquePolygon(dc, topLeft->x, topLeft->y, topRight->x, topRight->y, //bottomLeft->y - - // topLeft->y); - //} - */ - this->DrawObliquePolygon(dc, topLeft->x, topLeft->y, topRight->x, topRight->y, bottomLeft->y - - topLeft->y); } // Do not draw a left connector with obliques @@ -653,7 +643,7 @@ void View::CalcObliquePoints(Note *note1, Note *note2, Staff *staff, Point point const int stemWidth = m_doc->GetDrawingStemWidth(staff->m_drawingStaffSize); const int noteDiff = note1->PitchDifferenceTo(note2); - + const int yAdjust = noteDiff * stemWidth / 10; Point *topLeft = &points[0]; @@ -679,7 +669,7 @@ void View::CalcObliquePoints(Note *note1, Note *note2, Staff *staff, Point point sides[3] = sides2[3]; // With oblique it is best visually to move them up / down - more with (white) ligatures with serif - //double adjustmentFactor = (isMensuralBlack) ? 2.5 : 1.8; + // double adjustmentFactor = (isMensuralBlack) ? 2.5 : 1.8; double slope = 0.0; if (bottomRight->x != bottomLeft->x) slope = (double)(bottomRight->y - bottomLeft->y) / (double)(bottomRight->x - bottomLeft->x); @@ -707,7 +697,6 @@ void View::CalcObliquePoints(Note *note1, Note *note2, Staff *staff, Point point topRight->y -= yAdjust; bottomRight->y -= yAdjust; } - } /* From 58e969637b7f16ebb6f57c96b6fd8d871cf8f79e Mon Sep 17 00:00:00 2001 From: Laurent Pugin Date: Fri, 21 Feb 2025 18:07:21 +0100 Subject: [PATCH 4/8] Draw bent ligatures --- include/vrv/bboxdevicecontext.h | 2 +- include/vrv/devicecontext.h | 2 +- include/vrv/svgdevicecontext.h | 2 +- src/bboxdevicecontext.cpp | 4 +-- src/svgdevicecontext.cpp | 9 +++---- src/view_mensural.cpp | 44 +++++++++++++++++---------------- 6 files changed, 32 insertions(+), 31 deletions(-) diff --git a/include/vrv/bboxdevicecontext.h b/include/vrv/bboxdevicecontext.h index df600a9d5d..0171908981 100644 --- a/include/vrv/bboxdevicecontext.h +++ b/include/vrv/bboxdevicecontext.h @@ -72,7 +72,7 @@ class BBoxDeviceContext : public DeviceContext { void DrawQuadBezierPath(Point bezier[3]) override; void DrawCubicBezierPath(Point bezier[4]) override; void DrawCubicBezierPathFilled(Point bezier1[4], Point bezier2[4]) override; - void DrawBentParallelogramFilled(Point side1[4], Point side2[4]) override; + void DrawBentParallelogramFilled(Point side1[4], int height) override; void DrawCircle(int x, int y, int radius) override; void DrawEllipse(int x, int y, int width, int height) override; void DrawEllipticArc(int x, int y, int width, int height, double start, double end) override; diff --git a/include/vrv/devicecontext.h b/include/vrv/devicecontext.h index 7d3860a2a1..0004cd7be1 100644 --- a/include/vrv/devicecontext.h +++ b/include/vrv/devicecontext.h @@ -193,7 +193,7 @@ class DeviceContext { virtual void DrawQuadBezierPath(Point bezier[3]) = 0; virtual void DrawCubicBezierPath(Point bezier[4]) = 0; virtual void DrawCubicBezierPathFilled(Point bezier1[4], Point bezier2[4]) = 0; - virtual void DrawBentParallelogramFilled(Point side1[4], Point side2[4]) = 0; + virtual void DrawBentParallelogramFilled(Point side1[4], int height) = 0; virtual void DrawCircle(int x, int y, int radius) = 0; virtual void DrawEllipse(int x, int y, int width, int height) = 0; virtual void DrawEllipticArc(int x, int y, int width, int height, double start, double end) = 0; diff --git a/include/vrv/svgdevicecontext.h b/include/vrv/svgdevicecontext.h index c290952016..d7d1735722 100644 --- a/include/vrv/svgdevicecontext.h +++ b/include/vrv/svgdevicecontext.h @@ -78,7 +78,7 @@ class SvgDeviceContext : public DeviceContext { void DrawQuadBezierPath(Point bezier[3]) override; void DrawCubicBezierPath(Point bezier[4]) override; void DrawCubicBezierPathFilled(Point bezier1[4], Point bezier2[4]) override; - void DrawBentParallelogramFilled(Point side1[4], Point side2[4]) override; + void DrawBentParallelogramFilled(Point side1[4], int height) override; void DrawCircle(int x, int y, int radius) override; void DrawEllipse(int x, int y, int width, int height) override; void DrawEllipticArc(int x, int y, int width, int height, double start, double end) override; diff --git a/src/bboxdevicecontext.cpp b/src/bboxdevicecontext.cpp index d368f1443c..25bbedafc0 100644 --- a/src/bboxdevicecontext.cpp +++ b/src/bboxdevicecontext.cpp @@ -169,9 +169,9 @@ void BBoxDeviceContext::DrawCubicBezierPathFilled(Point bezier1[4], Point bezier this->UpdateBB(pos.x, pos.y, pos.x + width, pos.y + height); } -void BBoxDeviceContext::DrawBentParallelogramFilled(Point side1[4], Point side2[4]) +void BBoxDeviceContext::DrawBentParallelogramFilled(Point side1[4], int height) { - this->UpdateBB(side1[0].x, side1[0].y, side2[2].x, side2[2].y); + this->UpdateBB(side1[0].x, side1[0].y, side1[3].x, side1[3].y + height); } void BBoxDeviceContext::DrawCircle(int x, int y, int radius) diff --git a/src/svgdevicecontext.cpp b/src/svgdevicecontext.cpp index 679cadb7b7..d21b022b5d 100644 --- a/src/svgdevicecontext.cpp +++ b/src/svgdevicecontext.cpp @@ -693,14 +693,13 @@ void SvgDeviceContext::DrawCubicBezierPathFilled(Point bezier1[4], Point bezier2 pathChild.append_attribute("stroke-width") = m_penStack.top().GetWidth(); } -void SvgDeviceContext::DrawBentParallelogramFilled(Point side1[4], Point side2[4]) +void SvgDeviceContext::DrawBentParallelogramFilled(Point side1[4], int height) { pugi::xml_node pathChild = AddChild("path"); pathChild.append_attribute("d") - = StringFormat("M%d,%d Q%d,%d %d,%d L%d,%d Q%d,%d %d,%d Z", side1[0].x, side1[0].y, // M command - side1[1].x, side1[1].y, side1[2].x, side1[2].y, side2[2].x, side2[2].y, side2[1].x, side2[1].y, side2[0].x, - side2[0].y // Second Bezier - ) + = StringFormat("M%d,%d C%d,%d %d,%d %d,%d L%d,%d C%d,%d %d,%d %d,%d Z", side1[0].x, side1[0].y, // M command + side1[1].x, side1[1].y, side1[2].x, side1[2].y, side1[3].x, side1[3].y, side1[3].x, side1[3].y + height, + side1[2].x, side1[2].y + height, side1[1].x, side1[1].y + height, side1[0].x, side1[0].y + height) .c_str(); // pathChild.append_attribute("fill") = "currentColor"; // pathChild.append_attribute("fill-opacity") = "1"; diff --git a/src/view_mensural.cpp b/src/view_mensural.cpp index 726638d69b..7bb818957e 100644 --- a/src/view_mensural.cpp +++ b/src/view_mensural.cpp @@ -383,31 +383,33 @@ void View::DrawLigatureNote(DeviceContext *dc, LayerElement *element, Layer *lay } } + Point side1[4]; + int thickness = topLeft->y - bottomLeft->y; + side1[0] = ToDeviceContext(*topLeft); + side1[3] = ToDeviceContext(*topRight); + // + int width = (side1[3].x - side1[0].x); + int height = (side1[3].y - side1[0].y); + side1[1] = side1[3]; + side1[1].x -= (width * 0.75); + side1[1].y -= (height * 0.75) + (height * 0.05); + side1[2] = side1[3]; + side1[2].x -= (width * 0.25); + side1[2].y -= (height * 0.25) + (height * 0.05); + if (!fillNotehead) { // double the bases of rectangles - this->DrawObliquePolygon(dc, topLeft->x, topLeft->y, topRight->x, topRight->y, -strokeWidth); - this->DrawObliquePolygon(dc, bottomLeft->x, bottomLeft->y, bottomRight->x, bottomRight->y, strokeWidth); + dc->DrawBentParallelogramFilled(side1, strokeWidth); + for (Point &point : side1) { + point.y += thickness - strokeWidth; + } + dc->DrawBentParallelogramFilled(side1, strokeWidth); + + // this->DrawObliquePolygon(dc, topLeft->x, topLeft->y, topRight->x, topRight->y, -strokeWidth); + // this->DrawObliquePolygon(dc, bottomLeft->x, bottomLeft->y, bottomRight->x, bottomRight->y, strokeWidth); } else { - Point side1[4]; - Point side2[4]; - side1[0] = ToDeviceContext(*topLeft); - side1[2] = ToDeviceContext(*topRight); - // - side2[0] = ToDeviceContext(*bottomLeft); - side2[2] = ToDeviceContext(*bottomRight); - // - double ratio = (obliqueEnd) ? .5 : 0.5; - int width = (side1[2].x - side1[0].x); - int height = (side1[2].y - side1[0].y); - side1[1] = side1[2]; - side1[1].x -= (width * ratio); - side1[1].y -= (1.15 * height * ratio); - side2[1] = side2[2]; - side2[1].x -= width * ratio; - side2[1].y -= (1.15 * height * ratio); - - dc->DrawBentParallelogramFilled(side1, side2); + dc->DrawBentParallelogramFilled(side1, thickness); } // Do not draw a left connector with obliques From aad732821fa454fa1fbee1280e31d491b83d7d99 Mon Sep 17 00:00:00 2001 From: Laurent Pugin Date: Sat, 22 Feb 2025 08:33:54 +0100 Subject: [PATCH 5/8] Add option for `--ligature-straight` --- include/vrv/options.h | 1 + src/options.cpp | 4 +++ src/view_mensural.cpp | 57 +++++++++++++++++++++++++------------------ 3 files changed, 38 insertions(+), 24 deletions(-) diff --git a/include/vrv/options.h b/include/vrv/options.h index 5961c57ea3..0a3d9cda4d 100644 --- a/include/vrv/options.h +++ b/include/vrv/options.h @@ -845,6 +845,7 @@ class Options { OptionIntMap m_durationEquivalence; OptionBool m_ligatureAsBracket; + OptionBool m_ligatureStraight; OptionBool m_mensuralScoreUp; OptionBool m_mensuralResponsiveView; OptionBool m_mensuralToCmn; diff --git a/src/options.cpp b/src/options.cpp index dedfe749d8..a5346251fa 100644 --- a/src/options.cpp +++ b/src/options.cpp @@ -1832,6 +1832,10 @@ Options::Options() m_ligatureAsBracket.Init(false); this->Register(&m_ligatureAsBracket, "ligatureAsBracket", &m_mensural); + m_ligatureStraight.SetInfo("Ligature straight", "Render oblique ligatures as straight polygons"); + m_ligatureStraight.Init(false); + this->Register(&m_ligatureStraight, "ligatureStraight", &m_mensural); + m_mensuralResponsiveView.SetInfo( "Mensural reduced view", "Convert mensural content to a more responsive view reduced to the seleceted markup"); m_mensuralResponsiveView.Init(false); diff --git a/src/view_mensural.cpp b/src/view_mensural.cpp index 7bb818957e..1a2af85fcd 100644 --- a/src/view_mensural.cpp +++ b/src/view_mensural.cpp @@ -350,6 +350,7 @@ void View::DrawLigatureNote(DeviceContext *dc, LayerElement *element, Layer *lay bool oblique = ((shape & LIGATURE_OBLIQUE) || (prevShape & LIGATURE_OBLIQUE)); bool obliqueEnd = (prevShape & LIGATURE_OBLIQUE); bool stackedEnd = (shape & LIGATURE_STACKED); + bool straight = m_doc->GetOptions()->m_ligatureStraight.GetValue(); int stemWidth = m_doc->GetDrawingStemWidth(staff->m_drawingStaffSize); int strokeWidth = 2.8 * stemWidth; @@ -383,33 +384,41 @@ void View::DrawLigatureNote(DeviceContext *dc, LayerElement *element, Layer *lay } } - Point side1[4]; - int thickness = topLeft->y - bottomLeft->y; - side1[0] = ToDeviceContext(*topLeft); - side1[3] = ToDeviceContext(*topRight); - // - int width = (side1[3].x - side1[0].x); - int height = (side1[3].y - side1[0].y); - side1[1] = side1[3]; - side1[1].x -= (width * 0.75); - side1[1].y -= (height * 0.75) + (height * 0.05); - side1[2] = side1[3]; - side1[2].x -= (width * 0.25); - side1[2].y -= (height * 0.25) + (height * 0.05); - - if (!fillNotehead) { - // double the bases of rectangles - dc->DrawBentParallelogramFilled(side1, strokeWidth); - for (Point &point : side1) { - point.y += thickness - strokeWidth; + // Oblique polygons + if (straight) { + if (fillNotehead) { + this->DrawObliquePolygon(dc, topLeft->x, topLeft->y, topRight->x, topRight->y, -strokeWidth); + this->DrawObliquePolygon(dc, bottomLeft->x, bottomLeft->y, bottomRight->x, bottomRight->y, strokeWidth); + } + else { + this->DrawObliquePolygon(dc, topLeft->x, topLeft->y, topRight->x, topRight->y, bottomLeft->y - topLeft->y); } - dc->DrawBentParallelogramFilled(side1, strokeWidth); - - // this->DrawObliquePolygon(dc, topLeft->x, topLeft->y, topRight->x, topRight->y, -strokeWidth); - // this->DrawObliquePolygon(dc, bottomLeft->x, bottomLeft->y, bottomRight->x, bottomRight->y, strokeWidth); } + // Bent parallelograms else { - dc->DrawBentParallelogramFilled(side1, thickness); + const int thickness = topLeft->y - bottomLeft->y; + // The curved side points (two ends and two control points) + Point curvedSide[4]; + curvedSide[0] = ToDeviceContext(*topLeft); + curvedSide[3] = ToDeviceContext(*topRight); + // + const int width = (curvedSide[3].x - curvedSide[0].x); + const int height = (curvedSide[3].y - curvedSide[0].y); + curvedSide[1] = curvedSide[3]; + curvedSide[1].x -= (width * 0.75); + curvedSide[1].y -= (height * 0.75) + (height * 0.05); + curvedSide[2] = curvedSide[3]; + curvedSide[2].x -= (width * 0.25); + curvedSide[2].y -= (height * 0.25) + (height * 0.05); + + if (!fillNotehead) { + dc->DrawBentParallelogramFilled(curvedSide, strokeWidth); + for (Point &point : curvedSide) point.y += thickness - strokeWidth; + dc->DrawBentParallelogramFilled(curvedSide, strokeWidth); + } + else { + dc->DrawBentParallelogramFilled(curvedSide, thickness); + } } // Do not draw a left connector with obliques From 6f9fbe56e72380db27416b75ef4ac9717f29d1af Mon Sep 17 00:00:00 2001 From: Laurent Pugin Date: Sat, 22 Feb 2025 08:34:07 +0100 Subject: [PATCH 6/8] cleanup code --- include/vrv/bboxdevicecontext.h | 2 +- include/vrv/devicecontext.h | 2 +- include/vrv/svgdevicecontext.h | 2 +- src/bboxdevicecontext.cpp | 4 ++-- src/svgdevicecontext.cpp | 14 +++++--------- 5 files changed, 10 insertions(+), 14 deletions(-) diff --git a/include/vrv/bboxdevicecontext.h b/include/vrv/bboxdevicecontext.h index 0171908981..80315b7e39 100644 --- a/include/vrv/bboxdevicecontext.h +++ b/include/vrv/bboxdevicecontext.h @@ -72,7 +72,7 @@ class BBoxDeviceContext : public DeviceContext { void DrawQuadBezierPath(Point bezier[3]) override; void DrawCubicBezierPath(Point bezier[4]) override; void DrawCubicBezierPathFilled(Point bezier1[4], Point bezier2[4]) override; - void DrawBentParallelogramFilled(Point side1[4], int height) override; + void DrawBentParallelogramFilled(Point side[4], int height) override; void DrawCircle(int x, int y, int radius) override; void DrawEllipse(int x, int y, int width, int height) override; void DrawEllipticArc(int x, int y, int width, int height, double start, double end) override; diff --git a/include/vrv/devicecontext.h b/include/vrv/devicecontext.h index 0004cd7be1..e5f14a47b6 100644 --- a/include/vrv/devicecontext.h +++ b/include/vrv/devicecontext.h @@ -193,7 +193,7 @@ class DeviceContext { virtual void DrawQuadBezierPath(Point bezier[3]) = 0; virtual void DrawCubicBezierPath(Point bezier[4]) = 0; virtual void DrawCubicBezierPathFilled(Point bezier1[4], Point bezier2[4]) = 0; - virtual void DrawBentParallelogramFilled(Point side1[4], int height) = 0; + virtual void DrawBentParallelogramFilled(Point side[4], int height) = 0; virtual void DrawCircle(int x, int y, int radius) = 0; virtual void DrawEllipse(int x, int y, int width, int height) = 0; virtual void DrawEllipticArc(int x, int y, int width, int height, double start, double end) = 0; diff --git a/include/vrv/svgdevicecontext.h b/include/vrv/svgdevicecontext.h index d7d1735722..c8ca9dff7f 100644 --- a/include/vrv/svgdevicecontext.h +++ b/include/vrv/svgdevicecontext.h @@ -78,7 +78,7 @@ class SvgDeviceContext : public DeviceContext { void DrawQuadBezierPath(Point bezier[3]) override; void DrawCubicBezierPath(Point bezier[4]) override; void DrawCubicBezierPathFilled(Point bezier1[4], Point bezier2[4]) override; - void DrawBentParallelogramFilled(Point side1[4], int height) override; + void DrawBentParallelogramFilled(Point side[4], int height) override; void DrawCircle(int x, int y, int radius) override; void DrawEllipse(int x, int y, int width, int height) override; void DrawEllipticArc(int x, int y, int width, int height, double start, double end) override; diff --git a/src/bboxdevicecontext.cpp b/src/bboxdevicecontext.cpp index 25bbedafc0..5de7b21c38 100644 --- a/src/bboxdevicecontext.cpp +++ b/src/bboxdevicecontext.cpp @@ -169,9 +169,9 @@ void BBoxDeviceContext::DrawCubicBezierPathFilled(Point bezier1[4], Point bezier this->UpdateBB(pos.x, pos.y, pos.x + width, pos.y + height); } -void BBoxDeviceContext::DrawBentParallelogramFilled(Point side1[4], int height) +void BBoxDeviceContext::DrawBentParallelogramFilled(Point side[4], int height) { - this->UpdateBB(side1[0].x, side1[0].y, side1[3].x, side1[3].y + height); + this->UpdateBB(side[0].x, side[0].y, side[3].x, side[3].y + height); } void BBoxDeviceContext::DrawCircle(int x, int y, int radius) diff --git a/src/svgdevicecontext.cpp b/src/svgdevicecontext.cpp index d21b022b5d..c88b1585d5 100644 --- a/src/svgdevicecontext.cpp +++ b/src/svgdevicecontext.cpp @@ -693,20 +693,16 @@ void SvgDeviceContext::DrawCubicBezierPathFilled(Point bezier1[4], Point bezier2 pathChild.append_attribute("stroke-width") = m_penStack.top().GetWidth(); } -void SvgDeviceContext::DrawBentParallelogramFilled(Point side1[4], int height) +void SvgDeviceContext::DrawBentParallelogramFilled(Point side[4], int height) { pugi::xml_node pathChild = AddChild("path"); - pathChild.append_attribute("d") - = StringFormat("M%d,%d C%d,%d %d,%d %d,%d L%d,%d C%d,%d %d,%d %d,%d Z", side1[0].x, side1[0].y, // M command - side1[1].x, side1[1].y, side1[2].x, side1[2].y, side1[3].x, side1[3].y, side1[3].x, side1[3].y + height, - side1[2].x, side1[2].y + height, side1[1].x, side1[1].y + height, side1[0].x, side1[0].y + height) - .c_str(); - // pathChild.append_attribute("fill") = "currentColor"; - // pathChild.append_attribute("fill-opacity") = "1"; + pathChild.append_attribute("d") = StringFormat("M%d,%d C%d,%d %d,%d %d,%d L%d,%d C%d,%d %d,%d %d,%d Z", side[0].x, + side[0].y, side[1].x, side[1].y, side[2].x, side[2].y, side[3].x, side[3].y, side[3].x, side[3].y + height, + side[2].x, side[2].y + height, side[1].x, side[1].y + height, side[0].x, side[0].y + height) + .c_str(); pathChild.append_attribute("stroke") = this->GetColor(m_penStack.top().GetColor()).c_str(); pathChild.append_attribute("stroke-linecap") = "round"; pathChild.append_attribute("stroke-linejoin") = "round"; - // pathChild.append_attribute("stroke-opacity") = "1"; pathChild.append_attribute("stroke-width") = m_penStack.top().GetWidth(); } From 03757776b3bfa052fb45c0335d040881cb8a9887 Mon Sep 17 00:00:00 2001 From: Laurent Pugin Date: Sat, 22 Feb 2025 08:56:31 +0100 Subject: [PATCH 7/8] Adjust values --- src/view_mensural.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/view_mensural.cpp b/src/view_mensural.cpp index 1a2af85fcd..2888b8370d 100644 --- a/src/view_mensural.cpp +++ b/src/view_mensural.cpp @@ -405,11 +405,11 @@ void View::DrawLigatureNote(DeviceContext *dc, LayerElement *element, Layer *lay const int width = (curvedSide[3].x - curvedSide[0].x); const int height = (curvedSide[3].y - curvedSide[0].y); curvedSide[1] = curvedSide[3]; - curvedSide[1].x -= (width * 0.75); - curvedSide[1].y -= (height * 0.75) + (height * 0.05); + curvedSide[1].x -= (width * 0.7); + curvedSide[1].y -= (height * 0.7) + (height * 0.07); curvedSide[2] = curvedSide[3]; - curvedSide[2].x -= (width * 0.25); - curvedSide[2].y -= (height * 0.25) + (height * 0.05); + curvedSide[2].x -= (width * 0.3); + curvedSide[2].y -= (height * 0.3) + (height * 0.07); if (!fillNotehead) { dc->DrawBentParallelogramFilled(curvedSide, strokeWidth); From ee1cfffe601c7afeab15b1ddb7bf22d2a6ba89f9 Mon Sep 17 00:00:00 2001 From: Laurent Pugin Date: Sun, 23 Feb 2025 13:14:06 +0100 Subject: [PATCH 8/8] Change `--ligatureStraight` to `ligatureOblique` with `auto`, `straight` and `curved` --- include/vrv/options.h | 5 ++- include/vrv/view.h | 2 +- src/options.cpp | 9 ++-- src/view_mensural.cpp | 98 +++++++------------------------------------ 4 files changed, 26 insertions(+), 88 deletions(-) diff --git a/include/vrv/options.h b/include/vrv/options.h index 0a3d9cda4d..f545882b35 100644 --- a/include/vrv/options.h +++ b/include/vrv/options.h @@ -75,6 +75,8 @@ enum option_FOOTER { FOOTER_none = 0, FOOTER_auto, FOOTER_encoded, FOOTER_always enum option_HEADER { HEADER_none = 0, HEADER_auto, HEADER_encoded }; +enum option_LIGATURE_OBL { LIGATURE_OBL_auto = 0, LIGATURE_OBL_straight, LIGATURE_OBL_curved }; + enum option_MULTIRESTSTYLE { MULTIRESTSTYLE_auto = 0, MULTIRESTSTYLE_default, @@ -148,6 +150,7 @@ class Option { static const std::map s_fontFallback; static const std::map s_footer; static const std::map s_header; + static const std::map s_ligatureOblique; static const std::map s_multiRestStyle; static const std::map s_pedalStyle; static const std::map s_systemDivider; @@ -845,7 +848,7 @@ class Options { OptionIntMap m_durationEquivalence; OptionBool m_ligatureAsBracket; - OptionBool m_ligatureStraight; + OptionIntMap m_ligatureOblique; OptionBool m_mensuralScoreUp; OptionBool m_mensuralResponsiveView; OptionBool m_mensuralToCmn; diff --git a/include/vrv/view.h b/include/vrv/view.h index f73e89492d..d8c9b17b23 100644 --- a/include/vrv/view.h +++ b/include/vrv/view.h @@ -641,7 +641,7 @@ class View { void CalcBrevisPoints( Note *note, Staff *staff, Point *topLeft, Point *bottomRight, int sides[4], int shape, bool isMensuralBlack); void CalcObliquePoints(Note *note1, Note *note2, Staff *staff, Point points[4], int sides[4], int shape, - bool isMensuralBlack, bool firstHalf); + bool isMensuralBlack, bool firstHalf, bool straight); /** * Internal methods for drawing a BeamSegment diff --git a/src/options.cpp b/src/options.cpp index a5346251fa..0745085504 100644 --- a/src/options.cpp +++ b/src/options.cpp @@ -44,6 +44,9 @@ const std::map Option::s_footer const std::map Option::s_header = { { HEADER_none, "none" }, { HEADER_auto, "auto" }, { HEADER_encoded, "encoded" } }; +const std::map Option::s_ligatureOblique + = { { LIGATURE_OBL_auto, "auto" }, { LIGATURE_OBL_straight, "straight" }, { LIGATURE_OBL_curved, "curved" } }; + const std::map Option::s_multiRestStyle = { { MULTIRESTSTYLE_auto, "auto" }, { MULTIRESTSTYLE_default, "default" }, { MULTIRESTSTYLE_block, "block" }, { MULTIRESTSTYLE_symbols, "symbols" } }; @@ -1832,9 +1835,9 @@ Options::Options() m_ligatureAsBracket.Init(false); this->Register(&m_ligatureAsBracket, "ligatureAsBracket", &m_mensural); - m_ligatureStraight.SetInfo("Ligature straight", "Render oblique ligatures as straight polygons"); - m_ligatureStraight.Init(false); - this->Register(&m_ligatureStraight, "ligatureStraight", &m_mensural); + m_ligatureOblique.SetInfo("Ligature oblique", "Ligature oblique shape"); + m_ligatureOblique.Init(LIGATURE_OBL_auto, &Option::s_ligatureOblique); + this->Register(&m_ligatureOblique, "ligatureOblique", &m_mensural); m_mensuralResponsiveView.SetInfo( "Mensural reduced view", "Convert mensural content to a more responsive view reduced to the seleceted markup"); diff --git a/src/view_mensural.cpp b/src/view_mensural.cpp index 2888b8370d..c4b5bf28d6 100644 --- a/src/view_mensural.cpp +++ b/src/view_mensural.cpp @@ -350,12 +350,17 @@ void View::DrawLigatureNote(DeviceContext *dc, LayerElement *element, Layer *lay bool oblique = ((shape & LIGATURE_OBLIQUE) || (prevShape & LIGATURE_OBLIQUE)); bool obliqueEnd = (prevShape & LIGATURE_OBLIQUE); bool stackedEnd = (shape & LIGATURE_STACKED); - bool straight = m_doc->GetOptions()->m_ligatureStraight.GetValue(); - int stemWidth = m_doc->GetDrawingStemWidth(staff->m_drawingStaffSize); int strokeWidth = 2.8 * stemWidth; /** end code duplicated */ + bool straight = true; + switch (m_doc->GetOptions()->m_ligatureOblique.GetValue()) { + case LIGATURE_OBL_auto: straight = !isMensuralBlack; break; + case LIGATURE_OBL_straight: straight = true; break; + case LIGATURE_OBL_curved: straight = false; break; + } + Point points[4]; Point *topLeft = &points[0]; Point *bottomLeft = &points[1]; @@ -373,11 +378,11 @@ void View::DrawLigatureNote(DeviceContext *dc, LayerElement *element, Layer *lay // First half of the oblique - checking the nextNote is there just in case, but is should if ((shape & LIGATURE_OBLIQUE) && nextNote) { // return; - CalcObliquePoints(note, nextNote, staff, points, sides, shape, isMensuralBlack, true); + CalcObliquePoints(note, nextNote, staff, points, sides, shape, isMensuralBlack, true, straight); } // Second half of the oblique - checking the prevNote is there just in case, but is should else if ((prevShape & LIGATURE_OBLIQUE) && prevNote) { - CalcObliquePoints(prevNote, note, staff, points, sides, prevShape, isMensuralBlack, false); + CalcObliquePoints(prevNote, note, staff, points, sides, prevShape, isMensuralBlack, false, straight); } else { assert(false); @@ -386,7 +391,7 @@ void View::DrawLigatureNote(DeviceContext *dc, LayerElement *element, Layer *lay // Oblique polygons if (straight) { - if (fillNotehead) { + if (!fillNotehead) { this->DrawObliquePolygon(dc, topLeft->x, topLeft->y, topRight->x, topRight->y, -strokeWidth); this->DrawObliquePolygon(dc, bottomLeft->x, bottomLeft->y, bottomRight->x, bottomRight->y, strokeWidth); } @@ -646,7 +651,7 @@ void View::CalcBrevisPoints( } void View::CalcObliquePoints(Note *note1, Note *note2, Staff *staff, Point points[4], int sides[4], int shape, - bool isMensuralBlack, bool firstHalf) + bool isMensuralBlack, bool firstHalf, bool straight) { assert(note1); assert(note2); @@ -655,7 +660,8 @@ void View::CalcObliquePoints(Note *note1, Note *note2, Staff *staff, Point point const int stemWidth = m_doc->GetDrawingStemWidth(staff->m_drawingStaffSize); const int noteDiff = note1->PitchDifferenceTo(note2); - const int yAdjust = noteDiff * stemWidth / 10; + // Adjustment for end points according to the note diff + const int yAdjust = noteDiff * stemWidth / 5; Point *topLeft = &points[0]; Point *bottomLeft = &points[1]; @@ -686,10 +692,10 @@ void View::CalcObliquePoints(Note *note1, Note *note2, Staff *staff, Point point slope = (double)(bottomRight->y - bottomLeft->y) / (double)(bottomRight->x - bottomLeft->x); int length = (bottomRight->x - bottomLeft->x) / 2; - slope *= 0.85; + if (!straight) slope *= 0.85; if (firstHalf) { - // make sure there are some pixels of overlap + // make sure there is one pixel of overlap length += 1; bottomRight->x = bottomLeft->x + length; topRight->x = bottomRight->x; @@ -710,80 +716,6 @@ void View::CalcObliquePoints(Note *note1, Note *note2, Staff *staff, Point point } } -/* -void View::CalcObliquePoints(Note *note1, Note *note2, Staff *staff, Point points[4], int sides[4], int shape, - bool isMensuralBlack, bool firstHalf) -{ - assert(note1); - assert(note2); - assert(staff); - - const int stemWidth = m_doc->GetDrawingStemWidth(staff->m_drawingStaffSize); - - Point *topLeft = &points[0]; - Point *bottomLeft = &points[1]; - Point *topRight = &points[2]; - Point *bottomRight = &points[3]; - - int sides1[4]; - CalcBrevisPoints(note1, staff, topLeft, bottomLeft, sides1, shape, isMensuralBlack); - // Correct the x of bottomLeft - bottomLeft->x = topLeft->x; - // Copy the left sides - sides[0] = sides1[0]; - sides[1] = sides1[1]; - - int sides2[4]; - // add OBLIQUE shape to make sure sides are shortened in mensural black - CalcBrevisPoints(note2, staff, topRight, bottomRight, sides2, LIGATURE_OBLIQUE, isMensuralBlack); - // Correct the x of topRight; - topRight->x = bottomRight->x; - // Copy the right sides - sides[2] = sides2[2]; - sides[3] = sides2[3]; - - // With oblique it is best visually to move them up / down - more with (white) ligatures with serif - double adjustmentFactor = (isMensuralBlack) ? 2.5 : 1.8; - double slope = 0.0; - slope *= 1.6; - if (bottomRight->x != bottomLeft->x) - slope = (double)(bottomRight->y - bottomLeft->y) / (double)(bottomRight->x - bottomLeft->x); - int adjustment = (int)(slope * stemWidth) * adjustmentFactor; - topLeft->y -= adjustment; - // bottomLeft->y -= adjustment; - if (firstHalf) { - topRight->y -= adjustment; - // bottomRight->y += adjustment; - } - else { - // topRight->y += adjustment; - // bottomRight->y -= adjustment; - } - - slope = 0.0; - // recalculate slope after adjustment - if (bottomRight->x != bottomLeft->x) - slope = (double)(bottomRight->y - bottomLeft->y) / (double)(bottomRight->x - bottomLeft->x); - int length = (bottomRight->x - bottomLeft->x) / 2; - slope *= 1.6; - - if (firstHalf) { - // make sure there are some pixels of overlap - // length += 10; - bottomRight->x = bottomLeft->x + length; - topRight->x = bottomRight->x; - bottomRight->y = bottomLeft->y + (int)(length * slope); - topRight->y = topLeft->y + (int)(length * slope); - } - else { - bottomLeft->x = bottomLeft->x + length; - topLeft->x = bottomLeft->x; - bottomLeft->y = bottomLeft->y + (int)(length * slope); - topLeft->y = topLeft->y + (int)(length * slope); - } -} -*/ - data_STEMDIRECTION View::GetMensuralStemDir(Layer *layer, Note *note, int verticalCenter) { // constants