~oif-team/ubuntu/natty/qt4-x11/xi2.1

« back to all changes in this revision

Viewing changes to src/3rdparty/freetype/src/autofit/afhints.c

  • Committer: Bazaar Package Importer
  • Author(s): Adam Conrad
  • Date: 2005-08-24 04:09:09 UTC
  • Revision ID: james.westby@ubuntu.com-20050824040909-xmxe9jfr4a0w5671
Tags: upstream-4.0.0
ImportĀ upstreamĀ versionĀ 4.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include "afhints.h"
 
2
 
 
3
#ifdef AF_DEBUG
 
4
 
 
5
#include <stdio.h>
 
6
 
 
7
  static const char* af_dir_str( AF_Direction  dir )
 
8
  {
 
9
    const char*  result;
 
10
 
 
11
    switch (dir)
 
12
    {
 
13
     case AF_DIR_UP:    result = "up";    break;
 
14
     case AF_DIR_DOWN:  result = "down";  break;
 
15
     case AF_DIR_LEFT:  result = "left";  break;
 
16
     case AF_DIR_RIGHT: result = "right"; break;
 
17
     default:           result = "none";
 
18
    }
 
19
    return result;
 
20
  }
 
21
 
 
22
#define  AF_INDEX_NUM(ptr,base)  ( (ptr) ? ((ptr)-(base)) : -1 )
 
23
 
 
24
  void
 
25
  af_glyph_hints_dump_points( AF_GlyphHints  hints )
 
26
  {
 
27
    AF_Point  points = hints->points;
 
28
    AF_Point  limit  = points + hints->num_points;
 
29
    AF_Point  point;
 
30
 
 
31
    printf( "Table of points:\n" );
 
32
    printf(   "  [ index |  xorg |  yorg |  xscale |  yscale |  xfit  |  yfit  |  flags ]\n" );
 
33
    for ( point = points; point < limit; point++ )
 
34
    {
 
35
      printf( "  [ %5d | %5d | %5d | %-5.2f | %-5.2f | %-5.2f | %-5.2f | %c%c%c%c%c%c ]\n",
 
36
              point - points,
 
37
              point->fx,
 
38
              point->fy,
 
39
              point->ox/64.0,
 
40
              point->oy/64.0,
 
41
              point->x/64.0,
 
42
              point->y/64.0,
 
43
              (point->flags & AF_FLAG_WEAK_INTERPOLATION) ? 'w' : ' ',
 
44
              (point->flags & AF_FLAG_INFLECTION)         ? 'i' : ' ',
 
45
              (point->flags & AF_FLAG_EXTREMA_X)          ? '<' : ' ',
 
46
              (point->flags & AF_FLAG_EXTREMA_Y)          ? 'v' : ' ',
 
47
              (point->flags & AF_FLAG_ROUND_X)            ? '(' : ' ',
 
48
              (point->flags & AF_FLAG_ROUND_Y)            ? 'u' : ' '
 
49
            );
 
50
    }
 
51
    printf( "\n" );
 
52
  }
 
53
 
 
54
 
 
55
  /* A function used to dump the array of linked segments */
 
56
  void
 
57
  af_glyph_hints_dump_segments( AF_GlyphHints  hints )
 
58
  {
 
59
    AF_Point    points = hints->points;
 
60
    FT_Int      dimension;
 
61
 
 
62
    for ( dimension = 1; dimension >= 0; dimension-- )
 
63
    {
 
64
      AF_AxisHints  axis = &hints->axis[dimension];
 
65
      AF_Segment    segments = axis->segments;
 
66
      AF_Segment    limit    = segments + axis->num_segments;
 
67
      AF_Segment    seg;
 
68
 
 
69
 
 
70
      printf ( "Table of %s segments:\n",
 
71
               dimension == AF_DIMENSION_HORZ ? "vertical" : "horizontal" );
 
72
      printf ( "  [ index |  pos |  dir  | link | serif |"
 
73
               " numl | first | start ]\n" );
 
74
 
 
75
      for ( seg = segments; seg < limit; seg++ )
 
76
      {
 
77
        printf ( "  [ %5d | %4d | %5s | %4d | %5d | %4d | %5d | %5d ]\n",
 
78
                 seg - segments,
 
79
                 (int)seg->pos,
 
80
                 af_dir_str( seg->dir ),
 
81
                 AF_INDEX_NUM( seg->link, segments ),
 
82
                 AF_INDEX_NUM( seg->serif, segments ),
 
83
                 (int)seg->num_linked,
 
84
                 seg->first - points,
 
85
                 seg->last - points );
 
86
      }
 
87
      printf( "\n" );
 
88
    }
 
89
  }
 
90
 
 
91
 
 
92
  void
 
93
  af_glyph_hints_dump_edges( AF_GlyphHints  hints )
 
