+i_arc_out_aa(i_img *im, i_img_dim xc, i_img_dim yc, i_img_dim r, double d1, double d2, const i_color *col) {
+ i_img_dim i, j;
+ double t;
+ i_color workc = *col;
+ i_img_dim segs[2][2];
+ int seg_count;
+ i_img_dim sin_th;
+ i_img_dim seg_d1, seg_d2;
+ int seg_num;
+ int orig_alpha = col->channel[3];
+ i_img_dim scale = r + 1;
+ i_img_dim seg1 = scale * 2;
+ i_img_dim seg2 = scale * 4;
+ i_img_dim seg3 = scale * 6;
+ i_img_dim seg4 = scale * 8;
+ dIMCTXim(im);
+
+ im_log((aIMCTX,1,"i_arc_out_aa(im %p,centre(" i_DFp "), rad %" i_DF ", d1 %f, d2 %f, col %p)",
+ im, i_DFcp(xc, yc), i_DFc(r), d1, d2, col));
+
+ im_clear_error(aIMCTX);
+ if (r <= 0) {
+ im_push_error(aIMCTX, 0, "arc: radius must be non-negative");
+ return 0;
+ }
+ if (d1 + 360 <= d2)
+ return i_circle_out_aa(im, xc, yc, r, col);
+
+ if (d1 < 0)
+ d1 += 360 * floor((-d1 + 359) / 360);
+ if (d2 < 0)
+ d2 += 360 * floor((-d2 + 359) / 360);
+ d1 = fmod(d1, 360);
+ d2 = fmod(d2, 360);
+ seg_d1 = arc_seg(d1, scale);
+ seg_d2 = arc_seg(d2, scale);
+ if (seg_d2 < seg_d1) {
+ /* split into two segments */
+ segs[0][0] = 0;
+ segs[0][1] = seg_d2;
+ segs[1][0] = seg_d1;
+ segs[1][1] = seg4;
+ seg_count = 2;
+ }
+ else {
+ segs[0][0] = seg_d1;
+ segs[0][1] = seg_d2;
+ seg_count = 1;
+ }
+
+ for (seg_num = 0; seg_num < seg_count; ++seg_num) {
+ i_img_dim seg_start = segs[seg_num][0];
+ i_img_dim seg_end = segs[seg_num][1];
+
+ i = r;
+ j = 0;
+ t = 0;
+
+ if (seg_start == 0)
+ i_ppix_norm(im, xc+i, yc+j, col);
+ if (seg_start <= seg1 && seg_end >= seg1)
+ i_ppix_norm(im, xc+j, yc+i, col);
+ if (seg_start <= seg2 && seg_end >= seg2)
+ i_ppix_norm(im, xc-i, yc+j, col);
+ if (seg_start <= seg3 && seg_end >= seg3)
+ i_ppix_norm(im, xc+j, yc-i, col);
+
+ while (i > j+1) {
+ int cv, inv_cv;
+ double d;
+ j++;
+ d = cover(r, j);
+ cv = (int)(d * 255 + 0.5);
+ inv_cv = 255-cv;
+ if (d < t) {
+ --i;
+ }
+ sin_th = j;
+ if (inv_cv) {
+ workc.channel[3] = orig_alpha * inv_cv / 255;
+
+ if (seg_start <= sin_th && seg_end >= sin_th)
+ i_ppix_norm(im, xc+i, yc+j, &workc);
+ if (seg_start <= seg2 - sin_th && seg_end >= seg2 - sin_th)
+ i_ppix_norm(im, xc-i, yc+j, &workc);
+ if (seg_start <= seg4 - sin_th && seg_end >= seg4 - sin_th)
+ i_ppix_norm(im, xc+i, yc-j, &workc);
+ if (seg_start <= seg2 + sin_th && seg_end >= seg2 + sin_th)
+ i_ppix_norm(im, xc-i, yc-j, &workc);
+
+ if (i != j) {
+ if (seg_start <= seg1 - sin_th && seg_end >= seg1 - sin_th)
+ i_ppix_norm(im, xc+j, yc+i, &workc);
+ if (seg_start <= seg1 + sin_th && seg_end >= seg1 + sin_th)
+ i_ppix_norm(im, xc-j, yc+i, &workc);
+ if (seg_start <= seg3 + sin_th && seg_end >= seg3 + sin_th)
+ i_ppix_norm(im, xc+j, yc-i, &workc);
+ if (seg_start <= seg3 - sin_th && seg_end >= seg3 - sin_th)
+ i_ppix_norm(im, xc-j, yc-i, &workc);
+ }
+ }
+ if (cv && i > j) {
+ workc.channel[3] = orig_alpha * cv / 255;
+ if (seg_start <= sin_th && seg_end >= sin_th)
+ i_ppix_norm(im, xc+i-1, yc+j, &workc);
+ if (seg_start <= seg2 - sin_th && seg_end >= seg2 - sin_th)
+ i_ppix_norm(im, xc-i+1, yc+j, &workc);
+ if (seg_start <= seg4 - sin_th && seg_end >= seg4 - sin_th)
+ i_ppix_norm(im, xc+i-1, yc-j, &workc);
+ if (seg_start <= seg2 + sin_th && seg_end >= seg2 + sin_th)
+ i_ppix_norm(im, xc-i+1, yc-j, &workc);
+
+ if (seg_start <= seg1 - sin_th && seg_end >= seg1 - sin_th)
+ i_ppix_norm(im, xc+j, yc+i-1, &workc);
+ if (seg_start <= seg1 + sin_th && seg_end >= seg1 + sin_th)
+ i_ppix_norm(im, xc-j, yc+i-1, &workc);
+ if (seg_start <= seg3 + sin_th && seg_end >= seg3 + sin_th)
+ i_ppix_norm(im, xc+j, yc-i+1, &workc);
+ if (seg_start <= seg3 - sin_th && seg_end >= seg3 - sin_th)
+ i_ppix_norm(im, xc-j, yc-i+1, &workc);
+ }
+ t = d;
+ }
+ }
+
+ return 1;
+}
+
+/*
+=item i_box(im, x1, y1, x2, y2, color)
+
+=category Drawing
+=synopsis i_box(im, 0, 0, im->xsize-1, im->ysize-1, &color).
+
+Outlines the box from (x1,y1) to (x2,y2) inclusive with I<color>.
+
+=cut
+*/
+
+void
+i_box(i_img *im,i_img_dim x1,i_img_dim y1,i_img_dim x2,i_img_dim y2,const i_color *val) {
+ i_img_dim x,y;
+ dIMCTXim(im);
+
+ im_log((aIMCTX, 1,"i_box(im* %p, p1(" i_DFp "), p2(" i_DFp "),val %p)\n",
+ im, i_DFcp(x1,y1), i_DFcp(x2,y2), val));
+ for(x=x1;x<x2+1;x++) {
+ i_ppix(im,x,y1,val);
+ i_ppix(im,x,y2,val);
+ }
+ for(y=y1;y<y2+1;y++) {
+ i_ppix(im,x1,y,val);
+ i_ppix(im,x2,y,val);
+ }
+}
+
+/*
+=item i_box_filled(im, x1, y1, x2, y2, color)
+
+=category Drawing
+=synopsis i_box_filled(im, 0, 0, im->xsize-1, im->ysize-1, &color);
+
+Fills the box from (x1,y1) to (x2,y2) inclusive with color.
+
+=cut
+*/
+
+void
+i_box_filled(i_img *im,i_img_dim x1,i_img_dim y1,i_img_dim x2,i_img_dim y2, const i_color *val) {
+ i_img_dim x, y, width;
+ i_palidx index;
+ dIMCTXim(im);
+
+ im_log((aIMCTX,1,"i_box_filled(im* %p, p1(" i_DFp "), p2(" i_DFp "),val %p)\n",
+ im, i_DFcp(x1, y1), i_DFcp(x2,y2) ,val));
+
+ if (x1 > x2 || y1 > y2
+ || x2 < 0 || y2 < 0
+ || x1 >= im->xsize || y1 > im->ysize)
+ return;
+
+ if (x1 < 0)
+ x1 = 0;
+ if (x2 >= im->xsize)
+ x2 = im->xsize - 1;
+ if (y1 < 0)
+ y1 = 0;
+ if (y2 >= im->ysize)
+ y2 = im->ysize - 1;
+
+ width = x2 - x1 + 1;
+
+ if (im->type == i_palette_type
+ && i_findcolor(im, val, &index)) {
+ i_palidx *line = mymalloc(sizeof(i_palidx) * width);