chiark / gitweb /
bugfixes; background handling; etc.
authorian <ian>
Fri, 22 Oct 2004 22:10:41 +0000 (22:10 +0000)
committerian <ian>
Fri, 22 Oct 2004 22:10:41 +0000 (22:10 +0000)
layout/subseg2display.c

index 40695cb13fa8a50efc819c9906bed4c8f76b4e98..f960d71722f1c401277dd4e9547262aff0b7707b 100644 (file)
@@ -5,6 +5,7 @@
  * status-info args are:
  *   <idchar> <alpha> <red> <green> <blue>
  *   .. <alpha> <red> <green> <blue>
+ *   0. <alpha> <red> <green> <blue>
  *   <idchar><subseg>
  *
  * `..' group is for unspecified segments.
  * moveable feature and position as in segcmapassign and
  *
  * Resulting pixel is
- *                                               [ red   ]
- *    (alpha * DIRECTION_COLOUR) + ((1-alpha) *  [ green ] )
- *                                               [ blue  ]
+ *                                                   [ red   ]
+ *    (|alpha| * DIRECTION_COLOUR) + ((1-|alpha|) *  [ green ] )
+ *                                                   [ blue  ]
+ *
+ * where DIRECTION_COLOUR corresponds to the reverse of the stated
+ * direction iff alpha<0.
+ *
+ * All of alpha, red, green, blue are out of 1000.
  */
 
 #include <stdio.h>
@@ -72,7 +78,7 @@ static const char *nextarg(void) {
   return *argv++;
 }
 
-static double doublearg(void) {
+static double channelarg(void) {
   const char *arg= nextarg();
   char *ep;
   double v;
@@ -83,20 +89,21 @@ static double doublearg(void) {
   if (errno) badusage();
   if (!finite(v)) badusage();
 
-  return v;
+  return v / 1000.0;
 }
 
 /*---------- specification args ----------*/
 
-static void idgroupargs(id ix) {
-  struct result *r;
+static void resultargs(struct result *r) {
   int i;
 
-  r= &idinfo[ix];
-
-  r->alpha= doublearg();
+  r->alpha= channelarg();
   for (i=0; i<3; i++)
-    r->rgb[i]= doublearg();
+    r->rgb[i]= channelarg();
+}
+  
+static void idgroupargs(id ix) {
+  resultargs(&idinfo[ix]);
 }
 
 static void ensure_somethings(void **ary, int *allocd, int want, size_t item,
@@ -104,7 +111,7 @@ static void ensure_somethings(void **ary, int *allocd, int want, size_t item,
   int new_allocd;
   
   if (*allocd > want) return;
-  new_allocd= (*allocd+1)*2;
+  new_allocd= (want+1)*2;
   *ary= xrealloc(*ary, new_allocd * item);
   zero((char*)*ary + item * *allocd, new_allocd - *allocd);
   *allocd= new_allocd;
@@ -127,7 +134,7 @@ static void zero_mps(void *data_v, int count) {
 #define ENSURE_THINGS(sfx,type)                                                \
   static void ensure_##sfx(type **ary_io, int *allocd, int want) {     \
     void *ary= *ary_io;                                                        \
-    ensure_somethings(ary,allocd,want,sizeof(**ary_io),zero_##sfx);    \
+    ensure_somethings(&ary,allocd,want,sizeof(**ary_io),zero_##sfx);   \
     *ary_io= ary;                                                      \
   }                                                                    \
   struct eat_semicolon
@@ -162,7 +169,7 @@ static void subsegarg(id ix, const char *arg) {
   if (movfeatpos > MAXMOVFEATPOS) badusage();
 
   ensure_mps(&moveable,&moveable_a,segnum);
-  mps= &moveable[ix];
+  mps= &moveable[segnum];
   ensure_ids(&mps->lookup,&mps->lookup_a, movfeatpos ^ MAXMOVFEATPOS);
   mps->lookup[movfeatpos ^ MAXMOVFEATPOS]= ix;
 }  
@@ -187,15 +194,17 @@ static unsigned reverse_bits_in_byte (unsigned a) {
 }
 
 static void angle_to_colour(double result[3],
-                           double angle /* in units of 2pi radians< <1.0 */) {
+                           double angle /* in units of 2pi radians< <1.0 */,
+                           int reverse) {
   /* Inspired by http://www.acm.org/jgt/papers/SmithLyons96/hsv_rgb.html */
   int i;
   double f;
-  
+
   angle *= 6.0;
   i= floor(angle);
   f= angle - i;
   
+  if (reverse) { i += 3; i %= 6; }
   if (i&1) f= 1.0 - f;
 
   switch (i) {
@@ -234,8 +243,8 @@ static void process(void) {
          rgbod[i]= background.rgb[i];
        
       } else {
-       int segnum, movfeatpos, red, blue, green, ix;
-       double rgbdirn[3], angle;
+       int segnum, movfeatpos, movfeatposix, red, blue, green, ix;
+       double rgbdirn[3], angle, alpha;
        struct result *r;
 
        red= rgbi[0];
@@ -247,21 +256,23 @@ static void process(void) {
 
        segnum= blue | ((green & 0xc0) << 2);
        movfeatpos= green & 0x3f;
+       movfeatposix= movfeatpos ^ MAXMOVFEATPOS;
 
        assert(segnum <= MAXSEGNUM);
        assert(movfeatpos <= MAXMOVFEATPOS);
 
-       angle_to_colour(rgbdirn, angle);
-
        ix= !movfeatpos ?
          (segnum < fixed_a ? fixed[segnum] : 0) :
-         (segnum < moveable_a && movfeatpos < moveable[segnum].lookup_a
-          ? moveable[segnum].lookup[movfeatpos] : 0);
+         (segnum < moveable_a && movfeatposix < moveable[segnum].lookup_a
+          ? moveable[segnum].lookup[movfeatposix] : 0);
 
        r= &idinfo[ix];
 
+       angle_to_colour(rgbdirn, angle, r->alpha < 0);
+       alpha= fabs(r->alpha);
+
        for (i=0; i<3; i++)
-         rgbod[i]= r->alpha * rgbdirn[i] + (1.0 - r->alpha) * r->rgb[i];
+         rgbod[i]= alpha * rgbdirn[i] + (1.0 - alpha) * r->rgb[i];
 
       }
 
@@ -272,6 +283,8 @@ static void process(void) {
     }
 }
 
+/*---------- main program ----------*/
+
 int main(int argc_spec, char **argv_spec) {
   const char *arg, *encodingfilename;
 
@@ -285,6 +298,7 @@ int main(int argc_spec, char **argv_spec) {
     if (!*arg) badusage();
     if (!arg[1]) idgroupargs(arg[0]);
     else if (!strcmp(arg,"..")) idgroupargs(0);
+    else if (!strcmp(arg,"0.")) resultargs(&background);
     else subsegarg(arg[0],arg+1);
   }