94
  {
 
95
    FT_Int      dimension;
 
96
 
 
97
    for ( dimension = 1; dimension >= 0; dimension-- )
 
98
    {
 
99
      AF_AxisHints  axis  = &hints->axis[ dimension ];
 
100
      AF_Edge       edges = axis->edges;
 
101
      AF_Edge       limit = edges + axis->num_edges;
 
102
      AF_Edge       edge;
 
103
 
 
104
     /* note: AF_DIMENSION_HORZ corresponds to _vertical_ edges
 
105
      * since they have constant X coordinate
 
106
      */
 
107
      printf ( "Table of %s edges:\n",
 
108
               dimension == AF_DIMENSION_HORZ ? "vertical" : "horizontal" );
 
109
      printf ( "  [ index |  pos |  dir  | link |"
 
110
               " serif | blue | opos  |  pos  ]\n" );
 
111
 
 
112
      for ( edge = edges; edge < limit; edge++ )
 
113
      {
 
114
        printf ( "  [ %5d | %4d | %5s | %4d | %5d |   %c  | %5.2f | %5.2f ]\n",
 
115
                 edge - edges,
 
116
                 (int)edge->fpos,
 
117
                 af_dir_str( edge->dir ),
 
118
                 AF_INDEX_NUM( edge->link, edges ),
 
119
                 AF_INDEX_NUM( edge->serif, edges ),
 
120
                 edge->blue_edge ? 'y' : 'n',
 
121
                 edge->opos / 64.0,
 
122
                 edge->pos / 64.0 );
 
123
      }
 
124
 
 
125
      printf( "\n" );
 
126
    }
 
127
  }
 
128
 
 
129
 
 
130
 
 
131
#endif /* AF_DEBUG */
 
132
 
 
133
 
 
134
  /* compute the direction value of a given vector */
 
135
  FT_LOCAL_DEF( AF_Direction )
 
136
  af_direction_compute( FT_Pos  dx,
 
137
                        FT_Pos  dy )
 
138
  {
 
139
    AF_Direction  dir;
 
140
    FT_Pos        ax = FT_ABS( dx );
 
141
    FT_Pos        ay = FT_ABS( dy );
 
142
 
 
143
 
 
144
    dir = AF_DIR_NONE;
 
145
 
 
146
    /* atan(1/12) == 4.7 degrees */
 
147
 
 
148
    /* test for vertical direction */
 
149
    if ( ax * 12 < ay )
 
150
    {
 
151
      dir = dy > 0 ? AF_DIR_UP : AF_DIR_DOWN;
 
152
    }
 
153
    /* test for horizontal direction */
 
154
    else if ( ay * 12 < ax )
 
155
    {
 
156
      dir = dx > 0 ? AF_DIR_RIGHT : AF_DIR_LEFT;
 
157
    }
 
158
 
 
159
    return dir;
 
160
  }
 
161
 
 
162
 
 
163
  /* compute all inflex points in a given glyph */
 
164
  static void
 
165
  af_glyph_hints_compute_inflections( AF_GlyphHints  hints )
 
166
  {
 
167
    AF_Point*  contour       = hints->contours;
 
168
    AF_Point*  contour_limit = contour + hints->num_contours;
 
169
 
 
170
 
 
171
    /* do each contour separately */
 
172
    for ( ; contour < contour_limit; contour++ )
 
173
    {
 
174
      AF_Point   point = contour[0];
 
175
      AF_Point   first = point;
 
176
      AF_Point   start = point;
 
177
      AF_Point   end   = point;
 
178
      AF_Point   before;
 
179
      AF_Point   after;
 
180
      AF_Angle   angle_in, angle_seg, angle_out;
 
181
      AF_Angle   diff_in, diff_out;
 
182
      FT_Int     finished = 0;
 
183
 
 
184
 
 
185
      /* compute first segment in contour */
 
186
      first = point;
 
187
 
 
188
      start = end = first;
 
189
      do
 
190
      {
 
191
        end = end->next;
 
192
        if ( end == first )
 
193
          goto Skip;
 
194
 
 
195
      } while ( end->fx == first->fx && end->fy == first->fy );
 
196
 
 
197
      angle_seg = af_angle_atan( end->fx - start->fx,
 
198
                                 end->fy - start->fy );
 
199
 
 
200
      /* extend the segment start whenever possible */
 
201
      before = start;
 
202
      do
 
203
      {
 
204
        do
 
205
        {
 
206
          start  = before;
 
207
          before = before->prev;
 
208
          if ( before == first )
 
209
            goto Skip;
 
210
 
 
211
        } while ( before->fx == start->fx && before->fy == start->fy );
 
212
 
 
213
        angle_in = af_angle_atan( start->fx - before->fx,
 
214
                                  start->fy - before->fy );
 
215
 
 
216
      } while ( angle_in == angle_seg );
 
217
 
 
218
      first   = start;
 
219
      diff_in = af_angle_diff( angle_in, angle_seg );
 
220
 
 
221
      /* now, process all segments in the contour */
 
222
      do
 
223
      {
 
224
        /* first, extend current segment's end whenever possible */
 
225
        after = end;
 
226
        do
 
227
        {
 
228
          do
 
229
          {
 
230
            end   = after;
 
231
            after = after->next;
 
232
            if ( after == first )
 
233
              finished = 1;
 
234
 
 
235
          } while ( end->fx == after->fx && end->fy == after->fy );
 
236
 
 
237
          angle_out = af_angle_atan( after->fx - end->fx,
 
238
                                     after->fy - end->fy );
 
239
 
 
240
        } while ( angle_out == angle_seg );
 
241
 
 
242
        diff_out = af_angle_diff( angle_seg, angle_out );
 
243
 
 
244
        if ( ( diff_in ^ diff_out ) < 0 )
 
245
        {
 
246
          /* diff_in and diff_out have different signs, we have */
 
247
          /* inflection points here...                          */
 
248
          do
 
249
          {
 
250
            start->flags |= AF_FLAG_INFLECTION;
 
251
            start = start->next;
 
252
 
 
253
          } while ( start != end );
 
254
 
 
255
          start->flags |= AF_FLAG_INFLECTION;
 
256
        }
 
257
 
 
258
        start     = end;
 
259
        end       = after;
 
260
        angle_seg = angle_out;
 
261
        diff_in   = diff_out;
 
262
 
 
263
      } while ( !finished );
 
264
 
 
265
    Skip:
 
266
      ;
 
267
    }
 
268
  }
 
269
 
 
270
 
 
271
 
 
272
  FT_LOCAL_DEF( void )
 
273
  af_glyph_hints_init( AF_GlyphHints  hints,
 
274
                       FT_Memory      memory )
 
275
  {
 
276
    FT_ZERO( hints );
 
277
    hints->memory = memory;
 
278
  }
 
279
 
 
280
 
 
281
 
 
282
  FT_LOCAL_DEF( void )
 
283
  af_glyph_hints_done( AF_GlyphHints  hints )
 
284
  {
 
285
    if ( hints && hints->memory )
 
286
    {
 
287
      FT_Memory     memory = hints->memory;
 
288
      AF_Dimension  dim;
 
289
 
 
290
     /* note that we don't need to free the segment and edge
 
291
      * buffers, since they're really within the hints->points array
 
292
      */
 
293
      for ( dim = 0; dim < 2; dim++ )
 
294
      {
 
295
        AF_AxisHints  axis = &hints->axis[ dim ];
 
296
 
 
297
        axis->num_segments = 0;
 
298
        axis->num_edges    = 0;
 
299
        axis->segments     = NULL;
 
300
        axis->edges        = NULL;
 
301
      }
 
302
 
 
303
      FT_FREE( hints->contours );
 
304
      hints->max_contours = 0;
 
305
      hints->num_contours = 0;
 
306
 
 
307
      FT_FREE( hints->points );
 
308
      hints->num_points = 0;
 
309
      hints->max_points = 0;
 
310
 
 
311
      hints->memory = NULL;
 
312
    }
 
313
  }
 
314
 
 
315
 
 
316
 
 
317
  FT_LOCAL_DEF( void )
 
318
  af_glyph_hints_rescale( AF_GlyphHints     hints,
 
319
                          AF_ScriptMetrics  metrics )
 
320
  {
 
321
    hints->metrics = metrics;
 
322
  }
 
323
 
 
324
 
 
325
  FT_LOCAL_DEF( FT_Error )
 
326
  af_glyph_hints_reload( AF_GlyphHints     hints,
 
327
                         FT_Outline*       outline )
 
