# include "Ximage.h"

void CreateZoom32 (KapaImageWidget *image, Graphic *graphic, double x, double y) {

  int i, j, ii, jj;
  int i_start, i_end, j_start, j_end;
  int dropback;  /* this is a bit of a kludge... */
  int dx, dy, DX, DY;
  double expand, Ix, Iy;
  int expand_in, expand_out;
  unsigned int *out_pix, *out_pix2;
  unsigned short *in_pix, *in_pix2;
  unsigned long *pixel, pixvalue;
  unsigned long back;

  if (image[0].image[0].matrix.size == 0) {  /* create a test pattern */
    REALLOCATE (image[0].zoom.data, char, 4*image[0].zoom.dx*image[0].zoom.dy);
    image[0].zoom.pix = XCreateImage (graphic[0].display, graphic[0].visual, graphic[0].depth, ZPixmap, 0, 
				       image[0].zoom.data, image[0].zoom.dx, image[0].zoom.dy, 32, 0);
    return;
  }

  ALLOCATE (pixel, unsigned long, graphic[0].Npixels);

  // local array for pixel values
  for (i = 0; i < graphic[0].Npixels; i++) { 
    pixel[i] = graphic[0].cmap[i].pixel;
  }
  back = graphic[0].back;

  // set up expansions
  assert ((image[0].zoom.expand >= 1) || (image[0].zoom.expand <= -2));
  expand = expand_in = expand_out = 1.0;
  if (image[0].zoom.expand > 0) {
    expand = 1 / (1.0*image[0].zoom.expand);
    expand_out = image[0].zoom.expand;
    expand_in  = 1;
  }
  if (image[0].zoom.expand < 0) {
    expand = fabs((double)image[0].zoom.expand);
    expand_out = 1;
    expand_in  = -image[0].zoom.expand;
  }

  // define the image sizes
  dx = image[0].zoom.dx;
  dy = image[0].zoom.dy;
  DX = image[0].image[0].matrix.Naxis[0];
  DY = image[0].image[0].matrix.Naxis[1];
  
  // x, y are the closest lit screen pixel to 0,0
  Picture_Lower (&i_start, &j_start, &image[0].image[0].matrix, &image[0].zoom);

  // x, y are the closest lit screen pixel to dx, dy
  Picture_Upper (&i_end, &j_end, &image[0].image[0].matrix, &image[0].zoom);

  // Ix,Iy are the first displayed image pixel
  Picture_to_Image (&Ix, &Iy, i_start, j_start, &image[0].zoom);

  dropback = expand_out - (i_end - i_start) % expand_out;
  if ((i_end - i_start) % expand_out == 0) dropback = 0;

  out_pix = (unsigned int *) image[0].zoom.data;
  in_pix  = &image[0].pixmap[DX*(int)MAX(Iy,0) + (int)MAX(Ix,0)];

  /********** below we do the mapping from buffer pixels (in) to picture pixels (out) **********/

  // XXX can we just drop this?
  if ((i_end < i_start) || (j_end < j_start)) {
    for (j = 0; j < dx*dy; j++, out_pix++) 
      *out_pix = back;
    return;
  } 

  /**** fill in bottom area ****/
  for (j = 0; j < dx*j_start; j++, out_pix++) {
    *out_pix = back;
  }

  for (j = j_start; j < j_end; j+= expand_out, out_pix+=(expand_out-1)*dx, in_pix += expand_in*DX) {

    /**** fill in area to the left of the picture ****/
    for (jj = 0; (i_start > 0) && (jj < expand_out); jj++) { 
      out_pix2 = out_pix + jj*dx;
      for (i = 0; i < i_start; i++, out_pix2++) {
	*out_pix2 = back;
      }
    }
    out_pix += i_start;
    
    /*** fill in the picture region ***/
    in_pix2 = in_pix;
    if (expand_out == 1) {
      for (i = i_start; i < i_end; i++, in_pix2+= expand_in, out_pix++) {
	*out_pix = pixel[*in_pix2];
      }
    } else {
      // equiv to : out_pix += (i_end - i_start) + [expand_out - (i_end - i_start) % expand_out]
      for (i = i_start; i < i_end; i+= expand_out, in_pix2++, out_pix+= expand_out) { 
	pixvalue = pixel[*in_pix2];
	out_pix2 = out_pix;
	for (jj = 0; jj < expand_out; jj++, out_pix2+=(dx-expand_out)) {
	  for (ii = 0; ii < expand_out; ii++, out_pix2++) {
	    *out_pix2 = pixvalue; 
	  }
	}
      }
    }
    out_pix -= dropback;
    
    /**** fill in area to the right of the picture ****/
    for (jj = 0; jj < expand_out; jj++) {
      out_pix2 = out_pix + jj*dx;
      for (i = i_end; i < dx; i++, out_pix2++) {
	*out_pix2 = back;
      }
    }
    out_pix += (dx - i_end);
    assert (out_pix - (unsigned int *)image[0].zoom.data <= dx*dy);
  } 
  assert (out_pix - (unsigned int *)image[0].zoom.data <= dx*dy);
  
  if ((j_end - j_start) % expand_out > 0)
    out_pix -= (expand_out - (j_end - j_start) % expand_out);
  
  assert (out_pix - (unsigned int *)image[0].zoom.data <= dx*dy);

  /**** fill in top area ****/
  for (j = 0; (j < dx*(dy - j_end)) && (out_pix - (unsigned int *)image[0].zoom.data < dx*dy); j++, out_pix++) { 
    *out_pix = back;
  }
  assert (out_pix - (unsigned int *)image[0].zoom.data <= dx*dy);

  image[0].zoom.pix = XCreateImage (graphic[0].display, graphic[0].visual, graphic[0].depth, ZPixmap, 0, 
					image[0].zoom.data, image[0].zoom.dx, image[0].zoom.dy, 32, 0);
  
  free (pixel);
}
