/* $Log:	pktopxl.c,v $
 * Revision 0.8  92/11/23  19:46:53  19:46:53  bt (Bo Thide')
 * Fixed resolution bug. Portable downloading. Added/changed options. PJXL color support
 * 
 * Revision 0.7  92/11/13  02:41:38  02:41:38  bt (Bo Thide')
 * More bug fixes and improvements. Support for PaintJet XL
 * 
 * Revision 0.6  92/11/10  21:48:35  21:48:35  bt (Bo Thide')
 * Bug fixes. Added -R option. Better font handling.
 * 
 * Revision 0.5  92/11/09  16:25:42  16:25:42  bt (Bo Thide')
 * Rewrite of dospecial.c. Extended \special support
 * 
 * Revision 0.4  92/11/08  02:45:58  02:45:58  bt (Bo Thide')
 * Changed to portable bit manipulations. Replaced strrstr for non-POSIX compliant C. Fixed numerous bugs. Added support for more \special's.
 * 
 * Revision 0.3  92/08/24  12:45:48  12:45:48  bt (Bo Thide')
 * Fixed 8 bit (dc font) support.
 * 
 * Revision 0.2  92/08/23  17:28:59  17:28:59  bt (Bo Thide')
 * Source cleaned up.  Changed certain function calls.  Removed globals.
 * 
 * Revision 0.1  92/08/22  23:58:48  23:58:48  bt (Bo Thide')
 * First Release.
 *  */

int   repeat_count;

#include <stdio.h>
#include "globals.h"

static char rcsid[] = "$Header: pktopxl.c,v 0.8 92/11/23 19:46:53 bt Exp $";

/*
 * This routine converts a character coded in PK format into the appropriate
 * byte aligned pixel pattern. After calling 'pkcharinfo(c)', besides the
 * global variables 'dyn_f, c_flag, c_width, c_height, c_hoffset and c_voffset'
 * a pointer to the first run count is returned and stored in the global var
 * 'pk_ptr'. The produced pixel pattern is stored in the global array
 * 'pxl_buffer', and the global pointer 'endofchardata' points to the next free
 * byte in 'pxlbuffer'.
 *----------------------------------------------------------------------------
 * 'pktopxl' has two main branches: for those characters which are coded into
 * run-repeat counts, indicated by a value of dyn_f < 14, the first branch is
 * taken, while for bit mapped characters, indicated by dyn_f == 14, the
 * second branch is taken.
 */
pktopxl(c)
int c;
{
  static byte c_pad[]={'\0','\200','\300','\340','\360','\370','\374','\376'};
  byte	*pxl, *row="", *p;
  byte	pxl_byte;
  int	pad_bits, pad_comp;
  int   pad_mask;
  int   width_bytes;
  int   nrows,length;
  int   l, m=0, n=0;
  int   run_count;

  pk_ptr = pkcharinfo(c);
  nrows = c_height;
  width_bytes = (c_width + 7) / 8;
  pad_bits = c_width % 8;
  pad_mask = c_pad[pad_bits];
  pxl = pxlbuffer;

  if(dyn_f<14){
   /* Convert run/repeat counts to byte aligned pixels */
    run_count = repeat_count = 0;
    c_nib = 0;
    c_black = (c_flag & 0x8) ? 0 : ~0;
    while(nrows) {
      if(repeat_count) {
        while(repeat_count) {
          repeat_count--;
          m = width_bytes;
          while(m--)
            *pxl++ = *row++;
          nrows--;
        }
      }
      else {
        if(!run_count)
          run_count = pknum();
        if(run_count >= c_width)
          while(run_count >= c_width) {
            run_count -= c_width;
            m = pad_bits ? width_bytes : width_bytes + 1;
            while(--m)
              *pxl++ = c_black ? BLACKBYTE : WHITEBYTE;
            if(pad_bits)
              *pxl++ = c_black ? pad_mask : WHITEBYTE;
            nrows--;
          }
        else {
          row = pxl;
          m = pad_bits ? width_bytes : width_bytes + 1;
          while(--m) {
            if(run_count < 8) {
              pxl_byte = c_black ? c_pad[run_count] : ~c_pad[run_count];
              while((run_count += pknum()) < 8)
                if(c_black)
                  pxl_byte &= c_pad[run_count];
              else
                pxl_byte |= ~c_pad[run_count];
	      *pxl++ = pxl_byte;
	    }
	    else
	      *pxl++ = c_black ? BLACKBYTE : WHITEBYTE;
	    run_count -= 8;
	  }
	  if(pad_bits) {
	    if(run_count < pad_bits) {
	      pxl_byte = c_black ? c_pad[run_count] : ~c_pad[run_count];
	      while((run_count += pknum()) < pad_bits)
		if(c_black)
		  pxl_byte &=  c_pad[run_count];
		else
		  pxl_byte |= ~c_pad[run_count];
	      *pxl++ = pxl_byte & pad_mask;
	    }
	    else
	      *pxl++ = c_black ? pad_mask : WHITEBYTE;
	  }
	  nrows--;
	  run_count -= pad_bits;
	}
      }
    }
  }
  else {
    /* Convert bit mapped character into byte aligned pixel */
    p = pk_ptr;
    pad_comp = 8 - pad_bits;
    if(pad_bits) {
      m=0;
      while(nrows--) {
	l = width_bytes;
        while(--l)
	  *pxl++ = m ? (*p++) << m | (*p >> n) & ~c_pad[n] : *p++;
        if(m)
	  *pxl++ = m <= pad_comp ? (*p << m) & pad_mask :
	    (*p++) << m | *p >> n & ~c_pad[n] & pad_mask;
        else
	  *pxl++ = *p & pad_mask;
        m = (m + c_width) % 8;
        if(!m)
	  p++;
        else
	  n = 8 - m;
      }
    }
    else {
      length = width_bytes*c_height;
      if(!length)
	*pxl++ = 0;        /* special case for empty char */
      while(length--)
	*pxl++ = *p++;
    }
  }
  endofchardata = pxl;
}