328
  {
 
329
    FT_Error     error        = FT_Err_Ok;
 
330
    AF_Point     points;
 
331
    FT_UInt      old_max, new_max;
 
332
    AF_Scaler    scaler  = &hints->metrics->scaler;
 
333
    FT_Fixed     x_scale = hints->x_scale;
 
334
    FT_Fixed     y_scale = hints->y_scale;
 
335
    FT_Pos       x_delta = hints->x_delta;
 
336
    FT_Pos       y_delta = hints->y_delta;
 
337
    FT_Memory    memory  = hints->memory;
 
338
 
 
339
    hints->scaler_flags  = scaler->flags;
 
340
    hints->num_points    = 0;
 
341
    hints->num_contours  = 0;
 
342
 
 
343
    hints->axis[0].num_segments = 0;
 
344
    hints->axis[0].num_edges    = 0;
 
345
    hints->axis[1].num_segments = 0;
 
346
    hints->axis[1].num_edges    = 0;
 
347
 
 
348
   /* first of all, reallocate the contours array when necessary
 
349
    */
 
350
    new_max = (FT_UInt) outline->n_contours;
 
351
    old_max = hints->max_contours;
 
352
    if ( new_max > old_max )
 
353
    {
 
354
      new_max = (new_max + 3) & ~3;
 
355
 
 
356
      if ( FT_RENEW_ARRAY( hints->contours, old_max, new_max ) )
 
357
        goto Exit;
 
358
 
 
359
      hints->max_contours = new_max;
 
360
    }
 
361
 
 
362
   /* then, reallocate the points, segments & edges arrays if needed --
 
363
    * note that we reserved two additional point positions, used to
 
364
    * hint metrics appropriately
 
365
    */
 
366
    new_max = (FT_UInt)( outline->n_points + 2 );
 
367
    old_max = hints->max_points;
 
368
    if ( new_max > old_max )
 
369
    {
 
370
      FT_Byte*    items;
 
371
      FT_ULong    off1, off2, off3;
 
372
 
 
373
     /* we store in a single buffer the following arrays:
 
374
      *
 
375
      *  - an array of   N  AF_PointRec   items
 
376
      *  - an array of 2*N  AF_SegmentRec items
 
377
      *  - an array of 2*N  AF_EdgeRec    items
 
378
      *
 
379
      */
 
380
 
 
381
      new_max = ( new_max + 2 + 7 ) & ~7;
 
382
 
 
383
#define OFF_PAD2(x,y)   (((x)+(y)-1) & ~((y)-1))
 
384
#define OFF_PADX(x,y)   ((((x)+(y)-1)/(y))*(y))
 
385
#define OFF_PAD(x,y)    ( ((y) & ((y)-1)) ? OFF_PADX(x,y) : OFF_PAD2(x,y) )
 
386
 
 
387
#undef  OFF_INCREMENT
 
388
#define OFF_INCREMENT( _off, _type, _count )   \
 
389
     ( OFF_PAD( _off, sizeof(_type) ) + (_count)*sizeof(_type))
 
390
 
 
391
      off1 = OFF_INCREMENT( 0, AF_PointRec, new_max );
 
392
      off2 = OFF_INCREMENT( off1, AF_SegmentRec, new_max*2 );
 
393
      off3 = OFF_INCREMENT( off2, AF_EdgeRec, new_max*2 );
 
394
 
 
395
      FT_FREE( hints->points );
 
396
 
 
397
      if ( FT_ALLOC( items, off3 ) )
 
398
      {
 
399
        hints->max_points       = 0;
 
400
        hints->axis[0].segments = NULL;
 
401
        hints->axis[0].edges    = NULL;
 
402
        hints->axis[1].segments = NULL;
 
403
        hints->axis[1].edges    = NULL;
 
404
        goto Exit;
 
405
      }
 
406
 
 
407
     /* readjust some pointers
 
408
      */
 
409
      hints->max_points       = new_max;
 
410
      hints->points           = (AF_Point) items;
 
411
 
 
412
      hints->axis[0].segments = (AF_Segment)( items + off1 );
 
413
      hints->axis[1].segments = hints->axis[0].segments + new_max;
 
414
 
 
415
      hints->axis[0].edges    = (AF_Edge)   ( items + off2 );
 
416
      hints->axis[1].edges    = hints->axis[0].edges + new_max;
 
417
    }
 
418
 
 
419
    hints->num_points   = outline->n_points;
 
420
    hints->num_contours = outline->n_contours;
 
421
 
 
422
 
 
423
    /* We can't rely on the value of `FT_Outline.flags' to know the fill  */
 
424
    /* direction used for a glyph, given that some fonts are broken (e.g. */
 
425
    /* the Arphic ones).  We thus recompute it each time we need to.      */
 
426
    /*                                                                    */
 
427
    hints->axis[ AF_DIMENSION_HORZ ].major_dir = AF_DIR_UP;
 
428
    hints->axis[ AF_DIMENSION_VERT ].major_dir = AF_DIR_LEFT;
 
429
 
 
430
    if ( FT_Outline_Get_Orientation( outline ) == FT_ORIENTATION_POSTSCRIPT )
 
431
    {
 
432
      hints->axis[ AF_DIMENSION_HORZ ].major_dir = AF_DIR_DOWN;
 
433
      hints->axis[ AF_DIMENSION_VERT ].major_dir = AF_DIR_RIGHT;
 
434
    }
 
435
 
 
436
    hints->x_scale = x_scale;
 
437
    hints->y_scale = y_scale;
 
438
    hints->x_delta = x_delta;
 
439
    hints->y_delta = y_delta;
 
440
 
 
441
    points = hints->points;
 
442
    if ( hints->num_points == 0 )
 
443
      goto Exit;
 
444
 
 
445
    {
 
446
      AF_Point  point;
 
447
      AF_Point  point_limit = points + hints->num_points;
 
448
 
 
449
 
 
450
      /* compute coordinates & bezier flags */
 
451
      {
 
452
        FT_Vector*  vec = outline->points;
 
453
        char*       tag = outline->tags;
 
454
 
 
455
 
 
456
        for ( point = points; point < point_limit; point++, vec++, tag++ )
 
457
        {
 
458
          point->fx = vec->x;
 
459
          point->fy = vec->y;
 
460
          point->ox = point->x = FT_MulFix( vec->x, x_scale ) + x_delta;
 
461
          point->oy = point->y = FT_MulFix( vec->y, y_scale ) + y_delta;
 
462
 
 
463
          switch ( FT_CURVE_TAG( *tag ) )
 
464
          {
 
465
          case FT_CURVE_TAG_CONIC:
 
466
            point->flags = AF_FLAG_CONIC;
 
467
            break;
 
468
          case FT_CURVE_TAG_CUBIC:
 
469
            point->flags = AF_FLAG_CUBIC;
 
470
            break;
 
471
          default:
 
472
            point->flags = 0;
 
473
            ;
 
474
          }
 
475
        }
 
476
      }
 
477
 
 
478
      /* compute `next' and `prev' */
 
479
      {
 
480
        FT_Int    contour_index;
 
481
        AF_Point  prev;
 
482
        AF_Point  first;
 
483
        AF_Point  end;
 
484
 
 
485
 
 
486
        contour_index = 0;
 
487
 
 
488
        first = points;
 
489
        end   = points + outline->contours[0];
 
490
        prev  = end;
 
491
 
 
492
        for ( point = points; point < point_limit; point++ )
 
493
        {
 
494
          point->prev = prev;
 
495
          if ( point < end )
 
496
          {
 
497
            point->next = point + 1;
 
498
            prev        = point;
 
499
          }
 
500
          else
 
501
          {
 
502
            point->next = first;
 
503
            contour_index++;
 
504
            if ( point + 1 < point_limit )
 
505
            {
 
506
              end   = points + outline->contours[contour_index];
 
507
              first = point + 1;
 
508
              prev  = end;
 
509
            }
 
510
          }
 
511
        }
 
512
      }
 
513
 
 
514
      /* set-up the contours array */
 
515
      {
 
516
        AF_Point*  contour       = hints->contours;
 
517
        AF_Point*  contour_limit = contour + hints->num_contours;
 
518
        short*     end           = outline->contours;
 
519
        short      idx           = 0;
 
520
 
 
521
 
 
522
        for ( ; contour < contour_limit; contour++, end++ )
 
523
        {
 
524
          contour[0] = points + idx;
 
525
          idx        = (short)( end[0] + 1 );
 
526
        }
 
527
      }
 
528
 
 
529
      /* compute directions of in & out vectors */
 
530
      {
 
531
        for ( point = points; point < point_limit; point++ )
 
532
        {
 
533
          AF_Point   prev;
 
534
          AF_Point   next;
 
535
          FT_Pos     in_x, in_y, out_x, out_y;
 
536
 
 
537
 
 
538
          prev   = point->prev;
 
539
          in_x   = point->fx - prev->fx;
 
540
          in_y   = point->fy - prev->fy;
 
541
 
 
542
          point->in_dir = af_direction_compute( in_x, in_y );
 
543
 
 
544
          next   = point->next;
 
545
          out_x  = next->fx - point->fx;
 
546
          out_y  = next->fy - point->fy;
 
547
 
 
548
          point->out_dir = af_direction_compute( out_x, out_y );
 
549
 
 
550
          if ( point->flags & ( AF_FLAG_CONIC | AF_FLAG_CUBIC ) )
 
551
          {
 
552
          Is_Weak_Point:
 
553
            point->flags |= AF_FLAG_WEAK_INTERPOLATION;
 
554
          }
 
555
          else if ( point->out_dir == point->in_dir )
 
556
          {
 
557
            AF_Angle  angle_in, angle_out, delta;
 
558
 
 
559
 
 
560
            if ( point->out_dir != AF_DIR_NONE )
 
561
              goto Is_Weak_Point;
 
562
 
 
563
            angle_in  = af_angle_atan( in_x, in_y );
 
564
            angle_out = af_angle_atan( out_x, out_y );
 
565
            delta     = af_angle_diff( angle_in, angle_out );
 
566
 
 
567
            if ( delta < 2 && delta > -2 )
 
568
              goto Is_Weak_Point;
 
569
          }
 
570
          else if ( point->in_dir == -point->out_dir )
 
571
            goto Is_Weak_Point;
 
572
        }
 
573
      }
 
574
    }
 
575
 
 
576
   /* compute inflection points
 
577
    */
 
578
    af_glyph_hints_compute_inflections( hints );
 
579
 
 
580
  Exit:
 
581
    return error;
 
582
  }
 
583
 
 
584
 
 
585
  FT_LOCAL_DEF( void )
 
586
  af_glyph_hints_save( AF_GlyphHints   hints,
 
587
                       FT_Outline*     outline )
 
588
  {
 
589
    AF_Point    point = hints->points;
 
590
    AF_Point    limit = point + hints->num_points;
 
591
    FT_Vector*  vec   = outline->points;
 
592
    char*       tag   = outline->tags;
 
593
 
 
594
    for ( ; point < limit; point++, vec++, tag++ )
 
595
    {
 
596
      vec->x = (FT_Pos) point->x;
 
597
      vec->y = (FT_Pos) point->y;
 
598
 
 
599
      if ( point->flags & AF_FLAG_CONIC )
 
600
        tag[0] = FT_CURVE_TAG_CONIC;
 
601
      else if ( point->flags & AF_FLAG_CUBIC )
 
602
        tag[0] = FT_CURVE_TAG_CUBIC;
 
603
      else
 
604
        tag[0] = FT_CURVE_TAG_ON;
 
605
    }
 
606
  }
 
607
 
 
608
 
 
609
 /*
 
610
  *
 
611
  *  E D G E   P O I N T   G R I D - F I T T I N G
 
612
  *
 
613
  */
 
614
 
 
615
 
 
616
  FT_LOCAL_DEF( void )
 
