|
@@ -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
|