Fixed tests
Before Width: | Height: | Size: 284 B After Width: | Height: | Size: 248 B |
Before Width: | Height: | Size: 218 B After Width: | Height: | Size: 199 B |
Before Width: | Height: | Size: 384 B After Width: | Height: | Size: 314 B |
Before Width: | Height: | Size: 439 B After Width: | Height: | Size: 428 B |
Before Width: | Height: | Size: 438 B After Width: | Height: | Size: 426 B |
Before Width: | Height: | Size: 439 B After Width: | Height: | Size: 430 B |
Before Width: | Height: | Size: 402 B After Width: | Height: | Size: 404 B |
Before Width: | Height: | Size: 257 B After Width: | Height: | Size: 237 B |
Before Width: | Height: | Size: 324 B After Width: | Height: | Size: 301 B |
Before Width: | Height: | Size: 488 B After Width: | Height: | Size: 493 B |
Before Width: | Height: | Size: 507 B After Width: | Height: | Size: 514 B |
Before Width: | Height: | Size: 427 B After Width: | Height: | Size: 429 B |
Before Width: | Height: | Size: 394 B After Width: | Height: | Size: 375 B |
Before Width: | Height: | Size: 496 B After Width: | Height: | Size: 493 B |
Before Width: | Height: | Size: 523 B After Width: | Height: | Size: 519 B |
Before Width: | Height: | Size: 403 B After Width: | Height: | Size: 405 B |
|
@ -196,13 +196,11 @@ def helper_chord(mode, bbox, start, end):
|
||||||
def test_chord1():
|
def test_chord1():
|
||||||
for mode in ["RGB", "L"]:
|
for mode in ["RGB", "L"]:
|
||||||
helper_chord(mode, BBOX1, 0, 180)
|
helper_chord(mode, BBOX1, 0, 180)
|
||||||
helper_chord(mode, BBOX1, 0.5, 180.4)
|
|
||||||
|
|
||||||
|
|
||||||
def test_chord2():
|
def test_chord2():
|
||||||
for mode in ["RGB", "L"]:
|
for mode in ["RGB", "L"]:
|
||||||
helper_chord(mode, BBOX2, 0, 180)
|
helper_chord(mode, BBOX2, 0, 180)
|
||||||
helper_chord(mode, BBOX2, 0.5, 180.4)
|
|
||||||
|
|
||||||
|
|
||||||
def test_chord_width():
|
def test_chord_width():
|
||||||
|
@ -465,13 +463,13 @@ def helper_pieslice(bbox, start, end):
|
||||||
|
|
||||||
|
|
||||||
def test_pieslice1():
|
def test_pieslice1():
|
||||||
helper_pieslice(BBOX1, -90, 45)
|
helper_pieslice(BBOX1, -92, 46)
|
||||||
helper_pieslice(BBOX1, -90.5, 45.4)
|
helper_pieslice(BBOX1, -92.2, 46.2)
|
||||||
|
|
||||||
|
|
||||||
def test_pieslice2():
|
def test_pieslice2():
|
||||||
helper_pieslice(BBOX2, -90, 45)
|
helper_pieslice(BBOX2, -92, 46)
|
||||||
helper_pieslice(BBOX2, -90.5, 45.4)
|
helper_pieslice(BBOX2, -92.2, 46.2)
|
||||||
|
|
||||||
|
|
||||||
def test_pieslice_width():
|
def test_pieslice_width():
|
||||||
|
|
|
@ -119,7 +119,7 @@ class ImageDraw:
|
||||||
fill = self.draw.draw_ink(fill)
|
fill = self.draw.draw_ink(fill)
|
||||||
return ink, fill
|
return ink, fill
|
||||||
|
|
||||||
def arc(self, xy, start, end, fill=None, width=0):
|
def arc(self, xy, start, end, fill=None, width=1):
|
||||||
"""Draw an arc."""
|
"""Draw an arc."""
|
||||||
ink, fill = self._getink(fill)
|
ink, fill = self._getink(fill)
|
||||||
if ink is not None:
|
if ink is not None:
|
||||||
|
|
|
@ -1150,6 +1150,30 @@ typedef struct {
|
||||||
|
|
||||||
typedef void (*clip_ellipse_init)(clip_ellipse_state*, int32_t, int32_t, int32_t, float, float);
|
typedef void (*clip_ellipse_init)(clip_ellipse_state*, int32_t, int32_t, int32_t, float, float);
|
||||||
|
|
||||||
|
void debug_clip_tree(clip_node* root, int space) {
|
||||||
|
if (root == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (root->type == CT_CLIP) {
|
||||||
|
int t = space;
|
||||||
|
while (t--) {
|
||||||
|
fputc(' ', stderr);
|
||||||
|
}
|
||||||
|
fprintf(stderr, "clip %+fx%+fy%+f > 0\n", root->a, root->b, root->c);
|
||||||
|
} else {
|
||||||
|
debug_clip_tree(root->l, space + 2);
|
||||||
|
int t = space;
|
||||||
|
while (t--) {
|
||||||
|
fputc(' ', stderr);
|
||||||
|
}
|
||||||
|
fprintf(stderr, "%s\n", root->type == CT_AND ? "and" : "or");
|
||||||
|
debug_clip_tree(root->r, space + 2);
|
||||||
|
}
|
||||||
|
if (space == 0) {
|
||||||
|
fputc('\n', stderr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Resulting angles will satisfy 0 <= al < 360, al <= ar <= al + 360
|
// Resulting angles will satisfy 0 <= al < 360, al <= ar <= al + 360
|
||||||
void normalize_angles(float* al, float* ar) {
|
void normalize_angles(float* al, float* ar) {
|
||||||
if (*ar - *al >= 360) {
|
if (*ar - *al >= 360) {
|
||||||
|
@ -1162,10 +1186,10 @@ void normalize_angles(float* al, float* ar) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// An arc with caps orthogonal to the ellipse curve.
|
// An arc with caps orthogonal to the ellipse curve.
|
||||||
void arc_init(clip_ellipse_state* s, int32_t a, int32_t b, int32_t w, float _al, float _ar) {
|
void arc_init(clip_ellipse_state* s, int32_t a, int32_t b, int32_t w, float al, float ar) {
|
||||||
if (a < b) {
|
if (a < b) {
|
||||||
// transpose the coordinate system
|
// transpose the coordinate system
|
||||||
arc_init(s, b, a, w, 90 - _ar, 90 - _al);
|
arc_init(s, b, a, w, 90 - ar, 90 - al);
|
||||||
ellipse_init(&s->st, a, b, w);
|
ellipse_init(&s->st, a, b, w);
|
||||||
clip_tree_transpose(s->root);
|
clip_tree_transpose(s->root);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1175,8 +1199,6 @@ void arc_init(clip_ellipse_state* s, int32_t a, int32_t b, int32_t w, float _al,
|
||||||
s->head = NULL;
|
s->head = NULL;
|
||||||
s->node_count = 0;
|
s->node_count = 0;
|
||||||
|
|
||||||
int32_t al = round(_al), ar = round(_ar);
|
|
||||||
|
|
||||||
// building clipping tree, a lot of different cases
|
// building clipping tree, a lot of different cases
|
||||||
if (ar == al + 360) {
|
if (ar == al + 360) {
|
||||||
s->root = NULL;
|
s->root = NULL;
|
||||||
|
@ -1191,25 +1213,12 @@ void arc_init(clip_ellipse_state* s, int32_t a, int32_t b, int32_t w, float _al,
|
||||||
rc->a = a * sin(ar * M_PI / 180.0);
|
rc->a = a * sin(ar * M_PI / 180.0);
|
||||||
rc->b = -b * cos(ar * M_PI / 180.0);
|
rc->b = -b * cos(ar * M_PI / 180.0);
|
||||||
rc->c = (b * b - a * a) * sin(ar * M_PI / 90.0) / 2.0;
|
rc->c = (b * b - a * a) * sin(ar * M_PI / 90.0) / 2.0;
|
||||||
if (al % 180 == 0 || ar % 180 == 0 || al == ar) {
|
if (fmod(al, 180) == 0 || fmod(ar, 180) == 0) {
|
||||||
s->root = s->nodes + s->node_count++;
|
s->root = s->nodes + s->node_count++;
|
||||||
s->root->l = lc;
|
s->root->l = lc;
|
||||||
s->root->r = rc;
|
s->root->r = rc;
|
||||||
s->root->type = ar - al < 180 ? CT_AND : CT_OR;
|
s->root->type = ar - al < 180 ? CT_AND : CT_OR;
|
||||||
if (al == ar) {
|
} else if (((int)(al / 180) + (int)(ar / 180)) % 2 == 1) {
|
||||||
lc = s->nodes + s->node_count++;
|
|
||||||
lc->l = lc->r = NULL;
|
|
||||||
lc->type = CT_CLIP;
|
|
||||||
lc->a = al == 0 ? 1 : al == 180 ? -1 : 0;
|
|
||||||
lc->b = al % 180 ? (al < 180 ? 1 : -1) : 0;
|
|
||||||
lc->c = 0;
|
|
||||||
rc = s->root;
|
|
||||||
s->root = s->nodes + s->node_count++;
|
|
||||||
s->root->l = lc;
|
|
||||||
s->root->r = rc;
|
|
||||||
s->root->type = CT_AND;
|
|
||||||
}
|
|
||||||
} else if ((al / 180 + ar / 180) % 2 == 1) {
|
|
||||||
s->root = s->nodes + s->node_count++;
|
s->root = s->nodes + s->node_count++;
|
||||||
s->root->l = s->nodes + s->node_count++;
|
s->root->l = s->nodes + s->node_count++;
|
||||||
s->root->l->l = s->nodes + s->node_count++;
|
s->root->l->l = s->nodes + s->node_count++;
|
||||||
|
@ -1226,8 +1235,8 @@ void arc_init(clip_ellipse_state* s, int32_t a, int32_t b, int32_t w, float _al,
|
||||||
s->root->r->l->l = s->root->r->l->r = NULL;
|
s->root->r->l->l = s->root->r->l->r = NULL;
|
||||||
s->root->l->l->a = s->root->l->l->c = 0;
|
s->root->l->l->a = s->root->l->l->c = 0;
|
||||||
s->root->r->l->a = s->root->r->l->c = 0;
|
s->root->r->l->a = s->root->r->l->c = 0;
|
||||||
s->root->l->l->b = (al / 180) % 2 == 0 ? 1 : -1;
|
s->root->l->l->b = (int)(al / 180) % 2 == 0 ? 1 : -1;
|
||||||
s->root->r->l->b = (ar / 180) % 2 == 0 ? 1 : -1;
|
s->root->r->l->b = (int)(ar / 180) % 2 == 0 ? 1 : -1;
|
||||||
} else {
|
} else {
|
||||||
s->root = s->nodes + s->node_count++;
|
s->root = s->nodes + s->node_count++;
|
||||||
s->root->l = s->nodes + s->node_count++;
|
s->root->l = s->nodes + s->node_count++;
|
||||||
|
@ -1268,6 +1277,48 @@ void chord_line_init(clip_ellipse_state* s, int32_t a, int32_t b, int32_t w, flo
|
||||||
s->root->r->c = 2 * w * sqrt(pow(s->root->l->a, 2.0) + pow(s->root->l->b, 2.0)) - s->root->l->c;
|
s->root->r->c = 2 * w * sqrt(pow(s->root->l->a, 2.0) + pow(s->root->l->b, 2.0)) - s->root->l->c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Pie side.
|
||||||
|
void pie_side_init(clip_ellipse_state* s, int32_t a, int32_t b, int32_t w, float al, float _) {
|
||||||
|
ellipse_init(&s->st, a, b, a + b + 1);
|
||||||
|
|
||||||
|
s->head = NULL;
|
||||||
|
s->node_count = 0;
|
||||||
|
|
||||||
|
double xl = a * cos(al * M_PI / 180.0);
|
||||||
|
double yl = b * sin(al * M_PI / 180.0);
|
||||||
|
double a1 = -yl;
|
||||||
|
double b1 = xl;
|
||||||
|
double c1 = w * sqrt(a1 * a1 + b1 * b1);
|
||||||
|
|
||||||
|
s->root = s->nodes + s->node_count++;
|
||||||
|
s->root->type = CT_AND;
|
||||||
|
s->root->l = s->nodes + s->node_count++;
|
||||||
|
s->root->l->type = CT_AND;
|
||||||
|
|
||||||
|
clip_node* cnode;
|
||||||
|
cnode = s->nodes + s->node_count++;
|
||||||
|
cnode->l = cnode->r = NULL;
|
||||||
|
cnode->type = CT_CLIP;
|
||||||
|
cnode->a = a1;
|
||||||
|
cnode->b = b1;
|
||||||
|
cnode->c = c1;
|
||||||
|
s->root->l->l = cnode;
|
||||||
|
cnode = s->nodes + s->node_count++;
|
||||||
|
cnode->l = cnode->r = NULL;
|
||||||
|
cnode->type = CT_CLIP;
|
||||||
|
cnode->a = -a1;
|
||||||
|
cnode->b = -b1;
|
||||||
|
cnode->c = c1;
|
||||||
|
s->root->l->r = cnode;
|
||||||
|
cnode = s->nodes + s->node_count++;
|
||||||
|
cnode->l = cnode->r = NULL;
|
||||||
|
cnode->type = CT_CLIP;
|
||||||
|
cnode->a = b1;
|
||||||
|
cnode->b = -a1;
|
||||||
|
cnode->c = 0;
|
||||||
|
s->root->r = cnode;
|
||||||
|
}
|
||||||
|
|
||||||
// A chord.
|
// A chord.
|
||||||
void chord_init(clip_ellipse_state* s, int32_t a, int32_t b, int32_t w, float al, float ar) {
|
void chord_init(clip_ellipse_state* s, int32_t a, int32_t b, int32_t w, float al, float ar) {
|
||||||
ellipse_init(&s->st, a, b, w);
|
ellipse_init(&s->st, a, b, w);
|
||||||
|
@ -1384,12 +1435,13 @@ clipEllipseNew(Imaging im, int x0, int y0, int x1, int y1,
|
||||||
|
|
||||||
int a = x1 - x0;
|
int a = x1 - x0;
|
||||||
int b = y1 - y0;
|
int b = y1 - y0;
|
||||||
if (a < 0 || b < 0 || start == end) {
|
if (a < 0 || b < 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
clip_ellipse_state st;
|
clip_ellipse_state st;
|
||||||
init(&st, a, b, width, start, end);
|
init(&st, a, b, width, start, end);
|
||||||
|
// debug_clip_tree(st.root, 0);
|
||||||
int32_t X0, Y, X1;
|
int32_t X0, Y, X1;
|
||||||
int next_code;
|
int next_code;
|
||||||
while ((next_code = clip_ellipse_next(&st, &X0, &Y, &X1)) >= 0) {
|
while ((next_code = clip_ellipse_next(&st, &X0, &Y, &X1)) >= 0) {
|
||||||
|
@ -1425,9 +1477,17 @@ chordLineNew(Imaging im, int x0, int y0, int x1, int y1,
|
||||||
static int
|
static int
|
||||||
pieNew(Imaging im, int x0, int y0, int x1, int y1,
|
pieNew(Imaging im, int x0, int y0, int x1, int y1,
|
||||||
float start, float end,
|
float start, float end,
|
||||||
const void* ink_, int op)
|
const void* ink_, int width, int op)
|
||||||
{
|
{
|
||||||
return clipEllipseNew(im, x0, y0, x1, y1, start, end, ink_, x1 + y1 - x0 - y0, op, pie_init);
|
return clipEllipseNew(im, x0, y0, x1, y1, start, end, ink_, width, op, pie_init);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
pieSideNew(Imaging im, int x0, int y0, int x1, int y1,
|
||||||
|
float start,
|
||||||
|
const void* ink_, int width, int op)
|
||||||
|
{
|
||||||
|
return clipEllipseNew(im, x0, y0, x1, y1, start, 0, ink_, width, op, pie_side_init);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -1483,38 +1543,26 @@ ImagingDrawPieslice(Imaging im, int x0, int y0, int x1, int y1,
|
||||||
float start, float end, const void* ink, int fill,
|
float start, float end, const void* ink, int fill,
|
||||||
int width, int op)
|
int width, int op)
|
||||||
{
|
{
|
||||||
//fprintf(stderr, "P (%d %d) (%d %d) %f-%f %08X f%d w%d o%d\n", x0, y0, x1, y1, start, end, *(int*)ink, fill, width, op);
|
// fprintf(stderr, "P (%d %d) (%d %d) %f-%f %08X f%d w%d o%d\n", x0, y0, x1, y1, start, end, *(int*)ink, fill, width, op);
|
||||||
normalize_angles(&start, &end);
|
normalize_angles(&start, &end);
|
||||||
if (start + 360 == end) {
|
if (start + 360 == end) {
|
||||||
return ImagingDrawEllipse(im, x0, y0, x1, y1, ink, fill, width, op);
|
return ellipseNew(im, x0, y0, x1, y1, ink, fill, width, op);
|
||||||
}
|
}
|
||||||
if (start == end) {
|
if (start == end) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (fill) {
|
if (fill) {
|
||||||
return pieNew(im, x0, y0, x1, y1, start, end, ink, op);
|
return pieNew(im, x0, y0, x1, y1, start, end, ink, x1 + y1 - x0 - y0, op);
|
||||||
} else {
|
} else {
|
||||||
float xc = x0 + (x1 - x0) / 2.0, yc = y0 + (y1 - y0) / 2.0;
|
if (pieSideNew(im, x0, y0, x1, y1, start, ink, width, op)) {
|
||||||
float al = start * M_PI / 180.0, ar = end * M_PI / 180.0;
|
|
||||||
int32_t xa = xc + (x1 - x0 - width) * cos(al) / 2, ya = yc + (y1 - y0 - width) * sin(al) / 2;
|
|
||||||
int32_t xb = xc + (x1 - x0 - width) * cos(ar) / 2, yb = yc + (y1 - y0 - width) * sin(ar) / 2;
|
|
||||||
int32_t xt, yt;
|
|
||||||
if (ImagingDrawWideLine(im, xc, yc, xa, ya, ink, width, op) < 0) {
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (ImagingDrawWideLine(im, xc, yc, xb, yb, ink, width, op) < 0) {
|
if (pieSideNew(im, x0, y0, x1, y1, end, ink, width, op)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
xt = xc - width / 2;
|
float xc = round((x0 + x1 - width) / 2.0), yc = round((y0 + y1 - width) / 2.0);
|
||||||
yt = yc - width / 2;
|
ellipseNew(im, xc, yc, xc + width - 1, yc + width - 1, ink, 1, 0, op);
|
||||||
ellipseNew(im, xt, yt, xt + width, yt + width, ink, 1, 0, op);
|
return pieNew(im, x0, y0, x1, y1, start, end, ink, width, op);
|
||||||
xt = xa - width / 2;
|
|
||||||
yt = ya - width / 2;
|
|
||||||
ellipseNew(im, xt, yt, xt + width, yt + width, ink, 1, 0, op);
|
|
||||||
xt = xb - width / 2;
|
|
||||||
yt = yb - width / 2;
|
|
||||||
ellipseNew(im, xt, yt, xt + width, yt + width, ink, 1, 0, op);
|
|
||||||
return arcNew(im, x0, y0, x1, y1, start, end, ink, width, op);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|