617
  af_glyph_hints_align_edge_points( AF_GlyphHints  hints,
 
618
                                    AF_Dimension   dim )
 
619
  {
 
620
    AF_AxisHints  axis       = & hints->axis[ dim ];
 
621
    AF_Edge       edges      = axis->edges;
 
622
    AF_Edge       edge_limit = edges + axis->num_edges;
 
623
    AF_Edge       edge;
 
624
 
 
625
    for ( edge = edges; edge < edge_limit; edge++ )
 
626
    {
 
627
      /* move the points of each segment     */
 
628
      /* in each edge to the edge's position */
 
629
      AF_Segment  seg = edge->first;
 
630
 
 
631
 
 
632
      do
 
633
      {
 
634
        AF_Point  point = seg->first;
 
635
 
 
636
 
 
637
        for (;;)
 
638
        {
 
639
          if ( dim == AF_DIMENSION_HORZ )
 
640
          {
 
641
            point->x      = edge->pos;
 
642
            point->flags |= AF_FLAG_TOUCH_X;
 
643
          }
 
644
          else
 
645
          {
 
646
            point->y      = edge->pos;
 
647
            point->flags |= AF_FLAG_TOUCH_Y;
 
648
          }
 
649
 
 
650
          if ( point == seg->last )
 
651
            break;
 
652
 
 
653
          point = point->next;
 
654
        }
 
655
 
 
656
        seg = seg->edge_next;
 
657
 
 
658
      } while ( seg != edge->first );
 
659
    }
 
660
  }
 
661
 
 
662
 
 
663
 /*
 
664
  *
 
665
  *  S T R O N G   P O I N T   I N T E R P O L A T I O N
 
666
  *
 
667
  */
 
668
 
 
669
 
 
670
  /* hint the strong points -- this is equivalent to the TrueType `IP' */
 
671
  /* hinting instruction                                               */
 
672
  FT_LOCAL_DEF( void )
 
673
  af_glyph_hints_align_strong_points( AF_GlyphHints  hints,
 
674
                                      AF_Dimension   dim )
 
