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:
Lars Knoll 2011-08-19 11:58:18 +02:00 committed by Qt by Nokia
parent dd91701a50
commit 46ff3a4b1f
2 changed files with 32 additions and 28 deletions

View File

@ -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) {

View File

@ -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)