Category : Files from Magazines
Archive   : PJ91.ZIP
Filename : SPEEDO1.C
Program Name: FONTDEMO.C
Module Name: SPEEDO1.C
Author: Ron Fosner
Creation Date: March-90
Copyright Ron Fosner, (c) 1990
Description:
An program to demonstrate dynamic font generation.
This file contains the library specific calls & code.
***********************************************/
/* use function prototypes in speedo h file */
#define PROTOS_AVAIL 1
#include
#include
#include
#include "speedo.h" /* include the speedo header */
#include "local.h" /* local definitions for this program */
/**********************************************/
/* static function prototyes */
static ufix8 read_1b(ufix8* ptr);
static fix31 read_4b(ufix8* ptr);
static fix15 read_2b(ufix8* ptr);
static void place_char( char c );
/**********************************************/
/* external data used by the output routines */
extern POINT points_per_pixel;
extern int PixelsperInch_x,PixelsperInch_y,
Point_x,Point_y,
Value_xy,Value_yx;
extern short color0, color1, color2;
/**********************************************/
/* static data used by the input routines */
static ufix16 ORUs_per_em;
static ufix8* font_buffer = NULL; /* Pointer to allocated Font buffer */
static ufix8* char_buffer = NULL; /* Pointer to allocate Character buffer */
static buff_t font; /* Buffer descriptor for font data */
static ufix16 minimum_char_buffer_size;/* minimum character buffer size */
static ufix32 minimum_buffer_size;/* minimum font buffer size to allocate */
static int first_char_index; /* Index of first character in font */
static FILE * fp = NULL; /* the font file pointer */
/* static data used by the output routines */
/* offsets of where to start the first character */
static POINT char_origin, char_shift, line_origin;
/**********************************************/
/*
origin: this routine resets the local origin values
to their initial values
*/
void origin()
{
char_origin.x = char_origin.y = 0;
line_origin.x = Point_x*points_per_pixel.x;
line_origin.y = Point_y*points_per_pixel.y;
}
/**********************************************/
/*
newline: this routine resets the local horizontal origin
to the next line (move it down by the point size )
resets the vertical to its original value
- and draws in a baseline
*/
void newline( void )
{
char_origin.x = char_origin.y = 0;
line_origin.x = Point_x*points_per_pixel.x;
line_origin.y += Point_y*points_per_pixel.y;
_setcolor( color1 );
_moveto(video.x_pixels-1, line_origin.y);
_lineto(line_origin.x, line_origin.y);
_setcolor( color0 );
}
/**********************************************/
/*
place_char: this routine take an ASCII char value,
converts it to Bitstream's character index,
tells the routine to make the char bitmap (which
causes the character to be displayed) then returns.
*/
static void place_char( char c )
{
ufix16 char_index; /* Index of character to be generated */
ufix16 char_id; /* Character ID */
if ( c == '\n' )
{
newline();
return;
}
/* Force Bitstream index to ascii */
char_index = c + first_char_index - 32;
char_id = sp_get_char_id((ufix16)char_index);
/* make the bitmap */
if ( 0 != char_id )
sp_make_char(char_index);
}
/**********************************************/
/*
place_text: this routine takes a string and
calls place_char for each character.
*/
void place_text( char * string )
{
while ( *string )
place_char( *string++ );
}
/**********************************************/
/*
start_speedo:
The call to start up the library routines,
set the parameters to generate the bitmaps we want.
The argument is the location and name of the speedo file
for the typeface we want to use.
If an error occurs, a char pointer is returned pointing
to the error message, else NULL is returned.
*/
char * start_speedo( char * pathname )
{
int bytes_read;
specs_t specs; /* Bundle of character generation specs */
ufix8 header_buffer[500]; /* Font buffer */
char text_string[128]; /* display info */
/* Load Speedo outline file */
fp = fopen (pathname, "rb");
if ( NULL == fp )
return("****** Error: Cannot open the font file");
/* read in header info */
bytes_read =
fread( header_buffer, sizeof(ufix8), sizeof(header_buffer), fp );
if ( 0 == bytes_read )
{
fclose(fp);
fp = NULL;
return("****** Error on reading font file header");
}
/* make it in terms of ORU's */
ORUs_per_em = (ufix16)read_2b(header_buffer + FH_ORUPM);
/* read the minumum buffer size for reading in characters */
minimum_buffer_size = (ufix32)read_4b(header_buffer+FH_FBFSZ);
if ( NULL != font_buffer )
free( font_buffer );
if (NULL == (font_buffer = (ufix8 *)malloc((ufix16)minimum_buffer_size)))
{
fclose(fp);
fp = NULL;
return("****** Error: Unable to allocate memory for font buffer");
}
/* now load the fonts */
fseek( fp, (ufix32)0, 0);
if (0 == (bytes_read = fread((ufix8 *)font_buffer,
sizeof(ufix8), (ufix16)minimum_buffer_size, fp) ) )
{
fclose(fp);
fp = NULL;
return("****** Error on reading the fonts from the file");
}
/* now allocate minimum character buffer */
minimum_char_buffer_size = read_2b(font_buffer+FH_CBFSZ);
if ( NULL != char_buffer )
free( char_buffer );
if (NULL == (char_buffer = (ufix8*)malloc(minimum_char_buffer_size)))
{
fclose(fp);
fp = NULL;
return("****** Error: Unable to allocate memory for character buffer");
}
font.org = font_buffer;
font.no_bytes = bytes_read;
first_char_index = read_2b(font_buffer + FH_FCHRF);
/* Initialization */
sp_reset(); /* Reset Speedo character generator */
/* Set specifications for character to be generated */
specs.pfont = &font; /* Pointer to Speedo outline structure */
specs.xoffset = 0L << 16; /* Position of X origin */
specs.yoffset = 0L << 16; /* Position of Y origin */
specs.flags = MODE_0; /* Mode flags */
specs.out_info = NULL;
/* the values are multiplied by 65,536 (shifted left 16)
to conform to the internal representation used by Speedo.
This retains high accuracy while using integer math only */
/* Calculate X */
specs.xxmult = ( (unsigned long)(Point_x*PixelsperInch_x)<< 16 )
/(unsigned long)72;
/* Calculate Y */
specs.yymult = ( (unsigned long)(Point_y*PixelsperInch_y) <<16 )
/(unsigned long)72;
/* Coeff of Y to calculate X pixels */
specs.xymult = (unsigned long)(Value_xy)<< 16;
/* Coeff of X to calculate Y pixels */
specs.yxmult = (unsigned long)(Value_yx)<< 16;
/* OK, now call into the library with these settings */
if ( !sp_set_specs(&specs) )
{
fclose(fp);
fp = NULL;
return("****** Cannot set requested character specs");
}
/* all went well */
/* print out some info telling what the values
of the parameters are on the top of the screen */
_settextposition(1,1);
_settextcolor(6);
sprintf( text_string, "%s X point = %d Y Point = %d xyvalue = %u yxvalue = %u ",
(char *)(header_buffer + FH_FNTNM),Point_x, Point_y,Value_xy,Value_yx);
_outtext( text_string );
return( NULL );
}
/*** Now begins the routines required to use Speedo ***/
/**********************************************/
/*
sp_set_bitmap_bits:
Three arguments, the horizontal raster line, followed
by the beginning and ending vertical positions for
a line to be drawn. This is the routine that actually draws
the character.
*/
void sp_set_bitmap_bits( fix15 y, fix15 x1, fix15 x2 )
{
POINT start, stop;
/* convert from speedo bits to screen pixels */
start.x = line_origin.x + char_origin.x + x1;
stop.x = line_origin.x + char_origin.x + x2 - 1;
start.y = stop.y = line_origin.y - char_origin.y + y;
_moveto( start.x, start.y );
_lineto( stop.x, stop.y );
}
/**********************************************/
/*
sp_open_bitmap:
The first call to start a character, we save the set_widths
so we can move the current cahr position when we are done,
The origins are where we initially offset the char from the
starting location (some leading space), and the size parameters
are the dimensions of the bitmap, of which we only use the
vertical since our origin system is in the upper left corner.
*/
void sp_open_bitmap( fix31 x_set_width, fix31 y_set_width,
fix31 x_org, fix31 y_org, fix15 x_size, fix15 y_size )
{
/* save the x and y set widths so we know where
the next char is to start */
/* use integer math to retain accuracy */
char_shift.x = (int)( (x_set_width+32768)/(65536) );
char_shift.y = (int)( (y_set_width+32768)/(65536) );
/* add in the leading spacing for this bitmap */
char_origin.x += (int)( (x_org+(fix31)32768) / (fix31)65536 );
char_origin.y = y_size + (int)( (y_org+(fix31)32768) / (fix31)65536 );
}
/**********************************************/
/*
sp_close_bitmap:
The last call for a character, we use the set_widths
we saved to move the current point to the end of the
character we just drew, in preparation for the next one.
*/
void sp_close_bitmap( void )
{
/* we are done with this character, so
update the current char origin */
char_origin.x += char_shift.x;
char_origin.y += char_shift.y;
}
/**********************************************/
/*
sp_report_error:
The library calls this when an error occurs.
*/
void sp_report_error( fix15 error_number )
{
/*
the following are SPEEDO errors that
can be generated during calls to various
library routines.
*/
static char *message[] =
{
"Insufficient font data loaded",
"?",
"Transformation matrix out of range",
"Font format error",
"Requested specs not compatible with selected output module",
"?",
"Intelligent scaling requested but not supported",
"Unsupported output module requested",
"Extended font loaded but only compact font supported",
"Font specs not set prior to use",
"?",
"Character not available",
"Track kerning request rejected due to absence of required data in font",
"Pair kerning request rejected due to absence of required data in font"
};
/* reset video mode */
RESET_VIDEO_MODE;
/* display the error message */
printf( message[error_number-1] );
printf("\n");
exit(2); /* quit the program */
}
/**********************************************/
/*
sp_load_char_data:
This routine is to provide dynamic character loading
so that memory is conserved. It is not necessary
to use dynamic loading if you don't mind reading in the
enire font file at once, but most people will be interested
in trading speed for using less memory.
All it does is read in the requested number of bytes (no_bytes)
from the file at an offset (file_offset) into the location
in the character buffer (cb_offset).
It returns a pointer to the buffer.
*/
buff_t *sp_load_char_data( fix31 file_offset,
fix15 no_bytes, fix15 cb_offset)
{
/* Buffer descriptor for character data must be static
since we are passing back a pointer to it */
static buff_t char_data;
int bytes_read;
if ( NULL == fp )
{
RESET_VIDEO_MODE;
printf( "SP_LOAD_CHAR_DATA ERROR file never opened");
exit(1);
}
if ( 0 != fseek( fp, (long)file_offset, (int)0 ) )
{
RESET_VIDEO_MODE;
printf( "SP_LOAD_CHAR_DATA ERROR in seeking character");
fclose( fp );
fp = NULL;
exit( 1 );
}
if ( (no_bytes + cb_offset) > minimum_char_buffer_size )
{
RESET_VIDEO_MODE;
printf( "SP_LOAD_CHAR_DATA ERROR Character buffer overflow");
fclose( fp );
fp = NULL;
exit( 1 );
}
bytes_read = fread( (char_buffer + cb_offset), sizeof(ufix8), no_bytes, fp);
if ( bytes_read != no_bytes )
{
RESET_VIDEO_MODE;
printf( "SP_LOAD_CHAR_DATA ERROR on reading character data");
fclose( fp );
fp = NULL;
exit( 1 );
}
char_data.org = (ufix8 FONTFAR *)char_buffer + cb_offset;
char_data.no_bytes = no_bytes;
return( &char_data );
}
/**********************************************/
/*
functions patterned from some in Bitstream's nsample.c
program that read one, two, and four bytes
from the font buffer
*/
static ufix8 read_1b( ufix8 *pointer ) /* 1 byte */
{
return *pointer;
}
static fix15 read_2b( ufix8 *pointer ) /* 2 bytes */
{
fix31 temp;
temp = *pointer++;
temp = (temp << 8) + *(pointer);
return( (fix15)temp );
}
static fix31 read_4b( ufix8 *pointer ) /* 4 bytes */
{
fix31 temp;
temp = *pointer++;
temp = (temp << 8) + *(pointer++);
temp = (temp << 8) + *(pointer++);
temp = (temp << 8) + *(pointer );
return( temp );
}
Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!
This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.
But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/