summaryrefslogtreecommitdiffstats
path: root/src/gui/painting
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2020-05-29 11:56:16 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2020-11-09 14:04:13 +0100
commit04413b9dd8f3983fd5471354a48ad1257ca4f290 (patch)
treed5483c6d5f07251c18306e7f29ccbe5430b0761c /src/gui/painting
parentccc205bf38ffbe60180a069939a4aff01e7734e5 (diff)
Allow painting above INT16_MAX on 64-bit architectures
The logic in qgrayraster was ready for it except for an intermediate format. qrasterizer.cpp and qcosmeticstroker.cpp uses a dot-16 fixed point format, and had to be changed to handle higher coordinates on 64-bit architectures. Fixes: QTBUG-84428 Change-Id: I85ab7a04e38bd0dbcefa9f16c16ccc84785a33cf Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Diffstat (limited to 'src/gui/painting')
-rw-r--r--src/gui/painting/qcosmeticstroker.cpp40
-rw-r--r--src/gui/painting/qgrayraster.c32
-rw-r--r--src/gui/painting/qoutlinemapper_p.h11
-rw-r--r--src/gui/painting/qpaintengine_raster.cpp10
-rw-r--r--src/gui/painting/qrasterdefs_p.h8
-rw-r--r--src/gui/painting/qrasterizer.cpp285
6 files changed, 204 insertions, 182 deletions
diff --git a/src/gui/painting/qcosmeticstroker.cpp b/src/gui/painting/qcosmeticstroker.cpp
index 74e4fcb96f..9e06a3f109 100644
--- a/src/gui/painting/qcosmeticstroker.cpp
+++ b/src/gui/painting/qcosmeticstroker.cpp
@@ -58,6 +58,12 @@ inline QString capString(int caps)
}
#endif
+#if Q_PROCESSOR_WORDSIZE == 8
+typedef qint64 FDot16;
+#else
+typedef int FDot16;
+#endif
+
#define toF26Dot6(x) ((int)((x)*64.))
static inline uint sourceOver(uint d, uint color)
@@ -65,11 +71,15 @@ static inline uint sourceOver(uint d, uint color)
return color + BYTE_MUL(d, qAlpha(~color));
}
-inline static int F16Dot16FixedDiv(int x, int y)
+inline static FDot16 FDot16FixedDiv(int x, int y)
{
+#if Q_PROCESSOR_WORDSIZE == 8
+ return FDot16(x) * (1<<16) / y;
+#else
if (qAbs(x) > 0x7fff)
return qlonglong(x) * (1<<16) / y;
return x * (1<<16) / y;
+#endif
}
typedef void (*DrawPixel)(QCosmeticStroker *stroker, int x, int y, int coverage);
@@ -157,7 +167,7 @@ inline void drawPixel(QCosmeticStroker *stroker, int x, int y, int coverage)
}
}
- stroker->spans[stroker->current_span].x = ushort(x);
+ stroker->spans[stroker->current_span].x = x;
stroker->spans[stroker->current_span].len = 1;
stroker->spans[stroker->current_span].y = y;
stroker->spans[stroker->current_span].coverage = coverage*stroker->opacity >> 8;
@@ -441,8 +451,8 @@ void QCosmeticStroker::calculateLastPoint(qreal rx1, qreal ry1, qreal rx2, qreal
qSwap(y1, y2);
qSwap(x1, x2);
}
- int xinc = F16Dot16FixedDiv(x2 - x1, y2 - y1);
- int x = x1 * (1<<10);
+ FDot16 xinc = FDot16FixedDiv(x2 - x1, y2 - y1);
+ FDot16 x = FDot16(x1) * (1<<10);
int y = (y1 + 32) >> 6;
int ys = (y2 + 32) >> 6;
@@ -473,8 +483,8 @@ void QCosmeticStroker::calculateLastPoint(qreal rx1, qreal ry1, qreal rx2, qreal
qSwap(x1, x2);
qSwap(y1, y2);
}
- int yinc = F16Dot16FixedDiv(y2 - y1, x2 - x1);
- int y = y1 * (1 << 10);
+ FDot16 yinc = FDot16FixedDiv(y2 - y1, x2 - x1);
+ FDot16 y = FDot16(y1) * (1 << 10);
int x = (x1 + 32) >> 6;
int xs = (x2 + 32) >> 6;
@@ -715,7 +725,7 @@ static inline int swapCaps(int caps)
}
// adjust line by half a pixel
-static inline void capAdjust(int caps, int &x1, int &x2, int &y, int yinc)
+static inline void capAdjust(int caps, int &x1, int &x2, FDot16 &y, FDot16 yinc)
{
if (caps & QCosmeticStroker::CapBegin) {
x1 -= 32;
@@ -763,8 +773,8 @@ static bool drawLine(QCosmeticStroker *stroker, qreal rx1, qreal ry1, qreal rx2,
caps = swapCaps(caps);
dir = QCosmeticStroker::BottomToTop;
}
- int xinc = F16Dot16FixedDiv(x2 - x1, y2 - y1);
- int x = x1 * (1<<10);
+ FDot16 xinc = FDot16FixedDiv(x2 - x1, y2 - y1);
+ FDot16 x = FDot16(x1) * (1<<10);
if ((stroker->lastDir ^ QCosmeticStroker::VerticalMask) == dir)
caps |= swapped ? QCosmeticStroker::CapEnd : QCosmeticStroker::CapBegin;
@@ -853,8 +863,8 @@ static bool drawLine(QCosmeticStroker *stroker, qreal rx1, qreal ry1, qreal rx2,
caps = swapCaps(caps);
dir = QCosmeticStroker::RightToLeft;
}
- int yinc = F16Dot16FixedDiv(y2 - y1, x2 - x1);
- int y = y1 * (1<<10);
+ FDot16 yinc = FDot16FixedDiv(y2 - y1, x2 - x1);
+ FDot16 y = FDot16(y1) * (1<<10);
if ((stroker->lastDir ^ QCosmeticStroker::HorizontalMask) == dir)
caps |= swapped ? QCosmeticStroker::CapEnd : QCosmeticStroker::CapBegin;
@@ -950,7 +960,7 @@ static bool drawLineAA(QCosmeticStroker *stroker, qreal rx1, qreal ry1, qreal rx
if (qAbs(dx) < qAbs(dy)) {
// vertical
- int xinc = F16Dot16FixedDiv(dx, dy);
+ FDot16 xinc = FDot16FixedDiv(dx, dy);
bool swapped = false;
if (y1 > y2) {
@@ -960,7 +970,7 @@ static bool drawLineAA(QCosmeticStroker *stroker, qreal rx1, qreal ry1, qreal rx
caps = swapCaps(caps);
}
- int x = (x1 - 32) * (1<<10);
+ FDot16 x = FDot16(x1 - 32) * (1<<10);
x -= ( ((y1 & 63) - 32) * xinc ) >> 6;
capAdjust(caps, y1, y2, x, xinc);
@@ -1013,7 +1023,7 @@ static bool drawLineAA(QCosmeticStroker *stroker, qreal rx1, qreal ry1, qreal rx
if (!dx)
return true;
- int yinc = F16Dot16FixedDiv(dy, dx);
+ FDot16 yinc = FDot16FixedDiv(dy, dx);
bool swapped = false;
if (x1 > x2) {
@@ -1023,7 +1033,7 @@ static bool drawLineAA(QCosmeticStroker *stroker, qreal rx1, qreal ry1, qreal rx
caps = swapCaps(caps);
}
- int y = (y1 - 32) * (1<<10);
+ FDot16 y = FDot16(y1 - 32) * (1<<10);
y -= ( ((x1 & 63) - 32) * yinc ) >> 6;
capAdjust(caps, x1, x2, y, yinc);
diff --git a/src/gui/painting/qgrayraster.c b/src/gui/painting/qgrayraster.c
index 8eb6c11f3f..d457943a3a 100644
--- a/src/gui/painting/qgrayraster.c
+++ b/src/gui/painting/qgrayraster.c
@@ -1101,7 +1101,7 @@ QT_FT_END_STMNT
L = QT_FT_HYPOT( dx_, dy_ );
/* Avoid possible arithmetic overflow below by splitting. */
- if ( L > 32767 )
+ if ( L >= (1 << 23) )
goto Split;
/* Max deviation may be as much as (s/L) * 3/4 (if Hain's v = 1). */
@@ -1251,13 +1251,13 @@ QT_FT_END_STMNT
y += (TCoord)ras.min_ey;
x += (TCoord)ras.min_ex;
- /* QT_FT_Span.x is a 16-bit short, so limit our coordinates appropriately */
- if ( x >= 32767 )
- x = 32767;
+ /* QT_FT_Span.x is an int, so limit our coordinates appropriately */
+ if ( x >= (1 << 23) )
+ x = (1 << 23) - 1;
- /* QT_FT_Span.y is a 16-bit short, so limit our coordinates appropriately */
- if ( y >= 32767 )
- y = 32767;
+ /* QT_FT_Span.y is an int, so limit our coordinates appropriately */
+ if ( y >= (1 << 23) )
+ y = (1 << 23) - 1;
if ( coverage )
{
@@ -1271,10 +1271,10 @@ QT_FT_END_STMNT
span = ras.gray_spans + count - 1;
if ( count > 0 &&
span->y == y &&
- (int)span->x + span->len == (int)x &&
+ span->x + span->len == x &&
span->coverage == coverage )
{
- span->len = (unsigned short)( span->len + acount );
+ span->len = span->len + acount;
return;
}
@@ -1317,9 +1317,9 @@ QT_FT_END_STMNT
span++;
/* add a gray span to the current list */
- span->x = (short)x;
- span->len = (unsigned short)acount;
- span->y = (short)y;
+ span->x = x;
+ span->len = acount;
+ span->y = y;
span->coverage = (unsigned char)coverage;
ras.num_gray_spans++;
@@ -1895,10 +1895,10 @@ QT_FT_END_STMNT
}
else
{
- ras.clip_box.xMin = -32768L;
- ras.clip_box.yMin = -32768L;
- ras.clip_box.xMax = 32767L;
- ras.clip_box.yMax = 32767L;
+ ras.clip_box.xMin = -(1 << 23);
+ ras.clip_box.yMin = -(1 << 23);
+ ras.clip_box.xMax = (1 << 23) - 1;
+ ras.clip_box.yMax = (1 << 23) - 1;
}
gray_init_cells( worker, raster->buffer, raster->buffer_size );
diff --git a/src/gui/painting/qoutlinemapper_p.h b/src/gui/painting/qoutlinemapper_p.h
index 04a68797c2..b796fcca4b 100644
--- a/src/gui/painting/qoutlinemapper_p.h
+++ b/src/gui/painting/qoutlinemapper_p.h
@@ -66,10 +66,13 @@
QT_BEGIN_NAMESPACE
-// This limitations comes from qgrayraster.c. Any higher and
-// rasterization of shapes will produce incorrect results.
-const int QT_RASTER_COORD_LIMIT = 32767;
-
+// These limitations comes from qrasterizer.cpp, qcosmeticstroker.cpp, and qgrayraster.c.
+// Any higher and rasterization of shapes will produce incorrect results.
+#if Q_PROCESSOR_WORDSIZE == 8
+constexpr int QT_RASTER_COORD_LIMIT = ((1<<23) - 1); // F24dot8 in qgrayraster.c
+#else
+constexpr int QT_RASTER_COORD_LIMIT = ((1<<15) - 1); // F16dot16 in qrasterizer.cpp and qcosmeticstroker.cpp
+#endif
//#define QT_DEBUG_CONVERT
Q_GUI_EXPORT bool qt_scaleForTransform(const QTransform &transform, qreal *scale);
diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp
index a82d8df8b5..b458a2d627 100644
--- a/src/gui/painting/qpaintengine_raster.cpp
+++ b/src/gui/painting/qpaintengine_raster.cpp
@@ -4142,10 +4142,10 @@ static void qt_span_fill_clipped(int spanCount, const QSpan *spans, void *userDa
static int qt_intersect_spans(QT_FT_Span *&spans, int numSpans,
const QRect &clip)
{
- const short minx = clip.left();
- const short miny = clip.top();
- const short maxx = clip.right();
- const short maxy = clip.bottom();
+ const int minx = clip.left();
+ const int miny = clip.top();
+ const int maxx = clip.right();
+ const int maxy = clip.bottom();
QT_FT_Span *end = spans + numSpans;
while (spans < end) {
@@ -4167,7 +4167,7 @@ static int qt_intersect_spans(QT_FT_Span *&spans, int numSpans,
s->len = qMin(s->len - (minx - s->x), maxx - minx + 1);
s->x = minx;
} else {
- s->len = qMin(s->len, ushort(maxx - s->x + 1));
+ s->len = qMin(s->len, (maxx - s->x + 1));
}
++s;
}
diff --git a/src/gui/painting/qrasterdefs_p.h b/src/gui/painting/qrasterdefs_p.h
index bf57a84c24..f1ab64a70e 100644
--- a/src/gui/painting/qrasterdefs_p.h
+++ b/src/gui/painting/qrasterdefs_p.h
@@ -865,10 +865,10 @@ QT_FT_BEGIN_HEADER
/* */
typedef struct QT_FT_Span_
{
- short x;
- unsigned short len;
- short y;
- unsigned char coverage;
+ int x;
+ int len;
+ int y;
+ unsigned char coverage;
} QT_FT_Span;
diff --git a/src/gui/painting/qrasterizer.cpp b/src/gui/painting/qrasterizer.cpp
index e6f48a79b8..3902b072c9 100644
--- a/src/gui/painting/qrasterizer.cpp
+++ b/src/gui/painting/qrasterizer.cpp
@@ -52,15 +52,20 @@
QT_BEGIN_NAMESPACE
-typedef int Q16Dot16;
-#define Q16Dot16ToFloat(i) ((i)/65536.)
-#define FloatToQ16Dot16(i) (int)((i) * 65536.)
-#define IntToQ16Dot16(i) ((i) * (1 << 16))
-#define Q16Dot16ToInt(i) ((i) >> 16)
-#define Q16Dot16Factor 65536
-
-#define Q16Dot16Multiply(x, y) (int)((qlonglong(x) * qlonglong(y)) >> 16)
-#define Q16Dot16FastMultiply(x, y) (((x) * (y)) >> 16)
+#if Q_PROCESSOR_WORDSIZE == 8
+typedef qint64 QScFixed;
+#else
+typedef int QScFixed;
+#endif
+#define QScFixedToFloat(i) ((i) * (1./65536.))
+#define FloatToQScFixed(i) (QScFixed)((i) * 65536.)
+#define IntToQScFixed(i) ((QScFixed)(i) * (1 << 16))
+#define QScFixedToInt(i) ((i) >> 16)
+#define QScFixedFactor 65536
+#define FTPosToQScFixed(i) ((QScFixed)(i) * (1 << 10))
+
+#define QScFixedMultiply(x, y) (QScFixed)((qlonglong(x) * qlonglong(y)) >> 16)
+#define QScFixedFastMultiply(x, y) (((x) * (y)) >> 16)
#define SPAN_BUFFER_SIZE 256
@@ -88,11 +93,12 @@ public:
flushSpans();
}
- void addSpan(int x, unsigned int len, int y, unsigned char coverage)
+ void addSpan(int x, int len, int y, int coverage)
{
if (!coverage || !len)
return;
+ Q_ASSERT(coverage >= 0 && coverage <= 255);
Q_ASSERT(y >= m_clipRect.top());
Q_ASSERT(y <= m_clipRect.bottom());
Q_ASSERT(x >= m_clipRect.left());
@@ -140,8 +146,8 @@ public:
struct Line
{
- Q16Dot16 x;
- Q16Dot16 delta;
+ QScFixed x;
+ QScFixed delta;
int top, bottom;
@@ -157,7 +163,7 @@ private:
int left, right;
};
- inline bool clip(Q16Dot16 &xFP, int &iTop, int &iBottom, Q16Dot16 slopeFP, Q16Dot16 edgeFP, int winding);
+ inline bool clip(QScFixed &xFP, int &iTop, int &iBottom, QScFixed slopeFP, QScFixed edgeFP, int winding);
inline void mergeIntersection(Intersection *head, const Intersection &isect);
void prepareChunk();
@@ -175,8 +181,8 @@ private:
int m_top;
int m_bottom;
- Q16Dot16 m_leftFP;
- Q16Dot16 m_rightFP;
+ QScFixed m_leftFP;
+ QScFixed m_rightFP;
int m_fillRuleMask;
bool m_legacyRounding;
@@ -228,8 +234,8 @@ void QScanConverter::begin(int top, int bottom, int left, int right,
{
m_top = top;
m_bottom = bottom;
- m_leftFP = IntToQ16Dot16(left);
- m_rightFP = IntToQ16Dot16(right + 1);
+ m_leftFP = IntToQScFixed(left);
+ m_rightFP = IntToQScFixed(right + 1);
m_lines.reset();
@@ -350,7 +356,7 @@ void QScanConverter::scanConvert()
for (int i = 0; i < numActive; ++i) {
QScanConverter::Line *node = m_active.at(i);
- const int current = Q16Dot16ToInt(node->x);
+ const int current = QScFixedToInt(node->x);
if (winding & m_fillRuleMask)
m_spanBuffer->addSpan(x, current - x, y, 0xff);
@@ -414,12 +420,12 @@ void QScanConverter::end()
if (line.delta) {
for (; it != end; ++it) {
- isect.x = Q16Dot16ToInt(line.x);
+ isect.x = QScFixedToInt(line.x);
line.x += line.delta;
mergeIntersection(it, isect);
}
} else {
- isect.x = Q16Dot16ToInt(line.x);
+ isect.x = QScFixedToInt(line.x);
for (; it != end; ++it)
mergeIntersection(it, isect);
}
@@ -516,7 +522,7 @@ void QScanConverter::mergeCurve(const QT_FT_Vector &pa, const QT_FT_Vector &pb,
}
}
-inline bool QScanConverter::clip(Q16Dot16 &xFP, int &iTop, int &iBottom, Q16Dot16 slopeFP, Q16Dot16 edgeFP, int winding)
+inline bool QScanConverter::clip(QScFixed &xFP, int &iTop, int &iBottom, QScFixed slopeFP, QScFixed edgeFP, int winding)
{
bool right = edgeFP == m_rightFP;
@@ -530,7 +536,7 @@ inline bool QScanConverter::clip(Q16Dot16 &xFP, int &iTop, int &iBottom, Q16Dot1
}
}
- Q16Dot16 lastFP = xFP + slopeFP * (iBottom - iTop);
+ QScFixed lastFP = xFP + slopeFP * (iBottom - iTop);
if (lastFP == edgeFP) {
if ((slopeFP < 0) ^ right)
@@ -544,11 +550,11 @@ inline bool QScanConverter::clip(Q16Dot16 &xFP, int &iTop, int &iBottom, Q16Dot1
// does line cross edge?
if ((lastFP < edgeFP) ^ (xFP < edgeFP)) {
- Q16Dot16 deltaY = Q16Dot16((edgeFP - xFP) / Q16Dot16ToFloat(slopeFP));
+ QScFixed deltaY = QScFixed((edgeFP - xFP) / QScFixedToFloat(slopeFP));
if ((xFP < edgeFP) ^ right) {
// top segment needs to be clipped
- int iHeight = Q16Dot16ToInt(deltaY + 1);
+ int iHeight = QScFixedToInt(deltaY + 1);
int iMiddle = iTop + iHeight;
Line line = { edgeFP, 0, iTop, iMiddle, winding };
@@ -561,7 +567,7 @@ inline bool QScanConverter::clip(Q16Dot16 &xFP, int &iTop, int &iBottom, Q16Dot1
return true;
} else {
// bottom segment needs to be clipped
- int iHeight = Q16Dot16ToInt(deltaY);
+ int iHeight = QScFixedToInt(deltaY);
int iMiddle = iTop + iHeight;
if (iMiddle != iBottom) {
@@ -603,7 +609,7 @@ void QScanConverter::mergeLine(QT_FT_Vector a, QT_FT_Vector b)
int iBottom = qMin(m_bottom, int((b.y - 32 - rounding) >> 6));
if (iTop <= iBottom) {
- Q16Dot16 aFP = Q16Dot16Factor/2 + (a.x * (1 << 10)) - rounding;
+ QScFixed aFP = QScFixedFactor/2 + FTPosToQScFixed(a.x - rounding);
if (b.x == a.x) {
Line line = { qBound(m_leftFP, aFP, m_rightFP), 0, iTop, iBottom, winding };
@@ -611,11 +617,11 @@ void QScanConverter::mergeLine(QT_FT_Vector a, QT_FT_Vector b)
} else {
const qreal slope = (b.x - a.x) / qreal(b.y - a.y);
- const Q16Dot16 slopeFP = FloatToQ16Dot16(slope);
+ const QScFixed slopeFP = FloatToQScFixed(slope);
- Q16Dot16 xFP = aFP + Q16Dot16Multiply(slopeFP,
- IntToQ16Dot16(iTop)
- + Q16Dot16Factor/2 - (a.y * (1 << 10)));
+ QScFixed xFP = aFP + QScFixedMultiply(slopeFP,
+ IntToQScFixed(iTop)
+ + QScFixedFactor/2 - FTPosToQScFixed(a.y));
if (clip(xFP, iTop, iBottom, slopeFP, m_leftFP, winding))
return;
@@ -663,37 +669,37 @@ void QRasterizer::setLegacyRoundingEnabled(bool legacyRoundingEnabled)
d->legacyRounding = legacyRoundingEnabled;
}
-static Q16Dot16 intersectPixelFP(int x, Q16Dot16 top, Q16Dot16 bottom, Q16Dot16 leftIntersectX, Q16Dot16 rightIntersectX, Q16Dot16 slope, Q16Dot16 invSlope)
+static QScFixed intersectPixelFP(int x, QScFixed top, QScFixed bottom, QScFixed leftIntersectX, QScFixed rightIntersectX, QScFixed slope, QScFixed invSlope)
{
- Q16Dot16 leftX = IntToQ16Dot16(x);
- Q16Dot16 rightX = IntToQ16Dot16(x) + Q16Dot16Factor;
+ QScFixed leftX = IntToQScFixed(x);
+ QScFixed rightX = IntToQScFixed(x) + QScFixedFactor;
- Q16Dot16 leftIntersectY, rightIntersectY;
+ QScFixed leftIntersectY, rightIntersectY;
if (slope > 0) {
- leftIntersectY = top + Q16Dot16Multiply(leftX - leftIntersectX, invSlope);
+ leftIntersectY = top + QScFixedMultiply(leftX - leftIntersectX, invSlope);
rightIntersectY = leftIntersectY + invSlope;
} else {
- leftIntersectY = top + Q16Dot16Multiply(leftX - rightIntersectX, invSlope);
+ leftIntersectY = top + QScFixedMultiply(leftX - rightIntersectX, invSlope);
rightIntersectY = leftIntersectY + invSlope;
}
if (leftIntersectX >= leftX && rightIntersectX <= rightX) {
- return Q16Dot16Multiply(bottom - top, leftIntersectX - leftX + ((rightIntersectX - leftIntersectX) >> 1));
+ return QScFixedMultiply(bottom - top, leftIntersectX - leftX + ((rightIntersectX - leftIntersectX) >> 1));
} else if (leftIntersectX >= rightX) {
return bottom - top;
} else if (leftIntersectX >= leftX) {
if (slope > 0) {
- return (bottom - top) - Q16Dot16FastMultiply((rightX - leftIntersectX) >> 1, rightIntersectY - top);
+ return (bottom - top) - QScFixedFastMultiply((rightX - leftIntersectX) >> 1, rightIntersectY - top);
} else {
- return (bottom - top) - Q16Dot16FastMultiply((rightX - leftIntersectX) >> 1, bottom - rightIntersectY);
+ return (bottom - top) - QScFixedFastMultiply((rightX - leftIntersectX) >> 1, bottom - rightIntersectY);
}
} else if (rightIntersectX <= leftX) {
return 0;
} else if (rightIntersectX <= rightX) {
if (slope > 0) {
- return Q16Dot16FastMultiply((rightIntersectX - leftX) >> 1, bottom - leftIntersectY);
+ return QScFixedFastMultiply((rightIntersectX - leftX) >> 1, bottom - leftIntersectY);
} else {
- return Q16Dot16FastMultiply((rightIntersectX - leftX) >> 1, leftIntersectY - top);
+ return QScFixedFastMultiply((rightIntersectX - leftX) >> 1, leftIntersectY - top);
}
} else {
if (slope > 0) {
@@ -734,14 +740,14 @@ static inline qreal qSafeDivide(qreal x, qreal y)
too small to fit into INT_MIN, so we need this slightly safer conversion
when floating point exceptions are enabled
*/
-static inline int qSafeFloatToQ16Dot16(qreal x)
+static inline QScFixed qSafeFloatToQScFixed(qreal x)
{
- qreal tmp = x * 65536.;
- if (tmp > qreal(INT_MAX))
- return INT_MAX;
- else if (tmp < qreal(INT_MIN))
- return -INT_MAX;
- return int(tmp);
+ qreal tmp = x * QScFixedFactor;
+ if (tmp > qreal(std::numeric_limits<QScFixed>::max()))
+ return std::numeric_limits<QScFixed>::max();
+ else if (tmp < qreal(std::numeric_limits<QScFixed>::min()))
+ return std::numeric_limits<QScFixed>::min();
+ return QScFixed(tmp);
}
void QRasterizer::rasterizeLine(const QPointF &a, const QPointF &b, qreal width, bool squareCap)
@@ -855,30 +861,33 @@ void QRasterizer::rasterizeLine(const QPointF &a, const QPointF &b, qreal width,
return;
if (d->antialiased) {
- const Q16Dot16 iLeft = int(left);
- const Q16Dot16 iRight = int(right);
- const Q16Dot16 leftWidth = IntToQ16Dot16(iLeft + 1)
- - qSafeFloatToQ16Dot16(left);
- const Q16Dot16 rightWidth = qSafeFloatToQ16Dot16(right)
- - IntToQ16Dot16(iRight);
-
- Q16Dot16 coverage[3];
+ const int iLeft = int(left);
+ const int iRight = int(right);
+ const QScFixed leftWidth = IntToQScFixed(iLeft + 1)
+ - qSafeFloatToQScFixed(left);
+ const QScFixed rightWidth = qSafeFloatToQScFixed(right)
+ - IntToQScFixed(iRight);
+
+ QScFixed coverage[3];
int x[3];
int len[3];
int n = 1;
if (iLeft == iRight) {
- coverage[0] = (leftWidth + rightWidth) * 255;
+ if (leftWidth == QScFixedFactor)
+ coverage[0] = rightWidth * 255;
+ else
+ coverage[0] = (leftWidth + rightWidth) * 255;
x[0] = iLeft;
len[0] = 1;
} else {
coverage[0] = leftWidth * 255;
x[0] = iLeft;
len[0] = 1;
- if (leftWidth == Q16Dot16Factor) {
+ if (leftWidth == QScFixedFactor) {
len[0] = iRight - iLeft;
} else if (iRight - iLeft > 1) {
- coverage[1] = IntToQ16Dot16(255);
+ coverage[1] = IntToQScFixed(255);
x[1] = iLeft + 1;
len[1] = iRight - iLeft - 1;
++n;
@@ -891,19 +900,19 @@ void QRasterizer::rasterizeLine(const QPointF &a, const QPointF &b, qreal width,
}
}
- const Q16Dot16 iTopFP = IntToQ16Dot16(int(pa.y()));
- const Q16Dot16 iBottomFP = IntToQ16Dot16(int(pb.y()));
- const Q16Dot16 yPa = qSafeFloatToQ16Dot16(pa.y());
- const Q16Dot16 yPb = qSafeFloatToQ16Dot16(pb.y());
- for (Q16Dot16 yFP = iTopFP; yFP <= iBottomFP; yFP += Q16Dot16Factor) {
- const Q16Dot16 rowHeight = qMin(yFP + Q16Dot16Factor, yPb)
+ const QScFixed iTopFP = IntToQScFixed(int(pa.y()));
+ const QScFixed iBottomFP = IntToQScFixed(int(pb.y()));
+ const QScFixed yPa = qSafeFloatToQScFixed(pa.y());
+ const QScFixed yPb = qSafeFloatToQScFixed(pb.y());
+ for (QScFixed yFP = iTopFP; yFP <= iBottomFP; yFP += QScFixedFactor) {
+ const QScFixed rowHeight = qMin(yFP + QScFixedFactor, yPb)
- qMax(yFP, yPa);
- const int y = Q16Dot16ToInt(yFP);
+ const int y = QScFixedToInt(yFP);
if (y > d->clipRect.bottom())
break;
for (int i = 0; i < n; ++i) {
buffer.addSpan(x[i], len[i], y,
- Q16Dot16ToInt(Q16Dot16Multiply(rowHeight, coverage[i])));
+ QScFixedToInt(QScFixedMultiply(rowHeight, coverage[i])));
}
}
} else { // aliased
@@ -960,111 +969,111 @@ void QRasterizer::rasterizeLine(const QPointF &a, const QPointF &b, qreal width,
const qreal topRightSlope = qSafeDivide(topRightEdge.x(), topRightEdge.y());
const qreal bottomRightSlope = qSafeDivide(bottomRightEdge.x(), bottomRightEdge.y());
- const Q16Dot16 topLeftSlopeFP = qSafeFloatToQ16Dot16(topLeftSlope);
- const Q16Dot16 topRightSlopeFP = qSafeFloatToQ16Dot16(topRightSlope);
+ const QScFixed topLeftSlopeFP = qSafeFloatToQScFixed(topLeftSlope);
+ const QScFixed topRightSlopeFP = qSafeFloatToQScFixed(topRightSlope);
- const Q16Dot16 bottomLeftSlopeFP = qSafeFloatToQ16Dot16(bottomLeftSlope);
- const Q16Dot16 bottomRightSlopeFP = qSafeFloatToQ16Dot16(bottomRightSlope);
+ const QScFixed bottomLeftSlopeFP = qSafeFloatToQScFixed(bottomLeftSlope);
+ const QScFixed bottomRightSlopeFP = qSafeFloatToQScFixed(bottomRightSlope);
- const Q16Dot16 invTopLeftSlopeFP = qSafeFloatToQ16Dot16(qSafeDivide(1, topLeftSlope));
- const Q16Dot16 invTopRightSlopeFP = qSafeFloatToQ16Dot16(qSafeDivide(1, topRightSlope));
+ const QScFixed invTopLeftSlopeFP = qSafeFloatToQScFixed(qSafeDivide(1, topLeftSlope));
+ const QScFixed invTopRightSlopeFP = qSafeFloatToQScFixed(qSafeDivide(1, topRightSlope));
- const Q16Dot16 invBottomLeftSlopeFP = qSafeFloatToQ16Dot16(qSafeDivide(1, bottomLeftSlope));
- const Q16Dot16 invBottomRightSlopeFP = qSafeFloatToQ16Dot16(qSafeDivide(1, bottomRightSlope));
+ const QScFixed invBottomLeftSlopeFP = qSafeFloatToQScFixed(qSafeDivide(1, bottomLeftSlope));
+ const QScFixed invBottomRightSlopeFP = qSafeFloatToQScFixed(qSafeDivide(1, bottomRightSlope));
if (d->antialiased) {
- const Q16Dot16 iTopFP = IntToQ16Dot16(int(topBound));
- const Q16Dot16 iLeftFP = IntToQ16Dot16(int(left.y()));
- const Q16Dot16 iRightFP = IntToQ16Dot16(int(right.y()));
- const Q16Dot16 iBottomFP = IntToQ16Dot16(int(bottomBound));
+ const QScFixed iTopFP = IntToQScFixed(int(topBound));
+ const QScFixed iLeftFP = IntToQScFixed(int(left.y()));
+ const QScFixed iRightFP = IntToQScFixed(int(right.y()));
+ const QScFixed iBottomFP = IntToQScFixed(int(bottomBound));
- Q16Dot16 leftIntersectAf = qSafeFloatToQ16Dot16(top.x() + (int(topBound) - top.y()) * topLeftSlope);
- Q16Dot16 rightIntersectAf = qSafeFloatToQ16Dot16(top.x() + (int(topBound) - top.y()) * topRightSlope);
- Q16Dot16 leftIntersectBf = 0;
- Q16Dot16 rightIntersectBf = 0;
+ QScFixed leftIntersectAf = qSafeFloatToQScFixed(top.x() + (int(topBound) - top.y()) * topLeftSlope);
+ QScFixed rightIntersectAf = qSafeFloatToQScFixed(top.x() + (int(topBound) - top.y()) * topRightSlope);
+ QScFixed leftIntersectBf = 0;
+ QScFixed rightIntersectBf = 0;
if (iLeftFP < iTopFP)
- leftIntersectBf = qSafeFloatToQ16Dot16(left.x() + (int(topBound) - left.y()) * bottomLeftSlope);
+ leftIntersectBf = qSafeFloatToQScFixed(left.x() + (int(topBound) - left.y()) * bottomLeftSlope);
if (iRightFP < iTopFP)
- rightIntersectBf = qSafeFloatToQ16Dot16(right.x() + (int(topBound) - right.y()) * bottomRightSlope);
+ rightIntersectBf = qSafeFloatToQScFixed(right.x() + (int(topBound) - right.y()) * bottomRightSlope);
- Q16Dot16 rowTop, rowBottomLeft, rowBottomRight, rowTopLeft, rowTopRight, rowBottom;
- Q16Dot16 topLeftIntersectAf, topLeftIntersectBf, topRightIntersectAf, topRightIntersectBf;
- Q16Dot16 bottomLeftIntersectAf, bottomLeftIntersectBf, bottomRightIntersectAf, bottomRightIntersectBf;
+ QScFixed rowTop, rowBottomLeft, rowBottomRight, rowTopLeft, rowTopRight, rowBottom;
+ QScFixed topLeftIntersectAf, topLeftIntersectBf, topRightIntersectAf, topRightIntersectBf;
+ QScFixed bottomLeftIntersectAf, bottomLeftIntersectBf, bottomRightIntersectAf, bottomRightIntersectBf;
int leftMin, leftMax, rightMin, rightMax;
- const Q16Dot16 yTopFP = qSafeFloatToQ16Dot16(top.y());
- const Q16Dot16 yLeftFP = qSafeFloatToQ16Dot16(left.y());
- const Q16Dot16 yRightFP = qSafeFloatToQ16Dot16(right.y());
- const Q16Dot16 yBottomFP = qSafeFloatToQ16Dot16(bottom.y());
+ const QScFixed yTopFP = qSafeFloatToQScFixed(top.y());
+ const QScFixed yLeftFP = qSafeFloatToQScFixed(left.y());
+ const QScFixed yRightFP = qSafeFloatToQScFixed(right.y());
+ const QScFixed yBottomFP = qSafeFloatToQScFixed(bottom.y());
rowTop = qMax(iTopFP, yTopFP);
topLeftIntersectAf = leftIntersectAf +
- Q16Dot16Multiply(topLeftSlopeFP, rowTop - iTopFP);
+ QScFixedMultiply(topLeftSlopeFP, rowTop - iTopFP);
topRightIntersectAf = rightIntersectAf +
- Q16Dot16Multiply(topRightSlopeFP, rowTop - iTopFP);
+ QScFixedMultiply(topRightSlopeFP, rowTop - iTopFP);
- Q16Dot16 yFP = iTopFP;
+ QScFixed yFP = iTopFP;
while (yFP <= iBottomFP) {
- rowBottomLeft = qMin(yFP + Q16Dot16Factor, yLeftFP);
- rowBottomRight = qMin(yFP + Q16Dot16Factor, yRightFP);
+ rowBottomLeft = qMin(yFP + QScFixedFactor, yLeftFP);
+ rowBottomRight = qMin(yFP + QScFixedFactor, yRightFP);
rowTopLeft = qMax(yFP, yLeftFP);
rowTopRight = qMax(yFP, yRightFP);
- rowBottom = qMin(yFP + Q16Dot16Factor, yBottomFP);
+ rowBottom = qMin(yFP + QScFixedFactor, yBottomFP);
if (yFP == iLeftFP) {
- const int y = Q16Dot16ToInt(yFP);
- leftIntersectBf = qSafeFloatToQ16Dot16(left.x() + (y - left.y()) * bottomLeftSlope);
- topLeftIntersectBf = leftIntersectBf + Q16Dot16Multiply(bottomLeftSlopeFP, rowTopLeft - yFP);
- bottomLeftIntersectAf = leftIntersectAf + Q16Dot16Multiply(topLeftSlopeFP, rowBottomLeft - yFP);
+ const int y = QScFixedToInt(yFP);
+ leftIntersectBf = qSafeFloatToQScFixed(left.x() + (y - left.y()) * bottomLeftSlope);
+ topLeftIntersectBf = leftIntersectBf + QScFixedMultiply(bottomLeftSlopeFP, rowTopLeft - yFP);
+ bottomLeftIntersectAf = leftIntersectAf + QScFixedMultiply(topLeftSlopeFP, rowBottomLeft - yFP);
} else {
topLeftIntersectBf = leftIntersectBf;
bottomLeftIntersectAf = leftIntersectAf + topLeftSlopeFP;
}
if (yFP == iRightFP) {
- const int y = Q16Dot16ToInt(yFP);
- rightIntersectBf = qSafeFloatToQ16Dot16(right.x() + (y - right.y()) * bottomRightSlope);
- topRightIntersectBf = rightIntersectBf + Q16Dot16Multiply(bottomRightSlopeFP, rowTopRight - yFP);
- bottomRightIntersectAf = rightIntersectAf + Q16Dot16Multiply(topRightSlopeFP, rowBottomRight - yFP);
+ const int y = QScFixedToInt(yFP);
+ rightIntersectBf = qSafeFloatToQScFixed(right.x() + (y - right.y()) * bottomRightSlope);
+ topRightIntersectBf = rightIntersectBf + QScFixedMultiply(bottomRightSlopeFP, rowTopRight - yFP);
+ bottomRightIntersectAf = rightIntersectAf + QScFixedMultiply(topRightSlopeFP, rowBottomRight - yFP);
} else {
topRightIntersectBf = rightIntersectBf;
bottomRightIntersectAf = rightIntersectAf + topRightSlopeFP;
}
if (yFP == iBottomFP) {
- bottomLeftIntersectBf = leftIntersectBf + Q16Dot16Multiply(bottomLeftSlopeFP, rowBottom - yFP);
- bottomRightIntersectBf = rightIntersectBf + Q16Dot16Multiply(bottomRightSlopeFP, rowBottom - yFP);
+ bottomLeftIntersectBf = leftIntersectBf + QScFixedMultiply(bottomLeftSlopeFP, rowBottom - yFP);
+ bottomRightIntersectBf = rightIntersectBf + QScFixedMultiply(bottomRightSlopeFP, rowBottom - yFP);
} else {
bottomLeftIntersectBf = leftIntersectBf + bottomLeftSlopeFP;
bottomRightIntersectBf = rightIntersectBf + bottomRightSlopeFP;
}
if (yFP < iLeftFP) {
- leftMin = Q16Dot16ToInt(bottomLeftIntersectAf);
- leftMax = Q16Dot16ToInt(topLeftIntersectAf);
+ leftMin = QScFixedToInt(bottomLeftIntersectAf);
+ leftMax = QScFixedToInt(topLeftIntersectAf);
} else if (yFP == iLeftFP) {
- leftMin = Q16Dot16ToInt(qMax(bottomLeftIntersectAf, topLeftIntersectBf));
- leftMax = Q16Dot16ToInt(qMax(topLeftIntersectAf, bottomLeftIntersectBf));
+ leftMin = QScFixedToInt(qMax(bottomLeftIntersectAf, topLeftIntersectBf));
+ leftMax = QScFixedToInt(qMax(topLeftIntersectAf, bottomLeftIntersectBf));
} else {
- leftMin = Q16Dot16ToInt(topLeftIntersectBf);
- leftMax = Q16Dot16ToInt(bottomLeftIntersectBf);
+ leftMin = QScFixedToInt(topLeftIntersectBf);
+ leftMax = QScFixedToInt(bottomLeftIntersectBf);
}
leftMin = qBound(d->clipRect.left(), leftMin, d->clipRect.right());
leftMax = qBound(d->clipRect.left(), leftMax, d->clipRect.right());
if (yFP < iRightFP) {
- rightMin = Q16Dot16ToInt(topRightIntersectAf);
- rightMax = Q16Dot16ToInt(bottomRightIntersectAf);
+ rightMin = QScFixedToInt(topRightIntersectAf);
+ rightMax = QScFixedToInt(bottomRightIntersectAf);
} else if (yFP == iRightFP) {
- rightMin = Q16Dot16ToInt(qMin(topRightIntersectAf, bottomRightIntersectBf));
- rightMax = Q16Dot16ToInt(qMin(bottomRightIntersectAf, topRightIntersectBf));
+ rightMin = QScFixedToInt(qMin(topRightIntersectAf, bottomRightIntersectBf));
+ rightMax = QScFixedToInt(qMin(bottomRightIntersectAf, topRightIntersectBf));
} else {
- rightMin = Q16Dot16ToInt(bottomRightIntersectBf);
- rightMax = Q16Dot16ToInt(topRightIntersectBf);
+ rightMin = QScFixedToInt(bottomRightIntersectBf);
+ rightMax = QScFixedToInt(topRightIntersectBf);
}
rightMin = qBound(d->clipRect.left(), rightMin, d->clipRect.right());
@@ -1075,11 +1084,11 @@ void QRasterizer::rasterizeLine(const QPointF &a, const QPointF &b, qreal width,
if (rightMin < leftMin)
rightMin = leftMin;
- Q16Dot16 rowHeight = rowBottom - rowTop;
+ QScFixed rowHeight = rowBottom - rowTop;
int x = leftMin;
while (x <= leftMax) {
- Q16Dot16 excluded = 0;
+ QScFixed excluded = 0;
if (yFP <= iLeftFP)
excluded += intersectPixelFP(x, rowTop, rowBottomLeft,
@@ -1101,18 +1110,18 @@ void QRasterizer::rasterizeLine(const QPointF &a, const QPointF &b, qreal width,
bottomRightSlopeFP, invBottomRightSlopeFP);
}
- Q16Dot16 coverage = rowHeight - excluded;
- buffer.addSpan(x, 1, Q16Dot16ToInt(yFP),
- Q16Dot16ToInt(255 * coverage));
+ QScFixed coverage = rowHeight - excluded;
+ buffer.addSpan(x, 1, QScFixedToInt(yFP),
+ QScFixedToInt(255 * coverage));
++x;
}
if (x < rightMin) {
- buffer.addSpan(x, rightMin - x, Q16Dot16ToInt(yFP),
- Q16Dot16ToInt(255 * rowHeight));
+ buffer.addSpan(x, rightMin - x, QScFixedToInt(yFP),
+ QScFixedToInt(255 * rowHeight));
x = rightMin;
}
while (x <= rightMax) {
- Q16Dot16 excluded = 0;
+ QScFixed excluded = 0;
if (yFP <= iRightFP)
excluded += (rowBottomRight - rowTop) - intersectPixelFP(x, rowTop, rowBottomRight,
topRightIntersectAf, bottomRightIntersectAf,
@@ -1122,9 +1131,9 @@ void QRasterizer::rasterizeLine(const QPointF &a, const QPointF &b, qreal width,
bottomRightIntersectBf, topRightIntersectBf,
bottomRightSlopeFP, invBottomRightSlopeFP);
- Q16Dot16 coverage = rowHeight - excluded;
- buffer.addSpan(x, 1, Q16Dot16ToInt(yFP),
- Q16Dot16ToInt(255 * coverage));
+ QScFixed coverage = rowHeight - excluded;
+ buffer.addSpan(x, 1, QScFixedToInt(yFP),
+ QScFixedToInt(255 * coverage));
++x;
}
@@ -1135,7 +1144,7 @@ void QRasterizer::rasterizeLine(const QPointF &a, const QPointF &b, qreal width,
topLeftIntersectAf = leftIntersectAf;
topRightIntersectAf = rightIntersectAf;
- yFP += Q16Dot16Factor;
+ yFP += QScFixedFactor;
rowTop = yFP;
}
} else { // aliased
@@ -1145,10 +1154,10 @@ void QRasterizer::rasterizeLine(const QPointF &a, const QPointF &b, qreal width,
int iBottom = bottom.y() < 0.5f? -1 : int(bottom.y() - 0.5f);
int iMiddle = qMin(iLeft, iRight);
- Q16Dot16 leftIntersectAf = qSafeFloatToQ16Dot16(top.x() + 0.5f + (iTop + 0.5f - top.y()) * topLeftSlope);
- Q16Dot16 leftIntersectBf = qSafeFloatToQ16Dot16(left.x() + 0.5f + (iLeft + 1.5f - left.y()) * bottomLeftSlope);
- Q16Dot16 rightIntersectAf = qSafeFloatToQ16Dot16(top.x() - 0.5f + (iTop + 0.5f - top.y()) * topRightSlope);
- Q16Dot16 rightIntersectBf = qSafeFloatToQ16Dot16(right.x() - 0.5f + (iRight + 1.5f - right.y()) * bottomRightSlope);
+ QScFixed leftIntersectAf = qSafeFloatToQScFixed(top.x() + 0.5f + (iTop + 0.5f - top.y()) * topLeftSlope);
+ QScFixed leftIntersectBf = qSafeFloatToQScFixed(left.x() + 0.5f + (iLeft + 1.5f - left.y()) * bottomLeftSlope);
+ QScFixed rightIntersectAf = qSafeFloatToQScFixed(top.x() - 0.5f + (iTop + 0.5f - top.y()) * topRightSlope);
+ QScFixed rightIntersectBf = qSafeFloatToQScFixed(right.x() - 0.5f + (iRight + 1.5f - right.y()) * bottomRightSlope);
int ny;
int y = iTop;
@@ -1162,8 +1171,8 @@ void QRasterizer::rasterizeLine(const QPointF &a, const QPointF &b, qreal width,
if (next > d->clipRect.bottom()) \
next = d->clipRect.bottom(); \
for (; y <= next; ++y) { \
- const int x1 = qMax(Q16Dot16ToInt(li), d->clipRect.left()); \
- const int x2 = qMin(Q16Dot16ToInt(ri), d->clipRect.right()); \
+ const int x1 = qMax(QScFixedToInt(li), d->clipRect.left()); \
+ const int x2 = qMin(QScFixedToInt(ri), d->clipRect.right()); \
if (x2 >= x1) \
buffer.addSpan(x1, x2 - x1 + 1, y, 255); \
li += ls; \