76 lines
3.7 KiB
Bash
76 lines
3.7 KiB
Bash
|
|
#!/usr/bin/env bash
|
||
|
|
# tools/check-text-measure.sh — chrome text must be measured in the family
|
||
|
|
# it is painted in.
|
||
|
|
#
|
||
|
|
# `RenderBackend::measure_text` (jian's `Painter::measure_text`) is
|
||
|
|
# family-BLIND: it resolves the backend's default typeface — the bundled
|
||
|
|
# Roboto on native, the CanvasKit default in the browser — while every chrome
|
||
|
|
# string is DRAWN as a named run (`system-ui`, which macOS resolves to
|
||
|
|
# `.AppleSystemUIFont`). SF Pro is wider than Roboto at the same point size,
|
||
|
|
# so the blind call under-reports the painted width.
|
||
|
|
#
|
||
|
|
# Nothing errors when that happens. An ellipsizer believes a string fits and
|
||
|
|
# emits no `…`, so the content clip shears the last glyph in half; a centred
|
||
|
|
# label lands left of centre; a tooltip bubble sized as `measured + padding`
|
||
|
|
# is born too narrow for its own text; a caret drifts off the glyph being
|
||
|
|
# edited. And none of it reproduces in CI, because every test backend
|
||
|
|
# measures blind and family-aware identically — the bug is visible only by
|
||
|
|
# eye, on a real machine. That is what makes this worth a build gate.
|
||
|
|
#
|
||
|
|
# The sanctioned path is `crate::widgets::text_metrics` (`measure_chrome` /
|
||
|
|
# `fit_chrome` / `centered_text_x` / `measure_in_family`), which routes to
|
||
|
|
# `measure_text_family` with the run's real family.
|
||
|
|
#
|
||
|
|
# Exit semantics:
|
||
|
|
# 0 PASS — no family-blind measurement in widget code.
|
||
|
|
# 1 FAIL — a widget module called `measure_text` directly.
|
||
|
|
|
||
|
|
set -euo pipefail
|
||
|
|
|
||
|
|
WIDGETS="crates/op-editor-ui/src/widgets"
|
||
|
|
|
||
|
|
# Files that legitimately name the blind call:
|
||
|
|
# text_metrics.rs — defines the sanctioned wrappers, and its own
|
||
|
|
# tests compare blind against family-aware.
|
||
|
|
# text_input_backend.rs — a decorating `RenderBackend` that must forward
|
||
|
|
# every trait method, blind one included.
|
||
|
|
# test_family_gap_backend.rs / test_capture_backend.rs
|
||
|
|
# — test backends implementing the trait.
|
||
|
|
# text_metrics_paint_tests.rs
|
||
|
|
# — the cross-panel guard's negative control
|
||
|
|
# paints a deliberately blind fitter to prove the
|
||
|
|
# guard can fail.
|
||
|
|
ALLOWED_RE='^crates/op-editor-ui/src/widgets/(text_metrics|text_metrics_paint_tests|text_input_backend|test_family_gap_backend|test_capture_backend)\.rs:'
|
||
|
|
|
||
|
|
# `.measure_text(` as a method call, excluding the family-aware and
|
||
|
|
# weight-aware siblings (`measure_text_family`, `measure_text_family_styled`,
|
||
|
|
# `measure_text_weighted`, `measure_text_styled`) and trait-impl signatures
|
||
|
|
# (`fn measure_text(`).
|
||
|
|
hits="$(grep -RInE '\.[[:space:]]*measure_text[[:space:]]*\(' "${WIDGETS}" 2>/dev/null \
|
||
|
|
| grep -vE "${ALLOWED_RE}" \
|
||
|
|
|| true)"
|
||
|
|
|
||
|
|
if [ -n "${hits}" ]; then
|
||
|
|
printf 'FAIL: family-blind text measurement in widget code\n' >&2
|
||
|
|
printf '\n' >&2
|
||
|
|
printf '%s\n' "${hits}" >&2
|
||
|
|
printf '\n' >&2
|
||
|
|
printf 'RenderBackend::measure_text resolves the backend default font, not the\n' >&2
|
||
|
|
printf 'family these runs are painted with. Measure through\n' >&2
|
||
|
|
printf 'crate::widgets::text_metrics instead:\n' >&2
|
||
|
|
printf '\n' >&2
|
||
|
|
printf ' cx.backend.measure_text(s, size)\n' >&2
|
||
|
|
printf ' -> text_metrics::measure_chrome(cx.backend, s, size)\n' >&2
|
||
|
|
printf ' ellipsize_to_width(s, w, |t| cx.backend.measure_text(t, size))\n' >&2
|
||
|
|
printf ' -> text_metrics::fit_chrome(cx.backend, s, w, size)\n' >&2
|
||
|
|
printf ' rect.origin.x + (rect.size.x - measured) / 2.0\n' >&2
|
||
|
|
printf ' -> text_metrics::centered_text_x(cx.backend, s, size, rect)\n' >&2
|
||
|
|
printf '\n' >&2
|
||
|
|
printf 'For a run drawn in some other family (a jian component painting in\n' >&2
|
||
|
|
printf '"Inter", a monospace readout), name that family:\n' >&2
|
||
|
|
printf ' text_metrics::measure_in_family / fit_in_family.\n' >&2
|
||
|
|
exit 1
|
||
|
|
fi
|
||
|
|
|
||
|
|
echo "PASS: text measurement check"
|