Correctly position aliased lines with flat caps
The code was mispositioning lines by half a pixel, as it added half a pixel offset and then rounded in addition. This submit fixes this and also removes certain artifacts when drawing rects at .5 pixel positions. Lance now doesn't show any significant differences to the 4.7 rendering anymore. Task-number: QTBUG-20199 Reviewed-by: Aavit (cherry picked from commit 49409f612c47f30434aa809e4d2c963f1a6bb88a) Change-Id: Iab3936e688eba16b82f5cdb4f36f54af807d78ea Reviewed-on: http://codereview.qt.nokia.com/3260 Reviewed-by: Lars Knoll <lars.knoll@nokia.com> Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com>
This commit is contained in:
parent
dd91701a50
commit
46ff3a4b1f
@ -425,13 +425,12 @@ void QCosmeticStroker::calculateLastPoint(qreal rx1, qreal ry1, qreal rx2, qreal
|
|||||||
swapped = true;
|
swapped = true;
|
||||||
qSwap(y1, y2);
|
qSwap(y1, y2);
|
||||||
qSwap(x1, x2);
|
qSwap(x1, x2);
|
||||||
--x1; --x2; --y1; --y2;
|
|
||||||
}
|
}
|
||||||
int xinc = F16Dot16FixedDiv(x2 - x1, y2 - y1);
|
int xinc = F16Dot16FixedDiv(x2 - x1, y2 - y1);
|
||||||
int x = x1 << 10;
|
int x = x1 << 10;
|
||||||
|
|
||||||
int y = (y1+32) >> 6;
|
int y = y1 >> 6;
|
||||||
int ys = (y2+32) >> 6;
|
int ys = y2 >> 6;
|
||||||
|
|
||||||
if (y != ys) {
|
if (y != ys) {
|
||||||
x += ( ((((y << 6) + 32 - y1))) * xinc ) >> 6;
|
x += ( ((((y << 6) + 32 - y1))) * xinc ) >> 6;
|
||||||
@ -457,13 +456,12 @@ void QCosmeticStroker::calculateLastPoint(qreal rx1, qreal ry1, qreal rx2, qreal
|
|||||||
swapped = true;
|
swapped = true;
|
||||||
qSwap(x1, x2);
|
qSwap(x1, x2);
|
||||||
qSwap(y1, y2);
|
qSwap(y1, y2);
|
||||||
--x1; --x2; --y1; --y2;
|
|
||||||
}
|
}
|
||||||
int yinc = F16Dot16FixedDiv(y2 - y1, x2 - x1);
|
int yinc = F16Dot16FixedDiv(y2 - y1, x2 - x1);
|
||||||
int y = y1 << 10;
|
int y = y1 << 10;
|
||||||
|
|
||||||
int x = (x1+32) >> 6;
|
int x = x1 >> 6;
|
||||||
int xs = (x2+32) >> 6;
|
int xs = x2 >> 6;
|
||||||
|
|
||||||
if (x != xs) {
|
if (x != xs) {
|
||||||
y += ( ((((x << 6) + 32 - x1))) * yinc ) >> 6;
|
y += ( ((((x << 6) + 32 - x1))) * yinc ) >> 6;
|
||||||
@ -716,10 +714,11 @@ static void drawLine(QCosmeticStroker *stroker, qreal rx1, qreal ry1, qreal rx2,
|
|||||||
|
|
||||||
QCosmeticStroker::Point last = stroker->lastPixel;
|
QCosmeticStroker::Point last = stroker->lastPixel;
|
||||||
|
|
||||||
// qDebug() << "stroke" << x1/64. << y1/64. << x2/64. << y2/64. << capString(caps);
|
// qDebug() << "stroke" << x1/64. << y1/64. << x2/64. << y2/64.;
|
||||||
|
|
||||||
if (dx < dy) {
|
if (dx < dy) {
|
||||||
// vertical
|
// vertical
|
||||||
|
QCosmeticStroker::Direction dir = QCosmeticStroker::TopToBottom;
|
||||||
|
|
||||||
bool swapped = false;
|
bool swapped = false;
|
||||||
if (y1 > y2) {
|
if (y1 > y2) {
|
||||||
@ -727,30 +726,31 @@ static void drawLine(QCosmeticStroker *stroker, qreal rx1, qreal ry1, qreal rx2,
|
|||||||
qSwap(y1, y2);
|
qSwap(y1, y2);
|
||||||
qSwap(x1, x2);
|
qSwap(x1, x2);
|
||||||
caps = swapCaps(caps);
|
caps = swapCaps(caps);
|
||||||
--x1; --x2; --y1; --y2;
|
dir = QCosmeticStroker::BottomToTop;
|
||||||
}
|
}
|
||||||
int xinc = F16Dot16FixedDiv(x2 - x1, y2 - y1);
|
int xinc = F16Dot16FixedDiv(x2 - x1, y2 - y1);
|
||||||
int x = x1 << 10;
|
int x = x1 << 10;
|
||||||
|
|
||||||
|
if ((stroker->lastDir ^ QCosmeticStroker::VerticalMask) == dir)
|
||||||
|
caps |= swapped ? QCosmeticStroker::CapEnd : QCosmeticStroker::CapBegin;
|
||||||
|
|
||||||
capAdjust(caps, y1, y2, x, xinc);
|
capAdjust(caps, y1, y2, x, xinc);
|
||||||
|
|
||||||
int y = (y1+32) >> 6;
|
int y = y1 >> 6;
|
||||||
int ys = (y2+32) >> 6;
|
int ys = y2 >> 6;
|
||||||
|
|
||||||
if (y != ys) {
|
if (y != ys) {
|
||||||
x += ( ((((y << 6) + 32 - y1))) * xinc ) >> 6;
|
x += ( ((((y << 6) + 32 - y1))) * xinc ) >> 6;
|
||||||
|
|
||||||
// calculate first and last pixel and perform dropout control
|
// calculate first and last pixel and perform dropout control
|
||||||
QCosmeticStroker::Direction dir = QCosmeticStroker::TopToBottom;
|
|
||||||
QCosmeticStroker::Point first;
|
QCosmeticStroker::Point first;
|
||||||
first.x = x >> 16;
|
first.x = x >> 16;
|
||||||
first.y = y;
|
first.y = y;
|
||||||
last.x = (x + (ys - y - 1)*xinc) >> 16;
|
last.x = (x + (ys - y - 1)*xinc) >> 16;
|
||||||
last.y = ys - 1;
|
last.y = ys - 1;
|
||||||
if (swapped) {
|
if (swapped)
|
||||||
qSwap(first, last);
|
qSwap(first, last);
|
||||||
dir = QCosmeticStroker::BottomToTop;
|
|
||||||
}
|
|
||||||
bool axisAligned = qAbs(xinc) < (1 << 14);
|
bool axisAligned = qAbs(xinc) < (1 << 14);
|
||||||
if (stroker->lastPixel.x >= 0) {
|
if (stroker->lastPixel.x >= 0) {
|
||||||
if (first.x == stroker->lastPixel.x &&
|
if (first.x == stroker->lastPixel.x &&
|
||||||
@ -765,7 +765,7 @@ static void drawLine(QCosmeticStroker *stroker, qreal rx1, qreal ry1, qreal rx2,
|
|||||||
} else if (stroker->lastDir != dir &&
|
} else if (stroker->lastDir != dir &&
|
||||||
(((axisAligned && stroker->lastAxisAligned) &&
|
(((axisAligned && stroker->lastAxisAligned) &&
|
||||||
stroker->lastPixel.x != first.x && stroker->lastPixel.y != first.y) ||
|
stroker->lastPixel.x != first.x && stroker->lastPixel.y != first.y) ||
|
||||||
(qAbs(stroker->lastPixel.x - first.x) > 1 &&
|
(qAbs(stroker->lastPixel.x - first.x) > 1 ||
|
||||||
qAbs(stroker->lastPixel.y - first.y) > 1))) {
|
qAbs(stroker->lastPixel.y - first.y) > 1))) {
|
||||||
// have a missing pixel, insert it
|
// have a missing pixel, insert it
|
||||||
if (swapped) {
|
if (swapped) {
|
||||||
@ -793,37 +793,39 @@ static void drawLine(QCosmeticStroker *stroker, qreal rx1, qreal ry1, qreal rx2,
|
|||||||
if (!dx)
|
if (!dx)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
QCosmeticStroker::Direction dir = QCosmeticStroker::LeftToRight;
|
||||||
|
|
||||||
bool swapped = false;
|
bool swapped = false;
|
||||||
if (x1 > x2) {
|
if (x1 > x2) {
|
||||||
swapped = true;
|
swapped = true;
|
||||||
qSwap(x1, x2);
|
qSwap(x1, x2);
|
||||||
qSwap(y1, y2);
|
qSwap(y1, y2);
|
||||||
caps = swapCaps(caps);
|
caps = swapCaps(caps);
|
||||||
--x1; --x2; --y1; --y2;
|
dir = QCosmeticStroker::RightToLeft;
|
||||||
}
|
}
|
||||||
int yinc = F16Dot16FixedDiv(y2 - y1, x2 - x1);
|
int yinc = F16Dot16FixedDiv(y2 - y1, x2 - x1);
|
||||||
int y = y1 << 10;
|
int y = y1 << 10;
|
||||||
|
|
||||||
|
if ((stroker->lastDir ^ QCosmeticStroker::HorizontalMask) == dir)
|
||||||
|
caps |= swapped ? QCosmeticStroker::CapEnd : QCosmeticStroker::CapBegin;
|
||||||
|
|
||||||
capAdjust(caps, x1, x2, y, yinc);
|
capAdjust(caps, x1, x2, y, yinc);
|
||||||
|
|
||||||
int x = (x1+32) >> 6;
|
int x = x1 >> 6;
|
||||||
int xs = (x2+32) >> 6;
|
int xs = x2 >> 6;
|
||||||
|
|
||||||
|
|
||||||
if (x != xs) {
|
if (x != xs) {
|
||||||
y += ( ((((x << 6) + 32 - x1))) * yinc ) >> 6;
|
y += ( ((((x << 6) + 32 - x1))) * yinc ) >> 6;
|
||||||
|
|
||||||
// calculate first and last pixel to perform dropout control
|
// calculate first and last pixel to perform dropout control
|
||||||
QCosmeticStroker::Direction dir = QCosmeticStroker::LeftToRight;
|
|
||||||
QCosmeticStroker::Point first;
|
QCosmeticStroker::Point first;
|
||||||
first.x = x;
|
first.x = x;
|
||||||
first.y = y >> 16;
|
first.y = y >> 16;
|
||||||
last.x = xs - 1;
|
last.x = xs - 1;
|
||||||
last.y = (y + (xs - x - 1)*yinc) >> 16;
|
last.y = (y + (xs - x - 1)*yinc) >> 16;
|
||||||
if (swapped) {
|
if (swapped)
|
||||||
qSwap(first, last);
|
qSwap(first, last);
|
||||||
dir = QCosmeticStroker::RightToLeft;
|
|
||||||
}
|
|
||||||
bool axisAligned = qAbs(yinc) < (1 << 14);
|
bool axisAligned = qAbs(yinc) < (1 << 14);
|
||||||
if (stroker->lastPixel.x >= 0) {
|
if (stroker->lastPixel.x >= 0) {
|
||||||
if (first.x == stroker->lastPixel.x && first.y == stroker->lastPixel.y) {
|
if (first.x == stroker->lastPixel.x && first.y == stroker->lastPixel.y) {
|
||||||
@ -837,7 +839,7 @@ static void drawLine(QCosmeticStroker *stroker, qreal rx1, qreal ry1, qreal rx2,
|
|||||||
} else if (stroker->lastDir != dir &&
|
} else if (stroker->lastDir != dir &&
|
||||||
(((axisAligned && stroker->lastAxisAligned) &&
|
(((axisAligned && stroker->lastAxisAligned) &&
|
||||||
stroker->lastPixel.x != first.x && stroker->lastPixel.y != first.y) ||
|
stroker->lastPixel.x != first.x && stroker->lastPixel.y != first.y) ||
|
||||||
(qAbs(stroker->lastPixel.x - first.x) > 1 &&
|
(qAbs(stroker->lastPixel.x - first.x) > 1 ||
|
||||||
qAbs(stroker->lastPixel.y - first.y) > 1))) {
|
qAbs(stroker->lastPixel.y - first.y) > 1))) {
|
||||||
// have a missing pixel, insert it
|
// have a missing pixel, insert it
|
||||||
if (swapped) {
|
if (swapped) {
|
||||||
|
@ -78,10 +78,12 @@ public:
|
|||||||
|
|
||||||
// used to avoid drop outs or duplicated points
|
// used to avoid drop outs or duplicated points
|
||||||
enum Direction {
|
enum Direction {
|
||||||
TopToBottom,
|
TopToBottom = 0x1,
|
||||||
BottomToTop,
|
BottomToTop = 0x2,
|
||||||
LeftToRight,
|
LeftToRight = 0x4,
|
||||||
RightToLeft
|
RightToLeft = 0x8,
|
||||||
|
VerticalMask = 0x3,
|
||||||
|
HorizontalMask = 0xc
|
||||||
};
|
};
|
||||||
|
|
||||||
QCosmeticStroker(QRasterPaintEngineState *s, const QRect &dr)
|
QCosmeticStroker(QRasterPaintEngineState *s, const QRect &dr)
|
||||||
|
Loading…
Reference in New Issue
Block a user