Skip to content

Commit

Permalink
Update docs / 2024-04-18 / 16:09:52
Browse files Browse the repository at this point in the history
  • Loading branch information
pthom committed Apr 18, 2024
1 parent 2ca0553 commit 441c270
Show file tree
Hide file tree
Showing 10 changed files with 457 additions and 147 deletions.
152 changes: 120 additions & 32 deletions docs/book/_sources/doc_api.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,16 @@ float EmSize(float nbLines);
# Load fonts
See [hello_imgui_font.h](https://github.com/pthom/hello_imgui/blob/master/src/hello_imgui/hello_imgui_font.h).
```cpp
// When loading fonts, use
// HelloImGui::LoadFont(..)
// or
// HelloImGui::LoadDpiResponsiveFont()
//
// When loading fonts, use HelloImGui::LoadFont(fontFilename, fontSize, fontLoadingParams)
// Use these functions instead of ImGui::GetIO().Fonts->AddFontFromFileTTF(),
// because they will automatically adjust the font size to account for HighDPI,
// and will help you to get consistent font size across different OSes.
//
// Font loading parameters: several options are available (color, merging, range, ...)
struct FontLoadingParams
Expand Down Expand Up @@ -101,14 +109,32 @@ See [hello_imgui_font.h](https://github.com/pthom/hello_imgui/blob/master/src/he
ImFontConfig fontConfigFontAwesome = ImFontConfig();
};
// When loading fonts, use HelloImGui::LoadFont(FontLoadingParams)
// ===============================================================
// instead of ImGui::GetIO().Fonts->AddFontFromFileTTF(), because it will
// automatically adjust the font size to account for HighDPI, and will spare
// you headaches when trying to get consistent font size across different OSes.
// see FontLoadingParams and ImFontConfig
ImFont* LoadFont(const std::string & fontFilename, float fontSize,
const FontLoadingParams & params = {});
// A font that will be automatically resized to account for changes in DPI
// Use LoadAdaptiveFont instead of LoadFont to get this behavior.
// Fonts loaded with LoadAdaptiveFont will be reloaded during execution
// if ImGui::GetIO().FontGlobalScale is changed.
struct FontDpiResponsive
{
ImFont* font = nullptr;
std::string fontFilename;
float fontSize = 0.f;
FontLoadingParams fontLoadingParams;
};
// Loads a font with the specified parameters
// (this font will not adapt to DPI changes after startup)
ImFont* LoadFont(
const std::string & fontFilename, float fontSize,
const FontLoadingParams & params = {});
// Loads a font with the specified parameters
// This font will adapt to DPI changes after startup.
// Only fonts loaded with LoadAdaptiveFont will adapt to DPI changes:
// avoid mixing LoadFont/LoadFontDpiResponsive)
FontDpiResponsive* LoadFontDpiResponsive(
const std::string & fontFilename, float fontSize,
const FontLoadingParams & params = {});
```

Expand Down Expand Up @@ -266,6 +292,10 @@ ImGuiTestEngine* GetImGuiTestEngine();
// "Sdl - Vulkan"
std::string GetBackendDescription();
// `ChangeWindowSize(const ScreenSize &windowSize)`: sets the window size
// (useful if you want to change the window size during execution)
void ChangeWindowSize(const ScreenSize &windowSize);
```

----
Expand Down Expand Up @@ -408,42 +438,100 @@ void ShowAppMenu(RunnerParams & runnerParams);
# Handling screens with high DPI
_Note: This part is relevant only for more advanced usages. If you use `HelloImGui::LoadFont()`, and always use `HelloImGui::EmToVec2()` to place widgets, you do not need to worry about DPI handling_
## Details on DPI handling on different OS
_Note: This part is relevant only for more advanced usages. If you use `HelloImGui::LoadFont()`,
and always use `HelloImGui::EmToVec2()` to place widgets, you do not need to worry about DPI handling_
## OS specificities
There are several important things to know about high-DPI handling within Hello ImGui and Dear ImGui:
1. (virtual) screen coordinates vs (physical) pixels
2. DisplayFramebufferScale: Frame buffer size vs window size
3. FontGlobalScale: display-time font scaling factor
4. How to load fonts with the correct size
5. How to get similar window sizes on different OSes/DPI
## Screen coordinates
Screen coordinates are the coordinates you use to place and size windows on the screen.
**Screen coordinates do not always correspond to physical pixels**
- On macOS/iOS retina screens, a screen coordinate corresponds typically
to 2x2 physical pixels (but this may vary if you change the display scaling)
- On most Linux distributions, whenever there is a high DPI screen
you can set the display scale. For example if you set the scale to 300%,
then a screen coordinate will correspond to 3x3 physical pixels
- On Windows, there are two possible situations:
- If the application is DPI aware, a screen coordinate corresponds to 1x1 physical pixel,
and you can use the full extent of your screen resolution.
- If the application is not DPI aware, a screen coordinate may correspond to 2x2 physical pixels
(if the display scaling is set to 200% for example). However, the rendering of your application
will be blurry and will not use the full extent of your screen resolution.
- Notes:
- Applications created with HelloImGui are DPI aware by default (when using glfw and sdl backends).
- SDL applications are normally not DPI aware. However, HelloImGui makes them DPI aware.
## DisplayFramebufferScale
`DisplayFramebufferScale` is the ratio between the frame buffer size and the window size.
The frame buffer size is the size of the internal buffer used by the rendering backend.
It might be bigger than the actual window size.
`ImVec2 ImGui::GetIO().DisplayFramebufferScale` is a factor by which the frame buffer size is bigger than the window size.
It is set by the platform backend after it was initialized, and typically reflects the scaling ratio between
physical pixels and screen coordinates.
Under windows, it will always be (1,1). Under macOS / linux, it will reflect the current display scaling.
It will typically be (2,2) on a macOS retina screen.
Notes:
- You cannot change DisplayFramebufferScale manually, it will be reset at each new frame, by asking the platform backend.
## FontGlobalScale
`ImGui::GetIO().FontGlobalScale` is a factor by which fonts glyphs should be scaled at rendering time.
It is typically 1 on windows, and 0.5 on macOS retina screens.
Let's consider screen whose physical pixel resolution is 3600x2000, but which will displayed with a scaling factor of 200%, so that widgets do not look too small on it.
The way it is handled depends on the OS:
- On MacOS, the screen will be seen as having a resolution of 1800x1000, and the OS handles the resizing by itself.
- On Linux, and on Windows if the application is DPI aware, the screen will be seen as having a resolution of 3600x2000.
- On Windows if the application is not DPI aware, the screen will be seen as having a resolution of 1800x1000
## How to load fonts with the correct size
By default, if using the glfw backend, applications will be Dpi aware under windows.
Sdl applications are normally not Dpi aware. However HelloImGui makes them Dpi aware when using the sdl backend.
### Using HelloImGui (recommended)
[`HelloImGui::LoadFont()` and `HelloImGui::LoadFontDpiResponsive`](https://pthom.github.io/hello_imgui/book/doc_api.html#load-fonts) will load fonts
with the correct size, taking into account the DPI scaling.
## Dpi aware Font scaling
### Using Dear ImGui
`ImGui::GetIO().Fonts->AddFontFromFileTTF()` loads a font with a given size, in *physical pixels*.
`HelloImGui::LoadFont()` will load fonts with the correct size, taking into account the DPI scaling.
If for example, DisplayFramebufferScale is (2,2), and you load a font with a size of 16, it will by default be rendered
with size of 16 *virtual screen coordinate pixels* (i.e. 32 physical pixels). This will lead to blurry text.
To solve this, you should load your font with a size of 16 *virtual screen coordinate pixels* (i.e. 32 physical pixels),
and set `ImGui::GetIO().FontGlobalScale` to 0.5.
If you prefer to use `ImGui::GetIO().Fonts->AddFontFromFileTTF()`, there are two things to know:
Helpers if using `ImGui::GetIO().Fonts->AddFontFromFileTTF()`:
- `HelloImGui::ImGuiDefaultFontGlobalScale()` returns the default value that should be stored inside `ImGui::GetIO().FontGlobalScale`.
- `HelloImGui::DpiFontLoadingFactor()` returns a factor by which you shall multiply your font sizes when loading them.
1. You should adjust `ImGui::GetIO().FontGlobalScale`:
Under windows and linux, it should be is 1: no rescaling should be done by ImGui.
Under macOS and emscripten, it may need to bet set to 0.5 (for example it will be 0.5 if the dpi scaling is 200%
on a macOS retina screen)
## Reproducible physical window sizes (in mm or inches)
`HelloImGui::ImGuiDefaultFontGlobalScale()` returns the default value that should be stored inside `ImGui::GetIO().FontGlobalScale`.
### Using HelloImGui
Simply specify a window size that corresponds to theoretical 96 PPI screen (inside `RunnerParams.appWindowParams.windowGeometry.size`)
### Using your own code to create the backend window
If you prefer to create the window by yourself, its physical size in millimeters may vary widely,
depending on the OS and the current screen DPI setting.
Typically under Windows, your window may appear to be very small if your screen is high DPI.
2. You should adjust the font size when loading a font:
To get a similar window size on different OSes/DPI, you should multiply the window size by `HelloImGui::DpiWindowSizeFactor()`.
`HelloImGui::DpiFontLoadingFactor()` returns a factor by which you shall multiply your font sizes when loading them.
Note: DpiWindowSizeFactor() is equal to `CurrentScreenPixelPerInch / 96` under windows and linux, and always 1 under macOS.
`HelloImGui::DpiFontLoadingFactor()` corresponds to:
`DpiWindowSizeFactor() * 1.f / ImGui::GetIO().FontGlobalScale`
## Fine tune DPI Handling
where DpiWindowSizeFactor() is equal to `CurrentScreenPixelPerInch / 96`
under windows and linux, 1 under macOS
See [`HelloImGui::DpiAwareParams`](https://pthom.github.io/hello_imgui/book/doc_params.html#dpi-aware-params)
for more information on how to fine tune DPI handling when using Hello ImGui.
84 changes: 65 additions & 19 deletions docs/book/_sources/doc_params.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,27 @@
# Application parameters

_RunnerParams_ contains all the settings and callbacks in order to run an application.

__HelloImGui::Run()__ will run an application with a single call.

Three signatures are provided:

* `HelloImGui::Run(RunnerParams &)`: full signature, the most customizable version.
Runs an application whose params and Gui are provided by runnerParams.

* `HelloImGui::Run(const SimpleRunnerParams&)`:
Runs an application, using simpler params.

* `HelloImGui::Run(guiFunction, windowTitle, windowSize, windowSizeAuto=false, restoreLastWindowGeometry=false, fpsIdle=10)`
Runs an application, by providing the Gui function, the window title, etc.

Although the API is extremely simple, it is highly customizable, and you can set many options by filling
the elements in the `RunnerParams` struct, or in the simpler `SimpleRunnerParams`.

__HelloImGui::GetRunnerParams()__ will return the runnerParams of the current application.


# Diagram

The diagram below summarize all the possible settings and callbacks (which are explained in detail later in this document).

[![diagram](https://raw.githubusercontent.com/pthom/hello_imgui/master/src/hello_imgui/doc_src/hello_imgui_diagram.jpg)](https://raw.githubusercontent.com/pthom/hello_imgui/master/src/hello_imgui/doc_src/hello_imgui_diagram.jpg)
Expand Down Expand Up @@ -49,6 +70,8 @@ struct SimpleRunnerParams

// `windowSize`: _ScreenSize, default={800, 600}_.
// Size of the window
// The size will be handled as if it was specified for a 96PPI screen
// (i.e. a given size will correspond to the same physical size on different screens, whatever their DPI)
ScreenSize windowSize = DefaultWindowSize;

// `fpsIdle`: _float, default=9_.
Expand Down Expand Up @@ -131,7 +154,6 @@ struct RunnerParams
RendererBackendType rendererBackendType = RendererBackendType::FirstAvailable;



// --------------- Settings -------------------

// `iniFolderType`: _IniFolderType, default = IniFolderType::CurrentFolder_
Expand Down Expand Up @@ -194,6 +216,9 @@ struct RunnerParams
// Set the application refresh rate
// (only used on emscripten: 0 stands for "let the app or the browser decide")
int emscripten_fps = 0;

// Parameters for Remote display (experimental, unsupported)
RemoteParams remoteParams;
};
```

Expand All @@ -212,6 +237,7 @@ enum class PlatformBackendType
FirstAvailable,
Glfw,
Sdl,
Null
};

// Rendering backend type (OpenGL3, Metal, Vulkan, DirectX11, DirectX12)
Expand All @@ -224,6 +250,7 @@ enum class RendererBackendType
Vulkan,
DirectX11,
DirectX12,
Null
};

```
Expand Down Expand Up @@ -313,11 +340,10 @@ struct RunnerCallbacks
void EnqueuePostInit(const VoidFunction& callback);
// `LoadAdditionalFonts`: default=_LoadDefaultFont_WithFontAwesome*.
// A function that is called once, when fonts are ready to be loaded.
// By default, _LoadDefaultFont_WithFontAwesome_ is called,
// but you can copy and customize it.
// (LoadDefaultFont_WithFontAwesome will load fonts from assets/fonts/
// but reverts to the ImGui embedded font if not found)
// A function that is called in order to load fonts.
// `LoadAdditionalFonts` will be called once, then *set to nullptr*.
// If you want to load additional fonts, during the app execution, you can
// set LoadAdditionalFonts to a function that will load the additional fonts.
VoidFunction LoadAdditionalFonts = (VoidFunction)ImGuiDefaultSettings::LoadDefaultFont_WithFontAwesomeIcons;
// If LoadAdditionalFonts==LoadDefaultFont_WithFontAwesomeIcons, this parameter control
// which icon font will be loaded by default.
Expand Down Expand Up @@ -361,7 +387,7 @@ struct RunnerCallbacks
// `PreNewFrame`: You can here add a function that will be called at each frame,
// and before the call to ImGui::NewFrame().
// It is a good place to dynamically add new fonts, or new dockable windows.
// It is a good place to add new dockable windows.
VoidFunction PreNewFrame = EmptyVoidFunction();
// `BeforeImGuiRender`: You can here add a function that will be called at each frame,
Expand Down Expand Up @@ -581,6 +607,8 @@ struct WindowGeometry

// Size of the application window
// used if fullScreenMode==NoFullScreen and sizeAuto==false. Default=(800, 600)
// The size will be handled as if it was specified for a 96PPI screen
// (i.e. a given size will correspond to the same physical size on different screens, whatever their DPI)
ScreenSize size = DefaultWindowSize;

// If sizeAuto=true, adapt the app window size to the presented widgets.
Expand Down Expand Up @@ -821,8 +849,9 @@ struct FpsIdling

# Dpi Aware Params

See [dpi_aware.h](https://github.com/pthom/hello_imgui/blob/master/src/hello_imgui/dpi_aware.h)
Optionally, DPI parameters can be fine-tuned. For detailed info, see [handling screens with high dpi](https://pthom.github.io/hello_imgui/book/doc_api.html#handling-screens-with-high-dpi)

Source: [dpi_aware.h](https://github.com/pthom/hello_imgui/blob/master/src/hello_imgui/dpi_aware.h)
```cpp

//
Expand Down Expand Up @@ -855,11 +884,15 @@ See [dpi_aware.h](https://github.com/pthom/hello_imgui/blob/master/src/hello_img
// dpiWindowSizeFactor=2
// fontRenderingScale=0.5
//
// For more information, see the documentation on DPI handling, here: https://pthom.github.io/hello_imgui/book/doc_api.html#handling-screens-with-high-dpi
//
struct DpiAwareParams
{
// `dpiWindowSizeFactor`
// factor by which window size should be multiplied to get a similar
// visible size on different OSes.
// factor by which window size should be multiplied to get a similar
// physical size on different OSes (as if they were all displayed on a 96 PPI screen).
// This affects the size of native app windows,
// but *not* imgui Windows, and *not* the size of widgets and text.
// In a standard environment (i.e. outside of Hello ImGui), an application with a size of 960x480 pixels,
// may have a physical size (in mm or inches) that varies depending on the screen DPI, and the OS.
//
Expand All @@ -874,23 +907,36 @@ struct DpiAwareParams
float dpiWindowSizeFactor = 0.0f;

// `fontRenderingScale`
// factor (that is either 1 or < 1.) by which fonts glyphs should be
// scaled at rendering time.
// On macOS retina screens, it will be 0.5, since macOS APIs hide
// the real resolution of the screen.
// factor (that is either 1 or < 1.) by which fonts glyphs should be scaled at rendering time.
// On macOS retina screens, it will be 0.5, since macOS APIs hide the real resolution of the screen.
// Changing this value will *not* change the visible font size on the screen, however it will
// affect the size of the loaded glyphs.
// For example, if fontRenderingScale=0.5 (which is the default on a macOS retina screen),
// a font size of 16 will be loaded as if it was 32, and will be rendered at half size.
// This leads to a better rendering quality on some platforms.
// (This parameter will be used to set ImGui::GetIO().FontGlobalScale at startup)
float fontRenderingScale = 0.0f;

// `onlyUseFontDpiResponsive`
// If true, guarantees that only HelloImGui::LoadDpiResponsiveFont will be used to load fonts.
// (also for the default font)
bool onlyUseFontDpiResponsive = false;

// `dpiFontLoadingFactor`
// factor by which font size should be multiplied at loading time to get a similar
// visible size on different OSes.
// The size will be equivalent to a size given for a 96 PPI screen
float DpiFontLoadingFactor() { return dpiWindowSizeFactor / fontRenderingScale;};
// factor by which font size should be multiplied at loading time to get a similar
// visible size on different OSes.
// The size will be equivalent to a size given for a 96 PPI screen
float DpiFontLoadingFactor() const {
float r = dpiWindowSizeFactor / fontRenderingScale;
return r;
};
};

// ----------------------------------------------------------------------------

```


----

# Docking
Expand Down
Loading

0 comments on commit 441c270

Please sign in to comment.