Lyrics: Better dash control

This patch gives better control on lyrics dash management and it is intended to supersede https://github.com/musescore/MuseScore/pull/2213 which did not suit the taste of several forum users; for a discussion, see https://musescore.org/en/node/76021 .

Adds 3 new score style parameters:
- `lyricsDashMinLength` to control the minimum dash length (default: 0.4sp)
- `lyricsDashMaxLength` to control the maximum dash length (default: 0.8sp)
- `lyricsDashForce`: if set to __true__, a dash is always generated between two syllables of a word and, if there is not enough space for the min dash length, more space is added between the syllables to accommodate it; if set to __false__, no extra space is added and the two syllables are joined together (default: true)

The effect of the last parameter is exemplified by the following screen-shots:

Current situation (before this patch); if there is no room for the min dash length, the dash is skipped and some blank is left between syllables:

Patch with `lyricsDashForce = true`; chords are further spaced and a min-length dash is inserted:

Patch with `lyricsDashForce = false`: the second syllable is moved (slightly) to the left to reclaim the blank:
This commit is contained in:
Maurizio M. Gavioli 2015-10-03 23:55:33 +02:00
parent 79ea7ff7d9
commit 8c017d8536
9 changed files with 163 additions and 16 deletions

View file

@ -3825,6 +3825,8 @@ qreal Score::computeMinWidth(Segment* fs, bool firstMeasureInSystem)
qreal minNoteDistance = styleS(StyleIdx::minNoteDistance).val() * _spatium;
qreal minHarmonyDistance = styleS(StyleIdx::minHarmonyDistance).val() * _spatium;
qreal maxHarmonyBarDistance = styleS(StyleIdx::maxHarmonyBarDistance).val() * _spatium;
qreal minLyricsDashWidth = (styleS(StyleIdx::lyricsDashMinLength).val()
+ Lyrics::LYRICS_DASH_DEFAULT_PAD * 2) * _spatium;
qreal rest[_nstaves]; // fixed space needed from previous segment
memset(rest, 0, _nstaves * sizeof(qreal));
@ -3986,8 +3988,15 @@ qreal Score::computeMinWidth(Segment* fs, bool firstMeasureInSystem)
if (!l->isEmpty()) {
lyrics = l;
QRectF b(l->bbox().translated(l->pos()));
qreal brgt = b.right();
// if lyrics followed by a dash & score style requires the dash in any case,
// reserve at least the min dash length plus before and after padding
if ( (l->syllabic() == Lyrics::Syllabic::BEGIN
|| l->syllabic() == Lyrics::Syllabic::MIDDLE)
&& styleB(StyleIdx::lyricsDashForce) )
brgt += minLyricsDashWidth;
llw = qMax(llw, -(b.left()+lx+cx));
rrw = qMax(rrw, b.right()+rx+cx);
rrw = qMax(rrw, brgt+rx+cx);
}
}
}

View file

@ -868,17 +868,18 @@ void LyricsLineSegment::layout()
_dashLength = lyr->dashLength();
#else
rypos() -= lyr->bbox().height() * Lyrics::LYRICS_DASH_Y_POS_RATIO; // set conventional dash Y pos
_dashLength = Lyrics::LYRICS_DASH_DEFAULT_LENGTH * sp; // and dash length
_dashLength = score()->styleS(StyleIdx::lyricsDashMaxLength).val() * sp; // and dash length
#endif
qreal len = pos2().x();
qreal minDashLen = Lyrics::LYRICS_DASH_MIN_LENGTH * sp;
qreal minDashLen = score()->styleS(StyleIdx::lyricsDashMinLength).val() * sp;
if (len < minDashLen) { // if no room for a dash
if (endOfSystem) { // if at end of system
// if at end of system or dash is forced
if (endOfSystem || score()->styleB(StyleIdx::lyricsDashForce)) {
rxpos2() = minDashLen; // draw minimal dash
_numOfDashes = 1;
_dashLength = minDashLen;
}
else // if within system
else // if within system or dash not forced
_numOfDashes = 0; // draw no dash
}
else if (len < (Lyrics::LYRICS_DASH_DEFAULT_STEP * TWICE * sp)) { // if no room for two dashes

View file

@ -62,11 +62,10 @@ class Lyrics : public Text {
static constexpr qreal MELISMA_DEFAULT_PAD = 0.10; // the empty space before a melisma line
static constexpr qreal LYRICS_DASH_DEFAULT_STEP = 16.0; // the max. distance between dashes
static constexpr qreal LYRICS_DASH_DEFAULT_PAD = 0.05; // the min. empty space before and after a dash
static constexpr qreal LYRICS_DASH_MIN_LENGTH = 0.25; // below this length, the dash is skipped
static constexpr qreal LYRICS_WORD_MIN_DISTANCE = 0.33; // min. distance between lyrics from different words
// WORD_MIN_DISTANCE has never been implemented
// static constexpr qreal LYRICS_WORD_MIN_DISTANCE = 0.33; // min. distance between lyrics from different words
// These values are used when USE_FONT_DASH_METRIC is not defined
#if !defined(USE_FONT_DASH_METRIC)
static constexpr qreal LYRICS_DASH_DEFAULT_LENGTH = 0.80; // in sp. units
static constexpr qreal LYRICS_DASH_DEFAULT_LINE_THICKNESS = 0.15; // in sp. units
static constexpr qreal LYRICS_DASH_Y_POS_RATIO = 0.25; // the fraction of lyrics font tot. height to
// raise the dashes above text base line;

View file

@ -3128,6 +3128,8 @@ void Measure::layoutX(qreal stretch)
qreal clefKeyRightMargin = score()->styleS(StyleIdx::clefKeyRightMargin).val() * _spatium;
qreal minHarmonyDistance = score()->styleS(StyleIdx::minHarmonyDistance).val() * _spatium;
qreal maxHarmonyBarDistance = score()->styleS(StyleIdx::maxHarmonyBarDistance).val() * _spatium;
qreal minLyricsDashWidth = (score()->styleS(StyleIdx::lyricsDashMinLength).val()
+ Lyrics::LYRICS_DASH_DEFAULT_PAD * 2) * _spatium;
qreal rest[nstaves]; // fixed space needed from previous segment
memset(rest, 0, nstaves * sizeof(qreal));
@ -3324,8 +3326,15 @@ void Measure::layoutX(qreal stretch)
continue;
lyrics = l;
QRectF b(l->bbox().translated(l->pos()));
qreal brgt = b.right();
// if lyrics followed by a dash & score style requires the dash in any case,
// reserve at least the min dash length plus before and after padding
if ( (l->syllabic() == Lyrics::Syllabic::BEGIN
|| l->syllabic() == Lyrics::Syllabic::MIDDLE)
&& score()->styleB(StyleIdx::lyricsDashForce) )
brgt += minLyricsDashWidth;
llw = qMax(llw, -(b.left()+lx+cx));
rrw = qMax(rrw, b.right()+rx+cx);
rrw = qMax(rrw, brgt+rx+cx);
}
}
if (lyrics) {

View file

@ -234,7 +234,10 @@ static const StyleTypes2 styleTypes2[] = {
{ StyleIdx::barreLineWidth, StyleType("barreLineWidth", StyleValueType::DOUBLE) },
{ StyleIdx::fretMag, StyleType("fretMag", StyleValueType::DOUBLE) },
{ StyleIdx::scaleBarlines, StyleType("scaleBarlines", StyleValueType::BOOL) },
{ StyleIdx::barGraceDistance, StyleType("barGraceDistance", StyleValueType::SPATIUM) }
{ StyleIdx::barGraceDistance, StyleType("barGraceDistance", StyleValueType::SPATIUM) },
{ StyleIdx::lyricsDashMinLength, StyleType("lyricsDashMinLength", StyleValueType::SPATIUM) },
{ StyleIdx::lyricsDashMaxLength, StyleType("lyricsDashMaxLegth", StyleValueType::SPATIUM) },
{ StyleIdx::lyricsDashForce, StyleType("lyricsDashForce", StyleValueType::BOOL) }
};
class StyleTypes {
@ -598,6 +601,9 @@ StyleData::StyleData()
{ StyleIdx::fretMag, QVariant(1.0) },
{ StyleIdx::scaleBarlines, QVariant(true) },
{ StyleIdx::barGraceDistance, QVariant(.6) },
{ StyleIdx::lyricsDashMinLength, QVariant(0.4) },
{ StyleIdx::lyricsDashMaxLength, QVariant(0.8) },
{ StyleIdx::lyricsDashForce, QVariant(true) }
};
for (unsigned i = 0; i < sizeof(values2)/sizeof(*values2); ++i)
_values[int(values2[i].idx)] = values2[i].val;

View file

@ -373,7 +373,9 @@ enum class StyleIdx : unsigned char {
fretMag,
scaleBarlines,
barGraceDistance,
lyricsDashMinLength,
lyricsDashMaxLength,
lyricsDashForce,
STYLES
};

View file

@ -288,6 +288,8 @@ EditStyle::EditStyle(Score* s, QWidget* parent)
connect(swingEighth, SIGNAL(toggled(bool)), SLOT(setSwingParams(bool)));
connect(swingSixteenth, SIGNAL(toggled(bool)), SLOT(setSwingParams(bool)));
connect(hideEmptyStaves, SIGNAL(clicked(bool)), dontHideStavesInFirstSystem, SLOT(setEnabled(bool)));
connect(lyricsDashMinLength, SIGNAL(valueChanged(double)), SLOT(lyricsDashMinLengthValueChanged(double)));
connect(lyricsDashMaxLength, SIGNAL(valueChanged(double)), SLOT(lyricsDashMaxLengthValueChanged(double)));
QSignalMapper* mapper = new QSignalMapper(this);
@ -439,6 +441,9 @@ void EditStyle::getValues()
lstyle.set(StyleIdx::smallStaffMag, smallStaffSize->value() / 100.0);
lstyle.set(StyleIdx::smallNoteMag, smallNoteSize->value() / 100.0);
lstyle.set(StyleIdx::smallClefMag, smallClefSize->value() / 100.0);
lstyle.set(StyleIdx::lyricsDashMinLength, lyricsDashMinLength->value());
lstyle.set(StyleIdx::lyricsDashMaxLength, lyricsDashMaxLength->value());
lstyle.set(StyleIdx::lyricsDashForce, lyricsDashForce->isChecked());
lstyle.set(StyleIdx::lastSystemFillLimit, lastSystemFillThreshold->value() / 100.0);
lstyle.set(StyleIdx::genClef, genClef->isChecked());
lstyle.set(StyleIdx::genKeysig, genKeysig->isChecked());
@ -658,6 +663,9 @@ void EditStyle::setValues()
smallStaffSize->setValue(lstyle.value(StyleIdx::smallStaffMag).toDouble() * 100.0);
smallNoteSize->setValue(lstyle.value(StyleIdx::smallNoteMag).toDouble() * 100.0);
smallClefSize->setValue(lstyle.value(StyleIdx::smallClefMag).toDouble() * 100.0);
lyricsDashMinLength->setValue(lstyle.value(StyleIdx::lyricsDashMinLength).toDouble());
lyricsDashMaxLength->setValue(lstyle.value(StyleIdx::lyricsDashMaxLength).toDouble());
lyricsDashForce->setChecked(lstyle.value(StyleIdx::lyricsDashForce).toBool());
lastSystemFillThreshold->setValue(lstyle.value(StyleIdx::lastSystemFillLimit).toDouble() * 100.0);
genClef->setChecked(lstyle.value(StyleIdx::genClef).toBool());
@ -912,6 +920,26 @@ void EditStyle::toggleFooterOddEven(bool checked)
return;
}
//---------------------------------------------------------
// lyricsDashMin/MaxLengthValueChanged
//
// Ensure lyricsDashMinLength <= lyricsDashMaxLength
//---------------------------------------------------------
void EditStyle::lyricsDashMaxLengthValueChanged(double val)
{
double otherVal = lyricsDashMinLength->value();
if (otherVal > val)
lyricsDashMaxLength->setValue(otherVal);
}
void EditStyle::lyricsDashMinLengthValueChanged(double val)
{
double otherVal = lyricsDashMaxLength->value();
if (otherVal < val)
lyricsDashMaxLength->setValue(otherVal);
}
//---------------------------------------------------------
// setPage
//---------------------------------------------------------

View file

@ -68,6 +68,8 @@ class EditStyle : public QDialog, private Ui::EditStyleBase {
void toggleFooterOddEven(bool);
void buttonClicked(QAbstractButton*);
void setSwingParams(bool);
void lyricsDashMinLengthValueChanged(double val);
void lyricsDashMaxLengthValueChanged(double val);
void resetStyleValue(int i);
void on_comboFBFont_currentIndexChanged(int index);

View file

@ -3560,15 +3560,15 @@
</property>
</widget>
</item>
<item row="4" column="0">
<spacer>
<item row="0" column="2">
<spacer name="horizontalSpacer_24">
<property name="orientation">
<enum>Qt::Vertical</enum>
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>181</height>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
@ -3576,6 +3576,97 @@
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="lyricsDashGroup">
<property name="title">
<string>Lyrics Dash</string>
</property>
<layout class="QGridLayout" name="gridLayout_18">
<item row="1" column="0">
<widget class="QLabel" name="label_80">
<property name="text">
<string>Max. dash length:</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="lyricsDashForce">
<property name="text">
<string>Always force dash</string>
</property>
</widget>
</item>
<item row="0" column="2">
<spacer name="horizontalSpacer_23">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="1">
<widget class="QDoubleSpinBox" name="lyricsDashMaxLength">
<property name="suffix">
<string>sp</string>
</property>
<property name="minimum">
<double>0.050000000000000</double>
</property>
<property name="maximum">
<double>9.990000000000000</double>
</property>
<property name="singleStep">
<double>0.050000000000000</double>
</property>
<property name="value">
<double>0.800000000000000</double>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QDoubleSpinBox" name="lyricsDashMinLength">
<property name="suffix">
<string>sp</string>
</property>
<property name="maximum">
<double>9.990000000000000</double>
</property>
<property name="singleStep">
<double>0.050000000000000</double>
</property>
<property name="value">
<double>0.400000000000000</double>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_93">
<property name="text">
<string>Min. dash length:</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer_21">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<widget class="QWidget" name="Page13">