diff --git a/web/src/components/Minimap.tsx b/web/src/components/Minimap.tsx index 0dacc1b..24e5c5d 100644 --- a/web/src/components/Minimap.tsx +++ b/web/src/components/Minimap.tsx @@ -79,22 +79,23 @@ export const MAP_W = 180 * Розмін свідомий: мініатюра, на якій нічого не розібрати, не стає * кориснішою від того, що вміщає більше. */ -const ROW_PX = 8 +const ROW_PX = 7 /** * Розмір шрифту мініатюри. * - * Сім пікселів — найменше, на чому моноширинний шрифт ще лишається - * ЛІТЕРАМИ, а не сірою крупою. Менше пробували: на шести зникають - * внутрішні просвіти в «e», «a», «o», і слово перетворюється на пляму - * тієї самої довжини. + * Шість, а не сім. На сімці літери читались, але займали більше місця, + * ніж треба: мініатюра має показувати ДЕ ти в файлі, а не пропонувати + * себе замість тексту поруч. * - * Звідси й ROW_PX = 8: сім на літери, один на просвіт між рядками. - * Рядків у вікні стає близько вісімдесяти замість двохсот — і це не - * втрата, а обмін. Двісті нечитабельних рядків показують силует файла; - * вісімдесят читабельних показують, ДЕ ти в ньому. Друге і просили. + * Чіткість на шести тримається не розміром, а вирівнюванням по + * піксельній сітці (див. snap нижче). Без нього шрифт цього розміру + * розмазується на дробовому масштабі екрана — і саме розмиття, а не + * розмір, читається як «нечітко». + * + * ROW_PX = 7: шість на літери, один на просвіт між рядками. */ -const FONT_PX = 7 +const FONT_PX = 6 /** * Товщина штриха рядка. Один піксель, а не два — і це не косметика. @@ -398,6 +399,15 @@ export function Minimap({ // а хвіст із адресами й масками не читався б однаково. ctx.font = FONT_PX + 'px ui-monospace, SFMono-Regular, Menlo, Consolas, monospace' ctx.textBaseline = 'top' + + // Вирівнювання по піксельній сітці ПРИСТРОЮ, а не CSS. + // + // Полотно масштабоване на dpr, тож координата 9 при dpr 1.25 дає + // 11.25 фізичного пікселя — і браузер розмазує літеру між двома. + // На дрібному шрифті це видно як «нечітко»: розмір тут ні до чого, + // винне півпікселя зсуву. Округлення до цілого пристроєвого + // пікселя прибирає розмиття без жодної втрати. + const snap = (v: number) => Math.round(v * dpr) / dpr // Ширину символа беремо вимірюванням, а не формулою: у різних // системах підставляється різний моноширинний шрифт, і константа // тут рано чи пізно розійшлася б із дійсністю мовчки. @@ -442,7 +452,7 @@ export function Minimap({ // блоки JunOS з'їхали б до лівого краю й структура зникла саме // там, де вона найпомітніша. const flat = text.length > maxChars * 2 ? text.slice(0, maxChars * 2) : text - ctx.fillText(flat.replace(/ /g, ' ').slice(0, maxChars), left, y) + ctx.fillText(flat.replace(/ /g, ' ').slice(0, maxChars), snap(left), snap(y)) } if (fits) {