11512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod/*
21512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod * Copyright (C) 1998-2004  David Turner and Werner Lemberg
31512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod * Copyright (C) 2004,2007  Red Hat, Inc.
41512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod *
51512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod * This is part of HarfBuzz, an OpenType Layout engine library.
61512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod *
71512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod * Permission is hereby granted, without written agreement and without
81512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod * license or royalty fees, to use, copy, modify, and distribute this
91512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod * software and its documentation for any purpose, provided that the
101512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod * above copyright notice and the following two paragraphs appear in
111512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod * all copies of this software.
121512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod *
131512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
141512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
151512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
161512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
171512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod * DAMAGE.
181512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod *
191512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
201512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
211512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
221512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
231512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
241512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod *
251512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod * Red Hat Author(s): Owen Taylor, Behdad Esfahbod
261512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod */
271512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
281512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod#include "harfbuzz-impl.h"
291512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod#include "harfbuzz-buffer-private.h"
301512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod#include "harfbuzz-gsub-private.h"
311512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod#include "harfbuzz-gpos-private.h"
321512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
331512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod/* Here is how the buffer works internally:
341512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod *
351512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod * There are two string pointers: in_string and out_string.  They
361512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod * always have same allocated size, but different length and positions.
371512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod *
381512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod * As an optimization, both in_string and out_string may point to the
391512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod * same piece of memory, which is owned by in_string.  This remains the
401512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod * case as long as:
411512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod *
421512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod *   - copy_glyph() is called
431512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod *   - replace_glyph() is called with inplace=TRUE
441512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod *   - add_output_glyph() and add_output_glyphs() are not called
451512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod *
461512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod * In that case swap(), and copy_glyph(), and replace_glyph() are all
471512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod * mostly no-op.
481512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod *
491512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod * As soon an add_output_glyph[s]() or replace_glyph() with inplace=FALSE is
501512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod * called, out_string is moved over to an alternate buffer (alt_string), and
511512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod * its current contents (out_length entries) are copied to the alt buffer.
521512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod * This should all remain transparent to the user.  swap() then switches
531512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod * in_string and alt_string.  alt_string is not allocated until its needed,
541512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod * but after that it's grown with in_string unconditionally.
551512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod *
561512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod * The buffer->separate_out boolean keeps status of whether out_string points
571512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod * to in_string (FALSE) or alt_string (TRUE).
581512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod */
591512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
601512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod/* Internal API */
611512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
621512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbodstatic HB_Error
63fb47209c5b3aa992faf18d1a3f78b9d7682cf62fBehdad EsfahbodHB_Buffer_ensure( HB_Buffer buffer,
641512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod		   HB_UInt   size )
651512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod{
661512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_UInt new_allocated = buffer->allocated;
671512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
681512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  if (size > new_allocated)
691512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    {
701512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod      HB_Error error;
711512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
721512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod      while (size > new_allocated)
731512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod	new_allocated += (new_allocated >> 1) + 8;
741512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
751512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod      if ( buffer->positions )
761512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod        {
771512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod	  if ( REALLOC_ARRAY( buffer->positions, new_allocated, HB_PositionRec ) )
781512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod	    return error;
791512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod	}
801512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
811512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod      if ( REALLOC_ARRAY( buffer->in_string, new_allocated, HB_GlyphItemRec ) )
821512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod	return error;
831512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
841512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod      if ( buffer->separate_out )
851512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod        {
861512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod	  if ( REALLOC_ARRAY( buffer->alt_string, new_allocated, HB_GlyphItemRec ) )
871512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod	    return error;
881512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
891512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod	  buffer->out_string = buffer->alt_string;
901512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod	}
911512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod      else
921512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod        {
931512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod	  buffer->out_string = buffer->in_string;
941512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
951512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod	  if ( buffer->alt_string )
961512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod	    {
971512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod	      if ( REALLOC_ARRAY( buffer->alt_string, new_allocated, HB_GlyphItemRec ) )
981512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod		return error;
991512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod	    }
1001512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod	}
1011512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
1021512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod      buffer->allocated = new_allocated;
1031512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    }
1041512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
1051512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  return HB_Err_Ok;
1061512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod}
1071512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
1081512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbodstatic HB_Error
109fb47209c5b3aa992faf18d1a3f78b9d7682cf62fBehdad EsfahbodHB_Buffer_duplicate_out_buffer( HB_Buffer buffer )
1101512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod{
1111512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  if ( !buffer->alt_string )
1121512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    {
1131512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod      HB_Error error;
1141512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
1151512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod      if ( ALLOC_ARRAY( buffer->alt_string, buffer->allocated, HB_GlyphItemRec ) )
1161512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod	return error;
1171512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    }
1181512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
1191512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  buffer->out_string = buffer->alt_string;
1201512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  memcpy( buffer->out_string, buffer->in_string, buffer->out_length * sizeof (buffer->out_string[0]) );
1211512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  buffer->separate_out = TRUE;
1221512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
1231512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  return HB_Err_Ok;
1241512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod}
1251512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
1261512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod/* Public API */
1271512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
1281512a7357513b72e2a07dda706a176bb23d694e9Behdad EsfahbodHB_Error
129fb47209c5b3aa992faf18d1a3f78b9d7682cf62fBehdad EsfahbodHB_Buffer_new( HB_Buffer *pbuffer )
1301512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod{
1311512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_Buffer buffer;
1321512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_Error error;
1331512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
1341512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  if ( ALLOC( buffer, sizeof( HB_BufferRec ) ) )
1351512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    return error;
1361512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
1371512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  buffer->allocated = 0;
1381512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  buffer->in_string = NULL;
1391512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  buffer->alt_string = NULL;
1401512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  buffer->positions = NULL;
1411512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
142fb47209c5b3aa992faf18d1a3f78b9d7682cf62fBehdad Esfahbod  HB_Buffer_clear( buffer );
1431512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
1441512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  *pbuffer = buffer;
1451512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
1461512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  return HB_Err_Ok;
1471512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod}
1481512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
1491512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbodvoid
150fb47209c5b3aa992faf18d1a3f78b9d7682cf62fBehdad EsfahbodHB_Buffer_free( HB_Buffer buffer )
1511512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod{
1521512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  FREE( buffer->in_string );
1531512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  FREE( buffer->alt_string );
1541512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  buffer->out_string = NULL;
1551512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  FREE( buffer->positions );
1561512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  FREE( buffer );
1571512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod}
1581512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
1591512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbodvoid
160fb47209c5b3aa992faf18d1a3f78b9d7682cf62fBehdad EsfahbodHB_Buffer_clear( HB_Buffer buffer )
1611512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod{
1621512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  buffer->in_length = 0;
1631512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  buffer->out_length = 0;
1641512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  buffer->in_pos = 0;
1651512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  buffer->out_pos = 0;
1661512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  buffer->out_string = buffer->in_string;
1671512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  buffer->separate_out = FALSE;
1681512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  buffer->max_ligID = 0;
1691512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod}
1701512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
1711512a7357513b72e2a07dda706a176bb23d694e9Behdad EsfahbodHB_Error
172fb47209c5b3aa992faf18d1a3f78b9d7682cf62fBehdad EsfahbodHB_Buffer_add_glyph( HB_Buffer buffer,
1731512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod		      HB_UInt   glyph_index,
1741512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod		      HB_UInt   properties,
1751512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod		      HB_UInt   cluster )
1761512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod{
1771512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_Error error;
1781512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_GlyphItem glyph;
1791512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
180fb47209c5b3aa992faf18d1a3f78b9d7682cf62fBehdad Esfahbod  error = HB_Buffer_ensure( buffer, buffer->in_length + 1 );
1811512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  if ( error )
1821512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    return error;
1831512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
1841512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  glyph = &buffer->in_string[buffer->in_length];
1851512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  glyph->gindex = glyph_index;
1861512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  glyph->properties = properties;
1871512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  glyph->cluster = cluster;
1881512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  glyph->component = 0;
1891512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  glyph->ligID = 0;
1901512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  glyph->gproperties = HB_GLYPH_PROPERTIES_UNKNOWN;
1911512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
1921512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  buffer->in_length++;
1931512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
1941512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  return HB_Err_Ok;
1951512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod}
1961512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
1971512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod/* HarfBuzz-Internal API */
1981512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
1991512a7357513b72e2a07dda706a176bb23d694e9Behdad EsfahbodHB_INTERNAL void
2001512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod_hb_buffer_clear_output( HB_Buffer buffer )
2011512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod{
2021512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  buffer->out_length = 0;
2031512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  buffer->out_pos = 0;
2041512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  buffer->out_string = buffer->in_string;
2051512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  buffer->separate_out = FALSE;
2061512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod}
2071512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
2081512a7357513b72e2a07dda706a176bb23d694e9Behdad EsfahbodHB_INTERNAL HB_Error
2091512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod_hb_buffer_clear_positions( HB_Buffer buffer )
2101512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod{
2111512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  if ( !buffer->positions )
2121512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    {
2131512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod      HB_Error error;
2141512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
2151512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod      if ( ALLOC_ARRAY( buffer->positions, buffer->allocated, HB_PositionRec ) )
2161512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod	return error;
2171512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    }
2181512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
2191512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  memset (buffer->positions, 0, sizeof (buffer->positions[0]) * buffer->in_length);
2201512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
2211512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  return HB_Err_Ok;
2221512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod}
2231512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
2241512a7357513b72e2a07dda706a176bb23d694e9Behdad EsfahbodHB_INTERNAL void
2251512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod_hb_buffer_swap( HB_Buffer buffer )
2261512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod{
2271512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_GlyphItem tmp_string;
2281512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  int tmp_length;
2291512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  int tmp_pos;
2301512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
2311512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  if ( buffer->separate_out )
2321512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    {
2331512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod      tmp_string = buffer->in_string;
2341512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod      buffer->in_string = buffer->out_string;
2351512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod      buffer->out_string = tmp_string;
2361512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod      buffer->alt_string = buffer->out_string;
2371512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    }
2381512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
2391512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  tmp_length = buffer->in_length;
2401512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  buffer->in_length = buffer->out_length;
2411512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  buffer->out_length = tmp_length;
2421512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
2431512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  tmp_pos = buffer->in_pos;
2441512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  buffer->in_pos = buffer->out_pos;
2451512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  buffer->out_pos = tmp_pos;
2461512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod}
2471512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
2481512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod/* The following function copies `num_out' elements from `glyph_data'
2491512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod   to `buffer->out_string', advancing the in array pointer in the structure
2501512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod   by `num_in' elements, and the out array pointer by `num_out' elements.
2511512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod   Finally, it sets the `length' field of `out' equal to
2521512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod   `pos' of the `out' structure.
2531512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
2541512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod   If `component' is 0xFFFF, the component value from buffer->in_pos
2551512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod   will copied `num_out' times, otherwise `component' itself will
2561512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod   be used to fill the `component' fields.
2571512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
2581512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod   If `ligID' is 0xFFFF, the ligID value from buffer->in_pos
2591512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod   will copied `num_out' times, otherwise `ligID' itself will
2601512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod   be used to fill the `ligID' fields.
2611512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
2621512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod   The properties for all replacement glyphs are taken
2631512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod   from the glyph at position `buffer->in_pos'.
2641512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
2651512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod   The cluster value for the glyph at position buffer->in_pos is used
2661512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod   for all replacement glyphs */
2671512a7357513b72e2a07dda706a176bb23d694e9Behdad EsfahbodHB_INTERNAL HB_Error
2681512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod_hb_buffer_add_output_glyphs( HB_Buffer  buffer,
2691512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod			      HB_UShort  num_in,
2701512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod			      HB_UShort  num_out,
2711512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod			      HB_UShort *glyph_data,
2721512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod			      HB_UShort  component,
2731512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod			      HB_UShort  ligID )
2741512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod{
2751512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_Error  error;
2761512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_UShort i;
2771512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_UInt properties;
2781512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_UInt cluster;
2791512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
280fb47209c5b3aa992faf18d1a3f78b9d7682cf62fBehdad Esfahbod  error = HB_Buffer_ensure( buffer, buffer->out_pos + num_out );
2811512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  if ( error )
2821512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    return error;
2831512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
2841512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  if ( !buffer->separate_out )
2851512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    {
286fb47209c5b3aa992faf18d1a3f78b9d7682cf62fBehdad Esfahbod      error = HB_Buffer_duplicate_out_buffer( buffer );
2871512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod      if ( error )
2881512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod	return error;
2891512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    }
2901512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
2911512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  properties = buffer->in_string[buffer->in_pos].properties;
2921512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  cluster = buffer->in_string[buffer->in_pos].cluster;
2931512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  if ( component == 0xFFFF )
2941512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    component = buffer->in_string[buffer->in_pos].component;
2951512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  if ( ligID == 0xFFFF )
2961512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    ligID = buffer->in_string[buffer->in_pos].ligID;
2971512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
2981512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  for ( i = 0; i < num_out; i++ )
2991512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  {
3001512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    HB_GlyphItem item = &buffer->out_string[buffer->out_pos + i];
3011512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
3021512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    item->gindex = glyph_data[i];
3031512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    item->properties = properties;
3041512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    item->cluster = cluster;
3051512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    item->component = component;
3061512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    item->ligID = ligID;
3071512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    item->gproperties = HB_GLYPH_PROPERTIES_UNKNOWN;
3081512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  }
3091512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
3101512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  buffer->in_pos  += num_in;
3111512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  buffer->out_pos += num_out;
3121512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
3131512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  buffer->out_length = buffer->out_pos;
3141512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
3151512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  return HB_Err_Ok;
3161512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod}
3171512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
3181512a7357513b72e2a07dda706a176bb23d694e9Behdad EsfahbodHB_INTERNAL HB_Error
3191512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod_hb_buffer_add_output_glyph( HB_Buffer buffer,
3201512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod			     HB_UInt   glyph_index,
3211512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod			     HB_UShort component,
3221512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod			     HB_UShort ligID )
3231512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod{
3241512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_UShort glyph_data =  glyph_index;
3251512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
3261512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  return _hb_buffer_add_output_glyphs ( buffer, 1, 1,
3271512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod					&glyph_data, component, ligID );
3281512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod}
3291512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
3301512a7357513b72e2a07dda706a176bb23d694e9Behdad EsfahbodHB_INTERNAL HB_Error
3311512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod_hb_buffer_copy_output_glyph ( HB_Buffer buffer )
3321512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod{
3331512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_Error  error;
3341512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
335fb47209c5b3aa992faf18d1a3f78b9d7682cf62fBehdad Esfahbod  error = HB_Buffer_ensure( buffer, buffer->out_pos + 1 );
3361512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  if ( error )
3371512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    return error;
3381512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
3391512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  if ( buffer->separate_out )
3401512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    {
3411512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod      buffer->out_string[buffer->out_pos] = buffer->in_string[buffer->in_pos];
3421512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    }
3431512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
3441512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  buffer->in_pos++;
3451512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  buffer->out_pos++;
3461512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  buffer->out_length = buffer->out_pos;
3471512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
3481512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  return HB_Err_Ok;
3491512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod}
3501512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
3511512a7357513b72e2a07dda706a176bb23d694e9Behdad EsfahbodHB_INTERNAL HB_Error
3521512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod_hb_buffer_replace_output_glyph( HB_Buffer buffer,
3531512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod				 HB_UInt   glyph_index,
3541512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod				 HB_Bool   inplace )
3551512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod{
3561512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
3571512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  HB_Error error;
3581512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
3591512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  if ( inplace )
3601512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    {
3611512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod      error = _hb_buffer_copy_output_glyph ( buffer );
3621512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod      if ( error )
3631512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod	return error;
3641512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
3651512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod      buffer->out_string[buffer->out_pos-1].gindex = glyph_index;
3661512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    }
3671512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  else
3681512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    {
3691512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod      return _hb_buffer_add_output_glyph( buffer, glyph_index, 0xFFFF, 0xFFFF );
3701512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    }
3711512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
3721512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  return HB_Err_Ok;
3731512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod}
3741512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
3751512a7357513b72e2a07dda706a176bb23d694e9Behdad EsfahbodHB_INTERNAL HB_UShort
3761512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod_hb_buffer_allocate_ligid( HB_Buffer buffer )
3771512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod{
3781512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  buffer->max_ligID++;
3791512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  if (HB_UNLIKELY (buffer->max_ligID == 0))
3801512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod    buffer->max_ligID++;
3811512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod
3821512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod  return buffer->max_ligID;
3831512a7357513b72e2a07dda706a176bb23d694e9Behdad Esfahbod}
384