1 
2 /*
3  * xa_utils.c
4  *
5  * Copyright (C) 1991-1998,1999 by Mark Podlipec.
6  * All rights reserved.
7  *
8  * This software may be freely used, copied and redistributed without
9  * fee for non-commerical purposes provided that this copyright
10  * notice is preserved intact on all copies.
11  *
12  * There is no warranty or other guarantee of fitness of this software.
13  * It is provided solely "as is". The author disclaims all
14  * responsibility and liability with respect to this software's usage
15  * or its effect upon hardware or computer systems.
16  *
17  */
18 /* revhist
19  * 12dec94  +bCdm caused core on Alpha OSF/1 v3.0.
20  *           found and fixed by David Mosberger-Tang.
21  * 14Dec97  Adam Moss:  Optimized scaling routines and found bug
22  *          when allocating memory for scaling the clip mask of
23  *	    an image(used in GIF animations).
24  *
25  */
26 #include "xanim.h"
27 #include <ctype.h>
28 
29 void UTIL_Sub_Image();
30 void UTIL_Create_Clip();
31 void UTIL_Mapped_To_Mapped();
32 void UTIL_Mapped_To_Bitmap();
33 xaULONG UTIL_Get_Buffer_Scale();
34 void UTIL_Scale_Buffer_Pos();
35 void UTIL_Scale_Pos_Size();
36 xaUBYTE *UTIL_Alloc_Scaled();
37 xaUBYTE *UTIL_Scale_Mapped();
38 xaUBYTE *UTIL_Scale_Bitmap();
39 void UTIL_Pack_Image();
40 void UTIL_FPS_2_Time();
41 
42 xaULONG UTIL_Get_LSB_Long();
43 xaULONG UTIL_Get_LSB_Short();
44 xaULONG UTIL_Get_MSB_Long();
45 xaULONG UTIL_Get_MSB_UShort();
46 xaLONG UTIL_Get_MSB_Short();
47 void UTIL_Mapped_To_Floyd();
48 xaULONG CMAP_Find_Closest();
49 void CMAP_Cache_Init();
50 void CMAP_Cache_Clear();
51 
52 extern xaULONG *xa_scale_row_buff;
53 extern xaULONG xa_scale_row_size;
54 extern char *xa_scale_buff;
55 extern xaULONG xa_scale_buff_size;
56 extern xaLONG xa_dither_flag;
57 extern xaULONG xa_buff_x,xa_buff_y;
58 extern float xa_bscalex,xa_bscaley;
59 
60 
61 void
UTIL_Sub_Image(out,in,xosize,yosize,xipos,yipos,xisize,pix_size)62 UTIL_Sub_Image(out,in,xosize,yosize,xipos,yipos,xisize,pix_size)
63 xaUBYTE *out,*in;
64 xaULONG xosize,yosize,xipos,yipos,xisize,pix_size;
65 {
66   xaULONG y,x;
67   xaUBYTE *in_ptr;
68   xosize *= pix_size;
69   xisize *= pix_size;
70   xipos  *= pix_size;
71   for(y=yipos; y < (yipos + yosize); y++)
72   {
73     in_ptr = (xaUBYTE *)(in + (y * xisize + xipos));
74     x = xosize;
75     while(x--) *out++ = *in_ptr++;
76   }
77 }
78 
79 void
UTIL_Mapped_To_Mapped(out,in,chdr,xipos,yipos,xosize,yosize,xisize,yisize)80 UTIL_Mapped_To_Mapped(out,in,chdr,xipos,yipos,xosize,yosize,xisize,yisize)
81 xaUBYTE *out;		/* output image - maybe the same as input image */
82 xaUBYTE *in;		/* input image */
83 XA_CHDR *chdr;		/* color header to remap to */
84 xaULONG xipos,yipos;	/* pos of section in input buffer */
85 xaULONG xosize,yosize;	/* size of section in input buffer */
86 xaULONG xisize,yisize;	/* size of input buffer */
87 {
88   xaULONG *map,moff;
89   xaULONG y,x;
90   xaUBYTE *in_ptr;
91 
92   map = chdr->map;
93   moff = chdr->moff;
94   switch(x11_bytes_pixel)
95   {
96    case 4: /* start from backside to allow for when out = in */
97 	{
98 	  xaULONG *ulp;
99 	  for(y=yosize; y > 0; y--)
100 	  {
101 	    in_ptr = (xaUBYTE *)(in + (y + yipos - 1) * xisize
102 						+ xipos + xosize - 1 );
103 	    ulp =    (xaULONG *)(out + ((4 * y * xosize) - 4));
104 	    x = xosize;
105 	    if (moff) while(x--) *ulp-- = map[(*in_ptr--)-moff];
106 	    else while(x--) *ulp-- = map[*in_ptr--];
107 	  }
108 	}
109 	break;
110    case 2: /* start from backside to allow for when out = in */
111 	{
112 	  xaUSHORT *usp;
113 	  for(y=yosize; y > 0; y--)
114 	  {
115 	    in_ptr = (xaUBYTE *)(in + (y + yipos - 1) * xisize
116 						+ xipos + xosize - 1 );
117 	    usp =    (xaUSHORT *)(out + ((2 * y * xosize) - 2));
118 	    x = xosize;
119 	    if (moff) while(x--) *usp-- = (xaUSHORT)map[(*in_ptr--)-moff];
120 	    else while(x--) *usp-- = (xaUSHORT)map[*in_ptr--];
121 	  }
122 	}
123 	break;
124    case 1:
125 	{
126 	  for(y=yipos; y < (yipos + yosize); y++)
127 	  {
128 	    in_ptr = (xaUBYTE *)(in + y * xisize + xipos);
129 	    x = xosize;
130 	    if (moff) while(x--) *out++ = (xaUBYTE)(map[(*in_ptr++)-moff]);
131 	    else while(x--) *out++ = (xaUBYTE)(map[*in_ptr++]);
132 	  }
133 	}
134 	break;
135   } /* end switch */
136 }
137 
138 void
UTIL_Create_Clip(out,in,pix_mask,xsize,ysize,pix_size,xosize,bit_order)139 UTIL_Create_Clip(out,in,pix_mask,xsize,ysize,pix_size,xosize,bit_order)
140 xaUBYTE *out,*in;
141 xaULONG pix_mask,xsize,ysize,pix_size,xosize,bit_order;
142 {
143   register xaULONG data_in,bit_mask,x,y,mask_start,mask_end;
144   register xaUBYTE data_out;
145 
146   if (bit_order == XA_MSBIT_1ST) { mask_start = 0x80; mask_end = 0x01; }
147   else { mask_start = 0x01; mask_end = 0x80; }
148 
149   for(y=0; y<ysize; y++)
150   {
151     bit_mask = mask_start;
152     data_out = 0;
153     for(x=0; x < xosize; x++)
154     {
155       if (x < xsize)
156       {
157         if (pix_size == 4)
158 	  { xaULONG *ulp = (xaULONG *)in;	data_in = *ulp; }
159         else if (pix_size == 2)
160 	  { xaUSHORT *usp = (xaUSHORT *)in;	data_in = (xaULONG)(*usp); }
161         else				data_in = (xaULONG)(*in);
162         in += pix_size;
163         if (data_in != pix_mask) data_out |= bit_mask;
164       }
165 
166       if (bit_mask == mask_end)
167       {
168         *out++ = data_out;
169         bit_mask = mask_start;
170 	data_out = 0;
171       }
172       else if (mask_start == 0x01) bit_mask <<= 1;
173            else bit_mask >>= 1;
174     } /* end of for x */
175     if (bit_mask != mask_start) *out++ = data_out;
176   } /* end of for y */
177 }
178 
179 void
UTIL_Mapped_To_Bitmap(out,in,chdr,xpos,ypos,xsize,ysize,width,height,line_size)180 UTIL_Mapped_To_Bitmap(out,in,chdr,xpos,ypos,xsize,ysize,width,height,line_size)
181 xaUBYTE *out;		/* output buffer */
182 xaUBYTE *in;		/* input buffer */
183 XA_CHDR *chdr;		/* Color Hdr to use */
184 xaULONG xpos,ypos;	/* pos of section in input buffer */
185 xaULONG xsize, ysize;	/* size of section in input buffer */
186 xaULONG width, height;	/* size of buffer */
187 xaULONG line_size;	/* size if bytes of input buffer */
188 {
189   xaULONG y,flag,csize;
190   ColorReg *cmap;
191   register xaULONG mask,invert,x,mask_start,mask_end;
192   xaSHORT *imap,*c_ptr,*n_ptr,*err_buff,err,threshold;
193   xaUBYTE data,*o_ptr;
194 
195   csize = chdr->csize;
196   cmap = chdr->cmap;
197 
198   err_buff = (xaSHORT *)malloc(xsize * 2 * sizeof(xaSHORT));
199   imap     = (xaSHORT *)malloc(csize * sizeof(xaSHORT));
200 
201    /* shift gray down to 8 bits */
202   for(x=0; x<csize; x++) imap[x] = cmap[x].gray >> 8;
203 
204   for(x = 0; x < xsize; x++) err_buff[x] = (xaUSHORT)imap[ *in++ ];
205   flag = 0;
206 
207   /* used to invert image */
208   if (x11_white & 0x01) invert = 0x00;
209   else invert = ~0x00;
210   threshold = 128;
211 
212   if (x11_bit_order == XA_MSBIT_1ST) { mask_start = 0x80; mask_end = 0x01; }
213   else { mask_start = 0x01; mask_end = 0x80; }
214 
215   for(y = 0; y < ysize; y++)
216   {
217     o_ptr = (xaUBYTE *)(out + (line_size * y));
218     /* double buffer error arrays */
219     n_ptr = c_ptr = err_buff;
220     if (flag == 0) { n_ptr += xsize; flag = 1; }
221     else { c_ptr += xsize; flag = 0;
222     }
223     data = 0x00;
224     mask = mask_start;
225     if (y < (ysize - 1) )  n_ptr[0] = (xaUSHORT)imap[ *in++ ];
226 
227     for(x=0; x<xsize; x++)
228     {
229       if (*c_ptr >= threshold) { err = *c_ptr - 255; data |= mask; }
230       else  err = *c_ptr;
231 
232       if (mask == mask_end)
233 	{ *o_ptr++ = data^invert; data = 0x00; mask = mask_start; }
234       else if (mask_start == 0x80) mask >>= 1;
235            else mask <<= 1;
236       c_ptr++;
237 
238       if (xa_dither_flag == xaFALSE)
239       {
240         if (x < (xsize - 1) ) *n_ptr++ = imap[ *in++ ];
241       }
242       else
243       {
244         if (x < (xsize - 1) )  *c_ptr += (7 * err)/16;
245         if (y < (ysize - 1) )
246         {
247           if (x > 0) *n_ptr++ += (3 * err)/16;
248           *n_ptr++ += (5 * err)/16;
249           if (x < (xsize - 1) )
250           { *n_ptr = (xaUSHORT)(imap[*in++]) + (xaSHORT)(err/16); n_ptr--; }
251         }
252       }
253     }
254     if (mask != mask_start) *o_ptr++ = data^invert; /* send out partial */
255 
256   }
257   FREE(err_buff,0x300); err_buff=0;
258   FREE(imap,0x301); imap=0;
259 }
260 
261 /* Routine to read a little endian long word.
262  */
UTIL_Get_LSB_Long(fp)263 xaULONG UTIL_Get_LSB_Long(fp)
264 FILE *fp;
265 {
266  xaULONG ret;
267 
268  ret =  fgetc(fp);
269  ret |= fgetc(fp) << 8;
270  ret |= fgetc(fp) << 16;
271  ret |= fgetc(fp) << 24;
272  return ret;
273 }
274 
275 /* Routine to read a little endian half word.
276  */
UTIL_Get_LSB_Short(fp)277 xaULONG UTIL_Get_LSB_Short(fp)
278 FILE *fp;
279 {
280  xaULONG ret;
281 
282  ret =  fgetc(fp);
283  ret |= fgetc(fp) << 8;
284  return ret;
285 }
286 
287 /* Routine to read a big endian long word.
288  */
UTIL_Get_MSB_Long(fp)289 xaULONG UTIL_Get_MSB_Long(fp)
290 FILE *fp;
291 {
292  xaULONG ret;
293 
294  ret  = fgetc(fp) << 24;
295  ret |= fgetc(fp) << 16;
296  ret |= fgetc(fp) << 8;
297  ret |=  fgetc(fp);
298  return ret;
299 }
300 
301 /* Routine to read a big endian half word.
302  */
UTIL_Get_MSB_Short(fp)303 xaLONG UTIL_Get_MSB_Short(fp)
304 FILE *fp;
305 {
306  xaLONG ret;
307  xaSHORT tmp;
308 
309  tmp  =  fgetc(fp) << 8;
310  tmp |=  fgetc(fp);
311  ret = tmp;
312  return ret;
313 }
314 
315 /*
316  * Routine to read a big endian half word.
317  */
UTIL_Get_MSB_UShort(fp)318 xaULONG UTIL_Get_MSB_UShort(fp)
319 FILE *fp;
320 {
321  xaULONG ret;
322 
323  ret  =  fgetc(fp) << 8;
324  ret |=  fgetc(fp);
325  return ret;
326 }
327 
328 /*
329  *
330  */
UTIL_Mapped_To_Floyd(out,in,chdr_out,chdr_in,xipos,yipos,xosize,yosize,xisize,yisize)331 void UTIL_Mapped_To_Floyd(out,in,chdr_out,chdr_in,
332 		xipos,yipos,xosize,yosize,xisize,yisize)
333 xaUBYTE *out;		/* output (size of section) */
334 xaUBYTE *in;		/* input image */
335 XA_CHDR *chdr_out;	/* chdr to map to */
336 XA_CHDR *chdr_in;	/* input images chdr */
337 xaULONG xipos,yipos;	/* section position within input buffer */
338 xaULONG xosize, yosize;	/* section size */
339 xaULONG xisize, yisize;	/* input buffer size */
340 {
341   xaULONG flag,csize_out,cflag;
342   ColorReg *cmap_in,*cmap_out;
343   register xaULONG x,y;
344   xaULONG shift_r,shift_g,shift_b,coff_out;
345   xaSHORT *err_buff0, *err_buff1, *e_ptr, *ne_ptr;
346   xaSHORT r_err,g_err,b_err;
347   xaUBYTE *o_ptr;
348 
349   cflag = (x11_display_type & XA_X11_COLOR)?xaTRUE:xaFALSE;
350 
351   if (!(x11_display_type & XA_X11_TRUE))
352   {
353     if (cmap_cache == 0) CMAP_Cache_Init(0);
354     if (chdr_out != cmap_cache_chdr)
355     {
356       DEBUG_LEVEL2 fprintf(stderr,"CACHE: clear new_chdr %x\n",(xaULONG)chdr_out);
357       CMAP_Cache_Clear();
358       cmap_cache_chdr = chdr_out;
359     }
360     shift_r = 3 * cmap_cache_bits;
361     shift_g = 2 * cmap_cache_bits;
362     shift_b = cmap_cache_bits;
363   }
364 
365   csize_out = chdr_out->csize;
366   cmap_out = chdr_out->cmap;
367   coff_out = chdr_out->coff;
368 
369   /* allocate error buffer and set up pointers */
370   e_ptr = err_buff1 = err_buff0 = (xaSHORT *)malloc(6 * xosize * sizeof(xaSHORT));
371   if (err_buff0 == 0) TheEnd1("UTIL_Mapped_To_Floyd: malloc err");
372   err_buff1 = &err_buff0[(3 * xosize)]; /* POD verify */
373   flag = 0;
374 
375   { /* POD NOTE: only do this with different cmaps */
376     register xaULONG i,moff,msize,mcoff;
377     moff = chdr_in->moff;
378     mcoff = moff - chdr_in->coff;
379     msize = chdr_in->msize;
380     cmap_in = (ColorReg *)malloc((moff + msize) * sizeof(ColorReg));
381     for(i=0; i<msize; i++)
382     {
383       cmap_in[i + moff].red   = chdr_in->cmap[i + mcoff].red >> 8;
384       cmap_in[i + moff].green = chdr_in->cmap[i + mcoff].green >> 8;
385       cmap_in[i + moff].blue  = chdr_in->cmap[i + mcoff].blue >> 8;
386       cmap_in[i + moff].gray  = chdr_in->cmap[i + mcoff].gray >> 8;
387     }
388   }
389   {
390     register xaUBYTE *i_ptr = (xaUBYTE *)(in + (xisize * (yosize-1+yipos) + xipos));
391     x = xosize; while(x--)
392     {
393       register xaULONG p = *i_ptr++;
394       *e_ptr++ = (xaUSHORT)cmap_in[ p ].red   << 4;
395       *e_ptr++ = (xaUSHORT)cmap_in[ p ].green << 4;
396       *e_ptr++ = (xaUSHORT)cmap_in[ p ].blue  << 4;
397     }
398   }
399 
400   y = yosize; while(y--)
401   {
402     o_ptr = (xaUBYTE *)(out + (xosize * y * x11_bytes_pixel));
403     if (flag) { e_ptr = err_buff1; ne_ptr = err_buff0; flag = 0; }
404     else      { e_ptr = err_buff0; ne_ptr = err_buff1; flag = 1; }
405     if (y > 0)
406     {
407       register xaSHORT *tptr = ne_ptr;
408       register xaUBYTE *i_ptr = (xaUBYTE *)(in + (xisize * (y-1+yipos) + xipos));
409       x = xosize; while(x--)
410       {
411 	register xaULONG p = *i_ptr++;
412 	*tptr++ = (xaUSHORT)cmap_in[ p ].red   << 4;
413 	*tptr++ = (xaUSHORT)cmap_in[ p ].green << 4;
414 	*tptr++ = (xaUSHORT)cmap_in[ p ].blue  << 4;
415       }
416     }
417 
418     x = xosize; while(x--)
419     {
420       xaULONG color_out,pix_out;
421       register xaSHORT r,g,b;
422 
423       r = (*e_ptr++)/16; if (r<0) r = 0; else if (r>255) r = 255;
424       g = (*e_ptr++)/16; if (g<0) g = 0; else if (g>255) g = 255;
425       b = (*e_ptr++)/16; if (b<0) b = 0; else if (b>255) b = 255;
426 
427       if (x11_display_type & XA_X11_TRUE)
428       {
429 	xaULONG tr,tg,tb;
430 	pix_out = X11_Get_True_Color(r,g,b,8);
431 /* TODO: mismatched byte order may break this if on non depth 8 machines */
432 	tr = ((pix_out & x11_red_mask)   >> x11_red_shift);
433 	tg = ((pix_out & x11_green_mask) >> x11_green_shift);
434 	tb = ((pix_out & x11_blue_mask)  >> x11_blue_shift);
435 	r_err = r - (xaSHORT)(cmap_out[tr].red >> 8);
436 	g_err = g - (xaSHORT)(cmap_out[tg].green >> 8);
437 	b_err = b - (xaSHORT)(cmap_out[tb].blue >> 8);
438       }
439       else
440       {
441         register xaULONG cache_i;
442         cache_i = (  ( (r << shift_r) & cmap_cache_rmask)
443                    | ( (g << shift_g) & cmap_cache_gmask)
444                    | ( (b << shift_b) & cmap_cache_bmask) ) >> 8;
445 	if (cmap_cache[cache_i] == 0xffff)
446 	{
447 	  color_out = CMAP_Find_Closest(cmap_out,csize_out,r,g,b,8,8,8,cflag);
448 	  cmap_cache[cache_i] = (xaSHORT)color_out;
449 	}
450 	else color_out = (xaULONG)cmap_cache[cache_i];
451 	pix_out = color_out + coff_out;
452         r_err = r - (xaSHORT)(cmap_out[color_out].red >> 8);
453         g_err = g - (xaSHORT)(cmap_out[color_out].green >> 8);
454         b_err = b - (xaSHORT)(cmap_out[color_out].blue >> 8);
455       }
456 
457       if (x11_bytes_pixel == 1) *o_ptr++ = (xaUBYTE)pix_out;
458       else if (x11_bytes_pixel == 2)
459       { xaUSHORT *so_ptr = (xaUSHORT *)(o_ptr);
460         *so_ptr = (xaUSHORT)pix_out; o_ptr +=2; }
461       else { xaULONG *lo_ptr = (xaULONG *)(o_ptr);
462              *lo_ptr = (xaULONG)pix_out; o_ptr +=4; }
463 
464       if (x)
465       {
466 	*e_ptr   += 7 * r_err;
467 	e_ptr[1] += 7 * g_err;
468 	e_ptr[2] += 7 * b_err;
469       }
470       if (y)
471       {
472         if (x < (xosize-1) ) /* not 1st of line */
473 	{
474 	  *ne_ptr++ += 3 * r_err;
475 	  *ne_ptr++ += 3 * g_err;
476 	  *ne_ptr++ += 3 * b_err;
477 	}
478         *ne_ptr   += 5 * r_err;
479         ne_ptr[1] += 5 * g_err;
480         ne_ptr[2] += 5 * b_err;
481         if (x)
482         {
483 	  ne_ptr[3] += r_err;
484 	  ne_ptr[4] += g_err;
485 	  ne_ptr[5] += b_err;
486 	}
487       }
488     } /* end of x */
489   } /* end of y */
490   if (err_buff0) FREE(err_buff0,0x302);
491   if (cmap_in) FREE(cmap_in,0x303);
492   err_buff0 = 0; cmap_in = 0;
493 }
494 
495 /*
496  * Function to Scale <x,y> positions and sizes
497  *
498  */
499 
500 void
UTIL_Scale_Pos_Size(xpos,ypos,xsize,ysize,xi_scale,yi_scale,xo_scale,yo_scale)501 UTIL_Scale_Pos_Size(xpos,ypos,xsize,ysize,xi_scale,yi_scale,
502 					xo_scale,yo_scale)
503 xaLONG *xpos,*ypos;	 /* input/output positions */
504 xaLONG *xsize,*ysize;	 /* input/output sizes */
505 xaLONG xi_scale,yi_scale; /* input scale/image size */
506 xaLONG xo_scale,yo_scale; /* output scale/image size */
507 {
508   xaLONG ixp,iyp,oxp,oyp;
509   xaLONG ixsize,iysize,oxsize,oysize;
510 
511   ixp = *xpos;      iyp = *ypos;
512   ixsize = *xsize;  iysize = *ysize;
513 
514   oxp = (ixp * xo_scale) / xi_scale;
515   if ( ((oxp * xi_scale) / xo_scale) < ixp ) oxp++;
516   oxsize = (((ixp + ixsize) * xo_scale) / xi_scale) + 1 - oxp;
517   if ( (((oxp+oxsize-1) * xi_scale) / xo_scale) >= (ixp+ixsize) ) oxsize--;
518 
519   oyp = (iyp * yo_scale) / yi_scale;
520   if ( ((oyp * yi_scale) / yo_scale) < iyp ) oyp++;
521   oysize = (((iyp + iysize) * yo_scale) / yi_scale) + 1 - oyp;
522   if ( (((oyp+oysize-1) * yi_scale) / yo_scale) >= (iyp+iysize) ) oysize--;
523 
524   *xpos = oxp;		*ypos = oyp;
525   *xsize = oxsize;	*ysize = oysize;
526 }
527 
528 
529 /*
530  * Function to Scale <x,y> positions
531  *
532  *  new <x,y> positions returned in xopos,yopos;
533  */
534 
535 void
UTIL_Scale_Buffer_Pos(xpos,ypos,xi_scale,yi_scale,xo_scale,yo_scale)536 UTIL_Scale_Buffer_Pos(xpos,ypos,xi_scale,yi_scale,
537 					xo_scale,yo_scale)
538 xaLONG *xpos,*ypos;	 /* input/output positions */
539 xaLONG xi_scale,yi_scale; /* input scale/image size */
540 xaLONG xo_scale,yo_scale; /* output scale/image size */
541 {
542   xaLONG ixp,iyp,oxp,oyp;
543 
544   ixp = *xpos; iyp = *ypos;
545 
546   oxp = (ixp * xo_scale) / xi_scale;
547   if ( ((oxp * xi_scale) / xo_scale) < ixp ) oxp++;
548 
549   oyp = (iyp * yo_scale) / yi_scale;
550   if ( ((oyp * yi_scale) / yo_scale) < iyp ) oyp++;
551 
552   *xpos = oxp;		*ypos = oyp;
553 }
554 
555 
556 /*
557  * Function to get Scaling Buffer Coordinates.
558  * 	returns xaTRUE if need to scale while buffering
559  *	returns xaFALSE if you don't
560  *
561  * NOTE: This should only be called within XXX_Read_File or else
562  *       scale isn't guaranteed to be valid.
563  * ACT_Setup_Mapped is okay since it has the same limitations.
564  */
UTIL_Get_Buffer_Scale(width,height,buffx_o,buffy_o)565 xaULONG UTIL_Get_Buffer_Scale(width,height,buffx_o,buffy_o)
566 xaULONG width,height;	 /* width, height of anim */
567 xaULONG *buffx_o,*buffy_o; /* scaled width, height of anim */
568 {
569  xaULONG need_to_scale;
570  xaULONG buff_x,buff_y;
571 
572   /* Figure out buffer scaling */
573   if ( (xa_buff_x != 0) && (xa_buff_y != 0) )
574         { buff_x = xa_buff_x; buff_y = xa_buff_y; }
575   else if (xa_buff_x != 0) /* if just x, then adjust y */
576         { buff_x = xa_buff_x; buff_y = (height * xa_buff_x) / width; }
577   else if (xa_buff_y != 0) /* if just y, then adjust x */
578         { buff_y = xa_buff_y; buff_x = (width * xa_buff_y) / height; }
579   else
580   {
581      /* handle any scaling */
582     buff_x = (xaULONG)((float)(width) * xa_bscalex);
583     if (buff_x == 0) buff_x = width;
584     buff_y = (xaULONG)((float)(height) * xa_bscaley);
585     if (buff_y == 0) buff_y = height;
586   }
587   if ((buff_x != width) || (buff_y != height)) need_to_scale = xaTRUE;
588   else need_to_scale = xaFALSE;
589   *buffx_o = buff_x; *buffy_o = buff_y;
590   return(need_to_scale);
591 }
592 
593 /*
594  * Function to allocate buffer for Scaling
595  *
596  */
UTIL_Alloc_Scaled(xi_size,yi_size,xi_scale,yi_scale,xo_scale,yo_scale,pix_size,xo_pos,yo_pos,bitmap_flag)597 xaUBYTE *UTIL_Alloc_Scaled(xi_size,yi_size,xi_scale,yi_scale,
598 	xo_scale,yo_scale,pix_size,xo_pos,yo_pos,bitmap_flag)
599 xaULONG xi_size,yi_size;   /* size of section */
600 xaULONG xi_scale,yi_scale; /* size of full input image */
601 xaULONG xo_scale,yo_scale; /* size of full output image */
602 xaULONG pix_size;          /* pixel size */
603 xaULONG xo_pos,yo_pos;     /* pos of section in input buffer */
604 xaULONG bitmap_flag;	 /* if true, then alloc for a bitmap */
605 
606 {
607   xaULONG sx,sy,xsize,ysize;
608   xaUBYTE *out;
609 
610   sx = (xo_pos * xo_scale) / xi_scale;
611   if ( ((sx * xi_scale) / xo_scale) < xo_pos ) sx++;
612   xsize = (((xo_pos + xi_size) * xo_scale) / xi_scale) + 1 - sx;
613   if ( (((sx+xsize-1) * xi_scale) / xo_scale) >= (xo_pos+xi_size) ) xsize--;
614 
615   sy = (yo_pos * yo_scale) / yi_scale;
616   if ( ((sy * yi_scale) / yo_scale) < yo_pos ) sy++;
617   ysize = (((yo_pos + yi_size) * yo_scale) / yi_scale) + 1 - sy;
618   if ( (((sy+ysize-1) * yi_scale) / yo_scale) >= (yo_pos+yi_size) ) ysize--;
619 
620   if ( (xsize==0) || (ysize==0) )
621   {
622     DEBUG_LEVEL1 fprintf(stderr,"SCALE: zero size %d %d\n",xsize,ysize);
623     return(0);
624   }
625 
626 DEBUG_LEVEL1 fprintf(stderr,"AllocScaled: xy %d %d  t %d\n",
627   xsize,ysize,(xsize * ysize * pix_size));
628 
629   if (bitmap_flag==xaTRUE)
630   {
631     xaULONG line_size;
632     line_size = X11_Get_Bitmap_Width(xsize) / 8;
633     out = (xaUBYTE *)malloc(line_size * ysize);
634   }
635   else out = (xaUBYTE *)malloc(xsize * ysize * pix_size);
636   if (out==0) TheEnd1("UTIL_Alloc_Scaled: malloc err");
637   return(out);
638 }
639 
640 /*
641  * Function to Scale a Mapped Image
642  *
643  */
UTIL_Scale_Mapped(out,in,xi_pos,yi_pos,xi_size,yi_size,xi_buff_size,xi_scale,yi_scale,xo_scale,yo_scale,pix_size,xo_pos,yo_pos,xo_size,yo_size,chdr)644 xaUBYTE *UTIL_Scale_Mapped(out,in,xi_pos,yi_pos,xi_size,yi_size,
645 	xi_buff_size,xi_scale,yi_scale,xo_scale,yo_scale,pix_size,
646 	xo_pos,yo_pos,xo_size,yo_size,chdr)
647 xaUBYTE *out;		 /* output buffer, if 0 then one is created */
648 xaUBYTE *in;		 /* input image buffer */
649 xaULONG xi_pos,yi_pos;     /* pos of section in input buffer */
650 xaULONG xi_size,yi_size;   /* size of section */
651 xaULONG xi_buff_size;      /* row size of input buffer in bytes */
652 xaULONG xi_scale,yi_scale; /* size of full input image */
653 xaULONG xo_scale,yo_scale; /* size of full output image */
654 xaULONG pix_size;		 /* pixel size */
655 xaULONG *xo_pos,*yo_pos;   /* I screen pos/O pos of section in output buffer */
656 xaULONG *xo_size,*yo_size; /* O size of outgoing section */
657 XA_CHDR *chdr;
658 /* note: pos of section in output buffer is always 0,0 */
659 {
660   xaULONG i,y,sx,sy,xvp,yvp,xsize,ysize,xoff;
661 
662 
663   xvp = *xo_pos; yvp = *yo_pos;
664   sx = (xvp * xo_scale) / xi_scale;
665   if ( ((sx * xi_scale) / xo_scale) < xvp ) sx++;
666   xsize = (((xvp + xi_size) * xo_scale) / xi_scale) + 1 - sx;
667   if ( (((sx+xsize-1) * xi_scale) / xo_scale) >= (xvp+xi_size) ) xsize--;
668 
669   sy = (yvp * yo_scale) / yi_scale;
670   if ( ((sy * yi_scale) / yo_scale) < yvp ) sy++;
671   ysize = (((yvp + yi_size) * yo_scale) / yi_scale) + 1 - sy;
672   if ( (((sy+ysize-1) * yi_scale) / yo_scale) >= (yvp+yi_size) ) ysize--;
673 
674   xoff = xvp - xi_pos;
675   if ( (xsize==0) || (ysize==0) )
676   {
677     DEBUG_LEVEL1 fprintf(stderr,"SCALE: zero size %d %d\n",xsize,ysize);
678     *xo_pos = *yo_pos = *xo_size = *yo_size = 0;
679     return(0);
680   }
681 
682   /* use scale buffer if necessary */
683   if (out == 0)
684   {
685     xaULONG tsize = xsize * ysize * pix_size;
686     XA_REALLOC(xa_scale_buff,xa_scale_buff_size,tsize);
687     out = (xaUBYTE *)xa_scale_buff;
688   }
689 
690   /* readjust row cache buffer if necessary */
691   if (xsize > xa_scale_row_size)
692   {
693     xaULONG *tmp;
694     if (xa_scale_row_buff == 0) tmp = (xaULONG *) malloc(xsize * sizeof(xaULONG) );
695     else tmp = (xaULONG *) realloc(xa_scale_row_buff, xsize * sizeof(xaULONG) );
696     if (tmp == 0) TheEnd1("UTIL_Scale_Mapped: row malloc err\n");
697     xa_scale_row_buff = tmp;	xa_scale_row_size = xsize;
698   }
699 
700   y = sx; for(i = 0; i < xsize; i++,y++)
701 	xa_scale_row_buff[i] = ((y * xi_scale) / xo_scale ) - xoff;
702 
703   if (chdr==0) /* no mapping */
704   {
705     register xaULONG x,yoff;
706     yoff = yvp - yi_pos;
707     if (pix_size == 4)
708     {
709       register xaULONG *optr = (xaULONG *)out;
710       for(y=sy; y< (sy + ysize); y++)
711       { register xaULONG *in_r_ptr =
712 		(xaULONG *)(in+(((y*yi_scale)/yo_scale)-yoff)*xi_buff_size);
713         for(x = 0; x < xsize; x++) *optr++ = in_r_ptr[ xa_scale_row_buff[x] ];
714       }
715     }
716     else if (pix_size == 2)
717     {
718       register xaUSHORT *optr = (xaUSHORT *)out;
719       for(y=sy; y< (sy + ysize); y++)
720       { register xaUSHORT *in_r_ptr =
721 		(xaUSHORT *)(in+(((y*yi_scale)/yo_scale)-yoff)*xi_buff_size);
722         for(x = 0; x < xsize; x++) *optr++ = in_r_ptr[ xa_scale_row_buff[x] ];
723       }
724     }
725     else
726     {
727       register xaUBYTE *optr = (xaUBYTE *)out;
728       for(y=sy; y< (sy + ysize); y++)
729       { register xaUBYTE *in_r_ptr =
730 		(xaUBYTE *)(in+(((y*yi_scale)/yo_scale)-yoff)*xi_buff_size);
731         for(x = 0; x < xsize; x++) *optr++ = in_r_ptr[ xa_scale_row_buff[x] ];
732       }
733     }
734   }
735   else /* remap as we scale */
736   {
737     register xaULONG x,yoff,moff,*map;
738     map  = chdr->map; moff = chdr->moff; yoff = yvp - yi_pos;
739     if (pix_size == 4)
740     {
741       register xaULONG *optr = (xaULONG *)out;
742       for(y=sy; y< (sy + ysize); y++)
743       { register xaUBYTE *in_r_ptr =
744 		(xaUBYTE *)(in+(((y*yi_scale)/yo_scale)-yoff)*xi_buff_size);
745 	if (moff) for(x = 0; x < xsize; x++)
746 		*optr++ = (xaULONG)map[in_r_ptr[ xa_scale_row_buff[x]]-moff];
747 	else for(x = 0; x < xsize; x++)
748 		*optr++ = (xaULONG)map[in_r_ptr[ xa_scale_row_buff[x]]];
749       }
750     }
751     else if (pix_size == 2)
752     {
753       register xaUSHORT *optr = (xaUSHORT *)out;
754       for(y=sy; y< (sy + ysize); y++)
755       { register xaUBYTE *in_r_ptr =
756 		(xaUBYTE *)(in+(((y*yi_scale)/yo_scale)-yoff)*xi_buff_size);
757 	if (moff) for(x = 0; x < xsize; x++)
758 		*optr++ = (xaUSHORT)map[in_r_ptr[ xa_scale_row_buff[x]]-moff];
759 	else for(x = 0; x < xsize; x++)
760 		*optr++ = (xaUSHORT)map[in_r_ptr[ xa_scale_row_buff[x]]];
761       }
762     }
763     else
764     {
765       register xaUBYTE *optr = (xaUBYTE *)out;
766       for(y=sy; y< (sy + ysize); y++)
767       { register xaUBYTE *in_r_ptr =
768 		(xaUBYTE *)(in+(((y*yi_scale)/yo_scale)-yoff)*xi_buff_size);
769 	if (moff) for(x = 0; x < xsize; x++)
770 		*optr++ = (xaUBYTE)map[in_r_ptr[ xa_scale_row_buff[x]]-moff];
771 	else for(x = 0; x < xsize; x++)
772 		*optr++ = (xaUBYTE)map[in_r_ptr[ xa_scale_row_buff[x]]];
773       }
774     }
775   }
776   *yo_pos = sy; *yo_size = ysize;
777   *xo_pos = sx; *xo_size = xsize;
778   return(out);
779 }
780 
781 
782 /*
783  * for now assum xi_pos=yi_pos=0 and size are multiple of 8s
784  *
785  */
UTIL_Scale_Bitmap(out,in,xi_size,yi_size,xi_line_size,xi_scale,yi_scale,xo_scale,yo_scale,xo_pos,yo_pos,xo_size,yo_size,ibit_order,obit_order)786 xaUBYTE *UTIL_Scale_Bitmap(out,in,xi_size,yi_size,
787 	xi_line_size,xi_scale,yi_scale,xo_scale,yo_scale,
788 	xo_pos,yo_pos,xo_size,yo_size,ibit_order,obit_order)
789 xaUBYTE *out,*in;
790 xaULONG xi_size,yi_size;   /* size of section */
791 xaULONG xi_line_size;      /* row size of input buffer in bytes*/
792 xaULONG xi_scale,yi_scale; /* size of full input image */
793 xaULONG xo_scale,yo_scale; /* size of full output image */
794 xaULONG *xo_pos,*yo_pos;   /* pos of section in input/output buffer */
795 xaULONG *xo_size,*yo_size; /* size of outgoing section */
796 xaULONG ibit_order;	 /* input bit_order */
797 xaULONG obit_order;	 /* output bit_order */
798 {
799   xaULONG xo_line_size;
800   xaULONG i,y,sx,sy,xvp,yvp,xsize,ysize;
801   xaULONG *row_b_ptr;
802   xaUBYTE *row_msk_ptr,mask_start,mask_end;
803 
804   xvp = *xo_pos; yvp = *yo_pos;
805   sx = (xvp * xo_scale) / xi_scale;
806   if ( ((sx * xi_scale) / xo_scale) < xvp ) sx++;
807   xsize = (((xvp + xi_size) * xo_scale) / xi_scale) + 1 - sx;
808   if ( (((sx+xsize-1) * xi_scale) / xo_scale) >= (xvp+xi_size) ) xsize--;
809 
810   sy = (yvp * yo_scale) / yi_scale;
811   if ( ((sy * yi_scale) / yo_scale) < yvp ) sy++;
812   ysize = (((yvp + yi_size) * yo_scale) / yi_scale) + 1 - sy;
813   if ( (((sy+ysize-1) * yi_scale) / yo_scale) >= (yvp+yi_size) ) ysize--;
814 
815 DEBUG_LEVEL1 fprintf(stderr,"SCALE BITMAP: siz %dx%d -> %dx%d\n",
816 	xi_size,yi_size,xsize,ysize);
817 DEBUG_LEVEL1 fprintf(stderr,"SCALE BITMAP: pos %dx%d -> %dx%d\n",
818 	xvp,yvp,sx,sy);
819 
820   if ( (xsize==0) || (ysize==0) )
821   {
822     DEBUG_LEVEL1 fprintf(stderr,"SCALE: zero size %d %d\n",xsize,ysize);
823     *xo_size = *yo_size = 0;
824     return(0);
825   }
826   xo_line_size = X11_Get_Bitmap_Width(xsize) / 8;
827   /* use scale buffer if necessary */
828   if (out == 0)
829   {
830     xaULONG tsize = ysize * xo_line_size;
831     XA_REALLOC(xa_scale_buff,xa_scale_buff_size,tsize);
832     out = (xaUBYTE *)xa_scale_buff;
833   }
834 
835   /* readjust row cache buffer if necessary */
836   if ( (xsize<<1) > xa_scale_row_size)
837   {
838     xaULONG *tmp;
839     if (xa_scale_row_buff == 0)
840 	tmp = (xaULONG *) malloc((xsize<<1) * sizeof(xaULONG) );
841     else
842 	tmp = (xaULONG *) realloc(xa_scale_row_buff,(xsize<<1)*sizeof(xaULONG));
843     if (tmp == 0) TheEnd1("UTIL_Scale_Mapped: row malloc err\n");
844     xa_scale_row_buff = tmp;    xa_scale_row_size = (xsize<<1);
845   }
846   row_b_ptr = xa_scale_row_buff;
847   row_msk_ptr = (xaUBYTE *)&xa_scale_row_buff[xsize];
848 
849   y = sx;
850   for(i = 0; i < xsize; i++,y++)
851   {
852     register xaULONG x = ((y * xi_scale) / xo_scale) - xvp;
853     row_b_ptr[i] = x/8;
854     if (ibit_order == XA_LSBIT_1ST) row_msk_ptr[i] = 0x01 << (x%8);
855     else row_msk_ptr[i] = 0x01 << (7 - (x%8));
856   }
857   if (obit_order == XA_MSBIT_1ST) { mask_start = 0x80; mask_end = 0x01; }
858   else { mask_start = 0x01; mask_end = 0x80; }
859   for(y=sy; y < (sy+ysize);y++)
860   {
861     register xaULONG x;
862     register xaUBYTE omsk,odat;
863     register xaUBYTE *iptr,*optr;
864     iptr = (xaUBYTE *)(in + (((y * yi_scale) / yo_scale)-yvp) * xi_line_size);
865     optr = (xaUBYTE *)(out + ((y - sy) * xo_line_size));
866     omsk = mask_start; odat = 0;
867     for(x=0; x<xsize; x++)
868     {
869       if ( iptr[ row_b_ptr[x] ] & row_msk_ptr[x] ) odat |= omsk;
870       if (omsk == mask_end) { *optr++ = odat; omsk = mask_start; odat = 0; }
871       else if (mask_start == 0x01) omsk <<= 1; else omsk >>= 1;
872     }
873     if (omsk) *optr++ = odat;
874   }
875   *xo_pos = sx;     *yo_pos = sy;
876   *xo_size = xsize; *yo_size = ysize;
877   return(out);
878 }
879 
880 /**********************
881  * UTIL_RGB_To_Map
882  *
883  **********************/
UTIL_RGB_To_Map(out,in,chdr,xsize,ysize,free_in_flag)884 xaUBYTE *UTIL_RGB_To_Map(out,in,chdr,xsize,ysize,free_in_flag)
885 xaUBYTE *out,*in;
886 XA_CHDR *chdr;
887 xaULONG xsize,ysize;
888 xaULONG free_in_flag;
889 {
890   xaULONG i,shift_r,shift_g,shift_b,pic_size;
891   xaUBYTE *t_pic,*iptr,*optr;
892   xaULONG csize,coff;
893 
894   DEBUG_LEVEL1 fprintf(stderr,"UTIL_RGB_To_Map\n");
895   pic_size = xsize * ysize;
896   if (out == 0)
897   {
898     t_pic = (xaUBYTE *)malloc( XA_PIC_SIZE(pic_size) );
899     if (t_pic == 0) TheEnd1("RGB: t_pic malloc err");
900   } else t_pic = out;
901 
902   if (cmap_cache == 0) CMAP_Cache_Init(0);
903   if (chdr != cmap_cache_chdr)
904   {
905     DEBUG_LEVEL2 fprintf(stderr,"CACHE: clear new_chdr %x\n",
906                                                         (xaULONG)chdr);
907     CMAP_Cache_Clear();
908     cmap_cache_chdr = chdr;
909   }
910   shift_r = 3 * cmap_cache_bits;
911   shift_g = 2 * cmap_cache_bits;
912   shift_b = cmap_cache_bits;
913 
914 
915   csize = chdr->csize;
916   coff = chdr->coff;
917   iptr = in;
918   optr = t_pic;
919   for(i=0; i < pic_size; i++)
920   {
921     register xaULONG color_out,r,g,b;
922     register xaULONG cache_i;
923 
924     r = (xaULONG)(*iptr++); g = (xaULONG)(*iptr++); b = (xaULONG)(*iptr++);
925     cache_i  = (xaULONG)(  (  ( (r << shift_r) & cmap_cache_rmask)
926                           | ( (g << shift_g) & cmap_cache_gmask)
927                           | ( (b << shift_b) & cmap_cache_bmask)
928                          ) >> 8);
929     if (cmap_cache[cache_i] == 0xffff)
930     {
931       color_out = coff +
932                 CMAP_Find_Closest(chdr->cmap,csize,r,g,b,8,8,8,xaTRUE);
933       cmap_cache[cache_i] = (xaUSHORT)color_out;
934     }
935     else color_out = (xaULONG)cmap_cache[cache_i];
936 
937     *optr++ = (xaUBYTE)(color_out);
938 
939   }
940   if (free_in_flag == xaTRUE) FREE(in,0x304); in=0;
941   return(t_pic);
942 }
943 
944 /**********************
945  *
946  **********************/
UTIL_RGB_To_FS_Map(out,in,chdr,xsize,ysize,free_in_flag)947 xaUBYTE *UTIL_RGB_To_FS_Map(out,in,chdr,xsize,ysize,free_in_flag)
948 xaUBYTE *out,*in;
949 XA_CHDR *chdr;
950 xaULONG xsize,ysize;
951 xaULONG free_in_flag;
952 {
953   xaULONG flag,csize,xsize3;
954   ColorReg *cmap;
955   register xaULONG x,y;
956   xaULONG shift_r,shift_g,shift_b,coff;
957   xaSHORT *err_buff0, *err_buff1, *e_ptr, *ne_ptr;
958   xaSHORT r_err,g_err,b_err;
959   xaUBYTE *o_ptr,*tpic;
960 
961   DEBUG_LEVEL1 fprintf(stderr,"UTIL_RGB_To_FS_Map\n");
962 
963   if (out == 0)
964   {
965     tpic = (xaUBYTE *)malloc( XA_PIC_SIZE(xsize * ysize) );
966     if (tpic == 0) TheEnd1("UTIL_RGB_To_FS_Map: malloc err");
967   } else tpic = out;
968 
969   if (cmap_cache == 0) CMAP_Cache_Init(0);
970 
971   if (chdr != cmap_cache_chdr)
972   {
973     DEBUG_LEVEL2 fprintf(stderr,"CACHE: clear new_chdr %x\n",(xaULONG)chdr);
974     CMAP_Cache_Clear();
975     cmap_cache_chdr = chdr;
976   }
977   shift_r = 3 * cmap_cache_bits;
978   shift_g = 2 * cmap_cache_bits;
979   shift_b = cmap_cache_bits;
980 
981   csize = chdr->csize;
982   cmap = chdr->cmap;
983   coff = chdr->coff;
984 
985   /* allocate error buffer and set up pointers */
986   xsize3 = xsize * 3;
987   e_ptr = err_buff0 = (xaSHORT *)malloc(6 * xsize * sizeof(xaSHORT) );
988   if (err_buff0 == 0) TheEnd1("UTIL_Mapped_To_Floyd: malloc err");
989   err_buff1 = &err_buff0[xsize3];
990   flag = 0;
991 
992   {
993     register xaUBYTE *i_ptr = (xaUBYTE *)( in + (xsize3 * (ysize-1)));
994     x = xsize; while(x--)
995     {
996       *e_ptr++ = (xaUSHORT)(*i_ptr++) << 4;
997       *e_ptr++ = (xaUSHORT)(*i_ptr++) << 4;
998       *e_ptr++ = (xaUSHORT)(*i_ptr++) << 4;
999     }
1000   }
1001 
1002   y = ysize; while(y--)
1003   {
1004     o_ptr = (xaUBYTE *)(tpic + (xsize * y));
1005     if (flag) { e_ptr = err_buff1; ne_ptr = err_buff0; flag = 0; }
1006     else      { e_ptr = err_buff0; ne_ptr = err_buff1; flag = 1; }
1007     if (y > 0)
1008     {
1009       register xaSHORT *tptr = ne_ptr;
1010       register xaUBYTE *i_ptr = (xaUBYTE *)(in + (xsize3 * (y-1)));
1011       x = xsize; while(x--)
1012       {
1013 	*tptr++ = (xaUSHORT)(*i_ptr++) << 4;
1014 	*tptr++ = (xaUSHORT)(*i_ptr++) << 4;
1015 	*tptr++ = (xaUSHORT)(*i_ptr++) << 4;
1016       }
1017     }
1018 
1019     x = xsize; while(x--)
1020     {
1021       xaULONG color_out;
1022       register xaSHORT r,g,b;
1023       register xaULONG cache_i;
1024 
1025       r = (*e_ptr++)/16; if (r<0) r = 0; else if (r>255) r = 255;
1026       g = (*e_ptr++)/16; if (g<0) g = 0; else if (g>255) g = 255;
1027       b = (*e_ptr++)/16; if (b<0) b = 0; else if (b>255) b = 255;
1028 
1029       cache_i = (  ( (r << shift_r) & cmap_cache_rmask)
1030                  | ( (g << shift_g) & cmap_cache_gmask)
1031                  | ( (b << shift_b) & cmap_cache_bmask) ) >> 8;
1032 
1033       if (cmap_cache[cache_i] == 0xffff)
1034       {
1035         color_out = CMAP_Find_Closest(cmap,csize,r,g,b,8,8,8,xaTRUE);
1036         cmap_cache[cache_i] = (xaSHORT)color_out;
1037       }
1038       else color_out = (xaULONG)cmap_cache[cache_i];
1039 
1040       *o_ptr++ = (xaUBYTE)(color_out + coff);
1041 
1042       r_err = r - (xaSHORT)(cmap[color_out].red >> 8);
1043       g_err = g - (xaSHORT)(cmap[color_out].green >> 8);
1044       b_err = b - (xaSHORT)(cmap[color_out].blue >> 8);
1045 
1046       if (x)
1047       {
1048 	*e_ptr   += 7 * r_err;
1049 	e_ptr[1] += 7 * g_err;
1050 	e_ptr[2] += 7 * b_err;
1051       }
1052       if (y)
1053       {
1054         if (x < (xsize-1) ) /* not 1st of line */
1055 	{
1056 	  *ne_ptr++ += 3 * r_err;
1057 	  *ne_ptr++ += 3 * g_err;
1058 	  *ne_ptr++ += 3 * b_err;
1059 	}
1060         *ne_ptr   += 5 * r_err;
1061         ne_ptr[1] += 5 * g_err;
1062         ne_ptr[2] += 5 * b_err;
1063         if (x)
1064         {
1065 	  ne_ptr[3] += r_err;
1066 	  ne_ptr[4] += g_err;
1067 	  ne_ptr[5] += b_err;
1068 	}
1069       }
1070     } /* end of x */
1071   } /* end of y */
1072   if (err_buff0) { FREE(err_buff0,0x305); err_buff0=0; }
1073   if (free_in_flag == xaTRUE) FREE(in,0x306);
1074   return(tpic);
1075 }
1076 
1077 void
UTIL_Pack_Image(out,in,xsize,ysize)1078 UTIL_Pack_Image(out,in,xsize,ysize)
1079 xaUBYTE *out;
1080 xaUBYTE *in;
1081 xaULONG xsize,ysize;
1082 {
1083   xaUBYTE *o_ptr;
1084   xaULONG x,y,shft_msk;
1085   xaLONG shft_start,shft_end,shft_inc;
1086 
1087   if (x11_bits_per_pixel == 4)
1088   { shft_msk = 0x0f;
1089     if (x11_byte_order == XA_MSBIT_1ST)
1090 			{shft_start=4; shft_end=0; shft_inc= -4;}
1091     else		{shft_start=0; shft_end=4; shft_inc=  4;}
1092   }
1093   else if (x11_bits_per_pixel == 2)
1094   { shft_msk = 0x03;
1095     if (x11_byte_order == XA_MSBIT_1ST)
1096 			{shft_start=6; shft_end=0; shft_inc= -2;}
1097     else		{shft_start=0; shft_end=6; shft_inc=  2;}
1098   }
1099   else /* unsupported depth */
1100   {
1101     fprintf(stderr,"X11 Packing of bits %d to depth %d not yet supported\n",
1102 	x11_bits_per_pixel,x11_depth);
1103     return;
1104   }
1105 
1106   o_ptr = out;
1107   for(y=0;y<ysize;y++)
1108   { register xaULONG data = 0;
1109     register xaLONG shft  = shft_start;
1110     for(x=0; x<xsize; x++)
1111     {
1112 	if (shft != shft_end) /* still creating byte */
1113 	{ data |= ((*in++) & shft_msk) << shft;
1114 	  shft += shft_inc;
1115 	}
1116 	else /* at the end */
1117 	{
1118 	  *o_ptr++ = data | (((*in++) & shft_msk) << shft);
1119 	  shft = shft_start;
1120 	  data = 0;
1121 	}
1122     }
1123     if (shft != shft_start) *o_ptr++ = data; /* partial byte */
1124   } /* end of y loop */
1125 }
1126 
1127 /**************************
1128  *
1129  * Convert frames per second into vid_time(ms)
1130  * and vid_timelo(fractional ms).
1131  *
1132  * Global Variable: xa_jiffy_flag   non-zero then IS ms to use.
1133  ***********************/
UTIL_FPS_2_Time(anim,fps)1134 void UTIL_FPS_2_Time(anim,fps)
1135 XA_ANIM_SETUP *anim;
1136 double fps;
1137 {
1138   if (xa_jiffy_flag) { anim->vid_time = xa_jiffy_flag; anim->vid_timelo = 0; }
1139   { double ptime = (double)(1000.0) / fps;
1140     anim->vid_time = (xaULONG)(ptime);
1141     ptime -= (double)(anim->vid_time);
1142     anim->vid_timelo = (xaULONG)(ptime * (double)(1<<24));
1143   }
1144 }
1145 
1146 /**************************
1147  * Index
1148  * Searches string "s" for character "c" starting at the
1149  * beginning of the string.
1150  **************************/
XA_index(s,c)1151 char *XA_index(s,c)
1152 char *s,c;
1153 { int len;
1154   char *p = s;
1155 
1156   if (s == (char *)(NULL)) return((char *)(NULL));
1157   len = strlen(s);
1158   while(len >= 0)
1159   { if (*p == c) return(p);
1160     else {p++; len--;}
1161   }
1162   return( (char *)(NULL) );
1163 }
1164 
1165 /**************************
1166  * Reverse Index
1167  * Searches string "s" for character "c" starting at the
1168  * end of the string.
1169  **************************/
XA_rindex(s,c)1170 char *XA_rindex(s,c)
1171 char *s,c;
1172 { int len;
1173   char *p = s;
1174 
1175   if (c == 0) return((char *)(NULL));
1176   if (s == (char *)(NULL)) return((char *)(NULL));
1177   len = strlen(s);
1178   p += len;
1179   while(len >= 0)
1180   { if (*p == c) return(p);
1181     else {p--; len--;}
1182   }
1183   return( (char *)(NULL) );
1184 }
1185 
1186 /**************************
1187  * Return xaTRUE is key is inside s, else return xaFALSE
1188  **************************/
XA_find_str(s,key)1189 xaULONG XA_find_str(s,key)
1190 char *s, *key;
1191 { xaULONG key_len;
1192   char first = *key;
1193   char *tmp_s = s;
1194 
1195   if (key == 0) return(xaFALSE);
1196   key_len = strlen(key);
1197   while(s)
1198   { tmp_s = XA_index(s,first);
1199     if (tmp_s)
1200     {
1201       if (strncmp(tmp_s,key,key_len) == 0) return(xaTRUE);
1202       s = tmp_s; s++;
1203     }
1204     else break;
1205   }
1206   return(xaFALSE);
1207 }
1208 
1209 /****----------------------------------------------------------------****
1210  *
1211  ****----------------------------------------------------------------****/
XA_white_out(s)1212 char *XA_white_out(s)
1213 char *s;
1214 { char *tp;
1215   if ((s==0) || (*s==0)) return( (char *)(0) );
1216 
1217 	/* strip white space off the end */
1218   tp = &s[ strlen(s) - 1 ];
1219   while((tp != s) && isspace((int)(*tp))) { *tp = 0; tp--; }
1220 
1221 	/* strip white space from the front */
1222   tp = s;
1223   while( *tp && isspace((int)(*tp))) { tp++; }
1224   return(tp);
1225 }
1226 
1227 /****----------------------------------------------------------------****
1228  * Print out a string, indenting with "indent" if there is an embedded
1229  * newline.
1230  ****----------------------------------------------------------------****/
XA_Indent_Print(fout,indent,s,first)1231 void XA_Indent_Print(fout, indent, s, first)
1232 FILE	*fout;
1233 char	*indent;
1234 char	*s;
1235 int	first;
1236 { char *p = s;
1237   int ret = 0;
1238   if (first) fprintf(fout,"%s",indent);
1239   while( p && *p)
1240   { fputc( (int)(*p), fout);
1241     ret = (*p =='\n')?(1):(0);
1242     p++;
1243     if (ret && (p[1] != 0)) fprintf(fout,"%s",indent);
1244   }
1245   if (ret == 0) fprintf(fout,"\n");
1246 }
1247 
1248 
1249 
1250