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

📄 ftstroke.c

📁 奇趣公司比较新的qt/emd版本
💻 C
📖 第 1 页 / 共 4 页
字号:
/***************************************************************************//*                                                                         *//*  ftstroke.c                                                             *//*                                                                         *//*    FreeType path stroker (body).                                        *//*                                                                         *//*  Copyright 2002, 2003, 2004, 2005, 2006 by                              *//*  David Turner, Robert Wilhelm, and Werner Lemberg.                      *//*                                                                         *//*  This file is part of the FreeType project, and may only be used,       *//*  modified, and distributed under the terms of the FreeType project      *//*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     *//*  this file you indicate that you have read the license and              *//*  understand and accept it fully.                                        *//*                                                                         *//***************************************************************************/#include <ft2build.h>#include FT_STROKER_H#include FT_TRIGONOMETRY_H#include FT_OUTLINE_H#include FT_INTERNAL_MEMORY_H#include FT_INTERNAL_DEBUG_H#include FT_INTERNAL_OBJECTS_H  /* documentation is in ftstroke.h */  FT_EXPORT_DEF( FT_StrokerBorder )  FT_Outline_GetInsideBorder( FT_Outline*  outline )  {    FT_Orientation  o = FT_Outline_Get_Orientation( outline );    return o == FT_ORIENTATION_TRUETYPE ? FT_STROKER_BORDER_RIGHT                                        : FT_STROKER_BORDER_LEFT ;  }  /* documentation is in ftstroke.h */  FT_EXPORT_DEF( FT_StrokerBorder )  FT_Outline_GetOutsideBorder( FT_Outline*  outline )  {    FT_Orientation  o = FT_Outline_Get_Orientation( outline );    return o == FT_ORIENTATION_TRUETYPE ? FT_STROKER_BORDER_LEFT                                        : FT_STROKER_BORDER_RIGHT ;  } /***************************************************************************/ /***************************************************************************/ /*****                                                                 *****/ /*****                       BEZIER COMPUTATIONS                       *****/ /*****                                                                 *****/ /***************************************************************************/ /***************************************************************************/#define FT_SMALL_CONIC_THRESHOLD  ( FT_ANGLE_PI / 6 )#define FT_SMALL_CUBIC_THRESHOLD  ( FT_ANGLE_PI / 6 )#define FT_EPSILON  2#define FT_IS_SMALL( x )  ( (x) > -FT_EPSILON && (x) < FT_EPSILON )  static FT_Pos  ft_pos_abs( FT_Pos  x )  {    return x >= 0 ? x : -x ;  }  static void  ft_conic_split( FT_Vector*  base )  {    FT_Pos  a, b;    base[4].x = base[2].x;    b = base[1].x;    a = base[3].x = ( base[2].x + b ) / 2;    b = base[1].x = ( base[0].x + b ) / 2;    base[2].x = ( a + b ) / 2;    base[4].y = base[2].y;    b = base[1].y;    a = base[3].y = ( base[2].y + b ) / 2;    b = base[1].y = ( base[0].y + b ) / 2;    base[2].y = ( a + b ) / 2;  }  static FT_Bool  ft_conic_is_small_enough( FT_Vector*  base,                            FT_Angle   *angle_in,                            FT_Angle   *angle_out )  {    FT_Vector  d1, d2;    FT_Angle   theta;    FT_Int     close1, close2;    d1.x = base[1].x - base[2].x;    d1.y = base[1].y - base[2].y;    d2.x = base[0].x - base[1].x;    d2.y = base[0].y - base[1].y;    close1 = FT_IS_SMALL( d1.x ) && FT_IS_SMALL( d1.y );    close2 = FT_IS_SMALL( d2.x ) && FT_IS_SMALL( d2.y );    if ( close1 )    {      if ( close2 )        *angle_in = *angle_out = 0;      else        *angle_in = *angle_out = FT_Atan2( d2.x, d2.y );    }    else if ( close2 )    {      *angle_in = *angle_out = FT_Atan2( d1.x, d1.y );    }    else    {      *angle_in  = FT_Atan2( d1.x, d1.y );      *angle_out = FT_Atan2( d2.x, d2.y );    }    theta = ft_pos_abs( FT_Angle_Diff( *angle_in, *angle_out ) );    return FT_BOOL( theta < FT_SMALL_CONIC_THRESHOLD );  }  static void  ft_cubic_split( FT_Vector*  base )  {    FT_Pos  a, b, c, d;    base[6].x = base[3].x;    c = base[1].x;    d = base[2].x;    base[1].x = a = ( base[0].x + c ) / 2;    base[5].x = b = ( base[3].x + d ) / 2;    c = ( c + d ) / 2;    base[2].x = a = ( a + c ) / 2;    base[4].x = b = ( b + c ) / 2;    base[3].x = ( a + b ) / 2;    base[6].y = base[3].y;    c = base[1].y;    d = base[2].y;    base[1].y = a = ( base[0].y + c ) / 2;    base[5].y = b = ( base[3].y + d ) / 2;    c = ( c + d ) / 2;    base[2].y = a = ( a + c ) / 2;    base[4].y = b = ( b + c ) / 2;    base[3].y = ( a + b ) / 2;  }  static FT_Bool  ft_cubic_is_small_enough( FT_Vector*  base,                            FT_Angle   *angle_in,                            FT_Angle   *angle_mid,                            FT_Angle   *angle_out )  {    FT_Vector  d1, d2, d3;    FT_Angle   theta1, theta2;    FT_Int     close1, close2, close3;    d1.x = base[2].x - base[3].x;    d1.y = base[2].y - base[3].y;    d2.x = base[1].x - base[2].x;    d2.y = base[1].y - base[2].y;    d3.x = base[0].x - base[1].x;    d3.y = base[0].y - base[1].y;    close1 = FT_IS_SMALL( d1.x ) && FT_IS_SMALL( d1.y );    close2 = FT_IS_SMALL( d2.x ) && FT_IS_SMALL( d2.y );    close3 = FT_IS_SMALL( d3.x ) && FT_IS_SMALL( d3.y );    if ( close1 || close3 )    {      if ( close2 )      {        /* basically a point */        *angle_in = *angle_out = *angle_mid = 0;      }      else if ( close1 )      {        *angle_in  = *angle_mid = FT_Atan2( d2.x, d2.y );        *angle_out = FT_Atan2( d3.x, d3.y );      }      else  /* close2 */      {        *angle_in  = FT_Atan2( d1.x, d1.y );        *angle_mid = *angle_out = FT_Atan2( d2.x, d2.y );      }    }    else if ( close2 )    {      *angle_in  = *angle_mid = FT_Atan2( d1.x, d1.y );      *angle_out = FT_Atan2( d3.x, d3.y );    }    else    {      *angle_in  = FT_Atan2( d1.x, d1.y );      *angle_mid = FT_Atan2( d2.x, d2.y );      *angle_out = FT_Atan2( d3.x, d3.y );    }    theta1 = ft_pos_abs( FT_Angle_Diff( *angle_in,  *angle_mid ) );    theta2 = ft_pos_abs( FT_Angle_Diff( *angle_mid, *angle_out ) );    return FT_BOOL( theta1 < FT_SMALL_CUBIC_THRESHOLD &&                    theta2 < FT_SMALL_CUBIC_THRESHOLD );  } /***************************************************************************/ /***************************************************************************/ /*****                                                                 *****/ /*****                       STROKE BORDERS                            *****/ /*****                                                                 *****/ /***************************************************************************/ /***************************************************************************/  typedef enum  {    FT_STROKE_TAG_ON    = 1,   /* on-curve point  */    FT_STROKE_TAG_CUBIC = 2,   /* cubic off-point */    FT_STROKE_TAG_BEGIN = 4,   /* sub-path start  */    FT_STROKE_TAG_END   = 8    /* sub-path end    */  } FT_StrokeTags;#define  FT_STROKE_TAG_BEGIN_END  (FT_STROKE_TAG_BEGIN|FT_STROKE_TAG_END)  typedef struct  FT_StrokeBorderRec_  {    FT_UInt     num_points;    FT_UInt     max_points;    FT_Vector*  points;    FT_Byte*    tags;    FT_Bool     movable;    FT_Int      start;    /* index of current sub-path start point */    FT_Memory   memory;    FT_Bool     valid;  } FT_StrokeBorderRec, *FT_StrokeBorder;  static FT_Error  ft_stroke_border_grow( FT_StrokeBorder  border,                         FT_UInt          new_points )  {    FT_UInt   old_max = border->max_points;    FT_UInt   new_max = border->num_points + new_points;    FT_Error  error   = 0;    if ( new_max > old_max )    {      FT_UInt    cur_max = old_max;      FT_Memory  memory  = border->memory;      while ( cur_max < new_max )        cur_max += ( cur_max >> 1 ) + 16;      if ( FT_RENEW_ARRAY( border->points, old_max, cur_max ) ||           FT_RENEW_ARRAY( border->tags,   old_max, cur_max ) )        goto Exit;      border->max_points = cur_max;    }  Exit:    return error;  }  static void  ft_stroke_border_close( FT_StrokeBorder  border,                          FT_Bool          reverse )  {    FT_UInt  start = border->start;    FT_UInt  count = border->num_points;    FT_ASSERT( border->start >= 0 );    /* don't record empty paths! */    if ( count <= start + 1U )      border->num_points = start;    else    {      /* copy the last point to the start of this sub-path, since */      /* it contains the `adjusted' starting coordinates          */      border->num_points    = --count;      border->points[start] = border->points[count];      if ( reverse )      {        /* reverse the points */        {          FT_Vector*  vec1 = border->points + start + 1;          FT_Vector*  vec2 = border->points + count - 1;          for ( ; vec1 < vec2; vec1++, vec2-- )          {            FT_Vector  tmp;            tmp   = *vec1;            *vec1 = *vec2;            *vec2 = tmp;          }        }        /* then the tags */        {          FT_Byte*  tag1 = border->tags + start + 1;          FT_Byte*  tag2 = border->tags + count - 1;          for ( ; tag1 < tag2; tag1++, tag2-- )          {            FT_Byte  tmp;            tmp   = *tag1;            *tag1 = *tag2;            *tag2 = tmp;          }        }      }      border->tags[start    ] |= FT_STROKE_TAG_BEGIN;      border->tags[count - 1] |= FT_STROKE_TAG_END;    }    border->start   = -1;    border->movable = 0;  }  static FT_Error  ft_stroke_border_lineto( FT_StrokeBorder  border,                           FT_Vector*       to,                           FT_Bool          movable )  {    FT_Error  error = 0;    FT_ASSERT( border->start >= 0 );    if ( border->movable )    {      /* move last point */      border->points[border->num_points - 1] = *to;    }    else    {      /* add one point */      error = ft_stroke_border_grow( border, 1 );      if ( !error )      {        FT_Vector*  vec = border->points + border->num_points;        FT_Byte*    tag = border->tags   + border->num_points;        vec[0] = *to;        tag[0] = FT_STROKE_TAG_ON;        border->num_points += 1;      }    }    border->movable = movable;    return error;  }  static FT_Error  ft_stroke_border_conicto( FT_StrokeBorder  border,                            FT_Vector*       control,                            FT_Vector*       to )  {    FT_Error  error;    FT_ASSERT( border->start >= 0 );    error = ft_stroke_border_grow( border, 2 );    if ( !error )    {      FT_Vector*  vec = border->points + border->num_points;      FT_Byte*    tag = border->tags   + border->num_points;      vec[0] = *control;      vec[1] = *to;      tag[0] = 0;      tag[1] = FT_STROKE_TAG_ON;      border->num_points += 2;    }    border->movable = 0;    return error;  }  static FT_Error  ft_stroke_border_cubicto( FT_StrokeBorder  border,                            FT_Vector*       control1,                            FT_Vector*       control2,                            FT_Vector*       to )  {    FT_Error  error;    FT_ASSERT( border->start >= 0 );    error = ft_stroke_border_grow( border, 3 );    if ( !error )    {      FT_Vector*  vec = border->points + border->num_points;      FT_Byte*    tag = border->tags   + border->num_points;      vec[0] = *control1;      vec[1] = *control2;      vec[2] = *to;      tag[0] = FT_STROKE_TAG_CUBIC;      tag[1] = FT_STROKE_TAG_CUBIC;      tag[2] = FT_STROKE_TAG_ON;      border->num_points += 3;    }    border->movable = 0;    return error;  }#define FT_ARC_CUBIC_ANGLE  ( FT_ANGLE_PI / 2 )  static FT_Error  ft_stroke_border_arcto( FT_StrokeBorder  border,                          FT_Vector*       center,                          FT_Fixed         radius,                          FT_Angle         angle_start,                          FT_Angle         angle_diff )  {    FT_Angle   total, angle, step, rotate, next, theta;    FT_Vector  a, b, a2, b2;    FT_Fixed   length;    FT_Error   error = 0;    /* compute start point */    FT_Vector_From_Polar( &a, radius, angle_start );    a.x += center->x;    a.y += center->y;    total  = angle_diff;    angle  = angle_start;    rotate = ( angle_diff >= 0 ) ? FT_ANGLE_PI2 : -FT_ANGLE_PI2;    while ( total != 0 )    {      step = total;      if ( step > FT_ARC_CUBIC_ANGLE )        step = FT_ARC_CUBIC_ANGLE;      else if ( step < -FT_ARC_CUBIC_ANGLE )        step = -FT_ARC_CUBIC_ANGLE;      next  = angle + step;      theta = step;      if ( theta < 0 )        theta = -theta;      theta >>= 1;      /* compute end point */      FT_Vector_From_Polar( &b, radius, next );      b.x += center->x;      b.y += center->y;      /* compute first and second control points */      length = FT_MulDiv( radius, FT_Sin( theta ) * 4,                          ( 0x10000L + FT_Cos( theta ) ) * 3 );      FT_Vector_From_Polar( &a2, length, angle + rotate );      a2.x += a.x;      a2.y += a.y;

⌨️ 快捷键说明

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