⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ftstroke.c

📁 下载来的一个看图软件的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
    /* copy tags */    {      FT_UInt   count = border->num_points;      FT_Byte*  read  = border->tags;      FT_Byte*  write = (FT_Byte*)outline->tags + outline->n_points;      for ( ; count > 0; count--, read++, write++ )      {        if ( *read & FT_STROKE_TAG_ON )          *write = FT_CURVE_TAG_ON;        else if ( *read & FT_STROKE_TAG_CUBIC )          *write = FT_CURVE_TAG_CUBIC;        else          *write = FT_CURVE_TAG_CONIC;      }    }    /* copy contours */    {      FT_UInt    count = border->num_points;      FT_Byte*   tags  = border->tags;      FT_Short*  write = outline->contours + outline->n_contours;      FT_Short   idx   = (FT_Short)outline->n_points;      for ( ; count > 0; count--, tags++, idx++ )      {        if ( *tags & FT_STROKE_TAG_END )        {          *write++ = idx;          outline->n_contours++;        }      }    }    outline->n_points  = (short)( outline->n_points + border->num_points );    FT_ASSERT( FT_Outline_Check( outline ) == 0 );  } /***************************************************************************/ /***************************************************************************/ /*****                                                                 *****/ /*****                           STROKER                               *****/ /*****                                                                 *****/ /***************************************************************************/ /***************************************************************************/#define FT_SIDE_TO_ROTATE( s )   ( FT_ANGLE_PI2 - (s) * FT_ANGLE_PI )  typedef struct  FT_StrokerRec_  {    FT_Angle             angle_in;    FT_Angle             angle_out;    FT_Vector            center;    FT_Bool              first_point;    FT_Bool              subpath_open;    FT_Angle             subpath_angle;    FT_Vector            subpath_start;    FT_Stroker_LineCap   line_cap;    FT_Stroker_LineJoin  line_join;    FT_Fixed             miter_limit;    FT_Fixed             radius;    FT_Bool              valid;    FT_StrokeBorderRec   borders[2];    FT_Memory            memory;  } FT_StrokerRec;  FT_EXPORT_DEF( FT_Error )  FT_Stroker_New( FT_Memory    memory,                  FT_Stroker  *astroker )  {    FT_Error    error;    FT_Stroker  stroker;    if ( !FT_NEW( stroker ) )    {      stroker->memory = memory;      ft_stroke_border_init( &stroker->borders[0], memory );      ft_stroke_border_init( &stroker->borders[1], memory );    }    *astroker = stroker;    return error;  }  FT_EXPORT_DEF( void )  FT_Stroker_Set( FT_Stroker           stroker,                  FT_Fixed             radius,                  FT_Stroker_LineCap   line_cap,                  FT_Stroker_LineJoin  line_join,                  FT_Fixed             miter_limit )  {    stroker->radius      = radius;    stroker->line_cap    = line_cap;    stroker->line_join   = line_join;    stroker->miter_limit = miter_limit;    stroker->valid = 0;    ft_stroke_border_reset( &stroker->borders[0] );    ft_stroke_border_reset( &stroker->borders[1] );  }  FT_EXPORT_DEF( void )  FT_Stroker_Done( FT_Stroker  stroker )  {    if ( stroker )    {      FT_Memory  memory = stroker->memory;      ft_stroke_border_done( &stroker->borders[0] );      ft_stroke_border_done( &stroker->borders[1] );      stroker->memory = NULL;      FT_FREE( stroker );    }  }  /* creates a circular arc at a corner or cap */  static FT_Error  ft_stroker_arcto( FT_Stroker  stroker,                    FT_Int      side )  {    FT_Angle         total, rotate;    FT_Fixed         radius = stroker->radius;    FT_Error         error  = 0;    FT_StrokeBorder  border = stroker->borders + side;    rotate = FT_SIDE_TO_ROTATE( side );    total = FT_Angle_Diff( stroker->angle_in, stroker->angle_out );    if ( total == FT_ANGLE_PI )      total = -rotate * 2;    error = ft_stroke_border_arcto( border,                                    &stroker->center,                                    radius,                                    stroker->angle_in + rotate,                                    total );    border->movable = 0;    return error;  }  /* adds a cap at the end of an opened path */  static FT_Error  ft_stroker_cap( FT_Stroker  stroker,                  FT_Angle    angle,                  FT_Int      side )  {    FT_Error  error  = 0;    if ( stroker->line_cap == FT_STROKER_LINECAP_ROUND )    {      /* add a round cap */      stroker->angle_in  = angle;      stroker->angle_out = angle + FT_ANGLE_PI;      error = ft_stroker_arcto( stroker, side );    }    else if ( stroker->line_cap == FT_STROKER_LINECAP_SQUARE )    {      /* add a square cap */      FT_Vector        delta, delta2;      FT_Angle         rotate = FT_SIDE_TO_ROTATE( side );      FT_Fixed         radius = stroker->radius;      FT_StrokeBorder  border = stroker->borders + side;      FT_Vector_From_Polar( &delta2, radius, angle + rotate );      FT_Vector_From_Polar( &delta,  radius, angle );      delta.x += stroker->center.x + delta2.x;      delta.y += stroker->center.y + delta2.y;      error = ft_stroke_border_lineto( border, &delta, 0 );      if ( error )        goto Exit;      FT_Vector_From_Polar( &delta2, radius, angle - rotate );      FT_Vector_From_Polar( &delta,  radius, angle );      delta.x += delta2.x + stroker->center.x;      delta.y += delta2.y + stroker->center.y;      error = ft_stroke_border_lineto( border, &delta, 0 );    }  Exit:    return error;  }  /* process an inside corner, i.e. compute intersection */  static FT_Error  ft_stroker_inside( FT_Stroker  stroker,                     FT_Int      side)  {    FT_StrokeBorder  border = stroker->borders + side;    FT_Angle         phi, theta, rotate;    FT_Fixed         length, thcos, sigma;    FT_Vector        delta;    FT_Error         error = 0;    rotate = FT_SIDE_TO_ROTATE( side );    /* compute median angle */    theta = FT_Angle_Diff( stroker->angle_in, stroker->angle_out );    if ( theta == FT_ANGLE_PI )      theta = rotate;    else      theta = theta / 2;    phi = stroker->angle_in + theta;    thcos  = FT_Cos( theta );    sigma  = FT_MulFix( stroker->miter_limit, thcos );    if ( sigma < 0x10000L )    {      FT_Vector_From_Polar( &delta, stroker->radius,                            stroker->angle_out + rotate );      delta.x += stroker->center.x;      delta.y += stroker->center.y;      border->movable = 0;    }    else    {      length = FT_DivFix( stroker->radius, thcos );      FT_Vector_From_Polar( &delta, length, phi + rotate );      delta.x += stroker->center.x;      delta.y += stroker->center.y;    }    error = ft_stroke_border_lineto( border, &delta, 0 );    return error;  }  /* process an outside corner, i.e. compute bevel/miter/round */  static FT_Error  ft_stroker_outside( FT_Stroker  stroker,                      FT_Int      side )  {    FT_StrokeBorder  border = stroker->borders + side;    FT_Error         error;    FT_Angle         rotate;    if ( stroker->line_join == FT_STROKER_LINEJOIN_ROUND )    {      error = ft_stroker_arcto( stroker, side );    }    else    {      /* this is a mitered or beveled corner */      FT_Fixed  sigma, radius = stroker->radius;      FT_Angle  theta, phi;      FT_Fixed  thcos;      FT_Bool   miter;      rotate = FT_SIDE_TO_ROTATE( side );      miter  = FT_BOOL( stroker->line_join == FT_STROKER_LINEJOIN_MITER );      theta  = FT_Angle_Diff( stroker->angle_in, stroker->angle_out );      if ( theta == FT_ANGLE_PI )      {        theta = rotate;        phi   = stroker->angle_in;      }      else      {        theta = theta / 2;        phi   = stroker->angle_in + theta + rotate;      }      thcos = FT_Cos( theta );      sigma = FT_MulFix( stroker->miter_limit, thcos );      if ( sigma >= 0x10000L )        miter = 0;      if ( miter )  /* this is a miter (broken angle) */      {        FT_Vector  middle, delta;        FT_Fixed   length;        /* compute middle point */        FT_Vector_From_Polar( &middle,                              FT_MulFix( radius, stroker->miter_limit ),                              phi );        middle.x += stroker->center.x;        middle.y += stroker->center.y;        /* compute first angle point */        length = FT_MulFix( radius,                            FT_DivFix( 0x10000L - sigma,                                       ft_pos_abs( FT_Sin( theta ) ) ) );        FT_Vector_From_Polar( &delta, length, phi + rotate );        delta.x += middle.x;        delta.y += middle.y;        error = ft_stroke_border_lineto( border, &delta, 0 );        if ( error )          goto Exit;        /* compute second angle point */        FT_Vector_From_Polar( &delta, length, phi - rotate );        delta.x += middle.x;        delta.y += middle.y;        error = ft_stroke_border_lineto( border, &delta, 0 );        if ( error )          goto Exit;        /* finally, add a movable end point */        FT_Vector_From_Polar( &delta, radius, stroker->angle_out + rotate );        delta.x += stroker->center.x;        delta.y += stroker->center.y;        error = ft_stroke_border_lineto( border, &delta, 1 );      }      else /* this is a bevel (intersection) */      {        FT_Fixed   length;        FT_Vector  delta;        length = FT_DivFix( stroker->radius, thcos );        FT_Vector_From_Polar( &delta, length, phi );        delta.x += stroker->center.x;        delta.y += stroker->center.y;        error = ft_stroke_border_lineto( border, &delta, 0 );        if (error) goto Exit;        /* now add end point */        FT_Vector_From_Polar( &delta, stroker->radius,                              stroker->angle_out + rotate );        delta.x += stroker->center.x;        delta.y += stroker->center.y;        error = ft_stroke_border_lineto( border, &delta, 1 );      }    }  Exit:    return error;  }  static FT_Error  ft_stroker_process_corner( FT_Stroker  stroker )  {    FT_Error  error = 0;    FT_Angle  turn;    FT_Int    inside_side;    turn = FT_Angle_Diff( stroker->angle_in, stroker->angle_out );    /* no specific corner processing is required if the turn is 0 */    if ( turn == 0 )      goto Exit;    /* when we turn to the right, the inside side is 0 */    inside_side = 0;    /* otherwise, the inside side is 1 */    if ( turn < 0 )      inside_side = 1;    /* process the inside side */    error = ft_stroker_inside( stroker, inside_side );    if ( error )      goto Exit;    /* process the outside side */    error = ft_stroker_outside( stroker, 1 - inside_side );  Exit:    return error;  }  /* add two points to the left and right borders corresponding to the */  /* start of the subpath..                                            */  static FT_Error  ft_stroker_subpath_start( FT_Stroker  stroker,                            FT_Angle    start_angle )  {    FT_Vector        delta;    FT_Vector        point;    FT_Error         error;    FT_StrokeBorder  border;    FT_Vector_From_Polar( &delta, stroker->radius,                          start_angle + FT_ANGLE_PI2 );    point.x = stroker->center.x + delta.x;    point.y = stroker->center.y + delta.y;    border = stroker->borders;    error = ft_stroke_border_moveto( border, &point );    if ( error )      goto Exit;    point.x = stroker->center.x - delta.x;    point.y = stroker->center.y - delta.y;    border++;    error = ft_stroke_border_moveto( border, &point );    /* save angle for last cap */    stroker->subpath_angle = start_angle;    stroker->first_point   = 0;  Exit:    return error;  }  FT_EXPORT_DEF( FT_Error )  FT_Stroker_LineTo( FT_Stroker  stroker,                     FT_Vector*  to )  {    FT_Error         error = 0;    FT_StrokeBorder  border;    FT_Vector        delta;    FT_Angle         angle;    FT_Int           side;    delta.x = to->x - stroker->center.x;    delta.y = to->y - stroker->center.y;    angle = FT_Atan2( delta.x, delta.y );    FT_Vector_From_Polar( &delta, stroker->radius, angle + FT_ANGLE_PI2 );    /* process corner if necessary */    if ( stroker->first_point )    {      /* This is the first segment of a subpath.  We need to     */      /* add a point to each border at their respective starting */      /* point locations.                                        */      error = ft_stroker_subpath_start( stroker, angle );      if ( error )        goto Exit;    }    else    {      /* process the current corner */      stroker->angle_out = angle;      error = ft_stroker_process_corner( stroker );      if ( error )        goto Exit;    }    /* now add a line segment to both the "inside" and "outside" paths */    for ( border = stroker->borders, side = 1; side >= 0; side--, border++ )    {      FT_Vector  point;      point.x = to->x + delta.x;      point.y = to->y + delta.y;      error = ft_stroke_border_lineto( border, &point, 1 );      if ( error )        goto Exit;      delta.x = -delta.x;      delta.y = -delta.y;    }    stroker->angle_in = angle;    stroker->center   = *to;  Exit:    return error;  }  FT_EXPORT_DEF( FT_Error )  FT_Stroker_ConicTo( FT_Stroker  stroker,                      FT_Vector*  control,                      FT_Vector*  to )  {    FT_Error    error = 0;    FT_Vector   bez_stack[34];    FT_Vector*  arc;    FT_Vector*  limit = bez_stack + 30;    FT_Angle    start_angle;    FT_Bool     first_arc = 1;    arc    = bez_stack;    arc[0] = *to;    arc[1] = *control;    arc[2] = stroker->center;    while ( arc >= bez_stack )    {      FT_Angle  angle_in, angle_out;      angle_in = angle_out = 0;  /* remove compiler warnings */      if ( arc < limit                                             &&           !ft_conic_is_small_enough( arc, &angle_in, &angle_out ) )      {        ft_conic_split( arc );        arc += 2;        continue;      }      if ( first_arc )      {        first_arc = 0;        start_angle = angle_in;        /* process corner if necessary */        if ( stroker->first_point )          error = ft_stroker_subpath_start( stroker, start_angle );        else        {          stroker->angle_out = start_angle;          error = ft_stroker_process_corner( stroker );        }      }      /* the arc's angle is small enough; we can add it directly to each */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -