From f7f8ce71aee2c3c92d0aab845c737c4c998fa60e Mon Sep 17 00:00:00 2001 From: Alexander Pavlov Date: Thu, 29 Oct 2026 16:19:55 +0200 Subject: [PATCH 01/11] fontsprovider, fontsdatabase are using local context --- .gitmodules | 3 +- muse | 2 +- src/engraving/engravingmodule.cpp | 28 ++++++++++--------- src/engraving/engravingmodule.h | 4 +-- src/engraving/iengravingfontsprovider.h | 2 +- src/engraving/internal/engravingfont.cpp | 22 +++++++++++---- src/engraving/internal/engravingfont.h | 12 ++++---- .../internal/engravingfontsprovider.cpp | 9 ++++-- .../internal/engravingfontsprovider.h | 3 +- .../internal/engravingfontscontroller.h | 9 ++++-- src/notation/notationmodule.cpp | 19 +++++++------ src/notation/notationmodule.h | 5 +++- 12 files changed, 75 insertions(+), 43 deletions(-) diff --git a/.gitmodules b/.gitmodules index 66511aed7e85..d28147cb1211 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,7 @@ [submodule "muse_framework"] path = muse - url = https://github.com/musescore/muse_framework.git + url = https://github.com/alexpavlov96/muse_framework.git + branch = alex/fonts-context [submodule "muse_deps"] path = muse_deps url = https://github.com/musescore/muse_deps.git diff --git a/muse b/muse index ecdc6e7ef87b..53fc2db88091 160000 --- a/muse +++ b/muse @@ -1 +1 @@ -Subproject commit ecdc6e7ef87b41c3fd2ce4e9df39343640862c4f +Subproject commit 53fc2db88091e2fdf564e848287bbf91a36bdc94 diff --git a/src/engraving/engravingmodule.cpp b/src/engraving/engravingmodule.cpp index 9b3b6e2d2760..f0c8cfeb1b13 100644 --- a/src/engraving/engravingmodule.cpp +++ b/src/engraving/engravingmodule.cpp @@ -103,10 +103,8 @@ void EngravingModule::registerExports() #ifndef ENGRAVING_NO_INTERNAL m_configuration = std::make_shared(); - m_engravingfonts = std::make_shared(); globalIoc()->registerExport(mname, m_configuration); - globalIoc()->registerExport(mname, m_engravingfonts); #endif // internal @@ -158,14 +156,14 @@ void EngravingModule::registerUiTypes() MScore::registerUiTypes(); } -void EngravingModule::onInit(const IApplication::RunMode&) +void EngravingContext::onInit(const muse::IApplication::RunMode&) { #ifndef ENGRAVING_NO_INTERNAL // Init fonts { using namespace muse::draw; - std::shared_ptr fdb = globalIoc()->resolve(mname); + std::shared_ptr fdb = ioc()->resolve(mname); // Text fdb->addFont(FontDataKey(u"Edwin", false, false), ":/fonts/edwin/Edwin-Roman.otf"); @@ -240,7 +238,6 @@ void EngravingModule::onInit(const IApplication::RunMode&) fdb->insertSubstitution(u"ScoreFont", u"Leland Text");// alias for current Musical Text Font // Symbols - Smufl::init(); //! NOTE It may be necessary to draw something with these fonts without requesting the fonts themselves //! (for example, simply specifying the family name for painter). @@ -249,6 +246,15 @@ void EngravingModule::onInit(const IApplication::RunMode&) m_engravingfonts->loadAllFonts(); } + m_paletteScoreProvider->init(); +#endif +} + +void EngravingModule::onInit(const IApplication::RunMode&) +{ +#ifndef ENGRAVING_NO_INTERNAL + Smufl::init(); + m_configuration->init(); DefaultStyle::instance()->init(m_configuration->defaultStyleFilePath(), @@ -274,7 +280,7 @@ void EngravingModule::onInit(const IApplication::RunMode&) //! NOTE And some initialization in the `Notation::init()` } -void EngravingModule::onDeinit() +void EngravingContext::onDeinit() { #ifndef ENGRAVING_NO_INTERNAL m_engravingfonts->deinit(); @@ -289,6 +295,9 @@ IContextSetup* EngravingModule::newContext(const muse::modularity::ContextPtr& c void EngravingContext::registerExports() { #ifndef ENGRAVING_NO_INTERNAL + m_engravingfonts = std::make_shared(iocContext()); + ioc()->registerExport(mname, m_engravingfonts); + m_paletteScoreProvider = std::make_shared(iocContext()); ioc()->registerExport(mname, m_paletteScoreProvider); ioc()->registerExport(mname, new EngravingElementsProvider()); @@ -296,13 +305,6 @@ void EngravingContext::registerExports() #endif } -void EngravingContext::onInit(const muse::IApplication::RunMode&) -{ -#ifndef ENGRAVING_NO_INTERNAL - m_paletteScoreProvider->init(); -#endif -} - void EngravingContext::onDestroy() { #ifndef ENGRAVING_NO_INTERNAL diff --git a/src/engraving/engravingmodule.h b/src/engraving/engravingmodule.h index 2edd30057bbf..709467612ec3 100644 --- a/src/engraving/engravingmodule.h +++ b/src/engraving/engravingmodule.h @@ -41,14 +41,12 @@ class EngravingModule : public muse::modularity::IModuleSetup void registerResources() override; void registerUiTypes() override; void onInit(const muse::IApplication::RunMode& mode) override; - void onDeinit() override; muse::modularity::IContextSetup* newContext(const muse::modularity::ContextPtr& ctx) const override; private: std::shared_ptr m_configuration; - std::shared_ptr m_engravingfonts; }; class EngravingContext : public muse::modularity::IContextSetup @@ -60,10 +58,12 @@ class EngravingContext : public muse::modularity::IContextSetup void registerExports() override; void onInit(const muse::IApplication::RunMode& mode) override; + void onDeinit() override; void onDestroy() override; private: + std::shared_ptr m_engravingfonts; std::shared_ptr m_paletteScoreProvider; }; } diff --git a/src/engraving/iengravingfontsprovider.h b/src/engraving/iengravingfontsprovider.h index 43ba68d82ec8..d864794d6efb 100644 --- a/src/engraving/iengravingfontsprovider.h +++ b/src/engraving/iengravingfontsprovider.h @@ -32,7 +32,7 @@ #include "iengravingfont.h" namespace mu::engraving { -class IEngravingFontsProvider : MODULE_GLOBAL_INTERFACE +class IEngravingFontsProvider : MODULE_CONTEXT_INTERFACE { INTERFACE_ID(IEngravingFontsProvider) diff --git a/src/engraving/internal/engravingfont.cpp b/src/engraving/internal/engravingfont.cpp index f54b054c376b..e157f0239871 100644 --- a/src/engraving/internal/engravingfont.cpp +++ b/src/engraving/internal/engravingfont.cpp @@ -44,14 +44,15 @@ using namespace mu::engraving; // ScoreFont // ============================================= -EngravingFont::EngravingFont(const std::string& name, const std::string& family, const path_t& filePath, const path_t& metadataPath) - : EngravingFont(name, family, std::make_shared(filePath), std::make_shared(metadataPath)) +EngravingFont::EngravingFont(const std::string& name, const std::string& family, const path_t& filePath, const path_t& metadataPath, + const muse::modularity::ContextPtr& iocCtx) + : EngravingFont(name, family, std::make_shared(filePath), std::make_shared(metadataPath), iocCtx) { } EngravingFont::EngravingFont(const std::string& name, const std::string& family, std::shared_ptr font, - std::shared_ptr metadata) - : m_symbols(static_cast(SymId::lastSym) + 1), + std::shared_ptr metadata, const muse::modularity::ContextPtr& iocCtx) + : muse::Contextable(iocCtx), m_symbols(static_cast(SymId::lastSym) + 1), m_name(name), m_family(family), m_fontDevice(std::move(font)), @@ -60,6 +61,7 @@ EngravingFont::EngravingFont(const std::string& name, const std::string& family, } EngravingFont::EngravingFont(const EngravingFont& other) + : muse::Contextable(other.iocContext()) { m_loaded = false; m_symbols = other.m_symbols; @@ -69,6 +71,13 @@ EngravingFont::EngravingFont(const EngravingFont& other) m_metadataDevice = other.m_metadataDevice; } +EngravingFont::~EngravingFont() +{ + if (m_symbolFontId != -1) { + fontProvider()->removeSymbolFont(m_symbolFontId); + } +} + // ============================================= // Properties // ============================================= @@ -104,7 +113,10 @@ void EngravingFont::ensureLoad() } const String family = String::fromStdString(m_family); - if (!m_fontDevice || -1 == fontProvider()->addSymbolFont(family, m_fontDevice)) { + if (m_symbolFontId == -1 && m_fontDevice) { + m_symbolFontId = fontProvider()->addSymbolFont(family, m_fontDevice); + } + if (m_symbolFontId == -1) { LOGE() << "fatal error: cannot load font: " << m_name; return; } diff --git a/src/engraving/internal/engravingfont.h b/src/engraving/internal/engravingfont.h index 17473f2fdd55..32aaf001cc73 100644 --- a/src/engraving/internal/engravingfont.h +++ b/src/engraving/internal/engravingfont.h @@ -50,16 +50,17 @@ class Painter; namespace mu::engraving { class Shape; -class EngravingFont : public IEngravingFont +class EngravingFont : public IEngravingFont, public muse::Contextable { - muse::GlobalInject fontProvider; - muse::GlobalInject engravingFonts; + muse::ContextInject fontProvider = { this }; + muse::ContextInject engravingFonts = { this }; public: EngravingFont(const std::string& name, const std::string& family, const muse::io::path_t& filePath, - const muse::io::path_t& metadataPath); + const muse::io::path_t& metadataPath, const muse::modularity::ContextPtr& iocCtx); EngravingFont(const std::string& name, const std::string& family, std::shared_ptr font, - std::shared_ptr metadata); + std::shared_ptr metadata, const muse::modularity::ContextPtr& iocCtx); EngravingFont(const EngravingFont& other); + ~EngravingFont() override; const std::string& name() const override; const std::string& family() const override; @@ -143,6 +144,7 @@ class EngravingFont : public IEngravingFont std::string m_family; std::shared_ptr m_fontDevice; std::shared_ptr m_metadataDevice; + int m_symbolFontId = -1; std::unordered_map m_engravingDefaults; double m_textEnclosureThickness = 0; diff --git a/src/engraving/internal/engravingfontsprovider.cpp b/src/engraving/internal/engravingfontsprovider.cpp index 7c6ce8a9599c..348aa43320cd 100644 --- a/src/engraving/internal/engravingfontsprovider.cpp +++ b/src/engraving/internal/engravingfontsprovider.cpp @@ -30,6 +30,11 @@ using namespace mu; using namespace mu::engraving; +EngravingFontsProvider::EngravingFontsProvider(const muse::modularity::ContextPtr& iocCtx) + : muse::Contextable(iocCtx) +{ +} + void EngravingFontsProvider::deinit() { m_symbolFonts.clear(); @@ -41,7 +46,7 @@ void EngravingFontsProvider::addInternalFont(const std::string& name, const std: { muse::io::path_t basePath = muse::io::dirpath(filePath.toQString()); muse::io::path_t metadataPath = basePath + "/metadata.json"; - std::shared_ptr f = std::make_shared(name, family, filePath, metadataPath); + std::shared_ptr f = std::make_shared(name, family, filePath, metadataPath, iocContext()); m_symbolFonts.push_back(f); m_fallback.font = nullptr; } @@ -56,7 +61,7 @@ void EngravingFontsProvider::addExternalFont(const std::string& name, const std: std::shared_ptr metadata) { UNUSED(family); - std::shared_ptr f = std::make_shared(name, family, std::move(font), std::move(metadata)); + std::shared_ptr f = std::make_shared(name, family, std::move(font), std::move(metadata), iocContext()); m_externalSymbolFonts.emplace(muse::strings::toLower(name), f); } diff --git a/src/engraving/internal/engravingfontsprovider.h b/src/engraving/internal/engravingfontsprovider.h index 197763dfc373..b0aa2b8536b3 100644 --- a/src/engraving/internal/engravingfontsprovider.h +++ b/src/engraving/internal/engravingfontsprovider.h @@ -30,9 +30,10 @@ namespace mu::engraving { class EngravingFont; -class EngravingFontsProvider : public IEngravingFontsProvider +class EngravingFontsProvider : public IEngravingFontsProvider, public muse::Contextable { public: + explicit EngravingFontsProvider(const muse::modularity::ContextPtr& iocCtx); void deinit(); diff --git a/src/notation/internal/engravingfontscontroller.h b/src/notation/internal/engravingfontscontroller.h index c8fcda0d94ba..1f8ba67d7a72 100644 --- a/src/notation/internal/engravingfontscontroller.h +++ b/src/notation/internal/engravingfontscontroller.h @@ -31,14 +31,17 @@ #include "ui/iuiconfiguration.h" namespace mu::notation { -class EngravingFontsController : public muse::async::Asyncable +class EngravingFontsController : public muse::async::Asyncable, public muse::Contextable { - muse::GlobalInject fontsDatabase; + muse::ContextInject fontsDatabase = { this }; muse::GlobalInject uiConfiguration; muse::GlobalInject configuration; - muse::GlobalInject engravingFonts; + muse::ContextInject engravingFonts = { this }; public: + EngravingFontsController(const muse::modularity::ContextPtr& iocCtx) + : muse::Contextable(iocCtx) {} + void init(); private: diff --git a/src/notation/notationmodule.cpp b/src/notation/notationmodule.cpp index de60ee1d9dd0..19e23decc713 100644 --- a/src/notation/notationmodule.cpp +++ b/src/notation/notationmodule.cpp @@ -50,10 +50,6 @@ void NotationModule::registerExports() m_configuration = std::make_shared(); m_instrumentsRepository = std::make_shared(); -#ifdef MUE_BUILD_ENGRAVING_FONTSCONTROLLER - m_engravingFontsController = std::make_shared(); -#endif - globalIoc()->registerExport(moduleName(), m_configuration); globalIoc()->registerExport(mname, m_instrumentsRepository); } @@ -85,10 +81,6 @@ void NotationModule::onInit(const IApplication::RunMode&) m_configuration->init(); m_instrumentsRepository->init(); -#ifdef MUE_BUILD_ENGRAVING_FONTSCONTROLLER - m_engravingFontsController->init(); -#endif - bool isVertical = m_configuration->canvasOrientation().val == muse::Orientation::Vertical; mu::engraving::MScore::setVerticalOrientation(isVertical); @@ -111,5 +103,16 @@ IContextSetup* NotationModule::newContext(const ContextPtr& ctx) const void NotationContext::registerExports() { +#ifdef MUE_BUILD_ENGRAVING_FONTSCONTROLLER + m_engravingFontsController = std::make_shared(iocContext()); +#endif + ioc()->registerExport(mname, new NotationContextConfiguration(iocContext())); } + +void NotationContext::onInit(const IApplication::RunMode&) +{ +#ifdef MUE_BUILD_ENGRAVING_FONTSCONTROLLER + m_engravingFontsController->init(); +#endif +} diff --git a/src/notation/notationmodule.h b/src/notation/notationmodule.h index 5c42e38fd2f8..7ccaf3566ca7 100644 --- a/src/notation/notationmodule.h +++ b/src/notation/notationmodule.h @@ -45,7 +45,6 @@ class NotationModule : public muse::modularity::IModuleSetup, public muse::async private: std::shared_ptr m_configuration; std::shared_ptr m_instrumentsRepository; - std::shared_ptr m_engravingFontsController; }; class NotationContext : public muse::modularity::IContextSetup @@ -55,5 +54,9 @@ class NotationContext : public muse::modularity::IContextSetup : muse::modularity::IContextSetup(ctx) {} void registerExports() override; + void onInit(const muse::IApplication::RunMode& mode) override; + +private: + std::shared_ptr m_engravingFontsController; }; } From bb250e0cb1afb284cb49ac2750bbb62d042f20ec Mon Sep 17 00:00:00 2001 From: Alexander Pavlov Date: Thu, 29 Oct 2026 16:31:19 +0200 Subject: [PATCH 02/11] engravingfontprovider consumers use local context --- src/engraving/dom/score.h | 2 +- src/engraving/dom/textbase.cpp | 10 +++++----- src/engraving/dom/textbase.h | 3 --- src/engraving/internal/palettescoreprovider.h | 2 +- src/engraving/rw/read400/readcontext.cpp | 5 +++++ src/engraving/rw/read400/readcontext.h | 4 +--- .../mei/internal/meiconverter.cpp | 17 ++++++++--------- src/importexport/mei/internal/meiconverter.h | 4 +--- src/importexport/mei/internal/meiimporter.cpp | 6 +++--- .../mnx/internal/export/mnxexportparts.cpp | 4 +--- .../internal/import/importmusicxmlpass1.cpp | 15 +++++---------- .../internal/import/importmusicxmlpass2.cpp | 19 +++++++------------ src/notationscene/widgets/editstyle.h | 2 +- src/palette/widgets/customizekitdialog.cpp | 12 +++++++----- src/palette/widgets/customizekitdialog.h | 2 +- src/palette/widgets/symboldialog.h | 2 +- .../notes/noteheads/noteheadgroupsmodel.h | 2 +- .../notation/symbols/symbolsettingsmodel.h | 2 +- 18 files changed, 50 insertions(+), 63 deletions(-) diff --git a/src/engraving/dom/score.h b/src/engraving/dom/score.h index 44a7e6ec993e..b703283a0932 100644 --- a/src/engraving/dom/score.h +++ b/src/engraving/dom/score.h @@ -279,7 +279,7 @@ class Score : public EngravingObject, public muse::Contextable DECLARE_CLASSOF(ElementType::SCORE) muse::GlobalInject configuration; - muse::GlobalInject engravingFonts; + muse::ContextInject engravingFonts = { this }; muse::ContextInject contextConfiguration; muse::ContextInject elementsProvider; muse::ContextInject paletteScoreProvider; diff --git a/src/engraving/dom/textbase.cpp b/src/engraving/dom/textbase.cpp index de7e1f1fa07f..b06fad6dbcfe 100644 --- a/src/engraving/dom/textbase.cpp +++ b/src/engraving/dom/textbase.cpp @@ -881,7 +881,8 @@ Font TextFragment::font(const TextBase* t) const Font::Type fontType = Font::Type::Unknown; if (format.fontFamily() == "ScoreText") { if (t->hasSymbolScale()) { - std::string fontName = engravingFonts()->fontByName(t->style().styleSt(Sid::musicalSymbolFont).toStdString())->family(); + std::string fontName + = t->score()->engravingFonts()->fontByName(t->style().styleSt(Sid::musicalSymbolFont).toStdString())->family(); family = String::fromStdString(fontName); fontType = Font::Type::MusicSymbol; @@ -892,7 +893,8 @@ Font TextFragment::font(const TextBase* t) const } if (t->style().styleB(Sid::dynamicsOverrideFont)) { - std::string fontName2 = engravingFonts()->fontByName(t->style().styleSt(Sid::dynamicsFont).toStdString())->family(); + std::string fontName2 + = t->score()->engravingFonts()->fontByName(t->style().styleSt(Sid::dynamicsFont).toStdString())->family(); family = String::fromStdString(fontName2); } @@ -1498,11 +1500,9 @@ TextBlock TextBlock::split(int column, TextCursor* cursor) static String toSymbolXml(Char c, const TextBase* t) { - static std::shared_ptr provider = muse::modularity::globalIoc()->resolve("engraving"); - SymId symId = t->score()->engravingFont()->fromCode(c.unicode()); if (symId == SymId::noSym) { - symId = provider->fallbackFont()->fromCode(c.unicode()); + symId = t->score()->engravingFonts()->fallbackFont()->fromCode(c.unicode()); } return u"" + String::fromAscii(SymNames::nameForSymId(symId).ascii()) + u""; } diff --git a/src/engraving/dom/textbase.h b/src/engraving/dom/textbase.h index c1ebb1055a1e..c89b3503f67f 100644 --- a/src/engraving/dom/textbase.h +++ b/src/engraving/dom/textbase.h @@ -223,9 +223,6 @@ class TextCursor class TextFragment { -public: - muse::GlobalInject engravingFonts; - public: mutable CharFormat format; PointF pos; // y is relative to TextBlock->y() diff --git a/src/engraving/internal/palettescoreprovider.h b/src/engraving/internal/palettescoreprovider.h index eba4fbab7e01..60252b4c5cfd 100644 --- a/src/engraving/internal/palettescoreprovider.h +++ b/src/engraving/internal/palettescoreprovider.h @@ -29,7 +29,7 @@ namespace mu::engraving { class PaletteScoreProvider : public IPaletteScoreProvider, public muse::Contextable { - muse::GlobalInject engravingfonts; + muse::ContextInject engravingfonts = { this }; public: PaletteScoreProvider(const muse::modularity::ContextPtr& iocCtx); ~PaletteScoreProvider() override; diff --git a/src/engraving/rw/read400/readcontext.cpp b/src/engraving/rw/read400/readcontext.cpp index fb04a33ec3a3..6800c5aa0fb7 100644 --- a/src/engraving/rw/read400/readcontext.cpp +++ b/src/engraving/rw/read400/readcontext.cpp @@ -82,6 +82,11 @@ const MStyle& ReadContext::style() const return score()->style(); } +std::shared_ptr ReadContext::engravingFonts() const +{ + return score()->engravingFonts(); +} + String ReadContext::mscoreVersion() const { return m_score->mscoreVersion(); diff --git a/src/engraving/rw/read400/readcontext.h b/src/engraving/rw/read400/readcontext.h index 68fdf4c1cc7c..772300ae35de 100644 --- a/src/engraving/rw/read400/readcontext.h +++ b/src/engraving/rw/read400/readcontext.h @@ -70,9 +70,6 @@ struct TextStyleMap { class ReadContext : public muse::Contextable { -public: - muse::GlobalInject engravingFonts; - public: ReadContext(const muse::modularity::ContextPtr& iocCtx); ReadContext(Score* score); @@ -82,6 +79,7 @@ class ReadContext : public muse::Contextable Score* score() const; const MStyle& style() const; + std::shared_ptr engravingFonts() const; bool pasteMode() const { return _pasteMode; } void setPasteMode(bool v) { _pasteMode = v; } diff --git a/src/importexport/mei/internal/meiconverter.cpp b/src/importexport/mei/internal/meiconverter.cpp index dd8f083073d9..249f849efb45 100644 --- a/src/importexport/mei/internal/meiconverter.cpp +++ b/src/importexport/mei/internal/meiconverter.cpp @@ -67,7 +67,6 @@ using namespace muse; StringList Convert::logs; -muse::GlobalInject Convert::engravingFonts; muse::GlobalInject Convert::engravingConfiguration; engraving::ElementType Convert::elementTypeForDir(const libmei::Element& meiElement) @@ -710,7 +709,7 @@ void Convert::breathFromMEI(engraving::Breath* breath, const libmei::Breath& mei } // This is for loading MEI files not written by MuseScore and that use @glyph.num instead of @glyph.name else if (smufl && meiBreath.HasGlyphNum()) { - symId = engravingFonts()->fallbackFont()->fromCode(meiBreath.GetGlyphNum()); + symId = breath->score()->engravingFonts()->fallbackFont()->fromCode(meiBreath.GetGlyphNum()); if (symId == engraving::SymId::noSym) { warning = true; } @@ -768,7 +767,7 @@ void Convert::caesuraFromMEI(engraving::Breath* breath, const libmei::Caesura& m } // This is for loading MEI files not written by MuseScore and that use @glyph.num instead of @glyph.name else if (smufl && meiCeasura.HasGlyphNum()) { - symId = engravingFonts()->fallbackFont()->fromCode(meiCeasura.GetGlyphNum()); + symId = breath->score()->engravingFonts()->fallbackFont()->fromCode(meiCeasura.GetGlyphNum()); if (symId == engraving::SymId::noSym) { warning = true; } @@ -1546,7 +1545,7 @@ void Convert::fermataFromMEI(engraving::Fermata* fermata, const libmei::Fermata& } // This is for loading MEI files not written by MuseScore and that use @glyph.num instead of @glyph.name else if (smufl && meiFermata.HasGlyphNum()) { - symId = engravingFonts()->fallbackFont()->fromCode(meiFermata.GetGlyphNum()); + symId = fermata->score()->engravingFonts()->fallbackFont()->fromCode(meiFermata.GetGlyphNum()); if (symId == engraving::SymId::noSym) { warning = true; } @@ -2361,7 +2360,7 @@ Convert::OrnamStruct Convert::mordentFromMEI(engraving::Ornament* ornament, cons } // This is for loading MEI files not written by MuseScore and that use @glyph.num instead of @glyph.name else if (smufl && meiMordent.HasGlyphNum()) { - symId = engravingFonts()->fallbackFont()->fromCode(meiMordent.GetGlyphNum()); + symId = ornament->score()->engravingFonts()->fallbackFont()->fromCode(meiMordent.GetGlyphNum()); if (symId == engraving::SymId::noSym) { warning = true; } @@ -3462,7 +3461,7 @@ std::tuple Convert::textToMEI(const engraving::T * The text block are {bool, string} pairs with true for smufl and false for plain text */ -void Convert::textFromMEI(String& text, const textWithSmufl& textBlocks) +void Convert::textFromMEI(String& text, const textWithSmufl& textBlocks, const engraving::Score* score) { text.clear(); @@ -3475,7 +3474,7 @@ void Convert::textFromMEI(String& text, const textWithSmufl& textBlocks) if (c < u'\uE000' || c > u'\uF8FF') { continue; // this should not happen because the char should be smufl } - engraving::SymId symId = engravingFonts()->fallbackFont()->fromCode(c); + engraving::SymId symId = score->engravingFonts()->fallbackFont()->fromCode(c); if (symId == engraving::SymId::noSym) { continue; // smufl code not found } @@ -3566,7 +3565,7 @@ Convert::OrnamStruct Convert::trillFromMEI(engraving::Ornament* ornament, const } // This is for loading MEI files not written by MuseScore and that use @glyph.num instead of @glyph.name else if (smufl && meiTrill.HasGlyphNum()) { - symId = engravingFonts()->fallbackFont()->fromCode(meiTrill.GetGlyphNum()); + symId = ornament->score()->engravingFonts()->fallbackFont()->fromCode(meiTrill.GetGlyphNum()); if (symId == engraving::SymId::noSym) { warning = true; } @@ -3692,7 +3691,7 @@ Convert::OrnamStruct Convert::turnFromMEI(engraving::Ornament* ornament, const l } // This is for loading MEI files not written by MuseScore and that use @glyph.num instead of @glyph.name else if (smufl && meiTurn.HasGlyphNum()) { - symId = engravingFonts()->fallbackFont()->fromCode(meiTurn.GetGlyphNum()); + symId = ornament->score()->engravingFonts()->fallbackFont()->fromCode(meiTurn.GetGlyphNum()); if (symId == engraving::SymId::noSym) { warning = true; } diff --git a/src/importexport/mei/internal/meiconverter.h b/src/importexport/mei/internal/meiconverter.h index 977b57497f3d..76b14aaf0406 100644 --- a/src/importexport/mei/internal/meiconverter.h +++ b/src/importexport/mei/internal/meiconverter.h @@ -88,8 +88,6 @@ enum ElisionType { class Convert { - // The fallback font is used to convert smufl codes (char32_t) to engraving::SymId - static muse::GlobalInject engravingFonts; static muse::GlobalInject engravingConfiguration; public: @@ -328,7 +326,7 @@ class Convert using textWithSmufl = std::vector >; - static void textFromMEI(muse::String& text, const textWithSmufl& textBlocks); + static void textFromMEI(muse::String& text, const textWithSmufl& textBlocks, const engraving::Score* score); static void textToMEI(textWithSmufl& textBlocks, const muse::String& text); static void tieFromMEI(engraving::SlurTie* tie, const libmei::Tie& meiTie, bool& warning); diff --git a/src/importexport/mei/internal/meiimporter.cpp b/src/importexport/mei/internal/meiimporter.cpp index 40fb554cc8bc..6b708f295b62 100644 --- a/src/importexport/mei/internal/meiimporter.cpp +++ b/src/importexport/mei/internal/meiimporter.cpp @@ -1200,7 +1200,7 @@ bool MeiImporter::readLinesWithSmufl(pugi::xml_node parentNode, StringList& line } // A line break, already convert the current text blocks else if (this->isNode(child, u"lb")) { - Convert::textFromMEI(line, lineBlocks); + Convert::textFromMEI(line, lineBlocks, m_score); lines.push_back(line); lineBlocks.clear(); } else { @@ -1209,7 +1209,7 @@ bool MeiImporter::readLinesWithSmufl(pugi::xml_node parentNode, StringList& line } // At the end, convert the remaining text blocks - Convert::textFromMEI(line, lineBlocks); + Convert::textFromMEI(line, lineBlocks, m_score); lines.push_back(line); return true; @@ -2332,7 +2332,7 @@ bool MeiImporter::readVerse(pugi::xml_node verseNode, Chord* chord) } String syllable; - Convert::textFromMEI(syllable, textBlocks); + Convert::textFromMEI(syllable, textBlocks, m_score); lyrics->setXmlText(syllable); lyrics->setVerse(no); diff --git a/src/importexport/mnx/internal/export/mnxexportparts.cpp b/src/importexport/mnx/internal/export/mnxexportparts.cpp index 7b642b996566..2a11e072fc5b 100644 --- a/src/importexport/mnx/internal/export/mnxexportparts.cpp +++ b/src/importexport/mnx/internal/export/mnxexportparts.cpp @@ -712,9 +712,7 @@ void MnxExporter::createArpeggios(const Part* part, const Measure* measure, mnx: /// describe -- the caller must not export a partial reading of it. static bool splitDynamicText(const Dynamic* dynamic, String& prefix, std::vector& symIds, String& suffix) { - const auto engravingFonts = [&]() -> std::shared_ptr { - return muse::modularity::globalIoc()->resolve("engraving"); - }(); + const std::shared_ptr engravingFonts = dynamic->score()->engravingFonts(); bool gotGlyph{}; bool gotSuffix{}; diff --git a/src/importexport/musicxml/internal/import/importmusicxmlpass1.cpp b/src/importexport/musicxml/internal/import/importmusicxmlpass1.cpp index 5bf983d30bf2..a9bd80715182 100644 --- a/src/importexport/musicxml/internal/import/importmusicxmlpass1.cpp +++ b/src/importexport/musicxml/internal/import/importmusicxmlpass1.cpp @@ -65,11 +65,6 @@ static std::shared_ptr configuration( return muse::modularity::globalIoc()->resolve("iex_musicxml"); } -static std::shared_ptr engravingFonts() -{ - return muse::modularity::globalIoc()->resolve("iex_musicxml"); -} - static bool musicXmlImportBreaks() { auto conf = configuration(); @@ -1577,7 +1572,7 @@ void MusicXmlParserPass1::identification() Convert SMuFL code points to MuseScore ... */ -static String text2syms(const String& t) +static String text2syms(const String& t, const Score* score) { //QTime time; //time.start(); @@ -1586,7 +1581,7 @@ static String text2syms(const String& t) // note that this takes about 1 msec on a Core i5, // caching does not gain much - IEngravingFontPtr sf = engravingFonts()->fallbackFont(); + IEngravingFontPtr sf = score->engravingFonts()->fallbackFont(); std::map map; size_t maxStringSize = 0; // maximum string size found @@ -1647,7 +1642,7 @@ static String text2syms(const String& t) Read the next part of a MusicXML formatted string and convert to MuseScore internal encoding. */ -static String nextPartOfFormattedString(XmlStreamReader& e) +static String nextPartOfFormattedString(XmlStreamReader& e, const Score* score) { //String lang = e.attribute(String("xml:lang"), "it"); String fontWeight = e.attribute("font-weight"); @@ -1661,7 +1656,7 @@ static String nextPartOfFormattedString(XmlStreamReader& e) String txt = e.readText(); // replace HTML entities txt = String::decodeXmlEntities(txt); - String syms = text2syms(txt); + String syms = text2syms(txt, score); if (overrideTextStyleForComposer(syms)) { return syms; } @@ -1768,7 +1763,7 @@ void MusicXmlParserPass1::credit(CreditWordsList& credits) valign = m_e.attribute("valign"); creditWordsRead = true; } - crwords += nextPartOfFormattedString(m_e); + crwords += nextPartOfFormattedString(m_e, m_score); } else if (m_e.name() == "credit-type") { // multiple credit-type elements may be present, supported by // e.g. Finale v26.3 for Mac. diff --git a/src/importexport/musicxml/internal/import/importmusicxmlpass2.cpp b/src/importexport/musicxml/internal/import/importmusicxmlpass2.cpp index 792d24ce86d6..2378e742f4d4 100644 --- a/src/importexport/musicxml/internal/import/importmusicxmlpass2.cpp +++ b/src/importexport/musicxml/internal/import/importmusicxmlpass2.cpp @@ -120,11 +120,6 @@ static std::shared_ptr configuration( return muse::modularity::globalIoc()->resolve("iex_musicxml"); } -static std::shared_ptr engravingFonts() -{ - return muse::modularity::globalIoc()->resolve("iex_musicxml"); -} - //--------------------------------------------------------- // local defines for debug output //--------------------------------------------------------- @@ -762,7 +757,7 @@ static void setPartInstruments(MusicXmlLogger* logger, const XmlStreamReader* xm characters are preserved as-is. */ namespace xmlpass2 { -static String text2syms(const String& t, bool isDolet = false) +static String text2syms(const String& t, const Score* score, bool isDolet = false) { //QTime time; //time.start(); @@ -771,7 +766,7 @@ static String text2syms(const String& t, bool isDolet = false) // note that this takes about 1 msec on a Core i5, // caching does not gain much - IEngravingFontPtr sf = engravingFonts()->fallbackFont(); + IEngravingFontPtr sf = score->engravingFonts()->fallbackFont(); std::map map; size_t maxStringSize = 0; // maximum string size found @@ -836,7 +831,7 @@ static String text2syms(const String& t, bool isDolet = false) // TODO: probably should be shared between pass 1 and 2 namespace xmlpass2 { -static String nextPartOfFormattedString(XmlStreamReader& e, bool isDolet = false) +static String nextPartOfFormattedString(XmlStreamReader& e, const Score* score, bool isDolet = false) { //String lang = e.attribute(String("xml:lang"), "it"); String fontWeight = e.attribute("font-weight"); @@ -850,7 +845,7 @@ static String nextPartOfFormattedString(XmlStreamReader& e, bool isDolet = false String txt = e.readText(); // replace HTML entities txt = String::decodeXmlEntities(txt); - String syms = xmlpass2::text2syms(txt, isDolet); + String syms = xmlpass2::text2syms(txt, score, isDolet); String importedtext; @@ -4043,7 +4038,7 @@ void MusicXmlParserDirection::directionType(std::vector& st } else if (m_e.name() == "words") { m_enclosure = m_e.attribute("enclosure"); m_fontFamily = m_e.attribute("font-family"); - String nextPart = xmlpass2::nextPartOfFormattedString(m_e, m_pass1.dolet()); + String nextPart = xmlpass2::nextPartOfFormattedString(m_e, m_score, m_pass1.dolet()); textToDynamic(nextPart); textToCrescLine(nextPart); @@ -4054,7 +4049,7 @@ void MusicXmlParserDirection::directionType(std::vector& st if (m_enclosure.empty()) { m_enclosure = u"square"; // note different default } - m_rehearsalText += xmlpass2::nextPartOfFormattedString(m_e, m_pass1.dolet()); + m_rehearsalText += xmlpass2::nextPartOfFormattedString(m_e, m_score, m_pass1.dolet()); } else if (m_e.name() == "harp-pedals") { harpPedal(); } else if (m_e.name() == "pedal") { @@ -8237,7 +8232,7 @@ void MusicXmlParserLyric::parse(bool visibility) LOGD("unknown syllabic %s", muPrintable(syll)); // TODO } } else if (m_e.name() == "text") { - formattedText += xmlpass2::nextPartOfFormattedString(m_e); + formattedText += xmlpass2::nextPartOfFormattedString(m_e, m_score); } else { skipLogCurrElem(); } diff --git a/src/notationscene/widgets/editstyle.h b/src/notationscene/widgets/editstyle.h index 933698aced9c..d578d2d1066a 100644 --- a/src/notationscene/widgets/editstyle.h +++ b/src/notationscene/widgets/editstyle.h @@ -50,7 +50,7 @@ class EditStyle : public muse::ui::WidgetDialog, private Ui::EditStyleBase muse::GlobalInject configuration; muse::GlobalInject uiConfiguration; - muse::GlobalInject engravingFonts; + muse::ContextInject engravingFonts = { this }; muse::ContextInject projectSession = { this }; muse::ContextInject interactive = { this }; muse::ContextInject uiEngine = { this }; diff --git a/src/palette/widgets/customizekitdialog.cpp b/src/palette/widgets/customizekitdialog.cpp index 86f5265d0354..c294ede207f5 100644 --- a/src/palette/widgets/customizekitdialog.cpp +++ b/src/palette/widgets/customizekitdialog.cpp @@ -122,14 +122,14 @@ struct SymbolIcon { : id(i), icon(j) {} - static SymbolIcon generateIcon(const SymId& id, double w, double h, double defaultScale) + static SymbolIcon generateIcon(const mu::engraving::IEngravingFontPtr& font, const SymId& id, double w, double h, double defaultScale) { QIcon icon; QPixmap image(w, h); image.fill(Qt::transparent); muse::draw::Painter painter(&image, "generateicon"); - const muse::RectF& bbox = CustomizeKitDialog::engravingFonts()->fallbackFont()->bbox(id, 1); + const muse::RectF& bbox = font->bbox(id, 1); const qreal actualSymbolScale = std::min(w / bbox.width(), h / bbox.height()); qreal mag = std::min(defaultScale, actualSymbolScale); const qreal& xStShift = (w - mag * bbox.width()) / 2 - mag * bbox.left(); @@ -139,7 +139,7 @@ struct SymbolIcon { painter.setPen(Color(CustomizeKitDialog::uiConfiguration()->currentTheme().values[muse::ui::FONT_PRIMARY_COLOR].toString())); painter.setBrush(Color::transparent); - CustomizeKitDialog::engravingFonts()->fallbackFont()->draw(id, &painter, mag, stPtPos); + font->draw(id, &painter, mag, stPtPos); icon.addPixmap(image); @@ -233,15 +233,17 @@ CustomizeKitDialog::CustomizeKitDialog(QWidget* parent) //default scale is 0.3, will use smaller scale for large noteheads symbols const qreal defaultScale = 0.3 * qApp->devicePixelRatio(); + const IEngravingFontPtr fallbackFont = engravingFonts()->fallbackFont(); + QList resNoteheads; for (SymId symId : primaryNoteheads) { - resNoteheads.append(SymbolIcon::generateIcon(symId, w, h, defaultScale)); + resNoteheads.append(SymbolIcon::generateIcon(fallbackFont, symId, w, h, defaultScale)); } for (const String& range : validNoteheadRanges) { for (SymId symId : Smufl::smuflRanges().at(range)) { if (!excludedSyms.contains(symId) && !primaryNoteheads.contains(symId)) { - resNoteheads.append(SymbolIcon::generateIcon(symId, w, h, defaultScale)); + resNoteheads.append(SymbolIcon::generateIcon(fallbackFont, symId, w, h, defaultScale)); } } } diff --git a/src/palette/widgets/customizekitdialog.h b/src/palette/widgets/customizekitdialog.h index e12591ee00ab..aaf16999a70a 100644 --- a/src/palette/widgets/customizekitdialog.h +++ b/src/palette/widgets/customizekitdialog.h @@ -48,7 +48,7 @@ class CustomizeKitDialog : public muse::ui::WidgetDialog, private Ui::CustomizeK Q_OBJECT public: - inline static muse::GlobalInject engravingFonts; + muse::ContextInject engravingFonts = { this }; inline static muse::GlobalInject uiConfiguration; muse::GlobalInject notationConfiguration; muse::GlobalInject engravingRenderer; diff --git a/src/palette/widgets/symboldialog.h b/src/palette/widgets/symboldialog.h index 39db42658974..2eac9ddba34b 100644 --- a/src/palette/widgets/symboldialog.h +++ b/src/palette/widgets/symboldialog.h @@ -40,7 +40,7 @@ class PaletteWidget; class SymbolDialog : public QWidget, Ui::SymbolDialogBase, public muse::Contextable { Q_OBJECT - muse::GlobalInject engravingFonts; + muse::ContextInject engravingFonts = { this }; muse::ContextInject projectSession = { this }; muse::ContextInject paletteScoreProvider = { this }; diff --git a/src/propertiespanel/qml/MuseScore/PropertiesPanel/notation/notes/noteheads/noteheadgroupsmodel.h b/src/propertiespanel/qml/MuseScore/PropertiesPanel/notation/notes/noteheads/noteheadgroupsmodel.h index a596bdc065dc..fa3b8e1bb9d9 100644 --- a/src/propertiespanel/qml/MuseScore/PropertiesPanel/notation/notes/noteheads/noteheadgroupsmodel.h +++ b/src/propertiespanel/qml/MuseScore/PropertiesPanel/notation/notes/noteheads/noteheadgroupsmodel.h @@ -34,7 +34,7 @@ class NoteheadGroupsModel : public QAbstractListModel, public muse::Contextable Q_OBJECT QML_ELEMENT - muse::GlobalInject engravingFonts; + muse::ContextInject engravingFonts = { this }; public: explicit NoteheadGroupsModel(QObject* parent = nullptr); diff --git a/src/propertiespanel/qml/MuseScore/PropertiesPanel/notation/symbols/symbolsettingsmodel.h b/src/propertiespanel/qml/MuseScore/PropertiesPanel/notation/symbols/symbolsettingsmodel.h index 7ce65663ba23..b70811c3903a 100644 --- a/src/propertiespanel/qml/MuseScore/PropertiesPanel/notation/symbols/symbolsettingsmodel.h +++ b/src/propertiespanel/qml/MuseScore/PropertiesPanel/notation/symbols/symbolsettingsmodel.h @@ -40,7 +40,7 @@ class SymbolSettingsModel : public PropertiesPanelAbstractModel Q_PROPERTY(QVariantList symFonts READ symFonts NOTIFY symFontsChanged) - muse::GlobalInject engravingFonts; + muse::ContextInject engravingFonts = { this }; public: explicit SymbolSettingsModel(QObject* parent, const muse::modularity::ContextPtr& iocCtx, IElementRepositoryService* repository); From 78ff40ef934891432ec303bd5cd79ee7540b22fd Mon Sep 17 00:00:00 2001 From: Alexander Pavlov Date: Thu, 29 Oct 2026 16:37:55 +0200 Subject: [PATCH 03/11] fontmetrics consumers use local context --- src/engraving/dom/harmony.cpp | 10 ++++----- src/engraving/dom/harmony.h | 6 +++-- src/engraving/dom/note.cpp | 2 +- src/engraving/dom/stafftype.cpp | 4 ++-- src/engraving/dom/textbase.cpp | 20 ++++++++--------- src/engraving/dom/textbase.h | 3 ++- src/engraving/rendering/score/boxlayout.cpp | 2 +- .../rendering/score/harmonylayout.cpp | 19 ++++++++-------- .../rendering/score/parenthesislayout.cpp | 2 +- src/engraving/rendering/score/tdraw.cpp | 4 ++-- src/engraving/rendering/score/textlayout.cpp | 12 +++++----- src/engraving/rendering/score/tlayout.cpp | 22 +++++++++---------- src/engraving/rendering/single/singledraw.cpp | 2 +- .../rendering/single/singlelayout.cpp | 10 ++++----- .../internal/import/importmusicxmlpass1.cpp | 2 +- .../videoexport/internal/videowriter.cpp | 4 ++-- .../fretdiagrams/internal/fretcanvas.cpp | 2 +- 17 files changed, 65 insertions(+), 61 deletions(-) diff --git a/src/engraving/dom/harmony.cpp b/src/engraving/dom/harmony.cpp index c831ae5d2e4d..94900029f4c9 100644 --- a/src/engraving/dom/harmony.cpp +++ b/src/engraving/dom/harmony.cpp @@ -1185,22 +1185,22 @@ void Harmony::setColor(const Color& color) double TextSegment::width() const { - return FontMetrics::width(m_font, m_text); + return FontMetrics::width(m_font, m_text, m_iocCtx); } double TextSegment::capHeight() const { - return FontMetrics::capHeight(m_font); + return FontMetrics::capHeight(m_font, m_iocCtx); } RectF TextSegment::tightBoundingRect() const { - return FontMetrics::tightBoundingRect(m_font, m_text); + return FontMetrics::tightBoundingRect(m_font, m_text, m_iocCtx); } RectF TextSegment::boundingRect() const { - return FontMetrics::boundingRect(m_font, m_text); + return FontMetrics::boundingRect(m_font, m_text, m_iocCtx); } void TextSegment::setFont(const muse::draw::Font& f) @@ -1211,7 +1211,7 @@ void TextSegment::setFont(const muse::draw::Font& f) } // Check all symbols in string are available in this font - FontMetrics fm(f); + FontMetrics fm(f, m_iocCtx); bool fail = false; for (size_t i = 0; i < m_text.size(); ++i) { const Char& c = m_text.at(i); diff --git a/src/engraving/dom/harmony.h b/src/engraving/dom/harmony.h index cbacf64ee617..9d58c6817092 100644 --- a/src/engraving/dom/harmony.h +++ b/src/engraving/dom/harmony.h @@ -131,12 +131,14 @@ struct TextSegment : HarmonyRenderItem { HarmonyRenderItemType type() const override { return HarmonyRenderItemType::TEXT; } - TextSegment(const String& s, const muse::draw::Font& f, double _x, double _y, bool align) - : HarmonyRenderItem(align, _x, _y) { setText(s); setFont(f); } + TextSegment(const String& s, const muse::draw::Font& f, double _x, double _y, bool align, + const muse::modularity::ContextPtr& iocCtx) + : HarmonyRenderItem(align, _x, _y), m_iocCtx(iocCtx) { setText(s); setFont(f); } private: muse::draw::Font m_font; String m_text; + muse::modularity::ContextPtr m_iocCtx; }; class HDegree; diff --git a/src/engraving/dom/note.cpp b/src/engraving/dom/note.cpp index 6e310b9636b6..2a8418ca67b6 100644 --- a/src/engraving/dom/note.cpp +++ b/src/engraving/dom/note.cpp @@ -1236,7 +1236,7 @@ double Note::tabHeadWidth(const StaffType* tab) const if (tab && tab->isTabStaff() && m_fret != INVALID_FRET_INDEX && m_string != INVALID_STRING_INDEX) { Font f = tab->fretFont(); f.setPointSizeF(tab->fretFontSize()); - val = FontMetrics::width(f, m_fretString) * magS(); + val = FontMetrics::width(f, m_fretString, iocContext()) * magS(); } else { val = headWidth(); } diff --git a/src/engraving/dom/stafftype.cpp b/src/engraving/dom/stafftype.cpp index 0664222513c7..03849f476b31 100644 --- a/src/engraving/dom/stafftype.cpp +++ b/src/engraving/dom/stafftype.cpp @@ -406,7 +406,7 @@ void StaffType::setDurationMetrics() // use a scaled up font and then scale computed values down Font font(durationFont()); font.setPointSizeF(m_durationFontSize); - FontMetrics fm(font); + FontMetrics fm(font, m_score->iocContext()); String txt(m_durationFonts[m_durationFontIdx].displayValue, size_t(TabVal::NUM_OF)); RectF bb(fm.tightBoundingRect(txt)); // raise symbols by a default margin and, if marks are above lines, by half the line distance @@ -428,7 +428,7 @@ void StaffType::setFretMetrics() return; } - FontMetrics fm(fretFont()); + FontMetrics fm(fretFont(), m_score->iocContext()); RectF bb; // compute vertical displacement if (m_useNumbers) { diff --git a/src/engraving/dom/textbase.cpp b/src/engraving/dom/textbase.cpp index b06fad6dbcfe..68074bc74937 100644 --- a/src/engraving/dom/textbase.cpp +++ b/src/engraving/dom/textbase.cpp @@ -285,7 +285,7 @@ RectF TextCursor::cursorRect() const // Ensure the cursor height matches that of the associated text font TextLayout::substituteMusicFont(_font, fragment->calculatedFontSize(m_text)); } - const FontMetrics fm(_font); + const FontMetrics fm(_font, m_text->iocContext()); double fontCapHeight = fm.capHeight(); double fontAscent = fm.ascent(); @@ -911,9 +911,9 @@ Font TextFragment::font(const TextBase* t) const // check if all symbols are available font.setFamily(family, fontType); font.setNoFontMerging(true); - FontMetrics fm(font); + FontMetrics fm(font, t->iocContext()); - resolveFallback(fontType, fm, family); + resolveFallback(fontType, fm, family, t->iocContext()); } else { family = format.fontFamily(); fontType = Font::Type::Unknown; @@ -950,7 +950,7 @@ double TextFragment::calculatedFontSize(const TextBase* t) const } void TextFragment::resolveFallback(muse::draw::Font::Type fontType, const muse::draw::FontMetrics& fm, - String& family) const + String& family, const muse::modularity::ContextPtr& iocCtx) const { std::vector missingChars; for (size_t i = 0; i < text.size(); ++i) { @@ -974,8 +974,8 @@ void TextFragment::resolveFallback(muse::draw::Font::Type fontType, const muse:: static String fallbackSymbolFontFamily = String::fromUtf8(FALLBACK_SYMBOL_FONT); static String fallbackSymbolTextFontFamily = String::fromUtf8(FALLBACK_SYMBOLTEXT_FONT); - static FontMetrics fallbackSymbolFM(Font(fallbackSymbolFontFamily, Font::Type::MusicSymbol)); - static FontMetrics fallbackSymbolTextFM(Font(fallbackSymbolTextFontFamily, Font::Type::MusicSymbolText)); + const FontMetrics fallbackSymbolFM(Font(fallbackSymbolFontFamily, Font::Type::MusicSymbol), iocCtx); + const FontMetrics fallbackSymbolTextFM(Font(fallbackSymbolTextFontFamily, Font::Type::MusicSymbolText), iocCtx); if (fontType == Font::Type::MusicSymbol) { for (char32_t missingChar : missingChars) { @@ -1022,7 +1022,7 @@ double TextBlock::xpos(size_t column, const TextBase* t) const if (column == col) { return f.pos.x(); } - FontMetrics fm(f.font(t)); + FontMetrics fm(f.font(t), t->iocContext()); size_t idx = 0; for (size_t i = 0; i < f.text.size(); ++i) { ++idx; @@ -1128,7 +1128,7 @@ int TextBlock::column(double x, TextBase* t) const if (f.text.at(i).isHighSurrogate()) { continue; } - FontMetrics fm(f.font(t)); + FontMetrics fm(f.font(t), t->iocContext()); double xo = fm.width(f.text.left(idx)); if (x <= f.pos.x() + px + (xo - px) * .5) { return col; @@ -1865,7 +1865,7 @@ void TextBase::layoutFrame(LayoutData* ldata) const // if (empty()) { // or bbox.width() <= 1.0 if (ldata->bbox().width() <= 1.0 || ldata->bbox().height() < 1.0) { // or bbox.width() <= 1.0 // this does not work for Harmony: - FontMetrics fm(font()); + FontMetrics fm(font(), iocContext()); double ch = fm.ascent(); double cw = fm.width('n'); ldata->frame = RectF(0.0, -ch, cw, ch); @@ -2585,7 +2585,7 @@ Font TextBase::font() const FontMetrics TextBase::fontMetrics() const { - return FontMetrics(font()); + return FontMetrics(font(), iocContext()); } bool TextBase::isPropertyLinkedToMaster(Pid id) const diff --git a/src/engraving/dom/textbase.h b/src/engraving/dom/textbase.h index c89b3503f67f..23b29bb0c7da 100644 --- a/src/engraving/dom/textbase.h +++ b/src/engraving/dom/textbase.h @@ -244,7 +244,8 @@ class TextFragment void changeFormat(FormatId id, const FormatValue& data); private: - void resolveFallback(muse::draw::Font::Type fontType, const muse::draw::FontMetrics& fm, String& family) const; + void resolveFallback(muse::draw::Font::Type fontType, const muse::draw::FontMetrics& fm, String& family, + const muse::modularity::ContextPtr& iocCtx) const; }; //--------------------------------------------------------- diff --git a/src/engraving/rendering/score/boxlayout.cpp b/src/engraving/rendering/score/boxlayout.cpp index e82cb7598abf..a19120ffe763 100644 --- a/src/engraving/rendering/score/boxlayout.cpp +++ b/src/engraving/rendering/score/boxlayout.cpp @@ -354,7 +354,7 @@ void BoxLayout::layoutTBox(const TBox* item, TBox::LayoutData* ldata, const Layo double h = 0.0; if (item->text()->empty()) { - h = FontMetrics::ascent(item->text()->font()); + h = FontMetrics::ascent(item->text()->font(), item->iocContext()); } else { h = textLD->bbox().height(); } diff --git a/src/engraving/rendering/score/harmonylayout.cpp b/src/engraving/rendering/score/harmonylayout.cpp index 6ea899bc390d..38bc13f759ed 100644 --- a/src/engraving/rendering/score/harmonylayout.cpp +++ b/src/engraving/rendering/score/harmonylayout.cpp @@ -662,7 +662,7 @@ void HarmonyLayout::render(Harmony* item, Harmony::LayoutData* ldata, const Stri } Font f = item->harmonyType() != HarmonyType::ROMAN ? ldata->fontList.value().front() : item->font(); - TextSegment* ts = new TextSegment(s, f, harmonyCtx.x(), harmonyCtx.y(), harmonyCtx.hAlign); + TextSegment* ts = new TextSegment(s, f, harmonyCtx.x(), harmonyCtx.y(), harmonyCtx.hAlign, item->iocContext()); harmonyCtx.renderItemList.push_back(ts); harmonyCtx.movex(ts->width()); } @@ -678,7 +678,7 @@ void HarmonyLayout::render(Harmony* item, Harmony::LayoutData* ldata, SymId sym, String s = ctx.conf().engravingFont()->toString(sym); - TextSegment* ts = new TextSegment(s, f, harmonyCtx.x(), harmonyCtx.y(), harmonyCtx.hAlign); + TextSegment* ts = new TextSegment(s, f, harmonyCtx.x(), harmonyCtx.y(), harmonyCtx.hAlign, item->iocContext()); harmonyCtx.renderItemList.push_back(ts); harmonyCtx.movex(ts->width()); } @@ -788,7 +788,7 @@ void HarmonyLayout::renderActionNote(Harmony* item, Harmony::LayoutData* ldata, muse::draw::Font font = cs.isValid() ? ldata->fontList.value()[cs.fontIdx] : ldata->fontList.value().front(); font.setPointSizeF(font.pointSizeF() * harmonyCtx.scale); - TextSegment* ts = new TextSegment(text, font, harmonyCtx.x(), harmonyCtx.y(), harmonyCtx.hAlign); + TextSegment* ts = new TextSegment(text, font, harmonyCtx.x(), harmonyCtx.y(), harmonyCtx.hAlign, item->iocContext()); harmonyCtx.renderItemList.push_back(ts); harmonyCtx.movex(ts->width()); } @@ -841,7 +841,7 @@ void HarmonyLayout::renderActionAcc(Harmony* item, Harmony::LayoutData* ldata, H muse::draw::Font font = cs.isValid() ? ldata->fontList.value()[cs.fontIdx] : ldata->fontList.value().front(); font.setPointSizeF(font.pointSizeF() * harmonyCtx.scale); - TextSegment* ts = new TextSegment(text, font, harmonyCtx.x(), harmonyCtx.y(), harmonyCtx.hAlign); + TextSegment* ts = new TextSegment(text, font, harmonyCtx.x(), harmonyCtx.y(), harmonyCtx.hAlign, item->iocContext()); harmonyCtx.renderItemList.push_back(ts); harmonyCtx.movex(ts->width()); } @@ -913,9 +913,10 @@ void HarmonyLayout::kernCharacters(const Harmony* item, const String& text, Harm } bool startMatchAny = kernPair.second.isEmpty(); if ((endChar && startChar) || (endChar && startMatchAny)) { - const FontMetrics fm = FontMetrics(item->font()); + const FontMetrics fm = FontMetrics(item->font(), item->iocContext()); const double scale = harmonyCtx.scale * item->mag(); - harmonyCtx.pos = harmonyCtx.pos + PointF(kernInfo.second, 0.0) * FontMetrics::capHeight(item->font()) * scale; + harmonyCtx.pos = harmonyCtx.pos + + PointF(kernInfo.second, 0.0) * FontMetrics::capHeight(item->font(), item->iocContext()) * scale; break; } } @@ -936,7 +937,7 @@ void HarmonyLayout::renderActionSet(Harmony* item, Harmony::LayoutData* ldata, c kernCharacters(item, text, harmonyCtx, ctx); - TextSegment* ts = new TextSegment(text, font, harmonyCtx.x(), harmonyCtx.y(), harmonyCtx.hAlign); + TextSegment* ts = new TextSegment(text, font, harmonyCtx.x(), harmonyCtx.y(), harmonyCtx.hAlign, item->iocContext()); harmonyCtx.movex(ts->width()); if (a->renderText()) { @@ -950,13 +951,13 @@ void HarmonyLayout::renderActionSet(Harmony* item, Harmony::LayoutData* ldata, c void HarmonyLayout::renderActionMove(Harmony* item, const RenderActionMovePtr& a, HarmonyRenderCtx& harmonyCtx) { const double scale = (a->scaled() ? harmonyCtx.scale : 1.0) * item->mag(); - harmonyCtx.pos = harmonyCtx.pos + a->vec() * FontMetrics::capHeight(item->font()) * scale; + harmonyCtx.pos = harmonyCtx.pos + a->vec() * FontMetrics::capHeight(item->font(), item->iocContext()) * scale; } void HarmonyLayout::renderActionMoveXHeight(Harmony* item, const RenderActionMoveXHeightPtr& a, HarmonyRenderCtx& harmonyCtx) { const int direction = a->up() ? -1 : 1; const double scale = a->scaled() ? harmonyCtx.scale : 1.0; - const FontMetrics fm = FontMetrics(item->font()); + const FontMetrics fm = FontMetrics(item->font(), item->iocContext()); harmonyCtx.movey(direction * fm.xHeight() * scale); } diff --git a/src/engraving/rendering/score/parenthesislayout.cpp b/src/engraving/rendering/score/parenthesislayout.cpp index 177812c2d457..43621755cdda 100644 --- a/src/engraving/rendering/score/parenthesislayout.cpp +++ b/src/engraving/rendering/score/parenthesislayout.cpp @@ -484,7 +484,7 @@ void ParenthesisLayout::setHarmonyValues(Parenthesis* item, Parenthesis::LayoutD double extension = 0.1 * spatium * (parent->size() / 10.0); double bottom = parent->baseLine() + extension; - double defaultCapHeight = muse::draw::FontMetrics::capHeight(parent->font()); + double defaultCapHeight = muse::draw::FontMetrics::capHeight(parent->font(), parent->iocContext()); double topCapHeight = DBL_MAX; const TextSegment* rootTextSeg = nullptr; diff --git a/src/engraving/rendering/score/tdraw.cpp b/src/engraving/rendering/score/tdraw.cpp index 12aefd747942..7dd8a157bdfd 100644 --- a/src/engraving/rendering/score/tdraw.cpp +++ b/src/engraving/rendering/score/tdraw.cpp @@ -910,7 +910,7 @@ void TDraw::draw(const BarLine* item, Painter* painter, const PaintOptions& opt) f.setPointSizeF(12 * item->spatium() / item->defaultSpatium()); f.setBold(true); Char ch = measure->ticks() > measure->timesig() ? u'+' : u'-'; - RectF r = FontMetrics(f).boundingRect(ch); + RectF r = FontMetrics(f, item->iocContext()).boundingRect(ch); painter->setFont(f); painter->drawText(-r.width(), -item->spatium(), ch); @@ -1654,7 +1654,7 @@ void TDraw::draw(const GlissandoSegment* item, Painter* painter, const PaintOpti f.setItalic(glissando->fontStyle() & FontStyle::Italic); f.setUnderline(glissando->fontStyle() & FontStyle::Underline); f.setStrike(glissando->fontStyle() & FontStyle::Strike); - FontMetrics fm(f); + FontMetrics fm(f, item->iocContext()); RectF r = fm.boundingRect(glissando->text()); // if text longer than available space, skip it diff --git a/src/engraving/rendering/score/textlayout.cpp b/src/engraving/rendering/score/textlayout.cpp index beae4d8cf430..5b10d478086d 100644 --- a/src/engraving/rendering/score/textlayout.cpp +++ b/src/engraving/rendering/score/textlayout.cpp @@ -161,7 +161,7 @@ void TextLayout::computeTextHighResShape(const TextBase* item, TextBase::LayoutD for (const TextBlock& block : ldata->blocks) { double y = block.y(); for (const TextFragment& fragment : block.fragments()) { - FontMetrics fontMetrics = FontMetrics(fragment.font(item)); + FontMetrics fontMetrics = FontMetrics(fragment.font(item), item->iocContext()); double x = fragment.pos.x(); size_t textSize = fragment.text.size(); for (size_t i = 0; i < textSize; ++i) { @@ -271,7 +271,7 @@ void TextLayout::justifyLine(const TextBase* item, TextBlock* textBlock, double std::vector subfrags; for (const TextFragment& f : textBlock->fragments()) { String current; - FontMetrics fm(f.font(item)); + FontMetrics fm(f.font(item), item->iocContext()); for (size_t i = 0; i < f.text.size(); ++i) { Char c = f.text.at(i); current += c; @@ -328,7 +328,7 @@ void TextLayout::layoutTextBlock(TextBlock* item, const TextBase* t) f.pos.setX(x); Font font = f.font(t); substituteMusicFont(font, f.calculatedFontSize(t)); - FontMetrics fm(font); + FontMetrics fm(font, t->iocContext()); if (f.format.valign() != VerticalAlignment::AlignNormal) { double voffset = fm.xHeight() / SUBSCRIPT_SIZE; // use original height if (f.format.valign() == VerticalAlignment::AlignSubScript) { @@ -351,7 +351,7 @@ void TextLayout::layoutTextBlock(TextBlock* item, const TextBase* t) TextFragment& f = *fi; f.pos.setX(x); Font fragmentFont = f.font(t); - FontMetrics fm(fragmentFont); + FontMetrics fm(fragmentFont, t->iocContext()); if (f.format.valign() != VerticalAlignment::AlignNormal) { double voffset = fm.xHeight() / SUBSCRIPT_SIZE; // use original height if (f.format.valign() == VerticalAlignment::AlignSubScript) { @@ -418,7 +418,7 @@ double TextLayout::musicSymbolBaseLineAdjust(const TextBlock* block, const TextB const std::list::iterator fi) { Font fragmentFont = f.font(t); - FontMetrics fm(fragmentFont); + FontMetrics fm(fragmentFont, t->iocContext()); const bool adjustSymbol = fragmentFont.type() == Font::Type::MusicSymbolText && t->isMarker(); if (!adjustSymbol) { return 0.0; @@ -432,7 +432,7 @@ double TextLayout::musicSymbolBaseLineAdjust(const TextBlock* block, const TextB TextFragment& refFragment = fi != block->fragments().begin() ? *(std::prev(fi)) : *(std::next(fi)); refFont = refFragment.font(t); } - FontMetrics refFm(refFont); + FontMetrics refFm(refFont, t->iocContext()); const double middle = (fm.tightBoundingRect(f.text).height() / 2) - fm.tightBoundingRect(f.text).bottom(); const double refXHeight = refFm.capHeight() / 2; diff --git a/src/engraving/rendering/score/tlayout.cpp b/src/engraving/rendering/score/tlayout.cpp index 68e8099ce896..aa9ae8d2832c 100644 --- a/src/engraving/rendering/score/tlayout.cpp +++ b/src/engraving/rendering/score/tlayout.cpp @@ -632,7 +632,7 @@ void TLayout::layoutActionIcon(const ActionIcon* item, ActionIcon::LayoutData* l return; } - FontMetrics fontMetrics(item->iconFont()); + FontMetrics fontMetrics(item->iconFont(), item->iocContext()); ldata->setBbox(fontMetrics.boundingRect(Char(item->icon()))); ldata->setPos(PointF()); } @@ -1317,7 +1317,7 @@ void TLayout::layoutBend(const Bend* item, Bend::LayoutData* ldata) RectF bb; - FontMetrics fm(item->font(spatium)); + FontMetrics fm(item->font(spatium), item->iocContext()); size_t n = item->points().size(); double x = ldata->noteWidth; @@ -2092,7 +2092,7 @@ void TLayout::layoutFiguredBassItem(const FiguredBassItem* item, FiguredBassItem // (use the same font selection as used in draw() below) double m = ctx.conf().styleD(Sid::figuredBassFontSize) * item->spatium() / item->defaultSpatium(); f.setPointSizeF(m); - FontMetrics fm(f); + FontMetrics fm(f, item->iocContext()); String str; double x = item->symWidth(SymId::noteheadBlack) * .5; @@ -2524,7 +2524,7 @@ void TLayout::layoutFretDiagram(const FretDiagram* item, FretDiagram::LayoutData } } Font scaledFont(item->fretNumFont()); - FontMetrics fm2(scaledFont); + FontMetrics fm2(scaledFont, item->iocContext()); String fretText = String::number(item->fretOffset() + 1); if (ctx.conf().styleB(Sid::fretUseCustomSuffix)) { fretText += ctx.conf().styleSt(Sid::fretCustomSuffix); @@ -2556,7 +2556,7 @@ void TLayout::layoutFretDiagram(const FretDiagram* item, FretDiagram::LayoutData if (item->showFingering()) { const double padding = 0.2 * spatium; Font fingeringFont = item->fingeringFont(); - FontMetrics fontMetrics(fingeringFont); + FontMetrics fontMetrics(fingeringFont, item->iocContext()); double fontHeight = fontMetrics.capHeight(); for (size_t i = 0; i < item->fingering().size(); ++i) { int finger = item->fingering()[i]; @@ -3709,7 +3709,7 @@ void TLayout::layoutLayoutBreak(const LayoutBreak* item, LayoutBreak::LayoutData return; } - FontMetrics metrics(item->font()); + FontMetrics metrics(item->font(), item->iocContext()); RectF bbox = metrics.boundingRect(item->iconCode()); ldata->setShape(Shape(bbox, item)); } @@ -3724,7 +3724,7 @@ void TLayout::layoutIndicatorIcon(const IndicatorIcon* item, IndicatorIcon::Layo Shape shape; - const FontMetrics metrics(item->font()); + const FontMetrics metrics(item->font(), item->iocContext()); const RectF iconBox = metrics.boundingRect(item->iconCode()); shape.add(iconBox, item); @@ -3766,7 +3766,7 @@ void TLayout::layoutIndicatorIcon(const IndicatorIcon* item, IndicatorIcon::Layo for (const SystemLockIndicator* sli : item->system()->systemLockIndicators()) { if (sli != item && sli->systemLock()->endMB() == endMB) { - const double sliWidth = FontMetrics(sli->font()).boundingRect(sli->iconCode()).width(); + const double sliWidth = FontMetrics(sli->font(), sli->iocContext()).boundingRect(sli->iconCode()).width(); // TODO: Rough spacing here xOffset -= (sliWidth * 2) - spatium; } @@ -4379,7 +4379,7 @@ void TLayout::layoutPageLockIndicator(const PageLockIndicator* item, PageLockInd const double spatium = item->spatium(); - const FontMetrics metrics(item->font()); + const FontMetrics metrics(item->font(), item->iocContext()); const RectF iconBox = metrics.boundingRect(item->iconCode()); shape.add(iconBox, item); @@ -5613,7 +5613,7 @@ void TLayout::layoutFSymbol(const FSymbol* item, FSymbol::LayoutData* ldata) return; } - ldata->setBbox(FontMetrics::boundingRect(item->font(), item->toString())); + ldata->setBbox(FontMetrics::boundingRect(item->font(), item->toString(), item->iocContext())); } void TLayout::layoutSystemDivider(const SystemDivider* item, SystemDivider::LayoutData* ldata, const LayoutContext& ctx) @@ -5685,7 +5685,7 @@ void TLayout::layoutTabDurationSymbol(const TabDurationSymbol* item, TabDuration && connects(chord, Navigation::nextChordRest(chord)); // if no chord (shouldn't happens...) or not a special beam mode, layout regular symbol if (beamLevel < 1 || (!joinsPrevious && !joinsNext)) { - FontMetrics fm(item->tab()->durationFont()); + FontMetrics fm(item->tab()->durationFont(), item->iocContext()); hbb = item->tab()->durationBoxH(); wbb = fm.width(item->text()); xbb = 0.0; diff --git a/src/engraving/rendering/single/singledraw.cpp b/src/engraving/rendering/single/singledraw.cpp index 7a09df084161..d89f4679f3fe 100644 --- a/src/engraving/rendering/single/singledraw.cpp +++ b/src/engraving/rendering/single/singledraw.cpp @@ -1457,7 +1457,7 @@ void SingleDraw::draw(const GlissandoSegment* item, Painter* painter, const Pain f.setItalic(glissando->fontStyle() & FontStyle::Italic); f.setUnderline(glissando->fontStyle() & FontStyle::Underline); f.setStrike(glissando->fontStyle() & FontStyle::Strike); - FontMetrics fm(f); + FontMetrics fm(f, item->iocContext()); RectF r = fm.boundingRect(glissando->text()); // if text longer than available space, skip it diff --git a/src/engraving/rendering/single/singlelayout.cpp b/src/engraving/rendering/single/singlelayout.cpp index 0e8f34cb9e72..0a63afbe354a 100644 --- a/src/engraving/rendering/single/singlelayout.cpp +++ b/src/engraving/rendering/single/singlelayout.cpp @@ -330,7 +330,7 @@ void SingleLayout::layout(Accidental* item, const Context&) void SingleLayout::layout(ActionIcon* item, const Context&) { - FontMetrics fontMetrics(item->iconFont()); + FontMetrics fontMetrics(item->iconFont(), item->iocContext()); item->setbbox(fontMetrics.boundingRect(Char(item->icon()))); } @@ -672,7 +672,7 @@ void SingleLayout::layout(Bend* item, const Context&) RectF bb; - FontMetrics fm(item->font(spatium)); + FontMetrics fm(item->font(spatium), item->iocContext()); size_t n = item->points().size(); double x = ldata->noteWidth; @@ -997,7 +997,7 @@ void SingleLayout::layout(FretDiagram* item, const Context& ctx) Font scaledFont(item->fretNumFont()); scaledFont.setPointSizeF(item->fretNumFont().pointSizeF() * item->userMag()); - FontMetrics fm2(scaledFont); + FontMetrics fm2(scaledFont, item->iocContext()); double numw = fm2.width(String::number(item->fretOffset() + 1)); double xdiff = numw + ldata->stringDist * .4; w += xdiff; @@ -1014,7 +1014,7 @@ void SingleLayout::layout(FretDiagram* item, const Context& ctx) void SingleLayout::layout(FSymbol* item, const Context&) { - item->setbbox(FontMetrics::boundingRect(item->font(), item->toString())); + item->setbbox(FontMetrics::boundingRect(item->font(), item->toString(), item->iocContext())); item->setOffset(0.0, 0.0); item->setPos(0.0, 0.0); } @@ -1399,7 +1399,7 @@ void SingleLayout::layout(KeySig* item, const Context& ctx) void SingleLayout::layout(LayoutBreak* item, const Context&) { - FontMetrics metrics(item->font()); + FontMetrics metrics(item->font(), item->iocContext()); RectF bbox = metrics.boundingRect(item->iconCode()); item->mutldata()->setShape(Shape(bbox, item)); } diff --git a/src/importexport/musicxml/internal/import/importmusicxmlpass1.cpp b/src/importexport/musicxml/internal/import/importmusicxmlpass1.cpp index a9bd80715182..75ea1d1f3cea 100644 --- a/src/importexport/musicxml/internal/import/importmusicxmlpass1.cpp +++ b/src/importexport/musicxml/internal/import/importmusicxmlpass1.cpp @@ -1907,7 +1907,7 @@ static double scaleText(const String& str, const Sid fontFaceSid, const double f const String fontFace = style.styleV(fontFaceSid).value(); Font font(fontFace, Font::Type::Unknown); font.setPointSizeF(fontSize); - const FontMetrics fm(font); + const FontMetrics fm(font, score->iocContext()); const double pagePrintableWidth = style.styleV(Sid::pagePrintableWidth).value() * DPI; diff --git a/src/importexport/videoexport/internal/videowriter.cpp b/src/importexport/videoexport/internal/videowriter.cpp index 88b3fe93ee95..db091afda358 100644 --- a/src/importexport/videoexport/internal/videowriter.cpp +++ b/src/importexport/videoexport/internal/videowriter.cpp @@ -495,11 +495,11 @@ bool VideoWriter::generateLeadingFrames(muse::media::IVideoEncoderPtr encoder, I return std::max(1, static_cast(std::ceil(textWidth / maxTextWidth))); }; - FontMetrics titleFontMetrics(titleFont); + FontMetrics titleFontMetrics(titleFont, iocContext()); const int titleLines = lineCount(titleFontMetrics, title); const double titleHeight = titleLines * titleFontMetrics.lineSpacing(); - FontMetrics subtitleFontMetrics(subtitleFont); + FontMetrics subtitleFontMetrics(subtitleFont, iocContext()); const int subtitleLines = lineCount(subtitleFontMetrics, subtitle); const double subtitleHeight = subtitleLines * subtitleFontMetrics.lineSpacing(); diff --git a/src/propertiespanel/qml/MuseScore/PropertiesPanel/notation/fretdiagrams/internal/fretcanvas.cpp b/src/propertiespanel/qml/MuseScore/PropertiesPanel/notation/fretdiagrams/internal/fretcanvas.cpp index 614f656bdb9d..3396ea265bd7 100644 --- a/src/propertiespanel/qml/MuseScore/PropertiesPanel/notation/fretdiagrams/internal/fretcanvas.cpp +++ b/src/propertiespanel/qml/MuseScore/PropertiesPanel/notation/fretdiagrams/internal/fretcanvas.cpp @@ -205,7 +205,7 @@ void FretCanvas::draw(QPainter* painter) if (m_diagram->showFingering()) { // Copy-pasted from layout and drawing code. Needs cleanup in future. (M.S.) const double padding = 0.2 * _spatium; - muse::draw::FontMetrics fontMetrics(muse::draw::Font::fromQFont(font, muse::draw::Font::Type::Text)); + muse::draw::FontMetrics fontMetrics(muse::draw::Font::fromQFont(font, muse::draw::Font::Type::Text), iocContext()); double fontHeight = fontMetrics.capHeight(); for (size_t i = 0; i < m_diagram->fingering().size(); ++i) { int finger = m_diagram->fingering()[i]; From 43e82ea1814d061e669736318a20319f7d1d2b08 Mon Sep 17 00:00:00 2001 From: Alexander Pavlov Date: Thu, 29 Oct 2026 17:04:20 +0200 Subject: [PATCH 04/11] storing default cap height as fixed number --- src/engraving/rw/compat/compatutils.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/engraving/rw/compat/compatutils.cpp b/src/engraving/rw/compat/compatutils.cpp index 866d4878541e..f93ba88f5030 100644 --- a/src/engraving/rw/compat/compatutils.cpp +++ b/src/engraving/rw/compat/compatutils.cpp @@ -598,9 +598,7 @@ double CompatUtils::convertChordExtModUnits(double val) // The best we can do for conversion of old files is to assume a default spatium of 1.75mm and a default font size of 10pt // The height value is calculated from Edwin at 10pt using FontMetrics::capHeight const double DEFAULT_SPATIUM = StyleDef::styleValues[static_cast(Sid::spatium)].defaultValue.toDouble(); - muse::draw::Font f(u"Edwin", muse::draw::Font::Type::Text); - f.setPointSizeF(10); - const double DEFAULT_FONT_CAP_HEIGHT = muse::draw::FontMetrics::capHeight(f); // 121 + const double DEFAULT_FONT_CAP_HEIGHT = 121; // Edwin at 10pt return ((val / 5) * DEFAULT_SPATIUM) / DEFAULT_FONT_CAP_HEIGHT; } From 829edc9a986fc1f3d8f6fd52f7871c66a9f11bf6 Mon Sep 17 00:00:00 2001 From: Alexander Pavlov Date: Thu, 29 Oct 2026 17:06:18 +0200 Subject: [PATCH 05/11] tests are moved to local context --- src/braille/tests/environment.cpp | 4 ++-- src/converter/tests/environment.cpp | 1 + src/engraving/api/tests/environment.cpp | 4 ++-- src/engraving/tests/environment.cpp | 4 ++-- src/engraving/tests/utils/scorerw.cpp | 8 ++++++-- src/engraving/tests/utils/scorerw.h | 1 + src/importexport/bb/tests/environment.cpp | 4 ++-- src/importexport/bww/tests/environment.cpp | 6 ++++-- src/importexport/capella/tests/environment.cpp | 4 ++-- src/importexport/guitarpro/tests/environment.cpp | 4 ++-- src/importexport/lyricsexport/tests/environment.cpp | 4 ++-- src/importexport/mei/tests/environment.cpp | 4 ++-- src/importexport/midi/tests/environment.cpp | 4 ++-- src/importexport/mnx/tests/environment.cpp | 4 ++-- src/importexport/mnx/tests/mnx_tests.cpp | 2 +- src/importexport/musicxml/tests/environment.cpp | 4 ++-- src/importexport/ove/tests/environment.cpp | 4 ++-- src/importexport/tabledit/tests/environment.cpp | 4 ++-- .../qml/MuseScore/NotationScene/tests/environment.cpp | 1 + 19 files changed, 40 insertions(+), 31 deletions(-) diff --git a/src/braille/tests/environment.cpp b/src/braille/tests/environment.cpp index 67feb694d66f..4c191b520142 100644 --- a/src/braille/tests/environment.cpp +++ b/src/braille/tests/environment.cpp @@ -29,7 +29,7 @@ #include "engraving/dom/instrtemplate.h" #include "engraving/dom/mscore.h" -static muse::testing::SuiteEnvironment importexport_se( +static muse::testing::SuiteEnvironment importexport_se = muse::testing::SuiteEnvironment( { new muse::draw::DrawModule(), new mu::engraving::EngravingModule() @@ -46,4 +46,4 @@ static muse::testing::SuiteEnvironment importexport_se( mu::engraving::loadInstrumentTemplates(":/engraving/instruments/instruments.xml"); } - ); + ).setContext(mu::engraving::ScoreRW::iocContext()); diff --git a/src/converter/tests/environment.cpp b/src/converter/tests/environment.cpp index 847c6bc5e5ca..c874e030a18c 100644 --- a/src/converter/tests/environment.cpp +++ b/src/converter/tests/environment.cpp @@ -32,6 +32,7 @@ static muse::testing::SuiteEnvironment converter_se = muse::testing::SuiteEnvironment() .setDependencyModules({ new muse::draw::DrawModule(), new mu::engraving::EngravingModule() }) + .setContext(mu::engraving::ScoreRW::iocContext()) .setPostInit([]() { LOGI() << "converter tests suite post init"; diff --git a/src/engraving/api/tests/environment.cpp b/src/engraving/api/tests/environment.cpp index e76a30c4a73c..ab7c95fe5d15 100644 --- a/src/engraving/api/tests/environment.cpp +++ b/src/engraving/api/tests/environment.cpp @@ -32,7 +32,7 @@ #include "log.h" -static muse::testing::SuiteEnvironment engraving_api_se( +static muse::testing::SuiteEnvironment engraving_api_se = muse::testing::SuiteEnvironment( { new muse::draw::DrawModule(), new mu::engraving::EngravingModule() @@ -49,4 +49,4 @@ static muse::testing::SuiteEnvironment engraving_api_se( // Load instrument templates for tests that need them mu::engraving::loadInstrumentTemplates(":/engraving/instruments/instruments.xml"); } - ); + ).setContext(mu::engraving::ScoreRW::iocContext()); diff --git a/src/engraving/tests/environment.cpp b/src/engraving/tests/environment.cpp index 151455325eb8..a847b689cf31 100644 --- a/src/engraving/tests/environment.cpp +++ b/src/engraving/tests/environment.cpp @@ -36,7 +36,7 @@ static const mu::engraving::IEngravingConfiguration::DebuggingOptions debugOpt {}; -static muse::testing::SuiteEnvironment engraving_se( +static muse::testing::SuiteEnvironment engraving_se = muse::testing::SuiteEnvironment( { new muse::draw::DrawModule(), new mu::engraving::EngravingModule() @@ -77,4 +77,4 @@ static muse::testing::SuiteEnvironment engraving_se( mu::engraving::IEngravingConfiguration* ecptr = mock.get(); delete ecptr; } - ); + ).setContext(mu::engraving::ScoreRW::iocContext()); diff --git a/src/engraving/tests/utils/scorerw.cpp b/src/engraving/tests/utils/scorerw.cpp index a5f89e29f7a4..410be3f414f0 100644 --- a/src/engraving/tests/utils/scorerw.cpp +++ b/src/engraving/tests/utils/scorerw.cpp @@ -43,7 +43,11 @@ using namespace mu::engraving; String ScoreRW::m_rootPath; //! NOTE Temporary for testing -static const muse::modularity::ContextPtr utestCtx = std::make_shared(1); +const muse::modularity::ContextPtr& ScoreRW::iocContext() +{ + static const muse::modularity::ContextPtr utestCtx = std::make_shared(1); + return utestCtx; +} void ScoreRW::setRootPath(const String& path) { @@ -58,7 +62,7 @@ String ScoreRW::rootPath() MasterScore* ScoreRW::readScore(const String& name, bool isAbsolutePath, ImportFunc importFunc, const muse::modularity::ContextPtr& iocCtx_) { - const muse::modularity::ContextPtr iocCtx = iocCtx_ ? iocCtx_ : utestCtx; + const muse::modularity::ContextPtr iocCtx = iocCtx_ ? iocCtx_ : iocContext(); muse::io::path_t path = isAbsolutePath ? name : (rootPath() + u"/" + name); MasterScore* score = compat::ScoreAccess::createMasterScoreWithBaseStyle(iocCtx); diff --git a/src/engraving/tests/utils/scorerw.h b/src/engraving/tests/utils/scorerw.h index a2d0ecb16127..25f89f173d6e 100644 --- a/src/engraving/tests/utils/scorerw.h +++ b/src/engraving/tests/utils/scorerw.h @@ -38,6 +38,7 @@ class ScoreRW public: ScoreRW() = default; + static const muse::modularity::ContextPtr& iocContext(); static void setRootPath(const String& path); static String rootPath(); diff --git a/src/importexport/bb/tests/environment.cpp b/src/importexport/bb/tests/environment.cpp index e616305854c4..69a2dc353142 100644 --- a/src/importexport/bb/tests/environment.cpp +++ b/src/importexport/bb/tests/environment.cpp @@ -31,7 +31,7 @@ #include "log.h" -static muse::testing::SuiteEnvironment importexport_se( +static muse::testing::SuiteEnvironment importexport_se = muse::testing::SuiteEnvironment( { new muse::draw::DrawModule(), new mu::engraving::EngravingModule() @@ -47,4 +47,4 @@ static muse::testing::SuiteEnvironment importexport_se( mu::engraving::loadInstrumentTemplates(":/engraving/instruments/instruments.xml"); } - ); + ).setContext(mu::engraving::ScoreRW::iocContext()); diff --git a/src/importexport/bww/tests/environment.cpp b/src/importexport/bww/tests/environment.cpp index 105d8bbed336..a3fa8c11832d 100644 --- a/src/importexport/bww/tests/environment.cpp +++ b/src/importexport/bww/tests/environment.cpp @@ -25,12 +25,14 @@ #include "draw/drawmodule.h" #include "engraving/engravingmodule.h" +#include "engraving/tests/utils/scorerw.h" + #include "engraving/dom/instrtemplate.h" #include "engraving/dom/mscore.h" #include "log.h" -static muse::testing::SuiteEnvironment importexport_se( +static muse::testing::SuiteEnvironment importexport_se = muse::testing::SuiteEnvironment( { new muse::draw::DrawModule(), new mu::engraving::EngravingModule() @@ -44,4 +46,4 @@ static muse::testing::SuiteEnvironment importexport_se( mu::engraving::loadInstrumentTemplates(":/engraving/instruments/instruments.xml"); } - ); + ).setContext(mu::engraving::ScoreRW::iocContext()); diff --git a/src/importexport/capella/tests/environment.cpp b/src/importexport/capella/tests/environment.cpp index a4adc526c209..61cace7c6460 100644 --- a/src/importexport/capella/tests/environment.cpp +++ b/src/importexport/capella/tests/environment.cpp @@ -31,7 +31,7 @@ #include "log.h" -static muse::testing::SuiteEnvironment importexport_se( +static muse::testing::SuiteEnvironment importexport_se = muse::testing::SuiteEnvironment( { new muse::draw::DrawModule(), new mu::engraving::EngravingModule() @@ -47,4 +47,4 @@ static muse::testing::SuiteEnvironment importexport_se( mu::engraving::loadInstrumentTemplates(":/engraving/instruments/instruments.xml"); } - ); + ).setContext(mu::engraving::ScoreRW::iocContext()); diff --git a/src/importexport/guitarpro/tests/environment.cpp b/src/importexport/guitarpro/tests/environment.cpp index 887b3519bbce..c3b8f607d616 100644 --- a/src/importexport/guitarpro/tests/environment.cpp +++ b/src/importexport/guitarpro/tests/environment.cpp @@ -35,7 +35,7 @@ using namespace mu::iex::guitarpro; -static muse::testing::SuiteEnvironment importexport_se( +static muse::testing::SuiteEnvironment importexport_se = muse::testing::SuiteEnvironment( { new muse::draw::DrawModule(), // needs for engraving new mu::engraving::EngravingModule(), @@ -53,4 +53,4 @@ static muse::testing::SuiteEnvironment importexport_se( mu::engraving::loadInstrumentTemplates(":/engraving/instruments/instruments.xml"); } - ); + ).setContext(mu::engraving::ScoreRW::iocContext()); diff --git a/src/importexport/lyricsexport/tests/environment.cpp b/src/importexport/lyricsexport/tests/environment.cpp index 83be029c90e5..170c722686de 100644 --- a/src/importexport/lyricsexport/tests/environment.cpp +++ b/src/importexport/lyricsexport/tests/environment.cpp @@ -33,7 +33,7 @@ #include "log.h" -static muse::testing::SuiteEnvironment importexport_se( +static muse::testing::SuiteEnvironment importexport_se = muse::testing::SuiteEnvironment( { new muse::draw::DrawModule(), new mu::engraving::EngravingModule(), @@ -50,4 +50,4 @@ static muse::testing::SuiteEnvironment importexport_se( mu::engraving::loadInstrumentTemplates(":/engraving/instruments/instruments.xml"); } - ); + ).setContext(mu::engraving::ScoreRW::iocContext()); diff --git a/src/importexport/mei/tests/environment.cpp b/src/importexport/mei/tests/environment.cpp index 78a7d7179a75..e05a41fbbdab 100644 --- a/src/importexport/mei/tests/environment.cpp +++ b/src/importexport/mei/tests/environment.cpp @@ -35,7 +35,7 @@ using namespace mu::iex::mei; -static muse::testing::SuiteEnvironment importexport_se( +static muse::testing::SuiteEnvironment importexport_se = muse::testing::SuiteEnvironment( { new muse::draw::DrawModule(), // needs for engraving new mu::engraving::EngravingModule(), @@ -52,4 +52,4 @@ static muse::testing::SuiteEnvironment importexport_se( mu::engraving::loadInstrumentTemplates(":/engraving/instruments/instruments.xml"); } - ); + ).setContext(mu::engraving::ScoreRW::iocContext()); diff --git a/src/importexport/midi/tests/environment.cpp b/src/importexport/midi/tests/environment.cpp index b80e5c76e6a7..4f5bfdc0ef79 100644 --- a/src/importexport/midi/tests/environment.cpp +++ b/src/importexport/midi/tests/environment.cpp @@ -32,7 +32,7 @@ #include "log.h" -static muse::testing::SuiteEnvironment importexport_se( +static muse::testing::SuiteEnvironment importexport_se = muse::testing::SuiteEnvironment( { new muse::draw::DrawModule(), new mu::engraving::EngravingModule() @@ -48,4 +48,4 @@ static muse::testing::SuiteEnvironment importexport_se( mu::engraving::loadInstrumentTemplates(":/engraving/instruments/instruments.xml"); } - ); + ).setContext(mu::engraving::ScoreRW::iocContext()); diff --git a/src/importexport/mnx/tests/environment.cpp b/src/importexport/mnx/tests/environment.cpp index 76afaf9accd8..b72440fbf3a3 100644 --- a/src/importexport/mnx/tests/environment.cpp +++ b/src/importexport/mnx/tests/environment.cpp @@ -36,7 +36,7 @@ using namespace mu; using namespace mu::engraving; -static muse::testing::SuiteEnvironment mnx_se( +static muse::testing::SuiteEnvironment mnx_se = muse::testing::SuiteEnvironment( { new muse::draw::DrawModule(), new mu::engraving::EngravingModule(), @@ -53,4 +53,4 @@ static muse::testing::SuiteEnvironment mnx_se( loadInstrumentTemplates(":/engraving/instruments/instruments.xml"); } - ); + ).setContext(mu::engraving::ScoreRW::iocContext()); diff --git a/src/importexport/mnx/tests/mnx_tests.cpp b/src/importexport/mnx/tests/mnx_tests.cpp index 8cfea43bdc41..434bd7290324 100644 --- a/src/importexport/mnx/tests/mnx_tests.cpp +++ b/src/importexport/mnx/tests/mnx_tests.cpp @@ -292,7 +292,7 @@ static void fixupScore(MasterScore* score) MasterScore* Mnx_Tests::readMnxScore(const String& fileName, bool isAbsolutePath) { const muse::io::path_t path = isAbsolutePath ? fileName : (ScoreRW::rootPath() + u"/" + fileName); - MasterScore* score = compat::ScoreAccess::createMasterScoreWithBaseStyle(muse::modularity::globalCtx()); + MasterScore* score = compat::ScoreAccess::createMasterScoreWithBaseStyle(ScoreRW::iocContext()); score->setFileInfoProvider(std::make_shared(path)); NotationMnxReader reader(muse::modularity::globalCtx()); diff --git a/src/importexport/musicxml/tests/environment.cpp b/src/importexport/musicxml/tests/environment.cpp index 7c69983598f4..c27774ef2bbc 100644 --- a/src/importexport/musicxml/tests/environment.cpp +++ b/src/importexport/musicxml/tests/environment.cpp @@ -36,7 +36,7 @@ using namespace mu; using namespace mu::engraving; -static muse::testing::SuiteEnvironment musicxml_se( +static muse::testing::SuiteEnvironment musicxml_se = muse::testing::SuiteEnvironment( { new muse::draw::DrawModule(), new mu::engraving::EngravingModule(), @@ -53,4 +53,4 @@ static muse::testing::SuiteEnvironment musicxml_se( loadInstrumentTemplates(":/engraving/instruments/instruments.xml"); } - ); + ).setContext(mu::engraving::ScoreRW::iocContext()); diff --git a/src/importexport/ove/tests/environment.cpp b/src/importexport/ove/tests/environment.cpp index 8a113db9f605..f96f885de0c9 100644 --- a/src/importexport/ove/tests/environment.cpp +++ b/src/importexport/ove/tests/environment.cpp @@ -33,7 +33,7 @@ #include "log.h" -static muse::testing::SuiteEnvironment importexport_se( +static muse::testing::SuiteEnvironment importexport_se = muse::testing::SuiteEnvironment( { new muse::draw::DrawModule(), // needs for engraving new mu::engraving::EngravingModule(), @@ -50,4 +50,4 @@ static muse::testing::SuiteEnvironment importexport_se( mu::engraving::loadInstrumentTemplates(":/engraving/instruments/instruments.xml"); } - ); + ).setContext(mu::engraving::ScoreRW::iocContext()); diff --git a/src/importexport/tabledit/tests/environment.cpp b/src/importexport/tabledit/tests/environment.cpp index 67aecd75ddb6..6d75b36049c0 100644 --- a/src/importexport/tabledit/tests/environment.cpp +++ b/src/importexport/tabledit/tests/environment.cpp @@ -34,7 +34,7 @@ using namespace mu::iex::tabledit; -static muse::testing::SuiteEnvironment importexport_se( +static muse::testing::SuiteEnvironment importexport_se = muse::testing::SuiteEnvironment( { new muse::draw::DrawModule(), // needs for engraving new mu::engraving::EngravingModule(), @@ -51,4 +51,4 @@ static muse::testing::SuiteEnvironment importexport_se( mu::engraving::loadInstrumentTemplates(":/engraving/instruments/instruments.xml"); } - ); + ).setContext(mu::engraving::ScoreRW::iocContext()); diff --git a/src/notationscene/qml/MuseScore/NotationScene/tests/environment.cpp b/src/notationscene/qml/MuseScore/NotationScene/tests/environment.cpp index cf43dcb237e2..bfaeff72267d 100644 --- a/src/notationscene/qml/MuseScore/NotationScene/tests/environment.cpp +++ b/src/notationscene/qml/MuseScore/NotationScene/tests/environment.cpp @@ -32,6 +32,7 @@ static muse::testing::SuiteEnvironment notation_se = muse::testing::SuiteEnvironment() .setDependencyModules({ new muse::draw::DrawModule(), new mu::engraving::EngravingModule() }) + .setContext(mu::engraving::ScoreRW::iocContext()) .setPostInit([]() { LOGI() << "notationscene_qml tests suite post init"; From 3faa3051e6e2c5c2e1cce4dd4593a8532413732d Mon Sep 17 00:00:00 2001 From: Alexander Pavlov Date: Fri, 30 Oct 2026 01:02:42 +0200 Subject: [PATCH 06/11] fixed build without qt --- tools/check_build_without_qt/fontproviderstub.cpp | 4 ++++ tools/check_build_without_qt/fontproviderstub.h | 1 + tools/check_build_without_qt/main.cpp | 5 +++-- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/tools/check_build_without_qt/fontproviderstub.cpp b/tools/check_build_without_qt/fontproviderstub.cpp index 37db0479ea57..9ed78505e3fb 100644 --- a/tools/check_build_without_qt/fontproviderstub.cpp +++ b/tools/check_build_without_qt/fontproviderstub.cpp @@ -13,6 +13,10 @@ int FontProviderStub::addSymbolFont(const String&, std::shared_ptr return -1; } +void FontProviderStub::removeSymbolFont(int) +{ +} + double FontProviderStub::lineSpacing(const Font&) const { return 0.0; diff --git a/tools/check_build_without_qt/fontproviderstub.h b/tools/check_build_without_qt/fontproviderstub.h index 6d798a773ecc..d5ba4cd76611 100644 --- a/tools/check_build_without_qt/fontproviderstub.h +++ b/tools/check_build_without_qt/fontproviderstub.h @@ -10,6 +10,7 @@ class FontProviderStub : public IFontProvider int addSymbolFont(const String& family, const io::path_t& path) override; int addSymbolFont(const String& family, std::shared_ptr device) override; + void removeSymbolFont(int id) override; double lineSpacing(const Font& f) const override; double xHeight(const Font& f) const override; diff --git a/tools/check_build_without_qt/main.cpp b/tools/check_build_without_qt/main.cpp index 2fec4d5dc4df..7867e3575627 100644 --- a/tools/check_build_without_qt/main.cpp +++ b/tools/check_build_without_qt/main.cpp @@ -9,9 +9,10 @@ int main() { - muse::modularity::globalIoc()->registerExport("test", new muse::draw::FontProviderStub()); + const muse::modularity::ContextPtr ctx = std::make_shared(1); + muse::modularity::ioc(ctx)->registerExport("test", new muse::draw::FontProviderStub()); - mu::engraving::compat::ScoreAccess::createMasterScore(nullptr); + mu::engraving::compat::ScoreAccess::createMasterScore(ctx); mu::iex::guitarpro::GuitarProModule gm; } From d6d46816c80bc742df02c46fd140fecb0daf49f1 Mon Sep 17 00:00:00 2001 From: Alexander Pavlov Date: Fri, 30 Oct 2026 02:34:33 +0200 Subject: [PATCH 07/11] painters take the context of the score --- src/app/internal/consoleapp.cpp | 10 ++++----- .../drawdata/diagnosticdrawprovider.cpp | 18 ++++++++------- .../drawdata/diagnosticdrawprovider.h | 10 +++++---- .../devtools/drawdata/drawdataconverter.cpp | 9 ++++++-- .../devtools/drawdata/drawdataconverter.h | 5 +++-- .../devtools/drawdata/drawdatagenerator.cpp | 11 +++++++--- .../devtools/drawdata/drawdatagenerator.h | 4 +++- .../drawdata/idiagnosticdrawprovider.h | 12 ++++++---- src/engraving/rw/mscsaver.cpp | 2 +- src/engraving/tests/drawdata_tests.cpp | 22 ++++++++++--------- .../imagesexport/internal/pdfwriter.cpp | 4 ++-- .../imagesexport/internal/pngwriter.cpp | 2 +- .../imagesexport/internal/svgwriter.cpp | 2 +- .../videoexport/internal/videowriter.cpp | 2 +- src/notation/internal/notationinteraction.cpp | 2 +- .../abstractnotationpaintview.cpp | 2 +- .../NotationScene/paintedengravingitem.cpp | 6 ++++- src/notationscene/widgets/exampleview.cpp | 2 +- .../internal/palettecelliconengine.cpp | 2 +- src/palette/widgets/customizekitdialog.cpp | 9 ++++---- src/palette/widgets/keyedit.cpp | 2 +- src/palette/widgets/palettewidget.cpp | 4 ++-- src/print/internal/printprovider.cpp | 2 +- 23 files changed, 86 insertions(+), 58 deletions(-) diff --git a/src/app/internal/consoleapp.cpp b/src/app/internal/consoleapp.cpp index c8b161582299..a078e9abbc06 100644 --- a/src/app/internal/consoleapp.cpp +++ b/src/app/internal/consoleapp.cpp @@ -261,7 +261,7 @@ int MuseScoreConsoleApp::processConverter(const MuseScoreCmdOptions::ConverterTa return ret.code(); } -int MuseScoreConsoleApp::processDiagnostic(const MuseScoreCmdOptions::Diagnostic& task, const muse::modularity::ContextPtr&) +int MuseScoreConsoleApp::processDiagnostic(const MuseScoreCmdOptions::Diagnostic& task, const muse::modularity::ContextPtr& ctx) { if (!diagnosticDrawProvider()) { return make_ret(Ret::Code::NotSupported); @@ -286,16 +286,16 @@ int MuseScoreConsoleApp::processDiagnostic(const MuseScoreCmdOptions::Diagnostic switch (task.type) { case DiagnosticType::GenDrawData: - ret = diagnosticDrawProvider()->generateDrawData(input.front(), output); + ret = diagnosticDrawProvider()->generateDrawData(input.front(), output, ctx); break; case DiagnosticType::ComDrawData: { IF_ASSERT_FAILED(input.size() == 2) { return make_ret(Ret::Code::UnknownError); } - ret = diagnosticDrawProvider()->compareDrawData(input.at(0), input.at(1), output); + ret = diagnosticDrawProvider()->compareDrawData(input.at(0), input.at(1), output, ctx); } break; case DiagnosticType::DrawDataToPng: - ret = diagnosticDrawProvider()->drawDataToPng(input.front(), output); + ret = diagnosticDrawProvider()->drawDataToPng(input.front(), output, ctx); break; case DiagnosticType::DrawDiffToPng: { muse::io::path_t diffPath = input.at(0); @@ -303,7 +303,7 @@ int MuseScoreConsoleApp::processDiagnostic(const MuseScoreCmdOptions::Diagnostic if (input.size() > 1) { refPath = input.at(1); } - ret = diagnosticDrawProvider()->drawDiffToPng(diffPath, refPath, output); + ret = diagnosticDrawProvider()->drawDiffToPng(diffPath, refPath, output, ctx); } break; default: break; diff --git a/src/engraving/devtools/drawdata/diagnosticdrawprovider.cpp b/src/engraving/devtools/drawdata/diagnosticdrawprovider.cpp index 4ef6f512142e..80315b898ae0 100644 --- a/src/engraving/devtools/drawdata/diagnosticdrawprovider.cpp +++ b/src/engraving/devtools/drawdata/diagnosticdrawprovider.cpp @@ -41,10 +41,11 @@ using namespace mu::engraving; // ./vtest/scores/accidental-1.mscx -o ./work/1_accidental-1.exp.png // ./vtest/scores/emmentaler-text-3.mscx -o ./work/emmentaler-text-3.png -Ret DiagnosticDrawProvider::generateDrawData(const muse::io::path_t& dirOrFile, const muse::io::path_t& outDirOrFile, const GenOpt& opt) +Ret DiagnosticDrawProvider::generateDrawData(const muse::io::path_t& dirOrFile, const muse::io::path_t& outDirOrFile, + const muse::modularity::ContextPtr& iocCtx, const GenOpt& opt) { LOGI() << "scoresDir: " << dirOrFile << ", outDir: " << outDirOrFile; - DrawDataGenerator g; + DrawDataGenerator g(iocCtx); if (io::FileInfo(dirOrFile).entryType() == io::EntryType::File) { return g.processFile(dirOrFile, outDirOrFile, opt); @@ -54,7 +55,7 @@ Ret DiagnosticDrawProvider::generateDrawData(const muse::io::path_t& dirOrFile, } Ret DiagnosticDrawProvider::compareDrawData(const muse::io::path_t& ref, const muse::io::path_t& test, const muse::io::path_t& outDiff, - const ComOpt& opt) + const muse::modularity::ContextPtr& iocCtx, const ComOpt& opt) { LOGI() << "ref: " << ref << ", test: " << test << ", outDiff: " << outDiff; DrawDataComparator c; @@ -72,7 +73,7 @@ Ret DiagnosticDrawProvider::compareDrawData(const muse::io::path_t& ref, const m } if (opt.isMakePng) { - DrawDataConverter c2; + DrawDataConverter c2(iocCtx); c2.drawDataToPng(ref, outDir + "/" + io::FileInfo(ref).completeBaseName() + ".ref.png"); c2.drawDataToPng(test, outDir + "/" + io::FileInfo(test).completeBaseName() + ".png"); c2.drawDiffToPng(outDiff, ref, outDir + "/" + io::FileInfo(outDiff).completeBaseName() + ".diff.png"); @@ -81,17 +82,18 @@ Ret DiagnosticDrawProvider::compareDrawData(const muse::io::path_t& ref, const m return ret; } -Ret DiagnosticDrawProvider::drawDataToPng(const muse::io::path_t& dataFile, const muse::io::path_t& outFile) +Ret DiagnosticDrawProvider::drawDataToPng(const muse::io::path_t& dataFile, const muse::io::path_t& outFile, + const muse::modularity::ContextPtr& iocCtx) { LOGI() << "dataFile: " << dataFile << ", outFile: " << outFile; - DrawDataConverter c; + DrawDataConverter c(iocCtx); return c.drawDataToPng(dataFile, outFile); } Ret DiagnosticDrawProvider::drawDiffToPng(const muse::io::path_t& diffFile, const muse::io::path_t& refFile, - const muse::io::path_t& outFile) + const muse::io::path_t& outFile, const muse::modularity::ContextPtr& iocCtx) { LOGI() << "diffFile: " << diffFile << ", refFile: " << refFile << ", outFile: " << outFile; - DrawDataConverter c; + DrawDataConverter c(iocCtx); return c.drawDiffToPng(diffFile, refFile, outFile); } diff --git a/src/engraving/devtools/drawdata/diagnosticdrawprovider.h b/src/engraving/devtools/drawdata/diagnosticdrawprovider.h index bbe50077b85a..076525a792fd 100644 --- a/src/engraving/devtools/drawdata/diagnosticdrawprovider.h +++ b/src/engraving/devtools/drawdata/diagnosticdrawprovider.h @@ -29,10 +29,12 @@ class DiagnosticDrawProvider : public IDiagnosticDrawProvider { public: muse::Ret generateDrawData(const muse::io::path_t& dirOrFile, const muse::io::path_t& outDirOrFile, - const GenOpt& opt = GenOpt()) override; + const muse::modularity::ContextPtr& iocCtx, const GenOpt& opt = GenOpt()) override; muse::Ret compareDrawData(const muse::io::path_t& ref, const muse::io::path_t& test, const muse::io::path_t& outDiff, - const ComOpt& opt = ComOpt()) override; - muse::Ret drawDataToPng(const muse::io::path_t& dataFile, const muse::io::path_t& outFile) override; - muse::Ret drawDiffToPng(const muse::io::path_t& diffFile, const muse::io::path_t& refFile, const muse::io::path_t& outFile) override; + const muse::modularity::ContextPtr& iocCtx, const ComOpt& opt = ComOpt()) override; + muse::Ret drawDataToPng(const muse::io::path_t& dataFile, const muse::io::path_t& outFile, + const muse::modularity::ContextPtr& iocCtx) override; + muse::Ret drawDiffToPng(const muse::io::path_t& diffFile, const muse::io::path_t& refFile, const muse::io::path_t& outFile, + const muse::modularity::ContextPtr& iocCtx) override; }; } diff --git a/src/engraving/devtools/drawdata/drawdataconverter.cpp b/src/engraving/devtools/drawdata/drawdataconverter.cpp index 41f663b91c62..5f1b50c78f02 100644 --- a/src/engraving/devtools/drawdata/drawdataconverter.cpp +++ b/src/engraving/devtools/drawdata/drawdataconverter.cpp @@ -37,6 +37,11 @@ using namespace muse::draw; static const Color REF_COLOR("#999999"); static const Color ADDED_COLOR("#ff0000"); +DrawDataConverter::DrawDataConverter(const muse::modularity::ContextPtr& iocCtx) + : muse::Contextable(iocCtx) +{ +} + Ret DrawDataConverter::drawDataToPng(const muse::io::path_t& dataFile, const muse::io::path_t& outFile) { RetVal drawData = DrawDataRW::readData(dataFile); @@ -93,7 +98,7 @@ Pixmap DrawDataConverter::drawDataToPixmap(const DrawDataPtr& data) image.fill(Qt::white); - Painter painter(&image, "DrawData"); + Painter painter(&image, "DrawData", iocContext()); DrawDataPaint::paint(&painter, data); @@ -109,7 +114,7 @@ void DrawDataConverter::drawOnPixmap(Pixmap& px, const DrawDataPtr& data, const qim.setDotsPerMeterX(std::lrint((DrawData::CANVAS_DPI * 1000) / mu::engraving::INCH)); qim.setDotsPerMeterY(std::lrint((DrawData::CANVAS_DPI * 1000) / mu::engraving::INCH)); - Painter painter(&qim, "DrawData"); + Painter painter(&qim, "DrawData", iocContext()); DrawDataPaint::paint(&painter, data, overlay); painter.endDraw(); diff --git a/src/engraving/devtools/drawdata/drawdataconverter.h b/src/engraving/devtools/drawdata/drawdataconverter.h index 70b01c66000e..ab6ca3386aa2 100644 --- a/src/engraving/devtools/drawdata/drawdataconverter.h +++ b/src/engraving/devtools/drawdata/drawdataconverter.h @@ -26,12 +26,13 @@ #include "global/io/path.h" #include "draw/types/drawdata.h" #include "draw/types/pixmap.h" +#include "modularity/ioc.h" namespace mu::engraving { -class DrawDataConverter +class DrawDataConverter : public muse::Contextable { public: - DrawDataConverter() = default; + DrawDataConverter(const muse::modularity::ContextPtr& iocCtx); muse::Ret drawDataToPng(const muse::io::path_t& dataFile, const muse::io::path_t& outFile); muse::Ret drawDiffToPng(const muse::io::path_t& diffFile, const muse::io::path_t& refFile, const muse::io::path_t& outFile); diff --git a/src/engraving/devtools/drawdata/drawdatagenerator.cpp b/src/engraving/devtools/drawdata/drawdatagenerator.cpp index e5e8e972fba7..1682a33e5d72 100644 --- a/src/engraving/devtools/drawdata/drawdatagenerator.cpp +++ b/src/engraving/devtools/drawdata/drawdatagenerator.cpp @@ -52,6 +52,11 @@ using namespace mu::engraving; static const std::vector FILES_FILTER = { "*.mscz", "*.mscx", "*.gp", "*.gpx", "*.gp4", "*.gp5" }; +DrawDataGenerator::DrawDataGenerator(const muse::modularity::ContextPtr& iocCtx) + : muse::Contextable(iocCtx) +{ +} + Ret DrawDataGenerator::processDir(const muse::io::path_t& scoreDir, const muse::io::path_t& outDir, const GenOpt& opt) { io::Dir::mkpath(outDir); @@ -102,7 +107,7 @@ Ret DrawDataGenerator::processFile(const muse::io::path_t& scoreFile, const muse DrawDataPtr DrawDataGenerator::genDrawData(const muse::io::path_t& scorePath, const GenOpt& opt) const { - MasterScore* score = compat::ScoreAccess::createMasterScoreWithBaseStyle(nullptr); + MasterScore* score = compat::ScoreAccess::createMasterScoreWithBaseStyle(iocContext()); if (!loadScore(score, scorePath)) { LOGE() << "failed load score: " << scorePath; return nullptr; @@ -140,7 +145,7 @@ DrawDataPtr DrawDataGenerator::genDrawData(const muse::io::path_t& scorePath, co Pixmap DrawDataGenerator::genImage(const muse::io::path_t& scorePath) const { LOGD() << "try: " << scorePath; - MasterScore* score = compat::ScoreAccess::createMasterScoreWithBaseStyle(nullptr); + MasterScore* score = compat::ScoreAccess::createMasterScoreWithBaseStyle(iocContext()); if (!loadScore(score, scorePath)) { LOGE() << "failed load score: " << scorePath; return Pixmap(); @@ -164,7 +169,7 @@ Pixmap DrawDataGenerator::genImage(const muse::io::path_t& scorePath) const image.fill(Qt::white); { - Painter painter(&image, "DrawData"); + Painter painter(&image, "DrawData", score->iocContext()); rendering::IScoreRenderer::ScorePaintOptions opt; opt.fromPage = 0; diff --git a/src/engraving/devtools/drawdata/drawdatagenerator.h b/src/engraving/devtools/drawdata/drawdatagenerator.h index 21966d9d73e2..88e72b18452a 100644 --- a/src/engraving/devtools/drawdata/drawdatagenerator.h +++ b/src/engraving/devtools/drawdata/drawdatagenerator.h @@ -33,11 +33,13 @@ namespace mu::engraving { class MasterScore; -class DrawDataGenerator +class DrawDataGenerator : public muse::Contextable { muse::GlobalInject scoreRenderer; public: + DrawDataGenerator(const muse::modularity::ContextPtr& iocCtx); + muse::Ret processDir(const muse::io::path_t& scoreDir, const muse::io::path_t& outDir, const GenOpt& opt = GenOpt()); muse::Ret processFile(const muse::io::path_t& scoreFile, const muse::io::path_t& outFile, const GenOpt& opt = GenOpt()); diff --git a/src/engraving/devtools/drawdata/idiagnosticdrawprovider.h b/src/engraving/devtools/drawdata/idiagnosticdrawprovider.h index 4fc3b49292a6..991fa809e1ed 100644 --- a/src/engraving/devtools/drawdata/idiagnosticdrawprovider.h +++ b/src/engraving/devtools/drawdata/idiagnosticdrawprovider.h @@ -23,6 +23,7 @@ #define MU_ENGRAVING_IDIAGNOSTICDRAWPROVIDER_H #include "modularity/imoduleinterface.h" +#include "modularity/ioc.h" #include "global/types/ret.h" #include "global/io/path.h" @@ -35,11 +36,14 @@ class IDiagnosticDrawProvider : MODULE_GLOBAL_INTERFACE public: virtual ~IDiagnosticDrawProvider() = default; - virtual muse::Ret generateDrawData(const muse::io::path_t& scoresDir, const muse::io::path_t& outDir, const GenOpt& opt = GenOpt()) = 0; + virtual muse::Ret generateDrawData(const muse::io::path_t& scoresDir, const muse::io::path_t& outDir, + const muse::modularity::ContextPtr& iocCtx, const GenOpt& opt = GenOpt()) = 0; virtual muse::Ret compareDrawData(const muse::io::path_t& ref, const muse::io::path_t& test, const muse::io::path_t& outDiff, - const ComOpt& opt = ComOpt()) = 0; - virtual muse::Ret drawDataToPng(const muse::io::path_t& dataFile, const muse::io::path_t& outFile) = 0; - virtual muse::Ret drawDiffToPng(const muse::io::path_t& diffFile, const muse::io::path_t& refFile, const muse::io::path_t& outFile) = 0; + const muse::modularity::ContextPtr& iocCtx, const ComOpt& opt = ComOpt()) = 0; + virtual muse::Ret drawDataToPng(const muse::io::path_t& dataFile, const muse::io::path_t& outFile, + const muse::modularity::ContextPtr& iocCtx) = 0; + virtual muse::Ret drawDiffToPng(const muse::io::path_t& diffFile, const muse::io::path_t& refFile, const muse::io::path_t& outFile, + const muse::modularity::ContextPtr& iocCtx) = 0; }; } diff --git a/src/engraving/rw/mscsaver.cpp b/src/engraving/rw/mscsaver.cpp index acbada2bb000..7d0ac4ab21b9 100644 --- a/src/engraving/rw/mscsaver.cpp +++ b/src/engraving/rw/mscsaver.cpp @@ -261,7 +261,7 @@ std::shared_ptr MscSaver::createThumbnail(Score* score) auto pixmap = imageProvider()->createPixmap(w, h, dpm, configuration()->thumbnailBackgroundColor()); - auto painterProvider = imageProvider()->painterForImage(pixmap); + auto painterProvider = imageProvider()->painterForImage(pixmap, score->iocContext()); muse::draw::Painter p(painterProvider, "thumbnail"); p.setAntialiasing(true); diff --git a/src/engraving/tests/drawdata_tests.cpp b/src/engraving/tests/drawdata_tests.cpp index e873dd4a2b61..20484e0247a6 100644 --- a/src/engraving/tests/drawdata_tests.cpp +++ b/src/engraving/tests/drawdata_tests.cpp @@ -34,6 +34,8 @@ #include "engraving/devtools/drawdata/drawdataconverter.h" #include "engraving/devtools/drawdata/drawdatagenerator.h" +#include "utils/scorerw.h" + #include "log.h" using namespace muse; @@ -50,14 +52,14 @@ class Engraving_DrawDataTests : public ::testing::Test void saveAsPng(const muse::io::path_t& path, const DrawDataPtr& data) { - DrawDataConverter c; + DrawDataConverter c(ScoreRW::iocContext()); Pixmap px = c.drawDataToPixmap(data); io::File::writeFile(path, px.data()); } void saveDiff(const muse::io::path_t& path, const DrawDataPtr& origin, const DrawDataPtr& diff) { - DrawDataConverter c; + DrawDataConverter c(ScoreRW::iocContext()); Pixmap px(std::lrint(origin->viewport.width()), std::lrint(origin->viewport.height())); c.drawOnPixmap(px, origin, Color("#999999")); c.drawOnPixmap(px, diff, Color("#ff0000")); @@ -68,7 +70,7 @@ TEST_F(Engraving_DrawDataTests, DISABLED_Rw) { DrawDataPtr origin; { - DrawDataGenerator g; + DrawDataGenerator g(ScoreRW::iocContext()); origin = g.genDrawData(VTEST_SCORES + "/accidental-1.mscx"); DrawDataRW::writeData("rw_data.origin.json", origin); } @@ -155,7 +157,7 @@ TEST_F(Engraving_DrawDataTests, SimpleDraw) // convert { - DrawDataConverter c; + DrawDataConverter c(ScoreRW::iocContext()); Pixmap px = c.drawDataToPixmap(data); io::File::writeFile("1_data.png", px.data()); } @@ -165,14 +167,14 @@ TEST_F(Engraving_DrawDataTests, ScoreDraw) { Pixmap originImage; { - DrawDataGenerator g; + DrawDataGenerator g(ScoreRW::iocContext()); originImage = g.genImage(VTEST_SCORES + "/accidental-1.mscx"); io::File::writeFile("2_accidental-1.origin.png", originImage.data()); } { PainterItemMarker::enabled = false; - DrawDataGenerator g; + DrawDataGenerator g(ScoreRW::iocContext()); DrawDataPtr drawData = g.genDrawData(VTEST_SCORES + "/accidental-1.mscx"); DrawDataRW::writeData("2_accidental-1_no_objects.json", drawData); PainterItemMarker::enabled = true; @@ -180,14 +182,14 @@ TEST_F(Engraving_DrawDataTests, ScoreDraw) DrawDataPtr drawData; { - DrawDataGenerator g; + DrawDataGenerator g(ScoreRW::iocContext()); drawData = g.genDrawData(VTEST_SCORES + "/accidental-1.mscx"); DrawDataRW::writeData("2_accidental-1.json", drawData); } Pixmap dataImage; { - DrawDataConverter c; + DrawDataConverter c(ScoreRW::iocContext()); dataImage = c.drawDataToPixmap(drawData); io::File::writeFile("2_accidental-1.data.png", dataImage.data()); } @@ -283,13 +285,13 @@ TEST_F(Engraving_DrawDataTests, ScoreDrawDiff) { DrawDataPtr data1; { - DrawDataGenerator g; + DrawDataGenerator g(ScoreRW::iocContext()); data1 = g.genDrawData(VTEST_SCORES + "/accidental-1.mscx"); } DrawDataPtr data2; { - DrawDataGenerator g; + DrawDataGenerator g(ScoreRW::iocContext()); data2 = g.genDrawData(VTEST_SCORES + "/accidental-2.mscx"); } diff --git a/src/importexport/imagesexport/internal/pdfwriter.cpp b/src/importexport/imagesexport/internal/pdfwriter.cpp index 551333fe0655..e6de44c46ab1 100644 --- a/src/importexport/imagesexport/internal/pdfwriter.cpp +++ b/src/importexport/imagesexport/internal/pdfwriter.cpp @@ -61,7 +61,7 @@ Ret PdfWriter::write(INotationPtr notation, io::IODevice& destinationDevice, con QPdfWriter pdfWriter(&buf); preparePdfWriter(pdfWriter, notation->projectWorkTitleAndPartName(), notation->painting()->pageSizeInch().toQSizeF()); - Painter painter(&pdfWriter, "pdfwriter"); + Painter painter(&pdfWriter, "pdfwriter", notation->elements()->msScore()->iocContext()); if (!painter.isActive()) { return false; } @@ -113,7 +113,7 @@ Ret PdfWriter::writeList(const INotationPtrList& notations, io::IODevice& destin QPdfWriter pdfWriter(&buf); preparePdfWriter(pdfWriter, firstNotation->projectWorkTitle(), firstNotation->painting()->pageSizeInch().toQSizeF()); - Painter painter(&pdfWriter, "pdfwriter"); + Painter painter(&pdfWriter, "pdfwriter", firstNotation->elements()->msScore()->iocContext()); if (!painter.isActive()) { return false; } diff --git a/src/importexport/imagesexport/internal/pngwriter.cpp b/src/importexport/imagesexport/internal/pngwriter.cpp index 2173d0be721a..7d7e73a33587 100644 --- a/src/importexport/imagesexport/internal/pngwriter.cpp +++ b/src/importexport/imagesexport/internal/pngwriter.cpp @@ -72,7 +72,7 @@ Ret PngWriter::write(INotationPtr notation, io::IODevice& destinationDevice, con Val(configuration()->exportPngWithTransparentBackground())).toBool(); image.fill(TRANSPARENT_BACKGROUND ? Qt::transparent : Qt::white); - muse::draw::Painter painter(&image, "pngwriter"); + muse::draw::Painter painter(&image, "pngwriter", notation->elements()->msScore()->iocContext()); notation->painting()->paintPng(&painter, opt); diff --git a/src/importexport/imagesexport/internal/svgwriter.cpp b/src/importexport/imagesexport/internal/svgwriter.cpp index d248bd81135a..f3ead4d228a1 100644 --- a/src/importexport/imagesexport/internal/svgwriter.cpp +++ b/src/importexport/imagesexport/internal/svgwriter.cpp @@ -102,7 +102,7 @@ Ret SvgWriter::write(INotationPtr notation, io::IODevice& destinationDevice, con printer.setSize(QSize(width, height)); printer.setViewBox(QRectF(0, 0, width, height)); - muse::draw::Painter painter(&printer, "svgwriter"); + muse::draw::Painter painter(&printer, "svgwriter", score->iocContext()); painter.setAntialiasing(true); if (TRIM_MARGIN_SIZE >= 0) { painter.translate(-pageRect.topLeft()); diff --git a/src/importexport/videoexport/internal/videowriter.cpp b/src/importexport/videoexport/internal/videowriter.cpp index db091afda358..5c1124ca8cad 100644 --- a/src/importexport/videoexport/internal/videowriter.cpp +++ b/src/importexport/videoexport/internal/videowriter.cpp @@ -425,7 +425,7 @@ void VideoWriter::doGenerate(muse::media::IVideoEncoderPtr encoder, INotationPtr qp.setRenderHint(QPainter::Antialiasing, true); qp.setRenderHint(QPainter::TextAntialiasing, true); - Painter painter(&qp, "video_writer"); + Painter painter(&qp, "video_writer", notation->elements()->msScore()->iocContext()); // Setup duration INotationPlaybackPtr playback = notation->masterNotation()->playback(); diff --git a/src/notation/internal/notationinteraction.cpp b/src/notation/internal/notationinteraction.cpp index 36d0e15cbba6..15bbcf9b86f7 100644 --- a/src/notation/internal/notationinteraction.cpp +++ b/src/notation/internal/notationinteraction.cpp @@ -1339,7 +1339,7 @@ void NotationInteraction::startOutgoingDragElement(const EngravingItem* element, QPainter qp(&pixmap); - Painter p(&qp, "startOutgoingDragElement"); + Painter p(&qp, "startOutgoingDragElement", iocContext()); p.setAntialiasing(true); p.scale(physDpiRatio, physDpiRatio); diff --git a/src/notationscene/qml/MuseScore/NotationScene/abstractnotationpaintview.cpp b/src/notationscene/qml/MuseScore/NotationScene/abstractnotationpaintview.cpp index 8bc6fb0ebaf0..c1c30b64f15c 100644 --- a/src/notationscene/qml/MuseScore/NotationScene/abstractnotationpaintview.cpp +++ b/src/notationscene/qml/MuseScore/NotationScene/abstractnotationpaintview.cpp @@ -730,7 +730,7 @@ void AbstractNotationPaintView::paint(QPainter* qp) RectF rect = RectF::fromQRectF(qp->clipBoundingRect()); rect = correctDrawRect(rect); - muse::draw::Painter mup(qp, objectName().toStdString()); + muse::draw::Painter mup(qp, objectName().toStdString(), iocContext()); muse::draw::Painter* painter = &mup; paintBackground(rect, painter); diff --git a/src/notationscene/qml/MuseScore/NotationScene/paintedengravingitem.cpp b/src/notationscene/qml/MuseScore/NotationScene/paintedengravingitem.cpp index 1a8f66e5d132..6751b3673a7e 100644 --- a/src/notationscene/qml/MuseScore/NotationScene/paintedengravingitem.cpp +++ b/src/notationscene/qml/MuseScore/NotationScene/paintedengravingitem.cpp @@ -83,7 +83,11 @@ void PaintedEngravingItem::setSpatium(double spatium) void PaintedEngravingItem::paint(QPainter* painter) { - muse::draw::Painter p(painter, "paintedengravingitem"); + IF_ASSERT_FAILED(m_item) { + return; + } + + muse::draw::Painter p(painter, "paintedengravingitem", m_item->iocContext()); p.save(); p.setAntialiasing(true); paintNotationPreview(p); diff --git a/src/notationscene/widgets/exampleview.cpp b/src/notationscene/widgets/exampleview.cpp index b76b7f5fb173..436f30b20610 100644 --- a/src/notationscene/widgets/exampleview.cpp +++ b/src/notationscene/widgets/exampleview.cpp @@ -151,7 +151,7 @@ void ExampleView::paintEvent(QPaintEvent* event) return; } - Painter painter(this, "exampleview"); + Painter painter(this, "exampleview", m_score->iocContext()); painter.setAntialiasing(true); const RectF rect = RectF::fromQRectF(event->rect()); diff --git a/src/palette/internal/palettecelliconengine.cpp b/src/palette/internal/palettecelliconengine.cpp index d8281fe98a97..575aa8d78ce9 100644 --- a/src/palette/internal/palettecelliconengine.cpp +++ b/src/palette/internal/palettecelliconengine.cpp @@ -46,7 +46,7 @@ QIconEngine* PaletteCellIconEngine::clone() const void PaletteCellIconEngine::paint(QPainter* qp, const QRect& rect, QIcon::Mode mode, QIcon::State state) { - Painter p(qp, "palettecell"); + Painter p(qp, "palettecell", m_cell->iocContext()); p.save(); p.setAntialiasing(true); paintCell(p, RectF::fromQRectF(rect), mode == QIcon::Selected, state == QIcon::On); diff --git a/src/palette/widgets/customizekitdialog.cpp b/src/palette/widgets/customizekitdialog.cpp index c294ede207f5..0065f9f0e29c 100644 --- a/src/palette/widgets/customizekitdialog.cpp +++ b/src/palette/widgets/customizekitdialog.cpp @@ -122,12 +122,13 @@ struct SymbolIcon { : id(i), icon(j) {} - static SymbolIcon generateIcon(const mu::engraving::IEngravingFontPtr& font, const SymId& id, double w, double h, double defaultScale) + static SymbolIcon generateIcon(const mu::engraving::IEngravingFontPtr& font, const SymId& id, double w, double h, double defaultScale, + const muse::modularity::ContextPtr& iocCtx) { QIcon icon; QPixmap image(w, h); image.fill(Qt::transparent); - muse::draw::Painter painter(&image, "generateicon"); + muse::draw::Painter painter(&image, "generateicon", iocCtx); const muse::RectF& bbox = font->bbox(id, 1); const qreal actualSymbolScale = std::min(w / bbox.width(), h / bbox.height()); @@ -237,13 +238,13 @@ CustomizeKitDialog::CustomizeKitDialog(QWidget* parent) QList resNoteheads; for (SymId symId : primaryNoteheads) { - resNoteheads.append(SymbolIcon::generateIcon(fallbackFont, symId, w, h, defaultScale)); + resNoteheads.append(SymbolIcon::generateIcon(fallbackFont, symId, w, h, defaultScale, iocContext())); } for (const String& range : validNoteheadRanges) { for (SymId symId : Smufl::smuflRanges().at(range)) { if (!excludedSyms.contains(symId) && !primaryNoteheads.contains(symId)) { - resNoteheads.append(SymbolIcon::generateIcon(fallbackFont, symId, w, h, defaultScale)); + resNoteheads.append(SymbolIcon::generateIcon(fallbackFont, symId, w, h, defaultScale, iocContext())); } } } diff --git a/src/palette/widgets/keyedit.cpp b/src/palette/widgets/keyedit.cpp index cd9a21fef138..0e467456846f 100644 --- a/src/palette/widgets/keyedit.cpp +++ b/src/palette/widgets/keyedit.cpp @@ -112,7 +112,7 @@ void KeyCanvas::clear() void KeyCanvas::paintEvent(QPaintEvent*) { - muse::draw::Painter painter(this, "keycanvas"); + muse::draw::Painter painter(this, "keycanvas", iocContext()); painter.setAntialiasing(true); qreal wh = double(height()); qreal ww = double(width()); diff --git a/src/palette/widgets/palettewidget.cpp b/src/palette/widgets/palettewidget.cpp index 9140a31530ce..660362981bc3 100644 --- a/src/palette/widgets/palettewidget.cpp +++ b/src/palette/widgets/palettewidget.cpp @@ -604,7 +604,7 @@ QPixmap PaletteWidget::pixmapForCellAt(int paletteIdx) const QPixmap pm(w, h); pm.fill(configuration()->elementsBackgroundColor()); - muse::draw::Painter painter(&pm, "palette"); + muse::draw::Painter painter(&pm, "palette", iocContext()); painter.setAntialiasing(true); painter.scale(cellMag, cellMag); @@ -950,7 +950,7 @@ void PaletteWidget::paintEvent(QPaintEvent* /*event*/) qreal mag = magS / _spatium; paletteScore->style().setSpatium(paletteScore->style().defaultSpatium()); - muse::draw::Painter painter(this, "palette"); + muse::draw::Painter painter(this, "palette", iocContext()); painter.setAntialiasing(true); if (m_paintOptions.backgroundColor.isValid()) { diff --git a/src/print/internal/printprovider.cpp b/src/print/internal/printprovider.cpp index bc35e8909f3c..eed96e8a50c9 100644 --- a/src/print/internal/printprovider.cpp +++ b/src/print/internal/printprovider.cpp @@ -76,7 +76,7 @@ Ret PrintProvider::printNotation(INotationPtr notation) return muse::make_ret(Ret::Code::Cancel); } - Painter painter(&printerDev, "print"); + Painter painter(&printerDev, "print", iocContext()); INotationPainting::Options opt; opt.fromPage = printerDev.fromPage() - 1; From ce6115c957989288298d247be65c52dd5d758581 Mon Sep 17 00:00:00 2001 From: Alexander Pavlov Date: Fri, 30 Oct 2026 02:35:07 +0200 Subject: [PATCH 08/11] video writer uses context of notation --- src/importexport/videoexport/internal/videowriter.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/importexport/videoexport/internal/videowriter.cpp b/src/importexport/videoexport/internal/videowriter.cpp index 5c1124ca8cad..7ad8e7495a9a 100644 --- a/src/importexport/videoexport/internal/videowriter.cpp +++ b/src/importexport/videoexport/internal/videowriter.cpp @@ -495,11 +495,11 @@ bool VideoWriter::generateLeadingFrames(muse::media::IVideoEncoderPtr encoder, I return std::max(1, static_cast(std::ceil(textWidth / maxTextWidth))); }; - FontMetrics titleFontMetrics(titleFont, iocContext()); + FontMetrics titleFontMetrics(titleFont, notation->elements()->msScore()->iocContext()); const int titleLines = lineCount(titleFontMetrics, title); const double titleHeight = titleLines * titleFontMetrics.lineSpacing(); - FontMetrics subtitleFontMetrics(subtitleFont, iocContext()); + FontMetrics subtitleFontMetrics(subtitleFont, notation->elements()->msScore()->iocContext()); const int subtitleLines = lineCount(subtitleFontMetrics, subtitle); const double subtitleHeight = subtitleLines * subtitleFontMetrics.lineSpacing(); @@ -577,7 +577,7 @@ bool VideoWriter::generateScoreFrames(muse::media::IVideoEncoderPtr encoder, INo const Color CURSOR_COLOR = Color(2, 109, 203, 127); - PlaybackCursor cursor(iocContext()); + PlaybackCursor cursor(notation->elements()->msScore()->iocContext()); cursor.setNotation(notation); for (int f = 0; f < scoreFrameCount; f++) { From 303b2d4af1af782ca75037c3d49c994222055997 Mon Sep 17 00:00:00 2001 From: Alexander Pavlov Date: Fri, 30 Oct 2026 02:35:46 +0200 Subject: [PATCH 09/11] customize kit dialog builds notehead icons after it gets its context --- src/palette/widgets/customizekitdialog.cpp | 14 ++++++++++---- src/palette/widgets/customizekitdialog.h | 1 + 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/palette/widgets/customizekitdialog.cpp b/src/palette/widgets/customizekitdialog.cpp index 0065f9f0e29c..13e6b6c10daa 100644 --- a/src/palette/widgets/customizekitdialog.cpp +++ b/src/palette/widgets/customizekitdialog.cpp @@ -179,6 +179,14 @@ CustomizeKitDialog::CustomizeKitDialog(QWidget* parent) pitchList->setColumnWidth(1, 60); pitchList->setColumnWidth(2, 30); + connect(customGbox, &QGroupBox::toggled, this, &CustomizeKitDialog::customGboxToggled); + + //! NOTE: It is necessary for the correct start of navigation in the dialog + setFocus(); +} + +void CustomizeKitDialog::initNoteheadsCombos() +{ StringList validNoteheadRanges = { u"Noteheads", u"Round and square noteheads", @@ -263,20 +271,18 @@ CustomizeKitDialog::CustomizeKitDialog(QWidget* parent) quarterCmb->setCurrentIndex(quarterCmb->findData(static_cast(SymId::noteheadBlack))); doubleWholeCmb->setCurrentIndex(quarterCmb->findData(static_cast(SymId::noteheadDoubleWhole))); - connect(customGbox, &QGroupBox::toggled, this, &CustomizeKitDialog::customGboxToggled); connect(quarterCmb, &QComboBox::currentIndexChanged, this, &CustomizeKitDialog::customQuarterChanged); quarterCmb->setAccessibleName(quarterLbl->text() + " " + quarterCmb->currentText()); halfCmb->setAccessibleName(halfLbl->text() + " " + halfCmb->currentText()); wholeCmb->setAccessibleName(wholeLbl->text() + " " + wholeCmb->currentText()); doubleWholeCmb->setAccessibleName(doubleWholeLbl->text() + " " + doubleWholeCmb->currentText()); - - //! NOTE: It is necessary for the correct start of navigation in the dialog - setFocus(); } void CustomizeKitDialog::componentComplete() { + initNoteheadsCombos(); + m_notation = projectSession()->currentNotation(); if (!m_notation) { return; diff --git a/src/palette/widgets/customizekitdialog.h b/src/palette/widgets/customizekitdialog.h index aaf16999a70a..36a5fa34211c 100644 --- a/src/palette/widgets/customizekitdialog.h +++ b/src/palette/widgets/customizekitdialog.h @@ -73,6 +73,7 @@ private slots: void defineShortcut(); private: + void initNoteheadsCombos(); void initDrumsetAndKey(); void apply(); From f83e65d114249d7a6523e9809b14701c981b934b Mon Sep 17 00:00:00 2001 From: Alexander Pavlov Date: Fri, 30 Oct 2026 02:37:48 +0200 Subject: [PATCH 10/11] updated the framework --- muse | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/muse b/muse index 53fc2db88091..ee2bbb3fa44f 160000 --- a/muse +++ b/muse @@ -1 +1 @@ -Subproject commit 53fc2db88091e2fdf564e848287bbf91a36bdc94 +Subproject commit ee2bbb3fa44f367f81cac8c3e670829859160901 From 0d6cf9e3ae22fa656a7d9002e3288c7cd330074e Mon Sep 17 00:00:00 2001 From: Alexander Pavlov Date: Fri, 30 Oct 2026 03:06:07 +0200 Subject: [PATCH 11/11] engraving font keeps its font provider alive until destruction --- src/engraving/internal/engravingfont.cpp | 5 +++-- src/engraving/internal/engravingfont.h | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/engraving/internal/engravingfont.cpp b/src/engraving/internal/engravingfont.cpp index e157f0239871..658f50d8faf4 100644 --- a/src/engraving/internal/engravingfont.cpp +++ b/src/engraving/internal/engravingfont.cpp @@ -74,7 +74,7 @@ EngravingFont::EngravingFont(const EngravingFont& other) EngravingFont::~EngravingFont() { if (m_symbolFontId != -1) { - fontProvider()->removeSymbolFont(m_symbolFontId); + m_symbolFontProvider->removeSymbolFont(m_symbolFontId); } } @@ -114,7 +114,8 @@ void EngravingFont::ensureLoad() const String family = String::fromStdString(m_family); if (m_symbolFontId == -1 && m_fontDevice) { - m_symbolFontId = fontProvider()->addSymbolFont(family, m_fontDevice); + m_symbolFontProvider = fontProvider(); + m_symbolFontId = m_symbolFontProvider->addSymbolFont(family, m_fontDevice); } if (m_symbolFontId == -1) { LOGE() << "fatal error: cannot load font: " << m_name; diff --git a/src/engraving/internal/engravingfont.h b/src/engraving/internal/engravingfont.h index 32aaf001cc73..624e2d249a8f 100644 --- a/src/engraving/internal/engravingfont.h +++ b/src/engraving/internal/engravingfont.h @@ -145,6 +145,7 @@ class EngravingFont : public IEngravingFont, public muse::Contextable std::shared_ptr m_fontDevice; std::shared_ptr m_metadataDevice; int m_symbolFontId = -1; + std::shared_ptr m_symbolFontProvider; std::unordered_map m_engravingDefaults; double m_textEnclosureThickness = 0;