Pillow-6.0.0/src/libImaging/Draw.c
/*
 * Filled polygon draw function using scan line algorithm.
 */
Filled polygon draw function using scan line algorithm.
Filled polygon draw function using scan line algorithm .
static inline int
polygon_generic(Imaging im, int n, Edge *e, int ink, int eofill,
        hline_handler hline)
{
    Edge** edge_table;
    float* xx;
    int edge_count = 0;
    int ymin = im->ysize - 1;
    int ymax = 0;
    int i;
    if (n <= 0) {
        return 0;
    }
    edge_table = calloc(n, sizeof(Edge*));
    if (!edge_table) {
        return -1;
    }
    for (i = 0; i < n; i++) {
        if (e[i].ymin == e[i].ymax) {
            (*hline)(im, e[i].xmin, e[i].ymin, e[i].xmax, ink);
            continue;
        }
        if (ymin > e[i].ymin) {
            ymin = e[i].ymin;
        }
        if (ymax < e[i].ymax) {
            ymax = e[i].ymax;
        }
        edge_table[edge_count++] = (e + i);
    }
    if (ymin < 0) {
        ymin = 0;
    }
    if (ymax > im->ysize) {
        ymax = im->ysize;
    }
    xx = calloc(edge_count * 2, sizeof(float));
    if (!xx) {
        free(edge_table);
        return -1;
    }
    for (; ymin <= ymax; ymin++) {
        int j = 0;
        for (i = 0; i < edge_count; i++) {
            Edge* current = edge_table[i];
            if (ymin >= current->ymin && ymin <= current->ymax) {
                xx[j++] = (ymin - current->y0) * current->dx + current->x0;
            }
            if (ymin == current->ymax && ymin < ymax) {
                xx[j] = xx[j - 1];
                j++;
            }
        }
        qsort(xx, j, sizeof(float), x_cmp);
        for (i = 1; i < j; i += 2) {
            (*hline)(im, ROUND_UP(xx[i - 1]), ymin, ROUND_DOWN(xx[i]), ink);
        }
    }
    free(xx);
    free(edge_table);
    return 0;
}
static inline int polygon_generic ( Imaging im , int n , Edge * e , int ink , int eofill , hline_handler hline ) { Edge * * edge_table ; float * xx ; int edge_count = 0 ; int ymin = im -> ysize - 1 ; int ymax = 0 ; int i ; if ( n <= 0 ) { return 0 ; } edge_table = calloc ( n , sizeof ( Edge * ) ) ; if ( ! edge_table ) { return -1 ; } for ( i = 0 ; i < n ; i ++ ) { if ( e [ i ] . ymin == e [ i ] . ymax ) { ( * hline ) ( im , e [ i ] . xmin , e [ i ] . ymin , e [ i ] . xmax , ink ) ; continue ; } if ( ymin > e [ i ] . ymin ) { ymin = e [ i ] . ymin ; } if ( ymax < e [ i ] . ymax ) { ymax = e [ i ] . ymax ; } edge_table [ edge_count ++ ] = ( e + i ) ; } if ( ymin < 0 ) { ymin = 0 ; } if ( ymax > im -> ysize ) { ymax = im -> ysize ; } xx = calloc ( edge_count * 2 , sizeof ( float ) ) ; if ( ! xx ) { free ( edge_table ) ; return -1 ; } for ( ; ymin <= ymax ; ymin ++ ) { int j = 0 ; for ( i = 0 ; i < edge_count ; i ++ ) { Edge * current = edge_table [ i ] ; if ( ymin >= current -> ymin && ymin <= current -> ymax ) { xx [ j ++ ] = ( ymin - current -> y0 ) * current -> dx + current -> x0 ; } if ( ymin == current -> ymax && ymin < ymax ) { xx [ j ] = xx [ j - 1 ] ; j ++ ; } } qsort ( xx , j , sizeof ( float ) , x_cmp ) ; for ( i = 1 ; i < j ; i += 2 ) { ( * hline ) ( im , ROUND_UP ( xx [ i - 1 ] ) , ymin , ROUND_DOWN ( xx [ i ] ) , ink ) ; } } free ( xx ) ; free ( edge_table ) ; return 0 ; }
Filled polygon draw function using scan line algorithm.
Filled polygon draw function using scan line algorithm .
/* Initialize the edge table and find polygon boundaries */ /* malloc check ok, using calloc */ /* This causes the pixels of horizontal edges to be drawn twice :(
         * but without it there are inconsistencies in ellipses */ /* Process the edge table with a scan line searching for intersections */ /* malloc check ok, using calloc */ /* Needed to draw consistent polygons */