예제 #1
0
        ////////////////////////////////////////////////////////////////////////////
        //--------------------------------- REVISIONS ------------------------------
        // Date       Name                 Tracking #         Description
        // ---------  -------------------  -------------      ----------------------
        // 13JUN2009  James Shen                              Initial Creation
        ////////////////////////////////////////////////////////////////////////////
        private void Next(bool doNext)
        {
            int level;

            if (_holdIndex >= _holdEnd)
            {
                if (doNext)
                {
                    _src.Next();
                }
                if (_src.IsDone())
                {
                    _done = true;
                    return;
                }
                _holdType = _src.CurrentSegment(_intHold);
                for (int i = 0; i < _intHold.Length; i++)
                {
                    _hold[i] = _intHold[i];
                }
                _levelIndex = 0;
                _levels[0]  = 0;
            }

            switch (_holdType)
            {
            case SEG_MOVETO:
            case SEG_LINETO:
                _curx = _hold[0];
                _cury = _hold[1];
                if (_holdType == SEG_MOVETO)
                {
                    _movx = _curx;
                    _movy = _cury;
                }
                _holdIndex = 0;
                _holdEnd   = 0;
                break;

            case SEG_CLOSE:
                _curx      = _movx;
                _cury      = _movy;
                _holdIndex = 0;
                _holdEnd   = 0;
                break;

            case SEG_QUADTO:
                if (_holdIndex >= _holdEnd)
                {
                    // Move the coordinates to the end of the array.
                    _holdIndex            = _hold.Length - 6;
                    _holdEnd              = _hold.Length - 2;
                    _hold[_holdIndex + 0] = _curx;
                    _hold[_holdIndex + 1] = _cury;
                    _hold[_holdIndex + 2] = _hold[0];
                    _hold[_holdIndex + 3] = _hold[1];
                    _hold[_holdIndex + 4] = _curx = _hold[2];
                    _hold[_holdIndex + 5] = _cury = _hold[3];
                }

                level = _levels[_levelIndex];
                while (level < _limit)
                {
                    for (int i = 0; i < _intHold.Length; i++)
                    {
                        _intHold[i] = (int)(_hold[i] + .5);
                    }
                    if (QuadCurve.GetFlatnessSq(_intHold, _holdIndex) < _squareflat)
                    {
                        break;
                    }

                    EnsureHoldCapacity(4);
                    QuadCurve.Subdivide(_hold, _holdIndex,
                                        _hold, _holdIndex - 4,
                                        _hold, _holdIndex);
                    _holdIndex -= 4;

                    // Now that we have subdivided, we have constructed
                    // two curves of one depth lower than the original
                    // curve.  One of those curves is in the place of
                    // the former curve and one of them is in the next
                    // set of held coordinate slots.  We now set both
                    // curves level values to the next higher level.
                    level++;
                    _levels[_levelIndex] = level;
                    _levelIndex++;
                    _levels[_levelIndex] = level;
                }

                // This curve segment is flat enough, or it is too deep
                // in recursion levels to try to flatten any more.  The
                // two coordinates at holdIndex+4 and holdIndex+5 now
                // contain the endpoint of the curve which can be the
                // endpoint of an approximating line segment.
                _holdIndex += 4;
                _levelIndex--;
                break;

            case SEG_CUBICTO:
                if (_holdIndex >= _holdEnd)
                {
                    // Move the coordinates to the end of the array.
                    _holdIndex            = _hold.Length - 8;
                    _holdEnd              = _hold.Length - 2;
                    _hold[_holdIndex + 0] = _curx;
                    _hold[_holdIndex + 1] = _cury;
                    _hold[_holdIndex + 2] = _hold[0];
                    _hold[_holdIndex + 3] = _hold[1];
                    _hold[_holdIndex + 4] = _hold[2];
                    _hold[_holdIndex + 5] = _hold[3];
                    _hold[_holdIndex + 6] = _curx = _hold[4];
                    _hold[_holdIndex + 7] = _cury = _hold[5];
                }

                level = _levels[_levelIndex];
                while (level < _limit)
                {
                    for (int i = 0; i < _intHold.Length; i++)
                    {
                        _intHold[i] = (int)(_hold[i] + .5);
                    }
                    if (CubicCurve.GetFlatnessSq(_intHold, _holdIndex) < _squareflat)
                    {
                        break;
                    }

                    EnsureHoldCapacity(6);
                    CubicCurve.Subdivide(_hold, _holdIndex,
                                         _hold, _holdIndex - 6,
                                         _hold, _holdIndex);
                    _holdIndex -= 6;

                    // Now that we have subdivided, we have constructed
                    // two curves of one depth lower than the original
                    // curve.  One of those curves is in the place of
                    // the former curve and one of them is in the next
                    // set of held coordinate slots.  We now set both
                    // curves level values to the next higher level.
                    level++;
                    _levels[_levelIndex] = level;
                    _levelIndex++;
                    _levels[_levelIndex] = level;
                }

                // This curve segment is flat enough, or it is too deep
                // in recursion levels to try to flatten any more.  The
                // two coordinates at holdIndex+6 and holdIndex+7 now
                // contain the endpoint of the curve which can be the
                // endpoint of an approximating line segment.
                _holdIndex += 6;
                _levelIndex--;
                break;
            }
        }
예제 #2
0
 /**
  * Calculates the number of times the given path
  * crosses the ray extending to the right from (px,py).
  * If the point lies on a part of the path,
  * then no crossings are counted for that intersection.
  * +1 is added for each crossing where the Y coordinate is increasing
  * -1 is added for each crossing where the Y coordinate is decreasing
  * The return Value is the sum of all crossings for every segment in
  * the path.
  * The path must start with a SEG_MOVETO, otherwise an exception is
  * thrown.
  * The caller must check p[xy] for NaN values.
  * The caller may also reject infinite p[xy] values as well.
  */
 public static int PointCrossingsForPath(PathIterator pi,
         double px, double py)
 {
     if (pi.IsDone())
     {
         return 0;
     }
     int[] coords = new int[6];
     if (pi.CurrentSegment(coords) != PathIterator.SEG_MOVETO)
     {
         throw new IllegalPathStateException("missing initial moveto " +
                 "in path definition");
     }
     pi.Next();
     double movx = coords[0];
     double movy = coords[1];
     double curx = movx;
     double cury = movy;
     int crossings = 0;
     while (!pi.IsDone())
     {
         double endx;
         double endy;
         switch (pi.CurrentSegment(coords))
         {
             case PathIterator.SEG_MOVETO:
                 if (cury != movy)
                 {
                     crossings += PointCrossingsForLine(px, py,
                             curx, cury,
                             movx, movy);
                 }
                 movx = curx = coords[0];
                 movy = cury = coords[1];
                 break;
             case PathIterator.SEG_LINETO:
                 endx = coords[0];
                 endy = coords[1];
                 crossings += PointCrossingsForLine(px, py,
                         curx, cury,
                         endx, endy);
                 curx = endx;
                 cury = endy;
                 break;
             case PathIterator.SEG_QUADTO:
                 endx = coords[2];
                 endy = coords[3];
                 crossings += PointCrossingsForQuad(px, py,
                         curx, cury,
                         coords[0], coords[1],
                         endx, endy, 0);
                 curx = endx;
                 cury = endy;
                 break;
             case PathIterator.SEG_CUBICTO:
                 endx = coords[4];
                 endy = coords[5];
                 crossings += PointCrossingsForCubic(px, py,
                         curx, cury,
                         coords[0], coords[1],
                         coords[2], coords[3],
                         endx, endy, 0);
                 curx = endx;
                 cury = endy;
                 break;
             case PathIterator.SEG_CLOSE:
                 if (cury != movy)
                 {
                     crossings += PointCrossingsForLine(px, py,
                             curx, cury,
                             movx, movy);
                 }
                 curx = movx;
                 cury = movy;
                 break;
         }
         pi.Next();
     }
     if (cury != movy)
     {
         crossings += PointCrossingsForLine(px, py,
                 curx, cury,
                 movx, movy);
     }
     return crossings;
 }
예제 #3
0
 /**
  * Accumulate the number of times the path crosses the shadow
  * extending to the right of the rectangle.  See the comment
  * for the RECT_INTERSECTS constant for more complete details.
  * The return Value is the sum of all crossings for both the
  * top and bottom of the shadow for every segment in the path,
  * or the special Value RECT_INTERSECTS if the path ever enters
  * the interior of the rectangle.
  * The path must start with a SEG_MOVETO, otherwise an exception is
  * thrown.
  * The caller must check r[xy]{Min,Max} for NaN values.
  */
 public static int RectCrossingsForPath(PathIterator pi,
         double rxmin, double rymin,
         double rxmax, double rymax)
 {
     if (rxmax <= rxmin || rymax <= rymin)
     {
         return 0;
     }
     if (pi.IsDone())
     {
         return 0;
     }
     int[] coords = new int[6];
     if (pi.CurrentSegment(coords) != PathIterator.SEG_MOVETO)
     {
         throw new IllegalPathStateException("missing initial moveto " +
                 "in path definition");
     }
     pi.Next();
     double movx, movy;
     double curx = movx = coords[0];
     double cury = movy = coords[1];
     int crossings = 0;
     while (crossings != RECT_INTERSECTS && !pi.IsDone())
     {
         double endx;
         double endy;
         switch (pi.CurrentSegment(coords))
         {
             case PathIterator.SEG_MOVETO:
                 if (curx != movx || cury != movy)
                 {
                     crossings = RectCrossingsForLine(crossings,
                             rxmin, rymin,
                             rxmax, rymax,
                             curx, cury,
                             movx, movy);
                 }
                 // Count should always be a multiple of 2 here.
                 // assert((crossings & 1) != 0);
                 movx = curx = coords[0];
                 movy = cury = coords[1];
                 break;
             case PathIterator.SEG_LINETO:
                 endx = coords[0];
                 endy = coords[1];
                 crossings = RectCrossingsForLine(crossings,
                         rxmin, rymin,
                         rxmax, rymax,
                         curx, cury,
                         endx, endy);
                 curx = endx;
                 cury = endy;
                 break;
             case PathIterator.SEG_QUADTO:
                 endx = coords[2];
                 endy = coords[3];
                 crossings = RectCrossingsForQuad(crossings,
                         rxmin, rymin,
                         rxmax, rymax,
                         curx, cury,
                         coords[0], coords[1],
                         endx, endy, 0);
                 curx = endx;
                 cury = endy;
                 break;
             case PathIterator.SEG_CUBICTO:
                 endx = coords[4];
                 endy = coords[5];
                 crossings = RectCrossingsForCubic(crossings,
                         rxmin, rymin,
                         rxmax, rymax,
                         curx, cury,
                         coords[0], coords[1],
                         coords[2], coords[3],
                         endx, endy, 0);
                 curx = endx;
                 cury = endy;
                 break;
             case PathIterator.SEG_CLOSE:
                 if (curx != movx || cury != movy)
                 {
                     crossings = RectCrossingsForLine(crossings,
                             rxmin, rymin,
                             rxmax, rymax,
                             curx, cury,
                             movx, movy);
                 }
                 curx = movx;
                 cury = movy;
                 // Count should always be a multiple of 2 here.
                 // assert((crossings & 1) != 0);
                 break;
         }
         pi.Next();
     }
     if (crossings != RECT_INTERSECTS && (curx != movx || cury != movy))
     {
         crossings = RectCrossingsForLine(crossings,
                 rxmin, rymin,
                 rxmax, rymax,
                 curx, cury,
                 movx, movy);
     }
     // Count should always be a multiple of 2 here.
     // assert((crossings & 1) != 0);
     return crossings;
 }
예제 #4
0
        ////////////////////////////////////////////////////////////////////////////
        //--------------------------------- REVISIONS ------------------------------
        // Date       Name                 Tracking #         Description
        // ---------  -------------------  -------------      ----------------------
        // 13JUN2009  James Shen                              Initial Creation
        ////////////////////////////////////////////////////////////////////////////
        private static ArrayList PathToCurves(PathIterator pi)
        {
            ArrayList curves      = new ArrayList();
            int       windingRule = pi.GetWindingRule();
            // coords array is big enough for holding:
            //     coordinates returned from currentSegment (6)
            //     OR
            //         two subdivided quadratic curves (2+4+4=10)
            //         AND
            //             0-1 horizontal splitting parameters
            //             OR
            //             2 parametric equation derivative coefficients
            //     OR
            //         three subdivided cubic curves (2+6+6+6=20)
            //         AND
            //             0-2 horizontal splitting parameters
            //             OR
            //             3 parametric equation derivative coefficients
            var    coords = new int[23];
            double movx = 0, movy = 0;
            double curx = 0, cury = 0;

            while (!pi.IsDone())
            {
                double newx;
                double newy;
                switch (pi.CurrentSegment(coords))
                {
                case PathIterator.SEG_MOVETO:
                    Curve.InsertLine(curves, curx, cury, movx, movy);
                    curx = movx = coords[0];
                    cury = movy = coords[1];
                    Curve.InsertMove(curves, movx, movy);
                    break;

                case PathIterator.SEG_LINETO:
                    newx = coords[0];
                    newy = coords[1];
                    Curve.InsertLine(curves, curx, cury, newx, newy);
                    curx = newx;
                    cury = newy;
                    break;

                case PathIterator.SEG_QUADTO:
                {
                    newx = coords[2];
                    newy = coords[3];
                    var dblCoords = new double[coords.Length];
                    for (int i = 0; i < coords.Length; i++)
                    {
                        dblCoords[i] = coords[i];
                    }
                    Curve.InsertQuad(curves, curx, cury, dblCoords);
                    curx = newx;
                    cury = newy;
                }
                break;

                case PathIterator.SEG_CUBICTO:
                {
                    newx = coords[4];
                    newy = coords[5];
                    var dblCoords = new double[coords.Length];
                    for (int i = 0; i < coords.Length; i++)
                    {
                        dblCoords[i] = coords[i];
                    }
                    Curve.InsertCubic(curves, curx, cury, dblCoords);
                    curx = newx;
                    cury = newy;
                }
                break;

                case PathIterator.SEG_CLOSE:
                    Curve.InsertLine(curves, curx, cury, movx, movy);
                    curx = movx;
                    cury = movy;
                    break;
                }
                pi.Next();
            }
            Curve.InsertLine(curves, curx, cury, movx, movy);
            AreaOp op;

            if (windingRule == PathIterator.WIND_EVEN_ODD)
            {
                op = new AreaOp.EoWindOp();
            }
            else
            {
                op = new AreaOp.NzWindOp();
            }
            return(op.Calculate(curves, EmptyCurves));
        }
예제 #5
0
        public static Crossings FindCrossings(PathIterator pi,
                                              double xlo, double ylo,
                                              double xhi, double yhi)
        {
            Crossings cross;

            if (pi.GetWindingRule() == PathIterator.WIND_EVEN_ODD)
            {
                cross = new EvenOdd(xlo, ylo, xhi, yhi);
            }
            else
            {
                cross = new NonZero(xlo, ylo, xhi, yhi);
            }
            // coords array is big enough for holding:
            //     coordinates returned from currentSegment (6)
            //     OR
            //         two subdivided quadratic curves (2+4+4=10)
            //         AND
            //             0-1 horizontal splitting parameters
            //             OR
            //             2 parametric equation derivative coefficients
            //     OR
            //         three subdivided cubic curves (2+6+6+6=20)
            //         AND
            //             0-2 horizontal splitting parameters
            //             OR
            //             3 parametric equation derivative coefficients
            var    coords = new int[23];
            double movx   = 0;
            double movy   = 0;
            double curx   = 0;
            double cury   = 0;

            while (!pi.IsDone())
            {
                int    type = pi.CurrentSegment(coords);
                double newx;
                double newy;
                switch (type)
                {
                case PathIterator.SEG_MOVETO:
                    if (movy != cury &&
                        cross.AccumulateLine(curx, cury, movx, movy))
                    {
                        return(null);
                    }
                    movx = curx = coords[0];
                    movy = cury = coords[1];
                    break;

                case PathIterator.SEG_LINETO:
                    newx = coords[0];
                    newy = coords[1];
                    if (cross.AccumulateLine(curx, cury, newx, newy))
                    {
                        return(null);
                    }
                    curx = newx;
                    cury = newy;
                    break;

                case PathIterator.SEG_QUADTO:
                {
                    newx = coords[2];
                    newy = coords[3];
                    var dblCoords = new double[coords.Length];
                    for (int i = 0; i < coords.Length; i++)
                    {
                        dblCoords[i] = coords[i];
                    }
                    if (cross.AccumulateQuad(curx, cury, dblCoords))
                    {
                        return(null);
                    }
                    curx = newx;
                    cury = newy;
                }
                break;

                case PathIterator.SEG_CUBICTO:
                {
                    newx = coords[4];
                    newy = coords[5];
                    var dblCoords = new double[coords.Length];
                    for (int i = 0; i < coords.Length; i++)
                    {
                        dblCoords[i] = coords[i];
                    }
                    if (cross.AccumulateCubic(curx, cury, dblCoords))
                    {
                        return(null);
                    }
                    curx = newx;
                    cury = newy;
                    break;
                }

                case PathIterator.SEG_CLOSE:
                    if (movy != cury &&
                        cross.AccumulateLine(curx, cury, movx, movy))
                    {
                        return(null);
                    }
                    curx = movx;
                    cury = movy;
                    break;
                }
                pi.Next();
            }
            if (movy != cury)
            {
                if (cross.AccumulateLine(curx, cury, movx, movy))
                {
                    return(null);
                }
            }

            return(cross);
        }
예제 #6
0
        public static Crossings FindCrossings(PathIterator pi,
                double xlo, double ylo,
                double xhi, double yhi)
        {
            Crossings cross;
            if (pi.GetWindingRule() == PathIterator.WIND_EVEN_ODD)
            {
                cross = new EvenOdd(xlo, ylo, xhi, yhi);
            }
            else
            {
                cross = new NonZero(xlo, ylo, xhi, yhi);
            }
            // coords array is big enough for holding:
            //     coordinates returned from currentSegment (6)
            //     OR
            //         two subdivided quadratic curves (2+4+4=10)
            //         AND
            //             0-1 horizontal splitting parameters
            //             OR
            //             2 parametric equation derivative coefficients
            //     OR
            //         three subdivided cubic curves (2+6+6+6=20)
            //         AND
            //             0-2 horizontal splitting parameters
            //             OR
            //             3 parametric equation derivative coefficients
            var coords = new int[23];
            double movx = 0;
            double movy = 0;
            double curx = 0;
            double cury = 0;
            while (!pi.IsDone())
            {
                int type = pi.CurrentSegment(coords);
                double newx;
                double newy;
                switch (type)
                {
                    case PathIterator.SEG_MOVETO:
                        if (movy != cury &&
                                cross.AccumulateLine(curx, cury, movx, movy))
                        {
                            return null;
                        }
                        movx = curx = coords[0];
                        movy = cury = coords[1];
                        break;
                    case PathIterator.SEG_LINETO:
                        newx = coords[0];
                        newy = coords[1];
                        if (cross.AccumulateLine(curx, cury, newx, newy))
                        {
                            return null;
                        }
                        curx = newx;
                        cury = newy;
                        break;
                    case PathIterator.SEG_QUADTO:
                        {
                            newx = coords[2];
                            newy = coords[3];
                            var dblCoords = new double[coords.Length];
                            for (int i = 0; i < coords.Length; i++)
                            {
                                dblCoords[i] = coords[i];
                            }
                            if (cross.AccumulateQuad(curx, cury, dblCoords))
                            {
                                return null;
                            }
                            curx = newx;
                            cury = newy;
                        }
                        break;
                    case PathIterator.SEG_CUBICTO:
                        {
                            newx = coords[4];
                            newy = coords[5];
                            var dblCoords = new double[coords.Length];
                            for (int i = 0; i < coords.Length; i++)
                            {
                                dblCoords[i] = coords[i];
                            }
                            if (cross.AccumulateCubic(curx, cury, dblCoords))
                            {
                                return null;
                            }
                            curx = newx;
                            cury = newy;
                            break;
                        }
                    case PathIterator.SEG_CLOSE:
                        if (movy != cury &&
                                cross.AccumulateLine(curx, cury, movx, movy))
                        {
                            return null;
                        }
                        curx = movx;
                        cury = movy;
                        break;
                }
                pi.Next();
            }
            if (movy != cury)
            {
                if (cross.AccumulateLine(curx, cury, movx, movy))
                {
                    return null;
                }
            }

            return cross;
        }
예제 #7
0
 ////////////////////////////////////////////////////////////////////////////
 //--------------------------------- REVISIONS ------------------------------
 // Date       Name                 Tracking #         Description
 // ---------  -------------------  -------------      ----------------------
 // 13JUN2009  James Shen                 	          Initial Creation
 ////////////////////////////////////////////////////////////////////////////
 private static ArrayList PathToCurves(PathIterator pi)
 {
     ArrayList curves = new ArrayList();
     int windingRule = pi.GetWindingRule();
     // coords array is big enough for holding:
     //     coordinates returned from currentSegment (6)
     //     OR
     //         two subdivided quadratic curves (2+4+4=10)
     //         AND
     //             0-1 horizontal splitting parameters
     //             OR
     //             2 parametric equation derivative coefficients
     //     OR
     //         three subdivided cubic curves (2+6+6+6=20)
     //         AND
     //             0-2 horizontal splitting parameters
     //             OR
     //             3 parametric equation derivative coefficients
     var coords = new int[23];
     double movx = 0, movy = 0;
     double curx = 0, cury = 0;
     while (!pi.IsDone())
     {
         double newx;
         double newy;
         switch (pi.CurrentSegment(coords))
         {
             case PathIterator.SEG_MOVETO:
                 Curve.InsertLine(curves, curx, cury, movx, movy);
                 curx = movx = coords[0];
                 cury = movy = coords[1];
                 Curve.InsertMove(curves, movx, movy);
                 break;
             case PathIterator.SEG_LINETO:
                 newx = coords[0];
                 newy = coords[1];
                 Curve.InsertLine(curves, curx, cury, newx, newy);
                 curx = newx;
                 cury = newy;
                 break;
             case PathIterator.SEG_QUADTO:
                 {
                     newx = coords[2];
                     newy = coords[3];
                     var dblCoords = new double[coords.Length];
                     for (int i = 0; i < coords.Length; i++)
                     {
                         dblCoords[i] = coords[i];
                     }
                     Curve.InsertQuad(curves, curx, cury, dblCoords);
                     curx = newx;
                     cury = newy;
                 }
                 break;
             case PathIterator.SEG_CUBICTO:
                 {
                     newx = coords[4];
                     newy = coords[5];
                     var dblCoords = new double[coords.Length];
                     for (int i = 0; i < coords.Length; i++)
                     {
                         dblCoords[i] = coords[i];
                     }
                     Curve.InsertCubic(curves, curx, cury, dblCoords);
                     curx = newx;
                     cury = newy;
                 }
                 break;
             case PathIterator.SEG_CLOSE:
                 Curve.InsertLine(curves, curx, cury, movx, movy);
                 curx = movx;
                 cury = movy;
                 break;
         }
         pi.Next();
     }
     Curve.InsertLine(curves, curx, cury, movx, movy);
     AreaOp op;
     if (windingRule == PathIterator.WIND_EVEN_ODD)
     {
         op = new AreaOp.EoWindOp();
     }
     else
     {
         op = new AreaOp.NzWindOp();
     }
     return op.Calculate(curves, EmptyCurves);
 }
예제 #8
0
 ////////////////////////////////////////////////////////////////////////////
 //--------------------------------- REVISIONS ------------------------------
 // Date       Name                 Tracking #         Description
 // ---------  -------------------  -------------      ----------------------
 // 13JUN2009  James Shen                 	          Initial Creation
 ////////////////////////////////////////////////////////////////////////////
 /**
  * Appends the geometry of the specified
  * {@link PathIterator} object
  * to the path, possibly connecting the new geometry to the existing
  * path segments with a line segment.
  * If the {@code connect} parameter is {@code true} and the
  * path is not empty then any initial {@code moveTo} in the
  * geometry of the appended {@code IShape} is turned into a
  * {@code lineTo} segment.
  * If the destination coordinates of such a connecting {@code lineTo}
  * segment match the ending coordinates of a currently open
  * subpath then the segment is omitted as superfluous.
  * The winding rule of the specified {@code IShape} is ignored
  * and the appended geometry is governed by the winding
  * rule specified for this path.
  *
  * @param pi the {@code PathIterator} whose geometry is appended to
  *           this path
  * @param connect a bool to control whether or not to turn an initial
  *                {@code moveTo} segment into a {@code lineTo} segment
  *                to connect the new geometry to the existing path
  */
 public void Append(PathIterator pi, bool connect)
 {
     int[] coords = new int[6];
     while (!pi.IsDone())
     {
         switch (pi.CurrentSegment(coords))
         {
             case SEG_MOVETO:
                 if (!connect || _numTypes < 1 || _numCoords < 1)
                 {
                     MoveTo(coords[0], coords[1]);
                     break;
                 }
                 if (_pointTypes[_numTypes - 1] != SEG_CLOSE &&
                         _intCoords[_numCoords - 2] == coords[0] &&
                         _intCoords[_numCoords - 1] == coords[1])
                 {
                     // Collapse out initial moveto/lineto
                     break;
                 }
                 LineTo(coords[0], coords[1]);
                 break;
             case SEG_LINETO:
                 LineTo(coords[0], coords[1]);
                 break;
             case SEG_QUADTO:
                 QuadTo(coords[0], coords[1],
                         coords[2], coords[3]);
                 break;
             case SEG_CUBICTO:
                 CurveTo(coords[0], coords[1],
                         coords[2], coords[3],
                         coords[4], coords[5]);
                 break;
             case SEG_CLOSE:
                 ClosePath();
                 break;
         }
         pi.Next();
         connect = false;
     }
 }