LCOV - code coverage report
Current view: top level - src/engraving/dom - location.cpp Coverage Total Hit
Test: filtered_coverage.info Lines: 56.0 % 109 61
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              : 
      23              : #include "location.h"
      24              : 
      25              : #include "chord.h"
      26              : #include "engravingitem.h"
      27              : #include "measure.h"
      28              : #include "mscore.h"
      29              : #include "note.h"
      30              : 
      31              : #include "log.h"
      32              : 
      33              : using namespace mu;
      34              : using namespace mu::engraving;
      35              : 
      36              : namespace mu::engraving {
      37              : static constexpr Location absDefaults = Location::absolute();
      38              : 
      39              : //---------------------------------------------------------
      40              : //   Location::track
      41              : //---------------------------------------------------------
      42              : 
      43        26663 : int Location::track() const
      44              : {
      45        26663 :     if ((m_staff == absDefaults.m_staff) || (m_voice == absDefaults.m_voice)) {
      46        12706 :         return INT_MIN;
      47              :     }
      48        13957 :     return static_cast<int>(VOICES) * m_staff + m_voice;
      49              : }
      50              : 
      51              : //---------------------------------------------------------
      52              : //   Location::setTrack
      53              : //---------------------------------------------------------
      54              : 
      55         6933 : void Location::setTrack(int track)
      56              : {
      57         6933 :     m_staff = track / VOICES;
      58         6933 :     m_voice = track % VOICES;
      59         6933 : }
      60              : 
      61              : //---------------------------------------------------------
      62              : //   Location::toAbsolute
      63              : //---------------------------------------------------------
      64              : 
      65         4203 : void Location::toAbsolute(const Location& ref)
      66              : {
      67         4203 :     if (isAbsolute()) {
      68            0 :         return;
      69              :     }
      70         4203 :     m_staff += ref.m_staff;
      71         4203 :     m_voice += ref.m_voice;
      72         4203 :     m_measure += ref.m_measure;
      73         4203 :     m_frac += ref.m_frac;
      74         4203 :     m_note += ref.m_note;
      75         4203 :     m_rel = false;
      76              : }
      77              : 
      78              : //---------------------------------------------------------
      79              : //   Location::toRelative
      80              : //---------------------------------------------------------
      81              : 
      82          294 : void Location::toRelative(const Location& ref)
      83              : {
      84          294 :     if (isRelative()) {
      85            0 :         return;
      86              :     }
      87          294 :     m_staff -= ref.m_staff;
      88          294 :     m_voice -= ref.m_voice;
      89          294 :     m_measure -= ref.m_measure;
      90          294 :     m_frac -= ref.m_frac;
      91          294 :     m_note -= ref.m_note;
      92          294 :     m_rel = true;
      93              : }
      94              : 
      95              : //---------------------------------------------------------
      96              : //   Location::fillPositionForElement
      97              : //    Fills default fields of Location by values relevant
      98              : //    for the given EngravingItem. This function fills only
      99              : //    position values, not dealing with parameters specific
     100              : //    for Chords and Notes, like grace index.
     101              : //---------------------------------------------------------
     102              : 
     103         3903 : void Location::fillPositionForElement(const EngravingItem* e, bool absfrac)
     104              : {
     105         3903 :     assert(isAbsolute());
     106         3903 :     if (!e) {
     107            0 :         LOGW("Location::fillPositionForElement: element is nullptr");
     108            0 :         return;
     109              :     }
     110         3903 :     if (track() == absDefaults.track()) {
     111            0 :         setTrack(track(e));
     112              :     }
     113         3903 :     if (frac() == absDefaults.frac()) {
     114            0 :         setFrac(absfrac ? e->tick() : e->rtick());
     115              :     }
     116         3903 :     if (measure() == absDefaults.measure()) {
     117            0 :         setMeasure(absfrac ? 0 : measure(e));
     118              :     }
     119              : }
     120              : 
     121              : //---------------------------------------------------------
     122              : //   Location::fillForElement
     123              : //    Fills default fields of Location by values relevant
     124              : //    for the given EngravingItem, including parameters specific
     125              : //    for Chords and Notes.
     126              : //---------------------------------------------------------
     127              : 
     128         3903 : void Location::fillForElement(const EngravingItem* e, bool absfrac)
     129              : {
     130         3903 :     assert(isAbsolute());
     131         3903 :     if (!e) {
     132            0 :         LOGW("Location::fillForElement: element is nullptr");
     133            0 :         return;
     134              :     }
     135              : 
     136         3903 :     fillPositionForElement(e, absfrac);
     137         3903 :     setGraceIndex(graceIndex(e));
     138         3903 :     setNote(note(e));
     139              : }
     140              : 
     141              : //---------------------------------------------------------
     142              : //   Location::forElement
     143              : //---------------------------------------------------------
     144              : 
     145            0 : Location Location::forElement(const EngravingItem* e, bool absfrac)
     146              : {
     147            0 :     Location i = Location::absolute();
     148            0 :     i.fillForElement(e, absfrac);
     149            0 :     return i;
     150              : }
     151              : 
     152              : //---------------------------------------------------------
     153              : //   Location::positionForElement
     154              : //---------------------------------------------------------
     155              : 
     156            0 : Location Location::positionForElement(const EngravingItem* e, bool absfrac)
     157              : {
     158            0 :     Location i = Location::absolute();
     159            0 :     i.fillPositionForElement(e, absfrac);
     160            0 :     return i;
     161              : }
     162              : 
     163              : //---------------------------------------------------------
     164              : //   Location::track
     165              : //---------------------------------------------------------
     166              : 
     167            0 : int Location::track(const EngravingItem* e)
     168              : {
     169            0 :     int track = static_cast<int>(e->track());
     170            0 :     if (track < 0) {
     171            0 :         const MeasureBase* mb = e->findMeasureBase();
     172            0 :         if (mb && !mb->isMeasure()) {
     173              :             // Such elements are written in the first staff,
     174              :             // see writeMeasure() in rw/write/measurewrite.cpp
     175            0 :             track = 0;
     176              :         }
     177              :     }
     178            0 :     return track;
     179              : }
     180              : 
     181              : //---------------------------------------------------------
     182              : //   Location::measure
     183              : //---------------------------------------------------------
     184              : 
     185            0 : int Location::measure(const EngravingItem* e)
     186              : {
     187            0 :     const Measure* m = toMeasure(e->findMeasure());
     188            0 :     if (m) {
     189            0 :         return m->measureIndex();
     190              :     }
     191            0 :     LOGW("Location::measure: cannot find element's measure (%s)", e->typeName());
     192            0 :     return 0;
     193              : }
     194              : 
     195              : //---------------------------------------------------------
     196              : //   Location::graceIndex
     197              : //---------------------------------------------------------
     198              : 
     199         3903 : int Location::graceIndex(const EngravingItem* e)
     200              : {
     201         3903 :     if (e->isChord() || (e->ownershipParent() && e->ownershipParent()->isChord())) {
     202         2951 :         const Chord* ch = e->isChord() ? toChord(e) : toChord(e->ownershipParent());
     203         2951 :         if (ch->isGrace()) {
     204           74 :             return static_cast<int>(ch->graceIndex());
     205              :         }
     206              :     }
     207         3829 :     return absDefaults.graceIndex();
     208              : }
     209              : 
     210              : //---------------------------------------------------------
     211              : //   Location::note
     212              : //---------------------------------------------------------
     213              : 
     214         3903 : int Location::note(const EngravingItem* e)
     215              : {
     216         3903 :     if (e->isNote()) {
     217         2426 :         const Note* n = toNote(e);
     218         2426 :         const std::vector<Note*>& notes = n->chord()->notes();
     219         2426 :         if (notes.size() == 1) {
     220         2259 :             return 0;
     221              :         }
     222              :         size_t noteIdx;
     223          326 :         for (noteIdx = 0; noteIdx < notes.size(); ++noteIdx) {
     224          326 :             if (n == notes.at(noteIdx)) {
     225          167 :                 break;
     226              :             }
     227              :         }
     228          167 :         return static_cast<int>(noteIdx);
     229              :     }
     230         1477 :     return absDefaults.note();
     231              : }
     232              : 
     233              : //---------------------------------------------------------
     234              : //   Location::getLocationProperty
     235              : //---------------------------------------------------------
     236              : 
     237            0 : PropertyValue Location::getLocationProperty(Pid pid, const EngravingItem* start, const EngravingItem* end)
     238              : {
     239            0 :     if (!start || !end) {
     240            0 :         return 0;
     241              :     }
     242            0 :     switch (pid) {
     243            0 :     case Pid::LOCATION_STAVES:
     244            0 :         return (track(start) / VOICES) - (track(end) / VOICES);
     245            0 :     case Pid::LOCATION_VOICES:
     246            0 :         return (track(start) % VOICES) - (track(end) / VOICES);
     247            0 :     case Pid::LOCATION_MEASURES:
     248            0 :         return measure(end) - measure(start);
     249            0 :     case Pid::LOCATION_FRACTIONS:
     250            0 :         return end->rtick() - start->rtick();
     251            0 :     case Pid::LOCATION_GRACE:
     252            0 :         return graceIndex(start) - graceIndex(end);
     253            0 :     case Pid::LOCATION_NOTE:
     254            0 :         return note(start) - note(end);
     255            0 :     default:
     256            0 :         return PropertyValue();
     257              :     }
     258              : }
     259              : 
     260              : //---------------------------------------------------------
     261              : //   Location::operator==
     262              : //---------------------------------------------------------
     263              : 
     264        24305 : bool Location::operator==(const Location& pi2) const
     265              : {
     266        24305 :     const Location& pi1 = *this;
     267        24305 :     return (pi1.m_frac == pi2.m_frac)
     268         6731 :            && (pi1.m_measure == pi2.m_measure)
     269         6719 :            && (pi1.m_voice == pi2.m_voice)
     270         6608 :            && (pi1.m_staff == pi2.m_staff)
     271         6594 :            && (pi1.m_graceIndex == pi2.m_graceIndex)
     272        31036 :            && (pi1.m_note == pi2.m_note)
     273              :     ;
     274              : }
     275              : }
        

Generated by: LCOV version 2.0-1