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

📄 ftbbox.c

📁 qt-x11-opensource-src-4.1.4.tar.gz源码
💻 C
📖 第 1 页 / 共 2 页
字号:
  static void  BBox_Cubic_Check( FT_Pos   y1,                    FT_Pos   y2,                    FT_Pos   y3,                    FT_Pos   y4,                    FT_Pos*  min,                    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 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 its product is held in a `16.16' value.                      */      {        FT_ULong  t1, t2;        int       shift = 0;        /* 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 its 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 we can be sure that the most significant bit of `t1'  */        /* is the most significant bit of either `a', `b', or `c',   */        /* depending on the greatest integer range of the particular */        /* variable.                                                 */        /*                                                           */        /* Next, we 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., 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 polynomial coefficients.     */        /*                                                           */        /* This algorithm should ensure reasonably accurate values   */        /* for the zeros.  Note that they 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 );          /* this loses 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 */          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 subdivide 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 + -