< prev index next >

src/java.desktop/share/native/libfreetype/src/base/ftstroke.c

Print this page


   1 /****************************************************************************
   2  *
   3  * ftstroke.c
   4  *
   5  *   FreeType path stroker (body).
   6  *
   7  * Copyright (C) 2002-2019 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 


 523 
 524       border->num_points += 3;
 525     }
 526 
 527     border->movable = FALSE;
 528 
 529     return error;
 530   }
 531 
 532 
 533 #define FT_ARC_CUBIC_ANGLE  ( FT_ANGLE_PI / 2 )
 534 
 535 
 536   static FT_Error
 537   ft_stroke_border_arcto( FT_StrokeBorder  border,
 538                           FT_Vector*       center,
 539                           FT_Fixed         radius,
 540                           FT_Angle         angle_start,
 541                           FT_Angle         angle_diff )
 542   {
 543     FT_Angle   total, angle, step, rotate, next, theta;
 544     FT_Vector  a, b, a2, b2;
 545     FT_Fixed   length;
 546     FT_Error   error = FT_Err_Ok;
 547 
 548 
 549     /* compute start point */
 550     FT_Vector_From_Polar( &a, radius, angle_start );
 551     a.x += center->x;
 552     a.y += center->y;
 553 
 554     total  = angle_diff;
 555     angle  = angle_start;
 556     rotate = ( angle_diff >= 0 ) ? FT_ANGLE_PI2 : -FT_ANGLE_PI2;
 557 
 558     while ( total != 0 )
 559     {
 560       step = total;
 561       if ( step > FT_ARC_CUBIC_ANGLE )
 562         step = FT_ARC_CUBIC_ANGLE;
 563 
 564       else if ( step < -FT_ARC_CUBIC_ANGLE )
 565         step = -FT_ARC_CUBIC_ANGLE;
 566 
 567       next  = angle + step;
 568       theta = step;
 569       if ( theta < 0 )
 570         theta = -theta;
 571 
 572       theta >>= 1;
 573 
 574       /* compute end point */
 575       FT_Vector_From_Polar( &b, radius, next );
 576       b.x += center->x;
 577       b.y += center->y;
 578 
 579       /* compute first and second control points */
 580       length = FT_MulDiv( radius, FT_Sin( theta ) * 4,
 581                           ( 0x10000L + FT_Cos( theta ) ) * 3 );
 582 
 583       FT_Vector_From_Polar( &a2, length, angle + rotate );
 584       a2.x += a.x;
 585       a2.y += a.y;
 586 
 587       FT_Vector_From_Polar( &b2, length, next - rotate );
 588       b2.x += b.x;
 589       b2.y += b.y;
 590 
 591       /* add cubic arc */
 592       error = ft_stroke_border_cubicto( border, &a2, &b2, &b );
 593       if ( error )
 594         break;
 595 
 596       /* process the rest of the arc ?? */
 597       a      = b;
 598       total -= step;
 599       angle  = next;
 600     }
 601 
 602     return error;
 603   }
 604 
 605 
 606   static FT_Error
 607   ft_stroke_border_moveto( FT_StrokeBorder  border,
 608                            FT_Vector*       to )
 609   {
 610     /* close current open path if any ? */
 611     if ( border->start >= 0 )
 612       ft_stroke_border_close( border, FALSE );
 613 
 614     border->start = (FT_Int)border->num_points;
 615     border->movable = FALSE;
 616 
 617     return ft_stroke_border_lineto( border, to, FALSE );
 618   }
 619 


 917   }
 918 
 919 
 920   /* add a cap at the end of an opened path */
 921   static FT_Error
 922   ft_stroker_cap( FT_Stroker  stroker,
 923                   FT_Angle    angle,
 924                   FT_Int      side )
 925   {
 926     FT_Error  error = FT_Err_Ok;
 927 
 928 
 929     if ( stroker->line_cap == FT_STROKER_LINECAP_ROUND )
 930     {
 931       /* add a round cap */
 932       stroker->angle_in  = angle;
 933       stroker->angle_out = angle + FT_ANGLE_PI;
 934 
 935       error = ft_stroker_arcto( stroker, side );
 936     }
 937     else if ( stroker->line_cap == FT_STROKER_LINECAP_SQUARE )
 938     {
 939       /* add a square cap */
 940       FT_Vector        delta, delta2;
 941       FT_Angle         rotate = FT_SIDE_TO_ROTATE( side );
 942       FT_Fixed         radius = stroker->radius;
 943       FT_StrokeBorder  border = stroker->borders + side;
 944 
 945 
 946       FT_Vector_From_Polar( &delta2, radius, angle + rotate );
 947       FT_Vector_From_Polar( &delta,  radius, angle );
 948 
 949       delta.x += stroker->center.x + delta2.x;
 950       delta.y += stroker->center.y + delta2.y;
 951 
 952       error = ft_stroke_border_lineto( border, &delta, FALSE );
 953       if ( error )
 954         goto Exit;
 955 
 956       FT_Vector_From_Polar( &delta2, radius, angle - rotate );
 957       FT_Vector_From_Polar( &delta,  radius, angle );
 958 
 959       delta.x += delta2.x + stroker->center.x;
 960       delta.y += delta2.y + stroker->center.y;
 961 
 962       error = ft_stroke_border_lineto( border, &delta, FALSE );
 963     }
 964     else if ( stroker->line_cap == FT_STROKER_LINECAP_BUTT )
 965     {
 966       /* add a butt ending */
 967       FT_Vector        delta;
 968       FT_Angle         rotate = FT_SIDE_TO_ROTATE( side );
 969       FT_Fixed         radius = stroker->radius;
 970       FT_StrokeBorder  border = stroker->borders + side;
 971 
 972 
 973       FT_Vector_From_Polar( &delta, radius, angle + rotate );
 974 
 975       delta.x += stroker->center.x;
 976       delta.y += stroker->center.y;
 977 
 978       error = ft_stroke_border_lineto( border, &delta, FALSE );
 979       if ( error )
 980         goto Exit;
 981 
 982       FT_Vector_From_Polar( &delta, radius, angle - rotate );
 983 
 984       delta.x += stroker->center.x;
 985       delta.y += stroker->center.y;
 986 
 987       error = ft_stroke_border_lineto( border, &delta, FALSE );
 988     }
 989 
 990   Exit:
 991     return error;
 992   }
 993 
 994 
 995   /* process an inside corner, i.e. compute intersection */
 996   static FT_Error
 997   ft_stroker_inside( FT_Stroker  stroker,
 998                      FT_Int      side,
 999                      FT_Fixed    line_length )
1000   {
1001     FT_StrokeBorder  border = stroker->borders + side;
1002     FT_Angle         phi, theta, rotate;
1003     FT_Fixed         length, thcos;
1004     FT_Vector        delta;
1005     FT_Error         error = FT_Err_Ok;
1006     FT_Bool          intersect;          /* use intersection of lines? */
1007 
1008 
1009     rotate = FT_SIDE_TO_ROTATE( side );
1010 
1011     theta = FT_Angle_Diff( stroker->angle_in, stroker->angle_out ) / 2;
1012 
1013     /* Only intersect borders if between two lineto's and both */
1014     /* lines are long enough (line_length is zero for curves). */
1015     /* Also avoid U-turns of nearly 180 degree.                */
1016     if ( !border->movable || line_length == 0  ||
1017          theta > 0x59C000 || theta < -0x59C000 )
1018       intersect = FALSE;
1019     else
1020     {
1021       /* compute minimum required length of lines */
1022       FT_Fixed  min_length = ft_pos_abs( FT_MulFix( stroker->radius,
1023                                                     FT_Tan( theta ) ) );
1024 
1025 




1026       intersect = FT_BOOL( min_length                         &&
1027                            stroker->line_length >= min_length &&
1028                            line_length          >= min_length );
1029     }
1030 
1031     if ( !intersect )
1032     {
1033       FT_Vector_From_Polar( &delta, stroker->radius,
1034                             stroker->angle_out + rotate );
1035       delta.x += stroker->center.x;
1036       delta.y += stroker->center.y;
1037 
1038       border->movable = FALSE;
1039     }
1040     else
1041     {
1042       /* compute median angle */
1043       phi = stroker->angle_in + theta;
1044 
1045       thcos = FT_Cos( theta );
1046 
1047       length = FT_DivFix( stroker->radius, thcos );
1048 
1049       FT_Vector_From_Polar( &delta, length, phi + rotate );
1050       delta.x += stroker->center.x;
1051       delta.y += stroker->center.y;
1052     }
1053 
1054     error = ft_stroke_border_lineto( border, &delta, FALSE );
1055 
1056     return error;
1057   }
1058 
1059 
1060   /* process an outside corner, i.e. compute bevel/miter/round */
1061   static FT_Error
1062   ft_stroker_outside( FT_Stroker  stroker,
1063                       FT_Int      side,
1064                       FT_Fixed    line_length )
1065   {
1066     FT_StrokeBorder  border = stroker->borders + side;
1067     FT_Error         error;
1068     FT_Angle         rotate;
1069 
1070 
1071     if ( stroker->line_join == FT_STROKER_LINEJOIN_ROUND )
1072       error = ft_stroker_arcto( stroker, side );
1073     else
1074     {
1075       /* this is a mitered (pointed) or beveled (truncated) corner */
1076       FT_Fixed  sigma = 0, radius = stroker->radius;

1077       FT_Angle  theta = 0, phi = 0;
1078       FT_Fixed  thcos = 0;
1079       FT_Bool   bevel, fixed_bevel;
1080 
1081 
1082       rotate = FT_SIDE_TO_ROTATE( side );
1083 
1084       bevel =
1085         FT_BOOL( stroker->line_join == FT_STROKER_LINEJOIN_BEVEL );
1086 
1087       fixed_bevel =
1088         FT_BOOL( stroker->line_join != FT_STROKER_LINEJOIN_MITER_VARIABLE );
1089 

1090       if ( !bevel )
1091       {
1092         theta = FT_Angle_Diff( stroker->angle_in, stroker->angle_out );



1093 
1094         if ( theta == FT_ANGLE_PI )
1095         {
1096           theta = rotate;
1097           phi   = stroker->angle_in;
1098         }
1099         else
1100         {
1101           theta /= 2;
1102           phi    = stroker->angle_in + theta + rotate;
1103         }
1104 
1105         thcos = FT_Cos( theta );
1106         sigma = FT_MulFix( stroker->miter_limit, thcos );
1107 
1108         /* is miter limit exceeded? */
1109         if ( sigma < 0x10000L )
1110         {
1111           /* don't create variable bevels for very small deviations; */
1112           /* FT_Sin(x) = 0 for x <= 57                               */
1113           if ( fixed_bevel || ft_pos_abs( theta ) > 57 )
1114             bevel = TRUE;
1115         }
1116       }
1117 
1118       if ( bevel )  /* this is a bevel (broken angle) */
1119       {
1120         if ( fixed_bevel )
1121         {
1122           /* the outer corners are simply joined together */
1123           FT_Vector  delta;
1124 
1125 
1126           /* add bevel */
1127           FT_Vector_From_Polar( &delta,
1128                                 radius,
1129                                 stroker->angle_out + rotate );
1130           delta.x += stroker->center.x;
1131           delta.y += stroker->center.y;
1132 
1133           border->movable = FALSE;
1134           error = ft_stroke_border_lineto( border, &delta, FALSE );
1135         }
1136         else /* variable bevel */
1137         {
1138           /* the miter is truncated */
1139           FT_Vector  middle, delta;
1140           FT_Fixed   length;
1141 
1142 
1143           /* compute middle point */
1144           FT_Vector_From_Polar( &middle,
1145                                 FT_MulFix( radius, stroker->miter_limit ),
1146                                 phi );
1147           middle.x += stroker->center.x;
1148           middle.y += stroker->center.y;
1149 
1150           /* compute first angle point */
1151           length = FT_MulDiv( radius, 0x10000L - sigma,
1152                               ft_pos_abs( FT_Sin( theta ) ) );
1153 
1154           FT_Vector_From_Polar( &delta, length, phi + rotate );

1155           delta.x += middle.x;
1156           delta.y += middle.y;
1157 
1158           error = ft_stroke_border_lineto( border, &delta, FALSE );
1159           if ( error )
1160             goto Exit;
1161 
1162           /* compute second angle point */
1163           FT_Vector_From_Polar( &delta, length, phi - rotate );
1164           delta.x += middle.x;
1165           delta.y += middle.y;
1166 
1167           error = ft_stroke_border_lineto( border, &delta, FALSE );
1168           if ( error )
1169             goto Exit;
1170 
1171           /* finally, add an end point; only needed if not lineto */
1172           /* (line_length is zero for curves)                     */
1173           if ( line_length == 0 )
1174           {
1175             FT_Vector_From_Polar( &delta,
1176                                   radius,
1177                                   stroker->angle_out + rotate );
1178 
1179             delta.x += stroker->center.x;
1180             delta.y += stroker->center.y;
1181 
1182             error = ft_stroke_border_lineto( border, &delta, FALSE );
1183           }
1184         }
1185       }
1186       else /* this is a miter (intersection) */
1187       {
1188         FT_Fixed   length;
1189         FT_Vector  delta;
1190 
1191 
1192         length = FT_DivFix( stroker->radius, thcos );
1193 
1194         FT_Vector_From_Polar( &delta, length, phi );
1195         delta.x += stroker->center.x;
1196         delta.y += stroker->center.y;
1197 
1198         error = ft_stroke_border_lineto( border, &delta, FALSE );
1199         if ( error )
1200           goto Exit;
1201 
1202         /* now add an end point; only needed if not lineto */
1203         /* (line_length is zero for curves)                */
1204         if ( line_length == 0 )
1205         {
1206           FT_Vector_From_Polar( &delta,
1207                                 stroker->radius,
1208                                 stroker->angle_out + rotate );
1209           delta.x += stroker->center.x;
1210           delta.y += stroker->center.y;
1211 
1212           error = ft_stroke_border_lineto( border, &delta, FALSE );


   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 <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 


 523 
 524       border->num_points += 3;
 525     }
 526 
 527     border->movable = FALSE;
 528 
 529     return error;
 530   }
 531 
 532 
 533 #define FT_ARC_CUBIC_ANGLE  ( FT_ANGLE_PI / 2 )
 534 
 535 
 536   static FT_Error
 537   ft_stroke_border_arcto( FT_StrokeBorder  border,
 538                           FT_Vector*       center,
 539                           FT_Fixed         radius,
 540                           FT_Angle         angle_start,
 541                           FT_Angle         angle_diff )
 542   {
 543     FT_Fixed   coef;
 544     FT_Vector  a0, a1, a2, a3;
 545     FT_Int     i, arcs = 1;
 546     FT_Error   error = FT_Err_Ok;
 547 
 548 
 549     /* number of cubic arcs to draw */
 550     while (  angle_diff > FT_ARC_CUBIC_ANGLE * arcs ||
 551             -angle_diff > FT_ARC_CUBIC_ANGLE * arcs )
 552       arcs++;
 553 
 554     /* control tangents */
 555     coef  = FT_Tan( angle_diff / ( 4 * arcs ) );
 556     coef += coef / 3;
 557 
 558     /* compute start and first control point */
 559     FT_Vector_From_Polar( &a0, radius, angle_start );
 560     a1.x = FT_MulFix( -a0.y, coef );
 561     a1.y = FT_MulFix(  a0.x, coef );
 562 
 563     a0.x += center->x;
 564     a0.y += center->y;
 565     a1.x += a0.x;
 566     a1.y += a0.y;
 567 
 568     for ( i = 1; i <= arcs; i++ )
 569     {
 570       /* compute end and second control point */
 571       FT_Vector_From_Polar( &a3, radius,
 572                             angle_start + i * angle_diff / arcs );
 573       a2.x = FT_MulFix(  a3.y, coef );
 574       a2.y = FT_MulFix( -a3.x, coef );
 575 
 576       a3.x += center->x;
 577       a3.y += center->y;
 578       a2.x += a3.x;
 579       a2.y += a3.y;










 580 
 581       /* add cubic arc */
 582       error = ft_stroke_border_cubicto( border, &a1, &a2, &a3 );
 583       if ( error )
 584         break;
 585 
 586       /* a0 = a3; */
 587       a1.x = a3.x - a2.x + a3.x;
 588       a1.y = a3.y - a2.y + a3.y;

 589     }
 590 
 591     return error;
 592   }
 593 
 594 
 595   static FT_Error
 596   ft_stroke_border_moveto( FT_StrokeBorder  border,
 597                            FT_Vector*       to )
 598   {
 599     /* close current open path if any ? */
 600     if ( border->start >= 0 )
 601       ft_stroke_border_close( border, FALSE );
 602 
 603     border->start = (FT_Int)border->num_points;
 604     border->movable = FALSE;
 605 
 606     return ft_stroke_border_lineto( border, to, FALSE );
 607   }
 608 


 906   }
 907 
 908 
 909   /* add a cap at the end of an opened path */
 910   static FT_Error
 911   ft_stroker_cap( FT_Stroker  stroker,
 912                   FT_Angle    angle,
 913                   FT_Int      side )
 914   {
 915     FT_Error  error = FT_Err_Ok;
 916 
 917 
 918     if ( stroker->line_cap == FT_STROKER_LINECAP_ROUND )
 919     {
 920       /* add a round cap */
 921       stroker->angle_in  = angle;
 922       stroker->angle_out = angle + FT_ANGLE_PI;
 923 
 924       error = ft_stroker_arcto( stroker, side );
 925     }
 926     else
 927     {
 928       /* add a square or butt cap */
 929       FT_Vector        middle, delta;

 930       FT_Fixed         radius = stroker->radius;
 931       FT_StrokeBorder  border = stroker->borders + side;
 932 
 933 
 934       /* compute middle point and first angle point */
 935       FT_Vector_From_Polar( &middle, radius, angle );
 936       delta.x = side ?  middle.y : -middle.y;
 937       delta.y = side ? -middle.x :  middle.x;








 938 
 939       if ( stroker->line_cap == FT_STROKER_LINECAP_SQUARE )
 940       {
 941         middle.x += stroker->center.x;
 942         middle.y += stroker->center.y;
 943       }
 944       else  /* FT_STROKER_LINECAP_BUTT */
 945       {
 946         middle.x  = stroker->center.x;
 947         middle.y  = stroker->center.y;
 948       }





 949 
 950       delta.x  += middle.x;
 951       delta.y  += middle.y;
 952 
 953       error = ft_stroke_border_lineto( border, &delta, FALSE );
 954       if ( error )
 955         goto Exit;
 956 
 957       /* compute second angle point */
 958       delta.x = middle.x - delta.x + middle.x;
 959       delta.y = middle.y - delta.y + middle.y;

 960 
 961       error = ft_stroke_border_lineto( border, &delta, FALSE );
 962     }
 963 
 964   Exit:
 965     return error;
 966   }
 967 
 968 
 969   /* process an inside corner, i.e. compute intersection */
 970   static FT_Error
 971   ft_stroker_inside( FT_Stroker  stroker,
 972                      FT_Int      side,
 973                      FT_Fixed    line_length )
 974   {
 975     FT_StrokeBorder  border = stroker->borders + side;
 976     FT_Angle         phi, theta, rotate;
 977     FT_Fixed         length;
 978     FT_Vector        sigma, delta;
 979     FT_Error         error = FT_Err_Ok;
 980     FT_Bool          intersect;          /* use intersection of lines? */
 981 
 982 
 983     rotate = FT_SIDE_TO_ROTATE( side );
 984 
 985     theta = FT_Angle_Diff( stroker->angle_in, stroker->angle_out ) / 2;
 986 
 987     /* Only intersect borders if between two lineto's and both */
 988     /* lines are long enough (line_length is zero for curves). */
 989     /* Also avoid U-turns of nearly 180 degree.                */
 990     if ( !border->movable || line_length == 0  ||
 991          theta > 0x59C000 || theta < -0x59C000 )
 992       intersect = FALSE;
 993     else
 994     {
 995       /* compute minimum required length of lines */
 996       FT_Fixed  min_length;

 997 
 998 
 999       FT_Vector_Unit( &sigma, theta );
1000       min_length =
1001         ft_pos_abs( FT_MulDiv( stroker->radius, sigma.y, sigma.x ) );
1002 
1003       intersect = FT_BOOL( min_length                         &&
1004                            stroker->line_length >= min_length &&
1005                            line_length          >= min_length );
1006     }
1007 
1008     if ( !intersect )
1009     {
1010       FT_Vector_From_Polar( &delta, stroker->radius,
1011                             stroker->angle_out + rotate );
1012       delta.x += stroker->center.x;
1013       delta.y += stroker->center.y;
1014 
1015       border->movable = FALSE;
1016     }
1017     else
1018     {
1019       /* compute median angle */
1020       phi = stroker->angle_in + theta + rotate;


1021 
1022       length = FT_DivFix( stroker->radius, sigma.x );
1023 
1024       FT_Vector_From_Polar( &delta, length, phi );
1025       delta.x += stroker->center.x;
1026       delta.y += stroker->center.y;
1027     }
1028 
1029     error = ft_stroke_border_lineto( border, &delta, FALSE );
1030 
1031     return error;
1032   }
1033 
1034 
1035   /* process an outside corner, i.e. compute bevel/miter/round */
1036   static FT_Error
1037   ft_stroker_outside( FT_Stroker  stroker,
1038                       FT_Int      side,
1039                       FT_Fixed    line_length )
1040   {
1041     FT_StrokeBorder  border = stroker->borders + side;
1042     FT_Error         error;
1043     FT_Angle         rotate;
1044 
1045 
1046     if ( stroker->line_join == FT_STROKER_LINEJOIN_ROUND )
1047       error = ft_stroker_arcto( stroker, side );
1048     else
1049     {
1050       /* this is a mitered (pointed) or beveled (truncated) corner */
1051       FT_Fixed   radius = stroker->radius;
1052       FT_Vector  sigma;
1053       FT_Angle   theta = 0, phi = 0;

1054       FT_Bool    bevel, fixed_bevel;
1055 
1056 
1057       rotate = FT_SIDE_TO_ROTATE( side );
1058 
1059       bevel =
1060         FT_BOOL( stroker->line_join == FT_STROKER_LINEJOIN_BEVEL );
1061 
1062       fixed_bevel =
1063         FT_BOOL( stroker->line_join != FT_STROKER_LINEJOIN_MITER_VARIABLE );
1064 
1065       /* check miter limit first */
1066       if ( !bevel )
1067       {
1068         theta = FT_Angle_Diff( stroker->angle_in, stroker->angle_out ) / 2;
1069 
1070         if ( theta == FT_ANGLE_PI2 )
1071           theta = -rotate;
1072 








1073         phi    = stroker->angle_in + theta + rotate;

1074 
1075         FT_Vector_From_Polar( &sigma, stroker->miter_limit, theta );

1076 
1077         /* is miter limit exceeded? */
1078         if ( sigma.x < 0x10000L )
1079         {
1080           /* don't create variable bevels for very small deviations; */
1081           /* FT_Sin(x) = 0 for x <= 57                               */
1082           if ( fixed_bevel || ft_pos_abs( theta ) > 57 )
1083             bevel = TRUE;
1084         }
1085       }
1086 
1087       if ( bevel )  /* this is a bevel (broken angle) */
1088       {
1089         if ( fixed_bevel )
1090         {
1091           /* the outer corners are simply joined together */
1092           FT_Vector  delta;
1093 
1094 
1095           /* add bevel */
1096           FT_Vector_From_Polar( &delta,
1097                                 radius,
1098                                 stroker->angle_out + rotate );
1099           delta.x += stroker->center.x;
1100           delta.y += stroker->center.y;
1101 
1102           border->movable = FALSE;
1103           error = ft_stroke_border_lineto( border, &delta, FALSE );
1104         }
1105         else /* variable bevel or clipped miter */
1106         {
1107           /* the miter is truncated */
1108           FT_Vector  middle, delta;
1109           FT_Fixed   coef;
1110 
1111 
1112           /* compute middle point and first angle point */
1113           FT_Vector_From_Polar( &middle,
1114                                 FT_MulFix( radius, stroker->miter_limit ),
1115                                 phi );


1116 
1117           coef    = FT_DivFix(  0x10000L - sigma.x, sigma.y );
1118           delta.x = FT_MulFix(  middle.y, coef );
1119           delta.y = FT_MulFix( -middle.x, coef );
1120 
1121           middle.x += stroker->center.x;
1122           middle.y += stroker->center.y;
1123           delta.x  += middle.x;
1124           delta.y  += middle.y;
1125 
1126           error = ft_stroke_border_lineto( border, &delta, FALSE );
1127           if ( error )
1128             goto Exit;
1129 
1130           /* compute second angle point */
1131           delta.x = middle.x - delta.x + middle.x;
1132           delta.y = middle.y - delta.y + middle.y;

1133 
1134           error = ft_stroke_border_lineto( border, &delta, FALSE );
1135           if ( error )
1136             goto Exit;
1137 
1138           /* finally, add an end point; only needed if not lineto */
1139           /* (line_length is zero for curves)                     */
1140           if ( line_length == 0 )
1141           {
1142             FT_Vector_From_Polar( &delta,
1143                                   radius,
1144                                   stroker->angle_out + rotate );
1145 
1146             delta.x += stroker->center.x;
1147             delta.y += stroker->center.y;
1148 
1149             error = ft_stroke_border_lineto( border, &delta, FALSE );
1150           }
1151         }
1152       }
1153       else /* this is a miter (intersection) */
1154       {
1155         FT_Fixed   length;
1156         FT_Vector  delta;
1157 
1158 
1159         length = FT_MulDiv( stroker->radius, stroker->miter_limit, sigma.x );
1160 
1161         FT_Vector_From_Polar( &delta, length, phi );
1162         delta.x += stroker->center.x;
1163         delta.y += stroker->center.y;
1164 
1165         error = ft_stroke_border_lineto( border, &delta, FALSE );
1166         if ( error )
1167           goto Exit;
1168 
1169         /* now 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                                 stroker->radius,
1175                                 stroker->angle_out + rotate );
1176           delta.x += stroker->center.x;
1177           delta.y += stroker->center.y;
1178 
1179           error = ft_stroke_border_lineto( border, &delta, FALSE );


< prev index next >