?? ftxgdef.c
字號:
TTO_CaretValue* cv; if ( lg->CaretValue ) { count = lg->CaretCount; cv = lg->CaretValue; for ( n = 0; n < count; n++ ) Free_CaretValue( &cv[n] ); FREE( cv ); } } /* LigCaretList */ static TT_Error Load_LigCaretList( TTO_LigCaretList* lcl, PFace input ) { DEFINE_LOAD_LOCALS( input->stream ); UShort n, count; ULong cur_offset, new_offset, base_offset; TTO_LigGlyph* lg; 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( &lcl->Coverage, input ) ) != TT_Err_Ok ) return error; (void)FILE_Seek( cur_offset ); if ( ACCESS_Frame( 2L ) ) goto Fail2; count = lcl->LigGlyphCount = GET_UShort(); FORGET_Frame(); lcl->LigGlyph = NULL; if ( ALLOC_ARRAY( lcl->LigGlyph, count, TTO_LigGlyph ) ) goto Fail2; lg = lcl->LigGlyph; 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_LigGlyph( &lg[n], input ) ) != TT_Err_Ok ) goto Fail1; (void)FILE_Seek( cur_offset ); } lcl->loaded = TRUE; return TT_Err_Ok; Fail1: for ( n = 0; n < count; n++ ) Free_LigGlyph( &lg[n] ); FREE( lg ); Fail2: Free_Coverage( &lcl->Coverage ); return error; } static void Free_LigCaretList( TTO_LigCaretList* lcl ) { UShort n, count; TTO_LigGlyph* lg; if ( !lcl->loaded ) return; if ( lcl->LigGlyph ) { count = lcl->LigGlyphCount; lg = lcl->LigGlyph; for ( n = 0; n < count; n++ ) Free_LigGlyph( &lg[n] ); FREE( lg ); } Free_Coverage( &lcl->Coverage ); } /*********** * GDEF API ***********/ static UShort Get_New_Class( TTO_GDEFHeader* gdef, UShort glyphID, UShort index ) { UShort glyph_index, array_index; UShort byte, bits; TTO_ClassRangeRecord* gcrr; UShort** ngc; if ( glyphID >= gdef->LastGlyph ) return 0; gcrr = gdef->GlyphClassDef.cd.cd2.ClassRangeRecord; ngc = gdef->NewGlyphClasses; if ( glyphID < gcrr[index].Start ) { array_index = 0; if ( index == 0 ) glyph_index = glyphID; else glyph_index = glyphID - gcrr[index - 1].End - 1; } else { array_index = index + 1; glyph_index = glyphID - gcrr[index].End - 1; } byte = ngc[array_index][glyph_index / 4 + 1]; bits = byte >> ( 16 - ( glyph_index % 4 + 1 ) * 4 ); return bits & 0x000F; } FT_EXPORT_FUNC( TT_Error ) TT_GDEF_Get_Glyph_Property( TTO_GDEFHeader* gdef, TT_UShort glyphID, TT_UShort* property ) { UShort class, index; TT_Error error; if ( !gdef || !property ) return TT_Err_Invalid_Argument; /* first, we check for mark attach classes */ if ( gdef->MarkAttachClassDef.loaded ) { error = Get_Class( &gdef->MarkAttachClassDef, glyphID, &class, &index ); if ( error && error != TTO_Err_Not_Covered ) return error; if ( !error ) { *property = class << 8; return TT_Err_Ok; } } error = Get_Class( &gdef->GlyphClassDef, glyphID, &class, &index ); if ( error && error != TTO_Err_Not_Covered ) return error; /* if we have a constructed class table, check whether additional values have been assigned */ if ( error == TTO_Err_Not_Covered && gdef->NewGlyphClasses ) class = Get_New_Class( gdef, glyphID, index ); switch ( class ) { case UNCLASSIFIED_GLYPH: *property = 0; break; case SIMPLE_GLYPH: *property = TTO_BASE_GLYPH; break; case LIGATURE_GLYPH: *property = TTO_LIGATURE; break; case MARK_GLYPH: *property = TTO_MARK; break; case COMPONENT_GLYPH: *property = TTO_COMPONENT; break; } return TT_Err_Ok; } static TT_Error Make_ClassRange( TTO_ClassDefinition* cd, UShort start, UShort end, UShort class ) { TT_Error error; UShort index; TTO_ClassDefFormat2* cdf2; TTO_ClassRangeRecord* crr; cdf2 = &cd->cd.cd2; cdf2->ClassRangeCount++; if ( REALLOC_ARRAY( cdf2->ClassRangeRecord, cdf2->ClassRangeCount, TTO_ClassRangeRecord ) ) return error; crr = cdf2->ClassRangeRecord; index = cdf2->ClassRangeCount - 1; crr[index].Start = start; crr[index].End = end; crr[index].Class = class; cd->Defined[class] = TRUE; return TT_Err_Ok; } FT_EXPORT_FUNC( TT_Error ) TT_GDEF_Build_ClassDefinition( TTO_GDEFHeader* gdef, TT_UShort num_glyphs, TT_UShort glyph_count, TT_UShort* glyph_array, TT_UShort* class_array ) { UShort start, curr_glyph, curr_class; UShort n, count; TT_Error error; TTO_ClassDefinition* gcd; TTO_ClassRangeRecord* gcrr; UShort** ngc; if ( !gdef || !glyph_array || !class_array ) return TT_Err_Invalid_Argument; gcd = &gdef->GlyphClassDef; /* We build a format 2 table */ gcd->ClassFormat = 2; /* A GlyphClassDef table contains at most 5 different class values */ if ( ALLOC_ARRAY( gcd->Defined, 5, Bool ) ) return error; gcd->cd.cd2.ClassRangeCount = 0; gcd->cd.cd2.ClassRangeRecord = NULL; start = glyph_array[0]; curr_class = class_array[0]; curr_glyph = start; if ( curr_class >= 5 ) { error = TT_Err_Invalid_Argument; goto Fail4; } glyph_count--; for ( n = 0; n <= glyph_count; n++ ) { if ( curr_glyph == glyph_array[n] && curr_class == class_array[n] ) { if ( n == glyph_count ) { if ( ( error = Make_ClassRange( gcd, start, curr_glyph, curr_class ) ) != TT_Err_Ok ) goto Fail3; } else { if ( curr_glyph == 0xFFFF ) { error = TT_Err_Invalid_Argument; goto Fail3; } else curr_glyph++; } } else { if ( ( error = Make_ClassRange( gcd, start, curr_glyph - 1, curr_class ) ) != TT_Err_Ok ) goto Fail3; if ( curr_glyph > glyph_array[n] ) { error = TT_Err_Invalid_Argument; goto Fail3; } start = glyph_array[n]; curr_class = class_array[n]; curr_glyph = start; if ( curr_class >= 5 ) { error = TT_Err_Invalid_Argument; goto Fail3; } if ( n == glyph_count ) { if ( ( error = Make_ClassRange( gcd, start, curr_glyph, curr_class ) ) != TT_Err_Ok ) goto Fail3; } else { if ( curr_glyph == 0xFFFF ) { error = TT_Err_Invalid_Argument; goto Fail3; } else curr_glyph++; } } } /* now prepare the arrays for class values assigned during the lookup process */ if ( ALLOC_ARRAY( gdef->NewGlyphClasses, gcd->cd.cd2.ClassRangeCount + 1, UShort* ) ) goto Fail2; count = gcd->cd.cd2.ClassRangeCount; gcrr = gcd->cd.cd2.ClassRangeRecord; ngc = gdef->NewGlyphClasses; /* We allocate arrays for all glyphs not covered by the class range records. Each element holds four class values. */ if ( gcrr[0].Start ) { if ( ALLOC_ARRAY( ngc[0], gcrr[0].Start / 4 + 1, UShort ) ) goto Fail1; } for ( n = 1; n < count; n++ ) { if ( gcrr[n].Start - gcrr[n - 1].End > 1 ) if ( ALLOC_ARRAY( ngc[n], ( gcrr[n].Start - gcrr[n - 1].End - 1 ) / 4 + 1, UShort ) ) goto Fail1; } if ( gcrr[count - 1].End != num_glyphs - 1 ) { if ( ALLOC_ARRAY( ngc[count], ( num_glyphs - gcrr[count - 1].End - 1 ) / 4 + 1, UShort ) ) goto Fail1; } gdef->LastGlyph = num_glyphs - 1; gdef->MarkAttachClassDef_offset = 0L; gdef->MarkAttachClassDef.loaded = FALSE; return TT_Err_Ok; Fail1: for ( n = 0; n < count; n++ ) FREE( ngc[n] ); Fail2: FREE( gdef->NewGlyphClasses ); Fail3: FREE( gcd->cd.cd2.ClassRangeRecord ); Fail4: FREE( gcd->Defined ); return error; } static void Free_NewGlyphClasses( TTO_GDEFHeader* gdef ) { UShort** ngc; UShort n, count; if ( gdef->NewGlyphClasses ) { count = gdef->GlyphClassDef.cd.cd2.ClassRangeCount + 1; ngc = gdef->NewGlyphClasses; for ( n = 0; n < count; n++ ) FREE( ngc[n] ); FREE( ngc ); } } TT_Error Add_Glyph_Property( TTO_GDEFHeader* gdef, UShort glyphID, UShort property ) { TT_Error error; UShort class, new_class, index; UShort byte, bits, mask; UShort array_index, glyph_index; TTO_ClassRangeRecord* gcrr; UShort** ngc; error = Get_Class( &gdef->GlyphClassDef, glyphID, &class, &index ); if ( error && error != TTO_Err_Not_Covered ) return error; /* we don't accept glyphs covered in `GlyphClassDef' */ if ( !error ) return TTO_Err_Not_Covered; switch ( property ) { case 0: new_class = UNCLASSIFIED_GLYPH; break; case TTO_BASE_GLYPH: new_class = SIMPLE_GLYPH; break; case TTO_LIGATURE: new_class = LIGATURE_GLYPH; break; case TTO_MARK: new_class = MARK_GLYPH; break; case TTO_COMPONENT: new_class = COMPONENT_GLYPH; break; default: return TT_Err_Invalid_Argument; } gcrr = gdef->GlyphClassDef.cd.cd2.ClassRangeRecord; ngc = gdef->NewGlyphClasses; if ( glyphID < gcrr[index].Start ) { array_index = 0; if ( index == 0 ) glyph_index = glyphID; else glyph_index = glyphID - gcrr[index - 1].End - 1; } else { array_index = index + 1; glyph_index = glyphID - gcrr[index].End - 1; } byte = ngc[array_index][glyph_index / 4 + 1]; bits = byte >> ( 16 - ( glyph_index % 4 + 1 ) * 4 ); class = bits & 0x000F; /* we don't overwrite existing entries */ if ( !class ) { bits = new_class << ( 16 - ( glyph_index % 4 + 1 ) * 4 ); mask = ~( 0x000F << ( 16 - ( glyph_index % 4 + 1 ) * 4 ) ); ngc[array_index][glyph_index / 4 + 1] &= mask; ngc[array_index][glyph_index / 4 + 1] |= bits; } return TT_Err_Ok; } TT_Error Check_Property( TTO_GDEFHeader* gdef, UShort index, UShort flags, UShort* property ) { TT_Error error; if ( gdef ) { error = TT_GDEF_Get_Glyph_Property( gdef, index, property ); if ( error ) return error; if ( flags & IGNORE_SPECIAL_MARKS ) { /* This is OpenType 1.2 */ if ( (flags & 0xFF00) != *property ) return TTO_Err_Not_Covered; } else { if ( flags & *property ) return TTO_Err_Not_Covered; } } return TT_Err_Ok; }/* END */
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -