Skip to content

Commit

Permalink
Merge pull request #5876 from njvdberg/issue-293785-jumping-harmonies
Browse files Browse the repository at this point in the history
Fix #293785: Fix #302590: Fix #294890: Chord symbols jump when user goes into edit…
  • Loading branch information
anatoly-os authored Apr 28, 2020
2 parents df0e501 + 9946fb7 commit 45fd0fa
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 67 deletions.
2 changes: 1 addition & 1 deletion libmscore/element.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -473,7 +473,7 @@ QPointF Element::canvasPos() const
else if (parent()->isChord()) // grace chord
measure = toSegment(parent()->parent())->measure();
else if (parent()->isFretDiagram())
return p + parent()->canvasPos();
return p + parent()->canvasPos() + QPointF(toFretDiagram(parent())->centerX(), 0.0);
else
qFatal("this %s parent %s\n", name(), parent()->name());
if (measure) {
Expand Down
15 changes: 8 additions & 7 deletions libmscore/fret.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,7 @@ void FretDiagram::draw(QPainter* painter) const
case FretDotType::TRIANGLE:
painter->drawLine(QLineF(x, y + dotd, x + .5 * dotd, y));
painter->drawLine(QLineF(x + .5 * dotd, y, x + dotd, y + dotd));
painter->drawLine(QLineF(x + dotd, y + dotd, x, y + dotd));
painter->drawLine(QLineF(x + dotd, y + dotd, x, y + dotd));
break;
case FretDotType::NORMAL:
default:
Expand Down Expand Up @@ -465,7 +465,7 @@ void FretDiagram::layout()
int si = staffIdx();

SysStaff* ss = m->system()->staff(si);
QRectF r = _harmony->bbox().translated(m->pos() + s->pos() + pos() + _harmony->pos());
QRectF r = _harmony->bbox().translated(m->pos() + s->pos() + pos() + _harmony->pos() + QPointF(_harmony->xShapeOffset(), 0.0));

qreal minDistance = _harmony->minDistance().val() * spatium();
SkylineLine sk(false);
Expand All @@ -485,6 +485,7 @@ void FretDiagram::layout()
//---------------------------------------------------------
// centerX
/// used by harmony for layout. Keep in sync with layout, same dotd and x as above
// also used in Element::canvasPos().
//---------------------------------------------------------

qreal FretDiagram::centerX() const
Expand Down Expand Up @@ -700,9 +701,9 @@ void FretDiagram::read(XmlReader& e)
}
if (tag == "fretDiagram") {
readNew(e);
haveReadNew = true;
haveReadNew = true;
}

// Check for new properties
else if (tag == "showNut")
readProperty(e, Pid::FRET_NUT);
Expand Down Expand Up @@ -888,7 +889,7 @@ void FretDiagram::setBarre(int string, int fret, bool add /*= false*/)
_barres[fret] = FretItem::Barre(string, -1);
removeDotsMarkers(string, -1, fret);
}
}
}
else if (b.endString == -1 && b.startString < string) {
_barres[fret].endString = string;
}
Expand Down Expand Up @@ -967,7 +968,7 @@ void FretDiagram::removeBarres(int string, int fret /*= 0*/)
else
++iter;
}
}
}

//---------------------------------------------------------
// removeMarker
Expand Down Expand Up @@ -1049,7 +1050,7 @@ void FretDiagram::undoFretClear()

//---------------------------------------------------------
// dot
// take fret value of zero to mean all dots
// take fret value of zero to mean all dots
//---------------------------------------------------------

std::vector<FretItem::Dot> FretDiagram::dot(int s, int f /*= 0*/) const
Expand Down
136 changes: 79 additions & 57 deletions libmscore/harmony.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ Harmony::Harmony(const Harmony& h)
_realizedHarmony.setHarmony(this);
for (const TextSegment* s : h.textList) {
TextSegment* ns = new TextSegment();
ns->set(s->text, s->font, s->x, s->y);
ns->set(s->text, s->font, s->x, s->y, s->offset);
textList.append(ns);
}
}
Expand Down Expand Up @@ -1269,53 +1269,7 @@ void Harmony::layout()
//if (isStyled(Pid::OFFSET))
// setOffset(propertyDefault(Pid::OFFSET).toPointF());

if (placeBelow())
rypos() = staff() ? staff()->height() : 0.0;
else
rypos() = 0.0;
layout1();

qreal yy = ipos().y();
qreal xx = 0.0;

if (parent()->isFretDiagram()) {
if (isStyled(Pid::ALIGN))
setAlign(Align::HCENTER | Align::BASELINE);
yy = -score()->styleP(Sid::harmonyFretDist);
}

qreal hb = lineHeight() - TextBase::baseLine();
if (align() & Align::BOTTOM)
yy -= hb;
else if (align() & Align::VCENTER) {
yy -= hb;
yy += (height() * .5);
}
else if (align() & Align::BASELINE) {
}
else { // Align::TOP
yy -= hb;
yy += height();
}

qreal cw = symWidth(SymId::noteheadBlack);
if (align() & Align::RIGHT) {
xx += cw;
xx -= width();
}
else if (align() & Align::HCENTER) {
if (parent()->isFretDiagram()) {
FretDiagram* fd = toFretDiagram(parent());
xx += fd->centerX();
xx -= width() * .5;
}
else {
xx += (cw * .5);
xx -= (width() * .5);
}
}

setPos(xx, yy);
}

//---------------------------------------------------------
Expand All @@ -1340,13 +1294,67 @@ void Harmony::layout1()

void Harmony::calculateBoundingRect()
{
if (textList.empty())
const qreal ypos = (placeBelow() && staff()) ? staff()->height() : 0.0;
const FretDiagram* fd = (parent() && parent()->isFretDiagram()) ? toFretDiagram(parent()) : nullptr;
const qreal cw = symWidth(SymId::noteheadBlack);

if (textList.empty()) {
TextBase::layout1();

// When in EDIT mode, the bbox is different as in NORMAL mode.
// Adjust the position so the both bbox have the same alignment.

qreal xx = 0.0;
qreal yy = 0.0;
if (fd) {
if (align() & Align::RIGHT)
xx = fd->width() / 2.0;
yy = rypos();
}
else {
if (align() & Align::RIGHT)
xx = cw;
else if (align() & Align::HCENTER)
xx = cw / 2.0;
yy = ypos - ((align() & Align::BOTTOM) ? _harmonyHeight - bbox().height() : 0.0);
}

setPos(xx, yy);
}
else {
QRectF bb;
for (const TextSegment* ts : textList)
for (TextSegment* ts : textList)
bb |= ts->tightBoundingRect().translated(ts->x, ts->y);
setbbox(bb);

qreal yy = -bb.y(); // Align::TOP
if (align() & Align::VCENTER)
yy = -bb.y() / 2.0;
else if (align() & Align::BASELINE)
yy = 0.0;
else if (align() & Align::BOTTOM)
yy = -bb.height() - bb.y();

qreal xx = -bb.x(); // Align::LEFT
if (fd) {
if (align() & Align::RIGHT)
xx = fd->bbox().width() - bb.width();
else if (align() & Align::HCENTER)
xx = fd->centerX() - bb.width() / 2.0;
}
else {
if (align() & Align::RIGHT)
xx = -bb.x() -bb.width() + cw;
else if (align() & Align::HCENTER)
xx = -bb.x() -bb.width() / 2.0 + cw / 2.0;
}

for (TextSegment* ts : textList)
ts->offset = QPointF(xx, yy);

setbbox(bb.translated(xx, yy));
setPos(0.0, fd ? rypos() : ypos);
_harmonyHeight = bbox().height();

for (int i = 0; i < rows(); ++i) {
TextBlock& t = textBlockList()[i];

Expand All @@ -1355,12 +1363,24 @@ void Harmony::calculateBoundingRect()
// To correct placement of text in editing we need to layout textBlockList() elements
t.layout(this);
for (auto& s : t.fragments()) {
s.pos = { 0, 0 };
s.pos = { 0.0 , 0.0 };
}

}
}
}

