GRAPHICS: Properly take stroke width into account when drawing lines
Old code: - didn't handle well strokes with an odd width - didn't handle strokes widths above 1 in generic lines handler
This commit is contained in:
parent
777a681937
commit
f06f470685
1 changed files with 164 additions and 36 deletions
|
@ -1081,39 +1081,33 @@ drawLine(int x1, int y1, int x2, int y2) {
|
||||||
|
|
||||||
PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x1, y1);
|
PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x1, y1);
|
||||||
int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
|
int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
|
||||||
int st = Base::_strokeWidth >> 1;
|
// Stroke widths before and after the coordinate
|
||||||
|
// Before is favoured in case of even stroke width
|
||||||
|
int stb = Base::_strokeWidth >> 1;
|
||||||
|
int sta = stb + (Base::_strokeWidth & 1);
|
||||||
|
|
||||||
bool useClippingVersions = !_clippingArea.contains(x1, y1) || !_clippingArea.contains(x2, y2);
|
bool useClippingVersions = !_clippingArea.contains(x1, y1) || !_clippingArea.contains(x2, y2);
|
||||||
|
|
||||||
int ptr_x = x1, ptr_y = y1;
|
|
||||||
|
|
||||||
if (dy == 0) { // horizontal lines
|
if (dy == 0) { // horizontal lines
|
||||||
if (useClippingVersions) {
|
intptr p = -stb * pitch;
|
||||||
colorFillClip<PixelType>(ptr, ptr + dx + 1, (PixelType)_fgColor, x1, y1, _clippingArea);
|
for (int i = -stb; i < sta; i++, p += pitch) {
|
||||||
} else {
|
|
||||||
colorFill<PixelType>(ptr, ptr + dx + 1, (PixelType)_fgColor);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0, p = pitch; i < st; ++i, p += pitch) {
|
|
||||||
if (useClippingVersions) {
|
if (useClippingVersions) {
|
||||||
colorFillClip<PixelType>(ptr + p, ptr + dx + 1 + p, (PixelType)_fgColor, x1, y1 + p/pitch, _clippingArea);
|
colorFillClip<PixelType>(ptr + p, ptr + p + dx + 1, (PixelType)_fgColor, x1, y1 + i, _clippingArea);
|
||||||
colorFillClip<PixelType>(ptr - p, ptr + dx + 1 - p, (PixelType)_fgColor, x1, y1 - p/pitch, _clippingArea);
|
|
||||||
} else {
|
} else {
|
||||||
colorFill<PixelType>(ptr + p, ptr + dx + 1 + p, (PixelType)_fgColor);
|
colorFill<PixelType>(ptr + p, ptr + p + dx + 1, (PixelType)_fgColor);
|
||||||
colorFill<PixelType>(ptr - p, ptr + dx + 1 - p, (PixelType)_fgColor);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (dx == 0) { // vertical lines
|
} else if (dx == 0) { // vertical lines
|
||||||
// these ones use a static pitch increase.
|
// these ones use a static pitch increase.
|
||||||
while (y1++ <= y2) {
|
while (y1 <= y2) {
|
||||||
if (useClippingVersions) {
|
if (useClippingVersions) {
|
||||||
colorFillClip<PixelType>(ptr - st, ptr + st, (PixelType)_fgColor, x1 - st, ptr_y, _clippingArea);
|
colorFillClip<PixelType>(ptr - stb, ptr + sta, (PixelType)_fgColor, x1 - stb, y1, _clippingArea);
|
||||||
} else {
|
} else {
|
||||||
colorFill<PixelType>(ptr - st, ptr + st, (PixelType)_fgColor);
|
colorFill<PixelType>(ptr - stb, ptr + sta, (PixelType)_fgColor);
|
||||||
}
|
}
|
||||||
ptr += pitch;
|
ptr += pitch;
|
||||||
++ptr_y;
|
y1++;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (dx == dy) { // diagonal lines
|
} else if (dx == dy) { // diagonal lines
|
||||||
|
@ -1122,13 +1116,13 @@ drawLine(int x1, int y1, int x2, int y2) {
|
||||||
|
|
||||||
while (dy--) {
|
while (dy--) {
|
||||||
if (useClippingVersions) {
|
if (useClippingVersions) {
|
||||||
colorFillClip<PixelType>(ptr - st, ptr + st, (PixelType)_fgColor, ptr_x - st, ptr_y, _clippingArea);
|
colorFillClip<PixelType>(ptr - stb, ptr + sta, (PixelType)_fgColor, x1 - stb, y1, _clippingArea);
|
||||||
} else {
|
} else {
|
||||||
colorFill<PixelType>(ptr - st, ptr + st, (PixelType)_fgColor);
|
colorFill<PixelType>(ptr - stb, ptr + sta, (PixelType)_fgColor);
|
||||||
}
|
}
|
||||||
ptr += pitch;
|
ptr += pitch;
|
||||||
++ptr_y;
|
y1++;
|
||||||
if (x2 > x1) ++ptr_x; else --ptr_x;
|
if (x2 > x1) ++x1; else --x1;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else { // generic lines, use the standard algorithm...
|
} else { // generic lines, use the standard algorithm...
|
||||||
|
@ -2089,9 +2083,26 @@ void VectorRendererSpec<PixelType>::
|
||||||
drawLineAlg(int x1, int y1, int x2, int y2, uint dx, uint dy, PixelType color) {
|
drawLineAlg(int x1, int y1, int x2, int y2, uint dx, uint dy, PixelType color) {
|
||||||
PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x1, y1);
|
PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x1, y1);
|
||||||
int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
|
int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
|
||||||
|
int strokeState = Base::_strokeWidth > 1 ? ((dx > dy) ? 1 : 2) : 0;
|
||||||
|
// Stroke widths before and after the coordinate
|
||||||
|
// Before is favoured in case of even stroke width
|
||||||
|
int stb = Base::_strokeWidth >> 1;
|
||||||
|
int sta = stb + (Base::_strokeWidth & 1);
|
||||||
int xdir = (x2 > x1) ? 1 : -1;
|
int xdir = (x2 > x1) ? 1 : -1;
|
||||||
|
|
||||||
*ptr = (PixelType)color;
|
if (strokeState == 0) {
|
||||||
|
// No stroke width
|
||||||
|
*ptr = (PixelType)color;
|
||||||
|
} else if (strokeState == 1) {
|
||||||
|
// Horizontal line
|
||||||
|
intptr p = -stb * pitch;
|
||||||
|
for (int i = -stb; i < sta; i++, p += pitch) {
|
||||||
|
*(ptr + p) = (PixelType)color;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Vertical line
|
||||||
|
colorFill<PixelType>(ptr - stb, ptr + sta, (PixelType)color);
|
||||||
|
}
|
||||||
|
|
||||||
if (dx > dy) {
|
if (dx > dy) {
|
||||||
int ddy = dy * 2;
|
int ddy = dy * 2;
|
||||||
|
@ -2107,7 +2118,15 @@ drawLineAlg(int x1, int y1, int x2, int y2, uint dx, uint dy, PixelType color) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ptr += xdir;
|
ptr += xdir;
|
||||||
*ptr = (PixelType)color;
|
|
||||||
|
if (strokeState) {
|
||||||
|
intptr p = -stb * pitch;
|
||||||
|
for (int i = -stb; i < sta; i++, p += pitch) {
|
||||||
|
*(ptr + p) = (PixelType)color;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
*ptr = (PixelType)color;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
int ddx = dx * 2;
|
int ddx = dx * 2;
|
||||||
|
@ -2123,12 +2142,28 @@ drawLineAlg(int x1, int y1, int x2, int y2, uint dx, uint dy, PixelType color) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ptr += pitch;
|
ptr += pitch;
|
||||||
*ptr = (PixelType)color;
|
if (strokeState) {
|
||||||
|
colorFill<PixelType>(ptr - stb, ptr + sta, (PixelType)color);
|
||||||
|
} else {
|
||||||
|
*ptr = (PixelType)color;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ptr = (PixelType *)_activeSurface->getBasePtr(x2, y2);
|
ptr = (PixelType *)_activeSurface->getBasePtr(x2, y2);
|
||||||
*ptr = (PixelType)color;
|
if (strokeState == 0) {
|
||||||
|
// No stroke width
|
||||||
|
*ptr = (PixelType)color;
|
||||||
|
} else if (strokeState == 1) {
|
||||||
|
// Horizontal line
|
||||||
|
intptr p = -stb * pitch;
|
||||||
|
for (int i = -stb; i < sta; i++, p += pitch) {
|
||||||
|
*(ptr + p) = (PixelType)color;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Vertical line
|
||||||
|
colorFill<PixelType>(ptr - stb, ptr + sta, (PixelType)color);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename PixelType>
|
template<typename PixelType>
|
||||||
|
@ -2136,10 +2171,27 @@ void VectorRendererSpec<PixelType>::
|
||||||
drawLineAlgClip(int x1, int y1, int x2, int y2, uint dx, uint dy, PixelType color) {
|
drawLineAlgClip(int x1, int y1, int x2, int y2, uint dx, uint dy, PixelType color) {
|
||||||
PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x1, y1);
|
PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x1, y1);
|
||||||
int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
|
int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
|
||||||
|
int strokeState = Base::_strokeWidth > 1 ? ((dx > dy) ? 1 : 2) : 0;
|
||||||
|
// Stroke widths before and after the coordinate
|
||||||
|
// Before is favoured in case of even stroke width
|
||||||
|
int stb = Base::_strokeWidth >> 1;
|
||||||
|
int sta = stb + (Base::_strokeWidth & 1);
|
||||||
int xdir = (x2 > x1) ? 1 : -1;
|
int xdir = (x2 > x1) ? 1 : -1;
|
||||||
int ptr_x = x1, ptr_y = y1;
|
int ptr_x = x1, ptr_y = y1;
|
||||||
|
|
||||||
if (IS_IN_CLIP(ptr_x, ptr_y)) *ptr = (PixelType)color;
|
if (strokeState == 0) {
|
||||||
|
// No stroke width
|
||||||
|
if (IS_IN_CLIP(ptr_x, ptr_y)) *ptr = (PixelType)color;
|
||||||
|
} else if (strokeState == 1) {
|
||||||
|
// Horizontal line
|
||||||
|
intptr p = -stb * pitch;
|
||||||
|
for (int i = -stb; i < sta; i++, p += pitch) {
|
||||||
|
if (IS_IN_CLIP(ptr_x, ptr_y + i)) *(ptr + p) = (PixelType)color;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Vertical line
|
||||||
|
colorFillClip<PixelType>(ptr - stb, ptr + sta, (PixelType)_fgColor, ptr_x - stb, ptr_y, _clippingArea);
|
||||||
|
}
|
||||||
|
|
||||||
if (dx > dy) {
|
if (dx > dy) {
|
||||||
int ddy = dy * 2;
|
int ddy = dy * 2;
|
||||||
|
@ -2157,7 +2209,15 @@ drawLineAlgClip(int x1, int y1, int x2, int y2, uint dx, uint dy, PixelType colo
|
||||||
|
|
||||||
ptr += xdir;
|
ptr += xdir;
|
||||||
ptr_x += xdir;
|
ptr_x += xdir;
|
||||||
if (IS_IN_CLIP(ptr_x, ptr_y)) *ptr = (PixelType)color;
|
|
||||||
|
if (strokeState) {
|
||||||
|
intptr p = -stb * pitch;
|
||||||
|
for (int i = -stb; i < sta; i++, p += pitch) {
|
||||||
|
if (IS_IN_CLIP(ptr_x, ptr_y + i)) *(ptr + p) = (PixelType)color;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (IS_IN_CLIP(ptr_x, ptr_y)) *ptr = (PixelType)color;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
int ddx = dx * 2;
|
int ddx = dx * 2;
|
||||||
|
@ -2175,13 +2235,29 @@ drawLineAlgClip(int x1, int y1, int x2, int y2, uint dx, uint dy, PixelType colo
|
||||||
|
|
||||||
ptr += pitch;
|
ptr += pitch;
|
||||||
++ptr_y;
|
++ptr_y;
|
||||||
if (IS_IN_CLIP(ptr_x, ptr_y)) *ptr = (PixelType)color;
|
if (strokeState) {
|
||||||
|
colorFillClip<PixelType>(ptr - stb, ptr + sta, (PixelType)_fgColor, ptr_x - stb, ptr_y, _clippingArea);
|
||||||
|
} else {
|
||||||
|
if (IS_IN_CLIP(ptr_x, ptr_y)) *ptr = (PixelType)color;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ptr = (PixelType *)_activeSurface->getBasePtr(x2, y2);
|
ptr = (PixelType *)_activeSurface->getBasePtr(x2, y2);
|
||||||
ptr_x = x2; ptr_y = y2;
|
ptr_x = x2; ptr_y = y2;
|
||||||
if (IS_IN_CLIP(ptr_x, ptr_y)) *ptr = (PixelType)color;
|
if (strokeState == 0) {
|
||||||
|
// No stroke width
|
||||||
|
if (IS_IN_CLIP(ptr_x, ptr_y)) *ptr = (PixelType)color;
|
||||||
|
} else if (strokeState == 1) {
|
||||||
|
// Horizontal line
|
||||||
|
intptr p = -stb * pitch;
|
||||||
|
for (int i = -stb; i < sta; i++, p += pitch) {
|
||||||
|
if (IS_IN_CLIP(ptr_x, ptr_y + i)) *(ptr + p) = (PixelType)color;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Vertical line
|
||||||
|
colorFillClip<PixelType>(ptr - stb, ptr + sta, (PixelType)_fgColor, ptr_x - stb, ptr_y, _clippingArea);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** VERTICAL TRIANGLE DRAWING ALGORITHM **/
|
/** VERTICAL TRIANGLE DRAWING ALGORITHM **/
|
||||||
|
@ -3891,11 +3967,28 @@ void VectorRendererAA<PixelType>::
|
||||||
drawLineAlg(int x1, int y1, int x2, int y2, uint dx, uint dy, PixelType color) {
|
drawLineAlg(int x1, int y1, int x2, int y2, uint dx, uint dy, PixelType color) {
|
||||||
PixelType *ptr = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1);
|
PixelType *ptr = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1);
|
||||||
int pitch = Base::_activeSurface->pitch / Base::_activeSurface->format.bytesPerPixel;
|
int pitch = Base::_activeSurface->pitch / Base::_activeSurface->format.bytesPerPixel;
|
||||||
|
int strokeState = Base::_strokeWidth > 1 ? ((dx > dy) ? 1 : 2) : 0;
|
||||||
|
// Stroke widths before and after the coordinate
|
||||||
|
// Before is favoured in case of even stroke width
|
||||||
|
int stb = Base::_strokeWidth >> 1;
|
||||||
|
int sta = stb + (Base::_strokeWidth & 1);
|
||||||
int xdir = (x2 > x1) ? 1 : -1;
|
int xdir = (x2 > x1) ? 1 : -1;
|
||||||
uint16 error_tmp, error_acc, gradient;
|
uint16 error_tmp, error_acc, gradient;
|
||||||
uint8 alpha;
|
uint8 alpha;
|
||||||
|
|
||||||
*ptr = (PixelType)color;
|
if (strokeState == 0) {
|
||||||
|
// No stroke width
|
||||||
|
*ptr = (PixelType)color;
|
||||||
|
} else if (strokeState == 1) {
|
||||||
|
// Horizontal line
|
||||||
|
intptr p = -stb * pitch;
|
||||||
|
for (int i = -stb; i < sta; i++, p += pitch) {
|
||||||
|
*(ptr + p) = (PixelType)color;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Vertical line
|
||||||
|
colorFill<PixelType>(ptr - stb, ptr + sta, (PixelType)color);
|
||||||
|
}
|
||||||
|
|
||||||
if (dx > dy) {
|
if (dx > dy) {
|
||||||
gradient = (dy << 16) / dx;
|
gradient = (dy << 16) / dx;
|
||||||
|
@ -3911,8 +4004,18 @@ drawLineAlg(int x1, int y1, int x2, int y2, uint dx, uint dy, PixelType color) {
|
||||||
ptr += xdir;
|
ptr += xdir;
|
||||||
alpha = (error_acc >> 8);
|
alpha = (error_acc >> 8);
|
||||||
|
|
||||||
this->blendPixelPtr(ptr, color, ~alpha);
|
if (strokeState) {
|
||||||
this->blendPixelPtr(ptr + pitch, color, alpha);
|
intptr p = -stb * pitch;
|
||||||
|
this->blendPixelPtr(ptr + p, color, ~alpha);
|
||||||
|
p += pitch;
|
||||||
|
for (int i = -stb + 1; i < sta; i++, p += pitch) {
|
||||||
|
*(ptr + p) = (PixelType)color;
|
||||||
|
}
|
||||||
|
this->blendPixelPtr(ptr + p, color, alpha);
|
||||||
|
} else {
|
||||||
|
this->blendPixelPtr(ptr, color, ~alpha);
|
||||||
|
this->blendPixelPtr(ptr + pitch, color, alpha);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (dy != 0) {
|
} else if (dy != 0) {
|
||||||
gradient = (dx << 16) / dy;
|
gradient = (dx << 16) / dy;
|
||||||
|
@ -3928,12 +4031,37 @@ drawLineAlg(int x1, int y1, int x2, int y2, uint dx, uint dy, PixelType color) {
|
||||||
ptr += pitch;
|
ptr += pitch;
|
||||||
alpha = (error_acc >> 8);
|
alpha = (error_acc >> 8);
|
||||||
|
|
||||||
this->blendPixelPtr(ptr, color, ~alpha);
|
if (strokeState) {
|
||||||
this->blendPixelPtr(ptr + xdir, color, alpha);
|
if (xdir > 0) {
|
||||||
|
this->blendPixelPtr(ptr - stb, color, ~alpha);
|
||||||
|
colorFill<PixelType>(ptr - stb + 1, ptr + sta, (PixelType)color);
|
||||||
|
this->blendPixelPtr(ptr + sta, color, alpha);
|
||||||
|
} else {
|
||||||
|
this->blendPixelPtr(ptr - stb, color, alpha);
|
||||||
|
colorFill<PixelType>(ptr - stb + 1, ptr + sta, (PixelType)color);
|
||||||
|
this->blendPixelPtr(ptr + sta, color, ~alpha);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this->blendPixelPtr(ptr, color, ~alpha);
|
||||||
|
this->blendPixelPtr(ptr + xdir, color, alpha);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Base::putPixel(x2, y2, color);
|
ptr = (PixelType *)Base::_activeSurface->getBasePtr(x2, y2);
|
||||||
|
if (strokeState == 0) {
|
||||||
|
// No stroke width
|
||||||
|
*ptr = (PixelType)color;
|
||||||
|
} else if (strokeState == 1) {
|
||||||
|
// Horizontal line
|
||||||
|
intptr p = -stb * pitch;
|
||||||
|
for (int i = -stb; i < sta; i++, p += pitch) {
|
||||||
|
*(ptr + p) = (PixelType)color;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Vertical line
|
||||||
|
colorFill<PixelType>(ptr - stb, ptr + sta, (PixelType)color);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** TAB ALGORITHM */
|
/** TAB ALGORITHM */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue