Skip to content

Commit

Permalink
Fix #325982: Allow for strike-through text
Browse files Browse the repository at this point in the history
Backport of musescore#9630
  • Loading branch information
Jojo-Schmitz committed Nov 30, 2021
1 parent d8aeb27 commit 5a578a6
Show file tree
Hide file tree
Showing 25 changed files with 211 additions and 25 deletions.
3 changes: 3 additions & 0 deletions importexport/musicxml/exportxml.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -598,6 +598,9 @@ static QString fontStyleToXML(const FontStyle style, bool allowUnderline = true)
res += " font-style=\"italic\"";
if (allowUnderline && style & FontStyle::Underline)
res += " underline=\"1\"";
// at places where underline is not wanted (e.g. fingering, pluck), strike is not wanted too
if (allowUnderline && style & FontStyle::Strike)
res += " line-through=\"1\"";
return res;
}

Expand Down
13 changes: 12 additions & 1 deletion importexport/musicxml/importmxmlpass1.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1316,6 +1316,7 @@ static QString nextPartOfFormattedString(QXmlStreamReader& e)
QString fontSize = e.attributes().value("font-size").toString();
QString fontStyle = e.attributes().value("font-style").toString();
QString underline = e.attributes().value("underline").toString();
QString strike = e.attributes().value("line-through").toString();
QString fontFamily = e.attributes().value("font-family").toString();
// TODO: color, enclosure, yoffset in only part of the text, ...

Expand Down Expand Up @@ -1346,11 +1347,19 @@ static QString nextPartOfFormattedString(QXmlStreamReader& e)
if (!underline.isEmpty()) {
bool ok = true;
int lines = underline.toInt(&ok);
if (ok && (lines > 0)) // 1,2, or 3 underlines are imported as single underline
if (ok && (lines > 0)) // 1, 2, or 3 underlines are imported as single underline
importedtext += "<u>";
else
underline = "";
}
if (!strike.isEmpty()) {
bool ok = true;
int lines = strike.toInt(&ok);
if (ok && (lines > 0)) // 1, 2, or 3 strikes are imported as single strike
importedtext += "<s>";
else
strike = "";
}
if (txt == syms) {
txt.replace(QString("\r"), QString("")); // convert Windows line break \r\n -> \n
importedtext += txt.toHtmlEscaped();
Expand All @@ -1359,6 +1368,8 @@ static QString nextPartOfFormattedString(QXmlStreamReader& e)
// <sym> replacement made, should be no need for line break or other conversions
importedtext += syms;
}
if (strike != "")
importedtext += "</s>";
if (underline != "")
importedtext += "</u>";
if (fontStyle == "italic")
Expand Down
13 changes: 12 additions & 1 deletion importexport/musicxml/importmxmlpass2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -781,6 +781,7 @@ static QString nextPartOfFormattedString(QXmlStreamReader& e)
QString fontSize = e.attributes().value("font-size").toString();
QString fontStyle = e.attributes().value("font-style").toString();
QString underline = e.attributes().value("underline").toString();
QString strike = e.attributes().value("line-through").toString();
QString fontFamily = e.attributes().value("font-family").toString();
// TODO: color, enclosure, yoffset in only part of the text, ...

