build(freetype): color-emoji rendering via a cross-platform FreeType backend

The chat "Emoji style: Color" option renders the merged emoji in color (COLR/CPAL
Twemoji) instead of the monochrome NotoEmoji subset. This needs FreeType, which the
default stb_truetype rasterizer can't do for color glyphs.

- Vendor imgui_freetype (matches the bundled 1.92 ImFontLoader API) and embed a 1.4 MB
  COLRv0 Twemoji font (no libpng/harfbuzz needed).
- CMake gains an optional FreeType path: native Linux/macOS use the system FreeType via
  find_package; the mingw-w64 cross-compile has none, so build.sh --win-release now
  cross-builds a minimal static FreeType (scripts/build-freetype-mingw.sh) and passes it
  in. Absent FreeType => graceful monochrome fallback, so no build breaks.
- Typography selects the FreeType loader + the color font (LoadColor) when color emoji is
  on, else the stb loader + mono subset; toggling reloads the atlas. Both the DX11 and
  OpenGL backends already support the 1.92 RGBA dynamic atlas, so color glyphs render.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-17 18:44:19 -05:00
parent 63ed31d2ec
commit a78b44246e
11 changed files with 1035 additions and 9 deletions

View File

@@ -406,6 +406,35 @@ else()
list(APPEND IMGUI_HEADERS ${IMGUI_DIR}/backends/imgui_impl_opengl3.h)
endif()
# Optional FreeType font loader — enables color-emoji rendering (COLR/CPAL Twemoji) when the chat
# "color emoji" setting is on; otherwise the wallet falls back to the monochrome emoji subset.
# - Native Linux/macOS: use the system FreeType via find_package.
# - Windows (mingw cross): the toolchain ships no FreeType, so build.sh --win-release cross-builds a
# static one (scripts/build-freetype-mingw.sh) and passes -DDRAGONX_MINGW_FREETYPE_PREFIX here.
# - Other cross builds (osxcross) without FreeType: silently fall back to monochrome.
set(DRAGONX_FREETYPE OFF)
set(DRAGONX_FREETYPE_LIB "")
set(DRAGONX_FREETYPE_INC "")
if(DEFINED DRAGONX_MINGW_FREETYPE_PREFIX AND EXISTS "${DRAGONX_MINGW_FREETYPE_PREFIX}/lib/libfreetype.a")
set(DRAGONX_FREETYPE ON)
set(DRAGONX_FREETYPE_LIB "${DRAGONX_MINGW_FREETYPE_PREFIX}/lib/libfreetype.a")
set(DRAGONX_FREETYPE_INC "${DRAGONX_MINGW_FREETYPE_PREFIX}/include/freetype2")
message(STATUS "FreeType (mingw cross-built) found — chat color emoji enabled")
elseif(NOT CMAKE_CROSSCOMPILING)
find_package(Freetype QUIET)
if(FREETYPE_FOUND)
set(DRAGONX_FREETYPE ON)
set(DRAGONX_FREETYPE_LIB Freetype::Freetype) # imported target carries include dirs
message(STATUS "FreeType ${FREETYPE_VERSION_STRING} found — chat color emoji enabled")
endif()
endif()
if(DRAGONX_FREETYPE)
list(APPEND IMGUI_SOURCES ${IMGUI_DIR}/misc/freetype/imgui_freetype.cpp)
list(APPEND IMGUI_HEADERS ${IMGUI_DIR}/misc/freetype/imgui_freetype.h)
else()
message(STATUS "FreeType not found — chat color emoji falls back to monochrome")
endif()
# -----------------------------------------------------------------------------
# QR Code library (bundled)
# -----------------------------------------------------------------------------
@@ -730,7 +759,9 @@ ${CMAKE_SOURCE_DIR}/res/fonts/Ubuntu-Medium.ttf;\
${CMAKE_SOURCE_DIR}/res/fonts/UbuntuMono-R.ttf;\
${CMAKE_SOURCE_DIR}/res/fonts/MaterialIcons-Regular.ttf;\
${CMAKE_SOURCE_DIR}/res/fonts/MaterialDesignIcons-Pickaxe-Subset.ttf;\
${CMAKE_SOURCE_DIR}/res/fonts/NotoSansCJK-Subset.ttf"
${CMAKE_SOURCE_DIR}/res/fonts/NotoSansCJK-Subset.ttf;\
${CMAKE_SOURCE_DIR}/res/fonts/NotoEmoji-Subset.ttf;\
${CMAKE_SOURCE_DIR}/res/fonts/TwemojiMozilla-Color.ttf"
)
add_executable(ObsidianDragon
@@ -863,6 +894,15 @@ else()
target_compile_definitions(ObsidianDragon PRIVATE DRAGONX_HAS_GLAD)
endif()
# Color-emoji font loader (FreeType) — linked + flagged only when found (see DRAGONX_FREETYPE above).
if(DRAGONX_FREETYPE)
target_link_libraries(ObsidianDragon PRIVATE ${DRAGONX_FREETYPE_LIB})
if(DRAGONX_FREETYPE_INC)
target_include_directories(ObsidianDragon PRIVATE ${DRAGONX_FREETYPE_INC})
endif()
target_compile_definitions(ObsidianDragon PRIVATE DRAGONX_HAVE_FREETYPE)
endif()
add_executable(HushChatFixtureCheck
tools/hushchat_fixture_check.cpp
src/chat/chat_protocol.cpp