commit changes from draw branch
[imager.git] / fills.c
diff --git a/fills.c b/fills.c
index 251d6b7..55139ed 100644 (file)
--- a/fills.c
+++ b/fills.c
@@ -166,10 +166,6 @@ 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 i_fill_solid_t base_solid_fill =
 {
@@ -181,16 +177,6 @@ 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)
@@ -228,12 +214,11 @@ 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]);
@@ -260,12 +245,11 @@ 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]);
@@ -490,6 +474,16 @@ struct i_fill_image_t {
   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)
 
@@ -508,9 +502,7 @@ i_fill_t *
 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;
-  fill->base.destroy = NULL;
+  *fill = image_fill_proto;
 
   if (combine) {
     i_get_combine(combine, &fill->base.combine, &fill->base.combinef);
@@ -555,8 +547,10 @@ The 8-bit sample fill function for non-combining solid fills.
 static void
 fill_solid(i_fill_t *fill, int x, int y, int 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++ = T_SOLID_FILL(fill)->c;
+    *data++ = c;
   }
 }
 
@@ -570,45 +564,23 @@ The floating sample fill function for non-combining solid fills.
 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;
-  }
-}
-
-/*
-=item fill_solid_comb(fill, x, y, width, channels, data)
-
-The 8-bit sample fill function for combining solid fills.
-
-=cut
-*/
-static void
-fill_solid_comb(i_fill_t *fill, int x, int y, int width, int channels, 
-                i_color *data) {
-  i_color c = T_SOLID_FILL(fill)->c;
-
-  while (width-- > 0) {
-    *data++ = c;
-  }
-}
-
-/*
-=item fill_solidf_comb(fill, x, y, width, channels, data)
-
-The floating sample fill function for combining solid fills.
-
-=cut
-*/
-static void
-fill_solidf_comb(i_fill_t *fill, int x, int y, int 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)
 
@@ -624,9 +596,7 @@ i_new_hatch_low(const i_color *fg, const i_color *bg,
                 int dx, int 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 = hatch_fill_proto;
   /* Some Sun C didn't like the condition expressions that were here.
      See https://rt.cpan.org/Ticket/Display.html?id=21944
    */
@@ -954,467 +924,6 @@ static void fill_imagef(i_fill_t *fill, int x, int y, int width, int channels,
   }
 }
 
-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;
-  }
-}
-
-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 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;
-  }
-}
-
 
 /*
 =back