From da8ee4f7345f14808a05a52ff7fe6dc4c4fe3c67 Mon Sep 17 00:00:00 2001
From: Sergey Fedorov <barracuda@macos-powerpc.org>
Date: Mon, 3 Aug 2026 04:05:08 +0000
Subject: [PATCH 70/71] fix(macos): adapt frontend to upstream engine
 signature/target changes on rebase

Rebasing the vendor series onto upstream 0397f9cf (then ca44f8de, then c51e15ed)
moved engine APIs the macOS frontend calls, renamed a library target it links,
and re-spelled every engine header and much of crispy/text_shaper's vocabulary;
this patch adapts the affected sites so the frontend compiles and links against
the new base. Kept as a single trailing patch rather than folded into the
originals so the drift is reviewable in one place and the earlier patches stay
byte-for-byte what they were before the rebase.

- Terminal::sendCharEvent() gained a KeyIdentity second parameter (the Kitty /
  win32-input keyboard-protocol identity). SessionBridge::bridge_send_char()
  now passes vtbackend::KeyIdentity{ .unshiftedKey = codepoint,
  .nativeVirtualKey = 0 }: the bridge only ever receives an already-resolved
  codepoint (AppKit characterAtIndex:, not a raw key position), so the unshifted
  key is that codepoint and nativeVirtualKey stays 0 (a Win32 VK code, which no
  macOS key has -- matching the Qt frontend's discipline).

- vtrasterizer::Renderer's constructor gained a PageMargin as its second
  argument. The three frontend Renderer constructions now pass it, spelled
  vtrasterizer::PageMargin (fully qualified: both smoke_main.cpp and
  render_probe.cpp pull in vtbackend:: AND vtrasterizer:: via using-directives,
  and PageMargin exists in both namespaces -- a bare name is ambiguous).
  TerminalSession.cpp reuses the file's existing PageMarginPx (the same value it
  already feeds applyResize()); the probe and smoke executables pass an explicit
  margin. No behavioural change -- the live margin is still applied via
  applyResize() after the first resize.

- The vtmux library was renamed vtworkspace upstream (src/vtworkspace, target
  vtworkspace). contour_macos/CMakeLists.txt's link line now names vtworkspace,
  fixing "ld: library not found for -lvtmux". The frontend uses no vtmux/
  vtworkspace symbols directly; it is a transitive engine dependency, so this is
  a pure link-list rename.

- vtbackend::Terminal's constructor gained a crispy::environment const& second
  parameter (upstream #2044 made the environment an injected interface; the
  terminal resolves $HOME and $CONTOUR_SYNC_PTY_OUTPUT once, at construction).
  TerminalSession.cpp now passes crispy::defaultEnvironment() -- the frontend's
  session is its composition root, so this is the same resolution upstream's
  main() makes before threading it through the app. The render probe and smoke
  binaries need no change: they construct via MockTerm, whose own signature is
  unchanged and which supplies the environment internally.

- vtrasterizer::Renderer's constructor gained a text::FontLocator& parameter,
  after atlasDirectMapping (upstream 5a44dc7e: the shaper's locator is injected
  rather than fetched from FontLocatorProvider, so a renderer can be built
  against MockFontLocator). All three frontend construction sites now pass
  vtrasterizer::createFontLocator(vtrasterizer::FontLocatorEngine::Native) --
  the same call upstream's Qt display makes, differing only in that it reads the
  engine from a config profile the macOS frontend does not have. Native resolves
  to text::CoreTextLocator on Apple, which is the locator this port ships and the
  one render_probe.cpp already queried directly for its diagnostic. Spelled fully
  qualified for the reason PageMargin is: the probe and smoke sources pull in both
  vtbackend:: and vtrasterizer:: through using-directives.

- Upstream #2046 renamed C++ headers .h -> .hpp, re-spelled crispy and
  text_shaper filenames in CamelCase, and unified type/function naming there.
  The frontend follows: 20 engine includes now name .hpp (and the two re-spelled
  ones, text_shaper/CoreTextLocator.hpp and text_shaper/FontLocator.hpp,
  crispy/Environment.hpp, vtbackend/Primitives.hpp); text::font_description,
  font_size, font_slant, font_spacing, font_weight, font_path, render_mode and
  their enumerators take their CamelCase spellings; crispy::lru_capacity and
  crispy::strong_hashtable_size become crispy::LRUCapacity and
  crispy::StrongHashtableSize. Our own contour_macos headers keep their .h
  extension -- upstream does not build this directory, and renaming them would
  rewrite the file paths of patches 0001-0069.

Verified by static analysis only (this port cannot be built on the dev host);
the fixed call sites match the new signatures argument-for-argument and the
renamed target matches upstream's own src/CMakeLists.txt.
---
 docs/macos-port.md                       | 14 ++++----
 src/contour_macos/CMakeLists.txt         |  2 +-
 src/contour_macos/GLRenderTarget.h       |  6 ++--
 src/contour_macos/PixelBuffer.h          |  2 +-
 src/contour_macos/SessionBridge.cpp      | 30 +++++++++-------
 src/contour_macos/SoftwareRenderTarget.h |  6 ++--
 src/contour_macos/StubRenderTarget.h     |  6 ++--
 src/contour_macos/TerminalSession.cpp    | 26 ++++++++++----
 src/contour_macos/TerminalSession.h      |  8 ++---
 src/contour_macos/Themes.h               |  2 +-
 src/contour_macos/render_probe.cpp       | 46 +++++++++++++-----------
 src/contour_macos/smoke_main.cpp         | 18 +++++-----
 12 files changed, 95 insertions(+), 71 deletions(-)

diff --git a/docs/macos-port.md b/docs/macos-port.md
index bae1880e..ae8a0bd9 100644
--- a/docs/macos-port.md
+++ b/docs/macos-port.md
@@ -78,7 +78,7 @@ replacing) `src/contour/`. It contains:
 ## The seam: `vtbackend::Terminal::Events`
 
 The host↔engine boundary is **not** contour's `TerminalSession` (which is Qt). It is
-`vtbackend::Terminal::Events` (`src/vtbackend/Terminal.h`), a pure-virtual listener
+`vtbackend::Terminal::Events` (`src/vtbackend/Terminal.hpp`), a pure-virtual listener
 that is 100% Qt-free — every method takes plain types (`std::string_view`,
 `RGBColor`, `LineCount`, …) and almost all have default no-op bodies. The new session
 object implements it. Relevant callbacks include: `screenUpdated`,
