Я учел фидбек сообщества, открыл исходный код и сменил стек — теперь на Rust написано 99,6% всего кода, а от Tauri и Webview я полностью отказался. В статье расскажу, что внедрено и улучшено благодаря сообществу, а также какие проблемы возникли в процессе рефакторинга.

С прошлой частью, где подробно описан функционал, можно ознакомиться здесь.

Интерфейс заметочника Aquilum, написанного полностью на Rust
Интерфейс заметочника Aquilum, написанного полностью на Rust

Ссылка на репозиторий проекта и последние релизы.

В комментариях под прошлой статьей меня упрекнули за то, что на Rust у проекта написан только бэк-енд, а Tauri, на котором работал фронт-енд, нуждается в системном движке WebView — а это чревато дополнительным потреблением ОЗУ и багами на разных платформах.

Я глубже погрузился в тему и загорелся желанием переписать проект с нуля на Rust, чтобы философия минимального потребления ресурсов соблюдалась.

Переписывание приложения с Tauri на нативный UI на Rust заняло примерно 4–5 дней. В разработке мне помогали Claude Opus 5.5 и Gemini 3.8 Flash.

Оглавление

  1. Определение проекта

  2. Основные изменения по сравнению с прошлой версией 0.2.6

  3. Основные библиотеки проекта

  4. Как шел переход

  5. Ядро на Rust

  6. Почему растеризация на CPU, а не GPU

  7. Окно и кадры: что сделано поверх winit

    1. Такт кадров

    2. Вывод кадров

    3. Плавность скролла

    4. Простой

    5. Доступность

  8. Почему пришлось форкать движки

    1. Что изменено в vello_cpu и glifo

    2. Что изменено в masonry_core

    3. Что это дало

  9. Перерисовка только изменившегося

  10. Свой редактор

  11. Работа с памятью

  12. Свои читалка, граф и PDF

  13. Шрифты

  14. Что далось особенно тяжело

Короткое определение проекта:

Aquilum — локальная база знаний из обычных markdown-файлов: вики-ссылки, граф связей, таблицы, работа с данными, запросы по свойствам заметок, мгновенный поиск, читалка книг (EPUB, FB2, MOBI, AZW3), история версий, экспорт в PDF и MCP-сервер, через который с базой работают ИИ-агенты. Лицензия AGPL-3.0, Windows, macOS и Linux.

Основные изменения

В 0.3.0 убран WebView. Интерфейс, Markdown-редактор, граф, читалка книг и экспорт в PDF теперь написаны на Rust и растеризуются на процессоре.

Что это дало:

  • память — порядка 70 МБ вместо 650 МБ (сценарии замеров разные, это порядок величины);

  • прокрутка тяжёлой заметки — 120 кадров в секунду с запасом: кадр 3–5 мс при бюджете 8,3 мс;

  • заметка в 10 МБ — первый кадр через 131 мс вместо 8 секунд;

Таблица библиотек проекта одним взглядом

Ниже будут основные библиотеки, на которых работает приложение:

Слой

Библиотеки и своё

Окно и ввод

winit 0.31 (бета, версия зафиксирована), буфер обмена arboard, системные диалоги rfd

Виджеты

Masonry с главной ветки xilem (ревизия сентября 2026, новее последнего релиза 0.4.0); masonry_core — наш форк

Текст

parley 0.8 (раскладка и перенос строк), fontique (шрифты системы), harfrust (шейпинг, порт HarfBuzz), skrifa (чтение шрифтов), icu_segmenter (правила переносов), unicode-segmentation (графемы)

Растеризация

vello_cpu 0.3 и glifo (атлас глифов) — наши форки; геометрия kurbo, кисти peniko

Вывод кадра

Windows: цепочка DXGI на WARP (крейт windows); macOS и Linux: softbuffer

Доступность

AccessKit для Windows, macOS и Linux

Файлы и документы

атомарная запись atomic-write-file, наблюдение за папкой notify, обход базы walkdir, отпечатки файлов blake3, CRDT yrs (см. ниже)

Хранилище

rusqlite (SQLite встроен в бинарник)

Поиск

полнотекстовый индекс tantivy 0.26, стемминг rust-stemmers; свои BM25F и Adamic-Adar для похожих заметок и графа

Markdown

pulldown-cmark; свой построчный разбор для живого превью

Картинки

png, jpeg-decoder, image (WebP, GIF, BMP); своё уменьшение под размер показа прямо при декодировании

Граф

раскладка в ядре, свой растеризатор полосами на rayon

Читалка книг

ZIP на flate2, XML на roxmltree; свои порты CFI и FB2, переносы Лианга

PDF

krilla (векторный PDF с выделяемым текстом)

Видео

системные API: Media Foundation и WASAPI (Windows), AVFoundation (macOS), GStreamer (Linux)

Сеть и MCP

HTTP-клиент ureq (TLS через rustls); свой HTTP-сервер MCP на httparse

Обновления

проверка подписи minisign-verify, распаковка flate2, свой разбор tar

Упаковка

cargo-packager (NSIS, .app, DMG, AppImage), nfpm (deb, rpm)

Полный список крейтов с версиями — в Cargo.toml ядра и нативной части в репозитории.

Как шёл переход

Всё сразу не переписывалось, переход шёл по шагам.

Сначала всё, кроме интерфейса, ушло из WebView и из Tauri. Документ, который жил в браузерной части (Yjs и IndexedDB), ещё в Tauri-версии переехал в Rust на yrs. Затем вся логика — документы, файлы, поиск, история, настройки, MCP — собрана в отдельную библиотеку aquilum-core, которая не зависит ни от Tauri, ни от WebView: интерфейс вызывает её напрямую, без команд Tauri, а события получает через EventSink. Новому окну всё это досталось готовым.

Потом — пробное окно. На одном макете (боковая панель, вкладки, колонка текста; окно 2881×1717 при масштабе 175 %) сравнивались своё окно на winit и vello_cpu и Freya — готовый фреймворк интерфейса на Rust. Условие было поставлено заранее: если пустое окно займёт 150 МБ и больше, переход теряет смысл.

Вариант

Память (рабочий набор)

Процессор в простое

своё окно, vello_cpu в 1 поток

59 МБ

0 %

Freya, рисует процессор

45 МБ

0,3 %

Freya, рисует видеокарта (OpenGL)

139 МБ

0 %

Отрисовка на видеокарте подошла к порогу вплотную, на процессоре окно заняло втрое меньше. Отсюда первое решение: кадр рисует процессор.

Второе — библиотека виджетов. Выбрана Masonry: её ядро masonry_core само окно не создаёт, а принимает события и отдаёт, что нарисовать, и дерево для скринридеров. Окно, ввод и вывод на экран остаются своими. Freya на процессоре была даже легче, но у неё своё окно на winit 0.30 без нового API для IME из версии 0.31, текст на Skia вместо parley и бинарник 22,7 МБ против 5 МБ.

Ядро на Rust

Ядро — отдельная библиотека без интерфейса: файлы, история, поиск, MCP. Окно только показывает то, что оно отдаёт.

Все записи заметок идут через одну функцию. Она проверяет по хешу, не изменили ли файл снаружи с момента чтения, записывает его атомарно (на диске либо целиком новый файл, либо старый), сохраняет версию в историю и обновляет поиск. Так пишут и редактор, и MCP-агент.

Если заметку изменили снаружи, а несохранённых правок нет, она сразу перечитывается; свою же запись приложение узнаёт по хешу. Если в этот момент идёт набор, текст не затирается: при записи сработает проверка хеша, ваш вариант сохранится копией рядом, а редактор покажет версию с диска и скажет об этом. Для отката и восстановления версий используется трёхстороннее слияние текста — перенесено с TypeScript вместе с тестами, включая 400 случайных прогонов.

yrs (CRDT) в ядре остался и покрыт тестами, но в живом пути окна сейчас не используется: редактор правит свой текст, а запись идёт через ту же функцию.

Наблюдатель за папкой базы сразу показывает новые и изменённые файлы. В 0.3.4 тут была критичная ошибка: события приходили с путём в особой «расширенной» форме Windows и не совпадали с путём открытой заметки.

Данные лежат в SQLite, встроенном в программу: состояние интерфейса (вкладки, каретка, прокрутка), копии документов и данные поиска (отпечатки файлов, граф ссылок, поля свойств).

Полнотекстовый поиск — tantivy со стеммингом. Ему урезан аппетит: индексу дано 2 потока и 40 МБ памяти вместо 256 МБ на все ядра (пик индексации доходил до 641 МБ), а кэш хранилища уменьшен со 100 блоков до двух.

Поверх индекса — свои алгоритмы: «похожие заметки» по тексту считаются по BM25F, «связанные» по графу — мерой Adamic-Adar. Граф строится из таблиц SQLite, раскладку считает ядро. Блоки dataview выполняют запросы по свойствам заметок.

MCP-сервер работает внутри приложения, только на 127.0.0.1 и только с токеном. Внутри — потому что приложение единственный владелец поискового индекса. Агент ищет, читает и правит заметки (через ту же функцию записи), ходит по ссылкам и версиям истории.

Сеть нужна для трёх вещей: источники из Википедии для заметки, заголовки вставленных ссылок и проверка обновлений.

Тесты: 626 в ядре и 373 в нативной части, на Windows, macOS и Linux.

Почему растеризация на CPU, а не GPU

Видеокарта стоит памяти, даже если она только показывает готовый кадр: её драйвер загружается в процесс приложения. Драйвер AMD занимал около 85 МБ — больше, чем всё приложение без него. Поэтому кадр рисует процессор, а на Windows его выводит WARP — программная реализация Direct3D от Microsoft, которой драйвер не нужен.

Цена — время процессора: на тяжёлой заметке кадр занимает 3–5 мс из 8,3 мс, отведённых на кадр при 120 Гц (Ryzen 9 8945HS). Кроме того, на пути через WARP изредка повторяются кадры, подробнее об этом в Плавности скролла. Зато код рисования один на всех трёх ОС.

Честно говоря, мне хотелось попробовать именно программную растеризацию: заметкам видеокарта почти не нужна.

Окно и кадры: что сделано поверх winit

Такт кадров

Кадр привязан к вертикальной синхронизации: отдельный поток ждёт IDXGIOutput::WaitForVBlank (как VSyncThreadWin в Chromium) и будит цикл событий, кадр рисуется один раз за такт. При выключенном мониторе WaitForVBlank возвращается сразу, поэтому такт ограничен периодом обновления, иначе выходило 200–300 кадров в секунду. Пропуски кадров считаются по GetFrameStatistics после каждого Present.

Вывод кадров

На Windows — цепочка DXGI с flip-моделью и тремя буферами. Процессор растрирует только изменённые области, и Present1 передаёт их списком. На macOS и Linux — softbuffer.

Плавность скролла

Больше всего времени я потратил на плавность прокрутки, и каждое изменение начиналось с замера. Колесо — порт кривой Безье из Firefox, тачпад — DirectManipulation со своей инерцией.

Итог на тяжёлой заметке при 120 Гц: работа кадра 20 → 3,6–5,4 мс, 49 → 115–120 кадров в секунду. Рывки колеса по метрике PredictorJank из Chromium сократились с 25,9 % кадров до нуля.

Мелкие рывки всё же остались, и эта проблема пока не решена. На пути WARP → DWM 1–6 % кадров показываются по два такта, а следующий сливается с ещё одним: прокрутка на мгновение замирает и догоняет скачком.

Сильнее всего это заметно на малой скорости, в хвосте затухания после тачпада. Кадр аквилума тут ни при чём: он готов через 2–3 мс после такта, а DWM не сообщает о пропущенных или опоздавших кадрах. Где именно теряется кадр, пока не выяснено.

С аппаратным драйвером повторов почти нет — 0–2 на 480 кадров против 10–50 у WARP. Но драйвер добавляет около 85 МБ памяти, и пока выбор сделан в пользу памяти. Дальше стоит попробовать передавать сдвиг прокрутки прямо в Present1 (pScrollRect) и выводить кадр через DirectComposition.

Простой

Кадры рисуются только по запросу. Каретка мигает по таймеру: 2 пробуждения в секунду вместо 120. Даже пустое пробуждение стоит около 0,27 мс процессора, так что кадр на каждый такт 120 Гц — это 30 мс в секунду впустую.

Доступность

AccessKit строит дерево для экранных дикторов, на Windows через UI Automation. Адаптеры для macOS и Linux подключены, но вручную проверена пока только Windows.

Почему пришлось форкать движки

Готовые библиотеки не давали трёх вещей:

  1. В выпущенной Masonry нет рендера на процессоре, он есть только в основной ветке xilem, а последний релиз Masonry 0.4.0 вышел в октябре 2025. Поэтому взята основная ветка с зафиксированной ревизией. Её готовый хост окна masonry_winit рассчитан только на видеокарту и старый winit 0.30, так что из Masonry взято только ядро masonry_core, а хост окна написан свой.

  2. Эмодзи ломались при масштабе экрана — штатный адаптер imaging_vello_cpu не учитывал масштаб для цветных глифов: при 175 % эмодзи рисовался как при 100 % и оставлял следы при прокрутке. Исправленной версии не было, поэтому адаптер написан свой. Заодно он дал то, чего не хватало: перерисовку только изменившихся областей, вывод прямо в буфер окна и многопоточность.

  3. Masonry перерисовывает всё окно на каждом кадре — при вводе текста это около 14 мс на кадр в 5 Мп — почти весь бюджет кадра при 60 Гц (16 мс). Для 120 Гц нужно укладываться в 8,3 мс и ничего не делать в простое.

