/******************************************************************* * * ttapi.c * * High-level interface implementation * * 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. * * Notes: * * This file is used to implement most of the functions that are * defined in the file "freetype.h". However, two functions are * implemented elsewhere : * * TT_MulDiv and TT_MulFix are in ttcalc.h/ttcalc.c * ******************************************************************/ #include "ttconfig.h" #include "freetype.h" #include "ttengine.h" #include "ttcalc.h" #include "ttmemory.h" #include "ttcache.h" #include "ttfile.h" #include "ttobjs.h" #include "ttload.h" #include "ttgload.h" #include "ttraster.h" #include "ttextend.h" /* required by the tracing mode */ #undef TT_COMPONENT #define TT_COMPONENT trace_api #ifdef TT_STATIC_RASTER #define RAS_OPS /* void */ #define RAS_OP /* void */ #else #define RAS_OPS ((TRaster_Instance*)_engine->raster_component), #define RAS_OP ((TRaster_Instance*)_engine->raster_component) #endif /* TT_STATIC_RASTER */ #define RENDER_Glyph( glyph, target ) \ Render_Glyph( RAS_OPS glyph, target ) #define RENDER_Gray_Glyph( glyph, target, palette ) \ Render_Gray_Glyph( RAS_OPS glyph, target, palette ) /******************************************************************* * * Function : TT_FreeType_Version * * Description : Returns the major and minor version of the library. * * Input : major, minor addresses * * Output : Error code. * * MT-Note : YES! * ******************************************************************/ EXPORT_FUNC TT_Error TT_FreeType_Version( int *major, int *minor ) { if ( !major || !minor ) return TT_Err_Invalid_Argument; *major = TT_FREETYPE_MAJOR; *minor = TT_FREETYPE_MINOR; return TT_Err_Ok; } /******************************************************************* * * Function : TT_Init_FreeType * * Description : The library's engine initializer. This function * must be called prior to any call. * * Input : engine pointer to a FreeType engine instance * * Output : Error code. * * MT-Note : This function should be called each time you want * to create a TT_Engine. It is not necessarily thread * safe depending on the implementations of ttmemory, * ttfile and ttmutex, so take care. Their default * implementations are safe, however. * ******************************************************************/ EXPORT_FUNC TT_Error TT_Init_FreeType( TT_Engine* engine ) { PEngine_Instance _engine; TT_Error error; int n; /* first of all, initialize memory sub-system */ error = TTMemory_Init(); if ( error ) return error; /* Allocate engine instance */ if ( ALLOC( _engine, sizeof ( TEngine_Instance ) ) ) return error; #undef TT_FAIL #define TT_FAIL( x ) ( error = x (_engine) ) != TT_Err_Ok /* Initalize components */ if ( TT_FAIL( TTFile_Init ) || TT_FAIL( TTCache_Init ) || #ifdef TT_CONFIG_OPTION_EXTEND_ENGINE TT_FAIL( TTExtend_Init ) || #endif TT_FAIL( TTObjs_Init ) || TT_FAIL( TTRaster_Init ) ) goto Fail; #undef TT_FAIL /* set the gray palette defaults: 0 to 4 */ for ( n = 0; n < 5; n++ ) _engine->raster_palette[n] = (Byte)n; /* Conversion ok, some warn */ /* create the engine lock */ MUTEX_Create( _engine->lock ); HANDLE_Set( *engine, _engine ); return TT_Err_Ok; Fail: TT_Done_FreeType( *engine ); HANDLE_Set( *engine, NULL ); return error; } /******************************************************************* * * Function : TT_Done_FreeType * * Description : The library's engine finalizer. This function * will discard all active face and glyph objects * from the heap. * * Input : engine FreeType engine instance * * Output : Error code. * * MT-Note : Destroys an engine. Not necessarily thread-safe * depending on the implementations of ttmemory, * ttfile and ttmutex. The default implementations * are safe, however. * ******************************************************************/ EXPORT_FUNC TT_Error TT_Done_FreeType( TT_Engine engine ) { PEngine_Instance _engine = HANDLE_Engine( engine ); if ( !_engine ) return TT_Err_Ok; MUTEX_Destroy( _engine->lock ); TTRaster_Done( _engine ); TTObjs_Done ( _engine ); #ifdef TT_CONFIG_OPTION_EXTEND_ENGINE TTExtend_Done( _engine ); #endif TTCache_Done ( _engine ); TTFile_Done ( _engine ); FREE( _engine ); TTMemory_Done(); return TT_Err_Ok; } #ifdef TT_CONFIG_OPTION_GRAY_SCALING /******************************************************************* * * Function : TT_Set_Raster_Gray_Palette * * Description : Sets the gray-levels palette used for font * smoothing. * * Input : engine FreeType engine instance * palette address of palette (a 5 byte array) * * Output : Invalid argument if 'palette' is NULL. * * MT-Note: NO! Unprotected modification of an engine's palette. * ******************************************************************/ EXPORT_FUNC TT_Error TT_Set_Raster_Gray_Palette( TT_Engine engine, Byte* palette ) { int i; if ( !palette ) return TT_Err_Invalid_Argument; for ( i = 0; i < 5; i++ ) HANDLE_Engine( engine )->raster_palette[i] = (Byte)palette[i]; return TT_Err_Ok; } #endif /* TT_CONFIG_OPTION_GRAY_SCALING */ /******************************************************************* * * Function : TT_Open_Face * * Description : Creates a new face object from a given font file. * * Input : engine FreeType engine instance * fontPathName the font file's pathname * face adress of returned face handle * * Output : Error code. * * Note : The face handle is set to NULL in case of failure. * * MT-Note : YES! * ******************************************************************/ EXPORT_FUNC TT_Error TT_Open_Face( TT_Engine engine, const TT_Text* fontPathName, TT_Face* face ) { PEngine_Instance _engine = HANDLE_Engine( engine ); TFont_Input input; TT_Error error; TT_Stream stream; PFace _face; if ( !_engine ) return TT_Err_Invalid_Engine; /* open the file */ error = TT_Open_Stream( fontPathName, &stream ); if ( error ) return error; input.stream = stream; input.fontIndex = 0; input.engine = _engine; /* Create and load the new face object - this is thread-safe */ error = CACHE_New( _engine->objs_face_cache, _face, &input ); /* Set the handle */ HANDLE_Set( *face, _face ); if ( error ) goto Fail; return TT_Err_Ok; Fail: TT_Close_Stream( &stream ); return error; } /******************************************************************* * * Function : TT_Open_Collection * * Description : Creates a new face object from a given font file. * * Input : engine FreeType engine instance * collectionPathName the font file's pathname * fontIndex index of font in TrueType collection * face adress of returned face handle * * Output : Error code. * * Note : The face handle is set to NULL in case of failure. * * MT-Note : YES! * ******************************************************************/ EXPORT_FUNC TT_Error TT_Open_Collection( TT_Engine engine, const TT_Text* collectionPathName, TT_ULong fontIndex, TT_Face* face ) { PEngine_Instance _engine = HANDLE_Engine( engine ); TFont_Input input; TT_Error error; TT_Stream stream; PFace _face; if ( !_engine ) return TT_Err_Invalid_Engine; /* open the file */ error = TT_Open_Stream( collectionPathName, &stream ); if ( error ) return error; input.stream = stream; input.fontIndex = fontIndex; input.engine = _engine; /* Create and load the new face object - this is thread-safe */ error = CACHE_New( _engine->objs_face_cache, _face, &input ); /* Set the handle */ HANDLE_Set( *face, _face ); if ( error ) goto Fail; return TT_Err_Ok; Fail: TT_Close_Stream( &stream ); return error; } /******************************************************************* * * Function : TT_Get_Face_Properties * * Description : Returns face properties. * * Input : face the face handle * properties address of target properties record * * Output : Error code. * * Note : Currently, max_Faces is always set to 0. * * MT-Note : YES! Reads only permanent data. * ******************************************************************/ EXPORT_FUNC TT_Error TT_Get_Face_Properties( TT_Face face, TT_Face_Properties* properties ) { PFace _face = HANDLE_Face( face ); if ( !_face ) return TT_Err_Invalid_Face_Handle; properties->num_Glyphs = _face->numGlyphs; properties->max_Points = _face->maxPoints; properties->max_Contours = _face->maxContours; properties->num_CharMaps = _face->numCMaps; properties->num_Names = _face->nameTable.numNameRecords; if ( _face->ttcHeader.DirCount == 0 ) properties->num_Faces = 1; else properties->num_Faces = _face->ttcHeader.DirCount; properties->header = &_face->fontHeader; properties->horizontal = &_face->horizontalHeader; if ( _face->verticalInfo ) properties->vertical = &_face->verticalHeader; else properties->vertical = NULL; properties->os2 = &_face->os2; properties->postscript = &_face->postscript; properties->hdmx = &_face->hdmx; return TT_Err_Ok; } /******************************************************************* * * Function : TT_Set_Face_Pointer * * Description : Each face object has one pointer, which use is * reserved to client applications. The TrueType * engine never accesses or uses this field. * * This function is used to set the pointer. * * Input : face the given face handle * data the generic pointer value * * Output : Error code. * * MT-Note : NO! But this function is reserved to "enlightened" * developers, so it shouldn't be a problem. * ******************************************************************/ EXPORT_FUNC TT_Error TT_Set_Face_Pointer( TT_Face face, void* data ) { PFace faze = HANDLE_Face( face ); if ( !faze ) return TT_Err_Invalid_Face_Handle; else faze->generic = data; return TT_Err_Ok; } /******************************************************************* * * Function : TT_Get_Face_Pointer * * Description : Each face object has one pointer, which use is * reserved to client applications. The TrueType * engine never access or use this field. * * This function is used to read the pointer. * * Input : face the given face handle * data the generic pointer value * * Output : Error code. * * MT-Note : NO! But this function is reserved to "enlightened" * developers, so it shouldn't be a problem. * ******************************************************************/ EXPORT_FUNC void* TT_Get_Face_Pointer( TT_Face face ) { PFace faze = HANDLE_Face( face ); if ( !faze ) return NULL; else return faze->generic; } /******************************************************************* * * Function : TT_Get_Face_Metrics * * Description : This function returns the original horizontal AND * vertical metrics as found in the "hmtx" and "vmtx" * tables. These are the glyphs' left-side-bearings * and advance widths (horizontal), as well as top * side bearings and advance heights (vertical). * * All are expressed in FONT UNITS, a.k.a. EM * units. * * Input : face The given face handle. * first Index of first glyph in table. * last Index of last glyph in table. * * leftBearings A pointer to an array of TT_Shorts where the * left side bearings for the glyphs 'first' * to 'last' will be returned. If these metrics * don't interest you, simply set it to NULL. * * widths A pointer to an array of TT_UShorts * where the advance widths for the glyphs * 'first' to 'last' will be returned. If these * metrics don't interest you, simply set it * to NULL. * * topBearings A pointer to an array of TT_Shorts where the * top side bearings for the glyphs 'first' * to 'last' will be returned. If these metrics * don't interest you, simply set it to NULL. * * heights A pointer to an array of TT_UShorts * where the advance heights for the glyphs * 'first' to 'last' will be returned. If these * metrics don't interest you, simply set it * to NULL. * * Output : Error code. * * IMPORTANT NOTE : * * As vertical metrics are optional in a TrueType font, this * function will return an error ( TT_Err_No_Vertical_Data ) * whenever this function is called on such a face with non-NULL * 'topBearings' or 'heights' arguments. * * When a font has no vertical data, the 'vertical' field in its * properties structure is set to NULL. * * MT-Note : YES! Reads only permanent data. * ******************************************************************/ EXPORT_FUNC TT_Error TT_Get_Face_Metrics( TT_Face face, TT_UShort firstGlyph, TT_UShort lastGlyph, TT_Short* leftBearings, TT_UShort* widths, TT_Short* topBearings, TT_UShort* heights ) { PFace _face = HANDLE_Face( face ); UShort num; if ( !_face ) return TT_Err_Invalid_Face_Handle; /* Check the glyph range */ if ( lastGlyph >= _face->numGlyphs || firstGlyph > lastGlyph ) return TT_Err_Invalid_Argument; num = lastGlyph - firstGlyph; /* number of elements-1 in each array */ /* store the left side bearings and advance widths first */ { UShort n; Short left_bearing; UShort advance_width; for ( n = 0; n <= num; n++ ) { TT_Get_Metrics( &_face->horizontalHeader, firstGlyph + n, &left_bearing, &advance_width ); if ( leftBearings ) leftBearings[n] = left_bearing; if ( widths ) widths[n] = advance_width; } } /* check for vertical data if topBearings or heights is non-NULL */ if ( !topBearings && !heights ) return TT_Err_Ok; if ( !_face->verticalInfo ) return TT_Err_No_Vertical_Data; /* store the top side bearings */ { UShort n; Short top_bearing; UShort advance_height; for ( n = 0; n <= num; n++ ) { TT_Get_Metrics( (TT_Horizontal_Header*)&_face->verticalHeader, firstGlyph + n, &top_bearing, &advance_height ); if ( topBearings ) topBearings[n] = top_bearing; if ( heights ) heights[n] = advance_height; } } return TT_Err_Ok; } /******************************************************************* * * Function : TT_Flush_Face * * Description : This function is used to close an active face's * file handle or descriptor. This is useful to save * system resources, if your application uses tons * of fonts. * * Input : face the given face handle * * Output : Error code. * * MT-Note : YES! (If ttfile is.) * ******************************************************************/ EXPORT_FUNC TT_Error TT_Flush_Face( TT_Face face ) { PFace faze = HANDLE_Face( face ); if ( !faze ) return TT_Err_Invalid_Face_Handle; else return TT_Flush_Stream( &faze->stream ); } /******************************************************************* * * Function : TT_Close_Face * * Description : Closes an opened face object. This function * will destroy all objects associated to the * face, except the glyphs. * * Input : face the given face handle * * Output : Error code. * * NOTE : The handle is set to NULL on exit. * * MT-Note : YES! * ******************************************************************/ EXPORT_FUNC TT_Error TT_Close_Face( TT_Face face ) { PFace _face = HANDLE_Face( face ); if ( !_face ) return TT_Err_Invalid_Face_Handle; TT_Close_Stream( &_face->stream ); /* delete the face object -- this is thread-safe */ return CACHE_Done( _face->engine->objs_face_cache, _face ); } /******************************************************************* * * Function : TT_New_Instance * * Description : Creates a new instance from a given face. * * Input : face parent face handle * instance address of instance handle * * Output : Error code. * * Note : The handle is set to NULL in case of failure. * * MT-Note : YES! * ******************************************************************/ EXPORT_FUNC TT_Error TT_New_Instance( TT_Face face, TT_Instance* instance ) { TT_Error error; PFace _face = HANDLE_Face( face ); PInstance _ins; if ( !_face ) return TT_Err_Invalid_Face_Handle; /* get a new instance from the face's cache -- this is thread-safe */ error = CACHE_New( &_face->instances, _ins, _face ); HANDLE_Set( *instance, _ins ); if ( !error ) { error = Instance_Init( _ins ); if ( error ) { HANDLE_Set( *instance, NULL ); CACHE_Done( &_face->instances, _ins ); } } return error; } /******************************************************************* * * Function : TT_Set_Instance_Resolutions * * Description : Resets an instance to a new device resolution. * * Input : instance the instance handle * xResolution new horizontal device resolution in dpi * yResolution new vertical device resolution in dpi * * Output : Error code. * * Note : There is no check for overflow; with other words, * the product of glyph dimensions times the device * resolutions must have reasonable values. * * MT-Note : You should set the charsize or pixel size immediately * after this call in multi-threaded programs. This will * force the instance data to be resetted. Otherwise, you * may encounter corruption when loading two glyphs from * the same instance concurrently! * * Happily, 99.99% will do just that :-) * ******************************************************************/ EXPORT_FUNC TT_Error TT_Set_Instance_Resolutions( TT_Instance instance, TT_UShort xResolution, TT_UShort yResolution ) { PInstance ins = HANDLE_Instance( instance ); if ( !ins ) return TT_Err_Invalid_Instance_Handle; ins->metrics.x_resolution = xResolution; ins->metrics.y_resolution = yResolution; ins->valid = FALSE; /* In the case of a thread-safe implementation, we immediately */ /* call Instance_Reset in order to change the instance's variable */ /* In the case of a non-threaded build, we simply set the 'valid' */ /* flag to FALSE, which will force the instance's resetting at */ /* the next glyph loading */ return TT_Err_Ok; } /******************************************************************* * * Function : TT_Set_Instance_CharSizes * * Description : Resets an instance to new point size. * * Input : instance the instance handle * charWidth the new width in 26.6 char points * charHeight the new height in 26.6 char points * * Output : Error code. * * Note : There is no check for overflow; with other words, * the product of glyph dimensions times the device * resolution must have reasonable values. * * MT-Note : NO! This should be called only when setting/resetting * instances, so there is no need to protect. * ******************************************************************/ EXPORT_FUNC TT_Error TT_Set_Instance_CharSizes( TT_Instance instance, TT_F26Dot6 charWidth, TT_F26Dot6 charHeight ) { PInstance ins = HANDLE_Instance( instance ); if ( !ins ) return TT_Err_Invalid_Instance_Handle; if ( charWidth < 1 * 64 ) charWidth = 1 * 64; if ( charHeight < 1 * 64 ) charHeight = 1 * 64; ins->metrics.x_scale1 = ( charWidth * ins->metrics.x_resolution ) / 72; ins->metrics.x_scale2 = ins->owner->fontHeader.Units_Per_EM; ins->metrics.y_scale1 = ( charHeight * ins->metrics.y_resolution ) / 72; ins->metrics.y_scale2 = ins->owner->fontHeader.Units_Per_EM; if ( ins->owner->fontHeader.Flags & 8 ) { ins->metrics.x_scale1 = (ins->metrics.x_scale1+32) & -64; ins->metrics.y_scale1 = (ins->metrics.y_scale1+32) & -64; } ins->metrics.x_ppem = ins->metrics.x_scale1 / 64; ins->metrics.y_ppem = ins->metrics.y_scale1 / 64; if ( charWidth > charHeight ) ins->metrics.pointSize = charWidth; else ins->metrics.pointSize = charHeight; ins->valid = FALSE; return Instance_Reset( ins ); } /******************************************************************* * * Function : TT_Set_Instance_CharSize * * Description : Resets an instance to new point size. * * Input : instance the instance handle * charSize the new character size in 26.6 char points * * Output : Error code. * * Note : There is no check for overflow; with other words, * the product of glyph dimensions times the device * resolution must have reasonable values. * * MT-Note : NO! This should be called only when setting/resetting * instances, so there is no need to protect. * ******************************************************************/ EXPORT_FUNC TT_Error TT_Set_Instance_CharSize( TT_Instance instance, TT_F26Dot6 charSize ) { return TT_Set_Instance_CharSizes( instance, charSize, charSize ); } /******************************************************************* * * Function : TT_Set_Instance_PixelSizes * * Description : Resets an instance to new pixel sizes * * Input : instance the instance handle * pixelWidth the new width in pixels * pixelHeight the new height in pixels * * Output : Error code. * * Note : There is no check for overflow; with other words, * the product of glyph dimensions times the device * resolution must have reasonable values. * * MT-Note : NO! This should be called only when setting/resetting * instances, so there is no need to protect. * ******************************************************************/ EXPORT_FUNC TT_Error TT_Set_Instance_PixelSizes( TT_Instance instance, TT_UShort pixelWidth, TT_UShort pixelHeight, TT_F26Dot6 pointSize ) { PInstance ins = HANDLE_Instance( instance ); if ( !ins ) return TT_Err_Invalid_Instance_Handle; if ( pixelWidth < 1 ) pixelWidth = 1; if ( pixelHeight < 1 ) pixelHeight = 1; ins->metrics.x_ppem = pixelWidth; ins->metrics.y_ppem = pixelHeight; ins->metrics.pointSize = pointSize; ins->metrics.x_scale1 = ins->metrics.x_ppem * 64L; ins->metrics.x_scale2 = ins->owner->fontHeader.Units_Per_EM; ins->metrics.y_scale1 = ins->metrics.y_ppem * 64L; ins->metrics.y_scale2 = ins->owner->fontHeader.Units_Per_EM; ins->valid = FALSE; return Instance_Reset( ins ); } /******************************************************************* * * Function : TT_Set_Instance_Transform_Flags * * Description : Informs the interpreter about the transformations * that will be applied to the rendered glyphs. * * Input : instance the instance handle * rotated set to TRUE if the glyph are rotated * stretched set to TRUE if the glyph are stretched * * Output : Error code. * * Note : This function is deprecated! It's much better to * control hinting manually when calling TT_Load_Glyph * than relying on the font programs... * * Never use it, unless calling for trouble ;-) * * MT-Note : NO! This should be called only when setting/resetting * instances, so there is no need to protect. * ******************************************************************/ EXPORT_FUNC TT_Error TT_Set_Instance_Transform_Flags( TT_Instance instance, TT_Bool rotated, TT_Bool stretched ) { PInstance ins = HANDLE_Instance( instance ); if ( !ins ) return TT_Err_Invalid_Instance_Handle; ins->metrics.rotated = rotated; ins->metrics.stretched = stretched; ins->valid = FALSE; return TT_Err_Ok; } /******************************************************************* * * Function : TT_Get_Instance_Metrics * * Description : Returns instance metrics. * * Input : instance the instance handle * metrics address of target instance metrics record * * Output : Error code. * * MT-Note : YES! Reads only semi-permanent data. * ******************************************************************/ EXPORT_FUNC TT_Error TT_Get_Instance_Metrics( TT_Instance instance, TT_Instance_Metrics* metrics ) { PInstance ins = HANDLE_Instance( instance ); if ( !ins ) return TT_Err_Invalid_Instance_Handle; if ( !ins->valid ) Instance_Reset( ins ); metrics->pointSize = ins->metrics.pointSize; metrics->x_scale = TT_MulDiv( 0x10000, ins->metrics.x_scale1, ins->metrics.x_scale2 ); metrics->y_scale = TT_MulDiv( 0x10000, ins->metrics.y_scale1, ins->metrics.y_scale2 ); metrics->x_resolution = ins->metrics.x_resolution; metrics->y_resolution = ins->metrics.y_resolution; metrics->x_ppem = ins->metrics.x_ppem; metrics->y_ppem = ins->metrics.y_ppem; return TT_Err_Ok; } /******************************************************************* * * Function : TT_Set_Instance_Pointer * * Description : Each instance has one pointer, which use is * reserved to client applications. The TrueType * engine never accesses or uses this field. * * This function is used to set the pointer. * * Input : face the given face handle * data the generic pointer value * * Output : Error code. * * MT-Note : NO! * ******************************************************************/ EXPORT_FUNC TT_Error TT_Set_Instance_Pointer( TT_Instance instance, void* data ) { PInstance ins = HANDLE_Instance( instance ); if ( !ins ) return TT_Err_Invalid_Instance_Handle; else ins->generic = data; return TT_Err_Ok; } /******************************************************************* * * Function : TT_Get_Instance_Pointer * * Description : Each instance has one pointer, which use is * reserved to client applications. The TrueType * engine never accesses or uses this field. * * This function is used to read the pointer. * * Input : face the given face handle * data the generic pointer value * * Output : Error code. * * MT-Safe : NO! * ******************************************************************/ EXPORT_FUNC void* TT_Get_Instance_Pointer( TT_Instance instance ) { PInstance ins = HANDLE_Instance( instance ); if ( !ins ) return NULL; else return ins->generic; } /******************************************************************* * * Function : TT_Done_Instance * * Description : Closes a given instance. * * Input : instance address of instance handle * * Output : Error code. * * MT-Safe : YES! * ******************************************************************/ EXPORT_FUNC TT_Error TT_Done_Instance( TT_Instance instance ) { PInstance ins = HANDLE_Instance( instance ); if ( !ins ) return TT_Err_Invalid_Instance_Handle; /* delete the instance -- this is thread-safe */ return CACHE_Done( &ins->owner->instances, ins ); } /******************************************************************* * * Function : TT_New_Glyph * * Description : Creates a new glyph object related to a given * face. * * Input : face the face handle * glyph address of target glyph handle * * Output : Error code. * * MT-Safe : YES! * ******************************************************************/ EXPORT_FUNC TT_Error TT_New_Glyph( TT_Face face, TT_Glyph* glyph ) { TT_Error error; PFace _face = HANDLE_Face( face ); PGlyph _glyph; if ( !_face ) return TT_Err_Invalid_Face_Handle; /* get a new glyph from the face's cache -- this is thread-safe */ error = CACHE_New( &_face->glyphs, _glyph, _face ); HANDLE_Set( *glyph, _glyph ); return error; } /******************************************************************* * * Function : TT_Done_Glyph * * Description : Destroys a given glyph object. * * Input : glyph the glyph handle * * Output : Error code. * * MT-Safe : YES! * ******************************************************************/ EXPORT_FUNC TT_Error TT_Done_Glyph( TT_Glyph glyph ) { PGlyph _glyph = HANDLE_Glyph( glyph ); if ( !_glyph ) return TT_Err_Invalid_Glyph_Handle; /* delete the engine -- this is thread-safe */ return CACHE_Done( &_glyph->face->glyphs, _glyph ); } /******************************************************************* * * Function : TT_Load_Glyph * * Description : Loads a glyph. * * Input : instance the instance handle * glyph the glyph handle * glyphIndex the glyph index * loadFlags flags controlling how to load the glyph * (none, scaled, hinted, both) * * Output : Error code. * * MT-Safe : YES! * ******************************************************************/ EXPORT_FUNC TT_Error TT_Load_Glyph( TT_Instance instance, TT_Glyph glyph, TT_UShort glyphIndex, TT_UShort loadFlags ) { PInstance _ins; PGlyph _glyph; TT_Error error; _ins = HANDLE_Instance( instance ); if ( !_ins ) loadFlags &= ~(TTLOAD_SCALE_GLYPH | TTLOAD_HINT_GLYPH); if ( (loadFlags & TTLOAD_SCALE_GLYPH) == 0 ) _ins = 0; _glyph = HANDLE_Glyph( glyph ); if ( !_glyph ) return TT_Err_Invalid_Glyph_Handle; if ( _ins ) { if ( _ins->owner != _glyph->face ) return TT_Err_Invalid_Face_Handle; if ( !_ins->valid ) { /* This code can only be called in non thread-safe builds */ error = Instance_Reset( _ins ); if ( error ) return error; } } return Load_TrueType_Glyph( _ins, _glyph, glyphIndex, loadFlags ); } /******************************************************************* * * Function : TT_Get_Glyph_Outline * * Description : Returns the glyph's outline data. * * Input : glyph the glyph handle * outline address where the glyph outline will be returned * * Output : Error code. * * MT-Safe : YES! Reads only semi-permanent data. * ******************************************************************/ EXPORT_FUNC TT_Error TT_Get_Glyph_Outline( TT_Glyph glyph, TT_Outline* outline ) { PGlyph _glyph = HANDLE_Glyph( glyph ); if ( !_glyph ) return TT_Err_Invalid_Glyph_Handle; *outline = _glyph->outline; outline->owner = FALSE; return TT_Err_Ok; } /******************************************************************* * * Function : TT_Get_Glyph_Metrics * * Description : Extracts the glyph's horizontal metrics information. * * Input : glyph glyph object handle * metrics address where metrics will be returned * * Output : Error code. * * MT-Safe : NO! Glyph containers can't be shared. * ******************************************************************/ EXPORT_FUNC TT_Error TT_Get_Glyph_Metrics( TT_Glyph glyph, TT_Glyph_Metrics* metrics ) { PGlyph _glyph = HANDLE_Glyph( glyph ); if ( !_glyph ) return TT_Err_Invalid_Glyph_Handle; metrics->bbox = _glyph->metrics.bbox; metrics->bearingX = _glyph->metrics.horiBearingX; metrics->bearingY = _glyph->metrics.horiBearingY; metrics->advance = _glyph->metrics.horiAdvance; return TT_Err_Ok; } /******************************************************************* * * Function : TT_Get_Glyph_Big_Metrics * * Description : Extracts the glyph's big metrics information. * * Input : glyph glyph object handle * metrics address where big metrics will be returned * * Output : Error code. * * MT-Safe : NO! Glyph containers can't be shared. * ******************************************************************/ EXPORT_FUNC TT_Error TT_Get_Glyph_Big_Metrics( TT_Glyph glyph, TT_Big_Glyph_Metrics* metrics ) { PGlyph _glyph = HANDLE_Glyph( glyph ); if ( !_glyph ) return TT_Err_Invalid_Glyph_Handle; *metrics = _glyph->metrics; return TT_Err_Ok; } /******************************************************************* * * Function : TT_Get_Glyph_Bitmap * * Description : Produces a bitmap from a glyph outline. * * Input : glyph the glyph container's handle * map target pixmap description block * xOffset x offset in fractional pixels (26.6 format) * yOffset y offset in fractional pixels (26.6 format) * * Output : Error code. * * Note : Only use integer pixel offsets if you want to preserve * the fine hints applied to the outline. This means that * xOffset and yOffset must be multiples of 64! * * MT-Safe : NO! Glyph containers can't be shared. * ******************************************************************/ EXPORT_FUNC TT_Error TT_Get_Glyph_Bitmap( TT_Glyph glyph, TT_Raster_Map* map, TT_F26Dot6 xOffset, TT_F26Dot6 yOffset ) { PEngine_Instance _engine; TT_Engine engine; TT_Error error; PGlyph _glyph = HANDLE_Glyph( glyph ); TT_Outline outline; if ( !_glyph ) return TT_Err_Invalid_Glyph_Handle; _engine = _glyph->face->engine; HANDLE_Set( engine, _engine ); outline = _glyph->outline; /* XXX : For now, use only dropout mode 2 */ /* outline.dropout_mode = _glyph->scan_type; */ outline.dropout_mode = 2; TT_Translate_Outline( &outline, xOffset, yOffset ); error = TT_Get_Outline_Bitmap( engine, &outline, map ); TT_Translate_Outline( &outline, -xOffset, -yOffset ); return error; } #ifdef TT_CONFIG_OPTION_GRAY_SCALING /******************************************************************* * * Function : TT_Get_Glyph_Pixmap * * Description : Produces a grayscaled pixmap from a glyph * outline. * * Input : glyph the glyph container's handle * map target pixmap description block * xOffset x offset in fractional pixels (26.6 format) * yOffset y offset in fractional pixels (26.6 format) * * Output : Error code. * * Note : Only use integer pixel offsets to preserve the fine * hinting of the glyph and the 'correct' anti-aliasing * (where vertical and horizontal stems aren't grayed). * This means that xOffset and yOffset must be multiples * of 64! * * You can experiment with offsets of +32 to get 'blurred' * versions of the glyphs (a nice effect at large sizes that * some graphic designers may appreciate :) * * MT-Safe : NO! Glyph containers can't be shared. * ******************************************************************/ EXPORT_FUNC TT_Error TT_Get_Glyph_Pixmap( TT_Glyph glyph, TT_Raster_Map* map, TT_F26Dot6 xOffset, TT_F26Dot6 yOffset ) { PEngine_Instance _engine; TT_Engine engine; TT_Error error; PGlyph _glyph = HANDLE_Glyph( glyph ); TT_Outline outline; if ( !_glyph ) return TT_Err_Invalid_Glyph_Handle; _engine = _glyph->face->engine; HANDLE_Set(engine,_engine); outline = _glyph->outline; /* XXX : For now, use only dropout mode 2 */ /* outline.dropout_mode = _glyph->scan_type; */ outline.dropout_mode = 2; TT_Translate_Outline( &outline, xOffset, yOffset ); error = TT_Get_Outline_Pixmap( engine, &outline, map ); TT_Translate_Outline( &outline, -xOffset, -yOffset ); return error; } #endif /* TT_CONFIG_OPTION_GRAY_SCALING */ static const TT_Outline null_outline = { 0, 0, NULL, NULL, NULL, 0, 0, 0, 0 }; /******************************************************************* * * Function : TT_New_Outline * * Description : Creates a new TrueType outline, reserving * array space for a given number of points and * contours. * * Input : numPoints number of points * numContours number of contours * outline address of target outline structure * * Output : Error code * * MT-Safe : YES! * ******************************************************************/ EXPORT_FUNC TT_Error TT_New_Outline( TT_UShort numPoints, TT_Short numContours, TT_Outline* outline ) { TT_Error error; if ( !outline ) return TT_Err_Invalid_Argument; *outline = null_outline; if ( ALLOC( outline->points, numPoints*2*sizeof ( TT_F26Dot6 ) ) || ALLOC( outline->flags, numPoints *sizeof ( Byte ) ) || ALLOC( outline->contours, numContours*sizeof ( UShort ) ) ) goto Fail; outline->n_points = numPoints; outline->n_contours = numContours; outline->owner = TRUE; return TT_Err_Ok; Fail: outline->owner = TRUE; TT_Done_Outline( outline ); return error; } /******************************************************************* * * Function : TT_Done_Outline * * Description : Deletes an outline created through TT_New_Outline(). * Calling this function for outlines returned * by TT_Get_Glyph_Outline() yields an error. * * Input : outline address of outline * * Output : Error code. * * MT-Safe : YES! * ******************************************************************/ EXPORT_FUNC TT_Error TT_Done_Outline( TT_Outline* outline ) { if ( outline ) { if ( outline->owner ) { FREE( outline->points ); FREE( outline->flags ); FREE( outline->contours ); } *outline = null_outline; return TT_Err_Ok; } else return TT_Err_Invalid_Argument; } /******************************************************************* * * Function : TT_Get_Outline_Bitmap * * Description : Render a TrueType outline into a bitmap. * Note that the bitmap must be created by the caller. * * Input : outline the outline to render * map the target bitmap * * Output : Error code. * * MT-Safe : YES! * ******************************************************************/ EXPORT_FUNC TT_Error TT_Get_Outline_Bitmap( TT_Engine engine, TT_Outline* outline, TT_Raster_Map* map ) { PEngine_Instance _engine = HANDLE_Engine( engine ); TT_Error error; if ( !_engine ) return TT_Err_Invalid_Engine; if ( !outline || !map ) return TT_Err_Invalid_Argument; MUTEX_Lock( _engine->raster_lock ); error = RENDER_Glyph( outline, map ); MUTEX_Release( _engine->raster_lock ); return error; } #ifdef TT_CONFIG_OPTION_GRAY_SCALING /******************************************************************* * * Function : TT_Get_Outline_Pixmap * * Description : Render a TrueType outline into a pixmap. * Note that the pixmap must be created by the caller. * * Input : outline the outline to render * map the target bitmap * * Output : Error code * * MT-Safe : YES! * ******************************************************************/ EXPORT_FUNC TT_Error TT_Get_Outline_Pixmap( TT_Engine engine, TT_Outline* outline, TT_Raster_Map* map ) { PEngine_Instance _engine = HANDLE_Engine( engine ); TT_Error error; if ( !_engine ) return TT_Err_Invalid_Engine; if ( !outline || !map ) return TT_Err_Invalid_Argument; MUTEX_Lock( _engine->raster_lock ); error = RENDER_Gray_Glyph( outline, map, _engine->raster_palette ); MUTEX_Release( _engine->raster_lock ); return error; } #endif /* TT_CONFIG_OPTION_GRAY_SCALING */ /******************************************************************* * * Function : TT_Copy_Outline * * Description : Copy an outline into another. The source and * target outlines must have the same points and * contours numbers. * * Input : source address of source outline * target address of target outline * * Output : Error code * * Note : This function doesn't touch the target outline's 'owner' * field. * * MT-Safe : YES! * ******************************************************************/ EXPORT_FUNC TT_Error TT_Copy_Outline( TT_Outline* source, TT_Outline* target ) { if ( !source || !target || source->n_points != target->n_points || source->n_contours != target->n_contours ) return TT_Err_Invalid_Argument; MEM_Copy( target->points, source->points, source->n_points * 2 * sizeof ( TT_F26Dot6 ) ); MEM_Copy( target->flags, source->flags, source->n_points * sizeof ( Byte ) ); MEM_Copy( target->contours, source->contours, source->n_contours * sizeof ( Short ) ); target->high_precision = source->high_precision; target->second_pass = target->second_pass; target->dropout_mode = source->dropout_mode; return TT_Err_Ok; } /******************************************************************* * * Function : TT_Transform_Outline * * Description : Applies a simple transformation to an outline. * * Input : outline the glyph's outline. Can be extracted * from a glyph container through * TT_Get_Glyph_Outline(). * * matrix simple matrix with 16.16 fixed floats * * Output : Error code (always TT_Err_Ok). * * MT-Safe : YES! * ******************************************************************/ EXPORT_FUNC void TT_Transform_Outline( TT_Outline* outline, TT_Matrix* matrix ) { UShort n; TT_F26Dot6 x, y; TT_Vector* vec; vec = outline->points; for ( n = 0; n < outline->n_points; n++ ) { x = TT_MulFix( vec->x, matrix->xx ) + TT_MulFix( vec->y, matrix->xy ); y = TT_MulFix( vec->x, matrix->yx ) + TT_MulFix( vec->y, matrix->yy ); vec->x = x; vec->y = y; vec++; } } /******************************************************************* * * Function : TT_Transform_Vector * * Description : Apply a simple transform to a vector * * Input : x, y the vector. * * matrix simple matrix with 16.16 fixed floats * * Output : None. * * MT-Safe : YES! * ******************************************************************/ EXPORT_FUNC void TT_Transform_Vector( TT_F26Dot6* x, TT_F26Dot6* y, TT_Matrix* matrix ) { TT_F26Dot6 xz, yz; xz = TT_MulFix( *x, matrix->xx ) + TT_MulFix( *y, matrix->xy ); yz = TT_MulFix( *x, matrix->yx ) + TT_MulFix( *y, matrix->yy ); *x = xz; *y = yz; } /******************************************************************* * * Function : TT_Translate_Outline * * Description : Applies a simple translation. * * Input : outline no comment :) * xOffset * yOffset * * Output : Error code. * * MT-Safe : YES! * ******************************************************************/ EXPORT_FUNC void TT_Translate_Outline( TT_Outline* outline, TT_F26Dot6 xOffset, TT_F26Dot6 yOffset ) { UShort n; TT_Vector* vec = outline->points; for ( n = 0; n < outline->n_points; n++ ) { vec->x += xOffset; vec->y += yOffset; vec++; } } /******************************************************************* * * Function : TT_Get_Outline_BBox * * Description : Returns an outline's bounding box. * * Input : outline no comment :) * bbox address where the bounding box is returned * * Output : Error code. * * MT-Safe : YES! * ******************************************************************/ EXPORT_FUNC TT_Error TT_Get_Outline_BBox( TT_Outline* outline, TT_BBox* bbox ) { TT_F26Dot6 x, y; UShort k; if ( outline && bbox ) { if ( outline->n_points == 0 ) { bbox->xMin = 0; bbox->yMin = 0; bbox->xMax = 0; bbox->yMax = 0; } else { TT_Vector* vec = outline->points; bbox->xMin = bbox->xMax = vec->x; bbox->yMin = bbox->yMax = vec->y; vec++; for ( k = 1; k < outline->n_points; k++ ) { x = vec->x; if ( x < bbox->xMin ) bbox->xMin = x; if ( x > bbox->xMax ) bbox->xMax = x; y = vec->y; if ( y < bbox->yMin ) bbox->yMin = y; if ( y > bbox->yMax ) bbox->yMax = y; vec++; } } return TT_Err_Ok; } else return TT_Err_Invalid_Argument; } /* ----------------- character mappings support ------------- */ /******************************************************************* * * Function : TT_Get_CharMap_Count * * Description : Returns the number of charmaps in a given face. * * Input : face face object handle * * Output : Number of tables. -1 in case of error (bad handle). * * Note : DON'T USE THIS FUNCTION! IT HAS BEEN DEPRECATED! * * It is retained for backwards compatibility only and will * fail on 16bit systems. * * MT-Safe : YES ! * ******************************************************************/ EXPORT_FUNC int TT_Get_CharMap_Count( TT_Face face ) { PFace faze = HANDLE_Face( face ); return ( faze ? faze->numCMaps : -1 ); } /******************************************************************* * * Function : TT_Get_CharMap_ID * * Description : Returns the ID of a given charmap. * * Input : face face object handle * charmapIndex index of charmap in directory * platformID address of returned platform ID * encodingID address of returned encoding ID * * Output : error code * * MT-Safe : YES ! * ******************************************************************/ EXPORT_FUNC TT_Error TT_Get_CharMap_ID( TT_Face face, TT_UShort charmapIndex, TT_UShort* platformID, TT_UShort* encodingID ) { PCMapTable cmap; PFace faze = HANDLE_Face( face ); if ( !faze ) return TT_Err_Invalid_Face_Handle; if ( charmapIndex >= faze->numCMaps ) return TT_Err_Invalid_Argument; cmap = faze->cMaps + charmapIndex; *platformID = cmap->platformID; *encodingID = cmap->platformEncodingID; return TT_Err_Ok; } /******************************************************************* * * Function : TT_Get_CharMap * * Description : Looks up a charmap. * * Input : face face object handle * charmapIndex index of charmap in directory * charMap address of returned charmap handle * * Output : Error code. * * MT-Safe : YES! * ******************************************************************/ EXPORT_FUNC TT_Error TT_Get_CharMap( TT_Face face, TT_UShort charmapIndex, TT_CharMap* charMap ) { TT_Error error; TT_Stream stream; PCMapTable cmap; PFace faze = HANDLE_Face( face ); if ( !faze ) return TT_Err_Invalid_Face_Handle; if ( charmapIndex >= faze->numCMaps ) return TT_Err_Invalid_Argument; cmap = faze->cMaps + charmapIndex; /* Load table if needed */ error = TT_Err_Ok; /* MT-NOTE: We're modifying the face object, so protect it. */ MUTEX_Lock( faze->lock ); if ( !cmap->loaded ) { (void)USE_Stream( faze->stream, stream ); if ( !error ) { error = CharMap_Load( cmap, stream ); DONE_Stream( stream ); } if ( error ) cmap = NULL; else cmap->loaded = TRUE; } MUTEX_Release( faze->lock ); HANDLE_Set( *charMap, cmap ); return error; } /******************************************************************* * * Function : TT_Char_Index * * Description : Returns the glyph index corresponding to * a given character code defined for the 'charmap'. * * Input : charMap charmap handle * charcode character code * * Output : glyph index. * * Notes : Character code 0 is the unknown glyph, which should never * be displayed. * * MT-Safe : YES! * ******************************************************************/ EXPORT_FUNC TT_UShort TT_Char_Index( TT_CharMap charMap, TT_UShort charCode ) { PCMapTable cmap = HANDLE_CharMap( charMap ); if ( !cmap ) return 0; /* we return 0 in case of invalid char map */ return CharMap_Index( cmap, charCode ); } /******************************************************************* * * Function : TT_Get_Name_Count * * Description : Returns the number of strings found in the * name table. * * Input : face face handle * * Output : number of strings. * * Notes : Returns -1 on error (invalid handle). * * DON'T USE THIS FUNCTION! IT HAS BEEN DEPRECATED! * * It is retained for backwards compatibility only and will * fail on 16bit systems. * * MT-Safe : YES! * ******************************************************************/ EXPORT_FUNC int TT_Get_Name_Count( TT_Face face ) { PFace faze = HANDLE_Face( face ); if ( !faze ) return -1; return faze->nameTable.numNameRecords; } /******************************************************************* * * Function : TT_Get_Name_ID * * Description : Returns the IDs of the string number 'nameIndex' * in the name table of a given face. * * Input : face face handle * nameIndex index of string. First is 0 * platformID addresses of returned IDs * encodingID * languageID * nameID * * Output : Error code. * * Notes : Some files have a corrupt or unusual name table, with some * entries having a platformID > 3. These can usually * be ignored by a client application. * * MT-Safe : YES! * ******************************************************************/ EXPORT_FUNC TT_Error TT_Get_Name_ID( TT_Face face, TT_UShort nameIndex, TT_UShort* platformID, TT_UShort* encodingID, TT_UShort* languageID, TT_UShort* nameID ) { TNameRec* namerec; PFace faze = HANDLE_Face( face ); if ( !faze ) return TT_Err_Invalid_Face_Handle; if ( nameIndex >= faze->nameTable.numNameRecords ) return TT_Err_Invalid_Argument; namerec = faze->nameTable.names + nameIndex; *platformID = namerec->platformID; *encodingID = namerec->encodingID; *languageID = namerec->languageID; *nameID = namerec->nameID; return TT_Err_Ok; } /******************************************************************* * * Function : TT_Get_Name_String * * Description : Returns the address and length of a given * string found in the name table. * * Input : face face handle * nameIndex string index * stringPtr address of returned pointer to string * length address of returned string length * * Output : Error code. * * Notes : If the string's platformID is invalid, * stringPtr is NULL, and length is 0. * * MT-Safe : YES! * ******************************************************************/ EXPORT_FUNC TT_Error TT_Get_Name_String( TT_Face face, TT_UShort nameIndex, TT_String** stringPtr, TT_UShort* length ) { TNameRec* namerec; PFace faze = HANDLE_Face( face ); if ( !faze ) return TT_Err_Invalid_Face_Handle; if ( nameIndex >= faze->nameTable.numNameRecords ) return TT_Err_Invalid_Argument; namerec = faze->nameTable.names + nameIndex; *stringPtr = (String*)namerec->string; *length = namerec->stringLength; return TT_Err_Ok; } /******************************************************************* * * Function : TT_Get_Font_Data * * Description : Loads any font table into client memory. * * Input : face Face object to look for. * * tag Tag of table to load. Use the value 0 if you * want to access the whole font file, else set * this parameter to a valid TrueType table tag * that you can forge with the MAKE_TT_TAG * macro. * * offset Starting offset in the table (or the file * if tag == 0). * * buffer Address of target buffer * * length Address of decision variable: * * if length == NULL: * Load the whole table. Returns an * error if 'offset' != 0. * * if *length == 0 : * Exit immediately, returning the * length of the given table, or of * the font file, depending on the * value of 'tag'. * * if *length != 0 : * Load the next 'length' bytes of * table or font, starting at offset * 'offset' (in table or font too). * * Output : Error code. * * MT-Safe : YES! * ******************************************************************/ EXPORT_FUNC TT_Error TT_Get_Font_Data( TT_Face face, TT_ULong tag, TT_Long offset, void* buffer, TT_Long* length ) { PFace faze = HANDLE_Face( face ); if ( !faze ) return TT_Err_Invalid_Face_Handle; return Load_TrueType_Any( faze, tag, offset, buffer, length ); } /************************ callback definition ******************/ /* Register a new callback to the TrueType engine -- this should */ /* only be used by higher-level libraries, not typical clients */ /* */ /* This is not part of the current FreeType release, thus */ /* undefined... */ #if 0 EXPORT_FUNC TT_Error TT_Register_Callback( TT_Engine engine, int callback_id, void* callback_ptr ) { PEngine_Instance eng = HANDLE_Engine( engine ); if ( !eng ) return TT_Err_Invalid_Argument; /* currently, we only support one callback */ if (callback_id != TT_Callback_Glyph_Outline_Load) return TT_Err_Invalid_Argument; eng->glCallback = (TT_Glyph_Loader_Callback)callback_ptr; return TT_Err_Ok; } #endif /* 0 */ /* END */