otlcommn.c
来自「一个类似windows」· C语言 代码 · 共 941 行 · 第 1/2 页
C
941 行
/***************************************************************************/
/* */
/* 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 + =
减小字号Ctrl + -
显示快捷键?