[FREETYPE]
[reactos.git] / reactos / lib / 3rdparty / freetype / src / base / ftadvanc.c
1 /***************************************************************************/
2 /* */
3 /* ftadvanc.c */
4 /* */
5 /* Quick computation of advance widths (body). */
6 /* */
7 /* Copyright 2008, 2009, 2011, 2013 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_INTERNAL_DEBUG_H
21
22 #include FT_ADVANCES_H
23 #include FT_INTERNAL_OBJECTS_H
24
25
26 static FT_Error
27 _ft_face_scale_advances( FT_Face face,
28 FT_Fixed* advances,
29 FT_UInt count,
30 FT_Int32 flags )
31 {
32 FT_Fixed scale;
33 FT_UInt nn;
34
35
36 if ( flags & FT_LOAD_NO_SCALE )
37 return FT_Err_Ok;
38
39 if ( face->size == NULL )
40 return FT_THROW( Invalid_Size_Handle );
41
42 if ( flags & FT_LOAD_VERTICAL_LAYOUT )
43 scale = face->size->metrics.y_scale;
44 else
45 scale = face->size->metrics.x_scale;
46
47 /* this must be the same scaling as to get linear{Hori,Vert}Advance */
48 /* (see `FT_Load_Glyph' implementation in src/base/ftobjs.c) */
49
50 for ( nn = 0; nn < count; nn++ )
51 advances[nn] = FT_MulDiv( advances[nn], scale, 64 );
52
53 return FT_Err_Ok;
54 }
55
56
57 /* at the moment, we can perform fast advance retrieval only in */
58 /* the following cases: */
59 /* */
60 /* - unscaled load */
61 /* - unhinted load */
62 /* - light-hinted load */
63
64 #define LOAD_ADVANCE_FAST_CHECK( flags ) \
65 ( flags & ( FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING ) || \
66 FT_LOAD_TARGET_MODE( flags ) == FT_RENDER_MODE_LIGHT )
67
68
69 /* documentation is in ftadvanc.h */
70
71 FT_EXPORT_DEF( FT_Error )
72 FT_Get_Advance( FT_Face face,
73 FT_UInt gindex,
74 FT_Int32 flags,
75 FT_Fixed *padvance )
76 {
77 FT_Face_GetAdvancesFunc func;
78
79
80 if ( !face )
81 return FT_THROW( Invalid_Face_Handle );
82
83 if ( gindex >= (FT_UInt)face->num_glyphs )
84 return FT_THROW( Invalid_Glyph_Index );
85
86 func = face->driver->clazz->get_advances;
87 if ( func && LOAD_ADVANCE_FAST_CHECK( flags ) )
88 {
89 FT_Error error;
90
91
92 error = func( face, gindex, 1, flags, padvance );
93 if ( !error )
94 return _ft_face_scale_advances( face, padvance, 1, flags );
95
96 if ( FT_ERR_NEQ( error, Unimplemented_Feature ) )
97 return error;
98 }
99
100 return FT_Get_Advances( face, gindex, 1, flags, padvance );
101 }
102
103
104 /* documentation is in ftadvanc.h */
105
106 FT_EXPORT_DEF( FT_Error )
107 FT_Get_Advances( FT_Face face,
108 FT_UInt start,
109 FT_UInt count,
110 FT_Int32 flags,
111 FT_Fixed *padvances )
112 {
113 FT_Face_GetAdvancesFunc func;
114 FT_UInt num, end, nn;
115 FT_Error error = FT_Err_Ok;
116
117
118 if ( !face )
119 return FT_THROW( Invalid_Face_Handle );
120
121 num = (FT_UInt)face->num_glyphs;
122 end = start + count;
123 if ( start >= num || end < start || end > num )
124 return FT_THROW( Invalid_Glyph_Index );
125
126 if ( count == 0 )
127 return FT_Err_Ok;
128
129 func = face->driver->clazz->get_advances;
130 if ( func && LOAD_ADVANCE_FAST_CHECK( flags ) )
131 {
132 error = func( face, start, count, flags, padvances );
133 if ( !error )
134 return _ft_face_scale_advances( face, padvances, count, flags );
135
136 if ( FT_ERR_NEQ( error, Unimplemented_Feature ) )
137 return error;
138 }
139
140 error = FT_Err_Ok;
141
142 if ( flags & FT_ADVANCE_FLAG_FAST_ONLY )
143 return FT_THROW( Unimplemented_Feature );
144
145 flags |= (FT_UInt32)FT_LOAD_ADVANCE_ONLY;
146 for ( nn = 0; nn < count; nn++ )
147 {
148 error = FT_Load_Glyph( face, start + nn, flags );
149 if ( error )
150 break;
151
152 /* scale from 26.6 to 16.16 */
153 padvances[nn] = ( flags & FT_LOAD_VERTICAL_LAYOUT )
154 ? face->glyph->advance.y << 10
155 : face->glyph->advance.x << 10;
156 }
157
158 return error;
159 }
160
161
162 /* END */