Skip to content

Add a stroke rendering regression test over a type/head/tail matrix - #19

Merged
kurgm merged 1 commit into
kurgm:masterfrom
frankslin:test/stroke-matrix
Aug 2, 2026
Merged

Add a stroke rendering regression test over a type/head/tail matrix#19
kurgm merged 1 commit into
kurgm:masterfrom
frankslin:test/stroke-matrix

Conversation

@frankslin

Copy link
Copy Markdown

The testKage cases in test/index.js compare three hand-written glyphs
against inlined polygon coordinates. That is precise, but narrow: between them
they exercise 10 distinct (stroke type, head type, tail type) combinations, all
in mincho with kUseCurve off. Stroke types 3, 6 and 7 are never drawn, and
gothic is never rendered at all.

This PR adds test/strokes.js, which trades precision for breadth. It renders a
deterministic matrix and compares a fingerprint of each result against a
committed golden file:

  • stroke types {1,2,3,4,6,7} x 9 head types x 15 tail types x 4 control point
    geometries x both shotai
  • a kUseCurve sample over the curve-bearing stroke types (that code path in
    cdDrawCurveU is currently untested)
  • whole-glyph cases covering buhin expansion, the two-segment stretch mode
    (sx > 100) and the 0:97 / 0:98 / 0:99 transforms

7,614 cases, about 0.3 s. npm test now runs test/index.js and then
test/strokes.js.

The fingerprint is (polygon count, point count, sha1 of the coordinates),
stored in test/strokes-golden.tsv. It only answers "did the output change",
never "is the output correct" — deciding the latter is still a visual job. When
output changes on purpose: UPDATE_GOLDEN=1 node test/strokes.js, then read the
diff. Each changed line is one stroke whose shape moved, so a diff that is
larger than expected is itself a signal.

Design notes

One geometry runs right-to-left and upwards. The README lists several
head/tail shapes that behave oddly when a stroke points that way, deliberately
left alone for now to avoid affecting non-kanji glyphs. Pinning them down means
that when they do get fixed, it shows up as an explicit golden-file update
rather than silently.

A case that throws records ERROR <message> as its expected value instead
of failing the run. Some combinations in the matrix are not meaningful for their
stroke type, and what matters is that the engine's answer to them stays put — a
combination that starts or stops throwing is exactly the kind of change this is
meant to surface. Non-finite coordinates are recorded the same way.

The corpus is entirely fixed literals — no RNG, no dates — so the golden
file is reproducible across machines and runs.

Baseline

0 throwing cases, 32 that draw nothing. The 32 are mincho straight lines with
head type 2 or 7 where the stroke is not horizontal, e.g. 1:2:2:50:20:50:80.
I checked those inputs against kamichikoichi/kage-engine and the behavior is
identical there, so they are recorded as-is rather than treated as a defect.

Sanity check that the test actually bites

Changing Mincho's kMinWidthY from 2 to 2.05 makes it report 2282 changed
cases; reverting restores a pass.

Notes

  • No src/ changes, so no CHANGELOG entry — following the precedent of
    c9b8baa ("Add tests for rotation (0:99:2)"), which was also test-only.
  • test/strokes.js passes eslint under the existing flat config.
  • The golden file is 427 KB. If you would rather not carry that in the repo, I
    am happy to shrink it — truncating the hashes, dropping the rl geometry, or
    narrowing the tail-type list would each cut it substantially.

The existing `testKage` cases in test/index.js compare three hand-written
glyphs against inlined polygon coordinates. That is precise, but narrow:
between them they exercise 10 distinct (stroke type, head type, tail type)
combinations, all in mincho with `kUseCurve` off. Stroke types 3, 6 and 7
are never drawn, and gothic is never rendered at all.

This adds test/strokes.js, which trades precision for breadth. It renders a
deterministic matrix -- stroke types {1,2,3,4,6,7} x 9 head types x 15 tail
types x 4 control point geometries x both shotai, plus a `kUseCurve` sample
over the curve-bearing stroke types, plus whole-glyph cases covering buhin
expansion, the two-segment stretch mode and the 0:97/98/99 transforms --
and compares a fingerprint of each result (polygon count, point count, sha1
of the coordinates) against test/strokes-golden.tsv. 7,614 cases, ~0.3s.

Notes on the design:

- One of the four geometries runs right-to-left and upwards. The README
  lists several head/tail shapes that behave oddly in that direction and are
  deliberately left alone for now; pinning them down means a later fix shows
  up as an explicit golden update rather than silently.

- A case that throws records `ERROR <message>` as its expected value instead
  of failing the run. Some combinations in the matrix are not meaningful for
  their stroke type, and what matters is that the engine's answer to them
  stays put -- a combination that starts or stops throwing is exactly the
  kind of change this is meant to surface. Non-finite coordinates are
  recorded the same way.

- The fingerprint only answers "did the output change", never "is the output
  correct". Intentional changes are handled with
  `UPDATE_GOLDEN=1 node test/strokes.js` followed by reading the diff.

The current baseline is 0 throwing cases and 32 that draw nothing. The 32
are mincho straight lines with head type 2 or 7 where the stroke is not
horizontal; I checked these against kamichikoichi/kage-engine and the
behavior is identical there, so they are recorded as-is rather than treated
as a defect.

Sanity check that the test actually bites: changing `Mincho`'s kMinWidthY
from 2 to 2.05 makes it report 2282 changed cases.
frankslin added a commit to frankslin/kage-engine that referenced this pull request Jul 29, 2026
先前寫「npm test 完全沒有涵蓋筆畫繪製」是錯的。test/index.js 裡的 testKage
自 2017 年起就在逐點比對三個字形的完整多邊形輸出(容差 0.5、on/off-curve
旗標、NaN 檢查),只是通過時靜默,npm test 的輸出只看得到
「Buhin#onMissing: ok」,我據此下了結論沒有往下讀。

實際缺口比原本寫的窄但確實存在:實測枚舉過,現有測試只觸及 10 組(筆畫類型/
頭形/尾形)組合,全部是明朝體且 kUseCurve 關閉,筆畫類型 3/6/7 從未被畫出,
黑體完全沒有渲染過。

補齊用的矩陣回歸測試(7,614 個 case)已提到上游 kurgm#19,
本 repo 不另外維護一份;若被合併,git merge kurgm/master 會一併帶進來。
文件改為說明這個狀態。
@kurgm

kurgm commented Aug 2, 2026

Copy link
Copy Markdown
Owner

Thank you for your contribution!

@kurgm
kurgm merged commit 11ccff0 into kurgm:master Aug 2, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants