ReactOS 0.4.16-dev-2332-g4cba65d
ftstroke.c
Go to the documentation of this file.
1/****************************************************************************
2 *
3 * ftstroke.c
4 *
5 * FreeType path stroker (body).
6 *
7 * Copyright (C) 2002-2020 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#include <freetype/ftstroke.h>
20#include <freetype/fttrigon.h>
21#include <freetype/ftoutln.h>
25
26
27 /* declare an extern to access `ft_outline_glyph_class' globally */
28 /* allocated in `ftglyph.c' */
30
31
32 /* documentation is in ftstroke.h */
33
36 {
38
39
42 }
43
44
45 /* documentation is in ftstroke.h */
46
49 {
51
52
55 }
56
57
58 /*************************************************************************/
59 /*************************************************************************/
60 /***** *****/
61 /***** BEZIER COMPUTATIONS *****/
62 /***** *****/
63 /*************************************************************************/
64 /*************************************************************************/
65
66#define FT_SMALL_CONIC_THRESHOLD ( FT_ANGLE_PI / 6 )
67#define FT_SMALL_CUBIC_THRESHOLD ( FT_ANGLE_PI / 8 )
68
69#define FT_EPSILON 2
70
71#define FT_IS_SMALL( x ) ( (x) > -FT_EPSILON && (x) < FT_EPSILON )
72
73
74 static FT_Pos
76 {
77 return x >= 0 ? x : -x;
78 }
79
80
81 static void
83 {
84 FT_Pos a, b;
85
86
87 base[4].x = base[2].x;
88 a = base[0].x + base[1].x;
89 b = base[1].x + base[2].x;
90 base[3].x = b >> 1;
91 base[2].x = ( a + b ) >> 2;
92 base[1].x = a >> 1;
93
94 base[4].y = base[2].y;
95 a = base[0].y + base[1].y;
96 b = base[1].y + base[2].y;
97 base[3].y = b >> 1;
98 base[2].y = ( a + b ) >> 2;
99 base[1].y = a >> 1;
100 }
101
102
103 static FT_Bool
105 FT_Angle *angle_in,
106 FT_Angle *angle_out )
107 {
108 FT_Vector d1, d2;
109 FT_Angle theta;
110 FT_Int close1, close2;
111
112
113 d1.x = base[1].x - base[2].x;
114 d1.y = base[1].y - base[2].y;
115 d2.x = base[0].x - base[1].x;
116 d2.y = base[0].y - base[1].y;
117
118 close1 = FT_IS_SMALL( d1.x ) && FT_IS_SMALL( d1.y );
119 close2 = FT_IS_SMALL( d2.x ) && FT_IS_SMALL( d2.y );
120
121 if ( close1 )
122 {
123 if ( close2 )
124 {
125 /* basically a point; */
126 /* do nothing to retain original direction */
127 }
128 else
129 {
130 *angle_in =
131 *angle_out = FT_Atan2( d2.x, d2.y );
132 }
133 }
134 else /* !close1 */
135 {
136 if ( close2 )
137 {
138 *angle_in =
139 *angle_out = FT_Atan2( d1.x, d1.y );
140 }
141 else
142 {
143 *angle_in = FT_Atan2( d1.x, d1.y );
144 *angle_out = FT_Atan2( d2.x, d2.y );
145 }
146 }
147
148 theta = ft_pos_abs( FT_Angle_Diff( *angle_in, *angle_out ) );
149
150 return FT_BOOL( theta < FT_SMALL_CONIC_THRESHOLD );
151 }
152
153
154 static void
156 {
157 FT_Pos a, b, c;
158
159
160 base[6].x = base[3].x;
161 a = base[0].x + base[1].x;
162 b = base[1].x + base[2].x;
163 c = base[2].x + base[3].x;
164 base[5].x = c >> 1;
165 c += b;
166 base[4].x = c >> 2;
167 base[1].x = a >> 1;
168 a += b;
169 base[2].x = a >> 2;
170 base[3].x = ( a + c ) >> 3;
171
172 base[6].y = base[3].y;
173 a = base[0].y + base[1].y;
174 b = base[1].y + base[2].y;
175 c = base[2].y + base[3].y;
176 base[5].y = c >> 1;
177 c += b;
178 base[4].y = c >> 2;
179 base[1].y = a >> 1;
180 a += b;
181 base[2].y = a >> 2;
182 base[3].y = ( a + c ) >> 3;
183 }
184
185
186 /* Return the average of `angle1' and `angle2'. */
187 /* This gives correct result even if `angle1' and `angle2' */
188 /* have opposite signs. */
189 static FT_Angle
191 FT_Angle angle2 )
192 {
193 return angle1 + FT_Angle_Diff( angle1, angle2 ) / 2;
194 }
195
196
197 static FT_Bool
199 FT_Angle *angle_in,
200 FT_Angle *angle_mid,
201 FT_Angle *angle_out )
202 {
203 FT_Vector d1, d2, d3;
204 FT_Angle theta1, theta2;
205 FT_Int close1, close2, close3;
206
207
208 d1.x = base[2].x - base[3].x;
209 d1.y = base[2].y - base[3].y;
210 d2.x = base[1].x - base[2].x;
211 d2.y = base[1].y - base[2].y;
212 d3.x = base[0].x - base[1].x;
213 d3.y = base[0].y - base[1].y;
214
215 close1 = FT_IS_SMALL( d1.x ) && FT_IS_SMALL( d1.y );
216 close2 = FT_IS_SMALL( d2.x ) && FT_IS_SMALL( d2.y );
217 close3 = FT_IS_SMALL( d3.x ) && FT_IS_SMALL( d3.y );
218
219 if ( close1 )
220 {
221 if ( close2 )
222 {
223 if ( close3 )
224 {
225 /* basically a point; */
226 /* do nothing to retain original direction */
227 }
228 else /* !close3 */
229 {
230 *angle_in =
231 *angle_mid =
232 *angle_out = FT_Atan2( d3.x, d3.y );
233 }
234 }
235 else /* !close2 */
236 {
237 if ( close3 )
238 {
239 *angle_in =
240 *angle_mid =
241 *angle_out = FT_Atan2( d2.x, d2.y );
242 }
243 else /* !close3 */
244 {
245 *angle_in =
246 *angle_mid = FT_Atan2( d2.x, d2.y );
247 *angle_out = FT_Atan2( d3.x, d3.y );
248 }
249 }
250 }
251 else /* !close1 */
252 {
253 if ( close2 )
254 {
255 if ( close3 )
256 {
257 *angle_in =
258 *angle_mid =
259 *angle_out = FT_Atan2( d1.x, d1.y );
260 }
261 else /* !close3 */
262 {
263 *angle_in = FT_Atan2( d1.x, d1.y );
264 *angle_out = FT_Atan2( d3.x, d3.y );
265 *angle_mid = ft_angle_mean( *angle_in, *angle_out );
266 }
267 }
268 else /* !close2 */
269 {
270 if ( close3 )
271 {
272 *angle_in = FT_Atan2( d1.x, d1.y );
273 *angle_mid =
274 *angle_out = FT_Atan2( d2.x, d2.y );
275 }
276 else /* !close3 */
277 {
278 *angle_in = FT_Atan2( d1.x, d1.y );
279 *angle_mid = FT_Atan2( d2.x, d2.y );
280 *angle_out = FT_Atan2( d3.x, d3.y );
281 }
282 }
283 }
284
285 theta1 = ft_pos_abs( FT_Angle_Diff( *angle_in, *angle_mid ) );
286 theta2 = ft_pos_abs( FT_Angle_Diff( *angle_mid, *angle_out ) );
287
288 return FT_BOOL( theta1 < FT_SMALL_CUBIC_THRESHOLD &&
289 theta2 < FT_SMALL_CUBIC_THRESHOLD );
290 }
291
292
293 /*************************************************************************/
294 /*************************************************************************/
295 /***** *****/
296 /***** STROKE BORDERS *****/
297 /***** *****/
298 /*************************************************************************/
299 /*************************************************************************/
300
301 typedef enum FT_StrokeTags_
302 {
303 FT_STROKE_TAG_ON = 1, /* on-curve point */
304 FT_STROKE_TAG_CUBIC = 2, /* cubic off-point */
305 FT_STROKE_TAG_BEGIN = 4, /* sub-path start */
306 FT_STROKE_TAG_END = 8 /* sub-path end */
307
309
310#define FT_STROKE_TAG_BEGIN_END ( FT_STROKE_TAG_BEGIN | FT_STROKE_TAG_END )
311
312 typedef struct FT_StrokeBorderRec_
313 {
318 FT_Bool movable; /* TRUE for ends of lineto borders */
319 FT_Int start; /* index of current sub-path start point */
322
324
325
326 static FT_Error
328 FT_UInt new_points )
329 {
330 FT_UInt old_max = border->max_points;
331 FT_UInt new_max = border->num_points + new_points;
333
334
335 if ( new_max > old_max )
336 {
337 FT_UInt cur_max = old_max;
338 FT_Memory memory = border->memory;
339
340
341 while ( cur_max < new_max )
342 cur_max += ( cur_max >> 1 ) + 16;
343
344 if ( FT_RENEW_ARRAY( border->points, old_max, cur_max ) ||
345 FT_RENEW_ARRAY( border->tags, old_max, cur_max ) )
346 goto Exit;
347
348 border->max_points = cur_max;
349 }
350
351 Exit:
352 return error;
353 }
354
355
356 static void
359 {
360 FT_UInt start = (FT_UInt)border->start;
361 FT_UInt count = border->num_points;
362
363
364 FT_ASSERT( border->start >= 0 );
365
366 /* don't record empty paths! */
367 if ( count <= start + 1U )
368 border->num_points = start;
369 else
370 {
371 /* copy the last point to the start of this sub-path, since */
372 /* it contains the `adjusted' starting coordinates */
373 border->num_points = --count;
374 border->points[start] = border->points[count];
375 border->tags[start] = border->tags[count];
376
377 if ( reverse )
378 {
379 /* reverse the points */
380 {
381 FT_Vector* vec1 = border->points + start + 1;
382 FT_Vector* vec2 = border->points + count - 1;
383
384
385 for ( ; vec1 < vec2; vec1++, vec2-- )
386 {
387 FT_Vector tmp;
388
389
390 tmp = *vec1;
391 *vec1 = *vec2;
392 *vec2 = tmp;
393 }
394 }
395
396 /* then the tags */
397 {
398 FT_Byte* tag1 = border->tags + start + 1;
399 FT_Byte* tag2 = border->tags + count - 1;
400
401
402 for ( ; tag1 < tag2; tag1++, tag2-- )
403 {
404 FT_Byte tmp;
405
406
407 tmp = *tag1;
408 *tag1 = *tag2;
409 *tag2 = tmp;
410 }
411 }
412 }
413
415 border->tags[count - 1] |= FT_STROKE_TAG_END;
416 }
417
418 border->start = -1;
419 border->movable = FALSE;
420 }
421
422
423 static FT_Error
425 FT_Vector* to,
426 FT_Bool movable )
427 {
429
430
431 FT_ASSERT( border->start >= 0 );
432
433 if ( border->movable )
434 {
435 /* move last point */
436 border->points[border->num_points - 1] = *to;
437 }
438 else
439 {
440 /* don't add zero-length lineto, but always add moveto */
441 if ( border->num_points > (FT_UInt)border->start &&
442 FT_IS_SMALL( border->points[border->num_points - 1].x - to->x ) &&
443 FT_IS_SMALL( border->points[border->num_points - 1].y - to->y ) )
444 return error;
445
446 /* add one point */
448 if ( !error )
449 {
450 FT_Vector* vec = border->points + border->num_points;
451 FT_Byte* tag = border->tags + border->num_points;
452
453
454 vec[0] = *to;
456
457 border->num_points += 1;
458 }
459 }
460 border->movable = movable;
461 return error;
462 }
463
464
465 static FT_Error
468 FT_Vector* to )
469 {
471
472
473 FT_ASSERT( border->start >= 0 );
474
476 if ( !error )
477 {
478 FT_Vector* vec = border->points + border->num_points;
479 FT_Byte* tag = border->tags + border->num_points;
480
481
482 vec[0] = *control;
483 vec[1] = *to;
484
485 tag[0] = 0;
487
488 border->num_points += 2;
489 }
490
491 border->movable = FALSE;
492
493 return error;
494 }
495
496
497 static FT_Error
499 FT_Vector* control1,
500 FT_Vector* control2,
501 FT_Vector* to )
502 {
504
505
506 FT_ASSERT( border->start >= 0 );
507
509 if ( !error )
510 {
511 FT_Vector* vec = border->points + border->num_points;
512 FT_Byte* tag = border->tags + border->num_points;
513
514
515 vec[0] = *control1;
516 vec[1] = *control2;
517 vec[2] = *to;
518
522
523 border->num_points += 3;
524 }
525
526 border->movable = FALSE;
527
528 return error;
529 }
530
531
532#define FT_ARC_CUBIC_ANGLE ( FT_ANGLE_PI / 2 )
533
534
535 static FT_Error
537 FT_Vector* center,
538 FT_Fixed radius,
539 FT_Angle angle_start,
540 FT_Angle angle_diff )
541 {
542 FT_Fixed coef;
543 FT_Vector a0, a1, a2, a3;
544 FT_Int i, arcs = 1;
546
547
548 /* number of cubic arcs to draw */
549 while ( angle_diff > FT_ARC_CUBIC_ANGLE * arcs ||
550 -angle_diff > FT_ARC_CUBIC_ANGLE * arcs )
551 arcs++;
552
553 /* control tangents */
554 coef = FT_Tan( angle_diff / ( 4 * arcs ) );
555 coef += coef / 3;
556
557 /* compute start and first control point */
558 FT_Vector_From_Polar( &a0, radius, angle_start );
559 a1.x = FT_MulFix( -a0.y, coef );
560 a1.y = FT_MulFix( a0.x, coef );
561
562 a0.x += center->x;
563 a0.y += center->y;
564 a1.x += a0.x;
565 a1.y += a0.y;
566
567 for ( i = 1; i <= arcs; i++ )
568 {
569 /* compute end and second control point */
570 FT_Vector_From_Polar( &a3, radius,
571 angle_start + i * angle_diff / arcs );
572 a2.x = FT_MulFix( a3.y, coef );
573 a2.y = FT_MulFix( -a3.x, coef );
574
575 a3.x += center->x;
576 a3.y += center->y;
577 a2.x += a3.x;
578 a2.y += a3.y;
579
580 /* add cubic arc */
582 if ( error )
583 break;
584
585 /* a0 = a3; */
586 a1.x = a3.x - a2.x + a3.x;
587 a1.y = a3.y - a2.y + a3.y;
588 }
589
590 return error;
591 }
592
593
594 static FT_Error
596 FT_Vector* to )
597 {
598 /* close current open path if any ? */
599 if ( border->start >= 0 )
601
602 border->start = (FT_Int)border->num_points;
603 border->movable = FALSE;
604
605 return ft_stroke_border_lineto( border, to, FALSE );
606 }
607
608
609 static void
612 {
613 border->memory = memory;
614 border->points = NULL;
615 border->tags = NULL;
616
617 border->num_points = 0;
618 border->max_points = 0;
619 border->start = -1;
620 border->valid = FALSE;
621 }
622
623
624 static void
626 {
627 border->num_points = 0;
628 border->start = -1;
629 border->valid = FALSE;
630 }
631
632
633 static void
635 {
636 FT_Memory memory = border->memory;
637
638
639 FT_FREE( border->points );
640 FT_FREE( border->tags );
641
642 border->num_points = 0;
643 border->max_points = 0;
644 border->start = -1;
645 border->valid = FALSE;
646 }
647
648
649 static FT_Error
651 FT_UInt *anum_points,
652 FT_UInt *anum_contours )
653 {
655 FT_UInt num_points = 0;
656 FT_UInt num_contours = 0;
657
658 FT_UInt count = border->num_points;
659 FT_Vector* point = border->points;
660 FT_Byte* tags = border->tags;
661 FT_Int in_contour = 0;
662
663
664 for ( ; count > 0; count--, num_points++, point++, tags++ )
665 {
666 if ( tags[0] & FT_STROKE_TAG_BEGIN )
667 {
668 if ( in_contour != 0 )
669 goto Fail;
670
671 in_contour = 1;
672 }
673 else if ( in_contour == 0 )
674 goto Fail;
675
676 if ( tags[0] & FT_STROKE_TAG_END )
677 {
678 in_contour = 0;
679 num_contours++;
680 }
681 }
682
683 if ( in_contour != 0 )
684 goto Fail;
685
686 border->valid = TRUE;
687
688 Exit:
689 *anum_points = num_points;
690 *anum_contours = num_contours;
691 return error;
692
693 Fail:
694 num_points = 0;
695 num_contours = 0;
696 goto Exit;
697 }
698
699
700 static void
703 {
704 /* copy point locations */
705 if ( border->num_points )
706 FT_ARRAY_COPY( outline->points + outline->n_points,
707 border->points,
708 border->num_points );
709
710 /* copy tags */
711 {
712 FT_UInt count = border->num_points;
713 FT_Byte* read = border->tags;
714 FT_Byte* write = (FT_Byte*)outline->tags + outline->n_points;
715
716
717 for ( ; count > 0; count--, read++, write++ )
718 {
719 if ( *read & FT_STROKE_TAG_ON )
721 else if ( *read & FT_STROKE_TAG_CUBIC )
723 else
725 }
726 }
727
728 /* copy contours */
729 {
730 FT_UInt count = border->num_points;
731 FT_Byte* tags = border->tags;
732 FT_Short* write = outline->contours + outline->n_contours;
733 FT_Short idx = (FT_Short)outline->n_points;
734
735
736 for ( ; count > 0; count--, tags++, idx++ )
737 {
738 if ( *tags & FT_STROKE_TAG_END )
739 {
740 *write++ = idx;
741 outline->n_contours++;
742 }
743 }
744 }
745
746 outline->n_points += (short)border->num_points;
747
749 }
750
751
752 /*************************************************************************/
753 /*************************************************************************/
754 /***** *****/
755 /***** STROKER *****/
756 /***** *****/
757 /*************************************************************************/
758 /*************************************************************************/
759
760#define FT_SIDE_TO_ROTATE( s ) ( FT_ANGLE_PI2 - (s) * FT_ANGLE_PI )
761
762 typedef struct FT_StrokerRec_
763 {
764 FT_Angle angle_in; /* direction into curr join */
765 FT_Angle angle_out; /* direction out of join */
766 FT_Vector center; /* current position */
767 FT_Fixed line_length; /* length of last lineto */
768 FT_Bool first_point; /* is this the start? */
769 FT_Bool subpath_open; /* is the subpath open? */
770 FT_Angle subpath_angle; /* subpath start direction */
771 FT_Vector subpath_start; /* subpath start position */
772 FT_Fixed subpath_line_length; /* subpath start lineto len */
773 FT_Bool handle_wide_strokes; /* use wide strokes logic? */
774
780
783
785
786
787 /* documentation is in ftstroke.h */
788
791 FT_Stroker *astroker )
792 {
793 FT_Error error; /* assigned in FT_NEW */
795 FT_Stroker stroker = NULL;
796
797
798 if ( !library )
799 return FT_THROW( Invalid_Library_Handle );
800
801 if ( !astroker )
802 return FT_THROW( Invalid_Argument );
803
805
806 if ( !FT_NEW( stroker ) )
807 {
808 stroker->library = library;
809
810 ft_stroke_border_init( &stroker->borders[0], memory );
811 ft_stroke_border_init( &stroker->borders[1], memory );
812 }
813
814 *astroker = stroker;
815
816 return error;
817 }
818
819
820 /* documentation is in ftstroke.h */
821
822 FT_EXPORT_DEF( void )
824 FT_Fixed radius,
825 FT_Stroker_LineCap line_cap,
826 FT_Stroker_LineJoin line_join,
827 FT_Fixed miter_limit )
828 {
829 if ( !stroker )
830 return;
831
832 stroker->radius = radius;
833 stroker->line_cap = line_cap;
834 stroker->line_join = line_join;
835 stroker->miter_limit = miter_limit;
836
837 /* ensure miter limit has sensible value */
838 if ( stroker->miter_limit < 0x10000L )
839 stroker->miter_limit = 0x10000L;
840
841 /* save line join style: */
842 /* line join style can be temporarily changed when stroking curves */
843 stroker->line_join_saved = line_join;
844
845 FT_Stroker_Rewind( stroker );
846 }
847
848
849 /* documentation is in ftstroke.h */
850
851 FT_EXPORT_DEF( void )
853 {
854 if ( stroker )
855 {
856 ft_stroke_border_reset( &stroker->borders[0] );
857 ft_stroke_border_reset( &stroker->borders[1] );
858 }
859 }
860
861
862 /* documentation is in ftstroke.h */
863
864 FT_EXPORT_DEF( void )
866 {
867 if ( stroker )
868 {
869 FT_Memory memory = stroker->library->memory;
870
871
872 ft_stroke_border_done( &stroker->borders[0] );
873 ft_stroke_border_done( &stroker->borders[1] );
874
875 stroker->library = NULL;
876 FT_FREE( stroker );
877 }
878 }
879
880
881 /* create a circular arc at a corner or cap */
882 static FT_Error
884 FT_Int side )
885 {
887 FT_Fixed radius = stroker->radius;
889 FT_StrokeBorder border = stroker->borders + side;
890
891
892 rotate = FT_SIDE_TO_ROTATE( side );
893
894 total = FT_Angle_Diff( stroker->angle_in, stroker->angle_out );
895 if ( total == FT_ANGLE_PI )
896 total = -rotate * 2;
897
899 &stroker->center,
900 radius,
901 stroker->angle_in + rotate,
902 total );
903 border->movable = FALSE;
904 return error;
905 }
906
907
908 /* add a cap at the end of an opened path */
909 static FT_Error
912 FT_Int side )
913 {
915
916
917 if ( stroker->line_cap == FT_STROKER_LINECAP_ROUND )
918 {
919 /* add a round cap */
920 stroker->angle_in = angle;
921 stroker->angle_out = angle + FT_ANGLE_PI;
922
923 error = ft_stroker_arcto( stroker, side );
924 }
925 else
926 {
927 /* add a square or butt cap */
928 FT_Vector middle, delta;
929 FT_Fixed radius = stroker->radius;
930 FT_StrokeBorder border = stroker->borders + side;
931
932
933 /* compute middle point and first angle point */
934 FT_Vector_From_Polar( &middle, radius, angle );
935 delta.x = side ? middle.y : -middle.y;
936 delta.y = side ? -middle.x : middle.x;
937
938 if ( stroker->line_cap == FT_STROKER_LINECAP_SQUARE )
939 {
940 middle.x += stroker->center.x;
941 middle.y += stroker->center.y;
942 }
943 else /* FT_STROKER_LINECAP_BUTT */
944 {
945 middle.x = stroker->center.x;
946 middle.y = stroker->center.y;
947 }
948
949 delta.x += middle.x;
950 delta.y += middle.y;
951
953 if ( error )
954 goto Exit;
955
956 /* compute second angle point */
957 delta.x = middle.x - delta.x + middle.x;
958 delta.y = middle.y - delta.y + middle.y;
959
961 }
962
963 Exit:
964 return error;
965 }
966
967
968 /* process an inside corner, i.e. compute intersection */
969 static FT_Error
971 FT_Int side,
972 FT_Fixed line_length )
973 {
974 FT_StrokeBorder border = stroker->borders + side;
975 FT_Angle phi, theta, rotate;
977 FT_Vector sigma, delta;
979 FT_Bool intersect; /* use intersection of lines? */
980
981
982 rotate = FT_SIDE_TO_ROTATE( side );
983
984 theta = FT_Angle_Diff( stroker->angle_in, stroker->angle_out ) / 2;
985
986 /* Only intersect borders if between two lineto's and both */
987 /* lines are long enough (line_length is zero for curves). */
988 /* Also avoid U-turns of nearly 180 degree. */
989 if ( !border->movable || line_length == 0 ||
990 theta > 0x59C000 || theta < -0x59C000 )
991 intersect = FALSE;
992 else
993 {
994 /* compute minimum required length of lines */
995 FT_Fixed min_length;
996
997
998 FT_Vector_Unit( &sigma, theta );
999 min_length =
1000 ft_pos_abs( FT_MulDiv( stroker->radius, sigma.y, sigma.x ) );
1001
1002 intersect = FT_BOOL( min_length &&
1003 stroker->line_length >= min_length &&
1004 line_length >= min_length );
1005 }
1006
1007 if ( !intersect )
1008 {
1009 FT_Vector_From_Polar( &delta, stroker->radius,
1010 stroker->angle_out + rotate );
1011 delta.x += stroker->center.x;
1012 delta.y += stroker->center.y;
1013
1014 border->movable = FALSE;
1015 }
1016 else
1017 {
1018 /* compute median angle */
1019 phi = stroker->angle_in + theta + rotate;
1020
1021 length = FT_DivFix( stroker->radius, sigma.x );
1022
1023 FT_Vector_From_Polar( &delta, length, phi );
1024 delta.x += stroker->center.x;
1025 delta.y += stroker->center.y;
1026 }
1027
1029
1030 return error;
1031 }
1032
1033
1034 /* process an outside corner, i.e. compute bevel/miter/round */
1035 static FT_Error
1037 FT_Int side,
1038 FT_Fixed line_length )
1039 {
1040 FT_StrokeBorder border = stroker->borders + side;
1043
1044
1045 if ( stroker->line_join == FT_STROKER_LINEJOIN_ROUND )
1046 error = ft_stroker_arcto( stroker, side );
1047 else
1048 {
1049 /* this is a mitered (pointed) or beveled (truncated) corner */
1050 FT_Fixed radius = stroker->radius;
1051 FT_Vector sigma;
1052 FT_Angle theta = 0, phi = 0;
1053 FT_Bool bevel, fixed_bevel;
1054
1055
1056 rotate = FT_SIDE_TO_ROTATE( side );
1057
1058 bevel =
1059 FT_BOOL( stroker->line_join == FT_STROKER_LINEJOIN_BEVEL );
1060
1061 fixed_bevel =
1062 FT_BOOL( stroker->line_join != FT_STROKER_LINEJOIN_MITER_VARIABLE );
1063
1064 /* check miter limit first */
1065 if ( !bevel )
1066 {
1067 theta = FT_Angle_Diff( stroker->angle_in, stroker->angle_out ) / 2;
1068
1069 if ( theta == FT_ANGLE_PI2 )
1070 theta = -rotate;
1071
1072 phi = stroker->angle_in + theta + rotate;
1073
1074 FT_Vector_From_Polar( &sigma, stroker->miter_limit, theta );
1075
1076 /* is miter limit exceeded? */
1077 if ( sigma.x < 0x10000L )
1078 {
1079 /* don't create variable bevels for very small deviations; */
1080 /* FT_Sin(x) = 0 for x <= 57 */
1081 if ( fixed_bevel || ft_pos_abs( theta ) > 57 )
1082 bevel = TRUE;
1083 }
1084 }
1085
1086 if ( bevel ) /* this is a bevel (broken angle) */
1087 {
1088 if ( fixed_bevel )
1089 {
1090 /* the outer corners are simply joined together */
1091 FT_Vector delta;
1092
1093
1094 /* add bevel */
1095 FT_Vector_From_Polar( &delta,
1096 radius,
1097 stroker->angle_out + rotate );
1098 delta.x += stroker->center.x;
1099 delta.y += stroker->center.y;
1100
1101 border->movable = FALSE;
1103 }
1104 else /* variable bevel or clipped miter */
1105 {
1106 /* the miter is truncated */
1107 FT_Vector middle, delta;
1108 FT_Fixed coef;
1109
1110
1111 /* compute middle point and first angle point */
1112 FT_Vector_From_Polar( &middle,
1113 FT_MulFix( radius, stroker->miter_limit ),
1114 phi );
1115
1116 coef = FT_DivFix( 0x10000L - sigma.x, sigma.y );
1117 delta.x = FT_MulFix( middle.y, coef );
1118 delta.y = FT_MulFix( -middle.x, coef );
1119
1120 middle.x += stroker->center.x;
1121 middle.y += stroker->center.y;
1122 delta.x += middle.x;
1123 delta.y += middle.y;
1124
1126 if ( error )
1127 goto Exit;
1128
1129 /* compute second angle point */
1130 delta.x = middle.x - delta.x + middle.x;
1131 delta.y = middle.y - delta.y + middle.y;
1132
1134 if ( error )
1135 goto Exit;
1136
1137 /* finally, add an end point; only needed if not lineto */
1138 /* (line_length is zero for curves) */
1139 if ( line_length == 0 )
1140 {
1141 FT_Vector_From_Polar( &delta,
1142 radius,
1143 stroker->angle_out + rotate );
1144
1145 delta.x += stroker->center.x;
1146 delta.y += stroker->center.y;
1147
1149 }
1150 }
1151 }
1152 else /* this is a miter (intersection) */
1153 {
1155 FT_Vector delta;
1156
1157
1158 length = FT_MulDiv( stroker->radius, stroker->miter_limit, sigma.x );
1159
1160 FT_Vector_From_Polar( &delta, length, phi );
1161 delta.x += stroker->center.x;
1162 delta.y += stroker->center.y;
1163
1165 if ( error )
1166 goto Exit;
1167
1168 /* now add an end point; only needed if not lineto */
1169 /* (line_length is zero for curves) */
1170 if ( line_length == 0 )
1171 {
1172 FT_Vector_From_Polar( &delta,
1173 stroker->radius,
1174 stroker->angle_out + rotate );
1175 delta.x += stroker->center.x;
1176 delta.y += stroker->center.y;
1177
1179 }
1180 }
1181 }
1182
1183 Exit:
1184 return error;
1185 }
1186
1187
1188 static FT_Error
1190 FT_Fixed line_length )
1191 {
1193 FT_Angle turn;
1194 FT_Int inside_side;
1195
1196
1197 turn = FT_Angle_Diff( stroker->angle_in, stroker->angle_out );
1198
1199 /* no specific corner processing is required if the turn is 0 */
1200 if ( turn == 0 )
1201 goto Exit;
1202
1203 /* when we turn to the right, the inside side is 0 */
1204 /* otherwise, the inside side is 1 */
1205 inside_side = ( turn < 0 );
1206
1207 /* process the inside side */
1208 error = ft_stroker_inside( stroker, inside_side, line_length );
1209 if ( error )
1210 goto Exit;
1211
1212 /* process the outside side */
1213 error = ft_stroker_outside( stroker, !inside_side, line_length );
1214
1215 Exit:
1216 return error;
1217 }
1218
1219
1220 /* add two points to the left and right borders corresponding to the */
1221 /* start of the subpath */
1222 static FT_Error
1224 FT_Angle start_angle,
1225 FT_Fixed line_length )
1226 {
1227 FT_Vector delta;
1231
1232
1233 FT_Vector_From_Polar( &delta, stroker->radius,
1234 start_angle + FT_ANGLE_PI2 );
1235
1236 point.x = stroker->center.x + delta.x;
1237 point.y = stroker->center.y + delta.y;
1238
1239 border = stroker->borders;
1241 if ( error )
1242 goto Exit;
1243
1244 point.x = stroker->center.x - delta.x;
1245 point.y = stroker->center.y - delta.y;
1246
1247 border++;
1249
1250 /* save angle, position, and line length for last join */
1251 /* (line_length is zero for curves) */
1252 stroker->subpath_angle = start_angle;
1253 stroker->first_point = FALSE;
1254 stroker->subpath_line_length = line_length;
1255
1256 Exit:
1257 return error;
1258 }
1259
1260
1261 /* documentation is in ftstroke.h */
1262
1265 FT_Vector* to )
1266 {
1269 FT_Vector delta;
1271 FT_Int side;
1272 FT_Fixed line_length;
1273
1274
1275 if ( !stroker || !to )
1276 return FT_THROW( Invalid_Argument );
1277
1278 delta.x = to->x - stroker->center.x;
1279 delta.y = to->y - stroker->center.y;
1280
1281 /* a zero-length lineto is a no-op; avoid creating a spurious corner */
1282 if ( delta.x == 0 && delta.y == 0 )
1283 goto Exit;
1284
1285 /* compute length of line */
1286 line_length = FT_Vector_Length( &delta );
1287
1288 angle = FT_Atan2( delta.x, delta.y );
1289 FT_Vector_From_Polar( &delta, stroker->radius, angle + FT_ANGLE_PI2 );
1290
1291 /* process corner if necessary */
1292 if ( stroker->first_point )
1293 {
1294 /* This is the first segment of a subpath. We need to */
1295 /* add a point to each border at their respective starting */
1296 /* point locations. */
1297 error = ft_stroker_subpath_start( stroker, angle, line_length );
1298 if ( error )
1299 goto Exit;
1300 }
1301 else
1302 {
1303 /* process the current corner */
1304 stroker->angle_out = angle;
1305 error = ft_stroker_process_corner( stroker, line_length );
1306 if ( error )
1307 goto Exit;
1308 }
1309
1310 /* now add a line segment to both the `inside' and `outside' paths */
1311 for ( border = stroker->borders, side = 1; side >= 0; side--, border++ )
1312 {
1314
1315
1316 point.x = to->x + delta.x;
1317 point.y = to->y + delta.y;
1318
1319 /* the ends of lineto borders are movable */
1321 if ( error )
1322 goto Exit;
1323
1324 delta.x = -delta.x;
1325 delta.y = -delta.y;
1326 }
1327
1328 stroker->angle_in = angle;
1329 stroker->center = *to;
1330 stroker->line_length = line_length;
1331
1332 Exit:
1333 return error;
1334 }
1335
1336
1337 /* documentation is in ftstroke.h */
1338
1342 FT_Vector* to )
1343 {
1345 FT_Vector bez_stack[34];
1346 FT_Vector* arc;
1347 FT_Vector* limit = bez_stack + 30;
1348 FT_Bool first_arc = TRUE;
1349
1350
1351 if ( !stroker || !control || !to )
1352 {
1353 error = FT_THROW( Invalid_Argument );
1354 goto Exit;
1355 }
1356
1357 /* if all control points are coincident, this is a no-op; */
1358 /* avoid creating a spurious corner */
1359 if ( FT_IS_SMALL( stroker->center.x - control->x ) &&
1360 FT_IS_SMALL( stroker->center.y - control->y ) &&
1361 FT_IS_SMALL( control->x - to->x ) &&
1362 FT_IS_SMALL( control->y - to->y ) )
1363 {
1364 stroker->center = *to;
1365 goto Exit;
1366 }
1367
1368 arc = bez_stack;
1369 arc[0] = *to;
1370 arc[1] = *control;
1371 arc[2] = stroker->center;
1372
1373 while ( arc >= bez_stack )
1374 {
1375 FT_Angle angle_in, angle_out;
1376
1377
1378 /* initialize with current direction */
1379 angle_in = angle_out = stroker->angle_in;
1380
1381 if ( arc < limit &&
1382 !ft_conic_is_small_enough( arc, &angle_in, &angle_out ) )
1383 {
1384 if ( stroker->first_point )
1385 stroker->angle_in = angle_in;
1386
1387 ft_conic_split( arc );
1388 arc += 2;
1389 continue;
1390 }
1391
1392 if ( first_arc )
1393 {
1394 first_arc = FALSE;
1395
1396 /* process corner if necessary */
1397 if ( stroker->first_point )
1398 error = ft_stroker_subpath_start( stroker, angle_in, 0 );
1399 else
1400 {
1401 stroker->angle_out = angle_in;
1402 error = ft_stroker_process_corner( stroker, 0 );
1403 }
1404 }
1405 else if ( ft_pos_abs( FT_Angle_Diff( stroker->angle_in, angle_in ) ) >
1407 {
1408 /* if the deviation from one arc to the next is too great, */
1409 /* add a round corner */
1410 stroker->center = arc[2];
1411 stroker->angle_out = angle_in;
1412 stroker->line_join = FT_STROKER_LINEJOIN_ROUND;
1413
1414 error = ft_stroker_process_corner( stroker, 0 );
1415
1416 /* reinstate line join style */
1417 stroker->line_join = stroker->line_join_saved;
1418 }
1419
1420 if ( error )
1421 goto Exit;
1422
1423 /* the arc's angle is small enough; we can add it directly to each */
1424 /* border */
1425 {
1427 FT_Angle theta, phi, rotate, alpha0 = 0;
1430 FT_Int side;
1431
1432
1433 theta = FT_Angle_Diff( angle_in, angle_out ) / 2;
1434 phi = angle_in + theta;
1435 length = FT_DivFix( stroker->radius, FT_Cos( theta ) );
1436
1437 /* compute direction of original arc */
1438 if ( stroker->handle_wide_strokes )
1439 alpha0 = FT_Atan2( arc[0].x - arc[2].x, arc[0].y - arc[2].y );
1440
1441 for ( border = stroker->borders, side = 0;
1442 side <= 1;
1443 side++, border++ )
1444 {
1445 rotate = FT_SIDE_TO_ROTATE( side );
1446
1447 /* compute control point */
1449 ctrl.x += arc[1].x;
1450 ctrl.y += arc[1].y;
1451
1452 /* compute end point */
1453 FT_Vector_From_Polar( &end, stroker->radius, angle_out + rotate );
1454 end.x += arc[0].x;
1455 end.y += arc[0].y;
1456
1457 if ( stroker->handle_wide_strokes )
1458 {
1460 FT_Angle alpha1;
1461
1462
1463 /* determine whether the border radius is greater than the */
1464 /* radius of curvature of the original arc */
1465 start = border->points[border->num_points - 1];
1466
1467 alpha1 = FT_Atan2( end.x - start.x, end.y - start.y );
1468
1469 /* is the direction of the border arc opposite to */
1470 /* that of the original arc? */
1471 if ( ft_pos_abs( FT_Angle_Diff( alpha0, alpha1 ) ) >
1472 FT_ANGLE_PI / 2 )
1473 {
1474 FT_Angle beta, gamma;
1475 FT_Vector bvec, delta;
1476 FT_Fixed blen, sinA, sinB, alen;
1477
1478
1479 /* use the sine rule to find the intersection point */
1480 beta = FT_Atan2( arc[2].x - start.x, arc[2].y - start.y );
1481 gamma = FT_Atan2( arc[0].x - end.x, arc[0].y - end.y );
1482
1483 bvec.x = end.x - start.x;
1484 bvec.y = end.y - start.y;
1485
1486 blen = FT_Vector_Length( &bvec );
1487
1488 sinA = ft_pos_abs( FT_Sin( alpha1 - gamma ) );
1489 sinB = ft_pos_abs( FT_Sin( beta - gamma ) );
1490
1491 alen = FT_MulDiv( blen, sinA, sinB );
1492
1493 FT_Vector_From_Polar( &delta, alen, beta );
1494 delta.x += start.x;
1495 delta.y += start.y;
1496
1497 /* circumnavigate the negative sector backwards */
1498 border->movable = FALSE;
1500 if ( error )
1501 goto Exit;
1503 if ( error )
1504 goto Exit;
1506 if ( error )
1507 goto Exit;
1508 /* and then move to the endpoint */
1510 if ( error )
1511 goto Exit;
1512
1513 continue;
1514 }
1515
1516 /* else fall through */
1517 }
1518
1519 /* simply add an arc */
1521 if ( error )
1522 goto Exit;
1523 }
1524 }
1525
1526 arc -= 2;
1527
1528 stroker->angle_in = angle_out;
1529 }
1530
1531 stroker->center = *to;
1532
1533 Exit:
1534 return error;
1535 }
1536
1537
1538 /* documentation is in ftstroke.h */
1539
1542 FT_Vector* control1,
1543 FT_Vector* control2,
1544 FT_Vector* to )
1545 {
1547 FT_Vector bez_stack[37];
1548 FT_Vector* arc;
1549 FT_Vector* limit = bez_stack + 32;
1550 FT_Bool first_arc = TRUE;
1551
1552
1553 if ( !stroker || !control1 || !control2 || !to )
1554 {
1555 error = FT_THROW( Invalid_Argument );
1556 goto Exit;
1557 }
1558
1559 /* if all control points are coincident, this is a no-op; */
1560 /* avoid creating a spurious corner */
1561 if ( FT_IS_SMALL( stroker->center.x - control1->x ) &&
1562 FT_IS_SMALL( stroker->center.y - control1->y ) &&
1563 FT_IS_SMALL( control1->x - control2->x ) &&
1564 FT_IS_SMALL( control1->y - control2->y ) &&
1565 FT_IS_SMALL( control2->x - to->x ) &&
1566 FT_IS_SMALL( control2->y - to->y ) )
1567 {
1568 stroker->center = *to;
1569 goto Exit;
1570 }
1571
1572 arc = bez_stack;
1573 arc[0] = *to;
1574 arc[1] = *control2;
1575 arc[2] = *control1;
1576 arc[3] = stroker->center;
1577
1578 while ( arc >= bez_stack )
1579 {
1580 FT_Angle angle_in, angle_mid, angle_out;
1581
1582
1583 /* initialize with current direction */
1584 angle_in = angle_out = angle_mid = stroker->angle_in;
1585
1586 if ( arc < limit &&
1587 !ft_cubic_is_small_enough( arc, &angle_in,
1588 &angle_mid, &angle_out ) )
1589 {
1590 if ( stroker->first_point )
1591 stroker->angle_in = angle_in;
1592
1593 ft_cubic_split( arc );
1594 arc += 3;
1595 continue;
1596 }
1597
1598 if ( first_arc )
1599 {
1600 first_arc = FALSE;
1601
1602 /* process corner if necessary */
1603 if ( stroker->first_point )
1604 error = ft_stroker_subpath_start( stroker, angle_in, 0 );
1605 else
1606 {
1607 stroker->angle_out = angle_in;
1608 error = ft_stroker_process_corner( stroker, 0 );
1609 }
1610 }
1611 else if ( ft_pos_abs( FT_Angle_Diff( stroker->angle_in, angle_in ) ) >
1613 {
1614 /* if the deviation from one arc to the next is too great, */
1615 /* add a round corner */
1616 stroker->center = arc[3];
1617 stroker->angle_out = angle_in;
1618 stroker->line_join = FT_STROKER_LINEJOIN_ROUND;
1619
1620 error = ft_stroker_process_corner( stroker, 0 );
1621
1622 /* reinstate line join style */
1623 stroker->line_join = stroker->line_join_saved;
1624 }
1625
1626 if ( error )
1627 goto Exit;
1628
1629 /* the arc's angle is small enough; we can add it directly to each */
1630 /* border */
1631 {
1632 FT_Vector ctrl1, ctrl2, end;
1633 FT_Angle theta1, phi1, theta2, phi2, rotate, alpha0 = 0;
1634 FT_Fixed length1, length2;
1636 FT_Int side;
1637
1638
1639 theta1 = FT_Angle_Diff( angle_in, angle_mid ) / 2;
1640 theta2 = FT_Angle_Diff( angle_mid, angle_out ) / 2;
1641 phi1 = ft_angle_mean( angle_in, angle_mid );
1642 phi2 = ft_angle_mean( angle_mid, angle_out );
1643 length1 = FT_DivFix( stroker->radius, FT_Cos( theta1 ) );
1644 length2 = FT_DivFix( stroker->radius, FT_Cos( theta2 ) );
1645
1646 /* compute direction of original arc */
1647 if ( stroker->handle_wide_strokes )
1648 alpha0 = FT_Atan2( arc[0].x - arc[3].x, arc[0].y - arc[3].y );
1649
1650 for ( border = stroker->borders, side = 0;
1651 side <= 1;
1652 side++, border++ )
1653 {
1654 rotate = FT_SIDE_TO_ROTATE( side );
1655
1656 /* compute control points */
1657 FT_Vector_From_Polar( &ctrl1, length1, phi1 + rotate );
1658 ctrl1.x += arc[2].x;
1659 ctrl1.y += arc[2].y;
1660
1661 FT_Vector_From_Polar( &ctrl2, length2, phi2 + rotate );
1662 ctrl2.x += arc[1].x;
1663 ctrl2.y += arc[1].y;
1664
1665 /* compute end point */
1666 FT_Vector_From_Polar( &end, stroker->radius, angle_out + rotate );
1667 end.x += arc[0].x;
1668 end.y += arc[0].y;
1669
1670 if ( stroker->handle_wide_strokes )
1671 {
1673 FT_Angle alpha1;
1674
1675
1676 /* determine whether the border radius is greater than the */
1677 /* radius of curvature of the original arc */
1678 start = border->points[border->num_points - 1];
1679
1680 alpha1 = FT_Atan2( end.x - start.x, end.y - start.y );
1681
1682 /* is the direction of the border arc opposite to */
1683 /* that of the original arc? */
1684 if ( ft_pos_abs( FT_Angle_Diff( alpha0, alpha1 ) ) >
1685 FT_ANGLE_PI / 2 )
1686 {
1687 FT_Angle beta, gamma;
1688 FT_Vector bvec, delta;
1689 FT_Fixed blen, sinA, sinB, alen;
1690
1691
1692 /* use the sine rule to find the intersection point */
1693 beta = FT_Atan2( arc[3].x - start.x, arc[3].y - start.y );
1694 gamma = FT_Atan2( arc[0].x - end.x, arc[0].y - end.y );
1695
1696 bvec.x = end.x - start.x;
1697 bvec.y = end.y - start.y;
1698
1699 blen = FT_Vector_Length( &bvec );
1700
1701 sinA = ft_pos_abs( FT_Sin( alpha1 - gamma ) );
1702 sinB = ft_pos_abs( FT_Sin( beta - gamma ) );
1703
1704 alen = FT_MulDiv( blen, sinA, sinB );
1705
1706 FT_Vector_From_Polar( &delta, alen, beta );
1707 delta.x += start.x;
1708 delta.y += start.y;
1709
1710 /* circumnavigate the negative sector backwards */
1711 border->movable = FALSE;
1713 if ( error )
1714 goto Exit;
1716 if ( error )
1717 goto Exit;
1719 &ctrl2,
1720 &ctrl1,
1721 &start );
1722 if ( error )
1723 goto Exit;
1724 /* and then move to the endpoint */
1726 if ( error )
1727 goto Exit;
1728
1729 continue;
1730 }
1731
1732 /* else fall through */
1733 }
1734
1735 /* simply add an arc */
1736 error = ft_stroke_border_cubicto( border, &ctrl1, &ctrl2, &end );
1737 if ( error )
1738 goto Exit;
1739 }
1740 }
1741
1742 arc -= 3;
1743
1744 stroker->angle_in = angle_out;
1745 }
1746
1747 stroker->center = *to;
1748
1749 Exit:
1750 return error;
1751 }
1752
1753
1754 /* documentation is in ftstroke.h */
1755
1758 FT_Vector* to,
1759 FT_Bool open )
1760 {
1761 if ( !stroker || !to )
1762 return FT_THROW( Invalid_Argument );
1763
1764 /* We cannot process the first point, because there is not enough */
1765 /* information regarding its corner/cap. The latter will be processed */
1766 /* in the `FT_Stroker_EndSubPath' routine. */
1767 /* */
1768 stroker->first_point = TRUE;
1769 stroker->center = *to;
1770 stroker->subpath_open = open;
1771
1772 /* Determine if we need to check whether the border radius is greater */
1773 /* than the radius of curvature of a curve, to handle this case */
1774 /* specially. This is only required if bevel joins or butt caps may */
1775 /* be created, because round & miter joins and round & square caps */
1776 /* cover the negative sector created with wide strokes. */
1777 stroker->handle_wide_strokes =
1778 FT_BOOL( stroker->line_join != FT_STROKER_LINEJOIN_ROUND ||
1779 ( stroker->subpath_open &&
1780 stroker->line_cap == FT_STROKER_LINECAP_BUTT ) );
1781
1782 /* record the subpath start point for each border */
1783 stroker->subpath_start = *to;
1784
1785 stroker->angle_in = 0;
1786
1787 return FT_Err_Ok;
1788 }
1789
1790
1791 static FT_Error
1793 FT_Bool open )
1794 {
1795 FT_StrokeBorder right = stroker->borders + 0;
1796 FT_StrokeBorder left = stroker->borders + 1;
1797 FT_Int new_points;
1799
1800
1801 FT_ASSERT( left->start >= 0 );
1802
1803 new_points = (FT_Int)left->num_points - left->start;
1804 if ( new_points > 0 )
1805 {
1806 error = ft_stroke_border_grow( right, (FT_UInt)new_points );
1807 if ( error )
1808 goto Exit;
1809
1810 {
1811 FT_Vector* dst_point = right->points + right->num_points;
1812 FT_Byte* dst_tag = right->tags + right->num_points;
1813 FT_Vector* src_point = left->points + left->num_points - 1;
1814 FT_Byte* src_tag = left->tags + left->num_points - 1;
1815
1816
1817 while ( src_point >= left->points + left->start )
1818 {
1819 *dst_point = *src_point;
1820 *dst_tag = *src_tag;
1821
1822 if ( open )
1823 dst_tag[0] &= ~FT_STROKE_TAG_BEGIN_END;
1824 else
1825 {
1826 FT_Byte ttag =
1827 (FT_Byte)( dst_tag[0] & FT_STROKE_TAG_BEGIN_END );
1828
1829
1830 /* switch begin/end tags if necessary */
1831 if ( ttag == FT_STROKE_TAG_BEGIN ||
1832 ttag == FT_STROKE_TAG_END )
1833 dst_tag[0] ^= FT_STROKE_TAG_BEGIN_END;
1834 }
1835
1836 src_point--;
1837 src_tag--;
1838 dst_point++;
1839 dst_tag++;
1840 }
1841 }
1842
1843 left->num_points = (FT_UInt)left->start;
1844 right->num_points += (FT_UInt)new_points;
1845
1846 right->movable = FALSE;
1847 left->movable = FALSE;
1848 }
1849
1850 Exit:
1851 return error;
1852 }
1853
1854
1855 /* documentation is in ftstroke.h */
1856
1857 /* there's a lot of magic in this function! */
1860 {
1862
1863
1864 if ( !stroker )
1865 {
1866 error = FT_THROW( Invalid_Argument );
1867 goto Exit;
1868 }
1869
1870 if ( stroker->subpath_open )
1871 {
1872 FT_StrokeBorder right = stroker->borders;
1873
1874
1875 /* All right, this is an opened path, we need to add a cap between */
1876 /* right & left, add the reverse of left, then add a final cap */
1877 /* between left & right. */
1878 error = ft_stroker_cap( stroker, stroker->angle_in, 0 );
1879 if ( error )
1880 goto Exit;
1881
1882 /* add reversed points from `left' to `right' */
1884 if ( error )
1885 goto Exit;
1886
1887 /* now add the final cap */
1888 stroker->center = stroker->subpath_start;
1889 error = ft_stroker_cap( stroker,
1890 stroker->subpath_angle + FT_ANGLE_PI, 0 );
1891 if ( error )
1892 goto Exit;
1893
1894 /* Now end the right subpath accordingly. The left one is */
1895 /* rewind and doesn't need further processing. */
1897 }
1898 else
1899 {
1900 FT_Angle turn;
1901 FT_Int inside_side;
1902
1903
1904 /* close the path if needed */
1905 if ( stroker->center.x != stroker->subpath_start.x ||
1906 stroker->center.y != stroker->subpath_start.y )
1907 {
1908 error = FT_Stroker_LineTo( stroker, &stroker->subpath_start );
1909 if ( error )
1910 goto Exit;
1911 }
1912
1913 /* process the corner */
1914 stroker->angle_out = stroker->subpath_angle;
1915 turn = FT_Angle_Diff( stroker->angle_in,
1916 stroker->angle_out );
1917
1918 /* no specific corner processing is required if the turn is 0 */
1919 if ( turn != 0 )
1920 {
1921 /* when we turn to the right, the inside side is 0 */
1922 /* otherwise, the inside side is 1 */
1923 inside_side = ( turn < 0 );
1924
1925 error = ft_stroker_inside( stroker,
1926 inside_side,
1927 stroker->subpath_line_length );
1928 if ( error )
1929 goto Exit;
1930
1931 /* process the outside side */
1932 error = ft_stroker_outside( stroker,
1933 !inside_side,
1934 stroker->subpath_line_length );
1935 if ( error )
1936 goto Exit;
1937 }
1938
1939 /* then end our two subpaths */
1940 ft_stroke_border_close( stroker->borders + 0, FALSE );
1941 ft_stroke_border_close( stroker->borders + 1, TRUE );
1942 }
1943
1944 Exit:
1945 return error;
1946 }
1947
1948
1949 /* documentation is in ftstroke.h */
1950
1954 FT_UInt *anum_points,
1955 FT_UInt *anum_contours )
1956 {
1957 FT_UInt num_points = 0, num_contours = 0;
1959
1960
1961 if ( !stroker || border > 1 )
1962 {
1963 error = FT_THROW( Invalid_Argument );
1964 goto Exit;
1965 }
1966
1967 error = ft_stroke_border_get_counts( stroker->borders + border,
1968 &num_points, &num_contours );
1969 Exit:
1970 if ( anum_points )
1971 *anum_points = num_points;
1972
1973 if ( anum_contours )
1974 *anum_contours = num_contours;
1975
1976 return error;
1977 }
1978
1979
1980 /* documentation is in ftstroke.h */
1981
1984 FT_UInt *anum_points,
1985 FT_UInt *anum_contours )
1986 {
1987 FT_UInt count1, count2, num_points = 0;
1988 FT_UInt count3, count4, num_contours = 0;
1990
1991
1992 if ( !stroker )
1993 {
1994 error = FT_THROW( Invalid_Argument );
1995 goto Exit;
1996 }
1997
1998 error = ft_stroke_border_get_counts( stroker->borders + 0,
1999 &count1, &count2 );
2000 if ( error )
2001 goto Exit;
2002
2003 error = ft_stroke_border_get_counts( stroker->borders + 1,
2004 &count3, &count4 );
2005 if ( error )
2006 goto Exit;
2007
2008 num_points = count1 + count3;
2009 num_contours = count2 + count4;
2010
2011 Exit:
2012 if ( anum_points )
2013 *anum_points = num_points;
2014
2015 if ( anum_contours )
2016 *anum_contours = num_contours;
2017
2018 return error;
2019 }
2020
2021
2022 /* documentation is in ftstroke.h */
2023
2024 FT_EXPORT_DEF( void )
2028 {
2029 if ( !stroker || !outline )
2030 return;
2031
2034 {
2035 FT_StrokeBorder sborder = & stroker->borders[border];
2036
2037
2038 if ( sborder->valid )
2039 ft_stroke_border_export( sborder, outline );
2040 }
2041 }
2042
2043
2044 /* documentation is in ftstroke.h */
2045
2046 FT_EXPORT_DEF( void )
2049 {
2052 }
2053
2054
2055 /* documentation is in ftstroke.h */
2056
2057 /*
2058 * The following is very similar to FT_Outline_Decompose, except
2059 * that we do support opened paths, and do not scale the outline.
2060 */
2064 FT_Bool opened )
2065 {
2066 FT_Vector v_last;
2067 FT_Vector v_control;
2068 FT_Vector v_start;
2069
2072 char* tags;
2073
2075
2076 FT_Int n; /* index of contour in outline */
2077 FT_UInt first; /* index of first point in contour */
2078 FT_Int tag; /* current point's state */
2079
2080
2081 if ( !outline )
2082 return FT_THROW( Invalid_Outline );
2083
2084 if ( !stroker )
2085 return FT_THROW( Invalid_Argument );
2086
2087 FT_Stroker_Rewind( stroker );
2088
2089 first = 0;
2090
2091 for ( n = 0; n < outline->n_contours; n++ )
2092 {
2093 FT_UInt last; /* index of last point in contour */
2094
2095
2096 last = (FT_UInt)outline->contours[n];
2097 limit = outline->points + last;
2098
2099 /* skip empty points; we don't stroke these */
2100 if ( last <= first )
2101 {
2102 first = last + 1;
2103 continue;
2104 }
2105
2106 v_start = outline->points[first];
2107 v_last = outline->points[last];
2108
2109 v_control = v_start;
2110
2111 point = outline->points + first;
2112 tags = outline->tags + first;
2113 tag = FT_CURVE_TAG( tags[0] );
2114
2115 /* A contour cannot start with a cubic control point! */
2116 if ( tag == FT_CURVE_TAG_CUBIC )
2117 goto Invalid_Outline;
2118
2119 /* check first point to determine origin */
2120 if ( tag == FT_CURVE_TAG_CONIC )
2121 {
2122 /* First point is conic control. Yes, this happens. */
2123 if ( FT_CURVE_TAG( outline->tags[last] ) == FT_CURVE_TAG_ON )
2124 {
2125 /* start at last point if it is on the curve */
2126 v_start = v_last;
2127 limit--;
2128 }
2129 else
2130 {
2131 /* if both first and last points are conic, */
2132 /* start at their middle */
2133 v_start.x = ( v_start.x + v_last.x ) / 2;
2134 v_start.y = ( v_start.y + v_last.y ) / 2;
2135 }
2136 point--;
2137 tags--;
2138 }
2139
2140 error = FT_Stroker_BeginSubPath( stroker, &v_start, opened );
2141 if ( error )
2142 goto Exit;
2143
2144 while ( point < limit )
2145 {
2146 point++;
2147 tags++;
2148
2149 tag = FT_CURVE_TAG( tags[0] );
2150 switch ( tag )
2151 {
2152 case FT_CURVE_TAG_ON: /* emit a single line_to */
2153 {
2154 FT_Vector vec;
2155
2156
2157 vec.x = point->x;
2158 vec.y = point->y;
2159
2160 error = FT_Stroker_LineTo( stroker, &vec );
2161 if ( error )
2162 goto Exit;
2163 continue;
2164 }
2165
2166 case FT_CURVE_TAG_CONIC: /* consume conic arcs */
2167 v_control.x = point->x;
2168 v_control.y = point->y;
2169
2170 Do_Conic:
2171 if ( point < limit )
2172 {
2173 FT_Vector vec;
2174 FT_Vector v_middle;
2175
2176
2177 point++;
2178 tags++;
2179 tag = FT_CURVE_TAG( tags[0] );
2180
2181 vec = point[0];
2182
2183 if ( tag == FT_CURVE_TAG_ON )
2184 {
2185 error = FT_Stroker_ConicTo( stroker, &v_control, &vec );
2186 if ( error )
2187 goto Exit;
2188 continue;
2189 }
2190
2191 if ( tag != FT_CURVE_TAG_CONIC )
2192 goto Invalid_Outline;
2193
2194 v_middle.x = ( v_control.x + vec.x ) / 2;
2195 v_middle.y = ( v_control.y + vec.y ) / 2;
2196
2197 error = FT_Stroker_ConicTo( stroker, &v_control, &v_middle );
2198 if ( error )
2199 goto Exit;
2200
2201 v_control = vec;
2202 goto Do_Conic;
2203 }
2204
2205 error = FT_Stroker_ConicTo( stroker, &v_control, &v_start );
2206 goto Close;
2207
2208 default: /* FT_CURVE_TAG_CUBIC */
2209 {
2210 FT_Vector vec1, vec2;
2211
2212
2213 if ( point + 1 > limit ||
2215 goto Invalid_Outline;
2216
2217 point += 2;
2218 tags += 2;
2219
2220 vec1 = point[-2];
2221 vec2 = point[-1];
2222
2223 if ( point <= limit )
2224 {
2225 FT_Vector vec;
2226
2227
2228 vec = point[0];
2229
2230 error = FT_Stroker_CubicTo( stroker, &vec1, &vec2, &vec );
2231 if ( error )
2232 goto Exit;
2233 continue;
2234 }
2235
2236 error = FT_Stroker_CubicTo( stroker, &vec1, &vec2, &v_start );
2237 goto Close;
2238 }
2239 }
2240 }
2241
2242 Close:
2243 if ( error )
2244 goto Exit;
2245
2246 /* don't try to end the path if no segments have been generated */
2247 if ( !stroker->first_point )
2248 {
2249 error = FT_Stroker_EndSubPath( stroker );
2250 if ( error )
2251 goto Exit;
2252 }
2253
2254 first = last + 1;
2255 }
2256
2257 return FT_Err_Ok;
2258
2259 Exit:
2260 return error;
2261
2262 Invalid_Outline:
2263 return FT_THROW( Invalid_Outline );
2264 }
2265
2266
2267 /* documentation is in ftstroke.h */
2268
2271 FT_Stroker stroker,
2273 {
2274 FT_Error error = FT_ERR( Invalid_Argument );
2275 FT_Glyph glyph = NULL;
2276
2277
2278 if ( !pglyph )
2279 goto Exit;
2280
2281 glyph = *pglyph;
2282 if ( !glyph || glyph->clazz != &ft_outline_glyph_class )
2283 goto Exit;
2284
2285 {
2286 FT_Glyph copy;
2287
2288
2289 error = FT_Glyph_Copy( glyph, &copy );
2290 if ( error )
2291 goto Exit;
2292
2293 glyph = copy;
2294 }
2295
2296 {
2297 FT_OutlineGlyph oglyph = (FT_OutlineGlyph)glyph;
2298 FT_Outline* outline = &oglyph->outline;
2299 FT_UInt num_points, num_contours;
2300
2301
2303 if ( error )
2304 goto Fail;
2305
2306 FT_Stroker_GetCounts( stroker, &num_points, &num_contours );
2307
2308 FT_Outline_Done( glyph->library, outline );
2309
2310 error = FT_Outline_New( glyph->library,
2311 num_points,
2312 (FT_Int)num_contours,
2313 outline );
2314 if ( error )
2315 goto Fail;
2316
2317 outline->n_points = 0;
2318 outline->n_contours = 0;
2319
2320 FT_Stroker_Export( stroker, outline );
2321 }
2322
2323 if ( destroy )
2324 FT_Done_Glyph( *pglyph );
2325
2326 *pglyph = glyph;
2327 goto Exit;
2328
2329 Fail:
2330 FT_Done_Glyph( glyph );
2331 glyph = NULL;
2332
2333 if ( !destroy )
2334 *pglyph = NULL;
2335
2336 Exit:
2337 return error;
2338 }
2339
2340
2341 /* documentation is in ftstroke.h */
2342
2345 FT_Stroker stroker,
2346 FT_Bool inside,
2348 {
2349 FT_Error error = FT_ERR( Invalid_Argument );
2350 FT_Glyph glyph = NULL;
2351
2352
2353 if ( !pglyph )
2354 goto Exit;
2355
2356 glyph = *pglyph;
2357 if ( !glyph || glyph->clazz != &ft_outline_glyph_class )
2358 goto Exit;
2359
2360 {
2361 FT_Glyph copy;
2362
2363
2364 error = FT_Glyph_Copy( glyph, &copy );
2365 if ( error )
2366 goto Exit;
2367
2368 glyph = copy;
2369 }
2370
2371 {
2372 FT_OutlineGlyph oglyph = (FT_OutlineGlyph)glyph;
2374 FT_Outline* outline = &oglyph->outline;
2375 FT_UInt num_points, num_contours;
2376
2377
2379 if ( inside )
2380 {
2383 else
2385 }
2386
2388 if ( error )
2389 goto Fail;
2390
2392 &num_points, &num_contours );
2393
2394 FT_Outline_Done( glyph->library, outline );
2395
2396 error = FT_Outline_New( glyph->library,
2397 num_points,
2398 (FT_Int)num_contours,
2399 outline );
2400 if ( error )
2401 goto Fail;
2402
2403 outline->n_points = 0;
2404 outline->n_contours = 0;
2405
2407 }
2408
2409 if ( destroy )
2410 FT_Done_Glyph( *pglyph );
2411
2412 *pglyph = glyph;
2413 goto Exit;
2414
2415 Fail:
2416 FT_Done_Glyph( glyph );
2417 glyph = NULL;
2418
2419 if ( !destroy )
2420 *pglyph = NULL;
2421
2422 Exit:
2423 return error;
2424 }
2425
2426
2427/* END */
_STLP_MOVE_TO_STD_NAMESPACE void rotate(_ForwardIter __first, _ForwardIter __middle, _ForwardIter __last)
Definition: _algo.c:519
void destroy(_Tp *__pointer)
Definition: _construct.h:278
#define read
Definition: acwin.h:96
#define write
Definition: acwin.h:97
INT copy(TCHAR source[MAX_PATH], TCHAR dest[MAX_PATH], INT append, DWORD lpdwFlags, BOOL bTouch)
Definition: copy.c:51
FT_Library library
Definition: cffdrivr.c:660
#define FT_CALLBACK_TABLE
#define FT_EXPORT_DEF(x)
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
unsigned int idx
Definition: utils.c:41
#define open
Definition: io.h:44
unsigned short(__cdecl typeof(TIFFCurrentDirectory))(struct tiff *)
Definition: typeof.h:94
POINTL point
Definition: edittest.c:50
int Fail
Definition: ehthrow.cxx:24
FT_DivFix(FT_Long a, FT_Long b)
Definition: ftcalc.c:607
FT_MulDiv(FT_Long a, FT_Long b, FT_Long c)
Definition: ftcalc.c:415
FT_MulFix(FT_Long a, FT_Long b)
Definition: ftcalc.c:508
FT_Vector * vec
Definition: ftbbox.c:469
return FT_Err_Ok
Definition: ftbbox.c:526
#define FT_ASSERT(condition)
Definition: ftdebug.h:241
#define FT_THROW(e)
Definition: ftdebug.h:243
FT_Done_Glyph(FT_Glyph glyph)
Definition: ftglyph.c:641
FT_Glyph_Copy(FT_Glyph source, FT_Glyph *target)
Definition: ftglyph.c:316
struct FT_OutlineGlyphRec_ * FT_OutlineGlyph
Definition: ftglyph.h:186
typedefFT_BEGIN_HEADER struct FT_Glyph_Class_ FT_Glyph_Class
Definition: ftglyph.h:69
#define FT_CURVE_TAG_CUBIC
Definition: ftimage.h:464
#define FT_CURVE_TAG_CONIC
Definition: ftimage.h:463
#define FT_CURVE_TAG(flag)
Definition: ftimage.h:459
#define FT_CURVE_TAG_ON
Definition: ftimage.h:462
FT_BEGIN_HEADER typedef signed long FT_Pos
Definition: ftimage.h:57
#define FT_NEW(ptr)
Definition: ftmemory.h:339
#define FT_FREE(ptr)
Definition: ftmemory.h:337
#define FT_ARRAY_COPY(dest, source, count)
Definition: ftmemory.h:253
#define FT_RENEW_ARRAY(ptr, curcnt, newcnt)
Definition: ftmemory.h:344
FT_Outline_Check(FT_Outline *outline)
Definition: ftoutln.c:341
@ FT_ORIENTATION_TRUETYPE
Definition: ftoutln.h:536
FT_Outline_Get_Orientation(FT_Outline *outline)
Definition: ftoutln.c:1039
enum FT_Orientation_ FT_Orientation
FT_Outline_New(FT_Library library, FT_UInt numPoints, FT_Int numContours, FT_Outline *anoutline)
Definition: ftoutln.c:293
FT_Outline_Done(FT_Library library, FT_Outline *outline)
Definition: ftoutln.c:425
FT_Stroker_Export(FT_Stroker stroker, FT_Outline *outline)
Definition: ftstroke.c:2047
FT_Stroker_LineTo(FT_Stroker stroker, FT_Vector *to)
Definition: ftstroke.c:1264
static void ft_conic_split(FT_Vector *base)
Definition: ftstroke.c:82
static void ft_stroke_border_reset(FT_StrokeBorder border)
Definition: ftstroke.c:625
FT_Stroker_Rewind(FT_Stroker stroker)
Definition: ftstroke.c:852
FT_Outline_GetInsideBorder(FT_Outline *outline)
Definition: ftstroke.c:35
#define FT_STROKE_TAG_BEGIN_END
Definition: ftstroke.c:310
static void ft_stroke_border_export(FT_StrokeBorder border, FT_Outline *outline)
Definition: ftstroke.c:701
static FT_Error ft_stroke_border_cubicto(FT_StrokeBorder border, FT_Vector *control1, FT_Vector *control2, FT_Vector *to)
Definition: ftstroke.c:498
FT_Stroker_GetBorderCounts(FT_Stroker stroker, FT_StrokerBorder border, FT_UInt *anum_points, FT_UInt *anum_contours)
Definition: ftstroke.c:1952
#define FT_SIDE_TO_ROTATE(s)
Definition: ftstroke.c:760
static FT_Error ft_stroker_inside(FT_Stroker stroker, FT_Int side, FT_Fixed line_length)
Definition: ftstroke.c:970
FT_Stroker_GetCounts(FT_Stroker stroker, FT_UInt *anum_points, FT_UInt *anum_contours)
Definition: ftstroke.c:1983
static FT_Bool ft_conic_is_small_enough(FT_Vector *base, FT_Angle *angle_in, FT_Angle *angle_out)
Definition: ftstroke.c:104
struct FT_StrokeBorderRec_ FT_StrokeBorderRec
static FT_Error ft_stroke_border_get_counts(FT_StrokeBorder border, FT_UInt *anum_points, FT_UInt *anum_contours)
Definition: ftstroke.c:650
FT_CALLBACK_TABLE const FT_Glyph_Class ft_outline_glyph_class
Definition: ftstroke.c:29
static FT_Error ft_stroker_arcto(FT_Stroker stroker, FT_Int side)
Definition: ftstroke.c:883
FT_Stroker_Done(FT_Stroker stroker)
Definition: ftstroke.c:865
static FT_Bool ft_cubic_is_small_enough(FT_Vector *base, FT_Angle *angle_in, FT_Angle *angle_mid, FT_Angle *angle_out)
Definition: ftstroke.c:198
static FT_Error ft_stroke_border_conicto(FT_StrokeBorder border, FT_Vector *control, FT_Vector *to)
Definition: ftstroke.c:466
static FT_Error ft_stroke_border_moveto(FT_StrokeBorder border, FT_Vector *to)
Definition: ftstroke.c:595
static void ft_cubic_split(FT_Vector *base)
Definition: ftstroke.c:155
static FT_Error ft_stroke_border_grow(FT_StrokeBorder border, FT_UInt new_points)
Definition: ftstroke.c:327
FT_Stroker_CubicTo(FT_Stroker stroker, FT_Vector *control1, FT_Vector *control2, FT_Vector *to)
Definition: ftstroke.c:1541
FT_Outline_GetOutsideBorder(FT_Outline *outline)
Definition: ftstroke.c:48
FT_StrokeTags_
Definition: ftstroke.c:302
@ FT_STROKE_TAG_END
Definition: ftstroke.c:306
@ FT_STROKE_TAG_ON
Definition: ftstroke.c:303
@ FT_STROKE_TAG_CUBIC
Definition: ftstroke.c:304
@ FT_STROKE_TAG_BEGIN
Definition: ftstroke.c:305
static FT_Error ft_stroker_process_corner(FT_Stroker stroker, FT_Fixed line_length)
Definition: ftstroke.c:1189
static FT_Angle ft_angle_mean(FT_Angle angle1, FT_Angle angle2)
Definition: ftstroke.c:190
FT_Stroker_New(FT_Library library, FT_Stroker *astroker)
Definition: ftstroke.c:790
FT_Stroker_BeginSubPath(FT_Stroker stroker, FT_Vector *to, FT_Bool open)
Definition: ftstroke.c:1757
FT_Stroker_ConicTo(FT_Stroker stroker, FT_Vector *control, FT_Vector *to)
Definition: ftstroke.c:1340
FT_Stroker_EndSubPath(FT_Stroker stroker)
Definition: ftstroke.c:1859
static FT_Error ft_stroker_cap(FT_Stroker stroker, FT_Angle angle, FT_Int side)
Definition: ftstroke.c:910
FT_Glyph_Stroke(FT_Glyph *pglyph, FT_Stroker stroker, FT_Bool destroy)
Definition: ftstroke.c:2270
static FT_Error ft_stroker_outside(FT_Stroker stroker, FT_Int side, FT_Fixed line_length)
Definition: ftstroke.c:1036
FT_Stroker_ParseOutline(FT_Stroker stroker, FT_Outline *outline, FT_Bool opened)
Definition: ftstroke.c:2062
static void ft_stroke_border_close(FT_StrokeBorder border, FT_Bool reverse)
Definition: ftstroke.c:357
#define FT_IS_SMALL(x)
Definition: ftstroke.c:71
static FT_Error ft_stroke_border_arcto(FT_StrokeBorder border, FT_Vector *center, FT_Fixed radius, FT_Angle angle_start, FT_Angle angle_diff)
Definition: ftstroke.c:536
#define FT_SMALL_CONIC_THRESHOLD
Definition: ftstroke.c:66
struct FT_StrokeBorderRec_ * FT_StrokeBorder
FT_Glyph_StrokeBorder(FT_Glyph *pglyph, FT_Stroker stroker, FT_Bool inside, FT_Bool destroy)
Definition: ftstroke.c:2344
static FT_Error ft_stroke_border_lineto(FT_StrokeBorder border, FT_Vector *to, FT_Bool movable)
Definition: ftstroke.c:424
struct FT_StrokerRec_ FT_StrokerRec
static void ft_stroke_border_done(FT_StrokeBorder border)
Definition: ftstroke.c:634
#define FT_SMALL_CUBIC_THRESHOLD
Definition: ftstroke.c:67
enum FT_StrokeTags_ FT_StrokeTags
#define FT_ARC_CUBIC_ANGLE
Definition: ftstroke.c:532
static void ft_stroke_border_init(FT_StrokeBorder border, FT_Memory memory)
Definition: ftstroke.c:610
static FT_Error ft_stroker_add_reverse_left(FT_Stroker stroker, FT_Bool open)
Definition: ftstroke.c:1792
static FT_Error ft_stroker_subpath_start(FT_Stroker stroker, FT_Angle start_angle, FT_Fixed line_length)
Definition: ftstroke.c:1223
FT_Stroker_Set(FT_Stroker stroker, FT_Fixed radius, FT_Stroker_LineCap line_cap, FT_Stroker_LineJoin line_join, FT_Fixed miter_limit)
Definition: ftstroke.c:823
static FT_Pos ft_pos_abs(FT_Pos x)
Definition: ftstroke.c:75
FT_Stroker_ExportBorder(FT_Stroker stroker, FT_StrokerBorder border, FT_Outline *outline)
Definition: ftstroke.c:2025
@ FT_STROKER_LINECAP_ROUND
Definition: ftstroke.h:168
@ FT_STROKER_LINECAP_BUTT
Definition: ftstroke.h:167
@ FT_STROKER_LINECAP_SQUARE
Definition: ftstroke.h:169
@ FT_STROKER_BORDER_RIGHT
Definition: ftstroke.h:202
@ FT_STROKER_BORDER_LEFT
Definition: ftstroke.h:201
enum FT_Stroker_LineCap_ FT_Stroker_LineCap
@ FT_STROKER_LINEJOIN_BEVEL
Definition: ftstroke.h:137
@ FT_STROKER_LINEJOIN_MITER_VARIABLE
Definition: ftstroke.h:138
@ FT_STROKER_LINEJOIN_ROUND
Definition: ftstroke.h:136
enum FT_StrokerBorder_ FT_StrokerBorder
typedefFT_BEGIN_HEADER struct FT_StrokerRec_ * FT_Stroker
Definition: ftstroke.h:91
enum FT_Stroker_LineJoin_ FT_Stroker_LineJoin
typedefFT_BEGIN_HEADER struct FT_MemoryRec_ * FT_Memory
Definition: ftsystem.h:64
FT_Vector_From_Polar(FT_Vector *vec, FT_Fixed length, FT_Angle angle)
Definition: fttrigon.c:484
FT_BEGIN_HEADER typedef FT_Fixed FT_Angle
Definition: fttrigon.h:52
#define FT_ANGLE_PI
Definition: fttrigon.h:64
FT_Atan2(FT_Fixed x, FT_Fixed y)
Definition: fttrigon.c:339
FT_Vector_Length(FT_Vector *vec)
Definition: fttrigon.c:417
FT_Vector_Unit(FT_Vector *vec, FT_Angle angle)
Definition: fttrigon.c:360
FT_Tan(FT_Angle angle)
Definition: fttrigon.c:325
#define FT_ANGLE_PI2
Definition: fttrigon.h:88
FT_Angle_Diff(FT_Angle angle1, FT_Angle angle2)
Definition: fttrigon.c:501
FT_Sin(FT_Angle angle)
Definition: fttrigon.c:311
FT_Cos(FT_Angle angle)
Definition: fttrigon.c:297
FT_BEGIN_HEADER typedef unsigned char FT_Bool
Definition: fttypes.h:108
unsigned char FT_Byte
Definition: fttypes.h:154
signed long FT_Fixed
Definition: fttypes.h:287
int FT_Error
Definition: fttypes.h:299
#define FT_ERR(e)
Definition: fttypes.h:599
signed short FT_Short
Definition: fttypes.h:198
unsigned int FT_UInt
Definition: fttypes.h:231
#define FT_BOOL(x)
Definition: fttypes.h:591
signed int FT_Int
Definition: fttypes.h:220
size_t total
GLint GLint GLsizei GLsizei GLsizei GLint border
Definition: gl.h:1546
GLuint start
Definition: gl.h:1545
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLint GLint GLint GLint GLint GLint y
Definition: gl.h:1548
GLuint GLuint end
Definition: gl.h:1545
GLdouble n
Definition: glext.h:7729
const GLubyte * c
Definition: glext.h:8905
GLdouble GLdouble right
Definition: glext.h:10859
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
GLint limit
Definition: glext.h:10326
GLint left
Definition: glext.h:7726
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
const GLint * first
Definition: glext.h:5794
GLfloat angle
Definition: glext.h:10853
GLboolean GLboolean GLboolean GLboolean a
Definition: glext.h:6204
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define a
Definition: ke_i.h:78
#define c
Definition: ke_i.h:80
#define b
Definition: ke_i.h:79
if(dx< 0)
Definition: linetemp.h:194
#define error(str)
Definition: mkdosfs.c:1605
#define for
Definition: utility.h:88
const char * tags[99]
Definition: apphelp.c:216
static const struct update_accum a1
Definition: msg.c:534
static const struct update_accum a2
Definition: msg.c:542
static const struct update_accum a3
Definition: msg.c:556
static UINT UINT last
Definition: font.c:45
static char memory[1024 *256]
Definition: process.c:122
#define ctrl
Definition: input.c:1756
@ Close
Definition: sacdrv.h:268
static void Exit(void)
Definition: sock.c:1330
FT_Library library
Definition: ftglyph.h:114
const FT_Glyph_Class * clazz
Definition: ftglyph.h:115
FT_Memory memory
Definition: ftobjs.h:895
FT_Outline outline
Definition: ftglyph.h:220
FT_UInt num_points
Definition: ftstroke.c:314
FT_Byte * tags
Definition: ftstroke.c:317
FT_Memory memory
Definition: ftstroke.c:320
FT_UInt max_points
Definition: ftstroke.c:315
FT_Vector * points
Definition: ftstroke.c:316
FT_Fixed radius
Definition: ftstroke.c:779
FT_Vector subpath_start
Definition: ftstroke.c:771
FT_Bool handle_wide_strokes
Definition: ftstroke.c:773
FT_Vector center
Definition: ftstroke.c:766
FT_Bool subpath_open
Definition: ftstroke.c:769
FT_Stroker_LineCap line_cap
Definition: ftstroke.c:775
FT_Fixed subpath_line_length
Definition: ftstroke.c:772
FT_Fixed line_length
Definition: ftstroke.c:767
FT_Fixed miter_limit
Definition: ftstroke.c:778
FT_Angle subpath_angle
Definition: ftstroke.c:770
FT_Stroker_LineJoin line_join
Definition: ftstroke.c:776
FT_Angle angle_in
Definition: ftstroke.c:764
FT_Bool first_point
Definition: ftstroke.c:768
FT_Library library
Definition: ftstroke.c:782
FT_StrokeBorderRec borders[2]
Definition: ftstroke.c:781
FT_Stroker_LineJoin line_join_saved
Definition: ftstroke.c:777
FT_Angle angle_out
Definition: ftstroke.c:765
FT_Pos x
Definition: ftimage.h:77
FT_Pos y
Definition: ftimage.h:78
LONG y
Definition: windef.h:130
LONG x
Definition: windef.h:129
Definition: dialog.c:52
Definition: mesh.c:5330
Definition: ecma_167.h:138
static void reverse(int *pidx, int cch)
Definition: bidi.c:1153