~ubuntu-branches/ubuntu/saucy/emscripten/saucy-proposed

« back to all changes in this revision

Viewing changes to tests/freetype/src/base/ftoutln.c

  • Committer: Package Import Robot
  • Author(s): Sylvestre Ledru
  • Date: 2013-05-02 13:11:51 UTC
  • Revision ID: package-import@ubuntu.com-20130502131151-q8dvteqr1ef2x7xz
Tags: upstream-1.4.1~20130504~adb56cb
ImportĀ upstreamĀ versionĀ 1.4.1~20130504~adb56cb

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/***************************************************************************/
 
2
/*                                                                         */
 
3
/*  ftoutln.c                                                              */
 
4
/*                                                                         */
 
5
/*    FreeType outline management (body).                                  */
 
6
/*                                                                         */
 
7
/*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010 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
  /*************************************************************************/
 
20
  /*                                                                       */
 
21
  /* All functions are declared in freetype.h.                             */
 
22
  /*                                                                       */
 
23
  /*************************************************************************/
 
24
 
 
25
 
 
26
#include <ft2build.h>
 
27
#include FT_OUTLINE_H
 
28
#include FT_INTERNAL_OBJECTS_H
 
29
#include FT_INTERNAL_DEBUG_H
 
30
#include FT_TRIGONOMETRY_H
 
31
 
 
32
 
 
33
  /*************************************************************************/
 
34
  /*                                                                       */
 
35
  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
 
36
  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
 
37
  /* messages during execution.                                            */
 
38
  /*                                                                       */
 
39
#undef  FT_COMPONENT
 
40
#define FT_COMPONENT  trace_outline
 
41
 
 
42
 
 
43
  static
 
44
  const FT_Outline  null_outline = { 0, 0, 0, 0, 0, 0 };
 
45
 
 
46
 
 
47
  /* documentation is in ftoutln.h */
 
48
 
 
49
  FT_EXPORT_DEF( FT_Error )
 
50
  FT_Outline_Decompose( FT_Outline*              outline,
 
51
                        const FT_Outline_Funcs*  func_interface,
 
52
                        void*                    user )
 
53
  {
 
54
#undef SCALED
 
55
#define SCALED( x )  ( ( (x) << shift ) - delta )
 
56
 
 
57
    FT_Vector   v_last;
 
58
    FT_Vector   v_control;
 
59
    FT_Vector   v_start;
 
60
 
 
61
    FT_Vector*  point;
 
62
    FT_Vector*  limit;
 
63
    char*       tags;
 
64
 
 
65
    FT_Error    error;
 
66
 
 
67
    FT_Int   n;         /* index of contour in outline     */
 
68
    FT_UInt  first;     /* index of first point in contour */
 
69
    FT_Int   tag;       /* current point's state           */
 
70
 
 
71
    FT_Int   shift;
 
72
    FT_Pos   delta;
 
73
 
 
74
 
 
75
    if ( !outline || !func_interface )
 
76
      return FT_Err_Invalid_Argument;
 
77
 
 
78
    shift = func_interface->shift;
 
79
    delta = func_interface->delta;
 
80
    first = 0;
 
81
 
 
82
    for ( n = 0; n < outline->n_contours; n++ )
 
83
    {
 
84
      FT_Int  last;  /* index of last point in contour */
 
85
 
 
86
 
 
87
      FT_TRACE5(( "FT_Outline_Decompose: Outline %d\n", n ));
 
88
 
 
89
      last = outline->contours[n];
 
90
      if ( last < 0 )
 
91
        goto Invalid_Outline;
 
92
      limit = outline->points + last;
 
93
 
 
94
      v_start   = outline->points[first];
 
95
      v_start.x = SCALED( v_start.x );
 
96
      v_start.y = SCALED( v_start.y );
 
97
 
 
98
      v_last   = outline->points[last];
 
99
      v_last.x = SCALED( v_last.x );
 
100
      v_last.y = SCALED( v_last.y );
 
101
 
 
102
      v_control = v_start;
 
103
 
 
104
      point = outline->points + first;
 
105
      tags  = outline->tags   + first;
 
106
      tag   = FT_CURVE_TAG( tags[0] );
 
107
 
 
108
      /* A contour cannot start with a cubic control point! */
 
109
      if ( tag == FT_CURVE_TAG_CUBIC )
 
110
        goto Invalid_Outline;
 
111
 
 
112
      /* check first point to determine origin */
 
113
      if ( tag == FT_CURVE_TAG_CONIC )
 
114
      {
 
115
        /* first point is conic control.  Yes, this happens. */
 
116
        if ( FT_CURVE_TAG( outline->tags[last] ) == FT_CURVE_TAG_ON )
 
117
        {
 
118
          /* start at last point if it is on the curve */
 
119
          v_start = v_last;
 
120
          limit--;
 
121
        }
 
122
        else
 
123
        {
 
124
          /* if both first and last points are conic,         */
 
125
          /* start at their middle and record its position    */
 
126
          /* for closure                                      */
 
127
          v_start.x = ( v_start.x + v_last.x ) / 2;
 
128
          v_start.y = ( v_start.y + v_last.y ) / 2;
 
129
 
 
130
          v_last = v_start;
 
131
        }
 
132
        point--;
 
133
        tags--;
 
134
      }
 
135
 
 
136
      FT_TRACE5(( "  move to (%.2f, %.2f)\n",
 
137
                  v_start.x / 64.0, v_start.y / 64.0 ));
 
138
      error = func_interface->move_to( &v_start, user );
 
139
      if ( error )
 
140
        goto Exit;
 
141
 
 
142
      while ( point < limit )
 
143
      {
 
144
        point++;
 
145
        tags++;
 
146
 
 
147
        tag = FT_CURVE_TAG( tags[0] );
 
148
        switch ( tag )
 
149
        {
 
150
        case FT_CURVE_TAG_ON:  /* emit a single line_to */
 
151
          {
 
152
            FT_Vector  vec;
 
153
 
 
154
 
 
155
            vec.x = SCALED( point->x );
 
156
            vec.y = SCALED( point->y );
 
157
 
 
158
            FT_TRACE5(( "  line to (%.2f, %.2f)\n",
 
159
                        vec.x / 64.0, vec.y / 64.0 ));
 
160
            error = func_interface->line_to( &vec, user );
 
161
            if ( error )
 
162
              goto Exit;
 
163
            continue;
 
164
          }
 
165
 
 
166
        case FT_CURVE_TAG_CONIC:  /* consume conic arcs */
 
167
          v_control.x = SCALED( point->x );
 
168
          v_control.y = SCALED( point->y );
 
169
 
 
170
        Do_Conic:
 
171
          if ( point < limit )
 
172
          {
 
173
            FT_Vector  vec;
 
174
            FT_Vector  v_middle;
 
175
 
 
176
 
 
177
            point++;
 
178
            tags++;
 
179
            tag = FT_CURVE_TAG( tags[0] );
 
180
 
 
181
            vec.x = SCALED( point->x );
 
182
            vec.y = SCALED( point->y );
 
183
 
 
184
            if ( tag == FT_CURVE_TAG_ON )
 
185
            {
 
186
              FT_TRACE5(( "  conic to (%.2f, %.2f)"
 
187
                          " with control (%.2f, %.2f)\n",
 
188
                          vec.x / 64.0, vec.y / 64.0,
 
189
                          v_control.x / 64.0, v_control.y / 64.0 ));
 
190
              error = func_interface->conic_to( &v_control, &vec, user );
 
191
              if ( error )
 
192
                goto Exit;
 
193
              continue;
 
194
            }
 
195
 
 
196
            if ( tag != FT_CURVE_TAG_CONIC )
 
197
              goto Invalid_Outline;
 
198
 
 
199
            v_middle.x = ( v_control.x + vec.x ) / 2;
 
200
            v_middle.y = ( v_control.y + vec.y ) / 2;
 
201
 
 
202
            FT_TRACE5(( "  conic to (%.2f, %.2f)"
 
203
                        " with control (%.2f, %.2f)\n",
 
204
                        v_middle.x / 64.0, v_middle.y / 64.0,
 
205
                        v_control.x / 64.0, v_control.y / 64.0 ));
 
206
            error = func_interface->conic_to( &v_control, &v_middle, user );
 
207
            if ( error )
 
208
              goto Exit;
 
209
 
 
210
            v_control = vec;
 
211
            goto Do_Conic;
 
212
          }
 
213
 
 
214
          FT_TRACE5(( "  conic to (%.2f, %.2f)"
 
215
                      " with control (%.2f, %.2f)\n",
 
216
                      v_start.x / 64.0, v_start.y / 64.0,
 
217
                      v_control.x / 64.0, v_control.y / 64.0 ));
 
218
          error = func_interface->conic_to( &v_control, &v_start, user );
 
219
          goto Close;
 
220
 
 
221
        default:  /* FT_CURVE_TAG_CUBIC */
 
222
          {
 
223
            FT_Vector  vec1, vec2;
 
224
 
 
225
 
 
226
            if ( point + 1 > limit                             ||
 
227
                 FT_CURVE_TAG( tags[1] ) != FT_CURVE_TAG_CUBIC )
 
228
              goto Invalid_Outline;
 
229
 
 
230
            point += 2;
 
231
            tags  += 2;
 
232
 
 
233
            vec1.x = SCALED( point[-2].x );
 
234
            vec1.y = SCALED( point[-2].y );
 
235
 
 
236
            vec2.x = SCALED( point[-1].x );
 
237
            vec2.y = SCALED( point[-1].y );
 
238
 
 
239
            if ( point <= limit )
 
240
            {
 
241
              FT_Vector  vec;
 
242
 
 
243
 
 
244
              vec.x = SCALED( point->x );
 
245
              vec.y = SCALED( point->y );
 
246
 
 
247
              FT_TRACE5(( "  cubic to (%.2f, %.2f)"
 
248
                          " with controls (%.2f, %.2f) and (%.2f, %.2f)\n",
 
249
                          vec.x / 64.0, vec.y / 64.0,
 
250
                          vec1.x / 64.0, vec1.y / 64.0,
 
251
                          vec2.x / 64.0, vec2.y / 64.0 ));
 
252
              error = func_interface->cubic_to( &vec1, &vec2, &vec, user );
 
253
              if ( error )
 
254
                goto Exit;
 
255
              continue;
 
256
            }
 
257
 
 
258
            FT_TRACE5(( "  cubic to (%.2f, %.2f)"
 
259
                        " with controls (%.2f, %.2f) and (%.2f, %.2f)\n",
 
260
                        v_start.x / 64.0, v_start.y / 64.0,
 
261
                        vec1.x / 64.0, vec1.y / 64.0,
 
262
                        vec2.x / 64.0, vec2.y / 64.0 ));
 
263
            error = func_interface->cubic_to( &vec1, &vec2, &v_start, user );
 
264
            goto Close;
 
265
          }
 
266
        }
 
267
      }
 
268
 
 
269
      /* close the contour with a line segment */
 
270
      FT_TRACE5(( "  line to (%.2f, %.2f)\n",
 
271
                  v_start.x / 64.0, v_start.y / 64.0 ));
 
272
      error = func_interface->line_to( &v_start, user );
 
273
 
 
274
    Close:
 
275
      if ( error )
 
276
        goto Exit;
 
277
 
 
278
      first = last + 1;
 
279
    }
 
280
 
 
281
    FT_TRACE5(( "FT_Outline_Decompose: Done\n", n ));
 
282
    return FT_Err_Ok;
 
283
 
 
284
  Exit:
 
285
    FT_TRACE5(( "FT_Outline_Decompose: Error %d\n", error ));
 
286
    return error;
 
287
 
 
288
  Invalid_Outline:
 
289
    return FT_Err_Invalid_Outline;
 
290
  }
 
291
 
 
292
 
 
293
  FT_EXPORT_DEF( FT_Error )
 
294
  FT_Outline_New_Internal( FT_Memory    memory,
 
295
                           FT_UInt      numPoints,
 
296
                           FT_Int       numContours,
 
297
                           FT_Outline  *anoutline )
 
298
  {
 
299
    FT_Error  error;
 
300
 
 
301
 
 
302
    if ( !anoutline || !memory )
 
303
      return FT_Err_Invalid_Argument;
 
304
 
 
305
    *anoutline = null_outline;
 
306
 
 
307
    if ( FT_NEW_ARRAY( anoutline->points,   numPoints   ) ||
 
308
         FT_NEW_ARRAY( anoutline->tags,     numPoints   ) ||
 
309
         FT_NEW_ARRAY( anoutline->contours, numContours ) )
 
310
      goto Fail;
 
311
 
 
312
    anoutline->n_points    = (FT_UShort)numPoints;
 
313
    anoutline->n_contours  = (FT_Short)numContours;
 
314
    anoutline->flags      |= FT_OUTLINE_OWNER;
 
315
 
 
316
    return FT_Err_Ok;
 
317
 
 
318
  Fail:
 
319
    anoutline->flags |= FT_OUTLINE_OWNER;
 
320
    FT_Outline_Done_Internal( memory, anoutline );
 
321
 
 
322
    return error;
 
323
  }
 
324
 
 
325
 
 
326
  /* documentation is in ftoutln.h */
 
327
 
 
328
  FT_EXPORT_DEF( FT_Error )
 
329
  FT_Outline_New( FT_Library   library,
 
330
                  FT_UInt      numPoints,
 
331
                  FT_Int       numContours,
 
332
                  FT_Outline  *anoutline )
 
333
  {
 
334
    if ( !library )
 
335
      return FT_Err_Invalid_Library_Handle;
 
336
 
 
337
    return FT_Outline_New_Internal( library->memory, numPoints,
 
338
                                    numContours, anoutline );
 
339
  }
 
340
 
 
341
 
 
342
  /* documentation is in ftoutln.h */
 
343
 
 
344
  FT_EXPORT_DEF( FT_Error )
 
345
  FT_Outline_Check( FT_Outline*  outline )
 
346
  {
 
347
    if ( outline )
 
348
    {
 
349
      FT_Int  n_points   = outline->n_points;
 
350
      FT_Int  n_contours = outline->n_contours;
 
351
      FT_Int  end0, end;
 
352
      FT_Int  n;
 
353
 
 
354
 
 
355
      /* empty glyph? */
 
356
      if ( n_points == 0 && n_contours == 0 )
 
357
        return 0;
 
358
 
 
359
      /* check point and contour counts */
 
360
      if ( n_points <= 0 || n_contours <= 0 )
 
361
        goto Bad;
 
362
 
 
363
      end0 = end = -1;
 
364
      for ( n = 0; n < n_contours; n++ )
 
365
      {
 
366
        end = outline->contours[n];
 
367
 
 
368
        /* note that we don't accept empty contours */
 
369
        if ( end <= end0 || end >= n_points )
 
370
          goto Bad;
 
371
 
 
372
        end0 = end;
 
373
      }
 
374
 
 
375
      if ( end != n_points - 1 )
 
376
        goto Bad;
 
377
 
 
378
      /* XXX: check the tags array */
 
379
      return 0;
 
380
    }
 
381
 
 
382
  Bad:
 
383
    return FT_Err_Invalid_Argument;
 
384
  }
 
385
 
 
386
 
 
387
  /* documentation is in ftoutln.h */
 
388
 
 
389
  FT_EXPORT_DEF( FT_Error )
 
390
  FT_Outline_Copy( const FT_Outline*  source,
 
391
                   FT_Outline        *target )
 
392
  {
 
393
    FT_Int  is_owner;
 
394
 
 
395
 
 
396
    if ( !source            || !target            ||
 
397
         source->n_points   != target->n_points   ||
 
398
         source->n_contours != target->n_contours )
 
399
      return FT_Err_Invalid_Argument;
 
400
 
 
401
    if ( source == target )
 
402
      return FT_Err_Ok;
 
403
 
 
404
    FT_ARRAY_COPY( target->points, source->points, source->n_points );
 
405
 
 
406
    FT_ARRAY_COPY( target->tags, source->tags, source->n_points );
 
407
 
 
408
    FT_ARRAY_COPY( target->contours, source->contours, source->n_contours );
 
409
 
 
410
    /* copy all flags, except the `FT_OUTLINE_OWNER' one */
 
411
    is_owner      = target->flags & FT_OUTLINE_OWNER;
 
412
    target->flags = source->flags;
 
413
 
 
414
    target->flags &= ~FT_OUTLINE_OWNER;
 
415
    target->flags |= is_owner;
 
416
 
 
417
    return FT_Err_Ok;
 
418
  }
 
419
 
 
420
 
 
421
  FT_EXPORT_DEF( FT_Error )
 
422
  FT_Outline_Done_Internal( FT_Memory    memory,
 
423
                            FT_Outline*  outline )
 
424
  {
 
425
    if ( memory && outline )
 
426
    {
 
427
      if ( outline->flags & FT_OUTLINE_OWNER )
 
428
      {
 
429
        FT_FREE( outline->points   );
 
430
        FT_FREE( outline->tags     );
 
431
        FT_FREE( outline->contours );
 
432
      }
 
433
      *outline = null_outline;
 
434
 
 
435
      return FT_Err_Ok;
 
436
    }
 
437
    else
 
438
      return FT_Err_Invalid_Argument;
 
439
  }
 
440
 
 
441
 
 
442
  /* documentation is in ftoutln.h */
 
443
 
 
444
  FT_EXPORT_DEF( FT_Error )
 
445
  FT_Outline_Done( FT_Library   library,
 
446
                   FT_Outline*  outline )
 
447
  {
 
448
    /* check for valid `outline' in FT_Outline_Done_Internal() */
 
449
 
 
450
    if ( !library )
 
451
      return FT_Err_Invalid_Library_Handle;
 
452
 
 
453
    return FT_Outline_Done_Internal( library->memory, outline );
 
454
  }
 
455
 
 
456
 
 
457
  /* documentation is in ftoutln.h */
 
458
 
 
459
  FT_EXPORT_DEF( void )
 
460
  FT_Outline_Get_CBox( const FT_Outline*  outline,
 
461
                       FT_BBox           *acbox )
 
462
  {
 
463
    FT_Pos  xMin, yMin, xMax, yMax;
 
464
 
 
465
 
 
466
    if ( outline && acbox )
 
467
    {
 
468
      if ( outline->n_points == 0 )
 
469
      {
 
470
        xMin = 0;
 
471
        yMin = 0;
 
472
        xMax = 0;
 
473
        yMax = 0;
 
474
      }
 
475
      else
 
476
      {
 
477
        FT_Vector*  vec   = outline->points;
 
478
        FT_Vector*  limit = vec + outline->n_points;
 
479
 
 
480
 
 
481
        xMin = xMax = vec->x;
 
482
        yMin = yMax = vec->y;
 
483
        vec++;
 
484
 
 
485
        for ( ; vec < limit; vec++ )
 
486
        {
 
487
          FT_Pos  x, y;
 
488
 
 
489
 
 
490
          x = vec->x;
 
491
          if ( x < xMin ) xMin = x;
 
492
          if ( x > xMax ) xMax = x;
 
493
 
 
494
          y = vec->y;
 
495
          if ( y < yMin ) yMin = y;
 
496
          if ( y > yMax ) yMax = y;
 
497
        }
 
498
      }
 
499
      acbox->xMin = xMin;
 
500
      acbox->xMax = xMax;
 
501
      acbox->yMin = yMin;
 
502
      acbox->yMax = yMax;
 
503
    }
 
504
  }
 
505
 
 
506
 
 
507
  /* documentation is in ftoutln.h */
 
508
 
 
509
  FT_EXPORT_DEF( void )
 
510
  FT_Outline_Translate( const FT_Outline*  outline,
 
511
                        FT_Pos             xOffset,
 
512
                        FT_Pos             yOffset )
 
513
  {
 
514
    FT_UShort   n;
 
515
    FT_Vector*  vec;
 
516
 
 
517
 
 
518
    if ( !outline )
 
519
      return;
 
520
 
 
521
    vec = outline->points;
 
522
 
 
523
    for ( n = 0; n < outline->n_points; n++ )
 
524
    {
 
525
      vec->x += xOffset;
 
526
      vec->y += yOffset;
 
527
      vec++;
 
528
    }
 
529
  }
 
530
 
 
531
 
 
532
  /* documentation is in ftoutln.h */
 
533
 
 
534
  FT_EXPORT_DEF( void )
 
535
  FT_Outline_Reverse( FT_Outline*  outline )
 
536
  {
 
537
    FT_UShort  n;
 
538
    FT_Int     first, last;
 
539
 
 
540
 
 
541
    if ( !outline )
 
542
      return;
 
543
 
 
544
    first = 0;
 
545
 
 
546
    for ( n = 0; n < outline->n_contours; n++ )
 
547
    {
 
548
      last  = outline->contours[n];
 
549
 
 
550
      /* reverse point table */
 
551
      {
 
552
        FT_Vector*  p = outline->points + first;
 
553
        FT_Vector*  q = outline->points + last;
 
554
        FT_Vector   swap;
 
555
 
 
556
 
 
557
        while ( p < q )
 
558
        {
 
559
          swap = *p;
 
560
          *p   = *q;
 
561
          *q   = swap;
 
562
          p++;
 
563
          q--;
 
564
        }
 
565
      }
 
566
 
 
567
      /* reverse tags table */
 
568
      {
 
569
        char*  p = outline->tags + first;
 
570
        char*  q = outline->tags + last;
 
571
        char   swap;
 
572
 
 
573
 
 
574
        while ( p < q )
 
575
        {
 
576
          swap = *p;
 
577
          *p   = *q;
 
578
          *q   = swap;
 
579
          p++;
 
580
          q--;
 
581
        }
 
582
      }
 
583
 
 
584
      first = last + 1;
 
585
    }
 
586
 
 
587
    outline->flags ^= FT_OUTLINE_REVERSE_FILL;
 
588
  }
 
589
 
 
590
 
 
591
  /* documentation is in ftoutln.h */
 
592
 
 
593
  FT_EXPORT_DEF( FT_Error )
 
594
  FT_Outline_Render( FT_Library         library,
 
595
                     FT_Outline*        outline,
 
596
                     FT_Raster_Params*  params )
 
597
  {
 
598
    FT_Error     error;
 
599
    FT_Bool      update = FALSE;
 
600
    FT_Renderer  renderer;
 
601
    FT_ListNode  node;
 
602
 
 
603
 
 
604
    if ( !library )
 
605
      return FT_Err_Invalid_Library_Handle;
 
606
 
 
607
    if ( !outline || !params )
 
608
      return FT_Err_Invalid_Argument;
 
609
 
 
610
    renderer = library->cur_renderer;
 
611
    node     = library->renderers.head;
 
612
 
 
613
    params->source = (void*)outline;
 
614
 
 
615
    error = FT_Err_Cannot_Render_Glyph;
 
616
    while ( renderer )
 
617
    {
 
618
      error = renderer->raster_render( renderer->raster, params );
 
619
      if ( !error || FT_ERROR_BASE( error ) != FT_Err_Cannot_Render_Glyph )
 
620
        break;
 
621
 
 
622
      /* FT_Err_Cannot_Render_Glyph is returned if the render mode   */
 
623
      /* is unsupported by the current renderer for this glyph image */
 
624
      /* format                                                      */
 
625
 
 
626
      /* now, look for another renderer that supports the same */
 
627
      /* format                                                */
 
628
      renderer = FT_Lookup_Renderer( library, FT_GLYPH_FORMAT_OUTLINE,
 
629
                                     &node );
 
630
      update   = TRUE;
 
631
    }
 
632
 
 
633
    /* if we changed the current renderer for the glyph image format */
 
634
    /* we need to select it as the next current one                  */
 
635
    if ( !error && update && renderer )
 
636
      FT_Set_Renderer( library, renderer, 0, 0 );
 
637
 
 
638
    return error;
 
639
  }
 
640
 
 
641
 
 
642
  /* documentation is in ftoutln.h */
 
643
 
 
644
  FT_EXPORT_DEF( FT_Error )
 
645
  FT_Outline_Get_Bitmap( FT_Library        library,
 
646
                         FT_Outline*       outline,
 
647
                         const FT_Bitmap  *abitmap )
 
648
  {
 
649
    FT_Raster_Params  params;
 
650
 
 
651
 
 
652
    if ( !abitmap )
 
653
      return FT_Err_Invalid_Argument;
 
654
 
 
655
    /* other checks are delayed to FT_Outline_Render() */
 
656
 
 
657
    params.target = abitmap;
 
658
    params.flags  = 0;
 
659
 
 
660
    if ( abitmap->pixel_mode == FT_PIXEL_MODE_GRAY  ||
 
661
         abitmap->pixel_mode == FT_PIXEL_MODE_LCD   ||
 
662
         abitmap->pixel_mode == FT_PIXEL_MODE_LCD_V )
 
663
      params.flags |= FT_RASTER_FLAG_AA;
 
664
 
 
665
    return FT_Outline_Render( library, outline, &params );
 
666
  }
 
667
 
 
668
 
 
669
  /* documentation is in freetype.h */
 
670
 
 
671
  FT_EXPORT_DEF( void )
 
672
  FT_Vector_Transform( FT_Vector*        vector,
 
673
                       const FT_Matrix*  matrix )
 
674
  {
 
675
    FT_Pos  xz, yz;
 
676
 
 
677
 
 
678
    if ( !vector || !matrix )
 
679
      return;
 
680
 
 
681
    xz = FT_MulFix( vector->x, matrix->xx ) +
 
682
         FT_MulFix( vector->y, matrix->xy );
 
683
 
 
684
    yz = FT_MulFix( vector->x, matrix->yx ) +
 
685
         FT_MulFix( vector->y, matrix->yy );
 
686
 
 
687
    vector->x = xz;
 
688
    vector->y = yz;
 
689
  }
 
690
 
 
691
 
 
692
  /* documentation is in ftoutln.h */
 
693
 
 
694
  FT_EXPORT_DEF( void )
 
695
  FT_Outline_Transform( const FT_Outline*  outline,
 
696
                        const FT_Matrix*   matrix )
 
697
  {
 
698
    FT_Vector*  vec;
 
699
    FT_Vector*  limit;
 
700
 
 
701
 
 
702
    if ( !outline || !matrix )
 
703
      return;
 
704
 
 
705
    vec   = outline->points;
 
706
    limit = vec + outline->n_points;
 
707
 
 
708
    for ( ; vec < limit; vec++ )
 
709
      FT_Vector_Transform( vec, matrix );
 
710
  }
 
711
 
 
712
 
 
713
#if 0
 
714
 
 
715
#define FT_OUTLINE_GET_CONTOUR( outline, c, first, last )  \
 
716
  do {                                                     \
 
717
    (first) = ( c > 0 ) ? (outline)->points +              \
 
718
                            (outline)->contours[c - 1] + 1 \
 
719
                        : (outline)->points;               \
 
720
    (last) = (outline)->points + (outline)->contours[c];   \
 
721
  } while ( 0 )
 
722
 
 
723
 
 
724
  /* Is a point in some contour?                     */
 
725
  /*                                                 */
 
726
  /* We treat every point of the contour as if it    */
 
727
  /* it were ON.  That is, we allow false positives, */
 
728
  /* but disallow false negatives.  (XXX really?)    */
 
729
  static FT_Bool
 
730
  ft_contour_has( FT_Outline*  outline,
 
731
                  FT_Short     c,
 
732
                  FT_Vector*   point )
 
733
  {
 
734
    FT_Vector*  first;
 
735
    FT_Vector*  last;
 
736
    FT_Vector*  a;
 
737
    FT_Vector*  b;
 
738
    FT_UInt     n = 0;
 
739
 
 
740
 
 
741
    FT_OUTLINE_GET_CONTOUR( outline, c, first, last );
 
742
 
 
743
    for ( a = first; a <= last; a++ )
 
744
    {
 
745
      FT_Pos  x;
 
746
      FT_Int  intersect;
 
747
 
 
748
 
 
749
      b = ( a == last ) ? first : a + 1;
 
750
 
 
751
      intersect = ( a->y - point->y ) ^ ( b->y - point->y );
 
752
 
 
753
      /* a and b are on the same side */
 
754
      if ( intersect >= 0 )
 
755
      {
 
756
        if ( intersect == 0 && a->y == point->y )
 
757
        {
 
758
          if ( ( a->x <= point->x && b->x >= point->x ) ||
 
759
               ( a->x >= point->x && b->x <= point->x ) )
 
760
            return 1;
 
761
        }
 
762
 
 
763
        continue;
 
764
      }
 
765
 
 
766
      x = a->x + ( b->x - a->x ) * (point->y - a->y ) / ( b->y - a->y );
 
767
 
 
768
      if ( x < point->x )
 
769
        n++;
 
770
      else if ( x == point->x )
 
771
        return 1;
 
772
    }
 
773
 
 
774
    return ( n % 2 );
 
775
  }
 
776
 
 
777
 
 
778
  static FT_Bool
 
779
  ft_contour_enclosed( FT_Outline*  outline,
 
780
                       FT_UShort    c )
 
781
  {
 
782
    FT_Vector*  first;
 
783
    FT_Vector*  last;
 
784
    FT_Short    i;
 
785
 
 
786
 
 
787
    FT_OUTLINE_GET_CONTOUR( outline, c, first, last );
 
788
 
 
789
    for ( i = 0; i < outline->n_contours; i++ )
 
790
    {
 
791
      if ( i != c && ft_contour_has( outline, i, first ) )
 
792
      {
 
793
        FT_Vector*  pt;
 
794
 
 
795
 
 
796
        for ( pt = first + 1; pt <= last; pt++ )
 
797
          if ( !ft_contour_has( outline, i, pt ) )
 
798
            return 0;
 
799
 
 
800
        return 1;
 
801
      }
 
802
    }
 
803
 
 
804
    return 0;
 
805
  }
 
806
 
 
807
 
 
808
  /* This version differs from the public one in that each */
 
809
  /* part (contour not enclosed in another contour) of the */
 
810
  /* outline is checked for orientation.  This is          */
 
811
  /* necessary for some buggy CJK fonts.                   */
 
812
  static FT_Orientation
 
813
  ft_outline_get_orientation( FT_Outline*  outline )
 
814
  {
 
815
    FT_Short        i;
 
816
    FT_Vector*      first;
 
817
    FT_Vector*      last;
 
818
    FT_Orientation  orient = FT_ORIENTATION_NONE;
 
819
 
 
820
 
 
821
    first = outline->points;
 
822
    for ( i = 0; i < outline->n_contours; i++, first = last + 1 )
 
823
    {
 
824
      FT_Vector*  point;
 
825
      FT_Vector*  xmin_point;
 
826
      FT_Pos      xmin;
 
827
 
 
828
 
 
829
      last = outline->points + outline->contours[i];
 
830
 
 
831
      /* skip degenerate contours */
 
832
      if ( last < first + 2 )
 
833
        continue;
 
834
 
 
835
      if ( ft_contour_enclosed( outline, i ) )
 
836
        continue;
 
837
 
 
838
      xmin       = first->x;
 
839
      xmin_point = first;
 
840
 
 
841
      for ( point = first + 1; point <= last; point++ )
 
842
      {
 
843
        if ( point->x < xmin )
 
844
        {
 
845
          xmin       = point->x;
 
846
          xmin_point = point;
 
847
        }
 
848
      }
 
849
 
 
850
      /* check the orientation of the contour */
 
851
      {
 
852
        FT_Vector*      prev;
 
853
        FT_Vector*      next;
 
854
        FT_Orientation  o;
 
855
 
 
856
 
 
857
        prev = ( xmin_point == first ) ? last : xmin_point - 1;
 
858
        next = ( xmin_point == last ) ? first : xmin_point + 1;
 
859
 
 
860
        if ( FT_Atan2( prev->x - xmin_point->x, prev->y - xmin_point->y ) >
 
861
             FT_Atan2( next->x - xmin_point->x, next->y - xmin_point->y ) )
 
862
          o = FT_ORIENTATION_POSTSCRIPT;
 
863
        else
 
864
          o = FT_ORIENTATION_TRUETYPE;
 
865
 
 
866
        if ( orient == FT_ORIENTATION_NONE )
 
867
          orient = o;
 
868
        else if ( orient != o )
 
869
          return FT_ORIENTATION_NONE;
 
870
      }
 
871
    }
 
872
 
 
873
    return orient;
 
874
  }
 