@@ -93,15 +93,15 @@ settings, now)`. The Terminal owns the Pty and calls back into the session.
 
 `CGRenderTarget` implements exactly these (`src/vtrasterizer/`):
 
-- **`RenderTarget`** (`RenderTarget.h`): `setRenderSize`, `renderSize`, `setMargin`,
+- **`RenderTarget`** (`RenderTarget.hpp`): `setRenderSize`, `renderSize`, `setMargin`,
   `textureScheduler()`, `imageScheduler()`, `renderRectangle`, `scheduleScreenshot`,
   `setScissorRect`/`clearScissorRect` (bottom-left origin!), `execute(now)`,
   `clearCache`, `readAtlas`, `inspect`, optional `setTextOutline`.
-- **`atlas::AtlasBackend`** (`TextureAtlas.h`) — four methods: `atlasSize`,
+- **`atlas::AtlasBackend`** (`TextureAtlas.hpp`) — four methods: `atlasSize`,
   `configureAtlas`, `uploadTile`, `renderTile`. The atlas is a CPU pixel buffer;
   `uploadTile` blits a bitmap into a tile slot at its pixel offset; `renderTile`
   composites a tile sub-rect onto the target surface.
-- **`atlas::ImageTextureBackend`** (`ImageTextureBackend.h`) — whole-image textures
+- **`atlas::ImageTextureBackend`** (`ImageTextureBackend.hpp`) — whole-image textures
   for sixel/images: `createImageTexture`, `destroyImageTexture`, `renderImageQuad`,
   `renderImageGap`, `takeFailedImageTextures`.
 
@@ -177,7 +177,7 @@ rather than reading screen state directly.
 
 `vtpty` is already cross-platform (openpty via `<util.h>` on Apple, `pipe2`→`pipe`
 fallback, epoll/eventfd/utempter all behind `__linux__`, and the read loop falls back
-to `select()` + self-pipe via `crispy::read_selector` on non-Linux).
+to `select()` + self-pipe via `crispy::ReadSelector` on non-Linux).
 
 The port depends on [macports-legacy-support](https://github.com/macports/macports-legacy-support)
 (via the MacPorts `legacysupport` PortGroup), which supplies real, tested
@@ -188,7 +188,7 @@ mask legacy-support's real close-on-exec support.
 
 That leaves one genuine, SDK-independent bug to patch:
 
-- **`strerror_r` return type** — the `ExitStatus` formatter in `Process.h` used the
+- **`strerror_r` return type** — the `ExitStatus` formatter in `Process.hpp` used the
   return value of `strerror_r` as a `char*`. That is only correct for glibc's GNU
   variant; Darwin, the BSDs, and plain POSIX ship the XSI (`int`-returning) variant,
   where the message is written into the buffer and the return is a status code. Fixed
@@ -220,7 +220,7 @@ The GUI is Objective-C(++) that must compile with modern GCC's ObjC frontend:
   standalone `<CoreText/CoreText.h>` umbrella. Several 10.7+ symbols
   (`NSFontWeight*`, ARC-style CoreText helpers) are absent on 10.6.
 
-These constraints are exercised by the existing `src/text_shaper/coretext_locator.mm`
+These constraints are exercised by the existing `src/text_shaper/CoreTextLocator.mm`
 plus the reference patches captured from the MacPorts port; note those patches were
 made to fix *compilation*, and were never run, so their runtime behavior (font-weight
 mapping, removed fallback-cascade logic) must be re-derived, not trusted.
diff --git a/src/contour_macos/CMakeLists.txt b/src/contour_macos/CMakeLists.txt
index 1259d932..0d308555 100644
--- a/src/contour_macos/CMakeLists.txt
+++ b/src/contour_macos/CMakeLists.txt
@@ -43,7 +43,7 @@ endif()
 
 add_library(contour_macos STATIC ${_source_files} ${_header_files})
 target_include_directories(contour_macos PUBLIC ${PROJECT_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/src)
-target_link_libraries(contour_macos PUBLIC vtrasterizer vtbackend vtmux text_shaper vtpty crispy::core)
+target_link_libraries(contour_macos PUBLIC vtrasterizer vtbackend vtworkspace text_shaper vtpty crispy::core)
 target_compile_options(contour_macos PRIVATE ${_contour_macos_warn_opts})
 
 # GLRenderTarget calls into the OpenGL framework. Default to the conservative 10.5 GL 2.0 baseline
diff --git a/src/contour_macos/GLRenderTarget.h b/src/contour_macos/GLRenderTarget.h
index 5a8bb501..3071d425 100644
--- a/src/contour_macos/GLRenderTarget.h
+++ b/src/contour_macos/GLRenderTarget.h
@@ -1,9 +1,9 @@
 // SPDX-License-Identifier: Apache-2.0
 #pragma once
 
-#include <vtrasterizer/ImageTextureBackend.h>
-#include <vtrasterizer/RenderTarget.h>
-#include <vtrasterizer/TextureAtlas.h>
+#include <vtrasterizer/ImageTextureBackend.hpp>
+#include <vtrasterizer/RenderTarget.hpp>
+#include <vtrasterizer/TextureAtlas.hpp>
 
 #include <cstdint>
 #include <optional>
diff --git a/src/contour_macos/PixelBuffer.h b/src/contour_macos/PixelBuffer.h
index 81412d64..a6c520b2 100644
--- a/src/contour_macos/PixelBuffer.h
+++ b/src/contour_macos/PixelBuffer.h
@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: Apache-2.0
 #pragma once
 
-#include <vtbackend/primitives.h>
+#include <vtbackend/Primitives.hpp>
 
 #include <algorithm>
 #include <cstddef>
diff --git a/src/contour_macos/SessionBridge.cpp b/src/contour_macos/SessionBridge.cpp
index 80d6f5cb..b059fda5 100644
--- a/src/contour_macos/SessionBridge.cpp
+++ b/src/contour_macos/SessionBridge.cpp
@@ -7,9 +7,9 @@
 #include <contour_macos/Themes.h>
 #include <contour_macos/TerminalSession.h>
 
-#include <vtbackend/InputGenerator.h>
-#include <vtbackend/Terminal.h>
-#include <vtrasterizer/FontDescriptions.h>
+#include <vtbackend/InputGenerator.hpp>
+#include <vtbackend/Terminal.hpp>
+#include <vtrasterizer/FontDescriptions.hpp>
 
 #include <algorithm>
 #include <chrono>
@@ -79,22 +79,22 @@ TerminalSession* bridge_create(int widthPx,
 {
     auto fonts = vtrasterizer::FontDescriptions {};
     fonts.dpi = text::DPI { font.dpiX, font.dpiY };
-    fonts.size = text::font_size { font.sizePt };
+    fonts.size = text::FontSize { font.sizePt };
     // render_mode has no default initializer, so it value-initializes to enum value 0 = `bitmap`
     // (1-bit monochrome, no anti-aliasing) — glyphs come out aliased. The Qt frontend defaults to
     // `gray`; do the same. gray (grayscale AA) is the right pick here: lcd/light are subpixel modes
     // for LCD panels, and FreeType's LCD filter is often not built in on this toolchain anyway.
-    fonts.renderMode = text::render_mode::gray;
+    fonts.renderMode = text::RenderMode::Gray;
     std::string const family = font.family ? font.family : "Menlo";
-    for (text::font_description* fd: { &fonts.regular, &fonts.bold, &fonts.italic, &fonts.boldItalic })
+    for (text::FontDescription* fd: { &fonts.regular, &fonts.bold, &fonts.italic, &fonts.boldItalic })
     {
         fd->familyName = family;
-        fd->spacing = text::font_spacing::mono;
+        fd->spacing = text::FontSpacing::Mono;
     }
-    fonts.bold.weight = text::font_weight::bold;
-    fonts.italic.slant = text::font_slant::italic;
-    fonts.boldItalic.weight = text::font_weight::bold;
-    fonts.boldItalic.slant = text::font_slant::italic;
+    fonts.bold.weight = text::FontWeight::Bold;
+    fonts.italic.slant = text::FontSlant::Italic;
+    fonts.boldItalic.weight = text::FontWeight::Bold;
+    fonts.boldItalic.slant = text::FontSlant::Italic;
 
     auto const surfaceSize = ImageSize { vtbackend::Width::cast_from(widthPx),
                                          vtbackend::Height::cast_from(heightPx) };
@@ -245,8 +245,14 @@ void bridge_send_key(TerminalSession* session, int bridgeKey, uint32_t modifiers
 
 void bridge_send_char(TerminalSession* session, uint32_t codepoint, uint32_t modifiers)
 {
+    // KeyIdentity carries what the platform natively calls this key, for the Kitty/win32-input
+    // keyboard protocols. This bridge only ever receives an already-resolved codepoint (the AppKit
+    // view hands us characterAtIndex:, not a raw key position), so the unshifted key IS that
+    // codepoint, and nativeVirtualKey stays 0 -- it is a Win32 VK code, which no macOS key has.
     session->terminal().sendCharEvent(static_cast<char32_t>(codepoint),
-                                      codepoint,
+                                      vtbackend::KeyIdentity { .unshiftedKey =
+                                                                  static_cast<char32_t>(codepoint),
+                                                              .nativeVirtualKey = 0 },
                                       toKeyboardModifiers(modifiers),
                                       vtbackend::KeyboardEventType::Press,
                                       std::chrono::steady_clock::now());
diff --git a/src/contour_macos/SoftwareRenderTarget.h b/src/contour_macos/SoftwareRenderTarget.h
index 6d58dedb..e7a2ab2f 100644
--- a/src/contour_macos/SoftwareRenderTarget.h
+++ b/src/contour_macos/SoftwareRenderTarget.h
@@ -3,9 +3,9 @@
 
 #include <contour_macos/PixelBuffer.h>
 
-#include <vtrasterizer/ImageTextureBackend.h>
-#include <vtrasterizer/RenderTarget.h>
-#include <vtrasterizer/TextureAtlas.h>
+#include <vtrasterizer/ImageTextureBackend.hpp>
+#include <vtrasterizer/RenderTarget.hpp>
+#include <vtrasterizer/TextureAtlas.hpp>
 
 #include <cstdint>
 #include <optional>
diff --git a/src/contour_macos/StubRenderTarget.h b/src/contour_macos/StubRenderTarget.h
index f7f38f4b..28bad245 100644
--- a/src/contour_macos/StubRenderTarget.h
+++ b/src/contour_macos/StubRenderTarget.h
@@ -1,9 +1,9 @@
 // SPDX-License-Identifier: Apache-2.0
 #pragma once
 
-#include <vtrasterizer/ImageTextureBackend.h>
-#include <vtrasterizer/RenderTarget.h>
-#include <vtrasterizer/TextureAtlas.h>
+#include <vtrasterizer/ImageTextureBackend.hpp>
+#include <vtrasterizer/RenderTarget.hpp>
+#include <vtrasterizer/TextureAtlas.hpp>
 
 #include <vector>
 
diff --git a/src/contour_macos/TerminalSession.cpp b/src/contour_macos/TerminalSession.cpp
index 7772791b..12d1e298 100644
--- a/src/contour_macos/TerminalSession.cpp
+++ b/src/contour_macos/TerminalSession.cpp
@@ -1,13 +1,15 @@
 // SPDX-License-Identifier: Apache-2.0
 #include <contour_macos/TerminalSession.h>
 
-#include <vtbackend/Settings.h>
+#include <vtbackend/Settings.hpp>
 
-#include <vtpty/Process.h>
-#include <vtpty/Pty.h>
-#include <vtpty/SshSession.h>
+#include <vtpty/Process.hpp>
+#include <vtpty/Pty.hpp>
+#include <vtpty/SshSession.hpp>
 
-#include <vtrasterizer/Decorator.h>
+#include <vtrasterizer/Decorator.hpp>
+
+#include <crispy/Environment.hpp>
 
 // ImageIO + CoreGraphics (via ApplicationServices on 10.6) for decoding inline PNG images. This is
 // a C API, so it is usable from this ordinary-C++ translation unit (no ObjC needed).
@@ -228,11 +230,17 @@ TerminalSession::TerminalSession(vtbackend::PageSize pageSize,
     _surfaceSize { surfaceSize },
     _backend { backend },
     _renderer { pageSize,
+                vtrasterizer::PageMargin { PageMarginPx, PageMarginPx, PageMarginPx },
                 std::move(fontDescriptions),
                 colorPalette,
-                crispy::strong_hashtable_size { 4096 },
-                crispy::lru_capacity { 4000 },
+                crispy::StrongHashtableSize { 4096 },
+                crispy::LRUCapacity { 4000 },
                 /* atlasDirectMapping */ true,
+                // The renderer's shaper resolves font descriptions through this locator, injected
+                // rather than fetched from the provider singleton. This session is the frontend's
+                // composition root, so it picks the engine, exactly as the Qt display does from its
+                // profile; Native is CoreText on Apple, which is what this port ships.
+                vtrasterizer::createFontLocator(vtrasterizer::FontLocatorEngine::Native),
                 vtrasterizer::Decorator::Underline,
                 vtrasterizer::Decorator::CurlyUnderline }
 {
@@ -266,6 +274,10 @@ TerminalSession::TerminalSession(vtbackend::PageSize pageSize,
 
     _terminal = std::make_unique<vtbackend::Terminal>(
         *this,
+        // The engine resolves its environment reads ($HOME, $CONTOUR_SYNC_PTY_OUTPUT) at
+        // construction. This session is the frontend's composition root, so hand it the
+        // process-wide environment -- the same resolution upstream's main() makes.
+        crispy::defaultEnvironment(),
         makePty(_pageSize, ssh, shellOverride, _callbacks.verifySshHostkey),
         makeSettings(_pageSize),
         steady_clock::now());
diff --git a/src/contour_macos/TerminalSession.h b/src/contour_macos/TerminalSession.h
index 415d74e2..559e2cd2 100644
--- a/src/contour_macos/TerminalSession.h
+++ b/src/contour_macos/TerminalSession.h
@@ -4,10 +4,10 @@
 #include <contour_macos/GLRenderTarget.h>
 #include <contour_macos/SoftwareRenderTarget.h>
 
-#include <vtbackend/Terminal.h>
-#include <vtrasterizer/FontDescriptions.h>
-#include <vtrasterizer/RenderTarget.h>
-#include <vtrasterizer/Renderer.h>
+#include <vtbackend/Terminal.hpp>
+#include <vtrasterizer/FontDescriptions.hpp>
+#include <vtrasterizer/RenderTarget.hpp>
+#include <vtrasterizer/Renderer.hpp>
 
 #include <functional>
 #include <memory>
diff --git a/src/contour_macos/Themes.h b/src/contour_macos/Themes.h
index 327ac391..2ec478f0 100644
--- a/src/contour_macos/Themes.h
+++ b/src/contour_macos/Themes.h
@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: Apache-2.0
 #pragma once
 
-#include <vtbackend/ColorPalette.h>
+#include <vtbackend/ColorPalette.hpp>
 
 #include <string_view>
 
diff --git a/src/contour_macos/render_probe.cpp b/src/contour_macos/render_probe.cpp
index 155b5565..b17f1ce1 100644
--- a/src/contour_macos/render_probe.cpp
+++ b/src/contour_macos/render_probe.cpp
@@ -11,19 +11,19 @@
 #include <contour_macos/SoftwareRenderTarget.h>
 
 #if defined(__APPLE__)
-    #include <text_shaper/coretext_locator.h>
+    #include <text_shaper/CoreTextLocator.hpp>
 #endif
-#include <text_shaper/font_locator.h>
+#include <text_shaper/FontLocator.hpp>
 
-#include <vtbackend/MockTerm.h>
+#include <vtbackend/MockTerm.hpp>
 
-#include <vtpty/MockPty.h>
+#include <vtpty/MockPty.hpp>
 
-#include <vtrasterizer/Decorator.h>
-#include <vtrasterizer/FontDescriptions.h>
-#include <vtrasterizer/Renderer.h>
+#include <vtrasterizer/Decorator.hpp>
+#include <vtrasterizer/FontDescriptions.hpp>
+#include <vtrasterizer/Renderer.hpp>
 
-#include <crispy/StrongLRUHashtable.h>
+#include <crispy/StrongLRUHashtable.hpp>
 
 #include <cstdint>
 #include <cstdio>
@@ -91,33 +91,33 @@ int main(int argc, char** argv)
     // A real DPI and size: the default dpi {0,0} produced a tiny ~7px cell where per-glyph
     // advance rounding is fragile (a wide cap rounds to 2 cells and drifts, eating spaces).
     fonts.dpi = text::DPI { 96, 96 };
-    fonts.size = text::font_size { 14.0 };
+    fonts.size = text::FontSize { 14.0 };
     char const* const family = argc > 2 ? argv[2] : "Menlo";
-    for (text::font_description* fd: { &fonts.regular, &fonts.bold, &fonts.italic, &fonts.boldItalic })
+    for (text::FontDescription* fd: { &fonts.regular, &fonts.bold, &fonts.italic, &fonts.boldItalic })
     {
         fd->familyName = family;
         // A terminal is a fixed grid: force monospace advances so the shaper does not apply
         // proportional kerning (which otherwise makes "mac" too sparse and "OS"/"we" too tight).
-        fd->spacing = text::font_spacing::mono;
+        fd->spacing = text::FontSpacing::Mono;
     }
-    fonts.regular.weight = text::font_weight::normal;
-    fonts.bold.weight = text::font_weight::bold;
-    fonts.italic.slant = text::font_slant::italic;
-    fonts.boldItalic.weight = text::font_weight::bold;
-    fonts.boldItalic.slant = text::font_slant::italic;
+    fonts.regular.weight = text::FontWeight::Normal;
+    fonts.bold.weight = text::FontWeight::Bold;
+    fonts.italic.slant = text::FontSlant::Italic;
+    fonts.boldItalic.weight = text::FontWeight::Bold;
+    fonts.boldItalic.slant = text::FontSlant::Italic;
 
 #if defined(__APPLE__)
     // Diagnostic: show exactly what the CoreText locator resolves for the regular face,
     // isolating a locator bug (bad/empty path) from a shaper/FreeType load failure.
     {
-        text::coretext_locator locator;
+        text::CoreTextLocator locator;
         auto const sources = locator.locate(fonts.regular);
         std::printf("locator.locate(regular=%s) -> %zu source(s):\n", family, sources.size());
         for (auto const& s: sources)
         {
-            if (std::holds_alternative<text::font_path>(s))
+            if (std::holds_alternative<text::FontPath>(s))
             {
-                auto const& p = std::get<text::font_path>(s);
+                auto const& p = std::get<text::FontPath>(s);
                 std::printf("  path='%s' collectionIndex=%d\n", p.value.c_str(), p.collectionIndex);
             }
             else
@@ -128,11 +128,15 @@ int main(int argc, char** argv)
 #endif
 
     auto renderer = Renderer { pageSize,
+                               vtrasterizer::PageMargin { 2, 2, 2 },
                                fonts,
                                colorPalette,
-                               crispy::strong_hashtable_size { 4096 },
-                               crispy::lru_capacity { 4000 },
+                               crispy::StrongHashtableSize { 4096 },
+                               crispy::LRUCapacity { 4000 },
                                /* atlasDirectMapping */ true,
+                               // Same locator the diagnostic above queried directly, reached through
+                               // the provider so the renderer and the probe share one instance.
+                               vtrasterizer::createFontLocator(vtrasterizer::FontLocatorEngine::Native),
                                Decorator::Underline,
                                Decorator::CurlyUnderline };
 
diff --git a/src/contour_macos/smoke_main.cpp b/src/contour_macos/smoke_main.cpp
index 84eb4d43..9a4d3cca 100644
--- a/src/contour_macos/smoke_main.cpp
+++ b/src/contour_macos/smoke_main.cpp
@@ -8,14 +8,14 @@
 
 #include <contour_macos/StubRenderTarget.h>
 
-#include <vtrasterizer/Decorator.h>
-#include <vtrasterizer/FontDescriptions.h>
-#include <vtrasterizer/Renderer.h>
+#include <vtrasterizer/Decorator.hpp>
+#include <vtrasterizer/FontDescriptions.hpp>
+#include <vtrasterizer/Renderer.hpp>
 
-#include <vtbackend/ColorPalette.h>
-#include <vtbackend/primitives.h>
+#include <vtbackend/ColorPalette.hpp>
+#include <vtbackend/Primitives.hpp>
 
-#include <crispy/StrongLRUHashtable.h>
+#include <crispy/StrongLRUHashtable.hpp>
 
 #include <cstdio>
 
@@ -29,11 +29,13 @@ int main()
     auto const fonts = FontDescriptions {};
 
     auto renderer = Renderer { pageSize,
+                               vtrasterizer::PageMargin { 0, 0, 0 },
                                fonts,
                                colorPalette,
-                               crispy::strong_hashtable_size { 4096 },
-                               crispy::lru_capacity { 4000 },
+                               crispy::StrongHashtableSize { 4096 },
+                               crispy::LRUCapacity { 4000 },
                                /* atlasDirectMapping */ true,
+                               vtrasterizer::createFontLocator(vtrasterizer::FontLocatorEngine::Native),
                                Decorator::Underline,
                                Decorator::CurlyUnderline };
 