Форк vello_cpu сделан от последнего релиза 0.3.0 (2 октября 2026). Новых релизов нет, поэтому полезные правки из основной ветки переносятся по одной: уже перенесены ускорение отрисовки картинок и глифов (PR #1961) и прямоугольные клипы.

Что изменено в vello_cpu и glifo

  • Новый глиф дорисовывается только в своём месте атласа. Раньше ради одного символа в одном потоке перерисовывалась вся страница атласа 4096×4096 — это и было главной причиной подтормаживаний.

  • Страница 512×512 вместо 4096×4096 (64 МБ), страниц не больше восьми, пустые освобождаются, кэши глифов чистятся раз в 30 секунд. Память (рабочий набор) на этом шаге: 145 → 84 МБ.

  • Кадр рисуется сразу в память окна — без промежуточной копии, минус 19 МБ на всех ОС.

  • Исправлена ошибка цвета в форке. В формате окна (BGRA) красный и синий менялись местами при записи, но не при чтении. В обычных кадрах ошибка не проявлялась, потому что кадр всегда начинается с непрозрачного фона.

  • На тестовом процессоре с AVX-512 старый набор SSE4.2 оказался в 1,6–2 раза быстрее AVX-512, поэтому используется SSE4.2.

  • Один набор шрифтовых библиотек с parley (skrifa 0.40). Только экспорт в PDF пока тянет второй — до обновления parley.

  • Убрано лишнее: второй конвейер растеризации на f32, отладочный текст, неиспользуемые возможности.

Что изменено в masonry_core

  • В кадр попадает только видимое, в то время как раньше на каждом кадре в сцену копировались все 2400 строк документа.

  • Смена темы без пересборки окна (RenderRoot::restyle). Цвета и шрифты пересчитываются на месте, как в браузере. Смена цвета — около 2 мс вместо 15 мс плюс полной перерисовки, окно настроек больше не закрывается и не открывается заново.

  • Прокрутка без ступенек при масштабе 175 %. Masonry округлял сдвиг прокрутки до целых пикселей, и текст двигался рывками. Теперь сдвиг не округляется и привязывается к физическим пикселям экрана.

  • Профилировщик aq_trace: Метки во всех этапах кадра Masonry и растеризатора, трасса открывается в Perfetto. Без него оптимизировать пришлось бы вслепую.

  • Убраны лишние зависимости: tracing-subscriber и time.

Что это дало

Вместе с работой над циклом кадра это подняло прокрутку тяжёлой заметки с 10 до 115–120 кадров в секунду, а удаление символа в большой заметке ускорилось с 81 до 1 мс (заметка 141 КБ, масштаб 175 %, 120 Гц, Ryzen 9 8945HS).

Перерисовка только изменившегося

Masonry на каждом кадре перерисовывает окно целиком. Поверх этого сделан механизм, как в браузерах: перерисовывается только то, что изменилось, остальное берётся из прошлого кадра.

  • Для каждой команды рисования считается отпечаток и её прямоугольник на экране. Сравнение с прошлым кадром даёт до четырёх изменившихся прямоугольников: только они растрируются и только они уходят в окно. Тест попиксельно сравнивает такой частичный кадр с полной перерисовкой.

  • Мигание каретки перерисовывает только её место: кадр 1,2 мс вместо 16,9, процессор 1,8 %. Строка текста сравнивается кусками по 48 пикселей, поэтому раскрытие разметки рядом с кареткой не перерисовывает всю строку (так же сделано в Chromium и Firefox).

  • Уже нарисованные пиксели сдвигаются копированием, растрируется только открывшаяся полоса: кадр прокрутки 3,2 → 1,9 мс. Края областей округляются до целых пикселей экрана, иначе при масштабе 175 % сдвиг не срабатывал.

  • Ползунок прокрутки — отдельная картинка поверх готового кадра: его появление и движение ничего не растрируют.

  • Анимированные обложки рисуются отдельным слоем поверх кэшированного кадра, без пересборки сцены Masonry. Узор считается своим кодом прямо в пиксели, 0,05–0,5 мс на кадр. Процессор в простое на заметке с такой обложкой: 1,7 → 0,33 ядра.

  • Карточка модального окна растрируется один раз, дальше готовая картинка сдвигается и проявляется, как opacity и transform в браузере: кадр 3–4,5 мс вместо 10–14.

  • Узоры обложек запекаются одной плиткой — узор повторяется, поэтому находится его период по каждой оси и запекается одна ячейка: 32 узора за 1 с вместо 7,9 с, кэш узора — сотни килобайт вместо 4,2 МБ.

  • Во время root.redraw() виджеты просили ещё один кадр, и анимации рисовались вдвое чаще, чем менялись. Такие запросы теперь отбрасываются.

Чтобы видеть, что именно перерисовывается, сделана подсветка перерисовки (paint flashing, как в Chrome DevTools). С ней я находил и недорисованные области, и избыточную перерисовку.

Например, раньше при скролле перерисовывалась вся ширина редактора, а после внедрения подсветки только контентная часть.

Подсветка перерисовки в отладочной сборке (F12) в Aquilum
Подсветка перерисовки в отладочной сборке (F12) в Aquilum

Красным вспыхивают области, которые растеризатор перерисовал в этом кадре, фиолетовым — анимированная обложка.

Рамки: зелёная — область прокрутки, синяя — сдвиг пикселей при прокрутке, жёлтая — слой анимированной обложки, голубая — ползунок полосы прокрутки, который накладывается на готовый кадр без перерисовки страницы.

Свой редактор

Стандартное поле TextArea из Masonry на каждую букву заново раскладывает весь текст — около 15 мс на заметке в 141 КБ. Живому превью Markdown нужно больше: прятать разметку, пока в строке нет каретки, показывать таблицы и встроенные блоки. Поэтому редактор написан свой: текст раскладывается по абзацам через parley, разбор Markdown общий с ядром, а каретка и Backspace шагают по целым символам, включая эмодзи и буквы с ударением.

Свой редактор MarkDown в заметочнике Aquilum
Свой редактор MarkDown в заметочнике Aquilum

Приёмы взяты из CodeMirror 6 и VS Code, по их исходникам:

  • Текст раскладывается на экран выше и ниже видимой части, для остального хранится только высота. Полная раскладка занимала около 40 байт на байт текста: заметка в 10 МБ съедала 931 МБ, теперь всё приложение с ней укладывается в 107 МБ.

  • Высота дальних строк оценивается по числу символов, а место прокрутки привязано к позиции в тексте, как в CodeMirror 6, поэтому прокрутка не прыгает, когда оценка сменяется точной высотой.

  • Разбирается только изменённое, как в VS Code. Для каждой строки запоминается состояние разбора в её конце. После правки разбор идёт с места правки и останавливается, как только состояние совпало с прежним. Проходов по всему документу на нажатие было пять, стало ноль.

  • Одна точка правки, как транзакции CodeMirror. Любое изменение — ввод, нумерация списка, правка таблицы — это список «где заменить → на что». Через эту точку пересчитываются каретка, курсоры и история отмены, и только этот список уходит в приложение. Раньше каждое нажатие копировало текст трижды.

  • Абзац в памяти: 320 → 112 байт. При 461 тысяче абзацев каждые 100 байт — это 46 МБ.

На заметке в 10 МБ: первый кадр — 131 мс вместо 8 с, куча — 82–85 МБ вместо 194, нажатие клавиши — меньше 1 мс вместо 50.

Каждая оптимизация закреплена тестом, который сравнивает быстрый путь с медленным, например частичный разбор с полным. Чтобы проверить сам тест, условие временно ломается: тест обязан упасть.

Память

Цель — 50–60 МБ частной памяти: без этого приложение не выпускалось.

Потребление памяти у Aquilum наравне с другими приложениями в диспетчере задач Windows
Потребление памяти у Aquilum наравне с другими приложениями в диспетчере задач Windows

Что дало больше всего:

  • Картинки держатся, пока видны — кэш помнит картинку, пока она на экране, и ещё последние 8 МБ — как в Chromium. Раньше после закрытия всех вкладок в памяти оставалось около 80 МБ пикселей, теперь ноль.

  • Картинки декодируются сразу в нужном размере. PNG уменьшается строка за строкой, JPEG — внутри самого декодера, полноразмерная копия не создаётся.
    Фото на 12 Мп: 49 → 18 МБ.

  • Свёрнутое окно отдаёт память: буферы кадра, слои, недавние картинки. Раньше оно держало десятки мегабайт, ничего не показывая.

  • Вывод через WARP вместо драйвера видеокарты — минус около 85 МБ.

  • Граф выгружается вместе со своей вкладкой, а раньше закрытый граф держал до четырёх кадров по 20 МБ.

  • Поиску задан бюджет памяти (см. «Ядро на Rust»).

Свои читалка, граф и PDF

Читалка открывает EPUB, FB2, MOBI и AZW3 без браузера: книга распаковывается, разбирается и раскладывается на страницы внутри приложения. Места чтения записываются в том же формате, что у прежней версии (EPUB CFI, перенесён из foliate-js), поэтому старые закладки работают.

Читалка в заметочнике Aquilum
Читалка в заметочнике Aquilum

Граф раскладывает ядро, а рисует окно своим растеризатором: картинка делится на полосы, и полосы рисуются параллельно на всех ядрах процессора. Если, пока граф двигается, кадр выходит дольше 12 мс, граф временно рисуется в половинном разрешении.

Граф в заметочнике Aquilum с настройками
Граф в заметочнике Aquilum с настройками

PDF раньше печатал браузер: на macOS без установленного принтера получался пустой лист, на Linux открывалось окно печати. Теперь PDF записывается напрямую через библиотеку krilla: текст векторный и выделяется, принтер и браузер не нужны ни на одной ОС.

Цена — две копии библиотеки, которая читает файлы шрифтов: krilla требует новую версию, а библиотека вёрстки текста parley пока работает со старой. Вторая копия уйдёт, когда parley обновится.

Видео играет через системные средства: Media Foundation и WASAPI на Windows, AVFoundation на macOS, GStreamer на Linux. На Linux программе нужны только GStreamer, GLib, fontconfig и FreeType, а ещё X11 или Wayland, которые есть в любой системе. GTK и WebKitGTK больше не нужны.

Шрифты

В приложении три семейства: iA Writer Mono, iA Writer Quattro и Inter, каждое в прямом начертании и курсиве. В репозитории они хранятся в сжатом формате WOFF2 — 8 файлов, около 330 КБ. Библиотека шрифтов такой формат не читает, поэтому при сборке файлы распаковываются в обычный TTF.

Кириллица Inter лежит в отдельном файле с тем же именем семейства, а из двух одноимённых шрифтов библиотека берёт один — кириллица ушла бы в системный шрифт. Поэтому при сборке кириллическая часть переименовывается в «Inter Cyrillic» и подключается следом за Inter.

В настройках можно выбрать любой шрифт, установленный в системе: список читается при открытии настроек и нигде не хранится.

Что далось тяжело

Не всё прошло гладко, и часть проблем осталась.

  • На плавность прокрутки ушло больше всего времени, и мелкие рывки всё равно остались: на пути от программного вывода WARP к композитору Windows 1–6 % кадров показываются дважды, и прокрутка на мгновение замирает. С драйвером видеокарты повторов почти нет, но он стоит около 85 МБ памяти, и пока выбрана память. Проблема не решена.

  • Релиза Masonry с нужным рендером нет, поэтому обновления приходится забирать вручную и сразу пачкой.

  • В репозитории живёт 31 тысяча строк чужого кода, и исправления из оригиналов приходится переносить по одному.

  • Две копии библиотеки чтения шрифтов (для PDF и для окна) и библиотека SVG, которую Masonry подключает всегда, хотя его виджет SVG не используется. На память это не влияет, только на размер программы.

  • Японский перенос строк не работает: библиотеке вёрстки нужен словарь для разбиения японского текста на слова, а его нет.

Данные пользователей мы не трогали: тот же каталог, те же форматы файлов и баз, тот же ключ подписи. Откат на 0.2.6 безопасен.

Заключение

Спасибо огромное всем тем, кто подсказал, куда можно двигаться проекту, а также отдельное спасибо тем, кто оставлял пул реквесты и исправления — почти все их я уже включил в последнюю версию Aquilum!

Предложить новую механику можно мне в личку в телеграм, но лучше делать это через pul requests или issues в репозитории.

В этой статье не затронуты аспекты UI и UX, которых было не меньше, чем технических нововведений, поэтому им будет отведена отдельная статья.

Что дальше:

  • убрать повторы кадров на пути WARP → DWM: передавать сдвиг прокрутки прямо в Present1 и попробовать вывод через DirectComposition;

  • верстать огромные главы книг по частям, чтобы FB2 из одной главы открывался так же быстро, как EPUB;

  • обновить parley и избавиться от второй копии библиотеки шрифтов;

  • заменить системное окно на Mac на нативную версию Aquilum.