| 100 | // *********************************************************************** |
| 101 | |
| 102 | void Packing::SkylinePackRects(Arena* pScratchMem, ResizableArray<Rect>& rects, i32 width, i32 height) { |
| 103 | for (i64 i = 0; i < rects.count; i++) { |
| 104 | rects[i].ordering = (int)i; |
| 105 | } |
| 106 | |
| 107 | // Sort by a heuristic |
| 108 | Sort(rects.pData, rects.count, SortByHeight()); |
| 109 | |
| 110 | i32 maxX = 0; |
| 111 | i32 maxY = 0; |
| 112 | i32 totalArea = 0; |
| 113 | |
| 114 | ResizableArray<SkylineNode> nodes(pScratchMem); |
| 115 | |
| 116 | nodes.PushBack({ 0, 0, width }); |
| 117 | |
| 118 | for (Rect& rect : rects) { |
| 119 | i32 bestHeight = height; |
| 120 | i32 bestWidth = width; |
| 121 | i32 bestNode = -1; |
| 122 | i32 bestX, bestY; |
| 123 | // We're going to search for the best location for this rect along the skyline |
| 124 | for (i64 i = 0; i < nodes.count; i++) { |
| 125 | SkylineNode& node = nodes[i]; |
| 126 | i32 highestY = CanRectFit(nodes, (i32)i, rect.w, rect.h, width, height); |
| 127 | if (highestY != -1) { |
| 128 | // Settling a tie here on best height by checking lowest width we can use up |
| 129 | if (highestY + rect.h < bestHeight || (highestY + rect.h == bestHeight && node.width < bestWidth)) { |
| 130 | bestNode = (int)i; |
| 131 | bestWidth = node.width; |
| 132 | bestHeight = highestY + rect.h; |
| 133 | bestX = node.x; |
| 134 | bestY = highestY; |
| 135 | } |
| 136 | } |
| 137 | } |
| 138 | |
| 139 | if (bestNode == -1) |
| 140 | continue; // We failed |
| 141 | |
| 142 | // Add the actual rect, changing the skyline |
| 143 | |
| 144 | // First add the new node |
| 145 | SkylineNode newNode; |
| 146 | newNode.width = rect.w; |
| 147 | newNode.x = bestX; |
| 148 | newNode.y = bestY + rect.h; |
| 149 | nodes.Insert(bestNode, newNode); |
| 150 | |
| 151 | // Now we have to find all the nodes underneath that new skyline level and remove them |
| 152 | for (int i = bestNode + 1; i < (int)nodes.count; i++) { |
| 153 | SkylineNode& node = nodes[i]; |
| 154 | SkylineNode& prevNode = nodes[i - 1]; |
| 155 | // Check to see if the current node is underneath the previous node |
| 156 | // Remember that i starts as the first node after we inserted, so the previous node is the one we inserted |
| 157 | if (node.x < prevNode.x + prevNode.width) { |
| 158 | // Draw a picture of this |
| 159 | i32 amountToShrink = (prevNode.x + prevNode.width) - node.x; |
nothing calls this directly
no test coverage detected