21 #include FT_TRIGONOMETRY_H
23 #include FT_INTERNAL_MEMORY_H
24 #include FT_INTERNAL_DEBUG_H
25 #include FT_INTERNAL_OBJECTS_H
62 #define FT_SMALL_CONIC_THRESHOLD ( FT_ANGLE_PI / 6 )
63 #define FT_SMALL_CUBIC_THRESHOLD ( FT_ANGLE_PI / 8 )
67 #define FT_IS_SMALL( x ) ( (x) > -FT_EPSILON && (x) < FT_EPSILON )
73 return x >= 0 ? x : -
x;
83 base[4].
x = base[2].
x;
85 a = base[3].
x = ( base[2].
x +
b ) / 2;
86 b = base[1].
x = ( base[0].
x +
b ) / 2;
87 base[2].
x = ( a +
b ) / 2;
89 base[4].
y = base[2].
y;
91 a = base[3].
y = ( base[2].
y +
b ) / 2;
92 b = base[1].
y = ( base[0].
y +
b ) / 2;
93 base[2].
y = ( a +
b ) / 2;
107 d1.
x = base[1].
x - base[2].
x;
108 d1.
y = base[1].
y - base[2].
y;
109 d2.
x = base[0].
x - base[1].
x;
110 d2.
y = base[0].
y - base[1].
y;
154 base[6].
x = base[3].
x;
157 base[1].
x = a = ( base[0].
x +
c ) / 2;
158 base[5].
x = b = ( base[3].
x +
d ) / 2;
160 base[2].
x = a = ( a +
c ) / 2;
161 base[4].
x = b = ( b +
c ) / 2;
162 base[3].
x = ( a +
b ) / 2;
164 base[6].
y = base[3].
y;
167 base[1].
y = a = ( base[0].
y +
c ) / 2;
168 base[5].
y = b = ( base[3].
y +
d ) / 2;
170 base[2].
y = a = ( a +
c ) / 2;
171 base[4].
y = b = ( b +
c ) / 2;
172 base[3].
y = ( a +
b ) / 2;
195 FT_Int close1, close2, close3;
198 d1.
x = base[2].
x - base[3].
x;
199 d1.
y = base[2].
y - base[3].
y;
200 d2.
x = base[1].
x - base[2].
x;
201 d2.
y = base[1].
y - base[2].
y;
202 d3.
x = base[0].
x - base[1].
x;
203 d3.
y = base[0].
y - base[1].
y;
300 #define FT_STROKE_TAG_BEGIN_END ( FT_STROKE_TAG_BEGIN | FT_STROKE_TAG_END )
302 typedef struct FT_StrokeBorderRec_
320 FT_UInt old_max = border->max_points;
321 FT_UInt new_max = border->num_points + new_points;
325 if ( new_max > old_max )
331 while ( cur_max < new_max )
332 cur_max += ( cur_max >> 1 ) + 16;
338 border->max_points = cur_max;
357 if ( count <= start + 1U )
358 border->num_points =
start;
363 border->num_points = --
count;
364 border->points[
start] = border->points[
count];
370 FT_Vector* vec1 = border->points + start + 1;
371 FT_Vector* vec2 = border->points + count - 1;
374 for ( ; vec1 < vec2; vec1++, vec2-- )
387 FT_Byte* tag1 = border->tags + start + 1;
388 FT_Byte* tag2 = border->tags + count - 1;
391 for ( ; tag1 < tag2; tag1++, tag2-- )
408 border->movable =
FALSE;
422 if ( border->movable )
425 border->points[border->num_points - 1] = *to;
430 if ( border->num_points > 0 &&
431 FT_IS_SMALL( border->points[border->num_points - 1].x - to->
x ) &&
432 FT_IS_SMALL( border->points[border->num_points - 1].y - to->
y ) )
440 FT_Byte* tag = border->tags + border->num_points;
446 border->num_points += 1;
449 border->movable = movable;
468 FT_Byte* tag = border->tags + border->num_points;
477 border->num_points += 2;
480 border->movable =
FALSE;
501 FT_Byte* tag = border->tags + border->num_points;
512 border->num_points += 3;
515 border->movable =
FALSE;
521 #define FT_ARC_CUBIC_ANGLE ( FT_ANGLE_PI / 2 )
569 ( 0x10000L +
FT_Cos( theta ) ) * 3 );
599 if ( border->start >= 0 )
602 border->start = border->num_points;
603 border->movable =
FALSE;
613 border->memory = memory;
614 border->points =
NULL;
617 border->num_points = 0;
618 border->max_points = 0;
620 border->valid =
FALSE;
627 border->num_points = 0;
629 border->valid =
FALSE;
642 border->num_points = 0;
643 border->max_points = 0;
645 border->valid =
FALSE;
664 for ( ; count > 0; count--, num_points++, point++, tags++ )
668 if ( in_contour != 0 )
673 else if ( in_contour == 0 )
683 if ( in_contour != 0 )
686 border->valid =
TRUE;
689 *anum_points = num_points;
690 *anum_contours = num_contours;
707 border->num_points );
716 for ( ; count > 0; count--, read++, write++ )
735 for ( ; count > 0; count--, tags++, idx++ )
759 #define FT_SIDE_TO_ROTATE( s ) ( FT_ANGLE_PI2 - (s) * FT_ANGLE_PI )
761 typedef struct FT_StrokerRec_
800 memory = library->memory;
825 stroker->radius = radius;
826 stroker->line_cap = line_cap;
827 stroker->line_join = line_join;
828 stroker->miter_limit = miter_limit;
831 if ( stroker->miter_limit < 0x10000 )
832 stroker->miter_limit = 0x10000;
836 stroker->line_join_saved = line_join;
862 FT_Memory memory = stroker->library->memory;
868 stroker->library =
NULL;
887 total =
FT_Angle_Diff( stroker->angle_in, stroker->angle_out );
894 stroker->angle_in + rotate,
896 border->movable =
FALSE;
913 stroker->angle_in =
angle;
930 delta.
x += stroker->center.x + delta2.
x;
931 delta.
y += stroker->center.y + delta2.
y;
940 delta.
x += delta2.
x + stroker->center.x;
941 delta.
y += delta2.
y + stroker->center.y;
956 delta.
x += stroker->center.x;
957 delta.
y += stroker->center.y;
965 delta.
x += stroker->center.x;
966 delta.
y += stroker->center.y;
992 theta =
FT_Angle_Diff( stroker->angle_in, stroker->angle_out ) / 2;
996 if ( !border->movable || line_length == 0 )
1005 intersect =
FT_BOOL( stroker->line_length >= min_length &&
1006 line_length >= min_length );
1012 stroker->angle_out + rotate );
1013 delta.
x += stroker->center.x;
1014 delta.
y += stroker->center.y;
1016 border->movable =
FALSE;
1021 phi = stroker->angle_in + theta;
1025 length =
FT_DivFix( stroker->radius, thcos );
1028 delta.
x += stroker->center.x;
1029 delta.
y += stroker->center.y;
1054 FT_Fixed sigma = 0, radius = stroker->radius;
1070 theta =
FT_Angle_Diff( stroker->angle_in, stroker->angle_out );
1075 phi = stroker->angle_in;
1080 phi = stroker->angle_in + theta + rotate;
1084 sigma =
FT_MulFix( stroker->miter_limit, thcos );
1087 if ( sigma < 0x10000L )
1091 if ( fixed_bevel ||
ft_pos_abs( theta ) > 57 )
1107 stroker->angle_out + rotate );
1108 delta.
x += stroker->center.x;
1109 delta.
y += stroker->center.y;
1111 border->movable =
FALSE;
1123 FT_MulFix( radius, stroker->miter_limit ),
1125 middle.
x += stroker->center.x;
1126 middle.
y += stroker->center.y;
1134 delta.
x += middle.
x;
1135 delta.
y += middle.
y;
1143 delta.
x += middle.
x;
1144 delta.
y += middle.
y;
1152 if ( line_length == 0 )
1156 stroker->angle_out + rotate );
1158 delta.
x += stroker->center.x;
1159 delta.
y += stroker->center.y;
1171 length =
FT_DivFix( stroker->radius, thcos );
1174 delta.
x += stroker->center.x;
1175 delta.
y += stroker->center.y;
1183 if ( line_length == 0 )
1187 stroker->angle_out + rotate );
1188 delta.
x += stroker->center.x;
1189 delta.
y += stroker->center.y;
1210 turn =
FT_Angle_Diff( stroker->angle_in, stroker->angle_out );
1252 point.
x = stroker->center.x + delta.
x;
1253 point.
y = stroker->center.y + delta.
y;
1255 border = stroker->borders;
1260 point.
x = stroker->center.x - delta.
x;
1261 point.
y = stroker->center.y - delta.
y;
1268 stroker->subpath_angle = start_angle;
1269 stroker->first_point =
FALSE;
1270 stroker->subpath_line_length = line_length;
1291 delta.
x = to->x - stroker->center.x;
1292 delta.
y = to->y - stroker->center.y;
1295 if ( delta.
x == 0 && delta.
y == 0 )
1305 if ( stroker->first_point )
1317 stroker->angle_out =
angle;
1324 for ( border = stroker->borders, side = 1; side >= 0; side--, border++ )
1329 point.
x = to->x + delta.
x;
1330 point.
y = to->y + delta.
y;
1341 stroker->angle_in =
angle;
1342 stroker->center = *to;
1343 stroker->line_length = line_length;
1366 if (
FT_IS_SMALL( stroker->center.x - control->x ) &&
1371 stroker->center = *to;
1378 arc[2] = stroker->center;
1380 while ( arc >= bez_stack )
1386 angle_in = angle_out = stroker->angle_in;
1391 if ( stroker->first_point )
1392 stroker->angle_in = angle_in;
1404 if ( stroker->first_point )
1408 stroker->angle_out = angle_in;
1417 stroker->center = arc[2];
1418 stroker->angle_out = angle_in;
1424 stroker->line_join = stroker->line_join_saved;
1434 FT_Angle theta, phi, rotate, alpha0 = 0;
1441 phi = angle_in + theta;
1445 if ( stroker->handle_wide_strokes )
1446 alpha0 =
FT_Atan2( arc[0].
x - arc[2].
x, arc[0].
y - arc[2].
y );
1448 for ( border = stroker->borders, side = 0;
1464 if ( stroker->handle_wide_strokes )
1472 start = border->points[border->num_points - 1];
1487 beta =
FT_Atan2( arc[2].x - start.
x, arc[2].
y - start.
y );
1488 gamma =
FT_Atan2( arc[0].x - end.
x, arc[0].
y - end.
y );
1490 bvec.
x = end.
x - start.
x;
1491 bvec.
y = end.
y - start.
y;
1505 border->movable =
FALSE;
1535 stroker->angle_in = angle_out;
1538 stroker->center = *to;
1562 if (
FT_IS_SMALL( stroker->center.x - control1->x ) &&
1569 stroker->center = *to;
1577 arc[3] = stroker->center;
1579 while ( arc >= bez_stack )
1581 FT_Angle angle_in, angle_mid, angle_out;
1585 angle_in = angle_out = angle_mid = stroker->angle_in;
1589 &angle_mid, &angle_out ) )
1591 if ( stroker->first_point )
1592 stroker->angle_in = angle_in;
1604 if ( stroker->first_point )
1608 stroker->angle_out = angle_in;
1617 stroker->center = arc[3];
1618 stroker->angle_out = angle_in;
1624 stroker->line_join = stroker->line_join_saved;
1634 FT_Angle theta1, phi1, theta2, phi2, rotate, alpha0 = 0;
1648 if ( stroker->handle_wide_strokes )
1649 alpha0 =
FT_Atan2( arc[0].
x - arc[3].
x, arc[0].
y - arc[3].
y );
1651 for ( border = stroker->borders, side = 0;
1659 ctrl1.
x += arc[2].
x;
1660 ctrl1.
y += arc[2].
y;
1663 ctrl2.
x += arc[1].
x;
1664 ctrl2.
y += arc[1].
y;
1671 if ( stroker->handle_wide_strokes )
1679 start = border->points[border->num_points - 1];
1694 beta =
FT_Atan2( arc[3].x - start.
x, arc[3].
y - start.
y );
1695 gamma =
FT_Atan2( arc[0].x - end.
x, arc[0].
y - end.
y );
1697 bvec.
x = end.
x - start.
x;
1698 bvec.
y = end.
y - start.
y;
1712 border->movable =
FALSE;
1745 stroker->angle_in = angle_out;
1748 stroker->center = *to;
1766 stroker->first_point =
TRUE;
1767 stroker->center = *to;
1768 stroker->subpath_open = open;
1775 stroker->handle_wide_strokes =
1777 ( stroker->subpath_open &&
1781 stroker->subpath_start = *to;
1783 stroker->angle_in = 0;
1801 new_points = left->num_points - left->start;
1802 if ( new_points > 0 )
1809 FT_Vector* dst_point = right->points + right->num_points;
1810 FT_Byte* dst_tag = right->tags + right->num_points;
1811 FT_Vector* src_point = left->points + left->num_points - 1;
1812 FT_Byte* src_tag = left->tags + left->num_points - 1;
1815 while ( src_point >= left->points + left->start )
1817 *dst_point = *src_point;
1818 *dst_tag = *src_tag;
1841 left->num_points = left->start;
1842 right->num_points += new_points;
1844 right->movable =
FALSE;
1845 left->movable =
FALSE;
1862 if ( stroker->subpath_open )
1880 stroker->center = stroker->subpath_start;
1897 if ( stroker->center.x != stroker->subpath_start.x ||
1898 stroker->center.y != stroker->subpath_start.y )
1906 stroker->angle_out = stroker->subpath_angle;
1908 stroker->angle_out );
1922 stroker->subpath_line_length );
1929 stroker->subpath_line_length );
1952 FT_UInt num_points = 0, num_contours = 0;
1956 if ( !stroker || border > 1 )
1963 &num_points, &num_contours );
1966 *anum_points = num_points;
1968 if ( anum_contours )
1969 *anum_contours = num_contours;
1982 FT_UInt count1, count2, num_points = 0;
1983 FT_UInt count3, count4, num_contours = 0;
1997 num_points = count1 + count3;
1998 num_contours = count2 + count4;
2001 *anum_points = num_points;
2002 *anum_contours = num_contours;
2020 if ( sborder->valid )
2063 if ( !outline || !stroker )
2070 for ( n = 0; n < outline->n_contours; n++ )
2075 last = outline->contours[
n];
2076 limit = outline->points + last;
2079 if ( last <= first )
2085 v_start = outline->points[
first];
2086 v_last = outline->points[last];
2088 v_control = v_start;
2090 point = outline->points +
first;
2091 tags = outline->tags +
first;
2096 goto Invalid_Outline;
2112 v_start.
x = ( v_start.
x + v_last.
x ) / 2;
2113 v_start.
y = ( v_start.
y + v_last.
y ) / 2;
2123 while ( point < limit )
2146 v_control.
x = point->
x;
2147 v_control.
y = point->
y;
2150 if ( point < limit )
2171 goto Invalid_Outline;
2173 v_middle.
x = ( v_control.
x + vec.
x ) / 2;
2174 v_middle.
y = ( v_control.
y + vec.
y ) / 2;
2192 if ( point + 1 > limit ||
2194 goto Invalid_Outline;
2202 if ( point <= limit )
2226 if ( !stroker->first_point )
2249 #ifndef FT_CONFIG_OPTION_PIC
2269 if ( pglyph ==
NULL )
2290 FT_UInt num_points, num_contours;
2302 num_points, num_contours, outline );
2345 if ( pglyph ==
NULL )
2367 FT_UInt num_points, num_contours;
2384 &num_points, &num_contours );
enum FT_Stroker_LineCap_ FT_Stroker_LineCap
FT_Stroker_ParseOutline(FT_Stroker stroker, FT_Outline *outline, FT_Bool opened)
FT_DivFix(FT_Long a, FT_Long b)
#define FT_ARC_CUBIC_ANGLE
const FT_Glyph_Class * clazz
struct FT_OutlineGlyphRec_ * FT_OutlineGlyph
FT_BEGIN_HEADER typedef signed long FT_Pos
struct FT_StrokeBorderRec_ FT_StrokeBorderRec
GLvoid **typedef void(GLAPIENTRY *PFNGLGETVERTEXATTRIBDVPROC)(GLuint
typedefFT_BEGIN_HEADER struct FT_Glyph_Class_ FT_Glyph_Class
FT_Stroker_Rewind(FT_Stroker stroker)
#define FT_CURVE_TAG_CUBIC
const FT_Glyph_Class ft_outline_glyph_class
#define FT_ARRAY_COPY(dest, source, count)
struct FT_StrokeBorderRec_ * FT_StrokeBorder
static void ft_conic_split(FT_Vector *base)
return FT_Err_Invalid_Argument
enum FT_Orientation_ FT_Orientation
FT_Glyph_Copy(FT_Glyph source, FT_Glyph *target)
FT_Outline_Get_Orientation(FT_Outline *outline)
static FT_Error ft_stroker_arcto(FT_Stroker stroker, FT_Int side)
#define FT_SMALL_CONIC_THRESHOLD
GLboolean GLboolean GLboolean GLboolean a
static FT_Error ft_stroker_outside(FT_Stroker stroker, FT_Int side, FT_Fixed line_length)
FT_Stroker_GetBorderCounts(FT_Stroker stroker, FT_StrokerBorder border, FT_UInt *anum_points, FT_UInt *anum_contours)
static FT_Error ft_stroke_border_lineto(FT_StrokeBorder border, FT_Vector *to, FT_Bool movable)
static void ft_stroke_border_close(FT_StrokeBorder border, FT_Bool reverse)
return Display return Display Bool Bool int d
static FT_Pos ft_pos_abs(FT_Pos x)
static FT_Error ft_stroker_subpath_start(FT_Stroker stroker, FT_Angle start_angle, FT_Fixed line_length)
FT_BEGIN_HEADER typedef unsigned char FT_Bool
FT_Glyph_StrokeBorder(FT_Glyph *pglyph, FT_Stroker stroker, FT_Bool inside, FT_Bool destroy)
FT_Stroker_ConicTo(FT_Stroker stroker, FT_Vector *control, FT_Vector *to)
static FT_Error ft_stroke_border_arcto(FT_StrokeBorder border, FT_Vector *center, FT_Fixed radius, FT_Angle angle_start, FT_Angle angle_diff)
#define FT_ASSERT(condition)
FT_Vector_From_Polar(FT_Vector *vec, FT_Fixed length, FT_Angle angle)
enum FT_StrokeTags_ FT_StrokeTags
#define FT_STROKE_TAG_BEGIN_END
FT_Outline_New(FT_Library library, FT_UInt numPoints, FT_Int numContours, FT_Outline *anoutline)
FT_Atan2(FT_Fixed x, FT_Fixed y)
enum FT_StrokerBorder_ FT_StrokerBorder
FT_Stroker_ExportBorder(FT_Stroker stroker, FT_StrokerBorder border, FT_Outline *outline)
FT_MulDiv(FT_Long a, FT_Long b, FT_Long c)
FT_Stroker_BeginSubPath(FT_Stroker stroker, FT_Vector *to, FT_Bool open)
FT_Outline_Done(FT_Library library, FT_Outline *outline)
struct FT_StrokerRec_ FT_StrokerRec
FT_Stroker_LineTo(FT_Stroker stroker, FT_Vector *to)
static FT_Bool ft_cubic_is_small_enough(FT_Vector *base, FT_Angle *angle_in, FT_Angle *angle_mid, FT_Angle *angle_out)
static FT_Error ft_stroker_process_corner(FT_Stroker stroker, FT_Fixed line_length)
static FT_Error ft_stroker_inside(FT_Stroker stroker, FT_Int side, FT_Fixed line_length)
FT_BEGIN_HEADER typedef FT_Fixed FT_Angle
FT_Stroker_EndSubPath(FT_Stroker stroker)
#define FT_RENEW_ARRAY(ptr, curcnt, newcnt)
FT_Stroker_Export(FT_Stroker stroker, FT_Outline *outline)
GLint GLenum GLsizei GLsizei GLsizei GLint border
static void ft_stroke_border_done(FT_StrokeBorder border)
FT_Glyph_Stroke(FT_Glyph *pglyph, FT_Stroker stroker, FT_Bool destroy)
#define FT_SIDE_TO_ROTATE(s)
local int destroy(gz_stream *s)
#define FT_SMALL_CUBIC_THRESHOLD
typedefFT_BEGIN_HEADER struct FT_MemoryRec_ * FT_Memory
static void ft_stroke_border_reset(FT_StrokeBorder border)
FT_Stroker_Set(FT_Stroker stroker, FT_Fixed radius, FT_Stroker_LineCap line_cap, FT_Stroker_LineJoin line_join, FT_Fixed miter_limit)
enum FT_Stroker_LineJoin_ FT_Stroker_LineJoin
FT_Stroker_CubicTo(FT_Stroker stroker, FT_Vector *control1, FT_Vector *control2, FT_Vector *to)
EGLSurface EGLint EGLint y
FT_MulFix(FT_Long a, FT_Long b)
FT_Outline_GetInsideBorder(FT_Outline *outline)
FT_Outline_Check(FT_Outline *outline)
#define FT_OUTLINE_GLYPH_CLASS_GET
static FT_Angle ft_angle_mean(FT_Angle angle1, FT_Angle angle2)
static FT_Error ft_stroke_border_cubicto(FT_StrokeBorder border, FT_Vector *control1, FT_Vector *control2, FT_Vector *to)
static FT_Bool ft_conic_is_small_enough(FT_Vector *base, FT_Angle *angle_in, FT_Angle *angle_out)
FT_Angle_Diff(FT_Angle angle1, FT_Angle angle2)
FT_Stroker_Done(FT_Stroker stroker)
static FT_Error ft_stroke_border_get_counts(FT_StrokeBorder border, FT_UInt *anum_points, FT_UInt *anum_contours)
static void ft_stroke_border_export(FT_StrokeBorder border, FT_Outline *outline)
static FT_Error ft_stroker_cap(FT_Stroker stroker, FT_Angle angle, FT_Int side)
GLdouble GLdouble GLdouble b
FT_Stroker_New(FT_Library library, FT_Stroker *astroker)
typedefFT_BEGIN_HEADER struct FT_StrokerRec_ * FT_Stroker
FT_Outline_GetOutsideBorder(FT_Outline *outline)
FT_Vector_Length(FT_Vector *vec)
GLuint GLdouble GLdouble GLint GLint const GLdouble * points
#define FT_CURVE_TAG_CONIC
static FT_Error ft_stroke_border_moveto(FT_StrokeBorder border, FT_Vector *to)
static void ft_cubic_split(FT_Vector *base)
#define FT_CURVE_TAG(flag)
FT_Stroker_GetCounts(FT_Stroker stroker, FT_UInt *anum_points, FT_UInt *anum_contours)
static FT_Error ft_stroke_border_conicto(FT_StrokeBorder border, FT_Vector *control, FT_Vector *to)
FT_Done_Glyph(FT_Glyph glyph)
static FT_Error ft_stroke_border_grow(FT_StrokeBorder border, FT_UInt new_points)
return FT_Err_Invalid_Outline
static FT_Error ft_stroker_add_reverse_left(FT_Stroker stroker, FT_Bool open)
static void ft_stroke_border_init(FT_StrokeBorder border, FT_Memory memory)