ref: 241e151eb2e97d01734d8f52693b404943b3a765
parent: 2e421319fc4bedef44218fc144b1186ea53df584
author: David Turner <[email protected]>
date: Sun May 28 13:15:37 EDT 2000
oops, forgot to commit these files
--- /dev/null
+++ b/demos/src/ftmulti.c
@@ -1,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 <freetype/freetype.h>
+#include <freetype/ftraster.h>
+#include <freetype/ftgrays.h>
+#include <freetype/ftmm.h>
+
+#include "common.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+
+#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 */
+
--- /dev/null
+++ b/src/sfnt/sfobjs.c
@@ -1,0 +1,499 @@
+#include <freetype/internal/sfnt.h>
+#include <freetype/internal/psnames.h>
+#include <freetype/ttnameid.h>
+
+ /*************************************************************************/
+ /* */
+ /* <Function> */
+ /* Get_Name */
+ /* */
+ /* <Description> */
+ /* Returns a given ENGLISH name record in ASCII. */
+ /* */
+ /* <Input> */
+ /* face :: A handle to the source face object. */
+ /* */
+ /* nameid :: The name id of the name record to return. */
+ /* */
+ /* <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;
+ }
+
--- /dev/null
+++ b/src/sfnt/sfobjs.h
@@ -1,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 <freetype/internal/sfnt.h>
+#include <freetype/internal/ftobjs.h>
+
+ 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 */