Edit

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

Branch :

  • Show log

    Commit

  • Author : David Turner
    Date : 2000-05-16 23:44:38
    Hash : e49ab25c
    Message : formatting - removed trailing spaces

  • src/otlayout/oltypes.c
  • #include <oltypes.h>
    
      LOCAL_FUNC
      TT_Error  OTL_Table_Init( OTL_Table*  table,
                                FT_Memory   memory )
      {
        MEM_Set( table, 0, sizeof(*table) );
        table->memory = memory;
      }
    
     /* read a script list table */
     /* use with any table       */
      LOCAL_FUNC
      TT_Error  OTL_Table_Set_Scripts( OTL_Table*  table,
                                       TT_Byte*    bytes,
                                       TT_Long     len,
                                       OTL_Type    otl_type )
      {
        TT_Byte*  p;
        TT_Byte*  start = bytes;
        TT_UInt   count, max_langs;
        TT_Error  error;
    
        /* skip version of the JSTF table */
        if (otl_type == otl_jstf)
          start += 4;
    
        p = start;
    
        /* we must allocate the script_tags and language_tags arrays     */
        /* this requires that we compute the maximum number of languages */
        /* per script..                                                  */
    
        count     = table->num_scripts = OTL_UShort(p);
        max_langs = 0;
        for ( ; count > 0; count++ )
        {
          TT_Byte*  script;
          TT_UInt   num_langs;
    
          p += 4; /* skip tag */
          script = bytes + OTL_UShort(p);
    
          /* skip the baseValues or extenders field of the BASE and JSTF table */
          if (otl_type == otl_type_base || otl_type == otl_type_jstf)
            script += 2;
    
          /* test if there is a default language system */
          if ( OTL_UShort(script) )
            num_langs++;
    
          /* test other language systems */
          num_langs += OTL_UShort(script); /* add other lang sys */
    
          if (num_langs > max_langs)
            max_langs = num_langs;
        }
    
        /* good, now allocate the tag arrays */
        if ( !ALLOC_ARRAY( table->script_tags,
                          table->num_scripts + max_langs,
                          TT_ULong ) )
        {
          table->language_tags = table->script_tags + table->num_scripts;
          table->max_languages = max_langs;
          table->num_languages = 0;
          table->otl_type      = otl_type;
    
          table->scripts_table = bytes;
          table->scripts_len   = len;
    
          /* fill the script_tags array */
          {
            TT_UInt  n;
            TT_Byte* p = start + 2; /* skip count */
    
            for ( n = 0; n < table->num_scripts; n++ )
            {
              table->script_tags[n] = OTL_ULong(p);
              p += 2; /* skip offset */
            }
          }
        }
        return error;
      }
    
    
    
     /* add a features list to the table   */
     /* use only with a GSUB or GPOS table */
      LOCAL_FUNC
      TT_Error  OTL_Table_Set_Features( OTL_Table*  table,
                                        TT_Byte*    bytes,
                                        TT_Long     len )
      {
        TT_Error  error;
        TT_Byte*  p = bytes;
        TT_UInt   count;
    
        table->max_features = count = OTL_UShort(p);
        if ( !ALLOC_ARRAY( table->feature_tags, count, TT_ULong ) &&
             !ALLOC_ARRAY( table->features,     count, TT_Bool  ) )
        {
          table->features_table = bytes;
          table->features_len   = len;
        }
        return error;
      }
    
    
     /* add a lookup list to the table     */
     /* use only with a GSUB or GPOS table */
      LOCAL_FUNC
      TT_Error  OTL_Table_Set_Lookups( OTL_Table*  table,
                                       TT_Byte*    bytes,
                                       TT_Long     len )
      {
        TT_Error  error;
        TT_Byte*  p = bytes;
        TT_UInt   count;
    
        table->max_lookups = count = OTL_UShort(p);
        if ( !ALLOC_ARRAY( table->lookups, count, TT_Bool ) )
        {
          table->lookups_table = bytes;
          table->lookups_len   = len;
        }
        return error;
      }
    
     /* discard table arrays */
      LOCAL_FUNC
      void      OTL_Table_Done( OTL_Table*  table )
      {
        FREE( table->scrip_tags );
        FREE( table->language_tags );
        FREE( table->feature_tags );
        FREE( table->lookups );
      }
    
    
     /* return the list of available languages for a given script */
     /* use with any table..                                      */
      LOCAL_FUNC
      void  OTL_Get_Languages_List( OTL_Table*  table,
                                    TT_ULong    script_tag )
      {
        TT_UInt  n;
        TT_Byte* p;
        TT_Byte* script = 0;
        TT_Byte* start = table->scripts_table;
    
        if ( table->otl_type == otl_type_jstf )  /* skip version for JSTF */
          start += 4;
    
        p = start + 6; /* skip count+first tag */
    
        for ( n = 0; n < table->num_scripts; n++, p += 6 )
        {
          if ( table->script_tags[n] == script_tag )
          {
            script = table->scripts_table + OTL_UShort(p);
            break;
          }
        }
    
        table->cur_script = script;
        if (!script)
          table->num_languages = 0;
        else
        {
          /* now fill the language_tags array with the appropriate values    */
          /* not that we put a '0' tag in front of the list to indicate that */
          /* there is a default language for this script..                   */
          TT_ULong* tags = table->language_tags;
    
          switch (table->otl_type)
          {
            case otl_type_base:
            case otl_type_jstf:
              script += 2;    /* skip basevalue or extenders */
              /* fall-through */
    
            default:
              if ( OTL_UShort(script) )
                *tags++ = 0;
          }
    
          count = OTL_UShort(script);
          for ( ; count > 0; count-- )
          {
            *tags++ = OTL_ULong(script);
            script += 2; /* skip offset */
          }
    
          table->num_langs = tags - table->language_tags;
        }
      }
    
    
     /* return the list of available features for the current script/language */
     /* use with a GPOS or GSUB script table                                  */
      LOCAL_FUNC
      void OTL_Get_Features_List( OTL_Table*  table,
                                  TT_ULong    language_tag )
      {
        TT_UInt   n;
        TT_Byte*  script   = table->cur_script;
        TT_Byte*  language = 0;
        TT_UShort offset;
    
        /* clear feature selection table */
        for ( n = 0; n < table->max_features; n++ )
          table->features[n] = 0;
    
        /* now, look for the current language */
        if ( language_tag == 0 )
        {
          offset = OTL_UShort(script);
          if (!offset) return; /* if there is no default language, exit */
    
          language = script - 2 + offset;
        }
        else
        {
          TT_Byte*  p = script + 8; /* skip default+count+1st tag */
          TT_UShort index;
    
          for ( n = 0; n < table->num_languages; n++, p+=6 )
          {
            if ( table->language_tags[n] == language_tag )
            {
              language = script + OTL_UShort(p);
              break;
            }
          }
    
          table->cur_language = language;
          if (!language) return;
    
          p     = language + 2;   /* skip lookup order */
          index = OTL_UShort(p);  /* required feature index */
          if (index != 0xFFFF)
          {
            if (index < table->max_features)
              table->features[index] = 1;
          }
    
          count = OTL_UShort(p);
          for ( ; count > 0; count-- )
          {
            index = OTL_UShort(p);
            if (index < table->max_features)
              table->features[index] = 1;
          }
        }
      }
    
    
     /* return the list of lookups for the current features list */
     /* use only with a GSUB or GPOS table                       */
      LOCAL_FUNC
      void  OTL_Get_Lookups_List( OTL_Table*  table )
      {
        TT_UInt  n;
        TT_Byte* features = table->features_table;
        TT_Byte* p        = features + 6; /* skip count+1st tag */
    
        /* clear lookup list */
        for ( n = 0; n < table->max_lookups; n++ )
          table->lookups[n] = 0;
    
        /* now, parse the features list */
        for ( n = 0; n < table->features; n++ )
        {
          if (table->features[n])
          {
            TT_UInt   count;
            TT_UShort index;
            TT_Byte*  feature;
    
            feature = features + OTL_UShort(p);
            p      += 4;  /* skip tag */
    
            /* now, select all lookups from this feature */
            count = OTL_UShort(feature);
            for ( ; count > 0; count-- )
            {
              index = OTL_UShort(feature);
              if (index < table->max_lookups)
                table->lookups[index] = 1;
            }
          }
        }
      }
    
    
     /* find the basevalues and minmax for the current script/language */
     /* only use it with a BASE table..                                */
      LOCAL_FUNC
      void OTL_Get_Baseline_Values( OTL_Table*  table,
                                    TT_ULong    language_tag )
      {
        TT_Byte*  script   = table->cur_script;
        TT_Byte*  p        = script;
        TT_UShort offset, count;
    
        table->cur_basevalues = 0;
        table->cur_minmax     = 0;
    
        /* read basevalues */
        offset = OTL_UShort(p);
        if (offset)
          table->cur_basevalues = script + offset;
    
        offset = OTL_UShort(p);
        if (offset)
          table->cur_minmax = script + offset;
    
        count = OTL_UShort(p);
        for ( ; count > 0; count-- )
        {
          TT_ULong  tag;
    
          tag = OTL_ULong(p);
          if ( language_tag == tag )
          {
            table->cur_minmax = script + OTL_UShort(p);
            break;
          }
          p += 2; /* skip offset */
        }
      }
    
    
     /* compute the coverage value of a given glyph id */
      LOCAL_FUNC
      TT_Long  OTL_Get_Coverage_Index( TT_Byte*  coverage,
                                       TT_UInt   glyph_id )
      {
        TT_Long    result = -1;
        TT_UInt    count, index, start, end;
        TT_Byte*   p = coverage;
    
        switch ( OTL_UShort(p) )
        {
          case 1:  /* coverage format 1 - array of glyph indices */
            {
              count = OTL_UShort(p);
              for ( index = 0; index < count; index++ )
              {
                if ( OTL_UShort(p) == glyph_id )
                {
                  result = index;
                  break;
                }
              }
            }
            break;
    
          case 2:
            {
              count = OTL_UShort(p);
              for ( ; count > 0; count-- )
              {
                start = OTL_UShort(p);
                end   = OTL_UShort(p);
                index = OTL_UShort(p);
                if (start <= glyph_id && glyph_id <= end)
                {
                  result = glyph_id - start + index;
                  break;
                }
              }
            }
            break;
        }
        return result;
      }
    
    
     /* compute the class value of a given glyph_id */
      LOCAL_FUNC
      TT_UInt  OTL_Get_Glyph_Class( TT_Byte*  class_def,
                                    TT_UInt   glyph_id )
      {
        TT_Byte*  p = class_def;
        TT_UInt   result = 0;
        TT_UInt   start, end, count, index;
    
        switch ( OTL_UShort(p) )
        {
          case 1:
            {
              start = OTL_UShort(p);
              count = OTL_UShort(p);
    
              glyph_id -= start;
              if (glyph_id < count)
              {
                p += 2*glyph_id;
                result = OTL_UShort(p);
              }
            }
            break;
    
          case 2:
            {
              count = OTL_UShort(p);
              for ( ; count > 0; count-- )
              {
                start = OTL_UShort(p);
                end   = OTL_UShort(p);
                index = OTL_UShort(p);
                if ( start <= glyph_id && glyph_id <= end )
                {
                  result = index;
                  break;
                }
              }
            }
            break;
        }
        return result;
      }
    
    
     /* compute the adjustement necessary for a given device size */
      LOCAL_FUNC
      TT_Int  OTL_Get_Device_Adjustment( TT_Byte* device,
                                         TT_UInt  size )
      {
        TT_Byte*  p = device;
        TT_Int    result = 0;
        TT_UInt   start, end;
        TT_Short  value;
    
        start = OTL_UShort(p);
        end   = OTL_UShort(p);
        if (size >= start && size <= end)
        {
          /* I know we could do all of this without a switch, with */
          /* clever shifts and everything, but it makes the code   */
          /* really difficult to understand..                      */
    
          size -= start;
          switch ( OTL_UShort(p) )
          {
            case 1: /* 2-bits per value */
              {
                p     += 2*(size >> 3);
                size   = (size & 7) << 1;
                value  = (TT_Short)((TT_Short)OTL_UShort(p) << size);
                result = value >> 14;
              }
              break;
    
            case 2: /* 4-bits per value */
              {
                p     += 2*(size >> 2);
                size   = (size & 3) << 2;
                value  = (TT_Short)((TT_Short)OTL_UShort(p) << size);
                result = value >> 12;
              }
              break;
    
            case 3: /* 8-bits per value */
              {
                p     += 2*(size >> 1);
                size   = (size & 1) << 3;
                value  = (TT_Short)((TT_Short)OTL_UShort(p) << size);
                result = value >> 8;
              }
              break;
          }
        }
        return result;
      }
    
     /* extract a BaseCoord value */
      LOCAL_FUNC
      void    OTL_Get_Base_Coordinate( TT_Byte*          base_coord,
                                       OTL_ValueRecord*  coord )
      {
        TT_Byte*  p = base_coord;
        TT_Int    result = 0;
    
        coord->format     = OTL_UShort(p);
        coord->coordinate = OTL_Short(p);
        coord->device     = 0;
    
        switch (coord->format)
        {
          case 2: /* format 2 */
            coord->ref_glyph = OTL_UShort(p);
            coord->ref_point = OTL_UShort(p);
            break;
    
          case 3: /* format 3 */
            coord->device = p - 4 + OTL_UShort(p);
            break;
    
          default:
            ;
        }
      }
    
    
     /* compute size of ValueRecord */
     LOCAL_FUNC
     TT_Int  OTL_ValueRecord_Size( TT_UShort  format )
     {
       TT_Int  count;
    
       /* each bit in the value format corresponds to a single ushort */
       /* we thus count the bits, and multiply the result by 2        */
    
       count = (TT_Int)(format & 0xFF);
       count = ((count & 0xAA) >> 1) + (count & 0x55);
       count = ((count & 0xCC) >> 2) + (count & 0x33);
       count = ((count & 0xF0) >> 4) + (count & 0x0F);
    
       return count*2;
     }
    
    
    
     /* extract ValueRecord */
     LOCAL_FUNC
     void  OTL_Get_ValueRecord( TT_Byte*          value_record,
                                TT_UShort         value_format,
    			    TT_Byte*          pos_table,
    			    OTL_ValueRecord*  record )
     {
       TT_Byte*  p = value_record;
    
       /* clear vectors */
       record->placement.x = 0;
       record->placement.y = 0;
       record->advance.x   = 0;
       record->advance.y   = 0;
    
       record->device_pla_x = 0;
       record->device_pla_y = 0;
       record->device_adv_x = 0;
       record->device_adv_y = 0;
    
       if (value_format & 1) record->placement.x = NEXT_Short(p);
       if (value_format & 2) record->placement.y = NEXT_Short(p);
       if (value_format & 4) record->advance.x   = NEXT_Short(p);
       if (value_format & 8) record->advance.y   = NEXT_Short(p);
    
       if (value_format & 16)  record->device_pla_x = pos_table + NEXT_UShort(p);
       if (value_format & 32)  record->device_pla_y = pos_table + NEXT_UShort(p);
       if (value_format & 64)  record->device_adv_x = pos_table + NEXT_UShort(p);
       if (value_format & 128) record->device_adv_y = pos_table + NEXT_UShort(p);
     }
    
    
    
     /* extract Anchor */
     LOCAL_FUNC
     void  OTL_Get_Anchor( TT_Byte*     anchor_table,
                           OTL_Anchor*  anchor )
     {
       TT_Byte*  p = anchor_table;
    
       anchor->format   = NEXT_UShort(p);
       anchor->coord.x  = NEXT_Short(p);
       anchor->coord.y  = NEXT_Short(p);
       anchor->point    = 0;
       anchor->device_x = 0;
       anchor->device_y = 0;
    
       switch (anchor->format)
       {
         case 2:
           anchor->point = NEXT_UShort(p);
           break;
    
         case 3:
           anchor->device_x = anchor_table + NEXT_UShort(p);
           anchor->device_y = anchor_table + NEXT_UShort(p);
           break;
    
         default:
           ;
       }
     }
    
    
    
     /* extract Mark from MarkArray */
     LOCAL_FUNC
     void  OTL_Get_Mark( TT_Byte*     mark_array,
                         TT_UInt      index,
    		     TT_UShort*   clazz,
    		     OTL_Anchor*  anchor )
     {
       TT_Byte* p = mark_array;
       TT_UInt  count;
    
       *clazz = 0;
       MEM_Set( anchor, 0, sizeof(*anchor) );
    
       count = NEXT_UShort(p);
       if (index < count)
       {
         p += 4*index;
         *clazz = NEXT_UShort(p);
         OTL_Get_Anchor( mark_array + NEXT_UShort(p), anchor );
       }
     }