This function reorder draw channels based on matching clip rectangle, to facilitate merging them. Called by EndTable(). For simplicity we call it TableMergeDrawChannels() but in fact it only reorder channels + overwrite ClipRect, actual merging is done by table->DrawSplitter.Merge() which is called right after TableMergeDrawChannels(). Columns where the contents didn't stray off their local clip
| 2343 | // |
| 2344 | // This function is particularly tricky to understand.. take a breath. |
| 2345 | void ImGui::TableMergeDrawChannels(ImGuiTable* table) |
| 2346 | { |
| 2347 | ImGuiContext& g = *GImGui; |
| 2348 | ImDrawListSplitter* splitter = table->DrawSplitter; |
| 2349 | const bool has_freeze_v = (table->FreezeRowsCount > 0); |
| 2350 | const bool has_freeze_h = (table->FreezeColumnsCount > 0); |
| 2351 | IM_ASSERT(splitter->_Current == 0); |
| 2352 | |
| 2353 | // Track which groups we are going to attempt to merge, and which channels goes into each group. |
| 2354 | struct MergeGroup |
| 2355 | { |
| 2356 | ImRect ClipRect; |
| 2357 | int ChannelsCount; |
| 2358 | ImBitArray<IMGUI_TABLE_MAX_DRAW_CHANNELS> ChannelsMask; |
| 2359 | |
| 2360 | MergeGroup() { ChannelsCount = 0; } |
| 2361 | }; |
| 2362 | int merge_group_mask = 0x00; |
| 2363 | MergeGroup merge_groups[4]; |
| 2364 | |
| 2365 | // 1. Scan channels and take note of those which can be merged |
| 2366 | for (int column_n = 0; column_n < table->ColumnsCount; column_n++) |
| 2367 | { |
| 2368 | if ((table->VisibleMaskByIndex & ((ImU64)1 << column_n)) == 0) |
| 2369 | continue; |
| 2370 | ImGuiTableColumn* column = &table->Columns[column_n]; |
| 2371 | |
| 2372 | const int merge_group_sub_count = has_freeze_v ? 2 : 1; |
| 2373 | for (int merge_group_sub_n = 0; merge_group_sub_n < merge_group_sub_count; merge_group_sub_n++) |
| 2374 | { |
| 2375 | const int channel_no = (merge_group_sub_n == 0) ? column->DrawChannelFrozen : column->DrawChannelUnfrozen; |
| 2376 | |
| 2377 | // Don't attempt to merge if there are multiple draw calls within the column |
| 2378 | ImDrawChannel* src_channel = &splitter->_Channels[channel_no]; |
| 2379 | if (src_channel->_CmdBuffer.Size > 0 && src_channel->_CmdBuffer.back().ElemCount == 0 && src_channel->_CmdBuffer.back().UserCallback == NULL) // Equivalent of PopUnusedDrawCmd() |
| 2380 | src_channel->_CmdBuffer.pop_back(); |
| 2381 | if (src_channel->_CmdBuffer.Size != 1) |
| 2382 | continue; |
| 2383 | |
| 2384 | // Find out the width of this merge group and check if it will fit in our column |
| 2385 | // (note that we assume that rendering didn't stray on the left direction. we should need a CursorMinPos to detect it) |
| 2386 | if (!(column->Flags & ImGuiTableColumnFlags_NoClip)) |
| 2387 | { |
| 2388 | float content_max_x; |
| 2389 | if (!has_freeze_v) |
| 2390 | content_max_x = ImMax(column->ContentMaxXUnfrozen, column->ContentMaxXHeadersUsed); // No row freeze |
| 2391 | else if (merge_group_sub_n == 0) |
| 2392 | content_max_x = ImMax(column->ContentMaxXFrozen, column->ContentMaxXHeadersUsed); // Row freeze: use width before freeze |
| 2393 | else |
| 2394 | content_max_x = column->ContentMaxXUnfrozen; // Row freeze: use width after freeze |
| 2395 | if (content_max_x > column->ClipRect.Max.x) |
| 2396 | continue; |
| 2397 | } |
| 2398 | |
| 2399 | const int merge_group_n = (has_freeze_h && column_n < table->FreezeColumnsCount ? 0 : 1) + (has_freeze_v && merge_group_sub_n == 0 ? 0 : 2); |
| 2400 | IM_ASSERT(channel_no < IMGUI_TABLE_MAX_DRAW_CHANNELS); |
| 2401 | MergeGroup* merge_group = &merge_groups[merge_group_n]; |
| 2402 | if (merge_group->ChannelsCount == 0) |
nothing calls this directly
no test coverage detected