Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qpainterpath_p.h
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#ifndef QPAINTERPATH_P_H
5#define QPAINTERPATH_P_H
6
7//
8// W A R N I N G
9// -------------
10//
11// This file is not part of the Qt API. It exists for the convenience
12// of other Qt classes. This header file may change from version to
13// version without notice, or even be removed.
14//
15// We mean it.
16//
17
18#include <QtGui/private/qtguiglobal_p.h>
19#include "QtGui/qpainterpath.h"
20#include "QtGui/qregion.h"
21#include "QtCore/qlist.h"
22#include "QtCore/qvarlengtharray.h"
23
24#include <private/qvectorpath_p.h>
25#include <private/qstroker_p.h>
26#include <private/qbezier_p.h>
27
28#include <memory>
29
30QT_BEGIN_NAMESPACE
31
32class QPolygonF;
34
36{
37public:
38 QVectorPathConverter(const QList<QPainterPath::Element> &path, bool hasWindingFill, bool convex)
41 {
42 }
43
45 return path;
46 }
47
49 QVectorPathData(const QList<QPainterPath::Element> &path, bool hasWindingFill, bool convex)
50 : elements(path.size()), points(path.size() * 2), flags(0)
51 {
52 int ptsPos = 0;
53 bool isLines = true;
54 for (int i=0; i<path.size(); ++i) {
55 const QPainterPath::Element &e = path.at(i);
56 elements[i] = e.type;
57 points[ptsPos++] = e.x;
58 points[ptsPos++] = e.y;
59 if (e.type == QPainterPath::CurveToElement)
60 flags |= QVectorPath::CurvedShapeMask;
61
62 // This is to check if the path contains only alternating lineTo/moveTo,
63 // in which case we can set the LinesHint in the path. MoveTo is 0 and
64 // LineTo is 1 so the i%2 gets us what we want cheaply.
65 isLines = isLines && e.type == (QPainterPath::ElementType) (i%2);
66 }
67
68 if (hasWindingFill)
69 flags |= QVectorPath::WindingFill;
70 else
71 flags |= QVectorPath::OddEvenFill;
72
73 if (isLines)
74 flags |= QVectorPath::LinesShapeMask;
75 else {
76 flags |= QVectorPath::AreaShapeMask;
77 if (!convex)
78 flags |= QVectorPath::NonConvexShapeMask;
79 }
80
81 }
84 uint flags;
85 };
86
89
90private:
92};
93
95{
96public:
97 friend class QPainterPath;
98 friend class QPainterPathStroker;
100 friend class QTransform;
101 friend class QVectorPath;
102#ifndef QT_NO_DATASTREAM
105#endif
106
108 : require_moveTo(false),
109 dirtyBounds(false),
110 dirtyControlBounds(false),
111 convex(false),
112 hasWindingFill(false),
113 cacheEnabled(false)
114 {
115 }
116
117 QPainterPathPrivate(QPointF startPoint)
119 bounds(startPoint, QSizeF(0, 0)),
121 require_moveTo(false),
122 dirtyBounds(false),
123 dirtyControlBounds(false),
124 convex(false),
125 hasWindingFill(false),
126 cacheEnabled(false)
127 {
128 }
129
135 cStart(other.cStart),
136 require_moveTo(false),
137 dirtyBounds(other.dirtyBounds),
138 dirtyControlBounds(other.dirtyControlBounds),
139 dirtyRunLengths(other.dirtyRunLengths),
140 convex(other.convex),
141 hasWindingFill(other.hasWindingFill),
142 cacheEnabled(other.cacheEnabled)
143 {
144 }
145
148
149 inline bool isClosed() const;
150 inline void close();
151 inline void maybeMoveTo();
152 inline void clear();
153 QPointF endPointOfElement(int elemIdx) const;
154 void computeRunLengths();
155 int elementAtLength(qreal len);
156 int elementAtT(qreal t);
157 QBezier bezierAtT(const QPainterPath &path, qreal t, qreal *startingLength,
158 qreal *bezierLength) const;
160 TrimStart = 0x01,
161 TrimEnd = 0x02
162 };
163 void appendTrimmedElement(QPainterPath *to, int elemIdx, int trimFlags, qreal startLen, qreal endLen);
164 void appendStartOfElement(QPainterPath *to, int elemIdx, qreal len)
165 {
166 appendTrimmedElement(to, elemIdx, TrimEnd, 0, len);
167 }
168 void appendEndOfElement(QPainterPath *to, int elemIdx, qreal len)
169 {
170 appendTrimmedElement(to, elemIdx, TrimStart, len, 0);
171 }
172 void appendSliceOfElement(QPainterPath *to, int elemIdx, qreal fromLen, qreal toLen)
173 {
174 appendTrimmedElement(to, elemIdx, TrimStart | TrimEnd, fromLen, toLen);
175 }
176 void appendElementRange(QPainterPath *to, int first, int last);
177
179 if (!pathConverter)
180 pathConverter.reset(new QVectorPathConverter(elements, hasWindingFill, convex));
181 return pathConverter->path;
182 }
183
184private:
185 QList<QPainterPath::Element> elements;
186 std::unique_ptr<QVectorPathConverter> pathConverter;
187 QList<qreal> m_runLengths;
188 QRectF bounds;
189 QRectF controlBounds;
190
191 int cStart = 0;
192
193 bool require_moveTo : 1;
194 bool dirtyBounds : 1;
195 bool dirtyControlBounds : 1;
196 bool dirtyRunLengths : 1;
197 bool convex : 1;
198 bool hasWindingFill : 1;
199 bool cacheEnabled : 1;
200};
201
211
212inline const QPainterPath QVectorPath::convertToPainterPath() const
213{
214 QPainterPath path;
215 path.ensureData();
216 QPainterPathPrivate *data = path.d_func();
217 data->elements.reserve(m_count);
218 int index = 0;
219 data->elements[0].x = m_points[index++];
220 data->elements[0].y = m_points[index++];
221
222 if (m_elements) {
223 data->elements[0].type = m_elements[0];
224 for (int i=1; i<m_count; ++i) {
225 QPainterPath::Element element;
226 element.x = m_points[index++];
227 element.y = m_points[index++];
228 element.type = m_elements[i];
229 data->elements << element;
230 }
231 } else {
232 data->elements[0].type = QPainterPath::MoveToElement;
233 for (int i=1; i<m_count; ++i) {
234 QPainterPath::Element element;
235 element.x = m_points[index++];
236 element.y = m_points[index++];
237 element.type = QPainterPath::LineToElement;
238 data->elements << element;
239 }
240 }
241
242 data->hasWindingFill = !(m_hints & OddEvenFill);
243 return path;
244}
245
246void Q_GUI_EXPORT qt_find_ellipse_coords(const QRectF &r, qreal angle, qreal length,
247 QPointF* startPoint, QPointF *endPoint);
248
249inline bool QPainterPathPrivate::isClosed() const
250{
251 const QPainterPath::Element &first = elements.at(cStart);
252 const QPainterPath::Element &last = elements.last();
253 return first.x == last.x && first.y == last.y;
254}
255
257{
258 require_moveTo = true;
259 const QPainterPath::Element &first = elements.at(cStart);
260 QPainterPath::Element &last = elements.last();
261 if (first.x != last.x || first.y != last.y) {
262 if (qFuzzyCompare(first.x, last.x) && qFuzzyCompare(first.y, last.y)) {
263 last.x = first.x;
264 last.y = first.y;
265 } else {
266 QPainterPath::Element e = { first.x, first.y, QPainterPath::LineToElement };
267 elements << e;
268 }
269 }
270}
271
273{
274 if (require_moveTo) {
275 QPainterPath::Element e = elements.last();
276 e.type = QPainterPath::MoveToElement;
277 elements.append(e);
278 require_moveTo = false;
279 }
280}
281
283{
284 elements.clear();
285 m_runLengths.clear();
286
287 cStart = 0;
288 bounds = {};
289 controlBounds = {};
290
291 require_moveTo = false;
292 dirtyBounds = false;
293 dirtyControlBounds = false;
294 dirtyRunLengths = false;
295 convex = false;
296
297 pathConverter.reset();
298}
299
301{
302 const QPainterPath::Element &e = elements.at(elemIdx);
303 if (e.isCurveTo())
304 return elements.at(elemIdx + 2);
305 else
306 return e;
307}
308
310{
311 Q_ASSERT(cacheEnabled);
312 Q_ASSERT(!dirtyRunLengths);
313 const auto it = std::lower_bound(m_runLengths.constBegin(), m_runLengths.constEnd(), len);
314 return (it == m_runLengths.constEnd()) ? m_runLengths.size() - 1 : int(it - m_runLengths.constBegin());
315}
316
317inline int QPainterPathPrivate::elementAtT(qreal t)
318{
319 Q_ASSERT(cacheEnabled);
320 if (dirtyRunLengths)
322 qreal len = t * m_runLengths.constLast();
323 return elementAtLength(len);
324}
325
326#define KAPPA qreal(0.5522847498)
327
328QT_END_NAMESPACE
329
330#endif // QPAINTERPATH_P_H
QTransform m_transform
QT_FT_Outline * outline()
void clipElements(const QPointF *points, const QPainterPath::ElementType *types, int count)
QDataBuffer< QT_FT_Vector > m_points
void convertElements(const QPointF *points, const QPainterPath::ElementType *types, int count)
void setMatrix(const QTransform &m)
Sets up the matrix to be used for conversion.
void moveTo(const QPointF &pt)
void curveTo(const QPointF &cp1, const QPointF &cp2, const QPointF &ep)
void setClipRect(QRect clipRect)
QDataBuffer< QPointF > m_elements
QPainterPath::ElementType * elementTypes() const
QDataBuffer< char > m_tags
QDataBuffer< int > m_contours
QDataBuffer< QPainterPath::ElementType > m_element_types
QT_FT_Outline m_outline
QT_FT_Outline * convertPath(const QPainterPath &path)
void beginOutline(Qt::FillRule fillRule)
void lineTo(const QPointF &pt)
int elementAtT(qreal t)
QPainterPathPrivate(QPointF startPoint)
void appendStartOfElement(QPainterPath *to, int elemIdx, qreal len)
int elementAtLength(qreal len)
void appendEndOfElement(QPainterPath *to, int elemIdx, qreal len)
QPainterPathPrivate(const QPainterPathPrivate &other) noexcept
void appendTrimmedElement(QPainterPath *to, int elemIdx, int trimFlags, qreal startLen, qreal endLen)
void appendSliceOfElement(QPainterPath *to, int elemIdx, qreal fromLen, qreal toLen)
QPainterPathPrivate & operator=(const QPainterPathPrivate &)=delete
const QVectorPath & vectorPath()
void appendElementRange(QPainterPath *to, int first, int last)
QBezier bezierAtT(const QPainterPath &path, qreal t, qreal *startingLength, qreal *bezierLength) const
QPointF endPointOfElement(int elemIdx) const
~QPainterPathPrivate()=default
QPainterPathPrivate() noexcept
friend class QPaintEngineExPrivate
Definition qpainter.h:438
QVectorPathConverter(const QList< QPainterPath::Element > &path, bool hasWindingFill, bool convex)
QVectorPathData pathData
const QVectorPath & vectorPath()
#define qreal_to_fixed_26_6(f)
Q_GUI_EXPORT bool qt_scaleForTransform(const QTransform &transform, qreal *scale)
QT_BEGIN_NAMESPACE constexpr int QT_RASTER_COORD_LIMIT
QDebug Q_GUI_EXPORT & operator<<(QDebug &s, const QVectorPath &path)
QVectorPathData(const QList< QPainterPath::Element > &path, bool hasWindingFill, bool convex)
QVarLengthArray< QPainterPath::ElementType > elements