Skip to content

Commit 3ec8f95

Browse files
committed
WIP: select size for fixed sized, unscalable bitmaps and correct for it with render density
1 parent b46f099 commit 3ec8f95

File tree

1 file changed

+56
-14
lines changed

1 file changed

+56
-14
lines changed

misc/freetype/imgui_freetype.cpp

Lines changed: 56 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ static FT_Error ImGuiLunasvgPortPresetSlot(FT_GlyphSlot slot, FT_Bool cache, FT_
108108
//-------------------------------------------------------------------------
109109

110110
#define FT_CEIL(X) (((X + 63) & -64) / 64) // From SDL_ttf: Handy routines for converting from fixed point
111-
#define FT_SCALEFACTOR 64.0f
111+
#define FT_SCALEFACTOR 64.0f // for converting from/to 26.6 factionals
112112

113113
// Glyph metrics:
114114
// --------------
@@ -435,19 +435,52 @@ static bool ImGui_ImplFreeType_FontBakedInit(ImFontAtlas* atlas, ImFontConfig* s
435435

436436
FT_New_Size(bd_font_data->FtFace, &bd_baked_data->FtSize);
437437
FT_Activate_Size(bd_baked_data->FtSize);
438-
439-
// Vuhdo 2017: "I'm not sure how to deal with font sizes properly. As far as I understand, currently ImGui assumes that the 'pixel_height'
440-
// 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.
441-
// FT_Set_Pixel_Sizes() doesn't seem to get us the same result."
442-
// (FT_Set_Pixel_Sizes() essentially calls FT_Request_Size() with FT_SIZE_REQUEST_TYPE_NOMINAL)
443438
const float rasterizer_density = src->RasterizerDensity * baked->RasterizerDensity;
444-
FT_Size_RequestRec req;
445-
req.type = (bd_font_data->UserFlags & ImGuiFreeTypeLoaderFlags_Bitmap) ? FT_SIZE_REQUEST_TYPE_NOMINAL : FT_SIZE_REQUEST_TYPE_REAL_DIM;
446-
req.width = 0;
447-
req.height = (uint32_t)(size * 64 * rasterizer_density);
448-
req.horiResolution = 0;
449-
req.vertResolution = 0;
450-
FT_Request_Size(bd_font_data->FtFace, &req);
439+
if ( // fixed sized bitmaps
440+
((bd_font_data->FtFace->face_flags & FT_FACE_FLAG_FIXED_SIZES) != 0) &&
441+
((bd_font_data->UserFlags & ImGuiFreeTypeLoaderFlags_Bitmap) != 0) &&
442+
((bd_font_data->FtFace->face_flags & FT_FACE_FLAG_SCALABLE) == 0)
443+
) {
444+
IM_ASSERT(bd_font_data->FtFace->num_fixed_sizes > 0);
445+
446+
// loop over sizes and pick the closest, larger (or better equal) size
447+
int best_index = 0;
448+
FT_Short best_height = bd_font_data->FtFace->available_sizes[best_index].y_ppem / FT_SCALEFACTOR;
449+
for (int i = 1; i < bd_font_data->FtFace->num_fixed_sizes; i++) {
450+
const auto cur_height = bd_font_data->FtFace->available_sizes[i].y_ppem / FT_SCALEFACTOR;
451+
// TODO: is this overkill
452+
// TODO: is-float-close with epsilon param would be nice, maybe
453+
if (ImFabs(cur_height - size) < 0.001f) {
454+
best_index = i;
455+
break;
456+
} else if (cur_height < size) {
457+
if (best_height < cur_height) {
458+
best_index = i;
459+
best_height = cur_height;
460+
}
461+
} else { // >
462+
if (best_height > cur_height) {
463+
best_index = i;
464+
best_height = cur_height;
465+
}
466+
}
467+
}
468+
//fprintf(stderr, "!!!!! selecting bitmap index: %zu, with height %d for size %f\n", best_index, best_height, size);
469+
FT_Select_Size(bd_font_data->FtFace, best_index);
470+
} else {
471+
// Vuhdo 2017: "I'm not sure how to deal with font sizes properly. As far as I understand, currently ImGui assumes that the 'pixel_height'
472+
// 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.
473+
// FT_Set_Pixel_Sizes() doesn't seem to get us the same result."
474+
// (FT_Set_Pixel_Sizes() essentially calls FT_Request_Size() with FT_SIZE_REQUEST_TYPE_NOMINAL)
475+
476+
FT_Size_RequestRec req;
477+
req.type = (bd_font_data->UserFlags & ImGuiFreeTypeLoaderFlags_Bitmap) ? FT_SIZE_REQUEST_TYPE_NOMINAL : FT_SIZE_REQUEST_TYPE_REAL_DIM;
478+
req.width = 0;
479+
req.height = (uint32_t)(size * FT_SCALEFACTOR * rasterizer_density);
480+
req.horiResolution = 0;
481+
req.vertResolution = 0;
482+
FT_Request_Size(bd_font_data->FtFace, &req);
483+
}
451484

452485
// Output
453486
if (src->MergeMode == false)
@@ -496,7 +529,16 @@ static bool ImGui_ImplFreeType_FontBakedLoadGlyph(ImFontAtlas* atlas, ImFontConf
496529

497530
FT_Face face = bd_font_data->FtFace;
498531
FT_GlyphSlot slot = face->glyph;
499-
const float rasterizer_density = src->RasterizerDensity * baked->RasterizerDensity;
532+
float bitmap_density = 1.f;
533+
if (
534+
((face->face_flags & FT_FACE_FLAG_FIXED_SIZES) != 0) &&
535+
((bd_font_data->UserFlags & ImGuiFreeTypeLoaderFlags_Bitmap) != 0) &&
536+
((face->face_flags & FT_FACE_FLAG_SCALABLE) == 0)
537+
) {
538+
// scale fixed size bitmap to target size
539+
bitmap_density = float(bd_font_data->FtFace->size->metrics.y_ppem) / baked->Size;
540+
}
541+
const float rasterizer_density = src->RasterizerDensity * baked->RasterizerDensity * bitmap_density;
500542

501543
// Load metrics only mode
502544
const float advance_x = (slot->advance.x / FT_SCALEFACTOR) / rasterizer_density;

0 commit comments

Comments
 (0)