2
0
Эх сурвалжийг харах

ImDrawList, ImFontAtlas: comments, tweaks. moved less scary functions at the top of the file.

ocornut 10 жил өмнө
parent
commit
bc8eb5e9cf
1 өөрчлөгдсөн 122 нэмэгдсэн , 118 устгасан
  1. 122 118
      imgui_draw.cpp

+ 122 - 118
imgui_draw.cpp

@@ -159,6 +159,69 @@ void ImDrawList::AddCallback(ImDrawCallback callback, void* callback_data)
     AddDrawCmd();
 }
 
+void ImDrawList::UpdateClipRect()
+{
+    ImDrawCmd* current_cmd = CmdBuffer.Size ? &CmdBuffer.back() : NULL;
+    if (!current_cmd || (current_cmd->ElemCount != 0) || current_cmd->UserCallback != NULL)
+    {
+        AddDrawCmd();
+    }
+    else
+    {
+        ImVec4 current_clip_rect = _ClipRectStack.Size ? _ClipRectStack.back() : GNullClipRect;
+        if (CmdBuffer.Size >= 2 && ImLengthSqr(CmdBuffer.Data[CmdBuffer.Size-2].ClipRect - current_clip_rect) < 0.00001f)
+            CmdBuffer.pop_back();
+        else
+            current_cmd->ClipRect = current_clip_rect;
+    }
+}
+
+// Scissoring. The values in clip_rect are x1, y1, x2, y2.
+void ImDrawList::PushClipRect(const ImVec4& clip_rect)
+{
+    _ClipRectStack.push_back(clip_rect);
+    UpdateClipRect();
+}
+
+void ImDrawList::PushClipRectFullScreen()
+{
+    PushClipRect(GNullClipRect);
+
+    // FIXME-OPT: This would be more correct but we're not supposed to access ImGuiState from here?
+    //ImGuiState& g = *GImGui;
+    //PushClipRect(GetVisibleRect());
+}
+
+void ImDrawList::PopClipRect()
+{
+    IM_ASSERT(_ClipRectStack.Size > 0);
+    _ClipRectStack.pop_back();
+    UpdateClipRect();
+}
+
+void ImDrawList::UpdateTextureID()
+{
+    ImDrawCmd* current_cmd = CmdBuffer.Size ? &CmdBuffer.back() : NULL;
+    const ImTextureID texture_id = _TextureIdStack.Size ? _TextureIdStack.back() : NULL;
+    if (!current_cmd || (current_cmd->ElemCount != 0 && current_cmd->TextureId != texture_id) || current_cmd->UserCallback != NULL)
+        AddDrawCmd();
+    else
+        current_cmd->TextureId = texture_id;
+}
+
+void ImDrawList::PushTextureID(const ImTextureID& texture_id)
+{
+    _TextureIdStack.push_back(texture_id);
+    UpdateTextureID();
+}
+
+void ImDrawList::PopTextureID()
+{
+    IM_ASSERT(_TextureIdStack.Size > 0);
+    _TextureIdStack.pop_back();
+    UpdateTextureID();
+}
+
 void ImDrawList::ChannelsSplit(int channels_count)
 {
     IM_ASSERT(_ChannelsCurrent == 0 && _ChannelsCount == 1);
@@ -195,7 +258,6 @@ void ImDrawList::ChannelsSplit(int channels_count)
 void ImDrawList::ChannelsMerge()
 {
     // Note that we never use or rely on channels.Size because it is merely a buffer that we never shrink back to 0 to keep all sub-buffers ready for use.
-    // This is why this function takes 'channel_count' as a parameter of how many channels to merge (the user knows)
     if (_ChannelsCount <= 1)
         return;
 
@@ -238,69 +300,6 @@ void ImDrawList::ChannelsSetCurrent(int idx)
     _IdxWritePtr = IdxBuffer.Data + IdxBuffer.Size;
 }
 
-void ImDrawList::UpdateClipRect()
-{
-    ImDrawCmd* current_cmd = CmdBuffer.Size ? &CmdBuffer.back() : NULL;
-    if (!current_cmd || (current_cmd->ElemCount != 0) || current_cmd->UserCallback != NULL)
-    {
-        AddDrawCmd();
-    }
-    else
-    {
-        ImVec4 current_clip_rect = _ClipRectStack.Size ? _ClipRectStack.back() : GNullClipRect;
-        if (CmdBuffer.Size >= 2 && ImLengthSqr(CmdBuffer.Data[CmdBuffer.Size-2].ClipRect - current_clip_rect) < 0.00001f)
-            CmdBuffer.pop_back();
-        else
-            current_cmd->ClipRect = current_clip_rect;
-    }
-}
-
-// Scissoring. The values in clip_rect are x1, y1, x2, y2.
-void ImDrawList::PushClipRect(const ImVec4& clip_rect)
-{
-    _ClipRectStack.push_back(clip_rect);
-    UpdateClipRect();
-}
-
-void ImDrawList::PushClipRectFullScreen()
-{
-    PushClipRect(GNullClipRect);
-
-    // This would be more correct but we're not supposed to access ImGuiState from here?
-    //ImGuiState& g = *GImGui;
-    //PushClipRect(GetVisibleRect());
-}
-
-void ImDrawList::PopClipRect()
-{
-    IM_ASSERT(_ClipRectStack.Size > 0);
-    _ClipRectStack.pop_back();
-    UpdateClipRect();
-}
-
-void ImDrawList::UpdateTextureID()
-{
-    ImDrawCmd* current_cmd = CmdBuffer.Size ? &CmdBuffer.back() : NULL;
-    const ImTextureID texture_id = _TextureIdStack.Size ? _TextureIdStack.back() : NULL;
-    if (!current_cmd || (current_cmd->ElemCount != 0 && current_cmd->TextureId != texture_id) || current_cmd->UserCallback != NULL)
-        AddDrawCmd();
-    else
-        current_cmd->TextureId = texture_id;
-}
-
-void ImDrawList::PushTextureID(const ImTextureID& texture_id)
-{
-    _TextureIdStack.push_back(texture_id);
-    UpdateTextureID();
-}
-
-void ImDrawList::PopTextureID()
-{
-    IM_ASSERT(_TextureIdStack.Size > 0);
-    _TextureIdStack.pop_back();
-    UpdateTextureID();
-}
-
 // NB: this can be called with negative count for removing primitives (as long as the result does not underflow)
 void ImDrawList::PrimReserve(int idx_count, int vtx_count)
 {
@@ -357,7 +356,7 @@ void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32
 
     const ImVec2 uv = GImGui->FontTexUvWhitePixel;
     anti_aliased &= GImGui->Style.AntiAliasedLines;
-    //if (ImGui::GetIO().KeyCtrl) anti_aliased = false;
+    //if (ImGui::GetIO().KeyCtrl) anti_aliased = false; // Debug
 
     int count = points_count;
     if (!closed)
@@ -535,7 +534,7 @@ void ImDrawList::AddConvexPolyFilled(const ImVec2* points, const int points_coun
 {
     const ImVec2 uv = GImGui->FontTexUvWhitePixel;
     anti_aliased &= GImGui->Style.AntiAliasedShapes;
-    //if (ImGui::GetIO().KeyCtrl) anti_aliased = false;
+    //if (ImGui::GetIO().KeyCtrl) anti_aliased = false; // Debug
 
     if (anti_aliased)
     {
@@ -786,6 +785,7 @@ void ImDrawList::AddTriangleFilled(const ImVec2& a, const ImVec2& b, const ImVec
 {
     if ((col >> 24) == 0)
         return;
+
     PathLineTo(a);
     PathLineTo(b);
     PathLineTo(c);
@@ -834,7 +834,7 @@ void ImDrawList::AddText(const ImFont* font, float font_size, const ImVec2& pos,
 
     IM_ASSERT(font->ContainerAtlas->TexID == _TextureIdStack.back());  // Use high-level ImGui::PushFont() or low-level ImDrawList::PushTextureId() to change font.
 
-    // reserve vertices for worse case
+    // reserve vertices for worse case (over-reserving is useful and easily amortized)
     const int char_count = (int)(text_end - text_begin);
     const int vtx_count_max = char_count * 4;
     const int idx_count_max = char_count * 6;
@@ -853,7 +853,7 @@ void ImDrawList::AddText(const ImFont* font, float font_size, const ImVec2& pos,
     font->RenderText(font_size, pos, col, clip_rect, text_begin, text_end, this, wrap_width, cpu_fine_clip_rect != NULL);
 
     // give back unused vertices
-    // FIXME-OPT
+    // FIXME-OPT: clean this up
     VtxBuffer.resize((int)(_VtxWritePtr - VtxBuffer.Data));
     IdxBuffer.resize((int)(_IdxWritePtr - IdxBuffer.Data));
     int vtx_unused = vtx_count_max - (VtxBuffer.Size - vtx_begin);
@@ -869,7 +869,8 @@ void ImDrawList::AddText(const ImVec2& pos, ImU32 col, const char* text_begin, c
 {
     if ((col >> 24) == 0)
         return;
-    AddText(ImGui::GetWindowFont(), ImGui::GetWindowFontSize(), pos, col, text_begin, text_end);
+
+    AddText(GImGui->Font, GImGui->FontSize, pos, col, text_begin, text_end);
 }
 
 void ImDrawList::AddImage(ImTextureID user_texture_id, const ImVec2& a, const ImVec2& b, const ImVec2& uv0, const ImVec2& uv1, ImU32 col)
@@ -927,7 +928,7 @@ void ImDrawData::ScaleClipRects(const ImVec2& scale)
 }
 
 //-----------------------------------------------------------------------------
-// ImFontAtlias
+// ImFontAtlas
 //-----------------------------------------------------------------------------
 
 ImFontConfig::ImFontConfig()
@@ -971,14 +972,14 @@ void    ImFontAtlas::ClearInputData()
             ConfigData[i].FontData = NULL;
         }
 
-        // When clearing this we lose access to the font name and other information used to build the font.
-        for (int i = 0; i < Fonts.Size; i++)
-            if (Fonts[i]->ConfigData >= ConfigData.Data && Fonts[i]->ConfigData < ConfigData.Data + ConfigData.Size)
-            {
-                Fonts[i]->ConfigData = NULL;
-                Fonts[i]->ConfigDataCount = 0;
-            }
-            ConfigData.clear();
+    // When clearing this we lose access to the font name and other information used to build the font.
+    for (int i = 0; i < Fonts.Size; i++)
+        if (Fonts[i]->ConfigData >= ConfigData.Data && Fonts[i]->ConfigData < ConfigData.Data + ConfigData.Size)
+        {
+            Fonts[i]->ConfigData = NULL;
+            Fonts[i]->ConfigDataCount = 0;
+        }
+    ConfigData.clear();
 }
 
 void    ImFontAtlas::ClearTexData()
@@ -1010,7 +1011,7 @@ void    ImFontAtlas::Clear()
 
 void    ImFontAtlas::GetTexDataAsAlpha8(unsigned char** out_pixels, int* out_width, int* out_height, int* out_bytes_per_pixel)
 {
-    // Lazily build
+    // Build atlas on demand
     if (TexPixelsAlpha8 == NULL)
     {
         if (ConfigData.empty())
@@ -1026,8 +1027,8 @@ void    ImFontAtlas::GetTexDataAsAlpha8(unsigned char** out_pixels, int* out_wid
 
 void    ImFontAtlas::GetTexDataAsRGBA32(unsigned char** out_pixels, int* out_width, int* out_height, int* out_bytes_per_pixel)
 {
-    // Lazily convert to RGBA32 format
-    // Although it is likely to be the most commonly used format, our font rendering is 8 bpp
+    // Convert to RGBA32 format on demand
+    // Although it is likely to be the most commonly used format, our font rendering is 1 channel / 8 bpp
     if (!TexPixelsRGBA32)
     {
         unsigned char* pixels;
@@ -1073,7 +1074,7 @@ ImFont* ImFontAtlas::AddFont(const ImFontConfig* font_cfg)
     return Fonts.back();
 }
 
-// Default font ttf is compressed with stb_compress then base85 encoded (see extra_fonts/binary_to_compressed_c.cpp for encoder)
+// Default font TTF is compressed with stb_compress then base85 encoded (see extra_fonts/binary_to_compressed_c.cpp for encoder)
 static unsigned int stb_decompress_length(unsigned char *input);
 static unsigned int stb_decompress(unsigned char *output, unsigned char *i, unsigned int length);
 static const char*  GetDefaultCompressedFontDataTTFBase85();
@@ -1116,7 +1117,7 @@ ImFont* ImFontAtlas::AddFontFromFileTTF(const char* filename, float size_pixels,
     return AddFontFromMemoryTTF(data, data_size, size_pixels, &font_cfg, glyph_ranges);
 }
 
-// Transfer ownership of 'ttf_data' to ImFontAtlas, will be deleted after Build()
+// NBM Transfer ownership of 'ttf_data' to ImFontAtlas, unless font_cfg_template->FontDataOwnedByAtlas == false. Owned TTF buffer will be deleted after Build().
 ImFont* ImFontAtlas::AddFontFromMemoryTTF(void* ttf_data, int ttf_size, float size_pixels, const ImFontConfig* font_cfg_template, const ImWchar* glyph_ranges)
 {
     ImFontConfig font_cfg = font_cfg_template ? *font_cfg_template : ImFontConfig();
@@ -1183,6 +1184,7 @@ bool    ImFontAtlas::Build()
         if (!stbtt_InitFont(&tmp.FontInfo, (unsigned char*)cfg.FontData, font_offset))
             return false;
 
+        // Count glyphs
         if (!cfg.GlyphRanges)
             cfg.GlyphRanges = GetGlyphRangesDefault();
         for (const ImWchar* in_range = cfg.GlyphRanges; in_range[0] && in_range[1]; in_range += 2)
@@ -1217,7 +1219,7 @@ bool    ImFontAtlas::Build()
     memset(buf_rects, 0, total_glyph_count * sizeof(stbrp_rect));              // Unnecessary but let's clear this for the sake of sanity.
     memset(buf_ranges, 0, total_glyph_range_count * sizeof(stbtt_pack_range));
 
-    // First font pass: pack all glyphs (no rendering at this point, we are working with glyph sizes only)
+    // First font pass: pack all glyphs (no rendering at this point, we are working with rectangles in an infinitely tall texture at this point)
     for (int input_i = 0; input_i < ConfigData.Size; input_i++)
     {
         ImFontConfig& cfg = ConfigData[input_i];
@@ -1355,7 +1357,8 @@ bool    ImFontAtlas::Build()
 
 void ImFontAtlas::RenderCustomTexData(int pass, void* p_rects)
 {
-    // . = white layer, X = black layer, others are blank
+    // A work of art lies ahead! (. = white layer, X = black layer, others are blank)
+    // The white texels on the top left are the ones we'll use everywhere in ImGui to render filled shapes.
     const int TEX_DATA_W = 90;
     const int TEX_DATA_H = 27;
     const char texture_data[TEX_DATA_W*TEX_DATA_H+1] =
@@ -1411,35 +1414,36 @@ void ImFontAtlas::RenderCustomTexData(int pass, void* p_rects)
                 TexPixelsAlpha8[offset0] = texture_data[n] == '.' ? 0xFF : 0x00;
                 TexPixelsAlpha8[offset1] = texture_data[n] == 'X' ? 0xFF : 0x00;
             }
-            const ImVec2 tex_uv_scale(1.0f / TexWidth, 1.0f / TexHeight);
-            TexUvWhitePixel = ImVec2((r.x + 0.5f) * tex_uv_scale.x, (r.y + 0.5f) * tex_uv_scale.y);
+        const ImVec2 tex_uv_scale(1.0f / TexWidth, 1.0f / TexHeight);
+        TexUvWhitePixel = ImVec2((r.x + 0.5f) * tex_uv_scale.x, (r.y + 0.5f) * tex_uv_scale.y);
 
-            const ImVec2 cursor_datas[ImGuiMouseCursor_Count_][3] =
-            {
-                // Pos ........ Size ......... Offset ......
-                { ImVec2(0,3),  ImVec2(12,19), ImVec2( 0, 0) }, // ImGuiMouseCursor_Arrow
-                { ImVec2(13,0), ImVec2(7,16),  ImVec2( 4, 8) }, // ImGuiMouseCursor_TextInput
-                { ImVec2(31,0), ImVec2(23,23), ImVec2(11,11) }, // ImGuiMouseCursor_Move
-                { ImVec2(21,0), ImVec2( 9,23), ImVec2( 5,11) }, // ImGuiMouseCursor_ResizeNS
-                { ImVec2(55,18),ImVec2(23, 9), ImVec2(11, 5) }, // ImGuiMouseCursor_ResizeEW
-                { ImVec2(73,0), ImVec2(17,17), ImVec2( 9, 9) }, // ImGuiMouseCursor_ResizeNESW
-                { ImVec2(55,0), ImVec2(17,17), ImVec2( 9, 9) }, // ImGuiMouseCursor_ResizeNWSE
-            };
-
-            for (int type = 0; type < ImGuiMouseCursor_Count_; type++)
-            {
-                ImGuiMouseCursorData& cursor_data = GImGui->MouseCursorData[type];
-                ImVec2 pos = cursor_datas[type][0] + ImVec2((float)r.x, (float)r.y);
-                const ImVec2 size = cursor_datas[type][1];
-                cursor_data.Type = type;
-                cursor_data.Size = size;
-                cursor_data.HotOffset = cursor_datas[type][2];
-                cursor_data.TexUvMin[0] = (pos) * tex_uv_scale;
-                cursor_data.TexUvMax[0] = (pos + size) * tex_uv_scale;
-                pos.x += TEX_DATA_W+1;
-                cursor_data.TexUvMin[1] = (pos) * tex_uv_scale;
-                cursor_data.TexUvMax[1] = (pos + size) * tex_uv_scale;
-            }
+        // Setup mouse cursors
+        const ImVec2 cursor_datas[ImGuiMouseCursor_Count_][3] =
+        {
+            // Pos ........ Size ......... Offset ......
+            { ImVec2(0,3),  ImVec2(12,19), ImVec2( 0, 0) }, // ImGuiMouseCursor_Arrow
+            { ImVec2(13,0), ImVec2(7,16),  ImVec2( 4, 8) }, // ImGuiMouseCursor_TextInput
+            { ImVec2(31,0), ImVec2(23,23), ImVec2(11,11) }, // ImGuiMouseCursor_Move
+            { ImVec2(21,0), ImVec2( 9,23), ImVec2( 5,11) }, // ImGuiMouseCursor_ResizeNS
+            { ImVec2(55,18),ImVec2(23, 9), ImVec2(11, 5) }, // ImGuiMouseCursor_ResizeEW
+            { ImVec2(73,0), ImVec2(17,17), ImVec2( 9, 9) }, // ImGuiMouseCursor_ResizeNESW
+            { ImVec2(55,0), ImVec2(17,17), ImVec2( 9, 9) }, // ImGuiMouseCursor_ResizeNWSE
+        };
+
+        for (int type = 0; type < ImGuiMouseCursor_Count_; type++)
+        {
+            ImGuiMouseCursorData& cursor_data = GImGui->MouseCursorData[type];
+            ImVec2 pos = cursor_datas[type][0] + ImVec2((float)r.x, (float)r.y);
+            const ImVec2 size = cursor_datas[type][1];
+            cursor_data.Type = type;
+            cursor_data.Size = size;
+            cursor_data.HotOffset = cursor_datas[type][2];
+            cursor_data.TexUvMin[0] = (pos) * tex_uv_scale;
+            cursor_data.TexUvMax[0] = (pos + size) * tex_uv_scale;
+            pos.x += TEX_DATA_W+1;
+            cursor_data.TexUvMin[1] = (pos) * tex_uv_scale;
+            cursor_data.TexUvMax[1] = (pos + size) * tex_uv_scale;
+        }
     }
 }
 
@@ -1603,7 +1607,7 @@ void ImFont::BuildLookupTable()
     }
 
     // Create a glyph to handle TAB
-    // FIXME: Needs proper TAB handling but it needs to be contextualized (can arbitrary say that each string starts at "column 0"
+    // FIXME: Needs proper TAB handling but it needs to be contextualized (or we could arbitrary say that each string starts at "column 0" ?)
     if (FindGlyph((unsigned short)' '))
     {
         if (Glyphs.back().Codepoint != '\t')   // So we can call this function multiple times
@@ -1783,7 +1787,7 @@ ImVec2 ImFont::CalcTextSizeA(float size, float max_width, float wrap_width, cons
             }
         }
 
-        // Decode and advance source (handle unlikely UTF-8 decoding failure by skipping to the next byte)
+        // Decode and advance source
         const char* prev_s = s;
         unsigned int c = (unsigned int)*s;
         if (c < 0x80)
@@ -1886,7 +1890,7 @@ void ImFont::RenderText(float size, ImVec2 pos, ImU32 col, const ImVec4& clip_re
             }
         }
 
-        // Decode and advance source (handle unlikely UTF-8 decoding failure by skipping to the next byte)
+        // Decode and advance source
         unsigned int c = (unsigned int)*s;
         if (c < 0x80)
         {
@@ -1925,7 +1929,7 @@ void ImFont::RenderText(float size, ImVec2 pos, ImU32 col, const ImVec4& clip_re
             // Clipping on Y is more likely
             if (c != ' ' && c != '\t')
             {
-                // We don't do a second finer clipping test on the Y axis (todo: do some measurement see if it is worth it, probably not)
+                // We don't do a second finer clipping test on the Y axis (TODO: do some measurement see if it is worth it, probably not)
                 float y1 = (float)(y + glyph->Y0 * scale);
                 float y2 = (float)(y + glyph->Y1 * scale);
 
@@ -1939,7 +1943,7 @@ void ImFont::RenderText(float size, ImVec2 pos, ImU32 col, const ImVec4& clip_re
                     float u2 = glyph->U1;
                     float v2 = glyph->V1;
 
-                    // CPU side clipping used to fit text in their frame when the frame is too small. Only does clipping for axis aligned quads
+                    // CPU side clipping used to fit text in their frame when the frame is too small. Only does clipping for axis aligned quads.
                     if (cpu_fine_clip)
                     {
                         if (x1 < clip_rect.x)