LCOV - code coverage report
Current view: top level - src/engraving/infrastructure - smufl.cpp Coverage Total Hit
Test: filtered_coverage.info Lines: 43.4 % 76 33
Test Date: 2026-11-05 04:07:02

            Line data    Source code
       1              : /*
       2              :  * SPDX-License-Identifier: GPL-3.0-only
       3              :  * MuseScore-Studio-CLA-applies
       4              :  *
       5              :  * MuseScore Studio
       6              :  * Music Composition & Notation
       7              :  *
       8              :  * Copyright (C) 2021 MuseScore Limited and others
       9              :  *
      10              :  * This program is free software: you can redistribute it and/or modify
      11              :  * it under the terms of the GNU General Public License version 3 as
      12              :  * published by the Free Software Foundation.
      13              :  *
      14              :  * This program is distributed in the hope that it will be useful,
      15              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      16              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17              :  * GNU General Public License for more details.
      18              :  *
      19              :  * You should have received a copy of the GNU General Public License
      20              :  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
      21              :  */
      22              : #include "smufl.h"
      23              : 
      24              : #include "io/file.h"
      25              : #include "serialization/json.h"
      26              : 
      27              : #include "types/symnames.h"
      28              : 
      29              : #include "dom/mscore.h"
      30              : 
      31              : #include "log.h"
      32              : 
      33              : using namespace mu;
      34              : using namespace muse;
      35              : using namespace muse::io;
      36              : using namespace mu::engraving;
      37              : 
      38              : std::array<Smufl::Code, size_t(SymId::lastSym) + 1> Smufl::s_symIdCodes { {  } };
      39              : 
      40       391552 : const Smufl::Code Smufl::code(SymId id)
      41              : {
      42       391552 :     return s_symIdCodes.at(static_cast<size_t>(id));
      43              : }
      44              : 
      45        43548 : char32_t Smufl::smuflCode(SymId id)
      46              : {
      47        43548 :     return s_symIdCodes.at(static_cast<size_t>(id)).smuflCode;
      48              : }
      49              : 
      50           16 : bool Smufl::init()
      51              : {
      52           16 :     bool ok = loadGlyphNamesJson();
      53              : 
      54           16 :     return ok;
      55              : }
      56              : 
      57           16 : bool Smufl::loadGlyphNamesJson()
      58              : {
      59           16 :     File file(":/fonts/smufl/glyphnames.json");
      60           16 :     if (!file.open(IODevice::ReadOnly)) {
      61            0 :         LOGE() << "could not open glyph names JSON file.";
      62            0 :         return false;
      63              :     }
      64              : 
      65           16 :     std::string error;
      66           16 :     JsonObject glyphNamesJson = JsonDocument::fromJson(file.readAll(), &error).rootObject();
      67           16 :     file.close();
      68              : 
      69           16 :     if (!error.empty()) {
      70            0 :         LOGE() << "JSON parse error in glyph names file: " << error;
      71            0 :         return false;
      72              :     }
      73              : 
      74           16 :     IF_ASSERT_FAILED(!glyphNamesJson.empty()) {
      75            0 :         LOGE() << "Could not read glyph names JSON";
      76            0 :         return false;
      77              :     }
      78              : 
      79        97920 :     for (size_t i = 0; i < s_symIdCodes.size(); ++i) {
      80        48944 :         SymId sym = static_cast<SymId>(i);
      81        48944 :         if (sym == SymId::noSym || sym == SymId::lastSym) {
      82         2032 :             continue;
      83              :         }
      84              : 
      85        48912 :         std::string name(SymNames::nameForSymId(sym).ascii());
      86        48912 :         JsonObject symObj = glyphNamesJson.value(name).toObject();
      87        48912 :         if (!symObj.isValid()) {
      88         2000 :             continue;
      89              :         }
      90              : 
      91              :         bool ok;
      92       140736 :         char32_t code = symObj.value("codepoint").toString().mid(2).toUInt(&ok, 16);
      93        46912 :         if (ok) {
      94        46912 :             s_symIdCodes[i].smuflCode = code;
      95            0 :         } else if (MScore::debugMode) {
      96            0 :             LOGD() << "could not read codepoint for glyph " << name;
      97              :         }
      98              : 
      99       140736 :         char32_t alernativeCode = symObj.value("alternateCodepoint").toString().mid(2).toUInt(&ok, 16);
     100        46912 :         if (ok) {
     101         3552 :             s_symIdCodes[i].musicSymBlockCode = alernativeCode;
     102        43360 :         } else if (MScore::debugMode) {
     103            0 :             LOGD() << "could not read alternate codepoint for glyph " << name;
     104              :         }
     105        50912 :     }
     106           16 :     return true;
     107           16 : }
     108              : 
     109            0 : const std::map<String, std::vector<SymId> >& Smufl::smuflRanges()
     110              : {
     111            0 :     static std::map<String, std::vector<SymId> > ranges = readSmuflRangesJson();
     112            0 :     return ranges;
     113              : }
     114              : 
     115            0 : std::map<String, std::vector<SymId> > Smufl::readSmuflRangesJson()
     116              : {
     117            0 :     std::map<String, std::vector<SymId> > ranges;
     118            0 :     std::vector<SymId> allSymbols;
     119              : 
     120            0 :     File fi(":/fonts/smufl/ranges.json");
     121            0 :     if (!fi.open(IODevice::ReadOnly)) {
     122            0 :         LOGE() << "failed open: " << fi.filePath();
     123            0 :         return ranges;
     124              :     }
     125              : 
     126            0 :     std::string error;
     127            0 :     JsonObject o = JsonDocument::fromJson(fi.readAll(), &error).rootObject();
     128            0 :     if (!error.empty()) {
     129            0 :         LOGE() << "failed parse, err: " << error << ", file: " << fi.filePath();
     130            0 :         return ranges;
     131              :     }
     132              : 
     133            0 :     for (const std::string& s : o.keys()) {
     134            0 :         const JsonObject range = o.value(s).toObject();
     135            0 :         const String desc      = range.value("description").toString();
     136            0 :         const JsonArray glyphs = range.value("glyphs").toArray();
     137              : 
     138            0 :         if (glyphs.empty()) {
     139            0 :             continue;
     140              :         }
     141            0 :         std::vector<SymId> rangeSymbols;
     142            0 :         for (size_t i = 0; i < glyphs.size(); ++i) {
     143            0 :             String symName = glyphs.at(i).toString();
     144            0 :             SymId symId = SymNames::symIdByName(symName);
     145            0 :             if (symId != SymId::noSym) {
     146            0 :                 rangeSymbols.push_back(symId);
     147            0 :                 allSymbols.push_back(symId);
     148              :             }
     149            0 :         }
     150            0 :         ranges.insert({ desc, rangeSymbols });
     151            0 :     }
     152              : 
     153            0 :     ranges.insert({ String::fromAscii(SMUFL_ALL_SYMBOLS), allSymbols }); // TODO: make translatable as well as ranges.json
     154              : 
     155            0 :     return ranges;
     156            0 : }
        

Generated by: LCOV version 2.0-1