Expand Down Expand Up @@ -811,11 +812,19 @@ static QString nextPartOfFormattedString(QXmlStreamReader& e)
if (!underline.isEmpty()) {
bool ok = true;
int lines = underline.toInt(&ok);
if (ok && (lines > 0)) // 1,2, or 3 underlines are imported as single underline
if (ok && (lines > 0)) // 1, 2, or 3 underlines are imported as single underline
importedtext += "<u>";
else
underline = "";
}
if (!strike.isEmpty()) {
bool ok = true;
int lines = underline.toInt(&ok);
if (ok && (lines > 0)) // 1, 2, or 3 strike are imported as single strike
importedtext += "<s>";
else
strike = "";
}
if (txt == syms) {
txt.replace(QString("\r"), QString("")); // convert Windows line break \r\n -> \n
importedtext += txt.toHtmlEscaped();
Expand All @@ -824,6 +833,8 @@ static QString nextPartOfFormattedString(QXmlStreamReader& e)
// <sym> replacement made, should be no need for line break or other conversions
importedtext += syms;
}
if (underline != "")
importedtext += "</s>";
if (underline != "")
importedtext += "</u>";
if (fontStyle == "italic")
Expand Down
5 changes: 4 additions & 1 deletion importexport/musicxml/musicxmlfonthandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,11 @@ namespace Ms {
#if 0
static QString charFormat2QString(const CharFormat& f)
{
return QString("b %1 i %2 u %3 va %4 fs %5 fam %6")
return QString("b %1 i %2 u %3 s %4 va %5 fs %6 fam %7")
.arg(f.bold())
.arg(f.italic())
.arg(f.underline())
.arg(f.strike())
.arg(static_cast<int>(f.valign()))
.arg(f.fontSize())
.arg(f.fontFamily())
Expand Down Expand Up @@ -82,6 +83,7 @@ MScoreTextToMXML::MScoreTextToMXML(const QString& tag, const QString& attr, cons
oldFormat.setBold(false);
oldFormat.setItalic(false);
oldFormat.setUnderline(false);
oldFormat.setStrike(false);
}

//---------------------------------------------------------
Expand Down Expand Up @@ -272,6 +274,7 @@ QString MScoreTextToMXML::updateFormat()
res += attribute(newFormat.bold() != oldFormat.bold(), newFormat.bold(), "font-weight=\"bold\"", "font-weight=\"normal\"");
res += attribute(newFormat.italic() != oldFormat.italic(), newFormat.italic(), "font-style=\"italic\"", "font-style=\"normal\"");
res += attribute(newFormat.underline() != oldFormat.underline(), newFormat.underline(), "underline=\"1\"", "underline=\"0\"");
res += attribute(newFormat.strike() != oldFormat.strike(), newFormat.strike(), "line-through=\"1\"", "line-through=\"0\"");
res += attribute(newFormat.fontFamily() != oldFormat.fontFamily(), true, QString("font-family=\"%1\"").arg(newFormat.fontFamily()), "");
bool needSize = newFormat.fontSize() < 0.99 * oldFormat.fontSize() || newFormat.fontSize() > 1.01 * oldFormat.fontSize();
res += attribute(needSize, true, QString("font-size=\"%1\"").arg(newFormat.fontSize()), "");
Expand Down
1 change: 1 addition & 0 deletions libmscore/bend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ QFont Bend::font(qreal sp) const
f.setBold(_fontStyle & FontStyle::Bold);
f.setItalic(_fontStyle & FontStyle::Italic);
f.setUnderline(_fontStyle & FontStyle::Underline);
f.setStrikeOut(_fontStyle & FontStyle::Strike);
qreal m = _fontSize;
m *= sp / SPATIUM20;

Expand Down
1 change: 1 addition & 0 deletions libmscore/glissando.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ void GlissandoSegment::draw(QPainter* painter) const
f.setBold(glissando()->fontStyle() & FontStyle::Bold);
f.setItalic(glissando()->fontStyle() & FontStyle::Italic);
f.setUnderline(glissando()->fontStyle() & FontStyle::Underline);
f.setStrikeOut(glissando()->fontStyle() & FontStyle::Strike);
QFontMetricsF fm(f, painter->device()); // use the QPaintDevice, otherwise calculations will be done in screen metrics
QRectF r = fm.boundingRect(glissando()->text());

Expand Down
8 changes: 8 additions & 0 deletions libmscore/read114.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,15 @@ QString convertFromHtml(TextBase* t, const QString& ss)
s += "<i>";
if (font.underline())
s += "<u>";
#if 0 // should not happen, but won't harm either
if (font.strikeOut())
s += "<s>";
#endif
s += f.text().toHtmlEscaped();
#if 0 // see above
if (font.strikeOut())
s += "</s>";
#endif
if (font.underline())
s += "</u>";
if (font.italic())
Expand Down
6 changes: 6 additions & 0 deletions libmscore/read206.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,12 @@ void readTextStyle206(MStyle* style, XmlReader& e, std::map<QString, std::map<Si
if (e.readInt())
fontStyle = fontStyle + FontStyle::Underline;
}
#if 0 // should not happen, but won't harm either
else if (tag == "strike") {
if (e.readInt())
fontStyle = fontStyle + FontStyle::Strike;
}
#endif
else if (tag == "align")
align = Align(e.readInt());
else if (tag == "anchor") // obsolete
Expand Down
2 changes: 2 additions & 0 deletions libmscore/scoreElement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,8 @@ void ScoreElement::writeProperty(XmlWriter& xml, Pid pid) const
xml.tag("italic", fs & FontStyle::Italic);
if ((fs & FontStyle::Underline) != (ds & FontStyle::Underline))
xml.tag("underline", fs & FontStyle::Underline);
if ((fs & FontStyle::Strike) != (ds & FontStyle::Strike))
xml.tag("strike", fs & FontStyle::Strike);
return;
}

Expand Down
9 changes: 5 additions & 4 deletions libmscore/style.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2945,17 +2945,18 @@ bool MStyle::readStyleValCompat(XmlReader& e)

//---------------------------------------------------------
// readTextStyleValCompat
// Handle transition from separate bold, underline and
// italic style properties to the single *FontStyle
// Handle transition from separate bold, underline, strike
// and italic style properties to the single *FontStyle
// property set.
//---------------------------------------------------------

bool MStyle::readTextStyleValCompat(XmlReader& e)
{
static const std::array<std::pair<const char*, FontStyle>, 3> styleNamesEndings {{
static const std::array<std::pair<const char*, FontStyle>, 4> styleNamesEndings {{
{ "FontBold", FontStyle::Bold },
{ "FontItalic", FontStyle::Italic },
{ "FontUnderline", FontStyle::Underline }
{ "FontUnderline", FontStyle::Underline },
{ "FontStrike", FontStyle::Strike }
}};

const QStringRef tag(e.name());
Expand Down
58 changes: 44 additions & 14 deletions libmscore/textbase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -765,7 +765,7 @@ void TextFragment::draw(QPainter* p, const TextBase* t) const
void TextBase::drawTextWorkaround(QPainter* p, QFont& f, const QPointF pos, const QString text)
{
qreal mm = p->worldTransform().m11();
if (!(MScore::pdfPrinting) && (mm < 1.0) && f.bold() && !(f.underline())) {
if (!(MScore::pdfPrinting) && (mm < 1.0) && f.bold() && !(f.underline() || f.strikeOut())) {
// workaround for https://musescore.org/en/node/284218
// and https://musescore.org/en/node/281601
// only needed for certain artificially emboldened fonts
Expand Down Expand Up @@ -849,6 +849,7 @@ QFont TextFragment::font(const TextBase* t) const
if (format.valign() != VerticalAlignment::AlignNormal)
m *= subScriptSize;
font.setUnderline(format.underline() || format.preedit());
font.setStrikeOut(format.strike() || format.preedit());

QString family;
if (format.fontFamily() == "ScoreText") {
Expand Down Expand Up @@ -1405,6 +1406,9 @@ void CharFormat::setFormat(FormatId id, QVariant data)
case FormatId::Underline:
setUnderline(data.toBool());
break;
case FormatId::Strike:
setStrike(data.toBool());
break;
case FormatId::Valign:
_valign = static_cast<VerticalAlignment>(data.toInt());
break;
Expand Down Expand Up @@ -1963,6 +1967,7 @@ class XmlNesting : public QStack<QString> {
void pushB() { pushToken("b"); }
void pushI() { pushToken("i"); }
void pushU() { pushToken("u"); }
void pushS() { pushToken("s"); }

QString popToken() {
QString s = pop();
Expand All @@ -1985,6 +1990,7 @@ class XmlNesting : public QStack<QString> {
void popB() { popToken("b"); }
void popI() { popToken("i"); }
void popU() { popToken("u"); }
void popS() { popToken("s"); }
};

//---------------------------------------------------------
Expand All @@ -1997,6 +2003,7 @@ void TextBase::genText() const
bool bold_ = false;
bool italic_ = false;
bool underline_ = false;
bool strike_ = false;

for (const TextBlock& block : _layout) {
for (const TextFragment& f : block.fragments()) {
Expand All @@ -2006,6 +2013,8 @@ void TextBase::genText() const
italic_ = true;
if (!f.format.underline() && underline())
underline_ = true;
if (!f.format.strike() && strike())
strike_ = true;
}
}
CharFormat fmt;
Expand All @@ -2022,6 +2031,8 @@ void TextBase::genText() const
xmlNesting.pushI();
if (underline_)
xmlNesting.pushU();
if (strike_)
xmlNesting.pushS();

for (const TextBlock& block : _layout) {
for (const TextFragment& f : block.fragments()) {
Expand All @@ -2047,6 +2058,12 @@ void TextBase::genText() const
else
xmlNesting.popU();
}
if (fmt.strike() != format.strike()) {
if (format.strike())
xmlNesting.pushS();
else
xmlNesting.popS();
}

if (format.fontSize() != fmt.fontSize())
_text += QString("<font size=\"%1\"/>").arg(format.fontSize());
Expand Down Expand Up @@ -2185,28 +2202,24 @@ bool TextBase::readProperties(XmlReader& e)
setXmlText(e.readXml());
else if (tag == "bold") {
bool val = e.readInt();
if (val)
_fontStyle = _fontStyle + FontStyle::Bold;
else
_fontStyle = _fontStyle - FontStyle::Bold;
setBold(val);
if (isStyled(Pid::FONT_STYLE))
setPropertyFlags(Pid::FONT_STYLE, PropertyFlags::UNSTYLED);
}
else if (tag == "italic") {
bool val = e.readInt();
if (val)
_fontStyle = _fontStyle + FontStyle::Italic;
else
_fontStyle = _fontStyle - FontStyle::Italic;
setItalic(val);
if (isStyled(Pid::FONT_STYLE))
setPropertyFlags(Pid::FONT_STYLE, PropertyFlags::UNSTYLED);
}
else if (tag == "underline") {
bool val = e.readInt();
if (val)
_fontStyle = _fontStyle + FontStyle::Underline;
else
_fontStyle = _fontStyle - FontStyle::Underline;
setUnderline(val); if (isStyled(Pid::FONT_STYLE))
setPropertyFlags(Pid::FONT_STYLE, PropertyFlags::UNSTYLED);
}
else if (tag == "strike") {
bool val = e.readInt();
setStrike(val);
if (isStyled(Pid::FONT_STYLE))
setPropertyFlags(Pid::FONT_STYLE, PropertyFlags::UNSTYLED);
}
Expand Down Expand Up @@ -2446,7 +2459,11 @@ QString TextBase::convertFromHtml(const QString& ss) const
s += "<i>";
if (font.underline())
s += "<u>";
if (font.strikeOut())
s += "<s>";
s += f.text().toHtmlEscaped();
if (font.strikeOut())
s += "</s>";
if (font.underline())
s += "</u>";
if (font.italic())
Expand Down Expand Up @@ -2674,7 +2691,7 @@ bool TextBase::validateText(QString& s)
d.append("&amp;");
}
else if (c == '<') {
const char* ok[] { "b>", "/b>", "i>", "/i>", "u>", "/u", "font ", "/font>", "sym>", "/sym>", "sub>", "/sub>", "sup>", "/sup>" };
const char* ok[] { "b>", "/b>", "i>", "/i>", "u>", "/u", "s>", "/s>", "font ", "/font>", "sym>", "/sym>", "sub>", "/sub>", "sup>", "/sup>" };
QString t = s.mid(i+1);
bool found = false;
for (auto k : ok) {
Expand Down Expand Up @@ -2720,6 +2737,8 @@ QFont TextBase::font() const
QFont f(_family, m, bold() ? QFont::Bold : QFont::Normal, italic());
if (underline())
f.setUnderline(underline());
if (strike())
f.setStrikeOut(strike());

return f;
}
Expand Down Expand Up @@ -3205,6 +3224,7 @@ QString TextBase::stripText(bool removeStyle, bool removeSize, bool removeFace)
bool bold_ = false;
bool italic_ = false;
bool underline_ = false;
bool strike_ = false;

for (const TextBlock& block : _layout) {
for (const TextFragment& f : block.fragments()) {
Expand All @@ -3214,6 +3234,8 @@ QString TextBase::stripText(bool removeStyle, bool removeSize, bool removeFace)
italic_ = true;
if (!f.format.underline() && underline())
underline_ = true;
if (!f.format.strike() && strike())
strike_ = true;
}
}
CharFormat fmt;
Expand All @@ -3231,6 +3253,8 @@ QString TextBase::stripText(bool removeStyle, bool removeSize, bool removeFace)
xmlNesting.pushI();
if (underline_)
xmlNesting.pushU();
if (strike_)
xmlNesting.pushS();
}

for (const TextBlock& block : _layout) {
Expand All @@ -3257,6 +3281,12 @@ QString TextBase::stripText(bool removeStyle, bool removeSize, bool removeFace)
else
xmlNesting.popU();
}
if (fmt.strike() != format.strike()) {
if (format.strike())
xmlNesting.pushS();
else
xmlNesting.popS();
}
}

if (!removeSize && (format.fontSize() != fmt.fontSize()))
Expand Down
Loading

0 comments on commit 5a578a6

Please sign in to comment.