1/***************************************************************************/
2/*                                                                         */
3/*  cf2stack.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 "cf2ft.h"
40#include FT_INTERNAL_DEBUG_H
41
42#include "cf2glue.h"
43#include "cf2font.h"
44#include "cf2stack.h"
45
46#include "cf2error.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  {
56    FT_Error  error = FT_Err_Ok;     /* for FT_QNEW */
57
58    CF2_Stack  stack = NULL;
59
60
61    if ( !FT_QNEW( stack ) )
62    {
63      /* initialize the structure; FT_QNEW zeroes it */
64      stack->memory = memory;
65      stack->error  = e;
66      stack->top    = &stack->buffer[0]; /* empty stack */
67    }
68
69    return stack;
70  }
71
72
73  FT_LOCAL_DEF( void )
74  cf2_stack_free( CF2_Stack  stack )
75  {
76    if ( stack )
77    {
78      FT_Memory  memory = stack->memory;
79
80
81      /* free the main structure */
82      FT_FREE( stack );
83    }
84  }
85
86
87  FT_LOCAL_DEF( CF2_UInt )
88  cf2_stack_count( CF2_Stack  stack )
89  {
90    return (CF2_UInt)( stack->top - &stack->buffer[0] );
91  }
92
93
94  FT_LOCAL_DEF( void )
95  cf2_stack_pushInt( CF2_Stack  stack,
96                     CF2_Int    val )
97  {
98    if ( stack->top == &stack->buffer[CF2_OPERAND_STACK_SIZE] )
99    {
100      CF2_SET_ERROR( stack->error, Stack_Overflow );
101      return;     /* stack overflow */
102    }
103
104    stack->top->u.i  = val;
105    stack->top->type = CF2_NumberInt;
106    ++stack->top;
107  }
108
109
110  FT_LOCAL_DEF( void )
111  cf2_stack_pushFixed( CF2_Stack  stack,
112                       CF2_Fixed  val )
113  {
114    if ( stack->top == &stack->buffer[CF2_OPERAND_STACK_SIZE] )
115    {
116      CF2_SET_ERROR( stack->error, Stack_Overflow );
117      return;     /* stack overflow */
118    }
119
120    stack->top->u.r  = val;
121    stack->top->type = CF2_NumberFixed;
122    ++stack->top;
123  }
124
125
126  /* this function is only allowed to pop an integer type */
127  FT_LOCAL_DEF( CF2_Int )
128  cf2_stack_popInt( CF2_Stack  stack )
129  {
130    if ( stack->top == &stack->buffer[0] )
131    {
132      CF2_SET_ERROR( stack->error, Stack_Underflow );
133      return 0;   /* underflow */
134    }
135    if ( stack->top[-1].type != CF2_NumberInt )
136    {
137      CF2_SET_ERROR( stack->error, Syntax_Error );
138      return 0;   /* type mismatch */
139    }
140
141    --stack->top;
142
143    return stack->top->u.i;
144  }
145
146
147  /* Note: type mismatch is silently cast */
148  /* TODO: check this */
149  FT_LOCAL_DEF( CF2_Fixed )
150  cf2_stack_popFixed( CF2_Stack  stack )
151  {
152    if ( stack->top == &stack->buffer[0] )
153    {
154      CF2_SET_ERROR( stack->error, Stack_Underflow );
155      return cf2_intToFixed( 0 );    /* underflow */
156    }
157
158    --stack->top;
159
160    switch ( stack->top->type )
161    {
162    case CF2_NumberInt:
163      return cf2_intToFixed( stack->top->u.i );
164    case CF2_NumberFrac:
165      return cf2_fracToFixed( stack->top->u.f );
166    default:
167      return stack->top->u.r;
168    }
169  }
170
171
172  /* Note: type mismatch is silently cast */
173  /* TODO: check this */
174  FT_LOCAL_DEF( CF2_Fixed )
175  cf2_stack_getReal( CF2_Stack  stack,
176                     CF2_UInt   idx )
177  {
178    FT_ASSERT( cf2_stack_count( stack ) <= CF2_OPERAND_STACK_SIZE );
179
180    if ( idx >= cf2_stack_count( stack ) )
181    {
182      CF2_SET_ERROR( stack->error, Stack_Overflow );
183      return cf2_intToFixed( 0 );    /* bounds error */
184    }
185
186    switch ( stack->buffer[idx].type )
187    {
188    case CF2_NumberInt:
189      return cf2_intToFixed( stack->buffer[idx].u.i );
190    case CF2_NumberFrac:
191      return cf2_fracToFixed( stack->buffer[idx].u.f );
192    default:
193      return stack->buffer[idx].u.r;
194    }
195  }
196
197
198  FT_LOCAL_DEF( void )
199  cf2_stack_clear( CF2_Stack  stack )
200  {
201    stack->top = &stack->buffer[0];
202  }
203
204
205/* END */
206