public static PdnGraphicsPath FromRegion(PdnRegion region)
        {
            Rectangle[] scans = region.GetRegionScansReadOnlyInt();

            if (scans.Length == 1)
            {
                PdnGraphicsPath path = new PdnGraphicsPath();
                path.AddRectangle(scans[0]);
                path.CloseFigure();
                return(path);
            }
            else
            {
                Rectangle   bounds  = region.GetBoundsInt();
                BitVector2D stencil = new BitVector2D(bounds.Width, bounds.Height);

                for (int i = 0; i < scans.Length; ++i)
                {
                    Rectangle rect = scans[i];
                    rect.X -= bounds.X;
                    rect.Y -= bounds.Y;

                    stencil.SetUnchecked(rect, true);
                }

                PdnGraphicsPath path = PathFromStencil(stencil, new Rectangle(0, 0, stencil.Width, stencil.Height));

                using (Matrix matrix = new Matrix())
                {
                    matrix.Reset();
                    matrix.Translate(bounds.X, bounds.Y);
                    path.Transform(matrix);
                }

                return(path);
            }
        }
        /// <summary>
        /// Creates a graphics path from the given stencil buffer. It should be filled with 'true' values
        /// to indicate the areas that should be outlined.
        /// </summary>
        /// <param name="stencil">The stencil buffer to read from. NOTE: The contents of this will be destroyed when this method returns.</param>
        /// <param name="bounds">The bounding box within the stencil buffer to limit discovery to.</param>
        /// <returns>A PdnGraphicsPath with traces that outline the various areas from the given stencil buffer.</returns>
        public unsafe static PdnGraphicsPath PathFromStencil(IBitVector2D stencil, Rectangle bounds)
        {
            if (stencil.IsEmpty)
            {
                return(new PdnGraphicsPath());
            }

            PdnGraphicsPath ret   = new PdnGraphicsPath();
            Point           start = bounds.Location;
            Vector <Point>  pts   = new Vector <Point>();
            int             count = 0;

            // find all islands
            while (true)
            {
                bool startFound = false;

                while (true)
                {
                    if (stencil[start])
                    {
                        startFound = true;
                        break;
                    }

                    ++start.X;

                    if (start.X >= bounds.Right)
                    {
                        ++start.Y;
                        start.X = bounds.Left;

                        if (start.Y >= bounds.Bottom)
                        {
                            break;
                        }
                    }
                }

                if (!startFound)
                {
                    break;
                }

                pts.Clear();
                Point last  = new Point(start.X, start.Y + 1);
                Point curr  = new Point(start.X, start.Y);
                Point next  = curr;
                Point left  = Point.Empty;
                Point right = Point.Empty;

                // trace island outline
                while (true)
                {
                    left.X = ((curr.X - last.X) + (curr.Y - last.Y) + 2) / 2 + curr.X - 1;
                    left.Y = ((curr.Y - last.Y) - (curr.X - last.X) + 2) / 2 + curr.Y - 1;

                    right.X = ((curr.X - last.X) - (curr.Y - last.Y) + 2) / 2 + curr.X - 1;
                    right.Y = ((curr.Y - last.Y) + (curr.X - last.X) + 2) / 2 + curr.Y - 1;

                    if (bounds.Contains(left) && stencil[left])
                    {
                        // go left
                        next.X += curr.Y - last.Y;
                        next.Y -= curr.X - last.X;
                    }
                    else if (bounds.Contains(right) && stencil[right])
                    {
                        // go straight
                        next.X += curr.X - last.X;
                        next.Y += curr.Y - last.Y;
                    }
                    else
                    {
                        // turn right
                        next.X -= curr.Y - last.Y;
                        next.Y += curr.X - last.X;
                    }

                    if (Math.Sign(next.X - curr.X) != Math.Sign(curr.X - last.X) ||
                        Math.Sign(next.Y - curr.Y) != Math.Sign(curr.Y - last.Y))
                    {
                        pts.Add(curr);
                        ++count;
                    }

                    last = curr;
                    curr = next;

                    if (next.X == start.X && next.Y == start.Y)
                    {
                        break;
                    }
                }

                Point[]    points = pts.ToArray();
                Scanline[] scans  = Utility.GetScans(points);

                foreach (Scanline scan in scans)
                {
                    stencil.Invert(scan);
                }

                ret.AddLines(points);
                ret.CloseFigure();
            }

            return(ret);
        }
        /// <summary>
        /// Creates a graphics path from the given stencil buffer. It should be filled with 'true' values
        /// to indicate the areas that should be outlined.
        /// </summary>
        /// <param name="stencil">The stencil buffer to read from. NOTE: The contents of this will be destroyed when this method returns.</param>
        /// <param name="bounds">The bounding box within the stencil buffer to limit discovery to.</param>
        /// <returns>A PdnGraphicsPath with traces that outline the various areas from the given stencil buffer.</returns>
        public unsafe static PdnGraphicsPath PathFromStencil(IBitVector2D stencil, Rectangle bounds)
        {
            if (stencil.IsEmpty)
            {
                return new PdnGraphicsPath();
            }

            PdnGraphicsPath ret = new PdnGraphicsPath();
            Point start = bounds.Location;
            Vector<Point> pts = new Vector<Point>();
            int count = 0;

            // find all islands
            while (true) 
            {
                bool startFound = false;

                while (true)
                {
                    if (stencil[start])
                    {
                        startFound = true;
                        break;
                    }

                    ++start.X;

                    if (start.X >= bounds.Right)
                    {
                        ++start.Y;
                        start.X = bounds.Left;

                        if (start.Y >= bounds.Bottom)
                        {
                            break;
                        }
                    }
                }
            
                if (!startFound)
                {
                    break;
                }

                pts.Clear();
                Point last = new Point(start.X, start.Y + 1);
                Point curr = new Point(start.X, start.Y);
                Point next = curr;
                Point left = Point.Empty;
                Point right = Point.Empty;
            
                // trace island outline
                while (true)
                {
                    left.X = ((curr.X - last.X) + (curr.Y - last.Y) + 2) / 2 + curr.X - 1;
                    left.Y = ((curr.Y - last.Y) - (curr.X - last.X) + 2) / 2 + curr.Y - 1;

                    right.X = ((curr.X - last.X) - (curr.Y - last.Y) + 2) / 2 + curr.X - 1;
                    right.Y = ((curr.Y - last.Y) + (curr.X - last.X) + 2) / 2 + curr.Y - 1;

                    if (bounds.Contains(left) && stencil[left])
                    {
                        // go left
                        next.X += curr.Y - last.Y;
                        next.Y -= curr.X - last.X;
                    }
                    else if (bounds.Contains(right) && stencil[right])
                    {
                        // go straight
                        next.X += curr.X - last.X;
                        next.Y += curr.Y - last.Y;
                    }
                    else
                    {
                        // turn right
                        next.X -= curr.Y - last.Y;
                        next.Y += curr.X - last.X;
                    }

                    if (Math.Sign(next.X - curr.X) != Math.Sign(curr.X - last.X) ||
                        Math.Sign(next.Y - curr.Y) != Math.Sign(curr.Y - last.Y))
                    {
                        pts.Add(curr);
                        ++count;
                    }

                    last = curr;
                    curr = next;

                    if (next.X == start.X && next.Y == start.Y)
                    {
                        break;
                    }
                }

                Point[] points = pts.ToArray();
                Scanline[] scans = Utility.GetScans(points);

                foreach (Scanline scan in scans)
                {
                    stencil.Invert(scan);
                }

                ret.AddLines(points);
                ret.CloseFigure();
            }

            return ret;
        }
        public static PdnGraphicsPath FromRegion(PdnRegion region)
        {
            Rectangle[] scans = region.GetRegionScansReadOnlyInt();

            if (scans.Length == 1)
            {
                PdnGraphicsPath path = new PdnGraphicsPath();
                path.AddRectangle(scans[0]);
                path.CloseFigure();
                return path;
            }
            else
            {
                Rectangle bounds = region.GetBoundsInt();
                BitVector2D stencil = new BitVector2D(bounds.Width, bounds.Height);

                for (int i = 0; i < scans.Length; ++i)
                {
                    Rectangle rect = scans[i];
                    rect.X -= bounds.X;
                    rect.Y -= bounds.Y;

                    stencil.SetUnchecked(rect, true);
                }

                PdnGraphicsPath path = PathFromStencil(stencil, new Rectangle(0, 0, stencil.Width, stencil.Height));

                using (Matrix matrix = new Matrix())
                {
                    matrix.Reset();
                    matrix.Translate(bounds.X, bounds.Y);
                    path.Transform(matrix);
                }

                return path;
            }
        }