w32tex
About: TeX Live provides a comprehensive TeX system including all the major TeX-related programs, macro packages, and fonts that are free software. Windows sources.
  Fossies Dox: w32tex-src.tar.xz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

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>
22 #include <freetype/internal/ftmemory.h>
23 #include <freetype/internal/ftdebug.h>
24 #include <freetype/internal/ftobjs.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  {
316  FT_Vector* points;
317  FT_Byte* tags;
318  FT_Bool movable; /* TRUE for ends of lineto borders */
319  FT_Int start; /* index of current sub-path start point */
321  FT_Bool valid;
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  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 
414  border->tags[start ] |= FT_STROKE_TAG_BEGIN;
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;
455  tag[0] = FT_STROKE_TAG_ON;
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  {
470  FT_Error error;
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;
486  tag[1] = FT_STROKE_TAG_ON;
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  {
503  FT_Error error;
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 
521  tag[2] = FT_STROKE_TAG_ON;
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,
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 */
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 
606  }
607 
608 
609  static void
611  FT_Memory memory )
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 )
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;
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;
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 */
794  FT_Memory memory;
796 
797 
798  if ( !library )
799  return FT_THROW( Invalid_Library_Handle );
800 
801  if ( !astroker )
802  return FT_THROW( Invalid_Argument );
803 
804  memory = library->memory;
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 )
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 
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
911  FT_Angle angle,
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 */
929  FT_Fixed radius = stroker->radius;
930  FT_StrokeBorder border = stroker->borders + side;
931 
932 
933  /* compute middle point and first angle point */
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,
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,
1039  {
1040  FT_StrokeBorder border = stroker->borders + side;
1041  FT_Error error;
1042  FT_Angle rotate;
1043 
1044 
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 =
1060 
1061  fixed_bevel =
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 */
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 */
1108  FT_Fixed coef;
1109 
1110 
1111  /* compute middle point and first angle point */
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  {
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  {
1154  FT_Fixed length;
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  {
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
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,
1226  {
1227  FT_Vector delta;
1228  FT_Vector point;
1229  FT_Error error;
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;
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;
1270  FT_Angle angle;
1271  FT_Int side;
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 */
1287 
1288  angle = FT_Atan2( delta.x, delta.y );
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. */
1298  if ( error )
1299  goto Exit;
1300  }
1301  else
1302  {
1303  /* process the current corner */
1304  stroker->angle_out = angle;
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  {
1313  FT_Vector point;
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 
1341  FT_Vector* control,
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;
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;
1413 
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  {
1426  FT_Vector ctrl, end;
1427  FT_Angle theta, phi, rotate, alpha0 = 0;
1428  FT_Fixed length;
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 */
1448  FT_Vector_From_Polar( &ctrl, length, phi + rotate );
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  {
1459  FT_Vector start;
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 */
1520  error = ft_stroke_border_conicto( border, &ctrl, &end );
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;
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;
1619 
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  {
1672  FT_Vector start;
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  /* */
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 =
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;
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 
1926  inside_side,
1927  stroker->subpath_line_length );
1928  if ( error )
1929  goto Exit;
1930 
1931  /* process the outside side */
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;
1958  FT_Error error;
1959 
1960 
1961  if ( !stroker || border > 1 )
1962  {
1963  error = FT_THROW( Invalid_Argument );
1964  goto Exit;
1965  }
1966 
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;
1989  FT_Error error;
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 )
2027  FT_Outline* outline )
2028  {
2029  if ( !stroker || !outline )
2030  return;
2031 
2032  if ( border == FT_STROKER_BORDER_LEFT ||
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 )
2048  FT_Outline* outline )
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 
2070  FT_Vector* point;
2071  FT_Vector* limit;
2072  char* tags;
2073 
2074  FT_Error error;
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 
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 
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 
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  {
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 
2272  FT_Bool destroy )
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  {
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 
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 
2346  FT_Bool inside,
2347  FT_Bool destroy )
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  {
2374  FT_Outline* outline = &oglyph->outline;
2375  FT_UInt num_points, num_contours;
2376 
2377 
2379  if ( inside )
2380  {
2381  if ( border == FT_STROKER_BORDER_LEFT )
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 */
#define count(a)
Definition: aptex-macros.h:781
middle
Definition: bibtex-3.c:951
static cairo_status_t intersect(rectangle_t **rectangles, int num_rectangles, cairo_boxes_t *out)
static struct brw_reg vec1(struct brw_reg reg)
static struct brw_reg vec2(struct brw_reg reg)
#define n
Definition: t4ht.c:1290
#define b
Definition: jpegint.h:372
@ FALSE
Definition: dd.h:101
@ TRUE
Definition: dd.h:102
#define control
Definition: devnag.c:323
#define error(a)
Definition: dviinfo.c:48
void Exit(int code)
Definition: dvispc.c:374
static inout inside(const HPGL_Pt2 point[], const size_t points, const double x, const double y, const int)
Definition: fillpoly.cpp:129
static void copy(GlyphCachePtr *root)
Definition: gcache.c:378
#define a0
#define a1
#define a2
#define a3
#define c(n)
Definition: gpos-common.c:150
#define a(n)
Definition: gpos-common.c:148
int base
Definition: gsftopk.c:1502
static char * tags[]
Definition: htex.c:62
#define FT_EXPORT_DEF(x)
Definition: ftconfig.h:32
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_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
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_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
#define FT_CALLBACK_TABLE
#define FT_ASSERT(condition)
Definition: ftdebug.h:241
#define FT_THROW(e)
Definition: ftdebug.h:243
#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
#define NULL
Definition: ftobjs.h:61
small capitals from c petite p scientific i
Definition: afcover.h:80
FT_Vector * vec
Definition: ftbbox.c:469
return FT_Err_Ok
Definition: ftbbox.c:526
for(n=0;n< outline->n_points;n++)
Definition: ftbbox.c:494
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
FT_Stroker_Rewind(FT_Stroker stroker)
Definition: ftstroke.c:852
FT_Outline_GetInsideBorder(FT_Outline *outline)
Definition: ftstroke.c:35
FT_Stroker_GetBorderCounts(FT_Stroker stroker, FT_StrokerBorder border, FT_UInt *anum_points, FT_UInt *anum_contours)
Definition: ftstroke.c:1952
FT_Stroker_GetCounts(FT_Stroker stroker, FT_UInt *anum_points, FT_UInt *anum_contours)
Definition: ftstroke.c:1983
struct FT_StrokeBorderRec_ FT_StrokeBorderRec
FT_CALLBACK_TABLE const FT_Glyph_Class ft_outline_glyph_class
Definition: ftstroke.c:29
FT_Stroker_Done(FT_Stroker stroker)
Definition: ftstroke.c:865
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
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
FT_Glyph_Stroke(FT_Glyph *pglyph, FT_Stroker stroker, FT_Bool destroy)
Definition: ftstroke.c:2270
FT_Stroker_ParseOutline(FT_Stroker stroker, FT_Outline *outline, FT_Bool opened)
Definition: ftstroke.c:2062
struct FT_StrokeBorderRec_ * FT_StrokeBorder
FT_Glyph_StrokeBorder(FT_Glyph *pglyph, FT_Stroker stroker, FT_Bool inside, FT_Bool destroy)
Definition: ftstroke.c:2344
struct FT_StrokerRec_ FT_StrokerRec
enum FT_StrokeTags_ FT_StrokeTags
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
FT_Stroker_ExportBorder(FT_Stroker stroker, FT_StrokerBorder border, FT_Outline *outline)
Definition: ftstroke.c:2025
FT_UInt idx
Definition: cffcmap.c:135
FT_Library library
Definition: cffdrivr.c:660
static uInt border[]
Definition: infblock.c:18
kerning y
Definition: ttdriver.c:212
@ center
Definition: annotate.c:15
@ right
Definition: annotate.c:15
#define beta
Definition: gd_nnquant.c:55
#define gamma
Definition: gd_nnquant.c:53
int radius
Definition: gdfx.h:8
#define read
Definition: win32lib.h:88
#define open
Definition: win32lib.h:86
#define write
Definition: win32lib.h:103
int line_length
Definition: fwrite.c:13
#define length(c)
Definition: ctangleboot.c:65
angle2
Definition: cordic.py:18
angle
Definition: cordic.py:17
float x
Definition: cordic.py:15
struct _arc * arc
Definition: obx.h:97
static int delta
Definition: pbmtolj.c:36
set set set set set set set macro pixldst1 abits if abits op else op endif endm macro pixldst2 abits if abits op else op endif endm macro pixldst4 abits if abits op else op endif endm macro pixldst0 abits op endm macro pixldst3 mem_operand op endm macro pixldst30 mem_operand op endm macro pixldst abits if abits elseif abits elseif abits elseif abits elseif abits pixldst0 abits else pixldst0 abits pixldst0 abits pixldst0 abits pixldst0 abits endif elseif abits else pixldst0 abits pixldst0 abits endif elseif abits else error unsupported bpp *numpix else pixst endif endm macro pixld1_s mem_operand if asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl elseif asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl else error unsupported endif endm macro pixld2_s mem_operand if mov asr add asl add asl mov asr sub UNIT_X add asl mov asr add asl add asl mov asr add UNIT_X add asl else pixld1_s mem_operand pixld1_s mem_operand endif endm macro pixld0_s mem_operand if asr adds SRC_WIDTH_FIXED bpl add asl elseif asr adds SRC_WIDTH_FIXED bpl add asl endif endm macro pixld_s_internal mem_operand if mem_operand pixld2_s mem_operand pixdeinterleave basereg elseif mem_operand elseif mem_operand elseif mem_operand elseif mem_operand pixld0_s mem_operand else pixld0_s mem_operand pixld0_s mem_operand pixld0_s mem_operand pixld0_s mem_operand endif elseif mem_operand else pixld0_s mem_operand pixld0_s mem_operand endif elseif mem_operand else error unsupported mem_operand if bpp mem_operand endif endm macro vuzp8 reg2 vuzp d d &reg2 endm macro vzip8 reg2 vzip d d &reg2 endm macro pixdeinterleave basereg basereg basereg basereg basereg endif endm macro pixinterleave basereg basereg basereg basereg basereg endif endm macro PF boost_increment endif if endif PF tst PF addne PF subne PF cmp ORIG_W if endif if endif if endif PF subge ORIG_W PF subges if endif if endif if endif endif endm macro cache_preload_simple endif if dst_r_bpp pld[DST_R, #(PREFETCH_DISTANCE_SIMPLE *dst_r_bpp/8)] endif if mask_bpp pld if[MASK, #(PREFETCH_DISTANCE_SIMPLE *mask_bpp/8)] endif endif endm macro fetch_mask_pixblock pixld mask_basereg pixblock_size MASK endm macro ensure_destination_ptr_alignment process_pixblock_tail_head if beq irp skip1(dst_w_bpp<=(lowbit *8)) &&((lowbit *8)<(pixblock_size *dst_w_bpp)) .if lowbit< 16 tst DST_R
real to[600]
Definition: pmxab.c:87
static boolean reverse
Definition: ppagelist.c:30
static int32_t last
Definition: ppagelist.c:29
static int32_t first
Definition: ppagelist.c:29
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
#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
#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
static FT_Bool ft_conic_is_small_enough(FT_Vector *base, FT_Angle *angle_in, FT_Angle *angle_out)
Definition: ftstroke.c:104
static FT_Error ft_stroke_border_get_counts(FT_StrokeBorder border, FT_UInt *anum_points, FT_UInt *anum_contours)
Definition: ftstroke.c:650
static FT_Error ft_stroker_arcto(FT_Stroker stroker, FT_Int side)
Definition: ftstroke.c:883
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
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
static FT_Error ft_stroker_cap(FT_Stroker stroker, FT_Angle angle, FT_Int side)
Definition: ftstroke.c:910
static FT_Error ft_stroker_outside(FT_Stroker stroker, FT_Int side, FT_Fixed line_length)
Definition: ftstroke.c:1036
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
static FT_Error ft_stroke_border_lineto(FT_StrokeBorder border, FT_Vector *to, FT_Bool movable)
Definition: ftstroke.c:424
static void ft_stroke_border_done(FT_StrokeBorder border)
Definition: ftstroke.c:634
#define FT_SMALL_CUBIC_THRESHOLD
Definition: ftstroke.c:67
#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
static FT_Pos ft_pos_abs(FT_Pos x)
Definition: ftstroke.c:75
#define rotate(D, num)
Definition: md5.c:38
d1
Definition: sec_div.c:81
FT_Memory memory
Definition: ftobjs.h:895
FT_Outline outline
Definition: ftglyph.h:220
FT_UInt num_points
Definition: ftstroke.c:314
FT_Vector * points
Definition: ftstroke.c:316
FT_Byte * tags
Definition: ftstroke.c:317
FT_Memory memory
Definition: ftstroke.c:320
FT_UInt max_points
Definition: ftstroke.c:315
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_Stroker_LineJoin line_join_saved
Definition: ftstroke.c:777
FT_Angle angle_out
Definition: ftstroke.c:765
FT_StrokeBorderRec borders[2]
Definition: ftstroke.c:781
FT_Pos x
Definition: ftimage.h:77
FT_Pos y
Definition: ftimage.h:78
TT_Short n_contours
Definition: freetype.h:175
TT_UShort * contours
Definition: freetype.h:180
TT_UShort n_points
Definition: freetype.h:176
TT_Vector * points
Definition: freetype.h:178
Definition: pbmfont.h:4
Definition: mpost.c:238
double y
Definition: mpost.c:239
double x
Definition: mpost.c:239
cairo_line_join_t line_join
cairo_point_t first_point
Definition: xmlparse.c:179
tag int tag
Definition: tex4ht.c:2554
TT_Glyph glyph
Definition: ttf2pfb.c:162
TT_Outline outline
Definition: ttf2pfb.c:167
@ start
Definition: preamble.c:52
#define limit(x)
Definition: yuvsplittoppm.c:26
#define end(cp)
Definition: zic.c:71