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