home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: SysTools
/
SysTools.zip
/
ft-beta.zip
/
freetype
/
test
/
zoom.c
< prev
Wrap
C/C++ Source or Header
|
1997-10-06
|
17KB
|
583 lines
/****************************************************************************/
/* */
/* The FreeType project - a free and portable quality TrueType renderer. */
/* */
/* Copyright 1996, 1997 by */
/* D. Turner, R.Wilhelm, and W. Lemberg */
/* */
/* zoom : A simple glyph viewer. Now supports graylevel rendering */
/* with the '-g' option. */
/* */
/* use -p <platformID> together with -e <encodingID> to select */
/* a cmap; */
/* */
/* */
/* Keys : */
/* */
/* x : fine counter_clockwise rotation */
/* c : fine clockwise rotation */
/* */
/* v : fast counter_clockwise rotation */
/* b : fast clockwise rotation */
/* */
/* + : fast scale up */
/* - : fast scale down */
/* u : fine scale down */
/* j : fine scale up */
/* */
/* l : go to next glyph */
/* k : go to previous glyph */
/* */
/* o : go to tenth next glyph */
/* i : go to tenth previous glyph */
/* */
/* 0 : go to hundredth next glyph */
/* 9 : go to hundredth previous glyph */
/* */
/* q : */
/* ESC : exit */
/* */
/* */
/* NOTE : This is just a test program that is used to show off and */
/* debug the current engine; which is still in alpha. In no */
/* way does it shows the final high-level interface that */
/* client applications will use. Wait for at least a beta for */
/* this. */
/* */
/****************************************************************************/
#ifdef ARM
#include "std.h"
#include "graflink.h"
#endif
#include "freetype.h"
#include "tterror.h" /* for Panic() and Message() only */
#include "ft_conf.h" /* This is needed to have getopt() and getind() */
/* working on Solaris. We should be able to remove */
/* this line on other platforms... */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
/* getopt() should be in either getopt.h, stdlib.h, or unistd.h */
/* The following is needed before the #include <unistd.h> */
/* with my school's Suns to have 'getopt' working - DavidT */
#if defined(__sun__)
#define __EXTENSIONS__
#endif
#ifdef HAVE_GETOPT_H
#include <getopt.h>
#else
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#endif
#include "gmain.h"
#include "gevents.h"
#include "gdriver.h"
#ifdef ARM
#include "armsup.c" /* pull in our routines */
#endif
/* The SunOS header files do not provide external declarations for `optarg' */
/* and `optind', so declare them here if necessary. A check to see if the */
/* GNU C library is being used on SunOS should be added at some point. If */
/* The GNU C library is being used, these declarations are not necessary. */
#if defined(__sun__) && !defined(SVR4) && !defined(__SVR4)
extern char *optarg;
extern int optind;
#endif
#define Pi 3.1415926535
#define MAXPTSIZE 500 /* dtp */
char Header[128];
TT_Face face;
TT_Instance instance;
TT_Glyph org_glyph; /* original glyph */
TT_Glyph glyph; /* rotated glyph */
TT_CharMap char_map;
TT_Glyph_Metrics metrics;
TT_Glyph_Outline org_outline; /* original glyph outline */
TT_Glyph_Outline outline; /* rotated glyph oultine */
TT_Face_Properties properties;
TT_Instance_Metrics imetrics;
int num_glyphs;
int xcenter_upem;
int ycenter_upem;
int units_per_em;
int ptsize;
int old_ptsize;
int rotation;
int old_rotation;
TT_Matrix matrix;
int apply_matrix;
int xcenter;
int ycenter;
int xoffset;
int yoffset;
TT_Raster_Map Bit;
int Fail;
int Num;
int Code;
unsigned char autorun;
int gray_render = 0;
int hinted = 1;
int use_cmap = 0;
static void ClearData( void );
char palette[5] = { 0, 1, 2, 3, 4 };
void Init_Raster_Area()
{
Bit.rows = vio_Height; /* The whole window */
Bit.width = vio_Width;
Bit.flow = TT_Flow_Up;
if ( gray_render )
{
Bit.cols = Bit.width;
Bit.size = Bit.rows * Bit.width;
}
else
{
Bit.cols = ( Bit.width + 7 ) / 8; /* convert to # of bytes */
Bit.size = Bit.rows * Bit.cols; /* number of bytes in buffer */
}
Bit.bitmap = (void*)malloc( (int)Bit.size );
if ( !Bit.bitmap )
Panic( "ERROR: Not enough memory to allocate bitmap!\n" );
ClearData();
}
static void ClearData()
{
if ( gray_render )
memset( Bit.bitmap, gray_palette[0], Bit.size );
else
memset( Bit.bitmap, 0, Bit.size );
}
static TT_Error Reset_PtSize( int pointSize )
{
TT_Error error;
if ( (error = TT_Set_Instance_PointSize( instance, pointSize )) )
{
RestoreScreen();
Message( "error = %d\n", error );
Panic( "could not reset instance\n" );
}
TT_Get_Instance_Metrics( instance, &imetrics );
xcenter = imetrics.x_ppem * xcenter_upem / units_per_em / 4;
ycenter = imetrics.y_ppem * ycenter_upem / units_per_em / 4;
xoffset = vio_Width/2 - xcenter;
yoffset = vio_Height/2 - ycenter;
return TT_Err_Ok;
}
static void Copy_Outline( TT_Glyph_Outline* from,
TT_Glyph_Outline* to )
{
int n;
to->points = from->points;
to->contours = from->contours;
n = from->points * sizeof(TT_F26Dot6 );
memcpy( to->xCoord, from->xCoord, n );
memcpy( to->yCoord, from->yCoord, n );
memcpy( to->flag, from->flag, from->points );
n = from->contours * sizeof(short);
memcpy( to->conStarts, from->conStarts, n );
}
static TT_Error Reset_Rotation( int rotation )
{
/* TT_Error error; */
Copy_Outline( &org_outline, &outline );
if ( rotation )
{
float angle;
/* error = TT_Set_Instance_Transforms( instance, 1, 0 ); */
/* it seems that rotation support is somehow broken, I'll have */
/* a finer look at that next week.. - David */
angle = rotation * Pi / 512;
matrix.xx = (TT_Fixed) (cos( angle ) * (1<<16));
matrix.xy = (TT_Fixed) (sin( angle ) * (1<<16));
matrix.yx = - matrix.xy;
matrix.yy = matrix.xx;
apply_matrix = 1;
}
else
apply_matrix = 0;
return TT_Err_Ok;
}
static TT_Error LoadTrueTypeChar( int idx, int hint )
{
TT_Error error;
int flags;
flags = TTLOAD_SCALE_GLYPH;
if ( hint )
flags |= TTLOAD_HINT_GLYPH;
error = TT_Load_Glyph( instance, glyph, idx, flags );
if (!error && apply_matrix)
{
TT_Get_Glyph_Outline( glyph, &outline );
TT_Apply_Outline_Translation( &outline, -xcenter*64, -ycenter*64 );
TT_Apply_Outline_Matrix( &outline, &matrix );
TT_Apply_Outline_Translation( &outline, xcenter*64, ycenter*64 );
}
return error;
}
TT_Error ConvertRaster()
{
if ( gray_render )
return TT_Get_Glyph_Pixmap( glyph, &Bit, xoffset*64, yoffset*64 );
else
return TT_Get_Glyph_Bitmap( glyph, &Bit, xoffset*64, yoffset*64 );
}
int Process_Event( TEvent* event )
{
switch ( event->what )
{
case event_Quit: /* ESC or q */
return 0;
case event_Keyboard:
if ( event->info == 'h' ) /* Toggle hinting */
hinted = !hinted;
break;
case event_Rotate_Glyph:
rotation = ( rotation + event->info ) & 1023;
break;
case event_Scale_Glyph:
ptsize += event->info;
if ( ptsize < 1 ) ptsize = 1;
if ( ptsize > MAXPTSIZE ) ptsize = MAXPTSIZE;
break;
case event_Change_Glyph:
Code += event->info;
if ( Code < 0 ) Code = 0;
if ( Code >= num_glyphs ) Code = num_glyphs - 1;
break;
}
return 1;
}
void usage( char* execname )
{
Message( "\n" );
Message( "Zoom: simple TrueType glyph viewer - part of the FreeType project\n" );
Message( "-----------------------------------------------------------------\n" );
Message( "\n" );
Message( "Usage: %s [options below] -fontname[.ttf|.ttc]\n", execname );
Message( "\n" );
Message( " -g gray-level rendering (default: none)\n" );
Message( " -p id platform id (default: none)\n" );
Message( " -e id encoding id (default: none)\n" );
Message( " If either -p or -e is not set, no cmap will be used.\n" );
Message( "\n" );
exit( 1 );
}
/* stack check dtp */
int main( int argc, char** argv )
{
int i, xpos, ypos;
int platform = -1, encoding = -1;
char filename[128 + 4];
char alt_filename[128 + 4];
char* execname;
int option;
TT_Error error;
TEvent event;
execname = argv[0];
gray_render = 0;
while ( 1 )
{
option = getopt( argc, argv, "e:gp:" );
if ( option == -1 )
break;
switch ( option )
{
case 'e':
encoding = atoi( optarg );
break;
case 'g':
gray_render = 1;
break;
case 'p':
platform = atoi( optarg );
break;
default:
usage( execname );
break;
}
}
if ( optind == argc )
usage( execname );
i = strlen( argv[optind] );
while ( i > 0 && argv[optind][i] != '\\' && argv[optind][i] != '/' )
{
if ( argv[optind][i] == '.' )
i = 0;
i--;
}
filename[128] = '\0';
alt_filename[128] = '\0';
strncpy( filename, argv[optind], 128 );
strncpy( alt_filename, argv[optind], 128 );
if ( i >= 0 )
{
strncpy( filename + strlen( filename ), ".ttf", 4 );
strncpy( alt_filename + strlen( alt_filename ), ".ttc", 4 );
}
if ( platform >= 0 || encoding >= 0 )
use_cmap = 1;
/* Initialization */
TT_Init_FreeType();
/* Load face */
error = TT_Open_Face( filename, &face );
if ( error == TT_Err_Could_Not_Open_File )
{
strcpy( filename, alt_filename );
error = TT_Open_Face( alt_filename, &face );
}
if ( error )
Panic( "ERROR: could not find/open %s\n", filename );
/* get face properties and allocate preload arrays */
TT_Get_Face_Properties( face, &properties );
num_glyphs = properties.num_Glyphs;
xcenter_upem = (properties.header->xMax - properties.header->xMin) / 2;
ycenter_upem = (properties.header->yMax - properties.header->yMin) / 2;
units_per_em = properties.header->Units_Per_EM;
/* create glyph */
error = TT_New_Glyph( face, &org_glyph );
if ( error )
Panic( "ERROR: could not create glyph container\n" );
error = TT_New_Glyph( face, &glyph );
if ( error )
Panic( "ERROR: could not create glyph container\n" );
/* create instance */
error = TT_New_Instance( face, &instance );
if ( error )
Panic( "ERROR: could not create instance for %s\n", filename );
error = TT_Set_Instance_Resolution( instance, 96, 96 );
if ( error )
Panic( "ERROR: could not set device resolutions" );
if ( gray_render )
{
if ( !SetGraphScreen( Graphics_Mode_Gray ) )
Panic( "ERROR: could not set up grayscale graphics mode\n" );
TT_Set_Raster_Gray_Palette( gray_palette );
}
else
{
if ( !SetGraphScreen( Graphics_Mode_Mono ) )
Panic( "ERROR: could not set up mono graphics mode\n" );
}
Init_Raster_Area();
old_ptsize = ptsize = 150;
old_rotation = rotation = 0;
Reset_PtSize ( ptsize );
Reset_Rotation( rotation );
if ( use_cmap )
{
int num_cmap;
short cmap_plat;
short cmap_enc;
num_cmap = TT_Get_CharMap_Count( face );
for ( i = 0; i < num_cmap; i++ )
{
error = TT_Get_CharMap_ID( face, i, &cmap_plat, &cmap_enc );
if ( error )
Panic( "ERROR: cannot query cmap, error=%d\n", error );
if ( cmap_plat == platform && cmap_enc == encoding )
break;
}
if ( i == num_cmap )
Panic( "ERROR: invalid platform and/or encoding ID\n" );
error = TT_Get_CharMap( face, i, &char_map );
if ( error )
Panic( "ERROR: cannot load cmap, error=%d\n", error );
num_glyphs = 1<<16;
}
Code = 0;
autorun = 0;
Fail = 0;
xpos = 0;
ypos = 0;
for ( ;; )
{
ClearData();
if ( ptsize != old_ptsize )
{
Reset_PtSize( ptsize );
old_ptsize = ptsize;
}
if ( rotation != old_rotation )
{
Reset_Rotation( rotation );
old_rotation = rotation;
}
if ( use_cmap )
Num = TT_Char_Index( char_map, Code );
else
Num = Code;
if ( (error = LoadTrueTypeChar( Num, hinted )) == TT_Err_Ok )
{
ConvertRaster();
sprintf( Header, "glyph index = %3d, char code = 0x%x",
Num, Code );
}
else {
Fail++;
sprintf( Header, "glyph index = %3d, (ERROR) %x",
Num, error );
}
Display_Bitmap_On_Screen( Bit.bitmap, Bit.rows, Bit.cols );
#ifndef X11
#ifndef OS2
Print_XY( 20, 0, Header );
#endif
#endif
#if 0
if ( autorun )
{
xpos += cur_AdvanceWidth;
if ( xpos + cur_AdvanceWidth > 640 )
{
xpos = 0;
ypos += ( cur_Ascent - cur_Descent ) / 64;
/* is == TRUETYPE DEFINED Precision */
}
Num = autorun++;
if( !autorun )
{
xpos = 0;
ypos += ( cur_Ascent - cur_Descent ) / 64;
/* is == TRUETYPE DEFINED Precision */
}
}
else
#endif
{
Get_Event( &event );
if ( !Process_Event( &event ) ) goto Fin;
}
}
Fin:
RestoreScreen();
TT_Done_FreeType();
Message( "fails = %d\n", Fail );
return 0;
}