mirror of
https://github.com/aseprite/aseprite.git
synced 2025-03-14 04:19:12 +00:00
similarly for algo_ellipsefill
This commit is contained in:
parent
8549774060
commit
debb8e9f32
133
src/doc/algo.cpp
133
src/doc/algo.cpp
@ -63,19 +63,22 @@ void algo_line(int x1, int y1, int x2, int y2, void* data, AlgoPixel proc)
|
||||
/* Additional helper functions for the ellipse-drawing helper function
|
||||
below corresponding to routines in Bresenham's algorithm. */
|
||||
namespace {
|
||||
int bresenham_ellipse_error(int rx, int ry, int x, int y) {
|
||||
int bresenham_ellipse_error(int rx, int ry, int x, int y)
|
||||
{
|
||||
return x*x*ry*ry + y*y*rx*rx - rx*rx*ry*ry;
|
||||
}
|
||||
|
||||
// Initialize positions x and y for Bresenham's algorithm
|
||||
void bresenham_ellipse_init(int rx, int ry, int *px, int *py) {
|
||||
void bresenham_ellipse_init(int rx, int ry, int *px, int *py)
|
||||
{
|
||||
// Start at the fatter pole
|
||||
if (rx > ry) { *px = 0; *py = ry; }
|
||||
else { *px = rx; *py = 0; }
|
||||
}
|
||||
|
||||
// Move to next pixel to draw, according to Bresenham's algorithm
|
||||
void bresenham_ellipse_step(int rx, int ry, int *px, int *py) {
|
||||
void bresenham_ellipse_step(int rx, int ry, int *px, int *py)
|
||||
{
|
||||
int &x = *px, &y = *py;
|
||||
// Move towards the skinnier pole. Having 2 cases isn't needed, but it ensures
|
||||
// swapping rx and ry is the same as rotating 90 degrees.
|
||||
@ -107,11 +110,13 @@ namespace {
|
||||
for Allegro 4.x.
|
||||
|
||||
Adapted for ASEPRITE by David A. Capello. */
|
||||
void algo_ellipse(int x1, int y1, int x2, int y2, void *data, AlgoPixel proc) {
|
||||
void algo_ellipse(int x1, int y1, int x2, int y2, void *data, AlgoPixel proc)
|
||||
{
|
||||
int mx, my, rx, ry;
|
||||
|
||||
int x, y;
|
||||
|
||||
/* Cheap hack to get elllipses with integer diameter, by just offsetting
|
||||
* some quadrants by one pixel. */
|
||||
int mx2, my2;
|
||||
|
||||
mx = (x1 + x2) / 2;
|
||||
@ -147,7 +152,7 @@ void algo_ellipse(int x1, int y1, int x2, int y2, void *data, AlgoPixel proc) {
|
||||
proc(mx - rx, my2, data);
|
||||
}
|
||||
|
||||
/* Initialize drawing position */
|
||||
/* Initialize drawing position at a pole. */
|
||||
bresenham_ellipse_init(rx, ry, &x, &y);
|
||||
|
||||
for (;;) {
|
||||
@ -155,8 +160,8 @@ void algo_ellipse(int x1, int y1, int x2, int y2, void *data, AlgoPixel proc) {
|
||||
bresenham_ellipse_step(rx, ry, &x, &y);
|
||||
|
||||
/* Edge conditions */
|
||||
if (y == 0 && x < rx) ++y; // don't draw on horizontal radius except at pole
|
||||
if (x == 0 && y < ry) ++x; // don't draw on vertical radius except at pole
|
||||
if (y == 0 && x < rx) ++y; // don't move to horizontal radius except at pole
|
||||
if (x == 0 && y < ry) ++x; // don't move to vertical radius except at pole
|
||||
if (y <= 0 || x <= 0) break; // stop before pole, since it's already drawn
|
||||
|
||||
/* Process pixel */
|
||||
@ -167,14 +172,9 @@ void algo_ellipse(int x1, int y1, int x2, int y2, void *data, AlgoPixel proc) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void algo_ellipsefill(int x1, int y1, int x2, int y2, void *data, AlgoHLine proc)
|
||||
{
|
||||
int mx, my, rx, ry;
|
||||
|
||||
int err;
|
||||
int xx, yy;
|
||||
int xa, ya;
|
||||
int x, y;
|
||||
|
||||
/* Cheap hack to get elllipses with integer diameter, by just offsetting
|
||||
@ -197,105 +197,30 @@ void algo_ellipsefill(int x1, int y1, int x2, int y2, void *data, AlgoHLine proc
|
||||
rx /= 2;
|
||||
ry /= 2;
|
||||
|
||||
/* Draw the 4 poles. */
|
||||
proc(mx, my2 + ry, mx, data);
|
||||
proc(mx, my - ry, mx, data);
|
||||
/* proc(mx2 + rx, my, mx2 + rx, data); */
|
||||
/* proc(mx - rx, my, mx - rx, data); */
|
||||
/* Draw the north and south poles (possibly 2 pixels) */
|
||||
proc(mx, my2 + ry, mx2, data);
|
||||
proc(mx, my - ry, mx2, data);
|
||||
|
||||
/* Draw the equator (possibly width 2) */
|
||||
proc(mx - rx, my, mx2 + rx, data);
|
||||
if (my != my2) proc(mx - rx, my2, mx2 + rx, data);
|
||||
|
||||
/* For even diameter axis, double the poles. */
|
||||
if (mx != mx2) {
|
||||
proc(mx2, my2 + ry, mx2, data);
|
||||
proc(mx2, my - ry, mx2, data);
|
||||
}
|
||||
|
||||
if (my != my2) {
|
||||
/* proc(mx2 + rx, my2, data); */
|
||||
/* proc(mx - rx, my2, data); */
|
||||
proc(mx - rx, my2, mx2 + rx, data);
|
||||
}
|
||||
|
||||
xx = rx * rx;
|
||||
yy = ry * ry;
|
||||
|
||||
/* Do the 'x direction' part of the arc. */
|
||||
|
||||
x = 0;
|
||||
y = ry;
|
||||
xa = 0;
|
||||
ya = xx * 2 * ry;
|
||||
err = xx / 4 - xx * ry;
|
||||
/* Initialize drawing position at a pole. */
|
||||
bresenham_ellipse_init(rx, ry, &x, &y);
|
||||
|
||||
for (;;) {
|
||||
err += xa + yy;
|
||||
if (err >= 0) {
|
||||
ya -= xx * 2;
|
||||
err -= ya;
|
||||
y--;
|
||||
}
|
||||
xa += yy * 2;
|
||||
x++;
|
||||
if (xa >= ya)
|
||||
break;
|
||||
/* Step to the next pixel to draw. */
|
||||
bresenham_ellipse_step(rx, ry, &x, &y);
|
||||
|
||||
/* proc(mx2 + x, my - y, data); */
|
||||
/* proc(mx - x, my - y, data); */
|
||||
/* proc(mx2 + x, my2 + y, data); */
|
||||
/* proc(mx - x, my2 + y, data); */
|
||||
/* Edge conditions */
|
||||
if (y == 0 && x < rx) ++y; // don't move to horizontal radius except at pole
|
||||
if (x == 0 && y < ry) ++x; // don't move to vertical radius except at pole
|
||||
if (y <= 0 || x <= 0) break; // stop before pole, since it's already drawn
|
||||
|
||||
/* Draw the north and south 'lines of latitude' */
|
||||
proc(mx - x, my - y, mx2 + x, data);
|
||||
proc(mx - x, my2 + y, mx2 + x, data);
|
||||
}
|
||||
|
||||
/* Fill in missing pixels for very thin ellipses. (This is caused because
|
||||
* we always take 1-pixel steps above, and thus might jump past the actual
|
||||
* ellipse line.)
|
||||
*/
|
||||
if (y == 0)
|
||||
while (x < rx) {
|
||||
/* proc(mx2 + x, my - 1, data); */
|
||||
/* proc(mx2 + x, my2 + 1, data); */
|
||||
/* proc(mx - x, my - 1, data); */
|
||||
/* proc(mx - x, my2 + 1, data); */
|
||||
x++;
|
||||
}
|
||||
|
||||
/* Do the 'y direction' part of the arc. */
|
||||
|
||||
x = rx;
|
||||
y = 0;
|
||||
xa = yy * 2 * rx;
|
||||
ya = 0;
|
||||
err = yy / 4 - yy * rx;
|
||||
|
||||
for (;;) {
|
||||
err += ya + xx;
|
||||
if (err >= 0) {
|
||||
xa -= yy * 2;
|
||||
err -= xa;
|
||||
x--;
|
||||
}
|
||||
ya += xx * 2;
|
||||
y++;
|
||||
if (ya > xa)
|
||||
break;
|
||||
/* proc(mx2 + x, my - y, data); */
|
||||
/* proc(mx - x, my - y, data); */
|
||||
/* proc(mx2 + x, my2 + y, data); */
|
||||
/* proc(mx - x, my2 + y, data); */
|
||||
proc(mx - x, my - y, mx2 + x, data);
|
||||
proc(mx - x, my2 + y, mx2 + x, data);
|
||||
}
|
||||
|
||||
/* See comment above. */
|
||||
if (x == 0)
|
||||
while (y < ry) {
|
||||
/* proc(mx - 1, my - y, data); */
|
||||
/* proc(mx2 + 1, my - y, data); */
|
||||
/* proc(mx - 1, my2 + y, data); */
|
||||
/* proc(mx2 + 1, my2 + y, data); */
|
||||
y++;
|
||||
}
|
||||
}
|
||||
|
||||
// Algorightm from Allegro (allegro/src/spline.c)
|
||||
|
Loading…
x
Reference in New Issue
Block a user