bd85159b36db7ff8c02b32eb18d96ed6066feb8f
braney
  Wed Aug 5 13:59:46 2026 -0700
hgTracks: measure text with the same font engine that will draw it, refs #38027

Pack mode works out how many rows a track needs by measuring its item labels,
and mgFontStringWidth answers from whichever text engine is loaded at the time.
FreeType was only loaded when an image was created, so the measuring could
happen on the bitmap engine while the drawing happened on FreeType -- and which
one you got depended on whether the ideogram image had been built first.

Load the engine in initTl(), alongside the rest of the font setup, before
anything measures a string.  maybeNewFonts() and the new initFontEngine() share
chosenFreeTypeFont(), and mgLoadFontEngine() loads an engine without attaching
it to an image.  ftInitialize() now keeps the face it already has when asked for
the same font file, so the glyph cache hanging off that face survives the extra
call.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

diff --git src/inc/memgfx.h src/inc/memgfx.h
index 2b96fc30738..bb659e71d8f 100644
--- src/inc/memgfx.h
+++ src/inc/memgfx.h
@@ -304,30 +304,36 @@
 int mgFontPixelHeight(MgFont *font);
 /* How high in pixels is font? */
 
 int mgFontLineHeight(MgFont *font);
 /* How many pixels to next line ideally? */
 
 int mgFontWidth(MgFont *font, char *chars, int charCount);
 /* How wide are a couple of letters? */
 
 int mgFontStringWidth(MgFont *font, char *string);
 /* How wide is a string? */
 
 int mgFontCharWidth(MgFont *font, char c);
 /* How wide is a character? */
 
+void mgLoadFontEngine(unsigned int method, char *fontFile);
+/* Load a text engine without attaching it to an image.  Text measurement
+ * (mgFontStringWidth) answers from whichever engine is loaded, so a caller that
+ * measures text before it has an image to draw on needs to load the engine
+ * first, or it will measure with one engine and draw with another. */
+
 char *mgFontSizeBackwardsCompatible(char *size);
 /* Given "size" argument that may be in old tiny/small/medium/big/huge format,
  * return it in new numerical string format. Do NOT free the return string*/
 
 MgFont *mgFontForSizeAndStyle(char *textSize, char *fontType);
 /* Get a font of given size and style.  Abort with error message if not found.
  * The textSize should be 6,8,10,12,14,18,24 or 34.  For backwards compatibility
  * textSizes of "tiny" "small", "medium", "large" and "huge" are also ok.
  * The fontType should be "medium", "bold", or "fixed" */
 
 MgFont *mgFontForSize(char *textSize);
 /* Get a font of given size and style.  Abort with error message if not found.
  * The textSize should be 6,8,10,12,14,18,24 or 34.  For backwards compatibility
  * textSizes of "tiny" "small", "medium", "large" and "huge" are also ok. */