static char *sccs_id= (sccs_id, "@(#)RastShape.c	1.2 7/28/92");

/*
 * This file implements a GeoShape which draws raster maps which
 * are created with the raster/makemaps script.
 */

#include "Class.h"
#include "IconShape.h"
#include "OverView.h"


class RastShape: public QueryShape {
  int	size_x, size_y;
  byte	*ba;
  byte	*newba;
  // Bitmap *bm;
public:
  RastShape(MapView *, int n, char **str);
  ~RastShape() {
    SafeDelete(ba);
    SafeDelete(newba);
    // SafeDelete(bm);
  }

  void Draw();
};


extern "C" RastShape *make_rast_shape();

RastShape *make_rast_shape(MapView *dv, int n, char **str)
{
  RastShape *s= new RastShape(dv, n, str);
  return s;
}


RastShape::RastShape(MapView *d, int n, char **str): (d)
{
  if (n != 4) {
    fprintf(stderr, "RastShape: bad number of arguments: %d", n);
    return;
  }

  float p1_x, p1_y, p2_x, p2_y;
  if (sscanf(str[2], "(%f,%f,%f,%f)", &p1_x, &p1_y, &p2_x, &p2_y) != 4) {
    fprintf(stderr, "RastShape: bad bbox !\n");
    return;
  }

  size_x= atoi(str[0]);
  size_y= atoi(str[1]);

  int size= size_x * size_y;
  ba= new byte[size];
  bcopy(str[3], ba, size);

  labelpos= d->GeoToPoint(p2_x, p2_y);
  SetBBox(NormRect(d->GeoToPoint(p1_x, p1_y), d->GeoToPoint(p2_x, p2_y)));
}

#define	START_COL	64
#define	MAX_COL		64

#define	OFFSET		(' ')


void RastShape::Draw()
{
  if (!size_x || bbox.extent.y == 0 || bbox.extent.x == 0)
    return;

  float	pw;
  float	ph;

  if (!newba) {
    pw= bbox.extent.x/float(size_x);
    ph= bbox.extent.y/float(size_y);
  }

  static bool	init_colors;
  static int	col_lookup[MAX_COL];

  if (!init_colors) {
      init_colors= TRUE;

      fprintf(stderr, "Initialising color palette...\n");
      // Rectangle r(bbox.origin.x, bbox.origin.y, 1, 1);
      for (int c= 0; c < MAX_COL; c++) {
	Ink *i;
        GrPaintRect(bbox, i= GetInk(START_COL + c));
	col_lookup[c]= i->GetId();
      }
  }

  if (newba || pw < 1 || ph < 1) {

    register int	xi, yi;
    register byte	*np;

    if (newba == 0) {

      int			odd= (bbox.extent.x & 0x1);

      float			maxx= float(size_x)/bbox.extent.x;
      float			maxy= float(size_y)/bbox.extent.y;
      int			maxxrnd= int(maxx+0.5);
      int			maxyrnd= int(maxy+0.5);
      int			x, y;
      int			cnt[MAX_COL];
      register byte		*p;

      np= newba= new byte[(bbox.extent.x + odd) * bbox.extent.y];

      for (y= 0; y < bbox.extent.y; y++) {
        for (x= 0; x < bbox.extent.x; x++) {

	  int colcnt= 0, maxcol= -1;
          bzero(cnt, sizeof(cnt));

	  for (yi= 0; yi < maxyrnd; yi++) {
	    p= ba + ((int)(y*maxy)+yi)*size_x + (int)(x*maxx);
            for (xi= 0; xi < maxxrnd; xi++, p++) {
	      int ind= *p - OFFSET;
	      if (ind >= MAX_COL)
		fprintf(stderr, "Illegal raster color number: %d\n", ind);
	      else
	        cnt[ind]++;
	    }
	  }

	  for (int i= 0; i < MAX_COL; i++) {
	    if (cnt[i] > maxcol) {
	      maxcol= cnt[i];
	      colcnt= i;
	    }
	  }

	  *np++= col_lookup[colcnt];
        }

	if (odd)
		np++;

      }

      SafeDelete(ba);
    }

    Bitmap *bm= new Bitmap(bbox.extent, (u_short*) newba, 8);
    GrShowBitMap(bbox, bm);
    delete bm;

  } else {

    int		pwround= int(pw+0.999);
    int		phround= int(ph+0.999);

    float	xstart= bbox.origin.x+0.5;
    float	ystart= bbox.origin.y+0.5;

    float	x, y;
    int		xi, yi;
    byte	*p= ba;

    if (bbox.extent.x/size_x > 4 || bbox.extent.y/size_y > 4) {

     for (y= ystart, yi= 0; yi < size_y; y+= ph, yi++) {
      for (x= xstart, xi= 0; xi < size_x; x+= pw, xi++) {
        Rectangle r(int(x),int(y),pwround,phround);

        GrPaintRect(r, GetInk(*p - OFFSET + START_COL));
        p++;
      }
     }

    } else {

     int odd= (bbox.extent.x & 0x1);

     // byte	*data= new byte[(bbox.extent.x + odd) * bbox.extent.y];
     byte	*data= new byte[(bbox.extent.x + odd + 1) * (bbox.extent.y+1)];
     byte	*p= ba;

     for (y= 0, yi= 0; yi < size_y; y+= ph, yi++) {
      for (x= 0, xi= 0; xi < size_x; x+= pw, xi++) {
	byte col= col_lookup[*p++ - OFFSET];
	register byte *p2= data + int(y) * (bbox.extent.x + odd) + int(x);
	for (register int yj= 0; yj < phround; yj++, p2+= bbox.extent.x + odd) {
	  for (register int xj= 0; xj < pwround; xj++) {
	    p2[xj]= col;
	  }
	}
      }
     }

     Bitmap *bm= new Bitmap(bbox.extent, (u_short*) data, 8);
     GrShowBitMap(bbox, bm);
     delete bm;
     delete data;
    }
  }
}
