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

📄 ftstroke.c

📁 下载来的一个看图软件的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
      /* border                                                          */      {        FT_Vector  ctrl, end;        FT_Angle   theta, phi, rotate;        FT_Fixed   length;        FT_Int     side;        theta  = FT_Angle_Diff( angle_in, angle_out ) / 2;        phi    = angle_in + theta;        length = FT_DivFix( stroker->radius, FT_Cos( theta ) );        for ( side = 0; side <= 1; side++ )        {          rotate = FT_SIDE_TO_ROTATE( side );          /* compute control point */          FT_Vector_From_Polar( &ctrl, length, phi + rotate );          ctrl.x += arc[1].x;          ctrl.y += arc[1].y;          /* compute end point */          FT_Vector_From_Polar( &end, stroker->radius, angle_out + rotate );          end.x += arc[0].x;          end.y += arc[0].y;          error = ft_stroke_border_conicto( stroker->borders + side,                                            &ctrl, &end );          if ( error )            goto Exit;        }      }      arc -= 2;      if ( arc < bez_stack )        stroker->angle_in = angle_out;    }    stroker->center = *to;  Exit:    return error;  }  FT_EXPORT_DEF( FT_Error )  FT_Stroker_CubicTo( FT_Stroker  stroker,                      FT_Vector*  control1,                      FT_Vector*  control2,                      FT_Vector*  to )  {    FT_Error    error = 0;    FT_Vector   bez_stack[37];    FT_Vector*  arc;    FT_Vector*  limit = bez_stack + 32;    FT_Angle    start_angle;    FT_Bool     first_arc = 1;    arc    = bez_stack;    arc[0] = *to;    arc[1] = *control2;    arc[2] = *control1;    arc[3] = stroker->center;    while ( arc >= bez_stack )    {      FT_Angle  angle_in, angle_mid, angle_out;      /* remove compiler warnings */      angle_in = angle_out = angle_mid = 0;      if ( arc < limit                                         &&           !ft_cubic_is_small_enough( arc, &angle_in,                                      &angle_mid, &angle_out ) )      {        ft_cubic_split( arc );        arc += 3;        continue;      }      if ( first_arc )      {        first_arc = 0;        /* process corner if necessary */        start_angle = angle_in;        if ( stroker->first_point )          error = ft_stroker_subpath_start( stroker, start_angle );        else        {          stroker->angle_out = start_angle;          error = ft_stroker_process_corner( stroker );        }        if ( error )          goto Exit;      }      /* the arc's angle is small enough; we can add it directly to each */      /* border                                                          */      {        FT_Vector  ctrl1, ctrl2, end;        FT_Angle   theta1, phi1, theta2, phi2, rotate;        FT_Fixed   length1, length2;        FT_Int     side;        theta1  = ft_pos_abs( angle_mid - angle_in ) / 2;        theta2  = ft_pos_abs( angle_out - angle_mid ) / 2;        phi1    = (angle_mid + angle_in ) / 2;        phi2    = (angle_mid + angle_out ) / 2;        length1 = FT_DivFix( stroker->radius, FT_Cos( theta1 ) );        length2 = FT_DivFix( stroker->radius, FT_Cos(theta2) );        for ( side = 0; side <= 1; side++ )        {          rotate = FT_SIDE_TO_ROTATE( side );          /* compute control points */          FT_Vector_From_Polar( &ctrl1, length1, phi1 + rotate );          ctrl1.x += arc[2].x;          ctrl1.y += arc[2].y;          FT_Vector_From_Polar( &ctrl2, length2, phi2 + rotate );          ctrl2.x += arc[1].x;          ctrl2.y += arc[1].y;          /* compute end point */          FT_Vector_From_Polar( &end, stroker->radius, angle_out + rotate );          end.x += arc[0].x;          end.y += arc[0].y;          error = ft_stroke_border_cubicto( stroker->borders + side,                                            &ctrl1, &ctrl2, &end );          if ( error )            goto Exit;        }      }      arc -= 3;      if ( arc < bez_stack )        stroker->angle_in = angle_out;    }    stroker->center = *to;  Exit:    return error;  }  FT_EXPORT_DEF( FT_Error )  FT_Stroker_BeginSubPath( FT_Stroker  stroker,                           FT_Vector*  to,                           FT_Bool     open )  {    /* We cannot process the first point, because there is not enough      */    /* information regarding its corner/cap.  The latter will be processed */    /* in the "end_subpath" routine.                                       */    /*                                                                     */    stroker->first_point   = 1;    stroker->center        = *to;    stroker->subpath_open  = open;    /* record the subpath start point index for each border */    stroker->subpath_start = *to;    return 0;  }  static FT_Error  ft_stroker_add_reverse_left( FT_Stroker  stroker,                               FT_Bool     open )  {    FT_StrokeBorder  right  = stroker->borders + 0;    FT_StrokeBorder  left   = stroker->borders + 1;    FT_Int           new_points;    FT_Error         error  = 0;    FT_ASSERT( left->start >= 0 );    new_points = left->num_points - left->start;    if ( new_points > 0 )    {      error = ft_stroke_border_grow( right, (FT_UInt)new_points );      if ( error )        goto Exit;      {        FT_Vector*  dst_point = right->points + right->num_points;        FT_Byte*    dst_tag   = right->tags   + right->num_points;        FT_Vector*  src_point = left->points  + left->num_points - 1;        FT_Byte*    src_tag   = left->tags    + left->num_points - 1;        while ( src_point >= left->points + left->start )        {          *dst_point = *src_point;          *dst_tag   = *src_tag;          if ( open )            dst_tag[0] &= ~( FT_STROKE_TAG_BEGIN | FT_STROKE_TAG_END );          else          {            /* switch begin/end tags if necessary.. */            if ( dst_tag[0] & ( FT_STROKE_TAG_BEGIN | FT_STROKE_TAG_END ) )              dst_tag[0] ^= ( FT_STROKE_TAG_BEGIN | FT_STROKE_TAG_END );          }          src_point--;          src_tag--;          dst_point++;          dst_tag++;        }      }      left->num_points   = left->start;      right->num_points += new_points;      right->movable = 0;      left->movable  = 0;    }  Exit:    return error;  }  /* there's a lot of magic in this function! */  FT_EXPORT_DEF( FT_Error )  FT_Stroker_EndSubPath( FT_Stroker  stroker )  {    FT_Error  error  = 0;    if ( stroker->subpath_open )    {      FT_StrokeBorder  right = stroker->borders;      /* All right, this is an opened path, we need to add a cap between */      /* right & left, add the reverse of left, then add a final cap     */      /* between left & right.                                           */      error = ft_stroker_cap( stroker, stroker->angle_in, 0 );      if ( error )        goto Exit;      /* add reversed points from "left" to "right" */      error = ft_stroker_add_reverse_left( stroker, 1 );      if ( error )        goto Exit;      /* now add the final cap */      stroker->center = stroker->subpath_start;      error = ft_stroker_cap( stroker,                              stroker->subpath_angle + FT_ANGLE_PI, 0 );      if ( error )        goto Exit;      /* Now end the right subpath accordingly.  The left one is */      /* rewind and doesn't need further processing.             */      ft_stroke_border_close( right );    }    else    {      FT_Angle  turn;      FT_Int    inside_side;      /* process the corner */      stroker->angle_out = stroker->subpath_angle;      turn               = FT_Angle_Diff( stroker->angle_in,                                          stroker->angle_out );      /* no specific corner processing is required if the turn is 0 */      if ( turn != 0 )      {        /* 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;        /* IMPORTANT: WE DO NOT PROCESS THE INSIDE BORDER HERE! */        /* 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 );        if ( error )          goto Exit;      }      /* we will first end our two subpaths */      ft_stroke_border_close( stroker->borders + 0 );      ft_stroke_border_close( stroker->borders + 1 );      /* now, add the reversed left subpath to "right" */      error = ft_stroker_add_reverse_left( stroker, 0 );      if ( error )        goto Exit;    }  Exit:    return error;  }  FT_EXPORT_DEF( FT_Error )  FT_Stroker_GetCounts( FT_Stroker  stroker,                        FT_UInt    *anum_points,                        FT_UInt    *anum_contours )  {    FT_UInt   count1, count2, num_points   = 0;    FT_UInt   count3, count4, num_contours = 0;    FT_Error  error;    error = ft_stroke_border_get_counts( stroker->borders + 0,                                         &count1, &count2 );    if ( error )      goto Exit;    error = ft_stroke_border_get_counts( stroker->borders + 1,                                         &count3, &count4 );    if ( error )      goto Exit;    num_points   = count1 + count3;    num_contours = count2 + count4;    stroker->valid = 1;  Exit:    *anum_points   = num_points;    *anum_contours = num_contours;    return error;  }  FT_EXPORT_DEF( void )  FT_Stroker_Export( FT_Stroker   stroker,                     FT_Outline*  outline )  {    if ( stroker->valid )    {      ft_stroke_border_export( stroker->borders + 0, outline );      ft_stroke_border_export( stroker->borders + 1, outline );    }  }  /*   *  The following is very similar to FT_Outline_Decompose, except   *  that we do support opened paths, and do not scale the outline.   */  FT_EXPORT_DEF( FT_Error )  FT_Stroker_ParseOutline( FT_Stroker   stroker,                           FT_Outline*  outline,                           FT_Bool      opened )  {    FT_Vector   v_last;    FT_Vector   v_control;    FT_Vector   v_start;    FT_Vector*  point;    FT_Vector*  limit;    char*       tags;    FT_Error    error;    FT_Int   n;         /* index of contour in outline     */    FT_UInt  first;     /* index of first point in contour */    FT_Int   tag;       /* current point's state           */    if ( !outline || !stroker )      return FT_Err_Invalid_Argument;    first = 0;    for ( n = 0; n < outline->n_contours; n++ )    {      FT_Int  last;  /* index of last point in contour */      last  = outline->contours[n];      limit = outline->points + last;      v_start = outline->points[first];      v_last  = outline->points[last];      v_control = v_start;      point = outline->points + first;      tags  = outline->tags  + first;      tag   = FT_CURVE_TAG( tags[0] );      /* A contour cannot start with a cubic control point! */      if ( tag == FT_CURVE_TAG_CUBIC )        goto Invalid_Outline;      /* check first point to determine origin */      if ( tag == FT_CURVE_TAG_CONIC )      {        /* First point is conic control.  Yes, this happens. */        if ( FT_CURVE_TAG( outline->tags[last] ) == FT_CURVE_TAG_ON )        {          /* start at last point if it is on the curve */          v_start = v_last;          limit--;        }        else        {          /* if both first and last points are conic,         */          /* start at their middle and record its position    */          /* for closure                                      */          v_start.x = ( v_start.x + v_last.x ) / 2;          v_start.y = ( v_start.y + v_last.y ) / 2;          v_last = v_start;        }        point--;        tags--;      }      error = FT_Stroker_BeginSubPath( stroker, &v_start, opened );      if ( error )        goto Exit;      while ( point < limit )      {        point++;        tags++;        tag = FT_CURVE_TAG( tags[0] );        switch ( tag )        {        case FT_CURVE_TAG_ON:  /* emit a single line_to */          {            FT_Vector  vec;            vec.x = point->x;            vec.y = point->y;            error = FT_Stroker_LineTo( stroker, &vec );            if ( error )              goto Exit;            continue;          }        case FT_CURVE_TAG_CONIC:  /* consume conic arcs */          v_control.x = point->x;          v_control.y = point->y;        Do_Conic:          if ( point < limit )          {            FT_Vector  vec;            FT_Vector  v_middle;            point++;            tags++;            tag = FT_CURVE_TAG( tags[0] );            vec = point[0];            if ( tag == FT_CURVE_TAG_ON )            {              error = FT_Stroker_ConicTo( stroker, &v_control, &vec );              if ( error )                goto Exit;              continue;            }            if ( tag != FT_CURVE_TAG_CONIC )              goto Invalid_Outline;            v_middle.x = ( v_control.x + vec.x ) / 2;            v_middle.y = ( v_control.y + vec.y ) / 2;            error = FT_Stroker_ConicTo( stroker, &v_control, &v_middle );            if ( error )              goto Exit;            v_control = vec;            goto Do_Conic;          }          error = FT_Stroker_ConicTo( stroker, &v_control, &v_start );          goto Close;        default:  /* FT_CURVE_TAG_CUBIC */          {            FT_Vector  vec1, vec2;            if ( point + 1 > limit                             ||                 FT_CURVE_TAG( tags[1] ) != FT_CURVE_TAG_CUBIC )              goto Invalid_Outline;            point += 2;            tags  += 2;            vec1 = point[-2];            vec2 = point[-1];            if ( point <= limit )            {              FT_Vector  vec;              vec = point[0];              error = FT_Stroker_CubicTo( stroker, &vec1, &vec2, &vec );              if ( error )                goto Exit;              continue;            }            error = FT_Stroker_CubicTo( stroker, &vec1, &vec2, &v_start );            goto Close;          }        }      }    Close:      if ( error )        goto Exit;      error = FT_Stroker_EndSubPath( stroker );      if ( error )        goto Exit;      first = last + 1;    }    return 0;  Exit:    return error;  Invalid_Outline:    return FT_Err_Invalid_Outline;  }/* END */

⌨️ 快捷键说明

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