Title: GC.textExtent() ignores requested font family and measures wider text in headless (Xvfb/GTK) vs. a real win32 display
Summary
Using a minimal, standalone SWT snippet (no Eclipse RCP application, no GEF/draw2d — pure org.eclipse.swt.graphics.GC#textExtent()), the same font name/size/text produces different measured extents when run headless on Linux under Xvfb (GTK) vs. on a real Windows display (win32).
Two distinct problems are visible in the data:
- Font family name has no effect on measurement in the headless/GTK case. Requesting
"Segoe UI", "DejaVu Sans", and "Sans" (all at 9pt) produces byte-identical width/height for every test string under Xvfb/GTK — even though Segoe UI (a physically installed TTF, verified via fc-match/fc-list outside this test) is a genuinely different typeface from DejaVu Sans. On win32, the three names produce measurably different results, as expected (Segoe UI differs from the DejaVu Sans/Sans fallback).
- Headless/GTK measurements are systematically wider than the win32 equivalent for the same font size, by roughly 6%–33% depending on the string (see table below). This causes downstream layout problems in any Eclipse RCP application that pre-computes fixed pixel geometry from text measured headlessly and expects it to match what was authored/measured on a real (typically Windows) display — e.g. GEF/draw2d figures with fixed bounds, as used by Archi (
archimatetool/archi) for diagram rendering.
Environment
- SWT jar (Linux):
org.eclipse.swt.gtk.linux.x86_64_3.134.0.v20260515-1429.jar
- SWT jar (Windows):
org.eclipse.swt.win32.win32.x86_64_3.126.0.v20240528-0813.jar
(version mismatch between the two — noted as a caveat below, but the within-platform font-name-has-no-effect finding on Linux is version-independent)
- Linux: Docker container, Xvfb virtual display (
xvfb-run -a ...), JRE 21
- Windows: normal desktop session, real display, JRE (same major version)
- Font
Segoe UI verified present on the Linux side (fc-match "Segoe UI" correctly resolves to segoeui.ttf, confirmed via fc-list)
Reproduction
Minimal snippet (attached in full below) does, per font name in {"Segoe UI", "DejaVu Sans", "Sans"}:
Display display = new Display();
Image dummy = new Image(display, 10, 10);
GC gc = new GC(dummy);
Font font = new Font(display, fontName, 9, SWT.NORMAL);
gc.setFont(font);
Point extent = gc.textExtent(text);
System.out.println(fontName + " -> " + extent.x + "x" + extent.y + " for: " + text);
Run headless:
xvfb-run -a java -cp ".:$SWT_JAR" TextExtentTest
Run on Windows desktop (real display, no Xvfb):
java -cp ".;<swt.jar>" TextExtentTest
Results
All measurements at 9pt. width in pixels as returned by GC.textExtent().
| Text |
Linux/Xvfb/GTK (all 3 font names identical) |
Windows/win32, Segoe UI |
Windows/win32, DejaVu Sans/Sans |
Linux vs Windows Segoe UI |
Компонент |
70 |
62 |
63 |
+12.9% |
финансово-экономического |
174 |
160 |
159 |
+8.75% |
ОООС «Ванильный Бюджет» (новая версия) |
277 |
243 |
255 |
+14.0% |
топик 20 \nзапрос на формирование УГПП по |
215 |
193 |
200 |
+11.4% |
192.168.231.150 \ngoogle.com |
112 |
84 |
96 |
+33.3% |
Hello World |
67 |
63 |
64 |
+6.3% |
AAAAAAAAAAAAAAAAAAAA (20×A) |
179 |
160 |
140 |
+11.9% |
Note on the Linux side: all three requested font names produced these exact same numbers, row for row — i.e. the "Segoe UI" column, "DejaVu Sans" column, and "Sans" column values on Linux are one and the same, whereas on Windows they genuinely differ per font.
Why this matters
Any application that measures/lays out text headlessly (CI pipelines, automated report/diagram generation, etc.) using SWT GC.textExtent() and expects that layout to match what a user sees/authored on a real (typically Windows) desktop will get incorrect, generally too-wide-but-not-reliably-scaled text metrics, and — separately — will get no differentiation at all between different font families in the headless/GTK case. We hit this in practice via Archi (archimatetool/archi) generating HTML diagram reports headlessly in a CI/Docker pipeline: text overflows figure boundaries that were sized correctly on Windows desktop, and no combination of installing/selecting fonts on the Linux side changed the outcome — which this snippet now explains: the font selection wasn't taking effect on the measurement path at all.
Caveats
- The two SWT jar versions compared (3.134.0 Linux vs 3.126.0 Windows) are not identical, so version drift could contribute to the magnitude of the width difference. However, the font-name-has-no-effect-on-Linux finding is internally consistent within the single Linux run (three different names, one identical result) and doesn't depend on cross-version comparison at all.
fc-match/fc-list outside this JVM confirm Segoe UI is present and correctly resolvable at the fontconfig level — so the lack of differentiation appears to be happening either in SWT's GTK backend itself, or in how it (or possibly Pango/Cairo under Xvfb) selects a font for measurement, not in fontconfig/system-level font registration.
Attached
TextExtentTest.java (full source, self-contained, no dependencies beyond the platform SWT jar)
- Raw output:
linux_headless_output.txt, windows_output.txt
Happy to run further variations (different SWT versions on both sides, real X11 display on Linux instead of Xvfb, etc.) if that would help narrow this down further.
windows_output.txt
linux_headless_output.txt
TextExtentTest.java
Title: GC.textExtent() ignores requested font family and measures wider text in headless (Xvfb/GTK) vs. a real win32 display
Summary
Using a minimal, standalone SWT snippet (no Eclipse RCP application, no GEF/draw2d — pure
org.eclipse.swt.graphics.GC#textExtent()), the same font name/size/text produces different measured extents when run headless on Linux under Xvfb (GTK) vs. on a real Windows display (win32).Two distinct problems are visible in the data:
"Segoe UI","DejaVu Sans", and"Sans"(all at 9pt) produces byte-identical width/height for every test string under Xvfb/GTK — even thoughSegoe UI(a physically installed TTF, verified viafc-match/fc-listoutside this test) is a genuinely different typeface fromDejaVu Sans. On win32, the three names produce measurably different results, as expected (Segoe UI differs from the DejaVu Sans/Sans fallback).archimatetool/archi) for diagram rendering.Environment
org.eclipse.swt.gtk.linux.x86_64_3.134.0.v20260515-1429.jarorg.eclipse.swt.win32.win32.x86_64_3.126.0.v20240528-0813.jar(version mismatch between the two — noted as a caveat below, but the within-platform font-name-has-no-effect finding on Linux is version-independent)
xvfb-run -a ...), JRE 21Segoe UIverified present on the Linux side (fc-match "Segoe UI"correctly resolves tosegoeui.ttf, confirmed viafc-list)Reproduction
Minimal snippet (attached in full below) does, per font name in
{"Segoe UI", "DejaVu Sans", "Sans"}:Run headless:
Run on Windows desktop (real display, no Xvfb):
Results
All measurements at 9pt.
widthin pixels as returned byGC.textExtent().Segoe UIDejaVu Sans/SansКомпонентфинансово-экономическогоОООС «Ванильный Бюджет» (новая версия)топик 20 \nзапрос на формирование УГПП по192.168.231.150 \ngoogle.comHello WorldAAAAAAAAAAAAAAAAAAAA(20×A)Note on the Linux side: all three requested font names produced these exact same numbers, row for row — i.e. the "Segoe UI" column, "DejaVu Sans" column, and "Sans" column values on Linux are one and the same, whereas on Windows they genuinely differ per font.
Why this matters
Any application that measures/lays out text headlessly (CI pipelines, automated report/diagram generation, etc.) using SWT
GC.textExtent()and expects that layout to match what a user sees/authored on a real (typically Windows) desktop will get incorrect, generally too-wide-but-not-reliably-scaled text metrics, and — separately — will get no differentiation at all between different font families in the headless/GTK case. We hit this in practice via Archi (archimatetool/archi) generating HTML diagram reports headlessly in a CI/Docker pipeline: text overflows figure boundaries that were sized correctly on Windows desktop, and no combination of installing/selecting fonts on the Linux side changed the outcome — which this snippet now explains: the font selection wasn't taking effect on the measurement path at all.Caveats
fc-match/fc-listoutside this JVM confirmSegoe UIis present and correctly resolvable at the fontconfig level — so the lack of differentiation appears to be happening either in SWT's GTK backend itself, or in how it (or possibly Pango/Cairo under Xvfb) selects a font for measurement, not in fontconfig/system-level font registration.Attached
TextExtentTest.java(full source, self-contained, no dependencies beyond the platform SWT jar)linux_headless_output.txt,windows_output.txtHappy to run further variations (different SWT versions on both sides, real X11 display on Linux instead of Xvfb, etc.) if that would help narrow this down further.
windows_output.txt
linux_headless_output.txt
TextExtentTest.java