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

📄 ftbbox.c

📁 下载来的一个看图软件的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
                    FT_Pos*  max )  {    /* always compare first and last points */    if      ( y1 < *min )  *min = y1;    else if ( y1 > *max )  *max = y1;    if      ( y4 < *min )  *min = y4;    else if ( y4 > *max )  *max = y4;    /* now, try to see if there are split points here */    if ( y1 <= y4 )    {      /* flat or ascending arc test */      if ( y1 <= y2 && y2 <= y4 && y1 <= y3 && y3 <= y4 )        return;    }    else /* y1 > y4 */    {      /* descending arc test */      if ( y1 >= y2 && y2 >= y4 && y1 >= y3 && y3 >= y4 )        return;    }    /* There are some split points.  Find them. */    {      FT_Pos    a = y4 - 3*y3 + 3*y2 - y1;      FT_Pos    b = y3 - 2*y2 + y1;      FT_Pos    c = y2 - y1;      FT_Pos    d;      FT_Fixed  t;      /* We need to solve "ax^2+2bx+c" here, without floating points!      */      /* The trick is to normalize to a different representation in order  */      /* to use our 16.16 fixed point routines.                            */      /*                                                                   */      /* We compute FT_MulFix(b,b) and FT_MulFix(a,c) after the            */      /* the normalization.  These values must fit into a single 16.16     */      /* value.                                                            */      /*                                                                   */      /* We normalize a, b, and c to "8.16" fixed float values to ensure   */      /* that their product is held in a "16.16" value.                    */      /*                                                                   */      {        FT_ULong  t1, t2;        int       shift = 0;        /* Technical explanation of what's happening there.            */        /*                                                             */        /*   The following computation is based on the fact that for   */        /*   any value "y", if "n" is the position of the most         */        /*   significant bit of "abs(y)" (starting from 0 for the      */        /*   least significant bit), then y is in the range            */        /*                                                             */        /*                  "-2^n..2^n-1"                              */        /*                                                             */        /*   We want to shift "a", "b" and "c" concurrently in order   */        /*   to ensure that they all fit in 8.16 values, which maps    */        /*   to the integer range "-2^23..2^23-1".                     */        /*                                                             */        /*   Necessarily, we need to shift "a", "b" and "c" so that    */        /*   the most significant bit of their absolute values is at   */        /*   _most_ at position 23.                                    */        /*                                                             */        /*   We begin by computing "t1" as the bitwise "or" of the     */        /*   absolute values of "a", "b", "c".                         */        /*                                                             */        t1  = (FT_ULong)((a >= 0) ? a : -a );        t2  = (FT_ULong)((b >= 0) ? b : -b );        t1 |= t2;        t2  = (FT_ULong)((c >= 0) ? c : -c );        t1 |= t2;        /*   Now, the most significant bit of "t1" is sure to be the   */        /*   msb of one of "a", "b", "c", depending on which one is    */        /*   expressed in the greatest integer range.                  */        /*                                                             */        /*   We now compute the "shift", by shifting "t1" as many      */        /*   times as necessary to move its msb to position 23.        */        /*                                                             */        /*   This corresponds to a value of t1 that is in the range    */        /*   0x40_0000..0x7F_FFFF.                                     */        /*                                                             */        /*   Finally, we shift "a", "b" and "c" by the same amount.    */        /*   This ensures that all values are now in the range         */        /*   -2^23..2^23, i.e. that they are now expressed as 8.16     */        /*   fixed float numbers.                                      */        /*                                                             */        /*   This also means that we are using 24 bits of precision    */        /*   to compute the zeros, independently of the range of       */        /*   the original polynom coefficients.                        */        /*                                                             */        /*   This should ensure reasonably accurate values for the     */        /*   zeros.  Note that the latter are only expressed with      */        /*   16 bits when computing the extrema (the zeros need to     */        /*   be in 0..1 exclusive to be considered part of the arc).   */        /*                                                             */        if ( t1 == 0 )  /* all coefficients are 0! */          return;        if ( t1 > 0x7FFFFFUL )        {          do          {            shift++;            t1 >>= 1;          } while ( t1 > 0x7FFFFFUL );          /* losing some bits of precision, but we use 24 of them */          /* for the computation anyway.                          */          a >>= shift;          b >>= shift;          c >>= shift;        }        else if ( t1 < 0x400000UL )        {          do          {            shift++;            t1 <<= 1;          } while ( t1 < 0x400000UL );          a <<= shift;          b <<= shift;          c <<= shift;        }      }      /* handle a == 0 */      if ( a == 0 )      {        if ( b != 0 )        {          t = - FT_DivFix( c, b ) / 2;          test_cubic_extrema( y1, y2, y3, y4, t, min, max );        }      }      else      {        /* solve the equation now */        d = FT_MulFix( b, b ) - FT_MulFix( a, c );        if ( d < 0 )          return;        if ( d == 0 )        {          /* there is a single split point at -b/a */          t = - FT_DivFix( b, a );          test_cubic_extrema( y1, y2, y3, y4, t, min, max );        }        else        {          /* there are two solutions; we need to filter them though */          d = FT_SqrtFixed( (FT_Int32)d );          t = - FT_DivFix( b - d, a );          test_cubic_extrema( y1, y2, y3, y4, t, min, max );          t = - FT_DivFix( b + d, a );          test_cubic_extrema( y1, y2, y3, y4, t, min, max );        }      }    }  }#endif  /*************************************************************************/  /*                                                                       */  /* <Function>                                                            */  /*    BBox_Cubic_To                                                      */  /*                                                                       */  /* <Description>                                                         */  /*    This function is used as a `cubic_to' emitter during               */  /*    FT_Raster_Decompose().  It checks a cubic Bezier curve with the    */  /*    current bounding box, and computes its extrema if necessary to     */  /*    update it.                                                         */  /*                                                                       */  /* <Input>                                                               */  /*    control1 :: A pointer to the first control point.                  */  /*    control2 :: A pointer to the second control point.                 */  /*    to       :: A pointer to the destination vector.                   */  /*                                                                       */  /* <InOut>                                                               */  /*    user     :: The address of the current walk context.               */  /*                                                                       */  /* <Return>                                                              */  /*    Always 0.  Needed for the interface only.                          */  /*                                                                       */  /* <Note>                                                                */  /*    In the case of a non-monotonous arc, we don't compute directly     */  /*    extremum coordinates, we subdivise instead.                        */  /*                                                                       */  static int  BBox_Cubic_To( FT_Vector*  control1,                 FT_Vector*  control2,                 FT_Vector*  to,                 TBBox_Rec*  user )  {    /* we don't need to check `to' since it is always an `on' point, thus */    /* within the bbox                                                    */    if ( CHECK_X( control1, user->bbox ) ||         CHECK_X( control2, user->bbox ) )        BBox_Cubic_Check( user->last.x,                          control1->x,                          control2->x,                          to->x,                          &user->bbox.xMin,                          &user->bbox.xMax );    if ( CHECK_Y( control1, user->bbox ) ||         CHECK_Y( control2, user->bbox ) )        BBox_Cubic_Check( user->last.y,                          control1->y,                          control2->y,                          to->y,                          &user->bbox.yMin,                          &user->bbox.yMax );    user->last = *to;    return 0;  }  /* documentation is in ftbbox.h */  FT_EXPORT_DEF( FT_Error )  FT_Outline_Get_BBox( FT_Outline*  outline,                       FT_BBox     *abbox )  {    FT_BBox     cbox;    FT_BBox     bbox;    FT_Vector*  vec;    FT_UShort   n;    if ( !abbox )      return FT_Err_Invalid_Argument;    if ( !outline )      return FT_Err_Invalid_Outline;    /* if outline is empty, return (0,0,0,0) */    if ( outline->n_points == 0 || outline->n_contours <= 0 )    {      abbox->xMin = abbox->xMax = 0;      abbox->yMin = abbox->yMax = 0;      return 0;    }    /* We compute the control box as well as the bounding box of  */    /* all `on' points in the outline.  Then, if the two boxes    */    /* coincide, we exit immediately.                             */    vec = outline->points;    bbox.xMin = bbox.xMax = cbox.xMin = cbox.xMax = vec->x;    bbox.yMin = bbox.yMax = cbox.yMin = cbox.yMax = vec->y;    vec++;    for ( n = 1; n < outline->n_points; n++ )    {      FT_Pos  x = vec->x;      FT_Pos  y = vec->y;      /* update control box */      if ( x < cbox.xMin ) cbox.xMin = x;      if ( x > cbox.xMax ) cbox.xMax = x;      if ( y < cbox.yMin ) cbox.yMin = y;      if ( y > cbox.yMax ) cbox.yMax = y;      if ( FT_CURVE_TAG( outline->tags[n] ) == FT_CURVE_TAG_ON )      {        /* update bbox for `on' points only */        if ( x < bbox.xMin ) bbox.xMin = x;        if ( x > bbox.xMax ) bbox.xMax = x;        if ( y < bbox.yMin ) bbox.yMin = y;        if ( y > bbox.yMax ) bbox.yMax = y;      }      vec++;    }    /* test two boxes for equality */    if ( cbox.xMin < bbox.xMin || cbox.xMax > bbox.xMax ||         cbox.yMin < bbox.yMin || cbox.yMax > bbox.yMax )    {      /* the two boxes are different, now walk over the outline to */      /* get the Bezier arc extrema.                               */      static const FT_Outline_Funcs  bbox_interface =      {        (FT_Outline_MoveTo_Func) BBox_Move_To,        (FT_Outline_LineTo_Func) BBox_Move_To,        (FT_Outline_ConicTo_Func)BBox_Conic_To,        (FT_Outline_CubicTo_Func)BBox_Cubic_To,        0, 0      };      FT_Error   error;      TBBox_Rec  user;      user.bbox = bbox;      error = FT_Outline_Decompose( outline, &bbox_interface, &user );      if ( error )        return error;      *abbox = user.bbox;    }    else      *abbox = bbox;    return FT_Err_Ok;  }/* END */

⌨️ 快捷键说明

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