/*
======================================================================
glyph.c

Routines for drawing a monospace font on a LightWave panel.  Part of
the LightWave SDK BinView sample plug-in.

Ernie Wright  3 Nov 99
====================================================================== */

#include <stdio.h>
#include <lwpanel.h>
#include "binview.h"

#define GLYPH_SKIP 32   /* lowest valid code is GLYPH_SKIP + 1 */
#define NUM_GLYPHS 94

/*
----------------------------------------------------------------------
Bits defining the font.  The character cell is TXWIDTH x TXHEIGHT
(constants defined in binview.h).  Each line contains TXHEIGHT bytes
and defines a character, with one byte per scanline and one bit per
pixel.  Set bits are character pixels and clear bits are background
pixels.  The leftmost pixel is in the highest bit; if TXWIDTH < 8, the
low bits are ignored.  Glyphs are defined for ASCII characters with
codes in the range GLYPH_SKIP + 1 to GLYPH_SKIP + NUM_GLYPHS.

You can replace this with the bits for any font without changing the
character drawing functions at all, as long as the bit array conforms
to the above description and TXWIDTH <= 8.  Be sure to set TXWIDTH and
TXHEIGHT appropriately.
---------------------------------------------------------------------- */

static unsigned char charbits[ 1128 ] = {
      0,0x20,0x20,0x20,0x20,0x20,0x20,   0,0x20,0x20,   0,   0,
      0,0x50,0x50,0x50,   0,   0,   0,   0,   0,   0,   0,   0,
      0,   0,0x50,0x50,0xF8,0x50,0x50,0xF8,0x50,0x50,   0,   0,
      0,0x20,0x70,0xA8,0xA0,0x70,0x28,0xA8,0x70,0x20,   0,   0,
      0,0xC8,0xC8,0x10,0x10,0x20,0x40,0x40,0x98,0x98,   0,   0,
      0,0x40,0xA0,0xA0,0x40,0xA0,0xA8,0x90,0xA8,0x48,   0,   0,
      0,0x10,0x10,0x10,0x20,   0,   0,   0,   0,   0,   0,   0,
      0,0x10,0x20,0x20,0x40,0x40,0x40,0x40,0x20,0x20,0x10,   0,
      0,0x40,0x20,0x20,0x10,0x10,0x10,0x10,0x20,0x20,0x40,   0,
      0,   0,   0,   0,0x50,0x70,0xF8,0x70,0x50,   0,   0,   0,
      0,   0,   0,0x20,0x20,0x20,0xF8,0x20,0x20,0x20,   0,   0,
      0,   0,   0,   0,   0,   0,   0,   0,0x60,0x60,0x20,0x40,
      0,   0,   0,   0,   0,   0,0x70,   0,   0,   0,   0,   0,
      0,   0,   0,   0,   0,   0,   0,   0,0x60,0x60,   0,   0,
      0,0x08,0x08,0x10,0x10,0x20,0x20,0x40,0x40,0x80,0x80,   0,
      0,0x70,0x88,0x88,0x98,0xA8,0xC8,0x88,0x88,0x70,   0,   0,
      0,0x20,0x20,0x60,0xA0,0x20,0x20,0x20,0x20,0x70,   0,   0,
      0,0x70,0x88,0x88,0x08,0x10,0x20,0x40,0x80,0xF8,   0,   0,
      0,0xF8,0x08,0x10,0x20,0x10,0x08,0x88,0x88,0x70,   0,   0,
      0,0x10,0x30,0x30,0x50,0x50,0x90,0xF8,0x10,0x38,   0,   0,
      0,0xF0,0x80,0x80,0xF0,0x08,0x08,0x88,0x88,0x70,   0,   0,
      0,0x30,0x40,0x80,0xF0,0x88,0x88,0x88,0x88,0x70,   0,   0,
      0,0xF8,0x88,0x08,0x10,0x10,0x20,0x20,0x40,0x40,   0,   0,
      0,0x70,0x88,0x88,0x88,0x70,0x88,0x88,0x88,0x70,   0,   0,
      0,0x70,0x88,0x88,0x88,0x78,0x08,0x08,0x08,0x70,   0,   0,
      0,   0,   0,0x60,0x60,   0,   0,   0,0x60,0x60,   0,   0,
      0,   0,   0,0x60,0x60,   0,   0,   0,0x60,0x60,0x20,0x40,
      0,   0,0x10,0x20,0x40,0x80,0x40,0x20,0x10,   0,   0,   0,
      0,   0,   0,   0,   0,0x70,   0,0x70,   0,   0,   0,   0,
      0,   0,0x40,0x20,0x10,0x08,0x10,0x20,0x40,   0,   0,   0,
      0,0x70,0x88,0x88,0x08,0x10,0x20,0x20,   0,0x20,   0,   0,
      0,0x70,0x88,0x98,0xA8,0xB8,0x80,0x80,0x80,0x78,   0,   0,
      0,0x20,0x50,0x88,0x88,0x88,0xF8,0x88,0x88,0x88,   0,   0,
      0,0xF0,0x48,0x48,0x48,0x70,0x48,0x48,0x48,0xF0,   0,   0,
      0,0x70,0x88,0x80,0x80,0x80,0x80,0x80,0x88,0x70,   0,   0,
      0,0xF0,0x48,0x48,0x48,0x48,0x48,0x48,0x48,0xF0,   0,   0,
      0,0xF8,0x80,0x80,0x80,0xF0,0x80,0x80,0x80,0xF8,   0,   0,
      0,0xF8,0x80,0x80,0x80,0xE0,0x80,0x80,0x80,0x80,   0,   0,
      0,0x70,0x88,0x80,0x80,0x80,0xB8,0x88,0x88,0x70,   0,   0,
      0,0x88,0x88,0x88,0x88,0xF8,0x88,0x88,0x88,0x88,   0,   0,
      0,0x70,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x70,   0,   0,
      0,0x18,0x08,0x08,0x08,0x08,0x08,0x08,0x88,0x70,   0,   0,
      0,0x88,0x88,0x90,0xA0,0xC0,0xA0,0x90,0x88,0x88,   0,   0,
      0,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0xF8,   0,   0,
      0,0x88,0x88,0xD8,0xA8,0xA8,0x88,0x88,0x88,0x88,   0,   0,
      0,0x88,0x88,0xC8,0xC8,0xA8,0xA8,0x98,0x98,0x88,   0,   0,
      0,0x70,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x70,   0,   0,
      0,0xF0,0x88,0x88,0x88,0xF0,0x80,0x80,0x80,0x80,   0,   0,
      0,0x70,0x88,0x88,0x88,0x88,0xA8,0xA8,0x90,0x68,0x08,   0,
      0,0xF0,0x88,0x88,0x88,0xF0,0x88,0x88,0x88,0x88,   0,   0,
      0,0x70,0x88,0x80,0x80,0x70,0x08,0x08,0x88,0x70,   0,   0,
      0,0xF8,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,   0,   0,
      0,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x88,0x70,   0,   0,
      0,0x88,0x88,0x88,0x50,0x50,0x50,0x20,0x20,0x20,   0,   0,
      0,0x88,0x88,0x88,0x88,0xA8,0xA8,0x50,0x50,0x50,   0,   0,
      0,0x88,0x88,0x50,0x50,0x20,0x50,0x50,0x88,0x88,   0,   0,
      0,0x88,0x88,0x88,0x50,0x50,0x20,0x20,0x20,0x20,   0,   0,
      0,0xF8,0x08,0x10,0x10,0x20,0x40,0x40,0x80,0xF8,   0,   0,
      0,0x70,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x70,   0,   0,
      0,0x80,0x80,0x40,0x40,0x20,0x20,0x10,0x10,0x08,0x08,   0,
      0,0x70,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x70,   0,   0,
      0,   0,   0,0x20,0x50,0x88,   0,   0,   0,   0,   0,   0,
      0,   0,   0,   0,   0,   0,   0,   0,   0,   0,0xF8,   0,
      0,0x40,0x40,0x40,0x20,   0,   0,   0,   0,   0,   0,   0,
      0,   0,   0,0x70,0x08,0x78,0x88,0x88,0x88,0x78,   0,   0,
      0,0x80,0x80,0xF0,0x88,0x88,0x88,0x88,0x88,0xF0,   0,   0,
      0,   0,   0,0x78,0x80,0x80,0x80,0x80,0x80,0x78,   0,   0,
      0,0x08,0x08,0x78,0x88,0x88,0x88,0x88,0x88,0x78,   0,   0,
      0,   0,   0,0x70,0x88,0x88,0xF8,0x80,0x88,0x70,   0,   0,
      0,0x20,0x50,0x40,0x40,0xE0,0x40,0x40,0x40,0x40,   0,   0,
      0,   0,   0,0x70,0x88,0x88,0x88,0x88,0x88,0x78,0x08,0x70,
      0,0x80,0x80,0xF0,0x88,0x88,0x88,0x88,0x88,0x88,   0,   0,
      0,0x20,   0,0x60,0x20,0x20,0x20,0x20,0x20,0x70,   0,   0,
      0,0x10,   0,0x30,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0xE0,
      0,0x80,0x80,0x88,0x90,0xA0,0xC0,0xA0,0x90,0x88,   0,   0,
      0,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x10,   0,   0,
      0,   0,   0,0x50,0xF8,0xA8,0xA8,0xA8,0xA8,0xA8,   0,   0,
      0,   0,   0,0xF0,0x88,0x88,0x88,0x88,0x88,0x88,   0,   0,
      0,   0,   0,0x70,0x88,0x88,0x88,0x88,0x88,0x70,   0,   0,
      0,   0,   0,0xF0,0x88,0x88,0x88,0x88,0x88,0xF0,0x80,0x80,
      0,   0,   0,0x78,0x88,0x88,0x88,0x88,0x88,0x78,0x08,0x08,
      0,   0,   0,0xB8,0xC0,0x80,0x80,0x80,0x80,0x80,   0,   0,
      0,   0,   0,0x78,0x80,0x80,0x70,0x08,0x08,0xF0,   0,   0,
      0,0x40,0x40,0xF0,0x40,0x40,0x40,0x40,0x40,0x38,   0,   0,
      0,   0,   0,0x88,0x88,0x88,0x88,0x88,0x88,0x78,   0,   0,
      0,   0,   0,0x88,0x88,0x88,0x50,0x50,0x20,0x20,   0,   0,
      0,   0,   0,0x88,0x88,0x88,0xA8,0xA8,0x50,0x50,   0,   0,
      0,   0,   0,0x88,0x88,0x50,0x20,0x50,0x88,0x88,   0,   0,
      0,   0,   0,0x88,0x88,0x50,0x50,0x20,0x20,0x40,0x40,0x80,
      0,   0,   0,0xF8,0x08,0x10,0x20,0x40,0x80,0xF8,   0,   0,
      0,0x18,0x20,0x20,0x20,0x40,0x20,0x20,0x20,0x18,   0,   0,
   0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
      0,0x40,0x20,0x20,0x20,0x18,0x20,0x20,0x20,0x40,   0,   0,
      0,0x40,0xA8,0x10,   0,   0,   0,   0,   0,   0,   0,   0
};


/* bit lookup:  bit[ n ] == 1 << (7 - n) */

static int bit[ 8 ] = { 128, 64, 32, 16, 8, 4, 2, 1 };


/*
======================================================================
create_char()

Initialize the glyph raster.

INPUTS
   fg       foreground color index
   bg       background color index
   rasf     raster functions returned by the Raster Services global

RESULTS
   Creates a raster and draws each character on it.  Returns the
   LWRasterID.

This should be called once, before calling draw_char().  The raster
returned by this function should be freed by calling free_char() when
it's no longer needed.
====================================================================== */

LWRasterID create_char( int fg, int bg, LWRasterFuncs *rasf )
{
   LWRasterID ras;
   int i, j, c, index;

   ras = rasf->create( TXWIDTH * ( NUM_GLYPHS + 1 ), TXHEIGHT, 0 );
   if ( !ras ) return NULL;

   rasf->drawBox( ras, bg, 0, 0, TXWIDTH * 96, TXHEIGHT );

   for ( c = 1; c <= NUM_GLYPHS; c++ ) {
      index = TXHEIGHT * ( c - 1 );
      for ( j = 0; j < TXHEIGHT; j++, index++ )
         for ( i = 0; i < TXWIDTH; i++ )
            if ( charbits[ index ] & bit[ i ] )
               rasf->drawPixel( ras, fg, c * TXWIDTH + i, j );
   }
   return ras;
}


/*
======================================================================
draw_char()

Draw a character on a LightWave panel window.

INPUTS
   c        ASCII code of the character to draw
   x, y     position of character cell's upper left corner
   ras      glyph raster created by create_char()
   rasf     raster functions returned by the Raster Services global
   panel    panel to draw on

RESULTS
   Blits the character glyph to the panel window, or a rectangle of
   the raster's background color if the character code is outside the
   range of defined glyphs.

The (x, y) pixel coordinates are relative to the top left corner of
the panel window.
====================================================================== */

void draw_char( int c, int x, int y, LWRasterID ras, LWRasterFuncs *rasf,
   LWPanelID panel )
{
   if ( c > GLYPH_SKIP && c <= GLYPH_SKIP + NUM_GLYPHS )
      rasf->blitPanel( ras, ( c - GLYPH_SKIP ) * TXWIDTH, 0, panel, x, y,
         TXWIDTH, TXHEIGHT );
   else
      rasf->blitPanel( ras, 0, 0, panel, x, y, TXWIDTH, TXHEIGHT );
}


/*
======================================================================
free_char()

Frees resources allocated by create_char().

INPUTS
   ras      glyph raster created by create_char()
   rasf     raster functions returned by the Raster Services global

RESULTS
   Frees the glyph raster.
====================================================================== */

void free_char( LWRasterID ras, LWRasterFuncs *rasf )
{
   rasf->destroy( ras );
}