6

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.Wikipedia sample
  • Rasterization with hinting and subpixel rendering for an RGB flat panel displayWikipedia sample

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: enter image description here enter image description here


2. Rendering result on another Linux PC: enter image description here enter image description here


3. Differences:

enter image description here enter image description here

6
  • How are you comparing the snapshots? Have you checked visual comparisons ? Tried running headless? Commented Oct 16, 2024 at 15:25
  • @PanagiotisKanavos that is exactly the feature we are using. So image comparison is done by playwright. It spits out the diff image attached. Since the comparison is not an issue (the differences are obvious even without the diff image), the snapshot mechanism shouldn't be the problem, I reckon. Commented Oct 16, 2024 at 16:02
  • @PanagiotisKanavos Playwright is configured to run the driver headless, as you can see in the mentioned config. Commented Oct 16, 2024 at 16:07
  • The initial question contained a wall of configuration, no code and doesn't even mention the language or how the screenshots were taken. It still doesn't mention the language but at least one can guess it's Javascript because other language bindings don't have visual snapshots yet. Commented Oct 17, 2024 at 7:01
  • On top of that, the demand for 0 pixel differences isn't realistic, even with software rendering. Software drivers can easily change from one OS version to the next or even if different patches are applied. Different machines can have different aliasing settings. What happens if you don't use such extreme thresholds? Commented Oct 17, 2024 at 7:07

1 Answer 1

6

We could solve the issue by setting the following additional argument for the chromium driver:

--disable-lcd-text

This disables subpixel antialiasing for LCD screens, which wasn't working on headless environments (without LCD screen) and also depends on what LCD screen you have and how the subpixels are positioned per pixel.

Without the setting chrome seems to use greyscale antialiasing for fonts.

enter image description here enter image description here

(src: https://www.alienryderflex.com/sub_pixel/ )

Sign up to request clarification or add additional context in comments.

3 Comments

So you're saying that running tests in headless mode mcr.microsoft.com/playwright on different hardware generates different results? Any way to reproduce it? I just checked my M2 Macbook and AMD Laptop with the latest docker, 1.48 container - I don't see it. Curios :) Good you solved it, just interested how to reproduce it
interesting answer!
This whole SO article helped me also in an other interesting scenario where everything was running fine on a Windows server while I was connected through RDP launching a local instance of Chrome, and all of a sudden, PDF was off the minute I disconnected from the RDP session. Basically I had to ensure that both were using the same restricted set of options so that the layout stayed consistent. This took me more than a week to figure out, sadly.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.