i_color color;
color.rgba.r = 255; color.rgba.g = 0; color.rgba.b = 255;
+ double x[] = { ... };
+ double y[] = { ... };
+ i_polygon_t poly;
+ poly.count = sizeof(x) / sizeof(*x);
+ poly.x = x;
+ poly.y = y;
EOS
See L</Context objects> for more information.
+=head2 i_polygon_t
+
+Represents a single polygon supplied to i_poly_poly_aa() and
+i_poly_poly_aa_cfill().
+
+This is a structure with 3 members:
+
+=over
+
+=item *
+
+C<x>, C<y> - pointers to the first elements of arrays of doubles that define
+the vertices of the polygon.
+
+=item *
+
+C<count> - the number of values in each of the C<x> and C<y> arrays.
+
+=back
+
+=head2 i_poly_fill_mode_t
+
+An enumerated type of the possible fill modes for polygons:
+
+=over
+
+=item *
+
+C<i_pfm_evenodd> - if areas overlap an odd number of times, they
+are filled, and are otherwise unfilled.
+
+=item *
+
+C<i_pfm_nonzero> - areas that have an unbalanced clockwise and
+anti-clockwise boundary are filled. This is the same as
+C<WindingRule> for X and C<WINDING> for Win32 GDI.
+
+=back
+
=head1 Create an XS module using the Imager API
=head2 Foo.pm
i_color color;
color.rgba.r = 255; color.rgba.g = 0; color.rgba.b = 255;
+ double x[] = { ... };
+ double y[] = { ... };
+ i_polygon_t poly;
+ poly.count = sizeof(x) / sizeof(*x);
+ poly.x = x;
+ poly.y = y;
# Blit tools
i_flood_cfill(im, 50, 50, fill);
i_flood_fill_border(im, 50, 50, &color, &border);
i_flood_cfill_border(im, 50, 50, fill, border);
+ i_poly_poly_aa(im, 1, &poly, mode, color);
+ i_poly_aa_m(im, count, x, y, mode, color);
+ i_poly_poly_aa_cfill(im, 1, &poly, mode, fill);
+ i_poly_aa_cfill(im, count, x, y, mode, fill);
# Error handling
im_clear_error(aIMCTX);
=for comment
From: File imext.c
+=item i_poly_aa_cfill_m(im, count, x, y, mode, fill)
+
+ i_poly_aa_cfill(im, count, x, y, mode, fill);
+
+Fill a polygon defined by the points specified by the x and y arrays with
+the fill specified by C<fill>.
+
+
+=for comment
+From: File polygon.c
+
+=item i_poly_aa_m(im, count, x, y, mode, color)
+
+ i_poly_aa_m(im, count, x, y, mode, color);
+
+Fill a polygon defined by the points specified by the x and y arrays with
+the color specified by C<color>.
+
+
+=for comment
+From: File polygon.c
+
+=item i_poly_poly_aa(im, count, polys, mode, color)
+
+ i_poly_poly_aa(im, 1, &poly, mode, color);
+
+Fill the C<count> polygons defined by C<polys> the color specified by
+C<color>.
+
+At least one polygon must be supplied.
+
+All polygons must have at least 3 points.
+
+
+=for comment
+From: File polygon.c
+
+=item i_poly_poly_aa_cfill(im, count, polys, mode, fill)
+
+ i_poly_poly_aa_cfill(im, 1, &poly, mode, fill);
+
+Fill the C<count> polygons defined by C<polys> the fill specified by
+C<fill>.
+
+At least one polygon must be supplied.
+
+All polygons must have at least 3 points.
+
+
+=for comment
+From: File polygon.c
+
=item i_ppal(im, left, right, y, indexes)
=item *
-B<i_poly_aa_cfill_m>
-
-=item *
-
-B<i_poly_aa_m>
-
-=item *
-
-B<i_poly_poly_aa>
-
-=item *
-
-B<i_poly_poly_aa_cfill>
-
-=item *
-
B<im_lhead>
=item *
hatched fills, image based fills and fountain fills. See
L<Imager::Fill> for more information.
+=head2 Polygon Fill Modes
+
+When filling a polygon that overlaps itself, or when filling several
+polygons with polypolygon() that overlap each other, you can supply a
+C<mode> parameter that controls how the overlap is resolved. This can
+have one of two possible values:
+
+=over
+
+=item *
+
+C<evenodd> - if areas overlap an odd number of times, they are filled,
+and are otherwise unfilled. This is the default and the historical
+Imager polygon fill mode.
+
+=item *
+
+C<nonzero> - areas that have an unbalanced clockwise and
+anti-clockwise boundary are filled. This is the same as
+C<WindingRule> for X and C<WINDING> for Win32 GDI.
+
+=back
+
+C<nonzero> allows polygons to overlap, either with itself, or with
+another polygon in the same polypolygon() call, without producing
+unfilled area in the overlap, and also allows areas to be cut out of
+the area by specifying the points making up a cut-out in the opposite
+order.
+
=head2 List of primitives
=over
C<fill> - the fill for the filled circle. See L</"Fill Parameters">
+=item *
+
+C<mode> - fill mode for the polygon. See L</"Polygon Fill Modes">
+
+=back
+
+Note: the points specified are as offsets from the top-left of the
+image, I<not> as pixel locations. This means that:
+
+ $img->polygon(points => [ [ 0, 0 ], [ 1, 0 ], [ 1, 1 ], [ 0, 1 ] ]);
+
+fills only a single pixel at C<(0, 0)>, not four.
+
+=item polypolygon()
+X<polypolygon() method>X<methods, polypolygon>
+
+ $img->polypolygon(points => $points, color => $color);
+
+Draw multiple polygons, either filled or unfilled.
+
+=over
+
+=item *
+
+C<points> - is an array reference containing polygon definitions, each
+polygon definition is a reference to an array containing two arrays,
+one each for the C<x> and C<y> co-ordinates.
+
+=item *
+
+C<filled> - if true, fill the polygons with the color defined by
+C<color>.
+
+=item *
+
+C<color> - the color to draw the polygons with if C<fill> is not
+supplied.
+
+=item *
+
+C<fill> - fill the polygons with this fill if supplied.
+
+=item *
+
+C<mode> - fill mode for the polygon. See L</"Polygon Fill Modes">
+
=back
+Note: the points specified are as offsets from the top-left of the
+image, I<not> as pixel locations. This means that:
+
+ $img->polypolygon(points => [ [ [ 0, 1, 1, 0 ], [ 0, 0, 1, 1 ] ] ],
+ filled => 1);
+
+fills only a single pixel at C<(0, 0)>, not four.
+
=item flood_fill()
X<flood_fill>You can fill a region that all has the same color using
=back
-=item polypolygon()
-
-C<FIXME>
-
=item setpixel()
$img->setpixel(x=>50, y=>70, color=>$color);
+#define IMAGER_NO_CONTEXT
#include "imager.h"
#include "draw.h"
#include "log.h"
static
void
-mark_updown_slices(p_line *lset, p_slice *tllist, int count) {
+mark_updown_slices(pIMCTX, p_line *lset, p_slice *tllist, int count) {
p_line *l, *r;
int k;
for(k=0; k<count; k+=2) {
l = lset + tllist[k].n;
if (l->y1 == l->y2) {
- mm_log((1, "mark_updown_slices: horizontal line being marked: internal error!\n"));
+ im_log((aIMCTX,1, "mark_updown_slices: horizontal line being marked: internal error!\n"));
exit(3);
}
);
if (k+1 >= count) {
- mm_log((1, "Invalid polygon spec, odd number of line crossings.\n"));
+ im_log((aIMCTX, 1, "Invalid polygon spec, odd number of line crossings.\n"));
return;
}
r = lset + tllist[k+1].n;
if (r->y1 == r->y2) {
- mm_log((1, "mark_updown_slices: horizontal line being marked: internal error!\n"));
+ im_log((aIMCTX, 1, "mark_updown_slices: horizontal line being marked: internal error!\n"));
exit(3);
}
p_line *lset; /* List of lines in polygon */
p_slice *tllist; /* List of slices */
size_t pcount, lcount;
+ dIMCTX;
- mm_log((1, "i_poly_poly_aa_low(im %p, count %d, polys %p, ctx %p, flusher %p)\n", im, count, polys, ctx, flusher));
+ im_log((aIMCTX, 1, "i_poly_poly_aa_low(im %p, count %d, polys %p, ctx %p, flusher %p)\n", im, count, polys, ctx, flusher));
+
+ i_clear_error();
+
+ if (count < 1) {
+ i_push_error(0, "no polygons to draw");
+ return 0;
+ }
+
+ for (k = 0; k < count; ++k) {
+ if (polys[k].count < 3) {
+ i_push_errorf(0, "polygons must have at least 3 points");
+ return 0;
+ }
+ }
for (k = 0; k < count; ++k) {
const i_polygon_t *p = polys + k;
- mm_log((2, "poly %d\n", k));
+ im_log((aIMCTX, 2, "poly %d\n", k));
for(i = 0; i < p->count; i++) {
- mm_log((2, " (%.2f, %.2f)\n", p->x[i], p->y[i]));
+ im_log((aIMCTX, 2, " (%.2f, %.2f)\n", p->x[i], p->y[i]));
}
}
clc = lines_in_interval(lset, lcount, tllist, pset[i].y, pset[i+1].y);
qsort(tllist, clc, sizeof(p_slice), (int(*)(const void *,const void *))p_compx);
- mark_updown_slices(lset, tllist, clc);
+ mark_updown_slices(aIMCTX, lset, tllist, clc);
POLY_DEB
(
return 1;
}
+/*
+=item i_poly_poly_aa(im, count, polys, mode, color)
+=synopsis i_poly_poly_aa(im, 1, &poly, mode, color);
+=category Drawing
+
+Fill the C<count> polygons defined by C<polys> the color specified by
+C<color>.
+
+At least one polygon must be supplied.
+
+All polygons must have at least 3 points.
+
+=cut
+*/
+
int
i_poly_poly_aa(i_img *im, int count, const i_polygon_t *polys,
i_poly_fill_mode_t mode, const i_color *val) {
return i_poly_poly_aa_low(im, count, polys, mode, &c, scanline_flush);
}
+/*
+=item i_poly_aa_m(im, count, x, y, mode, color)
+=synopsis i_poly_aa_m(im, count, x, y, mode, color);
+=category Drawing
+
+Fill a polygon defined by the points specified by the x and y arrays with
+the color specified by C<color>.
+
+=cut
+*/
+
int
i_poly_aa_m(i_img *im, int l, const double *x, const double *y,
i_poly_fill_mode_t mode, const i_color *val) {
}
}
+/*
+=item i_poly_poly_aa_cfill(im, count, polys, mode, fill)
+=synopsis i_poly_poly_aa_cfill(im, 1, &poly, mode, fill);
+=category Drawing
+
+Fill the C<count> polygons defined by C<polys> the fill specified by
+C<fill>.
+
+At least one polygon must be supplied.
+
+All polygons must have at least 3 points.
+
+=cut
+*/
+
int
i_poly_poly_aa_cfill(i_img *im, int count, const i_polygon_t *polys,
i_poly_fill_mode_t mode, i_fill_t *fill) {
return result;
}
+/*
+=item i_poly_aa_cfill_m(im, count, x, y, mode, fill)
+=synopsis i_poly_aa_cfill(im, count, x, y, mode, fill);
+=category Drawing
+
+Fill a polygon defined by the points specified by the x and y arrays with
+the fill specified by C<fill>.
+
+=cut
+*/
+
int
i_poly_aa_cfill_m(i_img *im, int l, const double *x, const double *y,
i_poly_fill_mode_t mode, i_fill_t *fill) {
CMYK
CPAN
FreeType
+GDI
GIF
HSV
Hrafnkelsson