qcosmeticstroker.cpp

Absolute File Name:/home/qt/qt5_coco/qt5/qtbase/src/gui/painting/qcosmeticstroker.cpp
Source codeSwitch to Preprocessed file
LineSourceCount
1/****************************************************************************-
2**-
3** Copyright (C) 2016 The Qt Company Ltd.-
4** Contact: https://www.qt.io/licensing/-
5**-
6** This file is part of the QtGui module of the Qt Toolkit.-
7**-
8** $QT_BEGIN_LICENSE:LGPL$-
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 https://www.qt.io/terms-conditions. For further-
15** information use the contact form at https://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 3 as published by the Free Software-
20** Foundation and appearing in the file LICENSE.LGPL3 included in the-
21** packaging of this file. Please review the following information to-
22** ensure the GNU Lesser General Public License version 3 requirements-
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.-
24**-
25** GNU General Public License Usage-
26** Alternatively, this file may be used under the terms of the GNU-
27** General Public License version 2.0 or (at your option) the GNU General-
28** Public license version 3 or any later version approved by the KDE Free-
29** Qt Foundation. The licenses are as published by the Free Software-
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3-
31** included in the packaging of this file. Please review the following-
32** information to ensure the GNU General Public License requirements will-
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and-
34** https://www.gnu.org/licenses/gpl-3.0.html.-
35**-
36** $QT_END_LICENSE$-
37**-
38****************************************************************************/-
39-
40#include "qcosmeticstroker_p.h"-
41#include "private/qpainterpath_p.h"-
42#include "private/qrgba64_p.h"-
43#include <qdebug.h>-
44-
45QT_BEGIN_NAMESPACE-
46-
47#if 0-
48inline QString capString(int caps)-
49{-
50 QString str;-
51 if (caps & QCosmeticStroker::CapBegin) {-
52 str += "CapBegin ";-
53 }-
54 if (caps & QCosmeticStroker::CapEnd) {-
55 str += "CapEnd ";-
56 }-
57 return str;-
58}-
59#endif-
60-
61#define toF26Dot6(x) ((int)((x)*64.))-
62-
63static inline uint sourceOver(uint d, uint color)-
64{-
65 return color + BYTE_MUL(d, qAlpha(~color));
never executed: return color + BYTE_MUL(d, qAlpha(~color));
0
66}-
67-
68inline static int F16Dot16FixedDiv(int x, int y)-
69{-
70 if (qAbs(x) > 0x7fff)
qAbs(x) > 0x7fffDescription
TRUEnever evaluated
FALSEnever evaluated
0
71 return qlonglong(x) * (1<<16) / y;
never executed: return qlonglong(x) * (1<<16) / y;
0
72 return x * (1<<16) / y;
never executed: return x * (1<<16) / y;
0
73}-
74-
75typedef void (*DrawPixel)(QCosmeticStroker *stroker, int x, int y, int coverage);-
76-
77namespace {-
78-
79struct Dasher {-
80 QCosmeticStroker *stroker;-
81 int *pattern;-
82 int offset;-
83 int dashIndex;-
84 int dashOn;-
85-
86 Dasher(QCosmeticStroker *s, bool reverse, int start, int stop)-
87 : stroker(s)-
88 {-
89 int delta = stop - start;-
90 if (reverse) {
reverseDescription
TRUEnever evaluated
FALSEnever evaluated
0
91 pattern = stroker->reversePattern;-
92 offset = stroker->patternLength - stroker->patternOffset - delta - ((start & 63) - 32);-
93 dashOn = 0;-
94 } else {
never executed: end of block
0
95 pattern = stroker->pattern;-
96 offset = stroker->patternOffset - ((start & 63) - 32);-
97 dashOn = 1;-
98 }
never executed: end of block
0
99 offset %= stroker->patternLength;-
100 if (offset < 0)
offset < 0Description
TRUEnever evaluated
FALSEnever evaluated
0
101 offset += stroker->patternLength;
never executed: offset += stroker->patternLength;
0
102-
103 dashIndex = 0;-
104 while (offset>= pattern[dashIndex])
offset>= pattern[dashIndex]Description
TRUEnever evaluated
FALSEnever evaluated
0
105 ++dashIndex;
never executed: ++dashIndex;
0
106-
107// qDebug() << " dasher" << offset/64. << reverse << dashIndex;-
108 stroker->patternOffset += delta;-
109 stroker->patternOffset %= stroker->patternLength;-
110 }
never executed: end of block
0
111-
112 bool on() const {-
113 return (dashIndex + dashOn) & 1;
never executed: return (dashIndex + dashOn) & 1;
0
114 }-
115 void adjust() {-
116 offset += 64;-
117 if (offset >= pattern[dashIndex]) {
offset >= pattern[dashIndex]Description
TRUEnever evaluated
FALSEnever evaluated
0
118 ++dashIndex;-
119 dashIndex %= stroker->patternSize;-
120 }
never executed: end of block
0
121 offset %= stroker->patternLength;-
122// qDebug() << "dasher.adjust" << offset/64. << dashIndex;-
123 }
never executed: end of block
0
124};-
125-
126struct NoDasher {-
127 NoDasher(QCosmeticStroker *, bool, int, int) {}-
128 bool on() const { return true; }
never executed: return true;
0
129 void adjust(int = 0) {}-
130};-
131-
132};-
133-
134/*-
135 * The return value is the result of the clipLine() call performed at the start-
136 * of each of the two functions, aka "false" means completely outside the devices-
137 * rect.-
138 */-
139template<DrawPixel drawPixel, class Dasher>-
140static bool drawLine(QCosmeticStroker *stroker, qreal x1, qreal y1, qreal x2, qreal y2, int caps);-
141template<DrawPixel drawPixel, class Dasher>-
142static bool drawLineAA(QCosmeticStroker *stroker, qreal x1, qreal y1, qreal x2, qreal y2, int caps);-
143-
144inline void drawPixel(QCosmeticStroker *stroker, int x, int y, int coverage)-
145{-
146 const QRect &cl = stroker->clip;-
147 if (x < cl.x() || x > cl.right() || y < cl.y() || y > cl.bottom())
x < cl.x()Description
TRUEnever evaluated
FALSEnever evaluated
x > cl.right()Description
TRUEnever evaluated
FALSEnever evaluated
y < cl.y()Description
TRUEnever evaluated
FALSEnever evaluated
y > cl.bottom()Description
TRUEnever evaluated
FALSEnever evaluated
0
148 return;
never executed: return;
0
149-
150 if (stroker->current_span > 0) {
stroker->current_span > 0Description
TRUEnever evaluated
FALSEnever evaluated
0
151 const int lastx = stroker->spans[stroker->current_span-1].x + stroker->spans[stroker->current_span-1].len ;-
152 const int lasty = stroker->spans[stroker->current_span-1].y;-
153-
154 if (stroker->current_span == QCosmeticStroker::NSPANS || y < lasty || (y == lasty && x < lastx)) {
stroker->curre...troker::NSPANSDescription
TRUEnever evaluated
FALSEnever evaluated
y < lastyDescription
TRUEnever evaluated
FALSEnever evaluated
y == lastyDescription
TRUEnever evaluated
FALSEnever evaluated
x < lastxDescription
TRUEnever evaluated
FALSEnever evaluated
0
155 stroker->blend(stroker->current_span, stroker->spans, &stroker->state->penData);-
156 stroker->current_span = 0;-
157 }
never executed: end of block
0
158 }
never executed: end of block
0
159-
160 stroker->spans[stroker->current_span].x = ushort(x);-
161 stroker->spans[stroker->current_span].len = 1;-
162 stroker->spans[stroker->current_span].y = y;-
163 stroker->spans[stroker->current_span].coverage = coverage*stroker->opacity >> 8;-
164 ++stroker->current_span;-
165}
never executed: end of block
0
166-
167inline void drawPixelARGB32(QCosmeticStroker *stroker, int x, int y, int coverage)-
168{-
169 const QRect &cl = stroker->clip;-
170 if (x < cl.x() || x > cl.right() || y < cl.y() || y > cl.bottom())
x < cl.x()Description
TRUEnever evaluated
FALSEnever evaluated
x > cl.right()Description
TRUEnever evaluated
FALSEnever evaluated
y < cl.y()Description
TRUEnever evaluated
FALSEnever evaluated
y > cl.bottom()Description
TRUEnever evaluated
FALSEnever evaluated
0
171 return;
never executed: return;
0
172-
173 int offset = x + stroker->ppl*y;-
174 uint c = BYTE_MUL(stroker->color, coverage);-
175 stroker->pixels[offset] = sourceOver(stroker->pixels[offset], c);-
176}
never executed: end of block
0
177-
178inline void drawPixelARGB32Opaque(QCosmeticStroker *stroker, int x, int y, int)-
179{-
180 const QRect &cl = stroker->clip;-
181 if (x < cl.x() || x > cl.right() || y < cl.y() || y > cl.bottom())
x < cl.x()Description
TRUEnever evaluated
FALSEnever evaluated
x > cl.right()Description
TRUEnever evaluated
FALSEnever evaluated
y < cl.y()Description
TRUEnever evaluated
FALSEnever evaluated
y > cl.bottom()Description
TRUEnever evaluated
FALSEnever evaluated
0
182 return;
never executed: return;
0
183-
184 int offset = x + stroker->ppl*y;-
185 stroker->pixels[offset] = sourceOver(stroker->pixels[offset], stroker->color);-
186}
never executed: end of block
0
187-
188enum StrokeSelection {-
189 Aliased = 0,-
190 AntiAliased = 1,-
191 Solid = 0,-
192 Dashed = 2,-
193 RegularDraw = 0,-
194 FastDraw = 4-
195};-
196-
197static StrokeLine strokeLine(int strokeSelection)-
198{-
199 StrokeLine stroke;-
200-
201 switch (strokeSelection) {-
202 case Aliased|Solid|RegularDraw:
never executed: case Aliased|Solid|RegularDraw:
0
203 stroke = &QT_PREPEND_NAMESPACE(drawLine)<drawPixel, NoDasher>;-
204 break;
never executed: break;
0
205 case Aliased|Solid|FastDraw:
never executed: case Aliased|Solid|FastDraw:
0
206 stroke = &QT_PREPEND_NAMESPACE(drawLine)<drawPixelARGB32Opaque, NoDasher>;-
207 break;
never executed: break;
0
208 case Aliased|Dashed|RegularDraw:
never executed: case Aliased|Dashed|RegularDraw:
0
209 stroke = &QT_PREPEND_NAMESPACE(drawLine)<drawPixel, Dasher>;-
210 break;
never executed: break;
0
211 case Aliased|Dashed|FastDraw:
never executed: case Aliased|Dashed|FastDraw:
0
212 stroke = &QT_PREPEND_NAMESPACE(drawLine)<drawPixelARGB32Opaque, Dasher>;-
213 break;
never executed: break;
0
214 case AntiAliased|Solid|RegularDraw:
never executed: case AntiAliased|Solid|RegularDraw:
0
215 stroke = &QT_PREPEND_NAMESPACE(drawLineAA)<drawPixel, NoDasher>;-
216 break;
never executed: break;
0
217 case AntiAliased|Solid|FastDraw:
never executed: case AntiAliased|Solid|FastDraw:
0
218 stroke = &QT_PREPEND_NAMESPACE(drawLineAA)<drawPixelARGB32, NoDasher>;-
219 break;
never executed: break;
0
220 case AntiAliased|Dashed|RegularDraw:
never executed: case AntiAliased|Dashed|RegularDraw:
0
221 stroke = &QT_PREPEND_NAMESPACE(drawLineAA)<drawPixel, Dasher>;-
222 break;
never executed: break;
0
223 case AntiAliased|Dashed|FastDraw:
never executed: case AntiAliased|Dashed|FastDraw:
0
224 stroke = &QT_PREPEND_NAMESPACE(drawLineAA)<drawPixelARGB32, Dasher>;-
225 break;
never executed: break;
0
226 default:
never executed: default:
0
227 Q_ASSERT(false);-
228 stroke = 0;-
229 }
never executed: end of block
0
230 return stroke;
never executed: return stroke;
0
231}-
232-
233void QCosmeticStroker::setup()-
234{-
235 blend = state->penData.blend;-
236 if (state->clip && state->clip->enabled && state->clip->hasRectClip && !state->clip->clipRect.isEmpty()) {
state->clipDescription
TRUEnever evaluated
FALSEnever evaluated
state->clip->enabledDescription
TRUEnever evaluated
FALSEnever evaluated
state->clip->hasRectClipDescription
TRUEnever evaluated
FALSEnever evaluated
!state->clip->...Rect.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
237 clip &= state->clip->clipRect;-
238 blend = state->penData.unclipped_blend;-
239 }
never executed: end of block
0
240-
241 int strokeSelection = 0;-
242 if (blend == state->penData.unclipped_blend
blend == state...nclipped_blendDescription
TRUEnever evaluated
FALSEnever evaluated
0
243 && state->penData.type == QSpanData::Solid
state->penData...panData::SolidDescription
TRUEnever evaluated
FALSEnever evaluated
0
244 && (state->penData.rasterBuffer->format == QImage::Format_ARGB32_Premultiplied
state->penData..._PremultipliedDescription
TRUEnever evaluated
FALSEnever evaluated
0
245 || state->penData.rasterBuffer->format == QImage::Format_RGB32)
state->penData...::Format_RGB32Description
TRUEnever evaluated
FALSEnever evaluated
0
246 && state->compositionMode() == QPainter::CompositionMode_SourceOver)
state->composi...ode_SourceOverDescription
TRUEnever evaluated
FALSEnever evaluated
0
247 strokeSelection |= FastDraw;
never executed: strokeSelection |= FastDraw;
0
248-
249 if (state->renderHints & QPainter::Antialiasing)
state->renderH...::AntialiasingDescription
TRUEnever evaluated
FALSEnever evaluated
0
250 strokeSelection |= AntiAliased;
never executed: strokeSelection |= AntiAliased;
0
251-
252 const QVector<qreal> &penPattern = state->lastPen.dashPattern();-
253 if (penPattern.isEmpty()) {
penPattern.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
254 Q_ASSERT(!pattern && !reversePattern);-
255 pattern = 0;-
256 reversePattern = 0;-
257 patternLength = 0;-
258 patternSize = 0;-
259 } else {
never executed: end of block
0
260 pattern = (int *)malloc(penPattern.size()*sizeof(int));-
261 reversePattern = (int *)malloc(penPattern.size()*sizeof(int));-
262 patternSize = penPattern.size();-
263-
264 patternLength = 0;-
265 for (int i = 0; i < patternSize; ++i) {
i < patternSizeDescription
TRUEnever evaluated
FALSEnever evaluated
0
266 patternLength += (int) qMax(1. , penPattern.at(i)*64.);-
267 pattern[i] = patternLength;-
268 }
never executed: end of block
0
269 patternLength = 0;-
270 for (int i = 0; i < patternSize; ++i) {
i < patternSizeDescription
TRUEnever evaluated
FALSEnever evaluated
0
271 patternLength += (int) qMax(1., penPattern.at(patternSize - 1 - i)*64.);-
272 reversePattern[i] = patternLength;-
273 }
never executed: end of block
0
274 strokeSelection |= Dashed;-
275// qDebug() << "setup: size=" << patternSize << "length=" << patternLength/64.;-
276 }
never executed: end of block
0
277-
278 stroke = strokeLine(strokeSelection);-
279-
280 qreal width = state->lastPen.widthF();-
281 if (width == 0)
width == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
282 opacity = 256;
never executed: opacity = 256;
0
283 else if (qt_pen_is_cosmetic(state->lastPen, state->renderHints))
qt_pen_is_cosm...->renderHints)Description
TRUEnever evaluated
FALSEnever evaluated
0
284 opacity = (int) 256*width;
never executed: opacity = (int) 256*width;
0
285 else-
286 opacity = (int) 256*width*state->txscale;
never executed: opacity = (int) 256*width*state->txscale;
0
287 opacity = qBound(0, opacity, 256);-
288-
289 drawCaps = state->lastPen.capStyle() != Qt::FlatCap;-
290-
291 if (strokeSelection & FastDraw) {
strokeSelection & FastDrawDescription
TRUEnever evaluated
FALSEnever evaluated
0
292 color = multiplyAlpha256(state->penData.solid.color, opacity).toArgb32();-
293 QRasterBuffer *buffer = state->penData.rasterBuffer;-
294 pixels = (uint *)buffer->buffer();-
295 ppl = buffer->bytesPerLine()>>2;-
296 }
never executed: end of block
0
297-
298 // line drawing produces different results with different clips, so-
299 // we need to clip consistently when painting to the same device-
300-
301 // setup FP clip bounds-
302 xmin = deviceRect.left() - 1;-
303 xmax = deviceRect.right() + 2;-
304 ymin = deviceRect.top() - 1;-
305 ymax = deviceRect.bottom() + 2;-
306-
307 lastPixel.x = -1;-
308 lastPixel.y = -1;-
309}
never executed: end of block
0
310-
311// returns true if the whole line gets clipped away-
312bool QCosmeticStroker::clipLine(qreal &x1, qreal &y1, qreal &x2, qreal &y2)-
313{-
314 // basic/rough clipping is done in floating point coordinates to avoid-
315 // integer overflow problems.-
316 if (x1 < xmin) {
x1 < xminDescription
TRUEnever evaluated
FALSEnever evaluated
0
317 if (x2 <= xmin)
x2 <= xminDescription
TRUEnever evaluated
FALSEnever evaluated
0
318 goto clipped;
never executed: goto clipped;
0
319 y1 += (y2 - y1)/(x2 - x1) * (xmin - x1);-
320 x1 = xmin;-
321 } else if (x1 > xmax) {
never executed: end of block
x1 > xmaxDescription
TRUEnever evaluated
FALSEnever evaluated
0
322 if (x2 >= xmax)
x2 >= xmaxDescription
TRUEnever evaluated
FALSEnever evaluated
0
323 goto clipped;
never executed: goto clipped;
0
324 y1 += (y2 - y1)/(x2 - x1) * (xmax - x1);-
325 x1 = xmax;-
326 }
never executed: end of block
0
327 if (x2 < xmin) {
x2 < xminDescription
TRUEnever evaluated
FALSEnever evaluated
0
328 lastPixel.x = -1;-
329 y2 += (y2 - y1)/(x2 - x1) * (xmin - x2);-
330 x2 = xmin;-
331 } else if (x2 > xmax) {
never executed: end of block
x2 > xmaxDescription
TRUEnever evaluated
FALSEnever evaluated
0
332 lastPixel.x = -1;-
333 y2 += (y2 - y1)/(x2 - x1) * (xmax - x2);-
334 x2 = xmax;-
335 }
never executed: end of block
0
336-
337 if (y1 < ymin) {
y1 < yminDescription
TRUEnever evaluated
FALSEnever evaluated
0
338 if (y2 <= ymin)
y2 <= yminDescription
TRUEnever evaluated
FALSEnever evaluated
0
339 goto clipped;
never executed: goto clipped;
0
340 x1 += (x2 - x1)/(y2 - y1) * (ymin - y1);-
341 y1 = ymin;-
342 } else if (y1 > ymax) {
never executed: end of block
y1 > ymaxDescription
TRUEnever evaluated
FALSEnever evaluated
0
343 if (y2 >= ymax)
y2 >= ymaxDescription
TRUEnever evaluated
FALSEnever evaluated
0
344 goto clipped;
never executed: goto clipped;
0
345 x1 += (x2 - x1)/(y2 - y1) * (ymax - y1);-
346 y1 = ymax;-
347 }
never executed: end of block
0
348 if (y2 < ymin) {
y2 < yminDescription
TRUEnever evaluated
FALSEnever evaluated
0
349 lastPixel.x = -1;-
350 x2 += (x2 - x1)/(y2 - y1) * (ymin - y2);-
351 y2 = ymin;-
352 } else if (y2 > ymax) {
never executed: end of block
y2 > ymaxDescription
TRUEnever evaluated
FALSEnever evaluated
0
353 lastPixel.x = -1;-
354 x2 += (x2 - x1)/(y2 - y1) * (ymax - y2);-
355 y2 = ymax;-
356 }
never executed: end of block
0
357-
358 return false;
never executed: return false;
0
359-
360 clipped:-
361 lastPixel.x = -1;-
362 return true;
never executed: return true;
0
363}-
364-
365-
366void QCosmeticStroker::drawLine(const QPointF &p1, const QPointF &p2)-
367{-
368 if (p1 == p2) {
p1 == p2Description
TRUEnever evaluated
FALSEnever evaluated
0
369 drawPoints(&p1, 1);-
370 return;
never executed: return;
0
371 }-
372-
373 QPointF start = p1 * state->matrix;-
374 QPointF end = p2 * state->matrix;-
375-
376 patternOffset = state->lastPen.dashOffset()*64;-
377 lastPixel.x = -1;-
378-
379 stroke(this, start.x(), start.y(), end.x(), end.y(), drawCaps ? CapBegin|CapEnd : 0);-
380-
381 blend(current_span, spans, &state->penData);-
382 current_span = 0;-
383}
never executed: end of block
0
384-
385void QCosmeticStroker::drawPoints(const QPoint *points, int num)-
386{-
387 const QPoint *end = points + num;-
388 while (points < end) {
points < endDescription
TRUEnever evaluated
FALSEnever evaluated
0
389 QPointF p = QPointF(*points) * state->matrix;-
390 drawPixel(this, qRound(p.x()), qRound(p.y()), 255);-
391 ++points;-
392 }
never executed: end of block
0
393-
394 blend(current_span, spans, &state->penData);-
395 current_span = 0;-
396}
never executed: end of block
0
397-
398void QCosmeticStroker::drawPoints(const QPointF *points, int num)-
399{-
400 const QPointF *end = points + num;-
401 while (points < end) {
points < endDescription
TRUEnever evaluated
FALSEnever evaluated
0
402 QPointF p = (*points) * state->matrix;-
403 drawPixel(this, qRound(p.x()), qRound(p.y()), 255);-
404 ++points;-
405 }
never executed: end of block
0
406-
407 blend(current_span, spans, &state->penData);-
408 current_span = 0;-
409}
never executed: end of block
0
410-
411void QCosmeticStroker::calculateLastPoint(qreal rx1, qreal ry1, qreal rx2, qreal ry2)-
412{-
413 // this is basically the same code as used in the aliased stroke method,-
414 // but it only determines the direction and last point of a line-
415 //-
416 // This is being used to have proper dropout control for closed contours-
417 // by calculating the direction and last pixel of the last segment in the contour.-
418 // the info is then used to perform dropout control when drawing the first line segment-
419 // of the contour-
420 lastPixel.x = -1;-
421 lastPixel.y = -1;-
422-
423 if (clipLine(rx1, ry1, rx2, ry2))
clipLine(rx1, ry1, rx2, ry2)Description
TRUEnever evaluated
FALSEnever evaluated
0
424 return;
never executed: return;
0
425-
426 const int half = legacyRounding ? 31 : 0;
legacyRoundingDescription
TRUEnever evaluated
FALSEnever evaluated
0
427 int x1 = toF26Dot6(rx1) + half;-
428 int y1 = toF26Dot6(ry1) + half;-
429 int x2 = toF26Dot6(rx2) + half;-
430 int y2 = toF26Dot6(ry2) + half;-
431-
432 int dx = qAbs(x2 - x1);-
433 int dy = qAbs(y2 - y1);-
434-
435 if (dx < dy) {
dx < dyDescription
TRUEnever evaluated
FALSEnever evaluated
0
436 // vertical-
437 bool swapped = false;-
438 if (y1 > y2) {
y1 > y2Description
TRUEnever evaluated
FALSEnever evaluated
0
439 swapped = true;-
440 qSwap(y1, y2);-
441 qSwap(x1, x2);-
442 }
never executed: end of block
0
443 int xinc = F16Dot16FixedDiv(x2 - x1, y2 - y1);-
444 int x = x1 * (1<<10);-
445-
446 int y = (y1 + 32) >> 6;-
447 int ys = (y2 + 32) >> 6;-
448-
449 int round = (xinc > 0) ? 32 : 0;
(xinc > 0)Description
TRUEnever evaluated
FALSEnever evaluated
0
450 if (y != ys) {
y != ysDescription
TRUEnever evaluated
FALSEnever evaluated
0
451 x += ((y * (1<<6)) + round - y1) * xinc >> 6;-
452-
453 if (swapped) {
swappedDescription
TRUEnever evaluated
FALSEnever evaluated
0
454 lastPixel.x = x >> 16;-
455 lastPixel.y = y;-
456 lastDir = QCosmeticStroker::BottomToTop;-
457 } else {
never executed: end of block
0
458 lastPixel.x = (x + (ys - y - 1)*xinc) >> 16;-
459 lastPixel.y = ys - 1;-
460 lastDir = QCosmeticStroker::TopToBottom;-
461 }
never executed: end of block
0
462 lastAxisAligned = qAbs(xinc) < (1 << 14);-
463 }
never executed: end of block
0
464 } else {
never executed: end of block
0
465 // horizontal-
466 if (!dx)
!dxDescription
TRUEnever evaluated
FALSEnever evaluated
0
467 return;
never executed: return;
0
468-
469 bool swapped = false;-
470 if (x1 > x2) {
x1 > x2Description
TRUEnever evaluated
FALSEnever evaluated
0
471 swapped = true;-
472 qSwap(x1, x2);-
473 qSwap(y1, y2);-
474 }
never executed: end of block
0
475 int yinc = F16Dot16FixedDiv(y2 - y1, x2 - x1);-
476 int y = y1 << 10;-
477-
478 int x = (x1 + 32) >> 6;-
479 int xs = (x2 + 32) >> 6;-
480-
481 int round = (yinc > 0) ? 32 : 0;
(yinc > 0)Description
TRUEnever evaluated
FALSEnever evaluated
0
482 if (x != xs) {
x != xsDescription
TRUEnever evaluated
FALSEnever evaluated
0
483 y += ((x * (1<<6)) + round - x1) * yinc >> 6;-
484-
485 if (swapped) {
swappedDescription
TRUEnever evaluated
FALSEnever evaluated
0
486 lastPixel.x = x;-
487 lastPixel.y = y >> 16;-
488 lastDir = QCosmeticStroker::RightToLeft;-
489 } else {
never executed: end of block
0
490 lastPixel.x = xs - 1;-
491 lastPixel.y = (y + (xs - x - 1)*yinc) >> 16;-
492 lastDir = QCosmeticStroker::LeftToRight;-
493 }
never executed: end of block
0
494 lastAxisAligned = qAbs(yinc) < (1 << 14);-
495 }
never executed: end of block
0
496 }
never executed: end of block
0
497// qDebug() << " moveTo: setting last pixel to x/y dir" << lastPixel.x << lastPixel.y << lastDir;-
498}-
499-
500static inline const QPainterPath::ElementType *subPath(const QPainterPath::ElementType *t, const QPainterPath::ElementType *end,-
501 const qreal *points, bool *closed)-
502{-
503 const QPainterPath::ElementType *start = t;-
504 ++t;-
505-
506 // find out if the subpath is closed-
507 while (t < end) {
t < endDescription
TRUEnever evaluated
FALSEnever evaluated
0
508 if (*t == QPainterPath::MoveToElement)
*t == QPainter...:MoveToElementDescription
TRUEnever evaluated
FALSEnever evaluated
0
509 break;
never executed: break;
0
510 ++t;-
511 }
never executed: end of block
0
512-
513 int offset = t - start - 1;-
514// qDebug() << "subpath" << offset << points[0] << points[1] << points[2*offset] << points[2*offset+1];-
515 *closed = (points[0] == points[2*offset] && points[1] == points[2*offset + 1]);
points[0] == points[2*offset]Description
TRUEnever evaluated
FALSEnever evaluated
points[1] == p...[2*offset + 1]Description
TRUEnever evaluated
FALSEnever evaluated
0
516-
517 return t;
never executed: return t;
0
518}-
519-
520void QCosmeticStroker::drawPath(const QVectorPath &path)-
521{-
522// qDebug() << ">>>> drawpath" << path.convertToPainterPath()-
523// << "antialiasing:" << (bool)(state->renderHints & QPainter::Antialiasing) << " implicit close:" << path.hasImplicitClose();-
524 if (path.isEmpty())
path.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
525 return;
never executed: return;
0
526-
527 const qreal *points = path.points();-
528 const QPainterPath::ElementType *type = path.elements();-
529-
530 if (type) {
typeDescription
TRUEnever evaluated
FALSEnever evaluated
0
531 const QPainterPath::ElementType *end = type + path.elementCount();-
532-
533 while (type < end) {
type < endDescription
TRUEnever evaluated
FALSEnever evaluated
0
534 Q_ASSERT(type == path.elements() || *type == QPainterPath::MoveToElement);-
535-
536 QPointF p = QPointF(points[0], points[1]) * state->matrix;-
537 patternOffset = state->lastPen.dashOffset()*64;-
538 lastPixel.x = INT_MIN;-
539 lastPixel.y = INT_MIN;-
540-
541 bool closed;-
542 const QPainterPath::ElementType *e = subPath(type, end, points, &closed);-
543 if (closed) {
closedDescription
TRUEnever evaluated
FALSEnever evaluated
0
544 const qreal *p = points + 2*(e-type);-
545 QPointF p1 = QPointF(p[-4], p[-3]) * state->matrix;-
546 QPointF p2 = QPointF(p[-2], p[-1]) * state->matrix;-
547 calculateLastPoint(p1.x(), p1.y(), p2.x(), p2.y());-
548 }
never executed: end of block
0
549 int caps = (!closed && drawCaps) ? CapBegin : NoCaps;
!closedDescription
TRUEnever evaluated
FALSEnever evaluated
drawCapsDescription
TRUEnever evaluated
FALSEnever evaluated
0
550// qDebug() << "closed =" << closed << capString(caps);-
551-
552 points += 2;-
553 ++type;-
554-
555 while (type < e) {
type < eDescription
TRUEnever evaluated
FALSEnever evaluated
0
556 QPointF p2 = QPointF(points[0], points[1]) * state->matrix;-
557 switch (*type) {-
558 case QPainterPath::MoveToElement:
never executed: case QPainterPath::MoveToElement:
0
559 Q_ASSERT(!"Logic error");-
560 break;
never executed: break;
0
561-
562 case QPainterPath::LineToElement:
never executed: case QPainterPath::LineToElement:
0
563 if (!closed && drawCaps && type == e - 1)
!closedDescription
TRUEnever evaluated
FALSEnever evaluated
drawCapsDescription
TRUEnever evaluated
FALSEnever evaluated
type == e - 1Description
TRUEnever evaluated
FALSEnever evaluated
0
564 caps |= CapEnd;
never executed: caps |= CapEnd;
0
565 stroke(this, p.x(), p.y(), p2.x(), p2.y(), caps);-
566 p = p2;-
567 points += 2;-
568 ++type;-
569 break;
never executed: break;
0
570-
571 case QPainterPath::CurveToElement: {
never executed: case QPainterPath::CurveToElement:
0
572 if (!closed && drawCaps && type == e - 3)
!closedDescription
TRUEnever evaluated
FALSEnever evaluated
drawCapsDescription
TRUEnever evaluated
FALSEnever evaluated
type == e - 3Description
TRUEnever evaluated
FALSEnever evaluated
0
573 caps |= CapEnd;
never executed: caps |= CapEnd;
0
574 QPointF p3 = QPointF(points[2], points[3]) * state->matrix;-
575 QPointF p4 = QPointF(points[4], points[5]) * state->matrix;-
576 renderCubic(p, p2, p3, p4, caps);-
577 p = p4;-
578 type += 3;-
579 points += 6;-
580 break;
never executed: break;
0
581 }-
582 case QPainterPath::CurveToDataElement:
never executed: case QPainterPath::CurveToDataElement:
0
583 Q_ASSERT(!"QPainterPath::toSubpathPolygons(), bad element type");-
584 break;
never executed: break;
0
585 }-
586 caps = NoCaps;-
587 }
never executed: end of block
0
588 }
never executed: end of block
0
589 } else { // !type, simple polygon
never executed: end of block
0
590 QPointF p = QPointF(points[0], points[1]) * state->matrix;-
591 QPointF movedTo = p;-
592 patternOffset = state->lastPen.dashOffset()*64;-
593 lastPixel.x = INT_MIN;-
594 lastPixel.y = INT_MIN;-
595-
596 const qreal *begin = points;-
597 const qreal *end = points + 2*path.elementCount();-
598 // handle closed path case-
599 bool closed = path.hasImplicitClose() || (points[0] == end[-2] && points[1] == end[-1]);
path.hasImplicitClose()Description
TRUEnever evaluated
FALSEnever evaluated
points[0] == end[-2]Description
TRUEnever evaluated
FALSEnever evaluated
points[1] == end[-1]Description
TRUEnever evaluated
FALSEnever evaluated
0
600 int caps = (!closed && drawCaps) ? CapBegin : NoCaps;
!closedDescription
TRUEnever evaluated
FALSEnever evaluated
drawCapsDescription
TRUEnever evaluated
FALSEnever evaluated
0
601 if (closed) {
closedDescription
TRUEnever evaluated
FALSEnever evaluated
0
602 QPointF p2 = QPointF(end[-2], end[-1]) * state->matrix;-
603 calculateLastPoint(p2.x(), p2.y(), p.x(), p.y());-
604 }
never executed: end of block
0
605-
606 bool fastPenAliased = (state->flags.fast_pen && !state->flags.antialiased);
state->flags.fast_penDescription
TRUEnever evaluated
FALSEnever evaluated
!state->flags.antialiasedDescription
TRUEnever evaluated
FALSEnever evaluated
0
607 points += 2;-
608 while (points < end) {
points < endDescription
TRUEnever evaluated
FALSEnever evaluated
0
609 QPointF p2 = QPointF(points[0], points[1]) * state->matrix;-
610-
611 if (!closed && drawCaps && points == end - 2)
!closedDescription
TRUEnever evaluated
FALSEnever evaluated
drawCapsDescription
TRUEnever evaluated
FALSEnever evaluated
points == end - 2Description
TRUEnever evaluated
FALSEnever evaluated
0
612 caps |= CapEnd;
never executed: caps |= CapEnd;
0
613-
614 bool moveNextStart = stroke(this, p.x(), p.y(), p2.x(), p2.y(), caps);-
615-
616 /* fix for gaps in polylines with fastpen and aliased in a sequence-
617 of points with small distances: if current point p2 has been dropped-
618 out, keep last non dropped point p.-
619-
620 However, if the line was completely outside the devicerect, we-
621 still need to update p to avoid drawing the line after this one from-
622 a bad starting position.-
623 */-
624 if (!fastPenAliased || moveNextStart || points == begin + 2 || points == end - 2)
!fastPenAliasedDescription
TRUEnever evaluated
FALSEnever evaluated
moveNextStartDescription
TRUEnever evaluated
FALSEnever evaluated
points == begin + 2Description
TRUEnever evaluated
FALSEnever evaluated
points == end - 2Description
TRUEnever evaluated
FALSEnever evaluated
0
625 p = p2;
never executed: p = p2;
0
626 points += 2;-
627 caps = NoCaps;-
628 }
never executed: end of block
0
629 if (path.hasImplicitClose())
path.hasImplicitClose()Description
TRUEnever evaluated
FALSEnever evaluated
0
630 stroke(this, p.x(), p.y(), movedTo.x(), movedTo.y(), NoCaps);
never executed: stroke(this, p.x(), p.y(), movedTo.x(), movedTo.y(), NoCaps);
0
631 }
never executed: end of block
0
632-
633-
634 blend(current_span, spans, &state->penData);-
635 current_span = 0;-
636}
never executed: end of block
0
637-
638void QCosmeticStroker::renderCubic(const QPointF &p1, const QPointF &p2, const QPointF &p3, const QPointF &p4, int caps)-
639{-
640// qDebug() << ">>>> renderCubic" << p1 << p2 << p3 << p4 << capString(caps);-
641 const int maxSubDivisions = 6;-
642 PointF points[3*maxSubDivisions + 4];-
643-
644 points[3].x = p1.x();-
645 points[3].y = p1.y();-
646 points[2].x = p2.x();-
647 points[2].y = p2.y();-
648 points[1].x = p3.x();-
649 points[1].y = p3.y();-
650 points[0].x = p4.x();-
651 points[0].y = p4.y();-
652-
653 PointF *p = points;-
654 int level = maxSubDivisions;-
655-
656 renderCubicSubdivision(p, level, caps);-
657}
never executed: end of block
0
658-
659static void splitCubic(QCosmeticStroker::PointF *points)-
660{-
661 const qreal half = .5;-
662 qreal a, b, c, d;-
663-
664 points[6].x = points[3].x;-
665 c = points[1].x;-
666 d = points[2].x;-
667 points[1].x = a = ( points[0].x + c ) * half;-
668 points[5].x = b = ( points[3].x + d ) * half;-
669 c = ( c + d ) * half;-
670 points[2].x = a = ( a + c ) * half;-
671 points[4].x = b = ( b + c ) * half;-
672 points[3].x = ( a + b ) * half;-
673-
674 points[6].y = points[3].y;-
675 c = points[1].y;-
676 d = points[2].y;-
677 points[1].y = a = ( points[0].y + c ) * half;-
678 points[5].y = b = ( points[3].y + d ) * half;-
679 c = ( c + d ) * half;-
680 points[2].y = a = ( a + c ) * half;-
681 points[4].y = b = ( b + c ) * half;-
682 points[3].y = ( a + b ) * half;-
683}
never executed: end of block
0
684-
685void QCosmeticStroker::renderCubicSubdivision(QCosmeticStroker::PointF *points, int level, int caps)-
686{-
687 if (level) {
levelDescription
TRUEnever evaluated
FALSEnever evaluated
0
688 qreal dx = points[3].x - points[0].x;-
689 qreal dy = points[3].y - points[0].y;-
690 qreal len = ((qreal).25) * (qAbs(dx) + qAbs(dy));-
691-
692 if (qAbs(dx * (points[0].y - points[2].y) - dy * (points[0].x - points[2].x)) >= len ||
qAbs(dx * (poi...[2].x)) >= lenDescription
TRUEnever evaluated
FALSEnever evaluated
0
693 qAbs(dx * (points[0].y - points[1].y) - dy * (points[0].x - points[1].x)) >= len) {
qAbs(dx * (poi...[1].x)) >= lenDescription
TRUEnever evaluated
FALSEnever evaluated
0
694 splitCubic(points);-
695-
696 --level;-
697 renderCubicSubdivision(points + 3, level, caps & CapBegin);-
698 renderCubicSubdivision(points, level, caps & CapEnd);-
699 return;
never executed: return;
0
700 }-
701 }
never executed: end of block
0
702-
703 stroke(this, points[3].x, points[3].y, points[0].x, points[0].y, caps);-
704}
never executed: end of block
0
705-
706static inline int swapCaps(int caps)-
707{-
708 return ((caps & QCosmeticStroker::CapBegin) << 1) |
never executed: return ((caps & QCosmeticStroker::CapBegin) << 1) | ((caps & QCosmeticStroker::CapEnd) >> 1);
0
709 ((caps & QCosmeticStroker::CapEnd) >> 1);
never executed: return ((caps & QCosmeticStroker::CapBegin) << 1) | ((caps & QCosmeticStroker::CapEnd) >> 1);
0
710}-
711-
712// adjust line by half a pixel-
713static inline void capAdjust(int caps, int &x1, int &x2, int &y, int yinc)-
714{-
715 if (caps & QCosmeticStroker::CapBegin) {
caps & QCosmet...oker::CapBeginDescription
TRUEnever evaluated
FALSEnever evaluated
0
716 x1 -= 32;-
717 y -= yinc >> 1;-
718 }
never executed: end of block
0
719 if (caps & QCosmeticStroker::CapEnd) {
caps & QCosmet...troker::CapEndDescription
TRUEnever evaluated
FALSEnever evaluated
0
720 x2 += 32;-
721 }
never executed: end of block
0
722}
never executed: end of block
0
723-
724/*-
725 The hard part about this is dropout control and avoiding douple drawing of points when-
726 the drawing shifts from horizontal to vertical or back.-
727 */-
728template<DrawPixel drawPixel, class Dasher>-
729static bool drawLine(QCosmeticStroker *stroker, qreal rx1, qreal ry1, qreal rx2, qreal ry2, int caps)-
730{-
731 bool didDraw = qAbs(rx2 - rx1) + qAbs(ry2 - ry1) >= 1.0;-
732-
733 if (stroker->clipLine(rx1, ry1, rx2, ry2))
stroker->clipL...ry1, rx2, ry2)Description
TRUEnever evaluated
FALSEnever evaluated
0
734 return true;
never executed: return true;
0
735-
736 const int half = stroker->legacyRounding ? 31 : 0;-
737 int x1 = toF26Dot6(rx1) + half;-
738 int y1 = toF26Dot6(ry1) + half;-
739 int x2 = toF26Dot6(rx2) + half;-
740 int y2 = toF26Dot6(ry2) + half;-
741-
742 int dx = qAbs(x2 - x1);-
743 int dy = qAbs(y2 - y1);-
744-
745 QCosmeticStroker::Point last = stroker->lastPixel;-
746-
747// qDebug() << "stroke" << x1/64. << y1/64. << x2/64. << y2/64.;-
748-
749 if (dx < dy) {
dx < dyDescription
TRUEnever evaluated
FALSEnever evaluated
0
750 // vertical-
751 QCosmeticStroker::Direction dir = QCosmeticStroker::TopToBottom;-
752-
753 bool swapped = false;-
754 if (y1 > y2) {
y1 > y2Description
TRUEnever evaluated
FALSEnever evaluated
0
755 swapped = true;-
756 qSwap(y1, y2);-
757 qSwap(x1, x2);-
758 caps = swapCaps(caps);-
759 dir = QCosmeticStroker::BottomToTop;-
760 }
never executed: end of block
0
761 int xinc = F16Dot16FixedDiv(x2 - x1, y2 - y1);-
762 int x = x1 * (1<<10);-
763-
764 if ((stroker->lastDir ^ QCosmeticStroker::VerticalMask) == dir)
(stroker->last...alMask) == dirDescription
TRUEnever evaluated
FALSEnever evaluated
0
765 caps |= swapped ? QCosmeticStroker::CapEnd : QCosmeticStroker::CapBegin;
never executed: caps |= swapped ? QCosmeticStroker::CapEnd : QCosmeticStroker::CapBegin;
swappedDescription
TRUEnever evaluated
FALSEnever evaluated
0
766-
767 capAdjust(caps, y1, y2, x, xinc);-
768-
769 int y = (y1 + 32) >> 6;-
770 int ys = (y2 + 32) >> 6;-
771 int round = (xinc > 0) ? 32 : 0;
(xinc > 0)Description
TRUEnever evaluated
FALSEnever evaluated
0
772-
773 if (y != ys) {
y != ysDescription
TRUEnever evaluated
FALSEnever evaluated
0
774 x += ((y * (1<<6)) + round - y1) * xinc >> 6;-
775-
776 // calculate first and last pixel and perform dropout control-
777 QCosmeticStroker::Point first;-
778 first.x = x >> 16;-
779 first.y = y;-
780 last.x = (x + (ys - y - 1)*xinc) >> 16;-
781 last.y = ys - 1;-
782 if (swapped)
swappedDescription
TRUEnever evaluated
FALSEnever evaluated
0
783 qSwap(first, last);
never executed: qSwap(first, last);
0
784-
785 bool axisAligned = qAbs(xinc) < (1 << 14);-
786 if (stroker->lastPixel.x >= 0) {
stroker->lastPixel.x >= 0Description
TRUEnever evaluated
FALSEnever evaluated
0
787 if (first.x == stroker->lastPixel.x &&
first.x == str...r->lastPixel.xDescription
TRUEnever evaluated
FALSEnever evaluated
0
788 first.y == stroker->lastPixel.y) {
first.y == str...r->lastPixel.yDescription
TRUEnever evaluated
FALSEnever evaluated
0
789 // remove duplicated pixel-
790 if (swapped) {
swappedDescription
TRUEnever evaluated
FALSEnever evaluated
0
791 --ys;-
792 } else {
never executed: end of block
0
793 ++y;-
794 x += xinc;-
795 }
never executed: end of block
0
796 } else if (stroker->lastDir != dir &&
stroker->lastDir != dirDescription
TRUEnever evaluated
FALSEnever evaluated
0
797 (((axisAligned && stroker->lastAxisAligned) &&
axisAlignedDescription
TRUEnever evaluated
FALSEnever evaluated
stroker->lastAxisAlignedDescription
TRUEnever evaluated
FALSEnever evaluated
0
798 stroker->lastPixel.x != first.x && stroker->lastPixel.y != first.y) ||
stroker->lastP...l.x != first.xDescription
TRUEnever evaluated
FALSEnever evaluated
stroker->lastP...l.y != first.yDescription
TRUEnever evaluated
FALSEnever evaluated
0
799 (qAbs(stroker->lastPixel.x - first.x) > 1 ||
qAbs(stroker->...- first.x) > 1Description
TRUEnever evaluated
FALSEnever evaluated
0
800 qAbs(stroker->lastPixel.y - first.y) > 1))) {
qAbs(stroker->...- first.y) > 1Description
TRUEnever evaluated
FALSEnever evaluated
0
801 // have a missing pixel, insert it-
802 if (swapped) {
swappedDescription
TRUEnever evaluated
FALSEnever evaluated
0
803 ++ys;-
804 } else {
never executed: end of block
0
805 --y;-
806 x -= xinc;-
807 }
never executed: end of block
0
808 }-
809 }
never executed: end of block
0
810 stroker->lastDir = dir;-
811 stroker->lastAxisAligned = axisAligned;-
812-
813 Dasher dasher(stroker, swapped, y * (1<<6), ys * (1<<6));-
814-
815 do {-
816 if (dasher.on())
dasher.on()Description
TRUEnever evaluated
FALSEnever evaluated
0
817 drawPixel(stroker, x >> 16, y, 255);
never executed: drawPixel(stroker, x >> 16, y, 255);
0
818 dasher.adjust();-
819 x += xinc;-
820 } while (++y < ys);
never executed: end of block
++y < ysDescription
TRUEnever evaluated
FALSEnever evaluated
0
821 didDraw = true;-
822 }
never executed: end of block
0
823 } else {
never executed: end of block
0
824 // horizontal-
825 if (!dx)
!dxDescription
TRUEnever evaluated
FALSEnever evaluated
0
826 return true;
never executed: return true;
0
827-
828 QCosmeticStroker::Direction dir = QCosmeticStroker::LeftToRight;-
829-
830 bool swapped = false;-
831 if (x1 > x2) {
x1 > x2Description
TRUEnever evaluated
FALSEnever evaluated
0
832 swapped = true;-
833 qSwap(x1, x2);-
834 qSwap(y1, y2);-
835 caps = swapCaps(caps);-
836 dir = QCosmeticStroker::RightToLeft;-
837 }
never executed: end of block
0
838 int yinc = F16Dot16FixedDiv(y2 - y1, x2 - x1);-
839 int y = y1 * (1<<10);-
840-
841 if ((stroker->lastDir ^ QCosmeticStroker::HorizontalMask) == dir)
(stroker->last...alMask) == dirDescription
TRUEnever evaluated
FALSEnever evaluated
0
842 caps |= swapped ? QCosmeticStroker::CapEnd : QCosmeticStroker::CapBegin;
never executed: caps |= swapped ? QCosmeticStroker::CapEnd : QCosmeticStroker::CapBegin;
swappedDescription
TRUEnever evaluated
FALSEnever evaluated
0
843-
844 capAdjust(caps, x1, x2, y, yinc);-
845-
846 int x = (x1 + 32) >> 6;-
847 int xs = (x2 + 32) >> 6;-
848 int round = (yinc > 0) ? 32 : 0;
(yinc > 0)Description
TRUEnever evaluated
FALSEnever evaluated
0
849-
850 if (x != xs) {
x != xsDescription
TRUEnever evaluated
FALSEnever evaluated
0
851 y += ((x * (1<<6)) + round - x1) * yinc >> 6;-
852-
853 // calculate first and last pixel to perform dropout control-
854 QCosmeticStroker::Point first;-
855 first.x = x;-
856 first.y = y >> 16;-
857 last.x = xs - 1;-
858 last.y = (y + (xs - x - 1)*yinc) >> 16;-
859 if (swapped)
swappedDescription
TRUEnever evaluated
FALSEnever evaluated
0
860 qSwap(first, last);
never executed: qSwap(first, last);
0
861-
862 bool axisAligned = qAbs(yinc) < (1 << 14);-
863 if (stroker->lastPixel.x >= 0) {
stroker->lastPixel.x >= 0Description
TRUEnever evaluated
FALSEnever evaluated
0
864 if (first.x == stroker->lastPixel.x && first.y == stroker->lastPixel.y) {
first.x == str...r->lastPixel.xDescription
TRUEnever evaluated
FALSEnever evaluated
first.y == str...r->lastPixel.yDescription
TRUEnever evaluated
FALSEnever evaluated
0
865 // remove duplicated pixel-
866 if (swapped) {
swappedDescription
TRUEnever evaluated
FALSEnever evaluated
0
867 --xs;-
868 } else {
never executed: end of block
0
869 ++x;-
870 y += yinc;-
871 }
never executed: end of block
0
872 } else if (stroker->lastDir != dir &&
stroker->lastDir != dirDescription
TRUEnever evaluated
FALSEnever evaluated
0
873 (((axisAligned && stroker->lastAxisAligned) &&
axisAlignedDescription
TRUEnever evaluated
FALSEnever evaluated
stroker->lastAxisAlignedDescription
TRUEnever evaluated
FALSEnever evaluated
0
874 stroker->lastPixel.x != first.x && stroker->lastPixel.y != first.y) ||
stroker->lastP...l.x != first.xDescription
TRUEnever evaluated
FALSEnever evaluated
stroker->lastP...l.y != first.yDescription
TRUEnever evaluated
FALSEnever evaluated
0
875 (qAbs(stroker->lastPixel.x - first.x) > 1 ||
qAbs(stroker->...- first.x) > 1Description
TRUEnever evaluated
FALSEnever evaluated
0
876 qAbs(stroker->lastPixel.y - first.y) > 1))) {
qAbs(stroker->...- first.y) > 1Description
TRUEnever evaluated
FALSEnever evaluated
0
877 // have a missing pixel, insert it-
878 if (swapped) {
swappedDescription
TRUEnever evaluated
FALSEnever evaluated
0
879 ++xs;-
880 } else {
never executed: end of block
0
881 --x;-
882 y -= yinc;-
883 }
never executed: end of block
0
884 }-
885 }
never executed: end of block
0
886 stroker->lastDir = dir;-
887 stroker->lastAxisAligned = axisAligned;-
888-
889 Dasher dasher(stroker, swapped, x * (1<<6), xs * (1<<6));-
890-
891 do {-
892 if (dasher.on())
dasher.on()Description
TRUEnever evaluated
FALSEnever evaluated
0
893 drawPixel(stroker, x, y >> 16, 255);
never executed: drawPixel(stroker, x, y >> 16, 255);
0
894 dasher.adjust();-
895 y += yinc;-
896 } while (++x < xs);
never executed: end of block
++x < xsDescription
TRUEnever evaluated
FALSEnever evaluated
0
897 didDraw = true;-
898 }
never executed: end of block
0
899 }
never executed: end of block
0
900 stroker->lastPixel = last;-
901 return didDraw;
never executed: return didDraw;
0
902}-
903-
904-
905template<DrawPixel drawPixel, class Dasher>-
906static bool drawLineAA(QCosmeticStroker *stroker, qreal rx1, qreal ry1, qreal rx2, qreal ry2, int caps)-
907{-
908 if (stroker->clipLine(rx1, ry1, rx2, ry2))
stroker->clipL...ry1, rx2, ry2)Description
TRUEnever evaluated
FALSEnever evaluated
0
909 return true;
never executed: return true;
0
910-
911 int x1 = toF26Dot6(rx1);-
912 int y1 = toF26Dot6(ry1);-
913 int x2 = toF26Dot6(rx2);-
914 int y2 = toF26Dot6(ry2);-
915-
916 int dx = x2 - x1;-
917 int dy = y2 - y1;-
918-
919 if (qAbs(dx) < qAbs(dy)) {
qAbs(dx) < qAbs(dy)Description
TRUEnever evaluated
FALSEnever evaluated
0
920 // vertical-
921-
922 int xinc = F16Dot16FixedDiv(dx, dy);-
923-
924 bool swapped = false;-
925 if (y1 > y2) {
y1 > y2Description
TRUEnever evaluated
FALSEnever evaluated
0
926 qSwap(y1, y2);-
927 qSwap(x1, x2);-
928 swapped = true;-
929 caps = swapCaps(caps);-
930 }
never executed: end of block
0
931-
932 int x = (x1 - 32) * (1<<10);-
933 x -= ( ((y1 & 63) - 32) * xinc ) >> 6;-
934-
935 capAdjust(caps, y1, y2, x, xinc);-
936-
937 Dasher dasher(stroker, swapped, y1, y2);-
938-
939 int y = y1 >> 6;-
940 int ys = y2 >> 6;-
941-
942 int alphaStart, alphaEnd;-
943 if (y == ys) {
y == ysDescription
TRUEnever evaluated
FALSEnever evaluated
0
944 alphaStart = y2 - y1;-
945 Q_ASSERT(alphaStart >= 0 && alphaStart < 64);-
946 alphaEnd = 0;-
947 } else {
never executed: end of block
0
948 alphaStart = 64 - (y1 & 63);-
949 alphaEnd = (y2 & 63);-
950 }
never executed: end of block
0
951// qDebug() << "vertical" << x1/64. << y1/64. << x2/64. << y2/64.;-
952// qDebug() << " x=" << x << "dx=" << dx << "xi=" << (x>>16) << "xsi=" << ((x+(ys-y)*dx)>>16) << "y=" << y << "ys=" << ys;-
953-
954 // draw first pixel-
955 if (dasher.on()) {
dasher.on()Description
TRUEnever evaluated
FALSEnever evaluated
0
956 uint alpha = (quint8)(x >> 8);-
957 drawPixel(stroker, x>>16, y, (255-alpha) * alphaStart >> 6);-
958 drawPixel(stroker, (x>>16) + 1, y, alpha * alphaStart >> 6);-
959 }
never executed: end of block
0
960 dasher.adjust();-
961 x += xinc;-
962 ++y;-
963 if (y < ys) {
y < ysDescription
TRUEnever evaluated
FALSEnever evaluated
0
964 do {-
965 if (dasher.on()) {
dasher.on()Description
TRUEnever evaluated
FALSEnever evaluated
0
966 uint alpha = (quint8)(x >> 8);-
967 drawPixel(stroker, x>>16, y, (255-alpha));-
968 drawPixel(stroker, (x>>16) + 1, y, alpha);-
969 }
never executed: end of block
0
970 dasher.adjust();-
971 x += xinc;-
972 } while (++y < ys);
never executed: end of block
++y < ysDescription
TRUEnever evaluated
FALSEnever evaluated
0
973 }
never executed: end of block
0
974 // draw last pixel-
975 if (alphaEnd && dasher.on()) {
alphaEndDescription
TRUEnever evaluated
FALSEnever evaluated
dasher.on()Description
TRUEnever evaluated
FALSEnever evaluated
0
976 uint alpha = (quint8)(x >> 8);-
977 drawPixel(stroker, x>>16, y, (255-alpha) * alphaEnd >> 6);-
978 drawPixel(stroker, (x>>16) + 1, y, alpha * alphaEnd >> 6);-
979 }
never executed: end of block
0
980 } else {
never executed: end of block
0
981 // horizontal-
982 if (!dx)
!dxDescription
TRUEnever evaluated
FALSEnever evaluated
0
983 return true;
never executed: return true;
0
984-
985 int yinc = F16Dot16FixedDiv(dy, dx);-
986-
987 bool swapped = false;-
988 if (x1 > x2) {
x1 > x2Description
TRUEnever evaluated
FALSEnever evaluated
0
989 qSwap(x1, x2);-
990 qSwap(y1, y2);-
991 swapped = true;-
992 caps = swapCaps(caps);-
993 }
never executed: end of block
0
994-
995 int y = (y1 - 32) * (1<<10);-
996 y -= ( ((x1 & 63) - 32) * yinc ) >> 6;-
997-
998 capAdjust(caps, x1, x2, y, yinc);-
999-
1000 Dasher dasher(stroker, swapped, x1, x2);-
1001-
1002 int x = x1 >> 6;-
1003 int xs = x2 >> 6;-
1004-
1005// qDebug() << "horizontal" << x1/64. << y1/64. << x2/64. << y2/64.;-
1006// qDebug() << " y=" << y << "dy=" << dy << "x=" << x << "xs=" << xs << "yi=" << (y>>16) << "ysi=" << ((y+(xs-x)*dy)>>16);-
1007 int alphaStart, alphaEnd;-
1008 if (x == xs) {
x == xsDescription
TRUEnever evaluated
FALSEnever evaluated
0
1009 alphaStart = x2 - x1;-
1010 Q_ASSERT(alphaStart >= 0 && alphaStart < 64);-
1011 alphaEnd = 0;-
1012 } else {
never executed: end of block
0
1013 alphaStart = 64 - (x1 & 63);-
1014 alphaEnd = (x2 & 63);-
1015 }
never executed: end of block
0
1016-
1017 // draw first pixel-
1018 if (dasher.on()) {
dasher.on()Description
TRUEnever evaluated
FALSEnever evaluated
0
1019 uint alpha = (quint8)(y >> 8);-
1020 drawPixel(stroker, x, y>>16, (255-alpha) * alphaStart >> 6);-
1021 drawPixel(stroker, x, (y>>16) + 1, alpha * alphaStart >> 6);-
1022 }
never executed: end of block
0
1023 dasher.adjust();-
1024 y += yinc;-
1025 ++x;-
1026 // draw line-
1027 if (x < xs) {
x < xsDescription
TRUEnever evaluated
FALSEnever evaluated
0
1028 do {-
1029 if (dasher.on()) {
dasher.on()Description
TRUEnever evaluated
FALSEnever evaluated
0
1030 uint alpha = (quint8)(y >> 8);-
1031 drawPixel(stroker, x, y>>16, (255-alpha));-
1032 drawPixel(stroker, x, (y>>16) + 1, alpha);-
1033 }
never executed: end of block
0
1034 dasher.adjust();-
1035 y += yinc;-
1036 } while (++x < xs);
never executed: end of block
++x < xsDescription
TRUEnever evaluated
FALSEnever evaluated
0
1037 }
never executed: end of block
0
1038 // draw last pixel-
1039 if (alphaEnd && dasher.on()) {
alphaEndDescription
TRUEnever evaluated
FALSEnever evaluated
dasher.on()Description
TRUEnever evaluated
FALSEnever evaluated
0
1040 uint alpha = (quint8)(y >> 8);-
1041 drawPixel(stroker, x, y>>16, (255-alpha) * alphaEnd >> 6);-
1042 drawPixel(stroker, x, (y>>16) + 1, alpha * alphaEnd >> 6);-
1043 }
never executed: end of block
0
1044 }
never executed: end of block
0
1045 return true;
never executed: return true;
0
1046}-
1047-
1048QT_END_NAMESPACE-
Source codeSwitch to Preprocessed file

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