📄 harfbuzz-open.c
字号:
/* * Copyright (C) 1998-2004 David Turner and Werner Lemberg * Copyright (C) 2006 Behdad Esfahbod * * This is part of HarfBuzz, an OpenType Layout engine library. * * Permission is hereby granted, without written agreement and without * license or royalty fees, to use, copy, modify, and distribute this * software and its documentation for any purpose, provided that the * above copyright notice and the following two paragraphs appear in * all copies of this software. * * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH * DAMAGE. * * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. */#include "harfbuzz-impl.h"#include "harfbuzz-open-private.h"/*************************** * Script related functions ***************************//* LangSys */static HB_Error Load_LangSys( HB_LangSys* ls, HB_Stream stream ){ HB_Error error; HB_UShort n, count; HB_UShort* fi; if ( ACCESS_Frame( 6L ) ) return error; ls->LookupOrderOffset = GET_UShort(); /* should be 0 */ ls->ReqFeatureIndex = GET_UShort(); count = ls->FeatureCount = GET_UShort(); FORGET_Frame(); ls->FeatureIndex = NULL; if ( ALLOC_ARRAY( ls->FeatureIndex, count, HB_UShort ) ) return error; if ( ACCESS_Frame( count * 2L ) ) { FREE( ls->FeatureIndex ); return error; } fi = ls->FeatureIndex; for ( n = 0; n < count; n++ ) fi[n] = GET_UShort(); FORGET_Frame(); return HB_Err_Ok;}static void Free_LangSys( HB_LangSys* ls ){ FREE( ls->FeatureIndex );}/* Script */static HB_Error Load_Script( HB_ScriptTable* s, HB_Stream stream ){ HB_Error error; HB_UShort n, m, count; HB_UInt cur_offset, new_offset, base_offset; HB_LangSysRecord* lsr; base_offset = FILE_Pos(); if ( ACCESS_Frame( 2L ) ) return error; new_offset = GET_UShort() + base_offset; FORGET_Frame(); if ( new_offset != base_offset ) /* not a NULL offset */ { cur_offset = FILE_Pos(); if ( FILE_Seek( new_offset ) || ( error = Load_LangSys( &s->DefaultLangSys, stream ) ) != HB_Err_Ok ) return error; (void)FILE_Seek( cur_offset ); } else { /* we create a DefaultLangSys table with no entries */ s->DefaultLangSys.LookupOrderOffset = 0; s->DefaultLangSys.ReqFeatureIndex = 0xFFFF; s->DefaultLangSys.FeatureCount = 0; s->DefaultLangSys.FeatureIndex = NULL; } if ( ACCESS_Frame( 2L ) ) goto Fail2; count = s->LangSysCount = GET_UShort(); /* safety check; otherwise the official handling of TrueType Open fonts won't work */ if ( s->LangSysCount == 0 && s->DefaultLangSys.FeatureCount == 0 ) { error = HB_Err_Not_Covered; goto Fail2; } FORGET_Frame(); s->LangSysRecord = NULL; if ( ALLOC_ARRAY( s->LangSysRecord, count, HB_LangSysRecord ) ) goto Fail2; lsr = s->LangSysRecord; for ( n = 0; n < count; n++ ) { if ( ACCESS_Frame( 6L ) ) goto Fail1; lsr[n].LangSysTag = GET_ULong(); new_offset = GET_UShort() + base_offset; FORGET_Frame(); cur_offset = FILE_Pos(); if ( FILE_Seek( new_offset ) || ( error = Load_LangSys( &lsr[n].LangSys, stream ) ) != HB_Err_Ok ) goto Fail1; (void)FILE_Seek( cur_offset ); } return HB_Err_Ok;Fail1: for ( m = 0; m < n; m++ ) Free_LangSys( &lsr[m].LangSys ); FREE( s->LangSysRecord );Fail2: Free_LangSys( &s->DefaultLangSys ); return error;}static void Free_Script( HB_ScriptTable* s ){ HB_UShort n, count; HB_LangSysRecord* lsr; Free_LangSys( &s->DefaultLangSys ); if ( s->LangSysRecord ) { count = s->LangSysCount; lsr = s->LangSysRecord; for ( n = 0; n < count; n++ ) Free_LangSys( &lsr[n].LangSys ); FREE( lsr ); }}/* ScriptList */HB_INTERNAL HB_Error_HB_OPEN_Load_ScriptList( HB_ScriptList* sl, HB_Stream stream ){ HB_Error error; HB_UShort n, script_count; HB_UInt cur_offset, new_offset, base_offset; HB_ScriptRecord* sr; base_offset = FILE_Pos(); if ( ACCESS_Frame( 2L ) ) return error; script_count = GET_UShort(); FORGET_Frame(); sl->ScriptRecord = NULL; if ( ALLOC_ARRAY( sl->ScriptRecord, script_count, HB_ScriptRecord ) ) return error; sr = sl->ScriptRecord; sl->ScriptCount= 0; for ( n = 0; n < script_count; n++ ) { if ( ACCESS_Frame( 6L ) ) goto Fail; sr[sl->ScriptCount].ScriptTag = GET_ULong(); new_offset = GET_UShort() + base_offset; FORGET_Frame(); cur_offset = FILE_Pos(); if ( FILE_Seek( new_offset ) ) goto Fail; error = Load_Script( &sr[sl->ScriptCount].Script, stream ); if ( error == HB_Err_Ok ) sl->ScriptCount += 1; else if ( error != HB_Err_Not_Covered ) goto Fail; (void)FILE_Seek( cur_offset ); } /* Empty tables are harmless and generated by fontforge. * See http://bugzilla.gnome.org/show_bug.cgi?id=347073 */#if 0 if ( sl->ScriptCount == 0 ) { error = ERR(HB_Err_Invalid_SubTable); goto Fail; }#endif return HB_Err_Ok;Fail: for ( n = 0; n < sl->ScriptCount; n++ ) Free_Script( &sr[n].Script ); FREE( sl->ScriptRecord ); return error;}HB_INTERNAL void_HB_OPEN_Free_ScriptList( HB_ScriptList* sl ){ HB_UShort n, count; HB_ScriptRecord* sr; if ( sl->ScriptRecord ) { count = sl->ScriptCount; sr = sl->ScriptRecord; for ( n = 0; n < count; n++ ) Free_Script( &sr[n].Script ); FREE( sr ); }}/********************************* * Feature List related functions *********************************//* Feature */static HB_Error Load_Feature( HB_Feature* f, HB_Stream stream ){ HB_Error error; HB_UShort n, count; HB_UShort* lli; if ( ACCESS_Frame( 4L ) ) return error; f->FeatureParams = GET_UShort(); /* should be 0 */ count = f->LookupListCount = GET_UShort(); FORGET_Frame(); f->LookupListIndex = NULL; if ( ALLOC_ARRAY( f->LookupListIndex, count, HB_UShort ) ) return error; lli = f->LookupListIndex; if ( ACCESS_Frame( count * 2L ) ) { FREE( f->LookupListIndex ); return error; } for ( n = 0; n < count; n++ ) lli[n] = GET_UShort(); FORGET_Frame(); return HB_Err_Ok;}static void Free_Feature( HB_Feature* f ){ FREE( f->LookupListIndex );}/* FeatureList */HB_INTERNAL HB_Error_HB_OPEN_Load_FeatureList( HB_FeatureList* fl, HB_Stream stream ){ HB_Error error; HB_UShort n, m, count; HB_UInt cur_offset, new_offset, base_offset; HB_FeatureRecord* fr; base_offset = FILE_Pos(); if ( ACCESS_Frame( 2L ) ) return error; count = fl->FeatureCount = GET_UShort(); FORGET_Frame(); fl->FeatureRecord = NULL; if ( ALLOC_ARRAY( fl->FeatureRecord, count, HB_FeatureRecord ) ) return error; if ( ALLOC_ARRAY( fl->ApplyOrder, count, HB_UShort ) ) goto Fail2; fl->ApplyCount = 0; fr = fl->FeatureRecord; for ( n = 0; n < count; n++ ) { if ( ACCESS_Frame( 6L ) ) goto Fail1; fr[n].FeatureTag = GET_ULong(); new_offset = GET_UShort() + base_offset; FORGET_Frame(); cur_offset = FILE_Pos(); if ( FILE_Seek( new_offset ) || ( error = Load_Feature( &fr[n].Feature, stream ) ) != HB_Err_Ok ) goto Fail1; (void)FILE_Seek( cur_offset ); } return HB_Err_Ok;Fail1: for ( m = 0; m < n; m++ ) Free_Feature( &fr[m].Feature ); FREE( fl->ApplyOrder );Fail2: FREE( fl->FeatureRecord ); return error;}HB_INTERNAL void_HB_OPEN_Free_FeatureList( HB_FeatureList* fl ){ HB_UShort n, count; HB_FeatureRecord* fr; if ( fl->FeatureRecord ) { count = fl->FeatureCount; fr = fl->FeatureRecord; for ( n = 0; n < count; n++ ) Free_Feature( &fr[n].Feature ); FREE( fr ); } FREE( fl->ApplyOrder );}/******************************** * Lookup List related functions ********************************//* the subroutines of the following two functions are defined in ftxgsub.c and ftxgpos.c respectively *//* SubTable */static HB_Error Load_SubTable( HB_SubTable* st, HB_Stream stream, HB_Type table_type, HB_UShort lookup_type ){ if ( table_type == HB_Type_GSUB ) return _HB_GSUB_Load_SubTable ( &st->st.gsub, stream, lookup_type ); else return _HB_GPOS_Load_SubTable ( &st->st.gpos, stream, lookup_type );}static void Free_SubTable( HB_SubTable* st, HB_Type table_type, HB_UShort lookup_type ){ if ( table_type == HB_Type_GSUB ) _HB_GSUB_Free_SubTable ( &st->st.gsub, lookup_type ); else _HB_GPOS_Free_SubTable ( &st->st.gpos, lookup_type );}/* Lookup */static HB_Error Load_Lookup( HB_Lookup* l, HB_Stream stream, HB_Type type ){ HB_Error error; HB_UShort n, m, count; HB_UInt cur_offset, new_offset, base_offset; HB_SubTable* st; HB_Bool is_extension = FALSE; base_offset = FILE_Pos(); if ( ACCESS_Frame( 6L ) ) return error; l->LookupType = GET_UShort(); l->LookupFlag = GET_UShort(); count = l->SubTableCount = GET_UShort(); FORGET_Frame(); l->SubTable = NULL; if ( ALLOC_ARRAY( l->SubTable, count, HB_SubTable ) ) return error; st = l->SubTable; if ( ( type == HB_Type_GSUB && l->LookupType == HB_GSUB_LOOKUP_EXTENSION ) || ( type == HB_Type_GPOS && l->LookupType == HB_GPOS_LOOKUP_EXTENSION ) ) is_extension = TRUE; 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 ( is_extension ) { if ( FILE_Seek( new_offset ) || ACCESS_Frame( 8L ) ) goto Fail; if (GET_UShort() != 1) /* format should be 1 */ goto Fail; l->LookupType = GET_UShort(); new_offset += GET_ULong(); FORGET_Frame(); } if ( FILE_Seek( new_offset ) || ( error = Load_SubTable( &st[n], stream, type, l->LookupType ) ) != HB_Err_Ok ) goto Fail; (void)FILE_Seek( cur_offset ); } return HB_Err_Ok;Fail: for ( m = 0; m < n; m++ ) Free_SubTable( &st[m], type, l->LookupType ); FREE( l->SubTable ); return error;}static void Free_Lookup( HB_Lookup* l, HB_Type type ){ HB_UShort n, count; HB_SubTable* st; if ( l->SubTable ) { count = l->SubTableCount; st = l->SubTable; for ( n = 0; n < count; n++ ) Free_SubTable( &st[n], type, l->LookupType ); FREE( st ); }}/* LookupList */HB_INTERNAL HB_Error_HB_OPEN_Load_LookupList( HB_LookupList* ll, HB_Stream stream, HB_Type type ){ HB_Error error; HB_UShort n, m, count; HB_UInt cur_offset, new_offset, base_offset; HB_Lookup* l; base_offset = FILE_Pos(); if ( ACCESS_Frame( 2L ) ) return error; count = ll->LookupCount = GET_UShort(); FORGET_Frame(); ll->Lookup = NULL; if ( ALLOC_ARRAY( ll->Lookup, count, HB_Lookup ) ) return error; if ( ALLOC_ARRAY( ll->Properties, count, HB_UInt ) ) goto Fail2; l = ll->Lookup; 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_Lookup( &l[n], stream, type ) ) != HB_Err_Ok ) goto Fail1; (void)FILE_Seek( cur_offset ); } return HB_Err_Ok;Fail1: FREE( ll->Properties ); for ( m = 0; m < n; m++ ) Free_Lookup( &l[m], type );Fail2: FREE( ll->Lookup ); return error;}HB_INTERNAL void_HB_OPEN_Free_LookupList( HB_LookupList* ll, HB_Type type ){ HB_UShort n, count; HB_Lookup* l; FREE( ll->Properties ); if ( ll->Lookup ) { count = ll->LookupCount; l = ll->Lookup; for ( n = 0; n < count; n++ ) Free_Lookup( &l[n], type ); FREE( l ); }}/***************************** * Coverage related functions *****************************//* CoverageFormat1 */static HB_Error Load_Coverage1( HB_CoverageFormat1* cf1, HB_Stream stream ){ HB_Error error; HB_UShort n, count; HB_UShort* ga; if ( ACCESS_Frame( 2L ) ) return error; count = cf1->GlyphCount = GET_UShort(); FORGET_Frame(); cf1->GlyphArray = NULL; if ( ALLOC_ARRAY( cf1->GlyphArray, count, HB_UShort ) ) return error; ga = cf1->GlyphArray; if ( ACCESS_Frame( count * 2L ) ) { FREE( cf1->GlyphArray ); return error; } for ( n = 0; n < count; n++ ) ga[n] = GET_UShort(); FORGET_Frame(); return HB_Err_Ok;}static void Free_Coverage1( HB_CoverageFormat1* cf1 ){ FREE( cf1->GlyphArray );}/* CoverageFormat2 */static HB_Error Load_Coverage2( HB_CoverageFormat2* cf2, HB_Stream stream ){ HB_Error error;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -