 /*
  * Khoros: $Id: lvlaser.c,v 1.1 1991/05/10 15:41:54 khoros Exp $
  */

#if !defined(lint) && !defined(SABER)
static char rcsid[] = "Khoros: $Id: lvlaser.c,v 1.1 1991/05/10 15:41:54 khoros Exp $";
#endif

 /*
  * $Log: lvlaser.c,v $
 * Revision 1.1  1991/05/10  15:41:54  khoros
 * Initial revision
 *
  */ 

/*
 *----------------------------------------------------------------------
 *
 * Copyright 1991, University of New Mexico.  All rights reserved.
 * Permission to copy and modify this software and its documen-
 * tation only for internal use in your organization is hereby
 * granted, provided that this notice is retained thereon and
 * on all copies.  UNM makes no representations as too the sui-
 * tability and operability of this software for any purpose.
 * It is provided "as is" without express or implied warranty.
 * 
 * UNM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT-
 * NESS.  IN NO EVENT SHALL UNM BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY OTHER DAMAGES WHAT-
 * SOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PER-
 * FORMANCE OF THIS SOFTWARE.
 * 
 * No other rights, including for example, the right to redis-
 * tribute this software and its documentation or the right to
 * prepare derivative works, are granted unless specifically
 * provided in a separate license agreement.
 *---------------------------------------------------------------------
 */

#include "unmcopyright.h"        /* Copyright 1991 by UNM */

/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 >>>>
 >>>>         File Name: lvlaser.c
 >>>>
 >>>>      Program Name: vlaser
 >>>>
 >>>> Date Last Updated: Thu Mar 28 00:09:47 1991 
 >>>>
 >>>>          Routines: lvlaser - the library call for vlaser
 >>>>
 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>   <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/


#include "vinclude.h"


/* -library_includes */
#define     DOTS_PER_INCH       300

#define     OPAQUE              3
#define     MAX_HSIZE           80
#define     MAX_VSIZE           104

#define     LOBYTE(number)      ((unsigned char)(number & 0x00FF))
#define     HIBYTE(number16)    ((unsigned char)((number16 >> 8) & 0x00FF))

#define     PATCH_SIZE          32
#define     PATCH_BYTES         4

typedef char patch[PATCH_SIZE][PATCH_BYTES];

int  hsize, vsize;    /* Size (in patches of image) */
/* -library_includes_end */


/****************************************************************
*
* Routine Name: lvlaser - library call for vlaser
*
* Purpose:
*    
*    Format a Khoros image in Impress for output  to  the  IMAGEN
*    8/300
*    
*    
* Input:
*    
*    file           files descriptor to write formatted IMPRESS to
*    
*    image          pointer to BIT xvimage structure to  be  formatted
*                   for printing
*    
*    magnification  log base two of the desired magnifcation (int)
*    
*    xoffset        horizontal offset from the left edge of  paper  of
*                   the upper left corner
*    
*    yoffset        vertical offset from the top edge of paper of  the
*                   upper left corner
*    
*    photo_neg      if non-zero, then  photonegative  output  is  gen-
*                   erated
*    
*    overlays       if non-zero then the page is not  printed  at  the
*                   end  of  execution  and  additional  output can be
*                   placed on the same page
*    
*    
* Output:
*    
*    Return Value:  1 on success, 0 on failure.
*    
*    
*
* Written By: Scott Wilson, Mark Young
*    
*    Scott Wilson, John Salas, Bret  Thaeler,  Tait  Cyrus,  Kurt
*    Zeilinga, Josh Seigel, Richard Krukar, Mark Young, Mike Lang
*    
*    
****************************************************************/


/* -library_def */
int
lvlaser(file, image, magnification, xoffset, yoffset, photo_neg, overlays)
FILE   *file;
struct xvimage *image;
int magnification, photo_neg, overlays;
float xoffset, yoffset;
/* -library_def_end */

/* -library_code */
{
  int rows, cols, i, j, k, l, mask, x, y;
  unsigned char *bptr,*pptr;
  char *malloc();
  unsigned char rev[256];

  /* See if we have an image of the proper type */
  if (image->data_storage_type != VFF_TYP_BIT)
  {
      (void) fprintf(stderr,"\n\nlvlaser: Cannot operate on non-BIT images!\n\n");
      return(0);
  }

  rows = image->col_size;
  cols = image->row_size;
  hsize = (cols+31)/32;           /* Make sure to round UP, not down! */
  vsize = (rows+31)/32;           /* Make sure to round UP, not down! */

  /* Note: The IMAGEN wants the least dependent bit to be the upper
     left pixel on the output page! */

  bptr = (unsigned char *)image->imagedata;
  pptr = (unsigned char *)malloc(hsize*vsize*sizeof(patch)); /* Patch array */
  if (pptr == NULL)
  {
      (void) fprintf(stderr,"\n\nlvlaser: Not enough memory for patch ");
      (void) fprintf(stderr,"bitarray!\n\n");
      return(0);
  }
  bzero(pptr,hsize*vsize*sizeof(patch));
  
  /* Go through and zero the pad bits at the end of the last char
     of each row in the bitmap.  This will make the IMAGEN print out
     the pad as white which is invisible, instead of black which, although
     is the correct rendition of the Bitmap, looks terrible! */
  k = (cols+7)/8;
  mask = ~0 << 8-(8*k-cols);
  for (i=k-1; i<k*rows; i += k) bptr[i] |= mask;

  /* Go fix up the bit ordering */
  impress_genrev(rev);

  /* Now invert the data if requeste, since whats dark on the screen
     is light on the IMAGEN, and vice versa */
  if (photo_neg)
  {
     for (i=0; i<k*rows; i++) 
         bptr[i] = ~rev[bptr[i]];
  }
  else
  {
     for (i=0; i<k*rows; i++) 
         bptr[i] = rev[bptr[i]];
  }

  /* Now copy the input data over to the upper left corner of the patch
     bitarray.  This makes sure that the patch array is 32-bit filled,
     i.e. images that have sizes which are not multiples of 32  will
     still be printed correctly! */
  l = 0;
  for (j=0; j<rows; j++)
    for (i=0; i<k; i++)
      pptr[j*hsize*PATCH_BYTES+i] = bptr[l++];

  /* Make the IMPRESS header */
  x = (int) xoffset * DOTS_PER_INCH;
  y = (int) yoffset * DOTS_PER_INCH;
  write_imp_header(file, 0, magnification, x, y);

  /* Now  build the IMPRESS data block */
  add_bytes(file, pptr,hsize*vsize*sizeof(patch));

  /* Send out the tail end */
  write_imp_trailer(file, overlays);
  free(pptr);
  return(1);
}


/*************************************************
                write_imp_header
*************************************************/
write_imp_header(file, include, magnification, offset, header)
FILE *file;
int  include, magnification, offset, header;
{
  if(!include)
  {
    fprintf(file, "@Document(Language ImPress,");
    fprintf(file, " Name \"Khoros Document\", jobheader on)");

    /* Set absolute horizontal position */
    fputc((unsigned char) 135, file); 
    fputc(HIBYTE( (short) offset ), file);
    fputc(LOBYTE( (short) offset ), file);

    /* Set absolute vertical position */
    fputc((unsigned char) 137, file); 
    fputc(HIBYTE( (short) header ), file);
    fputc(LOBYTE( (short) header ), file);

    /* Set Magnification if requested */
    fputc((unsigned char) 236, file ); 
    fputc((unsigned char) magnification, file);
  }

  /* Generate the BITMAP command */
  fputc((unsigned char) 235, file ); 
  fputc((unsigned char) OPAQUE, file );
  fputc((unsigned char) hsize, file ); 
  fputc((unsigned char) vsize, file );
}


/*************************************************
                write_imp_trailer
*************************************************/
write_imp_trailer(file, overlays)
FILE  *file;
int  overlays;
{
  if(!overlays)
  {
    fputc((unsigned char) 219, file);    /* endpage */ 
  }
}


/*************************************************
                write_patches
*************************************************/
write_patches (file, patches)
FILE  *file;
patch *patches;
{
  register int num, row, col;

  for(num=0; num<hsize; num++)
    for(row=0; row<PATCH_SIZE; row++)
      for(col=0; col<PATCH_BYTES; col++)
        fputc((unsigned char) patches[num][row][col], file);
}


/*************************************************
                add_bytes
*************************************************/
add_bytes(file, bytes, nbytes)
FILE   *file;
char   *bytes;
int  nbytes;
{
  static patch patches[ MAX_HSIZE ]; 
  static short patch_num = 0; 
  static short patch_row = 0; 
  static short patch_col = 0;

  register int  j;

  for(j=0; j<nbytes; j++)
  {
    patches[patch_num][patch_row][patch_col] = bytes[j];
    if (++patch_col >= PATCH_BYTES)
    {
      patch_col = 0;
      if (++patch_num >= hsize)
      {
        patch_num = 0; 
        if (++patch_row >= PATCH_SIZE)
        {
          patch_row = 0;
          write_patches(file, patches);
        }
      }
    }
  }
  return(nbytes);
}

/*************************************************
                impress_genrev
*************************************************/
impress_genrev(p)
unsigned char *p;
{
    /* Generate an array of bit-reverse characters */
    int i;
    unsigned char j,k;

    for (i=0; i<256; i++)
    {
        j = i;
        k = 0;
        k |= (j >> 7) & (1 << 0); /* Bit 7 to Bit 0 */
        k |= (j >> 5) & (1 << 1); /* Bit 6 to Bit 1 */
        k |= (j >> 3) & (1 << 2); /* Bit 5 to Bit 2 */
        k |= (j >> 1) & (1 << 3); /* Bit 4 to Bit 3 */
        k |= (j << 1) & (1 << 4); /* Bit 3 to Bit 4 */
        k |= (j << 3) & (1 << 5); /* Bit 2 to Bit 5 */
        k |= (j << 5) & (1 << 6); /* Bit 1 to Bit 6 */
        k |= (j << 7) & (1 << 7); /* Bit 0 to Bit 7 */
        p[i]=k;
    }
}
/* -library_code_end */
