From 241e151eb2e97d01734d8f52693b404943b3a765 Mon Sep 17 00:00:00 2001 From: David Turner Date: Sun, 28 May 2000 17:15:37 +0000 Subject: [PATCH] oops, forgot to commit these files --- demos/src/ftmulti.c | 809 ++++++++++++++++++++++++++++++++++++++++++++ src/sfnt/sfobjs.c | 499 +++++++++++++++++++++++++++ src/sfnt/sfobjs.h | 45 +++ 3 files changed, 1353 insertions(+) create mode 100644 demos/src/ftmulti.c create mode 100644 src/sfnt/sfobjs.c create mode 100644 src/sfnt/sfobjs.h diff --git a/demos/src/ftmulti.c b/demos/src/ftmulti.c new file mode 100644 index 000000000..77e3e1dbc --- /dev/null +++ b/demos/src/ftmulti.c @@ -0,0 +1,809 @@ +/****************************************************************************/ +/* */ +/* The FreeType project -- a free and portable quality TrueType renderer. */ +/* */ +/* Copyright 1996-1999 by */ +/* D. Turner, R.Wilhelm, and W. Lemberg */ +/* */ +/* */ +/* FTMulti- a simple multiple masters font viewer */ +/* */ +/* Press F1 when running this program to have a list of key-bindings */ +/* */ +/****************************************************************************/ + +#include +#include +#include +#include + +#include "common.h" + +#include +#include +#include +#include + +#include "graph.h" +#include "grfont.h" + +#define DIM_X 500 +#define DIM_Y 400 + +#define CENTER_X (bit.width/2) +#define CENTER_Y (bit.rows/2) + +#define MAXPTSIZE 500 /* dtp */ + + char Header[128]; + char* new_header = 0; + + const unsigned char* Text = (unsigned char*) +"The quick brown fox jumped over the lazy dog 0123456789 \ +\342\352\356\373\364\344\353\357\366\374\377\340\371\351\350\347 \ +&#~\"\'(-`_^@)=+\260 ABCDEFGHIJKLMNOPQRSTUVWXYZ \ +$\243^\250*\265\371%!\247:/;.,?<>"; + FT_Library library; /* the FreeType library */ + FT_Face face; /* the font face */ + FT_Size size; /* the font size */ + FT_GlyphSlot glyph; /* the glyph slot */ + + FT_Error error; /* error returned by FreeType ? */ + + grSurface* surface; /* current display surface */ + grBitmap bit; /* current display bitmap */ + + int num_glyphs; /* number of glyphs */ + int ptsize; /* current point size */ + + int hinted = 1; /* is glyph hinting active ? */ + int antialias = 1; /* is anti-aliasing active ? */ + int use_sbits = 1; /* do we use embedded bitmaps ? */ + int low_prec = 0; /* force low precision */ + int Num; /* current first glyph index */ + + int res = 72; + + static grColor fore_color = { 255 }; + + int Fail; + unsigned char autorun; + + int graph_init = 0; + + int render_mode = 1; + int use_grays = 1; + + /* the standard raster's interface */ + FT_Raster_Funcs std_raster; + + FT_Multi_Master multimaster; + FT_Long design_pos[ T1_MAX_MM_AXIS ]; + +#define RASTER_BUFF_SIZE 32768 + char raster_buff[ RASTER_BUFF_SIZE ]; + +#define DEBUGxxx + +#ifdef DEBUG +#define LOG(x) LogMessage##x +#else +#define LOG(x) /* rien */ +#endif + +#ifdef DEBUG + static void LogMessage( const char* fmt, ... ) + { + va_list ap; + + va_start( ap, fmt ); + vfprintf( stderr, fmt, ap ); + va_end( ap ); + } +#endif + + /* PanicZ */ + static void PanicZ( const char* message ) + { + fprintf( stderr, "%s\n error = 0x%04x\n", message, error ); + exit(1); + } + + + /* Clears the Bit bitmap/pixmap */ + static void Clear_Display( void ) + { + long size = (long)bit.pitch * bit.rows; + + if (size < 0) size = -size; + memset( bit.buffer, 0, size ); + } + + + /* Initialize the display bitmap named Bit */ + static int Init_Display() + { + grInitDevices(); + + bit.mode = gr_pixel_mode_gray; + bit.width = DIM_X; + bit.rows = DIM_Y; + bit.grays = 256; + + surface = grNewSurface( 0, &bit ); + if (!surface) + PanicZ( "could not allocate display surface\n" ); + + graph_init = 1; + return 0; + } + + +#define MAX_BUFFER 300000 + +#define FLOOR(x) ((x) & -64) +#define CEIL(x) (((x)+63) & -64) +#define TRUNC(x) ((x) >> 6) + + static + char bit_buffer[ MAX_BUFFER ]; + + /* Render a single glyph with the "grays" component */ + static FT_Error Render_Glyph( int x_offset, + int y_offset ) + { + /* first, render the glyph into an intermediate buffer */ + FT_Bitmap bit2; + grBitmap bit3; + int width, height, pitch, size; + int left, right, top, bottom; + int x_top, y_top; + + left = FLOOR( glyph->metrics.horiBearingX ); + right = CEIL( glyph->metrics.horiBearingX + glyph->metrics.width ); + width = TRUNC(right - left); + + top = CEIL( glyph->metrics.horiBearingY ); + bottom = FLOOR( glyph->metrics.horiBearingY - glyph->metrics.height ); + height = TRUNC( top - bottom ); + + if ( glyph->format == ft_glyph_format_outline ) + { + pitch = ( antialias ? (width+3) & -4 : (width+7) >> 3 ); + size = pitch*height; + + if (size > MAX_BUFFER) + return FT_Err_Out_Of_Memory; + + bit2.width = width; + bit2.rows = height; + bit2.pitch = pitch; + bit2.pixel_mode = antialias ? ft_pixel_mode_grays : ft_pixel_mode_mono; + bit2.buffer = bit_buffer; + + bit3.rows = bit2.rows; + bit3.width = bit2.width; + bit3.pitch = bit2.pitch; + bit3.mode = antialias ? bit.mode : gr_pixel_mode_mono; + bit3.buffer = bit_buffer; + bit3.grays = 256; + + FT_Outline_Translate( &glyph->outline, -left, -bottom ); + memset( bit_buffer, 0, size ); + + if (low_prec) + glyph->outline.flags &= ~ft_outline_high_precision; + + error = FT_Outline_Get_Bitmap( library, &glyph->outline, &bit2 ); + } + else + { + bit3.rows = glyph->bitmap.rows; + bit3.width = glyph->bitmap.width; + bit3.pitch = glyph->bitmap.pitch; + bit3.mode = gr_pixel_mode_mono; + bit3.buffer = glyph->bitmap.buffer; + bit3.grays = 0; + } + + /* Then, blit the image to the target surface */ + x_top = x_offset + TRUNC(left); + y_top = y_offset - TRUNC(top); + +/* + if (bit.pitch < 0) + y_top = bit.rows - y_top; +*/ + grBlitGlyphToBitmap( &bit, &bit3, x_top, y_top, fore_color ); + return 0; + } + + static FT_Error Reset_Scale( int pointSize ) + { + FT_Error error; + + error = FT_Set_Char_Size( face, pointSize << 6, + pointSize << 6, + res, + res ); + if ( error ) + { + } + return FT_Err_Ok; + } + + + static FT_Error LoadChar( int idx, int hint ) + { + int flags; + + flags = FT_LOAD_DEFAULT; + + if ( !hint ) + flags |= FT_LOAD_NO_HINTING; + + if ( !use_sbits ) + flags |= FT_LOAD_NO_BITMAP; + + return FT_Load_Glyph( face, idx, flags ); + } + + + + static FT_Error Render_All( int first_glyph, int ptsize ) + { + FT_F26Dot6 start_x, start_y, step_x, step_y, x, y; + int i; + + FT_Error error; + + start_x = 4; + start_y = 36 + ptsize ; + + step_x = size->metrics.x_ppem + 4; + step_y = size->metrics.y_ppem + 10; + + x = start_x; + y = start_y; + + i = first_glyph; + +#if 0 + while ( i < first_glyph+1 ) +#else + while ( i < num_glyphs ) +#endif + { + if ( !(error = LoadChar( i, hinted )) ) + { + #ifdef DEBUG + if (i <= first_glyph+6) + { + LOG(( "metrics[%02d] = [%x %x]\n", + i, + glyph->metrics.horiBearingX, + glyph->metrics.horiAdvance )); + + if (i == first_glyph+6) + LOG(( "-------------------------\n")); + } + #endif + + Render_Glyph( x, y ); + + x += ( glyph->metrics.horiAdvance >> 6 ) + 1; + + if ( x + size->metrics.x_ppem > bit.width ) + { + x = start_x; + y += step_y; + + if ( y >= bit.rows ) + return FT_Err_Ok; + } + } + else + Fail++; + + i++; + } + + return FT_Err_Ok; + } + + + static FT_Error Render_Text( int first_glyph, int ptsize ) + { + FT_F26Dot6 start_x, start_y, step_x, step_y, x, y; + int i; + + FT_Error error; + const unsigned char* p; + + start_x = 4; + start_y = 32 + size->metrics.y_ppem; + + step_x = size->metrics.x_ppem + 4; + step_y = size->metrics.y_ppem + 10; + + x = start_x; + y = start_y; + + i = first_glyph; + p = Text; + while (i > 0 && *p) { p++; i--; } + + while ( *p ) + { + if ( !(error = LoadChar( FT_Get_Char_Index( face, (unsigned char)*p ), hinted )) ) + { + #ifdef DEBUG + if (i <= first_glyph+6) + { + LOG(( "metrics[%02d] = [%x %x]\n", + i, + glyph->metrics.horiBearingX, + glyph->metrics.horiAdvance )); + + if (i == first_glyph+6) + LOG(( "-------------------------\n")); + } + #endif + + Render_Glyph( x, y ); + + x += ( glyph->metrics.horiAdvance >> 6 ) + 1; + + if ( x + size->metrics.x_ppem > bit.width ) + { + x = start_x; + y += step_y; + + if ( y >= bit.rows ) + return FT_Err_Ok; + } + } + else + Fail++; + + i++; + p++; + } + + return FT_Err_Ok; + } + + + static void Help( ) + { + grEvent dummy_event; + + Clear_Display(); + grGotoxy( 0, 0 ); + grSetMargin( 2, 1 ); + grGotobitmap( &bit ); + + grWriteln("FreeType Glyph Viewer - part of the FreeType test suite" ); + grLn(); + grWriteln("This program is used to display all glyphs from one or" ); + grWriteln("several font files, with the FreeType library."); + grLn(); + grWriteln("Use the following keys :"); + grLn(); + grWriteln(" F1 or ? : display this help screen" ); + grWriteln(" a : toggle anti-aliasing" ); + grWriteln(" h : toggle outline hinting" ); + grWriteln(" b : toggle embedded bitmaps" ); + grWriteln(" l : toggle low precision rendering" ); + grWriteln(" g : toggle between 'smooth' and 'standard' anti-aliaser" ); + grWriteln(" space : toggle rendering mode" ); + grLn(); + grWriteln(" Up : increase pointsize by 1 unit" ); + grWriteln(" Down : decrease pointsize by 1 unit" ); + grWriteln(" Page Up : increase pointsize by 10 units" ); + grWriteln(" Page Down : decrease pointsize by 10 units" ); + grLn(); + grWriteln(" Right : increment first glyph index" ); + grWriteln(" Left : decrement first glyph index" ); + grLn(); + grWriteln(" F3 : decrement first axis position by 20" ); + grWriteln(" F4 : increment first axis position by 20" ); + grWriteln(" F3 : decrement second axis position by 20" ); + grWriteln(" F4 : increment second axis position by 20" ); + grWriteln(" F3 : decrement third axis position by 20" ); + grWriteln(" F4 : increment third axis position by 20" ); + grLn(); + grWriteln("press any key to exit this help screen"); + + grRefreshSurface( surface ); + grListenSurface( surface, gr_event_key, &dummy_event ); + } + + static void reset_raster( void ) + { + if ( antialias && use_grays ) + FT_Set_Raster( library, &ft_grays_raster ); + else + FT_Set_Raster( library, &std_raster ); + } + + + static int Process_Event( grEvent* event ) + { + int i, axis; + + switch ( event->key ) + { + case grKeyEsc: /* ESC or q */ + case grKEY('q'): + return 0; + + case grKEY('a'): + antialias = !antialias; + new_header = ( antialias + ? "anti-aliasing is now on" + : "anti-aliasing is now off" ); + reset_raster(); + return 1; + + case grKEY('b'): + use_sbits = !use_sbits; + new_header = ( use_sbits + ? "embedded bitmaps are now used when available" + : "embedded bitmaps are now ignored" ); + return 1; + + case grKEY('n'): + case grKEY('p'): + return (int)event->key; + + case grKEY('g'): + use_grays = !use_grays; + new_header = ( use_grays + ? "now using the smooth anti-aliaser" + : "now using the standard anti-aliaser" ); + reset_raster(); + break; + + case grKEY('l'): + low_prec = !low_prec; + new_header = ( low_prec + ? "rendering precision is now forced to low" + : "rendering precision is now normal" ); + break; + + case grKEY('h'): + hinted = !hinted; + new_header = ( hinted + ? "glyph hinting is now active" + : "glyph hinting is now ignored" ); + break; + + case grKEY(' '): + render_mode ^= 1; + new_header = ( render_mode + ? "rendering all glyphs in font" + : "rendering test text string" ); + break; + + case grKeyF1: + case grKEY('?'): + Help(); + return 1; + + case grKeyF3: i = -20; axis = 0; goto Do_Axis; + case grKeyF4: i = 20; axis = 0; goto Do_Axis; + case grKeyF5: i = -20; axis = 1; goto Do_Axis; + case grKeyF6: i = 20; axis = 1; goto Do_Axis; + case grKeyF7: i = -20; axis = 2; goto Do_Axis; + case grKeyF8: i = 20; axis = 2; goto Do_Axis; + + case grKeyPageUp: i = 10; goto Do_Scale; + case grKeyPageDown: i = -10; goto Do_Scale; + case grKeyUp: i = 1; goto Do_Scale; + case grKeyDown: i = -1; goto Do_Scale; + + case grKeyLeft: i = -1; goto Do_Glyph; + case grKeyRight: i = 1; goto Do_Glyph; + case grKeyF9: i = -100; goto Do_Glyph; + case grKeyF10: i = 100; goto Do_Glyph; + case grKeyF11: i = -1000; goto Do_Glyph; + case grKeyF12: i = 1000; goto Do_Glyph; + default: + ; + } + return 1; + + Do_Axis: + if (axis < multimaster.num_axis) + { + FT_MM_Axis* a = multimaster.axis + axis; + FT_Long pos = design_pos[axis]; + + pos += i; + if (pos < a->minimum) pos = a->minimum; + if (pos > a->maximum) pos = a->maximum; + + design_pos[axis] = pos; + + FT_Set_MM_Design_Coordinates( face, multimaster.num_axis, design_pos ); + } + return 1; + + Do_Scale: + ptsize += i; + if (ptsize < 1) ptsize = 1; + if (ptsize > MAXPTSIZE) ptsize = MAXPTSIZE; + return 1; + + Do_Glyph: + Num += i; + if (Num < 0) Num = 0; + if (Num >= num_glyphs) Num = num_glyphs-1; + return 1; + } + + + + static void usage( char* execname ) + { + fprintf( stderr, "\n" ); + fprintf( stderr, "ftmulti: multiple masters font viewer - part of FreeType\n" ); + fprintf( stderr, "--------------------------------------------------------\n" ); + fprintf( stderr, "\n" ); + fprintf( stderr, "Usage: %s [options below] ppem fontname[.ttf|.ttc] ...\n", + execname ); + fprintf( stderr, "\n" ); + fprintf( stderr, " -r R use resolution R dpi (default: 72 dpi)\n" ); + fprintf( stderr, " -f index specify first glyph index to display\n" ); + fprintf( stderr, "\n" ); + + exit( 1 ); + } + + + int main( int argc, char** argv ) + { + int i, old_ptsize, orig_ptsize, file; + int first_glyph = 0; + int XisSetup = 0; + char filename[128 + 4]; + char alt_filename[128 + 4]; + char* execname; + int option; + int file_loaded; + + FT_Error error; + grEvent event; + + execname = ft_basename( argv[0] ); + + while ( 1 ) + { + option = getopt( argc, argv, "f:r:" ); + + if ( option == -1 ) + break; + + switch ( option ) + { + case 'f': + first_glyph = atoi( optarg ); + break; + + case 'r': + res = atoi( optarg ); + if ( res < 1 ) + usage( execname ); + break; + + default: + usage( execname ); + break; + } + } + + argc -= optind; + argv += optind; + + if ( argc <= 1 ) + usage( execname ); + + if ( sscanf( argv[0], "%d", &orig_ptsize ) != 1 ) + orig_ptsize = 64; + + file = 1; + + /* Initialize engine */ + error = FT_Init_FreeType( &library ); + if (error) PanicZ( "Could not initialise FreeType library" ); + + /* retrieve the standard raster's interface */ + (void)FT_Get_Raster( library, ft_glyph_format_outline, &std_raster ); + reset_raster(); + + NewFile: + ptsize = orig_ptsize; + hinted = 1; + file_loaded = 0; + +#ifndef macintosh + i = strlen( argv[file] ); + while ( i > 0 && argv[file][i] != '\\' && argv[file][i] != '/' ) + { + if ( argv[file][i] == '.' ) + i = 0; + i--; + } +#endif + + filename[128] = '\0'; + alt_filename[128] = '\0'; + + strncpy( filename, argv[file], 128 ); + strncpy( alt_filename, argv[file], 128 ); + +#ifndef macintosh + if ( i >= 0 ) + { + strncpy( filename + strlen( filename ), ".ttf", 4 ); + strncpy( alt_filename + strlen( alt_filename ), ".ttc", 4 ); + } +#endif + + /* Load face */ + error = FT_New_Face( library, filename, 0, &face ); + if (error) goto Display_Font; + + /* retrieve multiple master information */ + error = FT_Get_Multi_Master( face, &multimaster ); + if (error) goto Display_Font; + + /* set the current position to the minimum of each axis */ + { + int n; + + for ( n = 0; n < multimaster.num_axis; n++ ) + design_pos[n] = + (multimaster.axis[n].minimum + multimaster.axis[n].maximum)/2; + } + + error = FT_Set_MM_Design_Coordinates( face, multimaster.num_axis, design_pos ); + if (error) goto Display_Font; + + file_loaded++; + + error = Reset_Scale( ptsize ); + if (error) goto Display_Font; + + num_glyphs = face->num_glyphs; + glyph = face->glyph; + size = face->size; + + Display_Font: + /* initialise graphics if needed */ + if ( !XisSetup ) + { + XisSetup = 1; + Init_Display(); + } + + grSetTitle( surface, "FreeType Glyph Viewer - press F1 for help" ); + old_ptsize = ptsize; + + if ( file_loaded >= 1 ) + { + Fail = 0; + Num = first_glyph; + + if ( Num >= num_glyphs ) + Num = num_glyphs-1; + + if ( Num < 0 ) + Num = 0; + } + + for ( ;; ) + { + int key; + + Clear_Display(); + + if ( file_loaded >= 1 ) + { + switch (render_mode) + { + case 0: + Render_Text( Num, ptsize ); + break; + + default: + Render_All( Num, ptsize ); + } + + sprintf( Header, "%s %s (file %s)", + face->family_name, + face->style_name, + ft_basename( filename ) ); + + if (!new_header) + new_header = Header; + + grWriteCellString( &bit, 0, 0, new_header, fore_color ); + new_header = 0; + + sprintf( Header, "axis: " ); + { + int n; + for ( n = 0; n < multimaster.num_axis; n++ ) + { + char temp[32]; + sprintf( temp, " %s:%ld", multimaster.axis[n].name, design_pos[n] ); + strcat( Header, temp ); + } + } + grWriteCellString( &bit, 0, 16, Header, fore_color ); + + sprintf( Header, "at %d points, first glyph = %d", + ptsize, + Num ); + } + else + { + sprintf( Header, "%s : is not a multiple masters font file or could not be opened", + ft_basename(filename) ); + } + + grWriteCellString( &bit, 0, 8, Header, fore_color ); + grRefreshSurface( surface ); + + grListenSurface( surface, 0, &event ); + if ( !( key = Process_Event( &event ) ) ) + goto Fin; + + if ( key == 'n' ) + { + if (file_loaded >= 1) + FT_Done_Face( face ); + + if ( file < argc - 1 ) + file++; + + goto NewFile; + } + + if ( key == 'p' ) + { + if (file_loaded >= 1) + FT_Done_Face( face ); + + if ( file > 1 ) + file--; + + goto NewFile; + } + + if ( ptsize != old_ptsize ) + { + if ( Reset_Scale( ptsize ) ) + PanicZ( "Could not resize font." ); + + old_ptsize = ptsize; + } + } + + Fin: +#if 0 + grDoneSurface(surface); + grDone(); +#endif + printf( "Execution completed successfully.\n" ); + printf( "Fails = %d\n", Fail ); + + exit( 0 ); /* for safety reasons */ + return 0; /* never reached */ +} + + +/* End */ + diff --git a/src/sfnt/sfobjs.c b/src/sfnt/sfobjs.c new file mode 100644 index 000000000..e0c833e0c --- /dev/null +++ b/src/sfnt/sfobjs.c @@ -0,0 +1,499 @@ +#include +#include +#include + + /*************************************************************************/ + /* */ + /* */ + /* Get_Name */ + /* */ + /* */ + /* Returns a given ENGLISH name record in ASCII. */ + /* */ + /* */ + /* face :: A handle to the source face object. */ + /* */ + /* nameid :: The name id of the name record to return. */ + /* */ + /* */ + /* Char string. NULL if no name is present. */ + /* */ + static + FT_String* Get_Name( TT_Face face, + FT_UShort nameid ) + { + FT_Memory memory = face->root.memory; + FT_UShort n; + TT_NameRec* rec; + FT_Bool wide_chars = 1; + + /* first pass, look for a given name record */ + rec = face->name_table.names; + for ( n = 0; n < face->name_table.numNameRecords; n++, rec++ ) + { + if ( rec->nameID == nameid ) + { + /* found the name - now create an ASCII string from it */ + FT_Bool found = 0; + + /* Test for Microsoft English language */ + if ( rec->platformID == TT_PLATFORM_MICROSOFT && + rec->encodingID <= TT_MS_ID_UNICODE_CS && + (rec->languageID & 0x3FF) == 0x009 ) + found = 1; + + /* Test for Apple Unicode encoding */ + else if ( rec->platformID == TT_PLATFORM_APPLE_UNICODE ) + found = 1; + + /* Test for Apple Roman */ + else if ( rec->platformID == TT_PLATFORM_MACINTOSH && + rec->languageID == TT_MAC_ID_ROMAN ) + { + found = 1; + wide_chars = 0; + } + + /* Found a Unicode Name */ + if ( found ) + { + FT_String* string; + FT_UInt len; + + if ( wide_chars ) + { + TT_UInt m; + + len = (TT_UInt)rec->stringLength / 2; + if ( MEM_Alloc( string, len + 1 ) ) + return NULL; + + for ( m = 0; m < len; m ++ ) + string[m] = rec->string[2*m + 1]; + } + else + { + len = rec->stringLength; + if ( MEM_Alloc( string, len + 1 ) ) + return NULL; + + MEM_Copy( string, rec->string, len ); + } + + string[len] = '\0'; + return string; + } + } + } + return NULL; + } + + + static + FT_Encoding find_encoding( int platform_id, + int encoding_id ) + { + typedef struct TEncoding + { + int platform_id; + int encoding_id; + FT_Encoding encoding; + + } TEncoding; + + static + const TEncoding tt_encodings[] = + { + { TT_PLATFORM_ISO, -1, ft_encoding_unicode }, + + { TT_PLATFORM_APPLE_UNICODE, -1, ft_encoding_unicode }, + + { TT_PLATFORM_MACINTOSH, TT_MAC_ID_ROMAN, ft_encoding_apple_roman }, + + { TT_PLATFORM_MICROSOFT, TT_MS_ID_UNICODE_CS, ft_encoding_unicode }, + { TT_PLATFORM_MICROSOFT, TT_MS_ID_SJIS, ft_encoding_sjis }, + { TT_PLATFORM_MICROSOFT, TT_MS_ID_BIG_5, ft_encoding_big5 } + }; + + const TEncoding *cur, *limit; + + cur = tt_encodings; + limit = cur + sizeof(tt_encodings)/sizeof(tt_encodings[0]); + + for ( ; cur < limit; cur++ ) + { + if (cur->platform_id == platform_id) + { + if (cur->encoding_id == encoding_id || + cur->encoding_id == -1 ) + return cur->encoding; + } + } + return ft_encoding_none; + } + + + + + LOCAL_FUNC + FT_Error SFNT_Init_Face( FT_Stream stream, + TT_Face face, + TT_Int face_index, + TT_Int num_params, + FT_Parameter* params ) + { + FT_Error error; + SFNT_Interface* sfnt; + PSNames_Interface* psnames; + + /* for now, parameters are unused */ + UNUSED(num_params); + UNUSED(params); + + sfnt = (SFNT_Interface*)face->sfnt; + if (!sfnt) + { + /* look-up the SFNT driver */ + FT_Driver sfnt_driver; + + sfnt_driver = FT_Get_Driver( face->root.driver->library, "sfnt" ); + if (!sfnt_driver) + { + error = FT_Err_Invalid_File_Format; + goto Exit; + } + + sfnt = (SFNT_Interface*)(sfnt_driver->interface.format_interface); + if (!sfnt) + { + error = FT_Err_Invalid_File_Format; + goto Exit; + } + + face->sfnt = sfnt; + face->goto_table = sfnt->goto_table; + } + + psnames = (PSNames_Interface*)face->psnames; + if (!psnames) + { + /* look-up the PSNames driver */ + FT_Driver psnames_driver; + + psnames_driver = FT_Get_Driver( face->root.driver->library, "psnames" ); + if (psnames_driver) + face->psnames = (PSNames_Interface*) + (psnames_driver->interface.format_interface); + } + + /* check that we have a valid TrueType file */ + error = sfnt->load_format_tag( face, stream, face_index, + &face->format_tag ); + if (error) goto Exit; + + /* Load font directory */ + error = sfnt->load_directory( face, stream, face_index ); + if ( error ) goto Exit; + + face->root.num_faces = face->ttc_header.DirCount; + if ( face->root.num_faces < 1 ) + face->root.num_faces = 1; + + Exit: + return error; + } + + + +#undef LOAD_ +#define LOAD_(x) ( (error = sfnt->load_##x( face, stream )) != FT_Err_Ok ) + + + LOCAL_FUNC + TT_Error SFNT_Load_Face( FT_Stream stream, + TT_Face face, + TT_Int face_index, + TT_Int num_params, + FT_Parameter* params ) + { + FT_Error error; + SFNT_Interface* sfnt = (SFNT_Interface*)face->sfnt; + + /* Load tables */ + if ( LOAD_( header ) || + LOAD_( max_profile ) || + + (error = sfnt->load_metrics( face, stream, 0 )) != FT_Err_Ok || + /* load the `hhea' & `hmtx' tables at once */ + + (error = sfnt->load_metrics( face, stream, 1 )) != FT_Err_Ok || + /* try to load the `vhea' & `vmtx' at once if present */ + + LOAD_( charmaps ) || + LOAD_( names ) || + LOAD_( os2 ) || + LOAD_( psnames ) ) + goto Exit; + + /* the optional tables */ + + /* embedded bitmap support. */ +#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS + if (sfnt->load_sbits && LOAD_(sbits)) goto Exit; +#endif + + if ( LOAD_( hdmx ) || + LOAD_( gasp ) || + LOAD_( kerning ) || + LOAD_( pclt ) ) + goto Exit; + +#ifdef TT_CONFIG_OPTION_EXTEND_ENGINE + if ( ( error = TT_Extension_Create( face ) ) != FT_Err_Ok ) + goto Exit; +#endif + + face->root.family_name = Get_Name( face, TT_NAME_ID_FONT_FAMILY ); + face->root.style_name = Get_Name( face, TT_NAME_ID_FONT_SUBFAMILY ); + + /* now set up root fields */ + { + FT_Face root = &face->root; + FT_Int flags; + TT_CharMap charmap; + TT_Int n; + FT_Memory memory; + + memory = root->memory; + + /*****************************************************************/ + /* */ + /* Compute face flags. */ + /* */ + flags = FT_FACE_FLAG_SCALABLE | /* scalable outlines */ + FT_FACE_FLAG_SFNT | /* SFNT file format */ + FT_FACE_FLAG_HORIZONTAL; /* horizontal data */ + + /* fixed width font ? */ + if ( face->postscript.isFixedPitch ) + flags |= FT_FACE_FLAG_FIXED_WIDTH; + + /* vertical information ? */ + if ( face->vertical_info ) + flags |= FT_FACE_FLAG_VERTICAL; + + /* kerning available ? */ + if ( face->kern_pairs ) + flags |= FT_FACE_FLAG_KERNING; + + root->face_flags = flags; + + /*****************************************************************/ + /* */ + /* Compute style flags. */ + /* */ + flags = 0; + + if ( face->os2.version != 0xFFFF ) + { + /* We have an OS/2 table, use the `fsSelection' field */ + if ( face->os2.fsSelection & 1 ) + flags |= FT_STYLE_FLAG_ITALIC; + + if ( face->os2.fsSelection & 32 ) + flags |= FT_STYLE_FLAG_BOLD; + } + else + { + /* This is an old Mac font, use the header field */ + if ( face->header.Mac_Style & 1 ) + flags |= FT_STYLE_FLAG_BOLD; + + if ( face->header.Mac_Style & 2 ) + flags |= FT_STYLE_FLAG_ITALIC; + } + + face->root.style_flags = flags; + + /*****************************************************************/ + /* */ + /* Polish the charmaps. */ + /* */ + /* Try to set the charmap encoding according to the platform & */ + /* encoding ID of each charmap. */ + /* */ + charmap = face->charmaps; + root->num_charmaps = face->num_charmaps; + + /* allocate table of pointers */ + if ( ALLOC_ARRAY( root->charmaps, root->num_charmaps, FT_CharMap ) ) + goto Exit; + + for ( n = 0; n < root->num_charmaps; n++, charmap++ ) + { + FT_Int platform = charmap->cmap.platformID; + FT_Int encoding = charmap->cmap.platformEncodingID; + + charmap->root.face = (FT_Face)face; + charmap->root.platform_id = platform; + charmap->root.encoding_id = encoding; + charmap->root.encoding = find_encoding(platform,encoding); + + /* now, set root->charmap with a unicode charmap wherever available */ + if (!root->charmap && charmap->root.encoding == ft_encoding_unicode) + root->charmap = (FT_CharMap)charmap; + + root->charmaps[n] = (FT_CharMap)charmap; + } + +#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS + if ( face->num_sbit_strikes ) + { + face->root.num_fixed_sizes = face->num_sbit_strikes; + if ( ALLOC_ARRAY( face->root.available_sizes, + face->num_sbit_strikes, + FT_Bitmap_Size ) ) + return error; + + for ( n = 0 ; n < face->num_sbit_strikes ; n++ ) + { + face->root.available_sizes[n].width = + face->sbit_strikes[n].x_ppem; + face->root.available_sizes[n].height = + face->sbit_strikes[n].y_ppem; + } + } + else +#else + { + root->num_fixed_sizes = 0; + root->available_sizes = 0; + } +#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ + + /*****************************************************************/ + /* */ + /* Set up metrics. */ + /* */ + root->bbox.xMin = face->header.xMin; + root->bbox.yMin = face->header.yMin; + root->bbox.xMax = face->header.xMax; + root->bbox.yMax = face->header.yMax; + root->units_per_EM = face->header.Units_Per_EM; + + /* The ascender/descender/height are computed from the OS/2 table */ + /* when found. Otherwise, they're taken from the horizontal header */ + if ( face->os2.version != 0xFFFF ) + { + root->ascender = face->os2.sTypoAscender; + root->descender = -face->os2.sTypoDescender; + root->height = root->ascender + root->descender + + face->os2.sTypoLineGap; + } + else + { + root->ascender = face->horizontal.Ascender; + root->descender = face->horizontal.Descender; + root->height = root->ascender + root->descender + + face->horizontal.Line_Gap; + } + + root->max_advance_width = face->horizontal.advance_Width_Max; + + root->max_advance_height = root->height; + if ( face->vertical_info ) + root->max_advance_height = face->vertical.advance_Height_Max; + + root->underline_position = face->postscript.underlinePosition; + root->underline_thickness = face->postscript.underlineThickness; + + /* root->max_points - already set up */ + /* root->max_contours - already set up */ + } + + Exit: + return error; + } + + +#undef LOAD_ + + + LOCAL_FUNC + void SFNT_Done_Face( TT_Face face ) + { + FT_Memory memory = face->root.memory; + SFNT_Interface* sfnt = face->sfnt; + + if (sfnt) + { + /* destroy the postscript names table if it is supported */ + if (sfnt->free_psnames) + sfnt->free_psnames( face ); + + /* destroy the embedded bitmaps table if it is supported */ + if (sfnt->free_sbits) + sfnt->free_sbits( face ); + } + + /* freeing the kerning table */ + FREE( face->kern_pairs ); + face->num_kern_pairs = 0; + + /* freeing the collection table */ + FREE( face->ttc_header.TableDirectory ); + face->ttc_header.DirCount = 0; + + /* freeing table directory */ + FREE( face->dir_tables ); + face->num_tables = 0; + + /* freeing the character mapping tables */ + if (sfnt && sfnt->load_charmaps ) + { + FT_UShort n; + for ( n = 0; n < face->num_charmaps; n++ ) + sfnt->free_charmap( face, &face->charmaps[n].cmap ); + } + + FREE( face->charmaps ); + face->num_charmaps = 0; + + FREE( face->root.charmaps ); + face->root.num_charmaps = 0; + face->root.charmap = 0; + + /* freeing the horizontal metrics */ + FREE( face->horizontal.long_metrics ); + FREE( face->horizontal.short_metrics ); + + /* freeing the vertical ones, if any */ + if ( face->vertical_info ) + { + FREE( face->vertical.long_metrics ); + FREE( face->vertical.short_metrics ); + face->vertical_info = 0; + } + + /* freeing the gasp table */ + FREE( face->gasp.gaspRanges ); + face->gasp.numRanges = 0; + + /* freeing the name table */ + sfnt->free_names( face ); + + /* freeing the hdmx table */ + sfnt->free_hdmx( face ); + + /* freeing family and style name */ + FREE( face->root.family_name ); + FREE( face->root.style_name ); + + /* freeing sbit size table */ + face->root.num_fixed_sizes = 0; + if ( face->root.available_sizes ) + FREE( face->root.available_sizes ); + + face->sfnt = 0; + } + diff --git a/src/sfnt/sfobjs.h b/src/sfnt/sfobjs.h new file mode 100644 index 000000000..193cc9b90 --- /dev/null +++ b/src/sfnt/sfobjs.h @@ -0,0 +1,45 @@ +/***************************************************************************/ +/* */ +/* sfobjs.h */ +/* */ +/* SFNT object management */ +/* */ +/* Copyright 1996-1999 by */ +/* David Turner, Robert Wilhelm, and Werner Lemberg. */ +/* */ +/* This file is part of the FreeType project, and may only be used, */ +/* modified, and distributed under the terms of the FreeType project */ +/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ +/* this file you indicate that you have read the license and */ +/* understand and accept it fully. */ +/* */ +/***************************************************************************/ + +#ifndef SFOBJS_H +#define SFOBJS_H + +#include +#include + + LOCAL_DEF + FT_Error SFNT_Init_Face( FT_Stream stream, + TT_Face face, + TT_Int face_index, + TT_Int num_params, + FT_Parameter* params ); + + LOCAL_DEF + FT_Error SFNT_Load_Face( FT_Stream stream, + TT_Face face, + TT_Int face_index, + TT_Int num_params, + FT_Parameter* params ); + + LOCAL_DEF + void SFNT_Done_Face( TT_Face face ); + + +#endif /* SFDRIVER_H */ + + +/* END */