GUI: Add drawLineClip()
This commit is contained in:
parent
2231de040f
commit
05383532b7
3 changed files with 132 additions and 3 deletions
|
@ -142,6 +142,7 @@ public:
|
||||||
* @param y2 Vertical (Y) coordinate for the line end
|
* @param y2 Vertical (Y) coordinate for the line end
|
||||||
*/
|
*/
|
||||||
virtual void drawLine(int x1, int y1, int x2, int y2) = 0;
|
virtual void drawLine(int x1, int y1, int x2, int y2) = 0;
|
||||||
|
virtual void drawLineClip(int x1, int y1, int x2, int y2, Common::Rect clipping) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draws a circle centered at (x,y) with radius r.
|
* Draws a circle centered at (x,y) with radius r.
|
||||||
|
@ -374,10 +375,10 @@ public:
|
||||||
drawSquareClip(x, y, w, h, clip);
|
drawSquareClip(x, y, w, h, clip);
|
||||||
}
|
}
|
||||||
|
|
||||||
void drawCallback_LINE(const Common::Rect &area, const DrawStep &step, const Common::Rect &clip) { //TODO
|
void drawCallback_LINE(const Common::Rect &area, const DrawStep &step, const Common::Rect &clip) {
|
||||||
uint16 x, y, w, h;
|
uint16 x, y, w, h;
|
||||||
stepGetPositions(step, area, x, y, w, h);
|
stepGetPositions(step, area, x, y, w, h);
|
||||||
drawLine(x, y, x + w, y + w);
|
drawLineClip(x, y, x + w, y + w, clip);
|
||||||
}
|
}
|
||||||
|
|
||||||
void drawCallback_ROUNDSQ(const Common::Rect &area, const DrawStep &step, const Common::Rect &clip) { //TODO
|
void drawCallback_ROUNDSQ(const Common::Rect &area, const DrawStep &step, const Common::Rect &clip) { //TODO
|
||||||
|
|
|
@ -1030,6 +1030,77 @@ drawLine(int x1, int y1, int x2, int y2) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename PixelType>
|
||||||
|
void VectorRendererSpec<PixelType>::
|
||||||
|
drawLineClip(int x1, int y1, int x2, int y2, Common::Rect clipping) {
|
||||||
|
x1 = CLIP(x1, 0, (int)Base::_activeSurface->w);
|
||||||
|
x2 = CLIP(x2, 0, (int)Base::_activeSurface->w);
|
||||||
|
y1 = CLIP(y1, 0, (int)Base::_activeSurface->h);
|
||||||
|
y2 = CLIP(y2, 0, (int)Base::_activeSurface->h);
|
||||||
|
|
||||||
|
// we draw from top to bottom
|
||||||
|
if (y2 < y1) {
|
||||||
|
SWAP(x1, x2);
|
||||||
|
SWAP(y1, y2);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint dx = ABS(x2 - x1);
|
||||||
|
uint dy = ABS(y2 - y1);
|
||||||
|
|
||||||
|
// this is a point, not a line. stoopid.
|
||||||
|
if (dy == 0 && dx == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (Base::_strokeWidth == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x1, y1);
|
||||||
|
int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
|
||||||
|
int st = Base::_strokeWidth >> 1;
|
||||||
|
|
||||||
|
Common::Rect backup = _clippingArea;
|
||||||
|
_clippingArea = clipping;
|
||||||
|
bool needsClipping = !_clippingArea.isEmpty() && (!_clippingArea.contains(x1, y1) || !_clippingArea.contains(x2, y2));
|
||||||
|
if (!needsClipping) {
|
||||||
|
drawLine(x1, y1, x2, y2);
|
||||||
|
_clippingArea = backup;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ptr_x = x1, ptr_y = y1;
|
||||||
|
|
||||||
|
if (dy == 0) { // horizontal lines
|
||||||
|
colorFillClip<PixelType>(ptr, ptr + dx + 1, (PixelType)_fgColor, x1, y1, _clippingArea);
|
||||||
|
|
||||||
|
for (int i = 0, p = pitch; i < st; ++i, p += pitch) {
|
||||||
|
colorFillClip<PixelType>(ptr + p, ptr + dx + 1 + p, (PixelType)_fgColor, x1, y1 + p/pitch, _clippingArea);
|
||||||
|
colorFillClip<PixelType>(ptr - p, ptr + dx + 1 - p, (PixelType)_fgColor, x1, y1 - p/pitch, _clippingArea);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (dx == 0) { // vertical lines
|
||||||
|
// these ones use a static pitch increase.
|
||||||
|
while (y1++ <= y2) {
|
||||||
|
colorFillClip<PixelType>(ptr - st, ptr + st, (PixelType)_fgColor, x1 - st, ptr_y, _clippingArea);
|
||||||
|
ptr += pitch;
|
||||||
|
++ptr_y;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (dx == dy) { // diagonal lines
|
||||||
|
// these ones also use a fixed pitch increase
|
||||||
|
pitch += (x2 > x1) ? 1 : -1;
|
||||||
|
|
||||||
|
while (dy--) {
|
||||||
|
colorFillClip<PixelType>(ptr - st, ptr + st, (PixelType)_fgColor, ptr_x - st, ptr_y, _clippingArea);
|
||||||
|
ptr += pitch;
|
||||||
|
++ptr_y;
|
||||||
|
if (x2 > x1) ++ptr_x; else --ptr_x;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else { // generic lines, use the standard algorithm...
|
||||||
|
drawLineAlgClip(x1, y1, x2, y2, dx, dy, (PixelType)_fgColor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** CIRCLES **/
|
/** CIRCLES **/
|
||||||
template<typename PixelType>
|
template<typename PixelType>
|
||||||
void VectorRendererSpec<PixelType>::
|
void VectorRendererSpec<PixelType>::
|
||||||
|
@ -1872,6 +1943,59 @@ drawLineAlg(int x1, int y1, int x2, int y2, uint dx, uint dy, PixelType color) {
|
||||||
*ptr = (PixelType)color;
|
*ptr = (PixelType)color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename PixelType>
|
||||||
|
void VectorRendererSpec<PixelType>::
|
||||||
|
drawLineAlgClip(int x1, int y1, int x2, int y2, uint dx, uint dy, PixelType color) {
|
||||||
|
PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x1, y1);
|
||||||
|
int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
|
||||||
|
int xdir = (x2 > x1) ? 1 : -1;
|
||||||
|
int ptr_x = x1, ptr_y = y1;
|
||||||
|
|
||||||
|
if (IS_IN_CLIP(ptr_x, ptr_y)) *ptr = (PixelType)color;
|
||||||
|
|
||||||
|
if (dx > dy) {
|
||||||
|
int ddy = dy * 2;
|
||||||
|
int dysub = ddy - (dx * 2);
|
||||||
|
int error_term = ddy - dx;
|
||||||
|
|
||||||
|
while (dx--) {
|
||||||
|
if (error_term >= 0) {
|
||||||
|
ptr += pitch;
|
||||||
|
++ptr_y;
|
||||||
|
error_term += dysub;
|
||||||
|
} else {
|
||||||
|
error_term += ddy;
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr += xdir;
|
||||||
|
ptr_x += xdir;
|
||||||
|
if (IS_IN_CLIP(ptr_x, ptr_y)) *ptr = (PixelType)color;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
int ddx = dx * 2;
|
||||||
|
int dxsub = ddx - (dy * 2);
|
||||||
|
int error_term = ddx - dy;
|
||||||
|
|
||||||
|
while (dy--) {
|
||||||
|
if (error_term >= 0) {
|
||||||
|
ptr += xdir;
|
||||||
|
ptr_x += xdir;
|
||||||
|
error_term += dxsub;
|
||||||
|
} else {
|
||||||
|
error_term += ddx;
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr += pitch;
|
||||||
|
++ptr_y;
|
||||||
|
if (IS_IN_CLIP(ptr_x, ptr_y)) *ptr = (PixelType)color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr = (PixelType *)_activeSurface->getBasePtr(x2, y2);
|
||||||
|
ptr_x = x2; ptr_y = y2;
|
||||||
|
if (IS_IN_CLIP(ptr_x, ptr_y)) *ptr = (PixelType)color;
|
||||||
|
}
|
||||||
|
|
||||||
/** VERTICAL TRIANGLE DRAWING ALGORITHM **/
|
/** VERTICAL TRIANGLE DRAWING ALGORITHM **/
|
||||||
/**
|
/**
|
||||||
FIXED POINT ARITHMETIC
|
FIXED POINT ARITHMETIC
|
||||||
|
|
|
@ -50,7 +50,8 @@ class VectorRendererSpec : public VectorRenderer {
|
||||||
public:
|
public:
|
||||||
VectorRendererSpec(PixelFormat format);
|
VectorRendererSpec(PixelFormat format);
|
||||||
|
|
||||||
void drawLine(int x1, int y1, int x2, int y2); //TODO
|
void drawLine(int x1, int y1, int x2, int y2);
|
||||||
|
void drawLineClip(int x1, int y1, int x2, int y2, Common::Rect clipping);
|
||||||
void drawCircle(int x, int y, int r);
|
void drawCircle(int x, int y, int r);
|
||||||
void drawCircleClip(int x, int y, int r, Common::Rect clipping);
|
void drawCircleClip(int x, int y, int r, Common::Rect clipping);
|
||||||
void drawSquare(int x, int y, int w, int h);
|
void drawSquare(int x, int y, int w, int h);
|
||||||
|
@ -159,6 +160,9 @@ protected:
|
||||||
virtual void drawLineAlg(int x1, int y1, int x2, int y2,
|
virtual void drawLineAlg(int x1, int y1, int x2, int y2,
|
||||||
uint dx, uint dy, PixelType color);
|
uint dx, uint dy, PixelType color);
|
||||||
|
|
||||||
|
virtual void drawLineAlgClip(int x1, int y1, int x2, int y2,
|
||||||
|
uint dx, uint dy, PixelType color);
|
||||||
|
|
||||||
virtual void drawCircleAlg(int x, int y, int r,
|
virtual void drawCircleAlg(int x, int y, int r,
|
||||||
PixelType color, FillMode fill_m);
|
PixelType color, FillMode fill_m);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue