blob: 966a0df73dbc53929110633f56fb6fb1c96b70fd [file] [log] [blame]
Werner Lembergf13516c2005-03-03 17:09:08 +00001/***************************************************************************/
2/* */
3/* afloader.c */
4/* */
5/* Auto-fitter glyph loading routines (body). */
6/* */
Werner Lemberg6cfbb232011-02-26 17:32:38 +01007/* Copyright 2003-2009, 2011 by */
Werner Lembergf13516c2005-03-03 17:09:08 +00008/* 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
Werner Lemberg8bb07e62004-03-27 08:43:17 +000019#include "afloader.h"
20#include "afhints.h"
21#include "afglobal.h"
Werner Lemberga37745b2005-03-23 16:45:24 +000022#include "aferrors.h"
Werner Lemberg8bb07e62004-03-27 08:43:17 +000023
Werner Lembergb19b0812005-03-02 11:24:23 +000024
Werner Lemberg6cfbb232011-02-26 17:32:38 +010025 /* Initialize glyph loader. */
26
Werner Lemberg8bb07e62004-03-27 08:43:17 +000027 FT_LOCAL_DEF( FT_Error )
28 af_loader_init( AF_Loader loader,
29 FT_Memory memory )
30 {
Werner Lemberg8bb07e62004-03-27 08:43:17 +000031 FT_ZERO( loader );
32
33 af_glyph_hints_init( &loader->hints, memory );
Werner Lembergd503b1b2011-04-18 19:05:28 +020034#ifdef FT_DEBUG_AUTOFIT
David Turner40604742006-11-02 16:37:35 +000035 _af_debug_hints = &loader->hints;
36#endif
David Turner65c7c772006-04-13 07:51:58 +000037 return FT_GlyphLoader_New( memory, &loader->gloader );
Werner Lemberg8bb07e62004-03-27 08:43:17 +000038 }
39
40
Werner Lemberg6cfbb232011-02-26 17:32:38 +010041 /* Reset glyph loader and compute globals if necessary. */
42
Werner Lemberg8bb07e62004-03-27 08:43:17 +000043 FT_LOCAL_DEF( FT_Error )
Werner Lembergb19b0812005-03-02 11:24:23 +000044 af_loader_reset( AF_Loader loader,
45 FT_Face face )
Werner Lemberg8bb07e62004-03-27 08:43:17 +000046 {
Werner Lemberga37745b2005-03-23 16:45:24 +000047 FT_Error error = AF_Err_Ok;
Werner Lembergb19b0812005-03-02 11:24:23 +000048
Werner Lemberg8bb07e62004-03-27 08:43:17 +000049
50 loader->face = face;
Werner Lembergb19b0812005-03-02 11:24:23 +000051 loader->globals = (AF_FaceGlobals)face->autohint.data;
Werner Lemberg8bb07e62004-03-27 08:43:17 +000052
53 FT_GlyphLoader_Rewind( loader->gloader );
54
55 if ( loader->globals == NULL )
56 {
57 error = af_face_globals_new( face, &loader->globals );
58 if ( !error )
59 {
Werner Lembergb19b0812005-03-02 11:24:23 +000060 face->autohint.data =
61 (FT_Pointer)loader->globals;
62 face->autohint.finalizer =
63 (FT_Generic_Finalizer)af_face_globals_free;
Werner Lemberg8bb07e62004-03-27 08:43:17 +000064 }
65 }
Werner Lembergb19b0812005-03-02 11:24:23 +000066
Werner Lemberg8bb07e62004-03-27 08:43:17 +000067 return error;
68 }
69
70
Werner Lemberg6cfbb232011-02-26 17:32:38 +010071 /* Finalize glyph loader. */
72
Werner Lemberg8bb07e62004-03-27 08:43:17 +000073 FT_LOCAL_DEF( void )
Werner Lembergb19b0812005-03-02 11:24:23 +000074 af_loader_done( AF_Loader loader )
Werner Lemberg8bb07e62004-03-27 08:43:17 +000075 {
David Turner6a487b52005-02-28 22:09:07 +000076 af_glyph_hints_done( &loader->hints );
77
Werner Lemberg8bb07e62004-03-27 08:43:17 +000078 loader->face = NULL;
79 loader->globals = NULL;
80
Werner Lembergd503b1b2011-04-18 19:05:28 +020081#ifdef FT_DEBUG_AUTOFIT
David Turner40604742006-11-02 16:37:35 +000082 _af_debug_hints = NULL;
83#endif
Werner Lemberg8bb07e62004-03-27 08:43:17 +000084 FT_GlyphLoader_Done( loader->gloader );
85 loader->gloader = NULL;
86 }
87
88
Werner Lemberg6cfbb232011-02-26 17:32:38 +010089 /* Load a single glyph component. This routine calls itself */
90 /* recursively, if necessary, and does the main work of */
91 /* `af_loader_load_glyph.' */
92
Werner Lemberg8bb07e62004-03-27 08:43:17 +000093 static FT_Error
94 af_loader_load_g( AF_Loader loader,
95 AF_Scaler scaler,
96 FT_UInt glyph_index,
97 FT_Int32 load_flags,
98 FT_UInt depth )
99 {
Werner Lembergb19b0812005-03-02 11:24:23 +0000100 FT_Error error;
Werner Lemberg8bb07e62004-03-27 08:43:17 +0000101 FT_Face face = loader->face;
Werner Lemberg8bb07e62004-03-27 08:43:17 +0000102 FT_GlyphLoader gloader = loader->gloader;
103 AF_ScriptMetrics metrics = loader->metrics;
104 AF_GlyphHints hints = &loader->hints;
105 FT_GlyphSlot slot = face->glyph;
106 FT_Slot_Internal internal = slot->internal;
107
Werner Lembergb19b0812005-03-02 11:24:23 +0000108
Werner Lemberg8bb07e62004-03-27 08:43:17 +0000109 error = FT_Load_Glyph( face, glyph_index, load_flags );
110 if ( error )
111 goto Exit;
112
113 loader->transformed = internal->glyph_transformed;
114 if ( loader->transformed )
115 {
116 FT_Matrix inverse;
117
Werner Lembergb19b0812005-03-02 11:24:23 +0000118
Werner Lemberg8bb07e62004-03-27 08:43:17 +0000119 loader->trans_matrix = internal->glyph_matrix;
120 loader->trans_delta = internal->glyph_delta;
121
122 inverse = loader->trans_matrix;
123 FT_Matrix_Invert( &inverse );
124 FT_Vector_Transform( &loader->trans_delta, &inverse );
125 }
126
127 /* set linear metrics */
128 slot->linearHoriAdvance = slot->metrics.horiAdvance;
129 slot->linearVertAdvance = slot->metrics.vertAdvance;
130
131 switch ( slot->format )
132 {
Werner Lembergb19b0812005-03-02 11:24:23 +0000133 case FT_GLYPH_FORMAT_OUTLINE:
134 /* translate the loaded glyph when an internal transform is needed */
135 if ( loader->transformed )
136 FT_Outline_Translate( &slot->outline,
137 loader->trans_delta.x,
138 loader->trans_delta.y );
Werner Lemberg8bb07e62004-03-27 08:43:17 +0000139
Werner Lembergb19b0812005-03-02 11:24:23 +0000140 /* copy the outline points in the loader's current */
141 /* extra points which is used to keep original glyph coordinates */
David Turner9fbd2ab2005-10-28 16:14:14 +0000142 error = FT_GLYPHLOADER_CHECK_POINTS( gloader,
143 slot->outline.n_points + 4,
144 slot->outline.n_contours );
Werner Lembergb19b0812005-03-02 11:24:23 +0000145 if ( error )
146 goto Exit;
Werner Lemberg8bb07e62004-03-27 08:43:17 +0000147
Werner Lembergb19b0812005-03-02 11:24:23 +0000148 FT_ARRAY_COPY( gloader->current.outline.points,
149 slot->outline.points,
150 slot->outline.n_points );
Werner Lemberg8bb07e62004-03-27 08:43:17 +0000151
Werner Lembergb19b0812005-03-02 11:24:23 +0000152 FT_ARRAY_COPY( gloader->current.outline.contours,
153 slot->outline.contours,
154 slot->outline.n_contours );
Werner Lemberg8bb07e62004-03-27 08:43:17 +0000155
Werner Lembergb19b0812005-03-02 11:24:23 +0000156 FT_ARRAY_COPY( gloader->current.outline.tags,
157 slot->outline.tags,
158 slot->outline.n_points );
Werner Lemberg8bb07e62004-03-27 08:43:17 +0000159
Werner Lembergb19b0812005-03-02 11:24:23 +0000160 gloader->current.outline.n_points = slot->outline.n_points;
161 gloader->current.outline.n_contours = slot->outline.n_contours;
Werner Lemberg8bb07e62004-03-27 08:43:17 +0000162
Werner Lembergb19b0812005-03-02 11:24:23 +0000163 /* compute original horizontal phantom points (and ignore */
164 /* vertical ones) */
165 loader->pp1.x = hints->x_delta;
166 loader->pp1.y = hints->y_delta;
167 loader->pp2.x = FT_MulFix( slot->metrics.horiAdvance,
168 hints->x_scale ) + hints->x_delta;
169 loader->pp2.y = hints->y_delta;
Werner Lemberg8bb07e62004-03-27 08:43:17 +0000170
Werner Lembergb19b0812005-03-02 11:24:23 +0000171 /* be sure to check for spacing glyphs */
172 if ( slot->outline.n_points == 0 )
173 goto Hint_Metrics;
Werner Lemberg8bb07e62004-03-27 08:43:17 +0000174
Werner Lembergb19b0812005-03-02 11:24:23 +0000175 /* now load the slot image into the auto-outline and run the */
176 /* automatic hinting process */
Werner Lemberg44c655b2008-02-17 08:22:08 +0000177 if ( metrics->clazz->script_hints_apply )
178 metrics->clazz->script_hints_apply( hints,
179 &gloader->current.outline,
180 metrics );
David Turnere664efa2004-06-04 17:41:59 +0000181
Werner Lemberg6cfbb232011-02-26 17:32:38 +0100182 /* we now need to adjust the metrics according to the change in */
183 /* width/positioning that occurred during the hinting process */
David Turnerd91eebd2007-01-26 15:05:41 +0000184 if ( scaler->render_mode != FT_RENDER_MODE_LIGHT )
Werner Lembergb19b0812005-03-02 11:24:23 +0000185 {
Werner Lemberg607dec72007-05-15 06:49:37 +0000186 FT_Pos old_rsb, old_lsb, new_lsb;
Werner Lembergb19b0812005-03-02 11:24:23 +0000187 FT_Pos pp1x_uh, pp2x_uh;
Werner Lembergf13516c2005-03-03 17:09:08 +0000188 AF_AxisHints axis = &hints->axis[AF_DIMENSION_HORZ];
Werner Lembergb19b0812005-03-02 11:24:23 +0000189 AF_Edge edge1 = axis->edges; /* leftmost edge */
190 AF_Edge edge2 = edge1 +
191 axis->num_edges - 1; /* rightmost edge */
192
Werner Lembergb36bf522006-01-22 07:09:54 +0000193
Wu, Chia-I (吳佳一)4cdb45c2006-02-09 14:17:04 +0000194 if ( axis->num_edges > 1 && AF_HINTS_DO_ADVANCE( hints ) )
Werner Lemberg8bb07e62004-03-27 08:43:17 +0000195 {
Werner Lemberg8b84c9d2009-04-27 19:40:35 +0200196 old_rsb = loader->pp2.x - edge2->opos;
197 old_lsb = edge1->opos;
198 new_lsb = edge1->pos;
Werner Lemberg89d4e4b2004-06-05 06:27:08 +0000199
Werner Lembergb19b0812005-03-02 11:24:23 +0000200 /* remember unhinted values to later account */
201 /* for rounding errors */
Werner Lemberg8bb07e62004-03-27 08:43:17 +0000202
Werner Lembergb19b0812005-03-02 11:24:23 +0000203 pp1x_uh = new_lsb - old_lsb;
204 pp2x_uh = edge2->pos + old_rsb;
Werner Lemberg8bb07e62004-03-27 08:43:17 +0000205
Werner Lembergb19b0812005-03-02 11:24:23 +0000206 /* prefer too much space over too little space */
207 /* for very small sizes */
Werner Lemberg89d4e4b2004-06-05 06:27:08 +0000208
Werner Lembergb19b0812005-03-02 11:24:23 +0000209 if ( old_lsb < 24 )
David Turner2ef3e0f2007-02-12 21:28:21 +0000210 pp1x_uh -= 8;
Werner Lemberg89d4e4b2004-06-05 06:27:08 +0000211
Werner Lembergb19b0812005-03-02 11:24:23 +0000212 if ( old_rsb < 24 )
David Turner2ef3e0f2007-02-12 21:28:21 +0000213 pp2x_uh += 8;
Werner Lemberg89d4e4b2004-06-05 06:27:08 +0000214
Werner Lembergb19b0812005-03-02 11:24:23 +0000215 loader->pp1.x = FT_PIX_ROUND( pp1x_uh );
216 loader->pp2.x = FT_PIX_ROUND( pp2x_uh );
Werner Lemberg89d4e4b2004-06-05 06:27:08 +0000217
David Turner2ef3e0f2007-02-12 21:28:21 +0000218 if ( loader->pp1.x >= new_lsb && old_lsb > 0 )
David Turnerdbf3b432006-12-07 21:18:09 +0000219 loader->pp1.x -= 64;
220
David Turner2ef3e0f2007-02-12 21:28:21 +0000221 if ( loader->pp2.x <= edge2->pos && old_rsb > 0 )
David Turnerdbf3b432006-12-07 21:18:09 +0000222 loader->pp2.x += 64;
223
Werner Lembergb19b0812005-03-02 11:24:23 +0000224 slot->lsb_delta = loader->pp1.x - pp1x_uh;
225 slot->rsb_delta = loader->pp2.x - pp2x_uh;
Werner Lembergb19b0812005-03-02 11:24:23 +0000226 }
227 else
228 {
Werner Lemberg8b84c9d2009-04-27 19:40:35 +0200229 FT_Pos pp1x = loader->pp1.x;
230 FT_Pos pp2x = loader->pp2.x;
231
David Turner2ce92032006-03-23 20:58:20 +0000232
David Turnerd91eebd2007-01-26 15:05:41 +0000233 loader->pp1.x = FT_PIX_ROUND( pp1x );
234 loader->pp2.x = FT_PIX_ROUND( pp2x );
David Turner2ce92032006-03-23 20:58:20 +0000235
236 slot->lsb_delta = loader->pp1.x - pp1x;
237 slot->rsb_delta = loader->pp2.x - pp2x;
Werner Lembergb19b0812005-03-02 11:24:23 +0000238 }
239 }
David Turnerd91eebd2007-01-26 15:05:41 +0000240 else
241 {
Werner Lemberg8b84c9d2009-04-27 19:40:35 +0200242 FT_Pos pp1x = loader->pp1.x;
243 FT_Pos pp2x = loader->pp2.x;
244
David Turnerd91eebd2007-01-26 15:05:41 +0000245
246 loader->pp1.x = FT_PIX_ROUND( pp1x + hints->xmin_delta );
David Turnera7ee6082007-01-30 10:33:53 +0000247 loader->pp2.x = FT_PIX_ROUND( pp2x + hints->xmax_delta );
David Turnerd91eebd2007-01-26 15:05:41 +0000248
249 slot->lsb_delta = loader->pp1.x - pp1x;
250 slot->rsb_delta = loader->pp2.x - pp2x;
251 }
Werner Lembergb19b0812005-03-02 11:24:23 +0000252
253 /* good, we simply add the glyph to our loader's base */
254 FT_GlyphLoader_Add( gloader );
255 break;
Werner Lemberg8bb07e62004-03-27 08:43:17 +0000256
257 case FT_GLYPH_FORMAT_COMPOSITE:
258 {
259 FT_UInt nn, num_subglyphs = slot->num_subglyphs;
260 FT_UInt num_base_subgs, start_point;
261 FT_SubGlyph subglyph;
262
263
264 start_point = gloader->base.outline.n_points;
265
266 /* first of all, copy the subglyph descriptors in the glyph loader */
267 error = FT_GlyphLoader_CheckSubGlyphs( gloader, num_subglyphs );
268 if ( error )
269 goto Exit;
270
271 FT_ARRAY_COPY( gloader->current.subglyphs,
272 slot->subglyphs,
273 num_subglyphs );
274
275 gloader->current.num_subglyphs = num_subglyphs;
Werner Lembergb19b0812005-03-02 11:24:23 +0000276 num_base_subgs = gloader->base.num_subglyphs;
Werner Lemberg8bb07e62004-03-27 08:43:17 +0000277
Werner Lemberg6cfbb232011-02-26 17:32:38 +0100278 /* now read each subglyph independently */
Werner Lemberg8bb07e62004-03-27 08:43:17 +0000279 for ( nn = 0; nn < num_subglyphs; nn++ )
280 {
281 FT_Vector pp1, pp2;
282 FT_Pos x, y;
283 FT_UInt num_points, num_new_points, num_base_points;
284
285
286 /* gloader.current.subglyphs can change during glyph loading due */
287 /* to re-allocation -- we must recompute the current subglyph on */
288 /* each iteration */
289 subglyph = gloader->base.subglyphs + num_base_subgs + nn;
290
291 pp1 = loader->pp1;
292 pp2 = loader->pp2;
293
294 num_base_points = gloader->base.outline.n_points;
295
296 error = af_loader_load_g( loader, scaler, subglyph->index,
297 load_flags, depth + 1 );
298 if ( error )
299 goto Exit;
300
301 /* recompute subglyph pointer */
302 subglyph = gloader->base.subglyphs + num_base_subgs + nn;
303
304 if ( subglyph->flags & FT_SUBGLYPH_FLAG_USE_MY_METRICS )
305 {
306 pp1 = loader->pp1;
307 pp2 = loader->pp2;
308 }
309 else
310 {
311 loader->pp1 = pp1;
312 loader->pp2 = pp2;
313 }
314
315 num_points = gloader->base.outline.n_points;
316 num_new_points = num_points - num_base_points;
317
Werner Lemberg6cfbb232011-02-26 17:32:38 +0100318 /* now perform the transformation required for this subglyph */
Werner Lemberg8bb07e62004-03-27 08:43:17 +0000319
320 if ( subglyph->flags & ( FT_SUBGLYPH_FLAG_SCALE |
321 FT_SUBGLYPH_FLAG_XY_SCALE |
322 FT_SUBGLYPH_FLAG_2X2 ) )
323 {
324 FT_Vector* cur = gloader->base.outline.points +
325 num_base_points;
Werner Lemberg8bb07e62004-03-27 08:43:17 +0000326 FT_Vector* limit = cur + num_new_points;
327
328
David Turner65c7c772006-04-13 07:51:58 +0000329 for ( ; cur < limit; cur++ )
Werner Lemberg8bb07e62004-03-27 08:43:17 +0000330 FT_Vector_Transform( cur, &subglyph->transform );
Werner Lemberg8bb07e62004-03-27 08:43:17 +0000331 }
332
333 /* apply offset */
334
335 if ( !( subglyph->flags & FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES ) )
336 {
337 FT_Int k = subglyph->arg1;
338 FT_UInt l = subglyph->arg2;
339 FT_Vector* p1;
340 FT_Vector* p2;
341
342
343 if ( start_point + k >= num_base_points ||
344 l >= (FT_UInt)num_new_points )
345 {
Werner Lemberga37745b2005-03-23 16:45:24 +0000346 error = AF_Err_Invalid_Composite;
Werner Lemberg8bb07e62004-03-27 08:43:17 +0000347 goto Exit;
348 }
349
350 l += num_base_points;
351
352 /* for now, only use the current point coordinates; */
353 /* we may consider another approach in the near future */
354 p1 = gloader->base.outline.points + start_point + k;
355 p2 = gloader->base.outline.points + start_point + l;
356
357 x = p1->x - p2->x;
358 y = p1->y - p2->y;
359 }
360 else
361 {
362 x = FT_MulFix( subglyph->arg1, hints->x_scale ) + hints->x_delta;
363 y = FT_MulFix( subglyph->arg2, hints->y_scale ) + hints->y_delta;
364
Werner Lembergb19b0812005-03-02 11:24:23 +0000365 x = FT_PIX_ROUND( x );
366 y = FT_PIX_ROUND( y );
Werner Lemberg8bb07e62004-03-27 08:43:17 +0000367 }
368
369 {
370 FT_Outline dummy = gloader->base.outline;
371
372
373 dummy.points += num_base_points;
374 dummy.n_points = (short)num_new_points;
375
376 FT_Outline_Translate( &dummy, x, y );
377 }
378 }
379 }
380 break;
381
382 default:
383 /* we don't support other formats (yet?) */
Werner Lemberga37745b2005-03-23 16:45:24 +0000384 error = AF_Err_Unimplemented_Feature;
Werner Lemberg8bb07e62004-03-27 08:43:17 +0000385 }
386
387 Hint_Metrics:
388 if ( depth == 0 )
389 {
Wu, Chia-I (吳佳一)2e48a1a2006-02-27 09:18:07 +0000390 FT_BBox bbox;
391 FT_Vector vvector;
Werner Lemberg8bb07e62004-03-27 08:43:17 +0000392
393
Wu, Chia-I (吳佳一)2e48a1a2006-02-27 09:18:07 +0000394 vvector.x = slot->metrics.vertBearingX - slot->metrics.horiBearingX;
395 vvector.y = slot->metrics.vertBearingY - slot->metrics.horiBearingY;
396 vvector.x = FT_MulFix( vvector.x, metrics->scaler.x_scale );
397 vvector.y = FT_MulFix( vvector.y, metrics->scaler.y_scale );
398
Werner Lemberg8bb07e62004-03-27 08:43:17 +0000399 /* transform the hinted outline if needed */
400 if ( loader->transformed )
Wu, Chia-I (吳佳一)2e48a1a2006-02-27 09:18:07 +0000401 {
Werner Lemberg8bb07e62004-03-27 08:43:17 +0000402 FT_Outline_Transform( &gloader->base.outline, &loader->trans_matrix );
Wu, Chia-I (吳佳一)2e48a1a2006-02-27 09:18:07 +0000403 FT_Vector_Transform( &vvector, &loader->trans_matrix );
404 }
David Turnerb7920172007-06-11 05:37:35 +0000405#if 1
Werner Lemberg8bb07e62004-03-27 08:43:17 +0000406 /* we must translate our final outline by -pp1.x and compute */
407 /* the new metrics */
408 if ( loader->pp1.x )
409 FT_Outline_Translate( &gloader->base.outline, -loader->pp1.x, 0 );
David Turnerb7920172007-06-11 05:37:35 +0000410#endif
Werner Lemberg8bb07e62004-03-27 08:43:17 +0000411 FT_Outline_Get_CBox( &gloader->base.outline, &bbox );
412
Werner Lembergb19b0812005-03-02 11:24:23 +0000413 bbox.xMin = FT_PIX_FLOOR( bbox.xMin );
414 bbox.yMin = FT_PIX_FLOOR( bbox.yMin );
415 bbox.xMax = FT_PIX_CEIL( bbox.xMax );
416 bbox.yMax = FT_PIX_CEIL( bbox.yMax );
Werner Lemberg8bb07e62004-03-27 08:43:17 +0000417
418 slot->metrics.width = bbox.xMax - bbox.xMin;
419 slot->metrics.height = bbox.yMax - bbox.yMin;
420 slot->metrics.horiBearingX = bbox.xMin;
421 slot->metrics.horiBearingY = bbox.yMax;
422
Wu, Chia-I (吳佳一)2e48a1a2006-02-27 09:18:07 +0000423 slot->metrics.vertBearingX = FT_PIX_FLOOR( bbox.xMin + vvector.x );
424 slot->metrics.vertBearingY = FT_PIX_FLOOR( bbox.yMax + vvector.y );
425
Werner Lemberg8bb07e62004-03-27 08:43:17 +0000426 /* for mono-width fonts (like Andale, Courier, etc.) we need */
Werner Lemberg8b84c9d2009-04-27 19:40:35 +0200427 /* to keep the original rounded advance width; ditto for */
428 /* digits if all have the same advance width */
Werner Lemberg8bb07e62004-03-27 08:43:17 +0000429#if 0
430 if ( !FT_IS_FIXED_WIDTH( slot->face ) )
431 slot->metrics.horiAdvance = loader->pp2.x - loader->pp1.x;
432 else
433 slot->metrics.horiAdvance = FT_MulFix( slot->metrics.horiAdvance,
434 x_scale );
435#else
Werner Lemberg8b84c9d2009-04-27 19:40:35 +0200436 if ( FT_IS_FIXED_WIDTH( slot->face ) ||
437 ( af_face_globals_is_digit( loader->globals, glyph_index ) &&
438 metrics->digits_have_same_width ) )
David Turner23553d62007-03-26 13:37:17 +0000439 {
David Turnere664efa2004-06-04 17:41:59 +0000440 slot->metrics.horiAdvance = FT_MulFix( slot->metrics.horiAdvance,
441 metrics->scaler.x_scale );
David Turner23553d62007-03-26 13:37:17 +0000442
Werner Lemberg644b1ad2007-03-28 21:17:11 +0000443 /* Set delta values to 0. Otherwise code that uses them is */
444 /* going to ruin the fixed advance width. */
David Turner23553d62007-03-26 13:37:17 +0000445 slot->lsb_delta = 0;
446 slot->rsb_delta = 0;
447 }
Werner Lemberg8b84c9d2009-04-27 19:40:35 +0200448 else
449 {
450 /* non-spacing glyphs must stay as-is */
451 if ( slot->metrics.horiAdvance )
452 slot->metrics.horiAdvance = loader->pp2.x - loader->pp1.x;
453 }
Werner Lemberg8bb07e62004-03-27 08:43:17 +0000454#endif
455
Wu, Chia-I (吳佳一)2e48a1a2006-02-27 09:18:07 +0000456 slot->metrics.vertAdvance = FT_MulFix( slot->metrics.vertAdvance,
Werner Lemberg6cfbb232011-02-26 17:32:38 +0100457 metrics->scaler.y_scale );
Wu, Chia-I (吳佳一)2e48a1a2006-02-27 09:18:07 +0000458
Werner Lemberg8bb07e62004-03-27 08:43:17 +0000459 slot->metrics.horiAdvance = FT_PIX_ROUND( slot->metrics.horiAdvance );
Wu, Chia-I (吳佳一)2e48a1a2006-02-27 09:18:07 +0000460 slot->metrics.vertAdvance = FT_PIX_ROUND( slot->metrics.vertAdvance );
Werner Lemberg8bb07e62004-03-27 08:43:17 +0000461
462 /* now copy outline into glyph slot */
463 FT_GlyphLoader_Rewind( internal->loader );
464 error = FT_GlyphLoader_CopyPoints( internal->loader, gloader );
465 if ( error )
466 goto Exit;
467
468 slot->outline = internal->loader->base.outline;
469 slot->format = FT_GLYPH_FORMAT_OUTLINE;
470 }
471
Werner Lemberg8bb07e62004-03-27 08:43:17 +0000472 Exit:
473 return error;
474 }
475
476
Werner Lemberg6cfbb232011-02-26 17:32:38 +0100477 /* Load a glyph. */
478
Werner Lemberg8bb07e62004-03-27 08:43:17 +0000479 FT_LOCAL_DEF( FT_Error )
480 af_loader_load_glyph( AF_Loader loader,
481 FT_Face face,
482 FT_UInt gindex,
483 FT_UInt32 load_flags )
484 {
485 FT_Error error;
486 FT_Size size = face->size;
487 AF_ScalerRec scaler;
488
Werner Lembergb19b0812005-03-02 11:24:23 +0000489
Werner Lemberg8bb07e62004-03-27 08:43:17 +0000490 if ( !size )
Werner Lemberga37745b2005-03-23 16:45:24 +0000491 return AF_Err_Invalid_Argument;
Werner Lemberg8bb07e62004-03-27 08:43:17 +0000492
493 FT_ZERO( &scaler );
494
495 scaler.face = face;
496 scaler.x_scale = size->metrics.x_scale;
497 scaler.x_delta = 0; /* XXX: TODO: add support for sub-pixel hinting */
498 scaler.y_scale = size->metrics.y_scale;
499 scaler.y_delta = 0; /* XXX: TODO: add support for sub-pixel hinting */
500
501 scaler.render_mode = FT_LOAD_TARGET_MODE( load_flags );
502 scaler.flags = 0; /* XXX: fix this */
503
504 error = af_loader_reset( loader, face );
505 if ( !error )
506 {
507 AF_ScriptMetrics metrics;
David Turnerb7920172007-06-11 05:37:35 +0000508 FT_UInt options = 0;
Werner Lemberg8bb07e62004-03-27 08:43:17 +0000509
Werner Lemberg49e18b82007-06-11 21:15:09 +0000510
David Turnerb7920172007-06-11 05:37:35 +0000511#ifdef FT_OPTION_AUTOFIT2
512 /* XXX: undocumented hook to activate the latin2 hinter */
Werner Lemberg49e18b82007-06-11 21:15:09 +0000513 if ( load_flags & ( 1UL << 20 ) )
David Turnerb7920172007-06-11 05:37:35 +0000514 options = 2;
515#endif
Werner Lembergb19b0812005-03-02 11:24:23 +0000516
517 error = af_face_globals_get_metrics( loader->globals, gindex,
David Turnerb7920172007-06-11 05:37:35 +0000518 options, &metrics );
Werner Lemberg8bb07e62004-03-27 08:43:17 +0000519 if ( !error )
520 {
521 loader->metrics = metrics;
522
Werner Lemberg8bb07e62004-03-27 08:43:17 +0000523 if ( metrics->clazz->script_metrics_scale )
524 metrics->clazz->script_metrics_scale( metrics, &scaler );
David Turnerb9c22af2005-03-01 15:48:29 +0000525 else
526 metrics->scaler = scaler;
Werner Lemberg8bb07e62004-03-27 08:43:17 +0000527
528 load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_IGNORE_TRANSFORM;
529 load_flags &= ~FT_LOAD_RENDER;
530
Werner Lemberg44c655b2008-02-17 08:22:08 +0000531 if ( metrics->clazz->script_hints_init )
532 {
533 error = metrics->clazz->script_hints_init( &loader->hints,
534 metrics );
535 if ( error )
536 goto Exit;
537 }
David Turnere664efa2004-06-04 17:41:59 +0000538
Werner Lemberg8bb07e62004-03-27 08:43:17 +0000539 error = af_loader_load_g( loader, &scaler, gindex, load_flags, 0 );
540 }
541 }
David Turnere664efa2004-06-04 17:41:59 +0000542 Exit:
Werner Lemberg8bb07e62004-03-27 08:43:17 +0000543 return error;
544 }
Werner Lembergb19b0812005-03-02 11:24:23 +0000545
546
547/* END */