aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/wage/design.cpp378
-rw-r--r--engines/wage/design.h10
-rw-r--r--graphics/primitives.cpp357
-rw-r--r--graphics/primitives.h11
4 files changed, 378 insertions, 378 deletions
diff --git a/engines/wage/design.cpp b/engines/wage/design.cpp
index 8e5c753321..2acd872812 100644
--- a/engines/wage/design.cpp
+++ b/engines/wage/design.cpp
@@ -226,7 +226,7 @@ void Design::drawRect(Graphics::Surface *surface, Common::ReadStream &in,
plotData pd(surface, &patterns, fillType, 1);
if (fillType <= patterns.size())
- drawFilledRect(r, kColorBlack, drawPixel, &pd);
+ Graphics::drawFilledRect(r, kColorBlack, drawPixel, &pd);
pd.fillType = borderFillType;
pd.thickness = borderThickness;
@@ -256,13 +256,13 @@ void Design::drawRoundRect(Graphics::Surface *surface, Common::ReadStream &in,
plotData pd(surface, &patterns, fillType, 1);
if (fillType <= patterns.size())
- drawRoundRect(r, arc/2, kColorBlack, true, drawPixel, &pd);
+ Graphics::drawRoundRect(r, arc/2, kColorBlack, true, drawPixel, &pd);
pd.fillType = borderFillType;
pd.thickness = borderThickness;
if (borderThickness > 0 && borderFillType <= patterns.size())
- drawRoundRect(r, arc/2, kColorBlack, false, drawPixel, &pd);
+ Graphics::drawRoundRect(r, arc/2, kColorBlack, false, drawPixel, &pd);
}
void Design::drawPolygon(Graphics::Surface *surface, Common::ReadStream &in,
@@ -326,7 +326,7 @@ void Design::drawPolygon(Graphics::Surface *surface, Common::ReadStream &in,
plotData pd(surface, &patterns, fillType, 1);
if (fillType <= patterns.size()) {
- drawPolygonScan(xpoints, ypoints, npoints, bbox, kColorBlack, drawPixel, &pd);
+ Graphics::drawPolygonScan(xpoints, ypoints, npoints, bbox, kColorBlack, drawPixel, &pd);
}
pd.fillType = borderFillType;
@@ -349,13 +349,13 @@ void Design::drawOval(Graphics::Surface *surface, Common::ReadStream &in,
plotData pd(surface, &patterns, fillType, 1);
if (fillType <= patterns.size())
- drawEllipse(x1, y1, x2-1, y2-1, true, drawPixel, &pd);
+ Graphics::drawEllipse(x1, y1, x2-1, y2-1, kColorBlack, true, drawPixel, &pd);
pd.fillType = borderFillType;
pd.thickness = borderThickness;
if (borderThickness > 0 && borderFillType <= patterns.size())
- drawEllipse(x1, y1, x2-1, y2-1, false, drawPixel, &pd);
+ Graphics::drawEllipse(x1, y1, x2-1, y2-1, kColorBlack, false, drawPixel, &pd);
}
void Design::drawBitmap(Graphics::Surface *surface, Common::ReadStream &in) {
@@ -460,383 +460,25 @@ void Design::drawFilledRect(Graphics::Surface *surface, Common::Rect &rect, int
plotData pd(surface, &patterns, fillType, 1);
for (int y = rect.top; y <= rect.bottom; y++)
- drawHLine(rect.left, rect.right, y, color, drawPixel, &pd);
-}
-
-void Design::drawFilledRect(Common::Rect &rect, int color, void (*plotProc)(int, int, int, void *), void *data) {
- for (int y = rect.top; y <= rect.bottom; y++)
- drawHLine(rect.left, rect.right, y, color, plotProc, data);
+ Graphics::drawHLine(rect.left, rect.right, y, color, drawPixel, &pd);
}
void Design::drawFilledRoundRect(Graphics::Surface *surface, Common::Rect &rect, int arc, int color, Patterns &patterns, byte fillType) {
plotData pd(surface, &patterns, fillType, 1);
- drawRoundRect(rect, arc, color, true, drawPixel, &pd);
-}
-
-// http://members.chello.at/easyfilter/bresenham.html
-void Design::drawRoundRect(Common::Rect &rect, int arc, int color, bool filled, void (*plotProc)(int, int, int, void *), void *data) {
- if (rect.height() < rect.width()) {
- int x = -arc, y = 0, err = 2-2*arc; /* II. Quadrant */
- int dy = rect.height() - arc * 2;
- int r = arc;
- int stop = 0;
- int lastx, lasty;
- if (dy < 0)
- stop = -dy / 2;
-
- do {
- if (filled) {
- drawHLine(rect.left+x+r, rect.right-x-r, rect.top-y+r-stop, color, plotProc, data);
- drawHLine(rect.left+x+r, rect.right-x-r, rect.bottom+y-r+stop, color, plotProc, data);
- } else {
- (*plotProc)(rect.left+x+r, rect.top-y+r-stop, color, data);
- (*plotProc)(rect.right-x-r, rect.top-y+r-stop, color, data);
- (*plotProc)(rect.left+x+r, rect.bottom+y-r+stop, color, data);
- (*plotProc)(rect.right-x-r, rect.bottom+y-r+stop, color, data);
-
- lastx = x;
- lasty = y;
- }
- arc = err;
- if (arc <= y) err += ++y*2+1; /* e_xy+e_y < 0 */
- if (arc > x || err > y) err += ++x*2+1; /* e_xy+e_x > 0 or no 2nd y-step */
- if (stop && y > stop)
- break;
- } while (x < 0);
-
- if (!filled) {
- x = lastx;
- y = lasty;
-
- drawHLine(rect.left+x+r, rect.right-x-r, rect.top-y+r-stop, color, plotProc, data);
- drawHLine(rect.left+x+r, rect.right-x-r, rect.bottom+y-r+stop, color, plotProc, data);
- }
-
- for (int i = 0; i < dy; i++) {
- if (filled) {
- drawHLine(rect.left, rect.right, rect.top + r + i, color, plotProc, data);
- } else {
- (*plotProc)(rect.left, rect.top + r + i, color, data);
- (*plotProc)(rect.right, rect.top + r + i, color, data);
- }
- }
- } else {
- int y = -arc, x = 0, err = 2-2*arc; /* II. Quadrant */
- int dx = rect.width() - arc * 2;
- int r = arc;
- int stop = 0;
- int lastx, lasty;
- if (dx < 0)
- stop = -dx / 2;
-
- do {
- if (filled) {
- drawVLine(rect.left-x+r-stop, rect.top+y+r, rect.bottom-y-r, color, plotProc, data);
- drawVLine(rect.right+x-r+stop, rect.top+y+r, rect.bottom-y-r, color, plotProc, data);
- } else {
- (*plotProc)(rect.left-x+r-stop, rect.top+y+r, color, data);
- (*plotProc)(rect.left-x+r-stop, rect.bottom-y-r, color, data);
- (*plotProc)(rect.right+x-r+stop, rect.top+y+r, color, data);
- (*plotProc)(rect.right+x-r+stop, rect.bottom-y-r, color, data);
-
- lastx = x;
- lasty = y;
- }
-
- arc = err;
- if (arc <= x) err += ++x*2+1; /* e_xy+e_y < 0 */
- if (arc > y || err > x) err += ++y*2+1; /* e_xy+e_x > 0 or no 2nd y-step */
- if (stop && x > stop)
- break;
- } while (y < 0);
-
- if (!filled) {
- x = lastx;
- y = lasty;
- drawVLine(rect.left-x+r-stop, rect.top+y+r, rect.bottom-y-r, color, plotProc, data);
- drawVLine(rect.right+x-r+stop, rect.top+y+r, rect.bottom-y-r, color, plotProc, data);
- }
-
- for (int i = 0; i < dx; i++) {
- if (filled) {
- drawVLine(rect.left + r + i, rect.top, rect.bottom, color, plotProc, data);
- } else {
- (*plotProc)(rect.left + r + i, rect.top, color, data);
- (*plotProc)(rect.left + r + i, rect.bottom, color, data);
- }
- }
- }
-}
-
-// Based on public-domain code by Darel Rex Finley, 2007
-// http://alienryderflex.com/polygon_fill/
-void Design::drawPolygonScan(int *polyX, int *polyY, int npoints, Common::Rect &bbox, int color,
- void (*plotProc)(int, int, int, void *), void *data) {
- int *nodeX = (int *)calloc(npoints, sizeof(int));
- int i, j;
-
- // Loop through the rows of the image.
- for (int pixelY = bbox.top; pixelY < bbox.bottom; pixelY++) {
- // Build a list of nodes.
- int nodes = 0;
- j = npoints - 1;
-
- for (i = 0; i < npoints; i++) {
- if ((polyY[i] < pixelY && polyY[j] >= pixelY) || (polyY[j] < pixelY && polyY[i] >= pixelY)) {
- nodeX[nodes++] = (int)(polyX[i] + (double)(pixelY - polyY[i]) / (double)(polyY[j]-polyY[i]) *
- (double)(polyX[j] - polyX[i]) + 0.5);
- }
- j = i;
- }
-
- // Sort the nodes, via a simple “Bubble” sort.
- i = 0;
- while (i < nodes - 1) {
- if (nodeX[i] > nodeX[i + 1]) {
- SWAP(nodeX[i], nodeX[i + 1]);
- if (i)
- i--;
- } else {
- i++;
- }
- }
-
- // Fill the pixels between node pairs.
- for (i = 0; i < nodes; i += 2) {
- if (nodeX[i ] >= bbox.right)
- break;
- if (nodeX[i + 1] > bbox.left) {
- nodeX[i] = MAX<int16>(nodeX[i], bbox.left);
- nodeX[i + 1] = MIN<int16>(nodeX[i + 1], bbox.right);
-
- drawHLine(nodeX[i], nodeX[i + 1], pixelY, color, plotProc, data);
- }
- }
- }
-
- free(nodeX);
-}
-
-// http://members.chello.at/easyfilter/bresenham.html
-void Design::drawEllipse(int x0, int y0, int x1, int y1, bool filled, void (*plotProc)(int, int, int, void *), void *data) {
- int a = abs(x1-x0), b = abs(y1-y0), b1 = b&1; /* values of diameter */
- long dx = 4*(1-a)*b*b, dy = 4*(b1+1)*a*a; /* error increment */
- long err = dx+dy+b1*a*a, e2; /* error of 1.step */
-
- if (x0 > x1) { x0 = x1; x1 += a; } /* if called with swapped points */
- if (y0 > y1) y0 = y1; /* .. exchange them */
- y0 += (b+1)/2; y1 = y0-b1; /* starting pixel */
- a *= 8*a; b1 = 8*b*b;
-
- do {
- if (filled) {
- drawHLine(x0, x1, y0, kColorBlack, plotProc, data);
- drawHLine(x0, x1, y1, kColorBlack, plotProc, data);
- } else {
- (*plotProc)(x1, y0, kColorBlack, data); /* I. Quadrant */
- (*plotProc)(x0, y0, kColorBlack, data); /* II. Quadrant */
- (*plotProc)(x0, y1, kColorBlack, data); /* III. Quadrant */
- (*plotProc)(x1, y1, kColorBlack, data); /* IV. Quadrant */
- }
- e2 = 2*err;
- if (e2 <= dy) { y0++; y1--; err += dy += a; } /* y step */
- if (e2 >= dx || 2*err > dy) { x0++; x1--; err += dx += b1; } /* x step */
- } while (x0 <= x1);
-
- while (y0-y1 < b) { /* too early stop of flat ellipses a=1 */
- if (filled) {
- drawHLine(x0-1, x0-1, y0, kColorBlack, plotProc, data); /* -> finish tip of ellipse */
- drawHLine(x1+1, x1+1, y0, kColorBlack, plotProc, data);
- drawHLine(x0-1, x0-1, y1, kColorBlack, plotProc, data);
- drawHLine(x1+1, x1+1, y1, kColorBlack, plotProc, data);
- } else {
- (*plotProc)(x0-1, y0, kColorBlack, data); /* -> finish tip of ellipse */
- (*plotProc)(x1+1, y0, kColorBlack, data);
- (*plotProc)(x0-1, y1, kColorBlack, data);
- (*plotProc)(x1+1, y1, kColorBlack, data);
- }
- y0++;
- y1--;
- }
+ Graphics::drawRoundRect(rect, arc, color, true, drawPixel, &pd);
}
void Design::drawHLine(Graphics::Surface *surface, int x1, int x2, int y, int thickness, int color, Patterns &patterns, byte fillType) {
plotData pd(surface, &patterns, fillType, thickness);
- drawHLine(x1, x2, y, color, drawPixel, &pd);
-}
-
-void Design::drawHLine(int x1, int x2, int y, int color, void (*plotProc)(int, int, int, void *), void *data) {
- if (x1 > x2)
- SWAP(x1, x2);
-
- for (int x = x1; x <= x2; x++)
- (*plotProc)(x, y, color, data);
+ Graphics::drawHLine(x1, x2, y, color, drawPixel, &pd);
}
void Design::drawVLine(Graphics::Surface *surface, int x, int y1, int y2, int thickness, int color, Patterns &patterns, byte fillType) {
plotData pd(surface, &patterns, fillType, thickness);
- drawVLine(x, y1, y2, color, drawPixel, &pd);
-}
-
-void Design::drawVLine(int x, int y1, int y2, int color, void (*plotProc)(int, int, int, void *), void *data) {
- if (y1 > y2)
- SWAP(y1, y2);
-
- for (int y = y1; y <= y2; y++)
- (*plotProc)(x, y, color, data);
-}
-
-/* Bresenham as presented in Foley & Van Dam */
-/* Code is based on GD lib http://libgd.github.io/ */
-void Design::drawThickLine (int x1, int y1, int x2, int y2, int thick, int color,
- void (*plotProc)(int, int, int, void *), void *data) {
- int incr1, incr2, d, x, y, xend, yend, xdirflag, ydirflag;
- int wid;
- int w, wstart;
-
- int dx = abs(x2 - x1);
- int dy = abs(y2 - y1);
-
- if (dx == 0) {
- if (y1 > y2)
- SWAP(y1, y2);
- Common::Rect r(x1, y1, x1 + thick - 1, y2);
- drawFilledRect(r, color, plotProc, data);
- return;
- } else if (dy == 0) {
- if (x1 > x2)
- SWAP(x1, x2);
- Common::Rect r(x1, y1, x2, y1 + thick - 1);
- drawFilledRect(r, color, plotProc, data);
- return;
- }
-
- if (dy <= dx) {
- /* More-or-less horizontal. use wid for vertical stroke */
- /* Doug Claar: watch out for NaN in atan2 (2.0.5) */
-
- /* 2.0.12: Michael Schwartz: divide rather than multiply;
- TBB: but watch out for /0! */
- double ac = cos(atan2 (dy, dx));
- if (ac != 0) {
- wid = thick / ac;
- } else {
- wid = 1;
- }
- if (wid == 0) {
- wid = 1;
- }
- d = 2 * dy - dx;
- incr1 = 2 * dy;
- incr2 = 2 * (dy - dx);
- if (x1 > x2) {
- x = x2;
- y = y2;
- ydirflag = (-1);
- xend = x1;
- } else {
- x = x1;
- y = y1;
- ydirflag = 1;
- xend = x2;
- }
-
- /* Set up line thickness */
- wstart = y - wid / 2;
- for (w = wstart; w < wstart + wid; w++)
- (*plotProc)(x, y, color, data);
-
- if (((y2 - y1) * ydirflag) > 0) {
- while (x < xend) {
- x++;
- if (d < 0) {
- d += incr1;
- } else {
- y++;
- d += incr2;
- }
- wstart = y - wid / 2;
- for (w = wstart; w < wstart + wid; w++)
- (*plotProc)(x, w, color, data);
- }
- } else {
- while (x < xend) {
- x++;
- if (d < 0) {
- d += incr1;
- } else {
- y--;
- d += incr2;
- }
- wstart = y - wid / 2;
- for (w = wstart; w < wstart + wid; w++)
- (*plotProc)(x, w, color, data);
- }
- }
- } else {
- /* More-or-less vertical. use wid for horizontal stroke */
- /* 2.0.12: Michael Schwartz: divide rather than multiply;
- TBB: but watch out for /0! */
- double as = sin(atan2(dy, dx));
- if (as != 0) {
- wid = thick / as;
- } else {
- wid = 1;
- }
- if (wid == 0)
- wid = 1;
-
- d = 2 * dx - dy;
- incr1 = 2 * dx;
- incr2 = 2 * (dx - dy);
- if (y1 > y2) {
- y = y2;
- x = x2;
- yend = y1;
- xdirflag = (-1);
- } else {
- y = y1;
- x = x1;
- yend = y2;
- xdirflag = 1;
- }
-
- /* Set up line thickness */
- wstart = x - wid / 2;
- for (w = wstart; w < wstart + wid; w++)
- (*plotProc)(w, y, color, data);
-
- if (((x2 - x1) * xdirflag) > 0) {
- while (y < yend) {
- y++;
- if (d < 0) {
- d += incr1;
- } else {
- x++;
- d += incr2;
- }
- wstart = x - wid / 2;
- for (w = wstart; w < wstart + wid; w++)
- (*plotProc)(w, y, color, data);
- }
- } else {
- while (y < yend) {
- y++;
- if (d < 0) {
- d += incr1;
- } else {
- x--;
- d += incr2;
- }
- wstart = x - wid / 2;
- for (w = wstart; w < wstart + wid; w++)
- (*plotProc)(w, y, color, data);
- }
- }
- }
+ Graphics::drawVLine(x, y1, y2, color, drawPixel, &pd);
}
FloodFill::FloodFill(Graphics::Surface *surface, byte color1, byte color2) {
diff --git a/engines/wage/design.h b/engines/wage/design.h
index d98d30ce93..43f9ce1ce5 100644
--- a/engines/wage/design.h
+++ b/engines/wage/design.h
@@ -93,16 +93,6 @@ private:
void drawOval(Graphics::Surface *surface, Common::ReadStream &in,
Patterns &patterns, byte fillType, byte borderThickness, byte borderFillType);
void drawBitmap(Graphics::Surface *surface, Common::ReadStream &in);
-
- void drawFilledRect(Common::Rect &rect, int color, void (*plotProc)(int, int, int, void *), void *data);
- static void drawRoundRect(Common::Rect &rect, int arc, int color, bool filled, void (*plotProc)(int, int, int, void *), void *data);
- void drawPolygonScan(int *polyX, int *polyY, int npoints, Common::Rect &bbox, int color,
- void (*plotProc)(int, int, int, void *), void *data);
- void drawEllipse(int x0, int y0, int x1, int y1, bool filled, void (*plotProc)(int, int, int, void *), void *data);
- static void drawHLine(int x1, int x2, int y, int color, void (*plotProc)(int, int, int, void *), void *data);
- static void drawVLine(int x, int y1, int y2, int color, void (*plotProc)(int, int, int, void *), void *data);
- void drawThickLine (int x1, int y1, int x2, int y2, int thick, int color,
- void (*plotProc)(int, int, int, void *), void *data);
};
class FloodFill {
diff --git a/graphics/primitives.cpp b/graphics/primitives.cpp
index 564bdb9673..0e970655d4 100644
--- a/graphics/primitives.cpp
+++ b/graphics/primitives.cpp
@@ -21,6 +21,7 @@
*/
#include "common/util.h"
+#include "graphics/primitives.h"
namespace Graphics {
@@ -62,6 +63,22 @@ void drawLine(int x0, int y0, int x1, int y1, int color, void (*plotProc)(int, i
}
}
+void drawHLine(int x1, int x2, int y, int color, void (*plotProc)(int, int, int, void *), void *data) {
+ if (x1 > x2)
+ SWAP(x1, x2);
+
+ for (int x = x1; x <= x2; x++)
+ (*plotProc)(x, y, color, data);
+}
+
+void drawVLine(int x, int y1, int y2, int color, void (*plotProc)(int, int, int, void *), void *data) {
+ if (y1 > y2)
+ SWAP(y1, y2);
+
+ for (int y = y1; y <= y2; y++)
+ (*plotProc)(x, y, color, data);
+}
+
void drawThickLine(int x0, int y0, int x1, int y1, int penX, int penY, int color, void (*plotProc)(int, int, int, void *), void *data) {
assert(penX > 0 && penY > 0);
@@ -79,4 +96,344 @@ void drawThickLine(int x0, int y0, int x1, int y1, int penX, int penY, int color
drawLine(x0 + x, y0 + y, x1 + x, y1 + y, color, plotProc, data);
}
+/* Bresenham as presented in Foley & Van Dam */
+/* Code is based on GD lib http://libgd.github.io/ */
+void drawThickLine2(int x1, int y1, int x2, int y2, int thick, int color, void (*plotProc)(int, int, int, void *), void *data) {
+ int incr1, incr2, d, x, y, xend, yend, xdirflag, ydirflag;
+ int wid;
+ int w, wstart;
+
+ int dx = abs(x2 - x1);
+ int dy = abs(y2 - y1);
+
+ if (dx == 0) {
+ if (y1 > y2)
+ SWAP(y1, y2);
+ Common::Rect r(x1, y1, x1 + thick - 1, y2);
+ drawFilledRect(r, color, plotProc, data);
+ return;
+ } else if (dy == 0) {
+ if (x1 > x2)
+ SWAP(x1, x2);
+ Common::Rect r(x1, y1, x2, y1 + thick - 1);
+ drawFilledRect(r, color, plotProc, data);
+ return;
+ }
+
+ if (dy <= dx) {
+ /* More-or-less horizontal. use wid for vertical stroke */
+ /* Doug Claar: watch out for NaN in atan2 (2.0.5) */
+
+ /* 2.0.12: Michael Schwartz: divide rather than multiply;
+ TBB: but watch out for /0! */
+ double ac = cos(atan2 (dy, dx));
+ if (ac != 0) {
+ wid = thick / ac;
+ } else {
+ wid = 1;
+ }
+ if (wid == 0) {
+ wid = 1;
+ }
+ d = 2 * dy - dx;
+ incr1 = 2 * dy;
+ incr2 = 2 * (dy - dx);
+ if (x1 > x2) {
+ x = x2;
+ y = y2;
+ ydirflag = (-1);
+ xend = x1;
+ } else {
+ x = x1;
+ y = y1;
+ ydirflag = 1;
+ xend = x2;
+ }
+
+ /* Set up line thickness */
+ wstart = y - wid / 2;
+ for (w = wstart; w < wstart + wid; w++)
+ (*plotProc)(x, y, color, data);
+
+ if (((y2 - y1) * ydirflag) > 0) {
+ while (x < xend) {
+ x++;
+ if (d < 0) {
+ d += incr1;
+ } else {
+ y++;
+ d += incr2;
+ }
+ wstart = y - wid / 2;
+ for (w = wstart; w < wstart + wid; w++)
+ (*plotProc)(x, w, color, data);
+ }
+ } else {
+ while (x < xend) {
+ x++;
+ if (d < 0) {
+ d += incr1;
+ } else {
+ y--;
+ d += incr2;
+ }
+ wstart = y - wid / 2;
+ for (w = wstart; w < wstart + wid; w++)
+ (*plotProc)(x, w, color, data);
+ }
+ }
+ } else {
+ /* More-or-less vertical. use wid for horizontal stroke */
+ /* 2.0.12: Michael Schwartz: divide rather than multiply;
+ TBB: but watch out for /0! */
+ double as = sin(atan2(dy, dx));
+ if (as != 0) {
+ wid = thick / as;
+ } else {
+ wid = 1;
+ }
+ if (wid == 0)
+ wid = 1;
+
+ d = 2 * dx - dy;
+ incr1 = 2 * dx;
+ incr2 = 2 * (dx - dy);
+ if (y1 > y2) {
+ y = y2;
+ x = x2;
+ yend = y1;
+ xdirflag = (-1);
+ } else {
+ y = y1;
+ x = x1;
+ yend = y2;
+ xdirflag = 1;
+ }
+
+ /* Set up line thickness */
+ wstart = x - wid / 2;
+ for (w = wstart; w < wstart + wid; w++)
+ (*plotProc)(w, y, color, data);
+
+ if (((x2 - x1) * xdirflag) > 0) {
+ while (y < yend) {
+ y++;
+ if (d < 0) {
+ d += incr1;
+ } else {
+ x++;
+ d += incr2;
+ }
+ wstart = x - wid / 2;
+ for (w = wstart; w < wstart + wid; w++)
+ (*plotProc)(w, y, color, data);
+ }
+ } else {
+ while (y < yend) {
+ y++;
+ if (d < 0) {
+ d += incr1;
+ } else {
+ x--;
+ d += incr2;
+ }
+ wstart = x - wid / 2;
+ for (w = wstart; w < wstart + wid; w++)
+ (*plotProc)(w, y, color, data);
+ }
+ }
+ }
+}
+
+void drawFilledRect(Common::Rect &rect, int color, void (*plotProc)(int, int, int, void *), void *data) {
+ for (int y = rect.top; y <= rect.bottom; y++)
+ drawHLine(rect.left, rect.right, y, color, plotProc, data);
+}
+
+// http://members.chello.at/easyfilter/bresenham.html
+void drawRoundRect(Common::Rect &rect, int arc, int color, bool filled, void (*plotProc)(int, int, int, void *), void *data) {
+ if (rect.height() < rect.width()) {
+ int x = -arc, y = 0, err = 2-2*arc; /* II. Quadrant */
+ int dy = rect.height() - arc * 2;
+ int r = arc;
+ int stop = 0;
+ int lastx, lasty;
+ if (dy < 0)
+ stop = -dy / 2;
+
+ do {
+ if (filled) {
+ drawHLine(rect.left+x+r, rect.right-x-r, rect.top-y+r-stop, color, plotProc, data);
+ drawHLine(rect.left+x+r, rect.right-x-r, rect.bottom+y-r+stop, color, plotProc, data);
+ } else {
+ (*plotProc)(rect.left+x+r, rect.top-y+r-stop, color, data);
+ (*plotProc)(rect.right-x-r, rect.top-y+r-stop, color, data);
+ (*plotProc)(rect.left+x+r, rect.bottom+y-r+stop, color, data);
+ (*plotProc)(rect.right-x-r, rect.bottom+y-r+stop, color, data);
+
+ lastx = x;
+ lasty = y;
+ }
+ arc = err;
+ if (arc <= y) err += ++y*2+1; /* e_xy+e_y < 0 */
+ if (arc > x || err > y) err += ++x*2+1; /* e_xy+e_x > 0 or no 2nd y-step */
+ if (stop && y > stop)
+ break;
+ } while (x < 0);
+
+ if (!filled) {
+ x = lastx;
+ y = lasty;
+
+ drawHLine(rect.left+x+r, rect.right-x-r, rect.top-y+r-stop, color, plotProc, data);
+ drawHLine(rect.left+x+r, rect.right-x-r, rect.bottom+y-r+stop, color, plotProc, data);
+ }
+
+ for (int i = 0; i < dy; i++) {
+ if (filled) {
+ drawHLine(rect.left, rect.right, rect.top + r + i, color, plotProc, data);
+ } else {
+ (*plotProc)(rect.left, rect.top + r + i, color, data);
+ (*plotProc)(rect.right, rect.top + r + i, color, data);
+ }
+ }
+ } else {
+ int y = -arc, x = 0, err = 2-2*arc; /* II. Quadrant */
+ int dx = rect.width() - arc * 2;
+ int r = arc;
+ int stop = 0;
+ int lastx, lasty;
+ if (dx < 0)
+ stop = -dx / 2;
+
+ do {
+ if (filled) {
+ drawVLine(rect.left-x+r-stop, rect.top+y+r, rect.bottom-y-r, color, plotProc, data);
+ drawVLine(rect.right+x-r+stop, rect.top+y+r, rect.bottom-y-r, color, plotProc, data);
+ } else {
+ (*plotProc)(rect.left-x+r-stop, rect.top+y+r, color, data);
+ (*plotProc)(rect.left-x+r-stop, rect.bottom-y-r, color, data);
+ (*plotProc)(rect.right+x-r+stop, rect.top+y+r, color, data);
+ (*plotProc)(rect.right+x-r+stop, rect.bottom-y-r, color, data);
+
+ lastx = x;
+ lasty = y;
+ }
+
+ arc = err;
+ if (arc <= x) err += ++x*2+1; /* e_xy+e_y < 0 */
+ if (arc > y || err > x) err += ++y*2+1; /* e_xy+e_x > 0 or no 2nd y-step */
+ if (stop && x > stop)
+ break;
+ } while (y < 0);
+
+ if (!filled) {
+ x = lastx;
+ y = lasty;
+ drawVLine(rect.left-x+r-stop, rect.top+y+r, rect.bottom-y-r, color, plotProc, data);
+ drawVLine(rect.right+x-r+stop, rect.top+y+r, rect.bottom-y-r, color, plotProc, data);
+ }
+
+ for (int i = 0; i < dx; i++) {
+ if (filled) {
+ drawVLine(rect.left + r + i, rect.top, rect.bottom, color, plotProc, data);
+ } else {
+ (*plotProc)(rect.left + r + i, rect.top, color, data);
+ (*plotProc)(rect.left + r + i, rect.bottom, color, data);
+ }
+ }
+ }
+}
+
+// Based on public-domain code by Darel Rex Finley, 2007
+// http://alienryderflex.com/polygon_fill/
+void drawPolygonScan(int *polyX, int *polyY, int npoints, Common::Rect &bbox, int color, void (*plotProc)(int, int, int, void *), void *data) {
+ int *nodeX = (int *)calloc(npoints, sizeof(int));
+ int i, j;
+
+ // Loop through the rows of the image.
+ for (int pixelY = bbox.top; pixelY < bbox.bottom; pixelY++) {
+ // Build a list of nodes.
+ int nodes = 0;
+ j = npoints - 1;
+
+ for (i = 0; i < npoints; i++) {
+ if ((polyY[i] < pixelY && polyY[j] >= pixelY) || (polyY[j] < pixelY && polyY[i] >= pixelY)) {
+ nodeX[nodes++] = (int)(polyX[i] + (double)(pixelY - polyY[i]) / (double)(polyY[j]-polyY[i]) *
+ (double)(polyX[j] - polyX[i]) + 0.5);
+ }
+ j = i;
+ }
+
+ // Sort the nodes, via a simple “Bubble” sort.
+ i = 0;
+ while (i < nodes - 1) {
+ if (nodeX[i] > nodeX[i + 1]) {
+ SWAP(nodeX[i], nodeX[i + 1]);
+ if (i)
+ i--;
+ } else {
+ i++;
+ }
+ }
+
+ // Fill the pixels between node pairs.
+ for (i = 0; i < nodes; i += 2) {
+ if (nodeX[i ] >= bbox.right)
+ break;
+ if (nodeX[i + 1] > bbox.left) {
+ nodeX[i] = MAX<int16>(nodeX[i], bbox.left);
+ nodeX[i + 1] = MIN<int16>(nodeX[i + 1], bbox.right);
+
+ drawHLine(nodeX[i], nodeX[i + 1], pixelY, color, plotProc, data);
+ }
+ }
+ }
+
+ free(nodeX);
+}
+
+// http://members.chello.at/easyfilter/bresenham.html
+void drawEllipse(int x0, int y0, int x1, int y1, int color, bool filled, void (*plotProc)(int, int, int, void *), void *data) {
+ int a = abs(x1-x0), b = abs(y1-y0), b1 = b&1; /* values of diameter */
+ long dx = 4*(1-a)*b*b, dy = 4*(b1+1)*a*a; /* error increment */
+ long err = dx+dy+b1*a*a, e2; /* error of 1.step */
+
+ if (x0 > x1) { x0 = x1; x1 += a; } /* if called with swapped points */
+ if (y0 > y1) y0 = y1; /* .. exchange them */
+ y0 += (b+1)/2; y1 = y0-b1; /* starting pixel */
+ a *= 8*a; b1 = 8*b*b;
+
+ do {
+ if (filled) {
+ drawHLine(x0, x1, y0, color, plotProc, data);
+ drawHLine(x0, x1, y1, color, plotProc, data);
+ } else {
+ (*plotProc)(x1, y0, color, data); /* I. Quadrant */
+ (*plotProc)(x0, y0, color, data); /* II. Quadrant */
+ (*plotProc)(x0, y1, color, data); /* III. Quadrant */
+ (*plotProc)(x1, y1, color, data); /* IV. Quadrant */
+ }
+ e2 = 2*err;
+ if (e2 <= dy) { y0++; y1--; err += dy += a; } /* y step */
+ if (e2 >= dx || 2*err > dy) { x0++; x1--; err += dx += b1; } /* x step */
+ } while (x0 <= x1);
+
+ while (y0-y1 < b) { /* too early stop of flat ellipses a=1 */
+ if (filled) {
+ drawHLine(x0-1, x0-1, y0, color, plotProc, data); /* -> finish tip of ellipse */
+ drawHLine(x1+1, x1+1, y0, color, plotProc, data);
+ drawHLine(x0-1, x0-1, y1, color, plotProc, data);
+ drawHLine(x1+1, x1+1, y1, color, plotProc, data);
+ } else {
+ (*plotProc)(x0-1, y0, color, data); /* -> finish tip of ellipse */
+ (*plotProc)(x1+1, y0, color, data);
+ (*plotProc)(x0-1, y1, color, data);
+ (*plotProc)(x1+1, y1, color, data);
+ }
+ y0++;
+ y1--;
+ }
+}
+
} // End of namespace Graphics
diff --git a/graphics/primitives.h b/graphics/primitives.h
index a3e8ab1565..62dc10bfdf 100644
--- a/graphics/primitives.h
+++ b/graphics/primitives.h
@@ -23,10 +23,21 @@
#ifndef GRAPHICS_PRIMITIVES_H
#define GRAPHICS_PRIMITIVES_H
+#include "common/rect.h"
+
namespace Graphics {
void drawLine(int x0, int y0, int x1, int y1, int color, void (*plotProc)(int, int, int, void *), void *data);
+void drawHLine(int x1, int x2, int y, int color, void (*plotProc)(int, int, int, void *), void *data);
+void drawVLine(int x, int y1, int y2, int color, void (*plotProc)(int, int, int, void *), void *data);
void drawThickLine(int x0, int y0, int x1, int y1, int penX, int penY, int color, void (*plotProc)(int, int, int, void *), void *data);
+void drawThickLine2(int x1, int y1, int x2, int y2, int thick, int color,
+ void (*plotProc)(int, int, int, void *), void *data);
+void drawFilledRect(Common::Rect &rect, int color, void (*plotProc)(int, int, int, void *), void *data);
+void drawRoundRect(Common::Rect &rect, int arc, int color, bool filled, void (*plotProc)(int, int, int, void *), void *data);
+void drawPolygonScan(int *polyX, int *polyY, int npoints, Common::Rect &bbox, int color,
+ void (*plotProc)(int, int, int, void *), void *data);
+void drawEllipse(int x0, int y0, int x1, int y1, int color, bool filled, void (*plotProc)(int, int, int, void *), void *data);
} // End of namespace Graphics