diff --git a/misc/freetype/imgui_freetype.cpp b/misc/freetype/imgui_freetype.cpp index 0245856d2..47f8cc984 100644 --- a/misc/freetype/imgui_freetype.cpp +++ b/misc/freetype/imgui_freetype.cpp @@ -142,24 +142,12 @@ namespace // | | // |------------- advanceX ----------->| - // A structure that describe a glyph. - struct GlyphInfo - { - int Width; // Glyph's width in pixels. - int Height; // Glyph's height in pixels. - FT_Int OffsetX; // The distance from the origin ("pen position") to the left of the glyph. - FT_Int OffsetY; // The distance from the origin to the top of the glyph. This is usually a value < 0. - float AdvanceX; // The distance from the origin to the origin of the next glyph. This is usually a value > 0. - bool IsColored; // The glyph is colored - }; - // Stored in ImFontAtlas::FontLoaderData struct ImGui_ImplFreeType_Data { - FT_Library Library; - FT_MemoryRec_ MemoryManager; - - ImGui_ImplFreeType_Data() { memset((void*)this, 0, sizeof(*this)); } + FT_Library Library; + FT_MemoryRec_ MemoryManager; + ImGui_ImplFreeType_Data() { memset((void*)this, 0, sizeof(*this)); } }; // Font parameters and metrics. @@ -180,8 +168,7 @@ namespace void CloseFont(); void SetPixelHeight(float pixel_height); // Change font pixel size. const FT_Glyph_Metrics* LoadGlyph(uint32_t in_codepoint); - const FT_Bitmap* RenderGlyphAndGetInfo(GlyphInfo* out_glyph_info); - void BlitGlyph(const FT_Bitmap* ft_bitmap, uint32_t* dst, uint32_t dst_pitch, unsigned char* multiply_table = nullptr); + void BlitGlyph(const FT_Bitmap* ft_bitmap, uint32_t* dst, uint32_t dst_pitch); ImGui_ImplFreeType_FontSrcData() { memset((void*)this, 0, sizeof(*this)); } ~ImGui_ImplFreeType_FontSrcData() { CloseFont(); } @@ -316,25 +303,7 @@ namespace return &slot->metrics; } - const FT_Bitmap* ImGui_ImplFreeType_FontSrcData::RenderGlyphAndGetInfo(GlyphInfo* out_glyph_info) - { - FT_GlyphSlot slot = FtFace->glyph; - FT_Error error = FT_Render_Glyph(slot, RenderMode); - if (error != 0) - return nullptr; - - FT_Bitmap* ft_bitmap = &FtFace->glyph->bitmap; - out_glyph_info->Width = (int)ft_bitmap->width; - out_glyph_info->Height = (int)ft_bitmap->rows; - out_glyph_info->OffsetX = FtFace->glyph->bitmap_left; - out_glyph_info->OffsetY = -FtFace->glyph->bitmap_top; - out_glyph_info->AdvanceX = (float)slot->advance.x / FT_SCALEFACTOR; - out_glyph_info->IsColored = (ft_bitmap->pixel_mode == FT_PIXEL_MODE_BGRA); - - return ft_bitmap; - } - - void ImGui_ImplFreeType_FontSrcData::BlitGlyph(const FT_Bitmap* ft_bitmap, uint32_t* dst, uint32_t dst_pitch, unsigned char* multiply_table) + void ImGui_ImplFreeType_FontSrcData::BlitGlyph(const FT_Bitmap* ft_bitmap, uint32_t* dst, uint32_t dst_pitch) { IM_ASSERT(ft_bitmap != nullptr); const uint32_t w = ft_bitmap->width; @@ -346,24 +315,13 @@ namespace { case FT_PIXEL_MODE_GRAY: // Grayscale image, 1 byte per pixel. { - if (multiply_table == nullptr) - { - for (uint32_t y = 0; y < h; y++, src += src_pitch, dst += dst_pitch) - for (uint32_t x = 0; x < w; x++) - dst[x] = IM_COL32(255, 255, 255, src[x]); - } - else - { - for (uint32_t y = 0; y < h; y++, src += src_pitch, dst += dst_pitch) - for (uint32_t x = 0; x < w; x++) - dst[x] = IM_COL32(255, 255, 255, multiply_table[src[x]]); - } + for (uint32_t y = 0; y < h; y++, src += src_pitch, dst += dst_pitch) + for (uint32_t x = 0; x < w; x++) + dst[x] = IM_COL32(255, 255, 255, src[x]); break; } case FT_PIXEL_MODE_MONO: // Monochrome image, 1 bit per pixel. The bits in each byte are ordered from MSB to LSB. { - uint8_t color0 = multiply_table ? multiply_table[0] : 0; - uint8_t color1 = multiply_table ? multiply_table[255] : 255; for (uint32_t y = 0; y < h; y++, src += src_pitch, dst += dst_pitch) { uint8_t bits = 0; @@ -372,7 +330,7 @@ namespace { if ((x & 7) == 0) bits = *bits_ptr++; - dst[x] = IM_COL32(255, 255, 255, (bits & 0x80) ? color1 : color0); + dst[x] = IM_COL32(255, 255, 255, (bits & 0x80) ? 255 : 0); } } break; @@ -381,26 +339,12 @@ namespace { // FIXME: Converting pre-multiplied alpha to straight. Doesn't smell good. #define DE_MULTIPLY(color, alpha) ImMin((ImU32)(255.0f * (float)color / (float)(alpha + FLT_MIN) + 0.5f), 255u) - if (multiply_table == nullptr) - { - for (uint32_t y = 0; y < h; y++, src += src_pitch, dst += dst_pitch) - for (uint32_t x = 0; x < w; x++) - { - uint8_t r = src[x * 4 + 2], g = src[x * 4 + 1], b = src[x * 4], a = src[x * 4 + 3]; - dst[x] = IM_COL32(DE_MULTIPLY(r, a), DE_MULTIPLY(g, a), DE_MULTIPLY(b, a), a); - } - } - else - { - for (uint32_t y = 0; y < h; y++, src += src_pitch, dst += dst_pitch) + for (uint32_t y = 0; y < h; y++, src += src_pitch, dst += dst_pitch) + for (uint32_t x = 0; x < w; x++) { - for (uint32_t x = 0; x < w; x++) - { - uint8_t r = src[x * 4 + 2], g = src[x * 4 + 1], b = src[x * 4], a = src[x * 4 + 3]; - dst[x] = IM_COL32(multiply_table[DE_MULTIPLY(r, a)], multiply_table[DE_MULTIPLY(g, a)], multiply_table[DE_MULTIPLY(b, a)], multiply_table[a]); - } + uint8_t r = src[x * 4 + 2], g = src[x * 4 + 1], b = src[x * 4], a = src[x * 4 + 3]; + dst[x] = IM_COL32(DE_MULTIPLY(r, a), DE_MULTIPLY(g, a), DE_MULTIPLY(b, a), a); } - } #undef DE_MULTIPLY break; } @@ -410,376 +354,6 @@ namespace } } // namespace -#if 0 - -#ifndef STB_RECT_PACK_IMPLEMENTATION // in case the user already have an implementation in the _same_ compilation unit (e.g. unity builds) -#ifndef IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION -#define STBRP_ASSERT(x) do { IM_ASSERT(x); } while (0) -#define STBRP_STATIC -#define STB_RECT_PACK_IMPLEMENTATION -#endif -#ifdef IMGUI_STB_RECT_PACK_FILENAME -#include IMGUI_STB_RECT_PACK_FILENAME -#else -#include "imstb_rectpack.h" -#endif -#endif - -struct ImFontBuildSrcGlyphFT -{ - GlyphInfo Info; - uint32_t Codepoint; - unsigned int* BitmapData; // Point within one of the dst_tmp_bitmap_buffers[] array - - ImFontBuildSrcGlyphFT() { memset((void*)this, 0, sizeof(*this)); } -}; - -struct ImFontBuildSrcDataFT -{ - FreeTypeFont Font; - stbrp_rect* Rects; // Rectangle to pack. We first fill in their size and the packer will give us their position. - const ImWchar* SrcRanges; // Ranges as requested by user (user is allowed to request too much, e.g. 0x0020..0xFFFF) - int DstIndex; // Index into atlas->Fonts[] and dst_tmp_array[] - int GlyphsHighest; // Highest requested codepoint - int GlyphsCount; // Glyph count (excluding missing glyphs and glyphs already set by an earlier source font) - ImBitVector GlyphsSet; // Glyph bit map (random access, 1-bit per codepoint. This will be a maximum of 8KB) - ImVector GlyphsList; -}; - -// Temporary data for one destination ImFont* (multiple source fonts can be merged into one destination ImFont) -struct ImFontBuildDstDataFT -{ - int SrcCount; // Number of source fonts targeting this destination font. - int GlyphsHighest; - int GlyphsCount; - ImBitVector GlyphsSet; // This is used to resolve collision when multiple sources are merged into a same destination font. -}; - -bool ImFontAtlasBuildWithFreeTypeEx(FT_Library ft_library, ImFontAtlas* atlas, unsigned int extra_flags) -{ - IM_ASSERT(atlas->Sources.Size > 0); - - ImFontAtlasBuildInit(atlas); - - // Clear atlas - atlas->TexID._TexID = 0; - atlas->TexWidth = atlas->TexHeight = 0; - atlas->TexUvScale = ImVec2(0.0f, 0.0f); - atlas->TexUvWhitePixel = ImVec2(0.0f, 0.0f); - atlas->ClearTexData(); - - // Temporary storage for building - bool src_load_color = false; - ImVector src_tmp_array; - ImVector dst_tmp_array; - src_tmp_array.resize(atlas->Sources.Size); - dst_tmp_array.resize(atlas->Fonts.Size); - memset((void*)src_tmp_array.Data, 0, (size_t)src_tmp_array.size_in_bytes()); - memset((void*)dst_tmp_array.Data, 0, (size_t)dst_tmp_array.size_in_bytes()); - - // 1. Initialize font loading structure, check font data validity - for (int src_i = 0; src_i < atlas->Sources.Size; src_i++) - { - ImFontBuildSrcDataFT& src_tmp = src_tmp_array[src_i]; - ImFontConfig& src = atlas->Sources[src_i]; - FreeTypeFont& font_face = src_tmp.Font; - IM_ASSERT(src.DstFont && (!src.DstFont->IsLoaded() || src.DstFont->ContainerAtlas == atlas)); - - // Find index from src.DstFont (we allow the user to set cfg.DstFont. Also it makes casual debugging nicer than when storing indices) - src_tmp.DstIndex = -1; - for (int output_i = 0; output_i < atlas->Fonts.Size && src_tmp.DstIndex == -1; output_i++) - if (src.DstFont == atlas->Fonts[output_i]) - src_tmp.DstIndex = output_i; - IM_ASSERT(src_tmp.DstIndex != -1); // src.DstFont not pointing within atlas->Fonts[] array? - if (src_tmp.DstIndex == -1) - return false; - - // Load font - if (!font_face.InitFont(ft_library, src, extra_flags)) - return false; - - // Measure highest codepoints - src_load_color |= (src.FontBuilderFlags & ImGuiFreeTypeBuilderFlags_LoadColor) != 0; - ImFontBuildDstDataFT& dst_tmp = dst_tmp_array[src_tmp.DstIndex]; - src_tmp.SrcRanges = src.GlyphRanges ? src.GlyphRanges : atlas->GetGlyphRangesDefault(); - for (const ImWchar* src_range = src_tmp.SrcRanges; src_range[0] && src_range[1]; src_range += 2) - { - // Check for valid range. This may also help detect *some* dangling pointers, because a common - // user error is to setup ImFontConfig::GlyphRanges with a pointer to data that isn't persistent, - // or to forget to zero-terminate the glyph range array. - IM_ASSERT(src_range[0] <= src_range[1] && "Invalid range: is your glyph range array persistent? it is zero-terminated?"); - src_tmp.GlyphsHighest = ImMax(src_tmp.GlyphsHighest, (int)src_range[1]); - } - dst_tmp.SrcCount++; - dst_tmp.GlyphsHighest = ImMax(dst_tmp.GlyphsHighest, src_tmp.GlyphsHighest); - } - - // 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. - int total_glyphs_count = 0; - for (int src_i = 0; src_i < src_tmp_array.Size; src_i++) - { - ImFontBuildSrcDataFT& src_tmp = src_tmp_array[src_i]; - ImFontBuildDstDataFT& dst_tmp = dst_tmp_array[src_tmp.DstIndex]; - src_tmp.GlyphsSet.Create(src_tmp.GlyphsHighest + 1); - if (dst_tmp.GlyphsSet.Storage.empty()) - dst_tmp.GlyphsSet.Create(dst_tmp.GlyphsHighest + 1); - - for (const ImWchar* src_range = src_tmp.SrcRanges; src_range[0] && src_range[1]; src_range += 2) - for (int codepoint = src_range[0]; codepoint <= (int)src_range[1]; codepoint++) - { - if (dst_tmp.GlyphsSet.TestBit(codepoint)) // Don't overwrite existing glyphs. We could make this an option (e.g. MergeOverwrite) - continue; - 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..) - if (glyph_index == 0) - continue; - - // Add to avail set/counters - src_tmp.GlyphsCount++; - dst_tmp.GlyphsCount++; - src_tmp.GlyphsSet.SetBit(codepoint); - dst_tmp.GlyphsSet.SetBit(codepoint); - total_glyphs_count++; - } - } - - // 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) - for (int src_i = 0; src_i < src_tmp_array.Size; src_i++) - { - ImFontBuildSrcDataFT& src_tmp = src_tmp_array[src_i]; - src_tmp.GlyphsList.reserve(src_tmp.GlyphsCount); - - IM_ASSERT(sizeof(src_tmp.GlyphsSet.Storage.Data[0]) == sizeof(ImU32)); - const ImU32* it_begin = src_tmp.GlyphsSet.Storage.begin(); - const ImU32* it_end = src_tmp.GlyphsSet.Storage.end(); - for (const ImU32* it = it_begin; it < it_end; it++) - if (ImU32 entries_32 = *it) - for (ImU32 bit_n = 0; bit_n < 32; bit_n++) - if (entries_32 & ((ImU32)1 << bit_n)) - { - ImFontBuildSrcGlyphFT src_glyph; - src_glyph.Codepoint = (ImWchar)(((it - it_begin) << 5) + bit_n); - //src_glyph.GlyphIndex = 0; // FIXME-OPT: We had this info in the previous step and lost it.. - src_tmp.GlyphsList.push_back(src_glyph); - } - src_tmp.GlyphsSet.Clear(); - IM_ASSERT(src_tmp.GlyphsList.Size == src_tmp.GlyphsCount); - } - for (int dst_i = 0; dst_i < dst_tmp_array.Size; dst_i++) - dst_tmp_array[dst_i].GlyphsSet.Clear(); - dst_tmp_array.clear(); - - // Allocate packing character data and flag packed characters buffer as non-packed (x0=y0=x1=y1=0) - // (We technically don't need to zero-clear buf_rects, but let's do it for the sake of sanity) - ImVector buf_rects; - buf_rects.resize(total_glyphs_count); - memset(buf_rects.Data, 0, (size_t)buf_rects.size_in_bytes()); - - // Allocate temporary rasterization data buffers. - // We could not find a way to retrieve accurate glyph size without rendering them. - // (e.g. slot->metrics->width not always matching bitmap->width, especially considering the Oblique transform) - // We allocate in chunks of 256 KB to not waste too much extra memory ahead. Hopefully users of FreeType won't mind the temporary allocations. - const int BITMAP_BUFFERS_CHUNK_SIZE = 256 * 1024; - int buf_bitmap_current_used_bytes = 0; - ImVector buf_bitmap_buffers; - buf_bitmap_buffers.push_back((unsigned char*)IM_ALLOC(BITMAP_BUFFERS_CHUNK_SIZE)); - - // 4. Gather glyphs sizes so we can pack them in our virtual canvas. - // 8. Render/rasterize font characters into the texture - int total_surface = 0; - int buf_rects_out_n = 0; - const int pack_padding = atlas->TexGlyphPadding; - for (int src_i = 0; src_i < src_tmp_array.Size; src_i++) - { - ImFontBuildSrcDataFT& src_tmp = src_tmp_array[src_i]; - ImFontConfig& src = atlas->Sources[src_i]; - if (src_tmp.GlyphsCount == 0) - continue; - - src_tmp.Rects = &buf_rects[buf_rects_out_n]; - buf_rects_out_n += src_tmp.GlyphsCount; - - // Compute multiply table if requested - const bool multiply_enabled = (src.RasterizerMultiply != 1.0f); - unsigned char multiply_table[256]; - if (multiply_enabled) - ImFontAtlasBuildMultiplyCalcLookupTable(multiply_table, src.RasterizerMultiply); - - // Gather the sizes of all rectangles we will need to pack - for (int glyph_i = 0; glyph_i < src_tmp.GlyphsList.Size; glyph_i++) - { - ImFontBuildSrcGlyphFT& src_glyph = src_tmp.GlyphsList[glyph_i]; - - const FT_Glyph_Metrics* metrics = src_tmp.Font.LoadGlyph(src_glyph.Codepoint); - if (metrics == nullptr) - continue; - - // Render glyph into a bitmap (currently held by FreeType) - const FT_Bitmap* ft_bitmap = src_tmp.Font.RenderGlyphAndGetInfo(&src_glyph.Info); - if (ft_bitmap == nullptr) - continue; - - // Allocate new temporary chunk if needed - const int bitmap_size_in_bytes = src_glyph.Info.Width * src_glyph.Info.Height * 4; - if (buf_bitmap_current_used_bytes + bitmap_size_in_bytes > BITMAP_BUFFERS_CHUNK_SIZE) - { - buf_bitmap_current_used_bytes = 0; - buf_bitmap_buffers.push_back((unsigned char*)IM_ALLOC(BITMAP_BUFFERS_CHUNK_SIZE)); - } - IM_ASSERT(buf_bitmap_current_used_bytes + bitmap_size_in_bytes <= BITMAP_BUFFERS_CHUNK_SIZE); // We could probably allocate custom-sized buffer instead. - - // Blit rasterized pixels to our temporary buffer and keep a pointer to it. - src_glyph.BitmapData = (unsigned int*)(buf_bitmap_buffers.back() + buf_bitmap_current_used_bytes); - buf_bitmap_current_used_bytes += bitmap_size_in_bytes; - src_tmp.Font.BlitGlyph(ft_bitmap, src_glyph.BitmapData, src_glyph.Info.Width, multiply_enabled ? multiply_table : nullptr); - - src_tmp.Rects[glyph_i].w = (stbrp_coord)(src_glyph.Info.Width + pack_padding); - src_tmp.Rects[glyph_i].h = (stbrp_coord)(src_glyph.Info.Height + pack_padding); - total_surface += src_tmp.Rects[glyph_i].w * src_tmp.Rects[glyph_i].h; - } - } - for (int i = 0; i < atlas->CustomRects.Size; i++) - total_surface += (atlas->CustomRects[i].Width + pack_padding) * (atlas->CustomRects[i].Height + pack_padding); - - // We need a width for the skyline algorithm, any width! - // The exact width doesn't really matter much, but some API/GPU have texture size limitations and increasing width can decrease height. - // User can override TexDesiredWidth and TexGlyphPadding if they wish, otherwise we use a simple heuristic to select the width based on expected surface. - const int surface_sqrt = (int)ImSqrt((float)total_surface) + 1; - atlas->TexHeight = 0; - if (atlas->TexDesiredWidth > 0) - atlas->TexWidth = atlas->TexDesiredWidth; - else - atlas->TexWidth = (surface_sqrt >= 4096 * 0.7f) ? 4096 : (surface_sqrt >= 2048 * 0.7f) ? 2048 : (surface_sqrt >= 1024 * 0.7f) ? 1024 : 512; - - // 5. Start packing - // Pack our extra data rectangles first, so it will be on the upper-left corner of our texture (UV will have small values). - const int TEX_HEIGHT_MAX = 1024 * 32; - const int num_nodes_for_packing_algorithm = atlas->TexWidth - atlas->TexGlyphPadding; - ImVector pack_nodes; - pack_nodes.resize(num_nodes_for_packing_algorithm); - stbrp_context pack_context; - stbrp_init_target(&pack_context, atlas->TexWidth - atlas->TexGlyphPadding, TEX_HEIGHT_MAX - atlas->TexGlyphPadding, pack_nodes.Data, pack_nodes.Size); - ImFontAtlasBuildPackCustomRects(atlas, &pack_context); - - // 6. Pack each source font. No rendering yet, we are working with rectangles in an infinitely tall texture at this point. - for (int src_i = 0; src_i < src_tmp_array.Size; src_i++) - { - ImFontBuildSrcDataFT& src_tmp = src_tmp_array[src_i]; - if (src_tmp.GlyphsCount == 0) - continue; - - stbrp_pack_rects(&pack_context, src_tmp.Rects, src_tmp.GlyphsCount); - - // Extend texture height and mark missing glyphs as non-packed so we won't render them. - // 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?) - for (int glyph_i = 0; glyph_i < src_tmp.GlyphsCount; glyph_i++) - if (src_tmp.Rects[glyph_i].was_packed) - atlas->TexHeight = ImMax(atlas->TexHeight, src_tmp.Rects[glyph_i].y + src_tmp.Rects[glyph_i].h); - } - - // 7. Allocate texture - atlas->TexHeight = (atlas->Flags & ImFontAtlasFlags_NoPowerOfTwoHeight) ? (atlas->TexHeight + 1) : ImUpperPowerOfTwo(atlas->TexHeight); - atlas->TexUvScale = ImVec2(1.0f / atlas->TexWidth, 1.0f / atlas->TexHeight); - if (src_load_color) - { - size_t tex_size = (size_t)atlas->TexWidth * atlas->TexHeight * 4; - atlas->TexPixelsRGBA32 = (unsigned int*)IM_ALLOC(tex_size); - memset(atlas->TexPixelsRGBA32, 0, tex_size); - } - else - { - size_t tex_size = (size_t)atlas->TexWidth * atlas->TexHeight * 1; - atlas->TexPixelsAlpha8 = (unsigned char*)IM_ALLOC(tex_size); - memset(atlas->TexPixelsAlpha8, 0, tex_size); - } - - // 8. Copy rasterized font characters back into the main texture - // 9. Setup ImFont and glyphs for runtime - bool tex_use_colors = false; - for (int src_i = 0; src_i < src_tmp_array.Size; src_i++) - { - ImFontBuildSrcDataFT& src_tmp = src_tmp_array[src_i]; - - // When merging fonts with MergeMode=true: - // - We can have multiple input fonts writing into a same destination font. - // - dst_font->Sources is != from src which is our source configuration. - ImFontConfig& src = atlas->Sources[src_i]; - ImFont* dst_font = src.DstFont; - - const float ascent = src_tmp.Font.Info.Ascender; - const float descent = src_tmp.Font.Info.Descender; - ImFontAtlasBuildSetupFont(atlas, dst_font, &src, ascent, descent); - - if (src_tmp.GlyphsCount == 0) - continue; - const float font_off_x = src.GlyphOffset.x; - const float font_off_y = src.GlyphOffset.y + IM_ROUND(dst_font->Ascent); - - const int padding = atlas->TexGlyphPadding; - for (int glyph_i = 0; glyph_i < src_tmp.GlyphsCount; glyph_i++) - { - ImFontBuildSrcGlyphFT& src_glyph = src_tmp.GlyphsList[glyph_i]; - stbrp_rect& pack_rect = src_tmp.Rects[glyph_i]; - IM_ASSERT(pack_rect.was_packed); - if (pack_rect.w == 0 && pack_rect.h == 0) - continue; - - GlyphInfo& info = src_glyph.Info; - IM_ASSERT(info.Width + padding <= pack_rect.w); - IM_ASSERT(info.Height + padding <= pack_rect.h); - const int tx = pack_rect.x + padding; - const int ty = pack_rect.y + padding; - - // Register glyph - float x0 = info.OffsetX * src_tmp.Font.InvRasterizationDensity + font_off_x; - float y0 = info.OffsetY * src_tmp.Font.InvRasterizationDensity + font_off_y; - float x1 = x0 + info.Width * src_tmp.Font.InvRasterizationDensity; - float y1 = y0 + info.Height * src_tmp.Font.InvRasterizationDensity; - float u0 = (tx) / (float)atlas->TexWidth; - float v0 = (ty) / (float)atlas->TexHeight; - float u1 = (tx + info.Width) / (float)atlas->TexWidth; - float v1 = (ty + info.Height) / (float)atlas->TexHeight; - dst_font->AddGlyph(&src, (ImWchar)src_glyph.Codepoint, x0, y0, x1, y1, u0, v0, u1, v1, info.AdvanceX * src_tmp.Font.InvRasterizationDensity); - - ImFontGlyph* dst_glyph = &dst_font->Glyphs.back(); - IM_ASSERT(dst_glyph->Codepoint == src_glyph.Codepoint); - if (src_glyph.Info.IsColored) - dst_glyph->Colored = tex_use_colors = true; - - // Blit from temporary buffer to final texture - size_t blit_src_stride = (size_t)src_glyph.Info.Width; - size_t blit_dst_stride = (size_t)atlas->TexWidth; - unsigned int* blit_src = src_glyph.BitmapData; - if (atlas->TexPixelsAlpha8 != nullptr) - { - unsigned char* blit_dst = atlas->TexPixelsAlpha8 + (ty * blit_dst_stride) + tx; - for (int y = 0; y < info.Height; y++, blit_dst += blit_dst_stride, blit_src += blit_src_stride) - for (int x = 0; x < info.Width; x++) - blit_dst[x] = (unsigned char)((blit_src[x] >> IM_COL32_A_SHIFT) & 0xFF); - } - else - { - unsigned int* blit_dst = atlas->TexPixelsRGBA32 + (ty * blit_dst_stride) + tx; - for (int y = 0; y < info.Height; y++, blit_dst += blit_dst_stride, blit_src += blit_src_stride) - for (int x = 0; x < info.Width; x++) - blit_dst[x] = blit_src[x]; - } - } - - src_tmp.Rects = nullptr; - } - atlas->TexPixelsUseColors = tex_use_colors; - - // Cleanup - for (int buf_i = 0; buf_i < buf_bitmap_buffers.Size; buf_i++) - IM_FREE(buf_bitmap_buffers[buf_i]); - src_tmp_array.clear_destruct(); - - ImFontAtlasBuildFinish(atlas); - - return true; -} -#endif - // FreeType memory allocation callbacks static void* FreeType_Alloc(FT_Memory /*memory*/, long size) { @@ -941,7 +515,7 @@ bool ImGui_ImplFreeType_FontAddGlyph(ImFontAtlas* atlas, ImFont* font, ImFontCon // Render pixels to our temporary buffer atlas->Builder->TempBuffer.resize(w * h * 4); uint32_t* temp_buffer = (uint32_t*)atlas->Builder->TempBuffer.Data; - bd_font_data->BlitGlyph(ft_bitmap, temp_buffer, w, nullptr);// multiply_enabled ? multiply_table : nullptr); + bd_font_data->BlitGlyph(ft_bitmap, temp_buffer, w); float font_off_x = src->GlyphOffset.x; float font_off_y = src->GlyphOffset.y + IM_ROUND(font->Ascent);