1 // dear imgui, v1.60 WIP
2 // (drawing and font code)
3 
4 // Contains implementation for
5 // - Default styles
6 // - ImDrawList
7 // - ImDrawData
8 // - ImFontAtlas
9 // - ImFont
10 // - Default font data
11 
12 #if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
13 #define _CRT_SECURE_NO_WARNINGS
14 #endif
15 
16 #include "imgui.h"
17 #define IMGUI_DEFINE_MATH_OPERATORS
18 #include "imgui_internal.h"
19 
20 #include <stdio.h>  // vsnprintf, sscanf, printf
21 #if !defined(alloca)
22 #ifdef _WIN32
23 #include <malloc.h>  // alloca
24 #if !defined(alloca)
25 #define alloca _alloca  // for clang with MS Codegen
26 #endif
27 #elif defined(__GLIBC__) || defined(__sun)
28 #include <alloca.h>  // alloca
29 #else
30 #include <stdlib.h>  // alloca
31 #endif
32 #endif
33 
34 #ifdef _MSC_VER
35 #pragma warning(disable : 4505)  // unreferenced local function has been removed (stb stuff)
36 #pragma warning(disable : 4996)  // 'This function or variable may be unsafe': strcpy, strdup, sprintf, vsnprintf, sscanf, fopen
37 #define snprintf _snprintf
38 #endif
39 
40 #ifdef __clang__
41 #pragma clang diagnostic ignored "-Wold-style-cast"       // warning : use of old-style cast                              // yes, they are more terse.
42 #pragma clang diagnostic ignored "-Wfloat-equal"          // warning : comparing floating point with == or != is unsafe   // storing and comparing against same constants ok.
43 #pragma clang diagnostic ignored "-Wglobal-constructors"  // warning : declaration requires a global destructor           // similar to above, not sure what the exact difference it.
44 #pragma clang diagnostic ignored "-Wsign-conversion"      // warning : implicit conversion changes signedness             //
45 #if __has_warning("-Wcomma")
46 #pragma clang diagnostic ignored "-Wcomma"  // warning : possible misuse of comma operator here             //
47 #endif
48 #if __has_warning("-Wreserved-id-macro")
49 #pragma clang diagnostic ignored "-Wreserved-id-macro"  // warning : macro name is a reserved identifier                //
50 #endif
51 #if __has_warning("-Wdouble-promotion")
52 #pragma clang diagnostic ignored "-Wdouble-promotion"  // warning: implicit conversion from 'float' to 'double' when passing argument to function
53 #endif
54 #elif defined(__GNUC__)
55 #pragma GCC diagnostic ignored "-Wunused-function"   // warning: 'xxxx' defined but not used
56 #pragma GCC diagnostic ignored "-Wdouble-promotion"  // warning: implicit conversion from 'float' to 'double' when passing argument to function
57 #pragma GCC diagnostic ignored "-Wconversion"        // warning: conversion to 'xxxx' from 'xxxx' may alter its value
58 #pragma GCC diagnostic ignored "-Wcast-qual"         // warning: cast from type 'xxxx' to type 'xxxx' casts away qualifiers
59 #endif
60 
61 //-------------------------------------------------------------------------
62 // STB libraries implementation
63 //-------------------------------------------------------------------------
64 
65 //#define IMGUI_STB_NAMESPACE     ImGuiStb
66 //#define IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION
67 //#define IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION
68 
69 #ifdef IMGUI_STB_NAMESPACE
70 namespace IMGUI_STB_NAMESPACE
71 {
72 #endif
73 
74 #ifdef _MSC_VER
75 #pragma warning(push)
76 #pragma warning(disable : 4456)  // declaration of 'xx' hides previous local declaration
77 #endif
78 
79 #ifdef __clang__
80 #pragma clang diagnostic push
81 #pragma clang diagnostic ignored "-Wunused-function"
82 #pragma clang diagnostic ignored "-Wmissing-prototypes"
83 #pragma clang diagnostic ignored "-Wimplicit-fallthrough"
84 #endif
85 
86 #ifdef __GNUC__
87 #pragma GCC diagnostic push
88 #pragma GCC diagnostic ignored "-Wtype-limits"  // warning: comparison is always true due to limited range of data type [-Wtype-limits]
89 #endif
90 
91 #define STBRP_ASSERT(x) IM_ASSERT(x)
92 #ifndef IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION
93 #define STBRP_STATIC
94 #define STB_RECT_PACK_IMPLEMENTATION
95 #endif
96 #include "stb_rect_pack.h"
97 
98 #define STBTT_malloc(x, u) ((void)(u), ImGui::MemAlloc(x))
99 #define STBTT_free(x, u) ((void)(u), ImGui::MemFree(x))
100 #define STBTT_assert(x) IM_ASSERT(x)
101 #ifndef IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION
102 #define STBTT_STATIC
103 #define STB_TRUETYPE_IMPLEMENTATION
104 #else
105 #define STBTT_DEF extern
106 #endif
107 #include "stb_truetype.h"
108 
109 #ifdef __GNUC__
110 #pragma GCC diagnostic pop
111 #endif
112 
113 #ifdef __clang__
114 #pragma clang diagnostic pop
115 #endif
116 
117 #ifdef _MSC_VER
118 #pragma warning(pop)
119 #endif
120 
121 #ifdef IMGUI_STB_NAMESPACE
122 }  // namespace ImGuiStb
123 using namespace IMGUI_STB_NAMESPACE;
124 #endif
125 
126 //-----------------------------------------------------------------------------
127 // Style functions
128 //-----------------------------------------------------------------------------
129 
StyleColorsDark(ImGuiStyle * dst)130 void ImGui::StyleColorsDark(ImGuiStyle* dst)
131 {
132 	ImGuiStyle* style = dst ? dst : &ImGui::GetStyle();
133 	ImVec4* colors = style->Colors;
134 
135 	colors[ImGuiCol_Text] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f);
136 	colors[ImGuiCol_TextDisabled] = ImVec4(0.50f, 0.50f, 0.50f, 1.00f);
137 	colors[ImGuiCol_WindowBg] = ImVec4(0.06f, 0.06f, 0.06f, 0.94f);
138 	colors[ImGuiCol_ChildBg] = ImVec4(1.00f, 1.00f, 1.00f, 0.00f);
139 	colors[ImGuiCol_PopupBg] = ImVec4(0.08f, 0.08f, 0.08f, 0.94f);
140 	colors[ImGuiCol_Border] = ImVec4(0.43f, 0.43f, 0.50f, 0.50f);
141 	colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
142 	colors[ImGuiCol_FrameBg] = ImVec4(0.16f, 0.29f, 0.48f, 0.54f);
143 	colors[ImGuiCol_FrameBgHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.40f);
144 	colors[ImGuiCol_FrameBgActive] = ImVec4(0.26f, 0.59f, 0.98f, 0.67f);
145 	colors[ImGuiCol_TitleBg] = ImVec4(0.04f, 0.04f, 0.04f, 1.00f);
146 	colors[ImGuiCol_TitleBgActive] = ImVec4(0.16f, 0.29f, 0.48f, 1.00f);
147 	colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.00f, 0.00f, 0.00f, 0.51f);
148 	colors[ImGuiCol_MenuBarBg] = ImVec4(0.14f, 0.14f, 0.14f, 1.00f);
149 	colors[ImGuiCol_ScrollbarBg] = ImVec4(0.02f, 0.02f, 0.02f, 0.53f);
150 	colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.31f, 0.31f, 0.31f, 1.00f);
151 	colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.41f, 0.41f, 0.41f, 1.00f);
152 	colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.51f, 0.51f, 0.51f, 1.00f);
153 	colors[ImGuiCol_CheckMark] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f);
154 	colors[ImGuiCol_SliderGrab] = ImVec4(0.24f, 0.52f, 0.88f, 1.00f);
155 	colors[ImGuiCol_SliderGrabActive] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f);
156 	colors[ImGuiCol_Button] = ImVec4(0.26f, 0.59f, 0.98f, 0.40f);
157 	colors[ImGuiCol_ButtonHovered] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f);
158 	colors[ImGuiCol_ButtonActive] = ImVec4(0.06f, 0.53f, 0.98f, 1.00f);
159 	colors[ImGuiCol_Header] = ImVec4(0.26f, 0.59f, 0.98f, 0.31f);
160 	colors[ImGuiCol_HeaderHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.80f);
161 	colors[ImGuiCol_HeaderActive] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f);
162 	colors[ImGuiCol_Separator] = colors[ImGuiCol_Border];
163 	colors[ImGuiCol_SeparatorHovered] = ImVec4(0.10f, 0.40f, 0.75f, 0.78f);
164 	colors[ImGuiCol_SeparatorActive] = ImVec4(0.10f, 0.40f, 0.75f, 1.00f);
165 	colors[ImGuiCol_ResizeGrip] = ImVec4(0.26f, 0.59f, 0.98f, 0.25f);
166 	colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.67f);
167 	colors[ImGuiCol_ResizeGripActive] = ImVec4(0.26f, 0.59f, 0.98f, 0.95f);
168 	colors[ImGuiCol_CloseButton] = ImVec4(0.41f, 0.41f, 0.41f, 0.50f);
169 	colors[ImGuiCol_CloseButtonHovered] = ImVec4(0.98f, 0.39f, 0.36f, 1.00f);
170 	colors[ImGuiCol_CloseButtonActive] = ImVec4(0.98f, 0.39f, 0.36f, 1.00f);
171 	colors[ImGuiCol_PlotLines] = ImVec4(0.61f, 0.61f, 0.61f, 1.00f);
172 	colors[ImGuiCol_PlotLinesHovered] = ImVec4(1.00f, 0.43f, 0.35f, 1.00f);
173 	colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f);
174 	colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.60f, 0.00f, 1.00f);
175 	colors[ImGuiCol_TextSelectedBg] = ImVec4(0.26f, 0.59f, 0.98f, 0.35f);
176 	colors[ImGuiCol_ModalWindowDarkening] = ImVec4(0.80f, 0.80f, 0.80f, 0.35f);
177 	colors[ImGuiCol_DragDropTarget] = ImVec4(1.00f, 1.00f, 0.00f, 0.90f);
178 	colors[ImGuiCol_NavHighlight] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f);
179 	colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.70f);
180 }
181 
StyleColorsClassic(ImGuiStyle * dst)182 void ImGui::StyleColorsClassic(ImGuiStyle* dst)
183 {
184 	ImGuiStyle* style = dst ? dst : &ImGui::GetStyle();
185 	ImVec4* colors = style->Colors;
186 
187 	colors[ImGuiCol_Text] = ImVec4(0.90f, 0.90f, 0.90f, 1.00f);
188 	colors[ImGuiCol_TextDisabled] = ImVec4(0.60f, 0.60f, 0.60f, 1.00f);
189 	colors[ImGuiCol_WindowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.70f);
190 	colors[ImGuiCol_ChildBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
191 	colors[ImGuiCol_PopupBg] = ImVec4(0.11f, 0.11f, 0.14f, 0.92f);
192 	colors[ImGuiCol_Border] = ImVec4(0.50f, 0.50f, 0.50f, 0.50f);
193 	colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
194 	colors[ImGuiCol_FrameBg] = ImVec4(0.43f, 0.43f, 0.43f, 0.39f);
195 	colors[ImGuiCol_FrameBgHovered] = ImVec4(0.47f, 0.47f, 0.69f, 0.40f);
196 	colors[ImGuiCol_FrameBgActive] = ImVec4(0.42f, 0.41f, 0.64f, 0.69f);
197 	colors[ImGuiCol_TitleBg] = ImVec4(0.27f, 0.27f, 0.54f, 0.83f);
198 	colors[ImGuiCol_TitleBgActive] = ImVec4(0.32f, 0.32f, 0.63f, 0.87f);
199 	colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.40f, 0.40f, 0.80f, 0.20f);
200 	colors[ImGuiCol_MenuBarBg] = ImVec4(0.40f, 0.40f, 0.55f, 0.80f);
201 	colors[ImGuiCol_ScrollbarBg] = ImVec4(0.20f, 0.25f, 0.30f, 0.60f);
202 	colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.40f, 0.40f, 0.80f, 0.30f);
203 	colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.40f, 0.40f, 0.80f, 0.40f);
204 	colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.41f, 0.39f, 0.80f, 0.60f);
205 	colors[ImGuiCol_CheckMark] = ImVec4(0.90f, 0.90f, 0.90f, 0.50f);
206 	colors[ImGuiCol_SliderGrab] = ImVec4(1.00f, 1.00f, 1.00f, 0.30f);
207 	colors[ImGuiCol_SliderGrabActive] = ImVec4(0.41f, 0.39f, 0.80f, 0.60f);
208 	colors[ImGuiCol_Button] = ImVec4(0.35f, 0.40f, 0.61f, 0.62f);
209 	colors[ImGuiCol_ButtonHovered] = ImVec4(0.40f, 0.48f, 0.71f, 0.79f);
210 	colors[ImGuiCol_ButtonActive] = ImVec4(0.46f, 0.54f, 0.80f, 1.00f);
211 	colors[ImGuiCol_Header] = ImVec4(0.40f, 0.40f, 0.90f, 0.45f);
212 	colors[ImGuiCol_HeaderHovered] = ImVec4(0.45f, 0.45f, 0.90f, 0.80f);
213 	colors[ImGuiCol_HeaderActive] = ImVec4(0.53f, 0.53f, 0.87f, 0.80f);
214 	colors[ImGuiCol_Separator] = ImVec4(0.50f, 0.50f, 0.50f, 1.00f);
215 	colors[ImGuiCol_SeparatorHovered] = ImVec4(0.60f, 0.60f, 0.70f, 1.00f);
216 	colors[ImGuiCol_SeparatorActive] = ImVec4(0.70f, 0.70f, 0.90f, 1.00f);
217 	colors[ImGuiCol_ResizeGrip] = ImVec4(1.00f, 1.00f, 1.00f, 0.16f);
218 	colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.78f, 0.82f, 1.00f, 0.60f);
219 	colors[ImGuiCol_ResizeGripActive] = ImVec4(0.78f, 0.82f, 1.00f, 0.90f);
220 	colors[ImGuiCol_CloseButton] = ImVec4(0.50f, 0.50f, 0.90f, 0.50f);
221 	colors[ImGuiCol_CloseButtonHovered] = ImVec4(0.70f, 0.70f, 0.90f, 0.60f);
222 	colors[ImGuiCol_CloseButtonActive] = ImVec4(0.70f, 0.70f, 0.70f, 1.00f);
223 	colors[ImGuiCol_PlotLines] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f);
224 	colors[ImGuiCol_PlotLinesHovered] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f);
225 	colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f);
226 	colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.60f, 0.00f, 1.00f);
227 	colors[ImGuiCol_TextSelectedBg] = ImVec4(0.00f, 0.00f, 1.00f, 0.35f);
228 	colors[ImGuiCol_ModalWindowDarkening] = ImVec4(0.20f, 0.20f, 0.20f, 0.35f);
229 	colors[ImGuiCol_DragDropTarget] = ImVec4(1.00f, 1.00f, 0.00f, 0.90f);
230 	colors[ImGuiCol_NavHighlight] = colors[ImGuiCol_HeaderHovered];
231 	colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.70f);
232 }
233 
234 // Those light colors are better suited with a thicker font than the default one + FrameBorder
StyleColorsLight(ImGuiStyle * dst)235 void ImGui::StyleColorsLight(ImGuiStyle* dst)
236 {
237 	ImGuiStyle* style = dst ? dst : &ImGui::GetStyle();
238 	ImVec4* colors = style->Colors;
239 
240 	colors[ImGuiCol_Text] = ImVec4(0.00f, 0.00f, 0.00f, 1.00f);
241 	colors[ImGuiCol_TextDisabled] = ImVec4(0.60f, 0.60f, 0.60f, 1.00f);
242 	//colors[ImGuiCol_TextHovered]          = ImVec4(1.00f, 1.00f, 1.00f, 1.00f);
243 	//colors[ImGuiCol_TextActive]           = ImVec4(1.00f, 1.00f, 0.00f, 1.00f);
244 	colors[ImGuiCol_WindowBg] = ImVec4(0.94f, 0.94f, 0.94f, 1.00f);
245 	colors[ImGuiCol_ChildBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
246 	colors[ImGuiCol_PopupBg] = ImVec4(1.00f, 1.00f, 1.00f, 0.98f);
247 	colors[ImGuiCol_Border] = ImVec4(0.00f, 0.00f, 0.00f, 0.30f);
248 	colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
249 	colors[ImGuiCol_FrameBg] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f);
250 	colors[ImGuiCol_FrameBgHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.40f);
251 	colors[ImGuiCol_FrameBgActive] = ImVec4(0.26f, 0.59f, 0.98f, 0.67f);
252 	colors[ImGuiCol_TitleBg] = ImVec4(0.96f, 0.96f, 0.96f, 1.00f);
253 	colors[ImGuiCol_TitleBgActive] = ImVec4(0.82f, 0.82f, 0.82f, 1.00f);
254 	colors[ImGuiCol_TitleBgCollapsed] = ImVec4(1.00f, 1.00f, 1.00f, 0.51f);
255 	colors[ImGuiCol_MenuBarBg] = ImVec4(0.86f, 0.86f, 0.86f, 1.00f);
256 	colors[ImGuiCol_ScrollbarBg] = ImVec4(0.98f, 0.98f, 0.98f, 0.53f);
257 	colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.69f, 0.69f, 0.69f, 0.80f);
258 	colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.49f, 0.49f, 0.49f, 0.80f);
259 	colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.49f, 0.49f, 0.49f, 1.00f);
260 	colors[ImGuiCol_CheckMark] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f);
261 	colors[ImGuiCol_SliderGrab] = ImVec4(0.26f, 0.59f, 0.98f, 0.78f);
262 	colors[ImGuiCol_SliderGrabActive] = ImVec4(0.46f, 0.54f, 0.80f, 0.60f);
263 	colors[ImGuiCol_Button] = ImVec4(0.26f, 0.59f, 0.98f, 0.40f);
264 	colors[ImGuiCol_ButtonHovered] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f);
265 	colors[ImGuiCol_ButtonActive] = ImVec4(0.06f, 0.53f, 0.98f, 1.00f);
266 	colors[ImGuiCol_Header] = ImVec4(0.26f, 0.59f, 0.98f, 0.31f);
267 	colors[ImGuiCol_HeaderHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.80f);
268 	colors[ImGuiCol_HeaderActive] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f);
269 	colors[ImGuiCol_Separator] = ImVec4(0.39f, 0.39f, 0.39f, 1.00f);
270 	colors[ImGuiCol_SeparatorHovered] = ImVec4(0.14f, 0.44f, 0.80f, 0.78f);
271 	colors[ImGuiCol_SeparatorActive] = ImVec4(0.14f, 0.44f, 0.80f, 1.00f);
272 	colors[ImGuiCol_ResizeGrip] = ImVec4(0.80f, 0.80f, 0.80f, 0.56f);
273 	colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.26f, 0.59f, 0.98f, 0.67f);
274 	colors[ImGuiCol_ResizeGripActive] = ImVec4(0.26f, 0.59f, 0.98f, 0.95f);
275 	colors[ImGuiCol_CloseButton] = ImVec4(0.59f, 0.59f, 0.59f, 0.50f);
276 	colors[ImGuiCol_CloseButtonHovered] = ImVec4(0.98f, 0.39f, 0.36f, 1.00f);
277 	colors[ImGuiCol_CloseButtonActive] = ImVec4(0.98f, 0.39f, 0.36f, 1.00f);
278 	colors[ImGuiCol_PlotLines] = ImVec4(0.39f, 0.39f, 0.39f, 1.00f);
279 	colors[ImGuiCol_PlotLinesHovered] = ImVec4(1.00f, 0.43f, 0.35f, 1.00f);
280 	colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f);
281 	colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.45f, 0.00f, 1.00f);
282 	colors[ImGuiCol_TextSelectedBg] = ImVec4(0.26f, 0.59f, 0.98f, 0.35f);
283 	colors[ImGuiCol_ModalWindowDarkening] = ImVec4(0.20f, 0.20f, 0.20f, 0.35f);
284 	colors[ImGuiCol_DragDropTarget] = ImVec4(0.26f, 0.59f, 0.98f, 0.95f);
285 	colors[ImGuiCol_NavHighlight] = colors[ImGuiCol_HeaderHovered];
286 	colors[ImGuiCol_NavWindowingHighlight] = ImVec4(0.70f, 0.70f, 0.70f, 0.70f);
287 }
288 
289 //-----------------------------------------------------------------------------
290 // ImDrawListData
291 //-----------------------------------------------------------------------------
292 
ImDrawListSharedData()293 ImDrawListSharedData::ImDrawListSharedData()
294 {
295 	Font = NULL;
296 	FontSize = 0.0f;
297 	CurveTessellationTol = 0.0f;
298 	ClipRectFullscreen = ImVec4(-8192.0f, -8192.0f, +8192.0f, +8192.0f);
299 
300 	// Const data
301 	for (int i = 0; i < IM_ARRAYSIZE(CircleVtx12); i++)
302 	{
303 		const float a = ((float)i * 2 * IM_PI) / (float)IM_ARRAYSIZE(CircleVtx12);
304 		CircleVtx12[i] = ImVec2(cosf(a), sinf(a));
305 	}
306 }
307 
308 //-----------------------------------------------------------------------------
309 // ImDrawList
310 //-----------------------------------------------------------------------------
311 
Clear()312 void ImDrawList::Clear()
313 {
314 	CmdBuffer.resize(0);
315 	IdxBuffer.resize(0);
316 	VtxBuffer.resize(0);
317 	Flags = ImDrawListFlags_AntiAliasedLines | ImDrawListFlags_AntiAliasedFill;
318 	_VtxCurrentIdx = 0;
319 	_VtxWritePtr = NULL;
320 	_IdxWritePtr = NULL;
321 	_ClipRectStack.resize(0);
322 	_TextureIdStack.resize(0);
323 	_Path.resize(0);
324 	_ChannelsCurrent = 0;
325 	_ChannelsCount = 1;
326 	// NB: Do not clear channels so our allocations are re-used after the first frame.
327 }
328 
ClearFreeMemory()329 void ImDrawList::ClearFreeMemory()
330 {
331 	CmdBuffer.clear();
332 	IdxBuffer.clear();
333 	VtxBuffer.clear();
334 	_VtxCurrentIdx = 0;
335 	_VtxWritePtr = NULL;
336 	_IdxWritePtr = NULL;
337 	_ClipRectStack.clear();
338 	_TextureIdStack.clear();
339 	_Path.clear();
340 	_ChannelsCurrent = 0;
341 	_ChannelsCount = 1;
342 	for (int i = 0; i < _Channels.Size; i++)
343 	{
344 		if (i == 0) memset(&_Channels[0], 0, sizeof(_Channels[0]));  // channel 0 is a copy of CmdBuffer/IdxBuffer, don't destruct again
345 		_Channels[i].CmdBuffer.clear();
346 		_Channels[i].IdxBuffer.clear();
347 	}
348 	_Channels.clear();
349 }
350 
351 // Using macros because C++ is a terrible language, we want guaranteed inline, no code in header, and no overhead in Debug builds
352 #define GetCurrentClipRect() (_ClipRectStack.Size ? _ClipRectStack.Data[_ClipRectStack.Size - 1] : _Data->ClipRectFullscreen)
353 #define GetCurrentTextureId() (_TextureIdStack.Size ? _TextureIdStack.Data[_TextureIdStack.Size - 1] : NULL)
354 
AddDrawCmd()355 void ImDrawList::AddDrawCmd()
356 {
357 	ImDrawCmd draw_cmd;
358 	draw_cmd.ClipRect = GetCurrentClipRect();
359 	draw_cmd.TextureId = GetCurrentTextureId();
360 
361 	IM_ASSERT(draw_cmd.ClipRect.x <= draw_cmd.ClipRect.z && draw_cmd.ClipRect.y <= draw_cmd.ClipRect.w);
362 	CmdBuffer.push_back(draw_cmd);
363 }
364 
AddCallback(ImDrawCallback callback,void * callback_data)365 void ImDrawList::AddCallback(ImDrawCallback callback, void* callback_data)
366 {
367 	ImDrawCmd* current_cmd = CmdBuffer.Size ? &CmdBuffer.back() : NULL;
368 	if (!current_cmd || current_cmd->ElemCount != 0 || current_cmd->UserCallback != NULL)
369 	{
370 		AddDrawCmd();
371 		current_cmd = &CmdBuffer.back();
372 	}
373 	current_cmd->UserCallback = callback;
374 	current_cmd->UserCallbackData = callback_data;
375 
376 	AddDrawCmd();  // Force a new command after us (see comment below)
377 }
378 
379 // Our scheme may appears a bit unusual, basically we want the most-common calls AddLine AddRect etc. to not have to perform any check so we always have a command ready in the stack.
380 // The cost of figuring out if a new command has to be added or if we can merge is paid in those Update** functions only.
UpdateClipRect()381 void ImDrawList::UpdateClipRect()
382 {
383 	// If current command is used with different settings we need to add a new command
384 	const ImVec4 curr_clip_rect = GetCurrentClipRect();
385 	ImDrawCmd* curr_cmd = CmdBuffer.Size > 0 ? &CmdBuffer.Data[CmdBuffer.Size - 1] : NULL;
386 	if (!curr_cmd || (curr_cmd->ElemCount != 0 && memcmp(&curr_cmd->ClipRect, &curr_clip_rect, sizeof(ImVec4)) != 0) || curr_cmd->UserCallback != NULL)
387 	{
388 		AddDrawCmd();
389 		return;
390 	}
391 
392 	// Try to merge with previous command if it matches, else use current command
393 	ImDrawCmd* prev_cmd = CmdBuffer.Size > 1 ? curr_cmd - 1 : NULL;
394 	if (curr_cmd->ElemCount == 0 && prev_cmd && memcmp(&prev_cmd->ClipRect, &curr_clip_rect, sizeof(ImVec4)) == 0 && prev_cmd->TextureId == GetCurrentTextureId() && prev_cmd->UserCallback == NULL)
395 		CmdBuffer.pop_back();
396 	else
397 		curr_cmd->ClipRect = curr_clip_rect;
398 }
399 
UpdateTextureID()400 void ImDrawList::UpdateTextureID()
401 {
402 	// If current command is used with different settings we need to add a new command
403 	const ImTextureID curr_texture_id = GetCurrentTextureId();
404 	ImDrawCmd* curr_cmd = CmdBuffer.Size ? &CmdBuffer.back() : NULL;
405 	if (!curr_cmd || (curr_cmd->ElemCount != 0 && curr_cmd->TextureId != curr_texture_id) || curr_cmd->UserCallback != NULL)
406 	{
407 		AddDrawCmd();
408 		return;
409 	}
410 
411 	// Try to merge with previous command if it matches, else use current command
412 	ImDrawCmd* prev_cmd = CmdBuffer.Size > 1 ? curr_cmd - 1 : NULL;
413 	if (curr_cmd->ElemCount == 0 && prev_cmd && prev_cmd->TextureId == curr_texture_id && memcmp(&prev_cmd->ClipRect, &GetCurrentClipRect(), sizeof(ImVec4)) == 0 && prev_cmd->UserCallback == NULL)
414 		CmdBuffer.pop_back();
415 	else
416 		curr_cmd->TextureId = curr_texture_id;
417 }
418 
419 #undef GetCurrentClipRect
420 #undef GetCurrentTextureId
421 
422 // Render-level scissoring. This is passed down to your render function but not used for CPU-side coarse clipping. Prefer using higher-level ImGui::PushClipRect() to affect logic (hit-testing and widget culling)
PushClipRect(ImVec2 cr_min,ImVec2 cr_max,bool intersect_with_current_clip_rect)423 void ImDrawList::PushClipRect(ImVec2 cr_min, ImVec2 cr_max, bool intersect_with_current_clip_rect)
424 {
425 	ImVec4 cr(cr_min.x, cr_min.y, cr_max.x, cr_max.y);
426 	if (intersect_with_current_clip_rect && _ClipRectStack.Size)
427 	{
428 		ImVec4 current = _ClipRectStack.Data[_ClipRectStack.Size - 1];
429 		if (cr.x < current.x) cr.x = current.x;
430 		if (cr.y < current.y) cr.y = current.y;
431 		if (cr.z > current.z) cr.z = current.z;
432 		if (cr.w > current.w) cr.w = current.w;
433 	}
434 	cr.z = ImMax(cr.x, cr.z);
435 	cr.w = ImMax(cr.y, cr.w);
436 
437 	_ClipRectStack.push_back(cr);
438 	UpdateClipRect();
439 }
440 
PushClipRectFullScreen()441 void ImDrawList::PushClipRectFullScreen()
442 {
443 	PushClipRect(ImVec2(_Data->ClipRectFullscreen.x, _Data->ClipRectFullscreen.y), ImVec2(_Data->ClipRectFullscreen.z, _Data->ClipRectFullscreen.w));
444 }
445 
PopClipRect()446 void ImDrawList::PopClipRect()
447 {
448 	IM_ASSERT(_ClipRectStack.Size > 0);
449 	_ClipRectStack.pop_back();
450 	UpdateClipRect();
451 }
452 
PushTextureID(ImTextureID texture_id)453 void ImDrawList::PushTextureID(ImTextureID texture_id)
454 {
455 	_TextureIdStack.push_back(texture_id);
456 	UpdateTextureID();
457 }
458 
PopTextureID()459 void ImDrawList::PopTextureID()
460 {
461 	IM_ASSERT(_TextureIdStack.Size > 0);
462 	_TextureIdStack.pop_back();
463 	UpdateTextureID();
464 }
465 
ChannelsSplit(int channels_count)466 void ImDrawList::ChannelsSplit(int channels_count)
467 {
468 	IM_ASSERT(_ChannelsCurrent == 0 && _ChannelsCount == 1);
469 	int old_channels_count = _Channels.Size;
470 	if (old_channels_count < channels_count)
471 		_Channels.resize(channels_count);
472 	_ChannelsCount = channels_count;
473 
474 	// _Channels[] (24/32 bytes each) hold storage that we'll swap with this->_CmdBuffer/_IdxBuffer
475 	// The content of _Channels[0] at this point doesn't matter. We clear it to make state tidy in a debugger but we don't strictly need to.
476 	// When we switch to the next channel, we'll copy _CmdBuffer/_IdxBuffer into _Channels[0] and then _Channels[1] into _CmdBuffer/_IdxBuffer
477 	memset(&_Channels[0], 0, sizeof(ImDrawChannel));
478 	for (int i = 1; i < channels_count; i++)
479 	{
480 		if (i >= old_channels_count)
481 		{
482 			IM_PLACEMENT_NEW(&_Channels[i])
483 			ImDrawChannel();
484 		}
485 		else
486 		{
487 			_Channels[i].CmdBuffer.resize(0);
488 			_Channels[i].IdxBuffer.resize(0);
489 		}
490 		if (_Channels[i].CmdBuffer.Size == 0)
491 		{
492 			ImDrawCmd draw_cmd;
493 			draw_cmd.ClipRect = _ClipRectStack.back();
494 			draw_cmd.TextureId = _TextureIdStack.back();
495 			_Channels[i].CmdBuffer.push_back(draw_cmd);
496 		}
497 	}
498 }
499 
ChannelsMerge()500 void ImDrawList::ChannelsMerge()
501 {
502 	// 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.
503 	if (_ChannelsCount <= 1)
504 		return;
505 
506 	ChannelsSetCurrent(0);
507 	if (CmdBuffer.Size && CmdBuffer.back().ElemCount == 0)
508 		CmdBuffer.pop_back();
509 
510 	int new_cmd_buffer_count = 0, new_idx_buffer_count = 0;
511 	for (int i = 1; i < _ChannelsCount; i++)
512 	{
513 		ImDrawChannel& ch = _Channels[i];
514 		if (ch.CmdBuffer.Size && ch.CmdBuffer.back().ElemCount == 0)
515 			ch.CmdBuffer.pop_back();
516 		new_cmd_buffer_count += ch.CmdBuffer.Size;
517 		new_idx_buffer_count += ch.IdxBuffer.Size;
518 	}
519 	CmdBuffer.resize(CmdBuffer.Size + new_cmd_buffer_count);
520 	IdxBuffer.resize(IdxBuffer.Size + new_idx_buffer_count);
521 
522 	ImDrawCmd* cmd_write = CmdBuffer.Data + CmdBuffer.Size - new_cmd_buffer_count;
523 	_IdxWritePtr = IdxBuffer.Data + IdxBuffer.Size - new_idx_buffer_count;
524 	for (int i = 1; i < _ChannelsCount; i++)
525 	{
526 		ImDrawChannel& ch = _Channels[i];
527 		if (int sz = ch.CmdBuffer.Size)
528 		{
529 			memcpy(cmd_write, ch.CmdBuffer.Data, sz * sizeof(ImDrawCmd));
530 			cmd_write += sz;
531 		}
532 		if (int sz = ch.IdxBuffer.Size)
533 		{
534 			memcpy(_IdxWritePtr, ch.IdxBuffer.Data, sz * sizeof(ImDrawIdx));
535 			_IdxWritePtr += sz;
536 		}
537 	}
538 	UpdateClipRect();  // We call this instead of AddDrawCmd(), so that empty channels won't produce an extra draw call.
539 	_ChannelsCount = 1;
540 }
541 
ChannelsSetCurrent(int idx)542 void ImDrawList::ChannelsSetCurrent(int idx)
543 {
544 	IM_ASSERT(idx < _ChannelsCount);
545 	if (_ChannelsCurrent == idx) return;
546 	memcpy(&_Channels.Data[_ChannelsCurrent].CmdBuffer, &CmdBuffer, sizeof(CmdBuffer));  // copy 12 bytes, four times
547 	memcpy(&_Channels.Data[_ChannelsCurrent].IdxBuffer, &IdxBuffer, sizeof(IdxBuffer));
548 	_ChannelsCurrent = idx;
549 	memcpy(&CmdBuffer, &_Channels.Data[_ChannelsCurrent].CmdBuffer, sizeof(CmdBuffer));
550 	memcpy(&IdxBuffer, &_Channels.Data[_ChannelsCurrent].IdxBuffer, sizeof(IdxBuffer));
551 	_IdxWritePtr = IdxBuffer.Data + IdxBuffer.Size;
552 }
553 
554 // NB: this can be called with negative count for removing primitives (as long as the result does not underflow)
PrimReserve(int idx_count,int vtx_count)555 void ImDrawList::PrimReserve(int idx_count, int vtx_count)
556 {
557 	ImDrawCmd& draw_cmd = CmdBuffer.Data[CmdBuffer.Size - 1];
558 	draw_cmd.ElemCount += idx_count;
559 
560 	int vtx_buffer_old_size = VtxBuffer.Size;
561 	VtxBuffer.resize(vtx_buffer_old_size + vtx_count);
562 	_VtxWritePtr = VtxBuffer.Data + vtx_buffer_old_size;
563 
564 	int idx_buffer_old_size = IdxBuffer.Size;
565 	IdxBuffer.resize(idx_buffer_old_size + idx_count);
566 	_IdxWritePtr = IdxBuffer.Data + idx_buffer_old_size;
567 }
568 
569 // Fully unrolled with inline call to keep our debug builds decently fast.
PrimRect(const ImVec2 & a,const ImVec2 & c,ImU32 col)570 void ImDrawList::PrimRect(const ImVec2& a, const ImVec2& c, ImU32 col)
571 {
572 	ImVec2 b(c.x, a.y), d(a.x, c.y), uv(_Data->TexUvWhitePixel);
573 	ImDrawIdx idx = (ImDrawIdx)_VtxCurrentIdx;
574 	_IdxWritePtr[0] = idx;
575 	_IdxWritePtr[1] = (ImDrawIdx)(idx + 1);
576 	_IdxWritePtr[2] = (ImDrawIdx)(idx + 2);
577 	_IdxWritePtr[3] = idx;
578 	_IdxWritePtr[4] = (ImDrawIdx)(idx + 2);
579 	_IdxWritePtr[5] = (ImDrawIdx)(idx + 3);
580 	_VtxWritePtr[0].pos = a;
581 	_VtxWritePtr[0].uv = uv;
582 	_VtxWritePtr[0].col = col;
583 	_VtxWritePtr[1].pos = b;
584 	_VtxWritePtr[1].uv = uv;
585 	_VtxWritePtr[1].col = col;
586 	_VtxWritePtr[2].pos = c;
587 	_VtxWritePtr[2].uv = uv;
588 	_VtxWritePtr[2].col = col;
589 	_VtxWritePtr[3].pos = d;
590 	_VtxWritePtr[3].uv = uv;
591 	_VtxWritePtr[3].col = col;
592 	_VtxWritePtr += 4;
593 	_VtxCurrentIdx += 4;
594 	_IdxWritePtr += 6;
595 }
596 
PrimRectUV(const ImVec2 & a,const ImVec2 & c,const ImVec2 & uv_a,const ImVec2 & uv_c,ImU32 col)597 void ImDrawList::PrimRectUV(const ImVec2& a, const ImVec2& c, const ImVec2& uv_a, const ImVec2& uv_c, ImU32 col)
598 {
599 	ImVec2 b(c.x, a.y), d(a.x, c.y), uv_b(uv_c.x, uv_a.y), uv_d(uv_a.x, uv_c.y);
600 	ImDrawIdx idx = (ImDrawIdx)_VtxCurrentIdx;
601 	_IdxWritePtr[0] = idx;
602 	_IdxWritePtr[1] = (ImDrawIdx)(idx + 1);
603 	_IdxWritePtr[2] = (ImDrawIdx)(idx + 2);
604 	_IdxWritePtr[3] = idx;
605 	_IdxWritePtr[4] = (ImDrawIdx)(idx + 2);
606 	_IdxWritePtr[5] = (ImDrawIdx)(idx + 3);
607 	_VtxWritePtr[0].pos = a;
608 	_VtxWritePtr[0].uv = uv_a;
609 	_VtxWritePtr[0].col = col;
610 	_VtxWritePtr[1].pos = b;
611 	_VtxWritePtr[1].uv = uv_b;
612 	_VtxWritePtr[1].col = col;
613 	_VtxWritePtr[2].pos = c;
614 	_VtxWritePtr[2].uv = uv_c;
615 	_VtxWritePtr[2].col = col;
616 	_VtxWritePtr[3].pos = d;
617 	_VtxWritePtr[3].uv = uv_d;
618 	_VtxWritePtr[3].col = col;
619 	_VtxWritePtr += 4;
620 	_VtxCurrentIdx += 4;
621 	_IdxWritePtr += 6;
622 }
623 
PrimQuadUV(const ImVec2 & a,const ImVec2 & b,const ImVec2 & c,const ImVec2 & d,const ImVec2 & uv_a,const ImVec2 & uv_b,const ImVec2 & uv_c,const ImVec2 & uv_d,ImU32 col)624 void ImDrawList::PrimQuadUV(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& d, const ImVec2& uv_a, const ImVec2& uv_b, const ImVec2& uv_c, const ImVec2& uv_d, ImU32 col)
625 {
626 	ImDrawIdx idx = (ImDrawIdx)_VtxCurrentIdx;
627 	_IdxWritePtr[0] = idx;
628 	_IdxWritePtr[1] = (ImDrawIdx)(idx + 1);
629 	_IdxWritePtr[2] = (ImDrawIdx)(idx + 2);
630 	_IdxWritePtr[3] = idx;
631 	_IdxWritePtr[4] = (ImDrawIdx)(idx + 2);
632 	_IdxWritePtr[5] = (ImDrawIdx)(idx + 3);
633 	_VtxWritePtr[0].pos = a;
634 	_VtxWritePtr[0].uv = uv_a;
635 	_VtxWritePtr[0].col = col;
636 	_VtxWritePtr[1].pos = b;
637 	_VtxWritePtr[1].uv = uv_b;
638 	_VtxWritePtr[1].col = col;
639 	_VtxWritePtr[2].pos = c;
640 	_VtxWritePtr[2].uv = uv_c;
641 	_VtxWritePtr[2].col = col;
642 	_VtxWritePtr[3].pos = d;
643 	_VtxWritePtr[3].uv = uv_d;
644 	_VtxWritePtr[3].col = col;
645 	_VtxWritePtr += 4;
646 	_VtxCurrentIdx += 4;
647 	_IdxWritePtr += 6;
648 }
649 
650 // TODO: Thickness anti-aliased lines cap are missing their AA fringe.
AddPolyline(const ImVec2 * points,const int points_count,ImU32 col,bool closed,float thickness)651 void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32 col, bool closed, float thickness)
652 {
653 	if (points_count < 2)
654 		return;
655 
656 	const ImVec2 uv = _Data->TexUvWhitePixel;
657 
658 	int count = points_count;
659 	if (!closed)
660 		count = points_count - 1;
661 
662 	const bool thick_line = thickness > 1.0f;
663 	if (Flags & ImDrawListFlags_AntiAliasedLines)
664 	{
665 		// Anti-aliased stroke
666 		const float AA_SIZE = 1.0f;
667 		const ImU32 col_trans = col & ~IM_COL32_A_MASK;
668 
669 		const int idx_count = thick_line ? count * 18 : count * 12;
670 		const int vtx_count = thick_line ? points_count * 4 : points_count * 3;
671 		PrimReserve(idx_count, vtx_count);
672 
673 		// Temporary buffer
674 		ImVec2* temp_normals = (ImVec2*)alloca(points_count * (thick_line ? 5 : 3) * sizeof(ImVec2));
675 		ImVec2* temp_points = temp_normals + points_count;
676 
677 		for (int i1 = 0; i1 < count; i1++)
678 		{
679 			const int i2 = (i1 + 1) == points_count ? 0 : i1 + 1;
680 			ImVec2 diff = points[i2] - points[i1];
681 			diff *= ImInvLength(diff, 1.0f);
682 			temp_normals[i1].x = diff.y;
683 			temp_normals[i1].y = -diff.x;
684 		}
685 		if (!closed)
686 			temp_normals[points_count - 1] = temp_normals[points_count - 2];
687 
688 		if (!thick_line)
689 		{
690 			if (!closed)
691 			{
692 				temp_points[0] = points[0] + temp_normals[0] * AA_SIZE;
693 				temp_points[1] = points[0] - temp_normals[0] * AA_SIZE;
694 				temp_points[(points_count - 1) * 2 + 0] = points[points_count - 1] + temp_normals[points_count - 1] * AA_SIZE;
695 				temp_points[(points_count - 1) * 2 + 1] = points[points_count - 1] - temp_normals[points_count - 1] * AA_SIZE;
696 			}
697 
698 			// FIXME-OPT: Merge the different loops, possibly remove the temporary buffer.
699 			unsigned int idx1 = _VtxCurrentIdx;
700 			for (int i1 = 0; i1 < count; i1++)
701 			{
702 				const int i2 = (i1 + 1) == points_count ? 0 : i1 + 1;
703 				unsigned int idx2 = (i1 + 1) == points_count ? _VtxCurrentIdx : idx1 + 3;
704 
705 				// Average normals
706 				ImVec2 dm = (temp_normals[i1] + temp_normals[i2]) * 0.5f;
707 				float dmr2 = dm.x * dm.x + dm.y * dm.y;
708 				if (dmr2 > 0.000001f)
709 				{
710 					float scale = 1.0f / dmr2;
711 					if (scale > 100.0f) scale = 100.0f;
712 					dm *= scale;
713 				}
714 				dm *= AA_SIZE;
715 				temp_points[i2 * 2 + 0] = points[i2] + dm;
716 				temp_points[i2 * 2 + 1] = points[i2] - dm;
717 
718 				// Add indexes
719 				_IdxWritePtr[0] = (ImDrawIdx)(idx2 + 0);
720 				_IdxWritePtr[1] = (ImDrawIdx)(idx1 + 0);
721 				_IdxWritePtr[2] = (ImDrawIdx)(idx1 + 2);
722 				_IdxWritePtr[3] = (ImDrawIdx)(idx1 + 2);
723 				_IdxWritePtr[4] = (ImDrawIdx)(idx2 + 2);
724 				_IdxWritePtr[5] = (ImDrawIdx)(idx2 + 0);
725 				_IdxWritePtr[6] = (ImDrawIdx)(idx2 + 1);
726 				_IdxWritePtr[7] = (ImDrawIdx)(idx1 + 1);
727 				_IdxWritePtr[8] = (ImDrawIdx)(idx1 + 0);
728 				_IdxWritePtr[9] = (ImDrawIdx)(idx1 + 0);
729 				_IdxWritePtr[10] = (ImDrawIdx)(idx2 + 0);
730 				_IdxWritePtr[11] = (ImDrawIdx)(idx2 + 1);
731 				_IdxWritePtr += 12;
732 
733 				idx1 = idx2;
734 			}
735 
736 			// Add vertexes
737 			for (int i = 0; i < points_count; i++)
738 			{
739 				_VtxWritePtr[0].pos = points[i];
740 				_VtxWritePtr[0].uv = uv;
741 				_VtxWritePtr[0].col = col;
742 				_VtxWritePtr[1].pos = temp_points[i * 2 + 0];
743 				_VtxWritePtr[1].uv = uv;
744 				_VtxWritePtr[1].col = col_trans;
745 				_VtxWritePtr[2].pos = temp_points[i * 2 + 1];
746 				_VtxWritePtr[2].uv = uv;
747 				_VtxWritePtr[2].col = col_trans;
748 				_VtxWritePtr += 3;
749 			}
750 		}
751 		else
752 		{
753 			const float half_inner_thickness = (thickness - AA_SIZE) * 0.5f;
754 			if (!closed)
755 			{
756 				temp_points[0] = points[0] + temp_normals[0] * (half_inner_thickness + AA_SIZE);
757 				temp_points[1] = points[0] + temp_normals[0] * (half_inner_thickness);
758 				temp_points[2] = points[0] - temp_normals[0] * (half_inner_thickness);
759 				temp_points[3] = points[0] - temp_normals[0] * (half_inner_thickness + AA_SIZE);
760 				temp_points[(points_count - 1) * 4 + 0] = points[points_count - 1] + temp_normals[points_count - 1] * (half_inner_thickness + AA_SIZE);
761 				temp_points[(points_count - 1) * 4 + 1] = points[points_count - 1] + temp_normals[points_count - 1] * (half_inner_thickness);
762 				temp_points[(points_count - 1) * 4 + 2] = points[points_count - 1] - temp_normals[points_count - 1] * (half_inner_thickness);
763 				temp_points[(points_count - 1) * 4 + 3] = points[points_count - 1] - temp_normals[points_count - 1] * (half_inner_thickness + AA_SIZE);
764 			}
765 
766 			// FIXME-OPT: Merge the different loops, possibly remove the temporary buffer.
767 			unsigned int idx1 = _VtxCurrentIdx;
768 			for (int i1 = 0; i1 < count; i1++)
769 			{
770 				const int i2 = (i1 + 1) == points_count ? 0 : i1 + 1;
771 				unsigned int idx2 = (i1 + 1) == points_count ? _VtxCurrentIdx : idx1 + 4;
772 
773 				// Average normals
774 				ImVec2 dm = (temp_normals[i1] + temp_normals[i2]) * 0.5f;
775 				float dmr2 = dm.x * dm.x + dm.y * dm.y;
776 				if (dmr2 > 0.000001f)
777 				{
778 					float scale = 1.0f / dmr2;
779 					if (scale > 100.0f) scale = 100.0f;
780 					dm *= scale;
781 				}
782 				ImVec2 dm_out = dm * (half_inner_thickness + AA_SIZE);
783 				ImVec2 dm_in = dm * half_inner_thickness;
784 				temp_points[i2 * 4 + 0] = points[i2] + dm_out;
785 				temp_points[i2 * 4 + 1] = points[i2] + dm_in;
786 				temp_points[i2 * 4 + 2] = points[i2] - dm_in;
787 				temp_points[i2 * 4 + 3] = points[i2] - dm_out;
788 
789 				// Add indexes
790 				_IdxWritePtr[0] = (ImDrawIdx)(idx2 + 1);
791 				_IdxWritePtr[1] = (ImDrawIdx)(idx1 + 1);
792 				_IdxWritePtr[2] = (ImDrawIdx)(idx1 + 2);
793 				_IdxWritePtr[3] = (ImDrawIdx)(idx1 + 2);
794 				_IdxWritePtr[4] = (ImDrawIdx)(idx2 + 2);
795 				_IdxWritePtr[5] = (ImDrawIdx)(idx2 + 1);
796 				_IdxWritePtr[6] = (ImDrawIdx)(idx2 + 1);
797 				_IdxWritePtr[7] = (ImDrawIdx)(idx1 + 1);
798 				_IdxWritePtr[8] = (ImDrawIdx)(idx1 + 0);
799 				_IdxWritePtr[9] = (ImDrawIdx)(idx1 + 0);
800 				_IdxWritePtr[10] = (ImDrawIdx)(idx2 + 0);
801 				_IdxWritePtr[11] = (ImDrawIdx)(idx2 + 1);
802 				_IdxWritePtr[12] = (ImDrawIdx)(idx2 + 2);
803 				_IdxWritePtr[13] = (ImDrawIdx)(idx1 + 2);
804 				_IdxWritePtr[14] = (ImDrawIdx)(idx1 + 3);
805 				_IdxWritePtr[15] = (ImDrawIdx)(idx1 + 3);
806 				_IdxWritePtr[16] = (ImDrawIdx)(idx2 + 3);
807 				_IdxWritePtr[17] = (ImDrawIdx)(idx2 + 2);
808 				_IdxWritePtr += 18;
809 
810 				idx1 = idx2;
811 			}
812 
813 			// Add vertexes
814 			for (int i = 0; i < points_count; i++)
815 			{
816 				_VtxWritePtr[0].pos = temp_points[i * 4 + 0];
817 				_VtxWritePtr[0].uv = uv;
818 				_VtxWritePtr[0].col = col_trans;
819 				_VtxWritePtr[1].pos = temp_points[i * 4 + 1];
820 				_VtxWritePtr[1].uv = uv;
821 				_VtxWritePtr[1].col = col;
822 				_VtxWritePtr[2].pos = temp_points[i * 4 + 2];
823 				_VtxWritePtr[2].uv = uv;
824 				_VtxWritePtr[2].col = col;
825 				_VtxWritePtr[3].pos = temp_points[i * 4 + 3];
826 				_VtxWritePtr[3].uv = uv;
827 				_VtxWritePtr[3].col = col_trans;
828 				_VtxWritePtr += 4;
829 			}
830 		}
831 		_VtxCurrentIdx += (ImDrawIdx)vtx_count;
832 	}
833 	else
834 	{
835 		// Non Anti-aliased Stroke
836 		const int idx_count = count * 6;
837 		const int vtx_count = count * 4;  // FIXME-OPT: Not sharing edges
838 		PrimReserve(idx_count, vtx_count);
839 
840 		for (int i1 = 0; i1 < count; i1++)
841 		{
842 			const int i2 = (i1 + 1) == points_count ? 0 : i1 + 1;
843 			const ImVec2& p1 = points[i1];
844 			const ImVec2& p2 = points[i2];
845 			ImVec2 diff = p2 - p1;
846 			diff *= ImInvLength(diff, 1.0f);
847 
848 			const float dx = diff.x * (thickness * 0.5f);
849 			const float dy = diff.y * (thickness * 0.5f);
850 			_VtxWritePtr[0].pos.x = p1.x + dy;
851 			_VtxWritePtr[0].pos.y = p1.y - dx;
852 			_VtxWritePtr[0].uv = uv;
853 			_VtxWritePtr[0].col = col;
854 			_VtxWritePtr[1].pos.x = p2.x + dy;
855 			_VtxWritePtr[1].pos.y = p2.y - dx;
856 			_VtxWritePtr[1].uv = uv;
857 			_VtxWritePtr[1].col = col;
858 			_VtxWritePtr[2].pos.x = p2.x - dy;
859 			_VtxWritePtr[2].pos.y = p2.y + dx;
860 			_VtxWritePtr[2].uv = uv;
861 			_VtxWritePtr[2].col = col;
862 			_VtxWritePtr[3].pos.x = p1.x - dy;
863 			_VtxWritePtr[3].pos.y = p1.y + dx;
864 			_VtxWritePtr[3].uv = uv;
865 			_VtxWritePtr[3].col = col;
866 			_VtxWritePtr += 4;
867 
868 			_IdxWritePtr[0] = (ImDrawIdx)(_VtxCurrentIdx);
869 			_IdxWritePtr[1] = (ImDrawIdx)(_VtxCurrentIdx + 1);
870 			_IdxWritePtr[2] = (ImDrawIdx)(_VtxCurrentIdx + 2);
871 			_IdxWritePtr[3] = (ImDrawIdx)(_VtxCurrentIdx);
872 			_IdxWritePtr[4] = (ImDrawIdx)(_VtxCurrentIdx + 2);
873 			_IdxWritePtr[5] = (ImDrawIdx)(_VtxCurrentIdx + 3);
874 			_IdxWritePtr += 6;
875 			_VtxCurrentIdx += 4;
876 		}
877 	}
878 }
879 
AddConvexPolyFilled(const ImVec2 * points,const int points_count,ImU32 col)880 void ImDrawList::AddConvexPolyFilled(const ImVec2* points, const int points_count, ImU32 col)
881 {
882 	const ImVec2 uv = _Data->TexUvWhitePixel;
883 
884 	if (Flags & ImDrawListFlags_AntiAliasedFill)
885 	{
886 		// Anti-aliased Fill
887 		const float AA_SIZE = 1.0f;
888 		const ImU32 col_trans = col & ~IM_COL32_A_MASK;
889 		const int idx_count = (points_count - 2) * 3 + points_count * 6;
890 		const int vtx_count = (points_count * 2);
891 		PrimReserve(idx_count, vtx_count);
892 
893 		// Add indexes for fill
894 		unsigned int vtx_inner_idx = _VtxCurrentIdx;
895 		unsigned int vtx_outer_idx = _VtxCurrentIdx + 1;
896 		for (int i = 2; i < points_count; i++)
897 		{
898 			_IdxWritePtr[0] = (ImDrawIdx)(vtx_inner_idx);
899 			_IdxWritePtr[1] = (ImDrawIdx)(vtx_inner_idx + ((i - 1) << 1));
900 			_IdxWritePtr[2] = (ImDrawIdx)(vtx_inner_idx + (i << 1));
901 			_IdxWritePtr += 3;
902 		}
903 
904 		// Compute normals
905 		ImVec2* temp_normals = (ImVec2*)alloca(points_count * sizeof(ImVec2));
906 		for (int i0 = points_count - 1, i1 = 0; i1 < points_count; i0 = i1++)
907 		{
908 			const ImVec2& p0 = points[i0];
909 			const ImVec2& p1 = points[i1];
910 			ImVec2 diff = p1 - p0;
911 			diff *= ImInvLength(diff, 1.0f);
912 			temp_normals[i0].x = diff.y;
913 			temp_normals[i0].y = -diff.x;
914 		}
915 
916 		for (int i0 = points_count - 1, i1 = 0; i1 < points_count; i0 = i1++)
917 		{
918 			// Average normals
919 			const ImVec2& n0 = temp_normals[i0];
920 			const ImVec2& n1 = temp_normals[i1];
921 			ImVec2 dm = (n0 + n1) * 0.5f;
922 			float dmr2 = dm.x * dm.x + dm.y * dm.y;
923 			if (dmr2 > 0.000001f)
924 			{
925 				float scale = 1.0f / dmr2;
926 				if (scale > 100.0f) scale = 100.0f;
927 				dm *= scale;
928 			}
929 			dm *= AA_SIZE * 0.5f;
930 
931 			// Add vertices
932 			_VtxWritePtr[0].pos = (points[i1] - dm);
933 			_VtxWritePtr[0].uv = uv;
934 			_VtxWritePtr[0].col = col;  // Inner
935 			_VtxWritePtr[1].pos = (points[i1] + dm);
936 			_VtxWritePtr[1].uv = uv;
937 			_VtxWritePtr[1].col = col_trans;  // Outer
938 			_VtxWritePtr += 2;
939 
940 			// Add indexes for fringes
941 			_IdxWritePtr[0] = (ImDrawIdx)(vtx_inner_idx + (i1 << 1));
942 			_IdxWritePtr[1] = (ImDrawIdx)(vtx_inner_idx + (i0 << 1));
943 			_IdxWritePtr[2] = (ImDrawIdx)(vtx_outer_idx + (i0 << 1));
944 			_IdxWritePtr[3] = (ImDrawIdx)(vtx_outer_idx + (i0 << 1));
945 			_IdxWritePtr[4] = (ImDrawIdx)(vtx_outer_idx + (i1 << 1));
946 			_IdxWritePtr[5] = (ImDrawIdx)(vtx_inner_idx + (i1 << 1));
947 			_IdxWritePtr += 6;
948 		}
949 		_VtxCurrentIdx += (ImDrawIdx)vtx_count;
950 	}
951 	else
952 	{
953 		// Non Anti-aliased Fill
954 		const int idx_count = (points_count - 2) * 3;
955 		const int vtx_count = points_count;
956 		PrimReserve(idx_count, vtx_count);
957 		for (int i = 0; i < vtx_count; i++)
958 		{
959 			_VtxWritePtr[0].pos = points[i];
960 			_VtxWritePtr[0].uv = uv;
961 			_VtxWritePtr[0].col = col;
962 			_VtxWritePtr++;
963 		}
964 		for (int i = 2; i < points_count; i++)
965 		{
966 			_IdxWritePtr[0] = (ImDrawIdx)(_VtxCurrentIdx);
967 			_IdxWritePtr[1] = (ImDrawIdx)(_VtxCurrentIdx + i - 1);
968 			_IdxWritePtr[2] = (ImDrawIdx)(_VtxCurrentIdx + i);
969 			_IdxWritePtr += 3;
970 		}
971 		_VtxCurrentIdx += (ImDrawIdx)vtx_count;
972 	}
973 }
974 
PathArcToFast(const ImVec2 & centre,float radius,int a_min_of_12,int a_max_of_12)975 void ImDrawList::PathArcToFast(const ImVec2& centre, float radius, int a_min_of_12, int a_max_of_12)
976 {
977 	if (radius == 0.0f || a_min_of_12 > a_max_of_12)
978 	{
979 		_Path.push_back(centre);
980 		return;
981 	}
982 	_Path.reserve(_Path.Size + (a_max_of_12 - a_min_of_12 + 1));
983 	for (int a = a_min_of_12; a <= a_max_of_12; a++)
984 	{
985 		const ImVec2& c = _Data->CircleVtx12[a % IM_ARRAYSIZE(_Data->CircleVtx12)];
986 		_Path.push_back(ImVec2(centre.x + c.x * radius, centre.y + c.y * radius));
987 	}
988 }
989 
PathArcTo(const ImVec2 & centre,float radius,float a_min,float a_max,int num_segments)990 void ImDrawList::PathArcTo(const ImVec2& centre, float radius, float a_min, float a_max, int num_segments)
991 {
992 	if (radius == 0.0f)
993 	{
994 		_Path.push_back(centre);
995 		return;
996 	}
997 	_Path.reserve(_Path.Size + (num_segments + 1));
998 	for (int i = 0; i <= num_segments; i++)
999 	{
1000 		const float a = a_min + ((float)i / (float)num_segments) * (a_max - a_min);
1001 		_Path.push_back(ImVec2(centre.x + cosf(a) * radius, centre.y + sinf(a) * radius));
1002 	}
1003 }
1004 
PathBezierToCasteljau(ImVector<ImVec2> * path,float x1,float y1,float x2,float y2,float x3,float y3,float x4,float y4,float tess_tol,int level)1005 static void PathBezierToCasteljau(ImVector<ImVec2>* path, float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4, float tess_tol, int level)
1006 {
1007 	float dx = x4 - x1;
1008 	float dy = y4 - y1;
1009 	float d2 = ((x2 - x4) * dy - (y2 - y4) * dx);
1010 	float d3 = ((x3 - x4) * dy - (y3 - y4) * dx);
1011 	d2 = (d2 >= 0) ? d2 : -d2;
1012 	d3 = (d3 >= 0) ? d3 : -d3;
1013 	if ((d2 + d3) * (d2 + d3) < tess_tol * (dx * dx + dy * dy))
1014 	{
1015 		path->push_back(ImVec2(x4, y4));
1016 	}
1017 	else if (level < 10)
1018 	{
1019 		float x12 = (x1 + x2) * 0.5f, y12 = (y1 + y2) * 0.5f;
1020 		float x23 = (x2 + x3) * 0.5f, y23 = (y2 + y3) * 0.5f;
1021 		float x34 = (x3 + x4) * 0.5f, y34 = (y3 + y4) * 0.5f;
1022 		float x123 = (x12 + x23) * 0.5f, y123 = (y12 + y23) * 0.5f;
1023 		float x234 = (x23 + x34) * 0.5f, y234 = (y23 + y34) * 0.5f;
1024 		float x1234 = (x123 + x234) * 0.5f, y1234 = (y123 + y234) * 0.5f;
1025 
1026 		PathBezierToCasteljau(path, x1, y1, x12, y12, x123, y123, x1234, y1234, tess_tol, level + 1);
1027 		PathBezierToCasteljau(path, x1234, y1234, x234, y234, x34, y34, x4, y4, tess_tol, level + 1);
1028 	}
1029 }
1030 
PathBezierCurveTo(const ImVec2 & p2,const ImVec2 & p3,const ImVec2 & p4,int num_segments)1031 void ImDrawList::PathBezierCurveTo(const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, int num_segments)
1032 {
1033 	ImVec2 p1 = _Path.back();
1034 	if (num_segments == 0)
1035 	{
1036 		// Auto-tessellated
1037 		PathBezierToCasteljau(&_Path, p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, p4.x, p4.y, _Data->CurveTessellationTol, 0);
1038 	}
1039 	else
1040 	{
1041 		float t_step = 1.0f / (float)num_segments;
1042 		for (int i_step = 1; i_step <= num_segments; i_step++)
1043 		{
1044 			float t = t_step * i_step;
1045 			float u = 1.0f - t;
1046 			float w1 = u * u * u;
1047 			float w2 = 3 * u * u * t;
1048 			float w3 = 3 * u * t * t;
1049 			float w4 = t * t * t;
1050 			_Path.push_back(ImVec2(w1 * p1.x + w2 * p2.x + w3 * p3.x + w4 * p4.x, w1 * p1.y + w2 * p2.y + w3 * p3.y + w4 * p4.y));
1051 		}
1052 	}
1053 }
1054 
PathRect(const ImVec2 & a,const ImVec2 & b,float rounding,int rounding_corners)1055 void ImDrawList::PathRect(const ImVec2& a, const ImVec2& b, float rounding, int rounding_corners)
1056 {
1057 	rounding = ImMin(rounding, fabsf(b.x - a.x) * (((rounding_corners & ImDrawCornerFlags_Top) == ImDrawCornerFlags_Top) || ((rounding_corners & ImDrawCornerFlags_Bot) == ImDrawCornerFlags_Bot) ? 0.5f : 1.0f) - 1.0f);
1058 	rounding = ImMin(rounding, fabsf(b.y - a.y) * (((rounding_corners & ImDrawCornerFlags_Left) == ImDrawCornerFlags_Left) || ((rounding_corners & ImDrawCornerFlags_Right) == ImDrawCornerFlags_Right) ? 0.5f : 1.0f) - 1.0f);
1059 
1060 	if (rounding <= 0.0f || rounding_corners == 0)
1061 	{
1062 		PathLineTo(a);
1063 		PathLineTo(ImVec2(b.x, a.y));
1064 		PathLineTo(b);
1065 		PathLineTo(ImVec2(a.x, b.y));
1066 	}
1067 	else
1068 	{
1069 		const float rounding_tl = (rounding_corners & ImDrawCornerFlags_TopLeft) ? rounding : 0.0f;
1070 		const float rounding_tr = (rounding_corners & ImDrawCornerFlags_TopRight) ? rounding : 0.0f;
1071 		const float rounding_br = (rounding_corners & ImDrawCornerFlags_BotRight) ? rounding : 0.0f;
1072 		const float rounding_bl = (rounding_corners & ImDrawCornerFlags_BotLeft) ? rounding : 0.0f;
1073 		PathArcToFast(ImVec2(a.x + rounding_tl, a.y + rounding_tl), rounding_tl, 6, 9);
1074 		PathArcToFast(ImVec2(b.x - rounding_tr, a.y + rounding_tr), rounding_tr, 9, 12);
1075 		PathArcToFast(ImVec2(b.x - rounding_br, b.y - rounding_br), rounding_br, 0, 3);
1076 		PathArcToFast(ImVec2(a.x + rounding_bl, b.y - rounding_bl), rounding_bl, 3, 6);
1077 	}
1078 }
1079 
AddLine(const ImVec2 & a,const ImVec2 & b,ImU32 col,float thickness)1080 void ImDrawList::AddLine(const ImVec2& a, const ImVec2& b, ImU32 col, float thickness)
1081 {
1082 	if ((col & IM_COL32_A_MASK) == 0)
1083 		return;
1084 	PathLineTo(a + ImVec2(0.5f, 0.5f));
1085 	PathLineTo(b + ImVec2(0.5f, 0.5f));
1086 	PathStroke(col, false, thickness);
1087 }
1088 
1089 // a: upper-left, b: lower-right. we don't render 1 px sized rectangles properly.
AddRect(const ImVec2 & a,const ImVec2 & b,ImU32 col,float rounding,int rounding_corners_flags,float thickness)1090 void ImDrawList::AddRect(const ImVec2& a, const ImVec2& b, ImU32 col, float rounding, int rounding_corners_flags, float thickness)
1091 {
1092 	if ((col & IM_COL32_A_MASK) == 0)
1093 		return;
1094 	PathRect(a + ImVec2(0.5f, 0.5f), b - ImVec2(0.5f, 0.5f), rounding, rounding_corners_flags);
1095 	PathStroke(col, true, thickness);
1096 }
1097 
AddRectFilled(const ImVec2 & a,const ImVec2 & b,ImU32 col,float rounding,int rounding_corners_flags)1098 void ImDrawList::AddRectFilled(const ImVec2& a, const ImVec2& b, ImU32 col, float rounding, int rounding_corners_flags)
1099 {
1100 	if ((col & IM_COL32_A_MASK) == 0)
1101 		return;
1102 	if (rounding > 0.0f)
1103 	{
1104 		PathRect(a, b, rounding, rounding_corners_flags);
1105 		PathFillConvex(col);
1106 	}
1107 	else
1108 	{
1109 		PrimReserve(6, 4);
1110 		PrimRect(a, b, col);
1111 	}
1112 }
1113 
AddRectFilledMultiColor(const ImVec2 & a,const ImVec2 & c,ImU32 col_upr_left,ImU32 col_upr_right,ImU32 col_bot_right,ImU32 col_bot_left)1114 void ImDrawList::AddRectFilledMultiColor(const ImVec2& a, const ImVec2& c, ImU32 col_upr_left, ImU32 col_upr_right, ImU32 col_bot_right, ImU32 col_bot_left)
1115 {
1116 	if (((col_upr_left | col_upr_right | col_bot_right | col_bot_left) & IM_COL32_A_MASK) == 0)
1117 		return;
1118 
1119 	const ImVec2 uv = _Data->TexUvWhitePixel;
1120 	PrimReserve(6, 4);
1121 	PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx));
1122 	PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx + 1));
1123 	PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx + 2));
1124 	PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx));
1125 	PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx + 2));
1126 	PrimWriteIdx((ImDrawIdx)(_VtxCurrentIdx + 3));
1127 	PrimWriteVtx(a, uv, col_upr_left);
1128 	PrimWriteVtx(ImVec2(c.x, a.y), uv, col_upr_right);
1129 	PrimWriteVtx(c, uv, col_bot_right);
1130 	PrimWriteVtx(ImVec2(a.x, c.y), uv, col_bot_left);
1131 }
1132 
AddQuad(const ImVec2 & a,const ImVec2 & b,const ImVec2 & c,const ImVec2 & d,ImU32 col,float thickness)1133 void ImDrawList::AddQuad(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& d, ImU32 col, float thickness)
1134 {
1135 	if ((col & IM_COL32_A_MASK) == 0)
1136 		return;
1137 
1138 	PathLineTo(a);
1139 	PathLineTo(b);
1140 	PathLineTo(c);
1141 	PathLineTo(d);
1142 	PathStroke(col, true, thickness);
1143 }
1144 
AddQuadFilled(const ImVec2 & a,const ImVec2 & b,const ImVec2 & c,const ImVec2 & d,ImU32 col)1145 void ImDrawList::AddQuadFilled(const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& d, ImU32 col)
1146 {
1147 	if ((col & IM_COL32_A_MASK) == 0)
1148 		return;
1149 
1150 	PathLineTo(a);
1151 	PathLineTo(b);
1152 	PathLineTo(c);
1153 	PathLineTo(d);
1154 	PathFillConvex(col);
1155 }
1156 
AddTriangle(const ImVec2 & a,const ImVec2 & b,const ImVec2 & c,ImU32 col,float thickness)1157 void ImDrawList::AddTriangle(const ImVec2& a, const ImVec2& b, const ImVec2& c, ImU32 col, float thickness)
1158 {
1159 	if ((col & IM_COL32_A_MASK) == 0)
1160 		return;
1161 
1162 	PathLineTo(a);
1163 	PathLineTo(b);
1164 	PathLineTo(c);
1165 	PathStroke(col, true, thickness);
1166 }
1167 
AddTriangleFilled(const ImVec2 & a,const ImVec2 & b,const ImVec2 & c,ImU32 col)1168 void ImDrawList::AddTriangleFilled(const ImVec2& a, const ImVec2& b, const ImVec2& c, ImU32 col)
1169 {
1170 	if ((col & IM_COL32_A_MASK) == 0)
1171 		return;
1172 
1173 	PathLineTo(a);
1174 	PathLineTo(b);
1175 	PathLineTo(c);
1176 	PathFillConvex(col);
1177 }
1178 
AddCircle(const ImVec2 & centre,float radius,ImU32 col,int num_segments,float thickness)1179 void ImDrawList::AddCircle(const ImVec2& centre, float radius, ImU32 col, int num_segments, float thickness)
1180 {
1181 	if ((col & IM_COL32_A_MASK) == 0)
1182 		return;
1183 
1184 	const float a_max = IM_PI * 2.0f * ((float)num_segments - 1.0f) / (float)num_segments;
1185 	PathArcTo(centre, radius - 0.5f, 0.0f, a_max, num_segments);
1186 	PathStroke(col, true, thickness);
1187 }
1188 
AddCircleFilled(const ImVec2 & centre,float radius,ImU32 col,int num_segments)1189 void ImDrawList::AddCircleFilled(const ImVec2& centre, float radius, ImU32 col, int num_segments)
1190 {
1191 	if ((col & IM_COL32_A_MASK) == 0)
1192 		return;
1193 
1194 	const float a_max = IM_PI * 2.0f * ((float)num_segments - 1.0f) / (float)num_segments;
1195 	PathArcTo(centre, radius, 0.0f, a_max, num_segments);
1196 	PathFillConvex(col);
1197 }
1198 
AddBezierCurve(const ImVec2 & pos0,const ImVec2 & cp0,const ImVec2 & cp1,const ImVec2 & pos1,ImU32 col,float thickness,int num_segments)1199 void ImDrawList::AddBezierCurve(const ImVec2& pos0, const ImVec2& cp0, const ImVec2& cp1, const ImVec2& pos1, ImU32 col, float thickness, int num_segments)
1200 {
1201 	if ((col & IM_COL32_A_MASK) == 0)
1202 		return;
1203 
1204 	PathLineTo(pos0);
1205 	PathBezierCurveTo(cp0, cp1, pos1, num_segments);
1206 	PathStroke(col, false, thickness);
1207 }
1208 
AddText(const ImFont * font,float font_size,const ImVec2 & pos,ImU32 col,const char * text_begin,const char * text_end,float wrap_width,const ImVec4 * cpu_fine_clip_rect)1209 void ImDrawList::AddText(const ImFont* font, float font_size, const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end, float wrap_width, const ImVec4* cpu_fine_clip_rect)
1210 {
1211 	if ((col & IM_COL32_A_MASK) == 0)
1212 		return;
1213 
1214 	if (text_end == NULL)
1215 		text_end = text_begin + strlen(text_begin);
1216 	if (text_begin == text_end)
1217 		return;
1218 
1219 	// Pull default font/size from the shared ImDrawListSharedData instance
1220 	if (font == NULL)
1221 		font = _Data->Font;
1222 	if (font_size == 0.0f)
1223 		font_size = _Data->FontSize;
1224 
1225 	IM_ASSERT(font->ContainerAtlas->TexID == _TextureIdStack.back());  // Use high-level ImGui::PushFont() or low-level ImDrawList::PushTextureId() to change font.
1226 
1227 	ImVec4 clip_rect = _ClipRectStack.back();
1228 	if (cpu_fine_clip_rect)
1229 	{
1230 		clip_rect.x = ImMax(clip_rect.x, cpu_fine_clip_rect->x);
1231 		clip_rect.y = ImMax(clip_rect.y, cpu_fine_clip_rect->y);
1232 		clip_rect.z = ImMin(clip_rect.z, cpu_fine_clip_rect->z);
1233 		clip_rect.w = ImMin(clip_rect.w, cpu_fine_clip_rect->w);
1234 	}
1235 	font->RenderText(this, font_size, pos, col, clip_rect, text_begin, text_end, wrap_width, cpu_fine_clip_rect != NULL);
1236 }
1237 
AddText(const ImVec2 & pos,ImU32 col,const char * text_begin,const char * text_end)1238 void ImDrawList::AddText(const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end)
1239 {
1240 	AddText(NULL, 0.0f, pos, col, text_begin, text_end);
1241 }
1242 
AddImage(ImTextureID user_texture_id,const ImVec2 & a,const ImVec2 & b,const ImVec2 & uv_a,const ImVec2 & uv_b,ImU32 col)1243 void ImDrawList::AddImage(ImTextureID user_texture_id, const ImVec2& a, const ImVec2& b, const ImVec2& uv_a, const ImVec2& uv_b, ImU32 col)
1244 {
1245 	if ((col & IM_COL32_A_MASK) == 0)
1246 		return;
1247 
1248 	const bool push_texture_id = _TextureIdStack.empty() || user_texture_id != _TextureIdStack.back();
1249 	if (push_texture_id)
1250 		PushTextureID(user_texture_id);
1251 
1252 	PrimReserve(6, 4);
1253 	PrimRectUV(a, b, uv_a, uv_b, col);
1254 
1255 	if (push_texture_id)
1256 		PopTextureID();
1257 }
1258 
AddImageQuad(ImTextureID user_texture_id,const ImVec2 & a,const ImVec2 & b,const ImVec2 & c,const ImVec2 & d,const ImVec2 & uv_a,const ImVec2 & uv_b,const ImVec2 & uv_c,const ImVec2 & uv_d,ImU32 col)1259 void ImDrawList::AddImageQuad(ImTextureID user_texture_id, const ImVec2& a, const ImVec2& b, const ImVec2& c, const ImVec2& d, const ImVec2& uv_a, const ImVec2& uv_b, const ImVec2& uv_c, const ImVec2& uv_d, ImU32 col)
1260 {
1261 	if ((col & IM_COL32_A_MASK) == 0)
1262 		return;
1263 
1264 	const bool push_texture_id = _TextureIdStack.empty() || user_texture_id != _TextureIdStack.back();
1265 	if (push_texture_id)
1266 		PushTextureID(user_texture_id);
1267 
1268 	PrimReserve(6, 4);
1269 	PrimQuadUV(a, b, c, d, uv_a, uv_b, uv_c, uv_d, col);
1270 
1271 	if (push_texture_id)
1272 		PopTextureID();
1273 }
1274 
AddImageRounded(ImTextureID user_texture_id,const ImVec2 & a,const ImVec2 & b,const ImVec2 & uv_a,const ImVec2 & uv_b,ImU32 col,float rounding,int rounding_corners)1275 void ImDrawList::AddImageRounded(ImTextureID user_texture_id, const ImVec2& a, const ImVec2& b, const ImVec2& uv_a, const ImVec2& uv_b, ImU32 col, float rounding, int rounding_corners)
1276 {
1277 	if ((col & IM_COL32_A_MASK) == 0)
1278 		return;
1279 
1280 	if (rounding <= 0.0f || (rounding_corners & ImDrawCornerFlags_All) == 0)
1281 	{
1282 		AddImage(user_texture_id, a, b, uv_a, uv_b, col);
1283 		return;
1284 	}
1285 
1286 	const bool push_texture_id = _TextureIdStack.empty() || user_texture_id != _TextureIdStack.back();
1287 	if (push_texture_id)
1288 		PushTextureID(user_texture_id);
1289 
1290 	int vert_start_idx = VtxBuffer.Size;
1291 	PathRect(a, b, rounding, rounding_corners);
1292 	PathFillConvex(col);
1293 	int vert_end_idx = VtxBuffer.Size;
1294 	ImGui::ShadeVertsLinearUV(VtxBuffer.Data + vert_start_idx, VtxBuffer.Data + vert_end_idx, a, b, uv_a, uv_b, true);
1295 
1296 	if (push_texture_id)
1297 		PopTextureID();
1298 }
1299 
1300 //-----------------------------------------------------------------------------
1301 // ImDrawData
1302 //-----------------------------------------------------------------------------
1303 
1304 // For backward compatibility: convert all buffers from indexed to de-indexed, in case you cannot render indexed. Note: this is slow and most likely a waste of resources. Always prefer indexed rendering!
DeIndexAllBuffers()1305 void ImDrawData::DeIndexAllBuffers()
1306 {
1307 	ImVector<ImDrawVert> new_vtx_buffer;
1308 	TotalVtxCount = TotalIdxCount = 0;
1309 	for (int i = 0; i < CmdListsCount; i++)
1310 	{
1311 		ImDrawList* cmd_list = CmdLists[i];
1312 		if (cmd_list->IdxBuffer.empty())
1313 			continue;
1314 		new_vtx_buffer.resize(cmd_list->IdxBuffer.Size);
1315 		for (int j = 0; j < cmd_list->IdxBuffer.Size; j++)
1316 			new_vtx_buffer[j] = cmd_list->VtxBuffer[cmd_list->IdxBuffer[j]];
1317 		cmd_list->VtxBuffer.swap(new_vtx_buffer);
1318 		cmd_list->IdxBuffer.resize(0);
1319 		TotalVtxCount += cmd_list->VtxBuffer.Size;
1320 	}
1321 }
1322 
1323 // Helper to scale the ClipRect field of each ImDrawCmd. Use if your final output buffer is at a different scale than ImGui expects, or if there is a difference between your window resolution and framebuffer resolution.
ScaleClipRects(const ImVec2 & scale)1324 void ImDrawData::ScaleClipRects(const ImVec2& scale)
1325 {
1326 	for (int i = 0; i < CmdListsCount; i++)
1327 	{
1328 		ImDrawList* cmd_list = CmdLists[i];
1329 		for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
1330 		{
1331 			ImDrawCmd* cmd = &cmd_list->CmdBuffer[cmd_i];
1332 			cmd->ClipRect = ImVec4(cmd->ClipRect.x * scale.x, cmd->ClipRect.y * scale.y, cmd->ClipRect.z * scale.x, cmd->ClipRect.w * scale.y);
1333 		}
1334 	}
1335 }
1336 
1337 //-----------------------------------------------------------------------------
1338 // Shade functions
1339 //-----------------------------------------------------------------------------
1340 
1341 // Generic linear color gradient, write to RGB fields, leave A untouched.
ShadeVertsLinearColorGradientKeepAlpha(ImDrawVert * vert_start,ImDrawVert * vert_end,ImVec2 gradient_p0,ImVec2 gradient_p1,ImU32 col0,ImU32 col1)1342 void ImGui::ShadeVertsLinearColorGradientKeepAlpha(ImDrawVert* vert_start, ImDrawVert* vert_end, ImVec2 gradient_p0, ImVec2 gradient_p1, ImU32 col0, ImU32 col1)
1343 {
1344 	ImVec2 gradient_extent = gradient_p1 - gradient_p0;
1345 	float gradient_inv_length2 = 1.0f / ImLengthSqr(gradient_extent);
1346 	for (ImDrawVert* vert = vert_start; vert < vert_end; vert++)
1347 	{
1348 		float d = ImDot(vert->pos - gradient_p0, gradient_extent);
1349 		float t = ImClamp(d * gradient_inv_length2, 0.0f, 1.0f);
1350 		int r = ImLerp((int)(col0 >> IM_COL32_R_SHIFT) & 0xFF, (int)(col1 >> IM_COL32_R_SHIFT) & 0xFF, t);
1351 		int g = ImLerp((int)(col0 >> IM_COL32_G_SHIFT) & 0xFF, (int)(col1 >> IM_COL32_G_SHIFT) & 0xFF, t);
1352 		int b = ImLerp((int)(col0 >> IM_COL32_B_SHIFT) & 0xFF, (int)(col1 >> IM_COL32_B_SHIFT) & 0xFF, t);
1353 		vert->col = (r << IM_COL32_R_SHIFT) | (g << IM_COL32_G_SHIFT) | (b << IM_COL32_B_SHIFT) | (vert->col & IM_COL32_A_MASK);
1354 	}
1355 }
1356 
1357 // Scan and shade backward from the end of given vertices. Assume vertices are text only (= vert_start..vert_end going left to right) so we can break as soon as we are out the gradient bounds.
ShadeVertsLinearAlphaGradientForLeftToRightText(ImDrawVert * vert_start,ImDrawVert * vert_end,float gradient_p0_x,float gradient_p1_x)1358 void ImGui::ShadeVertsLinearAlphaGradientForLeftToRightText(ImDrawVert* vert_start, ImDrawVert* vert_end, float gradient_p0_x, float gradient_p1_x)
1359 {
1360 	float gradient_extent_x = gradient_p1_x - gradient_p0_x;
1361 	float gradient_inv_length2 = 1.0f / (gradient_extent_x * gradient_extent_x);
1362 	int full_alpha_count = 0;
1363 	for (ImDrawVert* vert = vert_end - 1; vert >= vert_start; vert--)
1364 	{
1365 		float d = (vert->pos.x - gradient_p0_x) * (gradient_extent_x);
1366 		float alpha_mul = 1.0f - ImClamp(d * gradient_inv_length2, 0.0f, 1.0f);
1367 		if (alpha_mul >= 1.0f && ++full_alpha_count > 2)
1368 			return;  // Early out
1369 		int a = (int)(((vert->col >> IM_COL32_A_SHIFT) & 0xFF) * alpha_mul);
1370 		vert->col = (vert->col & ~IM_COL32_A_MASK) | (a << IM_COL32_A_SHIFT);
1371 	}
1372 }
1373 
1374 // Distribute UV over (a, b) rectangle
ShadeVertsLinearUV(ImDrawVert * vert_start,ImDrawVert * vert_end,const ImVec2 & a,const ImVec2 & b,const ImVec2 & uv_a,const ImVec2 & uv_b,bool clamp)1375 void ImGui::ShadeVertsLinearUV(ImDrawVert* vert_start, ImDrawVert* vert_end, const ImVec2& a, const ImVec2& b, const ImVec2& uv_a, const ImVec2& uv_b, bool clamp)
1376 {
1377 	const ImVec2 size = b - a;
1378 	const ImVec2 uv_size = uv_b - uv_a;
1379 	const ImVec2 scale = ImVec2(
1380 		size.x != 0.0f ? (uv_size.x / size.x) : 0.0f,
1381 		size.y != 0.0f ? (uv_size.y / size.y) : 0.0f);
1382 
1383 	if (clamp)
1384 	{
1385 		const ImVec2 min = ImMin(uv_a, uv_b);
1386 		const ImVec2 max = ImMax(uv_a, uv_b);
1387 
1388 		for (ImDrawVert* vertex = vert_start; vertex < vert_end; ++vertex)
1389 			vertex->uv = ImClamp(uv_a + ImMul(ImVec2(vertex->pos.x, vertex->pos.y) - a, scale), min, max);
1390 	}
1391 	else
1392 	{
1393 		for (ImDrawVert* vertex = vert_start; vertex < vert_end; ++vertex)
1394 			vertex->uv = uv_a + ImMul(ImVec2(vertex->pos.x, vertex->pos.y) - a, scale);
1395 	}
1396 }
1397 
1398 //-----------------------------------------------------------------------------
1399 // ImFontConfig
1400 //-----------------------------------------------------------------------------
1401 
ImFontConfig()1402 ImFontConfig::ImFontConfig()
1403 {
1404 	FontData = NULL;
1405 	FontDataSize = 0;
1406 	FontDataOwnedByAtlas = true;
1407 	FontNo = 0;
1408 	SizePixels = 0.0f;
1409 	OversampleH = 3;
1410 	OversampleV = 1;
1411 	PixelSnapH = false;
1412 	GlyphExtraSpacing = ImVec2(0.0f, 0.0f);
1413 	GlyphOffset = ImVec2(0.0f, 0.0f);
1414 	GlyphRanges = NULL;
1415 	MergeMode = false;
1416 	RasterizerFlags = 0x00;
1417 	RasterizerMultiply = 1.0f;
1418 	memset(Name, 0, sizeof(Name));
1419 	DstFont = NULL;
1420 }
1421 
1422 //-----------------------------------------------------------------------------
1423 // ImFontAtlas
1424 //-----------------------------------------------------------------------------
1425 
1426 // A work of art lies ahead! (. = white layer, X = black layer, others are blank)
1427 // The white texels on the top left are the ones we'll use everywhere in ImGui to render filled shapes.
1428 const int FONT_ATLAS_DEFAULT_TEX_DATA_W_HALF = 90;
1429 const int FONT_ATLAS_DEFAULT_TEX_DATA_H = 27;
1430 const unsigned int FONT_ATLAS_DEFAULT_TEX_DATA_ID = 0x80000000;
1431 static const char FONT_ATLAS_DEFAULT_TEX_DATA_PIXELS[FONT_ATLAS_DEFAULT_TEX_DATA_W_HALF * FONT_ATLAS_DEFAULT_TEX_DATA_H + 1] =
1432 	{
1433 		"..-         -XXXXXXX-    X    -           X           -XXXXXXX          -          XXXXXXX"
1434 		"..-         -X.....X-   X.X   -          X.X          -X.....X          -          X.....X"
1435 		"---         -XXX.XXX-  X...X  -         X...X         -X....X           -           X....X"
1436 		"X           -  X.X  - X.....X -        X.....X        -X...X            -            X...X"
1437 		"XX          -  X.X  -X.......X-       X.......X       -X..X.X           -           X.X..X"
1438 		"X.X         -  X.X  -XXXX.XXXX-       XXXX.XXXX       -X.X X.X          -          X.X X.X"
1439 		"X..X        -  X.X  -   X.X   -          X.X          -XX   X.X         -         X.X   XX"
1440 		"X...X       -  X.X  -   X.X   -    XX    X.X    XX    -      X.X        -        X.X      "
1441 		"X....X      -  X.X  -   X.X   -   X.X    X.X    X.X   -       X.X       -       X.X       "
1442 		"X.....X     -  X.X  -   X.X   -  X..X    X.X    X..X  -        X.X      -      X.X        "
1443 		"X......X    -  X.X  -   X.X   - X...XXXXXX.XXXXXX...X -         X.X   XX-XX   X.X         "
1444 		"X.......X   -  X.X  -   X.X   -X.....................X-          X.X X.X-X.X X.X          "
1445 		"X........X  -  X.X  -   X.X   - X...XXXXXX.XXXXXX...X -           X.X..X-X..X.X           "
1446 		"X.........X -XXX.XXX-   X.X   -  X..X    X.X    X..X  -            X...X-X...X            "
1447 		"X..........X-X.....X-   X.X   -   X.X    X.X    X.X   -           X....X-X....X           "
1448 		"X......XXXXX-XXXXXXX-   X.X   -    XX    X.X    XX    -          X.....X-X.....X          "
1449 		"X...X..X    ---------   X.X   -          X.X          -          XXXXXXX-XXXXXXX          "
1450 		"X..X X..X   -       -XXXX.XXXX-       XXXX.XXXX       ------------------------------------"
1451 		"X.X  X..X   -       -X.......X-       X.......X       -    XX           XX    -           "
1452 		"XX    X..X  -       - X.....X -        X.....X        -   X.X           X.X   -           "
1453 		"      X..X          -  X...X  -         X...X         -  X..X           X..X  -           "
1454 		"       XX           -   X.X   -          X.X          - X...XXXXXXXXXXXXX...X -           "
1455 		"------------        -    X    -           X           -X.....................X-           "
1456 		"                    ----------------------------------- X...XXXXXXXXXXXXX...X -           "
1457 		"                                                      -  X..X           X..X  -           "
1458 		"                                                      -   X.X           X.X   -           "
1459 		"                                                      -    XX           XX    -           "};
1460 
1461 static const ImVec2 FONT_ATLAS_DEFAULT_TEX_CURSOR_DATA[ImGuiMouseCursor_Count_][3] =
1462 	{
1463 		// Pos ........ Size ......... Offset ......
1464 		{ImVec2(0, 3), ImVec2(12, 19), ImVec2(0, 0)},     // ImGuiMouseCursor_Arrow
1465 		{ImVec2(13, 0), ImVec2(7, 16), ImVec2(4, 8)},     // ImGuiMouseCursor_TextInput
1466 		{ImVec2(31, 0), ImVec2(23, 23), ImVec2(11, 11)},  // ImGuiMouseCursor_ResizeAll
1467 		{ImVec2(21, 0), ImVec2(9, 23), ImVec2(5, 11)},    // ImGuiMouseCursor_ResizeNS
1468 		{ImVec2(55, 18), ImVec2(23, 9), ImVec2(11, 5)},   // ImGuiMouseCursor_ResizeEW
1469 		{ImVec2(73, 0), ImVec2(17, 17), ImVec2(9, 9)},    // ImGuiMouseCursor_ResizeNESW
1470 		{ImVec2(55, 0), ImVec2(17, 17), ImVec2(9, 9)},    // ImGuiMouseCursor_ResizeNWSE
1471 };
1472 
ImFontAtlas()1473 ImFontAtlas::ImFontAtlas()
1474 {
1475 	Flags = 0x00;
1476 	TexID = NULL;
1477 	TexDesiredWidth = 0;
1478 	TexGlyphPadding = 1;
1479 
1480 	TexPixelsAlpha8 = NULL;
1481 	TexPixelsRGBA32 = NULL;
1482 	TexWidth = TexHeight = 0;
1483 	TexUvScale = ImVec2(0.0f, 0.0f);
1484 	TexUvWhitePixel = ImVec2(0.0f, 0.0f);
1485 	for (int n = 0; n < IM_ARRAYSIZE(CustomRectIds); n++)
1486 		CustomRectIds[n] = -1;
1487 }
1488 
~ImFontAtlas()1489 ImFontAtlas::~ImFontAtlas()
1490 {
1491 	Clear();
1492 }
1493 
ClearInputData()1494 void ImFontAtlas::ClearInputData()
1495 {
1496 	for (int i = 0; i < ConfigData.Size; i++)
1497 		if (ConfigData[i].FontData && ConfigData[i].FontDataOwnedByAtlas)
1498 		{
1499 			ImGui::MemFree(ConfigData[i].FontData);
1500 			ConfigData[i].FontData = NULL;
1501 		}
1502 
1503 	// When clearing this we lose access to  the font name and other information used to build the font.
1504 	for (int i = 0; i < Fonts.Size; i++)
1505 		if (Fonts[i]->ConfigData >= ConfigData.Data && Fonts[i]->ConfigData < ConfigData.Data + ConfigData.Size)
1506 		{
1507 			Fonts[i]->ConfigData = NULL;
1508 			Fonts[i]->ConfigDataCount = 0;
1509 		}
1510 	ConfigData.clear();
1511 	CustomRects.clear();
1512 	for (int n = 0; n < IM_ARRAYSIZE(CustomRectIds); n++)
1513 		CustomRectIds[n] = -1;
1514 }
1515 
ClearTexData()1516 void ImFontAtlas::ClearTexData()
1517 {
1518 	if (TexPixelsAlpha8)
1519 		ImGui::MemFree(TexPixelsAlpha8);
1520 	if (TexPixelsRGBA32)
1521 		ImGui::MemFree(TexPixelsRGBA32);
1522 	TexPixelsAlpha8 = NULL;
1523 	TexPixelsRGBA32 = NULL;
1524 }
1525 
ClearFonts()1526 void ImFontAtlas::ClearFonts()
1527 {
1528 	for (int i = 0; i < Fonts.Size; i++)
1529 		IM_DELETE(Fonts[i]);
1530 	Fonts.clear();
1531 }
1532 
Clear()1533 void ImFontAtlas::Clear()
1534 {
1535 	ClearInputData();
1536 	ClearTexData();
1537 	ClearFonts();
1538 }
1539 
GetTexDataAsAlpha8(unsigned char ** out_pixels,int * out_width,int * out_height,int * out_bytes_per_pixel)1540 void ImFontAtlas::GetTexDataAsAlpha8(unsigned char** out_pixels, int* out_width, int* out_height, int* out_bytes_per_pixel)
1541 {
1542 	// Build atlas on demand
1543 	if (TexPixelsAlpha8 == NULL)
1544 	{
1545 		if (ConfigData.empty())
1546 			AddFontDefault();
1547 		Build();
1548 	}
1549 
1550 	*out_pixels = TexPixelsAlpha8;
1551 	if (out_width) *out_width = TexWidth;
1552 	if (out_height) *out_height = TexHeight;
1553 	if (out_bytes_per_pixel) *out_bytes_per_pixel = 1;
1554 }
1555 
GetTexDataAsRGBA32(unsigned char ** out_pixels,int * out_width,int * out_height,int * out_bytes_per_pixel)1556 void ImFontAtlas::GetTexDataAsRGBA32(unsigned char** out_pixels, int* out_width, int* out_height, int* out_bytes_per_pixel)
1557 {
1558 	// Convert to RGBA32 format on demand
1559 	// Although it is likely to be the most commonly used format, our font rendering is 1 channel / 8 bpp
1560 	if (!TexPixelsRGBA32)
1561 	{
1562 		unsigned char* pixels = NULL;
1563 		GetTexDataAsAlpha8(&pixels, NULL, NULL);
1564 		if (pixels)
1565 		{
1566 			TexPixelsRGBA32 = (unsigned int*)ImGui::MemAlloc((size_t)(TexWidth * TexHeight * 4));
1567 			const unsigned char* src = pixels;
1568 			unsigned int* dst = TexPixelsRGBA32;
1569 			for (int n = TexWidth * TexHeight; n > 0; n--)
1570 				*dst++ = IM_COL32(255, 255, 255, (unsigned int)(*src++));
1571 		}
1572 	}
1573 
1574 	*out_pixels = (unsigned char*)TexPixelsRGBA32;
1575 	if (out_width) *out_width = TexWidth;
1576 	if (out_height) *out_height = TexHeight;
1577 	if (out_bytes_per_pixel) *out_bytes_per_pixel = 4;
1578 }
1579 
AddFont(const ImFontConfig * font_cfg)1580 ImFont* ImFontAtlas::AddFont(const ImFontConfig* font_cfg)
1581 {
1582 	IM_ASSERT(font_cfg->FontData != NULL && font_cfg->FontDataSize > 0);
1583 	IM_ASSERT(font_cfg->SizePixels > 0.0f);
1584 
1585 	// Create new font
1586 	if (!font_cfg->MergeMode)
1587 		Fonts.push_back(IM_NEW(ImFont));
1588 	else
1589 		IM_ASSERT(!Fonts.empty());  // When using MergeMode make sure that a font has already been added before. You can use ImGui::GetIO().Fonts->AddFontDefault() to add the default imgui font.
1590 
1591 	ConfigData.push_back(*font_cfg);
1592 	ImFontConfig& new_font_cfg = ConfigData.back();
1593 	if (!new_font_cfg.DstFont)
1594 		new_font_cfg.DstFont = Fonts.back();
1595 	if (!new_font_cfg.FontDataOwnedByAtlas)
1596 	{
1597 		new_font_cfg.FontData = ImGui::MemAlloc(new_font_cfg.FontDataSize);
1598 		new_font_cfg.FontDataOwnedByAtlas = true;
1599 		memcpy(new_font_cfg.FontData, font_cfg->FontData, (size_t)new_font_cfg.FontDataSize);
1600 	}
1601 
1602 	// Invalidate texture
1603 	ClearTexData();
1604 	return new_font_cfg.DstFont;
1605 }
1606 
1607 // Default font TTF is compressed with stb_compress then base85 encoded (see misc/fonts/binary_to_compressed_c.cpp for encoder)
1608 static unsigned int stb_decompress_length(unsigned char* input);
1609 static unsigned int stb_decompress(unsigned char* output, unsigned char* i, unsigned int length);
1610 static const char* GetDefaultCompressedFontDataTTFBase85();
Decode85Byte(char c)1611 static unsigned int Decode85Byte(char c) { return c >= '\\' ? c - 36 : c - 35; }
Decode85(const unsigned char * src,unsigned char * dst)1612 static void Decode85(const unsigned char* src, unsigned char* dst)
1613 {
1614 	while (*src)
1615 	{
1616 		unsigned int tmp = Decode85Byte(src[0]) + 85 * (Decode85Byte(src[1]) + 85 * (Decode85Byte(src[2]) + 85 * (Decode85Byte(src[3]) + 85 * Decode85Byte(src[4]))));
1617 		dst[0] = ((tmp >> 0) & 0xFF);
1618 		dst[1] = ((tmp >> 8) & 0xFF);
1619 		dst[2] = ((tmp >> 16) & 0xFF);
1620 		dst[3] = ((tmp >> 24) & 0xFF);  // We can't assume little-endianness.
1621 		src += 5;
1622 		dst += 4;
1623 	}
1624 }
1625 
1626 // Load embedded ProggyClean.ttf at size 13, disable oversampling
AddFontDefault(const ImFontConfig * font_cfg_template)1627 ImFont* ImFontAtlas::AddFontDefault(const ImFontConfig* font_cfg_template)
1628 {
1629 	ImFontConfig font_cfg = font_cfg_template ? *font_cfg_template : ImFontConfig();
1630 	if (!font_cfg_template)
1631 	{
1632 		font_cfg.OversampleH = font_cfg.OversampleV = 1;
1633 		font_cfg.PixelSnapH = true;
1634 	}
1635 	if (font_cfg.Name[0] == '\0') strcpy(font_cfg.Name, "ProggyClean.ttf, 13px");
1636 	if (font_cfg.SizePixels <= 0.0f) font_cfg.SizePixels = 13.0f;
1637 
1638 	const char* ttf_compressed_base85 = GetDefaultCompressedFontDataTTFBase85();
1639 	ImFont* font = AddFontFromMemoryCompressedBase85TTF(ttf_compressed_base85, font_cfg.SizePixels, &font_cfg, GetGlyphRangesDefault());
1640 	return font;
1641 }
1642 
AddFontFromFileTTF(const char * filename,float size_pixels,const ImFontConfig * font_cfg_template,const ImWchar * glyph_ranges)1643 ImFont* ImFontAtlas::AddFontFromFileTTF(const char* filename, float size_pixels, const ImFontConfig* font_cfg_template, const ImWchar* glyph_ranges)
1644 {
1645 	int data_size = 0;
1646 	void* data = ImFileLoadToMemory(filename, "rb", &data_size, 0);
1647 	if (!data)
1648 	{
1649 		IM_ASSERT(0);  // Could not load file.
1650 		return NULL;
1651 	}
1652 	ImFontConfig font_cfg = font_cfg_template ? *font_cfg_template : ImFontConfig();
1653 	if (font_cfg.Name[0] == '\0')
1654 	{
1655 		// Store a short copy of filename into into the font name for convenience
1656 		const char* p;
1657 		for (p = filename + strlen(filename); p > filename && p[-1] != '/' && p[-1] != '\\'; p--)
1658 		{
1659 		}
1660 		snprintf(font_cfg.Name, IM_ARRAYSIZE(font_cfg.Name), "%s, %.0fpx", p, size_pixels);
1661 	}
1662 	return AddFontFromMemoryTTF(data, data_size, size_pixels, &font_cfg, glyph_ranges);
1663 }
1664 
1665 // NB: Transfer ownership of 'ttf_data' to ImFontAtlas, unless font_cfg_template->FontDataOwnedByAtlas == false. Owned TTF buffer will be deleted after Build().
AddFontFromMemoryTTF(void * ttf_data,int ttf_size,float size_pixels,const ImFontConfig * font_cfg_template,const ImWchar * glyph_ranges)1666 ImFont* ImFontAtlas::AddFontFromMemoryTTF(void* ttf_data, int ttf_size, float size_pixels, const ImFontConfig* font_cfg_template, const ImWchar* glyph_ranges)
1667 {
1668 	ImFontConfig font_cfg = font_cfg_template ? *font_cfg_template : ImFontConfig();
1669 	IM_ASSERT(font_cfg.FontData == NULL);
1670 	font_cfg.FontData = ttf_data;
1671 	font_cfg.FontDataSize = ttf_size;
1672 	font_cfg.SizePixels = size_pixels;
1673 	if (glyph_ranges)
1674 		font_cfg.GlyphRanges = glyph_ranges;
1675 	return AddFont(&font_cfg);
1676 }
1677 
AddFontFromMemoryCompressedTTF(const void * compressed_ttf_data,int compressed_ttf_size,float size_pixels,const ImFontConfig * font_cfg_template,const ImWchar * glyph_ranges)1678 ImFont* ImFontAtlas::AddFontFromMemoryCompressedTTF(const void* compressed_ttf_data, int compressed_ttf_size, float size_pixels, const ImFontConfig* font_cfg_template, const ImWchar* glyph_ranges)
1679 {
1680 	const unsigned int buf_decompressed_size = stb_decompress_length((unsigned char*)compressed_ttf_data);
1681 	unsigned char* buf_decompressed_data = (unsigned char*)ImGui::MemAlloc(buf_decompressed_size);
1682 	stb_decompress(buf_decompressed_data, (unsigned char*)compressed_ttf_data, (unsigned int)compressed_ttf_size);
1683 
1684 	ImFontConfig font_cfg = font_cfg_template ? *font_cfg_template : ImFontConfig();
1685 	IM_ASSERT(font_cfg.FontData == NULL);
1686 	font_cfg.FontDataOwnedByAtlas = true;
1687 	return AddFontFromMemoryTTF(buf_decompressed_data, (int)buf_decompressed_size, size_pixels, &font_cfg, glyph_ranges);
1688 }
1689 
AddFontFromMemoryCompressedBase85TTF(const char * compressed_ttf_data_base85,float size_pixels,const ImFontConfig * font_cfg,const ImWchar * glyph_ranges)1690 ImFont* ImFontAtlas::AddFontFromMemoryCompressedBase85TTF(const char* compressed_ttf_data_base85, float size_pixels, const ImFontConfig* font_cfg, const ImWchar* glyph_ranges)
1691 {
1692 	int compressed_ttf_size = (((int)strlen(compressed_ttf_data_base85) + 4) / 5) * 4;
1693 	void* compressed_ttf = ImGui::MemAlloc((size_t)compressed_ttf_size);
1694 	Decode85((const unsigned char*)compressed_ttf_data_base85, (unsigned char*)compressed_ttf);
1695 	ImFont* font = AddFontFromMemoryCompressedTTF(compressed_ttf, compressed_ttf_size, size_pixels, font_cfg, glyph_ranges);
1696 	ImGui::MemFree(compressed_ttf);
1697 	return font;
1698 }
1699 
AddCustomRectRegular(unsigned int id,int width,int height)1700 int ImFontAtlas::AddCustomRectRegular(unsigned int id, int width, int height)
1701 {
1702 	IM_ASSERT(id >= 0x10000);
1703 	IM_ASSERT(width > 0 && width <= 0xFFFF);
1704 	IM_ASSERT(height > 0 && height <= 0xFFFF);
1705 	CustomRect r;
1706 	r.ID = id;
1707 	r.Width = (unsigned short)width;
1708 	r.Height = (unsigned short)height;
1709 	CustomRects.push_back(r);
1710 	return CustomRects.Size - 1;  // Return index
1711 }
1712 
AddCustomRectFontGlyph(ImFont * font,ImWchar id,int width,int height,float advance_x,const ImVec2 & offset)1713 int ImFontAtlas::AddCustomRectFontGlyph(ImFont* font, ImWchar id, int width, int height, float advance_x, const ImVec2& offset)
1714 {
1715 	IM_ASSERT(font != NULL);
1716 	IM_ASSERT(width > 0 && width <= 0xFFFF);
1717 	IM_ASSERT(height > 0 && height <= 0xFFFF);
1718 	CustomRect r;
1719 	r.ID = id;
1720 	r.Width = (unsigned short)width;
1721 	r.Height = (unsigned short)height;
1722 	r.GlyphAdvanceX = advance_x;
1723 	r.GlyphOffset = offset;
1724 	r.Font = font;
1725 	CustomRects.push_back(r);
1726 	return CustomRects.Size - 1;  // Return index
1727 }
1728 
CalcCustomRectUV(const CustomRect * rect,ImVec2 * out_uv_min,ImVec2 * out_uv_max)1729 void ImFontAtlas::CalcCustomRectUV(const CustomRect* rect, ImVec2* out_uv_min, ImVec2* out_uv_max)
1730 {
1731 	IM_ASSERT(TexWidth > 0 && TexHeight > 0);  // Font atlas needs to be built before we can calculate UV coordinates
1732 	IM_ASSERT(rect->IsPacked());               // Make sure the rectangle has been packed
1733 	*out_uv_min = ImVec2((float)rect->X * TexUvScale.x, (float)rect->Y * TexUvScale.y);
1734 	*out_uv_max = ImVec2((float)(rect->X + rect->Width) * TexUvScale.x, (float)(rect->Y + rect->Height) * TexUvScale.y);
1735 }
1736 
GetMouseCursorTexData(ImGuiMouseCursor cursor_type,ImVec2 * out_offset,ImVec2 * out_size,ImVec2 out_uv_border[2],ImVec2 out_uv_fill[2])1737 bool ImFontAtlas::GetMouseCursorTexData(ImGuiMouseCursor cursor_type, ImVec2* out_offset, ImVec2* out_size, ImVec2 out_uv_border[2], ImVec2 out_uv_fill[2])
1738 {
1739 	if (cursor_type <= ImGuiMouseCursor_None || cursor_type >= ImGuiMouseCursor_Count_)
1740 		return false;
1741 	if (Flags & ImFontAtlasFlags_NoMouseCursors)
1742 		return false;
1743 
1744 	ImFontAtlas::CustomRect& r = CustomRects[CustomRectIds[0]];
1745 	IM_ASSERT(r.ID == FONT_ATLAS_DEFAULT_TEX_DATA_ID);
1746 	ImVec2 pos = FONT_ATLAS_DEFAULT_TEX_CURSOR_DATA[cursor_type][0] + ImVec2((float)r.X, (float)r.Y);
1747 	ImVec2 size = FONT_ATLAS_DEFAULT_TEX_CURSOR_DATA[cursor_type][1];
1748 	*out_size = size;
1749 	*out_offset = FONT_ATLAS_DEFAULT_TEX_CURSOR_DATA[cursor_type][2];
1750 	out_uv_border[0] = (pos)*TexUvScale;
1751 	out_uv_border[1] = (pos + size) * TexUvScale;
1752 	pos.x += FONT_ATLAS_DEFAULT_TEX_DATA_W_HALF + 1;
1753 	out_uv_fill[0] = (pos)*TexUvScale;
1754 	out_uv_fill[1] = (pos + size) * TexUvScale;
1755 	return true;
1756 }
1757 
Build()1758 bool ImFontAtlas::Build()
1759 {
1760 	return ImFontAtlasBuildWithStbTruetype(this);
1761 }
1762 
ImFontAtlasBuildMultiplyCalcLookupTable(unsigned char out_table[256],float in_brighten_factor)1763 void ImFontAtlasBuildMultiplyCalcLookupTable(unsigned char out_table[256], float in_brighten_factor)
1764 {
1765 	for (unsigned int i = 0; i < 256; i++)
1766 	{
1767 		unsigned int value = (unsigned int)(i * in_brighten_factor);
1768 		out_table[i] = value > 255 ? 255 : (value & 0xFF);
1769 	}
1770 }
1771 
ImFontAtlasBuildMultiplyRectAlpha8(const unsigned char table[256],unsigned char * pixels,int x,int y,int w,int h,int stride)1772 void ImFontAtlasBuildMultiplyRectAlpha8(const unsigned char table[256], unsigned char* pixels, int x, int y, int w, int h, int stride)
1773 {
1774 	unsigned char* data = pixels + x + y * stride;
1775 	for (int j = h; j > 0; j--, data += stride)
1776 		for (int i = 0; i < w; i++)
1777 			data[i] = table[data[i]];
1778 }
1779 
ImFontAtlasBuildWithStbTruetype(ImFontAtlas * atlas)1780 bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas)
1781 {
1782 	IM_ASSERT(atlas->ConfigData.Size > 0);
1783 
1784 	ImFontAtlasBuildRegisterDefaultCustomRects(atlas);
1785 
1786 	atlas->TexID = NULL;
1787 	atlas->TexWidth = atlas->TexHeight = 0;
1788 	atlas->TexUvScale = ImVec2(0.0f, 0.0f);
1789 	atlas->TexUvWhitePixel = ImVec2(0.0f, 0.0f);
1790 	atlas->ClearTexData();
1791 
1792 	// Count glyphs/ranges
1793 	int total_glyphs_count = 0;
1794 	int total_ranges_count = 0;
1795 	for (int input_i = 0; input_i < atlas->ConfigData.Size; input_i++)
1796 	{
1797 		ImFontConfig& cfg = atlas->ConfigData[input_i];
1798 		if (!cfg.GlyphRanges)
1799 			cfg.GlyphRanges = atlas->GetGlyphRangesDefault();
1800 		for (const ImWchar* in_range = cfg.GlyphRanges; in_range[0] && in_range[1]; in_range += 2, total_ranges_count++)
1801 			total_glyphs_count += (in_range[1] - in_range[0]) + 1;
1802 	}
1803 
1804 	// We need a width for the skyline algorithm. Using a dumb heuristic here to decide of width. User can override TexDesiredWidth and TexGlyphPadding if they wish.
1805 	// Width doesn't really matter much, but some API/GPU have texture size limitations and increasing width can decrease height.
1806 	atlas->TexWidth = (atlas->TexDesiredWidth > 0) ? atlas->TexDesiredWidth : (total_glyphs_count > 4000) ? 4096 : (total_glyphs_count > 2000) ? 2048 : (total_glyphs_count > 1000) ? 1024 : 512;
1807 	atlas->TexHeight = 0;
1808 
1809 	// Start packing
1810 	const int max_tex_height = 1024 * 32;
1811 	stbtt_pack_context spc = {};
1812 	if (!stbtt_PackBegin(&spc, NULL, atlas->TexWidth, max_tex_height, 0, atlas->TexGlyphPadding, NULL))
1813 		return false;
1814 	stbtt_PackSetOversampling(&spc, 1, 1);
1815 
1816 	// Pack our extra data rectangles first, so it will be on the upper-left corner of our texture (UV will have small values).
1817 	ImFontAtlasBuildPackCustomRects(atlas, spc.pack_info);
1818 
1819 	// Initialize font information (so we can error without any cleanup)
1820 	struct ImFontTempBuildData
1821 	{
1822 		stbtt_fontinfo FontInfo;
1823 		stbrp_rect* Rects;
1824 		int RectsCount;
1825 		stbtt_pack_range* Ranges;
1826 		int RangesCount;
1827 	};
1828 	ImFontTempBuildData* tmp_array = (ImFontTempBuildData*)ImGui::MemAlloc((size_t)atlas->ConfigData.Size * sizeof(ImFontTempBuildData));
1829 	for (int input_i = 0; input_i < atlas->ConfigData.Size; input_i++)
1830 	{
1831 		ImFontConfig& cfg = atlas->ConfigData[input_i];
1832 		ImFontTempBuildData& tmp = tmp_array[input_i];
1833 		IM_ASSERT(cfg.DstFont && (!cfg.DstFont->IsLoaded() || cfg.DstFont->ContainerAtlas == atlas));
1834 
1835 		const int font_offset = stbtt_GetFontOffsetForIndex((unsigned char*)cfg.FontData, cfg.FontNo);
1836 		IM_ASSERT(font_offset >= 0);
1837 		if (!stbtt_InitFont(&tmp.FontInfo, (unsigned char*)cfg.FontData, font_offset))
1838 		{
1839 			atlas->TexWidth = atlas->TexHeight = 0;  // Reset output on failure
1840 			ImGui::MemFree(tmp_array);
1841 			return false;
1842 		}
1843 	}
1844 
1845 	// Allocate packing character data and flag packed characters buffer as non-packed (x0=y0=x1=y1=0)
1846 	int buf_packedchars_n = 0, buf_rects_n = 0, buf_ranges_n = 0;
1847 	stbtt_packedchar* buf_packedchars = (stbtt_packedchar*)ImGui::MemAlloc(total_glyphs_count * sizeof(stbtt_packedchar));
1848 	stbrp_rect* buf_rects = (stbrp_rect*)ImGui::MemAlloc(total_glyphs_count * sizeof(stbrp_rect));
1849 	stbtt_pack_range* buf_ranges = (stbtt_pack_range*)ImGui::MemAlloc(total_ranges_count * sizeof(stbtt_pack_range));
1850 	memset(buf_packedchars, 0, total_glyphs_count * sizeof(stbtt_packedchar));
1851 	memset(buf_rects, 0, total_glyphs_count * sizeof(stbrp_rect));  // Unnecessary but let's clear this for the sake of sanity.
1852 	memset(buf_ranges, 0, total_ranges_count * sizeof(stbtt_pack_range));
1853 
1854 	// First font pass: pack all glyphs (no rendering at this point, we are working with rectangles in an infinitely tall texture at this point)
1855 	for (int input_i = 0; input_i < atlas->ConfigData.Size; input_i++)
1856 	{
1857 		ImFontConfig& cfg = atlas->ConfigData[input_i];
1858 		ImFontTempBuildData& tmp = tmp_array[input_i];
1859 
1860 		// Setup ranges
1861 		int font_glyphs_count = 0;
1862 		int font_ranges_count = 0;
1863 		for (const ImWchar* in_range = cfg.GlyphRanges; in_range[0] && in_range[1]; in_range += 2, font_ranges_count++)
1864 			font_glyphs_count += (in_range[1] - in_range[0]) + 1;
1865 		tmp.Ranges = buf_ranges + buf_ranges_n;
1866 		tmp.RangesCount = font_ranges_count;
1867 		buf_ranges_n += font_ranges_count;
1868 		for (int i = 0; i < font_ranges_count; i++)
1869 		{
1870 			const ImWchar* in_range = &cfg.GlyphRanges[i * 2];
1871 			stbtt_pack_range& range = tmp.Ranges[i];
1872 			range.font_size = cfg.SizePixels;
1873 			range.first_unicode_codepoint_in_range = in_range[0];
1874 			range.num_chars = (in_range[1] - in_range[0]) + 1;
1875 			range.chardata_for_range = buf_packedchars + buf_packedchars_n;
1876 			buf_packedchars_n += range.num_chars;
1877 		}
1878 
1879 		// Pack
1880 		tmp.Rects = buf_rects + buf_rects_n;
1881 		tmp.RectsCount = font_glyphs_count;
1882 		buf_rects_n += font_glyphs_count;
1883 		stbtt_PackSetOversampling(&spc, cfg.OversampleH, cfg.OversampleV);
1884 		int n = stbtt_PackFontRangesGatherRects(&spc, &tmp.FontInfo, tmp.Ranges, tmp.RangesCount, tmp.Rects);
1885 		IM_ASSERT(n == font_glyphs_count);
1886 		stbrp_pack_rects((stbrp_context*)spc.pack_info, tmp.Rects, n);
1887 
1888 		// Extend texture height
1889 		for (int i = 0; i < n; i++)
1890 			if (tmp.Rects[i].was_packed)
1891 				atlas->TexHeight = ImMax(atlas->TexHeight, tmp.Rects[i].y + tmp.Rects[i].h);
1892 	}
1893 	IM_ASSERT(buf_rects_n == total_glyphs_count);
1894 	IM_ASSERT(buf_packedchars_n == total_glyphs_count);
1895 	IM_ASSERT(buf_ranges_n == total_ranges_count);
1896 
1897 	// Create texture
1898 	atlas->TexHeight = (atlas->Flags & ImFontAtlasFlags_NoPowerOfTwoHeight) ? (atlas->TexHeight + 1) : ImUpperPowerOfTwo(atlas->TexHeight);
1899 	atlas->TexUvScale = ImVec2(1.0f / atlas->TexWidth, 1.0f / atlas->TexHeight);
1900 	atlas->TexPixelsAlpha8 = (unsigned char*)ImGui::MemAlloc(atlas->TexWidth * atlas->TexHeight);
1901 	memset(atlas->TexPixelsAlpha8, 0, atlas->TexWidth * atlas->TexHeight);
1902 	spc.pixels = atlas->TexPixelsAlpha8;
1903 	spc.height = atlas->TexHeight;
1904 
1905 	// Second pass: render font characters
1906 	for (int input_i = 0; input_i < atlas->ConfigData.Size; input_i++)
1907 	{
1908 		ImFontConfig& cfg = atlas->ConfigData[input_i];
1909 		ImFontTempBuildData& tmp = tmp_array[input_i];
1910 		stbtt_PackSetOversampling(&spc, cfg.OversampleH, cfg.OversampleV);
1911 		stbtt_PackFontRangesRenderIntoRects(&spc, &tmp.FontInfo, tmp.Ranges, tmp.RangesCount, tmp.Rects);
1912 		if (cfg.RasterizerMultiply != 1.0f)
1913 		{
1914 			unsigned char multiply_table[256];
1915 			ImFontAtlasBuildMultiplyCalcLookupTable(multiply_table, cfg.RasterizerMultiply);
1916 			for (const stbrp_rect* r = tmp.Rects; r != tmp.Rects + tmp.RectsCount; r++)
1917 				if (r->was_packed)
1918 					ImFontAtlasBuildMultiplyRectAlpha8(multiply_table, spc.pixels, r->x, r->y, r->w, r->h, spc.stride_in_bytes);
1919 		}
1920 		tmp.Rects = NULL;
1921 	}
1922 
1923 	// End packing
1924 	stbtt_PackEnd(&spc);
1925 	ImGui::MemFree(buf_rects);
1926 	buf_rects = NULL;
1927 
1928 	// Third pass: setup ImFont and glyphs for runtime
1929 	for (int input_i = 0; input_i < atlas->ConfigData.Size; input_i++)
1930 	{
1931 		ImFontConfig& cfg = atlas->ConfigData[input_i];
1932 		ImFontTempBuildData& tmp = tmp_array[input_i];
1933 		ImFont* dst_font = cfg.DstFont;  // We can have multiple input fonts writing into a same destination font (when using MergeMode=true)
1934 
1935 		const float font_scale = stbtt_ScaleForPixelHeight(&tmp.FontInfo, cfg.SizePixels);
1936 		int unscaled_ascent, unscaled_descent, unscaled_line_gap;
1937 		stbtt_GetFontVMetrics(&tmp.FontInfo, &unscaled_ascent, &unscaled_descent, &unscaled_line_gap);
1938 
1939 		const float ascent = unscaled_ascent * font_scale;
1940 		const float descent = unscaled_descent * font_scale;
1941 		ImFontAtlasBuildSetupFont(atlas, dst_font, &cfg, ascent, descent);
1942 		const float off_x = cfg.GlyphOffset.x;
1943 		const float off_y = cfg.GlyphOffset.y + (float)(int)(dst_font->Ascent + 0.5f);
1944 
1945 		for (int i = 0; i < tmp.RangesCount; i++)
1946 		{
1947 			stbtt_pack_range& range = tmp.Ranges[i];
1948 			for (int char_idx = 0; char_idx < range.num_chars; char_idx += 1)
1949 			{
1950 				const stbtt_packedchar& pc = range.chardata_for_range[char_idx];
1951 				if (!pc.x0 && !pc.x1 && !pc.y0 && !pc.y1)
1952 					continue;
1953 
1954 				const int codepoint = range.first_unicode_codepoint_in_range + char_idx;
1955 				if (cfg.MergeMode && dst_font->FindGlyph((unsigned short)codepoint))
1956 					continue;
1957 
1958 				stbtt_aligned_quad q;
1959 				float dummy_x = 0.0f, dummy_y = 0.0f;
1960 				stbtt_GetPackedQuad(range.chardata_for_range, atlas->TexWidth, atlas->TexHeight, char_idx, &dummy_x, &dummy_y, &q, 0);
1961 				dst_font->AddGlyph((ImWchar)codepoint, q.x0 + off_x, q.y0 + off_y, q.x1 + off_x, q.y1 + off_y, q.s0, q.t0, q.s1, q.t1, pc.xadvance);
1962 			}
1963 		}
1964 	}
1965 
1966 	// Cleanup temporaries
1967 	ImGui::MemFree(buf_packedchars);
1968 	ImGui::MemFree(buf_ranges);
1969 	ImGui::MemFree(tmp_array);
1970 
1971 	ImFontAtlasBuildFinish(atlas);
1972 
1973 	return true;
1974 }
1975 
ImFontAtlasBuildRegisterDefaultCustomRects(ImFontAtlas * atlas)1976 void ImFontAtlasBuildRegisterDefaultCustomRects(ImFontAtlas* atlas)
1977 {
1978 	if (atlas->CustomRectIds[0] >= 0)
1979 		return;
1980 	if (!(atlas->Flags & ImFontAtlasFlags_NoMouseCursors))
1981 		atlas->CustomRectIds[0] = atlas->AddCustomRectRegular(FONT_ATLAS_DEFAULT_TEX_DATA_ID, FONT_ATLAS_DEFAULT_TEX_DATA_W_HALF * 2 + 1, FONT_ATLAS_DEFAULT_TEX_DATA_H);
1982 	else
1983 		atlas->CustomRectIds[0] = atlas->AddCustomRectRegular(FONT_ATLAS_DEFAULT_TEX_DATA_ID, 2, 2);
1984 }
1985 
ImFontAtlasBuildSetupFont(ImFontAtlas * atlas,ImFont * font,ImFontConfig * font_config,float ascent,float descent)1986 void ImFontAtlasBuildSetupFont(ImFontAtlas* atlas, ImFont* font, ImFontConfig* font_config, float ascent, float descent)
1987 {
1988 	if (!font_config->MergeMode)
1989 	{
1990 		font->ClearOutputData();
1991 		font->FontSize = font_config->SizePixels;
1992 		font->ConfigData = font_config;
1993 		font->ContainerAtlas = atlas;
1994 		font->Ascent = ascent;
1995 		font->Descent = descent;
1996 	}
1997 	font->ConfigDataCount++;
1998 }
1999 
ImFontAtlasBuildPackCustomRects(ImFontAtlas * atlas,void * pack_context_opaque)2000 void ImFontAtlasBuildPackCustomRects(ImFontAtlas* atlas, void* pack_context_opaque)
2001 {
2002 	stbrp_context* pack_context = (stbrp_context*)pack_context_opaque;
2003 
2004 	ImVector<ImFontAtlas::CustomRect>& user_rects = atlas->CustomRects;
2005 	IM_ASSERT(user_rects.Size >= 1);  // We expect at least the default custom rects to be registered, else something went wrong.
2006 
2007 	ImVector<stbrp_rect> pack_rects;
2008 	pack_rects.resize(user_rects.Size);
2009 	memset(pack_rects.Data, 0, sizeof(stbrp_rect) * user_rects.Size);
2010 	for (int i = 0; i < user_rects.Size; i++)
2011 	{
2012 		pack_rects[i].w = user_rects[i].Width;
2013 		pack_rects[i].h = user_rects[i].Height;
2014 	}
2015 	stbrp_pack_rects(pack_context, &pack_rects[0], pack_rects.Size);
2016 	for (int i = 0; i < pack_rects.Size; i++)
2017 		if (pack_rects[i].was_packed)
2018 		{
2019 			user_rects[i].X = pack_rects[i].x;
2020 			user_rects[i].Y = pack_rects[i].y;
2021 			IM_ASSERT(pack_rects[i].w == user_rects[i].Width && pack_rects[i].h == user_rects[i].Height);
2022 			atlas->TexHeight = ImMax(atlas->TexHeight, pack_rects[i].y + pack_rects[i].h);
2023 		}
2024 }
2025 
ImFontAtlasBuildRenderDefaultTexData(ImFontAtlas * atlas)2026 static void ImFontAtlasBuildRenderDefaultTexData(ImFontAtlas* atlas)
2027 {
2028 	IM_ASSERT(atlas->CustomRectIds[0] >= 0);
2029 	IM_ASSERT(atlas->TexPixelsAlpha8 != NULL);
2030 	ImFontAtlas::CustomRect& r = atlas->CustomRects[atlas->CustomRectIds[0]];
2031 	IM_ASSERT(r.ID == FONT_ATLAS_DEFAULT_TEX_DATA_ID);
2032 	IM_ASSERT(r.IsPacked());
2033 
2034 	const int w = atlas->TexWidth;
2035 	if (!(atlas->Flags & ImFontAtlasFlags_NoMouseCursors))
2036 	{
2037 		// Render/copy pixels
2038 		IM_ASSERT(r.Width == FONT_ATLAS_DEFAULT_TEX_DATA_W_HALF * 2 + 1 && r.Height == FONT_ATLAS_DEFAULT_TEX_DATA_H);
2039 		for (int y = 0, n = 0; y < FONT_ATLAS_DEFAULT_TEX_DATA_H; y++)
2040 			for (int x = 0; x < FONT_ATLAS_DEFAULT_TEX_DATA_W_HALF; x++, n++)
2041 			{
2042 				const int offset0 = (int)(r.X + x) + (int)(r.Y + y) * w;
2043 				const int offset1 = offset0 + FONT_ATLAS_DEFAULT_TEX_DATA_W_HALF + 1;
2044 				atlas->TexPixelsAlpha8[offset0] = FONT_ATLAS_DEFAULT_TEX_DATA_PIXELS[n] == '.' ? 0xFF : 0x00;
2045 				atlas->TexPixelsAlpha8[offset1] = FONT_ATLAS_DEFAULT_TEX_DATA_PIXELS[n] == 'X' ? 0xFF : 0x00;
2046 			}
2047 	}
2048 	else
2049 	{
2050 		IM_ASSERT(r.Width == 2 && r.Height == 2);
2051 		const int offset = (int)(r.X) + (int)(r.Y) * w;
2052 		atlas->TexPixelsAlpha8[offset] = atlas->TexPixelsAlpha8[offset + 1] = atlas->TexPixelsAlpha8[offset + w] = atlas->TexPixelsAlpha8[offset + w + 1] = 0xFF;
2053 	}
2054 	atlas->TexUvWhitePixel = ImVec2((r.X + 0.5f) * atlas->TexUvScale.x, (r.Y + 0.5f) * atlas->TexUvScale.y);
2055 }
2056 
ImFontAtlasBuildFinish(ImFontAtlas * atlas)2057 void ImFontAtlasBuildFinish(ImFontAtlas* atlas)
2058 {
2059 	// Render into our custom data block
2060 	ImFontAtlasBuildRenderDefaultTexData(atlas);
2061 
2062 	// Register custom rectangle glyphs
2063 	for (int i = 0; i < atlas->CustomRects.Size; i++)
2064 	{
2065 		const ImFontAtlas::CustomRect& r = atlas->CustomRects[i];
2066 		if (r.Font == NULL || r.ID > 0x10000)
2067 			continue;
2068 
2069 		IM_ASSERT(r.Font->ContainerAtlas == atlas);
2070 		ImVec2 uv0, uv1;
2071 		atlas->CalcCustomRectUV(&r, &uv0, &uv1);
2072 		r.Font->AddGlyph((ImWchar)r.ID, 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);
2073 	}
2074 
2075 	// Build all fonts lookup tables
2076 	for (int i = 0; i < atlas->Fonts.Size; i++)
2077 		atlas->Fonts[i]->BuildLookupTable();
2078 }
2079 
2080 // Retrieve list of range (2 int per range, values are inclusive)
GetGlyphRangesDefault()2081 const ImWchar* ImFontAtlas::GetGlyphRangesDefault()
2082 {
2083 	static const ImWchar ranges[] =
2084 		{
2085 			0x0020,
2086 			0x00FF,  // Basic Latin + Latin Supplement
2087 			0,
2088 		};
2089 	return &ranges[0];
2090 }
2091 
GetGlyphRangesKorean()2092 const ImWchar* ImFontAtlas::GetGlyphRangesKorean()
2093 {
2094 	static const ImWchar ranges[] =
2095 		{
2096 			0x0020,
2097 			0x00FF,  // Basic Latin + Latin Supplement
2098 			0x3131,
2099 			0x3163,  // Korean alphabets
2100 			0xAC00,
2101 			0xD79D,  // Korean characters
2102 			0,
2103 		};
2104 	return &ranges[0];
2105 }
2106 
GetGlyphRangesChinese()2107 const ImWchar* ImFontAtlas::GetGlyphRangesChinese()
2108 {
2109 	static const ImWchar ranges[] =
2110 		{
2111 			0x0020,
2112 			0x00FF,  // Basic Latin + Latin Supplement
2113 			0x3000,
2114 			0x30FF,  // Punctuations, Hiragana, Katakana
2115 			0x31F0,
2116 			0x31FF,  // Katakana Phonetic Extensions
2117 			0xFF00,
2118 			0xFFEF,  // Half-width characters
2119 			0x4e00,
2120 			0x9FAF,  // CJK Ideograms
2121 			0,
2122 		};
2123 	return &ranges[0];
2124 }
2125 
GetGlyphRangesJapanese()2126 const ImWchar* ImFontAtlas::GetGlyphRangesJapanese()
2127 {
2128 	// Store the 1946 ideograms code points as successive offsets from the initial unicode codepoint 0x4E00. Each offset has an implicit +1.
2129 	// This encoding is designed to helps us reduce the source code size.
2130 	// FIXME: Source a list of the revised 2136 joyo kanji list from 2010 and rebuild this.
2131 	// The current list was sourced from http://theinstructionlimit.com/author/renaudbedardrenaudbedard/page/3
2132 	// Note that you may use ImFontAtlas::GlyphRangesBuilder to create your own ranges, by merging existing ranges or adding new characters.
2133 	static const short offsets_from_0x4E00[] =
2134 		{
2135 			-1,
2136 			0,
2137 			1,
2138 			3,
2139 			0,
2140 			0,
2141 			0,
2142 			0,
2143 			1,
2144 			0,
2145 			5,
2146 			1,
2147 			1,
2148 			0,
2149 			7,
2150 			4,
2151 			6,
2152 			10,
2153 			0,
2154 			1,
2155 			9,
2156 			9,
2157 			7,
2158 			1,
2159 			3,
2160 			19,
2161 			1,
2162 			10,
2163 			7,
2164 			1,
2165 			0,
2166 			1,
2167 			0,
2168 			5,
2169 			1,
2170 			0,
2171 			6,
2172 			4,
2173 			2,
2174 			6,
2175 			0,
2176 			0,
2177 			12,
2178 			6,
2179 			8,
2180 			0,
2181 			3,
2182 			5,
2183 			0,
2184 			1,
2185 			0,
2186 			9,
2187 			0,
2188 			0,
2189 			8,
2190 			1,
2191 			1,
2192 			3,
2193 			4,
2194 			5,
2195 			13,
2196 			0,
2197 			0,
2198 			8,
2199 			2,
2200 			17,
2201 			4,
2202 			3,
2203 			1,
2204 			1,
2205 			9,
2206 			6,
2207 			0,
2208 			0,
2209 			0,
2210 			2,
2211 			1,
2212 			3,
2213 			2,
2214 			22,
2215 			1,
2216 			9,
2217 			11,
2218 			1,
2219 			13,
2220 			1,
2221 			3,
2222 			12,
2223 			0,
2224 			5,
2225 			9,
2226 			2,
2227 			0,
2228 			6,
2229 			12,
2230 			5,
2231 			3,
2232 			12,
2233 			4,
2234 			1,
2235 			2,
2236 			16,
2237 			1,
2238 			1,
2239 			4,
2240 			6,
2241 			5,
2242 			3,
2243 			0,
2244 			6,
2245 			13,
2246 			15,
2247 			5,
2248 			12,
2249 			8,
2250 			14,
2251 			0,
2252 			0,
2253 			6,
2254 			15,
2255 			3,
2256 			6,
2257 			0,
2258 			18,
2259 			8,
2260 			1,
2261 			6,
2262 			14,
2263 			1,
2264 			5,
2265 			4,
2266 			12,
2267 			24,
2268 			3,
2269 			13,
2270 			12,
2271 			10,
2272 			24,
2273 			0,
2274 			0,
2275 			0,
2276 			1,
2277 			0,
2278 			1,
2279 			1,
2280 			2,
2281 			9,
2282 			10,
2283 			2,
2284 			2,
2285 			0,
2286 			0,
2287 			3,
2288 			3,
2289 			1,
2290 			0,
2291 			3,
2292 			8,
2293 			0,
2294 			3,
2295 			2,
2296 			4,
2297 			4,
2298 			1,
2299 			6,
2300 			11,
2301 			10,
2302 			14,
2303 			6,
2304 			15,
2305 			3,
2306 			4,
2307 			15,
2308 			1,
2309 			0,
2310 			0,
2311 			5,
2312 			2,
2313 			2,
2314 			0,
2315 			0,
2316 			1,
2317 			6,
2318 			5,
2319 			5,
2320 			6,
2321 			0,
2322 			3,
2323 			6,
2324 			5,
2325 			0,
2326 			0,
2327 			1,
2328 			0,
2329 			11,
2330 			2,
2331 			2,
2332 			8,
2333 			4,
2334 			7,
2335 			0,
2336 			10,
2337 			0,
2338 			1,
2339 			2,
2340 			17,
2341 			19,
2342 			3,
2343 			0,
2344 			2,
2345 			5,
2346 			0,
2347 			6,
2348 			2,
2349 			4,
2350 			4,
2351 			6,
2352 			1,
2353 			1,
2354 			11,
2355 			2,
2356 			0,
2357 			3,
2358 			1,
2359 			2,
2360 			1,
2361 			2,
2362 			10,
2363 			7,
2364 			6,
2365 			3,
2366 			16,
2367 			0,
2368 			8,
2369 			24,
2370 			0,
2371 			0,
2372 			3,
2373 			1,
2374 			1,
2375 			3,
2376 			0,
2377 			1,
2378 			6,
2379 			0,
2380 			0,
2381 			0,
2382 			2,
2383 			0,
2384 			1,
2385 			5,
2386 			15,
2387 			0,
2388 			1,
2389 			0,
2390 			0,
2391 			2,
2392 			11,
2393 			19,
2394 			1,
2395 			4,
2396 			19,
2397 			7,
2398 			6,
2399 			5,
2400 			1,
2401 			0,
2402 			0,
2403 			0,
2404 			0,
2405 			5,
2406 			1,
2407 			0,
2408 			1,
2409 			9,
2410 			0,
2411 			0,
2412 			5,
2413 			0,
2414 			2,
2415 			0,
2416 			1,
2417 			0,
2418 			3,
2419 			0,
2420 			11,
2421 			3,
2422 			0,
2423 			2,
2424 			0,
2425 			0,
2426 			0,
2427 			0,
2428 			0,
2429 			9,
2430 			3,
2431 			6,
2432 			4,
2433 			12,
2434 			0,
2435 			14,
2436 			0,
2437 			0,
2438 			29,
2439 			10,
2440 			8,
2441 			0,
2442 			14,
2443 			37,
2444 			13,
2445 			0,
2446 			31,
2447 			16,
2448 			19,
2449 			0,
2450 			8,
2451 			30,
2452 			1,
2453 			20,
2454 			8,
2455 			3,
2456 			48,
2457 			21,
2458 			1,
2459 			0,
2460 			12,
2461 			0,
2462 			10,
2463 			44,
2464 			34,
2465 			42,
2466 			54,
2467 			11,
2468 			18,
2469 			82,
2470 			0,
2471 			2,
2472 			1,
2473 			2,
2474 			12,
2475 			1,
2476 			0,
2477 			6,
2478 			2,
2479 			17,
2480 			2,
2481 			12,
2482 			7,
2483 			0,
2484 			7,
2485 			17,
2486 			4,
2487 			2,
2488 			6,
2489 			24,
2490 			23,
2491 			8,
2492 			23,
2493 			39,
2494 			2,
2495 			16,
2496 			23,
2497 			1,
2498 			0,
2499 			5,
2500 			1,
2501 			2,
2502 			15,
2503 			14,
2504 			5,
2505 			6,
2506 			2,
2507 			11,
2508 			0,
2509 			8,
2510 			6,
2511 			2,
2512 			2,
2513 			2,
2514 			14,
2515 			20,
2516 			4,
2517 			15,
2518 			3,
2519 			4,
2520 			11,
2521 			10,
2522 			10,
2523 			2,
2524 			5,
2525 			2,
2526 			1,
2527 			30,
2528 			2,
2529 			1,
2530 			0,
2531 			0,
2532 			22,
2533 			5,
2534 			5,
2535 			0,
2536 			3,
2537 			1,
2538 			5,
2539 			4,
2540 			1,
2541 			0,
2542 			0,
2543 			2,
2544 			2,
2545 			21,
2546 			1,
2547 			5,
2548 			1,
2549 			2,
2550 			16,
2551 			2,
2552 			1,
2553 			3,
2554 			4,
2555 			0,
2556 			8,
2557 			4,
2558 			0,
2559 			0,
2560 			5,
2561 			14,
2562 			11,
2563 			2,
2564 			16,
2565 			1,
2566 			13,
2567 			1,
2568 			7,
2569 			0,
2570 			22,
2571 			15,
2572 			3,
2573 			1,
2574 			22,
2575 			7,
2576 			14,
2577 			22,
2578 			19,
2579 			11,
2580 			24,
2581 			18,
2582 			46,
2583 			10,
2584 			20,
2585 			64,
2586 			45,
2587 			3,
2588 			2,
2589 			0,
2590 			4,
2591 			5,
2592 			0,
2593 			1,
2594 			4,
2595 			25,
2596 			1,
2597 			0,
2598 			0,
2599 			2,
2600 			10,
2601 			0,
2602 			0,
2603 			0,
2604 			1,
2605 			0,
2606 			1,
2607 			2,
2608 			0,
2609 			0,
2610 			9,
2611 			1,
2612 			2,
2613 			0,
2614 			0,
2615 			0,
2616 			2,
2617 			5,
2618 			2,
2619 			1,
2620 			1,
2621 			5,
2622 			5,
2623 			8,
2624 			1,
2625 			1,
2626 			1,
2627 			5,
2628 			1,
2629 			4,
2630 			9,
2631 			1,
2632 			3,
2633 			0,
2634 			1,
2635 			0,
2636 			1,
2637 			1,
2638 			2,
2639 			0,
2640 			0,
2641 			2,
2642 			0,
2643 			1,
2644 			8,
2645 			22,
2646 			8,
2647 			1,
2648 			0,
2649 			0,
2650 			0,
2651 			0,
2652 			4,
2653 			2,
2654 			1,
2655 			0,
2656 			9,
2657 			8,
2658 			5,
2659 			0,
2660 			9,
2661 			1,
2662 			30,
2663 			24,
2664 			2,
2665 			6,
2666 			4,
2667 			39,
2668 			0,
2669 			14,
2670 			5,
2671 			16,
2672 			6,
2673 			26,
2674 			179,
2675 			0,
2676 			2,
2677 			1,
2678 			1,
2679 			0,
2680 			0,
2681 			0,
2682 			5,
2683 			2,
2684 			9,
2685 			6,
2686 			0,
2687 			2,
2688 			5,
2689 			16,
2690 			7,
2691 			5,
2692 			1,
2693 			1,
2694 			0,
2695 			2,
2696 			4,
2697 			4,
2698 			7,
2699 			15,
2700 			13,
2701 			14,
2702 			0,
2703 			0,
2704 			3,
2705 			0,
2706 			1,
2707 			0,
2708 			0,
2709 			0,
2710 			2,
2711 			1,
2712 			6,
2713 			4,
2714 			5,
2715 			1,
2716 			4,
2717 			9,
2718 			0,
2719 			3,
2720 			1,
2721 			8,
2722 			0,
2723 			0,
2724 			10,
2725 			5,
2726 			0,
2727 			43,
2728 			0,
2729 			2,
2730 			6,
2731 			8,
2732 			4,
2733 			0,
2734 			2,
2735 			0,
2736 			0,
2737 			9,
2738 			6,
2739 			0,
2740 			9,
2741 			3,
2742 			1,
2743 			6,
2744 			20,
2745 			14,
2746 			6,
2747 			1,
2748 			4,
2749 			0,
2750 			7,
2751 			2,
2752 			3,
2753 			0,
2754 			2,
2755 			0,
2756 			5,
2757 			0,
2758 			3,
2759 			1,
2760 			0,
2761 			3,
2762 			9,
2763 			7,
2764 			0,
2765 			3,
2766 			4,
2767 			0,
2768 			4,
2769 			9,
2770 			1,
2771 			6,
2772 			0,
2773 			9,
2774 			0,
2775 			0,
2776 			2,
2777 			3,
2778 			10,
2779 			9,
2780 			28,
2781 			3,
2782 			6,
2783 			2,
2784 			4,
2785 			1,
2786 			2,
2787 			32,
2788 			4,
2789 			1,
2790 			18,
2791 			2,
2792 			0,
2793 			3,
2794 			1,
2795 			5,
2796 			30,
2797 			10,
2798 			0,
2799 			2,
2800 			2,
2801 			2,
2802 			0,
2803 			7,
2804 			9,
2805 			8,
2806 			11,
2807 			10,
2808 			11,
2809 			7,
2810 			2,
2811 			13,
2812 			7,
2813 			5,
2814 			10,
2815 			0,
2816 			3,
2817 			40,
2818 			2,
2819 			0,
2820 			1,
2821 			6,
2822 			12,
2823 			0,
2824 			4,
2825 			5,
2826 			1,
2827 			5,
2828 			11,
2829 			11,
2830 			21,
2831 			4,
2832 			8,
2833 			3,
2834 			7,
2835 			8,
2836 			8,
2837 			33,
2838 			5,
2839 			23,
2840 			0,
2841 			0,
2842 			19,
2843 			8,
2844 			8,
2845 			2,
2846 			3,
2847 			0,
2848 			6,
2849 			1,
2850 			1,
2851 			1,
2852 			5,
2853 			1,
2854 			27,
2855 			4,
2856 			2,
2857 			5,
2858 			0,
2859 			3,
2860 			5,
2861 			6,
2862 			3,
2863 			1,
2864 			0,
2865 			3,
2866 			1,
2867 			12,
2868 			5,
2869 			3,
2870 			3,
2871 			2,
2872 			0,
2873 			7,
2874 			7,
2875 			2,
2876 			1,
2877 			0,
2878 			4,
2879 			0,
2880 			1,
2881 			1,
2882 			2,
2883 			0,
2884 			10,
2885 			10,
2886 			6,
2887 			2,
2888 			5,
2889 			9,
2890 			7,
2891 			5,
2892 			15,
2893 			15,
2894 			21,
2895 			6,
2896 			11,
2897 			5,
2898 			20,
2899 			4,
2900 			3,
2901 			5,
2902 			5,
2903 			2,
2904 			5,
2905 			0,
2906 			2,
2907 			1,
2908 			0,
2909 			1,
2910 			7,
2911 			28,
2912 			0,
2913 			9,
2914 			0,
2915 			5,
2916 			12,
2917 			5,
2918 			5,
2919 			18,
2920 			30,
2921 			0,
2922 			12,
2923 			3,
2924 			3,
2925 			21,
2926 			16,
2927 			25,
2928 			32,
2929 			9,
2930 			3,
2931 			14,
2932 			11,
2933 			24,
2934 			5,
2935 			66,
2936 			9,
2937 			1,
2938 			2,
2939 			0,
2940 			5,
2941 			9,
2942 			1,
2943 			5,
2944 			1,
2945 			8,
2946 			0,
2947 			8,
2948 			3,
2949 			3,
2950 			0,
2951 			1,
2952 			15,
2953 			1,
2954 			4,
2955 			8,
2956 			1,
2957 			2,
2958 			7,
2959 			0,
2960 			7,
2961 			2,
2962 			8,
2963 			3,
2964 			7,
2965 			5,
2966 			3,
2967 			7,
2968 			10,
2969 			2,
2970 			1,
2971 			0,
2972 			0,
2973 			2,
2974 			25,
2975 			0,
2976 			6,
2977 			4,
2978 			0,
2979 			10,
2980 			0,
2981 			4,
2982 			2,
2983 			4,
2984 			1,
2985 			12,
2986 			5,
2987 			38,
2988 			4,
2989 			0,
2990 			4,
2991 			1,
2992 			10,
2993 			5,
2994 			9,
2995 			4,
2996 			0,
2997 			14,
2998 			4,
2999 			2,
3000 			5,
3001 			18,
3002 			20,
3003 			21,
3004 			1,
3005 			3,
3006 			0,
3007 			5,
3008 			0,
3009 			7,
3010 			0,
3011 			3,
3012 			7,
3013 			1,
3014 			3,
3015 			1,
3016 			1,
3017 			8,
3018 			1,
3019 			0,
3020 			0,
3021 			0,
3022 			3,
3023 			2,
3024 			5,
3025 			2,
3026 			11,
3027 			6,
3028 			0,
3029 			13,
3030 			1,
3031 			3,
3032 			9,
3033 			1,
3034 			12,
3035 			0,
3036 			16,
3037 			6,
3038 			2,
3039 			1,
3040 			0,
3041 			2,
3042 			1,
3043 			12,
3044 			6,
3045 			13,
3046 			11,
3047 			2,
3048 			0,
3049 			28,
3050 			1,
3051 			7,
3052 			8,
3053 			14,
3054 			13,
3055 			8,
3056 			13,
3057 			0,
3058 			2,
3059 			0,
3060 			5,
3061 			4,
3062 			8,
3063 			10,
3064 			2,
3065 			37,
3066 			42,
3067 			19,
3068 			6,
3069 			6,
3070 			7,
3071 			4,
3072 			14,
3073 			11,
3074 			18,
3075 			14,
3076 			80,
3077 			7,
3078 			6,
3079 			0,
3080 			4,
3081 			72,
3082 			12,
3083 			36,
3084 			27,
3085 			7,
3086 			7,
3087 			0,
3088 			14,
3089 			17,
3090 			19,
3091 			164,
3092 			27,
3093 			0,
3094 			5,
3095 			10,
3096 			7,
3097 			3,
3098 			13,
3099 			6,
3100 			14,
3101 			0,
3102 			2,
3103 			2,
3104 			5,
3105 			3,
3106 			0,
3107 			6,
3108 			13,
3109 			0,
3110 			0,
3111 			10,
3112 			29,
3113 			0,
3114 			4,
3115 			0,
3116 			3,
3117 			13,
3118 			0,
3119 			3,
3120 			1,
3121 			6,
3122 			51,
3123 			1,
3124 			5,
3125 			28,
3126 			2,
3127 			0,
3128 			8,
3129 			0,
3130 			20,
3131 			2,
3132 			4,
3133 			0,
3134 			25,
3135 			2,
3136 			10,
3137 			13,
3138 			10,
3139 			0,
3140 			16,
3141 			4,
3142 			0,
3143 			1,
3144 			0,
3145 			2,
3146 			1,
3147 			7,
3148 			0,
3149 			1,
3150 			8,
3151 			11,
3152 			0,
3153 			0,
3154 			1,
3155 			2,
3156 			7,
3157 			2,
3158 			23,
3159 			11,
3160 			6,
3161 			6,
3162 			4,
3163 			16,
3164 			2,
3165 			2,
3166 			2,
3167 			0,
3168 			22,
3169 			9,
3170 			3,
3171 			3,
3172 			5,
3173 			2,
3174 			0,
3175 			15,
3176 			16,
3177 			21,
3178 			2,
3179 			9,
3180 			20,
3181 			15,
3182 			15,
3183 			5,
3184 			3,
3185 			9,
3186 			1,
3187 			0,
3188 			0,
3189 			1,
3190 			7,
3191 			7,
3192 			5,
3193 			4,
3194 			2,
3195 			2,
3196 			2,
3197 			38,
3198 			24,
3199 			14,
3200 			0,
3201 			0,
3202 			15,
3203 			5,
3204 			6,
3205 			24,
3206 			14,
3207 			5,
3208 			5,
3209 			11,
3210 			0,
3211 			21,
3212 			12,
3213 			0,
3214 			3,
3215 			8,
3216 			4,
3217 			11,
3218 			1,
3219 			8,
3220 			0,
3221 			11,
3222 			27,
3223 			7,
3224 			2,
3225 			4,
3226 			9,
3227 			21,
3228 			59,
3229 			0,
3230 			1,
3231 			39,
3232 			3,
3233 			60,
3234 			62,
3235 			3,
3236 			0,
3237 			12,
3238 			11,
3239 			0,
3240 			3,
3241 			30,
3242 			11,
3243 			0,
3244 			13,
3245 			88,
3246 			4,
3247 			15,
3248 			5,
3249 			28,
3250 			13,
3251 			1,
3252 			4,
3253 			48,
3254 			17,
3255 			17,
3256 			4,
3257 			28,
3258 			32,
3259 			46,
3260 			0,
3261 			16,
3262 			0,
3263 			18,
3264 			11,
3265 			1,
3266 			8,
3267 			6,
3268 			38,
3269 			11,
3270 			2,
3271 			6,
3272 			11,
3273 			38,
3274 			2,
3275 			0,
3276 			45,
3277 			3,
3278 			11,
3279 			2,
3280 			7,
3281 			8,
3282 			4,
3283 			30,
3284 			14,
3285 			17,
3286 			2,
3287 			1,
3288 			1,
3289 			65,
3290 			18,
3291 			12,
3292 			16,
3293 			4,
3294 			2,
3295 			45,
3296 			123,
3297 			12,
3298 			56,
3299 			33,
3300 			1,
3301 			4,
3302 			3,
3303 			4,
3304 			7,
3305 			0,
3306 			0,
3307 			0,
3308 			3,
3309 			2,
3310 			0,
3311 			16,
3312 			4,
3313 			2,
3314 			4,
3315 			2,
3316 			0,
3317 			7,
3318 			4,
3319 			5,
3320 			2,
3321 			26,
3322 			2,
3323 			25,
3324 			6,
3325 			11,
3326 			6,
3327 			1,
3328 			16,
3329 			2,
3330 			6,
3331 			17,
3332 			77,
3333 			15,
3334 			3,
3335 			35,
3336 			0,
3337 			1,
3338 			0,
3339 			5,
3340 			1,
3341 			0,
3342 			38,
3343 			16,
3344 			6,
3345 			3,
3346 			12,
3347 			3,
3348 			3,
3349 			3,
3350 			0,
3351 			9,
3352 			3,
3353 			1,
3354 			3,
3355 			5,
3356 			2,
3357 			9,
3358 			0,
3359 			18,
3360 			0,
3361 			25,
3362 			1,
3363 			3,
3364 			32,
3365 			1,
3366 			72,
3367 			46,
3368 			6,
3369 			2,
3370 			7,
3371 			1,
3372 			3,
3373 			14,
3374 			17,
3375 			0,
3376 			28,
3377 			1,
3378 			40,
3379 			13,
3380 			0,
3381 			20,
3382 			15,
3383 			40,
3384 			6,
3385 			38,
3386 			24,
3387 			12,
3388 			43,
3389 			1,
3390 			1,
3391 			9,
3392 			0,
3393 			12,
3394 			6,
3395 			0,
3396 			6,
3397 			2,
3398 			4,
3399 			19,
3400 			3,
3401 			7,
3402 			1,
3403 			48,
3404 			0,
3405 			9,
3406 			5,
3407 			0,
3408 			5,
3409 			6,
3410 			9,
3411 			6,
3412 			10,
3413 			15,
3414 			2,
3415 			11,
3416 			19,
3417 			3,
3418 			9,
3419 			2,
3420 			0,
3421 			1,
3422 			10,
3423 			1,
3424 			27,
3425 			8,
3426 			1,
3427 			3,
3428 			6,
3429 			1,
3430 			14,
3431 			0,
3432 			26,
3433 			0,
3434 			27,
3435 			16,
3436 			3,
3437 			4,
3438 			9,
3439 			6,
3440 			2,
3441 			23,
3442 			9,
3443 			10,
3444 			5,
3445 			25,
3446 			2,
3447 			1,
3448 			6,
3449 			1,
3450 			1,
3451 			48,
3452 			15,
3453 			9,
3454 			15,
3455 			14,
3456 			3,
3457 			4,
3458 			26,
3459 			60,
3460 			29,
3461 			13,
3462 			37,
3463 			21,
3464 			1,
3465 			6,
3466 			4,
3467 			0,
3468 			2,
3469 			11,
3470 			22,
3471 			23,
3472 			16,
3473 			16,
3474 			2,
3475 			2,
3476 			1,
3477 			3,
3478 			0,
3479 			5,
3480 			1,
3481 			6,
3482 			4,
3483 			0,
3484 			0,
3485 			4,
3486 			0,
3487 			0,
3488 			8,
3489 			3,
3490 			0,
3491 			2,
3492 			5,
3493 			0,
3494 			7,
3495 			1,
3496 			7,
3497 			3,
3498 			13,
3499 			2,
3500 			4,
3501 			10,
3502 			3,
3503 			0,
3504 			2,
3505 			31,
3506 			0,
3507 			18,
3508 			3,
3509 			0,
3510 			12,
3511 			10,
3512 			4,
3513 			1,
3514 			0,
3515 			7,
3516 			5,
3517 			7,
3518 			0,
3519 			5,
3520 			4,
3521 			12,
3522 			2,
3523 			22,
3524 			10,
3525 			4,
3526 			2,
3527 			15,
3528 			2,
3529 			8,
3530 			9,
3531 			0,
3532 			23,
3533 			2,
3534 			197,
3535 			51,
3536 			3,
3537 			1,
3538 			1,
3539 			4,
3540 			13,
3541 			4,
3542 			3,
3543 			21,
3544 			4,
3545 			19,
3546 			3,
3547 			10,
3548 			5,
3549 			40,
3550 			0,
3551 			4,
3552 			1,
3553 			1,
3554 			10,
3555 			4,
3556 			1,
3557 			27,
3558 			34,
3559 			7,
3560 			21,
3561 			2,
3562 			17,
3563 			2,
3564 			9,
3565 			6,
3566 			4,
3567 			2,
3568 			3,
3569 			0,
3570 			4,
3571 			2,
3572 			7,
3573 			8,
3574 			2,
3575 			5,
3576 			1,
3577 			15,
3578 			21,
3579 			3,
3580 			4,
3581 			4,
3582 			2,
3583 			2,
3584 			17,
3585 			22,
3586 			1,
3587 			5,
3588 			22,
3589 			4,
3590 			26,
3591 			7,
3592 			0,
3593 			32,
3594 			1,
3595 			11,
3596 			42,
3597 			15,
3598 			4,
3599 			1,
3600 			2,
3601 			5,
3602 			0,
3603 			19,
3604 			3,
3605 			1,
3606 			8,
3607 			6,
3608 			0,
3609 			10,
3610 			1,
3611 			9,
3612 			2,
3613 			13,
3614 			30,
3615 			8,
3616 			2,
3617 			24,
3618 			17,
3619 			19,
3620 			1,
3621 			4,
3622 			4,
3623 			25,
3624 			13,
3625 			0,
3626 			10,
3627 			16,
3628 			11,
3629 			39,
3630 			18,
3631 			8,
3632 			5,
3633 			30,
3634 			82,
3635 			1,
3636 			6,
3637 			8,
3638 			18,
3639 			77,
3640 			11,
3641 			13,
3642 			20,
3643 			75,
3644 			11,
3645 			112,
3646 			78,
3647 			33,
3648 			3,
3649 			0,
3650 			0,
3651 			60,
3652 			17,
3653 			84,
3654 			9,
3655 			1,
3656 			1,
3657 			12,
3658 			30,
3659 			10,
3660 			49,
3661 			5,
3662 			32,
3663 			158,
3664 			178,
3665 			5,
3666 			5,
3667 			6,
3668 			3,
3669 			3,
3670 			1,
3671 			3,
3672 			1,
3673 			4,
3674 			7,
3675 			6,
3676 			19,
3677 			31,
3678 			21,
3679 			0,
3680 			2,
3681 			9,
3682 			5,
3683 			6,
3684 			27,
3685 			4,
3686 			9,
3687 			8,
3688 			1,
3689 			76,
3690 			18,
3691 			12,
3692 			1,
3693 			4,
3694 			0,
3695 			3,
3696 			3,
3697 			6,
3698 			3,
3699 			12,
3700 			2,
3701 			8,
3702 			30,
3703 			16,
3704 			2,
3705 			25,
3706 			1,
3707 			5,
3708 			5,
3709 			4,
3710 			3,
3711 			0,
3712 			6,
3713 			10,
3714 			2,
3715 			3,
3716 			1,
3717 			0,
3718 			5,
3719 			1,
3720 			19,
3721 			3,
3722 			0,
3723 			8,
3724 			1,
3725 			5,
3726 			2,
3727 			6,
3728 			0,
3729 			0,
3730 			0,
3731 			19,
3732 			1,
3733 			2,
3734 			0,
3735 			5,
3736 			1,
3737 			2,
3738 			5,
3739 			1,
3740 			3,
3741 			7,
3742 			0,
3743 			4,
3744 			12,
3745 			7,
3746 			3,
3747 			10,
3748 			22,
3749 			0,
3750 			9,
3751 			5,
3752 			1,
3753 			0,
3754 			2,
3755 			20,
3756 			1,
3757 			1,
3758 			3,
3759 			23,
3760 			30,
3761 			3,
3762 			9,
3763 			9,
3764 			1,
3765 			4,
3766 			191,
3767 			14,
3768 			3,
3769 			15,
3770 			6,
3771 			8,
3772 			50,
3773 			0,
3774 			1,
3775 			0,
3776 			0,
3777 			4,
3778 			0,
3779 			0,
3780 			1,
3781 			0,
3782 			2,
3783 			4,
3784 			2,
3785 			0,
3786 			2,
3787 			3,
3788 			0,
3789 			2,
3790 			0,
3791 			2,
3792 			2,
3793 			8,
3794 			7,
3795 			0,
3796 			1,
3797 			1,
3798 			1,
3799 			3,
3800 			3,
3801 			17,
3802 			11,
3803 			91,
3804 			1,
3805 			9,
3806 			3,
3807 			2,
3808 			13,
3809 			4,
3810 			24,
3811 			15,
3812 			41,
3813 			3,
3814 			13,
3815 			3,
3816 			1,
3817 			20,
3818 			4,
3819 			125,
3820 			29,
3821 			30,
3822 			1,
3823 			0,
3824 			4,
3825 			12,
3826 			2,
3827 			21,
3828 			4,
3829 			5,
3830 			5,
3831 			19,
3832 			11,
3833 			0,
3834 			13,
3835 			11,
3836 			86,
3837 			2,
3838 			18,
3839 			0,
3840 			7,
3841 			1,
3842 			8,
3843 			8,
3844 			2,
3845 			2,
3846 			22,
3847 			1,
3848 			2,
3849 			6,
3850 			5,
3851 			2,
3852 			0,
3853 			1,
3854 			2,
3855 			8,
3856 			0,
3857 			2,
3858 			0,
3859 			5,
3860 			2,
3861 			1,
3862 			0,
3863 			2,
3864 			10,
3865 			2,
3866 			0,
3867 			5,
3868 			9,
3869 			2,
3870 			1,
3871 			2,
3872 			0,
3873 			1,
3874 			0,
3875 			4,
3876 			0,
3877 			0,
3878 			10,
3879 			2,
3880 			5,
3881 			3,
3882 			0,
3883 			6,
3884 			1,
3885 			0,
3886 			1,
3887 			4,
3888 			4,
3889 			33,
3890 			3,
3891 			13,
3892 			17,
3893 			3,
3894 			18,
3895 			6,
3896 			4,
3897 			7,
3898 			1,
3899 			5,
3900 			78,
3901 			0,
3902 			4,
3903 			1,
3904 			13,
3905 			7,
3906 			1,
3907 			8,
3908 			1,
3909 			0,
3910 			35,
3911 			27,
3912 			15,
3913 			3,
3914 			0,
3915 			0,
3916 			0,
3917 			1,
3918 			11,
3919 			5,
3920 			41,
3921 			38,
3922 			15,
3923 			22,
3924 			6,
3925 			14,
3926 			14,
3927 			2,
3928 			1,
3929 			11,
3930 			6,
3931 			20,
3932 			63,
3933 			5,
3934 			8,
3935 			27,
3936 			7,
3937 			11,
3938 			2,
3939 			2,
3940 			40,
3941 			58,
3942 			23,
3943 			50,
3944 			54,
3945 			56,
3946 			293,
3947 			8,
3948 			8,
3949 			1,
3950 			5,
3951 			1,
3952 			14,
3953 			0,
3954 			1,
3955 			12,
3956 			37,
3957 			89,
3958 			8,
3959 			8,
3960 			8,
3961 			2,
3962 			10,
3963 			6,
3964 			0,
3965 			0,
3966 			0,
3967 			4,
3968 			5,
3969 			2,
3970 			1,
3971 			0,
3972 			1,
3973 			1,
3974 			2,
3975 			7,
3976 			0,
3977 			3,
3978 			3,
3979 			0,
3980 			4,
3981 			6,
3982 			0,
3983 			3,
3984 			2,
3985 			19,
3986 			3,
3987 			8,
3988 			0,
3989 			0,
3990 			0,
3991 			4,
3992 			4,
3993 			16,
3994 			0,
3995 			4,
3996 			1,
3997 			5,
3998 			1,
3999 			3,
4000 			0,
4001 			3,
4002 			4,
4003 			6,
4004 			2,
4005 			17,
4006 			10,
4007 			10,
4008 			31,
4009 			6,
4010 			4,
4011 			3,
4012 			6,
4013 			10,
4014 			126,
4015 			7,
4016 			3,
4017 			2,
4018 			2,
4019 			0,
4020 			9,
4021 			0,
4022 			0,
4023 			5,
4024 			20,
4025 			13,
4026 			0,
4027 			15,
4028 			0,
4029 			6,
4030 			0,
4031 			2,
4032 			5,
4033 			8,
4034 			64,
4035 			50,
4036 			3,
4037 			2,
4038 			12,
4039 			2,
4040 			9,
4041 			0,
4042 			0,
4043 			11,
4044 			8,
4045 			20,
4046 			109,
4047 			2,
4048 			18,
4049 			23,
4050 			0,
4051 			0,
4052 			9,
4053 			61,
4054 			3,
4055 			0,
4056 			28,
4057 			41,
4058 			77,
4059 			27,
4060 			19,
4061 			17,
4062 			81,
4063 			5,
4064 			2,
4065 			14,
4066 			5,
4067 			83,
4068 			57,
4069 			252,
4070 			14,
4071 			154,
4072 			263,
4073 			14,
4074 			20,
4075 			8,
4076 			13,
4077 			6,
4078 			57,
4079 			39,
4080 			38,
4081 		};
4082 	static ImWchar base_ranges[] =
4083 		{
4084 			0x0020, 0x00FF,  // Basic Latin + Latin Supplement
4085 			0x3000, 0x30FF,  // Punctuations, Hiragana, Katakana
4086 			0x31F0, 0x31FF,  // Katakana Phonetic Extensions
4087 			0xFF00, 0xFFEF,  // Half-width characters
4088 		};
4089 	static bool full_ranges_unpacked = false;
4090 	static ImWchar full_ranges[IM_ARRAYSIZE(base_ranges) + IM_ARRAYSIZE(offsets_from_0x4E00) * 2 + 1];
4091 	if (!full_ranges_unpacked)
4092 	{
4093 		// Unpack
4094 		int codepoint = 0x4e00;
4095 		memcpy(full_ranges, base_ranges, sizeof(base_ranges));
4096 		ImWchar* dst = full_ranges + IM_ARRAYSIZE(base_ranges);
4097 		;
4098 		for (int n = 0; n < IM_ARRAYSIZE(offsets_from_0x4E00); n++, dst += 2)
4099 			dst[0] = dst[1] = (ImWchar)(codepoint += (offsets_from_0x4E00[n] + 1));
4100 		dst[0] = 0;
4101 		full_ranges_unpacked = true;
4102 	}
4103 	return &full_ranges[0];
4104 }
4105 
GetGlyphRangesCyrillic()4106 const ImWchar* ImFontAtlas::GetGlyphRangesCyrillic()
4107 {
4108 	static const ImWchar ranges[] =
4109 		{
4110 			0x0020,
4111 			0x00FF,  // Basic Latin + Latin Supplement
4112 			0x0400,
4113 			0x052F,  // Cyrillic + Cyrillic Supplement
4114 			0x2DE0,
4115 			0x2DFF,  // Cyrillic Extended-A
4116 			0xA640,
4117 			0xA69F,  // Cyrillic Extended-B
4118 			0,
4119 		};
4120 	return &ranges[0];
4121 }
4122 
GetGlyphRangesThai()4123 const ImWchar* ImFontAtlas::GetGlyphRangesThai()
4124 {
4125 	static const ImWchar ranges[] =
4126 		{
4127 			0x0020,
4128 			0x00FF,  // Basic Latin
4129 			0x2010,
4130 			0x205E,  // Punctuations
4131 			0x0E00,
4132 			0x0E7F,  // Thai
4133 			0,
4134 		};
4135 	return &ranges[0];
4136 }
4137 
4138 //-----------------------------------------------------------------------------
4139 // ImFontAtlas::GlyphRangesBuilder
4140 //-----------------------------------------------------------------------------
4141 
AddText(const char * text,const char * text_end)4142 void ImFontAtlas::GlyphRangesBuilder::AddText(const char* text, const char* text_end)
4143 {
4144 	while (text_end ? (text < text_end) : *text)
4145 	{
4146 		unsigned int c = 0;
4147 		int c_len = ImTextCharFromUtf8(&c, text, text_end);
4148 		text += c_len;
4149 		if (c_len == 0)
4150 			break;
4151 		if (c < 0x10000)
4152 			AddChar((ImWchar)c);
4153 	}
4154 }
4155 
AddRanges(const ImWchar * ranges)4156 void ImFontAtlas::GlyphRangesBuilder::AddRanges(const ImWchar* ranges)
4157 {
4158 	for (; ranges[0]; ranges += 2)
4159 		for (ImWchar c = ranges[0]; c <= ranges[1]; c++)
4160 			AddChar(c);
4161 }
4162 
BuildRanges(ImVector<ImWchar> * out_ranges)4163 void ImFontAtlas::GlyphRangesBuilder::BuildRanges(ImVector<ImWchar>* out_ranges)
4164 {
4165 	for (int n = 0; n < 0x10000; n++)
4166 		if (GetBit(n))
4167 		{
4168 			out_ranges->push_back((ImWchar)n);
4169 			while (n < 0x10000 && GetBit(n + 1))
4170 				n++;
4171 			out_ranges->push_back((ImWchar)n);
4172 		}
4173 	out_ranges->push_back(0);
4174 }
4175 
4176 //-----------------------------------------------------------------------------
4177 // ImFont
4178 //-----------------------------------------------------------------------------
4179 
ImFont()4180 ImFont::ImFont()
4181 {
4182 	Scale = 1.0f;
4183 	FallbackChar = (ImWchar)'?';
4184 	DisplayOffset = ImVec2(0.0f, 1.0f);
4185 	ClearOutputData();
4186 }
4187 
~ImFont()4188 ImFont::~ImFont()
4189 {
4190 	// Invalidate active font so that the user gets a clear crash instead of a dangling pointer.
4191 	// If you want to delete fonts you need to do it between Render() and NewFrame().
4192 	// FIXME-CLEANUP
4193 	/*
4194     ImGuiContext& g = *GImGui;
4195     if (g.Font == this)
4196         g.Font = NULL;
4197     */
4198 	ClearOutputData();
4199 }
4200 
ClearOutputData()4201 void ImFont::ClearOutputData()
4202 {
4203 	FontSize = 0.0f;
4204 	Glyphs.clear();
4205 	IndexAdvanceX.clear();
4206 	IndexLookup.clear();
4207 	FallbackGlyph = NULL;
4208 	FallbackAdvanceX = 0.0f;
4209 	ConfigDataCount = 0;
4210 	ConfigData = NULL;
4211 	ContainerAtlas = NULL;
4212 	Ascent = Descent = 0.0f;
4213 	MetricsTotalSurface = 0;
4214 }
4215 
BuildLookupTable()4216 void ImFont::BuildLookupTable()
4217 {
4218 	int max_codepoint = 0;
4219 	for (int i = 0; i != Glyphs.Size; i++)
4220 		max_codepoint = ImMax(max_codepoint, (int)Glyphs[i].Codepoint);
4221 
4222 	IM_ASSERT(Glyphs.Size < 0xFFFF);  // -1 is reserved
4223 	IndexAdvanceX.clear();
4224 	IndexLookup.clear();
4225 	GrowIndex(max_codepoint + 1);
4226 	for (int i = 0; i < Glyphs.Size; i++)
4227 	{
4228 		int codepoint = (int)Glyphs[i].Codepoint;
4229 		IndexAdvanceX[codepoint] = Glyphs[i].AdvanceX;
4230 		IndexLookup[codepoint] = (unsigned short)i;
4231 	}
4232 
4233 	// Create a glyph to handle TAB
4234 	// FIXME: Needs proper TAB handling but it needs to be contextualized (or we could arbitrary say that each string starts at "column 0" ?)
4235 	if (FindGlyph((unsigned short)' '))
4236 	{
4237 		if (Glyphs.back().Codepoint != '\t')  // So we can call this function multiple times
4238 			Glyphs.resize(Glyphs.Size + 1);
4239 		ImFontGlyph& tab_glyph = Glyphs.back();
4240 		tab_glyph = *FindGlyph((unsigned short)' ');
4241 		tab_glyph.Codepoint = '\t';
4242 		tab_glyph.AdvanceX *= 4;
4243 		IndexAdvanceX[(int)tab_glyph.Codepoint] = (float)tab_glyph.AdvanceX;
4244 		IndexLookup[(int)tab_glyph.Codepoint] = (unsigned short)(Glyphs.Size - 1);
4245 	}
4246 
4247 	FallbackGlyph = NULL;
4248 	FallbackGlyph = FindGlyph(FallbackChar);
4249 	FallbackAdvanceX = FallbackGlyph ? FallbackGlyph->AdvanceX : 0.0f;
4250 	for (int i = 0; i < max_codepoint + 1; i++)
4251 		if (IndexAdvanceX[i] < 0.0f)
4252 			IndexAdvanceX[i] = FallbackAdvanceX;
4253 }
4254 
SetFallbackChar(ImWchar c)4255 void ImFont::SetFallbackChar(ImWchar c)
4256 {
4257 	FallbackChar = c;
4258 	BuildLookupTable();
4259 }
4260 
GrowIndex(int new_size)4261 void ImFont::GrowIndex(int new_size)
4262 {
4263 	IM_ASSERT(IndexAdvanceX.Size == IndexLookup.Size);
4264 	if (new_size <= IndexLookup.Size)
4265 		return;
4266 	IndexAdvanceX.resize(new_size, -1.0f);
4267 	IndexLookup.resize(new_size, (unsigned short)-1);
4268 }
4269 
AddGlyph(ImWchar codepoint,float x0,float y0,float x1,float y1,float u0,float v0,float u1,float v1,float advance_x)4270 void ImFont::AddGlyph(ImWchar codepoint, float x0, float y0, float x1, float y1, float u0, float v0, float u1, float v1, float advance_x)
4271 {
4272 	Glyphs.resize(Glyphs.Size + 1);
4273 	ImFontGlyph& glyph = Glyphs.back();
4274 	glyph.Codepoint = (ImWchar)codepoint;
4275 	glyph.X0 = x0;
4276 	glyph.Y0 = y0;
4277 	glyph.X1 = x1;
4278 	glyph.Y1 = y1;
4279 	glyph.U0 = u0;
4280 	glyph.V0 = v0;
4281 	glyph.U1 = u1;
4282 	glyph.V1 = v1;
4283 	glyph.AdvanceX = advance_x + ConfigData->GlyphExtraSpacing.x;  // Bake spacing into AdvanceX
4284 
4285 	if (ConfigData->PixelSnapH)
4286 		glyph.AdvanceX = (float)(int)(glyph.AdvanceX + 0.5f);
4287 
4288 	// Compute rough surface usage metrics (+1 to account for average padding, +0.99 to round)
4289 	MetricsTotalSurface += (int)((glyph.U1 - glyph.U0) * ContainerAtlas->TexWidth + 1.99f) * (int)((glyph.V1 - glyph.V0) * ContainerAtlas->TexHeight + 1.99f);
4290 }
4291 
AddRemapChar(ImWchar dst,ImWchar src,bool overwrite_dst)4292 void ImFont::AddRemapChar(ImWchar dst, ImWchar src, bool overwrite_dst)
4293 {
4294 	IM_ASSERT(IndexLookup.Size > 0);  // Currently this can only be called AFTER the font has been built, aka after calling ImFontAtlas::GetTexDataAs*() function.
4295 	int index_size = IndexLookup.Size;
4296 
4297 	if (dst < index_size && IndexLookup.Data[dst] == (unsigned short)-1 && !overwrite_dst)  // 'dst' already exists
4298 		return;
4299 	if (src >= index_size && dst >= index_size)  // both 'dst' and 'src' don't exist -> no-op
4300 		return;
4301 
4302 	GrowIndex(dst + 1);
4303 	IndexLookup[dst] = (src < index_size) ? IndexLookup.Data[src] : (unsigned short)-1;
4304 	IndexAdvanceX[dst] = (src < index_size) ? IndexAdvanceX.Data[src] : 1.0f;
4305 }
4306 
FindGlyph(ImWchar c) const4307 const ImFontGlyph* ImFont::FindGlyph(ImWchar c) const
4308 {
4309 	if (c < IndexLookup.Size)
4310 	{
4311 		const unsigned short i = IndexLookup[c];
4312 		if (i != (unsigned short)-1)
4313 			return &Glyphs.Data[i];
4314 	}
4315 	return FallbackGlyph;
4316 }
4317 
CalcWordWrapPositionA(float scale,const char * text,const char * text_end,float wrap_width) const4318 const char* ImFont::CalcWordWrapPositionA(float scale, const char* text, const char* text_end, float wrap_width) const
4319 {
4320 	// Simple word-wrapping for English, not full-featured. Please submit failing cases!
4321 	// FIXME: Much possible improvements (don't cut things like "word !", "word!!!" but cut within "word,,,,", more sensible support for punctuations, support for Unicode punctuations, etc.)
4322 
4323 	// For references, possible wrap point marked with ^
4324 	//  "aaa bbb, ccc,ddd. eee   fff. ggg!"
4325 	//      ^    ^    ^   ^   ^__    ^    ^
4326 
4327 	// List of hardcoded separators: .,;!?'"
4328 
4329 	// Skip extra blanks after a line returns (that includes not counting them in width computation)
4330 	// e.g. "Hello    world" --> "Hello" "World"
4331 
4332 	// Cut words that cannot possibly fit within one line.
4333 	// e.g.: "The tropical fish" with ~5 characters worth of width --> "The tr" "opical" "fish"
4334 
4335 	float line_width = 0.0f;
4336 	float word_width = 0.0f;
4337 	float blank_width = 0.0f;
4338 	wrap_width /= scale;  // We work with unscaled widths to avoid scaling every characters
4339 
4340 	const char* word_end = text;
4341 	const char* prev_word_end = NULL;
4342 	bool inside_word = true;
4343 
4344 	const char* s = text;
4345 	while (s < text_end)
4346 	{
4347 		unsigned int c = (unsigned int)*s;
4348 		const char* next_s;
4349 		if (c < 0x80)
4350 			next_s = s + 1;
4351 		else
4352 			next_s = s + ImTextCharFromUtf8(&c, s, text_end);
4353 		if (c == 0)
4354 			break;
4355 
4356 		if (c < 32)
4357 		{
4358 			if (c == '\n')
4359 			{
4360 				line_width = word_width = blank_width = 0.0f;
4361 				inside_word = true;
4362 				s = next_s;
4363 				continue;
4364 			}
4365 			if (c == '\r')
4366 			{
4367 				s = next_s;
4368 				continue;
4369 			}
4370 		}
4371 
4372 		const float char_width = ((int)c < IndexAdvanceX.Size ? IndexAdvanceX[(int)c] : FallbackAdvanceX);
4373 		if (ImCharIsSpace(c))
4374 		{
4375 			if (inside_word)
4376 			{
4377 				line_width += blank_width;
4378 				blank_width = 0.0f;
4379 				word_end = s;
4380 			}
4381 			blank_width += char_width;
4382 			inside_word = false;
4383 		}
4384 		else
4385 		{
4386 			word_width += char_width;
4387 			if (inside_word)
4388 			{
4389 				word_end = next_s;
4390 			}
4391 			else
4392 			{
4393 				prev_word_end = word_end;
4394 				line_width += word_width + blank_width;
4395 				word_width = blank_width = 0.0f;
4396 			}
4397 
4398 			// Allow wrapping after punctuation.
4399 			inside_word = !(c == '.' || c == ',' || c == ';' || c == '!' || c == '?' || c == '\"');
4400 		}
4401 
4402 		// We ignore blank width at the end of the line (they can be skipped)
4403 		if (line_width + word_width >= wrap_width)
4404 		{
4405 			// Words that cannot possibly fit within an entire line will be cut anywhere.
4406 			if (word_width < wrap_width)
4407 				s = prev_word_end ? prev_word_end : word_end;
4408 			break;
4409 		}
4410 
4411 		s = next_s;
4412 	}
4413 
4414 	return s;
4415 }
4416 
CalcTextSizeA(float size,float max_width,float wrap_width,const char * text_begin,const char * text_end,const char ** remaining) const4417 ImVec2 ImFont::CalcTextSizeA(float size, float max_width, float wrap_width, const char* text_begin, const char* text_end, const char** remaining) const
4418 {
4419 	if (!text_end)
4420 		text_end = text_begin + strlen(text_begin);  // FIXME-OPT: Need to avoid this.
4421 
4422 	const float line_height = size;
4423 	const float scale = size / FontSize;
4424 
4425 	ImVec2 text_size = ImVec2(0, 0);
4426 	float line_width = 0.0f;
4427 
4428 	const bool word_wrap_enabled = (wrap_width > 0.0f);
4429 	const char* word_wrap_eol = NULL;
4430 
4431 	const char* s = text_begin;
4432 	while (s < text_end)
4433 	{
4434 		if (word_wrap_enabled)
4435 		{
4436 			// Calculate how far we can render. Requires two passes on the string data but keeps the code simple and not intrusive for what's essentially an uncommon feature.
4437 			if (!word_wrap_eol)
4438 			{
4439 				word_wrap_eol = CalcWordWrapPositionA(scale, s, text_end, wrap_width - line_width);
4440 				if (word_wrap_eol == s)  // Wrap_width is too small to fit anything. Force displaying 1 character to minimize the height discontinuity.
4441 					word_wrap_eol++;     // +1 may not be a character start point in UTF-8 but it's ok because we use s >= word_wrap_eol below
4442 			}
4443 
4444 			if (s >= word_wrap_eol)
4445 			{
4446 				if (text_size.x < line_width)
4447 					text_size.x = line_width;
4448 				text_size.y += line_height;
4449 				line_width = 0.0f;
4450 				word_wrap_eol = NULL;
4451 
4452 				// Wrapping skips upcoming blanks
4453 				while (s < text_end)
4454 				{
4455 					const char c = *s;
4456 					if (ImCharIsSpace(c))
4457 					{
4458 						s++;
4459 					}
4460 					else if (c == '\n')
4461 					{
4462 						s++;
4463 						break;
4464 					}
4465 					else
4466 					{
4467 						break;
4468 					}
4469 				}
4470 				continue;
4471 			}
4472 		}
4473 
4474 		// Decode and advance source
4475 		const char* prev_s = s;
4476 		unsigned int c = (unsigned int)*s;
4477 		if (c < 0x80)
4478 		{
4479 			s += 1;
4480 		}
4481 		else
4482 		{
4483 			s += ImTextCharFromUtf8(&c, s, text_end);
4484 			if (c == 0)  // Malformed UTF-8?
4485 				break;
4486 		}
4487 
4488 		if (c < 32)
4489 		{
4490 			if (c == '\n')
4491 			{
4492 				text_size.x = ImMax(text_size.x, line_width);
4493 				text_size.y += line_height;
4494 				line_width = 0.0f;
4495 				continue;
4496 			}
4497 			if (c == '\r')
4498 				continue;
4499 		}
4500 
4501 		const float char_width = ((int)c < IndexAdvanceX.Size ? IndexAdvanceX[(int)c] : FallbackAdvanceX) * scale;
4502 		if (line_width + char_width >= max_width)
4503 		{
4504 			s = prev_s;
4505 			break;
4506 		}
4507 
4508 		line_width += char_width;
4509 	}
4510 
4511 	if (text_size.x < line_width)
4512 		text_size.x = line_width;
4513 
4514 	if (line_width > 0 || text_size.y == 0.0f)
4515 		text_size.y += line_height;
4516 
4517 	if (remaining)
4518 		*remaining = s;
4519 
4520 	return text_size;
4521 }
4522 
RenderChar(ImDrawList * draw_list,float size,ImVec2 pos,ImU32 col,unsigned short c) const4523 void ImFont::RenderChar(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col, unsigned short c) const
4524 {
4525 	if (c == ' ' || c == '\t' || c == '\n' || c == '\r')  // Match behavior of RenderText(), those 4 codepoints are hard-coded.
4526 		return;
4527 	if (const ImFontGlyph* glyph = FindGlyph(c))
4528 	{
4529 		float scale = (size >= 0.0f) ? (size / FontSize) : 1.0f;
4530 		pos.x = (float)(int)pos.x + DisplayOffset.x;
4531 		pos.y = (float)(int)pos.y + DisplayOffset.y;
4532 		draw_list->PrimReserve(6, 4);
4533 		draw_list->PrimRectUV(ImVec2(pos.x + glyph->X0 * scale, pos.y + glyph->Y0 * scale), ImVec2(pos.x + glyph->X1 * scale, pos.y + glyph->Y1 * scale), ImVec2(glyph->U0, glyph->V0), ImVec2(glyph->U1, glyph->V1), col);
4534 	}
4535 }
4536 
RenderText(ImDrawList * draw_list,float size,ImVec2 pos,ImU32 col,const ImVec4 & clip_rect,const char * text_begin,const char * text_end,float wrap_width,bool cpu_fine_clip) const4537 void ImFont::RenderText(ImDrawList* draw_list, float size, ImVec2 pos, ImU32 col, const ImVec4& clip_rect, const char* text_begin, const char* text_end, float wrap_width, bool cpu_fine_clip) const
4538 {
4539 	if (!text_end)
4540 		text_end = text_begin + strlen(text_begin);  // ImGui functions generally already provides a valid text_end, so this is merely to handle direct calls.
4541 
4542 	// Align to be pixel perfect
4543 	pos.x = (float)(int)pos.x + DisplayOffset.x;
4544 	pos.y = (float)(int)pos.y + DisplayOffset.y;
4545 	float x = pos.x;
4546 	float y = pos.y;
4547 	if (y > clip_rect.w)
4548 		return;
4549 
4550 	const float scale = size / FontSize;
4551 	const float line_height = FontSize * scale;
4552 	const bool word_wrap_enabled = (wrap_width > 0.0f);
4553 	const char* word_wrap_eol = NULL;
4554 
4555 	// Skip non-visible lines
4556 	const char* s = text_begin;
4557 	if (!word_wrap_enabled && y + line_height < clip_rect.y)
4558 		while (s < text_end && *s != '\n')  // Fast-forward to next line
4559 			s++;
4560 
4561 	// Reserve vertices for remaining worse case (over-reserving is useful and easily amortized)
4562 	const int vtx_count_max = (int)(text_end - s) * 4;
4563 	const int idx_count_max = (int)(text_end - s) * 6;
4564 	const int idx_expected_size = draw_list->IdxBuffer.Size + idx_count_max;
4565 	draw_list->PrimReserve(idx_count_max, vtx_count_max);
4566 
4567 	ImDrawVert* vtx_write = draw_list->_VtxWritePtr;
4568 	ImDrawIdx* idx_write = draw_list->_IdxWritePtr;
4569 	unsigned int vtx_current_idx = draw_list->_VtxCurrentIdx;
4570 
4571 	while (s < text_end)
4572 	{
4573 		if (word_wrap_enabled)
4574 		{
4575 			// Calculate how far we can render. Requires two passes on the string data but keeps the code simple and not intrusive for what's essentially an uncommon feature.
4576 			if (!word_wrap_eol)
4577 			{
4578 				word_wrap_eol = CalcWordWrapPositionA(scale, s, text_end, wrap_width - (x - pos.x));
4579 				if (word_wrap_eol == s)  // Wrap_width is too small to fit anything. Force displaying 1 character to minimize the height discontinuity.
4580 					word_wrap_eol++;     // +1 may not be a character start point in UTF-8 but it's ok because we use s >= word_wrap_eol below
4581 			}
4582 
4583 			if (s >= word_wrap_eol)
4584 			{
4585 				x = pos.x;
4586 				y += line_height;
4587 				word_wrap_eol = NULL;
4588 
4589 				// Wrapping skips upcoming blanks
4590 				while (s < text_end)
4591 				{
4592 					const char c = *s;
4593 					if (ImCharIsSpace(c))
4594 					{
4595 						s++;
4596 					}
4597 					else if (c == '\n')
4598 					{
4599 						s++;
4600 						break;
4601 					}
4602 					else
4603 					{
4604 						break;
4605 					}
4606 				}
4607 				continue;
4608 			}
4609 		}
4610 
4611 		// Decode and advance source
4612 		unsigned int c = (unsigned int)*s;
4613 		if (c < 0x80)
4614 		{
4615 			s += 1;
4616 		}
4617 		else
4618 		{
4619 			s += ImTextCharFromUtf8(&c, s, text_end);
4620 			if (c == 0)  // Malformed UTF-8?
4621 				break;
4622 		}
4623 
4624 		if (c < 32)
4625 		{
4626 			if (c == '\n')
4627 			{
4628 				x = pos.x;
4629 				y += line_height;
4630 
4631 				if (y > clip_rect.w)
4632 					break;
4633 				if (!word_wrap_enabled && y + line_height < clip_rect.y)
4634 					while (s < text_end && *s != '\n')  // Fast-forward to next line
4635 						s++;
4636 				continue;
4637 			}
4638 			if (c == '\r')
4639 				continue;
4640 		}
4641 
4642 		float char_width = 0.0f;
4643 		if (const ImFontGlyph* glyph = FindGlyph((unsigned short)c))
4644 		{
4645 			char_width = glyph->AdvanceX * scale;
4646 
4647 			// Arbitrarily assume that both space and tabs are empty glyphs as an optimization
4648 			if (c != ' ' && c != '\t')
4649 			{
4650 				// We don't do a second finer clipping test on the Y axis as we've already skipped anything before clip_rect.y and exit once we pass clip_rect.w
4651 				float x1 = x + glyph->X0 * scale;
4652 				float x2 = x + glyph->X1 * scale;
4653 				float y1 = y + glyph->Y0 * scale;
4654 				float y2 = y + glyph->Y1 * scale;
4655 				if (x1 <= clip_rect.z && x2 >= clip_rect.x)
4656 				{
4657 					// Render a character
4658 					float u1 = glyph->U0;
4659 					float v1 = glyph->V0;
4660 					float u2 = glyph->U1;
4661 					float v2 = glyph->V1;
4662 
4663 					// CPU side clipping used to fit text in their frame when the frame is too small. Only does clipping for axis aligned quads.
4664 					if (cpu_fine_clip)
4665 					{
4666 						if (x1 < clip_rect.x)
4667 						{
4668 							u1 = u1 + (1.0f - (x2 - clip_rect.x) / (x2 - x1)) * (u2 - u1);
4669 							x1 = clip_rect.x;
4670 						}
4671 						if (y1 < clip_rect.y)
4672 						{
4673 							v1 = v1 + (1.0f - (y2 - clip_rect.y) / (y2 - y1)) * (v2 - v1);
4674 							y1 = clip_rect.y;
4675 						}
4676 						if (x2 > clip_rect.z)
4677 						{
4678 							u2 = u1 + ((clip_rect.z - x1) / (x2 - x1)) * (u2 - u1);
4679 							x2 = clip_rect.z;
4680 						}
4681 						if (y2 > clip_rect.w)
4682 						{
4683 							v2 = v1 + ((clip_rect.w - y1) / (y2 - y1)) * (v2 - v1);
4684 							y2 = clip_rect.w;
4685 						}
4686 						if (y1 >= y2)
4687 						{
4688 							x += char_width;
4689 							continue;
4690 						}
4691 					}
4692 
4693 					// We are NOT calling PrimRectUV() here because non-inlined causes too much overhead in a debug builds. Inlined here:
4694 					{
4695 						idx_write[0] = (ImDrawIdx)(vtx_current_idx);
4696 						idx_write[1] = (ImDrawIdx)(vtx_current_idx + 1);
4697 						idx_write[2] = (ImDrawIdx)(vtx_current_idx + 2);
4698 						idx_write[3] = (ImDrawIdx)(vtx_current_idx);
4699 						idx_write[4] = (ImDrawIdx)(vtx_current_idx + 2);
4700 						idx_write[5] = (ImDrawIdx)(vtx_current_idx + 3);
4701 						vtx_write[0].pos.x = x1;
4702 						vtx_write[0].pos.y = y1;
4703 						vtx_write[0].col = col;
4704 						vtx_write[0].uv.x = u1;
4705 						vtx_write[0].uv.y = v1;
4706 						vtx_write[1].pos.x = x2;
4707 						vtx_write[1].pos.y = y1;
4708 						vtx_write[1].col = col;
4709 						vtx_write[1].uv.x = u2;
4710 						vtx_write[1].uv.y = v1;
4711 						vtx_write[2].pos.x = x2;
4712 						vtx_write[2].pos.y = y2;
4713 						vtx_write[2].col = col;
4714 						vtx_write[2].uv.x = u2;
4715 						vtx_write[2].uv.y = v2;
4716 						vtx_write[3].pos.x = x1;
4717 						vtx_write[3].pos.y = y2;
4718 						vtx_write[3].col = col;
4719 						vtx_write[3].uv.x = u1;
4720 						vtx_write[3].uv.y = v2;
4721 						vtx_write += 4;
4722 						vtx_current_idx += 4;
4723 						idx_write += 6;
4724 					}
4725 				}
4726 			}
4727 		}
4728 
4729 		x += char_width;
4730 	}
4731 
4732 	// Give back unused vertices
4733 	draw_list->VtxBuffer.resize((int)(vtx_write - draw_list->VtxBuffer.Data));
4734 	draw_list->IdxBuffer.resize((int)(idx_write - draw_list->IdxBuffer.Data));
4735 	draw_list->CmdBuffer[draw_list->CmdBuffer.Size - 1].ElemCount -= (idx_expected_size - draw_list->IdxBuffer.Size);
4736 	draw_list->_VtxWritePtr = vtx_write;
4737 	draw_list->_IdxWritePtr = idx_write;
4738 	draw_list->_VtxCurrentIdx = (unsigned int)draw_list->VtxBuffer.Size;
4739 }
4740 
4741 //-----------------------------------------------------------------------------
4742 // Internals Drawing Helpers
4743 //-----------------------------------------------------------------------------
4744 
ImAcos01(float x)4745 static inline float ImAcos01(float x)
4746 {
4747 	if (x <= 0.0f) return IM_PI * 0.5f;
4748 	if (x >= 1.0f) return 0.0f;
4749 	return acosf(x);
4750 	//return (-0.69813170079773212f * x * x - 0.87266462599716477f) * x + 1.5707963267948966f; // Cheap approximation, may be enough for what we do.
4751 }
4752 
4753 // FIXME: Cleanup and move code to ImDrawList.
RenderRectFilledRangeH(ImDrawList * draw_list,const ImRect & rect,ImU32 col,float x_start_norm,float x_end_norm,float rounding)4754 void ImGui::RenderRectFilledRangeH(ImDrawList* draw_list, const ImRect& rect, ImU32 col, float x_start_norm, float x_end_norm, float rounding)
4755 {
4756 	if (x_end_norm == x_start_norm)
4757 		return;
4758 	if (x_start_norm > x_end_norm)
4759 		ImSwap(x_start_norm, x_end_norm);
4760 
4761 	ImVec2 p0 = ImVec2(ImLerp(rect.Min.x, rect.Max.x, x_start_norm), rect.Min.y);
4762 	ImVec2 p1 = ImVec2(ImLerp(rect.Min.x, rect.Max.x, x_end_norm), rect.Max.y);
4763 	if (rounding == 0.0f)
4764 	{
4765 		draw_list->AddRectFilled(p0, p1, col, 0.0f);
4766 		return;
4767 	}
4768 
4769 	rounding = ImClamp(ImMin((rect.Max.x - rect.Min.x) * 0.5f, (rect.Max.y - rect.Min.y) * 0.5f) - 1.0f, 0.0f, rounding);
4770 	const float inv_rounding = 1.0f / rounding;
4771 	const float arc0_b = ImAcos01(1.0f - (p0.x - rect.Min.x) * inv_rounding);
4772 	const float arc0_e = ImAcos01(1.0f - (p1.x - rect.Min.x) * inv_rounding);
4773 	const float x0 = ImMax(p0.x, rect.Min.x + rounding);
4774 	if (arc0_b == arc0_e)
4775 	{
4776 		draw_list->PathLineTo(ImVec2(x0, p1.y));
4777 		draw_list->PathLineTo(ImVec2(x0, p0.y));
4778 	}
4779 	else if (arc0_b == 0.0f && arc0_e == IM_PI * 0.5f)
4780 	{
4781 		draw_list->PathArcToFast(ImVec2(x0, p1.y - rounding), rounding, 3, 6);  // BL
4782 		draw_list->PathArcToFast(ImVec2(x0, p0.y + rounding), rounding, 6, 9);  // TR
4783 	}
4784 	else
4785 	{
4786 		draw_list->PathArcTo(ImVec2(x0, p1.y - rounding), rounding, IM_PI - arc0_e, IM_PI - arc0_b, 3);  // BL
4787 		draw_list->PathArcTo(ImVec2(x0, p0.y + rounding), rounding, IM_PI + arc0_b, IM_PI + arc0_e, 3);  // TR
4788 	}
4789 	if (p1.x > rect.Min.x + rounding)
4790 	{
4791 		const float arc1_b = ImAcos01(1.0f - (rect.Max.x - p1.x) * inv_rounding);
4792 		const float arc1_e = ImAcos01(1.0f - (rect.Max.x - p0.x) * inv_rounding);
4793 		const float x1 = ImMin(p1.x, rect.Max.x - rounding);
4794 		if (arc1_b == arc1_e)
4795 		{
4796 			draw_list->PathLineTo(ImVec2(x1, p0.y));
4797 			draw_list->PathLineTo(ImVec2(x1, p1.y));
4798 		}
4799 		else if (arc1_b == 0.0f && arc1_e == IM_PI * 0.5f)
4800 		{
4801 			draw_list->PathArcToFast(ImVec2(x1, p0.y + rounding), rounding, 9, 12);  // TR
4802 			draw_list->PathArcToFast(ImVec2(x1, p1.y - rounding), rounding, 0, 3);   // BR
4803 		}
4804 		else
4805 		{
4806 			draw_list->PathArcTo(ImVec2(x1, p0.y + rounding), rounding, -arc1_e, -arc1_b, 3);  // TR
4807 			draw_list->PathArcTo(ImVec2(x1, p1.y - rounding), rounding, +arc1_b, +arc1_e, 3);  // BR
4808 		}
4809 	}
4810 	draw_list->PathFillConvex(col);
4811 }
4812 
4813 //-----------------------------------------------------------------------------
4814 // DEFAULT FONT DATA
4815 //-----------------------------------------------------------------------------
4816 // Compressed with stb_compress() then converted to a C array.
4817 // Use the program in misc/fonts/binary_to_compressed_c.cpp to create the array from a TTF file.
4818 // Decompression from stb.h (public domain) by Sean Barrett https://github.com/nothings/stb/blob/master/stb.h
4819 //-----------------------------------------------------------------------------
4820 
stb_decompress_length(unsigned char * input)4821 static unsigned int stb_decompress_length(unsigned char* input)
4822 {
4823 	return (input[8] << 24) + (input[9] << 16) + (input[10] << 8) + input[11];
4824 }
4825 
4826 static unsigned char *stb__barrier, *stb__barrier2, *stb__barrier3, *stb__barrier4;
4827 static unsigned char* stb__dout;
stb__match(unsigned char * data,unsigned int length)4828 static void stb__match(unsigned char* data, unsigned int length)
4829 {
4830 	// INVERSE of memmove... write each byte before copying the next...
4831 	IM_ASSERT(stb__dout + length <= stb__barrier);
4832 	if (stb__dout + length > stb__barrier)
4833 	{
4834 		stb__dout += length;
4835 		return;
4836 	}
4837 	if (data < stb__barrier4)
4838 	{
4839 		stb__dout = stb__barrier + 1;
4840 		return;
4841 	}
4842 	while (length--) *stb__dout++ = *data++;
4843 }
4844 
stb__lit(unsigned char * data,unsigned int length)4845 static void stb__lit(unsigned char* data, unsigned int length)
4846 {
4847 	IM_ASSERT(stb__dout + length <= stb__barrier);
4848 	if (stb__dout + length > stb__barrier)
4849 	{
4850 		stb__dout += length;
4851 		return;
4852 	}
4853 	if (data < stb__barrier2)
4854 	{
4855 		stb__dout = stb__barrier + 1;
4856 		return;
4857 	}
4858 	memcpy(stb__dout, data, length);
4859 	stb__dout += length;
4860 }
4861 
4862 #define stb__in2(x) ((i[x] << 8) + i[(x) + 1])
4863 #define stb__in3(x) ((i[x] << 16) + stb__in2((x) + 1))
4864 #define stb__in4(x) ((i[x] << 24) + stb__in3((x) + 1))
4865 
stb_decompress_token(unsigned char * i)4866 static unsigned char* stb_decompress_token(unsigned char* i)
4867 {
4868 	if (*i >= 0x20)
4869 	{  // use fewer if's for cases that expand small
4870 		if (*i >= 0x80)
4871 			stb__match(stb__dout - i[1] - 1, i[0] - 0x80 + 1), i += 2;
4872 		else if (*i >= 0x40)
4873 			stb__match(stb__dout - (stb__in2(0) - 0x4000 + 1), i[2] + 1), i += 3;
4874 		else /* *i >= 0x20 */
4875 			stb__lit(i + 1, i[0] - 0x20 + 1), i += 1 + (i[0] - 0x20 + 1);
4876 	}
4877 	else
4878 	{  // more ifs for cases that expand large, since overhead is amortized
4879 		if (*i >= 0x18)
4880 			stb__match(stb__dout - (stb__in3(0) - 0x180000 + 1), i[3] + 1), i += 4;
4881 		else if (*i >= 0x10)
4882 			stb__match(stb__dout - (stb__in3(0) - 0x100000 + 1), stb__in2(3) + 1), i += 5;
4883 		else if (*i >= 0x08)
4884 			stb__lit(i + 2, stb__in2(0) - 0x0800 + 1), i += 2 + (stb__in2(0) - 0x0800 + 1);
4885 		else if (*i == 0x07)
4886 			stb__lit(i + 3, stb__in2(1) + 1), i += 3 + (stb__in2(1) + 1);
4887 		else if (*i == 0x06)
4888 			stb__match(stb__dout - (stb__in3(1) + 1), i[4] + 1), i += 5;
4889 		else if (*i == 0x04)
4890 			stb__match(stb__dout - (stb__in3(1) + 1), stb__in2(4) + 1), i += 6;
4891 	}
4892 	return i;
4893 }
4894 
stb_adler32(unsigned int adler32,unsigned char * buffer,unsigned int buflen)4895 static unsigned int stb_adler32(unsigned int adler32, unsigned char* buffer, unsigned int buflen)
4896 {
4897 	const unsigned long ADLER_MOD = 65521;
4898 	unsigned long s1 = adler32 & 0xffff, s2 = adler32 >> 16;
4899 	unsigned long blocklen, i;
4900 
4901 	blocklen = buflen % 5552;
4902 	while (buflen)
4903 	{
4904 		for (i = 0; i + 7 < blocklen; i += 8)
4905 		{
4906 			s1 += buffer[0], s2 += s1;
4907 			s1 += buffer[1], s2 += s1;
4908 			s1 += buffer[2], s2 += s1;
4909 			s1 += buffer[3], s2 += s1;
4910 			s1 += buffer[4], s2 += s1;
4911 			s1 += buffer[5], s2 += s1;
4912 			s1 += buffer[6], s2 += s1;
4913 			s1 += buffer[7], s2 += s1;
4914 
4915 			buffer += 8;
4916 		}
4917 
4918 		for (; i < blocklen; ++i)
4919 			s1 += *buffer++, s2 += s1;
4920 
4921 		s1 %= ADLER_MOD, s2 %= ADLER_MOD;
4922 		buflen -= blocklen;
4923 		blocklen = 5552;
4924 	}
4925 	return (unsigned int)(s2 << 16) + (unsigned int)s1;
4926 }
4927 
stb_decompress(unsigned char * output,unsigned char * i,unsigned int length)4928 static unsigned int stb_decompress(unsigned char* output, unsigned char* i, unsigned int length)
4929 {
4930 	unsigned int olen;
4931 	if (stb__in4(0) != 0x57bC0000) return 0;
4932 	if (stb__in4(4) != 0) return 0;  // error! stream is > 4GB
4933 	olen = stb_decompress_length(i);
4934 	stb__barrier2 = i;
4935 	stb__barrier3 = i + length;
4936 	stb__barrier = output + olen;
4937 	stb__barrier4 = output;
4938 	i += 16;
4939 
4940 	stb__dout = output;
4941 	for (;;)
4942 	{
4943 		unsigned char* old_i = i;
4944 		i = stb_decompress_token(i);
4945 		if (i == old_i)
4946 		{
4947 			if (*i == 0x05 && i[1] == 0xfa)
4948 			{
4949 				IM_ASSERT(stb__dout == output + olen);
4950 				if (stb__dout != output + olen) return 0;
4951 				if (stb_adler32(1, output, olen) != (unsigned int)stb__in4(2))
4952 					return 0;
4953 				return olen;
4954 			}
4955 			else
4956 			{
4957 				IM_ASSERT(0); /* NOTREACHED */
4958 				return 0;
4959 			}
4960 		}
4961 		IM_ASSERT(stb__dout <= output + olen);
4962 		if (stb__dout > output + olen)
4963 			return 0;
4964 	}
4965 }
4966 
4967 //-----------------------------------------------------------------------------
4968 // ProggyClean.ttf
4969 // Copyright (c) 2004, 2005 Tristan Grimmer
4970 // MIT license (see License.txt in http://www.upperbounds.net/download/ProggyClean.ttf.zip)
4971 // Download and more information at http://upperbounds.net
4972 //-----------------------------------------------------------------------------
4973 // File: 'ProggyClean.ttf' (41208 bytes)
4974 // Exported using binary_to_compressed_c.cpp
4975 //-----------------------------------------------------------------------------
4976 static const char proggy_clean_ttf_compressed_data_base85[11980 + 1] =
4977 	"7])#######hV0qs'/###[),##/l:$#Q6>##5[n42>c-TH`->>#/e>11NNV=Bv(*:.F?uu#(gRU.o0XGH`$vhLG1hxt9?W`#,5LsCp#-i>.r$<$6pD>Lb';9Crc6tgXmKVeU2cD4Eo3R/"
4978 	"2*>]b(MC;$jPfY.;h^`IWM9<Lh2TlS+f-s$o6Q<BWH`YiU.xfLq$N;$0iR/GX:U(jcW2p/W*q?-qmnUCI;jHSAiFWM.R*kU@C=GH?a9wp8f$e.-4^Qg1)Q-GL(lf(r/7GrRgwV%MS=C#"
4979 	"`8ND>Qo#t'X#(v#Y9w0#1D$CIf;W'#pWUPXOuxXuU(H9M(1<q-UE31#^-V'8IRUo7Qf./L>=Ke$$'5F%)]0^#0X@U.a<r:QLtFsLcL6##lOj)#.Y5<-R&KgLwqJfLgN&;Q?gI^#DY2uL"
4980 	"i@^rMl9t=cWq6##weg>$FBjVQTSDgEKnIS7EM9>ZY9w0#L;>>#Mx&4Mvt//L[MkA#W@lK.N'[0#7RL_&#w+F%HtG9M#XL`N&.,GM4Pg;-<nLENhvx>-VsM.M0rJfLH2eTM`*oJMHRC`N"
4981 	"kfimM2J,W-jXS:)r0wK#@Fge$U>`w'N7G#$#fB#$E^$#:9:hk+eOe--6x)F7*E%?76%^GMHePW-Z5l'&GiF#$956:rS?dA#fiK:)Yr+`&#0j@'DbG&#^$PG.Ll+DNa<XCMKEV*N)LN/N"
4982 	"*b=%Q6pia-Xg8I$<MR&,VdJe$<(7G;Ckl'&hF;;$<_=X(b.RS%%)###MPBuuE1V:v&cX&#2m#(&cV]`k9OhLMbn%s$G2,B$BfD3X*sp5#l,$R#]x_X1xKX%b5U*[r5iMfUo9U`N99hG)"
4983 	"tm+/Us9pG)XPu`<0s-)WTt(gCRxIg(%6sfh=ktMKn3j)<6<b5Sk_/0(^]AaN#(p/L>&VZ>1i%h1S9u5o@YaaW$e+b<TWFn/Z:Oh(Cx2$lNEoN^e)#CFY@@I;BOQ*sRwZtZxRcU7uW6CX"
4984 	"ow0i(?$Q[cjOd[P4d)]>ROPOpxTO7Stwi1::iB1q)C_=dV26J;2,]7op$]uQr@_V7$q^%lQwtuHY]=DX,n3L#0PHDO4f9>dC@O>HBuKPpP*E,N+b3L#lpR/MrTEH.IAQk.a>D[.e;mc."
4985 	"x]Ip.PH^'/aqUO/$1WxLoW0[iLA<QT;5HKD+@qQ'NQ(3_PLhE48R.qAPSwQ0/WK?Z,[x?-J;jQTWA0X@KJ(_Y8N-:/M74:/-ZpKrUss?d#dZq]DAbkU*JqkL+nwX@@47`5>w=4h(9.`G"
4986 	"CRUxHPeR`5Mjol(dUWxZa(>STrPkrJiWx`5U7F#.g*jrohGg`cg:lSTvEY/EV_7H4Q9[Z%cnv;JQYZ5q.l7Zeas:HOIZOB?G<Nald$qs]@]L<J7bR*>gv:[7MI2k).'2($5FNP&EQ(,)"
4987 	"U]W]+fh18.vsai00);D3@4ku5P?DP8aJt+;qUM]=+b'8@;mViBKx0DE[-auGl8:PJ&Dj+M6OC]O^((##]`0i)drT;-7X`=-H3[igUnPG-NZlo.#k@h#=Ork$m>a>$-?Tm$UV(?#P6YY#"
4988 	"'/###xe7q.73rI3*pP/$1>s9)W,JrM7SN]'/4C#v$U`0#V.[0>xQsH$fEmPMgY2u7Kh(G%siIfLSoS+MK2eTM$=5,M8p`A.;_R%#u[K#$x4AG8.kK/HSB==-'Ie/QTtG?-.*^N-4B/ZM"
4989 	"_3YlQC7(p7q)&](`6_c)$/*JL(L-^(]$wIM`dPtOdGA,U3:w2M-0<q-]L_?^)1vw'.,MRsqVr.L;aN&#/EgJ)PBc[-f>+WomX2u7lqM2iEumMTcsF?-aT=Z-97UEnXglEn1K-bnEO`gu"
4990 	"Ft(c%=;Am_Qs@jLooI&NX;]0#j4#F14;gl8-GQpgwhrq8'=l_f-b49'UOqkLu7-##oDY2L(te+Mch&gLYtJ,MEtJfLh'x'M=$CS-ZZ%P]8bZ>#S?YY#%Q&q'3^Fw&?D)UDNrocM3A76/"
4991 	"/oL?#h7gl85[qW/NDOk%16ij;+:1a'iNIdb-ou8.P*w,v5#EI$TWS>Pot-R*H'-SEpA:g)f+O$%%`kA#G=8RMmG1&O`>to8bC]T&$,n.LoO>29sp3dt-52U%VM#q7'DHpg+#Z9%H[K<L"
4992 	"%a2E-grWVM3@2=-k22tL]4$##6We'8UJCKE[d_=%wI;'6X-GsLX4j^SgJ$##R*w,vP3wK#iiW&#*h^D&R?jp7+/u&#(AP##XU8c$fSYW-J95_-Dp[g9wcO&#M-h1OcJlc-*vpw0xUX&#"
4993 	"OQFKNX@QI'IoPp7nb,QU//MQ&ZDkKP)X<WSVL(68uVl&#c'[0#(s1X&xm$Y%B7*K:eDA323j998GXbA#pwMs-jgD$9QISB-A_(aN4xoFM^@C58D0+Q+q3n0#3U1InDjF682-SjMXJK)("
4994 	"h$hxua_K]ul92%'BOU&#BRRh-slg8KDlr:%L71Ka:.A;%YULjDPmL<LYs8i#XwJOYaKPKc1h:'9Ke,g)b),78=I39B;xiY$bgGw-&.Zi9InXDuYa%G*f2Bq7mn9^#p1vv%#(Wi-;/Z5h"
4995 	"o;#2:;%d&#x9v68C5g?ntX0X)pT`;%pB3q7mgGN)3%(P8nTd5L7GeA-GL@+%J3u2:(Yf>et`e;)f#Km8&+DC$I46>#Kr]]u-[=99tts1.qb#q72g1WJO81q+eN'03'eM>&1XxY-caEnO"
4996 	"j%2n8)),?ILR5^.Ibn<-X-Mq7[a82Lq:F&#ce+S9wsCK*x`569E8ew'He]h:sI[2LM$[guka3ZRd6:t%IG:;$%YiJ:Nq=?eAw;/:nnDq0(CYcMpG)qLN4$##&J<j$UpK<Q4a1]MupW^-"
4997 	"sj_$%[HK%'F####QRZJ::Y3EGl4'@%FkiAOg#p[##O`gukTfBHagL<LHw%q&OV0##F=6/:chIm0@eCP8X]:kFI%hl8hgO@RcBhS-@Qb$%+m=hPDLg*%K8ln(wcf3/'DW-$.lR?n[nCH-"
4998 	"eXOONTJlh:.RYF%3'p6sq:UIMA945&^HFS87@$EP2iG<-lCO$%c`uKGD3rC$x0BL8aFn--`ke%#HMP'vh1/R&O_J9'um,.<tx[@%wsJk&bUT2`0uMv7gg#qp/ij.L56'hl;.s5CUrxjO"
4999 	"M7-##.l+Au'A&O:-T72L]P`&=;ctp'XScX*rU.>-XTt,%OVU4)S1+R-#dg0/Nn?Ku1^0f$B*P:Rowwm-`0PKjYDDM'3]d39VZHEl4,.j']Pk-M.h^&:0FACm$maq-&sgw0t7/6(^xtk%"
5000 	"LuH88Fj-ekm>GA#_>568x6(OFRl-IZp`&b,_P'$M<Jnq79VsJW/mWS*PUiq76;]/NM_>hLbxfc$mj`,O;&%W2m`Zh:/)Uetw:aJ%]K9h:TcF]u_-Sj9,VK3M.*'&0D[Ca]J9gp8,kAW]"
5001 	"%(?A%R$f<->Zts'^kn=-^@c4%-pY6qI%J%1IGxfLU9CP8cbPlXv);C=b),<2mOvP8up,UVf3839acAWAW-W?#ao/^#%KYo8fRULNd2.>%m]UK:n%r$'sw]J;5pAoO_#2mO3n,'=H5(et"
5002 	"Hg*`+RLgv>=4U8guD$I%D:W>-r5V*%j*W:Kvej.Lp$<M-SGZ':+Q_k+uvOSLiEo(<aD/K<CCc`'Lx>'?;++O'>()jLR-^u68PHm8ZFWe+ej8h:9r6L*0//c&iH&R8pRbA#Kjm%upV1g:"
5003 	"a_#Ur7FuA#(tRh#.Y5K+@?3<-8m0$PEn;J:rh6?I6uG<-`wMU'ircp0LaE_OtlMb&1#6T.#FDKu#1Lw%u%+GM+X'e?YLfjM[VO0MbuFp7;>Q&#WIo)0@F%q7c#4XAXN-U&VB<HFF*qL("
5004 	"$/V,;(kXZejWO`<[5?\?ewY(*9=%wDc;,u<'9t3W-(H1th3+G]ucQ]kLs7df($/*JL]@*t7Bu_G3_7mp7<iaQjO@.kLg;x3B0lqp7Hf,^Ze7-##@/c58Mo(3;knp0%)A7?-W+eI'o8)b<"
5005 	"nKnw'Ho8C=Y>pqB>0ie&jhZ[?iLR@@_AvA-iQC(=ksRZRVp7`.=+NpBC%rh&3]R:8XDmE5^V8O(x<<aG/1N$#FX$0V5Y6x'aErI3I$7x%E`v<-BY,)%-?Psf*l?%C3.mM(=/M0:JxG'?"
5006 	"7WhH%o'a<-80g0NBxoO(GH<dM]n.+%q@jH?f.UsJ2Ggs&4<-e47&Kl+f//9@`b+?.TeN_&B8Ss?v;^Trk;f#YvJkl&w$]>-+k?'(<S:68tq*WoDfZu';mM?8X[ma8W%*`-=;D.(nc7/;"
5007 	")g:T1=^J$&BRV(-lTmNB6xqB[@0*o.erM*<SWF]u2=st-*(6v>^](H.aREZSi,#1:[IXaZFOm<-ui#qUq2$##Ri;u75OK#(RtaW-K-F`S+cF]uN`-KMQ%rP/Xri.LRcB##=YL3BgM/3M"
5008 	"D?@f&1'BW-)Ju<L25gl8uhVm1hL$##*8###'A3/LkKW+(^rWX?5W_8g)a(m&K8P>#bmmWCMkk&#TR`C,5d>g)F;t,4:@_l8G/5h4vUd%&%950:VXD'QdWoY-F$BtUwmfe$YqL'8(PWX("
5009 	"P?^@Po3$##`MSs?DWBZ/S>+4%>fX,VWv/w'KD`LP5IbH;rTV>n3cEK8U#bX]l-/V+^lj3;vlMb&[5YQ8#pekX9JP3XUC72L,,?+Ni&co7ApnO*5NK,((W-i:$,kp'UDAO(G0Sq7MVjJs"
5010 	"bIu)'Z,*[>br5fX^:FPAWr-m2KgL<LUN098kTF&#lvo58=/vjDo;.;)Ka*hLR#/k=rKbxuV`>Q_nN6'8uTG&#1T5g)uLv:873UpTLgH+#FgpH'_o1780Ph8KmxQJ8#H72L4@768@Tm&Q"
5011 	"h4CB/5OvmA&,Q&QbUoi$a_%3M01H)4x7I^&KQVgtFnV+;[Pc>[m4k//,]1?#`VY[Jr*3&&slRfLiVZJ:]?=K3Sw=[$=uRB?3xk48@aeg<Z'<$#4H)6,>e0jT6'N#(q%.O=?2S]u*(m<-"
5012 	"V8J'(1)G][68hW$5'q[GC&5j`TE?m'esFGNRM)j,ffZ?-qx8;->g4t*:CIP/[Qap7/9'#(1sao7w-.qNUdkJ)tCF&#B^;xGvn2r9FEPFFFcL@.iFNkTve$m%#QvQS8U@)2Z+3K:AKM5i"
5013 	"sZ88+dKQ)W6>J%CL<KE>`.d*(B`-n8D9oK<Up]c$X$(,)M8Zt7/[rdkqTgl-0cuGMv'?>-XV1q['-5k'cAZ69e;D_?$ZPP&s^+7])$*$#@QYi9,5P&#9r+$%CE=68>K8r0=dSC%%(@p7"
5014 	".m7jilQ02'0-VWAg<a/''3u.=4L$Y)6k/K:_[3=&jvL<L0C/2'v:^;-DIBW,B4E68:kZ;%?8(Q8BH=kO65BW?xSG&#@uU,DS*,?.+(o(#1vCS8#CHF>TlGW'b)Tq7VT9q^*^$$.:&N@@"
5015 	"$&)WHtPm*5_rO0&e%K&#-30j(E4#'Zb.o/(Tpm$>K'f@[PvFl,hfINTNU6u'0pao7%XUp9]5.>%h`8_=VYbxuel.NTSsJfLacFu3B'lQSu/m6-Oqem8T+oE--$0a/k]uj9EwsG>%veR*"
5016 	"hv^BFpQj:K'#SJ,sB-'#](j.Lg92rTw-*n%@/;39rrJF,l#qV%OrtBeC6/,;qB3ebNW[?,Hqj2L.1NP&GjUR=1D8QaS3Up&@*9wP?+lo7b?@%'k4`p0Z$22%K3+iCZj?XJN4Nm&+YF]u"
5017 	"@-W$U%VEQ/,,>>#)D<h#`)h0:<Q6909ua+&VU%n2:cG3FJ-%@Bj-DgLr`Hw&HAKjKjseK</xKT*)B,N9X3]krc12t'pgTV(Lv-tL[xg_%=M_q7a^x?7Ubd>#%8cY#YZ?=,`Wdxu/ae&#"
5018 	"w6)R89tI#6@s'(6Bf7a&?S=^ZI_kS&ai`&=tE72L_D,;^R)7[$s<Eh#c&)q.MXI%#v9ROa5FZO%sF7q7Nwb&#ptUJ:aqJe$Sl68%.D###EC><?-aF&#RNQv>o8lKN%5/$(vdfq7+ebA#"
5019 	"u1p]ovUKW&Y%q]'>$1@-[xfn$7ZTp7mM,G,Ko7a&Gu%G[RMxJs[0MM%wci.LFDK)(<c`Q8N)jEIF*+?P2a8g%)$q]o2aH8C&<SibC/q,(e:v;-b#6[$NtDZ84Je2KNvB#$P5?tQ3nt(0"
5020 	"d=j.LQf./Ll33+(;q3L-w=8dX$#WF&uIJ@-bfI>%:_i2B5CsR8&9Z&#=mPEnm0f`<&c)QL5uJ#%u%lJj+D-r;BoF&#4DoS97h5g)E#o:&S4weDF,9^Hoe`h*L+_a*NrLW-1pG_&2UdB8"
5021 	"6e%B/:=>)N4xeW.*wft-;$'58-ESqr<b?UI(_%@[P46>#U`'6AQ]m&6/`Z>#S?YY#Vc;r7U2&326d=w&H####?TZ`*4?&.MK?LP8Vxg>$[QXc%QJv92.(Db*B)gb*BM9dM*hJMAo*c&#"
5022 	"b0v=Pjer]$gG&JXDf->'StvU7505l9$AFvgYRI^&<^b68?j#q9QX4SM'RO#&sL1IM.rJfLUAj221]d##DW=m83u5;'bYx,*Sl0hL(W;;$doB&O/TQ:(Z^xBdLjL<Lni;''X.`$#8+1GD"
5023 	":k$YUWsbn8ogh6rxZ2Z9]%nd+>V#*8U_72Lh+2Q8Cj0i:6hp&$C/:p(HK>T8Y[gHQ4`4)'$Ab(Nof%V'8hL&#<NEdtg(n'=S1A(Q1/I&4([%dM`,Iu'1:_hL>SfD07&6D<fp8dHM7/g+"
5024 	"tlPN9J*rKaPct&?'uBCem^jn%9_K)<,C5K3s=5g&GmJb*[SYq7K;TRLGCsM-$$;S%:Y@r7AK0pprpL<Lrh,q7e/%KWK:50I^+m'vi`3?%Zp+<-d+$L-Sv:@.o19n$s0&39;kn;S%BSq*"
5025 	"$3WoJSCLweV[aZ'MQIjO<7;X-X;&+dMLvu#^UsGEC9WEc[X(wI7#2.(F0jV*eZf<-Qv3J-c+J5AlrB#$p(H68LvEA'q3n0#m,[`*8Ft)FcYgEud]CWfm68,(aLA$@EFTgLXoBq/UPlp7"
5026 	":d[/;r_ix=:TF`S5H-b<LI&HY(K=h#)]Lk$K14lVfm:x$H<3^Ql<M`$OhapBnkup'D#L$Pb_`N*g]2e;X/Dtg,bsj&K#2[-:iYr'_wgH)NUIR8a1n#S?Yej'h8^58UbZd+^FKD*T@;6A"
5027 	"7aQC[K8d-(v6GI$x:T<&'Gp5Uf>@M.*J:;$-rv29'M]8qMv-tLp,'886iaC=Hb*YJoKJ,(j%K=H`K.v9HggqBIiZu'QvBT.#=)0ukruV&.)3=(^1`o*Pj4<-<aN((^7('#Z0wK#5GX@7"
5028 	"u][`*S^43933A4rl][`*O4CgLEl]v$1Q3AeF37dbXk,.)vj#x'd`;qgbQR%FW,2(?LO=s%Sc68%NP'##Aotl8x=BE#j1UD([3$M(]UI2LX3RpKN@;/#f'f/&_mt&F)XdF<9t4)Qa.*kT"
5029 	"LwQ'(TTB9.xH'>#MJ+gLq9-##@HuZPN0]u:h7.T..G:;$/Usj(T7`Q8tT72LnYl<-qx8;-HV7Q-&Xdx%1a,hC=0u+HlsV>nuIQL-5<N?)NBS)QN*_I,?&)2'IM%L3I)X((e/dl2&8'<M"
5030 	":^#M*Q+[T.Xri.LYS3v%fF`68h;b-X[/En'CR.q7E)p'/kle2HM,u;^%OKC-N+Ll%F9CF<Nf'^#t2L,;27W:0O@6##U6W7:$rJfLWHj$#)woqBefIZ.PK<b*t7ed;p*_m;4ExK#h@&]>"
5031 	"_>@kXQtMacfD.m-VAb8;IReM3$wf0''hra*so568'Ip&vRs849'MRYSp%:t:h5qSgwpEr$B>Q,;s(C#$)`svQuF$##-D,##,g68@2[T;.XSdN9Qe)rpt._K-#5wF)sP'##p#C0c%-Gb%"
5032 	"hd+<-j'Ai*x&&HMkT]C'OSl##5RG[JXaHN;d'uA#x._U;.`PU@(Z3dt4r152@:v,'R.Sj'w#0<-;kPI)FfJ&#AYJ&#//)>-k=m=*XnK$>=)72L]0I%>.G690a:$##<,);?;72#?x9+d;"
5033 	"^V'9;jY@;)br#q^YQpx:X#Te$Z^'=-=bGhLf:D6&bNwZ9-ZD#n^9HhLMr5G;']d&6'wYmTFmL<LD)F^%[tC'8;+9E#C$g%#5Y>q9wI>P(9mI[>kC-ekLC/R&CH+s'B;K-M6$EB%is00:"
5034 	"+A4[7xks.LrNk0&E)wILYF@2L'0Nb$+pv<(2.768/FrY&h$^3i&@+G%JT'<-,v`3;_)I9M^AE]CN?Cl2AZg+%4iTpT3<n-&%H%b<FDj2M<hH=&Eh<2Len$b*aTX=-8QxN)k11IM1c^j%"
5035 	"9s<L<NFSo)B?+<-(GxsF,^-Eh@$4dXhN$+#rxK8'je'D7k`e;)2pYwPA'_p9&@^18ml1^[@g4t*[JOa*[=Qp7(qJ_oOL^('7fB&Hq-:sf,sNj8xq^>$U4O]GKx'm9)b@p7YsvK3w^YR-"
5036 	"CdQ*:Ir<($u&)#(&?L9Rg3H)4fiEp^iI9O8KnTj,]H?D*r7'M;PwZ9K0E^k&-cpI;.p/6_vwoFMV<->#%Xi.LxVnrU(4&8/P+:hLSKj$#U%]49t'I:rgMi'FL@a:0Y-uA[39',(vbma*"
5037 	"hU%<-SRF`Tt:542R_VV$p@[p8DV[A,?1839FWdF<TddF<9Ah-6&9tWoDlh]&1SpGMq>Ti1O*H&#(AL8[_P%.M>v^-))qOT*F5Cq0`Ye%+$B6i:7@0IX<N+T+0MlMBPQ*Vj>SsD<U4JHY"
5038 	"8kD2)2fU/M#$e.)T4,_=8hLim[&);?UkK'-x?'(:siIfL<$pFM`i<?%W(mGDHM%>iWP,##P`%/L<eXi:@Z9C.7o=@(pXdAO/NLQ8lPl+HPOQa8wD8=^GlPa8TKI1CjhsCTSLJM'/Wl>-"
5039 	"S(qw%sf/@%#B6;/U7K]uZbi^Oc^2n<bhPmUkMw>%t<)'mEVE''n`WnJra$^TKvX5B>;_aSEK',(hwa0:i4G?.Bci.(X[?b*($,=-n<.Q%`(X=?+@Am*Js0&=3bh8K]mL<LoNs'6,'85`"
5040 	"0?t/'_U59@]ddF<#LdF<eWdF<OuN/45rY<-L@&#+fm>69=Lb,OcZV/);TTm8VI;?%OtJ<(b4mq7M6:u?KRdF<gR@2L=FNU-<b[(9c/ML3m;Z[$oF3g)GAWqpARc=<ROu7cL5l;-[A]%/"
5041 	"+fsd;l#SafT/f*W]0=O'$(Tb<[)*@e775R-:Yob%g*>l*:xP?Yb.5)%w_I?7uk5JC+FS(m#i'k.'a0i)9<7b'fs'59hq$*5Uhv##pi^8+hIEBF`nvo`;'l0.^S1<-wUK2/Coh58KKhLj"
5042 	"M=SO*rfO`+qC`W-On.=AJ56>>i2@2LH6A:&5q`?9I3@@'04&p2/LVa*T-4<-i3;M9UvZd+N7>b*eIwg:CC)c<>nO&#<IGe;__.thjZl<%w(Wk2xmp4Q@I#I9,DF]u7-P=.-_:YJ]aS@V"
5043 	"?6*C()dOp7:WL,b&3Rg/.cmM9&r^>$(>.Z-I&J(Q0Hd5Q%7Co-b`-c<N(6r@ip+AurK<m86QIth*#v;-OBqi+L7wDE-Ir8K['m+DDSLwK&/.?-V%U_%3:qKNu$_b*B-kp7NaD'QdWQPK"
5044 	"Yq[@>P)hI;*_F]u`Rb[.j8_Q/<&>uu+VsH$sM9TA%?)(vmJ80),P7E>)tjD%2L=-t#fK[%`v=Q8<FfNkgg^oIbah*#8/Qt$F&:K*-(N/'+1vMB,u()-a.VUU*#[e%gAAO(S>WlA2);Sa"
5045 	">gXm8YB`1d@K#n]76-a$U,mF<fX]idqd)<3,]J7JmW4`6]uks=4-72L(jEk+:bJ0M^q-8Dm_Z?0olP1C9Sa&H[d&c$ooQUj]Exd*3ZM@-WGW2%s',B-_M%>%Ul:#/'xoFM9QX-$.QN'>"
5046 	"[%$Z$uF6pA6Ki2O5:8w*vP1<-1`[G,)-m#>0`P&#eb#.3i)rtB61(o'$?X3B</R90;eZ]%Ncq;-Tl]#F>2Qft^ae_5tKL9MUe9b*sLEQ95C&`=G?@Mj=wh*'3E>=-<)Gt*Iw)'QG:`@I"
5047 	"wOf7&]1i'S01B+Ev/Nac#9S;=;YQpg_6U`*kVY39xK,[/6Aj7:'1Bm-_1EYfa1+o&o4hp7KN_Q(OlIo@S%;jVdn0'1<Vc52=u`3^o-n1'g4v58Hj&6_t7$##?M)c<$bgQ_'SY((-xkA#"
5048 	"Y(,p'H9rIVY-b,'%bCPF7.J<Up^,(dU1VY*5#WkTU>h19w,WQhLI)3S#f$2(eb,jr*b;3Vw]*7NH%$c4Vs,eD9>XW8?N]o+(*pgC%/72LV-u<Hp,3@e^9UB1J+ak9-TN/mhKPg+AJYd$"
5049 	"MlvAF_jCK*.O-^(63adMT->W%iewS8W6m2rtCpo'RS1R84=@paTKt)>=%&1[)*vp'u+x,VrwN;&]kuO9JDbg=pO$J*.jVe;u'm0dr9l,<*wMK*Oe=g8lV_KEBFkO'oU]^=[-792#ok,)"
5050 	"i]lR8qQ2oA8wcRCZ^7w/Njh;?.stX?Q1>S1q4Bn$)K1<-rGdO'$Wr.Lc.CG)$/*JL4tNR/,SVO3,aUw'DJN:)Ss;wGn9A32ijw%FL+Z0Fn.U9;reSq)bmI32U==5ALuG&#Vf1398/pVo"
5051 	"1*c-(aY168o<`JsSbk-,1N;$>0:OUas(3:8Z972LSfF8eb=c-;>SPw7.6hn3m`9^Xkn(r.qS[0;T%&Qc=+STRxX'q1BNk3&*eu2;&8q$&x>Q#Q7^Tf+6<(d%ZVmj2bDi%.3L2n+4W'$P"
5052 	"iDDG)g,r%+?,$@?uou5tSe2aN_AQU*<h`e-GI7)?OK2A.d7_c)?wQ5AS@DL3r#7fSkgl6-++D:'A,uq7SvlB$pcpH'q3n0#_%dY#xCpr-l<F0NR@-##FEV6NTF6##$l84N1w?AO>'IAO"
5053 	"URQ##V^Fv-XFbGM7Fl(N<3DhLGF%q.1rC$#:T__&Pi68%0xi_&[qFJ(77j_&JWoF.V735&T,[R*:xFR*K5>>#`bW-?4Ne_&6Ne_&6Ne_&n`kr-#GJcM6X;uM6X;uM(.a..^2TkL%oR(#"
5054 	";u.T%fAr%4tJ8&><1=GHZ_+m9/#H1F^R#SC#*N=BA9(D?v[UiFY>>^8p,KKF.W]L29uLkLlu/+4T<XoIB&hx=T1PcDaB&;HH+-AFr?(m9HZV)FKS8JCw;SD=6[^/DZUL`EUDf]GGlG&>"
5055 	"w$)F./^n3+rlo+DB;5sIYGNk+i1t-69Jg--0pao7Sm#K)pdHW&;LuDNH@H>#/X-TI(;P>#,Gc>#0Su>#4`1?#8lC?#<xU?#@.i?#D:%@#HF7@#LRI@#P_[@#Tkn@#Xw*A#]-=A#a9OA#"
5056 	"d<F&#*;G##.GY##2Sl##6`($#:l:$#>xL$#B.`$#F:r$#JF.%#NR@%#R_R%#Vke%#Zww%#_-4&#3^Rh%Sflr-k'MS.o?.5/sWel/wpEM0%3'/1)K^f1-d>G21&v(35>V`39V7A4=onx4"
5057 	"A1OY5EI0;6Ibgr6M$HS7Q<)58C5w,;WoA*#[%T*#`1g*#d=#+#hI5+#lUG+#pbY+#tnl+#x$),#&1;,#*=M,#.I`,#2Ur,#6b.-#;w[H#iQtA#m^0B#qjBB#uvTB##-hB#'9$C#+E6C#"
5058 	"/QHC#3^ZC#7jmC#;v)D#?,<D#C8ND#GDaD#KPsD#O]/E#g1A5#KA*1#gC17#MGd;#8(02#L-d3#rWM4#Hga1#,<w0#T.j<#O#'2#CYN1#qa^:#_4m3#o@/=#eG8=#t8J5#`+78#4uI-#"
5059 	"m3B2#SB[8#Q0@8#i[*9#iOn8#1Nm;#^sN9#qh<9#:=x-#P;K2#$%X9#bC+.#Rg;<#mN=.#MTF.#RZO.#2?)4#Y#(/#[)1/#b;L/#dAU/#0Sv;#lY$0#n`-0#sf60#(F24#wrH0#%/e0#"
5060 	"TmD<#%JSMFove:CTBEXI:<eh2g)B,3h2^G3i;#d3jD>)4kMYD4lVu`4m`:&5niUA5@(A5BA1]PBB:xlBCC=2CDLXMCEUtiCf&0g2'tN?PGT4CPGT4CPGT4CPGT4CPGT4CPGT4CPGT4CP"
5061 	"GT4CPGT4CPGT4CPGT4CPGT4CPGT4CP-qekC`.9kEg^+F$kwViFJTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5o,^<-28ZI'O?;xp"
5062 	"O?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xp;7q-#lLYI:xvD=#";
5063 
GetDefaultCompressedFontDataTTFBase85()5064 static const char* GetDefaultCompressedFontDataTTFBase85()
5065 {
5066 	return proggy_clean_ttf_compressed_data_base85;
5067 }
5068