public void Insert(Span <PackRect> rects, Span <PackRect> dst, FreeRectChoiceHeuristic method)
        {
            var remaining = rects.Length;
            var completed = new bool[rects.Length];

            while (remaining > 0)
            {
                int      bestScore1    = int.MaxValue;
                int      bestScore2    = int.MaxValue;
                int      bestRectIndex = -1;
                PackRect bestNode      = new PackRect();

                for (int i = 0; i < rects.Length; ++i)
                {
                    if (!completed[i])
                    {
                        int      score1  = 0;
                        int      score2  = 0;
                        PackRect newNode = ScoreRect((int)rects[i].Width, (int)rects[i].Height, method, ref score1, ref score2);

                        if (score1 < bestScore1 || (score1 == bestScore1 && score2 < bestScore2))
                        {
                            bestScore1    = score1;
                            bestScore2    = score2;
                            bestNode      = newNode;
                            bestRectIndex = i;
                        }
                    }
                }

                if (bestRectIndex == -1)
                {
                    return;
                }

                PlaceRect(bestNode);
                completed[bestRectIndex] = true;
                dst[bestRectIndex]       = bestNode;
                remaining--;
            }
        }
        public PackRect Insert(int width, int height, FreeRectChoiceHeuristic method)
        {
            PackRect newNode = new PackRect();
            int      score1  = 0; // Unused in this function. We don't need to know the score after finding the position.
            int      score2  = 0;

            switch (method)
            {
            case FreeRectChoiceHeuristic.RectBestShortSideFit: newNode = FindPositionForNewNodeBestShortSideFit(width, height, ref score1, ref score2); break;

            case FreeRectChoiceHeuristic.RectBottomLeftRule: newNode = FindPositionForNewNodeBottomLeft(width, height, ref score1, ref score2); break;

            case FreeRectChoiceHeuristic.RectContactPointRule: newNode = FindPositionForNewNodeContactPoint(width, height, ref score1); break;

            case FreeRectChoiceHeuristic.RectBestLongSideFit: newNode = FindPositionForNewNodeBestLongSideFit(width, height, ref score2, ref score1); break;

            case FreeRectChoiceHeuristic.RectBestAreaFit: newNode = FindPositionForNewNodeBestAreaFit(width, height, ref score1, ref score2); break;
            }

            if (newNode.Height == 0)
            {
                return(newNode);
            }

            int numRectanglesToProcess = _freeRectangles.Count;

            for (int i = 0; i < numRectanglesToProcess; ++i)
            {
                if (SplitFreeNode(_freeRectangles[i], ref newNode))
                {
                    _freeRectangles.RemoveAt(i);
                    --i;
                    --numRectanglesToProcess;
                }
            }

            PruneFreeList();

            _usedRectangles.Add(newNode);
            return(newNode);
        }
        PackRect FindPositionForNewNodeBottomLeft(int width, int height, ref int bestY, ref int bestX)
        {
            PackRect bestNode = new PackRect();

            //memset(bestNode, 0, sizeof(ImRect));

            bestY = int.MaxValue;

            for (int i = 0; i < _freeRectangles.Count; ++i)
            {
                // Try to place the rectangle in upright (non-flipped) orientation.
                if (_freeRectangles[i].Width >= width && _freeRectangles[i].Height >= height)
                {
                    int topSideY = (int)_freeRectangles[i].Y + height;
                    if (topSideY < bestY || (topSideY == bestY && _freeRectangles[i].X < bestX))
                    {
                        bestNode.X      = _freeRectangles[i].X;
                        bestNode.Y      = _freeRectangles[i].Y;
                        bestNode.Width  = width;
                        bestNode.Height = height;
                        bestY           = topSideY;
                        bestX           = (int)_freeRectangles[i].X;
                    }
                }
                if (allowRotations && _freeRectangles[i].Width >= height && _freeRectangles[i].Height >= width)
                {
                    int topSideY = (int)_freeRectangles[i].Y + width;
                    if (topSideY < bestY || (topSideY == bestY && _freeRectangles[i].X < bestX))
                    {
                        bestNode.X      = _freeRectangles[i].X;
                        bestNode.Y      = _freeRectangles[i].Y;
                        bestNode.Width  = height;
                        bestNode.Height = width;
                        bestY           = topSideY;
                        bestX           = (int)_freeRectangles[i].X;
                    }
                }
            }
            return(bestNode);
        }
        PackRect FindPositionForNewNodeContactPoint(int width, int height, ref int bestContactScore)
        {
            PackRect bestNode = new PackRect();

            //memset(&bestNode, 0, sizeof(ImRect));

            bestContactScore = -1;

            for (int i = 0; i < _freeRectangles.Count; ++i)
            {
                // Try to place the rectangle in upright (non-flipped) orientation.
                if (_freeRectangles[i].Width >= width && _freeRectangles[i].Height >= height)
                {
                    int score = ContactPointScoreNode((int)_freeRectangles[i].X, (int)_freeRectangles[i].Y, width, height);
                    if (score > bestContactScore)
                    {
                        bestNode.X       = (int)_freeRectangles[i].X;
                        bestNode.Y       = (int)_freeRectangles[i].Y;
                        bestNode.Width   = width;
                        bestNode.Height  = height;
                        bestContactScore = score;
                    }
                }
                if (allowRotations && _freeRectangles[i].Width >= height && _freeRectangles[i].Height >= width)
                {
                    int score = ContactPointScoreNode((int)_freeRectangles[i].X, (int)_freeRectangles[i].Y, height, width);
                    if (score > bestContactScore)
                    {
                        bestNode.X       = (int)_freeRectangles[i].X;
                        bestNode.Y       = (int)_freeRectangles[i].Y;
                        bestNode.Width   = height;
                        bestNode.Height  = width;
                        bestContactScore = score;
                    }
                }
            }
            return(bestNode);
        }
 bool IsContainedIn(PackRect a, PackRect b)
 {
     return(a.X >= b.X && a.Y >= b.Y &&
            a.X + a.Width <= b.X + b.Width &&
            a.Y + a.Height <= b.Y + b.Height);
 }