qtriangulatingstroker.cpp

Absolute File Name:/home/qt/qt5_coco/qt5/qtbase/src/gui/opengl/qtriangulatingstroker.cpp
Source codeSwitch to Preprocessed file
LineSourceCount
1/****************************************************************************-
2**-
3** Copyright (C) 2015 The Qt Company Ltd.-
4** Contact: http://www.qt.io/licensing/-
5**-
6** This file is part of the QtGui module of the Qt Toolkit.-
7**-
8** $QT_BEGIN_LICENSE:LGPL21$-
9** Commercial License Usage-
10** Licensees holding valid commercial Qt licenses may use this file in-
11** accordance with the commercial license agreement provided with the-
12** Software or, alternatively, in accordance with the terms contained in-
13** a written agreement between you and The Qt Company. For licensing terms-
14** and conditions see http://www.qt.io/terms-conditions. For further-
15** information use the contact form at http://www.qt.io/contact-us.-
16**-
17** GNU Lesser General Public License Usage-
18** Alternatively, this file may be used under the terms of the GNU Lesser-
19** General Public License version 2.1 or version 3 as published by the Free-
20** Software Foundation and appearing in the file LICENSE.LGPLv21 and-
21** LICENSE.LGPLv3 included in the packaging of this file. Please review the-
22** following information to ensure the GNU Lesser General Public License-
23** requirements will be met: https://www.gnu.org/licenses/lgpl.html and-
24** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.-
25**-
26** As a special exception, The Qt Company gives you certain additional-
27** rights. These rights are described in The Qt Company LGPL Exception-
28** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.-
29**-
30** $QT_END_LICENSE$-
31**-
32****************************************************************************/-
33-
34#include "qtriangulatingstroker_p.h"-
35#include <qmath.h>-
36-
37QT_BEGIN_NAMESPACE-
38-
39#define CURVE_FLATNESS Q_PI / 8-
40-
41-
42-
43-
44void QTriangulatingStroker::endCapOrJoinClosed(const qreal *start, const qreal *cur,-
45 bool implicitClose, bool endsAtStart)-
46{-
47 if (endsAtStart) {
endsAtStartDescription
TRUEnever evaluated
FALSEnever evaluated
0
48 join(start + 2);-
49 } else if (implicitClose) {
never executed: end of block
implicitCloseDescription
TRUEnever evaluated
FALSEnever evaluated
0
50 join(start);-
51 lineTo(start);-
52 join(start+2);-
53 } else {
never executed: end of block
0
54 endCap(cur);-
55 }
never executed: end of block
0
56 int count = m_vertices.size();-
57-
58 // Copy the (x, y) values because QDataBuffer::add(const float& t)-
59 // may resize the buffer, which will leave t pointing at the-
60 // previous buffer's memory region if we don't copy first.-
61 float x = m_vertices.at(count-2);-
62 float y = m_vertices.at(count-1);-
63 m_vertices.add(x);-
64 m_vertices.add(y);-
65}
never executed: end of block
0
66-
67static inline void skipDuplicatePoints(const qreal **pts, const qreal *endPts)-
68{-
69 while ((*pts + 2) < endPts && float((*pts)[0]) == float((*pts)[2])
(*pts + 2) < endPtsDescription
TRUEnever evaluated
FALSEnever evaluated
float((*pts)[0...oat((*pts)[2])Description
TRUEnever evaluated
FALSEnever evaluated
0
70 && float((*pts)[1]) == float((*pts)[3]))
float((*pts)[1...oat((*pts)[3])Description
TRUEnever evaluated
FALSEnever evaluated
0
71 {-
72 *pts += 2;-
73 }
never executed: end of block
0
74}
never executed: end of block
0
75-
76void QTriangulatingStroker::process(const QVectorPath &path, const QPen &pen, const QRectF &, QPainter::RenderHints hints)-
77{-
78 const qreal *pts = path.points();-
79 const QPainterPath::ElementType *types = path.elements();-
80 int count = path.elementCount();-
81 if (count < 2)
count < 2Description
TRUEnever evaluated
FALSEnever evaluated
0
82 return;
never executed: return;
0
83-
84 float realWidth = qpen_widthf(pen);-
85 if (realWidth == 0)
realWidth == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
86 realWidth = 1;
never executed: realWidth = 1;
0
87-
88 m_width = realWidth / 2;-
89-
90 bool cosmetic = qt_pen_is_cosmetic(pen, hints);-
91 if (cosmetic) {
cosmeticDescription
TRUEnever evaluated
FALSEnever evaluated
0
92 m_width = m_width * m_inv_scale;-
93 }
never executed: end of block
0
94-
95 m_join_style = qpen_joinStyle(pen);-
96 m_cap_style = qpen_capStyle(pen);-
97 m_vertices.reset();-
98 m_miter_limit = pen.miterLimit() * qpen_widthf(pen);-
99-
100 // The curvyness is based on the notion that I originally wanted-
101 // roughly one line segment pr 4 pixels. This may seem little, but-
102 // because we sample at constantly incrementing B(t) E [0<t<1], we-
103 // will get longer segments where the curvature is small and smaller-
104 // segments when the curvature is high.-
105 //-
106 // To get a rough idea of the length of each curve, I pretend that-
107 // the curve is a 90 degree arc, whose radius is-
108 // qMax(curveBounds.width, curveBounds.height). Based on this-
109 // logic we can estimate the length of the outline edges based on-
110 // the radius + a pen width and adjusting for scale factors-
111 // depending on if the pen is cosmetic or not.-
112 //-
113 // The curvyness value of PI/14 was based on,-
114 // arcLength = 2*PI*r/4 = PI*r/2 and splitting length into somewhere-
115 // between 3 and 8 where 5 seemed to be give pretty good results-
116 // hence: Q_PI/14. Lower divisors will give more detail at the-
117 // direct cost of performance.-
118-
119 // simplfy pens that are thin in device size (2px wide or less)-
120 if (realWidth < 2.5 && (cosmetic || m_inv_scale == 1)) {
realWidth < 2.5Description
TRUEnever evaluated
FALSEnever evaluated
cosmeticDescription
TRUEnever evaluated
FALSEnever evaluated
m_inv_scale == 1Description
TRUEnever evaluated
FALSEnever evaluated
0
121 if (m_cap_style == Qt::RoundCap)
m_cap_style == Qt::RoundCapDescription
TRUEnever evaluated
FALSEnever evaluated
0
122 m_cap_style = Qt::SquareCap;
never executed: m_cap_style = Qt::SquareCap;
0
123 if (m_join_style == Qt::RoundJoin)
m_join_style == Qt::RoundJoinDescription
TRUEnever evaluated
FALSEnever evaluated
0
124 m_join_style = Qt::MiterJoin;
never executed: m_join_style = Qt::MiterJoin;
0
125 m_curvyness_add = 0.5;-
126 m_curvyness_mul = CURVE_FLATNESS / m_inv_scale;-
127 m_roundness = 1;-
128 } else if (cosmetic) {
never executed: end of block
cosmeticDescription
TRUEnever evaluated
FALSEnever evaluated
0
129 m_curvyness_add = realWidth / 2;-
130 m_curvyness_mul = float(CURVE_FLATNESS);-
131 m_roundness = qMax<int>(4, realWidth * CURVE_FLATNESS);-
132 } else {
never executed: end of block
0
133 m_curvyness_add = m_width;-
134 m_curvyness_mul = CURVE_FLATNESS / m_inv_scale;-
135 m_roundness = qMax<int>(4, realWidth * m_curvyness_mul);-
136 }
never executed: end of block
0
137-
138 // Over this level of segmentation, there doesn't seem to be any-
139 // benefit, even for huge penWidth-
140 if (m_roundness > 24)
m_roundness > 24Description
TRUEnever evaluated
FALSEnever evaluated
0
141 m_roundness = 24;
never executed: m_roundness = 24;
0
142-
143 m_sin_theta = qFastSin(Q_PI / m_roundness);-
144 m_cos_theta = qFastCos(Q_PI / m_roundness);-
145-
146 const qreal *endPts = pts + (count<<1);-
147 const qreal *startPts = 0;-
148-
149 Qt::PenCapStyle cap = m_cap_style;-
150-
151 if (!types) {
!typesDescription
TRUEnever evaluated
FALSEnever evaluated
0
152 skipDuplicatePoints(&pts, endPts);-
153 if ((pts + 2) == endPts)
(pts + 2) == endPtsDescription
TRUEnever evaluated
FALSEnever evaluated
0
154 return;
never executed: return;
0
155-
156 startPts = pts;-
157-
158 bool endsAtStart = float(startPts[0]) == float(endPts[-2])
float(startPts...at(endPts[-2])Description
TRUEnever evaluated
FALSEnever evaluated
0
159 && float(startPts[1]) == float(endPts[-1]);
float(startPts...at(endPts[-1])Description
TRUEnever evaluated
FALSEnever evaluated
0
160-
161 if (endsAtStart || path.hasImplicitClose())
endsAtStartDescription
TRUEnever evaluated
FALSEnever evaluated
path.hasImplicitClose()Description
TRUEnever evaluated
FALSEnever evaluated
0
162 m_cap_style = Qt::FlatCap;
never executed: m_cap_style = Qt::FlatCap;
0
163 moveTo(pts);-
164 m_cap_style = cap;-
165 pts += 2;-
166 skipDuplicatePoints(&pts, endPts);-
167 lineTo(pts);-
168 pts += 2;-
169 skipDuplicatePoints(&pts, endPts);-
170 while (pts < endPts) {
pts < endPtsDescription
TRUEnever evaluated
FALSEnever evaluated
0
171 join(pts);-
172 lineTo(pts);-
173 pts += 2;-
174 skipDuplicatePoints(&pts, endPts);-
175 }
never executed: end of block
0
176 endCapOrJoinClosed(startPts, pts-2, path.hasImplicitClose(), endsAtStart);-
177-
178 } else {
never executed: end of block
0
179 bool endsAtStart = false;-
180 QPainterPath::ElementType previousType = QPainterPath::MoveToElement;-
181 const qreal *previousPts = pts;-
182 while (pts < endPts) {
pts < endPtsDescription
TRUEnever evaluated
FALSEnever evaluated
0
183 switch (*types) {-
184 case QPainterPath::MoveToElement: {
never executed: case QPainterPath::MoveToElement:
0
185 if (previousType != QPainterPath::MoveToElement)
previousType !...:MoveToElementDescription
TRUEnever evaluated
FALSEnever evaluated
0
186 endCapOrJoinClosed(startPts, previousPts, path.hasImplicitClose(), endsAtStart);
never executed: endCapOrJoinClosed(startPts, previousPts, path.hasImplicitClose(), endsAtStart);
0
187-
188 startPts = pts;-
189 skipDuplicatePoints(&startPts, endPts); // Skip duplicates to find correct normal.-
190 if (startPts + 2 >= endPts)
startPts + 2 >= endPtsDescription
TRUEnever evaluated
FALSEnever evaluated
0
191 return; // Nothing to see here...
never executed: return;
0
192-
193 int end = (endPts - pts) / 2;-
194 int i = 2; // Start looking to ahead since we never have two moveto's in a row-
195 while (i<end && types[i] != QPainterPath::MoveToElement) {
i<endDescription
TRUEnever evaluated
FALSEnever evaluated
types[i] != QP...:MoveToElementDescription
TRUEnever evaluated
FALSEnever evaluated
0
196 ++i;-
197 }
never executed: end of block
0
198 endsAtStart = float(startPts[0]) == float(pts[i*2 - 2])
float(startPts...(pts[i*2 - 2])Description
TRUEnever evaluated
FALSEnever evaluated
0
199 && float(startPts[1]) == float(pts[i*2 - 1]);
float(startPts...(pts[i*2 - 1])Description
TRUEnever evaluated
FALSEnever evaluated
0
200 if (endsAtStart || path.hasImplicitClose())
endsAtStartDescription
TRUEnever evaluated
FALSEnever evaluated
path.hasImplicitClose()Description
TRUEnever evaluated
FALSEnever evaluated
0
201 m_cap_style = Qt::FlatCap;
never executed: m_cap_style = Qt::FlatCap;
0
202-
203 moveTo(startPts);-
204 m_cap_style = cap;-
205 previousType = QPainterPath::MoveToElement;-
206 previousPts = pts;-
207 pts+=2;-
208 ++types;-
209 break; }
never executed: break;
0
210 case QPainterPath::LineToElement:
never executed: case QPainterPath::LineToElement:
0
211 if (float(m_cx) != float(pts[0]) || float(m_cy) != float(pts[1])) {
float(m_cx) != float(pts[0])Description
TRUEnever evaluated
FALSEnever evaluated
float(m_cy) != float(pts[1])Description
TRUEnever evaluated
FALSEnever evaluated
0
212 if (previousType != QPainterPath::MoveToElement)
previousType !...:MoveToElementDescription
TRUEnever evaluated
FALSEnever evaluated
0
213 join(pts);
never executed: join(pts);
0
214 lineTo(pts);-
215 previousType = QPainterPath::LineToElement;-
216 previousPts = pts;-
217 }
never executed: end of block
0
218 pts+=2;-
219 ++types;-
220 break;
never executed: break;
0
221 case QPainterPath::CurveToElement:
never executed: case QPainterPath::CurveToElement:
0
222 if (float(m_cx) != float(pts[0]) || float(m_cy) != float(pts[1])
float(m_cx) != float(pts[0])Description
TRUEnever evaluated
FALSEnever evaluated
float(m_cy) != float(pts[1])Description
TRUEnever evaluated
FALSEnever evaluated
0
223 || float(pts[0]) != float(pts[2]) || float(pts[1]) != float(pts[3])
float(pts[0]) != float(pts[2])Description
TRUEnever evaluated
FALSEnever evaluated
float(pts[1]) != float(pts[3])Description
TRUEnever evaluated
FALSEnever evaluated
0
224 || float(pts[2]) != float(pts[4]) || float(pts[3]) != float(pts[5]))
float(pts[2]) != float(pts[4])Description
TRUEnever evaluated
FALSEnever evaluated
float(pts[3]) != float(pts[5])Description
TRUEnever evaluated
FALSEnever evaluated
0
225 {-
226 if (float(m_cx) != float(pts[0]) || float(m_cy) != float(pts[1])) {
float(m_cx) != float(pts[0])Description
TRUEnever evaluated
FALSEnever evaluated
float(m_cy) != float(pts[1])Description
TRUEnever evaluated
FALSEnever evaluated
0
227 if (previousType != QPainterPath::MoveToElement)
previousType !...:MoveToElementDescription
TRUEnever evaluated
FALSEnever evaluated
0
228 join(pts);
never executed: join(pts);
0
229 }
never executed: end of block
0
230 cubicTo(pts);-
231 previousType = QPainterPath::CurveToElement;-
232 previousPts = pts + 4;-
233 }
never executed: end of block
0
234 pts+=6;-
235 types+=3;-
236 break;
never executed: break;
0
237 default:
never executed: default:
0
238 Q_ASSERT(false);-
239 break;
never executed: break;
0
240 }-
241 }-
242-
243 if (previousType != QPainterPath::MoveToElement)
previousType !...:MoveToElementDescription
TRUEnever evaluated
FALSEnever evaluated
0
244 endCapOrJoinClosed(startPts, previousPts, path.hasImplicitClose(), endsAtStart);
never executed: endCapOrJoinClosed(startPts, previousPts, path.hasImplicitClose(), endsAtStart);
0
245 }
never executed: end of block
0
246}-
247-
248void QTriangulatingStroker::moveTo(const qreal *pts)-
249{-
250 m_cx = pts[0];-
251 m_cy = pts[1];-
252-
253 float x2 = pts[2];-
254 float y2 = pts[3];-
255 normalVector(m_cx, m_cy, x2, y2, &m_nvx, &m_nvy);-
256-
257-
258 // To acheive jumps we insert zero-area tringles. This is done by-
259 // adding two identical points in both the end of previous strip-
260 // and beginning of next strip-
261 bool invisibleJump = m_vertices.size();-
262-
263 switch (m_cap_style) {-
264 case Qt::FlatCap:
never executed: case Qt::FlatCap:
0
265 if (invisibleJump) {
invisibleJumpDescription
TRUEnever evaluated
FALSEnever evaluated
0
266 m_vertices.add(m_cx + m_nvx);-
267 m_vertices.add(m_cy + m_nvy);-
268 }
never executed: end of block
0
269 break;
never executed: break;
0
270 case Qt::SquareCap: {
never executed: case Qt::SquareCap:
0
271 float sx = m_cx - m_nvy;-
272 float sy = m_cy + m_nvx;-
273 if (invisibleJump) {
invisibleJumpDescription
TRUEnever evaluated
FALSEnever evaluated
0
274 m_vertices.add(sx + m_nvx);-
275 m_vertices.add(sy + m_nvy);-
276 }
never executed: end of block
0
277 emitLineSegment(sx, sy, m_nvx, m_nvy);-
278 break; }
never executed: break;
0
279 case Qt::RoundCap: {
never executed: case Qt::RoundCap:
0
280 QVarLengthArray<float> points;-
281 arcPoints(m_cx, m_cy, m_cx + m_nvx, m_cy + m_nvy, m_cx - m_nvx, m_cy - m_nvy, points);-
282 m_vertices.resize(m_vertices.size() + points.size() + 2 * int(invisibleJump));-
283 int count = m_vertices.size();-
284 int front = 0;-
285 int end = points.size() / 2;-
286 while (front != end) {
front != endDescription
TRUEnever evaluated
FALSEnever evaluated
0
287 m_vertices.at(--count) = points[2 * end - 1];-
288 m_vertices.at(--count) = points[2 * end - 2];-
289 --end;-
290 if (front == end)
front == endDescription
TRUEnever evaluated
FALSEnever evaluated
0
291 break;
never executed: break;
0
292 m_vertices.at(--count) = points[2 * front + 1];-
293 m_vertices.at(--count) = points[2 * front + 0];-
294 ++front;-
295 }
never executed: end of block
0
296-
297 if (invisibleJump) {
invisibleJumpDescription
TRUEnever evaluated
FALSEnever evaluated
0
298 m_vertices.at(count - 1) = m_vertices.at(count + 1);-
299 m_vertices.at(count - 2) = m_vertices.at(count + 0);-
300 }
never executed: end of block
0
301 break; }
never executed: break;
0
302 default: break; // ssssh gcc...
never executed: break;
never executed: default:
0
303 }-
304 emitLineSegment(m_cx, m_cy, m_nvx, m_nvy);-
305}
never executed: end of block
0
306-
307void QTriangulatingStroker::cubicTo(const qreal *pts)-
308{-
309 const QPointF *p = (const QPointF *) pts;-
310 QBezier bezier = QBezier::fromPoints(*(p - 1), p[0], p[1], p[2]);-
311-
312 QRectF bounds = bezier.bounds();-
313 float rad = qMax(bounds.width(), bounds.height());-
314 int threshold = qMin<float>(64, (rad + m_curvyness_add) * m_curvyness_mul);-
315 if (threshold < 4)
threshold < 4Description
TRUEnever evaluated
FALSEnever evaluated
0
316 threshold = 4;
never executed: threshold = 4;
0
317 qreal threshold_minus_1 = threshold - 1;-
318 float vx, vy;-
319-
320 float cx = m_cx, cy = m_cy;-
321 float x, y;-
322-
323 for (int i=1; i<threshold; ++i) {
i<thresholdDescription
TRUEnever evaluated
FALSEnever evaluated
0
324 qreal t = qreal(i) / threshold_minus_1;-
325 QPointF p = bezier.pointAt(t);-
326 x = p.x();-
327 y = p.y();-
328-
329 normalVector(cx, cy, x, y, &vx, &vy);-
330-
331 emitLineSegment(x, y, vx, vy);-
332-
333 cx = x;-
334 cy = y;-
335 }
never executed: end of block
0
336-
337 m_cx = cx;-
338 m_cy = cy;-
339-
340 m_nvx = vx;-
341 m_nvy = vy;-
342}
never executed: end of block
0
343-
344void QTriangulatingStroker::join(const qreal *pts)-
345{-
346 // Creates a join to the next segment (m_cx, m_cy) -> (pts[0], pts[1])-
347 normalVector(m_cx, m_cy, pts[0], pts[1], &m_nvx, &m_nvy);-
348-
349 switch (m_join_style) {-
350 case Qt::BevelJoin:
never executed: case Qt::BevelJoin:
0
351 break;
never executed: break;
0
352 case Qt::SvgMiterJoin:
never executed: case Qt::SvgMiterJoin:
0
353 case Qt::MiterJoin: {
never executed: case Qt::MiterJoin:
0
354 // Find out on which side the join should be.-
355 int count = m_vertices.size();-
356 float prevNvx = m_vertices.at(count - 2) - m_cx;-
357 float prevNvy = m_vertices.at(count - 1) - m_cy;-
358 float xprod = prevNvx * m_nvy - prevNvy * m_nvx;-
359 float px, py, qx, qy;-
360-
361 // If the segments are parallel, use bevel join.-
362 if (qFuzzyIsNull(xprod))
qFuzzyIsNull(xprod)Description
TRUEnever evaluated
FALSEnever evaluated
0
363 break;
never executed: break;
0
364-
365 // Find the corners of the previous and next segment to join.-
366 if (xprod < 0) {
xprod < 0Description
TRUEnever evaluated
FALSEnever evaluated
0
367 px = m_vertices.at(count - 2);-
368 py = m_vertices.at(count - 1);-
369 qx = m_cx - m_nvx;-
370 qy = m_cy - m_nvy;-
371 } else {
never executed: end of block
0
372 px = m_vertices.at(count - 4);-
373 py = m_vertices.at(count - 3);-
374 qx = m_cx + m_nvx;-
375 qy = m_cy + m_nvy;-
376 }
never executed: end of block
0
377-
378 // Find intersection point.-
379 float pu = px * prevNvx + py * prevNvy;-
380 float qv = qx * m_nvx + qy * m_nvy;-
381 float ix = (m_nvy * pu - prevNvy * qv) / xprod;-
382 float iy = (prevNvx * qv - m_nvx * pu) / xprod;-
383-
384 // Check that the distance to the intersection point is less than the miter limit.-
385 if ((ix - px) * (ix - px) + (iy - py) * (iy - py) <= m_miter_limit * m_miter_limit) {
(ix - px) * (i... m_miter_limitDescription
TRUEnever evaluated
FALSEnever evaluated
0
386 m_vertices.add(ix);-
387 m_vertices.add(iy);-
388 m_vertices.add(ix);-
389 m_vertices.add(iy);-
390 }
never executed: end of block
0
391 // else-
392 // Do a plain bevel join if the miter limit is exceeded or if-
393 // the lines are parallel. This is not what the raster-
394 // engine's stroker does, but it is both faster and similar to-
395 // what some other graphics API's do.-
396-
397 break; }
never executed: break;
0
398 case Qt::RoundJoin: {
never executed: case Qt::RoundJoin:
0
399 QVarLengthArray<float> points;-
400 int count = m_vertices.size();-
401 float prevNvx = m_vertices.at(count - 2) - m_cx;-
402 float prevNvy = m_vertices.at(count - 1) - m_cy;-
403 if (m_nvx * prevNvy - m_nvy * prevNvx < 0) {
m_nvx * prevNv... * prevNvx < 0Description
TRUEnever evaluated
FALSEnever evaluated
0
404 arcPoints(0, 0, m_nvx, m_nvy, -prevNvx, -prevNvy, points);-
405 for (int i = points.size() / 2; i > 0; --i)
i > 0Description
TRUEnever evaluated
FALSEnever evaluated
0
406 emitLineSegment(m_cx, m_cy, points[2 * i - 2], points[2 * i - 1]);
never executed: emitLineSegment(m_cx, m_cy, points[2 * i - 2], points[2 * i - 1]);
0
407 } else {
never executed: end of block
0
408 arcPoints(0, 0, -prevNvx, -prevNvy, m_nvx, m_nvy, points);-
409 for (int i = 0; i < points.size() / 2; ++i)
i < points.size() / 2Description
TRUEnever evaluated
FALSEnever evaluated
0
410 emitLineSegment(m_cx, m_cy, points[2 * i + 0], points[2 * i + 1]);
never executed: emitLineSegment(m_cx, m_cy, points[2 * i + 0], points[2 * i + 1]);
0
411 }
never executed: end of block
0
412 break; }
never executed: break;
0
413 default: break; // gcc warn--
never executed: break;
never executed: default:
0
414 }-
415-
416 emitLineSegment(m_cx, m_cy, m_nvx, m_nvy);-
417}
never executed: end of block
0
418-
419void QTriangulatingStroker::endCap(const qreal *)-
420{-
421 switch (m_cap_style) {-
422 case Qt::FlatCap:
never executed: case Qt::FlatCap:
0
423 break;
never executed: break;
0
424 case Qt::SquareCap:
never executed: case Qt::SquareCap:
0
425 emitLineSegment(m_cx + m_nvy, m_cy - m_nvx, m_nvx, m_nvy);-
426 break;
never executed: break;
0
427 case Qt::RoundCap: {
never executed: case Qt::RoundCap:
0
428 QVarLengthArray<float> points;-
429 int count = m_vertices.size();-
430 arcPoints(m_cx, m_cy, m_vertices.at(count - 2), m_vertices.at(count - 1), m_vertices.at(count - 4), m_vertices.at(count - 3), points);-
431 int front = 0;-
432 int end = points.size() / 2;-
433 while (front != end) {
front != endDescription
TRUEnever evaluated
FALSEnever evaluated
0
434 m_vertices.add(points[2 * end - 2]);-
435 m_vertices.add(points[2 * end - 1]);-
436 --end;-
437 if (front == end)
front == endDescription
TRUEnever evaluated
FALSEnever evaluated
0
438 break;
never executed: break;
0
439 m_vertices.add(points[2 * front + 0]);-
440 m_vertices.add(points[2 * front + 1]);-
441 ++front;-
442 }
never executed: end of block
0
443 break; }
never executed: break;
0
444 default: break; // to shut gcc up...
never executed: break;
never executed: default:
0
445 }-
446}-
447-
448void QTriangulatingStroker::arcPoints(float cx, float cy, float fromX, float fromY, float toX, float toY, QVarLengthArray<float> &points)-
449{-
450 float dx1 = fromX - cx;-
451 float dy1 = fromY - cy;-
452 float dx2 = toX - cx;-
453 float dy2 = toY - cy;-
454-
455 // while more than 180 degrees left:-
456 while (dx1 * dy2 - dx2 * dy1 < 0) {
dx1 * dy2 - dx2 * dy1 < 0Description
TRUEnever evaluated
FALSEnever evaluated
0
457 float tmpx = dx1 * m_cos_theta - dy1 * m_sin_theta;-
458 float tmpy = dx1 * m_sin_theta + dy1 * m_cos_theta;-
459 dx1 = tmpx;-
460 dy1 = tmpy;-
461 points.append(cx + dx1);-
462 points.append(cy + dy1);-
463 }
never executed: end of block
0
464-
465 // while more than 90 degrees left:-
466 while (dx1 * dx2 + dy1 * dy2 < 0) {
dx1 * dx2 + dy1 * dy2 < 0Description
TRUEnever evaluated
FALSEnever evaluated
0
467 float tmpx = dx1 * m_cos_theta - dy1 * m_sin_theta;-
468 float tmpy = dx1 * m_sin_theta + dy1 * m_cos_theta;-
469 dx1 = tmpx;-
470 dy1 = tmpy;-
471 points.append(cx + dx1);-
472 points.append(cy + dy1);-
473 }
never executed: end of block
0
474-
475 // while more than 0 degrees left:-
476 while (dx1 * dy2 - dx2 * dy1 > 0) {
dx1 * dy2 - dx2 * dy1 > 0Description
TRUEnever evaluated
FALSEnever evaluated
0
477 float tmpx = dx1 * m_cos_theta - dy1 * m_sin_theta;-
478 float tmpy = dx1 * m_sin_theta + dy1 * m_cos_theta;-
479 dx1 = tmpx;-
480 dy1 = tmpy;-
481 points.append(cx + dx1);-
482 points.append(cy + dy1);-
483 }
never executed: end of block
0
484-
485 // remove last point which was rotated beyond [toX, toY].-
486 if (!points.isEmpty())
!points.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
487 points.resize(points.size() - 2);
never executed: points.resize(points.size() - 2);
0
488}
never executed: end of block
0
489-
490static void qdashprocessor_moveTo(qreal x, qreal y, void *data)-
491{-
492 ((QDashedStrokeProcessor *) data)->addElement(QPainterPath::MoveToElement, x, y);-
493}
never executed: end of block
0
494-
495static void qdashprocessor_lineTo(qreal x, qreal y, void *data)-
496{-
497 ((QDashedStrokeProcessor *) data)->addElement(QPainterPath::LineToElement, x, y);-
498}
never executed: end of block
0
499-
500static void qdashprocessor_cubicTo(qreal, qreal, qreal, qreal, qreal, qreal, void *)-
501{-
502 Q_ASSERT(0); // The dasher should not produce curves...-
503}
never executed: end of block
0
504-
505QDashedStrokeProcessor::QDashedStrokeProcessor()-
506 : m_points(0), m_types(0),-
507 m_dash_stroker(0), m_inv_scale(1)-
508{-
509 m_dash_stroker.setMoveToHook(qdashprocessor_moveTo);-
510 m_dash_stroker.setLineToHook(qdashprocessor_lineTo);-
511 m_dash_stroker.setCubicToHook(qdashprocessor_cubicTo);-
512}
never executed: end of block
0
513-
514void QDashedStrokeProcessor::process(const QVectorPath &path, const QPen &pen, const QRectF &clip, QPainter::RenderHints hints)-
515{-
516-
517 const qreal *pts = path.points();-
518 const QPainterPath::ElementType *types = path.elements();-
519 int count = path.elementCount();-
520-
521 bool cosmetic = qt_pen_is_cosmetic(pen, hints);-
522-
523 m_points.reset();-
524 m_types.reset();-
525 m_points.reserve(path.elementCount());-
526 m_types.reserve(path.elementCount());-
527-
528 qreal width = qpen_widthf(pen);-
529 if (width == 0)
width == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
530 width = 1;
never executed: width = 1;
0
531-
532 m_dash_stroker.setDashPattern(pen.dashPattern());-
533 m_dash_stroker.setStrokeWidth(cosmetic ? width * m_inv_scale : width);-
534 m_dash_stroker.setDashOffset(pen.dashOffset());-
535 m_dash_stroker.setMiterLimit(pen.miterLimit());-
536 m_dash_stroker.setClipRect(clip);-
537-
538 float curvynessAdd, curvynessMul;-
539-
540 // simplify pens that are thin in device size (2px wide or less)-
541 if (width < 2.5 && (cosmetic || m_inv_scale == 1)) {
width < 2.5Description
TRUEnever evaluated
FALSEnever evaluated
cosmeticDescription
TRUEnever evaluated
FALSEnever evaluated
m_inv_scale == 1Description
TRUEnever evaluated
FALSEnever evaluated
0
542 curvynessAdd = 0.5;-
543 curvynessMul = CURVE_FLATNESS / m_inv_scale;-
544 } else if (cosmetic) {
never executed: end of block
cosmeticDescription
TRUEnever evaluated
FALSEnever evaluated
0
545 curvynessAdd= width / 2;-
546 curvynessMul= float(CURVE_FLATNESS);-
547 } else {
never executed: end of block
0
548 curvynessAdd = width * m_inv_scale;-
549 curvynessMul = CURVE_FLATNESS / m_inv_scale;-
550 }
never executed: end of block
0
551-
552 if (count < 2)
count < 2Description
TRUEnever evaluated
FALSEnever evaluated
0
553 return;
never executed: return;
0
554-
555 const qreal *endPts = pts + (count<<1);-
556-
557 m_dash_stroker.begin(this);-
558-
559 if (!types) {
!typesDescription
TRUEnever evaluated
FALSEnever evaluated
0
560 m_dash_stroker.moveTo(pts[0], pts[1]);-
561 pts += 2;-
562 while (pts < endPts) {
pts < endPtsDescription
TRUEnever evaluated
FALSEnever evaluated
0
563 m_dash_stroker.lineTo(pts[0], pts[1]);-
564 pts += 2;-
565 }
never executed: end of block
0
566 } else {
never executed: end of block
0
567 while (pts < endPts) {
pts < endPtsDescription
TRUEnever evaluated
FALSEnever evaluated
0
568 switch (*types) {-
569 case QPainterPath::MoveToElement:
never executed: case QPainterPath::MoveToElement:
0
570 m_dash_stroker.moveTo(pts[0], pts[1]);-
571 pts += 2;-
572 ++types;-
573 break;
never executed: break;
0
574 case QPainterPath::LineToElement:
never executed: case QPainterPath::LineToElement:
0
575 m_dash_stroker.lineTo(pts[0], pts[1]);-
576 pts += 2;-
577 ++types;-
578 break;
never executed: break;
0
579 case QPainterPath::CurveToElement: {
never executed: case QPainterPath::CurveToElement:
0
580 QBezier b = QBezier::fromPoints(*(((const QPointF *) pts) - 1),-
581 *(((const QPointF *) pts)),-
582 *(((const QPointF *) pts) + 1),-
583 *(((const QPointF *) pts) + 2));-
584 QRectF bounds = b.bounds();-
585 float rad = qMax(bounds.width(), bounds.height());-
586 int threshold = qMin<float>(64, (rad + curvynessAdd) * curvynessMul);-
587 if (threshold < 4)
threshold < 4Description
TRUEnever evaluated
FALSEnever evaluated
0
588 threshold = 4;
never executed: threshold = 4;
0
589-
590 qreal threshold_minus_1 = threshold - 1;-
591 for (int i=0; i<threshold; ++i) {
i<thresholdDescription
TRUEnever evaluated
FALSEnever evaluated
0
592 QPointF pt = b.pointAt(i / threshold_minus_1);-
593 m_dash_stroker.lineTo(pt.x(), pt.y());-
594 }
never executed: end of block
0
595 pts += 6;-
596 types += 3;-
597 break; }
never executed: break;
0
598 default: break;
never executed: break;
never executed: default:
0
599 }-
600 }-
601 }
never executed: end of block
0
602-
603 m_dash_stroker.end();-
604}
never executed: end of block
0
605-
606QT_END_NAMESPACE-
607-
Source codeSwitch to Preprocessed file

Generated by Squish Coco Non-Commercial 4.3.0-BETA-master-30-08-2018-4cb69e9