📄 harfbuzz-gdef.c
字号:
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], stream ) ) != HB_Err_Ok ) goto Fail1; (void)FILE_Seek( cur_offset ); } lcl->loaded = TRUE; return HB_Err_Ok;Fail1: for ( m = 0; m < n; m++ ) Free_LigGlyph( &lg[m] ); FREE( lg );Fail2: _HB_OPEN_Free_Coverage( &lcl->Coverage ); return error;}static void Free_LigCaretList( HB_LigCaretList* lcl ){ HB_UShort n, count; HB_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 ); } _HB_OPEN_Free_Coverage( &lcl->Coverage );}/*********** * GDEF API ***********/static HB_UShort Get_New_Class( HB_GDEFHeader* gdef, HB_UShort glyphID, HB_UShort index ){ HB_UShort glyph_index, array_index, count; HB_UShort byte, bits; HB_ClassRangeRecord* gcrr; HB_UShort** ngc; if ( glyphID >= gdef->LastGlyph ) return 0; count = gdef->GlyphClassDef.cd.cd2.ClassRangeCount; gcrr = gdef->GlyphClassDef.cd.cd2.ClassRangeRecord; ngc = gdef->NewGlyphClasses; if ( index < count && glyphID < gcrr[index].Start ) { array_index = index; 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]; bits = byte >> ( 16 - ( glyph_index % 4 + 1 ) * 4 ); return bits & 0x000F;}HB_Error HB_GDEF_Get_Glyph_Property( HB_GDEFHeader* gdef, HB_UShort glyphID, HB_UShort* property ){ HB_UShort class = 0, index = 0; /* shut compiler up */ HB_Error error; if ( !gdef || !property ) return ERR(HB_Err_Invalid_Argument); /* first, we check for mark attach classes */ if ( gdef->MarkAttachClassDef.loaded ) { error = _HB_OPEN_Get_Class( &gdef->MarkAttachClassDef, glyphID, &class, &index ); if ( error && error != HB_Err_Not_Covered ) return error; if ( !error ) { *property = class << 8; return HB_Err_Ok; } } error = _HB_OPEN_Get_Class( &gdef->GlyphClassDef, glyphID, &class, &index ); if ( error && error != HB_Err_Not_Covered ) return error; /* if we have a constructed class table, check whether additional values have been assigned */ if ( error == HB_Err_Not_Covered && gdef->NewGlyphClasses ) class = Get_New_Class( gdef, glyphID, index ); switch ( class ) { default: case UNCLASSIFIED_GLYPH: *property = 0; break; case SIMPLE_GLYPH: *property = HB_GDEF_BASE_GLYPH; break; case LIGATURE_GLYPH: *property = HB_GDEF_LIGATURE; break; case MARK_GLYPH: *property = HB_GDEF_MARK; break; case COMPONENT_GLYPH: *property = HB_GDEF_COMPONENT; break; } return HB_Err_Ok;}static HB_Error Make_ClassRange( HB_ClassDefinition* cd, HB_UShort start, HB_UShort end, HB_UShort class ){ HB_Error error; HB_UShort index; HB_ClassDefFormat2* cdf2; HB_ClassRangeRecord* crr; cdf2 = &cd->cd.cd2; if ( REALLOC_ARRAY( cdf2->ClassRangeRecord, cdf2->ClassRangeCount + 1 , HB_ClassRangeRecord ) ) return error; cdf2->ClassRangeCount++; crr = cdf2->ClassRangeRecord; index = cdf2->ClassRangeCount - 1; crr[index].Start = start; crr[index].End = end; crr[index].Class = class; cd->Defined[class] = TRUE; return HB_Err_Ok;}HB_Error HB_GDEF_Build_ClassDefinition( HB_GDEFHeader* gdef, HB_UShort num_glyphs, HB_UShort glyph_count, HB_UShort* glyph_array, HB_UShort* class_array ){ HB_UShort start, curr_glyph, curr_class; HB_UShort n, m, count; HB_Error error; HB_ClassDefinition* gcd; HB_ClassRangeRecord* gcrr; HB_UShort** ngc; if ( !gdef || !glyph_array || !class_array ) return ERR(HB_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, HB_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 = ERR(HB_Err_Invalid_Argument); goto Fail4; } glyph_count--; for ( n = 0; n < glyph_count + 1; 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 ) ) != HB_Err_Ok ) goto Fail3; } else { if ( curr_glyph == 0xFFFF ) { error = ERR(HB_Err_Invalid_Argument); goto Fail3; } else curr_glyph++; } } else { if ( ( error = Make_ClassRange( gcd, start, curr_glyph - 1, curr_class ) ) != HB_Err_Ok ) goto Fail3; if ( curr_glyph > glyph_array[n] ) { error = ERR(HB_Err_Invalid_Argument); goto Fail3; } start = glyph_array[n]; curr_class = class_array[n]; curr_glyph = start; if ( curr_class >= 5 ) { error = ERR(HB_Err_Invalid_Argument); goto Fail3; } if ( n == glyph_count ) { if ( ( error = Make_ClassRange( gcd, start, curr_glyph, curr_class ) ) != HB_Err_Ok ) goto Fail3; } else { if ( curr_glyph == 0xFFFF ) { error = ERR(HB_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, HB_UShort* ) ) goto Fail3; 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 ( count > 0 ) { if ( gcrr[0].Start ) { if ( ALLOC_ARRAY( ngc[0], ( gcrr[0].Start + 3 ) / 4, HB_UShort ) ) goto Fail2; } 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 + 2 ) / 4, HB_UShort ) ) goto Fail1; } if ( gcrr[count - 1].End != num_glyphs - 1 ) { if ( ALLOC_ARRAY( ngc[count], ( num_glyphs - gcrr[count - 1].End + 2 ) / 4, HB_UShort ) ) goto Fail1; } } else if ( num_glyphs > 0 ) { if ( ALLOC_ARRAY( ngc[count], ( num_glyphs + 3 ) / 4, HB_UShort ) ) goto Fail2; } gdef->LastGlyph = num_glyphs - 1; gdef->MarkAttachClassDef_offset = 0L; gdef->MarkAttachClassDef.loaded = FALSE; gcd->loaded = TRUE; return HB_Err_Ok;Fail1: for ( m = 0; m < n; m++ ) FREE( ngc[m] );Fail2: FREE( gdef->NewGlyphClasses );Fail3: FREE( gcd->cd.cd2.ClassRangeRecord );Fail4: FREE( gcd->Defined ); return error;}static void Free_NewGlyphClasses( HB_GDEFHeader* gdef ){ HB_UShort** ngc; HB_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 ); }}HB_INTERNAL HB_Error_HB_GDEF_Add_Glyph_Property( HB_GDEFHeader* gdef, HB_UShort glyphID, HB_UShort property ){ HB_Error error; HB_UShort class, new_class, index = 0; /* shut compiler up */ HB_UShort byte, bits, mask; HB_UShort array_index, glyph_index, count; HB_ClassRangeRecord* gcrr; HB_UShort** ngc; error = _HB_OPEN_Get_Class( &gdef->GlyphClassDef, glyphID, &class, &index ); if ( error && error != HB_Err_Not_Covered ) return error; /* we don't accept glyphs covered in `GlyphClassDef' */ if ( !error ) return HB_Err_Not_Covered; switch ( property ) { case 0: new_class = UNCLASSIFIED_GLYPH; break; case HB_GDEF_BASE_GLYPH: new_class = SIMPLE_GLYPH; break; case HB_GDEF_LIGATURE: new_class = LIGATURE_GLYPH; break; case HB_GDEF_MARK: new_class = MARK_GLYPH; break; case HB_GDEF_COMPONENT: new_class = COMPONENT_GLYPH; break; default: return ERR(HB_Err_Invalid_Argument); } count = gdef->GlyphClassDef.cd.cd2.ClassRangeCount; gcrr = gdef->GlyphClassDef.cd.cd2.ClassRangeRecord; ngc = gdef->NewGlyphClasses; if ( index < count && glyphID < gcrr[index].Start ) { array_index = index; 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]; 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] &= mask; ngc[array_index][glyph_index / 4] |= bits; } return HB_Err_Ok;}HB_INTERNAL HB_Error_HB_GDEF_Check_Property( HB_GDEFHeader* gdef, HB_GlyphItem gitem, HB_UShort flags, HB_UShort* property ){ HB_Error error; if ( gdef ) { HB_UShort basic_glyph_class; HB_UShort desired_attachment_class; if ( gitem->gproperties == HB_GLYPH_PROPERTIES_UNKNOWN ) { error = HB_GDEF_Get_Glyph_Property( gdef, gitem->gindex, &gitem->gproperties ); if ( error ) return error; } *property = gitem->gproperties; /* If the glyph was found in the MarkAttachmentClass table, * then that class value is the high byte of the result, * otherwise the low byte contains the basic type of the glyph * as defined by the GlyphClassDef table. */ if ( *property & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS ) basic_glyph_class = HB_GDEF_MARK; else basic_glyph_class = *property; /* Return Not_Covered, if, for example, basic_glyph_class * is HB_GDEF_LIGATURE and LookFlags includes HB_LOOKUP_FLAG_IGNORE_LIGATURES */ if ( flags & basic_glyph_class ) return HB_Err_Not_Covered; /* The high byte of LookupFlags has the meaning * "ignore marks of attachment type different than * the attachment type specified." */ desired_attachment_class = flags & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS; if ( desired_attachment_class ) { if ( basic_glyph_class == HB_GDEF_MARK && *property != desired_attachment_class ) return HB_Err_Not_Covered; } } else { *property = 0; } return HB_Err_Ok;}HB_INTERNAL HB_Error_HB_GDEF_LoadMarkAttachClassDef_From_LookupFlags( HB_GDEFHeader* gdef, HB_Stream stream, HB_Lookup* lo, HB_UShort num_lookups){ HB_Error error = HB_Err_Ok; HB_UShort i; /* We now check the LookupFlags for values larger than 0xFF to find out whether we need to load the `MarkAttachClassDef' field of the GDEF table -- this hack is necessary for OpenType 1.2 tables since the version field of the GDEF table hasn't been incremented. For constructed GDEF tables, we only load it if `MarkAttachClassDef_offset' is not zero (nevertheless, a build of a constructed mark attach table is not supported currently). */ if ( gdef && gdef->MarkAttachClassDef_offset && !gdef->MarkAttachClassDef.loaded ) { for ( i = 0; i < num_lookups; i++ ) { if ( lo[i].LookupFlag & HB_LOOKUP_FLAG_IGNORE_SPECIAL_MARKS ) { if ( FILE_Seek( gdef->MarkAttachClassDef_offset ) || ( error = _HB_OPEN_Load_ClassDefinition( &gdef->MarkAttachClassDef, 256, stream ) ) != HB_Err_Ok ) goto Done; break; } } }Done: return error;}/* END */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -