home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
magazine
/
pctchnqs
/
1991
/
number2
/
hpfont.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
1991-03-08
|
8KB
|
278 lines
//-------------------------------------------------------------//
// File: HpFont.Cpp //
// Desc: Font implementation for HP Soft Font //
// Author: Marv Luse, Autumn Hill Software //
//-------------------------------------------------------------//
#include "stdlib.h"
#include "stdio.h"
#include "ctype.h"
#include "HpFont.Hpp"
#define BUF_SIZ 128
static int cur_ch = 0;
static int hp_stat;
//............................... Skip next n bytes from a file
static int skip_inp( FILE *inp, int nbytes )
{
int n;
char buf[BUF_SIZ];
while( nbytes > 0 )
{
n = nbytes > BUF_SIZ ? BUF_SIZ : nbytes;
if( fread(buf, n, 1, inp) != 1 )
return 0;
nbytes -= n;
}
return 1;
}
//......................... Determine char range from font type
static void char_range( int font_type, int& min_ch, int& max_ch )
{
switch( font_type )
{
case 0 : // 7-bit, 32-127
min_ch = 32;
max_ch = 127;
break;
case 1 : // 8-bit, 32-127 and 160-255
min_ch = 32;
max_ch = 255;
break;
default: // 8-bit, everything
min_ch = 0;
max_ch = 255;
break;
}
}
//................. Determine esq type and its numeric argument
static void get_esq_values( char esq_buf[], int& type, int& parm )
{
int i;
char c1, c2, clast;
/* extract group char and terminating char */
c1 = esq_buf[1];
c2 = esq_buf[2];
i = 0;
while( esq_buf[i] ) i++;
clast = esq_buf[i-1];
/* determine type */
if( (c1==')') && (c2=='s') && (clast=='W') )
type = eFONTDESC;
else if( (c1=='(') && (c2=='s') && (clast=='W') )
type = eCHARDESC;
else if( (c1=='*') && (c2=='c') && (clast=='E') )
type = eCHARCODE;
else
type = eUNKNOWN;
/* get the sequence's value field */
parm = 0;
i = 0;
while( (esq_buf[i]) && (! isdigit(esq_buf[i])) ) i++;
if( isdigit(esq_buf[i]) )
parm = atoi( esq_buf+i );
}
//.................... Read the next esc seq from the font file
static int get_esq( FILE *inp, char esq_buf[], int buf_len )
{
int i, nbytes;
nbytes = 0;
while( (i=fgetc( inp )) != EOF )
{
if( nbytes == buf_len )
{
hp_stat = hpOVRFLOW;
return 0;
}
esq_buf[nbytes++] = (char) i;
// check for end of sequence
if( isupper( i ) ) break;
}
// validity check - first char should be decimal 27
if( (nbytes > 0) && (esq_buf[0] != 27) )
{
hp_stat = hpBADFMT;
return 0;
}
// add a terminating null
esq_buf[nbytes] = 0;
return( nbytes );
}
//.................................... set font-related metrics
void HpFont::SetFontMetrics( font_desc& fd )
{
cell_w = REV_WRD( fd.cell_width );
cell_h = REV_WRD( fd.cell_height );
ascent = REV_WRD( fd.bl_dist );
descent = cell_h - ascent;
pitch = REV_WRD( fd.pitch ) >> 2;
}
//.................................... set char-related metrics
void HpFont::SetCharMetrics( Character& c, char_desc& cd )
{
c.left_ofs = REV_WRD( cd.left_ofs );
c.top_ofs = REV_WRD( cd.top_ofs );
c.width = REV_WRD( cd.char_width );
c.height = REV_WRD( cd.char_height );
c.rowbytes = (c.width + 7) / 8;
c.delta_x = (REV_WRD( cd.delta_x ) + 3) >> 2;
}
//........................ default destructor
HpFont::~HpFont( )
{
}
//........................ instantiate a font from HP Soft Font
HpFont::HpFont( char *path ) : Font( )
{
FILE *inp;
char esq_buf[BUF_SIZ];
font_desc fd;
char_desc cd;
int n, esq_type, esq_parm;
// open file
if( (inp = fopen( path, "rb" )) == NULL )
{
hpstatus = hpNOTFOUND;
fstatus = fntFAILED;
return;
}
// initialize static globals
cur_ch = 0;
hp_stat = hpNOINIT;
// scan the file and process
while( (get_esq( inp, esq_buf, BUF_SIZ ) > 0) &&
(hp_stat == hpNOINIT) )
{
// get the escape sequence type and its
// numeric value field...
get_esq_values( esq_buf, esq_type, esq_parm );
// process the sequence.....
switch( esq_type )
{
case eFONTDESC: //............... font descriptor
// read the descriptor
if( fread( &fd, sizeof(font_desc), 1, inp ) != 1 )
{
hp_stat = hpIOERROR;
break;
}
// allocate the Character array, init font stuff
char_range( (int) fd.font_type, min_ch, max_ch );
ch_cnt = max_ch - min_ch + 1;
ch = new Character[ch_cnt];
if( ch == 0 )
{
hp_stat = hpNOMEM;
break;
}
SetFontMetrics( fd );
// skip any trailing info
if( esq_parm > sizeof(font_desc) )
skip_inp( inp, esq_parm-sizeof(font_desc) );
break;
case eCHARDESC: //............... char descriptor
// read the descriptor
if( fread( &cd, sizeof(char_desc), 1, inp ) != 1 )
{
hp_stat = hpIOERROR;
break;
}
// is this a char we discard?
if( (cur_ch < min_ch) || (cur_ch > max_ch) )
{
skip_inp( inp, esq_parm-sizeof(char_desc) );
break;
}
// set char table entry
Character *c = &ch[cur_ch-min_ch];
SetCharMetrics( *c, cd );
// allocate this char's bitmap
int i = c->rowbytes * c->height;
if( i )
{
c->mask = new char[i];
if( c->mask == 0 )
{
hp_stat = hpNOMEM;
break;
}
}
else
c->mask = 0;
// get the bitmap which follows
if( esq_parm > sizeof(char_desc) )
{
n = esq_parm - sizeof(char_desc);
if( fread( c->mask, n, 1, inp ) != 1 )
{
hp_stat = hpIOERROR;
break;
}
}
break;
case eCHARCODE: //........ specify character code
// save char code for later use
cur_ch = esq_parm;
break;
case eUNKNOWN: //........ unknown seq - ignore it
break;
}
}
fclose( inp );
// update Font and HpFont status members
if( hp_stat != hpNOINIT )
{
hpstatus = hp_stat;
fstatus = fntFAILED;
return;
}
hpstatus = hpOKAY;
fstatus = fntOKAY;
// set width of blank-- may not have been a definition
Character *b = &ch[32-min_ch];
if( b->delta_x == 0 )
b->delta_x = pitch;
}