This commit was manufactured by cvs2svn to create branch 'captive'.
[reactos.git] / subsys / win32k / freetype / src / base / ftoutln.c
1 /***************************************************************************/
2 /*                                                                         */
3 /*  ftoutln.c                                                              */
4 /*                                                                         */
5 /*    FreeType outline management (body).                                  */
6 /*                                                                         */
7 /*  Copyright 1996-2000 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 <freetype/ftoutln.h>
27 #include <freetype/internal/ftobjs.h>
28
29
30   /*************************************************************************/
31   /*                                                                       */
32   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
33   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
34   /* messages during execution.                                            */
35   /*                                                                       */
36 #undef  FT_COMPONENT
37 #define FT_COMPONENT  trace_outline
38
39
40   static
41   const FT_Outline  null_outline = { 0, 0, 0, 0, 0, 0 };
42
43
44   /*************************************************************************/
45   /*                                                                       */
46   /* <Function>                                                            */
47   /*    FT_Outline_Decompose                                               */
48   /*                                                                       */
49   /* <Description>                                                         */
50   /*    Walks over an outline's structure to decompose it into individual  */
51   /*    segments and Bezier arcs.  This function is also able to emit      */
52   /*    `move to' and `close to' operations to indicate the start and end  */
53   /*    of new contours in the outline.                                    */
54   /*                                                                       */
55   /* <Input>                                                               */
56   /*    outline   :: A pointer to the source target.                       */
57   /*                                                                       */
58   /*    interface :: A table of `emitters', i.e,. function pointers called */
59   /*                 during decomposition to indicate path operations.     */
60   /*                                                                       */
61   /*    user      :: A typeless pointer which is passed to each emitter    */
62   /*                 during the decomposition.  It can be used to store    */
63   /*                 the state during the decomposition.                   */
64   /*                                                                       */
65   /* <Return>                                                              */
66   /*    FreeType error code.  0 means sucess.                              */
67   /*                                                                       */
68   FT_EXPORT_FUNC( FT_Error )  FT_Outline_Decompose(
69                                 FT_Outline*        outline,
70                                 FT_Outline_Funcs*  interface,
71                                 void*              user )
72   {
73 #undef SCALED
74 #define SCALED( x )  ( ( (x) << shift ) - delta )
75
76     FT_Vector   v_last;
77     FT_Vector   v_control;
78     FT_Vector   v_start;
79
80     FT_Vector*  point;
81     FT_Vector*  limit;
82     char*       tags;
83
84     FT_Error    error;
85
86     FT_Int   n;         /* index of contour in outline     */
87     FT_UInt  first;     /* index of first point in contour */
88     char     tag;       /* current point's state           */
89
90     FT_Int   shift;
91     FT_Pos   delta;
92
93
94     if ( !outline || !interface )
95       return FT_Err_Invalid_Argument;
96
97     shift = interface->shift;
98     delta = interface->delta;
99     first = 0;
100
101     for ( n = 0; n < outline->n_contours; n++ )
102     {
103       FT_Int  last;  /* index of last point in contour */
104
105
106       last  = outline->contours[n];
107       limit = outline->points + last;
108
109       v_start = outline->points[first];
110       v_last  = outline->points[last];
111
112       v_start.x = SCALED( v_start.x ); v_start.y = SCALED( v_start.y );
113       v_last.x  = SCALED( v_last.x );  v_last.y  = SCALED( v_last.y );
114
115       v_control = v_start;
116
117       point = outline->points + first;
118       tags  = outline->tags  + first;
119       tag   = FT_CURVE_TAG( tags[0] );
120
121       /* A contour cannot start with a cubic control point! */
122       if ( tag == FT_Curve_Tag_Cubic )
123         goto Invalid_Outline;
124
125       /* check first point to determine origin */
126       if ( tag == FT_Curve_Tag_Conic )
127       {
128         /* first point is conic control.  Yes, this happens. */
129         if ( FT_CURVE_TAG( outline->tags[last] ) == FT_Curve_Tag_On )
130         {
131           /* start at last point if it is on the curve */
132           v_start = v_last;
133           limit--;
134         }
135         else
136         {
137           /* if both first and last points are conic,         */
138           /* start at their middle and record its position    */
139           /* for closure                                      */
140           v_start.x = ( v_start.x + v_last.x ) / 2;
141           v_start.y = ( v_start.y + v_last.y ) / 2;
142
143           v_last = v_start;
144         }
145         point--;
146         tags--;
147       }
148
149       error = interface->move_to( &v_start, user );
150       if ( error )
151         goto Exit;
152
153       while ( point < limit )
154       {
155         point++;
156         tags++;
157
158         tag = FT_CURVE_TAG( tags[0] );
159         switch ( tag )
160         {
161         case FT_Curve_Tag_On:  /* emit a single line_to */
162           {
163             FT_Vector  vec;
164
165
166             vec.x = SCALED( point->x );
167             vec.y = SCALED( point->y );
168
169             error = interface->line_to( &vec, user );
170             if ( error )
171               goto Exit;
172             continue;
173           }
174
175         case FT_Curve_Tag_Conic:  /* consume conic arcs */
176           v_control.x = SCALED( point->x );
177           v_control.y = SCALED( point->y );
178
179         Do_Conic:
180           if ( point < limit )
181           {
182             FT_Vector  vec;
183             FT_Vector  v_middle;
184
185
186             point++;
187             tags++;
188             tag = FT_CURVE_TAG( tags[0] );
189
190             vec.x = SCALED( point->x );
191             vec.y = SCALED( point->y );
192
193             if ( tag == FT_Curve_Tag_On )
194             {
195               error = interface->conic_to( &v_control, &vec, user );
196               if ( error )
197                 goto Exit;
198               continue;
199             }
200
201             if ( tag != FT_Curve_Tag_Conic )
202               goto Invalid_Outline;
203
204             v_middle.x = ( v_control.x + vec.x ) / 2;
205             v_middle.y = ( v_control.y + vec.y ) / 2;
206
207             error = interface->conic_to( &v_control, &v_middle, user );
208             if ( error )
209               goto Exit;
210
211             v_control = vec;
212             goto Do_Conic;
213           }
214
215           error = interface->conic_to( &v_control, &v_start, user );
216           goto Close;
217
218         default:  /* FT_Curve_Tag_Cubic */
219           {
220             FT_Vector  vec1, vec2;
221
222
223             if ( point + 1 > limit                             ||
224                  FT_CURVE_TAG( tags[1] ) != FT_Curve_Tag_Cubic )
225               goto Invalid_Outline;
226
227             point += 2;
228             tags  += 2;
229
230             vec1.x = SCALED( point[-2].x ); vec1.y = SCALED( point[-2].y );
231             vec2.x = SCALED( point[-1].x ); vec2.y = SCALED( point[-1].y );
232
233             if ( point <= limit )
234             {
235               FT_Vector  vec;
236
237
238               vec.x = SCALED( point->x );
239               vec.y = SCALED( point->y );
240
241               error = interface->cubic_to( &vec1, &vec2, &vec, user );
242               if ( error )
243                 goto Exit;
244               continue;
245             }
246
247             error = interface->cubic_to( &vec1, &vec2, &v_start, user );
248             goto Close;
249           }
250         }
251       }
252
253       /* close the contour with a line segment */
254       error = interface->line_to( &v_start, user );
255
256     Close:
257       if ( error )
258         goto Exit;
259
260       first = last + 1;
261     }
262
263     return 0;
264
265   Exit:
266     return error;
267
268   Invalid_Outline:
269     return FT_Err_Invalid_Outline;
270   }
271
272
273   FT_EXPORT_FUNC( FT_Error )  FT_Outline_New_Internal(
274                                 FT_Memory    memory,
275                                 FT_UInt      numPoints,
276                                 FT_Int       numContours,
277                                 FT_Outline*  outline )
278   {
279     FT_Error  error;
280
281
282     if ( !outline || !memory )
283       return FT_Err_Invalid_Argument;
284
285     *outline = null_outline;
286
287     if ( ALLOC_ARRAY( outline->points,   numPoints * 2L, FT_Pos    ) ||
288          ALLOC_ARRAY( outline->tags,     numPoints,      FT_Byte   ) ||
289          ALLOC_ARRAY( outline->contours, numContours,    FT_UShort ) )
290       goto Fail;
291
292     outline->n_points    = (FT_UShort)numPoints;
293     outline->n_contours  = (FT_Short)numContours;
294     outline->flags      |= ft_outline_owner;
295
296     return FT_Err_Ok;
297
298   Fail:
299     outline->flags |= ft_outline_owner;
300     FT_Outline_Done_Internal( memory, outline );
301
302     return error;
303   }
304
305
306   /*************************************************************************/
307   /*                                                                       */
308   /* <Function>                                                            */
309   /*    FT_Outline_New                                                     */
310   /*                                                                       */
311   /* <Description>                                                         */
312   /*    Creates a new outline of a given size.                             */
313   /*                                                                       */
314   /* <Input>                                                               */
315   /*    library     :: A handle to the library object from where the       */
316   /*                   outline is allocated.  Note however that the new    */
317   /*                   outline will NOT necessarily be FREED, when         */
318   /*                   destroying the library, by FT_Done_FreeType().      */
319   /*                                                                       */
320   /*    numPoints   :: The maximal number of points within the outline.    */
321   /*                                                                       */
322   /*    numContours :: The maximal number of contours within the outline.  */
323   /*                                                                       */
324   /* <Output>                                                              */
325   /*    outline     :: A handle to the new outline.  NULL in case of       */
326   /*                   error.                                              */
327   /*                                                                       */
328   /* <Return>                                                              */
329   /*    FreeType error code.  0 means success.                             */
330   /*                                                                       */
331   /* <MT-Note>                                                             */
332   /*    No.                                                                */
333   /*                                                                       */
334   /* <Note>                                                                */
335   /*    The reason why this function takes a `library' parameter is simply */
336   /*    to use the library's memory allocator.                             */
337   /*                                                                       */
338   FT_EXPORT_FUNC( FT_Error )  FT_Outline_New( FT_Library   library,
339                                               FT_UInt      numPoints,
340                                               FT_Int       numContours,
341                                               FT_Outline*  outline )
342   {
343     if ( !library )
344       return FT_Err_Invalid_Library_Handle;
345
346     return FT_Outline_New_Internal( library->memory, numPoints,
347                                     numContours, outline );
348   }
349
350
351   /*************************************************************************/
352   /*                                                                       */
353   /* <Function>                                                            */
354   /*    FT_Outline_Copy                                                    */
355   /*                                                                       */
356   /* <Description>                                                         */
357   /*    Copies an outline into another one.  Both objects must have the    */
358   /*    same sizes (number of points & number of contours) when this       */
359   /*    function is called.                                                */
360   /*                                                                       */
361   /* <Input>                                                               */
362   /*    source :: A handle to the source outline.                          */
363   /*                                                                       */
364   /* <Output>                                                              */
365   /*    target :: A handle to the target outline.                          */
366   /*                                                                       */
367   /* <Return>                                                              */
368   /*    FreeType error code.  0 means success.                             */
369   /*                                                                       */
370   FT_EXPORT_FUNC( FT_Error )  FT_Outline_Copy( FT_Outline*  source,
371                                                FT_Outline*  target )
372   {
373     FT_Int  is_owner;
374
375
376     if ( !source            || !target            ||
377          source->n_points   != target->n_points   ||
378          source->n_contours != target->n_contours )
379       return FT_Err_Invalid_Argument;
380
381     MEM_Copy( target->points, source->points,
382               source->n_points * sizeof ( FT_Vector ) );
383
384     MEM_Copy( target->tags, source->tags,
385               source->n_points * sizeof ( FT_Byte ) );
386
387     MEM_Copy( target->contours, source->contours,
388               source->n_contours * sizeof ( FT_Short ) );
389
390     /* copy all flags, except the `ft_outline_owner' one */
391     is_owner      = target->flags & ft_outline_owner;
392     target->flags = source->flags;
393
394     target->flags &= ~ft_outline_owner;
395     target->flags |= is_owner;
396
397     return FT_Err_Ok;
398   }
399
400
401   FT_EXPORT_FUNC( FT_Error )  FT_Outline_Done_Internal( FT_Memory    memory,
402                                                         FT_Outline*  outline )
403   {
404     if ( outline )
405     {
406       if ( outline->flags & ft_outline_owner )
407       {
408         FREE( outline->points   );
409         FREE( outline->tags     );
410         FREE( outline->contours );
411       }
412       *outline = null_outline;
413
414       return FT_Err_Ok;
415     }
416     else
417       return FT_Err_Invalid_Argument;
418   }
419
420
421   /*************************************************************************/
422   /*                                                                       */
423   /* <Function>                                                            */
424   /*    FT_Outline_Done                                                    */
425   /*                                                                       */
426   /* <Description>                                                         */
427   /*    Destroys an outline created with FT_Outline_New().                 */
428   /*                                                                       */
429   /* <Input>                                                               */
430   /*    library :: A handle of the library object used to allocate the     */
431   /*               outline.                                                */
432   /*                                                                       */
433   /*    outline :: A pointer to the outline object to be discarded.        */
434   /*                                                                       */
435   /* <Return>                                                              */
436   /*    FreeType error code.  0 means success.                             */
437   /*                                                                       */
438   /* <MT-Note>                                                             */
439   /*    No.                                                                */
440   /*                                                                       */
441   /* <Note>                                                                */
442   /*    If the outline's `owner' field is not set, only the outline        */
443   /*    descriptor will be released.                                       */
444   /*                                                                       */
445   /*    The reason why this function takes an `outline' parameter is       */
446   /*    simply to use FT_Free().                                           */
447   /*                                                                       */
448   FT_EXPORT_FUNC( FT_Error )  FT_Outline_Done( FT_Library   library,
449                                                FT_Outline*  outline )
450   {
451     /* check for valid `outline' in FT_Outline_Done_Internal() */
452
453     if ( !library )
454       return FT_Err_Invalid_Library_Handle;
455
456     return FT_Outline_Done_Internal( library->memory, outline );
457   }
458
459
460   /*************************************************************************/
461   /*                                                                       */
462   /* <Function>                                                            */
463   /*    FT_Outline_Get_CBox                                                */
464   /*                                                                       */
465   /* <Description>                                                         */
466   /*    Returns an outline's `control box'.  The control box encloses all  */
467   /*    the outline's points, including Bezier control points.  Though it  */
468   /*    coincides with the exact bounding box for most glyphs, it can be   */
469   /*    slightly larger in some situations (like when rotating an outline  */
470   /*    which contains Bezier outside arcs).                               */
471   /*                                                                       */
472   /*    Computing the control box is very fast, while getting the bounding */
473   /*    box can take much more time as it needs to walk over all segments  */
474   /*    and arcs in the outline.  To get the latter, you can use the       */
475   /*    `ftbbox' component which is dedicated to this single task.         */
476   /*                                                                       */
477   /* <Input>                                                               */
478   /*    outline :: A pointer to the source outline descriptor.             */
479   /*                                                                       */
480   /* <Output>                                                              */
481   /*    cbox    :: The outline's control box.                              */
482   /*                                                                       */
483   /* <MT-Note>                                                             */
484   /*    Yes.                                                               */
485   /*                                                                       */
486   FT_EXPORT_FUNC( void )  FT_Outline_Get_CBox( FT_Outline*  outline,
487                                                FT_BBox*     cbox )
488   {
489     FT_Pos  xMin, yMin, xMax, yMax;
490
491
492     if ( outline && cbox )
493     {
494       if ( outline->n_points == 0 )
495       {
496         xMin = 0;
497         yMin = 0;
498         xMax = 0;
499         yMax = 0;
500       }
501       else
502       {
503         FT_Vector*  vec   = outline->points;
504         FT_Vector*  limit = vec + outline->n_points;
505
506
507         xMin = xMax = vec->x;
508         yMin = yMax = vec->y;
509         vec++;
510
511         for ( ; vec < limit; vec++ )
512         {
513           FT_Pos  x, y;
514
515
516           x = vec->x;
517           if ( x < xMin ) xMin = x;
518           if ( x > xMax ) xMax = x;
519
520           y = vec->y;
521           if ( y < yMin ) yMin = y;
522           if ( y > yMax ) yMax = y;
523         }
524       }
525       cbox->xMin = xMin;
526       cbox->xMax = xMax;
527       cbox->yMin = yMin;
528       cbox->yMax = yMax;
529     }
530   }
531
532
533   /*************************************************************************/
534   /*                                                                       */
535   /* <Function>                                                            */
536   /*    FT_Outline_Translate                                               */
537   /*                                                                       */
538   /* <Description>                                                         */
539   /*    Applies a simple translation to the points of an outline.          */
540   /*                                                                       */
541   /* <Input>                                                               */
542   /*    outline :: A pointer to the target outline descriptor.             */
543   /*                                                                       */
544   /*    xOffset :: The horizontal offset.                                  */
545   /*                                                                       */
546   /*    yOffset :: The vertical offset.                                    */
547   /*                                                                       */
548   /* <MT-Note>                                                             */
549   /*    Yes.                                                               */
550   /*                                                                       */
551   FT_EXPORT_FUNC( void )  FT_Outline_Translate( FT_Outline*  outline,
552                                                 FT_Pos       xOffset,
553                                                 FT_Pos       yOffset )
554   {
555     FT_UShort   n;
556     FT_Vector*  vec = outline->points;
557
558
559     for ( n = 0; n < outline->n_points; n++ )
560     {
561       vec->x += xOffset;
562       vec->y += yOffset;
563       vec++;
564     }
565   }
566
567
568   /*************************************************************************/
569   /*                                                                       */
570   /* <Function>                                                            */
571   /*    FT_Outline_Reverse                                                 */
572   /*                                                                       */
573   /* <Description>                                                         */
574   /*    Reverses the drawing direction of an outline.  This is used to     */
575   /*    ensure consistent fill conventions for mirrored glyphs.            */
576   /*                                                                       */
577   /* <Input>                                                               */
578   /*    outline :: A pointer to the target outline descriptor.             */
579   /*                                                                       */
580   /* <Note>                                                                */
581   /*    This functions toggles the bit flag `ft_outline_reverse_fill' in   */
582   /*    the outline's `flags' field.                                       */
583   /*                                                                       */
584   FT_EXPORT_FUNC( void )  FT_Outline_Reverse( FT_Outline*  outline )
585   {
586     FT_UShort  n;
587     FT_Int     first, last;
588
589
590     first = 0;
591
592     for ( n = 0; n < outline->n_contours; n++ )
593     {
594       last  = outline->contours[n];
595
596       /* reverse point table */
597       {
598         FT_Vector*  p = outline->points + first;
599         FT_Vector*  q = outline->points + last;
600         FT_Vector   swap;
601
602
603         while ( p < q )
604         {
605           swap = *p;
606           *p   = *q;
607           *q   = swap;
608           p++;
609           q--;
610         }
611       }
612
613       /* reverse tags table */
614       {
615         char*  p = outline->tags + first;
616         char*  q = outline->tags + last;
617         char   swap;
618
619
620         while ( p < q )
621         {
622           swap = *p;
623           *p   = *q;
624           *q   = swap;
625           p++;
626           q--;
627         }
628       }
629
630       first = last + 1;
631     }
632
633     outline->flags ^= ft_outline_reverse_fill;
634   }
635
636
637   /*************************************************************************/
638   /*                                                                       */
639   /* <Function>                                                            */
640   /*    FT_Outline_Render                                                  */
641   /*                                                                       */
642   /* <Description>                                                         */
643   /*    Renders an outline within a bitmap using the current scan-convert. */
644   /*    This functions uses an FT_Raster_Params structure as an argument,  */
645   /*    allowing advanced features like direct composition, translucency,  */
646   /*    etc.                                                               */
647   /*                                                                       */
648   /* <Input>                                                               */
649   /*    library :: A handle to a FreeType library object.                  */
650   /*                                                                       */
651   /*    outline :: A pointer to the source outline descriptor.             */
652   /*                                                                       */
653   /*    params  :: A pointer to a FT_Raster_Params structure used to       */
654   /*               describe the rendering operation.                       */
655   /*                                                                       */
656   /* <Return>                                                              */
657   /*    FreeType error code.  0 means success.                             */
658   /*                                                                       */
659   /* <MT-Note>                                                             */
660   /*    YES.  Rendering is synchronized, so that concurrent calls to the   */
661   /*    scan-line converter will be serialized.                            */
662   /*                                                                       */
663   /* <Note>                                                                */
664   /*    You should know what you are doing and how FT_Raster_Params works  */
665   /*    to use this function.                                              */
666   /*                                                                       */
667   /*    The field `params.source' will be set to `outline' before the scan */
668   /*    converter is called, which means that the value you give to it is  */
669   /*    actually ignored.                                                  */
670   /*                                                                       */
671   FT_EXPORT_FUNC( FT_Error )  FT_Outline_Render( FT_Library         library,
672                                                  FT_Outline*        outline,
673                                                  FT_Raster_Params*  params )
674   {
675     FT_Error     error;
676     FT_Bool      update = 0;
677     FT_Renderer  renderer;
678     FT_ListNode  node;
679
680
681     if ( !library )
682       return FT_Err_Invalid_Library_Handle;
683
684     if ( !params )
685       return FT_Err_Invalid_Argument;
686
687     renderer = library->cur_renderer;
688     node     = library->renderers.head;
689
690     params->source = (void*)outline;
691
692     error = FT_Err_Cannot_Render_Glyph;
693     while ( renderer )
694     {
695       error = renderer->raster_render( renderer->raster, params );
696       if ( !error || error != FT_Err_Cannot_Render_Glyph )
697         break;
698
699       /* FT_Err_Cannot_Render_Glyph is returned if the render mode   */
700       /* is unsupported by the current renderer for this glyph image */
701       /* format                                                      */
702
703       /* now, look for another renderer that supports the same */
704       /* format                                                */
705       renderer = FT_Lookup_Renderer( library, ft_glyph_format_outline,
706                                      &node );
707       update   = 1;
708     }
709
710     /* if we changed the current renderer for the glyph image format */
711     /* we need to select it as the next current one                  */
712     if ( !error && update && renderer )
713       FT_Set_Renderer( library, renderer, 0, 0 );
714
715     return error;
716   }
717
718
719   /*************************************************************************/
720   /*                                                                       */
721   /* <Function>                                                            */
722   /*    FT_Outline_Get_Bitmap                                              */
723   /*                                                                       */
724   /* <Description>                                                         */
725   /*    Renders an outline within a bitmap.  The outline's image is simply */
726   /*    OR-ed to the target bitmap.                                        */
727   /*                                                                       */
728   /* <Input>                                                               */
729   /*    library :: A handle to a FreeType library object.                  */
730   /*                                                                       */
731   /*    outline :: A pointer to the source outline descriptor.             */
732   /*                                                                       */
733   /*    map     :: A pointer to the target bitmap descriptor.              */
734   /*                                                                       */
735   /* <Return>                                                              */
736   /*    FreeType error code.  0 means success.                             */
737   /*                                                                       */
738   /* <MT-Note>                                                             */
739   /*    YES.  Rendering is synchronized, so that concurrent calls to the   */
740   /*    scan-line converter will be serialized.                            */
741   /*                                                                       */
742   /* <Note>                                                                */
743   /*    This function does NOT CREATE the bitmap, it only renders an       */
744   /*    outline image within the one you pass to it!                       */
745   /*                                                                       */
746   /*    It will use the raster correponding to the default glyph format.   */
747   /*                                                                       */
748   FT_EXPORT_FUNC( FT_Error )  FT_Outline_Get_Bitmap( FT_Library   library,
749                                                      FT_Outline*  outline,
750                                                      FT_Bitmap*   bitmap )
751   {
752     FT_Raster_Params  params;
753
754
755     if ( !bitmap )
756       return FT_Err_Invalid_Argument;
757
758     /* other checks are delayed to FT_Outline_Render() */
759
760     params.target = bitmap;
761     params.flags  = 0;
762
763     if ( bitmap->pixel_mode == ft_pixel_mode_grays )
764       params.flags |= ft_raster_flag_aa;
765
766     return FT_Outline_Render( library, outline, &params );
767   }
768
769
770   /*************************************************************************/
771   /*                                                                       */
772   /* <Function>                                                            */
773   /*    FT_Vector_Transform                                                */
774   /*                                                                       */
775   /* <Description>                                                         */
776   /*    Transforms a single vector through a 2x2 matrix.                   */
777   /*                                                                       */
778   /* <InOut>                                                               */
779   /*    vector :: The target vector to transform.                          */
780   /*                                                                       */
781   /* <Input>                                                               */
782   /*    matrix :: A pointer to the source 2x2 matrix.                      */
783   /*                                                                       */
784   /* <MT-Note>                                                             */
785   /*    Yes.                                                               */
786   /*                                                                       */
787   /* <Note>                                                                */
788   /*    The result is undefined if either `vector' or `matrix' is invalid. */
789   /*                                                                       */
790   FT_EXPORT_FUNC( void )  FT_Vector_Transform( FT_Vector*  vector,
791                                                FT_Matrix*  matrix )
792   {
793     FT_Pos xz, yz;
794
795
796     if ( !vector || !matrix )
797       return;
798
799     xz = FT_MulFix( vector->x, matrix->xx ) +
800          FT_MulFix( vector->y, matrix->xy );
801
802     yz = FT_MulFix( vector->x, matrix->yx ) +
803          FT_MulFix( vector->y, matrix->yy );
804
805     vector->x = xz;
806     vector->y = yz;
807   }
808
809
810   /*************************************************************************/
811   /*                                                                       */
812   /* <Function>                                                            */
813   /*    FT_Outline_Transform                                               */
814   /*                                                                       */
815   /* <Description>                                                         */
816   /*    Applies a simple 2x2 matrix to all of an outline's points.  Useful */
817   /*    for applying rotations, slanting, flipping, etc.                   */
818   /*                                                                       */
819   /* <Input>                                                               */
820   /*    outline :: A pointer to the target outline descriptor.             */
821   /*                                                                       */
822   /*    matrix  :: A pointer to the transformation matrix.                 */
823   /*                                                                       */
824   /* <MT-Note>                                                             */
825   /*    Yes.                                                               */
826   /*                                                                       */
827   /* <Note>                                                                */
828   /*    You can use FT_Outline_Translate() if you need to translate the    */
829   /*    outline's points.                                                  */
830   /*                                                                       */
831   FT_EXPORT_FUNC( void )  FT_Outline_Transform( FT_Outline*  outline,
832                                                 FT_Matrix*   matrix )
833   {
834     FT_Vector*  vec = outline->points;
835     FT_Vector*  limit = vec + outline->n_points;
836
837
838     for ( ; vec < limit; vec++ )
839       FT_Vector_Transform( vec, matrix );
840   }
841
842 /* END */