imgui_freetype.cpp
Go to the documentation of this file.
1 // Wrapper to use FreeType (instead of stb_truetype) for Dear ImGui
2 // Get latest version at https://github.com/ocornut/imgui/tree/master/misc/freetype
3 // Original code by @vuhdo (Aleksei Skriabin). Improvements by @mikesart. Maintained and v0.60+ by @ocornut.
4 
5 // Changelog:
6 // - v0.50: (2017/08/16) imported from https://github.com/Vuhdo/imgui_freetype into http://www.github.com/ocornut/imgui_club, updated for latest changes in ImFontAtlas, minor tweaks.
7 // - v0.51: (2017/08/26) cleanup, optimizations, support for ImFontConfig::RasterizerFlags, ImFontConfig::RasterizerMultiply.
8 // - v0.52: (2017/09/26) fixes for imgui internal changes.
9 // - v0.53: (2017/10/22) minor inconsequential change to match change in master (removed an unnecessary statement).
10 // - v0.54: (2018/01/22) fix for addition of ImFontAtlas::TexUvscale member.
11 // - v0.55: (2018/02/04) moved to main imgui repository (away from http://www.github.com/ocornut/imgui_club)
12 // - v0.56: (2018/06/08) added support for ImFontConfig::GlyphMinAdvanceX, GlyphMaxAdvanceX.
13 // - v0.60: (2019/01/10) re-factored to match big update in STB builder. fixed texture height waste. fixed redundant glyphs when merging. support for glyph padding.
14 // - v0.61: (2019/01/15) added support for imgui allocators + added FreeType only override function SetAllocatorFunctions().
15 // - v0.62: (2019/02/09) added RasterizerFlags::Monochrome flag to disable font anti-aliasing (combine with ::MonoHinting for best results!)
16 
17 // Gamma Correct Blending:
18 // FreeType assumes blending in linear space rather than gamma space.
19 // See https://www.freetype.org/freetype2/docs/reference/ft2-base_interface.html#FT_Render_Glyph
20 // For correct results you need to be using sRGB and convert to linear space in the pixel shader output.
21 // The default imgui styles will be impacted by this change (alpha values will need tweaking).
22 
23 // FIXME: cfg.OversampleH, OversampleV are not supported (but perhaps not so necessary with this rasterizer).
24 
25 #include "imgui_freetype.h"
26 #include "imgui_internal.h" // ImMin,ImMax,ImFontAtlasBuild*,
27 #include <stdint.h>
28 #include <ft2build.h>
29 #include FT_FREETYPE_H // <freetype/freetype.h>
30 #include FT_MODULE_H // <freetype/ftmodapi.h>
31 #include FT_GLYPH_H // <freetype/ftglyph.h>
32 #include FT_SYNTHESIS_H // <freetype/ftsynth.h>
33 
34 #ifdef _MSC_VER
35 #pragma warning (disable: 4505) // unreferenced local function has been removed (stb stuff)
36 #endif
37 
38 #if defined(__GNUC__)
39 #pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind
40 #pragma GCC diagnostic ignored "-Wunused-function" // warning: 'xxxx' defined but not used
41 #endif
42 
43 namespace
44 {
45  // Glyph metrics:
46  // --------------
47  //
48  // xmin xmax
49  // | |
50  // |<-------- width -------->|
51  // | |
52  // | +-------------------------+----------------- ymax
53  // | | ggggggggg ggggg | ^ ^
54  // | | g:::::::::ggg::::g | | |
55  // | | g:::::::::::::::::g | | |
56  // | | g::::::ggggg::::::gg | | |
57  // | | g:::::g g:::::g | | |
58  // offsetX -|-------->| g:::::g g:::::g | offsetY |
59  // | | g:::::g g:::::g | | |
60  // | | g::::::g g:::::g | | |
61  // | | g:::::::ggggg:::::g | | |
62  // | | g::::::::::::::::g | | height
63  // | | gg::::::::::::::g | | |
64  // baseline ---*---------|---- gggggggg::::::g-----*-------- |
65  // / | | g:::::g | |
66  // origin | | gggggg g:::::g | |
67  // | | g:::::gg gg:::::g | |
68  // | | g::::::ggg:::::::g | |
69  // | | gg:::::::::::::g | |
70  // | | ggg::::::ggg | |
71  // | | gggggg | v
72  // | +-------------------------+----------------- ymin
73  // | |
74  // |------------- advanceX ----------->|
75 
77  struct GlyphInfo
78  {
79  int Width; // Glyph's width in pixels.
80  int Height; // Glyph's height in pixels.
81  FT_Int OffsetX; // The distance from the origin ("pen position") to the left of the glyph.
82  FT_Int OffsetY; // The distance from the origin to the top of the glyph. This is usually a value < 0.
83  float AdvanceX; // The distance from the origin to the origin of the next glyph. This is usually a value > 0.
84  };
85 
86  // Font parameters and metrics.
87  struct FontInfo
88  {
89  uint32_t PixelHeight; // Size this font was generated with.
90  float Ascender; // The pixel extents above the baseline in pixels (typically positive).
91  float Descender; // The extents below the baseline in pixels (typically negative).
92  float LineSpacing; // The baseline-to-baseline distance. Note that it usually is larger than the sum of the ascender and descender taken as absolute values. There is also no guarantee that no glyphs extend above or below subsequent baselines when using this distance. Think of it as a value the designer of the font finds appropriate.
93  float LineGap; // The spacing in pixels between one row's descent and the next row's ascent.
94  float MaxAdvanceWidth; // This field gives the maximum horizontal cursor advance for all glyphs in the font.
95  };
96 
97  // FreeType glyph rasterizer.
98  // NB: No ctor/dtor, explicitly call Init()/Shutdown()
99  struct FreeTypeFont
100  {
101  bool InitFont(FT_Library ft_library, const ImFontConfig& cfg, unsigned int extra_user_flags); // Initialize from an external data buffer. Doesn't copy data, and you must ensure it stays valid up to this object lifetime.
102  void CloseFont();
103  void SetPixelHeight(int pixel_height); // Change font pixel size. All following calls to RasterizeGlyph() will use this size
104  const FT_Glyph_Metrics* LoadGlyph(uint32_t in_codepoint);
105  const FT_Bitmap* RenderGlyphAndGetInfo(GlyphInfo* out_glyph_info);
106  void BlitGlyph(const FT_Bitmap* ft_bitmap, uint8_t* dst, uint32_t dst_pitch, unsigned char* multiply_table = NULL);
107  ~FreeTypeFont() { CloseFont(); }
108 
109  // [Internals]
110  FontInfo Info; // Font descriptor of the current font.
111  FT_Face Face;
112  unsigned int UserFlags; // = ImFontConfig::RasterizerFlags
113  FT_Int32 LoadFlags;
114  FT_Render_Mode RenderMode;
115  };
116 
117  // From SDL_ttf: Handy routines for converting from fixed point
118  #define FT_CEIL(X) (((X + 63) & -64) / 64)
119 
120  bool FreeTypeFont::InitFont(FT_Library ft_library, const ImFontConfig& cfg, unsigned int extra_user_flags)
121  {
122  FT_Error error = FT_New_Memory_Face(ft_library, (uint8_t*)cfg.FontData, (uint32_t)cfg.FontDataSize, (uint32_t)cfg.FontNo, &Face);
123  if (error != 0)
124  return false;
125  error = FT_Select_Charmap(Face, FT_ENCODING_UNICODE);
126  if (error != 0)
127  return false;
128 
129  memset(&Info, 0, sizeof(Info));
130  SetPixelHeight((uint32_t)cfg.SizePixels);
131 
132  // Convert to FreeType flags (NB: Bold and Oblique are processed separately)
133  UserFlags = cfg.RasterizerFlags | extra_user_flags;
134  LoadFlags = FT_LOAD_NO_BITMAP;
135  if (UserFlags & ImGuiFreeType::NoHinting)
136  LoadFlags |= FT_LOAD_NO_HINTING;
137  if (UserFlags & ImGuiFreeType::NoAutoHint)
138  LoadFlags |= FT_LOAD_NO_AUTOHINT;
139  if (UserFlags & ImGuiFreeType::ForceAutoHint)
140  LoadFlags |= FT_LOAD_FORCE_AUTOHINT;
141  if (UserFlags & ImGuiFreeType::LightHinting)
142  LoadFlags |= FT_LOAD_TARGET_LIGHT;
143  else if (UserFlags & ImGuiFreeType::MonoHinting)
144  LoadFlags |= FT_LOAD_TARGET_MONO;
145  else
146  LoadFlags |= FT_LOAD_TARGET_NORMAL;
147 
148  if (UserFlags & ImGuiFreeType::Monochrome)
149  RenderMode = FT_RENDER_MODE_MONO;
150  else
151  RenderMode = FT_RENDER_MODE_NORMAL;
152 
153  return true;
154  }
155 
156  void FreeTypeFont::CloseFont()
157  {
158  if (Face)
159  {
160  FT_Done_Face(Face);
161  Face = NULL;
162  }
163  }
164 
165  void FreeTypeFont::SetPixelHeight(int pixel_height)
166  {
167  // Vuhdo: I'm not sure how to deal with font sizes properly. As far as I understand, currently ImGui assumes that the 'pixel_height'
168  // is a maximum height of an any given glyph, i.e. it's the sum of font's ascender and descender. Seems strange to me.
169  // NB: FT_Set_Pixel_Sizes() doesn't seem to get us the same result.
170  FT_Size_RequestRec req;
171  req.type = FT_SIZE_REQUEST_TYPE_REAL_DIM;
172  req.width = 0;
173  req.height = (uint32_t)pixel_height * 64;
174  req.horiResolution = 0;
175  req.vertResolution = 0;
176  FT_Request_Size(Face, &req);
177 
178  // Update font info
179  FT_Size_Metrics metrics = Face->size->metrics;
180  Info.PixelHeight = (uint32_t)pixel_height;
181  Info.Ascender = (float)FT_CEIL(metrics.ascender);
182  Info.Descender = (float)FT_CEIL(metrics.descender);
183  Info.LineSpacing = (float)FT_CEIL(metrics.height);
184  Info.LineGap = (float)FT_CEIL(metrics.height - metrics.ascender + metrics.descender);
185  Info.MaxAdvanceWidth = (float)FT_CEIL(metrics.max_advance);
186  }
187 
188  const FT_Glyph_Metrics* FreeTypeFont::LoadGlyph(uint32_t codepoint)
189  {
190  uint32_t glyph_index = FT_Get_Char_Index(Face, codepoint);
191  if (glyph_index == 0)
192  return NULL;
193  FT_Error error = FT_Load_Glyph(Face, glyph_index, LoadFlags);
194  if (error)
195  return NULL;
196 
197  // Need an outline for this to work
198  FT_GlyphSlot slot = Face->glyph;
199  IM_ASSERT(slot->format == FT_GLYPH_FORMAT_OUTLINE);
200 
201  // Apply convenience transform (this is not picking from real "Bold"/"Italic" fonts! Merely applying FreeType helper transform. Oblique == Slanting)
202  if (UserFlags & ImGuiFreeType::Bold)
203  FT_GlyphSlot_Embolden(slot);
204  if (UserFlags & ImGuiFreeType::Oblique)
205  {
206  FT_GlyphSlot_Oblique(slot);
207  //FT_BBox bbox;
208  //FT_Outline_Get_BBox(&slot->outline, &bbox);
209  //slot->metrics.width = bbox.xMax - bbox.xMin;
210  //slot->metrics.height = bbox.yMax - bbox.yMin;
211  }
212 
213  return &slot->metrics;
214  }
215 
216  const FT_Bitmap* FreeTypeFont::RenderGlyphAndGetInfo(GlyphInfo* out_glyph_info)
217  {
218  FT_GlyphSlot slot = Face->glyph;
219  FT_Error error = FT_Render_Glyph(slot, RenderMode);
220  if (error != 0)
221  return NULL;
222 
223  FT_Bitmap* ft_bitmap = &Face->glyph->bitmap;
224  out_glyph_info->Width = (int)ft_bitmap->width;
225  out_glyph_info->Height = (int)ft_bitmap->rows;
226  out_glyph_info->OffsetX = Face->glyph->bitmap_left;
227  out_glyph_info->OffsetY = -Face->glyph->bitmap_top;
228  out_glyph_info->AdvanceX = (float)FT_CEIL(slot->advance.x);
229 
230  return ft_bitmap;
231  }
232 
233  void FreeTypeFont::BlitGlyph(const FT_Bitmap* ft_bitmap, uint8_t* dst, uint32_t dst_pitch, unsigned char* multiply_table)
234  {
235  IM_ASSERT(ft_bitmap != NULL);
236  const uint32_t w = ft_bitmap->width;
237  const uint32_t h = ft_bitmap->rows;
238  const uint8_t* src = ft_bitmap->buffer;
239  const uint32_t src_pitch = ft_bitmap->pitch;
240 
241  switch (ft_bitmap->pixel_mode)
242  {
243  case FT_PIXEL_MODE_GRAY: // Grayscale image, 1 byte per pixel.
244  {
245  if (multiply_table == NULL)
246  {
247  for (uint32_t y = 0; y < h; y++, src += src_pitch, dst += dst_pitch)
248  memcpy(dst, src, w);
249  }
250  else
251  {
252  for (uint32_t y = 0; y < h; y++, src += src_pitch, dst += dst_pitch)
253  for (uint32_t x = 0; x < w; x++)
254  dst[x] = multiply_table[src[x]];
255  }
256  break;
257  }
258  case FT_PIXEL_MODE_MONO: // Monochrome image, 1 bit per pixel. The bits in each byte are ordered from MSB to LSB.
259  {
260  uint8_t color0 = multiply_table ? multiply_table[0] : 0;
261  uint8_t color1 = multiply_table ? multiply_table[255] : 255;
262  for (uint32_t y = 0; y < h; y++, src += src_pitch, dst += dst_pitch)
263  {
264  uint8_t bits = 0;
265  const uint8_t* bits_ptr = src;
266  for (uint32_t x = 0; x < w; x++, bits <<= 1)
267  {
268  if ((x & 7) == 0)
269  bits = *bits_ptr++;
270  dst[x] = (bits & 0x80) ? color1 : color0;
271  }
272  }
273  break;
274  }
275  default:
276  IM_ASSERT(0 && "FreeTypeFont::BlitGlyph(): Unknown bitmap pixel mode!");
277  }
278  }
279 }
280 
281 #ifndef STB_RECT_PACK_IMPLEMENTATION // in case the user already have an implementation in the _same_ compilation unit (e.g. unity builds)
282 #ifndef IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION
283 #define STBRP_ASSERT(x) IM_ASSERT(x)
284 #define STBRP_STATIC
285 #define STB_RECT_PACK_IMPLEMENTATION
286 #endif
287 #ifdef IMGUI_STB_RECT_PACK_FILENAME
288 #include IMGUI_STB_RECT_PACK_FILENAME
289 #else
290 #include "imstb_rectpack.h"
291 #endif
292 #endif
293 
295 {
296  GlyphInfo Info;
297  uint32_t Codepoint;
298  unsigned char* BitmapData; // Point within one of the dst_tmp_bitmap_buffers[] array
299 };
300 
302 {
303  FreeTypeFont Font;
304  stbrp_rect* Rects; // Rectangle to pack. We first fill in their size and the packer will give us their position.
305  const ImWchar* SrcRanges; // Ranges as requested by user (user is allowed to request too much, e.g. 0x0020..0xFFFF)
306  int DstIndex; // Index into atlas->Fonts[] and dst_tmp_array[]
307  int GlyphsHighest; // Highest requested codepoint
308  int GlyphsCount; // Glyph count (excluding missing glyphs and glyphs already set by an earlier source font)
309  ImBitVector GlyphsSet; // Glyph bit map (random access, 1-bit per codepoint. This will be a maximum of 8KB)
311 };
312 
313 // Temporary data for one destination ImFont* (multiple source fonts can be merged into one destination ImFont)
315 {
316  int SrcCount; // Number of source fonts targeting this destination font.
319  ImBitVector GlyphsSet; // This is used to resolve collision when multiple sources are merged into a same destination font.
320 };
321 
322 bool ImFontAtlasBuildWithFreeType(FT_Library ft_library, ImFontAtlas* atlas, unsigned int extra_flags)
323 {
324  IM_ASSERT(atlas->ConfigData.Size > 0);
325 
326  ImFontAtlasBuildInit(atlas);
327 
328  // Clear atlas
329  atlas->TexID = (ImTextureID)NULL;
330  atlas->TexWidth = atlas->TexHeight = 0;
331  atlas->TexUvScale = ImVec2(0.0f, 0.0f);
332  atlas->TexUvWhitePixel = ImVec2(0.0f, 0.0f);
333  atlas->ClearTexData();
334 
335  // Temporary storage for building
336  ImVector<ImFontBuildSrcDataFT> src_tmp_array;
337  ImVector<ImFontBuildDstDataFT> dst_tmp_array;
338  src_tmp_array.resize(atlas->ConfigData.Size);
339  dst_tmp_array.resize(atlas->Fonts.Size);
340  memset(src_tmp_array.Data, 0, (size_t)src_tmp_array.size_in_bytes());
341  memset(dst_tmp_array.Data, 0, (size_t)dst_tmp_array.size_in_bytes());
342 
343  // 1. Initialize font loading structure, check font data validity
344  for (int src_i = 0; src_i < atlas->ConfigData.Size; src_i++)
345  {
346  ImFontBuildSrcDataFT& src_tmp = src_tmp_array[src_i];
347  ImFontConfig& cfg = atlas->ConfigData[src_i];
348  FreeTypeFont& font_face = src_tmp.Font;
349  IM_ASSERT(cfg.DstFont && (!cfg.DstFont->IsLoaded() || cfg.DstFont->ContainerAtlas == atlas));
350 
351  // Find index from cfg.DstFont (we allow the user to set cfg.DstFont. Also it makes casual debugging nicer than when storing indices)
352  src_tmp.DstIndex = -1;
353  for (int output_i = 0; output_i < atlas->Fonts.Size && src_tmp.DstIndex == -1; output_i++)
354  if (cfg.DstFont == atlas->Fonts[output_i])
355  src_tmp.DstIndex = output_i;
356  IM_ASSERT(src_tmp.DstIndex != -1); // cfg.DstFont not pointing within atlas->Fonts[] array?
357  if (src_tmp.DstIndex == -1)
358  return false;
359 
360  // Load font
361  if (!font_face.InitFont(ft_library, cfg, extra_flags))
362  return false;
363 
364  // Measure highest codepoints
365  ImFontBuildDstDataFT& dst_tmp = dst_tmp_array[src_tmp.DstIndex];
366  src_tmp.SrcRanges = cfg.GlyphRanges ? cfg.GlyphRanges : atlas->GetGlyphRangesDefault();
367  for (const ImWchar* src_range = src_tmp.SrcRanges; src_range[0] && src_range[1]; src_range += 2)
368  src_tmp.GlyphsHighest = ImMax(src_tmp.GlyphsHighest, (int)src_range[1]);
369  dst_tmp.SrcCount++;
370  dst_tmp.GlyphsHighest = ImMax(dst_tmp.GlyphsHighest, src_tmp.GlyphsHighest);
371  }
372 
373  // 2. For every requested codepoint, check for their presence in the font data, and handle redundancy or overlaps between source fonts to avoid unused glyphs.
374  int total_glyphs_count = 0;
375  for (int src_i = 0; src_i < src_tmp_array.Size; src_i++)
376  {
377  ImFontBuildSrcDataFT& src_tmp = src_tmp_array[src_i];
378  ImFontBuildDstDataFT& dst_tmp = dst_tmp_array[src_tmp.DstIndex];
379  src_tmp.GlyphsSet.Create(src_tmp.GlyphsHighest + 1);
380  if (dst_tmp.GlyphsSet.Storage.empty())
381  dst_tmp.GlyphsSet.Create(dst_tmp.GlyphsHighest + 1);
382 
383  for (const ImWchar* src_range = src_tmp.SrcRanges; src_range[0] && src_range[1]; src_range += 2)
384  for (int codepoint = src_range[0]; codepoint <= src_range[1]; codepoint++)
385  {
386  if (dst_tmp.GlyphsSet.TestBit(codepoint)) // Don't overwrite existing glyphs. We could make this an option (e.g. MergeOverwrite)
387  continue;
388  uint32_t glyph_index = FT_Get_Char_Index(src_tmp.Font.Face, codepoint); // It is actually in the font? (FIXME-OPT: We are not storing the glyph_index..)
389  if (glyph_index == 0)
390  continue;
391 
392  // Add to avail set/counters
393  src_tmp.GlyphsCount++;
394  dst_tmp.GlyphsCount++;
395  src_tmp.GlyphsSet.SetBit(codepoint);
396  dst_tmp.GlyphsSet.SetBit(codepoint);
397  total_glyphs_count++;
398  }
399  }
400 
401  // 3. Unpack our bit map into a flat list (we now have all the Unicode points that we know are requested _and_ available _and_ not overlapping another)
402  for (int src_i = 0; src_i < src_tmp_array.Size; src_i++)
403  {
404  ImFontBuildSrcDataFT& src_tmp = src_tmp_array[src_i];
405  src_tmp.GlyphsList.reserve(src_tmp.GlyphsCount);
406 
407  IM_ASSERT(sizeof(src_tmp.GlyphsSet.Storage.Data[0]) == sizeof(ImU32));
408  const ImU32* it_begin = src_tmp.GlyphsSet.Storage.begin();
409  const ImU32* it_end = src_tmp.GlyphsSet.Storage.end();
410  for (const ImU32* it = it_begin; it < it_end; it++)
411  if (ImU32 entries_32 = *it)
412  for (ImU32 bit_n = 0; bit_n < 32; bit_n++)
413  if (entries_32 & ((ImU32)1 << bit_n))
414  {
415  ImFontBuildSrcGlyphFT src_glyph;
416  memset(&src_glyph, 0, sizeof(src_glyph));
417  src_glyph.Codepoint = (ImWchar)(((it - it_begin) << 5) + bit_n);
418  //src_glyph.GlyphIndex = 0; // FIXME-OPT: We had this info in the previous step and lost it..
419  src_tmp.GlyphsList.push_back(src_glyph);
420  }
421  src_tmp.GlyphsSet.Clear();
422  IM_ASSERT(src_tmp.GlyphsList.Size == src_tmp.GlyphsCount);
423  }
424  for (int dst_i = 0; dst_i < dst_tmp_array.Size; dst_i++)
425  dst_tmp_array[dst_i].GlyphsSet.Clear();
426  dst_tmp_array.clear();
427 
428  // Allocate packing character data and flag packed characters buffer as non-packed (x0=y0=x1=y1=0)
429  // (We technically don't need to zero-clear buf_rects, but let's do it for the sake of sanity)
430  ImVector<stbrp_rect> buf_rects;
431  buf_rects.resize(total_glyphs_count);
432  memset(buf_rects.Data, 0, (size_t)buf_rects.size_in_bytes());
433 
434  // Allocate temporary rasterization data buffers.
435  // We could not find a way to retrieve accurate glyph size without rendering them.
436  // (e.g. slot->metrics->width not always matching bitmap->width, especially considering the Oblique transform)
437  // We allocate in chunks of 256 KB to not waste too much extra memory ahead. Hopefully users of FreeType won't find the temporary allocations.
438  const int BITMAP_BUFFERS_CHUNK_SIZE = 256 * 1024;
439  int buf_bitmap_current_used_bytes = 0;
440  ImVector<unsigned char*> buf_bitmap_buffers;
441  buf_bitmap_buffers.push_back((unsigned char*)IM_ALLOC(BITMAP_BUFFERS_CHUNK_SIZE));
442 
443  // 4. Gather glyphs sizes so we can pack them in our virtual canvas.
444  // 8. Render/rasterize font characters into the texture
445  int total_surface = 0;
446  int buf_rects_out_n = 0;
447  for (int src_i = 0; src_i < src_tmp_array.Size; src_i++)
448  {
449  ImFontBuildSrcDataFT& src_tmp = src_tmp_array[src_i];
450  ImFontConfig& cfg = atlas->ConfigData[src_i];
451  if (src_tmp.GlyphsCount == 0)
452  continue;
453 
454  src_tmp.Rects = &buf_rects[buf_rects_out_n];
455  buf_rects_out_n += src_tmp.GlyphsCount;
456 
457  // Compute multiply table if requested
458  const bool multiply_enabled = (cfg.RasterizerMultiply != 1.0f);
459  unsigned char multiply_table[256];
460  if (multiply_enabled)
462 
463  // Gather the sizes of all rectangles we will need to pack
464  const int padding = atlas->TexGlyphPadding;
465  for (int glyph_i = 0; glyph_i < src_tmp.GlyphsList.Size; glyph_i++)
466  {
467  ImFontBuildSrcGlyphFT& src_glyph = src_tmp.GlyphsList[glyph_i];
468 
469  const FT_Glyph_Metrics* metrics = src_tmp.Font.LoadGlyph(src_glyph.Codepoint);
470  IM_ASSERT(metrics != NULL);
471  if (metrics == NULL)
472  continue;
473 
474  // Render glyph into a bitmap (currently held by FreeType)
475  const FT_Bitmap* ft_bitmap = src_tmp.Font.RenderGlyphAndGetInfo(&src_glyph.Info);
476  IM_ASSERT(ft_bitmap);
477 
478  // Allocate new temporary chunk if needed
479  const int bitmap_size_in_bytes = src_glyph.Info.Width * src_glyph.Info.Height;
480  if (buf_bitmap_current_used_bytes + bitmap_size_in_bytes > BITMAP_BUFFERS_CHUNK_SIZE)
481  {
482  buf_bitmap_current_used_bytes = 0;
483  buf_bitmap_buffers.push_back((unsigned char*)IM_ALLOC(BITMAP_BUFFERS_CHUNK_SIZE));
484  }
485 
486  // Blit rasterized pixels to our temporary buffer and keep a pointer to it.
487  src_glyph.BitmapData = buf_bitmap_buffers.back() + buf_bitmap_current_used_bytes;
488  buf_bitmap_current_used_bytes += bitmap_size_in_bytes;
489  src_tmp.Font.BlitGlyph(ft_bitmap, src_glyph.BitmapData, src_glyph.Info.Width * 1, multiply_enabled ? multiply_table : NULL);
490 
491  src_tmp.Rects[glyph_i].w = (stbrp_coord)(src_glyph.Info.Width + padding);
492  src_tmp.Rects[glyph_i].h = (stbrp_coord)(src_glyph.Info.Height + padding);
493  total_surface += src_tmp.Rects[glyph_i].w * src_tmp.Rects[glyph_i].h;
494  }
495  }
496 
497  // We need a width for the skyline algorithm, any width!
498  // The exact width doesn't really matter much, but some API/GPU have texture size limitations and increasing width can decrease height.
499  // User can override TexDesiredWidth and TexGlyphPadding if they wish, otherwise we use a simple heuristic to select the width based on expected surface.
500  const int surface_sqrt = (int)ImSqrt((float)total_surface) + 1;
501  atlas->TexHeight = 0;
502  if (atlas->TexDesiredWidth > 0)
503  atlas->TexWidth = atlas->TexDesiredWidth;
504  else
505  atlas->TexWidth = (surface_sqrt >= 4096*0.7f) ? 4096 : (surface_sqrt >= 2048*0.7f) ? 2048 : (surface_sqrt >= 1024*0.7f) ? 1024 : 512;
506 
507  // 5. Start packing
508  // Pack our extra data rectangles first, so it will be on the upper-left corner of our texture (UV will have small values).
509  const int TEX_HEIGHT_MAX = 1024 * 32;
510  const int num_nodes_for_packing_algorithm = atlas->TexWidth - atlas->TexGlyphPadding;
511  ImVector<stbrp_node> pack_nodes;
512  pack_nodes.resize(num_nodes_for_packing_algorithm);
513  stbrp_context pack_context;
514  stbrp_init_target(&pack_context, atlas->TexWidth, TEX_HEIGHT_MAX, pack_nodes.Data, pack_nodes.Size);
515  ImFontAtlasBuildPackCustomRects(atlas, &pack_context);
516 
517  // 6. Pack each source font. No rendering yet, we are working with rectangles in an infinitely tall texture at this point.
518  for (int src_i = 0; src_i < src_tmp_array.Size; src_i++)
519  {
520  ImFontBuildSrcDataFT& src_tmp = src_tmp_array[src_i];
521  if (src_tmp.GlyphsCount == 0)
522  continue;
523 
524  stbrp_pack_rects(&pack_context, src_tmp.Rects, src_tmp.GlyphsCount);
525 
526  // Extend texture height and mark missing glyphs as non-packed so we won't render them.
527  // FIXME: We are not handling packing failure here (would happen if we got off TEX_HEIGHT_MAX or if a single if larger than TexWidth?)
528  for (int glyph_i = 0; glyph_i < src_tmp.GlyphsCount; glyph_i++)
529  if (src_tmp.Rects[glyph_i].was_packed)
530  atlas->TexHeight = ImMax(atlas->TexHeight, src_tmp.Rects[glyph_i].y + src_tmp.Rects[glyph_i].h);
531  }
532 
533  // 7. Allocate texture
534  atlas->TexHeight = (atlas->Flags & ImFontAtlasFlags_NoPowerOfTwoHeight) ? (atlas->TexHeight + 1) : ImUpperPowerOfTwo(atlas->TexHeight);
535  atlas->TexUvScale = ImVec2(1.0f / atlas->TexWidth, 1.0f / atlas->TexHeight);
536  atlas->TexPixelsAlpha8 = (unsigned char*)IM_ALLOC(atlas->TexWidth * atlas->TexHeight);
537  memset(atlas->TexPixelsAlpha8, 0, atlas->TexWidth * atlas->TexHeight);
538 
539  // 8. Copy rasterized font characters back into the main texture
540  // 9. Setup ImFont and glyphs for runtime
541  for (int src_i = 0; src_i < src_tmp_array.Size; src_i++)
542  {
543  ImFontBuildSrcDataFT& src_tmp = src_tmp_array[src_i];
544  if (src_tmp.GlyphsCount == 0)
545  continue;
546 
547  ImFontConfig& cfg = atlas->ConfigData[src_i];
548  ImFont* dst_font = cfg.DstFont; // We can have multiple input fonts writing into a same destination font (when using MergeMode=true)
549 
550  const float ascent = src_tmp.Font.Info.Ascender;
551  const float descent = src_tmp.Font.Info.Descender;
552  ImFontAtlasBuildSetupFont(atlas, dst_font, &cfg, ascent, descent);
553  const float font_off_x = cfg.GlyphOffset.x;
554  const float font_off_y = cfg.GlyphOffset.y + IM_ROUND(dst_font->Ascent);
555 
556  const int padding = atlas->TexGlyphPadding;
557  for (int glyph_i = 0; glyph_i < src_tmp.GlyphsCount; glyph_i++)
558  {
559  ImFontBuildSrcGlyphFT& src_glyph = src_tmp.GlyphsList[glyph_i];
560  stbrp_rect& pack_rect = src_tmp.Rects[glyph_i];
561  IM_ASSERT(pack_rect.was_packed);
562 
563  GlyphInfo& info = src_glyph.Info;
564  IM_ASSERT(info.Width + padding <= pack_rect.w);
565  IM_ASSERT(info.Height + padding <= pack_rect.h);
566  const int tx = pack_rect.x + padding;
567  const int ty = pack_rect.y + padding;
568 
569  // Blit from temporary buffer to final texture
570  size_t blit_src_stride = (size_t)src_glyph.Info.Width;
571  size_t blit_dst_stride = (size_t)atlas->TexWidth;
572  unsigned char* blit_src = src_glyph.BitmapData;
573  unsigned char* blit_dst = atlas->TexPixelsAlpha8 + (ty * blit_dst_stride) + tx;
574  for (int y = info.Height; y > 0; y--, blit_dst += blit_dst_stride, blit_src += blit_src_stride)
575  memcpy(blit_dst, blit_src, blit_src_stride);
576 
577  float char_advance_x_org = info.AdvanceX;
578  float char_advance_x_mod = ImClamp(char_advance_x_org, cfg.GlyphMinAdvanceX, cfg.GlyphMaxAdvanceX);
579  float char_off_x = font_off_x;
580  if (char_advance_x_org != char_advance_x_mod)
581  char_off_x += cfg.PixelSnapH ? IM_FLOOR((char_advance_x_mod - char_advance_x_org) * 0.5f) : (char_advance_x_mod - char_advance_x_org) * 0.5f;
582 
583  // Register glyph
584  float x0 = info.OffsetX + char_off_x;
585  float y0 = info.OffsetY + font_off_y;
586  float x1 = x0 + info.Width;
587  float y1 = y0 + info.Height;
588  float u0 = (tx) / (float)atlas->TexWidth;
589  float v0 = (ty) / (float)atlas->TexHeight;
590  float u1 = (tx + info.Width) / (float)atlas->TexWidth;
591  float v1 = (ty + info.Height) / (float)atlas->TexHeight;
592  dst_font->AddGlyph((ImWchar)src_glyph.Codepoint, x0, y0, x1, y1, u0, v0, u1, v1, char_advance_x_mod);
593  }
594 
595  src_tmp.Rects = NULL;
596  }
597 
598  // Cleanup
599  for (int buf_i = 0; buf_i < buf_bitmap_buffers.Size; buf_i++)
600  IM_FREE(buf_bitmap_buffers[buf_i]);
601  for (int src_i = 0; src_i < src_tmp_array.Size; src_i++)
602  src_tmp_array[src_i].~ImFontBuildSrcDataFT();
603 
604  ImFontAtlasBuildFinish(atlas);
605 
606  return true;
607 }
608 
609 // Default memory allocators
610 static void* ImFreeTypeDefaultAllocFunc(size_t size, void* user_data) { IM_UNUSED(user_data); return IM_ALLOC(size); }
611 static void ImFreeTypeDefaultFreeFunc(void* ptr, void* user_data) { IM_UNUSED(user_data); IM_FREE(ptr); }
612 
613 // Current memory allocators
614 static void* (*GImFreeTypeAllocFunc)(size_t size, void* user_data) = ImFreeTypeDefaultAllocFunc;
615 static void (*GImFreeTypeFreeFunc)(void* ptr, void* user_data) = ImFreeTypeDefaultFreeFunc;
617 
618 // FreeType memory allocation callbacks
619 static void* FreeType_Alloc(FT_Memory /*memory*/, long size)
620 {
622 }
623 
624 static void FreeType_Free(FT_Memory /*memory*/, void* block)
625 {
627 }
628 
629 static void* FreeType_Realloc(FT_Memory /*memory*/, long cur_size, long new_size, void* block)
630 {
631  // Implement realloc() as we don't ask user to provide it.
632  if (block == NULL)
633  return GImFreeTypeAllocFunc((size_t)new_size, GImFreeTypeAllocatorUserData);
634 
635  if (new_size == 0)
636  {
638  return NULL;
639  }
640 
641  if (new_size > cur_size)
642  {
643  void* new_block = GImFreeTypeAllocFunc((size_t)new_size, GImFreeTypeAllocatorUserData);
644  memcpy(new_block, block, (size_t)cur_size);
646  return new_block;
647  }
648 
649  return block;
650 }
651 
652 bool ImGuiFreeType::BuildFontAtlas(ImFontAtlas* atlas, unsigned int extra_flags)
653 {
654  // FreeType memory management: https://www.freetype.org/freetype2/docs/design/design-4.html
655  FT_MemoryRec_ memory_rec = {};
656  memory_rec.user = NULL;
657  memory_rec.alloc = &FreeType_Alloc;
658  memory_rec.free = &FreeType_Free;
659  memory_rec.realloc = &FreeType_Realloc;
660 
661  // https://www.freetype.org/freetype2/docs/reference/ft2-module_management.html#FT_New_Library
662  FT_Library ft_library;
663  FT_Error error = FT_New_Library(&memory_rec, &ft_library);
664  if (error != 0)
665  return false;
666 
667  // If you don't call FT_Add_Default_Modules() the rest of code may work, but FreeType won't use our custom allocator.
668  FT_Add_Default_Modules(ft_library);
669 
670  bool ret = ImFontAtlasBuildWithFreeType(ft_library, atlas, extra_flags);
671  FT_Done_Library(ft_library);
672 
673  return ret;
674 }
675 
676 void ImGuiFreeType::SetAllocatorFunctions(void* (*alloc_func)(size_t sz, void* user_data), void (*free_func)(void* ptr, void* user_data), void* user_data)
677 {
678  GImFreeTypeAllocFunc = alloc_func;
679  GImFreeTypeFreeFunc = free_func;
680  GImFreeTypeAllocatorUserData = user_data;
681 }
ImBitVector::Create
void Create(int sz)
Definition: imgui_internal.h:378
ImFontAtlas::TexDesiredWidth
int TexDesiredWidth
Definition: imgui.h:2248
ImGuiFreeType::Monochrome
@ Monochrome
Definition: imgui_freetype.h:28
ImVector::begin
T * begin()
Definition: imgui.h:1326
ImFontBuildDstDataFT::GlyphsSet
ImBitVector GlyphsSet
Definition: imgui_freetype.cpp:319
ImClamp
static T ImClamp(T v, T mn, T mx)
Definition: imgui_internal.h:322
ImFontAtlas::TexID
ImTextureID TexID
Definition: imgui.h:2247
ImFontBuildSrcGlyphFT::BitmapData
unsigned char * BitmapData
Definition: imgui_freetype.cpp:298
NULL
NULL
Definition: test_security_zap.cpp:405
src
GLenum src
Definition: glcorearb.h:3364
ImGuiFreeType::MonoHinting
@ MonoHinting
Definition: imgui_freetype.h:25
ImFontBuildSrcGlyphFT::Info
GlyphInfo Info
Definition: imgui_freetype.cpp:296
ImGuiFreeType::NoAutoHint
@ NoAutoHint
Definition: imgui_freetype.h:22
GImFreeTypeAllocFunc
static void *(* GImFreeTypeAllocFunc)(size_t size, void *user_data)
Definition: imgui_freetype.cpp:614
ImFont::ContainerAtlas
ImFontAtlas * ContainerAtlas
Definition: imgui.h:2286
ImUpperPowerOfTwo
static int ImUpperPowerOfTwo(int v)
Definition: imgui_internal.h:226
ImFont::IsLoaded
bool IsLoaded() const
Definition: imgui.h:2303
ImFontBuildSrcDataFT::GlyphsHighest
int GlyphsHighest
Definition: imgui_freetype.cpp:307
ImFontBuildSrcDataFT::GlyphsList
ImVector< ImFontBuildSrcGlyphFT > GlyphsList
Definition: imgui_freetype.cpp:310
ImTextureID
void * ImTextureID
Definition: imgui.h:172
ImFont::AddGlyph
IMGUI_API void AddGlyph(ImWchar c, float x0, float y0, float x1, float y1, float u0, float v0, float u1, float v1, float advance_x)
Definition: imgui_draw.cpp:2713
ImFontBuildDstDataFT::SrcCount
int SrcCount
Definition: imgui_freetype.cpp:316
ImGuiFreeType::NoHinting
@ NoHinting
Definition: imgui_freetype.h:21
ImVector< ImFontBuildSrcGlyphFT >
ImFontAtlas::TexUvScale
ImVec2 TexUvScale
Definition: imgui.h:2257
stbrp_rect::y
stbrp_coord y
Definition: imstb_rectpack.h:124
y
GLint y
Definition: glcorearb.h:2768
ImFontBuildSrcDataFT::Rects
stbrp_rect * Rects
Definition: imgui_freetype.cpp:304
ImFontAtlas
Definition: imgui.h:2182
FreeType_Realloc
static void * FreeType_Realloc(FT_Memory, long cur_size, long new_size, void *block)
Definition: imgui_freetype.cpp:629
ImVec2
Definition: imgui.h:208
x
GLint GLenum GLint x
Definition: glcorearb.h:2834
IM_UNUSED
#define IM_UNUSED(_VAR)
Definition: imgui.h:89
error
Definition: cJSON.c:88
FT_CEIL
#define FT_CEIL(X)
Definition: imgui_freetype.cpp:118
GImFreeTypeAllocatorUserData
static void * GImFreeTypeAllocatorUserData
Definition: imgui_freetype.cpp:616
imgui_internal.h
ImBitVector::Storage
ImVector< ImU32 > Storage
Definition: imgui_internal.h:377
stbrp_rect::h
stbrp_coord h
Definition: imstb_rectpack.h:121
ImFontAtlas::TexGlyphPadding
int TexGlyphPadding
Definition: imgui.h:2249
ImFontBuildDstDataFT
Definition: imgui_freetype.cpp:314
ImFontConfig::GlyphMaxAdvanceX
float GlyphMaxAdvanceX
Definition: imgui.h:2105
ImGuiFreeType::SetAllocatorFunctions
IMGUI_API void SetAllocatorFunctions(void *(*alloc_func)(size_t sz, void *user_data), void(*free_func)(void *ptr, void *user_data), void *user_data=NULL)
Definition: imgui_freetype.cpp:676
ImFontAtlas::Flags
ImFontAtlasFlags Flags
Definition: imgui.h:2246
ImFontBuildSrcDataFT::GlyphsSet
ImBitVector GlyphsSet
Definition: imgui_freetype.cpp:309
ImFreeTypeDefaultAllocFunc
static void * ImFreeTypeDefaultAllocFunc(size_t size, void *user_data)
Definition: imgui_freetype.cpp:610
ImFontAtlasBuildSetupFont
void ImFontAtlasBuildSetupFont(ImFontAtlas *atlas, ImFont *font, ImFontConfig *font_config, float ascent, float descent)
Definition: imgui_draw.cpp:2216
ImVector::Data
T * Data
Definition: imgui.h:1305
ImVector::clear
void clear()
Definition: imgui.h:1325
imstb_rectpack.h
stbrp_rect
Definition: imstb_rectpack.h:115
ImFontBuildSrcGlyphFT::Codepoint
uint32_t Codepoint
Definition: imgui_freetype.cpp:297
ImVector::Size
int Size
Definition: imgui.h:1303
ImVec2::x
float x
Definition: imgui.h:210
stbrp_rect::w
stbrp_coord w
Definition: imstb_rectpack.h:121
ImVector::push_back
void push_back(const T &v)
Definition: imgui.h:1343
ImVector::end
T * end()
Definition: imgui.h:1328
stbrp_context
Definition: imstb_rectpack.h:181
ImFontConfig::PixelSnapH
bool PixelSnapH
Definition: imgui.h:2100
ImFontConfig::SizePixels
float SizePixels
Definition: imgui.h:2097
IM_ROUND
#define IM_ROUND(_VAL)
Definition: imgui_internal.h:186
IM_ALLOC
#define IM_ALLOC(_SIZE)
Definition: imgui.h:1283
ImFontConfig::RasterizerFlags
unsigned int RasterizerFlags
Definition: imgui.h:2107
size
#define size
Definition: glcorearb.h:2944
ImBitVector
Definition: imgui_internal.h:375
ImGuiFreeType::Bold
@ Bold
Definition: imgui_freetype.h:26
ImVector::reserve
void reserve(int new_capacity)
Definition: imgui.h:1340
ImFontAtlasBuildPackCustomRects
void ImFontAtlasBuildPackCustomRects(ImFontAtlas *atlas, void *stbrp_context_opaque)
Definition: imgui_draw.cpp:2230
ImFontConfig
Definition: imgui.h:2091
ImFreeTypeDefaultFreeFunc
static void ImFreeTypeDefaultFreeFunc(void *ptr, void *user_data)
Definition: imgui_freetype.cpp:611
ImFontConfig::GlyphRanges
const ImWchar * GlyphRanges
Definition: imgui.h:2103
ImFontBuildSrcDataFT::DstIndex
int DstIndex
Definition: imgui_freetype.cpp:306
ImFontConfig::DstFont
ImFont * DstFont
Definition: imgui.h:2113
ImGuiFreeType::BuildFontAtlas
IMGUI_API bool BuildFontAtlas(ImFontAtlas *atlas, unsigned int extra_flags=0)
Definition: imgui_freetype.cpp:652
ImMax
static T ImMax(T lhs, T rhs)
Definition: imgui_internal.h:321
ImU32
unsigned int ImU32
Definition: imgui.h:194
ImFontAtlas::TexWidth
int TexWidth
Definition: imgui.h:2255
ImVector::size_in_bytes
int size_in_bytes() const
Definition: imgui.h:1320
stbrp_pack_rects
STBRP_DEF int stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int num_rects)
ImGuiFreeType::LightHinting
@ LightHinting
Definition: imgui_freetype.h:24
ImFontConfig::RasterizerMultiply
float RasterizerMultiply
Definition: imgui.h:2108
void
typedef void(APIENTRY *GLDEBUGPROCARB)(GLenum source
ImBitVector::TestBit
bool TestBit(int n) const
Definition: imgui_internal.h:380
Info
Info
ImFontBuildSrcDataFT::SrcRanges
const ImWchar * SrcRanges
Definition: imgui_freetype.cpp:305
ImFontBuildDstDataFT::GlyphsHighest
int GlyphsHighest
Definition: imgui_freetype.cpp:317
IM_FLOOR
#define IM_FLOOR(_VAL)
Definition: imgui_internal.h:185
ImFontBuildDstDataFT::GlyphsCount
int GlyphsCount
Definition: imgui_freetype.cpp:318
ImFontConfig::FontNo
int FontNo
Definition: imgui.h:2096
v1
GLfloat GLfloat v1
Definition: glcorearb.h:3086
ImFontAtlasBuildFinish
void ImFontAtlasBuildFinish(ImFontAtlas *atlas)
Definition: imgui_draw.cpp:2288
ImFontAtlas::ClearTexData
IMGUI_API void ClearTexData()
Definition: imgui_draw.cpp:1637
ImFontAtlas::Fonts
ImVector< ImFont * > Fonts
Definition: imgui.h:2259
req
void * req
Definition: test_req_relaxed.cpp:10
ImFontBuildSrcDataFT::GlyphsCount
int GlyphsCount
Definition: imgui_freetype.cpp:308
ImGuiFreeType::ForceAutoHint
@ ForceAutoHint
Definition: imgui_freetype.h:23
ImFontBuildSrcGlyphFT
Definition: imgui_freetype.cpp:294
stbrp_rect::was_packed
int was_packed
Definition: imstb_rectpack.h:125
imgui_freetype.h
ImWchar
ImWchar16 ImWchar
Definition: imgui.h:185
size
GLsizeiptr size
Definition: glcorearb.h:2943
v0
GLfloat v0
Definition: glcorearb.h:3085
ImVector::resize
void resize(int new_size)
Definition: imgui.h:1337
ImFont::Ascent
float Ascent
Definition: imgui.h:2293
ImBitVector::Clear
void Clear()
Definition: imgui_internal.h:379
ImFontConfig::GlyphMinAdvanceX
float GlyphMinAdvanceX
Definition: imgui.h:2104
ImVector::empty
bool empty() const
Definition: imgui.h:1318
ImFontAtlas::ConfigData
ImVector< ImFontConfig > ConfigData
Definition: imgui.h:2261
dst
GLenum GLenum dst
Definition: glcorearb.h:3364
stbrp_rect::x
stbrp_coord x
Definition: imstb_rectpack.h:124
ImFont
Definition: imgui.h:2272
stbrp_coord
unsigned short stbrp_coord
Definition: imstb_rectpack.h:87
ImSqrt
#define ImSqrt(X)
Definition: imgui_internal.h:306
ImFontConfig::GlyphOffset
ImVec2 GlyphOffset
Definition: imgui.h:2102
ImFontAtlas::TexUvWhitePixel
ImVec2 TexUvWhitePixel
Definition: imgui.h:2258
ImFontConfig::FontDataSize
int FontDataSize
Definition: imgui.h:2094
IM_ASSERT
#define IM_ASSERT(_EXPR)
Definition: imgui.h:79
ImFontAtlasFlags_NoPowerOfTwoHeight
@ ImFontAtlasFlags_NoPowerOfTwoHeight
Definition: imgui.h:2161
ImFontAtlas::TexHeight
int TexHeight
Definition: imgui.h:2256
FreeType_Alloc
static void * FreeType_Alloc(FT_Memory, long size)
Definition: imgui_freetype.cpp:619
f
GLfloat f
Definition: glcorearb.h:3964
ImFontAtlasBuildInit
void ImFontAtlasBuildInit(ImFontAtlas *atlas)
Definition: imgui_draw.cpp:2206
w
GLubyte GLubyte GLubyte GLubyte w
Definition: glcorearb.h:3126
ImFontConfig::FontData
void * FontData
Definition: imgui.h:2093
ImFontAtlas::GetGlyphRangesDefault
const IMGUI_API ImWchar * GetGlyphRangesDefault()
Definition: imgui_draw.cpp:2330
IM_FREE
#define IM_FREE(_PTR)
Definition: imgui.h:1284
ImFontAtlas::TexPixelsAlpha8
unsigned char * TexPixelsAlpha8
Definition: imgui.h:2253
ImFontAtlasBuildWithFreeType
bool ImFontAtlasBuildWithFreeType(FT_Library ft_library, ImFontAtlas *atlas, unsigned int extra_flags)
Definition: imgui_freetype.cpp:322
ImGuiFreeType::Oblique
@ Oblique
Definition: imgui_freetype.h:27
ImVector::back
T & back()
Definition: imgui.h:1332
stbrp_init_target
STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes)
GImFreeTypeFreeFunc
static void(* GImFreeTypeFreeFunc)(void *ptr, void *user_data)
Definition: imgui_freetype.cpp:615
ImBitVector::SetBit
void SetBit(int n)
Definition: imgui_internal.h:381
ImFontBuildSrcDataFT::Font
FreeTypeFont Font
Definition: imgui_freetype.cpp:303
it
MapIter it
Definition: php/ext/google/protobuf/map.c:205
FreeType_Free
static void FreeType_Free(FT_Memory, void *block)
Definition: imgui_freetype.cpp:624
ImFontAtlasBuildMultiplyCalcLookupTable
void ImFontAtlasBuildMultiplyCalcLookupTable(unsigned char out_table[256], float in_brighten_factor)
Definition: imgui_draw.cpp:1895
h
GLfloat GLfloat GLfloat GLfloat h
Definition: glcorearb.h:4147
ImVec2::y
float y
Definition: imgui.h:210
ImFontBuildSrcDataFT
Definition: imgui_freetype.cpp:301


libaditof
Author(s):
autogenerated on Wed May 21 2025 02:06:54