private bool KDirStat_ArrangeChildren(ITreemapItem parent, Number[] childWidth, List <Number> rows, List <int> childrenPerRow)
        {
            Debug.Assert(!parent.IsLeaf);
            Debug.Assert(parent.ChildCount > 0);

            if (parent.Size == 0)
            {
                rows.Add(1);
                childrenPerRow.Add(parent.ChildCount);
                for (int i = 0; i < parent.ChildCount; i++)
                {
                    childWidth[i] = 1 / parent.ChildCount;
                }
                return(true);
            }

            bool horizontalRows = parent.Rectangle.Width >= parent.Rectangle.Height;

            Number width = 1;

            if (horizontalRows)
            {
                if (parent.Rectangle.Height > 0)
                {
                    width = (Number)parent.Rectangle.Width / parent.Rectangle.Height;
                }
            }
            else
            {
                if (parent.Rectangle.Width > 0)
                {
                    width = (Number)parent.Rectangle.Height / parent.Rectangle.Width;
                }
            }

            int nextChild = 0;

            while (nextChild < parent.ChildCount)
            {
                rows.Add(KDirStat_CalculateNextRow(parent, nextChild, width, out int childrenUsed, childWidth));
                childrenPerRow.Add(childrenUsed);
                nextChild += childrenUsed;
            }

            return(horizontalRows);
        }
        private void DrawChildren(Rgba32Color *bitmap, ITreemapItem parent, Number[] surface, Number h, uint flags)
        {
            switch (options.Style)
            {
            case TreemapStyle.KDirStatStyle:
                KDirStat_DrawChildren(bitmap, parent, surface, h, flags);
                break;

            case TreemapStyle.SequoiaViewStyle:
                throw new NotImplementedException("SequoiaViewStyle");

            //SequoiaView_DrawwChildren(bitmap, parent, surface, h, flags);
            //break;
            case TreemapStyle.SimpleStyle:
                throw new NotImplementedException("SimpleStyle");
                //Simple_DrawwChildren(bitmap, parent, surface, h, flags);
                //break;
            }
        }
        private void RecurseDrawGraph(Rgba32Color *bitmap, ITreemapItem item, Rectangle2I rc,
                                      bool isroot, Number[] pSurface, Number h, uint flags)
        {
            Debug.Assert(rc.Width >= 0);
            Debug.Assert(rc.Height >= 0);
            Debug.Assert(item.Size > 0);

            item.Rectangle = rc;

            int gridWidth = options.Grid ? 1 : 0;

            if (rc.Width <= gridWidth || rc.Height <= gridWidth)
            {
                return;
            }

            Number[] surface = new Number[] { 0, 0, 0, 0 };
            if (IsCushionShading)
            {
                Array.Copy(pSurface, surface, pSurface.Length);

                if (!isroot)
                {
                    AddRidge(rc, surface, h);
                }
            }

            if (item.IsLeaf)
            {
                RenderLeaf(bitmap, item, surface);
            }
            else
            {
                Debug.Assert(item.ChildCount > 0);
                Debug.Assert(item.Size > 0);

                DrawChildren(bitmap, item, surface, h, flags);
            }
        }
        private void KDirStat_DrawChildren(Rgba32Color *bitmap, ITreemapItem parent, Number[] surface, Number h, uint flags)
        {
            Debug.Assert(parent.ChildCount > 0);

            Rectangle2I   rc             = parent.Rectangle;
            List <Number> rows           = new List <Number>();
            List <int>    childrenPerRow = new List <int>();

            Number[] childWidth = new Number[parent.ChildCount];

            bool horizontalRows = KDirStat_ArrangeChildren(parent, childWidth, rows, childrenPerRow);

            int width  = horizontalRows ? rc.Width : rc.Height;
            int height = horizontalRows ? rc.Height : rc.Width;

            Debug.Assert(width >= 0);
            Debug.Assert(height >= 0);

            int    c   = 0;
            Number top = horizontalRows ? rc.Top : rc.Left;

            for (int row = 0; row < rows.Count; row++)
            {
                Number fBottom = top + rows[row] * height;
                int    bottom  = (int)fBottom;
                if (row == rows.Count - 1)
                {
                    bottom = horizontalRows ? rc.Bottom : rc.Right;
                }
                Number left = horizontalRows ? rc.Left : rc.Top;
                for (int i = 0; i < childrenPerRow[row]; i++, c++)
                {
                    ITreemapItem child = parent[c];
                    Debug.Assert(childWidth[c] >= 0);
                    Number fRight = left + childWidth[c] * width;
                    int    right  = (int)fRight;

                    bool lastChild = (i == childrenPerRow[row] - 1 || childWidth[c + 1] == 0);

                    if (lastChild)
                    {
                        right = horizontalRows ? rc.Right : rc.Bottom;
                    }

                    Rectangle2I rcChild;
                    if (horizontalRows)
                    {
                        rcChild = Rectangle2I.FromLTRB((int)left, (int)top, right, bottom);
                    }
                    else
                    {
                        rcChild = Rectangle2I.FromLTRB((int)top, (int)left, bottom, right);
                    }

#if DEBUG
                    if (rcChild.Width > 0 && rcChild.Height > 0)
                    {
                        //Rectangle2I test;
                        //test.IntersectRect(parent->TmiGetRectangle(), rcChild);
                        //Debug.Assert(test == rcChild);
                    }
#endif
                    RecurseDrawGraph(bitmap, child, rcChild, false, surface, h * options.ScaleFactor, 0);

                    if (lastChild)
                    {
                        i++; c++;

                        if (i < childrenPerRow[row])
                        {
                            parent[c].Rectangle = Rectangle2I.FromLTRB(-1, -1, -1, -1);
                        }

                        c += childrenPerRow[row] - i;
                        break;
                    }

                    left = fRight;
                }
                top = fBottom;
            }
        }
        private Number KDirStat_CalculateNextRow(ITreemapItem parent, int nextChild, Number width, out int childrenUsed, Number[] childWidth)
        {
            int          i             = 0;
            const Number minProportion = (Number)0.4;

            Debug.Assert(minProportion < 1);

            Debug.Assert(nextChild < parent.ChildCount);
            Debug.Assert(width >= 1);

            Number mySize = parent.Size;

            Debug.Assert(mySize > 0);
            long   sizeUsed  = 0;
            Number rowHeight = 0;

            for (i = nextChild; i < parent.ChildCount; i++)
            {
                long childSize = parent[i].Size;
                if (childSize == 0)
                {
                    Debug.Assert(i > nextChild);
                    break;
                }

                sizeUsed += childSize;
                Number virtualRowHeight = sizeUsed / mySize;
                Debug.Assert(virtualRowHeight > 0);
                Debug.Assert(virtualRowHeight <= 1);

                // Rectangle2I(mySize)    = width * 1.0
                // Rectangle2I(childSize) = childWidth * virtualRowHeight
                // Rectangle2I(childSize) = childSize / mySize * width

                Number childWidth_ = childSize / mySize * width / virtualRowHeight;

                if (childWidth_ / virtualRowHeight < minProportion)
                {
                    Debug.Assert(i > nextChild);                     // because width >= 1 and _minProportion < 1.
                    // For the first child we have:
                    // childWidth / rowHeight
                    // = childSize / mySize * width / rowHeight / rowHeight
                    // = childSize * width / sizeUsed / sizeUsed * mySize
                    // > childSize * mySize / sizeUsed / sizeUsed
                    // > childSize * childSize / childSize / childSize
                    // = 1 > _minProportion.
                    break;
                }
                rowHeight = virtualRowHeight;
            }
            Debug.Assert(i > nextChild);

            while (i < parent.ChildCount && parent[i].Size == 0)
            {
                i++;
            }

            childrenUsed = i - nextChild;

            for (i = 0; i < childrenUsed; i++)
            {
                // Rectangle2I(1 * 1) = mySize
                Number rowSize   = mySize * rowHeight;
                Number childSize = parent[nextChild + i].Size;
                Number cw        = childSize / rowSize;
                Debug.Assert(cw >= 0);
                childWidth[nextChild + i] = cw;
            }

            return(rowHeight);
        }