/* otlbuffer.c: Buffer of glyphs for substitution/positioning
 *
 * Copyright 2004 Red Hat Software
 *
 * Portions Copyright 1996-2000 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 <config.h>

#include <otlbuffer.h>

/* To get the gcc-3.3 strict-aliasing compatible versions
 * FREE/REALLOC_ARRAY/etc. rather than the FT_* versions
 * that
 */
#include "ftglue.h"

  static FT_Error
  otl_buffer_ensure( OTL_Buffer buffer,
		     FT_ULong   size )
  {
    FT_Memory memory = buffer->memory;
    FT_ULong new_allocated = buffer->allocated;

    if (size > new_allocated)
      {
	FT_Error error;

	while (size > new_allocated)
	  new_allocated += (new_allocated >> 1) + 8;
	
	if ( REALLOC_ARRAY( buffer->in_string, buffer->allocated, new_allocated, OTL_GlyphItemRec ) )
	  return error;
	if ( REALLOC_ARRAY( buffer->out_string, buffer->allocated, new_allocated, OTL_GlyphItemRec ) )
	  return error;
	if ( REALLOC_ARRAY( buffer->positions, buffer->allocated, new_allocated, OTL_PositionRec ) )
	  return error;

	buffer->allocated = new_allocated;
      }

    return FT_Err_Ok;
  }

  FT_Error
  otl_buffer_new( FT_Memory   memory,
		  OTL_Buffer *buffer )
  {
    FT_Error error;
    
    if ( ALLOC( *buffer, sizeof( OTL_BufferRec ) ) )
      return error;

    (*buffer)->memory = memory;
    (*buffer)->in_length = 0;
    (*buffer)->out_length = 0;
    (*buffer)->allocated = 0;
    (*buffer)->in_pos = 0;
    (*buffer)->out_pos = 0;

    (*buffer)->in_string = NULL;
    (*buffer)->out_string = NULL;
    (*buffer)->positions = NULL;
    (*buffer)->max_ligID = 0;

    return FT_Err_Ok;
  }

  FT_Error
  otl_buffer_swap( OTL_Buffer buffer )
  {
    OTL_GlyphItem tmp_string;

    tmp_string = buffer->in_string;
    buffer->in_string = buffer->out_string;
    buffer->out_string = tmp_string;

    buffer->in_length = buffer->out_length;
    buffer->out_length = 0;
    
    buffer->in_pos = 0;
    buffer->out_pos = 0;

    return FT_Err_Ok;
  }

  FT_Error
  otl_buffer_free( OTL_Buffer buffer )
  {
    FT_Memory memory = buffer->memory;

    FREE( buffer->in_string );
    FREE( buffer->out_string );
    FREE( buffer->positions );
    FREE( buffer );

    return FT_Err_Ok;
  }

  FT_Error
  otl_buffer_clear( OTL_Buffer buffer )
  {
    buffer->in_length = 0;
    buffer->out_length = 0;
    buffer->in_pos = 0;
    buffer->out_pos = 0;
    
    return FT_Err_Ok;
  }

  FT_Error
  otl_buffer_add_glyph( OTL_Buffer buffer,
			FT_UInt    glyph_index,
			FT_UInt    properties,
			FT_UInt    cluster )
  {
    FT_Error error;
    OTL_GlyphItem glyph;
    
    error = otl_buffer_ensure( buffer, buffer->in_length + 1 );
    if ( error )
      return error;

    glyph = &buffer->in_string[buffer->in_length];
    glyph->gindex = glyph_index;
    glyph->properties = properties;
    glyph->cluster = cluster;
    glyph->component = 0;
    glyph->ligID = 0;
    glyph->gproperties = OTL_GLYPH_PROPERTIES_UNKNOWN;
    
    buffer->in_length++;

    return FT_Err_Ok;
  }

  /* The following function copies `num_out' elements from `glyph_data'
     to `buffer->out_string', advancing the in array pointer in the structure
     by `num_in' elements, and the out array pointer by `num_out' elements.
     Finally, it sets the `length' field of `out' equal to
     `pos' of the `out' structure.

     If `component' is 0xFFFF, the component value from buffer->in_pos
     will copied `num_out' times, otherwise `component' itself will
     be used to fill the `component' fields.

     If `ligID' is 0xFFFF, the ligID value from buffer->in_pos
     will copied `num_out' times, otherwise `ligID' itself will
     be used to fill the `ligID' fields.

     The properties for all replacement glyphs are taken
     from the glyph at position `buffer->in_pos'.

     The cluster value for the glyph at position buffer->in_pos is used
     for all replacement glyphs */
  FT_Error
  otl_buffer_add_output_glyphs( OTL_Buffer buffer,
				FT_UShort  num_in,
				FT_UShort  num_out,
				FT_UShort *glyph_data,
				FT_UShort  component,
				FT_UShort  ligID )
  {
    FT_Error  error;
    FT_UShort i;
    FT_UInt properties;
    FT_UInt cluster;

    error = otl_buffer_ensure( buffer, buffer->out_pos + num_out );
    if ( error )
      return error;

    properties = buffer->in_string[buffer->in_pos].properties;
    cluster = buffer->in_string[buffer->in_pos].cluster;
    if ( component == 0xFFFF )
      component = buffer->in_string[buffer->in_pos].component;
    if ( ligID == 0xFFFF )
      ligID = buffer->in_string[buffer->in_pos].ligID;

    for ( i = 0; i < num_out; i++ )
    {
      OTL_GlyphItem item = &buffer->out_string[buffer->out_pos + i];

      item->gindex = glyph_data[i];
      item->properties = properties;
      item->cluster = cluster;
      item->component = component;
      item->ligID = ligID;
      item->gproperties = OTL_GLYPH_PROPERTIES_UNKNOWN;
    }

    buffer->in_pos  += num_in;
    buffer->out_pos += num_out;

    buffer->out_length = buffer->out_pos;

    return FT_Err_Ok;
  }

  FT_Error
  otl_buffer_add_output_glyph( OTL_Buffer buffer,	
			       FT_UInt    glyph_index,
			       FT_UShort  component,
			       FT_UShort  ligID )
  {
    FT_UShort glyph_data =  glyph_index;

    return otl_buffer_add_output_glyphs ( buffer, 1, 1,
					  &glyph_data, component, ligID );
  }

  FT_Error
  otl_buffer_copy_output_glyph ( OTL_Buffer buffer )
  {  
    FT_Error  error;

    error = otl_buffer_ensure( buffer, buffer->out_pos + 1 );
    if ( error )
      return error;
    
    buffer->out_string[buffer->out_pos++] = buffer->in_string[buffer->in_pos++];
    buffer->out_length = buffer->out_pos;

    return FT_Err_Ok;
  }

  FT_UShort
  otl_buffer_allocate_ligid( OTL_Buffer buffer )
  {
    return buffer->max_ligID++;
  }
