Skip to content

Commit

Permalink
[palette] added layout for Glissando
Browse files Browse the repository at this point in the history
  • Loading branch information
igorkorsukov committed Jul 10, 2023
1 parent 5664ed0 commit 4ccdf04
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 156 deletions.
162 changes: 6 additions & 156 deletions src/engraving/layout/pal/tlayout.cpp
Expand Up @@ -1080,166 +1080,16 @@ void TLayout::layout(FretCircle* item, LayoutContext&)
item->setbbox(item->rect().adjusted(-lw, -lw, lw, lw));
}

void TLayout::layout(Glissando* item, LayoutContext& ctx)
void TLayout::layout(Glissando*, LayoutContext&)
{
double _spatium = item->spatium();

if (ctx.conf().isPaletteMode() || !item->startElement() || !item->endElement()) { // for use in palettes or while dragging
if (item->spannerSegments().empty()) {
item->add(item->createLineSegment(ctx.mutDom().dummyParent()->system()));
}
LineSegment* s = item->frontSegment();
s->setPos(PointF(-_spatium * Glissando::GLISS_PALETTE_WIDTH / 2, _spatium * Glissando::GLISS_PALETTE_HEIGHT / 2));
s->setPos2(PointF(_spatium * Glissando::GLISS_PALETTE_WIDTH, -_spatium * Glissando::GLISS_PALETTE_HEIGHT));
layout(s, ctx);
return;
}
layoutLine(item, ctx);
if (item->spannerSegments().empty()) {
LOGD("no segments");
return;
}
item->setPos(0.0, 0.0);

Note* anchor1 = toNote(item->startElement());
Note* anchor2 = toNote(item->endElement());
Chord* cr1 = anchor1->chord();
Chord* cr2 = anchor2->chord();
GlissandoSegment* segm1 = toGlissandoSegment(item->frontSegment());
GlissandoSegment* segm2 = toGlissandoSegment(item->backSegment());

// Note: line segments are defined by
// initial point: ipos() (relative to system origin)
// ending point: pos2() (relative to initial point)

// LINE ENDING POINTS TO NOTEHEAD CENTRES

// assume gliss. line goes from centre of initial note centre to centre of ending note:
// move first segment origin and last segment ending point from notehead origin to notehead centre
// For TAB: begin at the right-edge of initial note rather than centre
PointF offs1 = (cr1->staff()->isTabStaff(cr1->tick()))
? PointF(anchor1->bbox().right(), 0.0)
: PointF(anchor1->headWidth() * 0.5, 0.0);

PointF offs2 = PointF(anchor2->headWidth() * 0.5, 0.0);

// AVOID HORIZONTAL LINES

int upDown = (0 < (anchor2->pitch() - anchor1->pitch())) - ((anchor2->pitch() - anchor1->pitch()) < 0);
// on TAB's, glissando are by necessity on the same string, this gives an horizontal glissando line;
// make bottom end point lower and top ending point higher
if (cr1->staff()->isTabStaff(cr1->tick())) {
double yOff = cr1->staff()->lineDistance(cr1->tick()) * 0.4 * _spatium;
offs1.ry() += yOff * upDown;
offs2.ry() -= yOff * upDown;
}
// if not TAB, angle glissando between notes on the same line
else {
if (anchor1->line() == anchor2->line()) {
offs1.ry() += _spatium * 0.25 * upDown;
offs2.ry() -= _spatium * 0.25 * upDown;
}
}

// move initial point of first segment and adjust its length accordingly
segm1->setPos(segm1->ipos() + offs1);
segm1->setPos2(segm1->ipos2() - offs1);
// adjust ending point of last segment
segm2->setPos2(segm2->ipos2() + offs2);

// INTERPOLATION OF INTERMEDIATE POINTS
// This probably belongs to SLine class itself; currently it does not seem
// to be needed for anything else than Glissando, though

// get total x-width and total y-height of all segments
double xTot = 0.0;
for (SpannerSegment* segm : item->spannerSegments()) {
xTot += segm->ipos2().x();
}
double y0 = segm1->ipos().y();
double yTot = segm2->ipos().y() + segm2->ipos2().y() - y0;
yTot -= yStaffDifference(segm2->system(), segm2->staffIdx(), segm1->system(), segm1->staffIdx());
double ratio = yTot / xTot;
// interpolate y-coord of intermediate points across total width and height
double xCurr = 0.0;
double yCurr;
for (unsigned i = 0; i + 1 < item->spannerSegments().size(); i++) {
SpannerSegment* segm = item->segmentAt(i);
xCurr += segm->ipos2().x();
yCurr = y0 + ratio * xCurr;
segm->rypos2() = yCurr - segm->ipos().y(); // position segm. end point at yCurr
// next segment shall start where this segment stopped, corrected for the staff y-difference
SpannerSegment* nextSeg = item->segmentAt(i + 1);
yCurr += yStaffDifference(nextSeg->system(), nextSeg->staffIdx(), segm->system(), segm->staffIdx());
segm = nextSeg;
segm->rypos2() += segm->ipos().y() - yCurr; // adjust next segm. vertical length
segm->setPosY(yCurr); // position next segm. start point at yCurr
}

// KEEP CLEAR OF ALL ELEMENTS OF THE CHORD
// Remove offset already applied
offs1 *= -1.0;
offs2 *= -1.0;
// Look at chord shapes (but don't consider lyrics)
Shape cr1shape = cr1->shape();
mu::remove_if(cr1shape, [](ShapeElement& s) {
if (!s.toItem || s.toItem->isLyrics()) {
return true;
} else {
return false;
}
});
offs1.rx() += cr1shape.right() - anchor1->pos().x();
if (!cr2->staff()->isTabStaff(cr2->tick())) {
offs2.rx() -= cr2->shape().left() + anchor2->pos().x();
}
// Add note distance
const double glissNoteDist = 0.25 * item->spatium(); // TODO: style
offs1.rx() += glissNoteDist;
offs2.rx() -= glissNoteDist;

// apply offsets: shorten first segment by x1 (and proportionally y) and adjust its length accordingly
offs1.ry() = segm1->ipos2().y() * offs1.x() / segm1->ipos2().x();
segm1->setPos(segm1->ipos() + offs1);
segm1->setPos2(segm1->ipos2() - offs1);
// adjust last segment length by x2 (and proportionally y)
offs2.ry() = segm2->ipos2().y() * offs2.x() / segm2->ipos2().x();
segm2->setPos2(segm2->ipos2() + offs2);

for (SpannerSegment* segm : item->spannerSegments()) {
layoutItem(segm, ctx);
}

// compute glissando bbox as the bbox of the last segment, relative to the end anchor note
PointF anchor2PagePos = anchor2->pagePos();
PointF system2PagePos;
IF_ASSERT_FAILED(cr2->segment()->system()) {
system2PagePos = segm2->pos();
} else {
system2PagePos = cr2->segment()->system()->pagePos();
}

PointF anchor2SystPos = anchor2PagePos - system2PagePos;
RectF r = RectF(anchor2SystPos - segm2->pos(), anchor2SystPos - segm2->pos() - segm2->pos2()).normalized();
double lw = item->lineWidth() * .5;
item->setbbox(r.adjusted(-lw, -lw, lw, lw));

item->addLineAttachPoints();
//! NOTE Moved to PaletteLayout
UNREACHABLE;
}

void TLayout::layout(GlissandoSegment* item, LayoutContext&)
void TLayout::layout(GlissandoSegment*, LayoutContext&)
{
if (item->pos2().x() <= 0) {
item->setbbox(RectF());
return;
}

if (item->staff()) {
item->setMag(item->staff()->staffMag(item->tick()));
}
RectF r = RectF(0.0, 0.0, item->pos2().x(), item->pos2().y()).normalized();
double lw = item->glissando()->lineWidth() * .5;
item->setbbox(r.adjusted(-lw, -lw, lw, lw));
//! NOTE Moved to PaletteLayout
UNREACHABLE;
}

void TLayout::layout(GraceNotesGroup* item, LayoutContext& ctx)
Expand Down
35 changes: 35 additions & 0 deletions src/palette/internal/palettelayout.cpp
Expand Up @@ -27,6 +27,8 @@
#include "engraving/types/typesconv.h"
#include "engraving/types/symnames.h"

#include "engraving/compat/dummyelement.h"

#include "engraving/libmscore/engravingitem.h"
#include "engraving/libmscore/score.h"

Expand All @@ -44,6 +46,7 @@
#include "engraving/libmscore/expression.h"
#include "engraving/libmscore/fingering.h"
#include "engraving/libmscore/fret.h"
#include "engraving/libmscore/glissando.h"
#include "engraving/libmscore/gradualtempochange.h"
#include "engraving/libmscore/hairpin.h"
#include "engraving/libmscore/harppedaldiagram.h"
Expand Down Expand Up @@ -115,6 +118,8 @@ void PaletteLayout::layoutItem(EngravingItem* item)
break;
case ElementType::FRET_DIAGRAM: layout(toFretDiagram(item), ctx);
break;
case ElementType::GLISSANDO: layout(toGlissando(item), ctx);
break;
case ElementType::GRADUAL_TEMPO_CHANGE: layout(toGradualTempoChange(item), ctx);
break;
case ElementType::HAIRPIN: layout(toHairpin(item), ctx);
Expand Down Expand Up @@ -206,6 +211,11 @@ std::shared_ptr<IEngravingFont> PaletteLayout::Context::engravingFont() const
return m_score->engravingFont();
}

compat::DummyElement* PaletteLayout::Context::dummyParent() const
{
return m_score->dummy();
}

void PaletteLayout::layout(Accidental* item, const Context&)
{
SymId s = item->symId();
Expand Down Expand Up @@ -629,6 +639,31 @@ void PaletteLayout::layout(Dynamic* item, const Context& ctx)
layoutTextBase(item, ctx);
}

void PaletteLayout::layout(Glissando* item, const Context& ctx)
{
double spatium = item->spatium();

if (item->spannerSegments().empty()) {
item->add(item->createLineSegment(ctx.dummyParent()->system()));
}
LineSegment* s = item->frontSegment();
s->setPos(PointF(-spatium * Glissando::GLISS_PALETTE_WIDTH / 2, spatium * Glissando::GLISS_PALETTE_HEIGHT / 2));
s->setPos2(PointF(spatium * Glissando::GLISS_PALETTE_WIDTH, -spatium * Glissando::GLISS_PALETTE_HEIGHT));
layout(static_cast<GlissandoSegment*>(s), ctx);
}

void PaletteLayout::layout(GlissandoSegment* item, const Context&)
{
if (item->pos2().x() <= 0) {
item->setbbox(RectF());
return;
}

RectF r = RectF(0.0, 0.0, item->pos2().x(), item->pos2().y()).normalized();
double lw = item->glissando()->lineWidth() * .5;
item->setbbox(r.adjusted(-lw, -lw, lw, lw));
}

void PaletteLayout::layout(GradualTempoChange* item, const Context& ctx)
{
layoutLine(item, ctx);
Expand Down
9 changes: 9 additions & 0 deletions src/palette/internal/palettelayout.h
Expand Up @@ -50,6 +50,8 @@ class Expression;
class Fingering;
class FretDiagram;

class Glissando;
class GlissandoSegment;
class GradualTempoChange;
class GradualTempoChangeSegment;

Expand Down Expand Up @@ -102,6 +104,10 @@ class Volta;
class VoltaSegment;
}

namespace mu::engraving::compat {
class DummyElement;
}

namespace mu::palette {
class PaletteLayout
{
Expand All @@ -116,6 +122,7 @@ class PaletteLayout

const engraving::MStyle& style() const;
std::shared_ptr<engraving::IEngravingFont> engravingFont() const;
engraving::compat::DummyElement* dummyParent() const;

private:
engraving::Score* m_score = nullptr;
Expand All @@ -141,6 +148,7 @@ class PaletteLayout
static void layout(engraving::Fingering* item, const Context& ctx);
static void layout(engraving::FretDiagram* item, const Context& ctx);

static void layout(engraving::Glissando* item, const Context& ctx);
static void layout(engraving::GradualTempoChange* item, const Context& ctx);

static void layout(engraving::Hairpin* item, const Context& ctx);
Expand Down Expand Up @@ -178,6 +186,7 @@ class PaletteLayout
static void layout(engraving::Volta* item, const Context& ctx);

private:
static void layout(engraving::GlissandoSegment* item, const Context& ctx);
static void layout(engraving::GradualTempoChangeSegment* item, const Context& ctx);
static void layout(engraving::HairpinSegment* item, const Context& ctx);
static void layout(engraving::LetRingSegment* item, const Context& ctx);
Expand Down

0 comments on commit 4ccdf04

Please sign in to comment.