LCOV - code coverage report
Current view: top level - src/engraving/rendering/score - accidentalslayout.h Coverage Total Hit
Test: filtered_coverage.info Lines: 100.0 % 18 18
Test Date: 2026-11-05 04:07:02

            Line data    Source code
       1              : /*
       2              :  * SPDX-License-Identifier: GPL-3.0-only
       3              :  * MuseScore-CLA-applies
       4              :  *
       5              :  * MuseScore Studio
       6              :  * Music Composition & Notation
       7              :  *
       8              :  * Copyright (C) 2023 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              : #pragma once
      23              : 
      24              : #include "vectorview.h"
      25              : 
      26              : #include "shape.h"
      27              : 
      28              : namespace mu::engraving {
      29              : class Accidental;
      30              : class Chord;
      31              : class EngravingItem;
      32              : class LedgerLine;
      33              : class Shape;
      34              : struct ShapeElement;
      35              : }
      36              : 
      37              : namespace mu::engraving::rendering::score {
      38              : class LayoutContext;
      39              : 
      40              : using AccidentalGroups = std::vector<std::vector<Accidental*> >;
      41              : 
      42              : class AccidentalsLayout
      43              : {
      44              : public:
      45              :     static void layoutAccidentals(const std::vector<Chord*>& chords, LayoutContext& ctx);
      46              : 
      47              : private:
      48              :     struct AccidentalsLayoutContext {
      49              :         AccidentalsLayoutContext (std::vector<Accidental*> acc, std::vector<Chord*> ch);
      50              : 
      51              :         std::vector<Accidental*> allAccidentals;
      52              :         std::vector<Chord*> chords;
      53              :         AccidentalGroups accidentalSubChords;
      54              :         std::vector<Accidental*> stackedAccidentals;
      55              :         Shape stackedAccidentalsShape;
      56              :         Shape chordsShape;
      57              :         size_t subChordsCountBeforeOctaveMerge = 1;
      58              : 
      59        80878 :         double spatium() const { return m_spatium; }
      60         5196 :         double verticalAccidentalToAccidentalClearance() const { return m_verticalAccidentalToAccidentalClearance; }
      61        13436 :         double verticalSharpToSharpClearance() const { return m_verticalSharpToSharpClearance; }
      62       136035 :         double verticalAccidentalToChordClearance() const { return m_verticalAccidentalToChordClearance; }
      63        17641 :         double accidentalAccidentalDistance() const { return m_accidentalAccidentalDistance; }
      64         2891 :         double additionalPaddingForVerticals() const { return m_additionalPaddingForVerticals; }
      65         3581 :         double xPosSplitThreshold() const { return m_xPosSplitThreshold; }
      66          352 :         double xVerticalAlignmentThreshold() const { return m_xVerticalAlignmentThreshold; }
      67         8567 :         double sharpAndNaturalLedgerLinePadding() const { return m_sharpAndNaturalLedgerLinePadding; }
      68          550 :         double reducedFlatToNotePadding() const { return m_reducedFlatToNotePadding; }
      69          129 :         double flatKerningOfFourth() const { return m_flatKerningOfFourth; }
      70            6 :         double naturalKerningOfFourth() const { return m_naturalKerningOfFourth; }
      71              : 
      72         3128 :         bool orderFollowNoteDisplacement() const { return m_orderFollowNoteDisplacement; }
      73         6241 :         bool alignOctavesAcrossSubChords() const { return m_alignOctavesAcrossSubChords; }
      74         4275 :         bool keepSecondsTogether() const { return m_keepSecondsTogether; }
      75         3043 :         bool alignOffsetOctaves() const { return m_alignOffsetOctaves; }
      76          120 :         size_t largeGroupLimit() const { return m_largeGroupLimit; }
      77         3458 :         size_t smallGroupLimit() const { return m_smallGroupLimit; }
      78              : 
      79              :     private:
      80              :         void initConstants();
      81              : 
      82              :         double m_spatium = 0.0;
      83              :         double m_verticalAccidentalToAccidentalClearance = 0.0;
      84              :         double m_verticalSharpToSharpClearance = 0.0;
      85              :         double m_verticalAccidentalToChordClearance = 0.0;
      86              :         double m_accidentalAccidentalDistance = 0.0;
      87              :         double m_additionalPaddingForVerticals = 0.0;
      88              :         double m_xPosSplitThreshold = 0.0;
      89              :         double m_xVerticalAlignmentThreshold = 0.0;
      90              :         double m_sharpAndNaturalLedgerLinePadding = 0.0;
      91              :         double m_reducedFlatToNotePadding = 0.0;
      92              :         double m_flatKerningOfFourth = 0.0;
      93              :         double m_naturalKerningOfFourth = 0.0;
      94              :         bool m_orderFollowNoteDisplacement = false;
      95              :         bool m_alignOctavesAcrossSubChords = false;
      96              :         bool m_keepSecondsTogether = false;
      97              :         bool m_alignOffsetOctaves = false;
      98              : 
      99              :         static constexpr size_t m_smallGroupLimit = 3;
     100              :         static constexpr size_t m_largeGroupLimit = 6;
     101              :     };
     102              : 
     103              :     using AccidentalsVectorView = muse::VectorView<Accidental*>;
     104              : 
     105              :     static void collectAccidentals(const std::vector<Chord*> chords, std::vector<Accidental*>& allAccidentals,
     106              :                                    std::vector<Accidental*>& redundantAccidentals, std::vector<Accidental*>& invisibleAccidentals);
     107              :     static bool accidentalIsRedundant(const Accidental* acc, const std::vector<Accidental*>& allAccidentals);
     108              : 
     109              :     static void doAccidentalPlacement(AccidentalsLayoutContext& ctx);
     110              : 
     111              :     static void findOctavesAndSeconds(const AccidentalsLayoutContext& ctx);
     112              : 
     113              :     static void splitIntoSubChords(AccidentalsLayoutContext& ctx);
     114              :     static void mergeAdjacentSubGroupsIfTooSmall(AccidentalsLayoutContext& ctx);
     115              :     static void mergeSubGroupsWithOctavesAcross(AccidentalsLayoutContext& ctx);
     116              : 
     117              :     static void createChordsShape(AccidentalsLayoutContext& ctx);
     118              : 
     119              :     static void layoutSubChord(std::vector<Accidental*>& accidentals, AccidentalsLayoutContext& ctx);
     120              :     static void stackAccidental(Accidental* acc, AccidentalsLayoutContext& ctx);
     121              : 
     122              :     static void computeOrdering(std::vector<Accidental*>& accidentals, AccidentalsLayoutContext& ctx);
     123              :     static AccidentalGroups splitIntoPriorityGroups(std::vector<Accidental*>& accidentals, AccidentalsLayoutContext& ctx);
     124              : 
     125              :     static AccidentalGroups splitAccordingToAccidDisplacement(std::vector<Accidental*>& accidentals, const AccidentalsLayoutContext& ctx);
     126              :     static AccidentalGroups groupAccidentalsByXPos(std::vector<Accidental*>& accidentals, const AccidentalsLayoutContext& ctx);
     127              :     static void moveOctavesToSecondGroup(AccidentalGroups& subGroups);
     128              : 
     129              :     static AccidentalGroups splitAccordingToNoteDisplacement(std::vector<Accidental*>& accidentals, const AccidentalsLayoutContext& ctx);
     130              :     static AccidentalGroups groupAccidentalsByNoteXPos(const std::vector<Accidental*>& accidentals);
     131              :     static void moveSecondsInSameGroup(AccidentalGroups& subGroups);
     132              : 
     133              :     static void determineStackingOrder(std::vector<Accidental*>& accidentals, AccidentalsLayoutContext& ctx);
     134              :     static void computeStandardOrdering(std::vector<Accidental*>& accidentals, AccidentalsLayoutContext& ctx);
     135              :     static void computeCompactOrdering(std::vector<Accidental*>& accidentals, AccidentalsLayoutContext& ctx);
     136              :     static void computeOrderingWithLeastColumns(std::vector<Accidental*>& accidentals, AccidentalsLayoutContext& ctx);
     137              :     static void findAndInsertSecond(Accidental* acc, std::vector<Accidental*>& accidentalsPlaced, AccidentalsVectorView& accidentalsToPlace,
     138              :                                     AccidentalsLayoutContext& ctx);
     139              :     static bool findAndInsertOctave(Accidental* acc, std::vector<Accidental*>& accidentalsPlaced, AccidentalsVectorView& accidentalsToPlace,
     140              :                                     AccidentalsLayoutContext& ctx, bool acceptAbove = true, bool acceptBelow = true);
     141              : 
     142              :     static void applyOrderingOffsets(std::vector<Accidental*>& accidentals);
     143              : 
     144              :     static double minAccidentalToChordDistance(Accidental* acc, const Shape& accShape, const AccidentalsLayoutContext& ctx);
     145              :     static double kerningLimitationsIntoChord(Accidental* acc, const Shape& accShape, const ShapeElement& chordElement,
     146              :                                               const AccidentalsLayoutContext& ctx);
     147              :     static double computePadding(Accidental* acc, const EngravingItem* chordElement, const AccidentalsLayoutContext& ctx);
     148              : 
     149              :     static double minAccidentalToAccidentalGroupDistance(Accidental* acc, Shape accShape, const Shape& accidentalsShape,
     150              :                                                          const AccidentalsLayoutContext& ctx);
     151              :     static double kerningOfFourth(const Shape& accShape, const ShapeElement& accGroupShapeElement, const AccidentalsLayoutContext& ctx);
     152              :     static void checkZeroColumn(Accidental* acc, const AccidentalsLayoutContext& ctx);
     153              : 
     154              :     static double additionalPaddingForVerticals(const Accidental* acc, const EngravingItem* item, const AccidentalsLayoutContext& ctx);
     155              : 
     156              :     static void verticallyAlignAccidentals(AccidentalsLayoutContext& ctx);
     157              :     static void collectVerticalSetsOfOffsetOctaves(std::set<Accidental*>& accidentalsAlreadyGrouped, std::map<Accidental*,
     158              :                                                                                                               std::vector<Accidental*> >& verticalSets, AccidentalsLayoutContext& ctx);
     159              :     static void collectVerticalSets(std::set<Accidental*>& accidentalsAlreadyGrouped, std::map<Accidental*,
     160              :                                                                                                std::vector<Accidental*> >& verticalSets,
     161              :                                     AccidentalsLayoutContext& ctx);
     162              :     static void alignVerticalSets(AccidentalGroups& vertSets, AccidentalsLayoutContext& ctx);
     163              : 
     164              :     static double verticalPadding(const Accidental* acc1, const Accidental* acc2, const AccidentalsLayoutContext& ctx);
     165              :     static bool canFitInSameColumn(const Accidental* acc1, const Accidental* acc2, AccidentalsLayoutContext& ctx);
     166              : 
     167              :     static double horizontalPadding(const Accidental* acc1, const Accidental* acc2, const AccidentalsLayoutContext& ctx);
     168              : 
     169              :     static bool isExceptionOfFourth(const Accidental* acc1, const Accidental* acc2);
     170              :     static bool isExceptionOfNaturalsSixth(const Accidental* acc1, const Accidental* acc2);
     171              :     static bool isOctave(const Accidental* acc1, const Accidental* acc2);
     172              : 
     173              :     static void setXposRelativeToSegment(Accidental* accidental, double x);
     174              :     static double xPosRelativeToSegment(const Accidental* accidental);
     175              : 
     176              :     static void sortTopDown(std::vector<Accidental*>& accidentals);
     177              : 
     178              :     static bool keepAccidentalsCloseToChord(const Chord* chord);
     179              : };
     180              : }
        

Generated by: LCOV version 2.0-1