]> git.imager.perl.org - imager.git/blobdiff - fills.c
add to_rgb16 method
[imager.git] / fills.c
diff --git a/fills.c b/fills.c
index de9f1628ecb6762ac7f0ad11a9181d72cc8382fd..6e929199dac9d1247173a6c5dd6d24c13a33aa1c 100644 (file)
--- a/fills.c
+++ b/fills.c
@@ -1,5 +1,5 @@
-#include "image.h"
-#include "imagei.h"
+#include "imager.h"
+#include "imageri.h"
 
 /*
 =head1 NAME
@@ -104,7 +104,7 @@ regmach - use the register machine to generate colors
 =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;
 
@@ -114,7 +114,7 @@ static i_color fcolor_to_color(i_fcolor *c) {
   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;
 
@@ -195,6 +195,8 @@ static i_fill_solid_t base_solid_fill_comb =
 /*
 =item i_fill_destroy(fill)
 
+=category Fills
+
 Call to destroy any fill object.
 
 =cut
@@ -210,6 +212,8 @@ i_fill_destroy(i_fill_t *fill) {
 /*
 =item i_new_fill_solidf(color, combine)
 
+=category Fills
+
 Create a solid fill based on a float color.
 
 If combine is non-zero then alpha values will be combined.
@@ -218,9 +222,9 @@ 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));
+  i_fill_solid_t *fill = mymalloc(sizeof(i_fill_solid_t)); /* checked 14jul05 tonyc */
   
   if (combine) {
     *fill = base_solid_fill_comb;
@@ -239,7 +243,9 @@ i_new_fill_solidf(i_fcolor *c, int combine) {
 /*
 =item i_new_fill_solid(color, combine)
 
-Create a solid fill based.
+=category Fills
+
+Create a solid fill based on an 8-bit color.
 
 If combine is non-zero then alpha values will be combined.
 
@@ -247,9 +253,9 @@ 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));
+  i_fill_solid_t *fill = mymalloc(sizeof(i_fill_solid_t)); /* checked 14jul05 tonyc */
 
   if (combine) {
     *fill = base_solid_fill_comb;
@@ -413,13 +419,15 @@ static void fill_hatchf(i_fill_t *fill, int x, int y, int 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,
+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,
                 int dx, int dy);
 
 /*
 =item i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch, dx, dy)
 
+=category Fills
+
 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.
@@ -434,8 +442,8 @@ If cust_hatch is NULL then one of the standard hatches is used.
 =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, int dx, int dy) {
   return i_new_hatch_low(fg, bg, NULL, NULL, combine, hatch, cust_hatch, 
                          dx, dy);
 }
@@ -443,6 +451,8 @@ i_new_fill_hatch(i_color *fg, i_color *bg, int combine, int hatch,
 /*
 =item i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch, dx, dy)
 
+=category Fills
+
 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.
@@ -457,8 +467,8 @@ If cust_hatch is NULL then one of the standard hatches is used.
 =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, int dx, int dy) {
   return i_new_hatch_low(NULL, NULL, fg, bg, combine, hatch, cust_hatch, 
                          dx, dy);
 }
@@ -478,13 +488,19 @@ struct i_fill_image_t {
 /*
 =item i_new_fill_image(im, matrix, xoff, yoff, combine)
 
+=category Fills
+
 Create an image based fill.
 
+matrix is an array of 9 doubles representing a transformation matrix.
+
+xoff and 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) {
-  struct i_fill_image_t *fill = mymalloc(sizeof(*fill));
+i_new_fill_image(i_img *im, const double *matrix, int xoff, int 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;
@@ -596,18 +612,34 @@ Implements creation of hatch fill objects.
 */
 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,
+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,
                 int dx, int dy) {
-  i_fill_hatch_t *fill = mymalloc(sizeof(i_fill_hatch_t));
+  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);
+  /* Some Sun C didn't like the condition expressions that were here.
+     See https://rt.cpan.org/Ticket/Display.html?id=21944
+   */
+  if (fg)
+    fill->fg = *fg;
+  else
+    fill->fg = fcolor_to_color(ffg);
+  if (bg)
+    fill->bg = *bg;
+  else
+    fill->bg = fcolor_to_color(fbg);
+  if (ffg) 
+    fill->ffg = *ffg;
+  else
+    fill->ffg = color_to_fcolor(fg);
+  if (fbg)
+    fill->fbg = *fbg;
+  else
+    fill->fbg = color_to_fcolor(bg);
   if (combine) {
     i_get_combine(combine, &fill->base.combine, &fill->base.combinef);
   }
@@ -644,7 +676,10 @@ static void fill_hatch(i_fill_t *fill, int x, int y, int width, int channels,
   int mask = 128 >> xpos;
 
   while (width-- > 0) {
-    *data++ = (byte & mask) ? f->fg : f->bg;
+    if (byte & mask)
+      *data++ = f->fg;
+    else
+      *data++ = f->bg;
     
     if ((mask >>= 1) == 0)
       mask = 128;
@@ -666,7 +701,10 @@ static void fill_hatchf(i_fill_t *fill, int x, int y, int width, int channels,
   int mask = 128 >> xpos;
   
   while (width-- > 0) {
-    *data++ = (byte & mask) ? f->ffg : f->fbg;
+    if (byte & mask)
+      *data++ = f->ffg;
+    else
+      *data++ = f->fbg;
     
     if ((mask >>= 1) == 0)
       mask = 128;
@@ -683,7 +721,7 @@ static i_color interp_i_color(i_color before, i_color after, double pos,
   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])
+  if (channels > 3 && out.channel[3])
     for (ch = 0; ch < channels; ++ch)
       if (ch != 3) {
         int temp = out.channel[ch] * 255 / out.channel[3];
@@ -726,7 +764,7 @@ static void fill_image(i_fill_t *fill, int x, int y, int width, int channels,
                        i_color *data) {
   struct i_fill_image_t *f = (struct i_fill_image_t *)fill;
   int i = 0;
-  i_color c;
+  i_color *out = data;
   
   if (f->has_matrix) {
     /* the hard way */
@@ -761,7 +799,7 @@ static void fill_image(i_fill_t *fill, int x, int y, int width, int channels,
         }
         c2[dy] = interp_i_color(c[dy][0], c[dy][1], rx, f->src->channels);
       }
-      *data++ = interp_i_color(c2[0], c2[1], ry, f->src->channels);
+      *out++ = interp_i_color(c2[0], c2[1], ry, f->src->channels);
       ++i;
     }
   }
@@ -784,11 +822,34 @@ static void fill_image(i_fill_t *fill, int x, int y, int width, int channels,
       }
       rx -= ix * f->src->xsize;
       ry -= iy * f->src->ysize;
-      i_gpix(f->src, rx, ry, data);
-      ++data;
+      i_gpix(f->src, rx, ry, out);
+      ++out;
       ++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++;
+    }
+  }
 }
 
 /*
@@ -800,7 +861,6 @@ static void fill_imagef(i_fill_t *fill, int x, int y, int width, int channels,
                        i_fcolor *data) {
   struct i_fill_image_t *f = (struct i_fill_image_t *)fill;
   int i = 0;
-  i_fcolor c;
   
   if (f->has_matrix) {
     /* the hard way */
@@ -863,6 +923,29 @@ static void fill_imagef(i_fill_t *fill, int x, int y, int width, int channels,
       ++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);
@@ -1003,7 +1086,6 @@ static void combine_mult(i_color *out, i_color *in, int channels, int count) {
   int ch;
 
   while (count--) {
-    i_color c = *in;
     double mult[MAXCHANNELS];
     mult[3] = in->channel[3];
     for (ch = 0; ch < (channels); ++ch) { 
@@ -1032,8 +1114,6 @@ static void combine_multf(i_fcolor *out, i_fcolor *in, int channels, int count)
 }
 
 static void combine_dissolve(i_color *out, i_color *in, int channels, int count) {
-  int ch;
-
   while (count--) {
     if (in->channel[3] > rand() * (255.0 / RAND_MAX))
       COMBINE(*out, *in, channels);
@@ -1043,8 +1123,6 @@ static void combine_dissolve(i_color *out, i_color *in, int channels, int count)
 }
 
 static void combine_dissolvef(i_fcolor *out, i_fcolor *in, int channels, int count) {
-  int ch;
-
   while (count--) {
     if (in->channel[3] > rand() * (1.0 / RAND_MAX))
       COMBINEF(*out, *in, channels);