875
 
 
876
#endif /* 0 */
 
877
 
 
878
 
 
879
  /* documentation is in ftoutln.h */
 
880
 
 
881
  FT_EXPORT_DEF( FT_Error )
 
882
  FT_Outline_Embolden( FT_Outline*  outline,
 
883
                       FT_Pos       strength )
 
884
  {
 
885
    FT_Vector*  points;
 
886
    FT_Vector   v_prev, v_first, v_next, v_cur;
 
887
    FT_Angle    rotate, angle_in, angle_out;
 
888
    FT_Int      c, n, first;
 
889
    FT_Int      orientation;
 
890
 
 
891
 
 
892
    if ( !outline )
 
893
      return FT_Err_Invalid_Argument;
 
894
 
 
895
    strength /= 2;
 
896
    if ( strength == 0 )
 
897
      return FT_Err_Ok;
 
898
 
 
899
    orientation = FT_Outline_Get_Orientation( outline );
 
900
    if ( orientation == FT_ORIENTATION_NONE )
 
901
    {
 
902
      if ( outline->n_contours )
 
903
        return FT_Err_Invalid_Argument;
 
904
      else
 
905
        return FT_Err_Ok;
 
906
    }
 
907
 
 
908
    if ( orientation == FT_ORIENTATION_TRUETYPE )
 
909
      rotate = -FT_ANGLE_PI2;
 
910
    else
 
911
      rotate = FT_ANGLE_PI2;
 
912
 
 
913
    points = outline->points;
 
914
 
 
915
    first = 0;
 
916
    for ( c = 0; c < outline->n_contours; c++ )
 
917
    {
 
918
      int  last = outline->contours[c];
 
919
 
 
920
 
 
921
      v_first = points[first];
 
922
      v_prev  = points[last];
 
923
      v_cur   = v_first;
 
924
 
 
925
      for ( n = first; n <= last; n++ )
 
926
      {
 
927
        FT_Vector  in, out;
 
928
        FT_Angle   angle_diff;
 
929
        FT_Pos     d;
 
930
        FT_Fixed   scale;
 
931
 
 
932
 
 
933
        if ( n < last )
 
934
          v_next = points[n + 1];
 
935
        else
 
936
          v_next = v_first;
 
937
 
 
938
        /* compute the in and out vectors */
 
939
        in.x = v_cur.x - v_prev.x;
 
940
        in.y = v_cur.y - v_prev.y;
 
941
 
 
942
        out.x = v_next.x - v_cur.x;
 
943
        out.y = v_next.y - v_cur.y;
 
944
 
 
945
        angle_in   = FT_Atan2( in.x, in.y );
 
946
        angle_out  = FT_Atan2( out.x, out.y );
 
947
        angle_diff = FT_Angle_Diff( angle_in, angle_out );
 
948
        scale      = FT_Cos( angle_diff / 2 );
 
949
 
 
950
        if ( scale < 0x4000L && scale > -0x4000L )
 
951
          in.x = in.y = 0;
 
952
        else
 
953
        {
 
954
          d = FT_DivFix( strength, scale );
 
955
 
 
956
          FT_Vector_From_Polar( &in, d, angle_in + angle_diff / 2 - rotate );
 
957
        }
 
958
 
 
959
        outline->points[n].x = v_cur.x + strength + in.x;
 
960
        outline->points[n].y = v_cur.y + strength + in.y;
 
961
 
 
962
        v_prev = v_cur;
 
963
        v_cur  = v_next;
 
964
      }
 
965
 
 
966
      first = last + 1;
 
967
    }
 
968
 
 
969
    return FT_Err_Ok;
 
970
  }
 
971
 
 
972
 
 
973
  /* documentation is in ftoutln.h */
 
974
 
 
975
  FT_EXPORT_DEF( FT_Orientation )
 
976
  FT_Outline_Get_Orientation( FT_Outline*  outline )
 
977
  {
 
978
    FT_Pos      xmin       = 32768L;
 
979
    FT_Pos      xmin_ymin  = 32768L;
 
980
    FT_Pos      xmin_ymax  = -32768L;
 
981
    FT_Vector*  xmin_first = NULL;
 
982
    FT_Vector*  xmin_last  = NULL;
 
983
 
 
984
    short*      contour;
 
985
 
 
986
    FT_Vector*  first;
 
987
    FT_Vector*  last;
 
988
    FT_Vector*  prev;
 
989
    FT_Vector*  point;
 
990
 
 
991
    int             i;
 
992
    FT_Pos          ray_y[3];
 
993
    FT_Orientation  result[3] =
 
994
      { FT_ORIENTATION_NONE, FT_ORIENTATION_NONE, FT_ORIENTATION_NONE };
 
995
 
 
996
 
 
997
    if ( !outline || outline->n_points <= 0 )
 
998
      return FT_ORIENTATION_TRUETYPE;
 
999
 
 
1000
    /* We use the nonzero winding rule to find the orientation.       */
 
1001
    /* Since glyph outlines behave much more `regular' than arbitrary */
 
1002
    /* cubic or quadratic curves, this test deals with the polygon    */
 
1003
    /* only which is spanned up by the control points.                */
 
1004
 
 
1005
    first = outline->points;
 
1006
    for ( contour = outline->contours;
 
1007
          contour < outline->contours + outline->n_contours;
 
1008
          contour++, first = last + 1 )
 
1009
    {
 
1010
      FT_Pos  contour_xmin = 32768L;
 
1011
      FT_Pos  contour_xmax = -32768L;
 
1012
      FT_Pos  contour_ymin = 32768L;
 
1013
      FT_Pos  contour_ymax = -32768L;
 
1014
 
 
1015
 
 
1016
      last = outline->points + *contour;
 
1017
 
 
1018
      /* skip degenerate contours */
 
1019
      if ( last < first + 2 )
 
1020
        continue;
 
1021
 
 
1022
      for ( point = first; point <= last; ++point )
 
1023
      {
 
1024
        if ( point->x < contour_xmin )
 
1025
          contour_xmin = point->x;
 
1026
 
 
1027
        if ( point->x > contour_xmax )
 
1028
          contour_xmax = point->x;
 
1029
 
 
1030
        if ( point->y < contour_ymin )
 
1031
          contour_ymin = point->y;
 
1032
 
 
1033
        if ( point->y > contour_ymax )
 
1034
          contour_ymax = point->y;
 
1035
      }
 
1036
 
 
1037
      if ( contour_xmin < xmin          &&
 
1038
           contour_xmin != contour_xmax &&
 
1039
           contour_ymin != contour_ymax )
 
1040
      {
 
1041
        xmin       = contour_xmin;
 
1042
        xmin_ymin  = contour_ymin;
 
1043
        xmin_ymax  = contour_ymax;
 
1044
        xmin_first = first;
 
1045
        xmin_last  = last;
 
1046
      }
 
1047
    }
 
1048
 
 
1049
    if ( xmin == 32768L )
 
1050
      return FT_ORIENTATION_TRUETYPE;
 
1051
 
 
1052
    ray_y[0] = ( xmin_ymin * 3 + xmin_ymax     ) >> 2;
 
1053
    ray_y[1] = ( xmin_ymin     + xmin_ymax     ) >> 1;
 
1054
    ray_y[2] = ( xmin_ymin     + xmin_ymax * 3 ) >> 2;
 
1055
 
 
1056
    for ( i = 0; i < 3; i++ )
 
1057
    {
 
1058
      FT_Pos      left_x;
 
1059
      FT_Pos      right_x;
 
1060
      FT_Vector*  left1;
 
1061
      FT_Vector*  left2;
 
1062
      FT_Vector*  right1;
 
1063
      FT_Vector*  right2;
 
1064
 
 
1065
 
 
1066
    RedoRay:
 
1067
      left_x  = 32768L;
 
1068
      right_x = -32768L;
 
1069
 
 
1070
      left1 = left2 = right1 = right2 = NULL;
 
1071
 
 
1072
      prev = xmin_last;
 
1073
      for ( point = xmin_first; point <= xmin_last; prev = point, ++point )
 
1074
      {
 
1075
        FT_Pos  tmp_x;
 
1076
 
 
1077
 
 
1078
        if ( point->y == ray_y[i] || prev->y == ray_y[i] )
 
1079
        {
 
1080
          ray_y[i]++;
 
1081
          goto RedoRay;
 
1082
        }
 
1083
 
 
1084
        if ( ( point->y < ray_y[i] && prev->y < ray_y[i] ) ||
 
1085
             ( point->y > ray_y[i] && prev->y > ray_y[i] ) )
 
1086
          continue;
 
1087
 
 
1088
        tmp_x = FT_MulDiv( point->x - prev->x,
 
1089
                           ray_y[i] - prev->y,
 
1090
                           point->y - prev->y ) + prev->x;
 
1091
 
 
1092
        if ( tmp_x < left_x )
 
1093
        {
 
1094
          left_x = tmp_x;
 
1095
          left1  = prev;
 
1096
          left2  = point;
 
1097
        }
 
1098
 
 
1099
        if ( tmp_x > right_x )
 
1100
        {
 
1101
          right_x = tmp_x;
 
1102
          right1  = prev;
 
1103
          right2  = point;
 
1104
        }
 
1105
      }
 
1106
 
 
1107
      if ( left1 && right1 )
 
1108
      {
 
1109
        if ( left1->y < left2->y && right1->y > right2->y )
 
1110
          result[i] = FT_ORIENTATION_TRUETYPE;
 
1111
        else if ( left1->y > left2->y && right1->y < right2->y )
 
1112
          result[i] = FT_ORIENTATION_POSTSCRIPT;
 
1113
        else
 
1114
          result[i] = FT_ORIENTATION_NONE;
 
1115
      }
 
1116
    }
 
1117
 
 
1118
    if ( result[0] != FT_ORIENTATION_NONE                     &&
 
1119
         ( result[0] == result[1] || result[0] == result[2] ) )
 
1120
      return result[0];
 
1121
 
 
1122
    if ( result[1] != FT_ORIENTATION_NONE && result[1] == result[2] )
 
1123
      return result[1];
 
1124
 
 
1125
    return FT_ORIENTATION_TRUETYPE;
 
1126
  }
 
1127
 
 
1128
 
 
1129
/* END */