# vendor/draw-your-font — чужой движок, взятый целиком

**Откуда:** https://github.com/danilo-znamerovszkij/draw-your-font
**Лицензия:** MIT (файл `LICENSE` рядом — обязателен к сохранению, это условие лицензии).
**Зафиксированный коммит:** `bb9a64c472b59ba876e3a21828e2c7c084144f34` (2026-07-27, «☁️cf config fix»).
**Что делает:** фото рукописных знаков → адаптивная бинаризация → поиск связных компонент
(блобы) → векторизация potrace → раскладка глифов в общей em-сетке 1000 UPM → TTF/WOFF/WOFF2.

## Почему вендор, а не npm-зависимость

Движок нужен в ДВУХ местах и в РАЗНЫХ рантаймах: браузер (бесплатный инструмент на сайте,
0 ₽, файл не уезжает с телефона человека) и наш Node-контур (`render`-сервис по запросу
агентов). Оба конца обязаны считать ОДНИМ ядром — иначе агент проверяет одно, а человек
получает другое. npm-пакет собирается под Node (`sharp`, `potrace`-бинарь), браузерная ветка
у автора живёт отдельным файлом демо-сайта. Вендор фиксирует ровно тот код, который мы
бандлим и в браузер, и в сервер.

## Что МЫ здесь изменили (иначе — ничего не трогать)

Правило: чужой код держим как есть, свои надстройки живут в `travinov/src/font/*`.
Исключение — единственная правка ниже; она минимальна нарочно, чтобы её можно было
отдать в апстрим и чтобы обновление вендора было тривиальным.

| Файл | Правка | Зачем |
|---|---|---|
| `src/metrics.js` | `placeGlyph(..., opts)` принимает `opts.band` — явную вертикальную полосу глифа | Полосы у автора зашиты таблицей под латиницу+испанский. Кириллице нужна СВОЯ таблица (у «р», «у», «ф» нижний вынос, у «б» верхний). Без этого хука наш слой пришлось бы копировать сам шаг раскладки — то есть копировать КРАФТ движка, и первая же правка автора разошлась бы с нашей копией. Хук в 2 строки вместо копии в 20. |
| `src/capture.browser.js` | НОВЫЙ файл: браузерный порт `capture.js` на Canvas | У автора этот код лежит внутри UI-файла его демо-сайта (`site/demo.src.js`, строки 21–146) и не экспортируется. Мы вынесли его один-в-один в модуль, чтобы наша страница и `render` звали его как библиотеку, а не тащили чужой UI. Логика не изменена, кроме пункта 3. |
| `src/capture.browser.js` → `traceCrop` | берём ВСЕ `<path d="...">` из ответа potrace, а не первый | **Это баг апстрима, а не наша прихоть.** Node-обёртка potrace отдаёт один тег со всеми контурами, браузерный `esm-potrace-wasm` — несколько тегов, по одному на группу. Регулярка автора `/d="([^"]+)"/.exec()` берёт первый; если первым оказалась крошка, буква молча теряет всё остальное, а TTF остаётся валидным. Замер 2026-07-30 на нашем экзамене: «О» вышла полоской в 2 % кегля. Бьёт по любой многосоставной букве — «ё», «й», кавычки, буквы раздельными штрихами. Кандидат в апстрим-PR. |

Проверка, что вендор не «поплыл»: `node travinov/tools/font_exam.js` — НАШ экзамен, покрывает
и кириллицу, и латиницу, и оба профиля письма.

Тест автора (`e2e.js` рядом) в нашем дереве НЕ ЗАПУСКАЕТСЯ и запускаться не должен: он требует
`sharp` и potrace-бинарь для node-ветки, а серверная ветка у нас работает через тот же браузерный
бандл (см. `travinov/tools/font_build.js`). Файл оставлен как справка о том, что автор проверял;
ссылаться на него как на наш прибор нельзя — это было бы «написано, не проверено».

## Как обновлять вендор

1. `git clone` апстрим, сверить `src/*.js` с нашими файлами.
2. Перенести изменения, ЗАНОВО наложить ТРИ правки из таблицы выше (их легко потерять — именно
   поэтому таблица существует, а страж `test_vendor_license_and_patch_log_present` проверяет,
   что она не опустела).
3. Прогнать `node travinov/tools/font_exam.js` — зелёный по всем трём наборам (кириллица,
   профиль «от руки», латиница). Пересобрать бандл: `cd travinov && node build.js`.
4. Обновить зафиксированный коммит в этом файле.
