* 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>
return *argv++;
}
-static double doublearg(void) {
+static double channelarg(void) {
const char *arg= nextarg();
char *ep;
double v;
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,
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;
#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
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;
}
}
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) {
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];
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];
}
}
}
+/*---------- main program ----------*/
+
int main(int argc_spec, char **argv_spec) {
const char *arg, *encodingfilename;
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);
}