📄 harfbuzz-gdef.c
字号:
/******************************************************************* * * Copyright 1996-2000 by * David Turner, Robert Wilhelm, and Werner Lemberg. * * Copyright 2006 Behdad Esfahbod * * This is part of HarfBuzz, an OpenType Layout engine library. * * See the file name COPYING for licensing information. * ******************************************************************/#include "harfbuzz-impl.h"#include "harfbuzz-gdef-private.h"#include "harfbuzz-open-private.h"static FT_Error Load_AttachList( HB_AttachList* al, FT_Stream stream );static FT_Error Load_LigCaretList( HB_LigCaretList* lcl, FT_Stream stream );static void Free_AttachList( HB_AttachList* al, FT_Memory memory );static void Free_LigCaretList( HB_LigCaretList* lcl, FT_Memory memory );static void Free_NewGlyphClasses( HB_GDEFHeader* gdef, FT_Memory memory );/********************** * Extension Functions **********************/#if 0#define GDEF_ID Build_Extension_ID( 'G', 'D', 'E', 'F' )static FT_Error GDEF_Create( void* ext, PFace face ){ DEFINE_LOAD_LOCALS( face->stream ); HB_GDEFHeader* gdef = (HB_GDEFHeader*)ext; Long table; /* by convention */ if ( !gdef ) return FT_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 = HB_LookUp_Table( face, TTAG_GDEF ); if ( table < 0 ) return FT_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 FT_Err_Ok;}static FT_Error GDEF_Destroy( void* ext, PFace face ){ HB_GDEFHeader* gdef = (HB_GDEFHeader*)ext; /* by convention */ if ( !gdef ) return FT_Err_Ok; if ( gdef->loaded ) { Free_LigCaretList( &gdef->LigCaretList, memory ); Free_AttachList( &gdef->AttachList, memory ); _HB_OPEN_Free_ClassDefinition( &gdef->GlyphClassDef, memory ); _HB_OPEN_Free_ClassDefinition( &gdef->MarkAttachClassDef, memory ); Free_NewGlyphClasses( gdef, memory ); } return FT_Err_Ok;}FT_Error HB_Init_GDEF_Extension( HB_Engine engine ){ PEngine_Instance _engine = HANDLE_Engine( engine ); if ( !_engine ) return FT_Err_Invalid_Engine; return HB_Register_Extension( _engine, GDEF_ID, sizeof ( HB_GDEFHeader ), GDEF_Create, GDEF_Destroy );}#endif/* GDEF glyph classes */#define UNCLASSIFIED_GLYPH 0#define SIMPLE_GLYPH 1#define LIGATURE_GLYPH 2#define MARK_GLYPH 3#define COMPONENT_GLYPH 4FT_Error HB_New_GDEF_Table( FT_Face face, HB_GDEFHeader** retptr ){ FT_Error error; FT_Memory memory = face->memory; HB_GDEFHeader* gdef; if ( !retptr ) return FT_Err_Invalid_Argument; if ( ALLOC( gdef, sizeof( *gdef ) ) ) return error; gdef->memory = face->memory; gdef->GlyphClassDef.loaded = FALSE; gdef->AttachList.loaded = FALSE; gdef->LigCaretList.loaded = FALSE; gdef->MarkAttachClassDef_offset = 0; gdef->MarkAttachClassDef.loaded = FALSE; gdef->LastGlyph = 0; gdef->NewGlyphClasses = NULL; *retptr = gdef; return FT_Err_Ok;}FT_Error HB_Load_GDEF_Table( FT_Face face, HB_GDEFHeader** retptr ){ FT_Error error; FT_Memory memory = face->memory; FT_Stream stream = face->stream; FT_ULong cur_offset, new_offset, base_offset; HB_GDEFHeader* gdef; if ( !retptr ) return FT_Err_Invalid_Argument; if (( error = _hb_ftglue_face_goto_table( face, TTAG_GDEF, stream ) )) return error; if (( error = HB_New_GDEF_Table ( face, &gdef ) )) return error; base_offset = FILE_Pos(); /* skip version */ if ( FILE_Seek( base_offset + 4L ) || ACCESS_Frame( 2L ) ) goto Fail0; 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 = _HB_OPEN_Load_ClassDefinition( &gdef->GlyphClassDef, 5, stream ) ) != FT_Err_Ok ) goto Fail0; (void)FILE_Seek( cur_offset ); } if ( ACCESS_Frame( 2L ) ) goto Fail1; 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, stream ) ) != FT_Err_Ok ) goto Fail1; (void)FILE_Seek( cur_offset ); } if ( ACCESS_Frame( 2L ) ) goto Fail2; 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, stream ) ) != FT_Err_Ok ) goto Fail2; (void)FILE_Seek( cur_offset ); } /* 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 offset of the table. */ if ( ACCESS_Frame( 2L ) ) goto Fail3; new_offset = GET_UShort(); FORGET_Frame(); if ( new_offset ) gdef->MarkAttachClassDef_offset = new_offset + base_offset; else gdef->MarkAttachClassDef_offset = 0; *retptr = gdef; return FT_Err_Ok;Fail3: Free_LigCaretList( &gdef->LigCaretList, memory ); Fail2: Free_AttachList( &gdef->AttachList, memory );Fail1: _HB_OPEN_Free_ClassDefinition( &gdef->GlyphClassDef, memory );Fail0: FREE( gdef ); return error;}FT_Error HB_Done_GDEF_Table ( HB_GDEFHeader* gdef ) { FT_Memory memory = gdef->memory; Free_LigCaretList( &gdef->LigCaretList, memory ); Free_AttachList( &gdef->AttachList, memory ); _HB_OPEN_Free_ClassDefinition( &gdef->GlyphClassDef, memory ); _HB_OPEN_Free_ClassDefinition( &gdef->MarkAttachClassDef, memory ); Free_NewGlyphClasses( gdef, memory ); FREE( gdef ); return FT_Err_Ok;}/******************************* * AttachList related functions *******************************//* AttachPoint */static FT_Error Load_AttachPoint( HB_AttachPoint* ap, FT_Stream stream ){ FT_Memory memory = stream->memory; FT_Error error; FT_UShort n, count; FT_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, FT_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 FT_Err_Ok;}static void Free_AttachPoint( HB_AttachPoint* ap, FT_Memory memory ){ FREE( ap->PointIndex );}/* AttachList */static FT_Error Load_AttachList( HB_AttachList* al, FT_Stream stream ){ FT_Memory memory = stream->memory; FT_Error error; FT_UShort n, m, count; FT_ULong cur_offset, new_offset, base_offset; HB_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 = _HB_OPEN_Load_Coverage( &al->Coverage, stream ) ) != FT_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, HB_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], stream ) ) != FT_Err_Ok ) goto Fail1; (void)FILE_Seek( cur_offset ); } al->loaded = TRUE; return FT_Err_Ok;Fail1: for ( m = 0; m < n; m++ ) Free_AttachPoint( &ap[m], memory ); FREE( ap );Fail2: _HB_OPEN_Free_Coverage( &al->Coverage, memory ); return error;}static void Free_AttachList( HB_AttachList* al, FT_Memory memory ){ FT_UShort n, count; HB_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], memory ); FREE( ap ); } _HB_OPEN_Free_Coverage( &al->Coverage, memory );}/********************************* * LigCaretList related functions *********************************//* CaretValueFormat1 *//* CaretValueFormat2 *//* CaretValueFormat3 *//* CaretValueFormat4 */static FT_Error Load_CaretValue( HB_CaretValue* cv, FT_Stream stream ){ FT_Error error; FT_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 = _HB_OPEN_Load_Device( &cv->cvf.cvf3.Device, stream ) ) != FT_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 HB_Err_Invalid_GDEF_SubTable_Format; } return FT_Err_Ok;}static void Free_CaretValue( HB_CaretValue* cv, FT_Memory memory ){ if ( cv->CaretValueFormat == 3 ) _HB_OPEN_Free_Device( &cv->cvf.cvf3.Device, memory );}/* LigGlyph */static FT_Error Load_LigGlyph( HB_LigGlyph* lg, FT_Stream stream ){ FT_Memory memory = stream->memory; FT_Error error; FT_UShort n, m, count; FT_ULong cur_offset, new_offset, base_offset; HB_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, HB_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], stream ) ) != FT_Err_Ok ) goto Fail; (void)FILE_Seek( cur_offset ); } return FT_Err_Ok;Fail: for ( m = 0; m < n; m++ ) Free_CaretValue( &cv[m], memory ); FREE( cv ); return error;}static void Free_LigGlyph( HB_LigGlyph* lg, FT_Memory memory )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -