# AGENTS.md — hand-writter Руководство для агентов (и людей), работающих с репозиторием `hand-writter`. ## О проекте `handwrite.py` — CLI-утилита на Python, превращающая текст в картинку рукописного текста с **поддержкой кириллицы** (полный русский алфавит, включая `Ё`, `щ`, `ъ`, `э`, `ю`, `я`). Единственная зависимость — **Pillow** (`PIL`). Ключевые особенности: - Автоподбор рукописного шрифта из системы с проверкой покрытия кириллицы (без сторонних библиотек — только Pillow: рендер символа и сравнение с `notdef`-глифом). Приоритет: `Marker Felt`, затем `Snell Roundhand`, затем любой шрифт с кириллицей. - Синие чернила по умолчанию (`#1a3b8c`) с имитацией письма ручкой: коррелированный дрейф «давления» (тёмные/светлые участки), полупрозрачные чернила, неровный край мазка. - Выравнивание глифов — стандартное PIL ``text((x, line_top))`` (через маску в ``_stamp_glyph``). Все обычные буквы (а, о, н, б, й) стоят на одной baseline, буквы с нижними выносными (р, у, д, ц, щ) опускают хвосты ниже — строчная «р» ниже обычных букв, точки/запятые внизу, спецсимволы ($ ~ % @ …) — по дизайну шрифта. Не вводите ручное смещение «по ink_bottom» — оно ломает б/й/н и обрезает глифы. - Перенос по словам + сохранение `\n` из входного файла/STDIN. - Тетрадная «линейная» бумага (`--lined`), цвета чернил/бумаги/линий, синие палитры и градиенты оттенков. ## Структура ``` hand-writter/ ├── handwrite.py # основной скрипт (точка входа) ├── requirements.txt # Pillow>=9.0.0 ├── run.sh # обёртка-команды: init/upd/render/... ├── README.md # пользовательская документация ├── AGENTS.md # этот файл └── examples/ # примеры вывода ├── blue_pen.png ├── blue_pen_lined.png ├── multiline.png └── sample_input.txt ``` ## Окружение и запуск - Python 3.8+ (в `run.sh` предполагается `python3.13`; если его нет — отредактируйте `PY` в `run.sh` или используйте системный `python3`). - Активация venv: `source .venv/bin/activate` (через `./run.sh init`). - Прямой запуск: `python3 handwrite.py "Текст" -o out.png`. - Команды-обёртки: `./run.sh render "Текст"` и др. (см. ниже). ## Правила работы с кодом 1. **Не добавляйте новых зависимостей** без крайней необходимости. Скрипт намеренно зависит только от Pillow — это упрощает установку в изолированных средах. Любая новая зависимость должна быть обоснована и добавлена в `requirements.txt`. 2. **Сохраняйте поддержку кириллицы.** Любое изменение рендера/шрифтов должно проверяться на полном русском алфавите (см. `CYRILLIC_TEST` в `handwrite.py`). Не полагайтесь на «визуальную» проверку — шрифт может отрисовывать `notdef` для отсутствующих глифов; используйте `_font_covers_cyrillic()`. 3. **Выравнивание — стандартное PIL.** В ``_stamp_glyph`` глиф рисуется маской с origin в канвасе и композируется так, чтобы совпадать с ``text((x, line_top))``. НЕ прижимайте ink_bottom вручную к baseline и НЕ сдвигайте глифы по bbox — это ломает б/й (обрезает) и делает их «слишком низкими». Канвас берётся по абсолютным границам bbox (включая отрицательные bbox[0]/bbox[1] для Ё, р). Знаки препинания рисуются с jitter=0 (чёткие точки), но тем же выравниванием. 4. **Сохраняйте переносы строк.** `wrap_text` использует `splitlines()` — каждая строка входа становится отдельной строкой на картинке. Не «схлоптывайте» пустые строки без явного флага. 5. **Не ломайте CLI-совместимость.** Новые параметры добавляйте с значениями по умолчанию, не меняйте семантику существующих. 6. **Внесение изменений:** после правок проверяйте - `python3 -c "import ast; ast.parse(open('handwrite.py').read())"` — синтаксис; - запуск на кириллице с точками/запятыми и многострочным файлом; - что точки-знаки остаются в нижней зоне строки. ## Команды (run.sh) | Команда | Описание | |---|---| | `./run.sh init` | Создать venv и установить зависимости | | `./run.sh upd` | Обновить зависимости | | `./run.sh render "текст"` | Рендер текста-аргумента → `out/handwriting.png` | | `./run.sh lined "текст"` | Рендер на тетрадной бумаге | | `./run.sh big "текст"` | Крупный шрифт (64pt) на тёплой бумаге | | `./run.sh calm "текст"` | «Спокойный» почерк (jitter 0.3, seed 42) | | `./run.sh plain "текст"` | Ровный текст (без дрожания/поворота строк) | | `./run.sh render-file file.txt` | Рендер файла (с переносами строк) | | `./run.sh poetry file.txt` | Многострочный файл → тетрадь, крупный шрифт → `out/poetry.png` | | `./run.sh render-stdin` | Чтение из STDIN (echo "..." \| ./run.sh render-stdin) | | `./run.sh list-fonts` | Показать доступные рукописные шрифты с кириллицей | | `./run.sh examples` | Перегенерировать примеры в `examples/` | Все команды рендера (`render`, `lined`, `big`, `calm`, `plain`, `poetry`, `render-file`, `render-stdin`) принимают доп. опции `handwrite.py` после `--`, например: `./run.sh render "Текст" -- --jitter 0.4 --seed 7 --lined`. ## Тестовые сценарии (обязательно прогонять при правках) ```bash # кириллица с б/й/р, точками и спецсимволами (б/й на baseline, р ниже, точки внизу) python3 handwrite.py "байты йогурт река. \$ ~ % @ # конец!" -o /tmp/t1.png # многострочный файл (каждая строка файла → строка на картинке) printf 'Строка 1.\nСтрока 2.\nСтрока 3.\n' > /tmp/m.txt python3 handwrite.py -i /tmp/m.txt -o /tmp/t2.png --lined # синий (по умолчанию) + тетрадь python3 handwrite.py "Текст" --lined -o /tmp/t3.png ``` ## Чего не делать - Не коммитьте `.DS_Store`, `.venv/`, временные `*.png` вне `examples/`. - Не удаляйте `examples/` — это демонстрация возможностей. - Не «упрощайте» проверку глифов кириллицы до `textbbox`/ширины — это ненадёжно (узкие буквы, например «г», неотличимы от `notdef` по ширине). - Цвет чернил по умолчанию — синий. Палитры/градиенты намеренно убраны (раньше были, но усложняли). Не возвращайте мульти-цвет без явной просьбы.