1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/***************************************************************************/
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/*                                                                         */
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/*  cf2stack.c                                                             */
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/*                                                                         */
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/*    Adobe's code for emulating a CFF stack (body).                       */
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/*                                                                         */
7ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/*  Copyright 2007-2013 Adobe Systems Incorporated.                        */
8bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.com/*                                                                         */
9bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.com/*  This software, and all works of authorship, whether in source or       */
10bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.com/*  object code form as indicated by the copyright notice(s) included      */
11bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.com/*  herein (collectively, the "Work") is made available, and may only be   */
12bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.com/*  used, modified, and distributed under the FreeType Project License,    */
13111fd11e11cbc296c97225ea16b7ff174a4bcdb5scroggo@google.com/*  LICENSE.TXT.  Additionally, subject to the terms and conditions of the */
14f523e25da069e3e1af2cb73d37073a34f3bb9ea2reed@android.com/*  FreeType Project License, each contributor to the Work hereby grants   */
15bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.com/*  to any individual or legal entity exercising permissions granted by    */
16b8b92ea089a380e17984e4df7b49b379cb6bd929reed@google.com/*  the FreeType Project License and this section (hereafter, "You" or     */
17410e6e80f00a6c660675c80904807a041c7b7d2amtklein@google.com/*  "Your") a perpetual, worldwide, non-exclusive, no-charge,              */
18b8b92ea089a380e17984e4df7b49b379cb6bd929reed@google.com/*  royalty-free, irrevocable (except as stated in this section) patent    */
19b8b92ea089a380e17984e4df7b49b379cb6bd929reed@google.com/*  license to make, have made, use, offer to sell, sell, import, and      */
20b8b92ea089a380e17984e4df7b49b379cb6bd929reed@google.com/*  otherwise transfer the Work, where such license applies only to those  */
21b8b92ea089a380e17984e4df7b49b379cb6bd929reed@google.com/*  patent claims licensable by such contributor that are necessarily      */
22b8b92ea089a380e17984e4df7b49b379cb6bd929reed@google.com/*  infringed by their contribution(s) alone or by combination of their    */
23b8b92ea089a380e17984e4df7b49b379cb6bd929reed@google.com/*  contribution(s) with the Work to which such contribution(s) was        */
24410e6e80f00a6c660675c80904807a041c7b7d2amtklein@google.com/*  submitted.  If You institute patent litigation against any entity      */
25410e6e80f00a6c660675c80904807a041c7b7d2amtklein@google.com/*  (including a cross-claim or counterclaim in a lawsuit) alleging that   */
26410e6e80f00a6c660675c80904807a041c7b7d2amtklein@google.com/*  the Work or a contribution incorporated within the Work constitutes    */
27b8b92ea089a380e17984e4df7b49b379cb6bd929reed@google.com/*  direct or contributory patent infringement, then any patent licenses   */
28b8b92ea089a380e17984e4df7b49b379cb6bd929reed@google.com/*  granted to You under this License for that Work shall terminate as of  */
29b8b92ea089a380e17984e4df7b49b379cb6bd929reed@google.com/*  the date such litigation is filed.                                     */
30bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.com/*                                                                         */
314bc1983e01d756ae9c91fd380758457f579d26eareed@android.com/*  By using, modifying, or distributing the Work you indicate that you    */
32bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.com/*  have read and understood the terms and conditions of the               */
334e635f9eb218b15f656a02e71c60d4f787fe9306reed@android.com/*  FreeType Project License as well as those provided in this section,    */
344e635f9eb218b15f656a02e71c60d4f787fe9306reed@android.com/*  and you accept them fully.                                             */
354e635f9eb218b15f656a02e71c60d4f787fe9306reed@android.com/*                                                                         */
364e635f9eb218b15f656a02e71c60d4f787fe9306reed@android.com/***************************************************************************/
374e635f9eb218b15f656a02e71c60d4f787fe9306reed@android.com
384e635f9eb218b15f656a02e71c60d4f787fe9306reed@android.com
394e635f9eb218b15f656a02e71c60d4f787fe9306reed@android.com#include "cf2ft.h"
40c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com#include FT_INTERNAL_DEBUG_H
414e635f9eb218b15f656a02e71c60d4f787fe9306reed@android.com
424e635f9eb218b15f656a02e71c60d4f787fe9306reed@android.com#include "cf2glue.h"
43bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.com#include "cf2font.h"
44bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.com#include "cf2stack.h"
4515e9d3e66e161ce23df30bc13f8a0c87d196b463robertphillips@google.com
4615e9d3e66e161ce23df30bc13f8a0c87d196b463robertphillips@google.com#include "cf2error.h"
47410e6e80f00a6c660675c80904807a041c7b7d2amtklein@google.com
484bc1983e01d756ae9c91fd380758457f579d26eareed@android.com
49bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.com  /* Allocate and initialize an instance of CF2_Stack.       */
50bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.com  /* Note: This function returns NULL on error (does not set */
5130e6d2c2054c15f1cb6c0637bee6756261291751bsalomon@google.com  /* `error').                                               */
5230e6d2c2054c15f1cb6c0637bee6756261291751bsalomon@google.com  FT_LOCAL_DEF( CF2_Stack )
5330e6d2c2054c15f1cb6c0637bee6756261291751bsalomon@google.com  cf2_stack_init( FT_Memory  memory,
5430e6d2c2054c15f1cb6c0637bee6756261291751bsalomon@google.com                  FT_Error*  e )
5530e6d2c2054c15f1cb6c0637bee6756261291751bsalomon@google.com  {
5630e6d2c2054c15f1cb6c0637bee6756261291751bsalomon@google.com    FT_Error  error = FT_Err_Ok;     /* for FT_QNEW */
57bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.com
5830e6d2c2054c15f1cb6c0637bee6756261291751bsalomon@google.com    CF2_Stack  stack = NULL;
5930e6d2c2054c15f1cb6c0637bee6756261291751bsalomon@google.com
6030e6d2c2054c15f1cb6c0637bee6756261291751bsalomon@google.com
6130e6d2c2054c15f1cb6c0637bee6756261291751bsalomon@google.com    if ( !FT_QNEW( stack ) )
6230e6d2c2054c15f1cb6c0637bee6756261291751bsalomon@google.com    {
6330e6d2c2054c15f1cb6c0637bee6756261291751bsalomon@google.com      /* initialize the structure; FT_QNEW zeroes it */
644bc1983e01d756ae9c91fd380758457f579d26eareed@android.com      stack->memory = memory;
654bc1983e01d756ae9c91fd380758457f579d26eareed@android.com      stack->error  = e;
664bc1983e01d756ae9c91fd380758457f579d26eareed@android.com      stack->top    = &stack->buffer[0]; /* empty stack */
67fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    }
684bc1983e01d756ae9c91fd380758457f579d26eareed@android.com
694bc1983e01d756ae9c91fd380758457f579d26eareed@android.com    return stack;
704bc1983e01d756ae9c91fd380758457f579d26eareed@android.com  }
71fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
7229348cb0612e19030d979156860946241e2ff4bdreed@android.com
7329348cb0612e19030d979156860946241e2ff4bdreed@android.com  FT_LOCAL_DEF( void )
7429348cb0612e19030d979156860946241e2ff4bdreed@android.com  cf2_stack_free( CF2_Stack  stack )
75fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com  {
764e635f9eb218b15f656a02e71c60d4f787fe9306reed@android.com    if ( stack )
774e635f9eb218b15f656a02e71c60d4f787fe9306reed@android.com    {
784e635f9eb218b15f656a02e71c60d4f787fe9306reed@android.com      FT_Memory  memory = stack->memory;
79e9d0060f4d7b5a07a220182d83aae3a140784c4breed@android.com
809dc2713fc4a75e7fbee2f985057fde680a07c7f0tomhudson@google.com
819dc2713fc4a75e7fbee2f985057fde680a07c7f0tomhudson@google.com      /* free the main structure */
829dc2713fc4a75e7fbee2f985057fde680a07c7f0tomhudson@google.com      FT_FREE( stack );
839dc2713fc4a75e7fbee2f985057fde680a07c7f0tomhudson@google.com    }
849dc2713fc4a75e7fbee2f985057fde680a07c7f0tomhudson@google.com  }
859dc2713fc4a75e7fbee2f985057fde680a07c7f0tomhudson@google.com
869dc2713fc4a75e7fbee2f985057fde680a07c7f0tomhudson@google.com
87ef77ec210416733e38072175cc948dcbdb831685reed@google.com  FT_LOCAL_DEF( CF2_UInt )
88ef77ec210416733e38072175cc948dcbdb831685reed@google.com  cf2_stack_count( CF2_Stack  stack )
89ef77ec210416733e38072175cc948dcbdb831685reed@google.com  {
90ef77ec210416733e38072175cc948dcbdb831685reed@google.com    return (CF2_UInt)( stack->top - &stack->buffer[0] );
91ef77ec210416733e38072175cc948dcbdb831685reed@google.com  }
92ef77ec210416733e38072175cc948dcbdb831685reed@google.com
93ef77ec210416733e38072175cc948dcbdb831685reed@google.com
94ef77ec210416733e38072175cc948dcbdb831685reed@google.com  FT_LOCAL_DEF( void )
95ef77ec210416733e38072175cc948dcbdb831685reed@google.com  cf2_stack_pushInt( CF2_Stack  stack,
96ef77ec210416733e38072175cc948dcbdb831685reed@google.com                     CF2_Int    val )
97ef77ec210416733e38072175cc948dcbdb831685reed@google.com  {
98ef77ec210416733e38072175cc948dcbdb831685reed@google.com    if ( stack->top == &stack->buffer[CF2_OPERAND_STACK_SIZE] )
99ef77ec210416733e38072175cc948dcbdb831685reed@google.com    {
100ef77ec210416733e38072175cc948dcbdb831685reed@google.com      CF2_SET_ERROR( stack->error, Stack_Overflow );
101c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com      return;     /* stack overflow */
102c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    }
103c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com
104c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    stack->top->u.i  = val;
105c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    stack->top->type = CF2_NumberInt;
106c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com    ++stack->top;
107c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com  }
108c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com
109ef77ec210416733e38072175cc948dcbdb831685reed@google.com
110111fd11e11cbc296c97225ea16b7ff174a4bcdb5scroggo@google.com  FT_LOCAL_DEF( void )
111111fd11e11cbc296c97225ea16b7ff174a4bcdb5scroggo@google.com  cf2_stack_pushFixed( CF2_Stack  stack,
112111fd11e11cbc296c97225ea16b7ff174a4bcdb5scroggo@google.com                       CF2_Fixed  val )
113111fd11e11cbc296c97225ea16b7ff174a4bcdb5scroggo@google.com  {
114bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.com    if ( stack->top == &stack->buffer[CF2_OPERAND_STACK_SIZE] )
1150561a3ccd24e46259d825adf5507c7ee9531b9c5reed@google.com    {
1164bc1983e01d756ae9c91fd380758457f579d26eareed@android.com      CF2_SET_ERROR( stack->error, Stack_Overflow );
117bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.com      return;     /* stack overflow */
11830e6d2c2054c15f1cb6c0637bee6756261291751bsalomon@google.com    }
119bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.com
12030e6d2c2054c15f1cb6c0637bee6756261291751bsalomon@google.com    stack->top->u.r  = val;
121f523e25da069e3e1af2cb73d37073a34f3bb9ea2reed@android.com    stack->top->type = CF2_NumberFixed;
122f523e25da069e3e1af2cb73d37073a34f3bb9ea2reed@android.com    ++stack->top;
1239dc2713fc4a75e7fbee2f985057fde680a07c7f0tomhudson@google.com  }
1249dc2713fc4a75e7fbee2f985057fde680a07c7f0tomhudson@google.com
125f523e25da069e3e1af2cb73d37073a34f3bb9ea2reed@android.com
1264bc1983e01d756ae9c91fd380758457f579d26eareed@android.com  /* this function is only allowed to pop an integer type */
1274bc1983e01d756ae9c91fd380758457f579d26eareed@android.com  FT_LOCAL_DEF( CF2_Int )
1284bc1983e01d756ae9c91fd380758457f579d26eareed@android.com  cf2_stack_popInt( CF2_Stack  stack )
12929348cb0612e19030d979156860946241e2ff4bdreed@android.com  {
1304e635f9eb218b15f656a02e71c60d4f787fe9306reed@android.com    if ( stack->top == &stack->buffer[0] )
131ef77ec210416733e38072175cc948dcbdb831685reed@google.com    {
132c289743864e2ab926a95e617a5cd1d29b26d1825mtklein@google.com      CF2_SET_ERROR( stack->error, Stack_Underflow );
133111fd11e11cbc296c97225ea16b7ff174a4bcdb5scroggo@google.com      return 0;   /* underflow */
13415e9d3e66e161ce23df30bc13f8a0c87d196b463robertphillips@google.com    }
13515e9d3e66e161ce23df30bc13f8a0c87d196b463robertphillips@google.com    if ( stack->top[-1].type != CF2_NumberInt )
136bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.com    {
137bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.com      CF2_SET_ERROR( stack->error, Syntax_Error );
138410e6e80f00a6c660675c80904807a041c7b7d2amtklein@google.com      return 0;   /* type mismatch */
139f523e25da069e3e1af2cb73d37073a34f3bb9ea2reed@android.com    }
140bd700c391dd45acd8ea1a40321789c9d92a14bb8reed@android.com
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