Webページで一部フォントの位置がOS依存になる問題に対処する #CSS - Qiita

DIN CondensedをVivliostyleで使用していたところ、WindowsとLinux(&macOS)で組版結果が異なることに気づきました。Playwrightを直接使用して確認してみても同様の問題が発生していたため、おそらくWindows版のChromiumのレンダリング実装周りに問題があるのではないかと推測します。

Linux Windows
before.linux.png before.win32.png
再現用ソースコード

  
    
      @font-face {
        font-family: "DIN Condensed Bold";
        src: url("DIN Condensed Bold.ttf");
      }
    
  
   style="margin: 0">
    

style=" margin: 0; width: 100px; height: 100px; background-color: lightgray; " >

style=' margin: 0; font-family: "DIN Condensed Bold"; font-size: 48px; position: absolute; left: 100px; top: 100px; border: solid black 1px; ' > 0

import os from "node:os";
import path from "node:path";
import * as url from "node:url";

import { chromium } from "playwright";

const indexPath = path.resolve(
  path.dirname(url.fileURLToPath(import.meta.url)),
  "index.html",
);
const indexUrl = url.pathToFileURL(indexPath).toString();

const browser = await chromium.launch();
try {
  const page = await browser.newPage();
  await page.goto(indexUrl);
  await page.screenshot({
    path: `screenshot.${os.platform()}.png`,
    clip: { x: 0, y: 0, width: 300, height: 300 },
  });
} finally {
  await browser.close();
}

メモ:

> docker run --rm --interactive --tty --mount type=bind,source=.,target=/workdir --entrypoint /bin/bash --workdir /workdir node:lts
# npm install && npx playwright install --with-deps chromium

CSSからフォントの設定値を上書きできれば解決できそうです。ascent-overridedescent-overrideline-gap-overrideプロパティが該当することがわかりました。

適切な値を設定するために、Pythonスクリプトでフォントのメトリクス情報を調べます。

import fontTools.ttLib

def get_font_metrics_for_override(path: str):
    font = fontTools.ttLib.TTFont(path)

    units_per_em = font["head"].unitsPerEm
    os2 = font["OS/2"]

    ascent = os2.sTypoAscender
    descent = abs(os2.sTypoDescender)
    line_gap = os2.sTypoLineGap

    ascent_override = 100 * ascent / units_per_em
    descent_override = 100 * descent / units_per_em
    line_gap_override = 100 * line_gap / units_per_em

    return [ascent_override, descent_override, line_gap_override]


[ascent_override, descent_override, line_gap_override] = get_font_metrics_for_override(
    "DIN Condensed Bold.ttf"
)
print(f"ascent-override: {ascent_override}%;")
print(f"descent-override: {descent_override}%;")
print(f"line-gap-override: {line_gap_override}%;")
$ .venv/bin/pip install fonttools
$ .venv/bin/python main.py
ascent-override: 71.2%;
descent-override: 28.8%;
line-gap-override: 20.0%;

上記で得られた値を使って、CSSの@font-faceルールを修正します。

  @font-face {
    font-family: "DIN Condensed Bold";
    src: url("DIN Condensed Bold.ttf");
+   ascent-override: 71.2%;
+   descent-override: 28.8%;
+   line-gap-override: 20.0%;
  }
Linux Windows
after.linux.png after.win32.png

完全一致とはいきませんが実用上問題ない程度に改善することができました。



フラッグシティパートナーズ海外不動産投資セミナー 【DMM FX】入金

Source link