-#include "image.h"
-#include "imagei.h"
+#define IMAGER_NO_CONTEXT
+#include "imager.h"
+#include "imageri.h"
+#include <assert.h>
/*
=head1 NAME
fill = i_new_fill_hatchf(&fc1, &fc2, combine, hatch, cust_hash, dx, dy);
fill = i_new_fill_hatch(&c1, &c2, combine, hatch, cust_hash, dx, dy);
fill = i_new_fill_image(im, matrix, xoff, yoff, combine);
+ fill = i_new_fill_opacity(fill, alpha_mult);
i_fill_destroy(fill);
=head1 DESCRIPTION
=cut
*/
-static i_color fcolor_to_color(i_fcolor *c) {
+static i_color fcolor_to_color(const i_fcolor *c) {
int ch;
i_color out;
return out;
}
-static i_fcolor color_to_fcolor(i_color *c) {
+static i_fcolor color_to_fcolor(const i_color *c) {
int ch;
i_fcolor out;
i_fcolor fc;
} i_fill_solid_t;
-static void fill_solid(i_fill_t *, int x, int y, int width, int channels,
- i_color *);
-static void fill_solidf(i_fill_t *, int x, int y, int width, int channels,
- i_fcolor *);
-static void fill_solid_comb(i_fill_t *, int x, int y, int width, int channels,
- i_color *);
-static void fill_solidf_comb(i_fill_t *, int x, int y, int width,
- int channels, i_fcolor *);
+static void fill_solid(i_fill_t *, i_img_dim x, i_img_dim y, i_img_dim width,
+ int channels, i_color *);
+static void fill_solidf(i_fill_t *, i_img_dim x, i_img_dim y, i_img_dim width,
+ int channels, i_fcolor *);
static i_fill_solid_t base_solid_fill =
{
NULL,
},
};
-static i_fill_solid_t base_solid_fill_comb =
-{
- {
- fill_solid_comb,
- fill_solidf_comb,
- NULL,
- NULL,
- NULL,
- },
-};
/*
=item i_fill_destroy(fill)
+=order 90
+=category Fills
+=synopsis i_fill_destroy(fill);
Call to destroy any fill object.
/*
=item i_new_fill_solidf(color, combine)
+=category Fills
+=synopsis i_fill_t *fill = i_new_fill_solidf(&fcolor, combine);
+
Create a solid fill based on a float color.
If combine is non-zero then alpha values will be combined.
*/
i_fill_t *
-i_new_fill_solidf(i_fcolor *c, int combine) {
+i_new_fill_solidf(const i_fcolor *c, int combine) {
int ch;
i_fill_solid_t *fill = mymalloc(sizeof(i_fill_solid_t)); /* checked 14jul05 tonyc */
+ *fill = base_solid_fill;
if (combine) {
- *fill = base_solid_fill_comb;
i_get_combine(combine, &fill->base.combine, &fill->base.combinef);
}
- else
- *fill = base_solid_fill;
+
fill->fc = *c;
for (ch = 0; ch < MAXCHANNELS; ++ch) {
fill->c.channel[ch] = SampleFTo8(c->channel[ch]);
/*
=item i_new_fill_solid(color, combine)
-Create a solid fill based.
+=category Fills
+=synopsis i_fill_t *fill = i_new_fill_solid(&color, combine);
+
+Create a solid fill based on an 8-bit color.
If combine is non-zero then alpha values will be combined.
*/
i_fill_t *
-i_new_fill_solid(i_color *c, int combine) {
+i_new_fill_solid(const i_color *c, int combine) {
int ch;
i_fill_solid_t *fill = mymalloc(sizeof(i_fill_solid_t)); /* checked 14jul05 tonyc */
+ *fill = base_solid_fill;
if (combine) {
- *fill = base_solid_fill_comb;
i_get_combine(combine, &fill->base.combine, &fill->base.combinef);
}
- else
- *fill = base_solid_fill;
+
fill->c = *c;
for (ch = 0; ch < MAXCHANNELS; ++ch) {
fill->fc.channel[ch] = Sample8ToF(c->channel[ch]);
i_color fg, bg;
i_fcolor ffg, fbg;
unsigned char hatch[8];
- int dx, dy;
+ i_img_dim dx, dy;
} i_fill_hatch_t;
-static void fill_hatch(i_fill_t *fill, int x, int y, int width, int channels,
- i_color *data);
-static void fill_hatchf(i_fill_t *fill, int x, int y, int width, int channels,
- i_fcolor *data);
+static void fill_hatch(i_fill_t *fill, i_img_dim x, i_img_dim y,
+ i_img_dim width, int channels, i_color *data);
+static void fill_hatchf(i_fill_t *fill, i_img_dim x, i_img_dim y,
+ i_img_dim width, int channels, i_fcolor *data);
static
i_fill_t *
-i_new_hatch_low(i_color *fg, i_color *bg, i_fcolor *ffg, i_fcolor *fbg,
- int combine, int hatch, unsigned char *cust_hatch,
- int dx, int dy);
+i_new_hatch_low(const i_color *fg, const i_color *bg, const i_fcolor *ffg, const i_fcolor *fbg,
+ int combine, int hatch, const unsigned char *cust_hatch,
+ i_img_dim dx, i_img_dim dy);
/*
-=item i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch, dx, dy)
+=item i_new_fill_hatch(C<fg>, C<bg>, C<combine>, C<hatch>, C<cust_hatch>, C<dx>, C<dy>)
+
+=category Fills
+=synopsis i_fill_t *fill = i_new_fill_hatch(&fg_color, &bg_color, combine, hatch, custom_hatch, dx, dy);
-Creates a new hatched fill with the fg color used for the 1 bits in
-the hatch and bg for the 0 bits. If combine is non-zero alpha values
-will be combined.
+Creates a new hatched fill with the C<fg> color used for the 1 bits in
+the hatch and C<bg> for the 0 bits. If C<combine> is non-zero alpha
+values will be combined.
-If cust_hatch is non-NULL it should be a pointer to 8 bytes of the
+If C<cust_hatch> is non-NULL it should be a pointer to 8 bytes of the
hash definition, with the high-bits to the left.
-If cust_hatch is NULL then one of the standard hatches is used.
+If C<cust_hatch> is NULL then one of the standard hatches is used.
-(dx, dy) are an offset into the hatch which can be used to unalign adjoining areas, or to align the origin of a hatch with the the side of a filled area.
+(C<dx>, C<dy>) are an offset into the hatch which can be used to hatch
+adjoining areas out of alignment, or to align the origin of a hatch
+with the side of a filled area.
=cut
*/
i_fill_t *
-i_new_fill_hatch(i_color *fg, i_color *bg, int combine, int hatch,
- unsigned char *cust_hatch, int dx, int dy) {
+i_new_fill_hatch(const i_color *fg, const i_color *bg, int combine, int hatch,
+ const unsigned char *cust_hatch, i_img_dim dx, i_img_dim dy) {
+ assert(fg);
+ assert(bg);
return i_new_hatch_low(fg, bg, NULL, NULL, combine, hatch, cust_hatch,
dx, dy);
}
/*
-=item i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch, dx, dy)
+=item i_new_fill_hatchf(C<fg>, C<bg>, C<combine>, C<hatch>, C<cust_hatch>, C<dx>, C<dy>)
-Creates a new hatched fill with the fg color used for the 1 bits in
-the hatch and bg for the 0 bits. If combine is non-zero alpha values
-will be combined.
+=category Fills
+=synopsis i_fill_t *fill = i_new_fill_hatchf(&fg_fcolor, &bg_fcolor, combine, hatch, custom_hatch, dx, dy);
-If cust_hatch is non-NULL it should be a pointer to 8 bytes of the
+Creates a new hatched fill with the C<fg> color used for the 1 bits in
+the hatch and C<bg> for the 0 bits. If C<combine> is non-zero alpha
+values will be combined.
+
+If C<cust_hatch> is non-NULL it should be a pointer to 8 bytes of the
hash definition, with the high-bits to the left.
-If cust_hatch is NULL then one of the standard hatches is used.
+If C<cust_hatch> is NULL then one of the standard hatches is used.
-(dx, dy) are an offset into the hatch which can be used to unalign adjoining areas, or to align the origin of a hatch with the the side of a filled area.
+(C<dx>, C<dy>) are an offset into the hatch which can be used to hatch
+adjoining areas out of alignment, or to align the origin of a hatch
+with the side of a filled area.
=cut
*/
i_fill_t *
-i_new_fill_hatchf(i_fcolor *fg, i_fcolor *bg, int combine, int hatch,
- unsigned char *cust_hatch, int dx, int dy) {
+i_new_fill_hatchf(const i_fcolor *fg, const i_fcolor *bg, int combine, int hatch,
+ const unsigned char *cust_hatch, i_img_dim dx, i_img_dim dy) {
+ assert(fg);
+ assert(bg);
return i_new_hatch_low(NULL, NULL, fg, bg, combine, hatch, cust_hatch,
dx, dy);
}
-static void fill_image(i_fill_t *fill, int x, int y, int width, int channels,
- i_color *data);
-static void fill_imagef(i_fill_t *fill, int x, int y, int width, int channels,
- i_fcolor *data);
+static void fill_image(i_fill_t *fill, i_img_dim x, i_img_dim y,
+ i_img_dim width, int channels, i_color *data);
+static void fill_imagef(i_fill_t *fill, i_img_dim x, i_img_dim y,
+ i_img_dim width, int channels, i_fcolor *data);
struct i_fill_image_t {
i_fill_t base;
i_img *src;
- int xoff, yoff;
+ i_img_dim xoff, yoff;
int has_matrix;
double matrix[9];
};
+static struct i_fill_image_t
+image_fill_proto =
+ {
+ {
+ fill_image,
+ fill_imagef,
+ NULL
+ }
+ };
+
/*
-=item i_new_fill_image(im, matrix, xoff, yoff, combine)
+=item i_new_fill_image(C<im>, C<matrix>, C<xoff>, C<yoff>, C<combine>)
+
+=category Fills
+=synopsis i_fill_t *fill = i_new_fill_image(src_img, matrix, x_offset, y_offset, combine);
Create an image based fill.
+matrix is an array of 9 doubles representing a transformation matrix.
+
+C<xoff> and C<yoff> are the offset into the image to start filling from.
+
=cut
*/
i_fill_t *
-i_new_fill_image(i_img *im, double *matrix, int xoff, int yoff, int combine) {
+i_new_fill_image(i_img *im, const double *matrix, i_img_dim xoff, i_img_dim yoff, int combine) {
struct i_fill_image_t *fill = mymalloc(sizeof(*fill)); /* checked 14jul05 tonyc */
- fill->base.fill_with_color = fill_image;
- fill->base.fill_with_fcolor = fill_imagef;
- fill->base.destroy = NULL;
+ *fill = image_fill_proto;
if (combine) {
i_get_combine(combine, &fill->base.combine, &fill->base.combinef);
return &fill->base;
}
+static void fill_opacity(i_fill_t *fill, i_img_dim x, i_img_dim y,
+ i_img_dim width, int channels, i_color *data);
+static void fill_opacityf(i_fill_t *fill, i_img_dim x, i_img_dim y,
+ i_img_dim width, int channels, i_fcolor *data);
-#define T_SOLID_FILL(fill) ((i_fill_solid_t *)(fill))
-
-/*
-=back
+struct i_fill_opacity_t {
+ i_fill_t base;
+ i_fill_t *other_fill;
+ double alpha_mult;
+};
-=head1 INTERNAL FUNCTIONS
+static struct i_fill_opacity_t
+opacity_fill_proto =
+ {
+ {
+ fill_opacity,
+ fill_opacityf,
+ NULL
+ }
+ };
-=over
+i_fill_t *
+i_new_fill_opacity(i_fill_t *base_fill, double alpha_mult) {
+ struct i_fill_opacity_t *fill = mymalloc(sizeof(*fill));
+ *fill = opacity_fill_proto;
-=item fill_solid(fill, x, y, width, channels, data)
+ fill->base.combine = base_fill->combine;
+ fill->base.combinef = base_fill->combinef;
-The 8-bit sample fill function for non-combining solid fills.
+ fill->other_fill = base_fill;
+ fill->alpha_mult = alpha_mult;
-=cut
-*/
-static void
-fill_solid(i_fill_t *fill, int x, int y, int width, int channels,
- i_color *data) {
- while (width-- > 0) {
- *data++ = T_SOLID_FILL(fill)->c;
+ if (!base_fill->f_fill_with_color) {
+ /* base fill only does floating, so we only do that too */
+ fill->base.f_fill_with_color = NULL;
}
+
+ return &fill->base;
}
+#define T_SOLID_FILL(fill) ((i_fill_solid_t *)(fill))
+
/*
-=item fill_solid(fill, x, y, width, channels, data)
+=back
-The floating sample fill function for non-combining solid fills.
+=head1 INTERNAL FUNCTIONS
-=cut
-*/
-static void
-fill_solidf(i_fill_t *fill, int x, int y, int width, int channels,
- i_fcolor *data) {
- while (width-- > 0) {
- *data++ = T_SOLID_FILL(fill)->fc;
- }
-}
+=over
-/*
-=item fill_solid_comb(fill, x, y, width, channels, data)
+=item fill_solid(fill, x, y, width, channels, data)
-The 8-bit sample fill function for combining solid fills.
+The 8-bit sample fill function for non-combining solid fills.
=cut
*/
static void
-fill_solid_comb(i_fill_t *fill, int x, int y, int width, int channels,
- i_color *data) {
+fill_solid(i_fill_t *fill, i_img_dim x, i_img_dim y, i_img_dim width,
+ int channels, i_color *data) {
i_color c = T_SOLID_FILL(fill)->c;
-
+ i_adapt_colors(channels > 2 ? 4 : 2, 4, &c, 1);
while (width-- > 0) {
*data++ = c;
}
}
/*
-=item fill_solidf_comb(fill, x, y, width, channels, data)
+=item fill_solid(fill, x, y, width, channels, data)
-The floating sample fill function for combining solid fills.
+The floating sample fill function for non-combining solid fills.
=cut
*/
static void
-fill_solidf_comb(i_fill_t *fill, int x, int y, int width, int channels,
- i_fcolor *data) {
+fill_solidf(i_fill_t *fill, i_img_dim x, i_img_dim y, i_img_dim width,
+ int channels, i_fcolor *data) {
i_fcolor c = T_SOLID_FILL(fill)->fc;
-
+ i_adapt_fcolors(channels > 2 ? 4 : 2, 4, &c, 1);
while (width-- > 0) {
*data++ = c;
}
}
+static i_fill_hatch_t
+hatch_fill_proto =
+ {
+ {
+ fill_hatch,
+ fill_hatchf,
+ NULL
+ }
+ };
+
/*
=item i_new_hatch_low(fg, bg, ffg, fbg, combine, hatch, cust_hatch, dx, dy)
*/
static
i_fill_t *
-i_new_hatch_low(i_color *fg, i_color *bg, i_fcolor *ffg, i_fcolor *fbg,
- int combine, int hatch, unsigned char *cust_hatch,
- int dx, int dy) {
+i_new_hatch_low(const i_color *fg, const i_color *bg,
+ const i_fcolor *ffg, const i_fcolor *fbg,
+ int combine, int hatch, const unsigned char *cust_hatch,
+ i_img_dim dx, i_img_dim dy) {
i_fill_hatch_t *fill = mymalloc(sizeof(i_fill_hatch_t)); /* checked 14jul05 tonyc */
- fill->base.fill_with_color = fill_hatch;
- fill->base.fill_with_fcolor = fill_hatchf;
- fill->base.destroy = NULL;
- fill->fg = fg ? *fg : fcolor_to_color(ffg);
- fill->bg = bg ? *bg : fcolor_to_color(fbg);
- fill->ffg = ffg ? *ffg : color_to_fcolor(fg);
- fill->fbg = fbg ? *fbg : color_to_fcolor(bg);
+ *fill = hatch_fill_proto;
+ if (fg && bg) {
+ fill->fg = *fg;
+ fill->bg = *bg;
+ fill->ffg = color_to_fcolor(fg);
+ fill->fbg = color_to_fcolor(bg);
+ }
+ else if (ffg && fbg) {
+ fill->fg = fcolor_to_color(ffg);
+ fill->bg = fcolor_to_color(fbg);
+ fill->ffg = *ffg;
+ fill->fbg = *fbg;
+ }
+ else {
+ assert(0);
+ /* NOTREACHED */
+ }
+
if (combine) {
i_get_combine(combine, &fill->base.combine, &fill->base.combinef);
}
memcpy(fill->hatch, cust_hatch, 8);
}
else {
- if (hatch > sizeof(builtin_hatches)/sizeof(*builtin_hatches))
+ if (hatch >= sizeof(builtin_hatches)/sizeof(*builtin_hatches)
+ || hatch < 0) {
hatch = 0;
+ }
memcpy(fill->hatch, builtin_hatches[hatch], 8);
}
fill->dx = dx & 7;
=cut
*/
-static void fill_hatch(i_fill_t *fill, int x, int y, int width, int channels,
- i_color *data) {
+static void
+fill_hatch(i_fill_t *fill, i_img_dim x, i_img_dim y, i_img_dim width,
+ int channels, i_color *data) {
i_fill_hatch_t *f = (i_fill_hatch_t *)fill;
int byte = f->hatch[(y + f->dy) & 7];
int xpos = (x + f->dx) & 7;
int mask = 128 >> xpos;
+ i_color fg = f->fg;
+ i_color bg = f->bg;
+
+ if (channels < 3) {
+ i_adapt_colors(2, 4, &fg, 1);
+ i_adapt_colors(2, 4, &bg, 1);
+ }
while (width-- > 0) {
- *data++ = (byte & mask) ? f->fg : f->bg;
+ if (byte & mask)
+ *data++ = fg;
+ else
+ *data++ = bg;
if ((mask >>= 1) == 0)
mask = 128;
The floating sample fill function for hatched fills.
-=back
+=cut
*/
-static void fill_hatchf(i_fill_t *fill, int x, int y, int width, int channels,
- i_fcolor *data) {
+static void
+fill_hatchf(i_fill_t *fill, i_img_dim x, i_img_dim y, i_img_dim width,
+ int channels, i_fcolor *data) {
i_fill_hatch_t *f = (i_fill_hatch_t *)fill;
int byte = f->hatch[(y + f->dy) & 7];
int xpos = (x + f->dx) & 7;
int mask = 128 >> xpos;
+ i_fcolor fg = f->ffg;
+ i_fcolor bg = f->fbg;
+
+ if (channels < 3) {
+ i_adapt_fcolors(2, 4, &fg, 1);
+ i_adapt_fcolors(2, 4, &bg, 1);
+ }
while (width-- > 0) {
- *data++ = (byte & mask) ? f->ffg : f->fbg;
+ if (byte & mask)
+ *data++ = fg;
+ else
+ *data++ = bg;
if ((mask >>= 1) == 0)
mask = 128;
pos -= floor(pos);
for (ch = 0; ch < channels; ++ch)
out.channel[ch] = (1-pos) * before.channel[ch] + pos * after.channel[ch];
- if (out.channel[3])
- for (ch = 0; ch < channels; ++ch)
+ if (channels > 3 && out.channel[3]) {
+ for (ch = 0; ch < channels; ++ch) {
if (ch != 3) {
int temp = out.channel[ch] * 255 / out.channel[3];
if (temp > 255)
temp = 255;
out.channel[ch] = temp;
}
+ }
+ }
return out;
}
pos -= floor(pos);
for (ch = 0; ch < channels; ++ch)
out.channel[ch] = (1-pos) * before.channel[ch] + pos * after.channel[ch];
- if (out.channel[3])
- for (ch = 0; ch < channels; ++ch)
+ if (out.channel[3]) {
+ for (ch = 0; ch < channels; ++ch) {
if (ch != 3) {
int temp = out.channel[ch] / out.channel[3];
if (temp > 1.0)
temp = 1.0;
out.channel[ch] = temp;
}
+ }
+ }
return out;
}
=cut
*/
-static void fill_image(i_fill_t *fill, int x, int y, int width, int channels,
- i_color *data) {
+static void
+fill_image(i_fill_t *fill, i_img_dim x, i_img_dim y, i_img_dim width,
+ int channels, i_color *data) {
struct i_fill_image_t *f = (struct i_fill_image_t *)fill;
- int i = 0;
+ i_img_dim i = 0;
i_color *out = data;
+ int want_channels = channels > 2 ? 4 : 2;
if (f->has_matrix) {
/* the hard way */
double iy = floor(ry / f->src->ysize);
i_color c[2][2];
i_color c2[2];
- int dy;
+ i_img_dim dy;
if (f->xoff) {
rx += iy * f->xoff;
ry -= iy * f->src->ysize;
for (dy = 0; dy < 2; ++dy) {
- if ((int)rx == f->src->xsize-1) {
- i_gpix(f->src, f->src->xsize-1, ((int)ry+dy) % f->src->ysize, &c[dy][0]);
- i_gpix(f->src, 0, ((int)ry+dy) % f->src->xsize, &c[dy][1]);
+ if ((i_img_dim)rx == f->src->xsize-1) {
+ i_gpix(f->src, f->src->xsize-1, ((i_img_dim)ry+dy) % f->src->ysize, &c[dy][0]);
+ i_gpix(f->src, 0, ((i_img_dim)ry+dy) % f->src->xsize, &c[dy][1]);
}
else {
- i_glin(f->src, (int)rx, (int)rx+2, ((int)ry+dy) % f->src->ysize,
+ i_glin(f->src, (i_img_dim)rx, (i_img_dim)rx+2, ((i_img_dim)ry+dy) % f->src->ysize,
c[dy]);
}
c2[dy] = interp_i_color(c[dy][0], c[dy][1], rx, f->src->channels);
/* the easy way */
/* this should be possible to optimize to use i_glin() */
while (i < width) {
- int rx = x+i;
- int ry = y;
- int ix = rx / f->src->xsize;
- int iy = ry / f->src->ysize;
+ i_img_dim rx = x+i;
+ i_img_dim ry = y;
+ i_img_dim ix = rx / f->src->xsize;
+ i_img_dim iy = ry / f->src->ysize;
if (f->xoff) {
rx += iy * f->xoff;
}
else if (f->yoff) {
ry += ix * f->yoff;
- iy = ry / f->src->xsize;
+ iy = ry / f->src->ysize;
}
rx -= ix * f->src->xsize;
ry -= iy * f->src->ysize;
++i;
}
}
- if (f->src->channels == 3) {
- /* just set the alpha */
- for (i = 0; i < width; ++i) {
- data->channel[3] = 255;
- data++;
- }
- }
- else if (f->src->channels == 2) {
- /* copy the alpha to channel 3, duplicate the grey value */
- for (i = 0; i < width; ++i) {
- data->channel[3] = data->channel[1];
- data->channel[1] = data->channel[2] = data->channel[0];
- data++;
- }
- }
- else if (f->src->channels == 1) {
- /* set the alpha, duplicate grey */
- for (i = 0; i < width; ++i) {
- data->channel[3] = 255;
- data->channel[1] = data->channel[2] = data->channel[0];
- data++;
- }
- }
+ if (f->src->channels != want_channels)
+ i_adapt_colors(want_channels, f->src->channels, data, width);
}
/*
-=item fill_image(fill, x, y, width, channels, data, work)
+=item fill_imagef(fill, x, y, width, channels, data, work)
=cut
*/
-static void fill_imagef(i_fill_t *fill, int x, int y, int width, int channels,
- i_fcolor *data) {
+static void
+fill_imagef(i_fill_t *fill, i_img_dim x, i_img_dim y, i_img_dim width,
+ int channels, i_fcolor *data) {
struct i_fill_image_t *f = (struct i_fill_image_t *)fill;
- int i = 0;
+ i_img_dim i = 0;
+ int want_channels = channels > 2 ? 4 : 2;
if (f->has_matrix) {
+ i_fcolor *work_data = data;
/* the hard way */
while (i < width) {
double rx = f->matrix[0] * (x+i) + f->matrix[1] * y + f->matrix[2];
double iy = floor(ry / f->src->ysize);
i_fcolor c[2][2];
i_fcolor c2[2];
- int dy;
+ i_img_dim dy;
if (f->xoff) {
rx += iy * f->xoff;
ry -= iy * f->src->ysize;
for (dy = 0; dy < 2; ++dy) {
- if ((int)rx == f->src->xsize-1) {
- i_gpixf(f->src, f->src->xsize-1, ((int)ry+dy) % f->src->ysize, &c[dy][0]);
- i_gpixf(f->src, 0, ((int)ry+dy) % f->src->xsize, &c[dy][1]);
+ if ((i_img_dim)rx == f->src->xsize-1) {
+ i_gpixf(f->src, f->src->xsize-1, ((i_img_dim)ry+dy) % f->src->ysize, &c[dy][0]);
+ i_gpixf(f->src, 0, ((i_img_dim)ry+dy) % f->src->xsize, &c[dy][1]);
}
else {
- i_glinf(f->src, (int)rx, (int)rx+2, ((int)ry+dy) % f->src->ysize,
+ i_glinf(f->src, (i_img_dim)rx, (i_img_dim)rx+2, ((i_img_dim)ry+dy) % f->src->ysize,
c[dy]);
}
c2[dy] = interp_i_fcolor(c[dy][0], c[dy][1], rx, f->src->channels);
}
- *data++ = interp_i_fcolor(c2[0], c2[1], ry, f->src->channels);
+ *work_data++ = interp_i_fcolor(c2[0], c2[1], ry, f->src->channels);
++i;
}
}
else {
+ i_fcolor *work_data = data;
/* the easy way */
/* this should be possible to optimize to use i_glin() */
while (i < width) {
- int rx = x+i;
- int ry = y;
- int ix = rx / f->src->xsize;
- int iy = ry / f->src->ysize;
+ i_img_dim rx = x+i;
+ i_img_dim ry = y;
+ i_img_dim ix = rx / f->src->xsize;
+ i_img_dim iy = ry / f->src->ysize;
if (f->xoff) {
rx += iy * f->xoff;
}
rx -= ix * f->src->xsize;
ry -= iy * f->src->ysize;
- i_gpixf(f->src, rx, ry, data);
- ++data;
+ i_gpixf(f->src, rx, ry, work_data);
+ ++work_data;
++i;
}
}
- if (f->src->channels == 3) {
- /* just set the alpha */
- for (i = 0; i < width; ++i) {
- data->channel[3] = 1.0;
- data++;
- }
- }
- else if (f->src->channels == 2) {
- /* copy the alpha to channel 3, duplicate the grey value */
- for (i = 0; i < width; ++i) {
- data->channel[3] = data->channel[1];
- data->channel[1] = data->channel[2] = data->channel[0];
- data++;
- }
- }
- else if (f->src->channels == 1) {
- /* set the alpha, duplicate grey */
- for (i = 0; i < width; ++i) {
- data->channel[3] = 1.0;
- data->channel[1] = data->channel[2] = data->channel[0];
- data++;
- }
- }
-}
-
-static void combine_replace(i_color *, i_color *, int, int);
-static void combine_replacef(i_fcolor *, i_fcolor *, int, int);
-static void combine_alphablend(i_color *, i_color *, int, int);
-static void combine_alphablendf(i_fcolor *, i_fcolor *, int, int);
-static void combine_mult(i_color *, i_color *, int, int);
-static void combine_multf(i_fcolor *, i_fcolor *, int, int);
-static void combine_dissolve(i_color *, i_color *, int, int);
-static void combine_dissolvef(i_fcolor *, i_fcolor *, int, int);
-static void combine_add(i_color *, i_color *, int, int);
-static void combine_addf(i_fcolor *, i_fcolor *, int, int);
-static void combine_subtract(i_color *, i_color *, int, int);
-static void combine_subtractf(i_fcolor *, i_fcolor *, int, int);
-static void combine_diff(i_color *, i_color *, int, int);
-static void combine_difff(i_fcolor *, i_fcolor *, int, int);
-static void combine_darken(i_color *, i_color *, int, int);
-static void combine_darkenf(i_fcolor *, i_fcolor *, int, int);
-static void combine_lighten(i_color *, i_color *, int, int);
-static void combine_lightenf(i_fcolor *, i_fcolor *, int, int);
-static void combine_hue(i_color *, i_color *, int, int);
-static void combine_huef(i_fcolor *, i_fcolor *, int, int);
-static void combine_sat(i_color *, i_color *, int, int);
-static void combine_satf(i_fcolor *, i_fcolor *, int, int);
-static void combine_value(i_color *, i_color *, int, int);
-static void combine_valuef(i_fcolor *, i_fcolor *, int, int);
-static void combine_color(i_color *, i_color *, int, int);
-static void combine_colorf(i_fcolor *, i_fcolor *, int, int);
-
-static struct i_combines {
- i_fill_combine_f combine;
- i_fill_combinef_f combinef;
-} combines[] =
-{
- { /* replace */
- combine_replace,
- combine_replacef,
- },
- { /* alpha blend */
- combine_alphablend,
- combine_alphablendf,
- },
- {
- /* multiply */
- combine_mult,
- combine_multf,
- },
- {
- /* dissolve */
- combine_dissolve,
- combine_dissolvef,
- },
- {
- /* add */
- combine_add,
- combine_addf,
- },
- {
- /* subtract */
- combine_subtract,
- combine_subtractf,
- },
- {
- /* diff */
- combine_diff,
- combine_difff,
- },
- {
- combine_lighten,
- combine_lightenf,
- },
- {
- combine_darken,
- combine_darkenf,
- },
- {
- combine_hue,
- combine_huef,
- },
- {
- combine_sat,
- combine_satf,
- },
- {
- combine_value,
- combine_valuef,
- },
- {
- combine_color,
- combine_colorf,
- },
-};
-
-/*
-=item i_get_combine(combine, color_func, fcolor_func)
-
-=cut
-*/
-
-void i_get_combine(int combine, i_fill_combine_f *color_func,
- i_fill_combinef_f *fcolor_func) {
- if (combine < 0 || combine > sizeof(combines) / sizeof(*combines))
- combine = 0;
-
- *color_func = combines[combine].combine;
- *fcolor_func = combines[combine].combinef;
-}
-
-static void combine_replace(i_color *out, i_color *in, int channels, int count) {
- while (count--) {
- *out++ = *in++;
- }
-}
-
-static void combine_replacef(i_fcolor *out, i_fcolor *in, int channels, int count) {
- while (count--) {
- *out++ = *in++;
- }
-}
-
-static void combine_alphablend(i_color *out, i_color *in, int channels, int count) {
- while (count--) {
- COMBINE(*out, *in, channels);
- ++out;
- ++in;
- }
-}
-
-static void combine_alphablendf(i_fcolor *out, i_fcolor *in, int channels, int count) {
- while (count--) {
- COMBINEF(*out, *in, channels);
- ++out;
- ++in;
- }
-}
-
-static void combine_mult(i_color *out, i_color *in, int channels, int count) {
- int ch;
-
- while (count--) {
- double mult[MAXCHANNELS];
- mult[3] = in->channel[3];
- for (ch = 0; ch < (channels); ++ch) {
- if (ch != 3)
- mult[ch] = (out->channel[ch] * in->channel[ch]) * (1.0 / 255);
- }
- COMBINEA(*out, mult, channels);
- ++out;
- ++in;
- }
-}
-
-static void combine_multf(i_fcolor *out, i_fcolor *in, int channels, int count) {
- int ch;
-
- while (count--) {
- i_fcolor c = *in;
- for (ch = 0; ch < channels; ++ch) {
- if (ch != 3)
- c.channel[ch] = out->channel[ch] * in->channel[ch];
- }
- COMBINEF(*out, c, channels);
- ++out;
- ++in;
- }
-}
-
-static void combine_dissolve(i_color *out, i_color *in, int channels, int count) {
- while (count--) {
- if (in->channel[3] > rand() * (255.0 / RAND_MAX))
- COMBINE(*out, *in, channels);
- ++out;
- ++in;
- }
-}
-
-static void combine_dissolvef(i_fcolor *out, i_fcolor *in, int channels, int count) {
- while (count--) {
- if (in->channel[3] > rand() * (1.0 / RAND_MAX))
- COMBINEF(*out, *in, channels);
- ++out;
- ++in;
- }
-}
-
-static void combine_add(i_color *out, i_color *in, int channels, int count) {
- int ch;
-
- while (count--) {
- i_color c = *in;
- for (ch = 0; ch < (channels); ++ch) {
- if (ch != 3) {
- int total = out->channel[ch] + in->channel[ch];
- if (total > 255)
- total = 255;
- c.channel[ch] = total;
- }
- }
- COMBINE(*out, c, channels);
- ++out;
- ++in;
- }
-}
-
-static void combine_addf(i_fcolor *out, i_fcolor *in, int channels, int count) {
- int ch;
-
- while (count--) {
- i_fcolor c = *in;
- for (ch = 0; ch < (channels); ++ch) {
- if (ch != 3) {
- double total = out->channel[ch] + in->channel[ch];
- if (total > 1.0)
- total = 1.0;
- out->channel[ch] = total;
- }
- }
- COMBINEF(*out, c, channels);
- ++out;
- ++in;
- }
-}
-
-static void combine_subtract(i_color *out, i_color *in, int channels, int count) {
- int ch;
-
- while (count--) {
- i_color c = *in;
- for (ch = 0; ch < (channels); ++ch) {
- if (ch != 3) {
- int total = out->channel[ch] - in->channel[ch];
- if (total < 0)
- total = 0;
- c.channel[ch] = total;
- }
- }
- COMBINE(*out, c, channels);
- ++out;
- ++in;
- }
-}
-
-static void combine_subtractf(i_fcolor *out, i_fcolor *in, int channels, int count) {
- int ch;
-
- while (count--) {
- i_fcolor c = *in;
- for (ch = 0; ch < channels; ++ch) {
- if (ch != 3) {
- double total = out->channel[ch] - in->channel[ch];
- if (total < 0)
- total = 0;
- c.channel[ch] = total;
- }
- }
- COMBINEF(*out, c, channels);
- ++out;
- ++in;
- }
-}
-
-static void combine_diff(i_color *out, i_color *in, int channels, int count) {
- int ch;
-
- while (count--) {
- i_color c = *in;
- for (ch = 0; ch < (channels); ++ch) {
- if (ch != 3)
- c.channel[ch] = abs(out->channel[ch] - in->channel[ch]);
- }
- COMBINE(*out, c, channels)
- ++out;
- ++in;
- }
-}
-
-static void combine_difff(i_fcolor *out, i_fcolor *in, int channels, int count) {
- int ch;
-
- while (count--) {
- i_fcolor c = *in;
- for (ch = 0; ch < (channels); ++ch) {
- if (ch != 3)
- c.channel[ch] = fabs(out->channel[ch] - in->channel[ch]);
- }
- COMBINEF(*out, c, channels);
- ++out;
- ++in;
- }
-}
-
-static void combine_darken(i_color *out, i_color *in, int channels, int count) {
- int ch;
-
- while (count--) {
- for (ch = 0; ch < channels; ++ch) {
- if (ch != 3 && out->channel[ch] < in->channel[ch])
- in->channel[ch] = out->channel[ch];
- }
- COMBINE(*out, *in, channels);
- ++out;
- ++in;
- }
-}
-
-static void combine_darkenf(i_fcolor *out, i_fcolor *in, int channels, int count) {
- int ch;
-
- while (count--) {
- for (ch = 0; ch < channels; ++ch) {
- if (ch != 3 && out->channel[ch] < in->channel[ch])
- in->channel[ch] = out->channel[ch];
- }
- COMBINEF(*out, *in, channels);
- ++out;
- ++in;
- }
-}
-
-static void combine_lighten(i_color *out, i_color *in, int channels, int count) {
- int ch;
-
- while (count--) {
- for (ch = 0; ch < channels; ++ch) {
- if (ch != 3 && out->channel[ch] > in->channel[ch])
- in->channel[ch] = out->channel[ch];
- }
- COMBINE(*out, *in, channels);
- ++out;
- ++in;
- }
-}
-
-static void combine_lightenf(i_fcolor *out, i_fcolor *in, int channels, int count) {
- int ch;
-
- while (count--) {
- for (ch = 0; ch < channels; ++ch) {
- if (ch != 3 && out->channel[ch] > in->channel[ch])
- in->channel[ch] = out->channel[ch];
- }
- COMBINEF(*out, *in, channels);
- ++out;
- ++in;
- }
-}
-
-static void combine_hue(i_color *out, i_color *in, int channels, int count) {
- while (count--) {
- i_color c = *out;
- i_rgb_to_hsv(&c);
- i_rgb_to_hsv(in);
- c.channel[0] = in->channel[0];
- i_hsv_to_rgb(&c);
- c.channel[3] = in->channel[3];
- COMBINE(*out, c, channels);
- ++out;
- ++in;
- }
-}
-
-static void combine_huef(i_fcolor *out, i_fcolor *in, int channels, int count) {
- while (count--) {
- i_fcolor c = *out;
- i_rgb_to_hsvf(&c);
- i_rgb_to_hsvf(in);
- c.channel[0] = in->channel[0];
- i_hsv_to_rgbf(&c);
- c.channel[3] = in->channel[3];
- COMBINEF(*out, c, channels);
- ++out;
- ++in;
- }
-}
-
-static void combine_sat(i_color *out, i_color *in, int channels, int count) {
- while (count--) {
- i_color c = *out;
- i_rgb_to_hsv(&c);
- i_rgb_to_hsv(in);
- c.channel[1] = in->channel[1];
- i_hsv_to_rgb(&c);
- c.channel[3] = in->channel[3];
- COMBINE(*out, c, channels);
- ++out;
- ++in;
- }
+ if (f->src->channels != want_channels)
+ i_adapt_fcolors(want_channels, f->src->channels, data, width);
}
-static void combine_satf(i_fcolor *out, i_fcolor *in, int channels, int count) {
- while (count--) {
- i_fcolor c = *out;
- i_rgb_to_hsvf(&c);
- i_rgb_to_hsvf(in);
- c.channel[1] = in->channel[1];
- i_hsv_to_rgbf(&c);
- c.channel[3] = in->channel[3];
- COMBINEF(*out, c, channels);
- ++out;
- ++in;
- }
-}
-
-static void combine_value(i_color *out, i_color *in, int channels, int count) {
- while (count--) {
- i_color c = *out;
- i_rgb_to_hsv(&c);
- i_rgb_to_hsv(in);
- c.channel[2] = in->channel[2];
- i_hsv_to_rgb(&c);
- c.channel[3] = in->channel[3];
- COMBINE(*out, c, channels);
- ++out;
- ++in;
- }
-}
-
-static void combine_valuef(i_fcolor *out, i_fcolor *in, int channels,
- int count) {
- while (count--) {
- i_fcolor c = *out;
- i_rgb_to_hsvf(&c);
- i_rgb_to_hsvf(in);
- c.channel[2] = in->channel[2];
- i_hsv_to_rgbf(&c);
- c.channel[3] = in->channel[3];
- COMBINEF(*out, c, channels);
- ++out;
- ++in;
- }
-}
-
-static void combine_color(i_color *out, i_color *in, int channels, int count) {
- while (count--) {
- i_color c = *out;
- i_rgb_to_hsv(&c);
- i_rgb_to_hsv(in);
- c.channel[0] = in->channel[0];
- c.channel[1] = in->channel[1];
- i_hsv_to_rgb(&c);
- c.channel[3] = in->channel[3];
- COMBINE(*out, c, channels);
- ++out;
- ++in;
- }
-}
+static void
+fill_opacity(i_fill_t *fill, i_img_dim x, i_img_dim y, i_img_dim width,
+ int channels, i_color *data) {
+ struct i_fill_opacity_t *f = (struct i_fill_opacity_t *)fill;
+ int alpha_chan = channels > 2 ? 3 : 1;
+ i_color *datap = data;
+
+ (f->other_fill->f_fill_with_color)(f->other_fill, x, y, width, channels, data);
+ while (width--) {
+ double new_alpha = datap->channel[alpha_chan] * f->alpha_mult;
+ if (new_alpha < 0)
+ datap->channel[alpha_chan] = 0;
+ else if (new_alpha > 255)
+ datap->channel[alpha_chan] = 255;
+ else datap->channel[alpha_chan] = (int)(new_alpha + 0.5);
+
+ ++datap;
+ }
+}
+static void
+fill_opacityf(i_fill_t *fill, i_img_dim x, i_img_dim y, i_img_dim width,
+ int channels, i_fcolor *data) {
+ struct i_fill_opacity_t *f = (struct i_fill_opacity_t *)fill;
+ int alpha_chan = channels > 2 ? 3 : 1;
+ i_fcolor *datap = data;
+
+ (f->other_fill->f_fill_with_fcolor)(f->other_fill, x, y, width, channels, data);
+
+ while (width--) {
+ double new_alpha = datap->channel[alpha_chan] * f->alpha_mult;
+ if (new_alpha < 0)
+ datap->channel[alpha_chan] = 0;
+ else if (new_alpha > 1.0)
+ datap->channel[alpha_chan] = 1.0;
+ else datap->channel[alpha_chan] = new_alpha;
-static void combine_colorf(i_fcolor *out, i_fcolor *in, int channels,
- int count) {
- while (count--) {
- i_fcolor c = *out;
- i_rgb_to_hsvf(&c);
- i_rgb_to_hsvf(in);
- c.channel[0] = in->channel[0];
- c.channel[1] = in->channel[1];
- i_hsv_to_rgbf(&c);
- c.channel[3] = in->channel[3];
- COMBINEF(*out, c, channels);
- ++out;
- ++in;
+ ++datap;
}
}
-
/*
=back