Beispiel #1
0
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 );
            }
        }
    }
Beispiel #2
0
  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 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 );
        }
      }
    }