📄 otlcommn.c
字号:
/***************************************************************************//* *//* otlcommn.c *//* *//* OpenType layout support, common tables (body). *//* *//* Copyright 2002 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 "otlayout.h" /*************************************************************************/ /*************************************************************************/ /***** *****/ /***** COVERAGE TABLE *****/ /***** *****/ /*************************************************************************/ /*************************************************************************/ OTL_LOCALDEF( void ) otl_coverage_validate( OTL_Bytes table, OTL_Validator valid ) { OTL_Bytes p; OTL_UInt format; if ( table + 4 > valid->limit ) OTL_INVALID_TOO_SHORT; format = OTL_NEXT_USHORT( p ); switch ( format ) { case 1: { OTL_UInt count = OTL_NEXT_USHORT( p ); if ( p + count * 2 >= valid->limit ) OTL_INVALID_TOO_SHORT; /* XXX: check glyph indices */ } break; case 2: { OTL_UInt n, num_ranges = OTL_NEXT_USHORT( p ); OTL_UInt start, end, start_cover, total = 0, last = 0; if ( p + num_ranges * 6 >= valid->limit ) OTL_INVALID_TOO_SHORT; for ( n = 0; n < num_ranges; n++ ) { start = OTL_NEXT_USHORT( p ); end = OTL_NEXT_USHORT( p ); start_cover = OTL_NEXT_USHORT( p ); if ( start > end || start_cover != total ) OTL_INVALID_DATA; if ( n > 0 && start <= last ) OTL_INVALID_DATA; total += end - start + 1; last = end; } } break; default: OTL_INVALID_FORMAT; } } OTL_LOCALDEF( OTL_UInt ) otl_coverage_get_count( OTL_Bytes table ) { OTL_Bytes p = table; OTL_UInt format = OTL_NEXT_USHORT( p ); OTL_UInt count = OTL_NEXT_USHORT( p ); OTL_UInt result = 0; switch ( format ) { case 1: return count; case 2: { OTL_UInt start, end; for ( ; count > 0; count-- ) { start = OTL_NEXT_USHORT( p ); end = OTL_NEXT_USHORT( p ); p += 2; /* skip start_index */ result += end - start + 1; } } break; default: ; } return result; } OTL_LOCALDEF( OTL_Int ) otl_coverage_get_index( OTL_Bytes table, OTL_UInt glyph_index ) { OTL_Bytes p = table; OTL_UInt format = OTL_NEXT_USHORT( p ); OTL_UInt count = OTL_NEXT_USHORT( p ); switch ( format ) { case 1: { OTL_UInt min = 0, max = count, mid, gindex; table += 4; while ( min < max ) { mid = ( min + max ) >> 1; p = table + 2 * mid; gindex = OTL_PEEK_USHORT( p ); if ( glyph_index == gindex ) return (OTL_Int)mid; if ( glyph_index < gindex ) max = mid; else min = mid + 1; } } break; case 2: { OTL_UInt min = 0, max = count, mid; OTL_UInt start, end, delta, start_cover; table += 4; while ( min < max ) { mid = ( min + max ) >> 1; p = table + 6 * mid; start = OTL_NEXT_USHORT( p ); end = OTL_NEXT_USHORT( p ); if ( glyph_index < start ) max = mid; else if ( glyph_index > end ) min = mid + 1; else return (OTL_Int)( glyph_index + OTL_NEXT_USHORT( p ) - start ); } } break; default: ; } return -1; } /*************************************************************************/ /*************************************************************************/ /***** *****/ /***** CLASS DEFINITION TABLE *****/ /***** *****/ /*************************************************************************/ /*************************************************************************/ OTL_LOCALDEF( void ) otl_class_definition_validate( OTL_Bytes table, OTL_Validator valid ) { OTL_Bytes p = table; OTL_UInt format; if ( p + 4 > valid->limit ) OTL_INVALID_TOO_SHORT; format = OTL_NEXT_USHORT( p ); switch ( format ) { case 1: { OTL_UInt count, start = OTL_NEXT_USHORT( p ); if ( p + 2 > valid->limit ) OTL_INVALID_TOO_SHORT; count = OTL_NEXT_USHORT( p ); if ( p + count * 2 > valid->limit ) OTL_INVALID_TOO_SHORT; /* XXX: check glyph indices */ } break; case 2: { OTL_UInt n, num_ranges = OTL_NEXT_USHORT( p ); OTL_UInt start, end, value, last = 0; if ( p + num_ranges * 6 > valid->limit ) OTL_INVALID_TOO_SHORT; for ( n = 0; n < num_ranges; n++ ) { start = OTL_NEXT_USHORT( p ); end = OTL_NEXT_USHORT( p ); value = OTL_NEXT_USHORT( p ); /* ignored */ if ( start > end || ( n > 0 && start <= last ) ) OTL_INVALID_DATA; last = end; } } break; default: OTL_INVALID_FORMAT; } } OTL_LOCALDEF( OTL_UInt ) otl_class_definition_get_value( OTL_Bytes table, OTL_UInt glyph_index ) { OTL_Bytes p = table; OTL_UInt format = OTL_NEXT_USHORT( p ); switch ( format ) { case 1: { OTL_UInt start = OTL_NEXT_USHORT( p ); OTL_UInt count = OTL_NEXT_USHORT( p ); OTL_UInt idx = (OTL_UInt)( glyph_index - start ); if ( idx < count ) { p += 2 * idx; return OTL_PEEK_USHORT( p ); } } break; case 2: { OTL_UInt count = OTL_NEXT_USHORT( p ); OTL_UInt min = 0, max = count, mid, gindex; table += 4; while ( min < max ) { mid = ( min + max ) >> 1; p = table + 6 * mid; start = OTL_NEXT_USHORT( p ); end = OTL_NEXT_USHORT( p ); if ( glyph_index < start ) max = mid; else if ( glyph_index > end ) min = mid + 1; else return OTL_PEEK_USHORT( p ); } } break; default: ; } return 0; } /*************************************************************************/ /*************************************************************************/ /***** *****/ /***** DEVICE TABLE *****/ /***** *****/ /*************************************************************************/ /*************************************************************************/ OTL_LOCALDEF( void ) otl_device_table_validate( OTL_Bytes table, OTL_Validator valid ) { OTL_Bytes p = table; OTL_UInt start, end, count, format, count; if ( p + 8 > valid->limit ) OTL_INVALID_TOO_SHORT; start = OTL_NEXT_USHORT( p ); end = OTL_NEXT_USHORT( p ); format = OTL_NEXT_USHORT( p ); if ( format < 1 || format > 3 || end < start ) OTL_INVALID_DATA; count = (OTL_UInt)( end - start + 1 ); if ( p + ( ( 1 << format ) * count ) / 8 > valid->limit ) OTL_INVALID_TOO_SHORT; } OTL_LOCALDEF( OTL_UInt ) otl_device_table_get_start( OTL_Bytes table ) { OTL_Bytes p = table; return OTL_PEEK_USHORT( p ); } OTL_LOCALDEF( OTL_UInt ) otl_device_table_get_end( OTL_Bytes table ) { OTL_Bytes p = table + 2; return OTL_PEEK_USHORT( p ); } OTL_LOCALDEF( OTL_Int ) otl_device_table_get_delta( OTL_Bytes table, OTL_UInt size ) { OTL_Bytes p = table; OTL_Int result = 0; OTL_UInt start, end, format, idx, value; start = OTL_NEXT_USHORT( p ); end = OTL_NEXT_USHORT( p ); format = OTL_NEXT_USHORT( p ); if ( size >= start && size <= end ) { /* we could do that with clever bit operations, but a switch is */ /* much simpler to understand and maintain */ /* */ switch ( format ) { case 1: idx = (OTL_UInt)( ( size - start ) * 2 ); p += idx / 16; value = OTL_PEEK_USHORT( p ); shift = idx & 15; result = (OTL_Short)( value << shift ) >> ( 14 - shift ); break; case 2: idx = (OTL_UInt)( ( size - start ) * 4 ); p += idx / 16; value = OTL_PEEK_USHORT( p ); shift = idx & 15; result = (OTL_Short)( value << shift ) >> ( 12 - shift ); break; case 3: idx = (OTL_UInt)( ( size - start ) * 8 ); p += idx / 16; value = OTL_PEEK_USHORT( p ); shift = idx & 15; result = (OTL_Short)( value << shift ) >> ( 8 - shift ); break; default: ; } } return result; } /*************************************************************************/ /*************************************************************************/ /***** *****/ /***** LOOKUP LISTS *****/ /***** *****/ /*************************************************************************/ /*************************************************************************/ OTL_LOCALDEF( void ) otl_lookup_validate( OTL_Bytes table, OTL_Validator valid ) { OTL_Bytes p = table; OTL_UInt num_tables; if ( table + 6 > valid->limit ) OTL_INVALID_TOO_SHORT; p += 4; num_tables = OTL_NEXT_USHORT( p ); if ( p + num_tables * 2 > valid->limit ) OTL_INVALID_TOO_SHORT; for ( ; num_tables > 0; num_tables-- ) { offset = OTL_NEXT_USHORT( p ); if ( table + offset >= valid->limit ) OTL_INVALID_OFFSET; } /* XXX: check sub-tables? */ } OTL_LOCALDEF( OTL_UInt ) otl_lookup_get_count( OTL_Bytes table ) { OTL_Bytes p = table + 4; return OTL_PEEK_USHORT( p ); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -