* docs: polish localized documentation - Rewrite Russian documentation for natural terminology and current source parity\n- Continue the Polish editorial pass across guides and SDK references\n- Refresh shared localized SDK API data imports * docs(pl): complete editorial pass - Rewrite the remaining advanced Vue SDK references\n- Refresh the Figma compatibility matrix against the canonical source\n- Align terminology and behavior across every Polish documentation page * docs(de): complete editorial pass - Rewrite German guides, automation docs, and Vue SDK references\n- Restore current AI, export, component, and variable behavior\n- Refresh the Penpot comparison and Figma compatibility matrix * docs(es): complete editorial pass - Rewrite Spanish guides, automation docs, and Vue SDK references\n- Restore current AI, export, component, and variable behavior\n- Refresh the Penpot comparison and Figma compatibility matrix * docs(fr): complete editorial pass - Rewrite French guides, automation docs, and Vue SDK references\n- Restore current AI, export, component, and variable behavior\n- Refresh the Penpot comparison and Figma compatibility matrix * docs: correct localized terminology - Replace unnecessary English prose with natural localized terminology\n- Derive documentation aliases from named directory roots\n- Preserve English only for identifiers, APIs, and exact product terms * docs(it): continue editorial pass - Rewrite Italian user guides and automation documentation\n- Update Vue SDK composables and component references\n- Restore current AI, export, component, and variable behavior * docs(it): complete editorial pass - Finish Italian advanced SDK and reference documentation\n- Refresh the Penpot comparison and Figma compatibility matrix\n- Replace literal machine translations with natural technical prose * docs(pl): refine property panel terminology * docs: refine remaining localized prose - Replace overfitted English prose in Polish feature documentation\n- Rewrite the Russian property-list reference in natural terminology * docs(ru): rewrite Penpot comparison naturally - Replace remaining English prose with natural Russian\n- Preserve code identifiers and library names only where required * docs: rewrite localized feature overviews naturally - Replace avoidable English prose in German, Spanish, and French\n- Keep identifiers and product names unchanged * docs(de): refine property panel terminology * docs: refine Spanish and French SDK terminology * docs(ru): continue full prose audit - Rewrite homepage, setup, navigation, and guide index naturally\n- Restore missing zoom shortcuts * docs(ru): audit user and automation guides - Rewrite selection, collaboration, and automation prose naturally\n- Preserve API identifiers while localizing ordinary terminology * docs(ru): audit CLI inspection and analysis * docs(ru): audit Vue SDK overview and guides * docs(ru): audit Vue SDK API prose - Localize ordinary component and composable terminology\n- Preserve API symbols and code identifiers * docs(ru): audit advanced and gradient API references * docs(ru): finish advanced API prose audit * docs(ru): audit JSX renderer guide * docs(ru): audit CLI export and scripting guides * docs(pl): audit Penpot comparison prose * docs(pl): audit selection and automation guides * docs(pl): audit homepage and variable guides * docs(pl): audit vector, layers, and Pen guides * docs(pl): audit Auto layout and shape guides * docs(pl): audit context menu and export guides * docs(pl): audit JSX and analysis guides * docs(pl): audit AI Chat guide * docs(pl): audit components and CLI inspection * docs(pl): audit scripting and SDK overview prose * docs(pl): audit SDK API indexes * docs(pl): audit SDK component references * docs(pl): audit SDK composable references * docs(ru): refine usePosition terminology * docs(pl): audit advanced SDK references * docs(pl): audit Figma compatibility matrix * docs(pl): finish residual SDK terminology audit * docs(pl): finish component terminology audit * docs(pl): finish SDK guide terminology audit * docs(de): begin full user guide prose audit * docs(de): audit navigation, Pen, and layers guides * docs(de): audit Auto Layout, shapes, menu, and export * docs(de): audit components, text, and vector guides * docs(de): audit variables and automation overview * docs(de): audit AI Chat and collaboration guides * docs(de): audit CLI inspection, analysis, and export * docs(de): audit scripting and JSX guides * docs(de): audit Vue SDK overview and guides * docs(de): audit SDK API indexes * docs(de): audit SDK component references * docs(de): audit SDK composable references * docs(de): audit advanced SDK references * docs(de): audit Penpot comparison prose * docs(de): audit Figma compatibility reference * docs(es): begin full user guide prose audit * docs(es): audit document organization guides * docs(es): audit editing workflow guides * docs(es): audit automation and collaboration prose * docs(es): audit CLI inspection and export guides * docs(es): audit CLI scripting guide * docs(es): audit JSX and feature overview prose * docs(es): audit Penpot comparison prose * docs(es): audit SDK overview and guides * docs(es): begin SDK component reference audit * docs(es): audit SDK navigation component references * docs(es): audit SDK color and layout components * docs(es): begin SDK composable reference audit * docs(es): audit SDK property composable references * docs(es): audit SDK editor composable references * docs(es): begin advanced SDK reference audit * docs(es): audit advanced SDK state references * docs(es): complete advanced SDK reference audit * docs(es): audit Figma compatibility reference * docs(es): complete residual terminology sweep * docs(fr): begin full prose second audit * docs(fr): audit AI and variables prose * docs(fr): audit core user guide prose * docs(fr): audit editing workflow guides * docs(fr): audit CLI and JSX prose * docs(fr): audit Penpot comparison prose * docs(fr): audit SDK overview and guides * docs(fr): begin SDK API reference audit * docs(fr): audit SDK navigation component references * docs(fr): audit SDK color and layout components * docs(fr): begin SDK composable reference audit * docs(fr): audit SDK property composable references * docs(fr): audit editor composables and advanced APIs * docs(fr): audit advanced SDK state references * docs(fr): complete advanced SDK reference audit * docs(fr): audit Figma compatibility reference * docs(fr): complete residual terminology sweep * docs(it): begin full prose second audit * docs(it): audit document workflow guides * docs(it): audit editing and automation prose * docs(it): audit CLI and JSX prose * docs(it): audit Penpot comparison and SDK guides * docs(it): begin SDK API reference audit * docs(it): audit SDK component and state references * docs(it): audit residual SDK references * docs(it): audit Figma compatibility reference * docs(it): complete residual terminology sweep * docs(i18n): verify residual locale terminology
14 KiB
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: один клиентский процесс
┌─────────────────────────────────┐
│ Tauri native shell │
│ ┌───────────────────────────┐ │
│ │ Vue 3 + TypeScript │ │
│ │ Editor + Kiwi codec │ │
│ │ SceneGraph in TypeScript │ │
│ │ CanvasKit + Yoga WASM │ │
│ └───────────────────────────┘ │
└─────────────────────────────────┘
Редактор, SceneGraph, кодек файлов и отрисовка работают в одном процессе. Отдельные сервер, база данных и Docker не нужны. SceneGraph хранится как Map<string, SceneNode>. TypeScript напрямую вызывает CanvasKit, а Yoga WASM синхронно рассчитывает компоновку.
Penpot: клиент-серверная платформа
┌───────────────────────────────────────────────────────┐
│ 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
renderSceneToCanvas(canvas, graph, pageId) {
this.fillPaint.setColor(...)
canvas.drawRRect(rrect, this.fillPaint)
}
- Один прямой переход из TypeScript в WASM.
- SceneGraph остаётся в памяти JavaScript и не сериализуется перед отрисовкой.
- Код отрисовки занимает около 3 200 строк и разделён на специализированные модули.
Penpot: ClojureScript → Rust WASM → Skia
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 и модель данных
nodes: Map<string, SceneNode>
OpenPencil обеспечивает поиск по идентификатору за O(1), 29 типов объектов из схемы Kiwi, около 390 полей в NodeChange, строгие типы TypeScript и GUID в формате Figma sessionID:localID.
Penpot поддерживает собственные определения типов в Clojure/ClojureScript и Rust. Отдельные модули отвечают за цвета, компоненты, контейнеры, заливки, сетку, модификаторы, страницы и контуры. Malli проверяет схемы во время выполнения, а данные отрисовки пересекают границу CLJS → Rust.
5. Движок компоновки
OpenPencil синхронно использует Yoga WASM:
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
- Серверная совместная работа: учётные записи, контроль доступа и центральное хранение через WebSockets.
- Экспорт PDF: отдельный экспортёр Chromium.
- Система плагинов: изолированное выполнение и API плагинов.
- Токены дизайна: встроенная поддержка.
- CSS Grid: собственная реализация; OpenPencil использует ответвление Yoga с Grid.
- Самостоятельное размещение: развёртывание для команды через Docker.
- Зрелость: несколько лет эксплуатации.
11. Сценарии и расширяемость
Команда eval предоставляет совместимый с 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. Оба поддерживают совместную работу, но используют разные модели.