43 #include "private/qpainterpath_p.h" 50 inline QString capString(
int caps)
63 #define toF26Dot6(x) ((int)((x)*64.)) 91 int delta = stop - start;
93 pattern = stroker->reversePattern;
94 offset = stroker->patternLength - stroker->patternOffset - delta - ((start & 63) - 32);
97 pattern = stroker->pattern;
98 offset = stroker->patternOffset - ((start & 63) - 32);
101 offset %= stroker->patternLength;
103 offset += stroker->patternLength;
106 while (offset>= pattern[dashIndex])
110 stroker->patternOffset += delta;
111 stroker->patternOffset %= stroker->patternLength;
115 return (dashIndex + dashOn) & 1;
119 if (offset >= pattern[dashIndex]) {
121 dashIndex %= stroker->patternSize;
123 offset %= stroker->patternLength;
130 bool on()
const {
return true; }
131 void adjust(
int = 0) {}
141 template<DrawPixel drawPixel,
class Dasher>
143 template<DrawPixel drawPixel,
class Dasher>
149 if (x < cl.
x() || x > cl.
right() || y < cl.
y() || y > cl.
bottom())
170 if (x < cl.
x() || x > cl.
right() || y < cl.
y() || y > cl.
bottom())
173 int offset = x + stroker->
ppl*y;
181 if (x < cl.
x() || x > cl.
right() || y < cl.
y() || y > cl.
bottom())
184 int offset = x + stroker->
ppl*y;
201 switch (strokeSelection) {
235 blend = state->penData.blend;
236 if (state->clip && state->clip->enabled && state->clip->hasRectClip && !state->clip->clipRect.isEmpty()) {
237 clip &= state->clip->clipRect;
238 blend = state->penData.unclipped_blend;
241 int strokeSelection = 0;
242 if (blend == state->penData.unclipped_blend
254 Q_ASSERT(!pattern && !reversePattern);
260 pattern = (
int *)malloc(penPattern.
size()*
sizeof(int));
261 reversePattern = (
int *)malloc(penPattern.
size()*
sizeof(int));
262 patternSize = penPattern.
size();
265 for (
int i = 0; i < patternSize; ++i) {
266 patternLength += (int)
qMax(1. , penPattern.
at(i)*64.);
267 pattern[i] = patternLength;
270 for (
int i = 0; i < patternSize; ++i) {
271 patternLength += (int)
qMax(1., penPattern.
at(patternSize - 1 - i)*64.);
272 reversePattern[i] = patternLength;
274 strokeSelection |=
Dashed;
280 qreal width = state->lastPen.widthF();
283 else if (state->lastPen.isCosmetic())
284 opacity = (
int) 256*width;
286 opacity = (int) 256*width*state->txscale;
287 opacity =
qBound(0, opacity, 256);
289 drawCaps = state->lastPen.capStyle() !=
Qt::FlatCap;
302 xmin = deviceRect.left() - 1;
303 xmax = deviceRect.right() + 2;
304 ymin = deviceRect.top() - 1;
305 ymax = deviceRect.bottom() + 2;
319 y1 += (y2 - y1)/(x2 - x1) * (xmin - x1);
321 }
else if (x1 > xmax) {
324 y1 += (y2 - y1)/(x2 - x1) * (xmax - x1);
329 y2 += (y2 - y1)/(x2 - x1) * (xmin - x2);
331 }
else if (x2 > xmax) {
333 y2 += (y2 - y1)/(x2 - x1) * (xmax - x2);
340 x1 += (x2 - x1)/(y2 - y1) * (ymin - y1);
342 }
else if (y1 > ymax) {
345 x1 += (x2 - x1)/(y2 - y1) * (ymax - y1);
350 x2 += (x2 - x1)/(y2 - y1) * (ymin - y2);
352 }
else if (y2 > ymax) {
354 x2 += (x2 - x1)/(y2 - y1) * (ymax - y2);
373 QPointF start = p1 * state->matrix;
376 patternOffset = state->lastPen.dashOffset()*64;
379 stroke(
this, start.
x(), start.
y(), end.
x(), end.
y(), drawCaps ? CapBegin|CapEnd : 0);
381 blend(current_span, spans, &state->penData);
388 while (points < end) {
394 blend(current_span, spans, &state->penData);
401 while (points < end) {
402 QPointF p = (*points) * state->matrix;
407 blend(current_span, spans, &state->penData);
432 int dx =
qAbs(x2 - x1);
433 int dy =
qAbs(y2 - y1);
437 bool swapped =
false;
446 int y = (y1 + 32) >> 6;
447 int ys = (y2 + 32) >> 6;
450 x += ( ((((y << 6) + 32 - y1))) * xinc ) >> 6;
453 lastPixel.x = x >> 16;
457 lastPixel.x = (x + (ys - y - 1)*xinc) >> 16;
458 lastPixel.y = ys - 1;
461 lastAxisAligned =
qAbs(xinc) < (1 << 14);
468 bool swapped =
false;
477 int x = (x1 + 32) >> 6;
478 int xs = (x2 + 32) >> 6;
481 y += ( ((((x << 6) + 32 - x1))) * yinc ) >> 6;
485 lastPixel.y = y >> 16;
488 lastPixel.x = xs - 1;
489 lastPixel.y = (y + (xs - x - 1)*yinc) >> 16;
492 lastAxisAligned =
qAbs(yinc) < (1 << 14);
499 const qreal *points,
bool *closed)
511 int offset = t - start - 1;
513 *closed = (points[0] == points[2*offset] && points[1] == points[2*offset + 1]);
535 patternOffset = state->lastPen.dashOffset()*64;
545 calculateLastPoint(p1.x(), p1.y(), p2.
x(), p2.
y());
547 int caps = (!closed & drawCaps) ? CapBegin : NoCaps;
561 if (!closed && drawCaps && type == e - 1)
563 stroke(
this, p.x(), p.y(), p2.
x(), p2.
y(), caps);
570 if (!closed && drawCaps && type == e - 3)
574 renderCubic(p, p2, p3, p4, caps);
581 Q_ASSERT(!
"QPainterPath::toSubpathPolygons(), bad element type");
590 patternOffset = state->lastPen.dashOffset()*64;
594 const qreal *begin = points;
597 bool closed = path.
hasImplicitClose() || (points[0] == end[-2] && points[1] == end[-1]);
598 int caps = (!closed & drawCaps) ? CapBegin : NoCaps;
601 calculateLastPoint(p2.
x(), p2.
y(), p.
x(), p.
y());
604 bool fastPenAliased = (state->flags.fast_pen && !state->flags.antialiased);
606 while (points < end) {
609 if (!closed && drawCaps && points == end - 2)
613 bool unclipped = stroke(
this, p.
x(), p.
y(), p2.
x(), p2.
y(), caps);
623 if (fastPenAliased && unclipped) {
624 if (last.
x != lastPixel.x || last.
y != lastPixel.y
625 || points == begin + 2 || points == end - 2) {
635 stroke(
this, p.
x(), p.
y(), movedTo.
x(), movedTo.
y(), NoCaps);
639 blend(current_span, spans, &state->penData);
646 const int maxSubDivisions = 6;
647 PointF points[3*maxSubDivisions + 4];
649 points[3].
x = p1.
x();
650 points[3].
y = p1.
y();
651 points[2].
x = p2.
x();
652 points[2].
y = p2.
y();
653 points[1].
x = p3.
x();
654 points[1].
y = p3.
y();
655 points[0].
x = p4.
x();
656 points[0].
y = p4.
y();
659 int level = maxSubDivisions;
661 renderCubicSubdivision(p, level, caps);
666 const qreal half = .5;
669 points[6].
x = points[3].
x;
672 points[1].
x = a = ( points[0].
x +
c ) * half;
673 points[5].
x = b = ( points[3].
x +
d ) * half;
674 c = ( c +
d ) * half;
675 points[2].
x = a = ( a +
c ) * half;
676 points[4].
x = b = ( b +
c ) * half;
677 points[3].
x = ( a + b ) * half;
679 points[6].
y = points[3].
y;
682 points[1].
y = a = ( points[0].
y +
c ) * half;
683 points[5].
y = b = ( points[3].
y +
d ) * half;
684 c = ( c +
d ) * half;
685 points[2].
y = a = ( a +
c ) * half;
686 points[4].
y = b = ( b +
c ) * half;
687 points[3].
y = ( a + b ) * half;
693 qreal dx = points[3].
x - points[0].
x;
694 qreal dy = points[3].
y - points[0].
y;
697 if (
qAbs(dx * (points[0].y - points[2].y) - dy * (points[0].x - points[2].x)) >= len ||
698 qAbs(dx * (points[0].y - points[1].y) - dy * (points[0].x - points[1].x)) >= len) {
702 renderCubicSubdivision(points + 3, level, caps & CapBegin);
703 renderCubicSubdivision(points, level, caps & CapEnd);
708 stroke(
this, points[3].x, points[3].y, points[0].x, points[0].y, caps);
713 return ((caps & QCosmeticStroker::CapBegin) << 1) |
718 static inline void capAdjust(
int caps,
int &x1,
int &x2,
int &y,
int yinc)
720 if (caps & QCosmeticStroker::CapBegin) {
733 template<DrawPixel drawPixel,
class Dasher>
736 if (stroker->
clipLine(rx1, ry1, rx2, ry2))
739 static const int half = 31;
745 int dx =
qAbs(x2 - x1);
746 int dy =
qAbs(y2 - y1);
756 bool swapped =
false;
772 int y = (y1 + 32) >> 6;
773 int ys = (y2 + 32) >> 6;
776 x += ( ((((y << 6) + 32 - y1))) * xinc ) >> 6;
782 last.
x = (x + (ys - y - 1)*xinc) >> 16;
787 bool axisAligned =
qAbs(xinc) < (1 << 14);
798 }
else if (stroker->
lastDir != dir &&
815 Dasher dasher(stroker, swapped, y << 6, ys << 6);
831 bool swapped =
false;
847 int x = (x1 + 32) >> 6;
848 int xs = (x2 + 32) >> 6;
851 y += ( ((((x << 6) + 32 - x1))) * yinc ) >> 6;
858 last.
y = (y + (xs - x - 1)*yinc) >> 16;
862 bool axisAligned =
qAbs(yinc) < (1 << 14);
872 }
else if (stroker->
lastDir != dir &&
889 Dasher dasher(stroker, swapped, x << 6, xs << 6);
904 template<DrawPixel drawPixel,
class Dasher>
907 if (stroker->
clipLine(rx1, ry1, rx2, ry2))
923 bool swapped =
false;
931 int x = (x1 - 32) << 10;
932 x -= ( ((y1 & 63) - 32) * xinc ) >> 6;
936 Dasher dasher(stroker, swapped, y1, y2);
941 int alphaStart, alphaEnd;
943 alphaStart = y2 - y1;
944 Q_ASSERT(alphaStart >= 0 && alphaStart < 64);
947 alphaStart = 64 - (y1 & 63);
948 alphaEnd = (y2 & 63);
956 drawPixel(stroker, x>>16, y, (255-alpha) * alphaStart >> 6);
957 drawPixel(stroker, (x>>16) + 1, y, alpha * alphaStart >> 6);
966 drawPixel(stroker, x>>16, y, (255-alpha));
967 drawPixel(stroker, (x>>16) + 1, y, alpha);
974 if (alphaEnd && dasher.on()) {
976 drawPixel(stroker, x>>16, y, (255-alpha) * alphaEnd >> 6);
977 drawPixel(stroker, (x>>16) + 1, y, alpha * alphaEnd >> 6);
986 bool swapped =
false;
994 int y = (y1 - 32) << 10;
995 y -= ( ((x1 & 63) - 32) * yinc ) >> 6;
999 Dasher dasher(stroker, swapped, x1, x2);
1006 int alphaStart, alphaEnd;
1008 alphaStart = x2 - x1;
1009 Q_ASSERT(alphaStart >= 0 && alphaStart < 64);
1012 alphaStart = 64 - (x1 & 63);
1013 alphaEnd = (x2 & 63);
1019 drawPixel(stroker, x, y>>16, (255-alpha) * alphaStart >> 6);
1020 drawPixel(stroker, x, (y>>16) + 1, alpha * alphaStart >> 6);
1030 drawPixel(stroker, x, y>>16, (255-alpha));
1031 drawPixel(stroker, x, (y>>16) + 1, alpha);
1038 if (alphaEnd && dasher.on()) {
1040 drawPixel(stroker, x, y>>16, (255-alpha) * alphaEnd >> 6);
1041 drawPixel(stroker, x, (y>>16) + 1, alpha * alphaEnd >> 6);
ElementType
This enum describes the types of elements used to connect vertices in subpaths.
static StrokeLine strokeLine(int strokeSelection)
#define QT_END_NAMESPACE
This macro expands to.
static bool drawLineAA(QCosmeticStroker *stroker, qreal x1, qreal y1, qreal x2, qreal y2, int caps)
void drawLine(const QPointF &p1, const QPointF &p2)
static C reverse(const C &l)
The QPointF class defines a point in the plane using floating point precision.
static bool clipLine(QLineF *line, const QRect &rect)
long ASN1_INTEGER_get ASN1_INTEGER * a
void drawPixelARGB32(QCosmeticStroker *stroker, int x, int y, int coverage)
int bottom() const
Returns the y-coordinate of the rectangle's bottom edge.
The QString class provides a Unicode character string.
Q_DECL_CONSTEXPR T qAbs(const T &t)
static void splitCubic(QCosmeticStroker::PointF *points)
static int F16Dot16FixedDiv(int x, int y)
const QPainterPath::ElementType * elements() const
static void capAdjust(int caps, int &x1, int &x2, int &y, int yinc)
Q_DECL_CONSTEXPR const T & qMax(const T &a, const T &b)
qreal x() const
Returns the x-coordinate of this point.
int qAlpha(QRgb rgba)
Returns the alpha component of the ARGB quadruplet rgba.
Q_STATIC_INLINE_FUNCTION uint BYTE_MUL(uint x, uint a)
#define QT_BEGIN_NAMESPACE
This macro expands to.
void renderCubic(const QPointF &p1, const QPointF &p2, const QPointF &p3, const QPointF &p4, int caps)
Q_STATIC_INLINE_FUNCTION uint INTERPOLATE_PIXEL_256(uint x, uint a, uint y, uint b)
#define QT_PREPEND_NAMESPACE(name)
This macro qualifies identifier with the full namespace.
void(* DrawPixel)(QCosmeticStroker *stroker, int x, int y, int coverage)
bool(* StrokeLine)(QCosmeticStroker *stroker, qreal x1, qreal y1, qreal x2, qreal y2, int caps)
static uint sourceOver(uint d, uint color)
void drawPixelARGB32Opaque(QCosmeticStroker *stroker, int x, int y, int)
void qSwap(T &value1, T &value2)
const T & at(int i) const
Returns the item at index position i in the vector.
void drawPoints(const QPoint *points, int num)
static bool drawLine(QCosmeticStroker *stroker, qreal x1, qreal y1, qreal x2, qreal y2, int caps)
int right() const
Returns the x-coordinate of the rectangle's right edge.
static int swapCaps(int caps)
int y() const
Returns the y-coordinate of the rectangle's top edge.
int x() const
Returns the x-coordinate of the rectangle's left edge.
The QPoint class defines a point in the plane using integer precision.
Q_DECL_CONSTEXPR const T & qBound(const T &min, const T &val, const T &max)
const qreal * points() const
The QRect class defines a rectangle in the plane using integer precision.
bool hasImplicitClose() const
static void drawPoints(const T *points, int n, const QTransform &transform, IDirectFBSurface *surface)
qreal y() const
Returns the y-coordinate of this point.
void calculateLastPoint(qreal rx1, qreal ry1, qreal rx2, qreal ry2)
bool isEmpty() const
Returns true if the vector has size 0; otherwise returns false.
void drawPixel(QCosmeticStroker *stroker, int x, int y, int coverage)
bool clipLine(qreal &x1, qreal &y1, qreal &x2, qreal &y2)
static const KeyPair *const end
void drawPath(const QVectorPath &path)
int size() const
Returns the number of items in the vector.
QRasterPaintEngineState * state
void renderCubicSubdivision(PointF *points, int level, int caps)
static const QPainterPath::ElementType * subPath(const QPainterPath::ElementType *t, const QPainterPath::ElementType *end, const qreal *points, bool *closed)
Q_DECL_CONSTEXPR int qRound(qreal d)