qcosmeticstroker.cpp

Absolute File Name:/home/qt/qt5_coco/qt5/qtbase/src/gui/painting/qcosmeticstroker.cpp
Switch to Source codePreprocessed file
LineSourceCount
1-
2-
3static inline uint sourceOver(uint d, uint color)-
4{-
5 return color + BYTE_MUL(d, qAlpha(~color));-
6}-
7-
8inline static int F16Dot16FixedDiv(int x, int y)-
9{-
10 if (qAbs(x) > 0x7fff)-
11 return qlonglong(x) * (1<<16) / y;-
12 return x * (1<<16) / y;-
13}-
14-
15typedef void (*DrawPixel)(QCosmeticStroker *stroker, int x, int y, int coverage);-
16-
17namespace {-
18-
19struct Dasher {-
20 QCosmeticStroker *stroker;-
21 int *pattern;-
22 int offset;-
23 int dashIndex;-
24 int dashOn;-
25-
26 Dasher(QCosmeticStroker *s, bool reverse, int start, int stop)-
27 : stroker(s)-
28 {-
29 int delta = stop - start;-
30 if (reverse) {-
31 pattern = stroker->reversePattern;-
32 offset = stroker->patternLength - stroker->patternOffset - delta - ((start & 63) - 32);-
33 dashOn = 0;-
34 } else {-
35 pattern = stroker->pattern;-
36 offset = stroker->patternOffset - ((start & 63) - 32);-
37 dashOn = 1;-
38 }-
39 offset %= stroker->patternLength;-
40 if (offset < 0)-
41 offset += stroker->patternLength;-
42-
43 dashIndex = 0;-
44 while (offset>= pattern[dashIndex])-
45 ++dashIndex;-
46-
47-
48 stroker->patternOffset += delta;-
49 stroker->patternOffset %= stroker->patternLength;-
50 }-
51-
52 bool on() const {-
53 return (dashIndex + dashOn) & 1;-
54 }-
55 void adjust() {-
56 offset += 64;-
57 if (offset >= pattern[dashIndex]) {-
58 ++dashIndex;-
59 dashIndex %= stroker->patternSize;-
60 }-
61 offset %= stroker->patternLength;-
62-
63 }-
64};-
65-
66struct NoDasher {-
67 NoDasher(QCosmeticStroker *, bool, int, int) {}-
68 bool on() const { return true; }-
69 void adjust(int = 0) {}-
70};-
71-
72};-
73-
74-
75-
76-
77-
78-
79template<DrawPixel drawPixel, class Dasher>-
80static bool drawLine(QCosmeticStroker *stroker, qreal x1, qreal y1, qreal x2, qreal y2, int caps);-
81template<DrawPixel drawPixel, class Dasher>-
82static bool drawLineAA(QCosmeticStroker *stroker, qreal x1, qreal y1, qreal x2, qreal y2, int caps);-
83-
84inline void drawPixel(QCosmeticStroker *stroker, int x, int y, int coverage)-
85{-
86 const QRect &cl = stroker->clip;-
87 if (x < cl.x() || x > cl.right() || y < cl.y() || y > cl.bottom())-
88 return;-
89-
90 if (stroker->current_span > 0) {-
91 const int lastx = stroker->spans[stroker->current_span-1].x + stroker->spans[stroker->current_span-1].len ;-
92 const int lasty = stroker->spans[stroker->current_span-1].y;-
93-
94 if (stroker->current_span == QCosmeticStroker::NSPANS || y < lasty || (y == lasty && x < lastx)) {-
95 stroker->blend(stroker->current_span, stroker->spans, &stroker->state->penData);-
96 stroker->current_span = 0;-
97 }-
98 }-
99-
100 stroker->spans[stroker->current_span].x = ushort(x);-
101 stroker->spans[stroker->current_span].len = 1;-
102 stroker->spans[stroker->current_span].y = y;-
103 stroker->spans[stroker->current_span].coverage = coverage*stroker->opacity >> 8;-
104 ++stroker->current_span;-
105}-
106-
107inline void drawPixelARGB32(QCosmeticStroker *stroker, int x, int y, int coverage)-
108{-
109 const QRect &cl = stroker->clip;-
110 if (x < cl.x() || x > cl.right() || y < cl.y() || y > cl.bottom())-
111 return;-
112-
113 int offset = x + stroker->ppl*y;-
114 uint c = BYTE_MUL(stroker->color, coverage);-
115 stroker->pixels[offset] = sourceOver(stroker->pixels[offset], c);-
116}-
117-
118inline void drawPixelARGB32Opaque(QCosmeticStroker *stroker, int x, int y, int)-
119{-
120 const QRect &cl = stroker->clip;-
121 if (x < cl.x() || x > cl.right() || y < cl.y() || y > cl.bottom())-
122 return;-
123-
124 int offset = x + stroker->ppl*y;-
125 stroker->pixels[offset] = sourceOver(stroker->pixels[offset], stroker->color);-
126}-
127-
128enum StrokeSelection {-
129 Aliased = 0,-
130 AntiAliased = 1,-
131 Solid = 0,-
132 Dashed = 2,-
133 RegularDraw = 0,-
134 FastDraw = 4-
135};-
136-
137static StrokeLine strokeLine(int strokeSelection)-
138{-
139 StrokeLine stroke;-
140-
141 switch (strokeSelection) {-
142 case Aliased|Solid|RegularDraw:-
143 stroke = &::drawLine<drawPixel, NoDasher>;-
144 break;-
145 case Aliased|Solid|FastDraw:-
146 stroke = &::drawLine<drawPixelARGB32Opaque, NoDasher>;-
147 break;-
148 case Aliased|Dashed|RegularDraw:-
149 stroke = &::drawLine<drawPixel, Dasher>;-
150 break;-
151 case Aliased|Dashed|FastDraw:-
152 stroke = &::drawLine<drawPixelARGB32Opaque, Dasher>;-
153 break;-
154 case AntiAliased|Solid|RegularDraw:-
155 stroke = &::drawLineAA<drawPixel, NoDasher>;-
156 break;-
157 case AntiAliased|Solid|FastDraw:-
158 stroke = &::drawLineAA<drawPixelARGB32, NoDasher>;-
159 break;-
160 case AntiAliased|Dashed|RegularDraw:-
161 stroke = &::drawLineAA<drawPixel, Dasher>;-
162 break;-
163 case AntiAliased|Dashed|FastDraw:-
164 stroke = &::drawLineAA<drawPixelARGB32, Dasher>;-
165 break;-
166 default:-
167 ((!(false)) ? qt_assert("false",__FILE__,221227) : qt_noop());-
168 stroke = 0;-
169 }-
170 return stroke;-
171}-
172-
173void QCosmeticStroker::setup()-
174{-
175 blend = state->penData.blend;-
176 if (state->clip && state->clip->enabled && state->clip->hasRectClip && !state->clip->clipRect.isEmpty()) {-
177 clip &= state->clip->clipRect;-
178 blend = state->penData.unclipped_blend;-
179 }-
180-
181 int strokeSelection = 0;-
182 if (blend == state->penData.unclipped_blend-
183 && state->penData.type == QSpanData::Solid-
184 && (state->penData.rasterBuffer->format == QImage::Format_ARGB32_Premultiplied-
185 || state->penData.rasterBuffer->format == QImage::Format_RGB32)-
186 && state->compositionMode() == QPainter::CompositionMode_SourceOver)-
187 strokeSelection |= FastDraw;-
188-
189 if (state->renderHints & QPainter::Antialiasing)-
190 strokeSelection |= AntiAliased;-
191-
192 const QVector<qreal> &penPattern = state->lastPen.dashPattern();-
193 if (penPattern.isEmpty()) {-
194 ((!(!pattern && !reversePattern)) ? qt_assert("!pattern && !reversePattern",__FILE__,248254) : qt_noop());-
195 pattern = 0;-
196 reversePattern = 0;-
197 patternLength = 0;-
198 patternSize = 0;-
199 } else {-
200 pattern = (int *)malloc(penPattern.size()*sizeof(int));-
201 reversePattern = (int *)malloc(penPattern.size()*sizeof(int));-
202 patternSize = penPattern.size();-
203-
204 patternLength = 0;-
205 for (int i = 0; i < patternSize; ++i) {-
206 patternLength += (int) qMax(1. , penPattern.at(i)*64.);-
207 pattern[i] = patternLength;-
208 }-
209 patternLength = 0;-
210 for (int i = 0; i < patternSize; ++i) {-
211 patternLength += (int) qMax(1., penPattern.at(patternSize - 1 - i)*64.);-
212 reversePattern[i] = patternLength;-
213 }-
214 strokeSelection |= Dashed;-
215-
216 }-
217-
218 stroke = strokeLine(strokeSelection);-
219-
220 qreal width = state->lastPen.widthF();-
221 if (width == 0)-
222 opacity = 256;-
223 else if (qt_pen_is_cosmetic(state->lastPen, state->renderHints))-
224 opacity = (int) 256*width;-
225 else-
226 opacity = (int) 256*width*state->txscale;-
227 opacity = qBound(0, opacity, 256);-
228-
229 drawCaps = state->lastPen.capStyle() != Qt::FlatCap;-
230-
231 if (strokeSelection & FastDraw) {-
232 color = multiplyAlpha256(state->penData.solid.color, opacity).toArgb32();-
233 QRasterBuffer *buffer = state->penData.rasterBuffer;-
234 pixels = (uint *)buffer->buffer();-
235 ppl = buffer->bytesPerLine()>>2;-
236 }-
237-
238-
239-
240-
241-
242 xmin = deviceRect.left() - 1;-
243 xmax = deviceRect.right() + 2;-
244 ymin = deviceRect.top() - 1;-
245 ymax = deviceRect.bottom() + 2;-
246-
247 lastPixel.x = -1;-
248 lastPixel.y = -1;-
249}-
250-
251-
252bool QCosmeticStroker::clipLine(qreal &x1, qreal &y1, qreal &x2, qreal &y2)-
253{-
254-
255-
256 if (x1 < xmin) {-
257 if (x2 <= xmin)-
258 goto clipped;-
259 y1 += (y2 - y1)/(x2 - x1) * (xmin - x1);-
260 x1 = xmin;-
261 } else if (x1 > xmax) {-
262 if (x2 >= xmax)-
263 goto clipped;-
264 y1 += (y2 - y1)/(x2 - x1) * (xmax - x1);-
265 x1 = xmax;-
266 }-
267 if (x2 < xmin) {-
268 lastPixel.x = -1;-
269 y2 += (y2 - y1)/(x2 - x1) * (xmin - x2);-
270 x2 = xmin;-
271 } else if (x2 > xmax) {-
272 lastPixel.x = -1;-
273 y2 += (y2 - y1)/(x2 - x1) * (xmax - x2);-
274 x2 = xmax;-
275 }-
276-
277 if (y1 < ymin) {-
278 if (y2 <= ymin)-
279 goto clipped;-
280 x1 += (x2 - x1)/(y2 - y1) * (ymin - y1);-
281 y1 = ymin;-
282 } else if (y1 > ymax) {-
283 if (y2 >= ymax)-
284 goto clipped;-
285 x1 += (x2 - x1)/(y2 - y1) * (ymax - y1);-
286 y1 = ymax;-
287 }-
288 if (y2 < ymin) {-
289 lastPixel.x = -1;-
290 x2 += (x2 - x1)/(y2 - y1) * (ymin - y2);-
291 y2 = ymin;-
292 } else if (y2 > ymax) {-
293 lastPixel.x = -1;-
294 x2 += (x2 - x1)/(y2 - y1) * (ymax - y2);-
295 y2 = ymax;-
296 }-
297-
298 return false;-
299-
300 clipped:-
301 lastPixel.x = -1;-
302 return true;-
303}-
304-
305-
306void QCosmeticStroker::drawLine(const QPointF &p1, const QPointF &p2)-
307{-
308 if (p1 == p2) {-
309 drawPoints(&p1, 1);-
310 return;-
311 }-
312-
313 QPointF start = p1 * state->matrix;-
314 QPointF end = p2 * state->matrix;-
315-
316 patternOffset = state->lastPen.dashOffset()*64;-
317 lastPixel.x = -1;-
318-
319 stroke(this, start.x(), start.y(), end.x(), end.y(), drawCaps ? CapBegin|CapEnd : 0);-
320-
321 blend(current_span, spans, &state->penData);-
322 current_span = 0;-
323}-
324-
325void QCosmeticStroker::drawPoints(const QPoint *points, int num)-
326{-
327 const QPoint *end = points + num;-
328 while (points < end) {-
329 QPointF p = QPointF(*points) * state->matrix;-
330 drawPixel(this, qRound(p.x()), qRound(p.y()), 255);-
331 ++points;-
332 }-
333-
334 blend(current_span, spans, &state->penData);-
335 current_span = 0;-
336}-
337-
338void QCosmeticStroker::drawPoints(const QPointF *points, int num)-
339{-
340 const QPointF *end = points + num;-
341 while (points < end) {-
342 QPointF p = (*points) * state->matrix;-
343 drawPixel(this, qRound(p.x()), qRound(p.y()), 255);-
344 ++points;-
345 }-
346-
347 blend(current_span, spans, &state->penData);-
348 current_span = 0;-
349}-
350-
351void QCosmeticStroker::calculateLastPoint(qreal rx1, qreal ry1, qreal rx2, qreal ry2)-
352{-
353-
354-
355-
356-
357-
358-
359-
360 lastPixel.x = -1;-
361 lastPixel.y = -1;-
362-
363 if (clipLine(rx1, ry1, rx2, ry2))-
364 return;-
365-
366 const int half = legacyRounding ? 31 : 0;-
367 int x1 = ((int)((rx1)*64.)) + half;-
368 int y1 = ((int)((ry1)*64.)) + half;-
369 int x2 = ((int)((rx2)*64.)) + half;-
370 int y2 = ((int)((ry2)*64.)) + half;-
371-
372 int dx = qAbs(x2 - x1);-
373 int dy = qAbs(y2 - y1);-
374-
375 if (dx < dy) {-
376-
377 bool swapped = false;-
378 if (y1 > y2) {-
379 swapped = true;-
380 qSwap(y1, y2);-
381 qSwap(x1, x2);-
382 }-
383 int xinc = F16Dot16FixedDiv(x2 - x1, y2 - y1);-
384 int x = x1 * (1<<10);-
385-
386 int y = (y1 + 32) >> 6;-
387 int ys = (y2 + 32) >> 6;-
388-
389 int round = (xinc > 0) ? 32 : 0;-
390 if (y != ys) {-
391 x += ((y * (1<<6)) + round - y1) * xinc >> 6;-
392-
393 if (swapped) {-
394 lastPixel.x = x >> 16;-
395 lastPixel.y = y;-
396 lastDir = QCosmeticStroker::BottomToTop;-
397 } else {-
398 lastPixel.x = (x + (ys - y - 1)*xinc) >> 16;-
399 lastPixel.y = ys - 1;-
400 lastDir = QCosmeticStroker::TopToBottom;-
401 }-
402 lastAxisAligned = qAbs(xinc) < (1 << 14);-
403 }-
404 } else {-
405-
406 if (!dx)-
407 return;-
408-
409 bool swapped = false;-
410 if (x1 > x2) {-
411 swapped = true;-
412 qSwap(x1, x2);-
413 qSwap(y1, y2);-
414 }-
415 int yinc = F16Dot16FixedDiv(y2 - y1, x2 - x1);-
416 int y = y1 << 10;-
417-
418 int x = (x1 + 32) >> 6;-
419 int xs = (x2 + 32) >> 6;-
420-
421 int round = (yinc > 0) ? 32 : 0;-
422 if (x != xs) {-
423 y += ((x * (1<<6)) + round - x1) * yinc >> 6;-
424-
425 if (swapped) {-
426 lastPixel.x = x;-
427 lastPixel.y = y >> 16;-
428 lastDir = QCosmeticStroker::RightToLeft;-
429 } else {-
430 lastPixel.x = xs - 1;-
431 lastPixel.y = (y + (xs - x - 1)*yinc) >> 16;-
432 lastDir = QCosmeticStroker::LeftToRight;-
433 }-
434 lastAxisAligned = qAbs(yinc) < (1 << 14);-
435 }-
436 }-
437-
438}-
439-
440static inline const QPainterPath::ElementType *subPath(const QPainterPath::ElementType *t, const QPainterPath::ElementType *end,-
441 const qreal *points, bool *closed)-
442{-
443 const QPainterPath::ElementType *start = t;-
444 ++t;-
445-
446-
447 while (t < end) {-
448 if (*t == QPainterPath::MoveToElement)-
449 break;-
450 ++t;-
451 }-
452-
453 int offset = t - start - 1;-
454-
455 *closed = (points[0] == points[2*offset] && points[1] == points[2*offset + 1]);-
456-
457 return t;-
458}-
459-
460void QCosmeticStroker::drawPath(const QVectorPath &path)-
461{-
462-
463-
464 if (path.isEmpty()
path.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
)
0
465 return;
never executed: return;
0
466-
467 const qreal *points = path.points();-
468 const QPainterPath::ElementType *type = path.elements();-
469-
470 if (type
typeDescription
TRUEnever evaluated
FALSEnever evaluated
) {
0
471 const QPainterPath::ElementType *end = type + path.elementCount();-
472-
473 while (type < end
type < endDescription
TRUEnever evaluated
FALSEnever evaluated
) {
0
474 ((!(type == path.elements() || *type == QPainterPath::MoveToElement)) ? qt_assert("type == path.elements() || *type == QPainterPath::MoveToElement",__FILE__,528534) : qt_noop());-
475-
476 QPointF p = QPointF(points[0], points[1]) * state->matrix;-
477 patternOffset = state->lastPen.dashOffset()*64;-
478 lastPixel.x = (-2147483647 - 1);-
479 lastPixel.y = (-2147483647 - 1);-
480-
481 bool closed;-
482 const QPainterPath::ElementType *e = subPath(type, end, points, &closed);-
483 if (closed
closedDescription
TRUEnever evaluated
FALSEnever evaluated
) {
0
484 const qreal *p = points + 2*(e-type);-
485 QPointF p1 = QPointF(p[-4], p[-3]) * state->matrix;-
486 QPointF p2 = QPointF(p[-2], p[-1]) * state->matrix;-
487 calculateLastPoint(p1.x(), p1.y(), p2.x(), p2.y());-
488 }
never executed: end of block
0
489 int caps = (!closed
!closedDescription
TRUEnever evaluated
FALSEnever evaluated
&&& drawCaps
drawCapsDescription
TRUEnever evaluated
FALSEnever evaluated
) ? CapBegin : NoCaps;
0
490-
491-
492 points += 2;-
493 ++type;-
494-
495 while (type < e
type < eDescription
TRUEnever evaluated
FALSEnever evaluated
) {
0
496 QPointF p2 = QPointF(points[0], points[1]) * state->matrix;-
497 switch (*type) {-
498 case
never executed: case QPainterPath::MoveToElement:
QPainterPath::MoveToElement:
never executed: case QPainterPath::MoveToElement:
0
499 ((!(!"Logic error")) ? qt_assert("!\"Logic error\"",__FILE__,553559) : qt_noop());-
500 break;
never executed: break;
0
501-
502 case
never executed: case QPainterPath::LineToElement:
QPainterPath::LineToElement:
never executed: case QPainterPath::LineToElement:
0
503 if (!closed
!closedDescription
TRUEnever evaluated
FALSEnever evaluated
&& drawCaps
drawCapsDescription
TRUEnever evaluated
FALSEnever evaluated
&& type == e - 1
type == e - 1Description
TRUEnever evaluated
FALSEnever evaluated
)
0
504 caps |= CapEnd;
never executed: caps |= CapEnd;
0
505 stroke(this, p.x(), p.y(), p2.x(), p2.y(), caps);-
506 p = p2;-
507 points += 2;-
508 ++type;-
509 break;
never executed: break;
0
510-
511 case
never executed: case QPainterPath::CurveToElement:
QPainterPath::CurveToElement:
never executed: case QPainterPath::CurveToElement:
{
0
512 if (!closed
!closedDescription
TRUEnever evaluated
FALSEnever evaluated
&& drawCaps
drawCapsDescription
TRUEnever evaluated
FALSEnever evaluated
&& type == e - 3
type == e - 3Description
TRUEnever evaluated
FALSEnever evaluated
)
0
513 caps |= CapEnd;
never executed: caps |= CapEnd;
0
514 QPointF p3 = QPointF(points[2], points[3]) * state->matrix;-
515 QPointF p4 = QPointF(points[4], points[5]) * state->matrix;-
516 renderCubic(p, p2, p3, p4, caps);-
517 p = p4;-
518 type += 3;-
519 points += 6;-
520 break;
never executed: break;
0
521 }-
522 case
never executed: case QPainterPath::CurveToDataElement:
QPainterPath::CurveToDataElement:
never executed: case QPainterPath::CurveToDataElement:
0
523 ((!(!"QPainterPath::toSubpathPolygons(), bad element type")) ? qt_assert("!\"QPainterPath::toSubpathPolygons(), bad element type\"",__FILE__,577583) : qt_noop());-
524 break;
never executed: break;
0
525 }-
526 caps = NoCaps;-
527 }
never executed: end of block
0
528 }
never executed: end of block
0
529 }
never executed: end of block
else {
0
530 QPointF p = QPointF(points[0], points[1]) * state->matrix;-
531 QPointF movedTo = p;-
532 patternOffset = state->lastPen.dashOffset()*64;-
533 lastPixel.x = (-2147483647 - 1);-
534 lastPixel.y = (-2147483647 - 1);-
535-
536 const qreal *begin = points;-
537 const qreal *end = points + 2*path.elementCount();-
538-
539 bool closed = path.hasImplicitClose()
path.hasImplicitClose()Description
TRUEnever evaluated
FALSEnever evaluated
|| (points[0] == end[-2]
points[0] == end[-2]Description
TRUEnever evaluated
FALSEnever evaluated
&& points[1] == end[-1]
points[1] == end[-1]Description
TRUEnever evaluated
FALSEnever evaluated
);
0
540 int caps = (!closed
!closedDescription
TRUEnever evaluated
FALSEnever evaluated
&&& drawCaps
drawCapsDescription
TRUEnever evaluated
FALSEnever evaluated
) ? CapBegin : NoCaps;
0
541 if (closed
closedDescription
TRUEnever evaluated
FALSEnever evaluated
) {
0
542 QPointF p2 = QPointF(end[-2], end[-1]) * state->matrix;-
543 calculateLastPoint(p2.x(), p2.y(), p.x(), p.y());-
544 }
never executed: end of block
0
545-
546 bool fastPenAliased = (state->flags.fast_pen
state->flags.fast_penDescription
TRUEnever evaluated
FALSEnever evaluated
&& !state->flags.antialiased
!state->flags.antialiasedDescription
TRUEnever evaluated
FALSEnever evaluated
);
0
547 points += 2;-
548 while (points < end
points < endDescription
TRUEnever evaluated
FALSEnever evaluated
) {
0
549 QPointF p2 = QPointF(points[0], points[1]) * state->matrix;-
550-
551 if (!closed
!closedDescription
TRUEnever evaluated
FALSEnever evaluated
&& drawCaps
drawCapsDescription
TRUEnever evaluated
FALSEnever evaluated
&& points == end - 2
points == end - 2Description
TRUEnever evaluated
FALSEnever evaluated
)
0
552 caps |= CapEnd;
never executed: caps |= CapEnd;
0
553-
554 bool moveNextStart = stroke(this, p.x(), p.y(), p2.x(), p2.y(), caps);-
555 if (!fastPenAliased
!fastPenAliasedDescription
TRUEnever evaluated
FALSEnever evaluated
|| moveNextStart
moveNextStartDescription
TRUEnever evaluated
FALSEnever evaluated
|| points == begin + 2
points == begin + 2Description
TRUEnever evaluated
FALSEnever evaluated
|| points == end - 2
points == end - 2Description
TRUEnever evaluated
FALSEnever evaluated
)
0
556 p = p2;
never executed: p = p2;
0
557 points += 2;-
558 caps = NoCaps;-
559 }
never executed: end of block
0
560 if (path.hasImplicitClose()
path.hasImplicitClose()Description
TRUEnever evaluated
FALSEnever evaluated
)
0
561 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
562 }
never executed: end of block
0
563-
564-
565 blend(current_span, spans, &state->penData);-
566 current_span = 0;-
567}
never executed: end of block
0
568-
569void QCosmeticStroker::renderCubic(const QPointF &p1, const QPointF &p2, const QPointF &p3, const QPointF &p4, int caps)-
570{-
571-
572 const int maxSubDivisions = 6;-
573 PointF points[3*maxSubDivisions + 4];-
574-
575 points[3].x = p1.x();-
576 points[3].y = p1.y();-
577 points[2].x = p2.x();-
578 points[2].y = p2.y();-
579 points[1].x = p3.x();-
580 points[1].y = p3.y();-
581 points[0].x = p4.x();-
582 points[0].y = p4.y();-
583-
584 PointF *p = points;-
585 int level = maxSubDivisions;-
586-
587 renderCubicSubdivision(p, level, caps);-
588}-
589-
590static void splitCubic(QCosmeticStroker::PointF *points)-
591{-
592 const qreal half = .5;-
593 qreal a, b, c, d;-
594-
595 points[6].x = points[3].x;-
596 c = points[1].x;-
597 d = points[2].x;-
598 points[1].x = a = ( points[0].x + c ) * half;-
599 points[5].x = b = ( points[3].x + d ) * half;-
600 c = ( c + d ) * half;-
601 points[2].x = a = ( a + c ) * half;-
602 points[4].x = b = ( b + c ) * half;-
603 points[3].x = ( a + b ) * half;-
604-
605 points[6].y = points[3].y;-
606 c = points[1].y;-
607 d = points[2].y;-
608 points[1].y = a = ( points[0].y + c ) * half;-
609 points[5].y = b = ( points[3].y + d ) * half;-
610 c = ( c + d ) * half;-
611 points[2].y = a = ( a + c ) * half;-
612 points[4].y = b = ( b + c ) * half;-
613 points[3].y = ( a + b ) * half;-
614}-
615-
616void QCosmeticStroker::renderCubicSubdivision(QCosmeticStroker::PointF *points, int level, int caps)-
617{-
618 if (level) {-
619 qreal dx = points[3].x - points[0].x;-
620 qreal dy = points[3].y - points[0].y;-
621 qreal len = ((qreal).25) * (qAbs(dx) + qAbs(dy));-
622-
623 if (qAbs(dx * (points[0].y - points[2].y) - dy * (points[0].x - points[2].x)) >= len ||-
624 qAbs(dx * (points[0].y - points[1].y) - dy * (points[0].x - points[1].x)) >= len) {-
625 splitCubic(points);-
626-
627 --level;-
628 renderCubicSubdivision(points + 3, level, caps & CapBegin);-
629 renderCubicSubdivision(points, level, caps & CapEnd);-
630 return;-
631 }-
632 }-
633-
634 stroke(this, points[3].x, points[3].y, points[0].x, points[0].y, caps);-
635}-
636-
637static inline int swapCaps(int caps)-
638{-
639 return ((caps & QCosmeticStroker::CapBegin) << 1) |-
640 ((caps & QCosmeticStroker::CapEnd) >> 1);-
641}-
642-
643-
644static inline void capAdjust(int caps, int &x1, int &x2, int &y, int yinc)-
645{-
646 if (caps & QCosmeticStroker::CapBegin) {-
647 x1 -= 32;-
648 y -= yinc >> 1;-
649 }-
650 if (caps & QCosmeticStroker::CapEnd) {-
651 x2 += 32;-
652 }-
653}-
654-
655-
656-
657-
658-
659template<DrawPixel drawPixel, class Dasher>-
660static bool drawLine(QCosmeticStroker *stroker, qreal rx1, qreal ry1, qreal rx2, qreal ry2, int caps)-
661{-
662 bool didDraw = qAbs(rx2 - rx1) + qAbs(ry2 - ry1) >= 1.0;-
663-
664 if (stroker->clipLine(rx1, ry1, rx2, ry2))-
665 return true;-
666-
667 const int half = stroker->legacyRounding ? 31 : 0;-
668 int x1 = ((int)((rx1)*64.)) + half;-
669 int y1 = ((int)((ry1)*64.)) + half;-
670 int x2 = ((int)((rx2)*64.)) + half;-
671 int y2 = ((int)((ry2)*64.)) + half;-
672-
673 int dx = qAbs(x2 - x1);-
674 int dy = qAbs(y2 - y1);-
675-
676 QCosmeticStroker::Point last = stroker->lastPixel;-
677-
678-
679-
680 if (dx < dy) {-
681-
682 QCosmeticStroker::Direction dir = QCosmeticStroker::TopToBottom;-
683-
684 bool swapped = false;-
685 if (y1 > y2) {-
686 swapped = true;-
687 qSwap(y1, y2);-
688 qSwap(x1, x2);-
689 caps = swapCaps(caps);-
690 dir = QCosmeticStroker::BottomToTop;-
691 }-
692 int xinc = F16Dot16FixedDiv(x2 - x1, y2 - y1);-
693 int x = x1 * (1<<10);-
694-
695 if ((stroker->lastDir ^ QCosmeticStroker::VerticalMask) == dir)-
696 caps |= swapped ? QCosmeticStroker::CapEnd : QCosmeticStroker::CapBegin;-
697-
698 capAdjust(caps, y1, y2, x, xinc);-
699-
700 int y = (y1 + 32) >> 6;-
701 int ys = (y2 + 32) >> 6;-
702 int round = (xinc > 0) ? 32 : 0;-
703-
704 if (y != ys) {-
705 x += ((y * (1<<6)) + round - y1) * xinc >> 6;-
706-
707-
708 QCosmeticStroker::Point first;-
709 first.x = x >> 16;-
710 first.y = y;-
711 last.x = (x + (ys - y - 1)*xinc) >> 16;-
712 last.y = ys - 1;-
713 if (swapped)-
714 qSwap(first, last);-
715-
716 bool axisAligned = qAbs(xinc) < (1 << 14);-
717 if (stroker->lastPixel.x >= 0) {-
718 if (first.x == stroker->lastPixel.x &&-
719 first.y == stroker->lastPixel.y) {-
720-
721 if (swapped) {-
722 --ys;-
723 } else {-
724 ++y;-
725 x += xinc;-
726 }-
727 } else if (stroker->lastDir != dir &&-
728 (((axisAligned && stroker->lastAxisAligned) &&-
729 stroker->lastPixel.x != first.x && stroker->lastPixel.y != first.y) ||-
730 (qAbs(stroker->lastPixel.x - first.x) > 1 ||-
731 qAbs(stroker->lastPixel.y - first.y) > 1))) {-
732-
733 if (swapped) {-
734 ++ys;-
735 } else {-
736 --y;-
737 x -= xinc;-
738 }-
739 }-
740 }-
741 stroker->lastDir = dir;-
742 stroker->lastAxisAligned = axisAligned;-
743-
744 Dasher dasher(stroker, swapped, y * (1<<6), ys * (1<<6));-
745-
746 do {-
747 if (dasher.on())-
748 drawPixel(stroker, x >> 16, y, 255);-
749 dasher.adjust();-
750 x += xinc;-
751 } while (++y < ys);-
752 didDraw = true;-
753 }-
754 } else {-
755-
756 if (!dx)-
757 return true;-
758-
759 QCosmeticStroker::Direction dir = QCosmeticStroker::LeftToRight;-
760-
761 bool swapped = false;-
762 if (x1 > x2) {-
763 swapped = true;-
764 qSwap(x1, x2);-
765 qSwap(y1, y2);-
766 caps = swapCaps(caps);-
767 dir = QCosmeticStroker::RightToLeft;-
768 }-
769 int yinc = F16Dot16FixedDiv(y2 - y1, x2 - x1);-
770 int y = y1 * (1<<10);-
771-
772 if ((stroker->lastDir ^ QCosmeticStroker::HorizontalMask) == dir)-
773 caps |= swapped ? QCosmeticStroker::CapEnd : QCosmeticStroker::CapBegin;-
774-
775 capAdjust(caps, x1, x2, y, yinc);-
776-
777 int x = (x1 + 32) >> 6;-
778 int xs = (x2 + 32) >> 6;-
779 int round = (yinc > 0) ? 32 : 0;-
780-
781 if (x != xs) {-
782 y += ((x * (1<<6)) + round - x1) * yinc >> 6;-
783-
784-
785 QCosmeticStroker::Point first;-
786 first.x = x;-
787 first.y = y >> 16;-
788 last.x = xs - 1;-
789 last.y = (y + (xs - x - 1)*yinc) >> 16;-
790 if (swapped)-
791 qSwap(first, last);-
792-
793 bool axisAligned = qAbs(yinc) < (1 << 14);-
794 if (stroker->lastPixel.x >= 0) {-
795 if (first.x == stroker->lastPixel.x && first.y == stroker->lastPixel.y) {-
796-
797 if (swapped) {-
798 --xs;-
799 } else {-
800 ++x;-
801 y += yinc;-
802 }-
803 } else if (stroker->lastDir != dir &&-
804 (((axisAligned && stroker->lastAxisAligned) &&-
805 stroker->lastPixel.x != first.x && stroker->lastPixel.y != first.y) ||-
806 (qAbs(stroker->lastPixel.x - first.x) > 1 ||-
807 qAbs(stroker->lastPixel.y - first.y) > 1))) {-
808-
809 if (swapped) {-
810 ++xs;-
811 } else {-
812 --x;-
813 y -= yinc;-
814 }-
815 }-
816 }-
817 stroker->lastDir = dir;-
818 stroker->lastAxisAligned = axisAligned;-
819-
820 Dasher dasher(stroker, swapped, x * (1<<6), xs * (1<<6));-
821-
822 do {-
823 if (dasher.on())-
824 drawPixel(stroker, x, y >> 16, 255);-
825 dasher.adjust();-
826 y += yinc;-
827 } while (++x < xs);-
828 didDraw = true;-
829 }-
830 }-
831 stroker->lastPixel = last;-
832 return didDraw;-
833}-
834-
835-
836template<DrawPixel drawPixel, class Dasher>-
837static bool drawLineAA(QCosmeticStroker *stroker, qreal rx1, qreal ry1, qreal rx2, qreal ry2, int caps)-
838{-
839 if (stroker->clipLine(rx1, ry1, rx2, ry2))-
840 return true;-
841-
842 int x1 = ((int)((rx1)*64.));-
843 int y1 = ((int)((ry1)*64.));-
844 int x2 = ((int)((rx2)*64.));-
845 int y2 = ((int)((ry2)*64.));-
846-
847 int dx = x2 - x1;-
848 int dy = y2 - y1;-
849-
850 if (qAbs(dx) < qAbs(dy)) {-
851-
852-
853 int xinc = F16Dot16FixedDiv(dx, dy);-
854-
855 bool swapped = false;-
856 if (y1 > y2) {-
857 qSwap(y1, y2);-
858 qSwap(x1, x2);-
859 swapped = true;-
860 caps = swapCaps(caps);-
861 }-
862-
863 int x = (x1 - 32) * (1<<10);-
864 x -= ( ((y1 & 63) - 32) * xinc ) >> 6;-
865-
866 capAdjust(caps, y1, y2, x, xinc);-
867-
868 Dasher dasher(stroker, swapped, y1, y2);-
869-
870 int y = y1 >> 6;-
871 int ys = y2 >> 6;-
872-
873 int alphaStart, alphaEnd;-
874 if (y == ys) {-
875 alphaStart = y2 - y1;-
876 ((!(alphaStart >= 0 && alphaStart < 64)) ? qt_assert("alphaStart >= 0 && alphaStart < 64",__FILE__,939945) : qt_noop());-
877 alphaEnd = 0;-
878 } else {-
879 alphaStart = 64 - (y1 & 63);-
880 alphaEnd = (y2 & 63);-
881 }-
882-
883-
884-
885-
886 if (dasher.on()) {-
887 uint alpha = (quint8)(x >> 8);-
888 drawPixel(stroker, x>>16, y, (255-alpha) * alphaStart >> 6);-
889 drawPixel(stroker, (x>>16) + 1, y, alpha * alphaStart >> 6);-
890 }-
891 dasher.adjust();-
892 x += xinc;-
893 ++y;-
894 if (y < ys) {-
895 do {-
896 if (dasher.on()) {-
897 uint alpha = (quint8)(x >> 8);-
898 drawPixel(stroker, x>>16, y, (255-alpha));-
899 drawPixel(stroker, (x>>16) + 1, y, alpha);-
900 }-
901 dasher.adjust();-
902 x += xinc;-
903 } while (++y < ys);-
904 }-
905-
906 if (alphaEnd && dasher.on()) {-
907 uint alpha = (quint8)(x >> 8);-
908 drawPixel(stroker, x>>16, y, (255-alpha) * alphaEnd >> 6);-
909 drawPixel(stroker, (x>>16) + 1, y, alpha * alphaEnd >> 6);-
910 }-
911 } else {-
912-
913 if (!dx)-
914 return true;-
915-
916 int yinc = F16Dot16FixedDiv(dy, dx);-
917-
918 bool swapped = false;-
919 if (x1 > x2) {-
920 qSwap(x1, x2);-
921 qSwap(y1, y2);-
922 swapped = true;-
923 caps = swapCaps(caps);-
924 }-
925-
926 int y = (y1 - 32) * (1<<10);-
927 y -= ( ((x1 & 63) - 32) * yinc ) >> 6;-
928-
929 capAdjust(caps, x1, x2, y, yinc);-
930-
931 Dasher dasher(stroker, swapped, x1, x2);-
932-
933 int x = x1 >> 6;-
934 int xs = x2 >> 6;-
935-
936-
937-
938 int alphaStart, alphaEnd;-
939 if (x == xs) {-
940 alphaStart = x2 - x1;-
941 ((!(alphaStart >= 0 && alphaStart < 64)) ? qt_assert("alphaStart >= 0 && alphaStart < 64",__FILE__,10041010) : qt_noop());-
942 alphaEnd = 0;-
943 } else {-
944 alphaStart = 64 - (x1 & 63);-
945 alphaEnd = (x2 & 63);-
946 }-
947-
948-
949 if (dasher.on()) {-
950 uint alpha = (quint8)(y >> 8);-
951 drawPixel(stroker, x, y>>16, (255-alpha) * alphaStart >> 6);-
952 drawPixel(stroker, x, (y>>16) + 1, alpha * alphaStart >> 6);-
953 }-
954 dasher.adjust();-
955 y += yinc;-
956 ++x;-
957-
958 if (x < xs) {-
959 do {-
960 if (dasher.on()) {-
961 uint alpha = (quint8)(y >> 8);-
962 drawPixel(stroker, x, y>>16, (255-alpha));-
963 drawPixel(stroker, x, (y>>16) + 1, alpha);-
964 }-
965 dasher.adjust();-
966 y += yinc;-
967 } while (++x < xs);-
968 }-
969-
970 if (alphaEnd && dasher.on()) {-
971 uint alpha = (quint8)(y >> 8);-
972 drawPixel(stroker, x, y>>16, (255-alpha) * alphaEnd >> 6);-
973 drawPixel(stroker, x, (y>>16) + 1, alpha * alphaEnd >> 6);-
974 }-
975 }-
976 return true;-
977}-
978-
979-
Switch to Source codePreprocessed file

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