LCOV - code coverage report
Current view: top level - muse/framework/draw/internal - qpainterprovider.cpp Coverage Total Hit
Test: filtered_coverage.info Lines: 63.7 % 168 107
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) 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 "qpainterprovider.h"
      23              : 
      24              : #include <QPainter>
      25              : #include <QRawFont>
      26              : #include <QTextLayout>
      27              : #include <QTextLine>
      28              : #include <QGlyphRun>
      29              : #include <QPixmapCache>
      30              : #include <QStaticText>
      31              : #include <QPainterPath>
      32              : 
      33              : #include "draw/utils/drawlogger.h"
      34              : #include "types/transform.h"
      35              : #include "types/painterpath.h"
      36              : 
      37              : #include "log.h"
      38              : 
      39              : using namespace muse::draw;
      40              : 
      41           18 : QPainterProvider::QPainterProvider(QPainter* painter, bool ownsPainter)
      42           18 :     : m_painter(painter), m_ownsPainter(ownsPainter), m_drawObjectsLogger(new DrawObjectsLogger())
      43              : {
      44           18 :     if (painter->isActive()) {
      45           18 :         m_font = Font::fromQFont(m_painter->font(), Font::Type::Undefined);
      46           18 :         m_pen = Pen::fromQPen(m_painter->pen());
      47           18 :         m_brush = Brush::fromQBrush(m_painter->brush());
      48           18 :         m_transform = Transform::fromQTransform(m_painter->transform());
      49              :     }
      50           18 : }
      51              : 
      52           18 : QPainterProvider::~QPainterProvider()
      53              : {
      54           18 :     if (m_ownsPainter) {
      55           14 :         delete m_painter;
      56              :     }
      57              : 
      58           18 :     delete m_drawObjectsLogger;
      59           18 : }
      60              : 
      61           14 : IPaintProviderPtr QPainterProvider::make(QPaintDevice* dp)
      62              : {
      63           14 :     return std::make_shared<QPainterProvider>(new QPainter(dp), true);
      64              : }
      65              : 
      66            4 : IPaintProviderPtr QPainterProvider::make(QPainter* qp, bool ownsPainter)
      67              : {
      68            4 :     return std::make_shared<QPainterProvider>(qp, ownsPainter);
      69              : }
      70              : 
      71            2 : QPainter* QPainterProvider::qpainter() const
      72              : {
      73            2 :     return m_painter;
      74              : }
      75              : 
      76           18 : void QPainterProvider::beginTarget(const std::string&)
      77              : {
      78           18 : }
      79              : 
      80           31 : void QPainterProvider::beforeEndTargetHook(Painter*)
      81              : {
      82           31 : }
      83              : 
      84           31 : bool QPainterProvider::endTarget(bool endDraw)
      85              : {
      86           31 :     if (endDraw) {
      87           13 :         return m_painter->end();
      88              :     }
      89           18 :     return true;
      90              : }
      91              : 
      92            0 : bool QPainterProvider::isActive() const
      93              : {
      94            0 :     return m_painter->isActive();
      95              : }
      96              : 
      97            1 : void QPainterProvider::beginObject(const std::string& name)
      98              : {
      99              :     UNUSED(name)
     100              :     //m_drawObjectsLogger->beginObject(name);
     101            1 : }
     102              : 
     103            1 : void QPainterProvider::endObject()
     104              : {
     105              :     //m_drawObjectsLogger->endObject();
     106            1 : }
     107              : 
     108          435 : void QPainterProvider::setAntialiasing(bool arg)
     109              : {
     110          435 :     m_painter->setRenderHint(QPainter::Antialiasing, arg);
     111          435 :     m_painter->setRenderHint(QPainter::TextAntialiasing, arg);
     112          435 : }
     113              : 
     114          434 : void QPainterProvider::setCompositionMode(CompositionMode mode)
     115              : {
     116          434 :     auto toQPainter = [](CompositionMode mode) {
     117          434 :         switch (mode) {
     118          434 :         case CompositionMode::SourceOver: return QPainter::CompositionMode_SourceOver;
     119            0 :         case CompositionMode::HardLight: return QPainter::CompositionMode_HardLight;
     120            0 :         case CompositionMode::SourceIn: return QPainter::CompositionMode_SourceIn;
     121              :         }
     122            0 :         return QPainter::CompositionMode_SourceOver;
     123              :     };
     124          434 :     m_painter->setCompositionMode(toQPainter(mode));
     125          434 : }
     126              : 
     127            4 : void QPainterProvider::setWindow(const RectF& window)
     128              : {
     129              :     // no need set
     130              :     UNUSED(window);
     131            4 : }
     132              : 
     133            4 : void QPainterProvider::setViewport(const RectF& viewport)
     134              : {
     135              :     // no need set
     136              :     UNUSED(viewport);
     137            4 : }
     138              : 
     139          540 : void QPainterProvider::setFont(const Font& font)
     140              : {
     141          540 :     if (m_font != font) {
     142          125 :         m_painter->setFont(font.toQFont());
     143          125 :         m_font = font;
     144              :     }
     145          540 : }
     146              : 
     147           53 : const Font& QPainterProvider::font() const
     148              : {
     149           53 :     return m_font;
     150              : }
     151              : 
     152          522 : void QPainterProvider::setPen(const Pen& pen)
     153              : {
     154          522 :     m_pen = pen;
     155          522 :     m_painter->setPen(Pen::toQPen(m_pen));
     156          522 : }
     157              : 
     158            0 : void QPainterProvider::setNoPen()
     159              : {
     160            0 :     m_pen = Pen(PenStyle::NoPen);
     161            0 :     m_painter->setPen(Pen::toQPen(m_pen));
     162            0 : }
     163              : 
     164            0 : const Pen& QPainterProvider::pen() const
     165              : {
     166            0 :     return m_pen;
     167              : }
     168              : 
     169          441 : void QPainterProvider::setBrush(const Brush& brush)
     170              : {
     171          441 :     m_brush = brush;
     172          441 :     m_painter->setBrush(Brush::toQBrush(m_brush));
     173          441 : }
     174              : 
     175            0 : const Brush& QPainterProvider::brush() const
     176              : {
     177            0 :     return m_brush;
     178              : }
     179              : 
     180           64 : void QPainterProvider::save()
     181              : {
     182           64 :     m_painter->save();
     183           64 : }
     184              : 
     185           64 : void QPainterProvider::restore()
     186              : {
     187           64 :     m_painter->restore();
     188           64 :     m_font = Font::fromQFont(m_painter->font(), Font::Type::Undefined);
     189           64 :     m_pen = Pen::fromQPen(m_painter->pen());
     190           64 :     m_brush = Brush::fromQBrush(m_painter->brush());
     191           64 :     m_transform = Transform::fromQTransform(m_painter->transform());
     192           64 : }
     193              : 
     194           53 : double QPainterProvider::deviceLogicalDpi() const
     195              : {
     196           53 :     return m_painter->device()->logicalDpiX();
     197              : }
     198              : 
     199          660 : void QPainterProvider::setTransform(const Transform& transform)
     200              : {
     201          660 :     m_transform = transform;
     202          660 :     m_painter->setTransform(Transform::toQTransform(m_transform));
     203          660 : }
     204              : 
     205           26 : const Transform& QPainterProvider::transform() const
     206              : {
     207           26 :     return m_transform;
     208              : }
     209              : 
     210              : // drawing functions
     211              : 
     212            7 : void QPainterProvider::drawPath(const PainterPath& path)
     213              : {
     214            7 :     m_painter->drawPath(PainterPath::toQPainterPath(path));
     215            7 : }
     216              : 
     217          308 : void QPainterProvider::drawPolygon(const PointF* points, size_t pointCount, PolygonMode mode)
     218              : {
     219              :     static_assert(sizeof(QPointF) == sizeof(PointF), "sizeof(QPointF) and sizeof(PointF) must be equal");
     220              : 
     221          308 :     const QPointF* qpoints = reinterpret_cast<const QPointF*>(points);
     222              : 
     223          308 :     switch (mode) {
     224            0 :     case PolygonMode::OddEven: {
     225            0 :         m_painter->drawPolygon(qpoints, int(pointCount), Qt::OddEvenFill);
     226            0 :     } break;
     227            0 :     case PolygonMode::Winding: {
     228            0 :         m_painter->drawPolygon(qpoints, int(pointCount), Qt::WindingFill);
     229            0 :     } break;
     230            0 :     case PolygonMode::Convex: {
     231            0 :         m_painter->drawConvexPolygon(qpoints, int(pointCount));
     232            0 :     } break;
     233          308 :     case PolygonMode::Polyline: {
     234          308 :         m_painter->drawPolyline(qpoints, int(pointCount));
     235          308 :     } break;
     236              :     }
     237          308 : }
     238              : 
     239          317 : void QPainterProvider::drawText(const PointF& point, const String& text)
     240              : {
     241          317 :     QPointF p = point.toQPointF();
     242          317 :     QString t = text.toQString();
     243          317 :     m_painter->drawText(p, t);
     244          317 : }
     245              : 
     246            0 : void QPainterProvider::drawText(const RectF& rect, Alignment alignment, TextFlags textFlags, const String& text)
     247              : {
     248            0 :     int flags = static_cast<int>(alignment) | static_cast<int>(textFlags);
     249            0 :     m_painter->drawText(rect.toQRectF(), flags, text.toQString());
     250            0 : }
     251              : 
     252           53 : void QPainterProvider::drawSymbol(const PointF& point, char32_t ucs4Code)
     253              : {
     254           54 :     static QHash<char32_t, QString> cache;
     255           53 :     if (!cache.contains(ucs4Code)) {
     256            8 :         cache[ucs4Code] = QString::fromUcs4(&ucs4Code, 1);
     257              :     }
     258              : 
     259           53 :     drawText(point, cache.value(ucs4Code));
     260           53 : }
     261              : 
     262            0 : void QPainterProvider::drawPixmap(const PointF& point, const Pixmap& pm)
     263              : {
     264            0 :     QString key = QString::number(pm.key());
     265            0 :     QPixmap pixmap;
     266            0 :     if (!QPixmapCache::find(key, &pixmap)) {
     267            0 :         pixmap.loadFromData(pm.data().toQByteArrayNoCopy());
     268            0 :         QPixmapCache::insert(key, pixmap);
     269              :     }
     270              : 
     271            0 :     m_painter->drawPixmap(QPointF(point.x(), point.y()), pixmap);
     272            0 : }
     273              : 
     274            0 : void QPainterProvider::drawTiledPixmap(const RectF& rect, const Pixmap& pm, const PointF& offset)
     275              : {
     276            0 :     QString key = QString::number(pm.key());
     277            0 :     QPixmap pixmap;
     278            0 :     if (!QPixmapCache::find(key, &pixmap)) {
     279            0 :         pixmap.loadFromData(pm.data().toQByteArrayNoCopy());
     280            0 :         QPixmapCache::insert(key, pixmap);
     281              :     }
     282              : 
     283            0 :     m_painter->drawTiledPixmap(rect.toQRectF(), pixmap, QPointF(offset.x(), offset.y()));
     284            0 : }
     285              : 
     286            0 : void QPainterProvider::drawPixmap(const PointF& point, const QPixmap& pm)
     287              : {
     288            0 :     m_painter->drawPixmap(QPointF(point.x(), point.y()), pm);
     289            0 : }
     290              : 
     291            0 : void QPainterProvider::drawTiledPixmap(const RectF& rect, const QPixmap& pm, const PointF& offset)
     292              : {
     293            0 :     m_painter->drawTiledPixmap(rect.toQRectF(), pm, QPointF(offset.x(), offset.y()));
     294            0 : }
     295              : 
     296            2 : bool QPainterProvider::hasClipping() const
     297              : {
     298            2 :     return m_painter->hasClipping();
     299              : }
     300              : 
     301            1 : void QPainterProvider::setClipRect(const RectF& rect)
     302              : {
     303            1 :     m_painter->setClipRect(rect.toQRectF());
     304            1 : }
     305              : 
     306            0 : void QPainterProvider::setMask(const RectF& background, const std::vector<RectF>& maskRects)
     307              : {
     308            0 :     if (maskRects.empty()) {
     309            0 :         m_painter->setClipPath(QPainterPath(), Qt::NoClip);
     310            0 :         return;
     311              :     }
     312              : 
     313            0 :     QPainterPath backgroundPath;
     314            0 :     backgroundPath.addRect(background.toQRectF());
     315              : 
     316            0 :     QPainterPath exclusionRegion;
     317            0 :     exclusionRegion.setFillRule(Qt::WindingFill);
     318            0 :     for (const RectF& rect : maskRects) {
     319            0 :         exclusionRegion.addRect(rect.toQRectF());
     320              :     }
     321              : 
     322            0 :     QPainterPath mask = backgroundPath.subtracted(exclusionRegion);
     323              : 
     324            0 :     m_painter->setClipPath(mask);
     325            0 : }
     326              : 
     327            2 : void QPainterProvider::setClipping(bool enable)
     328              : {
     329            2 :     m_painter->setClipping(enable);
     330            2 : }
        

Generated by: LCOV version 2.0-1