675
  {
 
676
    AF_Point      points      = hints->points;
 
677
    AF_Point      point_limit = points + hints->num_points;
 
678
    AF_AxisHints  axis        = &hints->axis[dim];
 
679
    AF_Edge       edges       = axis->edges;
 
680
    AF_Edge       edge_limit  = edges + axis->num_edges;
 
681
    AF_Flags      touch_flag;
 
682
 
 
683
 
 
684
    if ( dim == AF_DIMENSION_HORZ )
 
685
      touch_flag = AF_FLAG_TOUCH_X;
 
686
    else
 
687
      touch_flag  = AF_FLAG_TOUCH_Y;
 
688
 
 
689
    if ( edges < edge_limit )
 
690
    {
 
691
      AF_Point  point;
 
692
      AF_Edge   edge;
 
693
 
 
694
      for ( point = points; point < point_limit; point++ )
 
695
      {
 
696
        FT_Pos  u, ou, fu;  /* point position */
 
697
        FT_Pos  delta;
 
698
 
 
699
 
 
700
        if ( point->flags & touch_flag )
 
701
          continue;
 
702
 
 
703
        /* if this point is candidate to weak interpolation, we will  */
 
704
        /* interpolate it after all strong points have been processed */
 
705
        if (  ( point->flags & AF_FLAG_WEAK_INTERPOLATION ) &&
 
706
             !( point->flags & AF_FLAG_INFLECTION )         )
 
707
          continue;
 
708
 
 
709
        if ( dim == AF_DIMENSION_VERT )
 
710
        {
 
711
          u  = point->fy;
 
712
          ou = point->oy;
 
713
        }
 
714
        else
 
715
        {
 
716
          u  = point->fx;
 
717
          ou = point->ox;
 
718
        }
 
719
 
 
720
        fu = u;
 
721
 
 
722
        /* is the point before the first edge? */
 
723
        edge  = edges;
 
724
        delta = edge->fpos - u;
 
725
        if ( delta >= 0 )
 
726
        {
 
727
          u = edge->pos - ( edge->opos - ou );
 
728
          goto Store_Point;
 
729
        }
 
730
 
 
731
        /* is the point after the last edge? */
 
732
        edge  = edge_limit - 1;
 
733
        delta = u - edge->fpos;
 
734
        if ( delta >= 0 )
 
735
        {
 
736
          u = edge->pos + ( ou - edge->opos );
 
737
          goto Store_Point;
 
738
        }
 
739
 
 
740
        {
 
741
          FT_UInt  min, max, mid;
 
742
          FT_Pos   fpos;
 
743
 
 
744
 
 
745
          /* find enclosing edges */
 
746
          min = 0;
 
747
          max = edge_limit - edges;
 
748
 
 
749
          while ( min < max )
 
750
          {
 
751
            mid  = ( max + min ) >> 1;
 
752
            edge = edges + mid;
 
753
            fpos = edge->fpos;
 
754
 
 
755
            if ( u < fpos )
 
756
              max = mid;
 
757
            else if ( u > fpos )
 
758
              min = mid + 1;
 
759
            else
 
760
            {
 
761
              /* we are on the edge */
 
762
              u = edge->pos;
 
763
              goto Store_Point;
 
764
            }
 
765
          }
 
766
 
 
767
          {
 
768
            AF_Edge  before = edges + min - 1;
 
769
            AF_Edge  after  = edges + min + 0;
 
770
 
 
771
 
 
772
            /* assert( before && after && before != after ) */
 
773
            if ( before->scale == 0 )
 
774
              before->scale = FT_DivFix( after->pos - before->pos,
 
775
                                         after->fpos - before->fpos );
 
776
 
 
777
            u = before->pos + FT_MulFix( fu - before->fpos,
 
778
                                         before->scale );
 
779
          }
 
780
        }
 
781
 
 
782
 
 
783
      Store_Point:
 
784
 
 
785
        /* save the point position */
 
786
        if ( dim == AF_DIMENSION_HORZ )
 
787
          point->x = u;
 
788
        else
 
789
          point->y = u;
 
790
 
 
791
        point->flags |= touch_flag;
 
792
      }
 
793
    }
 
794
  }
 
795
 
 
796
 
 
797
 /*
 
798
  *
 
799
  *  W E A K   P O I N T   I N T E R P O L A T I O N
 
800
  *
 
801
  */
 
802
 
 
803
  static void
 
804
  af_iup_shift( AF_Point  p1,
 
805
                AF_Point  p2,
 
806
                AF_Point  ref )
 
807
  {
 
808
    AF_Point  p;
 
809
    FT_Pos    delta = ref->u - ref->v;
 
810
 
 
811
 
 
812
    for ( p = p1; p < ref; p++ )
 
813
      p->u = p->v + delta;
 
814
 
 
815
    for ( p = ref + 1; p <= p2; p++ )
 
816
      p->u = p->v + delta;
 
817
  }
 
818
 
 
819
 
 
820
  static void
 
821
  af_iup_interp( AF_Point  p1,
 
822
                 AF_Point  p2,
 
823
                 AF_Point  ref1,
 
824
                 AF_Point  ref2 )
 
