Edit

kc3-lang/freetype/src/otlayout/otlcommn.c

Branch :

  • Show log

    Commit

  • Author : David Turner
    Date : 2002-05-04 18:02:59
    Hash : 8cd89073
    Message : * src/truetype/ttgload.c (TT_Load_Glyph): finally fixing the last bug that prevented FreeType 2.x and FreeType 1.x to produce bit-by-bit identical monochrome glyph bitmaps with native TrueType hinting. The culprit was a single-bit flag that wasn't set correctly by the TrueType glyph loader !! * src/otlayout/otlayout.h, src/otlayout/otlbase.c, src/otlayout/otlbase.h, src/otlayout/otlconf.h, src/otlayout/otlgdef.c, src/otlayout/otlgdef.h, src/otlayout/otlgpos.c, src/otlayout/otlgpos.h, src/otlayout/otlgsub.c, src/otlayout/otlgsub.h, src/otlayout/otljstf.c, src/otlayout/otljstf.h, src/otlayout/otltable.c, src/otlayout/otltable.h, src/otlayout/otltags.h: adding OpenType Layout source files. Module is still incomplete

  • src/otlayout/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 );
      }
    
    
      OTL_LOCALDEF( OTL_Bytes )
      otl_lookup_get_table( OTL_Bytes  table,
                            OTL_UInt   idx )
      {
        OTL_Bytes  p, result = NULL;
        OTL_UInt   count;
    
    
        p     = table + 4;
        count = OTL_NEXT_USHORT( p );
        if ( idx < count )
        {
          p     += idx * 2;
          result = table + OTL_PEEK_USHORT( p );
        }
    
        return result;
      }
    
    
      /*************************************************************************/
      /*************************************************************************/
      /*****                                                               *****/
      /*****                      LOOKUP LISTS                             *****/
      /*****                                                               *****/
      /*************************************************************************/
      /*************************************************************************/
    
      OTL_LOCALDEF( void )
      otl_lookup_list_validate( OTL_Bytes      table,
                                OTL_Validator  valid )
      {
        OTL_Bytes  p = table, q;
        OTL_UInt   num_lookups, offset;
    
    
        if ( p + 2 > valid->limit )
          OTL_INVALID_TOO_SHORT;
    
        num_lookups = OTL_NEXT_USHORT( p );
    
        if ( p + num_lookups * 2 > valid->limit )
          OTL_INVALID_TOO_SHORT;
    
        for ( ; num_lookups > 0; num_lookups-- )
        {
          offset = OTL_NEXT_USHORT( p );
    
          otl_lookup_validate( table + offset, valid );
        }
      }
    
    
      OTL_LOCALDEF( OTL_UInt )
      otl_lookup_list_get_count( OTL_Bytes  table )
      {
        OTL_Bytes  p = table;
    
    
        return OTL_PEEK_USHORT( p );
      }
    
    
      OTL_LOCALDEF( OTL_Bytes )
      otl_lookup_list_get_lookup( OTL_Bytes  table,
                                  OTL_UInt   idx )
      {
        OTL_Bytes  p, result = 0;
        OTL_UInt   count;
    
    
        p     = table;
        count = OTL_NEXT_USHORT( p );
        if ( idx < count )
        {
          p     += idx * 2;
          result = table + OTL_PEEK_USHORT( p );
        }
    
        return result;
      }
    
    
      OTL_LOCALDEF( OTL_Bytes )
      otl_lookup_list_get_table( OTL_Bytes  table,
                                 OTL_UInt   lookup_index,
                                 OTL_UInt   table_index )
      {
        OTL_Bytes  result = NULL;
    
    
        result = otl_lookup_list_get_lookup( table, lookup_index );
        if ( result )
          result = otl_lookup_get_table( result, table_index );
    
        return result;
      }
    
    
      OTL_LOCALDEF( void )
      otl_lookup_list_foreach( OTL_Bytes        table,
                               OTL_ForeachFunc  func,
                               OTL_Pointer      func_data )
      {
        OTL_Bytes  p     = table;
        OTL_UInt   count = OTL_NEXT_USHORT( p );
    
    
        for ( ; count > 0; count-- )
          func( table + OTL_NEXT_USHORT( p ), func_data );
      }
    
    
      /*************************************************************************/
      /*************************************************************************/
      /*****                                                               *****/
      /*****                        FEATURES                               *****/
      /*****                                                               *****/
      /*************************************************************************/
      /*************************************************************************/
    
      OTL_LOCALDEF( void )
      otl_feature_validate( OTL_Bytes      table,
                            OTL_Validator  valid )
      {
        OTL_Bytes  p = table;
        OTL_UInt   feat_params, num_lookups;
    
    
        if ( p + 4 > valid->limit )
          OTL_INVALID_TOO_SHORT;
    
        feat_params = OTL_NEXT_USHORT( p );  /* ignored */
        num_lookups = OTL_NEXT_USHORT( p );
    
        if ( p + num_lookups * 2 > valid->limit )
          OTL_INVALID_TOO_SHORT;
    
        /* XXX: check lookup indices */
      }
    
    
      OTL_LOCALDEF( OTL_UInt )
      otl_feature_get_count( OTL_Bytes  table )
      {
        OTL_Bytes  p = table + 4;
    
    
        return OTL_PEEK_USHORT( p );
      }
    
    
      OTL_LOCALDEF( OTL_UInt )
      otl_feature_get_lookups( OTL_Bytes  table,
                               OTL_UInt   start,
                               OTL_UInt   count,
                               OTL_UInt  *lookups )
      {
        OTL_Bytes  p;
        OTL_UInt   num_features, result = 0;
    
    
        p            = table + 4;
        num_features = OTL_NEXT_USHORT( p );
    
        p += start * 2;
    
        for ( ; count > 0 && start < num_features; count--, start++ )
        {
          lookups[0] = OTL_NEXT_USHORT(p);
          lookups++;
          result++;
        }
    
        return result;
      }
    
    
      /*************************************************************************/
      /*************************************************************************/
      /*****                                                               *****/
      /*****                        FEATURE LIST                           *****/
      /*****                                                               *****/
      /*************************************************************************/
      /*************************************************************************/
    
      OTL_LOCALDEF( void )
      otl_feature_list_validate( OTL_Bytes      table,
                                 OTL_Validator  valid )
      {
        OTL_Bytes  p = table;
        OTL_UInt   num_features, offset;
    
    
        if ( table + 2 > valid->limit )
          OTL_INVALID_TOO_SHORT;
    
        num_features = OTL_NEXT_USHORT( p );
    
        if ( p + num_features * 2 > valid->limit )
          OTL_INVALID_TOO_SHORT;
    
        for ( ; num_features > 0; num_features-- )
        {
          p     += 4;                       /* skip tag */
          offset = OTL_NEXT_USHORT( p );
    
          otl_feature_table_validate( table + offset, valid );
        }
      }
    
    
      OTL_LOCALDEF( OTL_UInt )
      otl_feature_list_get_count( OTL_Bytes  table )
      {
        OTL_Bytes  p = table;
    
    
        return OTL_PEEK_USHORT( p );
      }
    
    
      OTL_LOCALDEF( OTL_Bytes )
      otl_feature_list_get_feature( OTL_Bytes  table,
                                    OTL_UInt   idx )
      {
        OTL_Bytes  p, result = NULL;
        OTL_UInt   count;
    
    
        p     = table;
        count = OTL_NEXT_USHORT( p );
    
        if ( idx < count )
        {
          p     += idx * 2;
          result = table + OTL_PEEK_USHORT( p );
        }
    
        return result;
      }
    
    
      OTL_LOCALDEF( void )
      otl_feature_list_foreach( OTL_Bytes        table,
                                OTL_ForeachFunc  func,
                                OTL_Pointer      func_data )
      {
        OTL_Bytes  p;
        OTL_UInt   count;
    
    
        p = table;
        count = OTL_NEXT_USHORT( p );
    
        for ( ; count > 0; count-- )
          func( table + OTL_NEXT_USHORT( p ), func_data );
      }
    
    
      /*************************************************************************/
      /*************************************************************************/
      /*****                                                               *****/
      /*****                       LANGUAGE SYSTEM                         *****/
      /*****                                                               *****/
      /*************************************************************************/
      /*************************************************************************/
    
    
      OTL_LOCALDEF( void )
      otl_lang_validate( OTL_Bytes      table,
                         OTL_Validator  valid )
      {
        OTL_Bytes  p = table;
        OTL_UInt   lookup_order;
        OTL_UInt   req_feature;
        OTL_UInt   num_features;
    
    
        if ( table + 6 >= valid->limit )
          OTL_INVALID_TOO_SHORT;
    
        lookup_order = OTL_NEXT_USHORT( p );
        req_feature  = OTL_NEXT_USHORT( p );
        num_features = OTL_NEXT_USHORT( p );
    
        /* XXX: check req_feature if not 0xFFFFU */
    
        if ( p + 2 * num_features >= valid->limit )
          OTL_INVALID_TOO_SHORT;
    
        /* XXX: check features indices! */
      }
    
    
      OTL_LOCALDEF( OTL_UInt )
      otl_lang_get_count( OTL_Bytes  table )
      {
        OTL_Bytes  p = table + 4;
    
        return OTL_PEEK_USHORT( p );
      }
    
    
      OTL_LOCALDEF( OTL_UInt )
      otl_lang_get_req_feature( OTL_Bytes  table )
      {
        OTL_Bytes  p = table + 2;
    
    
        return OTL_PEEK_USHORT( p );
      }
    
    
      OTL_LOCALDEF( OTL_UInt )
      otl_lang_get_features( OTL_Bytes  table,
                             OTL_UInt   start,
                             OTL_UInt   count,
                             OTL_UInt  *features )
      {
        OTL_Bytes  p            = table + 4;
        OTL_UInt   num_features = OTL_NEXT_USHORT( p );
        OTL_UInt   result       = 0;
    
    
        p += start * 2;
    
        for ( ; count > 0 && start < num_features; start++, count-- )
        {
          features[0] = OTL_NEXT_USHORT( p );
          features++;
          result++;
        }
    
        return result;
      }
    
    
    
    
      /*************************************************************************/
      /*************************************************************************/
      /*****                                                               *****/
      /*****                           SCRIPTS                             *****/
      /*****                                                               *****/
      /*************************************************************************/
      /*************************************************************************/
    
    
      OTL_LOCALDEF( void )
      otl_script_validate( OTL_Bytes      table,
                           OTL_Validator  valid )
      {
        OTL_UInt   default_lang;
        OTL_Bytes  p = table;
    
    
        if ( table + 4 > valid->limit )
          OTL_INVALID_TOO_SHORT;
    
        default_lang = OTL_NEXT_USHORT( p );
        num_langs    = OTL_NEXT_USHORT( p );
    
        if ( default_lang != 0 )
        {
          if ( table + default_lang >= valid->limit )
            OTL_INVALID_OFFSET;
        }
    
        if ( p + num_langs * 6 >= valid->limit )
          OTL_INVALID_OFFSET;
    
        for ( ; num_langs > 0; num_langs-- )
        {
          OTL_UInt  offset;
    
    
          p     += 4;  /* skip tag */
          offset = OTL_NEXT_USHORT( p );
    
          otl_lang_validate( table + offset, valid );
        }
      }
    
    
      OTL_LOCALDEF( void )
      otl_script_list_validate( OTL_Bytes      list,
                                OTL_Validator  valid )
      {
        OTL_UInt   num_scripts;
        OTL_Bytes  p = list;
    
    
        if ( list + 2 > valid->limit )
          OTL_INVALID_TOO_SHORT;
    
        num_scripts = OTL_NEXT_USHORT( p );
    
        if ( p + num_scripts * 6 > valid->limit )
          OTL_INVALID_TOO_SHORT;
    
        for ( ; num_scripts > 0; num_scripts-- )
        {
          OTL_UInt  offset;
    
    
          p     += 4;                       /* skip tag */
          offset = OTL_NEXT_USHORT( p );
    
          otl_script_table_validate( list + offset, valid );
        }
      }
    
    
      /*************************************************************************/
      /*************************************************************************/
      /*****                                                               *****/
      /*****                         LOOKUP LISTS                          *****/
      /*****                                                               *****/
      /*************************************************************************/
      /*************************************************************************/
    
      static void
      otl_lookup_table_validate( OTL_Bytes          table,
                                 OTL_UInt           type_count,
                                 OTL_ValidateFunc*  type_funcs,
                                 OTL_Validator      valid )
      {
        OTL_Bytes         p = table;
        OTL_UInt          lookup_type, lookup_flag, count;
        OTL_ValidateFunc  validate;
    
        OTL_CHECK( 6 );
        lookup_type = OTL_NEXT_USHORT( p );
        lookup_flag = OTL_NEXT_USHORT( p );
        count       = OTL_NEXT_USHORT( p );
    
        if ( lookup_type == 0 || lookup_type >= type_count )
          OTL_INVALID_DATA;
    
        validate = type_funcs[ lookup_type - 1 ];
    
        OTL_CHECK( 2*count );
        for ( ; count > 0; count-- )
          validate( table + OTL_NEXT_USHORT( p ), valid );
      }
    
    
      OTL_LOCALDEF( void )
      otl_lookup_list_validate( OTL_Bytes          table,
                                OTL_UInt           type_count,
                                OTL_ValidateFunc*  type_funcs,
                                OTL_Validator      valid )
      {
        OTL_Bytes  p = table;
        OTL_UInt   count;
    
        OTL_CHECK( 2 );
        count = OTL_NEXT_USHORT( p );
    
        OTL_CHECK( 2*count );
        for ( ; count > 0; count-- )
          otl_lookup_table_validate( table + OTL_NEXT_USHORT( p ),
                                     type_count, type_funcs, valid );
      }
    
    /* END */