?? ftxgdef.c
字號:
/******************************************************************* * * ftxgdef.c * * TrueType Open GDEF table support. * * Copyright 1996-2001 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. * ******************************************************************/#include "tttypes.h"#include "tttags.h"#include "ttload.h"#include "ttextend.h"#include "ttmemory.h"#include "ttfile.h"#include "ftxopen.h"#include "ftxopenf.h" static TT_Error Load_AttachList( TTO_AttachList* al, PFace input ); static TT_Error Load_LigCaretList( TTO_LigCaretList* lcl, PFace input ); static void Free_AttachList( TTO_AttachList* al ); static void Free_LigCaretList( TTO_LigCaretList* lcl ); static void Free_NewGlyphClasses( TTO_GDEFHeader* gdef ); /********************** * Extension Functions **********************/ static TT_Error GDEF_Create( void* ext, PFace face ) { DEFINE_LOAD_LOCALS( face->stream ); TTO_GDEFHeader* gdef = (TTO_GDEFHeader*)ext; Long table; /* by convention */ if ( !gdef ) return TT_Err_Ok; /* a null offset indicates that there is no GDEF table */ gdef->offset = 0; /* we store the start offset and the size of the subtable */ table = TT_LookUp_Table( face, TTAG_GDEF ); if ( table < 0 ) return TT_Err_Ok; /* The table is optional */ if ( FILE_Seek( face->dirTables[table].Offset ) || ACCESS_Frame( 4L ) ) return error; gdef->offset = FILE_Pos() - 4L; /* undo ACCESS_Frame() */ gdef->Version = GET_ULong(); FORGET_Frame(); gdef->loaded = FALSE; return TT_Err_Ok; } static TT_Error GDEF_Destroy( void* ext, PFace face ) { TTO_GDEFHeader* gdef = (TTO_GDEFHeader*)ext; /* by convention */ if ( !gdef ) return TT_Err_Ok; if ( gdef->loaded ) { Free_LigCaretList( &gdef->LigCaretList ); Free_AttachList( &gdef->AttachList ); Free_ClassDefinition( &gdef->GlyphClassDef ); Free_ClassDefinition( &gdef->MarkAttachClassDef ); Free_NewGlyphClasses( gdef ); } return TT_Err_Ok; } FT_EXPORT_FUNC( TT_Error ) TT_Init_GDEF_Extension( TT_Engine engine ) { PEngine_Instance _engine = HANDLE_Engine( engine ); if ( !_engine ) return TT_Err_Invalid_Engine; return TT_Register_Extension( _engine, GDEF_ID, sizeof ( TTO_GDEFHeader ), GDEF_Create, GDEF_Destroy ); } FT_EXPORT_FUNC( TT_Error ) TT_Load_GDEF_Table( TT_Face face, TTO_GDEFHeader* retptr ) { ULong cur_offset, new_offset, base_offset; TTO_GDEFHeader* gdef; PFace faze = HANDLE_Face( face ); DEFINE_ALL_LOCALS; if ( !retptr ) return TT_Err_Invalid_Argument; if ( !faze ) return TT_Err_Invalid_Face_Handle; error = TT_Extension_Get( faze, GDEF_ID, (void**)&gdef ); if ( error ) return error; if ( gdef->offset == 0 ) return TT_Err_Table_Missing; /* no GDEF table; nothing to do */ /* now access stream */ if ( USE_Stream( faze->stream, stream ) ) return error; base_offset = gdef->offset; /* skip version */ if ( FILE_Seek( base_offset + 4L ) || ACCESS_Frame( 2L ) ) return error; new_offset = GET_UShort(); FORGET_Frame(); /* all GDEF subtables are optional */ if ( new_offset ) { new_offset += base_offset; /* only classes 1-4 are allowed here */ cur_offset = FILE_Pos(); if ( FILE_Seek( new_offset ) || ( error = Load_ClassDefinition( &gdef->GlyphClassDef, 5, faze ) ) != TT_Err_Ok ) return error; (void)FILE_Seek( cur_offset ); } else gdef->GlyphClassDef.loaded = FALSE; if ( ACCESS_Frame( 2L ) ) return error; new_offset = GET_UShort(); FORGET_Frame(); if ( new_offset ) { new_offset += base_offset; cur_offset = FILE_Pos(); if ( FILE_Seek( new_offset ) || ( error = Load_AttachList( &gdef->AttachList, faze ) ) != TT_Err_Ok ) goto Fail1; (void)FILE_Seek( cur_offset ); } else gdef->AttachList.loaded = FALSE; if ( ACCESS_Frame( 2L ) ) return error; new_offset = GET_UShort(); FORGET_Frame(); if ( new_offset ) { new_offset += base_offset; cur_offset = FILE_Pos(); if ( FILE_Seek( new_offset ) || ( error = Load_LigCaretList( &gdef->LigCaretList, faze ) ) != TT_Err_Ok ) goto Fail2; (void)FILE_Seek( cur_offset ); } else gdef->LigCaretList.loaded = FALSE; /* OpenType 1.2 has introduced the `MarkAttachClassDef' field. We first have to scan the LookupFlag values to find out whether we must load it or not. Here we only store the current file offset. */ gdef->MarkAttachClassDef_offset = FILE_Pos(); gdef->MarkAttachClassDef.loaded = FALSE; gdef->LastGlyph = 0; gdef->NewGlyphClasses = NULL; gdef->loaded = TRUE; *retptr = *gdef; DONE_Stream( stream ); return TT_Err_Ok; Fail2: Free_AttachList( &gdef->AttachList ); Fail1: Free_ClassDefinition( &gdef->GlyphClassDef ); /* release stream */ DONE_Stream( stream ); return error; } /******************************* * AttachList related functions *******************************/ /* AttachPoint */ static TT_Error Load_AttachPoint( TTO_AttachPoint* ap, PFace input ) { DEFINE_LOAD_LOCALS( input->stream ); UShort n, count; UShort* pi; if ( ACCESS_Frame( 2L ) ) return error; count = ap->PointCount = GET_UShort(); FORGET_Frame(); ap->PointIndex = NULL; if ( count ) { if ( ALLOC_ARRAY( ap->PointIndex, count, UShort ) ) return error; pi = ap->PointIndex; if ( ACCESS_Frame( count * 2L ) ) { FREE( pi ); return error; } for ( n = 0; n < count; n++ ) pi[n] = GET_UShort(); FORGET_Frame(); } return TT_Err_Ok; } static void Free_AttachPoint( TTO_AttachPoint* ap ) { FREE( ap->PointIndex ); } /* AttachList */ static TT_Error Load_AttachList( TTO_AttachList* al, PFace input ) { DEFINE_LOAD_LOCALS( input->stream ); UShort n, count; ULong cur_offset, new_offset, base_offset; TTO_AttachPoint* ap; base_offset = FILE_Pos(); if ( ACCESS_Frame( 2L ) ) return error; new_offset = GET_UShort() + base_offset; FORGET_Frame(); cur_offset = FILE_Pos(); if ( FILE_Seek( new_offset ) || ( error = Load_Coverage( &al->Coverage, input ) ) != TT_Err_Ok ) return error; (void)FILE_Seek( cur_offset ); if ( ACCESS_Frame( 2L ) ) goto Fail2; count = al->GlyphCount = GET_UShort(); FORGET_Frame(); al->AttachPoint = NULL; if ( ALLOC_ARRAY( al->AttachPoint, count, TTO_AttachPoint ) ) goto Fail2; ap = al->AttachPoint; for ( n = 0; n < count; n++ ) { if ( ACCESS_Frame( 2L ) ) goto Fail1; new_offset = GET_UShort() + base_offset; FORGET_Frame(); cur_offset = FILE_Pos(); if ( FILE_Seek( new_offset ) || ( error = Load_AttachPoint( &ap[n], input ) ) != TT_Err_Ok ) goto Fail1; (void)FILE_Seek( cur_offset ); } al->loaded = TRUE; return TT_Err_Ok; Fail1: for ( n = 0; n < count; n++ ) Free_AttachPoint( &ap[n] ); FREE( ap ); Fail2: Free_Coverage( &al->Coverage ); return error; } static void Free_AttachList( TTO_AttachList* al ) { UShort n, count; TTO_AttachPoint* ap; if ( !al->loaded ) return; if ( al->AttachPoint ) { count = al->GlyphCount; ap = al->AttachPoint; for ( n = 0; n < count; n++ ) Free_AttachPoint( &ap[n] ); FREE( ap ); } Free_Coverage( &al->Coverage ); } /********************************* * LigCaretList related functions *********************************/ /* CaretValueFormat1 */ /* CaretValueFormat2 */ /* CaretValueFormat3 */ /* CaretValueFormat4 */ static TT_Error Load_CaretValue( TTO_CaretValue* cv, PFace input ) { DEFINE_LOAD_LOCALS( input->stream ); ULong cur_offset, new_offset, base_offset; base_offset = FILE_Pos(); if ( ACCESS_Frame( 2L ) ) return error; cv->CaretValueFormat = GET_UShort(); FORGET_Frame(); switch ( cv->CaretValueFormat ) { case 1: if ( ACCESS_Frame( 2L ) ) return error; cv->cvf.cvf1.Coordinate = GET_Short(); FORGET_Frame(); break; case 2: if ( ACCESS_Frame( 2L ) ) return error; cv->cvf.cvf2.CaretValuePoint = GET_UShort(); FORGET_Frame(); break; case 3: if ( ACCESS_Frame( 4L ) ) return error; cv->cvf.cvf3.Coordinate = GET_Short(); new_offset = GET_UShort() + base_offset; FORGET_Frame(); cur_offset = FILE_Pos(); if ( FILE_Seek( new_offset ) || ( error = Load_Device( &cv->cvf.cvf3.Device, input ) ) != TT_Err_Ok ) return error; (void)FILE_Seek( cur_offset ); break; case 4: if ( ACCESS_Frame( 2L ) ) return error; cv->cvf.cvf4.IdCaretValue = GET_UShort(); FORGET_Frame(); break; default: return TTO_Err_Invalid_GDEF_SubTable_Format; } return TT_Err_Ok; } static void Free_CaretValue( TTO_CaretValue* cv ) { if ( cv->CaretValueFormat == 3 ) Free_Device( &cv->cvf.cvf3.Device ); } /* LigGlyph */ static TT_Error Load_LigGlyph( TTO_LigGlyph* lg, PFace input ) { DEFINE_LOAD_LOCALS( input->stream ); UShort n, count; ULong cur_offset, new_offset, base_offset; TTO_CaretValue* cv; base_offset = FILE_Pos(); if ( ACCESS_Frame( 2L ) ) return error; count = lg->CaretCount = GET_UShort(); FORGET_Frame(); lg->CaretValue = NULL; if ( ALLOC_ARRAY( lg->CaretValue, count, TTO_CaretValue ) ) return error; cv = lg->CaretValue; for ( n = 0; n < count; n++ ) { if ( ACCESS_Frame( 2L ) ) goto Fail; new_offset = GET_UShort() + base_offset; FORGET_Frame(); cur_offset = FILE_Pos(); if ( FILE_Seek( new_offset ) || ( error = Load_CaretValue( &cv[n], input ) ) != TT_Err_Ok ) goto Fail; (void)FILE_Seek( cur_offset ); } return TT_Err_Ok; Fail: for ( n = 0; n < count; n++ ) Free_CaretValue( &cv[n] ); FREE( cv ); return error; } static void Free_LigGlyph( TTO_LigGlyph* lg ) { UShort n, count;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -