diff --git a/CMakeLists.txt b/CMakeLists.txt index 1d31e631e47af..5670e08da561a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -164,6 +164,7 @@ option(MUE_COMPILE_USE_SYSTEM_HARFBUZZ "Try use system harfbuzz" OFF) option(MUE_COMPILE_USE_SYSTEM_OPUS "Try use system opus" OFF) option(MUE_COMPILE_USE_SYSTEM_OPUSENC "Try use system libopusenc" OFF) option(MUE_COMPILE_USE_SYSTEM_MNXDOM "Try use system mnxdom" OFF) +option(MUE_COMPILE_USE_SYSTEM_PUGIXML "Try use system pugixml" OFF) # === Debug === option(MUE_ENABLE_LOAD_QML_FROM_SOURCE "Load qml files from source (not resource)" OFF) diff --git a/src/engraving/rendering/score/headerfooterlayout.cpp b/src/engraving/rendering/score/headerfooterlayout.cpp index c2f3c817021ad..c9a573efc560e 100644 --- a/src/engraving/rendering/score/headerfooterlayout.cpp +++ b/src/engraving/rendering/score/headerfooterlayout.cpp @@ -267,13 +267,13 @@ TextBlock HeaderFooterLayout::replaceTextMacros(const LayoutContext& ctx, const } [[fallthrough]]; case 'N': // on page 1 only if there are multiple pages - if ((page->score()->npages() + page->score()->pageNumberOffset()) <= 1) { + if ((static_cast(page->score()->npages()) + page->score()->pageNumberOffset()) <= 1) { break; } [[fallthrough]]; case 'P': // on all pages { - size_t no = page->pageNumber() + 1 + page->score()->pageNumberOffset(); + const int no = static_cast(page->pageNumber()) + 1 + page->score()->pageNumberOffset(); if (no > 0) { const String pageNumberString = String::number(no); const CharFormat pageNumberFormat = formatForMacro(ctx, String('$' + nc)); @@ -283,7 +283,7 @@ TextBlock HeaderFooterLayout::replaceTextMacros(const LayoutContext& ctx, const break; case 'n': { - size_t no = page->score()->npages() + page->score()->pageNumberOffset(); + const int no = static_cast(page->score()->npages()) + page->score()->pageNumberOffset(); const String numberOfPagesString = String::number(no); const CharFormat pageNumberFormat = formatForMacro(ctx, String('$' + nc)); appendFormattedString(newFragments, numberOfPagesString, defaultFormat, pageNumberFormat); diff --git a/src/engraving/rendering/score/parenthesislayout.cpp b/src/engraving/rendering/score/parenthesislayout.cpp index d84b5967a9af4..477a4f505b87e 100644 --- a/src/engraving/rendering/score/parenthesislayout.cpp +++ b/src/engraving/rendering/score/parenthesislayout.cpp @@ -314,8 +314,8 @@ void ParenthesisLayout::createPathAndShape(Parenthesis* item, Parenthesis::Layou PointF startPoint = PointF(); double midThickness = 2 * midPointThickness; - int nbShapes = round(5.0 * heightInSpatium); - nbShapes = std::clamp(nbShapes, 20, 50); + int nbShapes = round(2.0 * heightInSpatium); + nbShapes = std::clamp(nbShapes, 3, 10); PointF bezier1mid = bezier1for - PointF(midPointThickness * direction, 0.0); PointF bezier2mid = bezier2for - PointF(midPointThickness * direction, 0.0); const CubicBezier b(startPoint, bezier1mid, bezier2mid, endNormalised); diff --git a/src/engraving/rendering/score/tdraw.cpp b/src/engraving/rendering/score/tdraw.cpp index 1cb756cfdc84f..7f34eb4363ee7 100644 --- a/src/engraving/rendering/score/tdraw.cpp +++ b/src/engraving/rendering/score/tdraw.cpp @@ -953,7 +953,6 @@ void TDraw::draw(const Bend* item, Painter* painter, const PaintOptions& opt) painter->setBrush(Brush(item->curColor(opt))); Font f = item->font(spatium); - painter->setFont(f); double x = data->noteWidth + spatium * .2; double y = -spatium * .8; @@ -978,6 +977,7 @@ void TDraw::draw(const Bend* item, Painter* painter, const PaintOptions& opt) int idx = (pitch + 12) / 25; const char* l = item->label[idx]; + painter->setFont(f); painter->drawText(RectF(x2, y2, .0, .0), muse::draw::AlignHCenter | muse::draw::AlignBottom | muse::draw::TextDontClip, String::fromAscii(l)); @@ -1010,6 +1010,7 @@ void TDraw::draw(const Bend* item, Painter* painter, const PaintOptions& opt) int idx = (item->points()[pt + 1].pitch + 12) / 25; const char* l = item->label[idx]; double ty = y2; // - _spatium; + painter->setFont(f); painter->drawText(RectF(x2, ty, .0, .0), muse::draw::AlignHCenter | muse::draw::AlignBottom | muse::draw::TextDontClip, String::fromAscii(l)); diff --git a/src/engraving/rw/write/twrite.cpp b/src/engraving/rw/write/twrite.cpp index 0a285ad623710..5bf38ff82ae7b 100644 --- a/src/engraving/rw/write/twrite.cpp +++ b/src/engraving/rw/write/twrite.cpp @@ -3426,6 +3426,8 @@ static void writeTimeSig(Score* score, const Fraction& tick, XmlWriter& xml, Wri TimeSig* ts = Factory::createTimeSig(score->dummy()->segment()); ts->setSig(tsf); TWrite::write(ts, xml, ctx); + ts->masterScore()->eidRegister()->removeItem(ts); + delete ts; } //--------------------------------------------------------- @@ -3607,6 +3609,7 @@ void TWrite::writeSegments(XmlWriter& xml, WriteContext& ctx, track_idx_t strack KeySig* ks = Factory::createKeySig(score->dummy()->segment()); ks->setKey(ck, tk); TWrite::write(ks, xml, ctx); + ks->masterScore()->eidRegister()->removeItem(ks); delete ks; keySigWritten = true; } diff --git a/src/framework/global/CMakeLists.txt b/src/framework/global/CMakeLists.txt index 4d1c783e13f83..79aee9d4349ce 100644 --- a/src/framework/global/CMakeLists.txt +++ b/src/framework/global/CMakeLists.txt @@ -154,10 +154,19 @@ target_sources(muse_global PRIVATE serialization/xmlstreamwriter.h serialization/xmldom.cpp serialization/xmldom.h - - thirdparty/pugixml/pugixml.hpp - thirdparty/pugixml/pugixml.cpp ) +if (MUE_COMPILE_USE_SYSTEM_PUGIXML) + find_package(PkgConfig REQUIRED) + pkg_check_modules(pugixml REQUIRED IMPORTED_TARGET pugixml) + target_link_libraries(muse_global PRIVATE PkgConfig::pugixml) + target_include_directories(muse_global PRIVATE ${pugixml_INCLUDE_DIRS}) +else() + target_sources(muse_global PRIVATE + thirdparty/pugixml/pugixml.hpp + thirdparty/pugixml/pugixml.cpp + ) + target_include_directories(muse_global PRIVATE thirdparty/pugixml) +endif() if (MUSE_THREADS_SUPPORT) target_sources(muse_global PRIVATE diff --git a/src/importexport/musicxml/internal/export/exportmusicxml.cpp b/src/importexport/musicxml/internal/export/exportmusicxml.cpp index a3c54c388d2fc..622cad799a9d4 100644 --- a/src/importexport/musicxml/internal/export/exportmusicxml.cpp +++ b/src/importexport/musicxml/internal/export/exportmusicxml.cpp @@ -263,6 +263,7 @@ class GlissandoHandler { public: GlissandoHandler(); + void reset(); void doGlissandoStart(Glissando* gliss, Notations& notations, XmlWriter& xml); void doGlissandoStop(Glissando* gliss, Notations& notations, XmlWriter& xml); @@ -1005,6 +1006,11 @@ static void glissando(const Glissando* gli, int number, bool start, Notations& n //--------------------------------------------------------- GlissandoHandler::GlissandoHandler() +{ + reset(); +} + +void GlissandoHandler::reset() { for (int i = 0; i < MAX_NUMBER_LEVEL; ++i) { m_glissNote[i] = 0; @@ -1458,8 +1464,8 @@ static void creditWords(XmlWriter& xml, const MStyle& s, const page_idx_t pageNr if (!creditType.empty()) { xml.tag("credit-type", creditType); } - String attr = String(u" default-x=\"%1\"").arg(x); - attr += String(u" default-y=\"%1\"").arg(y); + String attr = String(u" default-x=\"%1\"").arg(String::number(x, 2)); + attr += String(u" default-y=\"%1\"").arg(String::number(y, 2)); attr += u" justify=\"" + just + u"\""; attr += u" valign=\"" + val + u"\""; MScoreTextToMusicXml mttm(u"credit-words", attr, defFmt, mtf); @@ -3360,6 +3366,12 @@ static void writeChordLines(const Chord* const chord, XmlWriter& xml, Notations& } if (!subtype.empty()) { subtype += color2xml(cl); + if (cl->isStraight()) { + subtype += u" line-shape=\"straight\""; + } + if (cl->isWavy()) { + subtype += u" line-type=\"wavy\""; + } notations.tag(xml, cl, "articulations"); xml.tagRaw(subtype); } @@ -5609,7 +5621,7 @@ void ExportMusicXml::pedal(Pedal const* const pd, staff_idx_t staff, const Fract pedalType = u"change"; break; case HookType::NONE: - pedalType = pd->lineVisible() ? u"resume" : u"start"; + pedalType = (pd->lineVisible() && pd->beginText().isEmpty()) ? u"resume" : u"start"; break; default: pedalType = u"start"; @@ -5619,10 +5631,12 @@ void ExportMusicXml::pedal(Pedal const* const pd, staff_idx_t staff, const Fract pedalType = u"sostenuto"; } } else { - if (!pd->endText().isEmpty() || pd->endHookType() == HookType::HOOK_90) { + switch (pd->endHookType()) { + case HookType::NONE: + pedalType = (pd->lineVisible() && pd->endText().isEmpty()) ? u"discontinue" : u"stop"; + break; + default: pedalType = u"stop"; - } else { - pedalType = u"discontinue"; } // "change" type is handled only on the beginning of pedal lines @@ -8629,6 +8643,7 @@ void ExportMusicXml::writeParts() for (size_t partIndex = 0; partIndex < parts.size(); ++partIndex) { const Part* part = parts.at(partIndex); + m_gh.reset(); // reset glissando handler state for each part m_tick = { 0, 1 }; m_xml.startElementRaw(String(u"part id=\"P%1\"").arg(partIndex + 1)); diff --git a/src/importexport/musicxml/internal/import/importmusicxmlpass1.cpp b/src/importexport/musicxml/internal/import/importmusicxmlpass1.cpp index 320f2d051b392..4f24a2afcc7b8 100644 --- a/src/importexport/musicxml/internal/import/importmusicxmlpass1.cpp +++ b/src/importexport/musicxml/internal/import/importmusicxmlpass1.cpp @@ -1001,7 +1001,7 @@ static void resizeTitleBox(VBox* vbox) score->renderer()->layoutItem(e); } - double padding = vbox->spatium(); + const double padding = vbox->sizeIsSpatiumDependent() ? vbox->style().spatium() : vbox->style().defaultSpatium(); for (EngravingItem* e : elist) { if (e->isText()) { diff --git a/src/importexport/musicxml/internal/import/importmusicxmlpass2.cpp b/src/importexport/musicxml/internal/import/importmusicxmlpass2.cpp index f497d9b4fab65..c1bd2205583aa 100644 --- a/src/importexport/musicxml/internal/import/importmusicxmlpass2.cpp +++ b/src/importexport/musicxml/internal/import/importmusicxmlpass2.cpp @@ -9215,6 +9215,8 @@ static void addChordLine(const Notation& notation, Note* note, MusicXmlLogger* logger, const XmlStreamReader* const xmlreader) { const String chordLineType = notation.subType(); + const String lineType = notation.attribute(u"line-type"); + const String lineShape = notation.attribute(u"line-shape"); if (!chordLineType.empty()) { if (note) { ChordLine* const chordline = Factory::createChordLine(note->chord()); @@ -9227,6 +9229,14 @@ static void addChordLine(const Notation& notation, Note* note, } else if (chordLineType == u"scoop") { chordline->setChordLineType(ChordLineType::SCOOP); } + if (lineShape == u"straight") { + chordline->setStraight(true); + } + if (lineType == u"wavy") { + chordline->setWavy(true); + } else if (!lineType.empty() && lineType != u"solid") { + logger->logError(String(u"unsupported line-type: %1").arg(lineType), xmlreader); + } chordline->setVisible(notation.visible()); colorItem(chordline, Color::fromString(notation.attribute(u"color"))); note->chord()->add(chordline); diff --git a/src/importexport/musicxml/tests/data/testColorExport.xml b/src/importexport/musicxml/tests/data/testColorExport.xml deleted file mode 100644 index de7973de84bcf..0000000000000 --- a/src/importexport/musicxml/tests/data/testColorExport.xml +++ /dev/null @@ -1,432 +0,0 @@ - - - - - - MuseScore 0.7.0 - 2007-09-10 - - - - - - - - - - Piano - Pno. - - Piano - - - - 1 - 1 - 78.7402 - 0 - - - - - - - 2 - - 2 - - - - G - 2 - - - - - C - - dominant - - - - - quarter - 80 - - - - - - - - - - - - - - - - - A - 4 - - 2 - 1 - quarter - up - normal - - - - - - - C - 5 - - 2 - 1 - quarter - natural - down - normal - - - - D - 5 - - 2 - - 1 - quarter - down - - - - - - - - D - 5 - - 2 - - 1 - quarter - down - - - - - - - - - - - - - - - - - - - 1. - - - - - - - - - - - - A - 4 - - 2 - 1 - quarter - up - - - - - - - G - 5 - - 2 - 1 - quarter - down - - - - - - - A - 4 - - 2 - 1 - quarter - up - - gliss. - - - - - G - 5 - - 2 - 1 - quarter - down - - - - - single - LYRICS - - - - - - - - - - B - - - - - 2 - 1 - quarter - - - - - - - - - A - -1 - 4 - - 2 - 1 - quarter - flat - up - - - - - - - - - - A - -1 - 4 - - 4 - 1 - half - up - - - - - - - - - - - - - light-light - - - - - - Ausdruck - - - - - - - - - - G - 3 - - 2 - 1 - quarter - down - - - - - - - - A - 3 - - 2 - 1 - quarter - down - - - - - - - - C - 1 - 4 - - 2 - 1 - quarter - down - - - - - - - - E - 4 - - 2 - 1 - quarter - down - - - - - - - 2 - 1 - quarter - - - - C - 1 - 4 - - 2 - 1 - quarter - down - - - 3 - - - - - - 2 - 1 - quarter - - - - - - - - - - - dim. - - - - - B - 4 - - 8 - 1 - whole - - - - - - - - - - - - - - - - C - 5 - - 7 - 1 - half - - - natural - down - - - - C - 5 - - 1 - 1 - eighth - up - - - - - - - - light-heavy - - - - diff --git a/src/importexport/musicxml/tests/data/testColorExport_ref.xml b/src/importexport/musicxml/tests/data/testColorExport_ref.xml index 59d09c153ee9c..46efef2327e1a 100644 --- a/src/importexport/musicxml/tests/data/testColorExport_ref.xml +++ b/src/importexport/musicxml/tests/data/testColorExport_ref.xml @@ -222,7 +222,7 @@ - + diff --git a/src/importexport/musicxml/tests/data/testExcludeInvisibleElements_invisible_ref.xml b/src/importexport/musicxml/tests/data/testExcludeInvisibleElements_invisible_ref.xml index b02b3b5399017..e3a84495d7978 100644 --- a/src/importexport/musicxml/tests/data/testExcludeInvisibleElements_invisible_ref.xml +++ b/src/importexport/musicxml/tests/data/testExcludeInvisibleElements_invisible_ref.xml @@ -409,7 +409,7 @@ - + @@ -467,7 +467,7 @@ - + diff --git a/src/importexport/musicxml/tests/data/testExcludeInvisibleElements_noinvisible_ref.xml b/src/importexport/musicxml/tests/data/testExcludeInvisibleElements_noinvisible_ref.xml index cb99aaa4a9b6a..c89c88a967b73 100644 --- a/src/importexport/musicxml/tests/data/testExcludeInvisibleElements_noinvisible_ref.xml +++ b/src/importexport/musicxml/tests/data/testExcludeInvisibleElements_noinvisible_ref.xml @@ -370,7 +370,7 @@ - + diff --git a/src/importexport/musicxml/tests/data/testLayout.xml b/src/importexport/musicxml/tests/data/testLayout.xml index 29c7fc03f57f7..bd7fc7a893290 100644 --- a/src/importexport/musicxml/tests/data/testLayout.xml +++ b/src/importexport/musicxml/tests/data/testLayout.xml @@ -138,7 +138,7 @@ - + 2 diff --git a/src/importexport/musicxml/tests/data/testLines1.xml b/src/importexport/musicxml/tests/data/testLines1.xml index e5738f61009ac..2e1fee258214d 100644 --- a/src/importexport/musicxml/tests/data/testLines1.xml +++ b/src/importexport/musicxml/tests/data/testLines1.xml @@ -269,7 +269,7 @@ - + diff --git a/src/importexport/musicxml/tests/data/testPedalStyles.xml b/src/importexport/musicxml/tests/data/testPedalStyles.xml index 64e18be4d9223..8229763ae8019 100644 --- a/src/importexport/musicxml/tests/data/testPedalStyles.xml +++ b/src/importexport/musicxml/tests/data/testPedalStyles.xml @@ -519,7 +519,7 @@ - + 2 diff --git a/src/importexport/musicxml/tests/data/testSystemDistance_ref.xml b/src/importexport/musicxml/tests/data/testSystemDistance_ref.xml index 3ff9824070ad7..1df3f31cf0397 100644 --- a/src/importexport/musicxml/tests/data/testSystemDistance_ref.xml +++ b/src/importexport/musicxml/tests/data/testSystemDistance_ref.xml @@ -67,7 +67,7 @@ title - System-Distance Test + System-Distance Test diff --git a/src/importexport/musicxml/tests/data/testTimeTickExport_ref.xml b/src/importexport/musicxml/tests/data/testTimeTickExport_ref.xml index 42b7d51de17f2..a249682dd8d23 100644 --- a/src/importexport/musicxml/tests/data/testTimeTickExport_ref.xml +++ b/src/importexport/musicxml/tests/data/testTimeTickExport_ref.xml @@ -123,7 +123,7 @@ - + -3 2 diff --git a/src/inspector/qml/MuseScore/Inspector/general/appearance/appearancesettingsmodel.cpp b/src/inspector/qml/MuseScore/Inspector/general/appearance/appearancesettingsmodel.cpp index bdb06a6bbf7e1..8003a5e9733f5 100644 --- a/src/inspector/qml/MuseScore/Inspector/general/appearance/appearancesettingsmodel.cpp +++ b/src/inspector/qml/MuseScore/Inspector/general/appearance/appearancesettingsmodel.cpp @@ -210,7 +210,9 @@ void AppearanceSettingsModel::pushBackwardsInOrder() } EngravingItem* elementBehind = elements[i - 1 >= 0 ? i - 1 : 0]; - m_arrangeOrder->setValue(elementBehind->z() - REARRANGE_ORDER_STEP); + int elementBehindZ = elementBehind->z(); + int newZ = elementBehindZ <= -INT_MAX + REARRANGE_ORDER_STEP ? elementBehindZ : elementBehindZ - REARRANGE_ORDER_STEP; // avoid underflow + m_arrangeOrder->setValue(newZ); } void AppearanceSettingsModel::pushForwardsInOrder() @@ -228,30 +230,58 @@ void AppearanceSettingsModel::pushForwardsInOrder() } EngravingItem* elementInFront = elements[i + 1 < elementsCount ? i + 1 : elementsCount - 1]; - m_arrangeOrder->setValue(elementInFront->z() + REARRANGE_ORDER_STEP); + int elementInFrontZ = elementInFront->z(); + int newZ = elementInFrontZ >= INT_MAX - REARRANGE_ORDER_STEP ? elementInFrontZ : elementInFrontZ + REARRANGE_ORDER_STEP; // avoid overflow + m_arrangeOrder->setValue(newZ); } void AppearanceSettingsModel::pushToBackInOrder() { std::vector elements = allElementsInPage(); - EngravingItem* minElement = *std::min_element(elements.begin(), elements.end(), elementLessThan); + EngravingItem* minElement = *std::min_element( + elements.begin(), elements.end(), [](const EngravingItem* const e1, const EngravingItem* const e2) { + // Certain elements (TimeTickAnchor) have their Z set to -INT_MAX to ensure they're always at the back. + // With this check, we make sure that those elements are not taken into account when looking for the + // min Z, in order to avoid all elements to be pushed back to -INT_MAX: + if (e1->z() == -INT_MAX) { + return false; + } else if (e2->z() == -INT_MAX) { + return true; + } + return elementLessThan(e1, e2); + }); if (m_elementsForArrangeProperty.contains(minElement)) { m_arrangeOrder->setValue(minElement->z()); } else { - m_arrangeOrder->setValue(minElement->z() - REARRANGE_ORDER_STEP); + int minElementZ = minElement->z(); + int newZ = minElementZ <= -INT_MAX + REARRANGE_ORDER_STEP ? minElementZ : minElementZ - REARRANGE_ORDER_STEP; // avoid underflow + m_arrangeOrder->setValue(newZ); } } void AppearanceSettingsModel::pushToFrontInOrder() { std::vector elements = allElementsInPage(); - EngravingItem* maxElement = *std::max_element(elements.begin(), elements.end(), elementLessThan); + EngravingItem* maxElement = *std::max_element( + elements.begin(), elements.end(), [](const EngravingItem* const e1, const EngravingItem* const e2) { + // Certain elements (SoundFlag) have their Z set to INT_MAX to ensure they're always at the front. + // With this check, we make sure that those elements are not taken into account when looking for the + // max Z, in order to avoid all elements to be pushed forward to INT_MAX: + if (e2->z() == INT_MAX) { + return false; + } else if (e1->z() == INT_MAX) { + return true; + } + return elementLessThan(e1, e2); + }); if (m_elementsForArrangeProperty.contains(maxElement)) { m_arrangeOrder->setValue(maxElement->z()); } else { - m_arrangeOrder->setValue(maxElement->z() + REARRANGE_ORDER_STEP); + int maxElementZ = maxElement->z(); + int newZ = maxElementZ >= INT_MAX - REARRANGE_ORDER_STEP ? maxElementZ : maxElementZ + REARRANGE_ORDER_STEP; // avoid overflow + m_arrangeOrder->setValue(newZ); } } diff --git a/src/notationscene/widgets/pagesettings.ui b/src/notationscene/widgets/pagesettings.ui index f2ba83576e50e..a219a94c4fc3a 100644 --- a/src/notationscene/widgets/pagesettings.ui +++ b/src/notationscene/widgets/pagesettings.ui @@ -502,10 +502,10 @@ false - -99 + -999999 - 999 + 999999