Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 64 additions & 15 deletions libmscore/chordrest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ ChordRest::ChordRest(Score* s)
_up = true;
_beamMode = Beam::Mode::AUTO;
_small = false;
_melismaEnd = false;
_crossMeasure = CrossMeasure::UNKNOWN;
}

Expand All @@ -80,7 +79,7 @@ ChordRest::ChordRest(const ChordRest& cr, bool link)
_beamMode = cr._beamMode;
_up = cr._up;
_small = cr._small;
_melismaEnd = cr._melismaEnd;
_melismaEnds = cr._melismaEnds;
_crossMeasure = cr._crossMeasure;

for (Lyrics* l : cr._lyrics) { // make deep copy
Expand Down Expand Up @@ -1232,20 +1231,31 @@ QString ChordRest::accessibleExtraInfo() const

bool ChordRest::isMelismaEnd() const
{
return _melismaEnd;
return !_melismaEnds.empty();
}

//---------------------------------------------------------
// setMelismaEnd
// removeMelismaEnd()
// removes a Lyrics object from the _melismaEnds set
// if present by iterating through the set.
// Returns a boolean representing whether the Lyrics
// was found.
// No-op and return false if Lyrics not present in _melismaEnds.
//---------------------------------------------------------

void ChordRest::setMelismaEnd(bool v)
bool ChordRest::removeMelismaEnd(const Lyrics* l)
{
_melismaEnd = v;
// TODO: don't take "false" at face value
// check to see if some other melisma ends here,
// in which case we can leave this set to true
// for now, rely on the fact that we'll generate the value correctly on layout
bool found = false;
for (std::set<Lyrics*>::iterator it = _melismaEnds.begin(); it != _melismaEnds.end(); ) {
if (*it == l) {
it = _melismaEnds.erase(it); // Returns next iterator
found = true;
}
else {
++it;
}
}
return found;
}

//---------------------------------------------------------
Expand All @@ -1256,6 +1266,8 @@ Shape ChordRest::shape() const
{
Shape shape;
{
// Add horizontal spacing for lyrics

qreal x1 = 1000000.0;
qreal x2 = -1000000.0;
bool adjustWidth = false;
Expand All @@ -1265,11 +1277,14 @@ Shape ChordRest::shape() const
qreal lmargin = score()->styleS(Sid::lyricsMinDistance).val() * spatium() * 0.5;
qreal rmargin = lmargin;
Lyrics::Syllabic syl = l->syllabic();
if ((syl == Lyrics::Syllabic::BEGIN || syl == Lyrics::Syllabic::MIDDLE) && score()->styleB(Sid::lyricsDashForce))
bool hasHyphen = syl == Lyrics::Syllabic::BEGIN || syl == Lyrics::Syllabic::MIDDLE;
if (hasHyphen && score()->styleB(Sid::lyricsDashForce))
rmargin = qMax(rmargin, styleP(Sid::lyricsDashMinLength));
// for horizontal spacing we only need the lyrics width:
// for horizontal spacing we only need the lyrics' width:
x1 = qMin(x1, l->bbox().x() - lmargin + l->pos().x());
x2 = qMax(x2, l->bbox().x() + l->bbox().width() + rmargin + l->pos().x());
// Melismas (without hyphens) only create right spacing on their last note
if (!l->isMelisma() || hasHyphen)
x2 = qMax(x2, l->bbox().x() + l->bbox().width() + rmargin + l->pos().x());
if (l->ticks() == Fraction::fromTicks(Lyrics::TEMP_MELISMA_TICKS))
x2 += spatium();
adjustWidth = true;
Expand All @@ -1279,6 +1294,8 @@ Shape ChordRest::shape() const
}

{
// Add horizontal spacing for annotations

qreal x1 = 1000000.0;
qreal x2 = -1000000.0;
bool adjustWidth = false;
Expand All @@ -1288,20 +1305,52 @@ Shape ChordRest::shape() const
if (e->isHarmony() && e->staffIdx() == staffIdx()) {
Harmony* h = toHarmony(e);
// calculate bbox only (do not reset position)
h->layout1();
if (h->bbox().isEmpty()) h->layout1();
const qreal margin = styleP(Sid::minHarmonyDistance) * 0.5;
x1 = qMin(x1, e->bbox().x() - margin + e->pos().x());
x2 = qMax(x2, e->bbox().x() + e->bbox().width() + margin + e->pos().x());
adjustWidth = true;
}
else if (e->isFretDiagram()) {
FretDiagram* fd = toFretDiagram(e);
if (fd->bbox().isEmpty()) fd->calculateBoundingRect();
qreal margin = styleP(Sid::fretMinDistance) * 0.5;
x1 = qMin(x1, e->bbox().x() - margin + e->pos().x());
x2 = qMax(x2, e->bbox().x() + e->bbox().width() + margin + e->pos().x());
adjustWidth = true;
if (fd->harmony()) {
Harmony* h = fd->harmony();
if (h->bbox().isEmpty()) h->layout1();
margin = styleP(Sid::minHarmonyDistance) * 0.5;
x1 = qMin(x1, h->bbox().x() - margin + h->pos().x() + e->pos().x());
x2 = qMax(x2, h->bbox().x() + h->bbox().width() + margin + h->pos().x() + e->pos().x());
adjustWidth = true;
}
}
}
if (adjustWidth)
shape.addHorizontalSpacing(Shape::SPACING_HARMONY, x1, x2);
}

if (isMelismaEnd()) {
// Add horizontal spacing (only on the right) for melismaEnds
// in case a melisma syllable extends beyond its last note.
// TODO: distribute this extra spacing rather than dumping
// it all on the last note (or otherwise overhaul horizontal spacing).
// TODO: this doesn't redraw on layout reset (like line breaks),
// causing temporary incorrect rendering.

qreal rmargin = score()->styleS(Sid::lyricsMinDistance).val() * spatium() * 0.5;
qreal right = rightEdge();
shape.addHorizontalSpacing(Shape::SPACING_LYRICS, right, right);

for (Lyrics* me : melismaEnds()) {
if (me->measure()->system() != measure()->system()) // ignore cross-system melisma
continue;
// Lyric's right edge relative to Chord by way of page position
qreal meRight = me->pageBoundingRect().right() + rmargin - pagePos().x();
right = qMax(right, meRight);
}
shape.addHorizontalSpacing(Shape::SPACING_LYRICS, 0, right);
}

return shape;
Expand Down
6 changes: 4 additions & 2 deletions libmscore/chordrest.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ class ChordRest : public DurationElement {
Beam::Mode _beamMode;
bool _up; // actual stem direction
bool _small;
bool _melismaEnd;
std::set<Lyrics*> _melismaEnds; // lyrics ending on this ChordRest, used for spacing

// CrossMeasure: combine 2 tied notes if across a bar line and can be combined in a single duration
CrossMeasure _crossMeasure; ///< 0: no cross-measure modification; 1: 1st note of a mod.; -1: 2nd note
Expand Down Expand Up @@ -138,8 +138,10 @@ class ChordRest : public DurationElement {
std::vector<Lyrics*>& lyrics() { return _lyrics; }
Lyrics* lyrics(int verse, Placement) const;
int lastVerse(Placement) const;
const std::set<Lyrics*>& melismaEnds() const { return _melismaEnds; }
std::set<Lyrics*>& melismaEnds() { return _melismaEnds; }
bool removeMelismaEnd(const Lyrics* l);
bool isMelismaEnd() const;
void setMelismaEnd(bool v);

virtual void add(Element*);
virtual void remove(Element*);
Expand Down
14 changes: 11 additions & 3 deletions libmscore/fret.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -452,10 +452,10 @@ void FretDiagram::draw(QPainter* painter) const
}

//---------------------------------------------------------
// layout
// calculateBoundingRect()
//---------------------------------------------------------

void FretDiagram::layout()
void FretDiagram::calculateBoundingRect()
{
qreal _spatium = spatium() * _userMag;
stringLw = _spatium * 0.08;
Expand Down Expand Up @@ -492,7 +492,15 @@ void FretDiagram::layout()
}

bbox().setRect(x, y, w, h);
}

//---------------------------------------------------------
// layout
//---------------------------------------------------------

void FretDiagram::layout()
{
calculateBoundingRect();
if (!parent() || !parent()->isSegment()) {
setPos(QPointF());
return;
Expand Down Expand Up @@ -522,7 +530,7 @@ void FretDiagram::layout()
mainWidth = stringDist * (_strings - 1);
else if (_orientation == Orientation::HORIZONTAL)
mainWidth = fretDist * (_frets + 0.5);
setPos((noteheadWidth - mainWidth)/2, -(h + styleP(Sid::fretY)));
setPos((noteheadWidth - mainWidth)/2, -(bbox().height() + styleP(Sid::fretY)));

autoplaceSegmentElement();

Expand Down
1 change: 1 addition & 0 deletions libmscore/fret.h
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ class FretDiagram final : public Element {

ElementType type() const override { return ElementType::FRET_DIAGRAM; }
void layout() override;
void calculateBoundingRect();
void write(XmlWriter& xml) const override;
void writeNew(XmlWriter& xml) const;
void writeOld(XmlWriter& xml) const;
Expand Down
11 changes: 4 additions & 7 deletions libmscore/lyrics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ void Lyrics::remove(Element* el)
if (!e)
e = score()->findCRinStaff(_separator->tick2(), track());
if (e && e->isChordRest())
toChordRest(e)->setMelismaEnd(false);
toChordRest(e)->removeMelismaEnd(this);
#endif
// Lyrics::remove() and LyricsLine::removeUnmanaged() call each other;
// be sure each finds a clean context
Expand Down Expand Up @@ -368,7 +368,7 @@ void Lyrics::layout()
// set melisma end
ChordRest* ecr = score()->findCR(endTick(), track());
if (ecr)
ecr->setMelismaEnd(true);
ecr->melismaEnds().insert(this);
}

}
Expand Down Expand Up @@ -525,7 +525,7 @@ void Lyrics::removeFromScore()
// clear melismaEnd flag from end cr
ChordRest* ecr = score()->findCR(endTick(), track());
if (ecr)
ecr->setMelismaEnd(false);
ecr->removeMelismaEnd(this);
}
if (_separator) {
_separator->removeUnmanaged();
Expand Down Expand Up @@ -567,16 +567,13 @@ bool Lyrics::setProperty(Pid propertyId, const QVariant& v)
break;
case Pid::LYRIC_TICKS:
if (_ticks.isNotZero()) {
// clear melismaEnd flag from previous end cr
// this might be premature, as there may be other melismas ending there
// but flag will be generated correctly on layout
// TODO: after inserting a measure,
// endTick info is wrong.
// Somehow we need to fix this.
// See https://musescore.org/en/node/285304 and https://musescore.org/en/node/311289
ChordRest* ecr = score()->findCR(endTick(), track());
if (ecr)
ecr->setMelismaEnd(false);
ecr->removeMelismaEnd(this);
}
_ticks = v.value<Fraction>();
break;
Expand Down
2 changes: 1 addition & 1 deletion libmscore/lyrics.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ class Lyrics final : public TextBase {
Syllabic _syllabic;
LyricsLine* _separator;

bool isMelisma() const;
void undoChangeProperty(Pid id, const QVariant&, PropertyFlags ps) override;

protected:
Expand Down Expand Up @@ -93,6 +92,7 @@ class Lyrics final : public TextBase {
Fraction ticks() const { return _ticks; }
void setTicks(const Fraction& tick) { _ticks = tick; }
Fraction endTick() const;
bool isMelisma() const;
void removeFromScore();

using ScoreElement::undoChangeProperty;
Expand Down
4 changes: 4 additions & 0 deletions libmscore/shape.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,11 @@ void Shape::addHorizontalSpacing(HorizontalSpacingType type, qreal leftEdge, qre
const qreal y = eps * int(type);
if (leftEdge == rightEdge) // HACK zero-width shapes collide with everything currently.
rightEdge += eps;
#ifndef NDEBUG
add(QRectF(leftEdge, y, rightEdge - leftEdge, 0), "Horizontal Spacing");
#else
add(QRectF(leftEdge, y, rightEdge - leftEdge, 0));
#endif
}

//---------------------------------------------------------
Expand Down
Loading