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

📄 ftstroke.c

📁 奇趣公司比较新的qt/emd版本
💻 C
📖 第 1 页 / 共 4 页
字号:
      FT_Vector_From_Polar( &b2, length, next - rotate );      b2.x += b.x;      b2.y += b.y;      /* add cubic arc */      error = ft_stroke_border_cubicto( border, &a2, &b2, &b );      if ( error )        break;      /* process the rest of the arc ?? */      a      = b;      total -= step;      angle  = next;    }    return error;  }  static FT_Error  ft_stroke_border_moveto( FT_StrokeBorder  border,                           FT_Vector*       to )  {    /* close current open path if any ? */    if ( border->start >= 0 )      ft_stroke_border_close( border, 0 );    border->start   = border->num_points;    border->movable = 0;    return ft_stroke_border_lineto( border, to, 0 );  }  static void  ft_stroke_border_init( FT_StrokeBorder  border,                         FT_Memory        memory )  {    border->memory = memory;    border->points = NULL;    border->tags   = NULL;    border->num_points = 0;    border->max_points = 0;    border->start      = -1;    border->valid      = 0;  }  static void  ft_stroke_border_reset( FT_StrokeBorder  border )  {    border->num_points = 0;    border->start      = -1;    border->valid      = 0;  }  static void  ft_stroke_border_done( FT_StrokeBorder  border )  {    FT_Memory  memory = border->memory;    FT_FREE( border->points );    FT_FREE( border->tags );    border->num_points = 0;    border->max_points = 0;    border->start      = -1;    border->valid      = 0;  }  static FT_Error  ft_stroke_border_get_counts( FT_StrokeBorder  border,                               FT_UInt         *anum_points,                               FT_UInt         *anum_contours )  {    FT_Error  error        = 0;    FT_UInt   num_points   = 0;    FT_UInt   num_contours = 0;    FT_UInt     count      = border->num_points;    FT_Vector*  point      = border->points;    FT_Byte*    tags       = border->tags;    FT_Int      in_contour = 0;    for ( ; count > 0; count--, num_points++, point++, tags++ )    {      if ( tags[0] & FT_STROKE_TAG_BEGIN )      {        if ( in_contour != 0 )          goto Fail;        in_contour = 1;      }      else if ( in_contour == 0 )        goto Fail;      if ( tags[0] & FT_STROKE_TAG_END )      {        if ( in_contour == 0 )          goto Fail;        in_contour = 0;        num_contours++;      }    }    if ( in_contour != 0 )      goto Fail;    border->valid = 1;  Exit:    *anum_points   = num_points;    *anum_contours = num_contours;    return error;  Fail:    num_points   = 0;    num_contours = 0;    goto Exit;  }  static void  ft_stroke_border_export( FT_StrokeBorder  border,                           FT_Outline*      outline )  {    /* copy point locations */    FT_ARRAY_COPY( outline->points + outline->n_points,                   border->points,                   border->num_points );    /* 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;  /* documentation is in ftstroke.h */  FT_EXPORT_DEF( FT_Error )  FT_Stroker_New( FT_Library   library,                  FT_Stroker  *astroker )  {    FT_Error    error;    FT_Memory   memory;    FT_Stroker  stroker;    if ( !library )      return FT_Err_Invalid_Argument;    memory = library->memory;    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;  }  /* documentation is in ftstroke.h */  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;    FT_Stroker_Rewind( stroker );  }  /* documentation is in ftstroke.h */  FT_EXPORT_DEF( void )  FT_Stroker_Rewind( FT_Stroker  stroker )  {    if ( stroker )    {      ft_stroke_border_reset( &stroker->borders[0] );      ft_stroke_border_reset( &stroker->borders[1] );    }  }  /* documentation is in ftstroke.h */  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 );    /* TODO: find better criterion to switch off the optimization */    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 );      }

⌨️ 快捷键说明

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