Skip to content

Commit 39ddfd0

Browse files
committed
Embed fonts and SPIR-V; Image List/UI fixes
Add build-time embedding for UI fonts and static Vulkan SPIR-V and wire it through the app and docs. Introduces OIIO_IMIV_EMBED_FONTS CMake option, embed_binary_header.cmake, and generated headers to include embedded DroidSans/DroidSansMono when enabled; preserve the old runtime fonts/ install/copy behavior when embedding is off. Update imiv_app to prefer embedded fonts, improve font loading fallbacks and logging. Adjust Image List behavior and UI: remove-from-session now retargets affected views (or clears them), keep the list visible when one item remains, add test-engine visibility overrides and a focused Image List centering regression test + CTest entry, and add imiv/tools/imiv_image_list_center_regression.py. Improve status bar/overlay text (file/specs/preview columns), viewport size tracking for smoother scroll sync, and various docs updates describing the embedding policy and runtime fallbacks. Signed-off-by: Vlad (Kuzmin) Erium <libalias@gmail.com> Signed-off-by: Vlad <shaamaan@gmail.com>
1 parent d18525c commit 39ddfd0

19 files changed

+839
-118
lines changed

src/doc/imiv_dev.rst

Lines changed: 78 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -280,15 +280,15 @@ being a passive history view:
280280

281281
* `>` marks the image shown in the active image view;
282282
* `[N]` reports how many open image views currently show that path;
283-
* a small inline close button appears for rows visible in the active view;
283+
* a small inline `x` button removes that path from the session queue;
284284
* the row popup menu routes the shared-library actions:
285285
`Open in active view`, `Open in new view`, `Close in active view`,
286286
`Close in all views`, and `Remove from session`.
287287

288288
Those actions are implemented against the shared `ImageLibraryState` plus the
289289
current `MultiViewWorkspace`. `Close` mutates view bindings only. `Remove`
290-
edits the shared session queue and then retargets or clears any views that
291-
were showing the removed path.
290+
edits the shared session queue and then retargets any affected views to the
291+
next surviving queue item, or clears them if the queue becomes empty.
292292

293293
Folder-open path filtering
294294
--------------------------
@@ -927,6 +927,9 @@ Important cache variables from `src/imiv/CMakeLists.txt` include:
927927
compile test-engine support when sources are available.
928928
* `OIIO_IMIV_USE_NATIVEFILEDIALOG`
929929
enable native file-open/save integration.
930+
* `OIIO_IMIV_EMBED_FONTS`
931+
embed the `DroidSans.ttf` and `DroidSansMono.ttf` runtime fonts into the
932+
:program:`imiv` binary. This is enabled by default.
930933
* `OIIO_IMIV_ADD_BACKEND_VERIFY_CTEST`
931934
add the longer per-backend verification CTest entries.
932935

@@ -950,6 +953,78 @@ macOS build with Metal default and OpenGL also compiled::
950953
-D OIIO_IMIV_DEFAULT_RENDERER=metal \
951954
-D OIIO_IMIV_ENABLE_IMGUI_TEST_ENGINE=ON
952955

956+
When `OIIO_IMIV_EMBED_FONTS=ON`, :program:`imiv` uses the embedded UI and mono
957+
fonts first and does not need an external `fonts/` directory at runtime.
958+
When it is `OFF`, :program:`imiv` tries to load those same fonts from the
959+
runtime `fonts/` directory and then falls back to Dear ImGui's default font if
960+
they are missing.
961+
962+
963+
Embedded binary assets
964+
======================
965+
966+
:program:`imiv` now uses two build-time embedding paths for runtime assets that
967+
used to be external files.
968+
969+
Fonts
970+
-----
971+
972+
The `OIIO_IMIV_EMBED_FONTS` option controls whether the two fonts actually used
973+
by :program:`imiv` are compiled into the binary:
974+
975+
* `src/fonts/Droid_Sans/DroidSans.ttf`
976+
* `src/fonts/Droid_Sans_Mono/DroidSansMono.ttf`
977+
978+
`src/imiv/CMakeLists.txt` generates binary headers for those files through
979+
`src/imiv/embed_binary_header.cmake`. The generated headers live in the build
980+
directory and are included from `src/imiv/imiv_app.cpp` when
981+
`IMIV_EMBED_FONTS` is enabled in `imiv_build_config.h`.
982+
983+
Runtime font loading order is:
984+
985+
1. embedded font data, if the build enabled it;
986+
2. `fonts/` next to the executable;
987+
3. Dear ImGui's default font for the UI font, then the UI font again for the
988+
mono slot if the mono font also could not be loaded.
989+
990+
Static Vulkan shaders
991+
---------------------
992+
993+
The static Vulkan upload and preview shaders are always embedded when the
994+
Vulkan backend is compiled. `src/imiv/CMakeLists.txt` first builds the SPIR-V
995+
files, then converts them into generated headers with
996+
`src/imiv/embed_spirv_header.cmake`.
997+
998+
Those embedded headers cover the fixed-function Vulkan shader set in
999+
`src/imiv/shaders/`:
1000+
1001+
* the upload compute shader variants;
1002+
* the static preview vertex shader;
1003+
* the static preview fragment shader.
1004+
1005+
`src/imiv/imiv_vulkan_setup.cpp` and `src/imiv/imiv_vulkan_ocio.cpp` use the
1006+
embedded SPIR-V words first and only fall back to `IMIV_SHADER_DIR` if needed.
1007+
That fallback keeps unusual build layouts working, but normal packaged builds
1008+
should no longer depend on external `.spv` files at runtime.
1009+
1010+
What is not embedded
1011+
--------------------
1012+
1013+
Not every renderer-side asset is a static binary blob:
1014+
1015+
* Vulkan OCIO preview still generates its fragment shader at runtime because it
1016+
depends on the active OCIO configuration and selected display/view.
1017+
* OpenGL still compiles native GLSL source strings with the GL driver.
1018+
* Metal still compiles embedded MSL source text at runtime.
1019+
1020+
So the embedded-binary policy is intentionally narrow:
1021+
1022+
* fonts are embedded to remove the runtime `fonts/` dependency by default;
1023+
* static Vulkan SPIR-V is embedded to remove the runtime `.spv` dependency by
1024+
default;
1025+
* dynamic OCIO and backend-native runtime shader generation remain runtime
1026+
features.
1027+
9531028
At the time of this writing, the shared backend verifier is green on macOS for
9541029
all three compiled backends:
9551030

src/doc/imiv_tests.rst

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,12 @@ When the test engine is not compiled in, :program:`imiv` will warn if
4747
automation is requested through `IMIV_IMGUI_TEST_ENGINE*` environment
4848
variables.
4949

50+
With the default build settings, focused regressions do not depend on an
51+
external `fonts/` directory or static Vulkan `.spv` files at runtime because
52+
those assets are embedded into the :program:`imiv` binary. OCIO preview
53+
regressions still depend on the runtime OCIO environment because the OCIO
54+
shader path is generated from the active configuration.
55+
5056

5157
Quick start
5258
===========
@@ -173,6 +179,7 @@ Per-view recipe overrides:
173179

174180
Image List actions:
175181

182+
* `image_list_visible`
176183
* `image_list_select_index`
177184
* `image_list_open_new_view_index`
178185
* `image_list_close_active_index`
@@ -224,7 +231,11 @@ Recent focused GUI regressions in `src/imiv/tools/` include:
224231
default Image List visibility and docked layout on multi-image startup;
225232
* `imiv_image_list_interaction_regression.py`
226233
Image List single-click, open-in-new-view, close-in-active-view, and
227-
remove-from-session behavior;
234+
remove-from-session behavior, including keeping the list visible with one
235+
remaining queue item;
236+
* `imiv_image_list_center_regression.py`
237+
opening `Image List` after a single-image load preserves centered scroll
238+
instead of snapping the image to the top-left;
228239
* `imiv_open_folder_regression.py`
229240
startup folder-open queue filtering for supported image files only;
230241
* `imiv_drag_drop_regression.py`

src/doc/imiv_user.rst

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,8 @@ The `Image List` window currently supports:
255255
* open-count badge
256256
`[N]` shows how many open image views currently display that image;
257257
* inline close button
258-
rows that are visible in the active image view show a small `x` button;
258+
each row shows a small `x` button that removes that image from the current
259+
session queue;
259260
* right-click context menu
260261
provides `Open in active view`, `Open in new view`,
261262
`Close in active view`, `Close in all views`, and
@@ -275,11 +276,24 @@ The main `Image` window remains the primary docked image pane. Additional
275276
`Image N` windows are currently created docked into the main dockspace.
276277
Undocking those image views is intentionally disabled in this first slice.
277278

278-
When more than one image is loaded into the queue, `Image List` becomes
279-
visible automatically and defaults to a narrow docked pane on the right side
280-
of the main image area. Its dock position and size may still be saved by Dear
281-
ImGui layout persistence, but its open/closed visibility is not treated as a
282-
persistent preference.
279+
Current builds embed the `imiv` UI and mono fonts by default. If a build is
280+
configured without font embedding, :program:`imiv` first looks for the same
281+
fonts in its runtime `fonts/` directory and then falls back to Dear ImGui's
282+
default font if they are not present.
283+
284+
Static Vulkan upload and preview shaders are also embedded into the binary at
285+
build time. That means normal Vulkan launches do not need separate `.spv`
286+
files next to the executable. OpenGL and Metal continue to compile their
287+
native shader source at runtime, and Vulkan OCIO preview still generates its
288+
backend shader at runtime because it depends on the active OCIO configuration.
289+
290+
When the queue first grows beyond one image, `Image List` becomes visible
291+
automatically and defaults to a narrow docked pane on the right side of the
292+
main image area. If it is already open and the queue later shrinks to one
293+
remaining image, it stays open so the last session item can still be managed
294+
from the list. It hides automatically only when the queue becomes empty. Its
295+
dock position and size may still be saved by Dear ImGui layout persistence,
296+
but its open/closed visibility is not treated as a persistent preference.
283297

284298
This is the first multi-view milestone. View windows already have independent
285299
loaded images, zoom, scroll, selection state, and preview recipe state.

src/imiv/CMakeLists.txt

Lines changed: 93 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ set (OIIO_IMIV_GLSLANG_DEFAULT_LIMITS_LIBRARY "" CACHE FILEPATH
2222
"Optional explicit glslang-default-resource-limits library path for imiv runtime shader compilation")
2323
option (OIIO_IMIV_USE_NATIVEFILEDIALOG
2424
"Use nativefiledialog-extended for imiv file open/save actions" ON)
25+
option (OIIO_IMIV_EMBED_FONTS
26+
"Embed imiv UI and mono fonts into the binary" ON)
2527
option (OIIO_IMIV_ENABLE_IMGUI_TEST_ENGINE
2628
"Build imiv with Dear ImGui Test Engine integration when sources are available" ON)
2729
option (OIIO_IMIV_ADD_UPLOAD_SMOKE_CTEST
@@ -228,6 +230,11 @@ set (_imiv_preview_vert_hdr "${CMAKE_CURRENT_BINARY_DIR}/imiv_preview_vert_spv.h
228230
set (_imiv_preview_frag_hdr "${CMAKE_CURRENT_BINARY_DIR}/imiv_preview_frag_spv.h")
229231
set (_imiv_shader_outputs)
230232
set (_imiv_embedded_shader_headers)
233+
set (_imiv_font_ui_ttf "${PROJECT_SOURCE_DIR}/src/fonts/Droid_Sans/DroidSans.ttf")
234+
set (_imiv_font_mono_ttf "${PROJECT_SOURCE_DIR}/src/fonts/Droid_Sans_Mono/DroidSansMono.ttf")
235+
set (_imiv_font_ui_hdr "${CMAKE_CURRENT_BINARY_DIR}/imiv_font_droidsans_ttf.h")
236+
set (_imiv_font_mono_hdr "${CMAKE_CURRENT_BINARY_DIR}/imiv_font_droidsansmono_ttf.h")
237+
set (_imiv_embedded_font_headers)
231238

232239
function (_imiv_add_embedded_spirv_header input_spv output_hdr symbol_name)
233240
add_custom_command (
@@ -243,6 +250,36 @@ function (_imiv_add_embedded_spirv_header input_spv output_hdr symbol_name)
243250
COMMENT "imiv: embedding Vulkan shader ${symbol_name}")
244251
endfunction ()
245252

253+
function (_imiv_add_embedded_binary_header input_bin output_hdr symbol_name)
254+
add_custom_command (
255+
OUTPUT "${output_hdr}"
256+
COMMAND ${CMAKE_COMMAND}
257+
-DINPUT="${input_bin}"
258+
-DOUTPUT="${output_hdr}"
259+
-DSYMBOL_NAME="${symbol_name}"
260+
-P "${CMAKE_CURRENT_SOURCE_DIR}/embed_binary_header.cmake"
261+
DEPENDS
262+
"${input_bin}"
263+
"${CMAKE_CURRENT_SOURCE_DIR}/embed_binary_header.cmake"
264+
COMMENT "imiv: embedding binary asset ${symbol_name}")
265+
endfunction ()
266+
267+
if (OIIO_IMIV_EMBED_FONTS)
268+
if (NOT EXISTS "${_imiv_font_ui_ttf}" OR NOT EXISTS "${_imiv_font_mono_ttf}")
269+
message (FATAL_ERROR
270+
"imiv: OIIO_IMIV_EMBED_FONTS=ON requires ${_imiv_font_ui_ttf} and ${_imiv_font_mono_ttf}")
271+
endif ()
272+
_imiv_add_embedded_binary_header ("${_imiv_font_ui_ttf}"
273+
"${_imiv_font_ui_hdr}"
274+
"g_imiv_font_droidsans_ttf")
275+
_imiv_add_embedded_binary_header ("${_imiv_font_mono_ttf}"
276+
"${_imiv_font_mono_hdr}"
277+
"g_imiv_font_droidsansmono_ttf")
278+
list (APPEND _imiv_embedded_font_headers
279+
"${_imiv_font_ui_hdr}"
280+
"${_imiv_font_mono_hdr}")
281+
endif ()
282+
246283
if (_imiv_want_vulkan)
247284
find_program (OIIO_IMIV_GLSLC_EXECUTABLE
248285
NAMES glslc
@@ -815,6 +852,7 @@ endif ()
815852
set (IMIV_WITH_VULKAN 0)
816853
set (IMIV_WITH_METAL 0)
817854
set (IMIV_WITH_OPENGL 0)
855+
set (IMIV_EMBED_FONTS 0)
818856
set (IMIV_BUILD_DEFAULT_BACKEND_KIND -1)
819857
if (_imiv_enabled_vulkan)
820858
set (IMIV_WITH_VULKAN 1)
@@ -825,6 +863,9 @@ endif ()
825863
if (_imiv_enabled_opengl)
826864
set (IMIV_WITH_OPENGL 1)
827865
endif ()
866+
if (OIIO_IMIV_EMBED_FONTS)
867+
set (IMIV_EMBED_FONTS 1)
868+
endif ()
828869
if (_imiv_renderer_is_vulkan)
829870
set (IMIV_BUILD_DEFAULT_BACKEND_KIND 0)
830871
elseif (_imiv_renderer_is_metal)
@@ -860,7 +901,8 @@ set (_imiv_core_sources
860901
${_imiv_shared_sources}
861902
${_imiv_test_engine_integration_sources}
862903
${_imiv_platform_glfw_sources}
863-
${_imiv_renderer_enabled_sources})
904+
${_imiv_renderer_enabled_sources}
905+
${_imiv_embedded_font_headers})
864906

865907
set (_imiv_imgui_renderer_sources)
866908
if (_imiv_enabled_vulkan)
@@ -1016,40 +1058,38 @@ if (TARGET imiv)
10161058
target_compile_definitions (imiv PRIVATE IMIV_HAS_NFD=0)
10171059
endif ()
10181060

1019-
add_custom_command (
1020-
TARGET imiv POST_BUILD
1021-
COMMAND ${CMAKE_COMMAND} -E make_directory
1022-
"$<TARGET_FILE_DIR:imiv>/fonts/Droid_Sans"
1023-
COMMAND ${CMAKE_COMMAND} -E make_directory
1024-
"$<TARGET_FILE_DIR:imiv>/fonts/Droid_Sans_Mono"
1025-
COMMAND ${CMAKE_COMMAND} -E copy_if_different
1026-
"${PROJECT_SOURCE_DIR}/src/fonts/Droid_Sans/DroidSans.ttf"
1027-
"$<TARGET_FILE_DIR:imiv>/fonts/Droid_Sans/DroidSans.ttf"
1028-
COMMAND ${CMAKE_COMMAND} -E copy_if_different
1029-
"${PROJECT_SOURCE_DIR}/src/fonts/Droid_Sans/DroidSans-Bold.ttf"
1030-
"$<TARGET_FILE_DIR:imiv>/fonts/Droid_Sans/DroidSans-Bold.ttf"
1031-
COMMAND ${CMAKE_COMMAND} -E copy_if_different
1032-
"${PROJECT_SOURCE_DIR}/src/fonts/Droid_Sans/droid-lic.txt"
1033-
"$<TARGET_FILE_DIR:imiv>/fonts/Droid_Sans/droid-lic.txt"
1034-
COMMAND ${CMAKE_COMMAND} -E copy_if_different
1035-
"${PROJECT_SOURCE_DIR}/src/fonts/Droid_Sans_Mono/DroidSansMono.ttf"
1036-
"$<TARGET_FILE_DIR:imiv>/fonts/Droid_Sans_Mono/DroidSansMono.ttf"
1037-
COMMAND ${CMAKE_COMMAND} -E copy_if_different
1038-
"${PROJECT_SOURCE_DIR}/src/fonts/Droid_Sans_Mono/droid-lic.txt"
1039-
"$<TARGET_FILE_DIR:imiv>/fonts/Droid_Sans_Mono/droid-lic.txt"
1040-
VERBATIM)
1041-
1042-
install (FILES
1043-
"${PROJECT_SOURCE_DIR}/src/fonts/Droid_Sans/DroidSans.ttf"
1044-
"${PROJECT_SOURCE_DIR}/src/fonts/Droid_Sans/DroidSans-Bold.ttf"
1045-
"${PROJECT_SOURCE_DIR}/src/fonts/Droid_Sans/droid-lic.txt"
1046-
DESTINATION
1047-
"${CMAKE_INSTALL_BINDIR}/fonts/Droid_Sans")
1048-
install (FILES
1049-
"${PROJECT_SOURCE_DIR}/src/fonts/Droid_Sans_Mono/DroidSansMono.ttf"
1050-
"${PROJECT_SOURCE_DIR}/src/fonts/Droid_Sans_Mono/droid-lic.txt"
1051-
DESTINATION
1052-
"${CMAKE_INSTALL_BINDIR}/fonts/Droid_Sans_Mono")
1061+
if (NOT OIIO_IMIV_EMBED_FONTS)
1062+
add_custom_command (
1063+
TARGET imiv POST_BUILD
1064+
COMMAND ${CMAKE_COMMAND} -E make_directory
1065+
"$<TARGET_FILE_DIR:imiv>/fonts/Droid_Sans"
1066+
COMMAND ${CMAKE_COMMAND} -E make_directory
1067+
"$<TARGET_FILE_DIR:imiv>/fonts/Droid_Sans_Mono"
1068+
COMMAND ${CMAKE_COMMAND} -E copy_if_different
1069+
"${PROJECT_SOURCE_DIR}/src/fonts/Droid_Sans/DroidSans.ttf"
1070+
"$<TARGET_FILE_DIR:imiv>/fonts/Droid_Sans/DroidSans.ttf"
1071+
COMMAND ${CMAKE_COMMAND} -E copy_if_different
1072+
"${PROJECT_SOURCE_DIR}/src/fonts/Droid_Sans/droid-lic.txt"
1073+
"$<TARGET_FILE_DIR:imiv>/fonts/Droid_Sans/droid-lic.txt"
1074+
COMMAND ${CMAKE_COMMAND} -E copy_if_different
1075+
"${PROJECT_SOURCE_DIR}/src/fonts/Droid_Sans_Mono/DroidSansMono.ttf"
1076+
"$<TARGET_FILE_DIR:imiv>/fonts/Droid_Sans_Mono/DroidSansMono.ttf"
1077+
COMMAND ${CMAKE_COMMAND} -E copy_if_different
1078+
"${PROJECT_SOURCE_DIR}/src/fonts/Droid_Sans_Mono/droid-lic.txt"
1079+
"$<TARGET_FILE_DIR:imiv>/fonts/Droid_Sans_Mono/droid-lic.txt"
1080+
VERBATIM)
1081+
1082+
install (FILES
1083+
"${PROJECT_SOURCE_DIR}/src/fonts/Droid_Sans/DroidSans.ttf"
1084+
"${PROJECT_SOURCE_DIR}/src/fonts/Droid_Sans/droid-lic.txt"
1085+
DESTINATION
1086+
"${CMAKE_INSTALL_BINDIR}/fonts/Droid_Sans")
1087+
install (FILES
1088+
"${PROJECT_SOURCE_DIR}/src/fonts/Droid_Sans_Mono/DroidSansMono.ttf"
1089+
"${PROJECT_SOURCE_DIR}/src/fonts/Droid_Sans_Mono/droid-lic.txt"
1090+
DESTINATION
1091+
"${CMAKE_INSTALL_BINDIR}/fonts/Droid_Sans_Mono")
1092+
endif ()
10531093
endif ()
10541094

10551095
if (MSVC)
@@ -1430,6 +1470,24 @@ if (TARGET imiv
14301470
LABELS "imiv;gui;imiv_multiview"
14311471
TIMEOUT 180)
14321472

1473+
if (TARGET oiiotool)
1474+
add_test (
1475+
NAME imiv_image_list_center_regression
1476+
COMMAND
1477+
"${Python3_EXECUTABLE}"
1478+
"${CMAKE_CURRENT_SOURCE_DIR}/tools/imiv_image_list_center_regression.py"
1479+
--bin "$<TARGET_FILE:imiv>"
1480+
--cwd "$<TARGET_FILE_DIR:imiv>"
1481+
--backend opengl
1482+
--oiiotool "$<TARGET_FILE:oiiotool>"
1483+
--env-script "${CMAKE_BINARY_DIR}/imiv_env.sh"
1484+
--out-dir "${CMAKE_BINARY_DIR}/imiv_captures/image_list_center_regression")
1485+
set_tests_properties (
1486+
imiv_image_list_center_regression PROPERTIES
1487+
LABELS "imiv;gui;imiv_multiview"
1488+
TIMEOUT 180)
1489+
endif ()
1490+
14331491
add_test (
14341492
NAME imiv_drag_drop_regression
14351493
COMMAND

0 commit comments

Comments
 (0)