1 /***************************************************************************/
5 /* FreeType outline management (body). */
7 /* Copyright 1996-2008, 2010, 2012-2014 by */
8 /* David Turner, Robert Wilhelm, and Werner Lemberg. */
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. */
16 /***************************************************************************/
19 /*************************************************************************/
21 /* All functions are declared in freetype.h. */
23 /*************************************************************************/
28 #include FT_INTERNAL_OBJECTS_H
29 #include FT_INTERNAL_CALC_H
30 #include FT_INTERNAL_DEBUG_H
31 #include FT_TRIGONOMETRY_H
34 /*************************************************************************/
36 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
37 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
38 /* messages during execution. */
41 #define FT_COMPONENT trace_outline
45 const FT_Outline null_outline
= { 0, 0, 0, 0, 0, 0 };
48 /* documentation is in ftoutln.h */
50 FT_EXPORT_DEF( FT_Error
)
51 FT_Outline_Decompose( FT_Outline
* outline
,
52 const FT_Outline_Funcs
* func_interface
,
56 #define SCALED( x ) ( ( (x) << shift ) - delta )
68 FT_Int n
; /* index of contour in outline */
69 FT_UInt first
; /* index of first point in contour */
70 FT_Int tag
; /* current point's state */
76 if ( !outline
|| !func_interface
)
77 return FT_THROW( Invalid_Argument
);
79 shift
= func_interface
->shift
;
80 delta
= func_interface
->delta
;
83 for ( n
= 0; n
< outline
->n_contours
; n
++ )
85 FT_Int last
; /* index of last point in contour */
88 FT_TRACE5(( "FT_Outline_Decompose: Outline %d\n", n
));
90 last
= outline
->contours
[n
];
93 limit
= outline
->points
+ last
;
95 v_start
= outline
->points
[first
];
96 v_start
.x
= SCALED( v_start
.x
);
97 v_start
.y
= SCALED( v_start
.y
);
99 v_last
= outline
->points
[last
];
100 v_last
.x
= SCALED( v_last
.x
);
101 v_last
.y
= SCALED( v_last
.y
);
105 point
= outline
->points
+ first
;
106 tags
= outline
->tags
+ first
;
107 tag
= FT_CURVE_TAG( tags
[0] );
109 /* A contour cannot start with a cubic control point! */
110 if ( tag
== FT_CURVE_TAG_CUBIC
)
111 goto Invalid_Outline
;
113 /* check first point to determine origin */
114 if ( tag
== FT_CURVE_TAG_CONIC
)
116 /* first point is conic control. Yes, this happens. */
117 if ( FT_CURVE_TAG( outline
->tags
[last
] ) == FT_CURVE_TAG_ON
)
119 /* start at last point if it is on the curve */
125 /* if both first and last points are conic, */
126 /* start at their middle and record its position */
128 v_start
.x
= ( v_start
.x
+ v_last
.x
) / 2;
129 v_start
.y
= ( v_start
.y
+ v_last
.y
) / 2;
131 /* v_last = v_start; */
137 FT_TRACE5(( " move to (%.2f, %.2f)\n",
138 v_start
.x
/ 64.0, v_start
.y
/ 64.0 ));
139 error
= func_interface
->move_to( &v_start
, user
);
143 while ( point
< limit
)
148 tag
= FT_CURVE_TAG( tags
[0] );
151 case FT_CURVE_TAG_ON
: /* emit a single line_to */
156 vec
.x
= SCALED( point
->x
);
157 vec
.y
= SCALED( point
->y
);
159 FT_TRACE5(( " line to (%.2f, %.2f)\n",
160 vec
.x
/ 64.0, vec
.y
/ 64.0 ));
161 error
= func_interface
->line_to( &vec
, user
);
167 case FT_CURVE_TAG_CONIC
: /* consume conic arcs */
168 v_control
.x
= SCALED( point
->x
);
169 v_control
.y
= SCALED( point
->y
);
180 tag
= FT_CURVE_TAG( tags
[0] );
182 vec
.x
= SCALED( point
->x
);
183 vec
.y
= SCALED( point
->y
);
185 if ( tag
== FT_CURVE_TAG_ON
)
187 FT_TRACE5(( " conic to (%.2f, %.2f)"
188 " with control (%.2f, %.2f)\n",
189 vec
.x
/ 64.0, vec
.y
/ 64.0,
190 v_control
.x
/ 64.0, v_control
.y
/ 64.0 ));
191 error
= func_interface
->conic_to( &v_control
, &vec
, user
);
197 if ( tag
!= FT_CURVE_TAG_CONIC
)
198 goto Invalid_Outline
;
200 v_middle
.x
= ( v_control
.x
+ vec
.x
) / 2;
201 v_middle
.y
= ( v_control
.y
+ vec
.y
) / 2;
203 FT_TRACE5(( " conic to (%.2f, %.2f)"
204 " with control (%.2f, %.2f)\n",
205 v_middle
.x
/ 64.0, v_middle
.y
/ 64.0,
206 v_control
.x
/ 64.0, v_control
.y
/ 64.0 ));
207 error
= func_interface
->conic_to( &v_control
, &v_middle
, user
);
215 FT_TRACE5(( " conic to (%.2f, %.2f)"
216 " with control (%.2f, %.2f)\n",
217 v_start
.x
/ 64.0, v_start
.y
/ 64.0,
218 v_control
.x
/ 64.0, v_control
.y
/ 64.0 ));
219 error
= func_interface
->conic_to( &v_control
, &v_start
, user
);
222 default: /* FT_CURVE_TAG_CUBIC */
224 FT_Vector vec1
, vec2
;
227 if ( point
+ 1 > limit
||
228 FT_CURVE_TAG( tags
[1] ) != FT_CURVE_TAG_CUBIC
)
229 goto Invalid_Outline
;
234 vec1
.x
= SCALED( point
[-2].x
);
235 vec1
.y
= SCALED( point
[-2].y
);
237 vec2
.x
= SCALED( point
[-1].x
);
238 vec2
.y
= SCALED( point
[-1].y
);
240 if ( point
<= limit
)
245 vec
.x
= SCALED( point
->x
);
246 vec
.y
= SCALED( point
->y
);
248 FT_TRACE5(( " cubic to (%.2f, %.2f)"
249 " with controls (%.2f, %.2f) and (%.2f, %.2f)\n",
250 vec
.x
/ 64.0, vec
.y
/ 64.0,
251 vec1
.x
/ 64.0, vec1
.y
/ 64.0,
252 vec2
.x
/ 64.0, vec2
.y
/ 64.0 ));
253 error
= func_interface
->cubic_to( &vec1
, &vec2
, &vec
, user
);
259 FT_TRACE5(( " cubic to (%.2f, %.2f)"
260 " with controls (%.2f, %.2f) and (%.2f, %.2f)\n",
261 v_start
.x
/ 64.0, v_start
.y
/ 64.0,
262 vec1
.x
/ 64.0, vec1
.y
/ 64.0,
263 vec2
.x
/ 64.0, vec2
.y
/ 64.0 ));
264 error
= func_interface
->cubic_to( &vec1
, &vec2
, &v_start
, user
);
270 /* close the contour with a line segment */
271 FT_TRACE5(( " line to (%.2f, %.2f)\n",
272 v_start
.x
/ 64.0, v_start
.y
/ 64.0 ));
273 error
= func_interface
->line_to( &v_start
, user
);
282 FT_TRACE5(( "FT_Outline_Decompose: Done\n", n
));
286 FT_TRACE5(( "FT_Outline_Decompose: Error %d\n", error
));
290 return FT_THROW( Invalid_Outline
);
294 FT_EXPORT_DEF( FT_Error
)
295 FT_Outline_New_Internal( FT_Memory memory
,
298 FT_Outline
*anoutline
)
303 if ( !anoutline
|| !memory
)
304 return FT_THROW( Invalid_Argument
);
306 *anoutline
= null_outline
;
308 if ( numContours
< 0 ||
309 (FT_UInt
)numContours
> numPoints
)
310 return FT_THROW( Invalid_Argument
);
312 if ( numPoints
> FT_OUTLINE_POINTS_MAX
)
313 return FT_THROW( Array_Too_Large
);
315 if ( FT_NEW_ARRAY( anoutline
->points
, numPoints
) ||
316 FT_NEW_ARRAY( anoutline
->tags
, numPoints
) ||
317 FT_NEW_ARRAY( anoutline
->contours
, numContours
) )
320 anoutline
->n_points
= (FT_UShort
)numPoints
;
321 anoutline
->n_contours
= (FT_Short
)numContours
;
322 anoutline
->flags
|= FT_OUTLINE_OWNER
;
327 anoutline
->flags
|= FT_OUTLINE_OWNER
;
328 FT_Outline_Done_Internal( memory
, anoutline
);
334 /* documentation is in ftoutln.h */
336 FT_EXPORT_DEF( FT_Error
)
337 FT_Outline_New( FT_Library library
,
340 FT_Outline
*anoutline
)
343 return FT_THROW( Invalid_Library_Handle
);
345 return FT_Outline_New_Internal( library
->memory
, numPoints
,
346 numContours
, anoutline
);
350 /* documentation is in ftoutln.h */
352 FT_EXPORT_DEF( FT_Error
)
353 FT_Outline_Check( FT_Outline
* outline
)
357 FT_Int n_points
= outline
->n_points
;
358 FT_Int n_contours
= outline
->n_contours
;
364 if ( n_points
== 0 && n_contours
== 0 )
367 /* check point and contour counts */
368 if ( n_points
<= 0 || n_contours
<= 0 )
372 for ( n
= 0; n
< n_contours
; n
++ )
374 end
= outline
->contours
[n
];
376 /* note that we don't accept empty contours */
377 if ( end
<= end0
|| end
>= n_points
)
383 if ( end
!= n_points
- 1 )
386 /* XXX: check the tags array */
391 return FT_THROW( Invalid_Argument
);
395 /* documentation is in ftoutln.h */
397 FT_EXPORT_DEF( FT_Error
)
398 FT_Outline_Copy( const FT_Outline
* source
,
404 if ( !source
|| !target
||
405 source
->n_points
!= target
->n_points
||
406 source
->n_contours
!= target
->n_contours
)
407 return FT_THROW( Invalid_Argument
);
409 if ( source
== target
)
412 FT_ARRAY_COPY( target
->points
, source
->points
, source
->n_points
);
414 FT_ARRAY_COPY( target
->tags
, source
->tags
, source
->n_points
);
416 FT_ARRAY_COPY( target
->contours
, source
->contours
, source
->n_contours
);
418 /* copy all flags, except the `FT_OUTLINE_OWNER' one */
419 is_owner
= target
->flags
& FT_OUTLINE_OWNER
;
420 target
->flags
= source
->flags
;
422 target
->flags
&= ~FT_OUTLINE_OWNER
;
423 target
->flags
|= is_owner
;
429 FT_EXPORT_DEF( FT_Error
)
430 FT_Outline_Done_Internal( FT_Memory memory
,
431 FT_Outline
* outline
)
433 if ( memory
&& outline
)
435 if ( outline
->flags
& FT_OUTLINE_OWNER
)
437 FT_FREE( outline
->points
);
438 FT_FREE( outline
->tags
);
439 FT_FREE( outline
->contours
);
441 *outline
= null_outline
;
446 return FT_THROW( Invalid_Argument
);
450 /* documentation is in ftoutln.h */
452 FT_EXPORT_DEF( FT_Error
)
453 FT_Outline_Done( FT_Library library
,
454 FT_Outline
* outline
)
456 /* check for valid `outline' in FT_Outline_Done_Internal() */
459 return FT_THROW( Invalid_Library_Handle
);
461 return FT_Outline_Done_Internal( library
->memory
, outline
);
465 /* documentation is in ftoutln.h */
467 FT_EXPORT_DEF( void )
468 FT_Outline_Get_CBox( const FT_Outline
* outline
,
471 FT_Pos xMin
, yMin
, xMax
, yMax
;
474 if ( outline
&& acbox
)
476 if ( outline
->n_points
== 0 )
485 FT_Vector
* vec
= outline
->points
;
486 FT_Vector
* limit
= vec
+ outline
->n_points
;
489 xMin
= xMax
= vec
->x
;
490 yMin
= yMax
= vec
->y
;
493 for ( ; vec
< limit
; vec
++ )
499 if ( x
< xMin
) xMin
= x
;
500 if ( x
> xMax
) xMax
= x
;
503 if ( y
< yMin
) yMin
= y
;
504 if ( y
> yMax
) yMax
= y
;
515 /* documentation is in ftoutln.h */
517 FT_EXPORT_DEF( void )
518 FT_Outline_Translate( const FT_Outline
* outline
,
529 vec
= outline
->points
;
531 for ( n
= 0; n
< outline
->n_points
; n
++ )
540 /* documentation is in ftoutln.h */
542 FT_EXPORT_DEF( void )
543 FT_Outline_Reverse( FT_Outline
* outline
)
554 for ( n
= 0; n
< outline
->n_contours
; n
++ )
556 last
= outline
->contours
[n
];
558 /* reverse point table */
560 FT_Vector
* p
= outline
->points
+ first
;
561 FT_Vector
* q
= outline
->points
+ last
;
575 /* reverse tags table */
577 char* p
= outline
->tags
+ first
;
578 char* q
= outline
->tags
+ last
;
597 outline
->flags
^= FT_OUTLINE_REVERSE_FILL
;
601 /* documentation is in ftoutln.h */
603 FT_EXPORT_DEF( FT_Error
)
604 FT_Outline_Render( FT_Library library
,
606 FT_Raster_Params
* params
)
609 FT_Bool update
= FALSE
;
610 FT_Renderer renderer
;
615 return FT_THROW( Invalid_Library_Handle
);
617 if ( !outline
|| !params
)
618 return FT_THROW( Invalid_Argument
);
620 renderer
= library
->cur_renderer
;
621 node
= library
->renderers
.head
;
623 params
->source
= (void*)outline
;
625 error
= FT_ERR( Cannot_Render_Glyph
);
628 error
= renderer
->raster_render( renderer
->raster
, params
);
629 if ( !error
|| FT_ERR_NEQ( error
, Cannot_Render_Glyph
) )
632 /* FT_Err_Cannot_Render_Glyph is returned if the render mode */
633 /* is unsupported by the current renderer for this glyph image */
636 /* now, look for another renderer that supports the same */
638 renderer
= FT_Lookup_Renderer( library
, FT_GLYPH_FORMAT_OUTLINE
,
643 /* if we changed the current renderer for the glyph image format */
644 /* we need to select it as the next current one */
645 if ( !error
&& update
&& renderer
)
646 FT_Set_Renderer( library
, renderer
, 0, 0 );
652 /* documentation is in ftoutln.h */
654 FT_EXPORT_DEF( FT_Error
)
655 FT_Outline_Get_Bitmap( FT_Library library
,
657 const FT_Bitmap
*abitmap
)
659 FT_Raster_Params params
;
663 return FT_THROW( Invalid_Argument
);
665 /* other checks are delayed to FT_Outline_Render() */
667 params
.target
= abitmap
;
670 if ( abitmap
->pixel_mode
== FT_PIXEL_MODE_GRAY
||
671 abitmap
->pixel_mode
== FT_PIXEL_MODE_LCD
||
672 abitmap
->pixel_mode
== FT_PIXEL_MODE_LCD_V
)
673 params
.flags
|= FT_RASTER_FLAG_AA
;
675 return FT_Outline_Render( library
, outline
, ¶ms
);
679 /* documentation is in freetype.h */
681 FT_EXPORT_DEF( void )
682 FT_Vector_Transform( FT_Vector
* vector
,
683 const FT_Matrix
* matrix
)
688 if ( !vector
|| !matrix
)
691 xz
= FT_MulFix( vector
->x
, matrix
->xx
) +
692 FT_MulFix( vector
->y
, matrix
->xy
);
694 yz
= FT_MulFix( vector
->x
, matrix
->yx
) +
695 FT_MulFix( vector
->y
, matrix
->yy
);
702 /* documentation is in ftoutln.h */
704 FT_EXPORT_DEF( void )
705 FT_Outline_Transform( const FT_Outline
* outline
,
706 const FT_Matrix
* matrix
)
712 if ( !outline
|| !matrix
)
715 vec
= outline
->points
;
716 limit
= vec
+ outline
->n_points
;
718 for ( ; vec
< limit
; vec
++ )
719 FT_Vector_Transform( vec
, matrix
);
725 #define FT_OUTLINE_GET_CONTOUR( outline, c, first, last ) \
728 (first) = ( c > 0 ) ? (outline)->points + \
729 (outline)->contours[c - 1] + 1 \
730 : (outline)->points; \
731 (last) = (outline)->points + (outline)->contours[c]; \
735 /* Is a point in some contour? */
737 /* We treat every point of the contour as if it */
738 /* it were ON. That is, we allow false positives, */
739 /* but disallow false negatives. (XXX really?) */
741 ft_contour_has( FT_Outline
* outline
,
752 FT_OUTLINE_GET_CONTOUR( outline
, c
, first
, last
);
754 for ( a
= first
; a
<= last
; a
++ )
760 b
= ( a
== last
) ? first
: a
+ 1;
762 intersect
= ( a
->y
- point
->y
) ^ ( b
->y
- point
->y
);
764 /* a and b are on the same side */
765 if ( intersect
>= 0 )
767 if ( intersect
== 0 && a
->y
== point
->y
)
769 if ( ( a
->x
<= point
->x
&& b
->x
>= point
->x
) ||
770 ( a
->x
>= point
->x
&& b
->x
<= point
->x
) )
777 x
= a
->x
+ ( b
->x
- a
->x
) * (point
->y
- a
->y
) / ( b
->y
- a
->y
);
781 else if ( x
== point
->x
)
790 ft_contour_enclosed( FT_Outline
* outline
,
798 FT_OUTLINE_GET_CONTOUR( outline
, c
, first
, last
);
800 for ( i
= 0; i
< outline
->n_contours
; i
++ )
802 if ( i
!= c
&& ft_contour_has( outline
, i
, first
) )
807 for ( pt
= first
+ 1; pt
<= last
; pt
++ )
808 if ( !ft_contour_has( outline
, i
, pt
) )
819 /* This version differs from the public one in that each */
820 /* part (contour not enclosed in another contour) of the */
821 /* outline is checked for orientation. This is */
822 /* necessary for some buggy CJK fonts. */
823 static FT_Orientation
824 ft_outline_get_orientation( FT_Outline
* outline
)
829 FT_Orientation orient
= FT_ORIENTATION_NONE
;
832 first
= outline
->points
;
833 for ( i
= 0; i
< outline
->n_contours
; i
++, first
= last
+ 1 )
836 FT_Vector
* xmin_point
;
840 last
= outline
->points
+ outline
->contours
[i
];
842 /* skip degenerate contours */
843 if ( last
< first
+ 2 )
846 if ( ft_contour_enclosed( outline
, i
) )
852 for ( point
= first
+ 1; point
<= last
; point
++ )
854 if ( point
->x
< xmin
)
861 /* check the orientation of the contour */
868 prev
= ( xmin_point
== first
) ? last
: xmin_point
- 1;
869 next
= ( xmin_point
== last
) ? first
: xmin_point
+ 1;
871 if ( FT_Atan2( prev
->x
- xmin_point
->x
, prev
->y
- xmin_point
->y
) >
872 FT_Atan2( next
->x
- xmin_point
->x
, next
->y
- xmin_point
->y
) )
873 o
= FT_ORIENTATION_POSTSCRIPT
;
875 o
= FT_ORIENTATION_TRUETYPE
;
877 if ( orient
== FT_ORIENTATION_NONE
)
879 else if ( orient
!= o
)
880 return FT_ORIENTATION_NONE
;
890 /* documentation is in ftoutln.h */
892 FT_EXPORT_DEF( FT_Error
)
893 FT_Outline_Embolden( FT_Outline
* outline
,
896 return FT_Outline_EmboldenXY( outline
, strength
, strength
);
900 /* documentation is in ftoutln.h */
902 FT_EXPORT_DEF( FT_Error
)
903 FT_Outline_EmboldenXY( FT_Outline
* outline
,
908 FT_Vector v_prev
, v_first
, v_next
, v_cur
;
914 return FT_THROW( Invalid_Argument
);
918 if ( xstrength
== 0 && ystrength
== 0 )
921 orientation
= FT_Outline_Get_Orientation( outline
);
922 if ( orientation
== FT_ORIENTATION_NONE
)
924 if ( outline
->n_contours
)
925 return FT_THROW( Invalid_Argument
);
930 points
= outline
->points
;
933 for ( c
= 0; c
< outline
->n_contours
; c
++ )
935 FT_Vector in
, out
, shift
;
936 FT_Fixed l_in
, l_out
, l
, q
, d
;
937 int last
= outline
->contours
[c
];
940 v_first
= points
[first
];
941 v_prev
= points
[last
];
944 /* compute incoming normalized vector */
945 in
.x
= v_cur
.x
- v_prev
.x
;
946 in
.y
= v_cur
.y
- v_prev
.y
;
947 l_in
= FT_Vector_Length( &in
);
950 in
.x
= FT_DivFix( in
.x
, l_in
);
951 in
.y
= FT_DivFix( in
.y
, l_in
);
954 for ( n
= first
; n
<= last
; n
++ )
957 v_next
= points
[n
+ 1];
961 /* compute outgoing normalized vector */
962 out
.x
= v_next
.x
- v_cur
.x
;
963 out
.y
= v_next
.y
- v_cur
.y
;
964 l_out
= FT_Vector_Length( &out
);
967 out
.x
= FT_DivFix( out
.x
, l_out
);
968 out
.y
= FT_DivFix( out
.y
, l_out
);
971 d
= FT_MulFix( in
.x
, out
.x
) + FT_MulFix( in
.y
, out
.y
);
973 /* shift only if turn is less than ~160 degrees */
978 /* shift components are aligned along lateral bisector */
979 /* and directed according to the outline orientation. */
980 shift
.x
= in
.y
+ out
.y
;
981 shift
.y
= in
.x
+ out
.x
;
983 if ( orientation
== FT_ORIENTATION_TRUETYPE
)
988 /* restrict shift magnitude to better handle collapsing segments */
989 q
= FT_MulFix( out
.x
, in
.y
) - FT_MulFix( out
.y
, in
.x
);
990 if ( orientation
== FT_ORIENTATION_TRUETYPE
)
993 l
= FT_MIN( l_in
, l_out
);
995 /* non-strict inequalities avoid divide-by-zero when q == l == 0 */
996 if ( FT_MulFix( xstrength
, q
) <= FT_MulFix( d
, l
) )
997 shift
.x
= FT_MulDiv( shift
.x
, xstrength
, d
);
999 shift
.x
= FT_MulDiv( shift
.x
, l
, q
);
1002 if ( FT_MulFix( ystrength
, q
) <= FT_MulFix( d
, l
) )
1003 shift
.y
= FT_MulDiv( shift
.y
, ystrength
, d
);
1005 shift
.y
= FT_MulDiv( shift
.y
, l
, q
);
1008 shift
.x
= shift
.y
= 0;
1010 outline
->points
[n
].x
= v_cur
.x
+ xstrength
+ shift
.x
;
1011 outline
->points
[n
].y
= v_cur
.y
+ ystrength
+ shift
.y
;
1025 /* documentation is in ftoutln.h */
1027 FT_EXPORT_DEF( FT_Orientation
)
1028 FT_Outline_Get_Orientation( FT_Outline
* outline
)
1031 FT_Int xshift
, yshift
;
1033 FT_Vector v_prev
, v_cur
;
1038 if ( !outline
|| outline
->n_points
<= 0 )
1039 return FT_ORIENTATION_TRUETYPE
;
1041 /* We use the nonzero winding rule to find the orientation. */
1042 /* Since glyph outlines behave much more `regular' than arbitrary */
1043 /* cubic or quadratic curves, this test deals with the polygon */
1044 /* only which is spanned up by the control points. */
1046 FT_Outline_Get_CBox( outline
, &cbox
);
1048 xshift
= FT_MSB( FT_ABS( cbox
.xMax
) | FT_ABS( cbox
.xMin
) ) - 14;
1049 xshift
= FT_MAX( xshift
, 0 );
1051 yshift
= FT_MSB( cbox
.yMax
- cbox
.yMin
) - 14;
1052 yshift
= FT_MAX( yshift
, 0 );
1054 points
= outline
->points
;
1057 for ( c
= 0; c
< outline
->n_contours
; c
++ )
1059 FT_Int last
= outline
->contours
[c
];
1062 v_prev
= points
[last
];
1064 for ( n
= first
; n
<= last
; n
++ )
1067 area
+= ( ( v_cur
.y
- v_prev
.y
) >> yshift
) *
1068 ( ( v_cur
.x
+ v_prev
.x
) >> xshift
);
1076 return FT_ORIENTATION_POSTSCRIPT
;
1077 else if ( area
< 0 )
1078 return FT_ORIENTATION_TRUETYPE
;
1080 return FT_ORIENTATION_NONE
;