diff options
Diffstat (limited to 'nx-X11/extras/freetype2/src/autofit/afhints.c')
-rw-r--r-- | nx-X11/extras/freetype2/src/autofit/afhints.c | 989 |
1 files changed, 989 insertions, 0 deletions
diff --git a/nx-X11/extras/freetype2/src/autofit/afhints.c b/nx-X11/extras/freetype2/src/autofit/afhints.c new file mode 100644 index 000000000..a1a50dce3 --- /dev/null +++ b/nx-X11/extras/freetype2/src/autofit/afhints.c @@ -0,0 +1,989 @@ +#include "afhints.h" + +#ifdef AF_DEBUG + +#include <stdio.h> + + static const char* af_dir_str( AF_Direction dir ) + { + const char* result; + + switch (dir) + { + case AF_DIR_UP: result = "up"; break; + case AF_DIR_DOWN: result = "down"; break; + case AF_DIR_LEFT: result = "left"; break; + case AF_DIR_RIGHT: result = "right"; break; + default: result = "none"; + } + return result; + } + +#define AF_INDEX_NUM(ptr,base) ( (ptr) ? ((ptr)-(base)) : -1 ) + + void + af_glyph_hints_dump_points( AF_GlyphHints hints ) + { + AF_Point points = hints->points; + AF_Point limit = points + hints->num_points; + AF_Point point; + + printf( "Table of points:\n" ); + printf( " [ index | xorg | yorg | xscale | yscale | xfit | yfit | flags ]\n" ); + for ( point = points; point < limit; point++ ) + { + printf( " [ %5d | %5d | %5d | %-5.2f | %-5.2f | %-5.2f | %-5.2f | %c%c%c%c%c%c ]\n", + point - points, + point->fx, + point->fy, + point->ox/64.0, + point->oy/64.0, + point->x/64.0, + point->y/64.0, + (point->flags & AF_FLAG_WEAK_INTERPOLATION) ? 'w' : ' ', + (point->flags & AF_FLAG_INFLECTION) ? 'i' : ' ', + (point->flags & AF_FLAG_EXTREMA_X) ? '<' : ' ', + (point->flags & AF_FLAG_EXTREMA_Y) ? 'v' : ' ', + (point->flags & AF_FLAG_ROUND_X) ? '(' : ' ', + (point->flags & AF_FLAG_ROUND_Y) ? 'u' : ' ' + ); + } + printf( "\n" ); + } + + + /* A function used to dump the array of linked segments */ + void + af_glyph_hints_dump_segments( AF_GlyphHints hints ) + { + AF_Point points = hints->points; + FT_Int dimension; + + for ( dimension = 1; dimension >= 0; dimension-- ) + { + AF_AxisHints axis = &hints->axis[dimension]; + AF_Segment segments = axis->segments; + AF_Segment limit = segments + axis->num_segments; + AF_Segment seg; + + + printf ( "Table of %s segments:\n", + dimension == AF_DIMENSION_HORZ ? "vertical" : "horizontal" ); + printf ( " [ index | pos | dir | link | serif |" + " numl | first | start ]\n" ); + + for ( seg = segments; seg < limit; seg++ ) + { + printf ( " [ %5d | %4d | %5s | %4d | %5d | %4d | %5d | %5d ]\n", + seg - segments, + (int)seg->pos, + af_dir_str( seg->dir ), + AF_INDEX_NUM( seg->link, segments ), + AF_INDEX_NUM( seg->serif, segments ), + (int)seg->num_linked, + seg->first - points, + seg->last - points ); + } + printf( "\n" ); + } + } + + + void + af_glyph_hints_dump_edges( AF_GlyphHints hints ) + { + FT_Int dimension; + + for ( dimension = 1; dimension >= 0; dimension-- ) + { + AF_AxisHints axis = &hints->axis[ dimension ]; + AF_Edge edges = axis->edges; + AF_Edge limit = edges + axis->num_edges; + AF_Edge edge; + + /* note: AF_DIMENSION_HORZ corresponds to _vertical_ edges + * since they have constant X coordinate + */ + printf ( "Table of %s edges:\n", + dimension == AF_DIMENSION_HORZ ? "vertical" : "horizontal" ); + printf ( " [ index | pos | dir | link |" + " serif | blue | opos | pos ]\n" ); + + for ( edge = edges; edge < limit; edge++ ) + { + printf ( " [ %5d | %4d | %5s | %4d | %5d | %c | %5.2f | %5.2f ]\n", + edge - edges, + (int)edge->fpos, + af_dir_str( edge->dir ), + AF_INDEX_NUM( edge->link, edges ), + AF_INDEX_NUM( edge->serif, edges ), + edge->blue_edge ? 'y' : 'n', + edge->opos / 64.0, + edge->pos / 64.0 ); + } + + printf( "\n" ); + } + } + + + +#endif /* AF_DEBUG */ + + + /* compute the direction value of a given vector */ + FT_LOCAL_DEF( AF_Direction ) + af_direction_compute( FT_Pos dx, + FT_Pos dy ) + { + AF_Direction dir; + FT_Pos ax = FT_ABS( dx ); + FT_Pos ay = FT_ABS( dy ); + + + dir = AF_DIR_NONE; + + /* atan(1/12) == 4.7 degrees */ + + /* test for vertical direction */ + if ( ax * 12 < ay ) + { + dir = dy > 0 ? AF_DIR_UP : AF_DIR_DOWN; + } + /* test for horizontal direction */ + else if ( ay * 12 < ax ) + { + dir = dx > 0 ? AF_DIR_RIGHT : AF_DIR_LEFT; + } + + return dir; + } + + + /* compute all inflex points in a given glyph */ + static void + af_glyph_hints_compute_inflections( AF_GlyphHints hints ) + { + AF_Point* contour = hints->contours; + AF_Point* contour_limit = contour + hints->num_contours; + + + /* do each contour separately */ + for ( ; contour < contour_limit; contour++ ) + { + AF_Point point = contour[0]; + AF_Point first = point; + AF_Point start = point; + AF_Point end = point; + AF_Point before; + AF_Point after; + AF_Angle angle_in, angle_seg, angle_out; + AF_Angle diff_in, diff_out; + FT_Int finished = 0; + + + /* compute first segment in contour */ + first = point; + + start = end = first; + do + { + end = end->next; + if ( end == first ) + goto Skip; + + } while ( end->fx == first->fx && end->fy == first->fy ); + + angle_seg = af_angle_atan( end->fx - start->fx, + end->fy - start->fy ); + + /* extend the segment start whenever possible */ + before = start; + do + { + do + { + start = before; + before = before->prev; + if ( before == first ) + goto Skip; + + } while ( before->fx == start->fx && before->fy == start->fy ); + + angle_in = af_angle_atan( start->fx - before->fx, + start->fy - before->fy ); + + } while ( angle_in == angle_seg ); + + first = start; + diff_in = af_angle_diff( angle_in, angle_seg ); + + /* now, process all segments in the contour */ + do + { + /* first, extend current segment's end whenever possible */ + after = end; + do + { + do + { + end = after; + after = after->next; + if ( after == first ) + finished = 1; + + } while ( end->fx == after->fx && end->fy == after->fy ); + + angle_out = af_angle_atan( after->fx - end->fx, + after->fy - end->fy ); + + } while ( angle_out == angle_seg ); + + diff_out = af_angle_diff( angle_seg, angle_out ); + + if ( ( diff_in ^ diff_out ) < 0 ) + { + /* diff_in and diff_out have different signs, we have */ + /* inflection points here... */ + do + { + start->flags |= AF_FLAG_INFLECTION; + start = start->next; + + } while ( start != end ); + + start->flags |= AF_FLAG_INFLECTION; + } + + start = end; + end = after; + angle_seg = angle_out; + diff_in = diff_out; + + } while ( !finished ); + + Skip: + ; + } + } + + + + FT_LOCAL_DEF( void ) + af_glyph_hints_init( AF_GlyphHints hints, + FT_Memory memory ) + { + FT_ZERO( hints ); + hints->memory = memory; + } + + + + FT_LOCAL_DEF( void ) + af_glyph_hints_done( AF_GlyphHints hints ) + { + if ( hints && hints->memory ) + { + FT_Memory memory = hints->memory; + AF_Dimension dim; + + /* note that we don't need to free the segment and edge + * buffers, since they're really within the hints->points array + */ + for ( dim = 0; dim < 2; dim++ ) + { + AF_AxisHints axis = &hints->axis[ dim ]; + + axis->num_segments = 0; + axis->num_edges = 0; + axis->segments = NULL; + axis->edges = NULL; + } + + FT_FREE( hints->contours ); + hints->max_contours = 0; + hints->num_contours = 0; + + FT_FREE( hints->points ); + hints->num_points = 0; + hints->max_points = 0; + + hints->memory = NULL; + } + } + + + + FT_LOCAL_DEF( void ) + af_glyph_hints_rescale( AF_GlyphHints hints, + AF_ScriptMetrics metrics ) + { + hints->metrics = metrics; + } + + + FT_LOCAL_DEF( FT_Error ) + af_glyph_hints_reload( AF_GlyphHints hints, + FT_Outline* outline ) + { + FT_Error error = FT_Err_Ok; + AF_Point points; + FT_UInt old_max, new_max; + AF_Scaler scaler = &hints->metrics->scaler; + FT_Fixed x_scale = hints->x_scale; + FT_Fixed y_scale = hints->y_scale; + FT_Pos x_delta = hints->x_delta; + FT_Pos y_delta = hints->y_delta; + FT_Memory memory = hints->memory; + + hints->scaler_flags = scaler->flags; + hints->num_points = 0; + hints->num_contours = 0; + + hints->axis[0].num_segments = 0; + hints->axis[0].num_edges = 0; + hints->axis[1].num_segments = 0; + hints->axis[1].num_edges = 0; + + /* first of all, reallocate the contours array when necessary + */ + new_max = (FT_UInt) outline->n_contours; + old_max = hints->max_contours; + if ( new_max > old_max ) + { + new_max = (new_max + 3) & ~3; + + if ( FT_RENEW_ARRAY( hints->contours, old_max, new_max ) ) + goto Exit; + + hints->max_contours = new_max; + } + + /* then, reallocate the points, segments & edges arrays if needed -- + * note that we reserved two additional point positions, used to + * hint metrics appropriately + */ + new_max = (FT_UInt)( outline->n_points + 2 ); + old_max = hints->max_points; + if ( new_max > old_max ) + { + FT_Byte* items; + FT_ULong off1, off2, off3; + + /* we store in a single buffer the following arrays: + * + * - an array of N AF_PointRec items + * - an array of 2*N AF_SegmentRec items + * - an array of 2*N AF_EdgeRec items + * + */ + + new_max = ( new_max + 2 + 7 ) & ~7; + +#define OFF_PAD2(x,y) (((x)+(y)-1) & ~((y)-1)) +#define OFF_PADX(x,y) ((((x)+(y)-1)/(y))*(y)) +#define OFF_PAD(x,y) ( ((y) & ((y)-1)) ? OFF_PADX(x,y) : OFF_PAD2(x,y) ) + +#undef OFF_INCREMENT +#define OFF_INCREMENT( _off, _type, _count ) \ + ( OFF_PAD( _off, sizeof(_type) ) + (_count)*sizeof(_type)) + + off1 = OFF_INCREMENT( 0, AF_PointRec, new_max ); + off2 = OFF_INCREMENT( off1, AF_SegmentRec, new_max*2 ); + off3 = OFF_INCREMENT( off2, AF_EdgeRec, new_max*2 ); + + FT_FREE( hints->points ); + + if ( FT_ALLOC( items, off3 ) ) + { + hints->max_points = 0; + hints->axis[0].segments = NULL; + hints->axis[0].edges = NULL; + hints->axis[1].segments = NULL; + hints->axis[1].edges = NULL; + goto Exit; + } + + /* readjust some pointers + */ + hints->max_points = new_max; + hints->points = (AF_Point) items; + + hints->axis[0].segments = (AF_Segment)( items + off1 ); + hints->axis[1].segments = hints->axis[0].segments + new_max; + + hints->axis[0].edges = (AF_Edge) ( items + off2 ); + hints->axis[1].edges = hints->axis[0].edges + new_max; + } + + hints->num_points = outline->n_points; + hints->num_contours = outline->n_contours; + + + /* We can't rely on the value of `FT_Outline.flags' to know the fill */ + /* direction used for a glyph, given that some fonts are broken (e.g. */ + /* the Arphic ones). We thus recompute it each time we need to. */ + /* */ + hints->axis[ AF_DIMENSION_HORZ ].major_dir = AF_DIR_UP; + hints->axis[ AF_DIMENSION_VERT ].major_dir = AF_DIR_LEFT; + + if ( FT_Outline_Get_Orientation( outline ) == FT_ORIENTATION_POSTSCRIPT ) + { + hints->axis[ AF_DIMENSION_HORZ ].major_dir = AF_DIR_DOWN; + hints->axis[ AF_DIMENSION_VERT ].major_dir = AF_DIR_RIGHT; + } + + hints->x_scale = x_scale; + hints->y_scale = y_scale; + hints->x_delta = x_delta; + hints->y_delta = y_delta; + + points = hints->points; + if ( hints->num_points == 0 ) + goto Exit; + + { + AF_Point point; + AF_Point point_limit = points + hints->num_points; + + + /* compute coordinates & bezier flags */ + { + FT_Vector* vec = outline->points; + char* tag = outline->tags; + + + for ( point = points; point < point_limit; point++, vec++, tag++ ) + { + point->fx = vec->x; + point->fy = vec->y; + point->ox = point->x = FT_MulFix( vec->x, x_scale ) + x_delta; + point->oy = point->y = FT_MulFix( vec->y, y_scale ) + y_delta; + + switch ( FT_CURVE_TAG( *tag ) ) + { + case FT_CURVE_TAG_CONIC: + point->flags = AF_FLAG_CONIC; + break; + case FT_CURVE_TAG_CUBIC: + point->flags = AF_FLAG_CUBIC; + break; + default: + point->flags = 0; + ; + } + } + } + + /* compute `next' and `prev' */ + { + FT_Int contour_index; + AF_Point prev; + AF_Point first; + AF_Point end; + + + contour_index = 0; + + first = points; + end = points + outline->contours[0]; + prev = end; + + for ( point = points; point < point_limit; point++ ) + { + point->prev = prev; + if ( point < end ) + { + point->next = point + 1; + prev = point; + } + else + { + point->next = first; + contour_index++; + if ( point + 1 < point_limit ) + { + end = points + outline->contours[contour_index]; + first = point + 1; + prev = end; + } + } + } + } + + /* set-up the contours array */ + { + AF_Point* contour = hints->contours; + AF_Point* contour_limit = contour + hints->num_contours; + short* end = outline->contours; + short idx = 0; + + + for ( ; contour < contour_limit; contour++, end++ ) + { + contour[0] = points + idx; + idx = (short)( end[0] + 1 ); + } + } + + /* compute directions of in & out vectors */ + { + for ( point = points; point < point_limit; point++ ) + { + AF_Point prev; + AF_Point next; + FT_Pos in_x, in_y, out_x, out_y; + + + prev = point->prev; + in_x = point->fx - prev->fx; + in_y = point->fy - prev->fy; + + point->in_dir = af_direction_compute( in_x, in_y ); + + next = point->next; + out_x = next->fx - point->fx; + out_y = next->fy - point->fy; + + point->out_dir = af_direction_compute( out_x, out_y ); + + if ( point->flags & ( AF_FLAG_CONIC | AF_FLAG_CUBIC ) ) + { + Is_Weak_Point: + point->flags |= AF_FLAG_WEAK_INTERPOLATION; + } + else if ( point->out_dir == point->in_dir ) + { + AF_Angle angle_in, angle_out, delta; + + + if ( point->out_dir != AF_DIR_NONE ) + goto Is_Weak_Point; + + angle_in = af_angle_atan( in_x, in_y ); + angle_out = af_angle_atan( out_x, out_y ); + delta = af_angle_diff( angle_in, angle_out ); + + if ( delta < 2 && delta > -2 ) + goto Is_Weak_Point; + } + else if ( point->in_dir == -point->out_dir ) + goto Is_Weak_Point; + } + } + } + + /* compute inflection points + */ + af_glyph_hints_compute_inflections( hints ); + + Exit: + return error; + } + + + FT_LOCAL_DEF( void ) + af_glyph_hints_save( AF_GlyphHints hints, + FT_Outline* outline ) + { + AF_Point point = hints->points; + AF_Point limit = point + hints->num_points; + FT_Vector* vec = outline->points; + char* tag = outline->tags; + + for ( ; point < limit; point++, vec++, tag++ ) + { + vec->x = (FT_Pos) point->x; + vec->y = (FT_Pos) point->y; + + if ( point->flags & AF_FLAG_CONIC ) + tag[0] = FT_CURVE_TAG_CONIC; + else if ( point->flags & AF_FLAG_CUBIC ) + tag[0] = FT_CURVE_TAG_CUBIC; + else + tag[0] = FT_CURVE_TAG_ON; + } + } + + + /* + * + * E D G E P O I N T G R I D - F I T T I N G + * + */ + + + FT_LOCAL_DEF( void ) + af_glyph_hints_align_edge_points( AF_GlyphHints hints, + AF_Dimension dim ) + { + AF_AxisHints axis = & hints->axis[ dim ]; + AF_Edge edges = axis->edges; + AF_Edge edge_limit = edges + axis->num_edges; + AF_Edge edge; + + for ( edge = edges; edge < edge_limit; edge++ ) + { + /* move the points of each segment */ + /* in each edge to the edge's position */ + AF_Segment seg = edge->first; + + + do + { + AF_Point point = seg->first; + + + for (;;) + { + if ( dim == AF_DIMENSION_HORZ ) + { + point->x = edge->pos; + point->flags |= AF_FLAG_TOUCH_X; + } + else + { + point->y = edge->pos; + point->flags |= AF_FLAG_TOUCH_Y; + } + + if ( point == seg->last ) + break; + + point = point->next; + } + + seg = seg->edge_next; + + } while ( seg != edge->first ); + } + } + + + /* + * + * S T R O N G P O I N T I N T E R P O L A T I O N + * + */ + + + /* hint the strong points -- this is equivalent to the TrueType `IP' */ + /* hinting instruction */ + FT_LOCAL_DEF( void ) + af_glyph_hints_align_strong_points( AF_GlyphHints hints, + AF_Dimension dim ) + { + AF_Point points = hints->points; + AF_Point point_limit = points + hints->num_points; + AF_AxisHints axis = &hints->axis[dim]; + AF_Edge edges = axis->edges; + AF_Edge edge_limit = edges + axis->num_edges; + AF_Flags touch_flag; + + + if ( dim == AF_DIMENSION_HORZ ) + touch_flag = AF_FLAG_TOUCH_X; + else + touch_flag = AF_FLAG_TOUCH_Y; + + if ( edges < edge_limit ) + { + AF_Point point; + AF_Edge edge; + + for ( point = points; point < point_limit; point++ ) + { + FT_Pos u, ou, fu; /* point position */ + FT_Pos delta; + + + if ( point->flags & touch_flag ) + continue; + + /* if this point is candidate to weak interpolation, we will */ + /* interpolate it after all strong points have been processed */ + if ( ( point->flags & AF_FLAG_WEAK_INTERPOLATION ) && + !( point->flags & AF_FLAG_INFLECTION ) ) + continue; + + if ( dim == AF_DIMENSION_VERT ) + { + u = point->fy; + ou = point->oy; + } + else + { + u = point->fx; + ou = point->ox; + } + + fu = u; + + /* is the point before the first edge? */ + edge = edges; + delta = edge->fpos - u; + if ( delta >= 0 ) + { + u = edge->pos - ( edge->opos - ou ); + goto Store_Point; + } + + /* is the point after the last edge? */ + edge = edge_limit - 1; + delta = u - edge->fpos; + if ( delta >= 0 ) + { + u = edge->pos + ( ou - edge->opos ); + goto Store_Point; + } + + { + FT_UInt min, max, mid; + FT_Pos fpos; + + + /* find enclosing edges */ + min = 0; + max = edge_limit - edges; + + while ( min < max ) + { + mid = ( max + min ) >> 1; + edge = edges + mid; + fpos = edge->fpos; + + if ( u < fpos ) + max = mid; + else if ( u > fpos ) + min = mid + 1; + else + { + /* we are on the edge */ + u = edge->pos; + goto Store_Point; + } + } + + { + AF_Edge before = edges + min - 1; + AF_Edge after = edges + min + 0; + + + /* assert( before && after && before != after ) */ + if ( before->scale == 0 ) + before->scale = FT_DivFix( after->pos - before->pos, + after->fpos - before->fpos ); + + u = before->pos + FT_MulFix( fu - before->fpos, + before->scale ); + } + } + + + Store_Point: + + /* save the point position */ + if ( dim == AF_DIMENSION_HORZ ) + point->x = u; + else + point->y = u; + + point->flags |= touch_flag; + } + } + } + + + /* + * + * W E A K P O I N T I N T E R P O L A T I O N + * + */ + + static void + af_iup_shift( AF_Point p1, + AF_Point p2, + AF_Point ref ) + { + AF_Point p; + FT_Pos delta = ref->u - ref->v; + + + for ( p = p1; p < ref; p++ ) + p->u = p->v + delta; + + for ( p = ref + 1; p <= p2; p++ ) + p->u = p->v + delta; + } + + + static void + af_iup_interp( AF_Point p1, + AF_Point p2, + AF_Point ref1, + AF_Point ref2 ) + { + AF_Point p; + FT_Pos u; + FT_Pos v1 = ref1->v; + FT_Pos v2 = ref2->v; + FT_Pos d1 = ref1->u - v1; + FT_Pos d2 = ref2->u - v2; + + + if ( p1 > p2 ) + return; + + if ( v1 == v2 ) + { + for ( p = p1; p <= p2; p++ ) + { + u = p->v; + + if ( u <= v1 ) + u += d1; + else + u += d2; + + p->u = u; + } + return; + } + + if ( v1 < v2 ) + { + for ( p = p1; p <= p2; p++ ) + { + u = p->v; + + if ( u <= v1 ) + u += d1; + else if ( u >= v2 ) + u += d2; + else + u = ref1->u + FT_MulDiv( u - v1, ref2->u - ref1->u, v2 - v1 ); + + p->u = u; + } + } + else + { + for ( p = p1; p <= p2; p++ ) + { + u = p->v; + + if ( u <= v2 ) + u += d2; + else if ( u >= v1 ) + u += d1; + else + u = ref1->u + FT_MulDiv( u - v1, ref2->u - ref1->u, v2 - v1 ); + + p->u = u; + } + } + } + + + FT_LOCAL_DEF( void ) + af_glyph_hints_align_weak_points( AF_GlyphHints hints, + AF_Dimension dim ) + { + AF_Point points = hints->points; + AF_Point point_limit = points + hints->num_points; + AF_Point* contour = hints->contours; + AF_Point* contour_limit = contour + hints->num_contours; + AF_Flags touch_flag; + AF_Point point; + AF_Point end_point; + AF_Point first_point; + + + /* PASS 1: Move segment points to edge positions */ + + if ( dim == AF_DIMENSION_HORZ ) + { + touch_flag = AF_FLAG_TOUCH_X; + + for ( point = points; point < point_limit; point++ ) + { + point->u = point->x; + point->v = point->ox; + } + } + else + { + touch_flag = AF_FLAG_TOUCH_Y; + + for ( point = points; point < point_limit; point++ ) + { + point->u = point->y; + point->v = point->oy; + } + } + + point = points; + + for ( ; contour < contour_limit; contour++ ) + { + point = *contour; + end_point = point->prev; + first_point = point; + + while ( point <= end_point && !( point->flags & touch_flag ) ) + point++; + + if ( point <= end_point ) + { + AF_Point first_touched = point; + AF_Point cur_touched = point; + + + point++; + while ( point <= end_point ) + { + if ( point->flags & touch_flag ) + { + /* we found two successive touched points; we interpolate */ + /* all contour points between them */ + af_iup_interp( cur_touched + 1, point - 1, + cur_touched, point ); + cur_touched = point; + } + point++; + } + + if ( cur_touched == first_touched ) + { + /* this is a special case: only one point was touched in the */ + /* contour; we thus simply shift the whole contour */ + af_iup_shift( first_point, end_point, cur_touched ); + } + else + { + /* now interpolate after the last touched point to the end */ + /* of the contour */ + af_iup_interp( cur_touched + 1, end_point, + cur_touched, first_touched ); + + /* if the first contour point isn't touched, interpolate */ + /* from the contour start to the first touched point */ + if ( first_touched > points ) + af_iup_interp( first_point, first_touched - 1, + cur_touched, first_touched ); + } + } + } + + /* now save the interpolated values back to x/y */ + if ( dim == AF_DIMENSION_HORZ ) + { + for ( point = points; point < point_limit; point++ ) + point->x = point->u; + } + else + { + for ( point = points; point < point_limit; point++ ) + point->y = point->u; + } + } |