Atlas build use GetCustomRectByIndex() + comments, rename, and shallow merge from tex_antialiasing_lines branch.

This commit is contained in:
Ben Carter
2020-07-08 17:17:52 +02:00
committed by omar
parent 0d03e1fafa
commit 8e4046e13b
4 changed files with 72 additions and 59 deletions

View File

@ -666,11 +666,9 @@ void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32
return;
const ImVec2 opaque_uv = _Data->TexUvWhitePixel;
int count = points_count;
if (!closed)
count = points_count - 1;
const int count = closed ? points_count : points_count - 1; // The number of line segments we need to draw
const bool thick_line = (thickness > 1.0f);
if (Flags & ImDrawListFlags_AntiAliasedLines)
{
// Anti-aliased stroke
@ -682,9 +680,11 @@ void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32
PrimReserve(idx_count, vtx_count);
// Temporary buffer
// The first <points_count> items are normals at each line point, then after that there are either 2 or 4 temp points for each line point
ImVec2* temp_normals = (ImVec2*)alloca(points_count * (thick_line ? 5 : 3) * sizeof(ImVec2)); //-V630
ImVec2* temp_points = temp_normals + points_count;
// Calculate normals (tangents) for each line segment
for (int i1 = 0; i1 < count; i1++)
{
const int i2 = (i1 + 1) == points_count ? 0 : i1 + 1;
@ -707,12 +707,14 @@ void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32
temp_points[(points_count-1)*2+1] = points[points_count-1] - temp_normals[points_count-1] * AA_SIZE;
}
// Generate the indices to form a number of triangles for each line segment, and the vertices for the line edges
// This takes points n and n+1 and writes into n+1, with the first point in a closed line being generated from the final one (as n+1 wraps)
// FIXME-OPT: Merge the different loops, possibly remove the temporary buffer.
unsigned int idx1 = _VtxCurrentIdx;
for (int i1 = 0; i1 < count; i1++)
unsigned int idx1 = _VtxCurrentIdx; // Vertex index for start of line segment
for (int i1 = 0; i1 < count; i1++) // i1 is the first point of the line segment
{
const int i2 = (i1 + 1) == points_count ? 0 : i1 + 1;
unsigned int idx2 = (i1 + 1) == points_count ? _VtxCurrentIdx : idx1 + 3;
const unsigned int idx2 = (i1 + 1) == points_count ? _VtxCurrentIdx : idx1 + 3;
// Average normals
float dm_x = (temp_normals[i1].x + temp_normals[i2].x) * 0.5f;
@ -721,14 +723,14 @@ void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32
dm_x *= AA_SIZE;
dm_y *= AA_SIZE;
// Add temporary vertices
// Add temporary vertexes for the outer edges
ImVec2* out_vtx = &temp_points[i2 * 2];
out_vtx[0].x = points[i2].x + dm_x;
out_vtx[0].y = points[i2].y + dm_y;
out_vtx[1].x = points[i2].x - dm_x;
out_vtx[1].y = points[i2].y - dm_y;
// Add indexes
// Add indexes for four triangles
_IdxWritePtr[0] = (ImDrawIdx)(idx2+0); _IdxWritePtr[1] = (ImDrawIdx)(idx1+0); _IdxWritePtr[2] = (ImDrawIdx)(idx1+2);
_IdxWritePtr[3] = (ImDrawIdx)(idx1+2); _IdxWritePtr[4] = (ImDrawIdx)(idx2+2); _IdxWritePtr[5] = (ImDrawIdx)(idx2+0);
_IdxWritePtr[6] = (ImDrawIdx)(idx2+1); _IdxWritePtr[7] = (ImDrawIdx)(idx1+1); _IdxWritePtr[8] = (ImDrawIdx)(idx1+0);
@ -738,7 +740,7 @@ void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32
idx1 = idx2;
}
// Add vertices
// Add vertexes for each point on the line
for (int i = 0; i < points_count; i++)
{
_VtxWritePtr[0].pos = points[i]; _VtxWritePtr[0].uv = opaque_uv; _VtxWritePtr[0].col = col;
@ -749,7 +751,10 @@ void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32
}
else
{
// Non texture-based lines (thick): we need to draw the solid line core and thus require four vertices per point
const float half_inner_thickness = (thickness - AA_SIZE) * 0.5f;
// If line is not closed, the first and last points need to be generated differently as there are no normals to blend
if (!closed)
{
const int points_last = points_count - 1;
@ -763,9 +768,11 @@ void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32
temp_points[points_last * 4 + 3] = points[points_last] - temp_normals[points_last] * (half_inner_thickness + AA_SIZE);
}
// Generate the indices to form a number of triangles for each line segment, and the vertices for the line edges
// This takes points n and n+1 and writes into n+1, with the first point in a closed line being generated from the final one (as n+1 wraps)
// FIXME-OPT: Merge the different loops, possibly remove the temporary buffer.
unsigned int idx1 = _VtxCurrentIdx;
for (int i1 = 0; i1 < count; i1++)
unsigned int idx1 = _VtxCurrentIdx; // Vertex index for start of line segment
for (int i1 = 0; i1 < count; i1++) // i1 is the first point of the line segment
{
const int i2 = (i1 + 1) == points_count ? 0 : (i1 + 1); // i2 is the second point of the line segment
const unsigned int idx2 = (i1 + 1) == points_count ? _VtxCurrentIdx : (idx1 + 4); // Vertex index for end of segment
@ -816,7 +823,7 @@ void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32
}
else
{
// Non Anti-aliased Stroke
// Non texture-based, Non anti-aliased lines
const int idx_count = count * 6;
const int vtx_count = count * 4; // FIXME-OPT: Not sharing edges
PrimReserve(idx_count, vtx_count);
@ -1656,8 +1663,7 @@ ImFontAtlas::ImFontAtlas()
TexWidth = TexHeight = 0;
TexUvScale = ImVec2(0.0f, 0.0f);
TexUvWhitePixel = ImVec2(0.0f, 0.0f);
for (int n = 0; n < IM_ARRAYSIZE(CustomRectIds); n++)
CustomRectIds[n] = -1;
PackIdMouseCursors = -1;
}
ImFontAtlas::~ImFontAtlas()
@ -1685,8 +1691,7 @@ void ImFontAtlas::ClearInputData()
}
ConfigData.clear();
CustomRects.clear();
for (int n = 0; n < IM_ARRAYSIZE(CustomRectIds); n++)
CustomRectIds[n] = -1;
PackIdMouseCursors = -1;
}
void ImFontAtlas::ClearTexData()
@ -1926,9 +1931,9 @@ bool ImFontAtlas::GetMouseCursorTexData(ImGuiMouseCursor cursor_type, ImVec2* ou
if (Flags & ImFontAtlasFlags_NoMouseCursors)
return false;
IM_ASSERT(CustomRectIds[0] != -1);
ImFontAtlasCustomRect& r = CustomRects[CustomRectIds[0]];
ImVec2 pos = FONT_ATLAS_DEFAULT_TEX_CURSOR_DATA[cursor_type][0] + ImVec2((float)r.X, (float)r.Y);
IM_ASSERT(PackIdMouseCursors != -1);
ImFontAtlasCustomRect* r = GetCustomRectByIndex(PackIdMouseCursors);
ImVec2 pos = FONT_ATLAS_DEFAULT_TEX_CURSOR_DATA[cursor_type][0] + ImVec2((float)r->X, (float)r->Y);
ImVec2 size = FONT_ATLAS_DEFAULT_TEX_CURSOR_DATA[cursor_type][1];
*out_size = size;
*out_offset = FONT_ATLAS_DEFAULT_TEX_CURSOR_DATA[cursor_type][2];
@ -2256,17 +2261,6 @@ bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas)
return true;
}
// Register default custom rectangles (this is called/shared by both the stb_truetype and the FreeType builder)
void ImFontAtlasBuildInit(ImFontAtlas* atlas)
{
if (atlas->CustomRectIds[0] >= 0)
return;
if (!(atlas->Flags & ImFontAtlasFlags_NoMouseCursors))
atlas->CustomRectIds[0] = atlas->AddCustomRectRegular(FONT_ATLAS_DEFAULT_TEX_DATA_W_HALF * 2 + 1, FONT_ATLAS_DEFAULT_TEX_DATA_H);
else
atlas->CustomRectIds[0] = atlas->AddCustomRectRegular(2, 2);
}
void ImFontAtlasBuildSetupFont(ImFontAtlas* atlas, ImFont* font, ImFontConfig* font_config, float ascent, float descent)
{
if (!font_config->MergeMode)
@ -2310,20 +2304,18 @@ void ImFontAtlasBuildPackCustomRects(ImFontAtlas* atlas, void* stbrp_context_opa
static void ImFontAtlasBuildRenderDefaultTexData(ImFontAtlas* atlas)
{
IM_ASSERT(atlas->CustomRectIds[0] >= 0);
IM_ASSERT(atlas->TexPixelsAlpha8 != NULL);
ImFontAtlasCustomRect& r = atlas->CustomRects[atlas->CustomRectIds[0]];
IM_ASSERT(r.IsPacked());
ImFontAtlasCustomRect* r = atlas->GetCustomRectByIndex(atlas->PackIdMouseCursors);
IM_ASSERT(r->IsPacked());
const int w = atlas->TexWidth;
if (!(atlas->Flags & ImFontAtlasFlags_NoMouseCursors))
{
// Render/copy pixels
IM_ASSERT(r.Width == FONT_ATLAS_DEFAULT_TEX_DATA_W_HALF * 2 + 1 && r.Height == FONT_ATLAS_DEFAULT_TEX_DATA_H);
IM_ASSERT(r->Width == FONT_ATLAS_DEFAULT_TEX_DATA_W_HALF * 2 + 1 && r->Height == FONT_ATLAS_DEFAULT_TEX_DATA_H);
for (int y = 0, n = 0; y < FONT_ATLAS_DEFAULT_TEX_DATA_H; y++)
for (int x = 0; x < FONT_ATLAS_DEFAULT_TEX_DATA_W_HALF; x++, n++)
{
const int offset0 = (int)(r.X + x) + (int)(r.Y + y) * w;
const int offset0 = (int)(r->X + x) + (int)(r->Y + y) * w;
const int offset1 = offset0 + FONT_ATLAS_DEFAULT_TEX_DATA_W_HALF + 1;
atlas->TexPixelsAlpha8[offset0] = FONT_ATLAS_DEFAULT_TEX_DATA_PIXELS[n] == '.' ? 0xFF : 0x00;
atlas->TexPixelsAlpha8[offset1] = FONT_ATLAS_DEFAULT_TEX_DATA_PIXELS[n] == 'X' ? 0xFF : 0x00;
@ -2331,29 +2323,46 @@ static void ImFontAtlasBuildRenderDefaultTexData(ImFontAtlas* atlas)
}
else
{
IM_ASSERT(r.Width == 2 && r.Height == 2);
const int offset = (int)(r.X) + (int)(r.Y) * w;
// Render 4 white pixels
IM_ASSERT(r->Width == 2 && r->Height == 2);
const int offset = (int)r->X + (int)r->Y * w;
atlas->TexPixelsAlpha8[offset] = atlas->TexPixelsAlpha8[offset + 1] = atlas->TexPixelsAlpha8[offset + w] = atlas->TexPixelsAlpha8[offset + w + 1] = 0xFF;
}
atlas->TexUvWhitePixel = ImVec2((r.X + 0.5f) * atlas->TexUvScale.x, (r.Y + 0.5f) * atlas->TexUvScale.y);
atlas->TexUvWhitePixel = ImVec2((r->X + 0.5f) * atlas->TexUvScale.x, (r->Y + 0.5f) * atlas->TexUvScale.y);
}
// Note: this is called / shared by both the stb_truetype and the FreeType builder
void ImFontAtlasBuildInit(ImFontAtlas* atlas)
{
// Register texture region for mouse cursors or standard white pixels
if (atlas->PackIdMouseCursors < 0)
{
if (!(atlas->Flags & ImFontAtlasFlags_NoMouseCursors))
atlas->PackIdMouseCursors = atlas->AddCustomRectRegular(FONT_ATLAS_DEFAULT_TEX_DATA_W_HALF * 2 + 1, FONT_ATLAS_DEFAULT_TEX_DATA_H);
else
atlas->PackIdMouseCursors = atlas->AddCustomRectRegular(2, 2);
}
}
// This is called/shared by both the stb_truetype and the FreeType builder.
void ImFontAtlasBuildFinish(ImFontAtlas* atlas)
{
// Render into our custom data block
// Render into our custom data blocks
IM_ASSERT(atlas->TexPixelsAlpha8 != NULL);
ImFontAtlasBuildRenderDefaultTexData(atlas);
// Register custom rectangle glyphs
for (int i = 0; i < atlas->CustomRects.Size; i++)
{
const ImFontAtlasCustomRect& r = atlas->CustomRects[i];
if (r.Font == NULL || r.GlyphID == 0)
const ImFontAtlasCustomRect* r = &atlas->CustomRects[i];
if (r->Font == NULL || r->GlyphID == 0)
continue;
IM_ASSERT(r.Font->ContainerAtlas == atlas);
IM_ASSERT(r->Font->ContainerAtlas == atlas);
ImVec2 uv0, uv1;
atlas->CalcCustomRectUV(&r, &uv0, &uv1);
r.Font->AddGlyph((ImWchar)r.GlyphID, r.GlyphOffset.x, r.GlyphOffset.y, r.GlyphOffset.x + r.Width, r.GlyphOffset.y + r.Height, uv0.x, uv0.y, uv1.x, uv1.y, r.GlyphAdvanceX);
atlas->CalcCustomRectUV(r, &uv0, &uv1);
r->Font->AddGlyph((ImWchar)r->GlyphID, r->GlyphOffset.x, r->GlyphOffset.y, r->GlyphOffset.x + r->Width, r->GlyphOffset.y + r->Height, uv0.x, uv0.y, uv1.x, uv1.y, r->GlyphAdvanceX);
}
// Build all fonts lookup tables