825
  {
 
826
    AF_Point  p;
 
827
    FT_Pos    u;
 
828
    FT_Pos    v1 = ref1->v;
 
829
    FT_Pos    v2 = ref2->v;
 
830
    FT_Pos    d1 = ref1->u - v1;
 
831
    FT_Pos    d2 = ref2->u - v2;
 
832
 
 
833
 
 
834
    if ( p1 > p2 )
 
835
      return;
 
836
 
 
837
    if ( v1 == v2 )
 
838
    {
 
839
      for ( p = p1; p <= p2; p++ )
 
840
      {
 
841
        u = p->v;
 
842
 
 
843
        if ( u <= v1 )
 
844
          u += d1;
 
845
        else
 
846
          u += d2;
 
847
 
 
848
        p->u = u;
 
849
      }
 
850
      return;
 
851
    }
 
852
 
 
853
    if ( v1 < v2 )
 
854
    {
 
855
      for ( p = p1; p <= p2; p++ )
 
856
      {
 
857
        u = p->v;
 
858
 
 
859
        if ( u <= v1 )
 
860
          u += d1;
 
861
        else if ( u >= v2 )
 
862
          u += d2;
 
863
        else
 
864
          u = ref1->u + FT_MulDiv( u - v1, ref2->u - ref1->u, v2 - v1 );
 
865
 
 
866
        p->u = u;
 
867
      }
 
868
    }
 
869
    else
 
870
    {
 
871
      for ( p = p1; p <= p2; p++ )
 
872
      {
 
873
        u = p->v;
 
874
 
 
875
        if ( u <= v2 )
 
876
          u += d2;
 
877
        else if ( u >= v1 )
 
878
          u += d1;
 
879
        else
 
880
          u = ref1->u + FT_MulDiv( u - v1, ref2->u - ref1->u, v2 - v1 );
 
881
 
 
882
        p->u = u;
 
883
      }
 
884
    }
 
885
  }
 
886
 
 
887
 
 
888
  FT_LOCAL_DEF( void )
 
889
  af_glyph_hints_align_weak_points( AF_GlyphHints  hints,
 
890
                                    AF_Dimension   dim )
 
891
  {
 
892
    AF_Point    points        = hints->points;
 
893
    AF_Point    point_limit   = points + hints->num_points;
 
894
    AF_Point*   contour       = hints->contours;
 
895
    AF_Point*   contour_limit = contour + hints->num_contours;
 
896
    AF_Flags    touch_flag;
 
897
    AF_Point    point;
 
898
    AF_Point    end_point;
 
899
    AF_Point    first_point;
 
900
 
 
901
 
 
902
    /* PASS 1: Move segment points to edge positions */
 
903
 
 
904
    if ( dim == AF_DIMENSION_HORZ )
 
905
    {
 
906
      touch_flag = AF_FLAG_TOUCH_X;
 
907
 
 
908
      for ( point = points; point < point_limit; point++ )
 
909
      {
 
910
        point->u = point->x;
 
911
        point->v = point->ox;
 
912
      }
 
913
    }
 
914
    else
 
915
    {
 
916
      touch_flag = AF_FLAG_TOUCH_Y;
 
917
 
 
918
      for ( point = points; point < point_limit; point++ )
 
919
      {
 
920
        point->u = point->y;
 
921
        point->v = point->oy;
 
922
      }
 
923
    }
 
924
 
 
925
    point   = points;
 
926
 
 
927
    for ( ; contour < contour_limit; contour++ )
 
928
    {
 
929
      point       = *contour;
 
930
      end_point   = point->prev;
 
931
      first_point = point;
 
932
 
 
933
      while ( point <= end_point && !( point->flags & touch_flag ) )
 
934
        point++;
 
935
 
 
936
      if ( point <= end_point )
 
937
      {
 
938
        AF_Point  first_touched = point;
 
939
        AF_Point  cur_touched   = point;
 
940
 
 
941
 
 
942
        point++;
 
943
        while ( point <= end_point )
 
944
        {
 
945
          if ( point->flags & touch_flag )
 
946
          {
 
947
            /* we found two successive touched points; we interpolate */
 
948
            /* all contour points between them                        */
 
949
            af_iup_interp( cur_touched + 1, point - 1,
 
950
                           cur_touched, point );
 
951
            cur_touched = point;
 
952
          }
 
953
          point++;
 
954
        }
 
955
 
 
956
        if ( cur_touched == first_touched )
 
957
        {
 
958
          /* this is a special case: only one point was touched in the */
 
959
          /* contour; we thus simply shift the whole contour           */
 
960
          af_iup_shift( first_point, end_point, cur_touched );
 
961
        }
 
962
        else
 
963
        {
 
964
          /* now interpolate after the last touched point to the end */
 
965
          /* of the contour                                          */
 
966
          af_iup_interp( cur_touched + 1, end_point,
 
967
                         cur_touched, first_touched );
 
968
 
 
969
          /* if the first contour point isn't touched, interpolate */
 
970
          /* from the contour start to the first touched point     */
 
971
          if ( first_touched > points )
 
972
            af_iup_interp( first_point, first_touched - 1,
 
973
                           cur_touched, first_touched );
 
974
        }
 
975
      }
 
976
    }
 
977
 
 
978
    /* now save the interpolated values back to x/y */
 
979
    if ( dim == AF_DIMENSION_HORZ )
 
980
    {
 
981
      for ( point = points; point < point_limit; point++ )
 
982
        point->x = point->u;
 
983
    }
 
984
    else
 
985
    {
 
986
      for ( point = points; point < point_limit; point++ )
 
987
        point->y = point->u;
 
988
    }
 
989
  }