/*
 * 5799-CGZ (C) COPYRIGHT IBM CORPORATION 1986,1987
 * LICENSED MATERIALS - PROPERTY OF IBM
 * REFER TO COPYRIGHT INSTRUCTIONS FORM NUMBER G120-2083
 */
/* $Header: raster.c,v 12.0 88/11/11 12:37:47 root dec88 $ */
/* $Source: /ibm/acis/usr/src/ibm/fdb_ca/src/RCS/raster.c,v $ */

#ifndef lint
static char *rcsid = "$Header: raster.c,v 12.0 88/11/11 12:37:47 root dec88 $";
#endif

/*
 * raster: collection of routines for manipulating image pel rasters
 */

/*-------------------include project and standard type defs*/
#include "itc.h"
#include "stddefs.h"
/*------------------include appropriate header files*/
#include <stdio.h>
#include "bits.h"
#include "palloc.h"
#include "raster.h"


palloc_pool_type pool;	/* memory pool used for raster allocation */

/*---------------------masks used in bit operations*/

byte raster_only_bit[] = {
    0x80,
    0x40,
    0x20,
    0x10,
    0x08,
    0x04,
    0x02,
    0x01
};

byte raster_allbut_bit[] = {
    0x7f,
    0xbf,
    0xdf,
    0xef,
    0xf7,
    0xfb,
    0xfd,
    0xfe
};


/*
 * raster_setup: must be the first routine called.  It sets up things.
 */
void raster_setup ()
{
}

/*
 * raster_free: frees the images data
 */
void raster_free (r)
raster_type *r;
{

    free(r->r);
}

/*
 * raster_clear: clears all the pels in a raster
 */
void raster_clear (r)
raster_type *r;
{
    natural size;
    byte *pos;
    natural i;

    pos = r->r;
    size = r->roww * r->maxh;
    for (i=0; i<size; i++) {
	*pos++ = 0;
    }
}

/*
 * raster_initialize: initialize r using parameters, no memory will be allocated
 * unless image is null and maxw and maxh are both > 0 or r is null
 */
void raster_initialize (newr, w, maxw, h, maxh, image)
raster_type *newr;
natural w, maxw, h, maxh;
byte *image;
{
    newr->w = w;
    newr->maxw = maxw;
    newr->roww = (maxw+7)>>3;
    newr->h = h;
    newr->maxh = maxh;
    fflush();
    /* initialize the image, note if the caller has specified a image
       then no check will be made to insure that it is big enough. */
    if (image != NULL) {
	newr->r = image;		/* use caller supplied image */
    } else {
	if (newr->maxw > 0 && newr->maxh > 0) {
	    newr->r = (byte *)  malloc (newr->roww * maxh);
	    raster_clear (newr);
	} else {
	    newr->r = NULL;
	}
    }
}

/*
 * raster_set_pel: turns on the indicated pel
 */
void raster_set_pel (r, row, col)
raster_type *r;
natural row, col;
{
    natural offset;

    offset = (row * r->roww) + (col >> 3);
    *(r->r + offset) |= raster_only_bit[col & 0x7];
}

/*
 * raster_clear_pel: turns off the indicated pel
 */
void raster_clear_pel (r, row, col)
raster_type *r;
natural row, col;
{
    natural offset;

    offset = (row * r->roww) + (col >> 3);
    *(r->r + offset) &= raster_allbut_bit[col & 0x7];
}

/*
 * raster_test_pel: tests the indicated pel, returns true for on
 */
boolean raster_test_pel (r, row, col)
raster_type *r;
natural row, col;
{
    natural offset;

    offset = (row * r->roww) + (col >> 3);
    return (*(r->r + offset) & raster_only_bit[col & 0x7]);
}

/*
 * raster_print: prints a raster object with the specified style
 */
void raster_print (r, id)
raster_type *r;
char *id;
{
    natural row, col;
    char pchar;

    printf ("Raster print - %s\n", id);
    printf ("		Width = %d, Max Width = %d\n", r->w, r->maxw);
    printf ("		Height = %d, Max Height = %d\n", r->h, r->maxh);

    for (row = 0; row < r->h; row++) {
	printf ("		|");
	for (col = 0; col < r->w; col++) {
	    pchar = (raster_test_pel(r, row, col)) ? '*' : '.';
	    putchar (pchar);
	}
	printf ("|\n");
    }
}

/*
 * raster_show: prints a raster object using x's and o's
 */
void raster_show (outfile, r)
FILE *outfile;
raster_type *r;
{
    natural row, col;
    char pchar;

    fprintf (outfile, "\t");
    for (col = 0; col < r->w; col++) {
	if ( ((col+1)%3) == 0) {
	    fprintf (outfile, "%3d", col);
	}
    }
    fprintf (outfile, "\n");

    for (row = 0; row < r->h; row++) {
	if ( ((row+1)%3) == 0) {
	    fprintf (outfile, " %d\t", row);
	} else {
	    fprintf (outfile, "\t");
	}
	for (col = 0; col < r->w; col++) {
	    pchar = (raster_test_pel(r, row, col)) ? '@' : '-';
	    fputc (pchar, outfile);
	}
	fprintf (outfile, "\n");
    }
}

/*
 *  raster_show_grid: prints a raster object with a superinposed grid using '-'s
 *                   and '@'s
 */
void raster_show_grid (outfile, r)
FILE *outfile;
raster_type *r;
{
    natural row, col;
    char pchar;

    fprintf (outfile, "\t");
    for (col = 0; col < r->w; col++) {
	if ((col%3) == 0) {
	    fprintf (outfile, "|%3d", col/3);
	}
    }
    fprintf (outfile, "\n");

    for (row = 0; row < r->h; row++) {
	if ((row%3) == 0) {
	    fprintf (outfile, "\t");
	    for (col = 0; col < r->w; col++) {
		if ((col%3) == 0) {
		    fprintf (outfile, "+");
		}
		fprintf (outfile, "-");
	    }
	    fprintf (outfile, " \n%d\t", row/3);
	} else {
	    fprintf (outfile, "\t");
	}
	for (col = 0; col < r->w; col++) {
	    if ((col%3) == 0) {
		fprintf (outfile, "|");
	    }
	    pchar = (raster_test_pel(r, row, col)) ? '@' : ' ';
	    fputc (pchar, outfile);
	}
	fprintf (outfile, "\n");
    }
}

/*
 * raster_dump: dumps a raster object 
 */
void raster_dump (outfile, r)
FILE *outfile;
raster_type *r;
{
    natural rowInc, byteWidth, row, colByte;
    byte *image;
    natural fill;
    
    rowInc = (r->maxw+7)>>3;
    byteWidth = (r->w+7)>>3;
    fill = byteWidth%2;
    image = r->r;
    for (row=0; row<r->h; row++) {
	for (colByte=0; colByte<byteWidth; colByte++) {
	    fprintf (outfile, "%02x", *(image+(row*rowInc)+colByte));
	}
	if (fill == 1) {
	    fprintf (outfile, "00");	/* fill to 2 byte hunks */
	}
	fprintf (outfile, "\n");
    }
}

/*
 * raster_copy: copies one raster into another including making a new copy of 
 * the raster image
 */
void raster_copy (src_r, dest_r, new_maxw, new_maxh)
raster_type *src_r;
raster_type *dest_r;
natural new_maxw, new_maxh;
{
    natural row, col;

    raster_initialize (dest_r, src_r->w, new_maxw, src_r->h, new_maxh, NULL);
    if (dest_r->r != NULL) {
	raster_clear (dest_r);
	for (row=0; row<src_r->h; row++) {
	    for (col=0; col<src_r->w; col++) {
		if (raster_test_pel(src_r, row, col)) {
		    raster_set_pel(dest_r, row, col);
		}
	    }
	}
    }
}

/*
 * raster_new_width: set the width of a raster to a new value, this may change
 * maximum width and cause the image to be copied if the width value in too
 * large
 */
void  raster_newwidth (r, newwidth)
raster_type *r;
natural newwidth;
{
}

/*
 * raster_new_height:set the height of a raster to a new value, this may change
 * maximum height and cause the image to be copied if the height value in too
 * large
 */
void raster_newheight (r, newheight)
raster_type *r;
natural newheight;
{
}

/*
 * raster_find_top_bottom: finds the first and last rows that contain turned
 * on pels
 */
void raster_find_top_bottom (r, top, bottom)
raster_type *r;
natural *top;
natural *bottom;
{
    natural row, col;

    if (r->h < 2) {
	*top = 0;
	*bottom = 0;
	return;
    }
    
    for (row=r->h-1; row>0; row--) {
	for (col=0; col<r->w; col++) {
	    if (raster_test_pel(r, row, col)) {
		goto bottom_found;
	    }
	}
    }
bottom_found:    
    *bottom = row;

    for (row=0; row<*bottom; row++) {
	for (col=0; col<r->w; col++) {
	    if (raster_test_pel(r, row, col)) {
		goto top_found;
	    }
	}
    }
top_found:
    *top = row;
}

/*
 * raster_find_left_right: finds the first and last cols that contain turned
 * on pels
 */
void raster_find_left_right (r, left, right)
raster_type *r;
natural *left;
natural *right;
{
    natural col, row;

    if (r->w < 2) {
	*left = 0;
	*right = 0;
	return;
    }
    
    for (col=r->w-1; col>0; col--) {
	for (row=0; row<r->h; row++) {
	    if (raster_test_pel(r, row, col)) {
		goto right_found;
	    }
	}
    }
right_found:
    *right = col;

    for (col=0; col<*right; col++) {
	for (row=0; row<r->h; row++) {
	    if (raster_test_pel(r, row, col)) {
		goto left_found;
	    }
	}
    }
left_found:
    *left = col;
}

/*
 * raster_compress: shifts a rectangle of pels to the upper left corner of
 * the raster box, adjusting the current height and width accordingly
 */
void raster_compress (r,d, top, bottom, left, right)
raster_type *r;
raster_type *d;
natural top, bottom, left, right;
{
    natural s_row, s_col;	/* the current location for taking bits */
    natural d_row, d_col;	/* the current location for putting bits */


    d_row = 0;
    for (s_row=top; s_row<=bottom; s_row++) {
	d_col = 0;
	for (s_col=left; s_col<=right; s_col++) {
	    if (raster_test_pel(r, s_row, s_col)) {
		raster_set_pel(d, d_row, d_col);
	    } else {
		raster_clear_pel(d, d_row, d_col);
	    }
	    d_col++;
	}
	d_row++;
    }

    r->h = (bottom-top) + 1;
    r->w = (right-left) + 1;
}
