LCOV - code coverage report
Current view: top level - src/engraving/infrastructure - shape.h Coverage Total Hit
Test: filtered_coverage.info Lines: 100.0 % 31 31
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) 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              : 
      23              : #ifndef MU_ENGRAVING_SHAPE_H
      24              : #define MU_ENGRAVING_SHAPE_H
      25              : 
      26              : #include <functional>
      27              : #include <optional>
      28              : 
      29              : #include "draw/types/geometry.h"
      30              : #include "draw/types/transform.h"
      31              : 
      32              : #include "engraving/types/types.h"
      33              : 
      34              : namespace muse::draw {
      35              : class Painter;
      36              : class Transform;
      37              : }
      38              : 
      39              : namespace mu::engraving {
      40              : class EngravingItem;
      41              : 
      42              : //---------------------------------------------------------
      43              : //   ShapeElement
      44              : //---------------------------------------------------------
      45              : 
      46              : struct ShapeElement : public RectF {
      47              : public:
      48              : 
      49       483359 :     ShapeElement(const RectF& f, const EngravingItem* p, bool ignoreForLayout)
      50       483359 :         : RectF(f), m_item(p), m_ignoreForLayout(ignoreForLayout) {}
      51      3107951 :     ShapeElement(const RectF& f, const EngravingItem* p)
      52      3107951 :         : RectF(f), m_item(p) {}
      53        12276 :     ShapeElement(const RectF& f)
      54        12276 :         : RectF(f) {}
      55              : 
      56     15308325 :     const EngravingItem* item() const { return m_item; }
      57       135600 :     void setItem(const EngravingItem* item) { m_item = item; }
      58      1924769 :     bool ignoreForLayout() const { return m_ignoreForLayout; }
      59              : 
      60              : private:
      61              :     const EngravingItem* m_item = nullptr;
      62              :     bool m_ignoreForLayout = false;
      63              : };
      64              : 
      65              : //---------------------------------------------------------
      66              : //   Shape
      67              : //---------------------------------------------------------
      68              : 
      69              : class Shape
      70              : {
      71              : public:
      72              : 
      73              :     enum class Type : unsigned char {
      74              :         Fixed,      // fixed size, like just bbox
      75              : //        FixedX,     // not implemented (reserved)
      76              : //        FixedY,     // not implemented (reserved)
      77              :         Composite   // composed of other shapes
      78              :     };
      79              : 
      80      3539613 :     Shape(Type t = Type::Fixed)
      81      3539613 :         : m_type(t) {}
      82      1909825 :     Shape(const RectF& r, const EngravingItem* p = nullptr, Type t = Type::Fixed)
      83      1909825 :         : m_type(t) { setBBox(r, p); }
      84              :     Shape(const std::vector<RectF>& rects, const EngravingItem* p = nullptr);
      85              : 
      86      1909825 :     Type type() const { return m_type; }
      87              :     bool isComposite() const { return m_type == Type::Composite; }
      88              : 
      89          172 :     size_t size() const { return m_elements.size(); }
      90       115904 :     bool empty() const { return m_elements.empty(); }
      91       746442 :     void clear() { m_elements.clear(); }
      92              : 
      93              :     bool equal(const Shape& sh) const
      94              :     {
      95              :         if (m_type != sh.m_type) {
      96              :             return false;
      97              :         }
      98              : 
      99              :         switch (m_type) {
     100              :         case Type::Fixed: return this->bbox() == sh.bbox();
     101              :         case Type::Composite: return this->m_elements == sh.m_elements;
     102              :         }
     103              : 
     104              :         return true;
     105              :     }
     106              : 
     107              :     // Fixed
     108              :     void setBBox(const RectF& r, const EngravingItem* p = nullptr);
     109              :     void addBBox(const RectF& r);
     110              : 
     111              :     // Composite
     112              :     void add(const Shape& s);
     113              :     void add(const ShapeElement& shapeEl);
     114       483359 :     void add(const RectF& r, const EngravingItem* p, bool ignoreForLayout) { add(ShapeElement(r, p, ignoreForLayout)); }
     115      1124099 :     void add(const RectF& r, const EngravingItem* p) { add(ShapeElement(r, p)); }
     116        12276 :     void add(const RectF& r) { add(ShapeElement(r)); }
     117              : 
     118              :     void remove(const RectF&);
     119              :     void remove(const Shape&);
     120              :     template<typename Predicate>
     121       693433 :     inline bool remove_if(Predicate p)
     122              :     {
     123       693433 :         size_t origSize = m_elements.size();
     124       693433 :         m_elements.erase(std::remove_if(m_elements.begin(), m_elements.end(), p), m_elements.end());
     125       693433 :         invalidateBBox();
     126       693433 :         return origSize != m_elements.size();
     127              :     }
     128              : 
     129              :     // ---
     130              : 
     131      5289105 :     const std::vector<ShapeElement>& elements() const { return m_elements; }
     132       150006 :     std::vector<ShapeElement>& elements() { return m_elements; }
     133              :     std::vector<RectF> toRects() const;
     134              : 
     135              :     std::optional<ShapeElement> find_if(const std::function<bool(const ShapeElement&)>& func) const;
     136              :     std::optional<ShapeElement> find_first(ElementType type) const;
     137              :     std::optional<ShapeElement> get_first() const;
     138              : 
     139              :     void removeInvisibles();
     140              :     void removeTypes(const std::set<ElementType>& types);
     141              : 
     142              :     void addHorizontalSpacing(EngravingItem* item, double left, double right);
     143              : 
     144              :     Shape& translate(const PointF&);
     145              :     void translateX(double);
     146              :     void translateY(double);
     147              :     Shape translated(const PointF&) const;
     148              :     Shape& scale(const SizeF&);
     149              :     Shape scaled(const SizeF&) const;
     150              :     Shape& adjust(double xp1, double yp1, double xp2, double yp2);
     151              :     Shape adjusted(double xp1, double yp1, double xp2, double yp2) const;
     152              :     Shape& pad(double p);
     153              :     Shape padded(double p) const;
     154              :     Shape& transform(const muse::draw::Transform& t);
     155              :     Shape transformed(const muse::draw::Transform& t);
     156              : 
     157              :     const RectF& bbox() const;
     158              :     double minVerticalDistance(const Shape&, double minHorizontalClearance = 0.0) const;
     159              :     double verticalClearance(const Shape&, double minHorizontalDistance = 0.0) const;
     160              :     double topDistance(const PointF&) const;
     161              :     double bottomDistance(const PointF&) const;
     162              :     double left() const;
     163              :     double right() const;
     164              :     double top() const;
     165              :     double bottom() const;
     166              :     double width() const;
     167              :     double height() const;
     168              :     double topAtX(double x) const;
     169              :     double bottomAtX(double x) const;
     170              :     double rightMostEdgeAtHeight(double yAbove, double yBelow) const;
     171              :     double leftMostEdgeAtHeight(double yAbove, double yBelow) const;
     172              :     double leftMostEdgeAtTop() const;
     173              : 
     174              :     bool contains(const PointF&) const;
     175              :     bool intersects(const RectF& rr) const;
     176              :     bool intersects(const Shape& other) const;
     177              :     bool clearsVertically(const Shape& a) const;
     178              : 
     179              :     void paint(muse::draw::Painter& painter) const;
     180              : 
     181              : private:
     182              : 
     183              :     void invalidateBBox();
     184              : 
     185              :     Type m_type = Type::Fixed;
     186              :     std::vector<ShapeElement> m_elements;
     187              :     mutable RectF m_bbox;   // cache
     188              : };
     189              : 
     190              : void dump(const ShapeElement& sh, std::stringstream& ss);
     191              : void dump(const Shape& sh, std::stringstream& ss);
     192              : std::string dump(const Shape& sh);
     193              : 
     194              : //---------------------------------------------------------
     195              : //   intersects
     196              : //---------------------------------------------------------
     197              : 
     198     12091950 : inline static bool intersects(double a, double b, double c, double d, double minClearance = 0.0)
     199              : {
     200     12091950 :     if (a == b || c == d) {
     201       194711 :         return false;
     202              :     }
     203     11897239 :     return (b + minClearance > c) && (a < d + minClearance);
     204              : }
     205              : } // namespace mu::engraving
     206              : 
     207              : #endif
        

Generated by: LCOV version 2.0-1