The BIG graph update
[rrdtool.git] / libraries / freetype-2.0.5 / t1gload.c
1 /***************************************************************************/
2 /*                                                                         */
3 /*  t1gload.c                                                              */
4 /*                                                                         */
5 /*    Type 1 Glyph Loader (body).                                          */
6 /*                                                                         */
7 /*  Copyright 1996-2001 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 "t1gload.h"
21 #include FT_INTERNAL_DEBUG_H
22 #include FT_INTERNAL_STREAM_H
23 #include FT_OUTLINE_H
24 #include FT_INTERNAL_POSTSCRIPT_AUX_H
25
26 #include "t1errors.h"
27
28 #include <string.h>     /* for strcmp() */
29
30
31   /*************************************************************************/
32   /*                                                                       */
33   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
34   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
35   /* messages during execution.                                            */
36   /*                                                                       */
37 #undef  FT_COMPONENT
38 #define FT_COMPONENT  trace_t1gload
39
40
41   /*************************************************************************/
42   /*************************************************************************/
43   /*************************************************************************/
44   /**********                                                      *********/
45   /**********            COMPUTE THE MAXIMUM ADVANCE WIDTH         *********/
46   /**********                                                      *********/
47   /**********    The following code is in charge of computing      *********/
48   /**********    the maximum advance width of the font.  It        *********/
49   /**********    quickly processes each glyph charstring to        *********/
50   /**********    extract the value from either a `sbw' or `seac'   *********/
51   /**********    operator.                                         *********/
52   /**********                                                      *********/
53   /*************************************************************************/
54   /*************************************************************************/
55   /*************************************************************************/
56
57
58   FT_CALLBACK_DEF( FT_Error )
59   T1_Parse_Glyph( T1_Decoder*  decoder,
60                   FT_UInt      glyph_index )
61   {
62     T1_Face   face  = (T1_Face)decoder->builder.face;
63     T1_Font*  type1 = &face->type1;
64
65
66     decoder->font_matrix = type1->font_matrix;
67     decoder->font_offset = type1->font_offset;
68
69     return decoder->funcs.parse_charstrings(
70                       decoder,
71                       type1->charstrings    [glyph_index],
72                       type1->charstrings_len[glyph_index] );
73   }
74
75
76   FT_LOCAL_DEF FT_Error
77   T1_Compute_Max_Advance( T1_Face  face,
78                           FT_Int*  max_advance )
79   {
80     FT_Error          error;
81     T1_Decoder        decoder;
82     FT_Int            glyph_index;
83     T1_Font*          type1 = &face->type1;
84     PSAux_Interface*  psaux = (PSAux_Interface*)face->psaux;
85
86
87     *max_advance = 0;
88
89     /* initialize load decoder */
90     error = psaux->t1_decoder_funcs->init( &decoder,
91                                            (FT_Face)face,
92                                            0, /* size       */
93                                            0, /* glyph slot */
94                                            (FT_Byte**)type1->glyph_names,
95                                            face->blend,
96                                            T1_Parse_Glyph );
97     if ( error )
98       return error;
99
100     decoder.builder.metrics_only = 1;
101     decoder.builder.load_points  = 0;
102
103     decoder.num_subrs = type1->num_subrs;
104     decoder.subrs     = type1->subrs;
105     decoder.subrs_len = type1->subrs_len;
106
107     /* for each glyph, parse the glyph charstring and extract */
108     /* the advance width                                      */
109     for ( glyph_index = 0; glyph_index < type1->num_glyphs; glyph_index++ )
110     {
111       /* now get load the unscaled outline */
112       error = T1_Parse_Glyph( &decoder, glyph_index );
113       /* ignore the error if one occured - skip to next glyph */
114     }
115
116     *max_advance = decoder.builder.advance.x;
117     return T1_Err_Ok;
118   }
119
120
121   /*************************************************************************/
122   /*************************************************************************/
123   /*************************************************************************/
124   /**********                                                      *********/
125   /**********               UNHINTED GLYPH LOADER                  *********/
126   /**********                                                      *********/
127   /**********    The following code is in charge of loading a      *********/
128   /**********    single outline.  It completely ignores hinting    *********/
129   /**********    and is used when FT_LOAD_NO_HINTING is set.       *********/
130   /**********                                                      *********/
131   /**********      The Type 1 hinter is located in `t1hint.c'      *********/
132   /**********                                                      *********/
133   /*************************************************************************/
134   /*************************************************************************/
135   /*************************************************************************/
136
137
138   FT_LOCAL_DEF FT_Error
139   T1_Load_Glyph( T1_GlyphSlot  glyph,
140                  T1_Size       size,
141                  FT_Int        glyph_index,
142                  FT_Int        load_flags )
143   {
144     FT_Error                error;
145     T1_Decoder              decoder;
146     T1_Face                 face = (T1_Face)glyph->root.face;
147     FT_Bool                 hinting;
148     T1_Font*                type1         = &face->type1;
149     PSAux_Interface*        psaux         = (PSAux_Interface*)face->psaux;
150     const T1_Decoder_Funcs* decoder_funcs = psaux->t1_decoder_funcs;
151
152     FT_Matrix               font_matrix;
153     FT_Vector               font_offset;
154
155     if ( load_flags & FT_LOAD_NO_RECURSE )
156       load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
157
158     glyph->x_scale = size->root.metrics.x_scale;
159     glyph->y_scale = size->root.metrics.y_scale;
160
161     glyph->root.outline.n_points   = 0;
162     glyph->root.outline.n_contours = 0;
163
164     hinting = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE   ) == 0 &&
165                        ( load_flags & FT_LOAD_NO_HINTING ) == 0 );
166
167     glyph->root.format = ft_glyph_format_outline;
168
169     error = decoder_funcs->init( &decoder,
170                                  (FT_Face)face,
171                                  (FT_Size)size,
172                                  (FT_GlyphSlot)glyph,
173                                  (FT_Byte**)type1->glyph_names,
174                                  face->blend,
175                                  T1_Parse_Glyph );
176     if ( error )
177       goto Exit;
178
179     decoder.builder.no_recurse = FT_BOOL(
180                                    ( load_flags & FT_LOAD_NO_RECURSE ) != 0 );
181
182     decoder.num_subrs = type1->num_subrs;
183     decoder.subrs     = type1->subrs;
184     decoder.subrs_len = type1->subrs_len;
185
186
187     /* now load the unscaled outline */
188     error = T1_Parse_Glyph( &decoder, glyph_index );
189     if ( error )
190       goto Exit;
191
192     font_matrix = decoder.font_matrix;
193     font_offset = decoder.font_offset;
194
195     /* save new glyph tables */
196     decoder_funcs->done( &decoder );
197
198     /* now, set the metrics -- this is rather simple, as   */
199     /* the left side bearing is the xMin, and the top side */
200     /* bearing the yMax                                    */
201     if ( !error )
202     {
203       glyph->root.outline.flags &= ft_outline_owner;
204       glyph->root.outline.flags |= ft_outline_reverse_fill;
205
206       /* for composite glyphs, return only left side bearing and */
207       /* advance width                                           */
208       if ( load_flags & FT_LOAD_NO_RECURSE )
209       {
210         FT_Slot_Internal  internal = glyph->root.internal;
211
212
213         glyph->root.metrics.horiBearingX = decoder.builder.left_bearing.x;
214         glyph->root.metrics.horiAdvance  = decoder.builder.advance.x;
215         internal->glyph_matrix           = font_matrix;
216         internal->glyph_delta            = font_offset;
217         internal->glyph_transformed      = 1;
218       }
219       else
220       {
221         FT_BBox            cbox;
222         FT_Glyph_Metrics*  metrics = &glyph->root.metrics;
223
224
225         /* copy the _unscaled_ advance width */
226         metrics->horiAdvance                    = decoder.builder.advance.x;
227         glyph->root.linearHoriAdvance           = decoder.builder.advance.x;
228         glyph->root.internal->glyph_transformed = 0;
229
230         /* make up vertical metrics */
231         metrics->vertBearingX = 0;
232         metrics->vertBearingY = 0;
233         metrics->vertAdvance  = 0;
234
235         glyph->root.linearVertAdvance = 0;
236
237         glyph->root.format = ft_glyph_format_outline;
238
239         if ( size && size->root.metrics.y_ppem < 24 )
240           glyph->root.outline.flags |= ft_outline_high_precision;
241
242         /* apply the font matrix */
243         FT_Outline_Transform( &glyph->root.outline, &font_matrix );
244
245         FT_Outline_Translate( &glyph->root.outline,
246                               font_offset.x,
247                               font_offset.y );
248
249 #if 0
250
251         glyph->root.outline.second_pass    = TRUE;
252         glyph->root.outline.high_precision = size->root.metrics.y_ppem < 24;
253         glyph->root.outline.dropout_mode   = 2;
254
255 #endif /* 0 */
256
257         if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 )
258         {
259           /* scale the outline and the metrics */
260           FT_Int       n;
261           FT_Outline*  cur = decoder.builder.base;
262           FT_Vector*   vec = cur->points;
263           FT_Fixed     x_scale = glyph->x_scale;
264           FT_Fixed     y_scale = glyph->y_scale;
265
266
267           /* First of all, scale the points */
268           for ( n = cur->n_points; n > 0; n--, vec++ )
269           {
270             vec->x = FT_MulFix( vec->x, x_scale );
271             vec->y = FT_MulFix( vec->y, y_scale );
272           }
273
274           FT_Outline_Get_CBox( &glyph->root.outline, &cbox );
275
276           /* Then scale the metrics */
277           metrics->horiAdvance  = FT_MulFix( metrics->horiAdvance,  x_scale );
278           metrics->vertAdvance  = FT_MulFix( metrics->vertAdvance,  y_scale );
279
280           metrics->vertBearingX = FT_MulFix( metrics->vertBearingX, x_scale );
281           metrics->vertBearingY = FT_MulFix( metrics->vertBearingY, y_scale );
282         }
283
284         /* compute the other metrics */
285         FT_Outline_Get_CBox( &glyph->root.outline, &cbox );
286
287         /* grid fit the bounding box if necessary */
288         if ( hinting )
289         {
290           cbox.xMin &= -64;
291           cbox.yMin &= -64;
292           cbox.xMax  = ( cbox.xMax+63 ) & -64;
293           cbox.yMax  = ( cbox.yMax+63 ) & -64;
294         }
295
296         metrics->width  = cbox.xMax - cbox.xMin;
297         metrics->height = cbox.yMax - cbox.yMin;
298
299         metrics->horiBearingX = cbox.xMin;
300         metrics->horiBearingY = cbox.yMax;
301       }
302
303       /* Set control data to the glyph charstrings.  Note that this is */
304       /* _not_ zero-terminated.                                        */
305       glyph->root.control_data = type1->charstrings    [glyph_index];
306       glyph->root.control_len  = type1->charstrings_len[glyph_index];
307     }
308
309   Exit:
310     return error;
311   }
312
313
314 /* END */