We use playwright with chromium-driver for our End-to-End tests and now are trying to establish image comparison tests. We fail with fonts getting rendered differently on different platforms, despite using the same chrome-driver. It even makes no difference if rendering using the official docker image mcr.microsoft.com/playwright:1.43.1.
We assume that somehow the host system hardware is involved and causes different results. Hence we tried to exclude the GPU and to force CPU rendering. Either we didn't succeed there or there still is any other difference in the configuration/environment.
The images below clearly show that there is an issue with Anti-Aliasing or Subpixel positioning (is it?) where in one case a multi-color and in the other case a grey-scale technique is used. Canvas rendered font does not show these differences.
The same effect is described here:
- Rasterization with anti-aliasing with hinting. Here pixels are forced to fall into integral pixel coordinates whenever possible.

- Rasterization with hinting and subpixel rendering for an RGB flat panel display

What option causes this difference?
Can it be unified for all host platforms?
Playwright config:
const config: PlaywrightTestConfig = {
testDir: 'tests/specs',
forbidOnly: CI,
workers: CI ? 10 : 1,
retries: CI ? 2 : 0,
timeout: 60 * 1000,
expect: {
timeout: 10 * 1000,
},
use: {
headless: true,
ignoreHTTPSErrors: true,
acceptDownloads: true,
screenshot: 'only-on-failure',
video: {
mode: 'retain-on-failure',
size: { width: 1280, height: 720 },
},
trace: 'retain-on-failure',
launchOptions: {
args: [
// https://peter.sh/experiments/chromium-command-line-switches/
'--disable-gpu', // Disables GPU hardware acceleration. If software renderer is not in place, then the GPU process won't launch.
'--disable-gpu-rasterization', // Disable GPU rasterization, i.e. rasterize on the CPU only. Overrides the kEnableGpuRasterization flag.
'--disable-gpu-compositing', // Prevent the compositor from using its GPU implementation.
'--disable-font-subpixel-positioning', // Force disables font subpixel positioning. This affects the character glyph sharpness, kerning, hinting and layout.
'--disable-software-rasterizer', // Disables the use of a 3D software rasterizer. (Necessary to make --disable-gpu work)
'--ppapi-subpixel-rendering-setting=0', // The enum value of FontRenderParams::subpixel_rendering to be passed to Ppapi processes.
'--force-device-scale-factor=1', // Overrides the device scale factor for the browser UI and the contents.
'--force-color-profile=srgb', // Force all monitors to be treated as though they have the specified color profile.
],
},
},
projects: [
{
name: 'Our project',
use: {
...devices['Desktop Chrome'],
viewport: { width: 1920, height: 1080 },
},
},
],
reporter:
CI ?
[
['list'],
['junit', { outputFile: 'test-results/results.xml' }],
['html', { open: 'never', outputFolder: 'test-reports' }],
]
: [['list']],
};
Snapshotting and comparison is done by PlayWright:
await expect(
locator,
'Snapshots do not match.',
).toHaveScreenshot(`${snapshotId}.png`, {
threshold: 0,
maxDiffPixels: 0,
maxDiffPixelRatio: 0,
});
(https://playwright.dev/docs/test-snapshots)
1. Rendering result on one Linux PC:

2. Rendering result on another Linux PC:

3. Differences:



