ref: b9ff415dfbffb540c4b2df3671fc95fcb07caf66
dir: /src/otlayout/otljstf.c/
/***************************************************************************/
/* */
/* otljstf.c */
/* */
/* OpenType layout support, JSTF table (body). */
/* */
/* Copyright 2002, 2004 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 "otljstf.h"
#include "otlcommn.h"
#include "otlgpos.h"
static void
otl_jstf_extender_validate( OTL_Bytes table,
OTL_UInt glyph_count,
OTL_Validator valid )
{
OTL_Bytes p = table;
OTL_UInt num_glyphs;
OTL_CHECK( 2 );
num_glyphs = OTL_NEXT_USHORT( p );
OTL_CHECK( num_glyphs * 2 );
for ( ; num_glyphs > 0; num_glyphs-- )
if ( OTL_NEXT_USHORT( p ) >= glyph_count )
OTL_INVALID_DATA;
}
static void
otl_jstf_gsubgpos_mods_validate( OTL_Bytes table,
OTL_UInt lookup_count,
OTL_Validator valid )
{
OTL_Bytes p = table;
OTL_UInt num_lookups;
OTL_CHECK( 2 );
num_lookups = OTL_NEXT_USHORT( p );
OTL_CHECK( num_lookups * 2 );
if ( lookup_count )
{
for ( ; num_lookups > 0; num_lookups-- )
if ( OTL_NEXT_USHORT( p ) >= lookup_count )
OTL_INVALID_DATA;
}
}
static void
otl_jstf_max_validate( OTL_Bytes table,
OTL_UInt lookup_count,
OTL_UInt glyph_count,
OTL_Validator valid )
{
OTL_Bytes p = table;
OTL_UInt num_lookups;
OTL_CHECK( 2 );
num_lookups = OTL_NEXT_USHORT( p );
OTL_CHECK( num_lookups * 2 );
/* scan subtable records */
for ( ; num_lookups > 0; num_lookups-- )
/* XXX: check lookup types? */
otl_gpos_subtable_validate( table + OTL_NEXT_USHORT( p ),
lookup_count, glyph_count, valid );
}
static void
otl_jstf_priority_validate( OTL_Bytes table,
OTL_UInt gsub_lookup_count,
OTL_UInt gpos_lookup_count,
OTL_UInt glyph_count,
OTL_Validator valid )
{
OTL_Bytes p = table;
OTL_UInt val;
OTL_CHECK( 20 );
/* shrinkage GSUB enable/disable */
val = OTL_NEXT_USHORT( p );
if ( val )
otl_jstf_gsubgpos_mods_validate( table + val, gsub_lookup_count,
valid );
val = OTL_NEXT_USHORT( p );
if ( val )
otl_jstf_gsubgpos_mods_validate( table + val, gsub_lookup_count,
valid );
/* shrinkage GPOS enable/disable */
val = OTL_NEXT_USHORT( p );
if ( val )
otl_jstf_gsubgpos_mods_validate( table + val, gpos_lookup_count,
valid );
val = OTL_NEXT_USHORT( p );
if ( val )
otl_jstf_gsubgpos_mods_validate( table + val, gpos_lookup_count,
valid );
/* shrinkage JSTF max */
val = OTL_NEXT_USHORT( p );
if ( val )
otl_jstf_max_validate( table + val, gpos_lookup_count, glyph_count,
valid );
/* extension GSUB enable/disable */
val = OTL_NEXT_USHORT( p );
if ( val )
otl_jstf_gsubgpos_mods_validate( table + val, gsub_lookup_count,
valid );
val = OTL_NEXT_USHORT( p );
if ( val )
otl_jstf_gsubgpos_mods_validate( table + val, gsub_lookup_count,
valid );
/* extension GPOS enable/disable */
val = OTL_NEXT_USHORT( p );
if ( val )
otl_jstf_gsubgpos_mods_validate( table + val, gpos_lookup_count,
valid );
val = OTL_NEXT_USHORT( p );
if ( val )
otl_jstf_gsubgpos_mods_validate( table + val, gpos_lookup_count,
valid );
/* extension JSTF max */
val = OTL_NEXT_USHORT( p );
if ( val )
otl_jstf_max_validate( table + val, gpos_lookup_count, glyph_count,
valid );
}
static void
otl_jstf_lang_validate( OTL_Bytes table,
OTL_UInt gsub_lookup_count,
OTL_UInt gpos_lookup_count,
OTL_UInt glyph_count,
OTL_Validator valid )
{
OTL_Bytes p = table;
OTL_UInt num_priorities;
OTL_CHECK( 2 );
num_priorities = OTL_NEXT_USHORT( p );
OTL_CHECK( num_priorities * 2 );
/* scan priority records */
for ( ; num_priorities > 0; num_priorities-- )
otl_jstf_priority_validate( table + OTL_NEXT_USHORT( p ),
gsub_lookup_count, gpos_lookup_count,
glyph_count, valid );
}
static void
otl_jstf_script_validate( OTL_Bytes table,
OTL_UInt gsub_lookup_count,
OTL_UInt gpos_lookup_count,
OTL_UInt glyph_count,
OTL_Validator valid )
{
OTL_Bytes p = table;
OTL_UInt num_langsys, extender, default_lang;
OTL_CHECK( 6 );
extender = OTL_NEXT_USHORT( p );
default_lang = OTL_NEXT_USHORT( p );
num_langsys = OTL_NEXT_USHORT( p );
if ( extender )
otl_jstf_extender_validate( table + extender, glyph_count, valid );
if ( default_lang )
otl_jstf_lang_validate( table + default_lang,
gsub_lookup_count, gpos_lookup_count,
glyph_count, valid );
OTL_CHECK( 6 * num_langsys );
/* scan langsys records */
for ( ; num_langsys > 0; num_langsys-- )
{
p += 4; /* skip tag */
otl_jstf_lang_validate( table + OTL_NEXT_USHORT( p ),
gsub_lookup_count, gpos_lookup_count,
glyph_count, valid );
}
}
OTL_LOCALDEF( void )
otl_jstf_validate( OTL_Bytes table,
OTL_Bytes gsub,
OTL_Bytes gpos,
OTL_UInt glyph_count,
OTL_Validator valid )
{
OTL_Bytes p = table;
OTL_UInt num_scripts, gsub_lookup_count, gpos_lookup_count;
OTL_CHECK( 6 );
if ( OTL_NEXT_ULONG( p ) != 0x10000UL )
OTL_INVALID_DATA;
num_scripts = OTL_NEXT_USHORT( p );
OTL_CHECK( num_scripts * 6 );
if ( gsub )
gsub_lookup_count = otl_gsubgpos_get_lookup_count( gsub );
else
gsub_lookup_count = 0;
if ( gpos )
gpos_lookup_count = otl_gsubgpos_get_lookup_count( gpos );
else
gpos_lookup_count = 0;
/* scan script records */
for ( ; num_scripts > 0; num_scripts-- )
{
p += 4; /* skip tag */
otl_jstf_script_validate( table + OTL_NEXT_USHORT( p ),
gsub_lookup_count, gpos_lookup_count,
glyph_count, valid );
}
}
/* END */