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 :
23 : #pragma once
24 :
25 : #include <stack>
26 :
27 : #include "global/types/string.h"
28 :
29 : #include "types/color.h"
30 : #include "types/geometry.h"
31 : #include "types/drawtypes.h"
32 : #include "types/font.h"
33 : #include "types/pen.h"
34 : #include "types/pixmap.h"
35 :
36 : #include "ipaintprovider.h"
37 :
38 : class QPaintDevice;
39 :
40 : #ifndef NO_QT_SUPPORT
41 : class QPainter;
42 : #endif
43 :
44 : namespace muse::draw {
45 : class Painter
46 : {
47 : public:
48 : Painter(IPaintProviderPtr provider, const std::string& name);
49 :
50 : #ifndef NO_QT_SUPPORT
51 : Painter(QPaintDevice* dp, const std::string& name);
52 : Painter(QPainter* qp, const std::string& name, bool ownsQPainter = false);
53 : #endif
54 :
55 : ~Painter();
56 :
57 : IPaintProviderPtr provider() const;
58 : void setProvider(const IPaintProviderPtr& p, bool reinit = true);
59 :
60 : bool isActive() const;
61 : bool endDraw();
62 :
63 : //! NOTE These are methods for debugging and automated testing.
64 : void beginObject(const std::string& name);
65 : void endObject();
66 :
67 : // state
68 : void setAntialiasing(bool arg);
69 : void setCompositionMode(CompositionMode mode);
70 :
71 : void setFont(const Font& font);
72 : const Font& font() const;
73 :
74 : void setPen(const Pen& pen);
75 : inline void setPen(const Color& color);
76 : void setNoPen();
77 : const Pen& pen() const;
78 :
79 : void setBrush(const Brush& brush);
80 : const Brush& brush() const;
81 :
82 : void setWorldTransform(const Transform& matrix, bool combine = false);
83 : const Transform& worldTransform() const;
84 : void scale(double sx, double sy);
85 : void rotate(double angle);
86 : void translate(double dx, double dy);
87 : inline void translate(const PointF& offset);
88 :
89 : RectF window() const;
90 : void setWindow(const RectF& window);
91 : RectF viewport() const;
92 : void setViewport(const RectF& viewport);
93 :
94 : void save();
95 : void restore();
96 :
97 : double deviceLogicalDpi() const;
98 :
99 : // drawing
100 : void fillPath(const PainterPath& path, const Brush& brush);
101 : void drawPath(const PainterPath& path);
102 : void strokePath(const PainterPath& path, const Pen& pen);
103 :
104 : void drawLines(const LineF* lines, size_t lineCount);
105 : void drawLines(const PointF* pointPairs, size_t lineCount);
106 : inline void drawLine(const LineF& line);
107 : inline void drawLine(const PointF& p1, const PointF& p2);
108 : inline void drawLine(double x1, double y1, double x2, double y2);
109 : inline void drawLines(const std::vector<LineF>& lines);
110 :
111 : inline void drawRect(const RectF& rect);
112 : inline void drawRect(double x1, double y1, double w, double h);
113 :
114 : void drawRects(const RectF* rects, size_t rectCount);
115 :
116 : void drawRoundedRect(const RectF& rect, double xRadius, double yRadius);
117 :
118 : void drawEllipse(const RectF& rect);
119 : inline void drawEllipse(const PointF& center, double rx, double ry);
120 :
121 : void drawPolyline(const PointF* points, size_t pointCount);
122 : inline void drawPolyline(const PolygonF& polyline);
123 :
124 : void drawPolygon(const PointF* points, size_t pointCount, FillRule fillRule = FillRule::OddEvenFill);
125 : inline void drawPolygon(const PolygonF& polygon, FillRule fillRule = FillRule::OddEvenFill);
126 :
127 : void drawConvexPolygon(const PointF* points, size_t pointCount);
128 : inline void drawConvexPolygon(const PolygonF& polygon);
129 :
130 : void drawArc(const RectF& rect, int a, int alen);
131 :
132 : void drawText(const PointF& point, const String& text);
133 : inline void drawText(double x, double y, const String& text);
134 :
135 : void drawText(const RectF& rect, Alignment alignment, TextFlags textFlags, const String& text);
136 :
137 : void drawSymbol(const PointF& point, char32_t ucs4Code);
138 :
139 : void fillRect(const RectF& rect, const Brush& brush);
140 :
141 : void drawPixmap(const PointF& point, const Pixmap& pm);
142 : void drawTiledPixmap(const RectF& rect, const Pixmap& pm, const PointF& offset = PointF());
143 :
144 : #ifndef NO_QT_SUPPORT
145 : void drawPixmap(const PointF& point, const QPixmap& pm);
146 : void drawTiledPixmap(const RectF& rect, const QPixmap& pm, const PointF& offset = PointF());
147 : #endif
148 :
149 : bool hasClipping() const;
150 :
151 : void setClipRect(const RectF& rect);
152 : void setMask(const RectF& background, const std::vector<RectF>& maskRects);
153 : void setClipping(bool enable);
154 :
155 : //! NOTE Provider for tests.
156 : //! We're not ready to use DI (ModuleIoC) here yet
157 : static IPaintProviderPtr extended;
158 :
159 : private:
160 :
161 : struct State {
162 : RectF window;
163 : RectF viewport;
164 : bool isVxF = false;
165 : Transform viewTransform;
166 : bool isWxF = false;
167 : Transform worldTransform; // World transformation matrix, not window and viewport
168 : Transform transform; // Complete transformation matrix
169 : };
170 :
171 : void init();
172 : State& editableState();
173 : const State& state() const;
174 : void updateViewTransform();
175 : void updateMatrix();
176 :
177 : void applyFontSizeScaling();
178 :
179 : bool endTarget(bool endDraw);
180 :
181 : IPaintProviderPtr m_provider;
182 : std::string m_name;
183 : std::stack<State> m_states;
184 : };
185 :
186 243 : inline void Painter::setPen(const Color& color)
187 : {
188 243 : setPen(Pen(color.isValid() ? color : Color::BLACK));
189 243 : }
190 :
191 774 : inline void Painter::translate(const PointF& offset)
192 : {
193 774 : translate(offset.x(), offset.y());
194 774 : }
195 :
196 124 : inline void Painter::drawLine(const LineF& l)
197 : {
198 124 : drawLines(&l, 1);
199 124 : }
200 :
201 0 : inline void Painter::drawLine(const PointF& p1, const PointF& p2)
202 : {
203 0 : drawLine(LineF(p1, p2));
204 0 : }
205 :
206 7 : inline void Painter::drawLine(double x1, double y1, double x2, double y2)
207 : {
208 7 : LineF l(PointF(x1, y1), PointF(x2, y2));
209 7 : drawLines(&l, 1);
210 7 : }
211 :
212 20 : inline void Painter::drawLines(const std::vector<LineF>& lines)
213 : {
214 20 : drawLines(lines.data(), lines.size());
215 20 : }
216 :
217 6 : inline void Painter::drawRect(const RectF& rect)
218 : {
219 6 : drawRects(&rect, 1);
220 6 : }
221 :
222 0 : inline void Painter::drawRect(double x, double y, double w, double h)
223 : {
224 0 : RectF r(x, y, w, h);
225 0 : drawRects(&r, 1);
226 0 : }
227 :
228 0 : inline void Painter::drawEllipse(const PointF& center, double rx, double ry)
229 : {
230 0 : drawEllipse(RectF(center.x() - rx, center.y() - ry, 2 * rx, 2 * ry));
231 0 : }
232 :
233 0 : inline void Painter::drawPolyline(const PolygonF& polyline)
234 : {
235 0 : drawPolyline(polyline.data(), polyline.size());
236 0 : }
237 :
238 0 : inline void Painter::drawPolygon(const PolygonF& polygon, FillRule fillRule)
239 : {
240 0 : drawPolygon(polygon.data(), polygon.size(), fillRule);
241 0 : }
242 :
243 0 : inline void Painter::drawConvexPolygon(const PolygonF& poly)
244 : {
245 0 : drawConvexPolygon(poly.data(), poly.size());
246 0 : }
247 :
248 0 : inline void Painter::drawText(double x, double y, const String& text)
249 : {
250 0 : drawText(PointF(x, y), text);
251 0 : }
252 :
253 : class PainterItemMarker
254 : {
255 : public:
256 : PainterItemMarker(Painter* p, const std::string& name)
257 : : m_painter(p)
258 : {
259 : if (!enabled) {
260 : return;
261 : }
262 : p->beginObject(name);
263 : }
264 :
265 : ~PainterItemMarker()
266 : {
267 : if (!enabled) {
268 : return;
269 : }
270 : m_painter->endObject();
271 : }
272 :
273 : static bool enabled;
274 :
275 : private:
276 : Painter* m_painter = nullptr;
277 : };
278 : }
279 :
280 : #ifdef MUSE_MODULE_DRAW_TRACE
281 : #define TRACE_ITEM_DRAW \
282 : muse::draw::PainterItemMarker __drawItemMarker(painter, typeName())
283 :
284 : #define TRACE_DRAW_ITEM \
285 : muse::draw::PainterItemMarker __drawItemMarker(painter, item->typeName())
286 :
287 : #define TRACE_ITEM_DRAW_C(painter, itemName) \
288 : muse::draw::PainterItemMarker __drawItemMarker(painter, itemName)
289 : #else
290 : #define TRACE_ITEM_DRAW
291 : #define TRACE_DRAW_ITEM
292 : #define TRACE_ITEM_DRAW_C(painter, objName)
293 : #endif
|