(root)/
freetype-2.13.2/
src/
psaux/
psstack.c
       1  /****************************************************************************
       2   *
       3   * psstack.c
       4   *
       5   *   Adobe's code for emulating a CFF stack (body).
       6   *
       7   * Copyright 2007-2013 Adobe Systems Incorporated.
       8   *
       9   * This software, and all works of authorship, whether in source or
      10   * object code form as indicated by the copyright notice(s) included
      11   * herein (collectively, the "Work") is made available, and may only be
      12   * used, modified, and distributed under the FreeType Project License,
      13   * LICENSE.TXT.  Additionally, subject to the terms and conditions of the
      14   * FreeType Project License, each contributor to the Work hereby grants
      15   * to any individual or legal entity exercising permissions granted by
      16   * the FreeType Project License and this section (hereafter, "You" or
      17   * "Your") a perpetual, worldwide, non-exclusive, no-charge,
      18   * royalty-free, irrevocable (except as stated in this section) patent
      19   * license to make, have made, use, offer to sell, sell, import, and
      20   * otherwise transfer the Work, where such license applies only to those
      21   * patent claims licensable by such contributor that are necessarily
      22   * infringed by their contribution(s) alone or by combination of their
      23   * contribution(s) with the Work to which such contribution(s) was
      24   * submitted.  If You institute patent litigation against any entity
      25   * (including a cross-claim or counterclaim in a lawsuit) alleging that
      26   * the Work or a contribution incorporated within the Work constitutes
      27   * direct or contributory patent infringement, then any patent licenses
      28   * granted to You under this License for that Work shall terminate as of
      29   * the date such litigation is filed.
      30   *
      31   * By using, modifying, or distributing the Work you indicate that you
      32   * have read and understood the terms and conditions of the
      33   * FreeType Project License as well as those provided in this section,
      34   * and you accept them fully.
      35   *
      36   */
      37  
      38  
      39  #include "psft.h"
      40  #include <freetype/internal/ftdebug.h>
      41  
      42  #include "psglue.h"
      43  #include "psfont.h"
      44  #include "psstack.h"
      45  
      46  #include "pserror.h"
      47  
      48  
      49    /* Allocate and initialize an instance of CF2_Stack.       */
      50    /* Note: This function returns NULL on error (does not set */
      51    /* `error').                                               */
      52    FT_LOCAL_DEF( CF2_Stack )
      53    cf2_stack_init( FT_Memory  memory,
      54                    FT_Error*  e,
      55                    FT_UInt    stackSize )
      56    {
      57      FT_Error   error;        /* for FT_QNEW */
      58      CF2_Stack  stack = NULL;
      59  
      60  
      61      if ( FT_QNEW( stack ) )
      62        return NULL;
      63  
      64      stack->memory = memory;
      65      stack->error  = e;
      66  
      67      /* allocate the stack buffer */
      68      if ( FT_QNEW_ARRAY( stack->buffer, stackSize ) )
      69      {
      70        FT_FREE( stack );
      71        return NULL;
      72      }
      73  
      74      stack->stackSize = stackSize;
      75      stack->top       = stack->buffer;     /* empty stack */
      76  
      77      return stack;
      78    }
      79  
      80  
      81    FT_LOCAL_DEF( void )
      82    cf2_stack_free( CF2_Stack  stack )
      83    {
      84      if ( stack )
      85      {
      86        FT_Memory  memory = stack->memory;
      87  
      88        /* free the buffer */
      89        FT_FREE( stack->buffer );
      90  
      91        /* free the main structure */
      92        FT_FREE( stack );
      93      }
      94    }
      95  
      96  
      97    FT_LOCAL_DEF( CF2_UInt )
      98    cf2_stack_count( CF2_Stack  stack )
      99    {
     100      return (CF2_UInt)( stack->top - stack->buffer );
     101    }
     102  
     103  
     104    FT_LOCAL_DEF( void )
     105    cf2_stack_pushInt( CF2_Stack  stack,
     106                       CF2_Int    val )
     107    {
     108      if ( stack->top == stack->buffer + stack->stackSize )
     109      {
     110        CF2_SET_ERROR( stack->error, Stack_Overflow );
     111        return;     /* stack overflow */
     112      }
     113  
     114      stack->top->u.i  = val;
     115      stack->top->type = CF2_NumberInt;
     116      stack->top++;
     117    }
     118  
     119  
     120    FT_LOCAL_DEF( void )
     121    cf2_stack_pushFixed( CF2_Stack  stack,
     122                         CF2_Fixed  val )
     123    {
     124      if ( stack->top == stack->buffer + stack->stackSize )
     125      {
     126        CF2_SET_ERROR( stack->error, Stack_Overflow );
     127        return;     /* stack overflow */
     128      }
     129  
     130      stack->top->u.r  = val;
     131      stack->top->type = CF2_NumberFixed;
     132      stack->top++;
     133    }
     134  
     135  
     136    /* this function is only allowed to pop an integer type */
     137    FT_LOCAL_DEF( CF2_Int )
     138    cf2_stack_popInt( CF2_Stack  stack )
     139    {
     140      if ( stack->top == stack->buffer )
     141      {
     142        CF2_SET_ERROR( stack->error, Stack_Underflow );
     143        return 0;   /* underflow */
     144      }
     145      if ( stack->top[-1].type != CF2_NumberInt )
     146      {
     147        CF2_SET_ERROR( stack->error, Syntax_Error );
     148        return 0;   /* type mismatch */
     149      }
     150  
     151      stack->top--;
     152  
     153      return stack->top->u.i;
     154    }
     155  
     156  
     157    /* Note: type mismatch is silently cast */
     158    /* TODO: check this                     */
     159    FT_LOCAL_DEF( CF2_Fixed )
     160    cf2_stack_popFixed( CF2_Stack  stack )
     161    {
     162      if ( stack->top == stack->buffer )
     163      {
     164        CF2_SET_ERROR( stack->error, Stack_Underflow );
     165        return cf2_intToFixed( 0 );    /* underflow */
     166      }
     167  
     168      stack->top--;
     169  
     170      switch ( stack->top->type )
     171      {
     172      case CF2_NumberInt:
     173        return cf2_intToFixed( stack->top->u.i );
     174      case CF2_NumberFrac:
     175        return cf2_fracToFixed( stack->top->u.f );
     176      default:
     177        return stack->top->u.r;
     178      }
     179    }
     180  
     181  
     182    /* Note: type mismatch is silently cast */
     183    /* TODO: check this                     */
     184    FT_LOCAL_DEF( CF2_Fixed )
     185    cf2_stack_getReal( CF2_Stack  stack,
     186                       CF2_UInt   idx )
     187    {
     188      FT_ASSERT( cf2_stack_count( stack ) <= stack->stackSize );
     189  
     190      if ( idx >= cf2_stack_count( stack ) )
     191      {
     192        CF2_SET_ERROR( stack->error, Stack_Overflow );
     193        return cf2_intToFixed( 0 );    /* bounds error */
     194      }
     195  
     196      switch ( stack->buffer[idx].type )
     197      {
     198      case CF2_NumberInt:
     199        return cf2_intToFixed( stack->buffer[idx].u.i );
     200      case CF2_NumberFrac:
     201        return cf2_fracToFixed( stack->buffer[idx].u.f );
     202      default:
     203        return stack->buffer[idx].u.r;
     204      }
     205    }
     206  
     207  
     208    /* provide random access to stack */
     209    FT_LOCAL_DEF( void )
     210    cf2_stack_setReal( CF2_Stack  stack,
     211                       CF2_UInt   idx,
     212                       CF2_Fixed  val )
     213    {
     214      if ( idx > cf2_stack_count( stack ) )
     215      {
     216        CF2_SET_ERROR( stack->error, Stack_Overflow );
     217        return;
     218      }
     219  
     220      stack->buffer[idx].u.r  = val;
     221      stack->buffer[idx].type = CF2_NumberFixed;
     222    }
     223  
     224  
     225    /* discard (pop) num values from stack */
     226    FT_LOCAL_DEF( void )
     227    cf2_stack_pop( CF2_Stack  stack,
     228                   CF2_UInt   num )
     229    {
     230      if ( num > cf2_stack_count( stack ) )
     231      {
     232        CF2_SET_ERROR( stack->error, Stack_Underflow );
     233        return;
     234      }
     235      stack->top -= num;
     236    }
     237  
     238  
     239    FT_LOCAL_DEF( void )
     240    cf2_stack_roll( CF2_Stack  stack,
     241                    CF2_Int    count,
     242                    CF2_Int    shift )
     243    {
     244      /* we initialize this variable to avoid compiler warnings */
     245      CF2_StackNumber  last = { { 0 }, CF2_NumberInt };
     246  
     247      CF2_Int  start_idx, idx, i;
     248  
     249  
     250      if ( count < 2 )
     251        return; /* nothing to do (values 0 and 1), or undefined value */
     252  
     253      if ( (CF2_UInt)count > cf2_stack_count( stack ) )
     254      {
     255        CF2_SET_ERROR( stack->error, Stack_Overflow );
     256        return;
     257      }
     258  
     259      /* before C99 it is implementation-defined whether    */
     260      /* the result of `%' is negative if the first operand */
     261      /* is negative                                        */
     262      if ( shift < 0 )
     263        shift = -( ( -shift ) % count );
     264      else
     265        shift %= count;
     266  
     267      if ( shift == 0 )
     268        return; /* nothing to do */
     269  
     270      /* We use the following algorithm to do the rolling, */
     271      /* which needs two temporary variables only.         */
     272      /*                                                   */
     273      /* Example:                                          */
     274      /*                                                   */
     275      /*   count = 8                                       */
     276      /*   shift = 2                                       */
     277      /*                                                   */
     278      /*   stack indices before roll:  7 6 5 4 3 2 1 0     */
     279      /*   stack indices after roll:   1 0 7 6 5 4 3 2     */
     280      /*                                                   */
     281      /* The value of index 0 gets moved to index 2, while */
     282      /* the old value of index 2 gets moved to index 4,   */
     283      /* and so on.  We thus have the following copying    */
     284      /* chains for shift value 2.                         */
     285      /*                                                   */
     286      /*   0 -> 2 -> 4 -> 6 -> 0                           */
     287      /*   1 -> 3 -> 5 -> 7 -> 1                           */
     288      /*                                                   */
     289      /* If `count' and `shift' are incommensurable, we    */
     290      /* have a single chain only.  Otherwise, increase    */
     291      /* the start index by 1 after the first chain, then  */
     292      /* do the next chain until all elements in all       */
     293      /* chains are handled.                               */
     294  
     295      start_idx = -1;
     296      idx       = -1;
     297      for ( i = 0; i < count; i++ )
     298      {
     299        CF2_StackNumber  tmp;
     300  
     301  
     302        if ( start_idx == idx )
     303        {
     304          start_idx++;
     305          idx  = start_idx;
     306          last = stack->buffer[idx];
     307        }
     308  
     309        idx += shift;
     310        if ( idx >= count )
     311          idx -= count;
     312        else if ( idx < 0 )
     313          idx += count;
     314  
     315        tmp                = stack->buffer[idx];
     316        stack->buffer[idx] = last;
     317        last               = tmp;
     318      }
     319    }
     320  
     321  
     322    FT_LOCAL_DEF( void )
     323    cf2_stack_clear( CF2_Stack  stack )
     324    {
     325      stack->top = stack->buffer;
     326    }
     327  
     328  
     329  /* END */