//---------------------------------------------------------
// xShapeOffset
// Returns the offset for the shapes.
//---------------------------------------------------------

qreal Harmony::xShapeOffset() const
{
const FretDiagram* fd = (parent() && parent()->isFretDiagram()) ? toFretDiagram(parent()) : nullptr;
return (fd && textList.empty()) ? fd->centerX() : 0.0;
}

//---------------------------------------------------------
// draw
//---------------------------------------------------------
Expand Down Expand Up @@ -1399,7 +1419,7 @@ void Harmony::draw(QPainter* painter) const
QFont f(ts->font);
f.setPointSizeF(f.pointSizeF() * MScore::pixelRatio);
painter->setFont(f);
painter->drawText(QPointF(ts->x, ts->y), ts->text);
painter->drawText(ts->pos(), ts->text);
}
}

Expand Down Expand Up @@ -1432,7 +1452,8 @@ void Harmony::drawEditMode(QPainter* p, EditData& ed)

TextSegment::TextSegment(const QString& s, const QFont& f, qreal x, qreal y)
{
set(s, f, x, y);
QPointF offset(0.0, 0.0);
set(s, f, x, y, offset);
select = false;
}

Expand Down Expand Up @@ -1481,11 +1502,12 @@ QRectF TextSegment::tightBoundingRect() const
// set
//---------------------------------------------------------

void TextSegment::set(const QString& s, const QFont& f, qreal _x, qreal _y)
void TextSegment::set(const QString& s, const QFont& f, qreal _x, qreal _y, QPointF _offset)
{
font = f;
x = _x;
y = _y;
font = f;
x = _x;
y = _y;
offset = _offset;
setText(s);
}

Expand Down
8 changes: 6 additions & 2 deletions libmscore/harmony.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,17 +29,19 @@ class ParsedChord;
struct TextSegment {
QFont font;
QString text;
qreal x, y;
qreal x, y; // Position of segments relative to each other.
QPointF offset; // Offset for placing within the TextBase.
bool select;

qreal width() const;
QRectF boundingRect() const;
QRectF tightBoundingRect() const;
QPointF pos() const { return QPointF(x, y) + offset; };

TextSegment() { select = false; x = y = 0.0; }
TextSegment(const QFont& f, qreal _x, qreal _y) : font(f), x(_x), y(_y), select(false) {}
TextSegment(const QString&, const QFont&, qreal x, qreal y);
void set(const QString&, const QFont&, qreal x, qreal y);
void set(const QString&, const QFont&, qreal x, qreal y, QPointF offset);
void setText(const QString& t) { text = t; }
};

Expand Down Expand Up @@ -83,6 +85,7 @@ class Harmony final : public TextBase {
ParsedChord* _parsedForm; // parsed form of chord
bool showSpell = false; // show spell check warning
HarmonyType _harmonyType; // used to control rendering, transposition, export, etc.
qreal _harmonyHeight; // used for calculating the the height is frame while editing.

RealizedHarmony _realizedHarmony; //the realized harmony used for playback

Expand Down Expand Up @@ -201,6 +204,7 @@ class Harmony final : public TextBase {
void localSpatiumChanged(qreal oldValue, qreal newValue) override;
void setHarmony(const QString& s);
void calculateBoundingRect();
qreal xShapeOffset() const;

QString userName() const override;
QString accessibleInfo() const override;
Expand Down

1 comment on commit 45fd0fa

@github-actions
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an automatic message. This commit appears to change some of the visual tests.
Please carefully review the new visual test results in the uploaded artifact that can be found
here

Please sign in to comment.