Мінікарта малює справжні літери, а не прямокутники
Скільки не підбирай товщину, колір і щільність — прямокутник не стає літерою. Арифметика: щоб текст читався, символу треба 5-6 пікселів; при 120 символах у смузі 180 px виходило 1.4. Читабельним він не міг стати за жодних налаштувань, і три попередні спроби це лікували симптоматично. Тепер canvas друкує ПОЧАТОК рядка шрифтом 7 px — найменшим, на якому моноширинний ще лишається літерами (на 6 зникають внутрішні просвіти в e, a, o). Ширина символа вимірюється, а не рахується формулою: у різних системах підставляється різний моноширинний шрифт. Для конфігу початок рядка й несе структуру: відступ і ключове слово стоять зліва, а хвіст з адресами не читався б однаково. Табуляція розгортається в пробіли — у canvas вона не має ширини, і блоки JunOS з їхали б до лівого краю. Рядків у вікні стало близько вісімдесяти замість двохсот. Це обмін, а не втрата: двісті нечитабельних показують силует файла, вісімдесят читабельних показують, ДЕ ти в ньому. Запасний шлях прямокутниками лишився для порівняння версій, де рядки беруться з різниці, а не з файла.
This commit is contained in:
parent
3a52d4a870
commit
68fd47ff19
1 changed files with 42 additions and 28 deletions
|
|
@ -79,7 +79,22 @@ export const MAP_W = 180
|
|||
* Розмін свідомий: мініатюра, на якій нічого не розібрати, не стає
|
||||
* кориснішою від того, що вміщає більше.
|
||||
*/
|
||||
const ROW_PX = 3
|
||||
const ROW_PX = 8
|
||||
|
||||
/**
|
||||
* Розмір шрифту мініатюри.
|
||||
*
|
||||
* Сім пікселів — найменше, на чому моноширинний шрифт ще лишається
|
||||
* ЛІТЕРАМИ, а не сірою крупою. Менше пробували: на шести зникають
|
||||
* внутрішні просвіти в «e», «a», «o», і слово перетворюється на пляму
|
||||
* тієї самої довжини.
|
||||
*
|
||||
* Звідси й ROW_PX = 8: сім на літери, один на просвіт між рядками.
|
||||
* Рядків у вікні стає близько вісімдесяти замість двохсот — і це не
|
||||
* втрата, а обмін. Двісті нечитабельних рядків показують силует файла;
|
||||
* вісімдесят читабельних показують, ДЕ ти в ньому. Друге і просили.
|
||||
*/
|
||||
const FONT_PX = 7
|
||||
|
||||
/**
|
||||
* Товщина штриха рядка. Один піксель, а не два — і це не косметика.
|
||||
|
|
@ -125,21 +140,6 @@ const GUTTER_W = 6
|
|||
*/
|
||||
const MAX_COLS = 120
|
||||
|
||||
/**
|
||||
* Скільки слів у рядку малюємо окремо.
|
||||
*
|
||||
* Саме проміжки між словами роблять смужку схожою на текст: суцільна
|
||||
* риса від відступу до кінця рядка читається як штрих, а не як рядок.
|
||||
*
|
||||
* Стеля потрібна, бо в конфігах трапляються рядки на сотні коротких
|
||||
* лексем (списки VLAN, префікс-листи): малювати їх усі — це тисячі
|
||||
* прямокутників заради ділянки в кілька пікселів завширшки.
|
||||
*/
|
||||
const MAX_SEGS = 40
|
||||
|
||||
const SP = ' '
|
||||
const TAB = ' '
|
||||
|
||||
/**
|
||||
* Форма тексту: довжина й відступ кожного рядка.
|
||||
*
|
||||
|
|
@ -384,6 +384,25 @@ export function Minimap({
|
|||
ctx.clearRect(0, 0, MAP_W, h)
|
||||
|
||||
const left = fits ? 3 : GUTTER_W + 3
|
||||
|
||||
// Справжній текст замість штрихів.
|
||||
//
|
||||
// Попередні версії малювали слова прямокутниками — і скільки не
|
||||
// підбирай товщину, колір і щільність, прямокутник не стає літерою.
|
||||
// Арифметика проста: щоб текст читався, символу треба 5–6 пікселів;
|
||||
// при 120 символах у смузі 180 px виходило 1.4, тобто читабельним
|
||||
// він не міг стати за жодних налаштувань.
|
||||
//
|
||||
// Тому показуємо ПОЧАТОК рядка справжніми літерами. Для конфігу це
|
||||
// саме те, що несе структуру: відступ і ключове слово стоять зліва,
|
||||
// а хвіст із адресами й масками не читався б однаково.
|
||||
ctx.font = FONT_PX + 'px ui-monospace, SFMono-Regular, Menlo, Consolas, monospace'
|
||||
ctx.textBaseline = 'top'
|
||||
// Ширину символа беремо вимірюванням, а не формулою: у різних
|
||||
// системах підставляється різний моноширинний шрифт, і константа
|
||||
// тут рано чи пізно розійшлася б із дійсністю мовчки.
|
||||
const charW = ctx.measureText('0').width || FONT_PX * 0.6
|
||||
const maxChars = Math.max(1, Math.floor((MAP_W - left - 3) / charW))
|
||||
const scale = (MAP_W - left - 3) / cols
|
||||
|
||||
// У режимі «влазить цілком» рядку дістається стільки пікселів,
|
||||
|
|
@ -411,24 +430,19 @@ export function Minimap({
|
|||
ctx.fillStyle = color
|
||||
|
||||
// Без доступу до самого тексту лишається суцільна риса від
|
||||
// відступу до кінця рядка. Працює, але читається гірше.
|
||||
// відступу до кінця рядка. Це запасний шлях: ним іде порівняння
|
||||
// версій, де рядки беруться не з файла, а з різниці.
|
||||
const text = lineAt?.(i)
|
||||
if (!text) {
|
||||
bar(shape.indent[i], L, y)
|
||||
return
|
||||
}
|
||||
|
||||
let j = 0
|
||||
let segs = 0
|
||||
while (j < text.length && segs < MAX_SEGS) {
|
||||
while (j < text.length && (text[j] === SP || text[j] === TAB)) j++
|
||||
const a = j
|
||||
while (j < text.length && text[j] !== SP && text[j] !== TAB) j++
|
||||
if (j > a) {
|
||||
bar(a, j, y)
|
||||
segs++
|
||||
}
|
||||
}
|
||||
// Табуляція в canvas не має ширини — розгортаємо в пробіли, інакше
|
||||
// блоки JunOS з'їхали б до лівого краю й структура зникла саме
|
||||
// там, де вона найпомітніша.
|
||||
const flat = text.length > maxChars * 2 ? text.slice(0, maxChars * 2) : text
|
||||
ctx.fillText(flat.replace(/ /g, ' ').slice(0, maxChars), left, y)
|
||||
}
|
||||
|
||||
if (fits) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue