# OpenPencil и Penpot: архитектура и производительность OpenPencil и Penpot — открытые инструменты дизайна с разными задачами и архитектурой. ::: info WASM-рендерер Penpot Penpot 2.x включает Rust/Skia WASM-рендерер `render-wasm/v1`, который включается параметрами сервера или `?wasm=true`. По умолчанию по-прежнему используется SVG-рендерер. Ниже рассматриваются оба варианта. ::: ## 1. Размер кодовой базы | Показатель | OpenPencil | Penpot | |------------|------------|--------| | Строк кода | **около 26 000** | **около 299 000** | | Исходных файлов | около 143 | около 2 900 | | Языки | TypeScript, Vue | Clojure, ClojureScript, Rust, JavaScript, SQL, SCSS | | Код отрисовки | около 3 200 строк, TypeScript | 22 000 строк, Rust/Skia WASM | | Интерфейс | около 4 500 строк | около 175 000 строк, CLJS и SCSS | | Серверная часть | Нет, локальная архитектура | 32 600 строк и 151 файл SQL | | Соотношение | **1×** | **около 11×** | OpenPencil примерно в 11 раз меньше. Это следствие другой архитектуры, а не только меньшего набора возможностей. ## 2. Архитектура ### OpenPencil: один клиентский процесс ```text ┌─────────────────────────────────┐ │ Tauri native shell │ │ ┌───────────────────────────┐ │ │ │ Vue 3 + TypeScript │ │ │ │ Editor + Kiwi codec │ │ │ │ SceneGraph in TypeScript │ │ │ │ CanvasKit + Yoga WASM │ │ │ └───────────────────────────┘ │ └─────────────────────────────────┘ ``` Редактор, SceneGraph, кодек файлов и отрисовка работают в одном процессе. Отдельные сервер, база данных и Docker не нужны. SceneGraph хранится как `Map`. TypeScript напрямую вызывает CanvasKit, а Yoga WASM синхронно рассчитывает компоновку. ### Penpot: клиент-серверная платформа ```text ┌───────────────────────────────────────────────────────┐ │ Docker Compose │ │ ClojureScript frontend │ Clojure/JVM backend │ │ Rust/Skia WASM │ PostgreSQL, Valkey, MinIO │ │ Chromium exporter │ MCP server │ └───────────────────────────────────────────────────────┘ ``` Для полной установки Penpot нужны интерфейс, серверная часть JVM, PostgreSQL, Valkey, MinIO и экспортёр на основе Chromium без интерфейса. Среда разработки требует Docker Compose, JVM, Node и инструменты Rust. OpenPencil избегает сетевой задержки, сериализации между службами, управления контейнерами и запросов к базе данных для обычных операций. Penpot рассчитан на многопользовательскую платформу с серверным размещением, а OpenPencil — на локальную работу с минимальной задержкой. ## 3. Конвейер отрисовки ### OpenPencil: TypeScript → CanvasKit WASM ```typescript renderSceneToCanvas(canvas, graph, pageId) { this.fillPaint.setColor(...) canvas.drawRRect(rrect, this.fillPaint) } ``` - Один прямой переход из TypeScript в WASM. - SceneGraph остаётся в памяти JavaScript и не сериализуется перед отрисовкой. - Код отрисовки занимает около 3 200 строк и разделён на специализированные модули. ### Penpot: ClojureScript → Rust WASM → Skia ```text ClojureScript → JavaScript → разложение и бинарная упаковка в память WASM → Rust WASM через Emscripten C FFI → skia-safe → Skia/WebGL ``` Без WASM каждая фигура отображается как элемент SVG DOM через React/Reagent. В режиме WASM UUID разбивается на четыре `u32`, преобразование — на шесть `f32`, заливки и обводки кодируются в двоичном виде, а основные свойства фигуры занимают структуру размером 104 байта. Система использует кеш плиток, области интереса, 11 поверхностей отрисовки и глобальное изменяемое состояние через `unsafe { STATE.as_mut() }`. Кеш может хранить до 1024 текстур. OpenPencil перерисовывает видимую область целиком. | Аспект | OpenPencil | Penpot | |--------|------------|--------| | JavaScript → WASM | Прямые вызовы с объектами TypeScript | Двоичные структуры | | Модель | Полная отрисовка видимой области | Кеш плиток | | Поверхности | 1 | 11 | | Дополнительный кеш | Нет | До 1024 плиток | | Размер кода отрисовки | около 3 200 строк | 22 000 строк | | Небезопасный код | Нет | Глобальное состояние через `unsafe` | Прямой путь CanvasKit требует меньше промежуточной обработки для небольших и средних документов. Кеш Penpot может быть выгоднее для документов со 100 000 и более фигур, когда видна лишь малая часть холста. ## 4. SceneGraph и модель данных ```typescript nodes: Map ``` OpenPencil обеспечивает поиск по идентификатору за O(1), 29 типов объектов из схемы Kiwi, около 390 полей в `NodeChange`, строгие типы TypeScript и GUID в формате Figma `sessionID:localID`. Penpot поддерживает собственные определения типов в Clojure/ClojureScript и Rust. Отдельные модули отвечают за цвета, компоненты, контейнеры, заливки, сетку, модификаторы, страницы и контуры. Malli проверяет схемы во время выполнения, а данные отрисовки пересекают границу CLJS → Rust. ## 5. Движок компоновки OpenPencil синхронно использует Yoga WASM: ```typescript const root = Yoga.Node.create() root.setFlexDirection(FlexDirection.Row) root.calculateLayout() ``` Penpot поддерживает собственные реализации Flex и Grid в ClojureScript и Rust WASM. Оба движка должны выдавать одинаковый результат. OpenPencil использует Yoga, включая ответвление с поддержкой Grid; Penpot поддерживает несколько тысяч строк собственного кода компоновки на двух языках. ## 6. Форматы и Figma OpenPencil использует бинарный формат Kiwi Figma, напрямую импортирует `.fig`, читает данные Kiwi из буфера обмена и совместим с многопользовательским протоколом Figma. Файл `.penpot` — ZIP-архив с манифестами JSON, данными документа, бинарными ресурсами и миниатюрами. Penpot не импортирует `.fig` напрямую и поддерживает несколько поколений формата через систему миграций. ## 7. Состояние и отмена OpenPencil использует обратные команды: функции применения и отмены сохраняют только необходимое состояние, а несколько операций можно объединить. Penpot использует Potok. `UpdateEvent` меняет состояние, `WatchEvent` выполняет побочные эффекты через RxJS, а история хранит обратные наборы изменений, ограничивается 50 записями и объединяет быстрые изменения в транзакции. ## 8. Разработка | Показатель | OpenPencil | Penpot | |------------|------------|--------| | Подготовка | `bun install && bun dev` | Docker Compose, JVM, Node и Rust | | Быстрое обновление | Vite | shadow-cljs | | Типы | Строгий TypeScript | Схемы Malli во время выполнения | | Настольная версия | Tauri v2 | Браузер | | Основные технологии | TypeScript и Vue | Clojure, ClojureScript, Rust и Docker | ## 9. Производительность | Сценарий | OpenPencil | Penpot | |----------|------------|--------| | Холодный запуск | менее 2 секунд с WASM | более 10 секунд для сервера, клиента и WASM | | Обычная операция | Внутри одного процесса | Возможен сетевой обмен | | Кадр | Прямой вызов Skia | CLJS → JS → WASM FFI → Skia | | Базовая память | около 50 МБ во вкладке браузера | JVM, база данных, кеш и браузер | | Работа без сети | Полная | Требует сервера | | 10 000 фигур | Один проход | Плиточная отрисовка с 11 поверхностями | ## 10. Преимущества Penpot 1. **Серверная совместная работа:** учётные записи, контроль доступа и центральное хранение через WebSockets. 2. **Экспорт PDF:** отдельный экспортёр Chromium. 3. **Система плагинов:** изолированное выполнение и API плагинов. 4. **Токены дизайна:** встроенная поддержка. 5. **CSS Grid:** собственная реализация; OpenPencil использует ответвление Yoga с Grid. 6. **Самостоятельное размещение:** развёртывание для команды через Docker. 7. **Зрелость:** несколько лет эксплуатации. ## 11. Сценарии и расширяемость Команда [`eval`](/programmable/cli/scripting) предоставляет совместимый с Figma Plugin API для сценариев без интерфейса, пакетных операций и автоматизированных тестов. Чат с ИИ, сервер MCP и CLI также предлагают 90 инструментов для чтения, создания, изменения, работы со структурой, переменными, векторными контурами, анализа, сравнения, логических операций и расположения. Penpot предлагает изолированные плагины, но не имеет сопоставимого API для сценариев без интерфейса или интеграции MCP. ## Итоги | Область | Преимущество | Причина | |---------|--------------|---------| | Простота | OpenPencil | Один процесс вместо нескольких служб | | Отрисовка | OpenPencil | Прямой путь CanvasKit | | Кодовая база | OpenPencil | Около 26 000 против 299 000 строк | | Совместимость с Figma | OpenPencil | Нативные Kiwi и `.fig` | | Разработка | OpenPencil | TypeScript и Vue вместо Clojure, Rust и Docker | | Настольное приложение | OpenPencil | Tauri | | Компоновка | OpenPencil | Yoga вместо двух собственных реализаций | | Совместная работа | Разные преимущества | Penpot: сервер и контроль доступа; OpenPencil: P2P без размещения | | Самостоятельное размещение | Penpot | Развёртывание Docker | | Зрелость | Penpot | Многолетняя эксплуатация | OpenPencil — компактный редактор в одном процессе с CanvasKit и нативной поддержкой `.fig`. Penpot — полная клиент-серверная платформа на Clojure, ClojureScript, Rust, базах данных и службах Docker. Оба поддерживают совместную работу, но используют разные модели.