tizen 2.3.1 release
[framework/graphics/freetype.git] / src / autofit / afangles.c
1 /***************************************************************************/
2 /*                                                                         */
3 /*  afangles.c                                                             */
4 /*                                                                         */
5 /*    Routines used to compute vector angles with limited accuracy         */
6 /*    and very high speed.  It also contains sorting routines (body).      */
7 /*                                                                         */
8 /*  Copyright 2003-2006, 2011-2012 by                                      */
9 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
10 /*                                                                         */
11 /*  This file is part of the FreeType project, and may only be used,       */
12 /*  modified, and distributed under the terms of the FreeType project      */
13 /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
14 /*  this file you indicate that you have read the license and              */
15 /*  understand and accept it fully.                                        */
16 /*                                                                         */
17 /***************************************************************************/
18
19
20 #include "aftypes.h"
21
22
23   /*
24    *  We are not using `af_angle_atan' anymore, but we keep the source
25    *  code below just in case...
26    */
27
28
29 #if 0
30
31
32   /*
33    *  The trick here is to realize that we don't need a very accurate angle
34    *  approximation.  We are going to use the result of `af_angle_atan' to
35    *  only compare the sign of angle differences, or check whether its
36    *  magnitude is very small.
37    *
38    *  The approximation
39    *
40    *    dy * PI / (|dx|+|dy|)
41    *
42    *  should be enough, and much faster to compute.
43    */
44   FT_LOCAL_DEF( AF_Angle )
45   af_angle_atan( FT_Fixed  dx,
46                  FT_Fixed  dy )
47   {
48     AF_Angle  angle;
49     FT_Fixed  ax = dx;
50     FT_Fixed  ay = dy;
51
52
53     if ( ax < 0 )
54       ax = -ax;
55     if ( ay < 0 )
56       ay = -ay;
57
58     ax += ay;
59
60     if ( ax == 0 )
61       angle = 0;
62     else
63     {
64       angle = ( AF_ANGLE_PI2 * dy ) / ( ax + ay );
65       if ( dx < 0 )
66       {
67         if ( angle >= 0 )
68           angle = AF_ANGLE_PI - angle;
69         else
70           angle = -AF_ANGLE_PI - angle;
71       }
72     }
73
74     return angle;
75   }
76
77
78 #elif 0
79
80
81   /* the following table has been automatically generated with */
82   /* the `mather.py' Python script                             */
83
84 #define AF_ATAN_BITS  8
85
86   static const FT_Byte  af_arctan[1L << AF_ATAN_BITS] =
87   {
88      0,  0,  1,  1,  1,  2,  2,  2,
89      3,  3,  3,  3,  4,  4,  4,  5,
90      5,  5,  6,  6,  6,  7,  7,  7,
91      8,  8,  8,  9,  9,  9, 10, 10,
92     10, 10, 11, 11, 11, 12, 12, 12,
93     13, 13, 13, 14, 14, 14, 14, 15,
94     15, 15, 16, 16, 16, 17, 17, 17,
95     18, 18, 18, 18, 19, 19, 19, 20,
96     20, 20, 21, 21, 21, 21, 22, 22,
97     22, 23, 23, 23, 24, 24, 24, 24,
98     25, 25, 25, 26, 26, 26, 26, 27,
99     27, 27, 28, 28, 28, 28, 29, 29,
100     29, 30, 30, 30, 30, 31, 31, 31,
101     31, 32, 32, 32, 33, 33, 33, 33,
102     34, 34, 34, 34, 35, 35, 35, 35,
103     36, 36, 36, 36, 37, 37, 37, 38,
104     38, 38, 38, 39, 39, 39, 39, 40,
105     40, 40, 40, 41, 41, 41, 41, 42,
106     42, 42, 42, 42, 43, 43, 43, 43,
107     44, 44, 44, 44, 45, 45, 45, 45,
108     46, 46, 46, 46, 46, 47, 47, 47,
109     47, 48, 48, 48, 48, 48, 49, 49,
110     49, 49, 50, 50, 50, 50, 50, 51,
111     51, 51, 51, 51, 52, 52, 52, 52,
112     52, 53, 53, 53, 53, 53, 54, 54,
113     54, 54, 54, 55, 55, 55, 55, 55,
114     56, 56, 56, 56, 56, 57, 57, 57,
115     57, 57, 57, 58, 58, 58, 58, 58,
116     59, 59, 59, 59, 59, 59, 60, 60,
117     60, 60, 60, 61, 61, 61, 61, 61,
118     61, 62, 62, 62, 62, 62, 62, 63,
119     63, 63, 63, 63, 63, 64, 64, 64
120   };
121
122
123   FT_LOCAL_DEF( AF_Angle )
124   af_angle_atan( FT_Fixed  dx,
125                  FT_Fixed  dy )
126   {
127     AF_Angle  angle;
128
129
130     /* check trivial cases */
131     if ( dy == 0 )
132     {
133       angle = 0;
134       if ( dx < 0 )
135         angle = AF_ANGLE_PI;
136       return angle;
137     }
138     else if ( dx == 0 )
139     {
140       angle = AF_ANGLE_PI2;
141       if ( dy < 0 )
142         angle = -AF_ANGLE_PI2;
143       return angle;
144     }
145
146     angle = 0;
147     if ( dx < 0 )
148     {
149       dx = -dx;
150       dy = -dy;
151       angle = AF_ANGLE_PI;
152     }
153
154     if ( dy < 0 )
155     {
156       FT_Pos  tmp;
157
158
159       tmp = dx;
160       dx  = -dy;
161       dy  = tmp;
162       angle -= AF_ANGLE_PI2;
163     }
164
165     if ( dx == 0 && dy == 0 )
166       return 0;
167
168     if ( dx == dy )
169       angle += AF_ANGLE_PI4;
170     else if ( dx > dy )
171       angle += af_arctan[FT_DivFix( dy, dx ) >> ( 16 - AF_ATAN_BITS )];
172     else
173       angle += AF_ANGLE_PI2 -
174                af_arctan[FT_DivFix( dx, dy ) >> ( 16 - AF_ATAN_BITS )];
175
176     if ( angle > AF_ANGLE_PI )
177       angle -= AF_ANGLE_2PI;
178
179     return angle;
180   }
181
182
183 #endif /* 0 */
184
185
186   FT_LOCAL_DEF( void )
187   af_sort_pos( FT_UInt  count,
188                FT_Pos*  table )
189   {
190     FT_UInt  i, j;
191     FT_Pos   swap;
192
193
194     for ( i = 1; i < count; i++ )
195     {
196       for ( j = i; j > 0; j-- )
197       {
198         if ( table[j] >= table[j - 1] )
199           break;
200
201         swap         = table[j];
202         table[j]     = table[j - 1];
203         table[j - 1] = swap;
204       }
205     }
206   }
207
208
209   FT_LOCAL_DEF( void )
210   af_sort_and_quantize_widths( FT_UInt*  count,
211                                AF_Width  table,
212                                FT_Pos    threshold )
213   {
214     FT_UInt      i, j;
215     FT_UInt      cur_idx;
216     FT_Pos       cur_val;
217     FT_Pos       sum;
218     AF_WidthRec  swap;
219
220
221     if ( *count == 1 )
222       return;
223
224     /* sort */
225     for ( i = 1; i < *count; i++ )
226     {
227       for ( j = i; j > 0; j-- )
228       {
229         if ( table[j].org >= table[j - 1].org )
230           break;
231
232         swap         = table[j];
233         table[j]     = table[j - 1];
234         table[j - 1] = swap;
235       }
236     }
237
238     cur_idx = 0;
239     cur_val = table[cur_idx].org;
240
241     /* compute and use mean values for clusters not larger than  */
242     /* `threshold'; this is very primitive and might not yield   */
243     /* the best result, but normally, using reference character  */
244     /* `o', `*count' is 2, so the code below is fully sufficient */
245     for ( i = 1; i < *count; i++ )
246     {
247       if ( table[i].org - cur_val > threshold ||
248            i == *count - 1                    )
249       {
250         sum = 0;
251
252         /* fix loop for end of array */
253         if ( table[i].org - cur_val <= threshold &&
254              i == *count - 1                     )
255           i++;
256
257         for ( j = cur_idx; j < i; j++ )
258         {
259           sum         += table[j].org;
260           table[j].org = 0;
261         }
262         table[cur_idx].org = sum / j;
263
264         if ( i < *count - 1 )
265         {
266           cur_idx = i + 1;
267           cur_val = table[cur_idx].org;
268         }
269       }
270     }
271
272     cur_idx = 1;
273
274     /* compress array to remove zero values */
275     for ( i = 1; i < *count; i++ )
276     {
277       if ( table[i].org )
278         table[cur_idx++] = table[i];
279     }
280
281     *count = cur_idx;
282   }
283
284
285 /* END */