void ImDrawList::AddShadowRect(const ImVec2& obj_min, const ImVec2& obj_max, ImU32 shadow_col, float shadow_thickness, const ImVec2& shadow_offset, ImDrawShadowFlags shadow_flags, float obj_rounding, ImDrawCornerFlags obj_rounding_corners)
{
if ((shadow_col & IM_COL32_A_MASK) == 0)
return;
ImVec2* inner_rect_points = NULL; // Points that make up the shape of the inner rectangle (used when it has rounded corners)
int inner_rect_points_count = 0;
// Generate a path describing the inner rectangle and copy it to our buffer
const bool is_filled = (shadow_flags & ImDrawShadowFlags_CutOutShapeBackground) == 0;
const bool is_rounded = (obj_rounding > 0.0f) && (obj_rounding_corners != ImDrawCornerFlags_None); // Do we have rounded corners?
if (is_rounded && !is_filled)
{
IM_ASSERT(_Path.Size == 0);
PathRect(obj_min, obj_max, obj_rounding, obj_rounding_corners);
inner_rect_points_count = _Path.Size;
inner_rect_points = (ImVec2*)alloca(inner_rect_points_count * sizeof(ImVec2)); //-V630
memcpy(inner_rect_points, _Path.Data, inner_rect_points_count * sizeof(ImVec2));
_Path.Size = 0;
}
if (is_filled)
PrimReserve(6 * 9, 4 * 9); // Reserve space for adding unclipped chunks
// Draw the relevant chunks of the texture (the texture is split into a 3x3 grid)
// FIXME-OPT: Might make sense to optimize/unroll for the fast paths (filled or not rounded)
for (int x = 0; x < 3; x++)
{
for (int y = 0; y < 3; y++)
{
const int uv_index = x + (y + y + y); // y*3 formatted so as to ensure the compiler avoids an actual multiply
const ImVec4 uvs = _Data->ShadowRectUvs[uv_index];
ImVec2 draw_min, draw_max;
switch (x)
{
case 0: draw_min.x = obj_min.x - shadow_thickness; draw_max.x = obj_min.x; break;
case 1: draw_min.x = obj_min.x; draw_max.x = obj_max.x; break;
case 2: draw_min.x = obj_max.x; draw_max.x = obj_max.x + shadow_thickness; break;
}
switch (y)
{
case 0: draw_min.y = obj_min.y - shadow_thickness; draw_max.y = obj_min.y; break;
case 1: draw_min.y = obj_min.y; draw_max.y = obj_max.y; break;
case 2: draw_min.y = obj_max.y; draw_max.y = obj_max.y + shadow_thickness; break;
}
ImVec2 uv_min(uvs.x, uvs.y);
ImVec2 uv_max(uvs.z, uvs.w);
if (is_filled)
PrimRectUV(draw_min + shadow_offset, draw_max + shadow_offset, uv_min, uv_max, shadow_col); // No clipping path (draw entire shadow)
else if (is_rounded)
AddSubtractedRect(this, draw_min + shadow_offset, draw_max + shadow_offset, uv_min, uv_max, inner_rect_points, inner_rect_points_count, shadow_col); // Complex path for rounded rectangles
else
AddSubtractedRect(this, draw_min + shadow_offset, draw_max + shadow_offset, uv_min, uv_max, obj_min, obj_max, shadow_col); // Simple fast path for non-rounded rectangles
}
}
}