8ab7fcb92714ecf2d142f5ad9008c923d5382271
[framework/graphics/freetype.git] / src / base / ftadvanc.c
1 /***************************************************************************/
2 /*                                                                         */
3 /*  ftadvanc.c                                                             */
4 /*                                                                         */
5 /*    Quick computation of advance widths (body).                          */
6 /*                                                                         */
7 /*  Copyright 2008, 2009 by                                                */
8 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
9 /*                                                                         */
10 /*  This file is part of the FreeType project, and may only be used,       */
11 /*  modified, and distributed under the terms of the FreeType project      */
12 /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
13 /*  this file you indicate that you have read the license and              */
14 /*  understand and accept it fully.                                        */
15 /*                                                                         */
16 /***************************************************************************/
17
18
19 #include <ft2build.h>
20 #include FT_ADVANCES_H
21 #include FT_INTERNAL_OBJECTS_H
22
23
24   static FT_Error
25   _ft_face_scale_advances( FT_Face    face,
26                            FT_Fixed*  advances,
27                            FT_UInt    count,
28                            FT_Int32   flags )
29   {
30     FT_Fixed  scale;
31     FT_UInt   nn;
32
33
34     if ( flags & FT_LOAD_NO_SCALE )
35       return FT_Err_Ok;
36
37     if ( face->size == NULL )
38       return FT_Err_Invalid_Size_Handle;
39
40     if ( flags & FT_LOAD_VERTICAL_LAYOUT )
41       scale = face->size->metrics.y_scale;
42     else
43       scale = face->size->metrics.x_scale;
44
45     /* this must be the same scaling as to get linear{Hori,Vert}Advance */
46     /* (see `FT_Load_Glyph' implementation in src/base/ftobjs.c)        */
47
48     for ( nn = 0; nn < count; nn++ )
49       advances[nn] = FT_MulDiv( advances[nn], scale, 64 );
50
51     return FT_Err_Ok;
52   }
53
54
55    /* at the moment, we can perform fast advance retrieval only in */
56    /* the following cases:                                         */
57    /*                                                              */
58    /*  - unscaled load                                             */
59    /*  - unhinted load                                             */
60    /*  - light-hinted load                                         */
61
62 #define LOAD_ADVANCE_FAST_CHECK( flags )                            \
63           ( flags & ( FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING )    || \
64             FT_LOAD_TARGET_MODE( flags ) == FT_RENDER_MODE_LIGHT )
65
66
67   /* documentation is in ftadvanc.h */
68
69   FT_EXPORT_DEF( FT_Error )
70   FT_Get_Advance( FT_Face    face,
71                   FT_UInt    gindex,
72                   FT_Int32   flags,
73                   FT_Fixed  *padvance )
74   {
75     FT_Face_GetAdvancesFunc  func;
76
77
78     if ( !face )
79       return FT_Err_Invalid_Face_Handle;
80
81     if ( gindex >= (FT_UInt)face->num_glyphs )
82       return FT_Err_Invalid_Glyph_Index;
83
84     func = face->driver->clazz->get_advances;
85     if ( func && LOAD_ADVANCE_FAST_CHECK( flags ) )
86     {
87       FT_Error  error;
88
89
90       error = func( face, gindex, 1, flags, padvance );
91       if ( !error )
92         return _ft_face_scale_advances( face, padvance, 1, flags );
93
94       if ( error != FT_ERROR_BASE( FT_Err_Unimplemented_Feature ) )
95         return error;
96     }
97
98     return FT_Get_Advances( face, gindex, 1, flags, padvance );
99   }
100
101
102   /* documentation is in ftadvanc.h */
103
104   FT_EXPORT_DEF( FT_Error )
105   FT_Get_Advances( FT_Face    face,
106                    FT_UInt    start,
107                    FT_UInt    count,
108                    FT_Int32   flags,
109                    FT_Fixed  *padvances )
110   {
111     FT_Face_GetAdvancesFunc  func;
112     FT_UInt                  num, end, nn;
113     FT_Error                 error = FT_Err_Ok;
114
115
116     if ( !face )
117       return FT_Err_Invalid_Face_Handle;
118
119     num = (FT_UInt)face->num_glyphs;
120     end = start + count;
121     if ( start >= num || end < start || end > num )
122       return FT_Err_Invalid_Glyph_Index;
123
124     if ( count == 0 )
125       return FT_Err_Ok;
126
127     func = face->driver->clazz->get_advances;
128     if ( func && LOAD_ADVANCE_FAST_CHECK( flags ) )
129     {
130       error = func( face, start, count, flags, padvances );
131       if ( !error )
132         goto Exit;
133
134       if ( error != FT_ERROR_BASE( FT_Err_Unimplemented_Feature ) )
135         return error;
136     }
137
138     error = FT_Err_Ok;
139
140     if ( flags & FT_ADVANCE_FLAG_FAST_ONLY )
141       return FT_Err_Unimplemented_Feature;
142
143     flags |= (FT_UInt32)FT_LOAD_ADVANCE_ONLY;
144     for ( nn = 0; nn < count; nn++ )
145     {
146       error = FT_Load_Glyph( face, start + nn, flags );
147       if ( error )
148         break;
149
150       padvances[nn] = ( flags & FT_LOAD_VERTICAL_LAYOUT )
151                       ? face->glyph->advance.y
152                       : face->glyph->advance.x;
153     }
154
155     if ( error )
156       return error;
157
158   Exit:
159     return _ft_face_scale_advances( face, padvances, count, flags );
160   }
161
162
163 /* END */