План: ядро MOffice на собственном коде
Решение владельца, 2026-10-04: «У нас должен быть свой полностью код, не используя чужие лицензионные решения — лучше их копировать на свой лад и своим кодом, так как это будет коммерческий продукт». Документ — план сессии A по ядру (
kernel/); зона B (оболочка, сервисы,meridian-crypto) — в её журнале.
1. Правило
- В продукт попадает только наш код. Чужой проект — образец алгоритма (читаем, понимаем, пишем заново своими структурами и своими тестами), но не копия, не форк и не зависимость.
- Опираемся на открытые спецификации: ISO 32000 (PDF), ECMA-376 (OOXML), OpenType, Unicode (UAX #9, #14, #29), RFC 1950/1951 (zlib/DEFLATE), PNG, JPEG (ITU T.81), Hunspell-формат словарей. Спецификация — не чужой код.
- Каждая замена приходит со сверкой: старая реализация (пока она есть) или эталон служат оракулом в тестах, пока наша не совпадёт на корпусе; после этого зависимость удаляется.
- Данные — отдельно от кода: таблицы Юникода (UCD), шрифты комплекта (Liberation, Carlito — OFL), словари (ru_RU — BSD, en_US — SCOWL), шаблоны переносов (hyph-utf8). Код для них пишем свой; судьба самих данных — решение владельца (раздел 4).
- Инструменты разработки вне продукта (
tools/corpus-tool,tools/lab-site, спайки,cargo-fuzz) правило не затрагивает, но и там новые вещи пишем сами, где это дёшево.
2. Что сейчас чужое в ядре (2026-10-04)
| Где | Что | Объём / вид | Замена |
|---|---|---|---|
meridian-layout/src/linebreak.rs |
оптимальный разрыв строк — фрагмент typst (Apache-2.0) | ≈ 150 строк | своя реализация Кнута–Пласса — сделано 2026-10-04 (раздел 3) |
meridian-hyph |
форк hypher (MIT): алгоритм Лианга, формат автоматов | ≈ 1 100 строк кода + данные | свой движок Лианга — сделано 2026-10-04; шаблоны — данные |
meridian-layout |
icu_segmenter (UAX #14), unicode-bidi (UAX
#9) |
крейты | свои UAX #14 и UAX #9 — сделано 2026-10-04
(meridian-unicode); словарное деление
тайского/лаосского/кхмерского/бирманского — отдельно |
meridian-layout, meridian-render |
harfrust, read-fonts, skrifa
— разбор шрифтов, шейпинг, контуры |
крейты | свой разбор OpenType (head, hhea, OS/2, cmap, hmtx, glyf/loca, CFF), свой шейпер: сначала латиница/кириллица/греческий (cmap + метрики + GPOS-метки), затем арабское и индийские письма |
meridian-render |
tiny-skia (растр), krilla (PDF),
zune-jpeg |
крейты | растр — meridian-raster (B) и PNG/JPEG —
meridian-image: переведено 2026-10-04;
контуры глифов — meridian-font (шаг 7); PDF/A-2b — свой
meridian-pdf: переведено 2026-10-04 (шаг
9) |
codec-ooxml, meridian-calc-xlsx |
quick-xml, zip |
крейты | свои meridian-xml и meridian-archive —
в codec-ooxml сделано 2026-10-04;
meridian-calc-xlsx переходит вместе с шагом 10 |
meridian-calc, meridian-calc-xlsx |
форк IronCalc (MIT/Apache) + chrono, regex, statrs, rand, csv, serde, bitcode | ≈ 143 тыс. строк | свой движок формул: разборщик A1/R1C1, вычислитель с графом
зависимостей и инкрементальным пересчётом (ADR-A1), функции по каталогу
docs/apps/sheets.md; оракул — эталонные книги Excel корпуса
и текущий форк до замены |
meridian-ffi |
tiny-skia (только тип буфера) |
крейт | переведено на meridian-raster
2026-10-04 |
3. Порядок и оценки (чел.-дни, оценка)
| № | Задача | Оценка | Готовность |
|---|---|---|---|
| 1 | Кнут–Пласс своим кодом (linebreak.rs) |
1 | сделано 2026-10-04 |
| 2 | Свой движок переносов (Лианг); сверка с прежним на словах словарей | 3–4 | сделано 2026-10-04: 654 тыс. слов, 0 расхождений |
| 3 | Свой INFLATE/DEFLATE и ZIP (чтение и запись), свой XML-разборщик; сверка на 1 075 файлах корпуса | 8–10 | сделано 2026-10-04: ZIP — 23 110 записей из 720 архивов побайтно как
у zip; XML — 16 739 из 16 742 частей как у quick-xml (3 —
наш строже к XML 1.0 или терпимее к обрыву CDATA); рендер корпуса
побайтно тот же |
| 4 | Свои UAX #14 и UAX #9 + генератор таблиц из UCD; сверка на тестах Unicode (LineBreakTest, BidiTest) | 6–8 | сделано 2026-10-04: LineBreakTest 19 338/19 338, BidiCharacterTest 91 707/91 707; рендер корпуса побайтно тот же |
| 5 | Свои PNG и JPEG (baseline и progressive) | 6–8 | сделано 2026-10-04 (meridian-image): PNG — 190/190
картинок корпуса как у прежнего декодера, JPEG — 296 картинок, PSNR
медиана 64,7 дБ, минимум 45,4 дБ |
| 4а | Словарное деление строк для тайского, лаосского, кхмерского, бирманского (у ICU — словари и LSTM); данные словарей — решение владельца | 10–15 | сделано 2026-10-04 (meridian-segment): свой алгоритм
(графемные границы, динамическое программирование «меньше символов вне
словаря, затем меньше слов»), словари — списки слов ICU как данные
(лицензия Unicode, BSD), ≈ 1 МБ сжато своим DEFLATE; сверка с ICU 76 на
статьях Википедии — F1: тайский 0,987, лаосский 0,978, бирманский 0,974,
кхмерский 0,939; раскладка переносит эти письменности по словам, рендер
корпуса побайтно тот же |
| 6 | Свой растеризатор: сглаживание, заливка по правилам non-zero/even-odd, наложение картинок; сверка SSIM с tiny-skia на страницах корпуса | 12–15 | делает сессия B (meridian-raster,
общий с оболочкой; договорённость 2026-10-04); A переводит
meridian-render |
| 7 | Свой разбор OpenType и контуры (glyf, CFF/CFF2) | 15–20 | TrueType сделан 2026-10-04 (meridian-font): 11 шрифтов
комплекта и 172 системных macOS — метрики, cmap по всему
Юникоду, продвижения и контуры всех глифов как у read-fonts/skrifa;
раскладка и рендер переведены, рендер корпуса побайтно тот же. CFF
сделан 2026-10-04: 118 системных шрифтов с контурами PostScript (STIX,
Noto, Kohinoor, Apple SD Gothic Neo, Hiragino — CID с FDArray/FDSelect),
≈1,1 млн глифов растр в растр как у skrifa; проверка на испорченных
данных без паник. Дополнительно 2026-10-04: 4 шрифта URW base35 (из Type
1) — контуры как у skrifa. Не сделано сознательно: CFF2 (вариативные
шрифты; в комплекте их нет, раскладка загружает только комплект),
нестандартная FontMatrix и seac (устаревшее составление
акцентов) — ни в одном из 122 проверенных CFF-шрифтов не встречаются,
проверить нечем; добавить, когда появится шрифт с ними |
| 8 | Свой шейпер: cmap, метрики, кернинг/лигатуры по флагам, GPOS-метки; затем арабский и деванагари; сверка с текущим (100 % глифов, как в спайке A8) | 25–40 | Пары GPOS (PairPos 1/2, расширение) и таблица kern
(Microsoft/Apple, форматы 0/2/3) сделаны 2026-10-04: 7,1 млн пар на 224
шрифтах как у harfrust. Этап 1 сделан 2026-10-04: свой шейпер
meridian-shape (GSUB/GPOS всех типов, нормализация,
запасное размещение, иврит) — 8,6 млн глифов как у harfrust, раскладка
переведена. Этап 2 (арабский, тайский/лаосский, хангыль) сделан
2026-10-04: 406 тыс. случайных строк как у harfrust. Этап 3 (индийские,
кхмерский, бирманский, USE) сделан 2026-10-04: 765 тыс. случайных строк
по 32 письменностям как у harfrust/HarfBuzz C. harfrust и read-fonts
убраны из раскладки 2026-10-04 (остались эталонами в тестах). AAT
(morx, kerx, trak) не поддержан —
раскладка загружает только шрифты комплекта OpenType |
| 9 | Свой PDF/A-2b: объекты, потоки, подмножества TrueType/CFF, ToUnicode, XMP; проверка veraPDF как внешним инструментом | 15–20 | сделано 2026-10-04 (meridian-pdf): Type0 + CIDFontType2
(подмножество glyf с сохранением номеров) или CIDFontType0 (CFF в
OpenType), W из hmtx, ToUnicode и /ActualText для
кластеров, JPEG как есть, остальное — Flate RGB + SMask, XMP pdfaid 2/B,
свой профиль sRGB, детерминированный /ID. veraPDF 1.30.2: 160/160
документов корпуса — PDF/A-2b PASS (и шрифт CFF); 1 428 страниц растр в
растр как у krilla (средняя разница 0,007 из 255), текст
pdftotext совпал у всех 160. krilla убран |
| 10 | Свой движок формул вместо форка IronCalc (по ADR-A1: граф, инкрементальный пересчёт) и свой xlsx | 90–120 | этапы 1–3 сделаны 2026-10-04: форк — только эталон в
kernel/oracles/; свой meridian-calc — парсер,
вычислитель, граф и пересчёт, разлив, имена, таблицы и структурированные
ссылки, LET/LAMBDA, 497 функций (все функции каталога
форка, плюс REGEX* на своём движке, FORECAST.ETS*), числовые форматы
Excel; meridian-calc-xlsx — чтение xlsx на своём ZIP/XML.
Сверка с Excel: 151 книга корпуса, 27 508 формул
пересчитаны своим движком — 99,94 % совпадают со значениями,
сохранёнными Excel (остаток — 16 ячеек одного файла стороннего
производителя с запятой в формуле). Запись xlsx своим кодом
(write_xlsx: файловая форма формул
_xlfn./_xlpm., разлив — формулой массива) —
круговой путь на 160 книгах корпуса без расхождений, все файлы открывает
и независимый читатель. Русская локаль формул (locale.rs:
ввод и показ =СУММ(A1;1,5), ИСТИНА/ЛОЖЬ,
#ДЕЛ/0!, числа 1 000,5 и даты
дд.мм.гггг; ≈ 220 русских имён функций, остальные
принимаются по-английски). Числовые форматы ячеек читаются и пишутся в
xlsx (круговой путь: 160 книг, 70 448 форматов без изменений); показ по
формату в локали (display.rs: 1 234,50, даты
ДД.ММ.ГГГГ, строка формул с полной точностью). C ABI для
приложения Sheets — meridian_book_* (контракт v0.4, пример
на C). Дальше: экран Sheets в оболочке (B) на этом ABI |
Итого ≈ 6–8 чел.-мес. Пункты 1–6 не меняют поведение и идут сразу; 7–9 — вместе, когда свой растр готов; 10 — отдельная большая ветка, форк IronCalc до неё остаётся оракулом в тестах.
4. Решения владельца (данные)
- Шрифты комплекта (Liberation, Carlito; OFL-1.1 разрешает коммерческое распространение с файлом лицензии). Варианты: оставить как данные; брать шрифты системы пользователя (без комплекта, но тогда вёрстка зависит от машины); заказать свои метрически совместимые шрифты (дизайнерская работа, месяцы). Рекомендация A: оставить как данные с лицензией.
- Словари ru_RU (BSD Лебедева) и en_US (SCOWL) — данные. Свой словарь — годы работы лингвистов. Рекомендация A: поставлять как данные с NOTICE; движок свой.
- Шаблоны переносов (hyph-utf8; у каждого языка своя лицензия) — то же самое: данные, движок свой.
- Таблицы Юникода (UCD, лицензия Unicode) — стандарт, без них нельзя; генератор таблиц пишем сами.
- Криптография (
meridian-crypto, зона B: AES-GCM, Argon2, HKDF, SHA-2 из крейтов RustCrypto). Свои реализации по стандартам возможны (FIPS 197, SP 800-38D, RFC 9106, RFC 5869, FIPS 180-4), но требуют постоянного времени и внешнего аудита. Рекомендация A: решение владельца вместе с B; если своя — только с векторами NIST/RFC и фаззингом. Сделано (2026-10-04, решение владельца — своя): крейтmeridian-cipherбез зависимостей — SHA-256, HMAC, HKDF, BLAKE2b, Argon2id, AES-256 (S-блок без таблиц: битовые плоскости, обращение x^254 в GF(2^8)), GCM (умножение GF(2^128) маскированием без ветвлений), сравнение и затирание за постоянное время, Base64, случайные байты ОС. Проверка: векторы FIPS 180-4, RFC 4231/5869/7693/9106, SP 800-38D; разностный тест против RustCrypto (300 случайных раундов, Argon2id на 5 наборах параметров) — выходы побайтно те же, старые файлы открываются; замер постоянного времени в духе dudect (t Уэлча, AES по данным и ключу, GHASH; стенд проверен на заведомо «текущем» сравнении). RustCrypto остаётся только оракулом тестов. Переключениеmeridian-crypto— за B. Переключено 2026-10-04 (B):meridian-cryptoцеликом наmeridian-cipher, затирание — свой модульsecret; эталонные векторы формата MOP v1 совпали побайтово. Скорость (Apple M5 Max, release): Argon2id 64 МиБ/t=3/p=4 — 89–117 мс (RustCrypto 74–80), AES-256-GCM — 16 МБ/с против 3,1–3,3 ГБ/с у RustCrypto (аппаратный AES). Аппаратный путь сделан 2026-10-04 (A):hw.rs— AESE/AESMC + PMULL (aarch64, с DIT на Apple Silicon), AES-NI + PCLMULQDQ (x86_64), проверка команд при запуске; AES-256-GCM 2,3–2,7 ГБ/с; свой побитовый путь — запасной. Внешний аудит — до выпуска 1.0.