Meridian Slides — спецификация приложения
Документ приложения по разделу 8 библии (
docs/00-foundation.md). Версия 0.1 · 2026-10-03. Собственный формат:.mpx(шаблон.mpt, плоский XML.mpxf), пространство имёнurn:meridian:office:slides:1, MIMEapplication/vnd.meridian.slides. Цвет приложения--app-slides#E25C3D, значок — прямоугольник с треугольником «play». Крейты ядра:kernel/crates/meridian-slides(модель презентации, пакет.mpx),meridian-scene(общая графика сцены: фигуры, геометрия, стили, группы — делится с Draw/Write/Sheets),meridian-anim(таймлайн и планировщик анимаций),meridian-show(сеанс показа, режим докладчика, перо/лазер),meridian-transitions(переходы, шейдеры SkSL),meridian-diagram(диаграммы-схемы),meridian-video(экспорт видео, запись),meridian-chart(диаграммы),meridian-codecs-{pptx,ppt,odp,iwork}; оболочка —shell/src/slides/(QML/C++); скрипты —meridian-script. Фаза по библии: 3 (12–22 мес от старта). Редакция: Slides входит в Free (Feature::CoreSlides); экспорт видео —Feature::SlidesVideoExport, пульт докладчика —Feature::SlidesPresenterRemote, скрипты —Feature::ScriptsRun/ScriptsEdit, совместная работа —Feature::CloudCollab(фаза 6).
Содержание
- Назначение и аналоги
- Функции (по группам, P0/P1/P2)
- Экраны
- Модель данных
- Алгоритмы
- MeridianScript API для Slides
- Форматы
- Горячие клавиши
- Критерии готовности 1.0
- Риски
- Вопросы к библии
1. Назначение и аналоги
Meridian Slides — редактор презентаций: слайды с заполнителями,
образцами и темами, анимации и переходы, показ с режимом докладчика на
втором экране, запись показа с голосом, экспорт в видео и PDF. Точно
открывает .pptx вместе с анимациями, переходами и
образцами, пишет .pptx без потерь для всего, что умеет
сам.
1.1 Аналоги
| Продукт | Сильные стороны | Слабые стороны, которые используем |
|---|---|---|
| Microsoft PowerPoint | эталон формата, богатые анимации, морфинг, дизайнерские идеи, режим докладчика | подписка, Windows/macOS только, тяжёлый, VBA, нет Linux, облако навязывается |
| LibreOffice Impress | бесплатен, кроссплатформенный, ODF | неточный импорт pptx (анимации, SmartArt, эффекты), устаревший интерфейс, слабый режим докладчика, нет экспорта видео без обходов |
| Apple Keynote | плавные анимации (Magic Move), красивые темы | только Apple, закрытый формат, экспорт в pptx с потерями |
| Google Slides | совместная работа | только в браузере, бедные анимации, пересохранение pptx теряет оформление |
| WPS Presentation | хорошая совместимость с pptx | закрытый, реклама, китайская юрисдикция данных |
1.2 Чем Slides будет лучше — конкретно
| Свойство | Как достигаем |
|---|---|
| Открывает pptx вместе с анимациями и переходами, а не «картинками» | таймлайн meridian-anim структурно равен
p:timing OOXML; 150+ пресетов анимаций и 45+ переходов
реализованы 1:1 |
| Показ 60 кадров/с, переходы на GPU | meridian-transitions: шейдеры SkSL (Skia runtime
effects), 3D-переходы через SkM44; отрисовка показа в
отдельном потоке |
| Режим докладчика на любом числе экранов и на Linux/Wayland | два QQuickWindow с одной моделью состояния показа
(ShowSession), выбор экрана через
QWindow::setScreen |
| Экспорт видео офлайн | виртуальные часы + offscreen-рендер + платформенные кодеры (Media Foundation / VideoToolbox / libvpx+libopus) |
| Текст в слайдах — тот же движок, что в Write | text-model/text-layout ядра: шейпинг,
переносы, RTL, вертикальный текст, проверка орфографии Lingo |
| Диаграммы, таблицы, формулы — общие модули | Meridian Chart, grid-model Sheets, Meridian Math встроены, а не «вставлены как объект» |
| Скрипты вместо VBA | MeridianScript (TypeScript) с типизированным API презентации, песочница, события показа |
| Нет сюрпризов с лицензией | Slides полностью бесплатен в редакции Free; экспорт видео и пульт докладчика — Pro |
1.3 Границы версии 1.0
В 1.0 (конец фазы 3) входят все P0 ниже. 3D-сцена фигур
(a:scene3d, a:sp3d), морфинг, запись с камеры,
сравнение презентаций, авто-субтитры и совместная работа появляются в
1.x/2.0 по приоритетам P1/P2 и фазам 6–7.
2. Функции
Приоритеты: P0 — без этого нельзя выпустить 1.0,
P1 — в 1.x, P2 — позже. Пометки
редакций — [Pro] и т.п. по
docs/10-licensing-accounts.md; без пометки — Free.
2.1 Слайды и структура презентации
| Функция | P | Поведение |
|---|---|---|
| Создать/дублировать/удалить/переставить слайды (перетаскиванием в миниатюрах и сортировщике, с мультивыбором) | P0 | дубликат получает новые id фигур, анимации и заметки копируются |
Новый слайд с выбором макета (галерея макетов текущего образца);
Ctrl+M — макет как у текущего (кроме титульного →
«Заголовок и объект») |
P0 | — |
| Скрыть/показать слайд; скрытые пропускаются при показе и видео, но печатаются по выбору | P0 | — |
| Размер слайда: 16:9 (13,333×7,5 дюйма), 4:3, 16:10, A4, Letter, свой; масштабирование содержимого при смене («вписать»/«по максимуму») | P0 | единицы — EMU внутри, см/дюймы/пункты в интерфейсе |
| Разделы: создать, переименовать, свернуть/развернуть, переместить вверх/вниз, удалить (с/без слайдов) | P0 | OOXML p14:sectionLst |
| Миниатюры слайдов: живые, с кэшем и фоновой генерацией (§5.7) | P0 | — |
| Копирование слайдов между презентациями с выбором «тема назначения» / «исходное оформление» | P0 | при переносе образец копируется, если выбрано исходное оформление |
| Повторное использование слайдов из другого файла (панель со списком миниатюр) | P1 | — |
| Сравнение двух презентаций с принятием/отклонением (§2.21) | P1 | — |
| Избранные (закреплённые) слайды и «библиотека слайдов» организации | P2 | фаза 6/7 |
2.2 Макеты, образцы, темы
| Функция | P | Поведение |
|---|---|---|
| Образец слайдов (slide master): несколько образцов в одной презентации, фон, заполнители, стили текста (заголовок, текст уровней 1–9, прочий), общие фигуры и колонтитулы | P0 | OOXML p:sldMaster:
p:txStyles/titleStyle,bodyStyle,otherStyle,
p:clrMap |
| Макеты (layouts): 11 стандартных типов + свои; переименование, скрытие фоновых фигур образца, свои заполнители с типом/индексом | P0 | типы ST_SlideLayoutType; стандартные: Титульный,
Заголовок и объект, Заголовок раздела, Два объекта, Сравнение, Только
заголовок, Пустой, Объект с подписью, Рисунок с подписью, Заголовок и
вертикальный текст, Вертикальный заголовок и текст |
| Тема: цветовая схема (12 цветов: dk1, lt1, dk2, lt2, accent1–6, hlink, folHlink) с картой цветов bg1/tx1/bg2/tx2, шрифтовая пара (major/minor для latin/ea/cs и переопределения по письменностям), эффекты (3 уровня заливок, линий, эффектов, фонов) | P0 | a:theme DrawingML 1:1; оттенки (lumMod/lumOff) в
палитре «Цвета темы» 6×10 |
| Варианты темы (variants) — 4 цветовых/фоновых варианта у каждой встроенной темы | P0 | p15:themeFamily/варианты хранятся как отдельные темы в
.mpt |
| Встроенные темы: не менее 30, в стиле MDS (спокойные, инженерные), плюс «Office-совместимые» (Carlito/Caladea) | P0 | галерея на вкладке «Дизайн» |
Шаблоны .mpt и .potx; «сохранить тему»
(.mthm — тема как пакет MOP с одной темой, импорт
.thmx) |
P0 | — |
| «Дизайнерские идеи»: локальный генератор вариантов раскладки слайда по правилам (сетка, пропорции, замена макета, акцентные блоки), без ИИ | P1 | ИИ-варианты через Assist — фаза 7 [Pro] |
| Фон слайда: сплошной, градиент, рисунок/текстура, узор; «скрыть фоновые графические объекты»; применить ко всем | P0 | — |
| Колонтитулы: дата/время (фиксированная или авто, 13 форматов), номер слайда, нижний колонтитул; отдельно для заметок и выдач | P0 | диалог SL-26 |
2.3 Заполнители
| Функция | P | Поведение |
|---|---|---|
| 16 типов: заголовок, центрированный заголовок, подзаголовок, текст, объект, рисунок, диаграмма, таблица, диаграмма-схема, медиа, картинка, дата, колонтитул, номер слайда, верхний колонтитул (заметки/выдачи), изображение слайда (заметки) | P0 | ST_PlaceholderType |
| Наследование образец → макет → слайд по типу и индексу (§4.5), «сбросить слайд» восстанавливает геометрию и форматирование | P0 | — |
| Текст-подсказка пустого заполнителя («Заголовок слайда»), не печатается и не показывается | P0 | — |
| Значки быстрой вставки в пустом заполнителе объекта: таблица, диаграмма, диаграмма-схема, рисунок, значок, видео | P0 | — |
| Автоподбор текста при переполнении (сжать/расширить фигуру/нет) (§5.2) | P0 | кнопка-подсказка «Параметры автоподбора» у фигуры |
Автонумерация слайда, авто-дата как поля (a:fld) |
P0 | — |
2.4 Текст (движок Write)
| Функция | P | Поведение |
|---|---|---|
Текстовое тело в любой фигуре: абзацы, уровни 1–9, выравнивание,
отступы, табуляции, интервалы, маркеры (символ, рисунок, автонумерация —
40 схем OOXML ST_TextAutonumberScheme), цвет/размер
маркера |
P0 | модель text-model, раскладка
text-layout |
| Символы: шрифт по письменности (latin/ea/cs/sym), размер, Ж/К/Ч/зачёркнутый (одинарный/двойной), капители/прописные, межзнаковый интервал, кернинг, верхний/нижний индекс, цвет/заливка текста, контур, тень, свечение, отражение | P0 | эффекты текста — a:effectLst на a:rPr;
рендер через Skia |
| Направление текста: горизонтальный, повёрнутый 90°/270°, вертикальный с накоплением, восточноазиатский вертикальный; RTL; колонки (до 16) с интервалом | P0 | a:bodyPr/@vert, @numCol,
@rtlCol |
| Привязка по вертикали (верх/центр/низ), по горизонтали центра, внутренние поля (по умолчанию 0,25/0,13 см), перенос слов, поворот текста отдельно от фигуры | P0 | — |
Деформация текста (WordArt-преобразования,
a:prstTxWarp, 40 видов) |
P1 | раскладка глифов по огибающей (§5.2) |
| Проверка орфографии (Lingo), автозамена, тезаурус, переносы, язык абзаца/фрагмента | P0 | — |
| Поиск и замена (по всей презентации, включая заметки), замена шрифтов во всём документе | P0 | — |
| Гиперссылки и действия на тексте (слайд, показ, URL, файл, скрипт) | P0 | — |
| Формулы Math в тексте (встроенные объекты) | P0 (отображение) / P1 (редактор, фаза 4) | — |
| Специальные символы, дата/время, номер слайда как поля | P0 | — |
| Вставка текста из Write/буфера с сохранением стилей или «только текст» | P0 | — |
2.5 Фигуры
Геометрия — общая библиотека meridian-scene, та же, что
в Write/Sheets/Draw: 187 предустановленных фигур OOXML
(a:prstGeom), вычисляемых по формулам направляющих (§5.1).
Группы галереи «Фигуры» (всего 187):
| Группа | Кол-во | Состав (идентификаторы ST_ShapeType) |
|---|---|---|
| Линии и соединительные линии | 11 | line, lineInv,
straightConnector1, bentConnector2…5,
curvedConnector2…5 |
| Прямоугольники | 9 | rect, roundRect, round1Rect,
round2SameRect, round2DiagRect,
snipRoundRect, snip1Rect,
snip2SameRect, snip2DiagRect |
| Основные фигуры | 43 | triangle, rtTriangle,
diamond, parallelogram,
trapezoid, nonIsoscelesTrapezoid,
pentagon, hexagon, heptagon,
octagon, decagon, dodecagon,
plaque, ellipse, teardrop,
pie, pieWedge, blockArc,
donut, noSmoking, cube,
can, lightningBolt, heart,
sun, moon, smileyFace,
foldedCorner, bevel, frame,
halfFrame, corner, diagStripe,
chord, arc, leftBracket,
rightBracket, leftBrace,
rightBrace, bracketPair,
bracePair, cloud, plus |
| Фигурные стрелки | 31 | rightArrow, leftArrow,
upArrow, downArrow,
leftRightArrow, upDownArrow,
quadArrow, leftRightUpArrow,
bentArrow, uturnArrow,
leftUpArrow, bentUpArrow,
curvedRightArrow, curvedLeftArrow,
curvedUpArrow, curvedDownArrow,
stripedRightArrow, notchedRightArrow,
homePlate, chevron,
rightArrowCallout, downArrowCallout,
leftArrowCallout, upArrowCallout,
leftRightArrowCallout, upDownArrowCallout,
quadArrowCallout, circularArrow,
leftCircularArrow, leftRightCircularArrow,
swooshArrow |
| Фигуры для формул | 6 | mathPlus, mathMinus,
mathMultiply, mathDivide,
mathEqual, mathNotEqual |
| Блок-схема | 29 | flowChartProcess,
flowChartAlternateProcess, flowChartDecision,
flowChartInputOutput,
flowChartPredefinedProcess,
flowChartInternalStorage, flowChartDocument,
flowChartMultidocument, flowChartTerminator,
flowChartPreparation, flowChartManualInput,
flowChartManualOperation, flowChartConnector,
flowChartOffpageConnector,
flowChartPunchedCard, flowChartPunchedTape,
flowChartSummingJunction, flowChartOr,
flowChartCollate, flowChartSort,
flowChartExtract, flowChartMerge,
flowChartOfflineStorage,
flowChartOnlineStorage, flowChartMagneticTape,
flowChartMagneticDisk, flowChartMagneticDrum,
flowChartDisplay, flowChartDelay |
| Звёзды и ленты | 21 | irregularSeal1, irregularSeal2,
star4, star5, star6,
star7, star8, star10,
star12, star16, star24,
star32, ribbon, ribbon2,
ellipseRibbon, ellipseRibbon2,
leftRightRibbon, verticalScroll,
horizontalScroll, wave,
doubleWave |
| Выноски | 16 | wedgeRectCallout, wedgeRoundRectCallout,
wedgeEllipseCallout, cloudCallout,
callout1…3, accentCallout1…3,
borderCallout1…3, accentBorderCallout1…3 |
| Управляющие кнопки | 12 | actionButtonBlank, actionButtonHome,
actionButtonHelp, actionButtonInformation,
actionButtonForwardNext,
actionButtonBackPrevious, actionButtonEnd,
actionButtonBeginning, actionButtonReturn,
actionButtonDocument, actionButtonSound,
actionButtonMovie |
| Служебные (не в галерее, нужны для импорта) | 9 | gear6, gear9, funnel,
cornerTabs, squareTabs,
plaqueTabs, chartX, chartStar,
chartPlus |
| Функция | P | Поведение |
|---|---|---|
Вставка фигур из галереи, рисование с ограничением пропорций (Shift)
и от центра (Ctrl), регуляторы формы (жёлтые маркеры
a:avLst) |
P0 | — |
| Произвольная фигура (кривая Безье, полилиния, карандаш), редактирование узлов — редактор из Draw | P0 | a:custGeom |
| Объединение фигур: объединить, объединить с пересечением, фрагментировать, пересечь, вычесть (булевы операции Draw) | P1 | результат — custGeom |
Стили фигур: матрица 6 акцентов × 7 стилей темы
(a:lnRef/fillRef/effectRef/fontRef), «другие
заливки/контуры/эффекты» |
P0 | — |
Заливки: нет, сплошная, градиент
(линейный/радиальный/прямоугольный/по контуру, до 10 остановок,
прозрачность), рисунок/текстура (растянуть/замостить, смещение,
прозрачность), узор (54 предустановленных
ST_PresetPatternVal) |
P0 | — |
| Линии: сплошная/градиент, толщина, 11 штрихов, составные (5), концы (плоский/круглый/квадратный), соединения (скос/срез/круглое), стрелки 6 типов × размеры 3×3 | P0 | — |
| Эффекты: тень (внешняя 9 пресетов, внутренняя 9, перспективная 5; цвет, размытие, расстояние, угол, прозрачность), отражение (9), свечение (24 пресета), сглаживание краёв (6) | P0 | рендер через SkImageFilter (DropShadow,
Blur) |
Рельеф, поворот объёмной фигуры, освещение, материал
(a:sp3d, a:scene3d) |
P2 | в 1.0 — плоское отображение с приближённым рельефом (внутренняя тень + блик) |
| Выравнивание (6 вариантов + относительно слайда/выделения), распределение, умные направляющие (§5.3), привязка к сетке/направляющим, сетка с шагом | P0 | — |
| Группировка/разгруппировка/перегруппировка, порядок (вперёд/назад/на передний/на задний), панель «Выделение» (имена, видимость, порядок) | P0 | — |
| Поворот (маркер, 15° с Shift, точный ввод), отражение, размер и положение с точностью 0,01 см, блокировка пропорций, замена фигуры с сохранением текста | P0 | — |
| Замещающий текст (alt), название, скрытие, запрет выделения/перемещения (блокировки) | P0 | — |
2.6 Рисунки
| Функция | P | Поведение |
|---|---|---|
| Вставка: файл (png, jpg, gif, webp, bmp, tiff, heic, avif, svg, emf, wmf), буфер обмена, снимок экрана/области (через Paint-модуль захвата), перетаскивание | P0 | хранение в media/; EMF/WMF — векторно через импорт
Draw, резерв — растр |
| Обрезка: прямоугольная, по фигуре (любая из 187), по пропорции (1:1, 4:3, 16:9, …), «заливка» и «вписать», обрезка не разрушает исходник | P0 | a:srcRect + a:prstGeom |
| Стили рисунков: 28 предустановленных (рамки, тени, скосы, отражения, мягкие края, повороты) | P0 | — |
| Коррекция: резкость/размытие, яркость, контраст; цвет: насыщенность, оттенок, перекраска (12 вариантов по теме), прозрачный цвет, прозрачность (ползунок) | P0 | параметры хранятся как a:lum,
a:alphaModFix, a:duotone,
a:clrChange; рендер через
SkColorFilter/SkImageFilter |
| Удаление фона: автоматическая маска (локальная модель сегментации из Paint) + кисти «отметить/исключить» | P1 | результат — альфа-маска в media/, исходник
сохраняется |
| Художественные эффекты (карандаш, акварель, мозаика, …) | P2 | — |
| Сжатие рисунков (целевое разрешение 96/150/220/330 dpi, удаление обрезанных областей), замена рисунка с сохранением формата, сброс | P0 | — |
| Альбом (фотоальбом из папки: раскладки 1/2/4 на слайд, подписи) | P2 | — |
| Alt-текст, «декоративный», подпись | P0 | Assist предлагает alt-текст [Pro] |
2.7 Значки и SVG
| Функция | P | Поведение |
|---|---|---|
| Библиотека значков: Meridian Glyphs + открытые наборы (Lucide, Fluent — MIT), ≥ 2 000 значков по категориям, поиск по русским и английским названиям | P0 | хранятся как SVG в ресурсах, вставляются как
svgBlip |
Вставка SVG с сохранением вектора; перекраска по цветам темы (замена
fill/stroke), контур, тень |
P0 | рендер через resvg/собственный SVG-парсер кодеков →
meridian-scene |
«Преобразовать в фигуру»: SVG → группа фигур с custGeom
(редактируемые узлы) |
P0 | — |
Экспорт в pptx: asvg:svgBlip + PNG-резерв (как
PowerPoint 2016+) |
P0 | — |
2.8 Таблицы
| Функция | P | Поведение |
|---|---|---|
| Вставка n×m (сетка-выбор до 10×8, диалог до 75×75), рисование таблицы, из Sheets с сохранением форматов, из Write | P0 | модель — grid-model Sheets (без формул), текст ячеек —
text-model |
Стили таблиц: 74 предустановленных (как
ppt/tableStyles.xml, GUID-идентификаторы), параметры:
строка заголовка, строка итогов, чередование строк/столбцов,
первый/последний столбец |
P0 | — |
| Ячейки: объединить/разделить, выравнивание, поля, направление текста, заливка (сплошная/градиент/рисунок), границы (пресеты и по сторонам), размеры, распределение, автоподбор | P0 | — |
| Эффекты таблицы (тень, отражение, рельеф), стили WordArt в ячейках | P1 | — |
| Связь с диапазоном Sheets (обновление по команде) | P1 | ссылка objects/table1.msx + диапазон |
2.9 Диаграммы (Meridian Chart)
| Функция | P | Поведение |
|---|---|---|
Все типы Meridian Chart
(docs/algorithms/chart-engine.md): классические P0,
современные (каскадная, воронка, treemap, солнечные лучи, гистограмма,
Парето, ящик с усами) P1 |
P0/P1 | один движок с Sheets/Write |
Данные: встроенная мини-таблица (objects/chartN.msx,
grid-model Sheets) редактируется в боковой панели; связь с внешним
.msx/.xlsx с обновлением по команде |
P0 / P1 | как c:externalData в pptx |
| Макеты, стили (16), цвета по теме, элементы (заголовок, оси, легенда, подписи данных, тренды, планки погрешностей) | P0 | — |
| Анимация диаграммы: как один объект, по сериям, по категориям, по элементам серий/категорий | P0 | p:bldOleChart/p:bldChart |
Шаблоны диаграмм .mcht |
P1 | общие с Sheets |
2.10 Диаграммы-схемы (аналог SmartArt)
Модуль meridian-diagram: дерево узлов с текстом →
автоматическая раскладка по выбранному макету → фигуры, стилизованные
темой. Доступен в Slides, Write, Sheets (один код). Категории и
макеты:
| Категория | Макеты P0 | Макеты P1 | P2 |
|---|---|---|---|
| Список | простой блочный список, вертикальный маркированный, горизонтальный маркированный, список с рисунками-акцентами, вертикальный блочный, табличный список, список с заголовками в блоках | список с округлёнными блоками, вертикальный список со стрелками, список-«лесенка», список с картинками в круге | — |
| Процесс | простой процесс, пошаговый (step down), процесс со стрелками-шевронами, повторяющийся изогнутый (змейка), процесс с акцентами, временная шкала | вертикальный процесс, чередующийся поток, круговой изогнутый, воронка-процесс, уравнение, процесс со сходящимися стрелками | процесс с рисунками |
| Цикл | простой цикл, радиальный цикл, цикл с текстом, сегментированный цикл | многонаправленный цикл, шестерёнки, непрерывный цикл, расходящийся радиальный | — |
| Иерархия | организационная диаграмма (с помощниками и вертикальными ветвями), иерархия, иерархия с подписями, горизонтальная иерархия | табличная иерархия, иерархия с рисунками, круговая иерархия, полукруглая организационная | — |
| Связь | баланс, воронка, сходящиеся/расходящиеся стрелки, диаграмма Венна (простая/линейная/вложенная), целевая (концентрическая) | противовес, уравнение, кластеры, радиальная, группированный список, «сравнение» (две колонки) | — |
| Матрица | простая матрица 2×2, матрица с заголовком, сетка 2×2 | циклическая матрица | — |
| Пирамида | простая пирамида, перевёрнутая, сегментированная | пирамида со списком | — |
| Рисунок | список с рисунками, подписанные рисунки | полоса рисунков с текстом, круг с рисунками | — |
| Функция | P | Поведение |
|---|---|---|
| Текстовая панель-структура: ввод по уровням, Tab/Shift+Tab — понизить/повысить, Enter — новый узел, перенос узлов перетаскиванием | P0 | — |
| Добавить фигуру (после/перед/выше/ниже/помощник), изменить направление (слева направо ↔︎ справа налево), макет организационной ветви (стандартный, обе стороны, слева, справа) | P0 | — |
| Сменить макет внутри категории и между категориями с сохранением текста; цвета (по теме: цветной, акцент 1–6, прозрачный/монохромный варианты), стили (7 плоских + 7 объёмных — объёмные P2) | P0 | — |
| Преобразовать в фигуры / в текст (список); восстановить макет; размер шрифта общий (§5.6) | P0 | — |
Импорт pptx: известные макеты (по uniqueId
dgm:layoutDef) → наш макет; неизвестные → редактируемая
группа фигур из кэша drawingN.xml |
P0 | интерпретатор dgm:layoutDef (алгоритмы
lin, hierChild, cycle,
snake, pyra, composite,
conn) — P2 |
2.11 Видео и аудио
| Функция | P | Поведение |
|---|---|---|
| Вставка видео (mp4/H.264, mp4/H.265 при поддержке ОС, webm/VP8/VP9/AV1, mov, m4v, avi, mkv — контейнеры через платформенный декодер) и аудио (mp3, wav, m4a/AAC, ogg/Vorbis, opus, flac) — встроить или связать с файлом | P0 | воспроизведение: Qt Multimedia (FFmpeg-бэкенд Qt 6.5+ / платформенные AVFoundation, Media Foundation, GStreamer) |
| Воспроизведение: автоматически / по щелчку / по последовательности щелчков; во весь экран; скрыть, пока не воспроизводится; непрерывно; перемотать после воспроизведения; громкость; без звука | P0 | p:nvPr/a:videoFile, p14:media, атрибуты
trim/fade/bmkLst |
| Обрезка (trim) начала/конца с предпросмотром и точным вводом времени; без перекодирования (метки), при экспорте видео — физически | P0 | p14:trim st/end |
| Появление/исчезание звука (fade in/out), закладки на временной шкале → триггеры анимаций «по закладке» | P0 | p14:fade, p14:bmk |
| Кадр-заставка (poster frame): из видео (текущий кадр) или из файла; стили видео (рамка, форма, тень), обрезка кадра | P0 | — |
| Фоновая музыка через слайды («воспроизводить для всех слайдов», скрыть значок), остановка на N-м слайде | P0 | — |
Сжатие медиа (целевое качество: Full HD / HD / стандартное) через
meridian-video |
P1 | — |
| Запись экрана (область, звук системы/микрофона) → вставка на слайд | P2 | — |
| Субтитры (WebVTT) к видео, отображение при показе | P2 | — |
| Онлайн-видео (ссылка на YouTube/VK) | P1 | постер + ссылка; при показе — открытие во встроенном браузере не делаем, открываем системный |
2.12 Переходы
Каталог переходов (имя, категория по PowerPoint, OOXML-элемент, параметры «Параметры эффекта», способ отрисовки):
| # | Переход | Категория | OOXML | Параметры | Рендер |
|---|---|---|---|---|---|
| 1 | Нет | — | — | — | — |
| 2 | Прорезание | Простые | p:cut |
через чёрный | CPU |
| 3 | Выцветание | Простые | p:fade |
плавно / через чёрный | шейдер |
| 4 | Сдвиг | Простые | p:push |
снизу/слева/справа/сверху | шейдер |
| 5 | Появление | Простые | p:wipe |
4 направления | шейдер |
| 6 | Панорама | Простые | p:split |
по вертикали/горизонтали, внутрь/наружу | шейдер |
| 7 | Проявление | Простые | p14:reveal |
плавно слева/справа, через чёрный | шейдер |
| 8 | Случайные полосы | Простые | p:randomBar |
по вертикали/горизонтали | шейдер (хэш полос) |
| 9 | Фигура | Простые | p:circle / p:diamond / p:plus
/ p:wedge / p:zoom |
круг, ромб, плюс, клин, внутрь/наружу | шейдер (SDF) |
| 10 | Открытие | Простые | p:pull |
8 направлений | шейдер |
| 11 | Наплыв | Простые | p:cover |
8 направлений | шейдер |
| 12 | Вспышка | Простые | p14:flash |
— | шейдер |
| 13 | Жалюзи | Простые | p:blinds |
по вертикали/горизонтали | шейдер |
| 14 | Шашки | Простые | p:checker |
по вертикали/горизонтали | шейдер |
| 15 | Часы | Простые | p:wheel |
1/2/3/4/8 спиц, обратно (p14:wheelReverse) |
шейдер |
| 16 | Растворение | Простые | p:dissolve |
— | шейдер (шум) |
| 17 | Гребёнка | Простые | p:comb |
по вертикали/горизонтали | шейдер |
| 18 | Полосы | Простые | p:strips |
4 диагонали | шейдер |
| 19 | Новости | Простые | p:newsflash |
— | 2D-трансформ |
| 20 | Падение | Эффектные | p15:prstTrans fallOver |
влево/вправо | 3D (SkM44) |
| 21 | Драпировка | Эффектные | p15:prstTrans drape |
влево/вправо | сетка вершин (drawVertices) |
| 22 | Занавес | Эффектные | p15:prstTrans curtains |
— | сетка вершин |
| 23 | Ветер | Эффектные | p15:prstTrans wind |
влево/вправо | частицы (полосы) |
| 24 | Престиж | Эффектные | p15:prstTrans prestige |
— | 3D |
| 25 | Разрушение | Эффектные | p15:prstTrans fracture |
— | осколки Вороного (предрасчёт) |
| 26 | Сжатие | Эффектные | p15:prstTrans crush |
— | сетка вершин |
| 27 | Отслаивание | Эффектные | p15:prstTrans peelOff |
влево/вправо | сетка вершин |
| 28 | Скручивание страницы | Эффектные | p15:prstTrans pageCurlDouble/Single |
влево/вправо | сетка вершин |
| 29 | Самолёт | Эффектные | p15:prstTrans airplane |
влево/вправо | 3D |
| 30 | Оригами | Эффектные | p15:prstTrans origami |
влево/вправо | 3D |
| 31 | Растворение (пиксели) | Эффектные | p14:glitter |
ромбы/шестиугольники, 4 направления | шейдер |
| 32 | Вихрь | Эффектные | p14:vortex |
4 направления | частицы (тайлы) |
| 33 | Измельчение | Эффектные | p14:shred |
полосы/прямоугольники, внутрь/наружу | тайлы |
| 34 | Переключение | Эффектные | p14:switch |
влево/вправо | 3D |
| 35 | Переворот | Эффектные | p14:flip |
влево/вправо | 3D |
| 36 | Галерея | Эффектные | p14:gallery |
влево/вправо | 3D |
| 37 | Куб | Эффектные | p14:prism (isContent=0) |
4 направления | 3D |
| 38 | Двери | Эффектные | p14:doors |
по вертикали/горизонтали | 3D |
| 39 | Прямоугольник (Box) | Эффектные | p14:prism (isContent=1) |
4 направления | 3D |
| 40 | Гребень/соты | Эффектные | p14:honeycomb |
— | тайлы |
| 41 | Рябь | Эффектные | p14:ripple |
центр/углы | шейдер |
| 42 | Колесо обозрения | Динамические | p14:ferris |
влево/вправо | 3D |
| 43 | Конвейер | Динамические | p14:conveyor |
влево/вправо | 3D |
| 44 | Поворот | Динамические | p14:prism (isInverted) |
4 направления | 3D |
| 45 | Окно | Динамические | p14:window |
по вертикали/горизонтали | 3D |
| 46 | Орбита | Динамические | p14:prism (вариант) |
4 направления | 3D |
| 47 | Пролёт | Динамические | p14:flythrough |
внутрь/наружу, с отскоком | 3D |
| 48 | Панорамирование | Динамические | p14:pan |
4 направления | 2D |
| 49 | Деформация | Эффектные | p14:warp |
внутрь/наружу | шейдер |
| 50 | Случайный | — | p:random |
— | выбор из 2–19 |
| 51 | Морфинг | — | p159:morph |
по объектам / словам / символам | интерполяция сцены (§5.10) — P1 |
| Функция | P | Поведение |
|---|---|---|
| Переходы 1–19 и 50 | P0 | — |
| Переходы 20–49 | P0 для 31–41 (шейдеры/тайлы), P1 для 20–30, 42–49 (3D и сетки вершин) | при отсутствии GPU — замена на «Выцветание» |
| Длительность (0,01–59 с), звук перехода (встроенные 19 + файл, «непрерывно»), смена слайда по щелчку и/или через время, применить ко всем | P0 | p:transition/@spd, p14:dur,
@advClick, @advTm, p:sndAc |
| Предпросмотр на холсте, автопредпросмотр при выборе | P0 | — |
| Морфинг | P1 | сопоставление фигур по имени !!имя и по id,
интерполяция положения/размера/поворота/цвета/геометрии с равным числом
узлов; текст — по словам/символам |
2.13 Анимации
| Функция | P | Поведение |
|---|---|---|
Эффекты входа (presetClass="entr"): появление,
выцветание, вылет, плавное приближение, панорама, появление (wipe),
фигура, часы, случайные полосы, увеличение с поворотом, масштабирование,
вращение, отскок; эффектные: бумеранг, падение, кнут, плавное появление
(float), центрифуга, вылет вверх по спирали, разворот, растягивание,
подпрыгивание, увеличение с поворотом, прыжки, спираль, вспышка,
пропеллер, появление с вращением — всего 52 пресета |
P0 | presetID/presetSubtype по таблице PowerPoint (каталог
meridian-anim/presets/*.xml, 150+ записей) |
Эффекты выделения (emph): пульсация, цветовая
пульсация, качание, вращение, увеличение/уменьшение, обесцвечивание,
затемнение, осветление, прозрачность, цвет объекта, дополнительный цвет,
цвет линии, цвет заливки, цвет кисти, цвет шрифта, подчёркивание,
мигание полужирным, проявление полужирным, волна — 30 пресетов |
P0 | — |
Эффекты выхода (exit): зеркальные входу — 52
пресета |
P0 | — |
Пути перемещения (path): линии (6), дуги (4), повороты
(4), фигуры (круг, ромб, шестиугольник, сердце, пятиугольник, квадрат,
треугольник, …), циклы (кривая, волна, пружина, …), пользовательский
путь (рисование, редактирование узлов),
«заблокированный/разблокированный» путь, обратное направление |
P0 | p:animMotion/@path (VML-подобный синтаксис
M L C Z E) |
| Параметры эффекта: направление, вариант, количество (для масштаба/вращения), плавное начало/конец (accel/decel), отскок в конце, звук, затемнение после анимации (скрыть/скрыть по щелчку/цвет), анимация текста (всё сразу / по абзацам N уровня / по словам / по буквам с задержкой %) | P0 | — |
| Время: начало (по щелчку / с предыдущим / после предыдущего), задержка, длительность (пресеты 0,5/1/2/3/5 с и ввод), повторение (N раз / до следующего щелчка / до конца слайда), перемотка по завершении, автообращение | P0 | — |
| Триггеры: по щелчку на фигуре; по закладке видео/аудио | P0 | p:cond/@evt="onClick", p:tgtEl/p:spTgt;
интерактивные последовательности
nodeType="interactive" |
| Анимация диаграмм (по сериям/категориям), диаграмм-схем (по ветвям/уровням), таблиц — как объект | P0 | p:bldLst |
| Панель «Анимация» с таймлайном: список эффектов с номерами, перетаскивание порядка, временная шкала с полосками (сдвиг/растяжение мышью), масштаб шкалы, щелчки как вертикальные маркеры, звуки, предпросмотр | P0 | SL-11 |
| Копирование анимации («кисть анимации») на другие фигуры | P0 | — |
| Нумерованные метки у фигур на холсте, порядок перетаскиванием меток | P0 | — |
| Воспроизведение: 60 кадров/с, ease-функции, пропуск кадров без накопления задержки (§5.4) | P0 | — |
| Анимация 3D-моделей, cameo | P2 | — |
2.14 Показ слайдов
| Функция | P | Поведение |
|---|---|---|
С начала (F5), с текущего (Shift+F5), в
окне, в режиме докладчика (Alt+F5), произвольный показ |
P0 | — |
| Типы показа: докладчик (полный экран), просмотр в окне (с полосой прокрутки), автоматический (киоск: цикл, только ESC) | P0 | p:showPr |
Навигация: щелчок/колесо/клавиши, «Перейти к слайду» (меню и ввод
номера+Enter), сетка всех слайдов (G), по разделам, назад к
последнему просмотренному, скрытые слайды по H |
P0 | — |
Чёрный (B) и белый (W) экран, пауза
автоматического показа (S), скрыть указатель
(Ctrl+H), показать (Ctrl+A) |
P0 | — |
Лазерная указка (Ctrl+L или Ctrl+ЛКМ),
перо (Ctrl+P), маркер (Ctrl+I), ластик
(Ctrl+E), очистить (E), цвет пера; штрихи
сглаживаются (как в Notes) |
P0 | по выходу — «Сохранить рукописный ввод?» → штрихи становятся
фигурами слайда (p14:ink/custGeom) |
Масштабирование фрагмента слайда (лупа,
+/-, перетаскивание области) |
P0 | — |
| Режим докладчика (SL-09): текущий слайд, следующий слайд/шаг анимации, заметки с масштабом, таймер и часы, панель миниатюр, инструменты пера, чёрный экран, завершение, обмен экранов, настройки | P0 | два окна, общая ShowSession (§5.9) |
| Выбор экрана для показа, автоопределение (показ — на внешнем, докладчик — на основном), «использовать режим докладчика» при одном экране (окно поверх) | P0 | — |
| Произвольные показы (подмножество слайдов с именем), запуск из гиперссылок/кнопок, «показать и вернуться» | P0 | p:custShowLst |
| Разрешение показа (авто/выбор), «использовать аппаратное ускорение» (отключение GPU-переходов) | P0 | — |
Пульт докладчика: управление с телефона через локальную сеть
(QR-код, веб-страница в WASM-свободном варианте: простой HTML+WebSocket)
[Pro] |
P1 | Feature::SlidesPresenterRemote |
Живые субтитры (локальное распознавание речи — Assist)
[Pro] |
P2 | фаза 7 |
| Трансляция показа через Meridian Cloud (зрители в браузере) | P2 | фаза 6+ |
Запуск показа из проводника/Finder: пункт «Показать» в контекстном
меню .mpx/.pptx (аргумент командной строки
--show); отдельное расширение «только показ» не вводится,
.ppsx открывается сразу в показе |
P0 | — |
2.15 Репетиция и хронометраж
| Функция | P | Поведение |
|---|---|---|
| Репетиция: показ с панелью «Запись» (время слайда, общее время, пауза, повтор слайда, далее) | P0 | — |
Сохранение времён на слайды (p:transition/@advTm) и в
сортировщике под миниатюрами; «использовать время» при показе |
P0 | — |
| Очистка времён (на слайде / во всех), ручной ввод времени | P0 | — |
| Отчёт о репетиции: таблица слайд → время, план vs факт (цель «уложиться в N минут»), экспорт в Sheets | P1 | — |
2.16 Запись показа
| Функция | P | Поведение |
|---|---|---|
| Запись голоса (микрофон, выбор устройства, уровень), хронометраж, лазер/перо/маркер как анимации с таймкодами; с текущего слайда или с начала | P0 | аудио — Opus (в .mpx), AAC/WAV при экспорте в pptx
(a:audioFile + p:cmd playFrom) |
| Экран записи (SL-23): предпросмотр, заметки, кнопки запись/пауза/стоп, очистить запись на слайде/во всех, переснять слайд | P0 | — |
| Видео с камеры (cameo-кружок/прямоугольник в углу), микшер камеры и экрана | P1 | хранится как видео-объект слайда |
| Экспорт записи в видео (§2.17), публикация (фаза 6) | P0 / P2 | — |
2.17 Экспорт
видео [Pro: Feature::SlidesVideoExport]
| Функция | P | Поведение |
|---|---|---|
| Контейнеры/кодеки: MP4 (H.264 + AAC), WebM (VP9 + Opus); разрешение 480p/720p/1080p/4K (с сохранением пропорций слайда), 30/60 к/с, качество (битрейт по пресетам) | P0 | §5.8 |
| Источник времени: записанные хронометраж и закадровый голос / фиксированное время на слайд (по умолчанию 5 с) | P0 | — |
| Включаются переходы, анимации, медиа слайдов (с обрезкой и затуханием), рукописный ввод записи, лазер | P0 | — |
| Прогресс, предварительная оценка длительности и размера, отмена, экспорт в фоне с уведомлением | P0 | — |
| Аппаратное ускорение кодирования (NVENC/QuickSync/AMF через Media Foundation, VideoToolbox) | P1 | — |
| GIF (анимированный, с ограничением 256 цветов и дизерингом), HEVC | P2 | — |
2.18 Раздаточные материалы, печать, PDF
| Функция | P | Поведение |
|---|---|---|
| Печать: слайды, страницы заметок, структура, выдачи (1, 2, 3 с линиями для заметок, 4, 6, 9 на лист; порядок горизонтальный/вертикальный), рамка слайдов, вписать по размеру, цвет/оттенки серого/ч/б, диапазоны и разделы, скрытые слайды | P0 | Meridian Print; диалог SL-27 |
| Образец выдач (SL-07): положение колонтитулов, число слайдов на странице, фон | P0 | — |
| PDF: слайды, заметки, выдачи; закладки по разделам/слайдам, гиперссылки, PDF/A, PDF/UA с тегами и порядком чтения; комментарии как аннотации | P0 (P1 — комментарии) | — |
| Экспорт слайдов в PNG/JPG/SVG (все/текущий/диапазон, разрешение) | P0 | — |
| Экспорт в HTML (статичные страницы с SVG слайдов, навигация клавишами, без анимаций) | P2 | — |
2.19 Заметки докладчика
| Функция | P | Поведение |
|---|---|---|
| Панель заметок под холстом (SL-13), форматирование Write (абзацы, списки, Ж/К/Ч), вставка рисунков в страницу заметок | P0 | p:notes, заполнитель body страницы
заметок |
| Страница заметок (SL-04) с образцом заметок (SL-06): изображение слайда, тело заметок, колонтитулы | P0 | — |
| В режиме докладчика: масштаб шрифта заметок, прокрутка | P0 | — |
| Печать и PDF с заметками; экспорт заметок в Write | P0 / P1 | — |
2.20 Разделы
См. §2.1. В сортировщике разделы — заголовки с кнопками сворачивания; перетаскивание раздела переносит его слайды; печать и экспорт «только раздел»; «Масштаб раздела» (section zoom) — P2.
2.21 Сравнение и рецензирование
| Функция | P | Поведение |
|---|---|---|
| Комментарии: к слайду и к фигуре (якорь с координатами), цепочки ответов, «решено», упоминания (фаза 6), панель SL-14, навигация, печать комментариев | P0 | импорт/экспорт ppt/comments/ (старые) и современных
modernComment (p188) |
| Сравнение двух презентаций: сопоставление слайдов по id/содержимому, фигур по id/имени, текста по словам; панель изменений с принятием/отклонением по одному/всем | P1 | Feature::WriteCompare не используем — отдельный флаг не
нужен (Free) |
Правописание, тезаурус, статистика, язык; перевод
фрагмента/презентации (Assist [Pro]) |
P0 / P2 | — |
| Проверка доступности: отсутствие alt-текста, порядок чтения, контраст текста, дубли заголовков слайдов, таблицы без заголовков, субтитры у видео | P0 | — |
| Рукописные пометки (ink) при рецензировании | P1 | — |
Защита: пароль на открытие (AES-256, совместимо с Office agile
encryption), только чтение, «пометить как окончательный», цифровая
подпись [Pro: DocSign] |
P0 / P1 | Feature::DocEncrypt — Pro; Free открывает и снимает
защиту при знании пароля |
2.22 Совместная
работа (фаза 6) [Pro: CloudCollab]
CRDT (Yrs) на уровне дерева слайдов и фигур и текста в фигурах;
присутствие (цветные рамки выделений других авторов, аватары на
миниатюрах), «следовать за автором», история версий из
history/, общий доступ по ссылке, комментарии с
упоминаниями и уведомлениями. Показ по сети («зрители следуют за
докладчиком») — P2.
2.23 Доступность
| Функция | P | Поведение |
|---|---|---|
| Дерево доступности слайда (Qt Accessibility → UIA/NSAccessibility/AT-SPI): фигуры в порядке чтения, текст, таблицы, alt-текст | P0 | порядок чтения = порядок в панели «Выделение» снизу вверх, редактируется |
Полное управление с клавиатуры (обход фигур Tab, ручки
размером/поворотом стрелками, меню действий Shift+F10) |
P0 | — |
| Высокая контрастность интерфейса, масштаб интерфейса 100–300 %, «уменьшить движение» (переходы → выцветание, анимации сокращаются) | P0 | — |
| Проверка доступности (§2.21), экспорт PDF/UA | P0 | — |
| Субтитры видео, живые субтитры, озвучивание заметок | P2 | — |
2.24 Прочее
| Функция | P | Поведение |
|---|---|---|
| Гиперссылки и действия: по щелчку/при наведении — переход (следующий/предыдущий/первый/последний/последний просмотренный/завершить/слайд/произвольный показ/URL/файл), запуск скрипта, звук, выделение | P0 | a:hlinkClick, a:hlinkHover,
ppaction:// |
| Управляющие кнопки с действиями по умолчанию | P0 | — |
Встраивание шрифтов в .mpx/.pptx
(подмножество; только шрифты с разрешением на встраивание по
OS/2 fsType) |
P1 | ppt/fonts/*.fntdata |
| Автосохранение (журнал операций каждые 2 с), восстановление после сбоя, версии | P0 | — |
| Свойства документа, статистика (слайды, слова, медиа, размер), «проверка документа» (личные данные, скрытые слайды, заметки, комментарии) | P0 | — |
| Шаблоны и Hub: галерея шаблонов (≥ 40 своих), недавние, закреплённые | P0 | — |
Скрипты: вкладка «Скрипты», редактор, события презентации и показа,
кнопки [Home+] |
P0 | §6 |
Assist: конспект → слайды, переписать заметки, предложить дизайн,
alt-текст [Pro] |
P2 | фаза 7 |
3. Экраны
Идентификаторы: SL-01…SL-09 — виды и окна;
SL-10…SL-19 — боковые и нижние панели;
SL-20…SL-59 — диалоги; SL-60…SL-69 —
контекстные меню; SL-70+ — всплывающие элементы. Макет —
mockups/slides.html, по одному
<section class="screen"> на идентификатор.
3.1 SL-01 Обычный вид (Normal)
Каркас — по §5.3 библии. Слева — панель миниатюр (SL-10) шириной 160–320 px с разделами; в центре — холст слайда с полями 24 px, линейками (опц.) и направляющими; под холстом — панель заметок (SL-13, сворачиваемая); справа — боковая панель с вкладками (SL-11, SL-12, SL-14…). Строка состояния: «Слайд 3 из 24 · Раздел „Введение" · Тема „Меридиан" · Русский · [Заметки] [Комментарии] · режимы · масштаб · [Вписать]».
┌──────────────────────────────────────────────────────────────────────────────────────┐
│ [▶] Отчёт Q3.mpx — Meridian Slides [⌘K Поиск команд] [☁ Сохранено] [👤] │
├──────────────────────────────────────────────────────────────────────────────────────┤
│ Файл Главная Вставка Дизайн Переходы Анимации Показ Рецензирование Вид Скрипты │ Формат фигуры │
│ [Слайды][Буфер][Шрифт][Абзац][Рисование][Редактирование] [⌄] │
├────────────┬──────────────────────────────────────────────────────┬──────────────────┤
│ ▾ Введение │ ┌────────────────────────────────────────────────┐ │ Формат фигуры │
│ ┌────────┐ │ │ │ │ ◇ Заливка │
│ │ 1 ▣ │ │ │ Итоги квартала │ │ ● Сплошная │
│ └────────┘ │ │ ───────────────────── │ │ ○ Градиент │
│ ┌────────┐ │ │ • Выручка +12 % │ │ ◇ Линия │
│ │ 2 ▣ ★ │ │ │ • Новые регионы: 3 │ │ ◇ Эффекты │
│ └────────┘ │ │ [диаграмма] │ │ ◇ Размер и полож.│
│ ▾ Финансы │ │ │ │ ◇ Текст │
│ ┌────────┐ │ └────────────────────────────────────────────────┘ │ │
│ │ 3 ▣ │ │ Заметки: Напомнить про сроки аудита… [▲] │ │
├────────────┴──────────────────────────────────────────────────────┴──────────────────┤
│ Слайд 2 из 24 · Финансы · Русский [Заметки] [Комментарии] ▦ ▤ ▥ ▶ ─●─ 85 % ⤢ │
└──────────────────────────────────────────────────────────────────────────────────────┘
Элементы холста: рамка выделения с 8 маркерами размера, маркером
поворота (сверху), жёлтыми регуляторами формы, нумерованные метки
анимаций слева от фигур (при открытой панели «Анимация»), умные
направляющие (цвет --m-sun), направляющие слайда
(перетаскиваемые, с подписью координаты), сетка, рамки заполнителей
пунктиром, значок «автоподбор» у переполненной фигуры, мини-панель
форматирования при выделении текста, значки комментариев в углах
фигур.
3.2 Остальные виды и окна
| ID | Экран | Описание |
|---|---|---|
| SL-02 | Сортировщик слайдов | сетка миниатюр (размер по масштабу 15–100 %), заголовки разделов с
кнопками сворачивания, под миниатюрой — номер, значок перехода (★),
время (advTm), значок «скрыт»; перетаскивание со вставочной
чертой; мультивыбор; клавиши как в проводнике; двойной клик → SL-01 |
| SL-03 | Структура | слева вместо миниатюр — дерево заголовков и текста заполнителей (уровни), правка текста прямо в структуре, повышение/понижение, развернуть/свернуть; фигуры без заполнителей не показываются |
| SL-04 | Страницы заметок | страница (A4/Letter по образцу заметок): изображение слайда сверху, тело заметок снизу, колонтитулы; масштаб, правка текста заметок и свободных объектов |
| SL-05 | Образец слайдов | панель миниатюр: образцы (крупные) и их макеты (отступом); холст образца/макета; контекстная вкладка «Образец слайдов» (вставить образец/макет, удалить, переименовать, сохранить, макет образца: показать/скрыть заполнители, вставить заполнитель▾, заголовок/колонтитулы, темы, фон, размер слайда, закрыть); макеты с индикатором «используется N слайдами» |
| SL-06 | Образец заметок | заполнители: изображение слайда, тело, верхний/нижний колонтитул, дата, номер; ориентация, фон |
| SL-07 | Образец выдач | число слайдов на странице (1/2/3/4/6/9/структура), ориентация страницы/слайдов, колонтитулы, фон |
| SL-08 | Режим чтения (показ в окне) | слайды в окне с панелью навигации внизу (назад/вперёд/меню/завершить), без ribbon; реагирует на размер окна |
| SL-09 | Показ и режим докладчика | Окно показа: полноэкранное на выбранном экране, чёрные поля при несовпадении пропорций, скрытая панель инструментов в левом нижнем углу (появляется при движении мыши: назад, перо▾, лупа, сетка слайдов, субтитры, меню, вперёд). Окно докладчика: вверху — таймер (старт/пауза/сброс), часы, индикатор «Экран N»; слева большой текущий слайд (с рукописными инструментами), справа сверху — следующий слайд/шаг («Далее: анимация 3 из 5»), справа снизу — заметки с кнопками A+/A−; внизу — лента миниатюр с номерами и разделами, кнопки «Чёрный экран», «Обмен экранов», «Показать панель задач», «Завершить». Клавиши — §8 |
3.3 Ribbon — вкладки и группы
| Вкладка | Группы (команды) |
|---|---|
| Файл (backstage) | Создать (шаблоны и темы Hub), Открыть, Сведения (защита, проверка, свойства, версии, встроенные шрифты, медиа: сжать/оптимизировать), Сохранить, Сохранить как, Экспорт (PDF, видео, изображения, выдачи в Write, HTML), Печать (SL-27), Поделиться (фаза 6), Параметры (SL-40), Аккаунт/Лицензия |
| Главная | Слайды (создать слайд▾, макет▾, сбросить, раздел▾) · Буфер обмена
(вставить▾, вырезать, копировать, формат по образцу) · Шрифт (гарнитура,
размер, увеличить/уменьшить, очистить формат, Ж/К/Ч/S, тень,
межзнаковый▾, регистр▾, цвет▾) · Абзац (маркеры▾, нумерация▾, уровень
−/+, интервал▾, направление▾, выравнивание ×4, колонки▾, выровнять
текст▾, преобразовать в диаграмму-схему▾) · Рисование (галерея фигур,
упорядочить▾, экспресс-стили▾, заливка▾, контур▾, эффекты▾) ·
Редактирование (найти, заменить▾, выделить▾) · Assist
[Pro] |
| Вставка | Слайды (создать слайд▾, повторное использование) · Таблицы (таблица▾) · Изображения (рисунки▾, снимок▾, фотоальбом P2) · Иллюстрации (фигуры▾, значки, диаграмма-схема, диаграмма) · Ссылки (гиперссылка, действие, масштаб слайдов P2) · Примечания (комментарий) · Текст (надпись, колонтитулы, WordArt▾, дата и время, номер слайда, объект Math) · Символы (формула▾, символ) · Мультимедиа (видео▾, звук▾, запись экрана P2) · Скрипты (кнопка) |
| Дизайн | Темы (галерея, цвета▾, шрифты▾, эффекты▾, фон▾) · Варианты (4 варианта) · Настроить (размер слайда▾, формат фона → SL-12, дизайнерские идеи P1) |
| Переходы | Просмотр (просмотр) · Переход к этому слайду (галерея из §2.12, параметры эффекта▾) · Время показа (звук▾, длительность, применить ко всем; смена слайда: по щелчку, через N с) |
| Анимации | Просмотр (просмотр▾) · Анимация (галерея: вход/выделение/выход/пути; параметры эффекта▾) · Расширенная анимация (добавить анимацию▾, область анимации → SL-11, триггер▾, по образцу) · Время показа (начало▾, длительность, задержка, порядок: раньше/позже) |
| Показ | Начать показ (с начала, с текущего, в режиме докладчика, произвольный показ▾, по сети P2) · Настройка (настройка показа → SL-21, скрыть слайд, репетиция, записать▾ → SL-23, воспроизвести закадровый текст, использовать время, показывать элементы управления) · Мониторы (экран показа▾, режим докладчика ☑) · Субтитры (P2) |
| Рецензирование | Правописание (орфография, тезаурус, статистика) · Доступность (проверка, alt-текст) · Язык (перевести P2, язык▾) · Примечания (создать, удалить▾, предыдущее, следующее, показать панель) · Сравнить (сравнить P1, принять▾, отклонить▾, далее/назад, панель, завершить) · Рукописный ввод (начать, скрыть P1) · Защита (пароль, только чтение, окончательный, подпись) |
| Вид | Режимы просмотра (обычный, структура, сортировщик, страницы заметок, чтение) · Режимы образцов (образец слайдов, заметок, выдач) · Показать (линейка, сетка, направляющие, заметки, параметры сетки → SL-29) · Масштаб (масштаб, вписать) · Цвет/оттенки серого (цвет, серый, ч/б — предпросмотр печати) · Окно (новое окно, упорядочить, каскад, переключить) · Фокус |
Скрипты [Home+] |
Код (редактор скриптов, записать действия, остановить, выполнить▾, отладчик) · Презентация (скрипты документа, события: открытие/показ/смена слайда/клик, расписания) · Кнопки (кнопка на слайде, в ленте, назначить действие) · Безопасность (разрешения, подписи, политики) |
| Формат фигуры (контекст) | Вставка фигур (галерея, изменить фигуру▾, объединить▾ P1, надпись) · Стили фигур (галерея, заливка▾, контур▾, эффекты▾) · Стили WordArt (галерея, заливка▾, контур▾, эффекты▾) · Специальные возможности (alt-текст) · Упорядочение (вперёд▾, назад▾, область выделения, выровнять▾, группировать▾, повернуть▾) · Размер (высота, ширина, дополнительно → SL-12) |
| Формат рисунка (контекст) | Изменение (удалить фон P1, коррекция▾, цвет▾, художественные эффекты P2, прозрачность▾, сжать, заменить▾, сброс▾) · Стили рисунков (галерея, граница▾, эффекты▾, макет рисунка — в диаграмму-схему▾) · Специальные возможности · Упорядочение · Размер (обрезка▾, высота, ширина) |
| Конструктор таблиц / Макет таблицы (контекст) | Параметры стиля · Стили таблиц · Стили WordArt · Нарисовать границы ‖ Таблица (выделить▾, сетка) · Строки и столбцы (удалить▾, вставить ×4) · Объединение · Размер ячейки · Выравнивание · Размер таблицы · Упорядочение |
| Конструктор диаграмм / Формат (контекст) | как в Sheets (docs/apps/sheets.md §3.2): макеты, стили,
данные (изменить данные → панель, выбрать данные, строка/столбец,
обновить связь), тип ‖ Формат |
| Конструктор диаграммы-схемы / Формат (контекст) | Создание рисунка (добавить фигуру▾, маркер, справа налево, макет▾, повысить/понизить, вверх/вниз, область текста) · Макеты (галерея) · Стили (цвета▾, галерея стилей) · Сброс (восстановить, преобразовать▾) ‖ Фигуры (в 2D-режиме, изменить фигуру▾, крупнее/мельче) · Стили фигур · Стили WordArt · Упорядочение · Размер |
| Формат видео / Воспроизведение (контекст) | Просмотр · Коррекция (яркость, цвет, заставка▾, сброс▾) · Стили видео (галерея, форма▾, граница▾, эффекты▾) · Упорядочение · Размер (обрезка) ‖ Закладки (добавить, удалить) · Редактирование (монтаж → SL-32, появление/исчезание) · Параметры (громкость▾, начало▾, во весь экран, скрыть пока не воспроизводится, непрерывно, перемотать) · Субтитры P2 |
| Формат звука / Воспроизведение (контекст) | Стили рисунка (значок) ‖ Закладки · Монтаж · Появление/исчезание · Параметры (громкость, начало, для всех слайдов, непрерывно, скрыть при показе, перемотать) · Стили звука (в фоне, нет стиля) |
| Образец слайдов / Образец заметок / Образец выдач (контекст) | см. SL-05…SL-07 |
| Запись (контекст, при открытой SL-23) | Запись (с текущего слайда, с начала) · Содержимое (снимок экрана P2, запись экрана P2) · Автовоспроизведение (воспроизвести, очистить▾) · Сохранить (экспорт в видео, опубликовать P2) |
Компактный режим и командная палитра — по §5.3 библии. Палитра в Slides дополнительно ищет слайды по заголовку («перейти к слайду „Бюджет"»), фигуры по имени и анимации.
3.4 Панели
| ID | Панель | Описание |
|---|---|---|
| SL-10 | Миниатюры слайдов (слева) | вертикальный список с номерами, значками «скрыт»/«переход»/«анимация»/«комментарии»/«скрипт», заголовки разделов (свернуть/развернуть, контекстное меню раздела), перетаскивание, мультивыбор (Ctrl/Shift), масштаб миниатюр (Ctrl+колесо), кнопка «Структура» переключает в SL-03; при совместной работе — аватары редакторов на миниатюрах |
| SL-11 | Анимация (справа) | верх: список эффектов (номер, значок типа, имя фигуры,
триггер-группы «Триггер: Фигура 5»), перетаскивание порядка, ▶
«Воспроизвести с/все», кнопки раньше/позже; низ: таймлайн — шкала секунд
(масштаб ×0,5…×8), полоски эффектов (цвет по типу: вход зелёный,
выделение жёлтый --m-sun, выход красный, путь синий),
перетаскивание начала/длины, маркеры щелчков, звуки; двойной клик по
эффекту → SL-24 «Параметры эффекта» |
| SL-12 | Формат фигуры / рисунка / фона / текста (справа) | аккордеон: Заливка, Линия, Эффекты (тень/отражение/свечение/мягкие края/рельеф P2/поворот 3D P2), Размер и свойства (размер, положение, надпись: привязка, поля, автоподбор, колонки; alt-текст), Рисунок (коррекция, цвет, обрезка); для фона — «Формат фона» с «применить ко всем» и «сбросить»; для текста — заливка/контур/эффекты текста |
| SL-13 | Заметки (внизу) | многострочный редактор Write, высота перетаскиванием (запоминается), кнопка разворота, счётчик слов |
| SL-14 | Комментарии (справа) | карточки по слайду: автор, время, текст, ответы, «решено», якорь (клик — подсветка фигуры), «Создать», фильтр (все/открытые/мои), навигация по слайдам с комментариями |
| SL-15 | Макеты / Дизайнерские идеи (справа) | вкладка «Макеты»: галерея макетов текущего образца (клик — применить); вкладка «Идеи» P1: 6–12 вариантов раскладки текущего слайда (миниатюры), «Ещё», применение с отменой |
| SL-16 | Выделение (справа) | дерево фигур слайда (группы раскрываются) в z-порядке, видимость (глаз), переименование, перетаскивание порядка, блокировка; порядок чтения для доступности = обратный z-порядок с ручной правкой |
| SL-17 | Данные диаграммы (справа) | мини-таблица Sheets (grid-model) для встроенных данных: правка ячеек, добавить/удалить ряды, «переключить строки/столбцы», «открыть в Sheets», связь с файлом |
| SL-18 | Повторное использование слайдов (справа) P1 | выбор файла, миниатюры, «сохранить исходное форматирование», клик — вставить после текущего |
| SL-19 | Текст диаграммы-схемы (плавающая у объекта) | структура узлов с уровнями, маркеры, подсказки клавиш |
| SL-70 | Мини-панель форматирования | при выделении текста/фигуры: шрифт, размер, Ж/К/Ч, цвет, выравнивание, маркеры, заливка/контур, «ещё…» |
| SL-71 | Кнопка «Параметры автоподбора» | у переполненного заполнителя: сжать текст / остановить / разделить на два слайда / продолжить на новом / изменить на два столбца |
| SL-72 | Панель репетиции | поверх показа: ▶/⏸, время слайда, ↻ повторить, общее время, «Далее» |
| SL-73 | Панель инструментов показа | полупрозрачная в левом нижнем углу окна показа |
3.5 Диалоги
| ID | Диалог | Содержимое |
|---|---|---|
| SL-20 | Параметры слайда (размер) | список пресетов (16:9, 4:3, 16:10, A4, A3, Letter, Ledger, B4, B5, 35 мм, баннер, свой), ширина/высота (см/дюйм/px), ориентация слайдов и заметок, нумерация с, при уменьшении: «вписать» / «по максимуму» с предпросмотром |
| SL-21 | Настройка показа | тип (докладчик / окно / киоск), параметры (непрерывный цикл до Esc, без закадрового текста, без анимации, отключить GPU-переходы), цвет пера/лазера, слайды (все / с N по M / произвольный показ), смена слайдов (вручную / по времени), мониторы (экран показа, режим докладчика), разрешение |
| SL-22 | Произвольный показ | список показов; создать/изменить: имя, два списка (слайды презентации → слайды показа) с добавлением/удалением/порядком; «Показать» |
| SL-23 | Запись показа (окно) | полноэкранное окно: предпросмотр слайда, заметки, устройства (микрофон, камера P1, уровень), кнопки Запись/Пауза/Стоп/Повтор, таймер, перо/лазер, навигация, «Очистить» ▾ (запись на слайде / все), по закрытии — сохранение хронометража |
| SL-24 | Параметры эффекта | вкладки: Эффект (направление/вариант, количество, плавное начало/конец, отскок, звук, после анимации, анимация текста), Время (начало, задержка, длительность, повтор, перемотка, триггеры), Анимация текста/диаграммы/схемы (группировка: как один объект / по абзацам уровня N / по сериям / по ветвям; порядок, обратный порядок, задержка между элементами, анимировать прикреплённую фигуру) |
| SL-25 | Экспорт видео [Pro] |
формат (MP4 H.264 / WebM VP9), качество (4K / Full HD / HD / SD — таблица битрейтов), к/с (30/60), источник времени (записанные / N с на слайд), использовать закадровый текст и лазер, диапазон (все / раздел / с-по), папка/имя, оценка размера и длительности, «Экспортировать» с прогрессом в фоне |
| SL-26 | Колонтитулы | вкладки Слайд / Заметки и выдачи: дата и время (автообновление: формат из 13, язык, календарь; фиксированная), номер слайда, нижний колонтитул (текст), верхний колонтитул (заметки), «не показывать на титульном», предпросмотр положения; «Применить» / «Применить ко всем» |
| SL-27 | Печать выдач | принтер и свойства (Meridian Print), что печатать (слайды / страницы заметок / структура / выдачи 1–9 с порядком), диапазон (все / текущий / выделенные / с-по / разделы), копии, разобрать, цвет, рамка, вписать, скрытые слайды, комментарии и рукописный ввод, предпросмотр справа |
| SL-28 | Гиперссылка / Действие | гиперссылка: файл/веб-страница, место в документе (список слайдов с миниатюрами, произвольные показы), адрес эл. почты, текст, подсказка; действие по щелчку/наведению: нет, переход▾, запуск программы (запрещено политикой по умолчанию), запуск скрипта▾, звук▾, выделить |
| SL-29 | Сетка и направляющие | привязка к сетке, к фигурам (умные направляющие), шаг сетки (0,1–5 см, пресеты 1/8…1/2 дюйма), показывать сетку, направляющие (вертикальные/горизонтальные, добавить/удалить, цвет), применить к образцу |
| SL-30 | Вставка таблицы | столбцы/строки (1–75) |
| SL-31 | Вставка видео / звука | из файла, из буфера, по ссылке (онлайн P1), «связать с файлом», сжать при вставке |
| SL-32 | Монтаж видео/звука | временная шкала с миниатюрами кадров/формой волны, маркеры начала/конца с полями времени, предпросмотр, кнопки покадровой навигации |
| SL-33 | Параметры переходов | звук (список 19 встроенных + «другой…», «непрерывно»), длительность, смена слайда |
| SL-34 | Диаграмма-схема — выбор макета | слева категории, в центре галерея, справа крупный пример с описанием |
| SL-35 | Вставка диаграммы | типы Meridian Chart с подтипами и предпросмотром на данных-образце |
| SL-36 | Сравнение презентаций P1 | выбор файла, отчёт: список изменений (слайд, тип, описание), принять/отклонить |
| SL-37 | Сжатие медиа | целевое качество, оценка экономии, прогресс |
| SL-38 | Встраивание шрифтов P1 | список использованных шрифтов, лицензия на встраивание (разрешено/только предпросмотр/запрещено), подмножество/все символы |
| SL-39 | Замена шрифтов | «заменить» → «на» по всей презентации |
| SL-40 | Параметры Slides | общие (единицы, язык), правка (автоподбор по умолчанию, умные направляющие, вставка), сохранение (формат по умолчанию, автосохранение, встраивать шрифты), показ (экраны, подсказки, конец показа чёрным), дополнительно (GPU, кэш миниатюр, качество рисунков), скрипты |
| SL-41 | Параметры автоподбора текста | для фигуры: не автоподбирать / сжимать при переполнении / подгонять размер фигуры |
| SL-42 | Произвольный путь — редактирование | редактор узлов пути перемещения (общий редактор Draw) с привязкой к центру фигуры, «замкнуть», «обратить» |
| SL-43 | Экспорт изображений | формат (PNG/JPG/SVG/WebP), слайды (все/текущий/диапазон), размер (ширина px или dpi), прозрачный фон (PNG), папка, шаблон имени |
| SL-44 | Защита: пароль / только чтение / подпись | как в Write |
| SL-45 | Фотоальбом P2 | источник, раскладка, подписи, порядок |
| SL-46 | Пульт докладчика [Pro] P1 |
QR-код и адрес, подключённые устройства, отключить |
| SL-60 | Контекстное меню слайда (миниатюра) | создать, дублировать, удалить, скрыть, макет▾, сбросить, добавить раздел, переименовать раздел, формат фона, новый комментарий, вставить▾ |
| SL-61 | Контекстное меню фигуры | вырезать/копировать/вставить▾, группировать▾, на передний/задний план▾, гиперссылка, сохранить как рисунок, изменить замещающий текст, размер и положение, формат фигуры, заблокировать, добавить анимацию▾ |
| SL-62 | Контекстное меню показа | далее, назад, последний просмотренный, показать все слайды, лупа, произвольный показ▾, показать режим докладчика, экран▾ (чёрный/белый/панель задач), указатель▾ (лазер/стрелка/перо/маркер/ластик/цвет), субтитры P2, справка, пауза/продолжить, завершить |
4. Модель данных
4.1 Пакет .mpx
mimetype application/vnd.meridian.slides (без сжатия, первым)
manifest.xml список частей, версия формата, роль (document|template), наличие скриптов/подписей
meta.xml Dublin Core + статистика (слайды, слова, медиа), приложение-создатель
presentation.xml корень: размер слайда, порядок слайдов, разделы, произвольные показы, настройки показа,
стиль текста по умолчанию, ссылки на образцы и темы
masters/master-<ulid>.xml образец слайдов (фон, заполнители, стили текста, карта цветов, список макетов)
layouts/layout-<ulid>.xml макет (ссылка на образец, тип, заполнители)
slides/slide-<ulid>.xml слайд (ссылка на макет, дерево фигур, фон, переход, таймлайн анимаций, заметки, комментарии)
themes/theme-<ulid>.xml тема DrawingML-подобной структуры (цвета, шрифты, эффекты)
notes-master.xml, handout-master.xml
styles.xml стили таблиц, стили фигур по умолчанию, именованные стили текста
settings.xml вид, масштаб, последний слайд, параметры сетки, кэш репетиции
media/<sha256>.<ext> изображения, видео, аудио (большие — stored, без deflate)
objects/chart-<ulid>.msx данные диаграмм, objects/table-<ulid>.msx — связанные таблицы, objects/*.meq — формулы
diagrams/diagram-<ulid>.xml модель диаграммы-схемы (узлы + макет + стиль)
thumbnails/slide-<ulid>.png кэш миниатюр (опционально), thumbnail.png — первый слайд 256 px
history/ журнал CRDT-операций (опционально)
scripts/, signatures/, fonts/ скрипты, подписи, встроенные подмножества шрифтов (WOFF2)
Идентификаторы — ULID (сортируемые, уникальные между документами) для
слайдов/образцов/макетов и u32 для фигур внутри слайда (как
p:cNvPr/@id, сохраняются при round-trip pptx). Пример
слайда:
<slide xmlns="urn:meridian:office:slides:1" id="01J9QZ3M7P6V8R2TQX4W5Y6Z7A" layout="01J9QZ…" hidden="false">
<background><solidFill color="scheme:bg1"/></background>
<shapes>
<sp id="2" name="Заголовок 1" ph="title">
<xfrm x="838200" y="365125" w="10515600" h="1325563"/>
<txBody><bodyPr anchor="b" autofit="shrink"/><p><r rPr.sz="4400">Итоги квартала</r></p></txBody>
</sp>
<sp id="3" name="Текст 2" ph="body" phIdx="1">
<xfrm x="838200" y="1825625" w="10515600" h="4351338"/>
<txBody><p lvl="0"><r>Выручка +12 %</r></p><p lvl="0"><r>Новые регионы: 3</r></p></txBody>
</sp>
<graphicFrame id="4" name="Диаграмма 3"><xfrm …/><chart ref="objects/chart-01J9…msx" model="charts/chart-01J9….xml"/></graphicFrame>
</shapes>
<transition kind="push" dir="l" dur="700" advClick="true" advTm="5000"/>
<timing>…(§4.6)…</timing>
<notes><p><r>Напомнить про сроки аудита</r></p></notes>
</slide>4.2 Структуры ядра
(Rust, meridian-slides)
// kernel/crates/meridian-slides/src/model.rs
use meridian_scene::{Shape, ShapeId, ShapeTree, Fill, Theme, ColorMap, TextStyleLevels};
/// Презентация — корень документа / Presentation document root.
pub struct Presentation {
pub id: Ulid,
pub size: SlideSize, // ширина/высота в EMU, тип пресета / width/height in EMU
pub masters: IndexMap<Ulid, SlideMaster>,
pub layouts: IndexMap<Ulid, SlideLayout>,
pub slides: Vec<Ulid>, // порядок слайдов / slide order
pub slide_store: IndexMap<Ulid, Slide>,
pub sections: Vec<Section>, // раздел = имя + диапазон слайдов / name + slide range
pub custom_shows: Vec<CustomShow>,
pub notes_master: NotesMaster,
pub handout_master: HandoutMaster,
pub themes: IndexMap<Ulid, Theme>,
pub default_text_style: TextStyleLevels,
pub show_settings: ShowSettings, // тип показа, цикл, экраны / show type, loop, screens
pub media: MediaStore, // sha256 → MediaEntry (путь, mime, размер, длительность)
pub comments: CommentStore, // комментарии по слайдам / per-slide comments
pub meta: DocMeta,
}
pub struct SlideMaster {
pub id: Ulid,
pub theme: Ulid,
pub color_map: ColorMap, // bg1→lt1, tx1→dk1, … / scheme-to-theme mapping
pub background: Background,
pub shapes: ShapeTree, // общие фигуры + заполнители с полным форматированием
pub text_styles: MasterTextStyles, // title, body (9 уровней), other
pub layouts: Vec<Ulid>,
pub transition: Option<Transition>,
pub timing: Option<AnimTimeline>,
pub header_footer: HeaderFooter,
}
pub struct SlideLayout {
pub id: Ulid,
pub master: Ulid,
pub kind: LayoutKind, // 36 типов ST_SlideLayoutType + Custom
pub name: String,
pub shapes: ShapeTree, // заполнители макета (ph type/idx) и фоновые фигуры
pub show_master_shapes: bool,
pub background: Option<Background>,
pub preserve: bool, // не удалять при неиспользовании / keep when unused
}
pub struct Slide {
pub id: Ulid,
pub layout: Ulid,
pub shapes: ShapeTree, // дерево фигур в z-порядке / shape tree in z-order
pub background: Option<Background>,
pub show_master_shapes: bool,
pub transition: Option<Transition>,
pub timing: Option<AnimTimeline>, // §4.6
pub notes: Option<NotesSlide>,
pub hidden: bool,
pub advance_ms: Option<u32>, // хронометраж репетиции / rehearsed advance time
pub narration: Option<MediaRef>, // закадровый голос / recorded narration
pub revision: u64, // для инвалидации миниатюр / thumbnail invalidation
}
/// Дерево фигур: плоское хранилище + порядок детей; группы — узлы с детьми.
pub struct ShapeTree {
pub nodes: SlotMap<ShapeId, ShapeNode>,
pub roots: Vec<ShapeId>, // z-порядок: первый — самый нижний / first = bottom-most
}
pub struct ShapeNode { pub shape: Shape, pub parent: Option<ShapeId>, pub children: Vec<ShapeId> }
pub enum ShapeKind {
Sp { geom: Geometry, text: Option<TextBody> }, // фигура с текстом / shape with text
Pic { media: MediaRef, crop: SrcRect, effects: PicEffects },
GraphicFrame(GraphicContent), // Table | Chart | Diagram | Ole | Math
Cxn { geom: Geometry, start: Option<CxnEnd>, end: Option<CxnEnd> },
Grp { child_xfrm: ChildTransform }, // группа: своя система координат
Media { media: MediaRef, poster: Option<MediaRef>, playback: Playback },
}
pub struct Shape {
pub id: ShapeId, // = p:cNvPr/@id при round-trip
pub name: String,
pub kind: ShapeKind,
pub xfrm: Transform2D, // off, ext, rot (1/60000°), flipH, flipV
pub placeholder: Option<Placeholder>, // type, idx, orient, size
pub style: ShapeStyleRefs, // lnRef/fillRef/effectRef/fontRef (idx + цвет)
pub props: ShapeProps, // fill, line, effects, scene3d/sp3d (P2)
pub hyperlink: Option<Action>,
pub hover: Option<Action>,
pub locks: Locks, // noGrp, noMove, noResize, noSelect, noTextEdit, …
pub alt_text: AltText,
pub hidden: bool,
pub ext: Vec<ExtensionBlob>, // неизвестные расширения — round-trip / unknown extensions
}
pub struct Placeholder { pub kind: PlaceholderType, pub idx: Option<u32>, pub orient: Orient, pub size: PhSize, pub has_custom_prompt: bool }4.3 Текстовое тело
TextBody — тот же тип, что в Write
(text-model): BodyProps (вставки, привязка,
перенос, направление, колонки, автоподбор, деформация),
ListStyle (9 уровней ParaProps),
Vec<Paragraph>;
Paragraph { props, runs },
Run { text, props: RunProps } | Field { kind: SlideNum | DateTime(fmt), props } | LineBreak | MathInline(ref).
Единицы: размер шрифта в 1/100 pt, отступы и интервалы в EMU или
процентах — как в DrawingML, чтобы round-trip был без округлений.
4.4 Геометрия и стили
(из meridian-scene)
pub enum Geometry {
Preset { kind: PresetShape /* 187 вариантов */, adj: SmallVec<[(AdjName, i64); 8]> },
Custom { paths: Vec<GeomPath>, guides: Vec<Guide>, adj: Vec<(AdjName, i64)>, cxn: Vec<CxnSite>, text_rect: Option<GuideRect> },
}
pub enum Fill { None, Solid(Color), Gradient(Gradient), Blip(BlipFill), Pattern { preset: PatternPreset, fg: Color, bg: Color }, Group /* наследовать от группы */ }
pub enum Color { Srgb(u32), Scheme { name: SchemeColor, mods: Vec<ColorMod> }, Preset(PresetColor), Hsl(..), System(..) }
pub struct Line { pub width_emu: i64, pub fill: Fill, pub dash: DashPreset | Custom(Vec<(u32,u32)>), pub cap: Cap, pub join: Join, pub compound: Compound, pub head: Arrow, pub tail: Arrow }
pub struct Effects { pub shadow: Option<Shadow>, pub reflection: Option<Reflection>, pub glow: Option<Glow>, pub soft_edge: Option<i64>, pub blur: Option<Blur> }Цвета разрешаются в sRGB только при рендере:
Color::resolve(theme, color_map); модификаторы
(lumMod, lumOff, tint,
shade, alpha, satMod,
hueOff …) применяются в порядке записи, как в
DrawingML.
4.5 Наследование свойств заполнителей (master → layout → slide)
Поиск «родителя» заполнителя:
- Фигура слайда с
placeholder{kind, idx}ищет в макете заполнитель с тем жеidx; еслиidxнет — с тем жеkind(дляkind ∈ {title, ctrTitle}ищетсяtitle/ctrTitle; дляbody/obj/tbl/chart/dgm/media/pic/clipArt—body). - Заполнитель макета ищет в образце по
kind(все «телесные» типы →body;dt,ftr,sldNum— по своему типу). - Для текста к цепочке добавляются стили образца
(
titleStyle/bodyStyle/otherStyleпо уровню абзаца), затемdefault_text_styleпрезентации, затем тема (шрифты+mj-lt/+mn-lt, цвета схемы), затем встроенные значения (размер 18 pt, выравнивание влево, чёрныйtx1).
/// Разрешение свойств абзаца/символов по цепочке наследования /
/// Resolve paragraph/run properties along the inheritance chain.
pub fn resolve_run_props(ctx: &ResolveCtx, slide: &Slide, shape: &Shape, para: &Paragraph, run: &Run) -> ResolvedRunProps {
let lvl = para.props.level.unwrap_or(0) as usize;
// Цепочка от самого конкретного к общему / chain from most specific to most generic
let mut chain: SmallVec<[&RunProps; 8]> = smallvec![&run.props];
if let Some(pr) = para.props.default_run.as_ref() { chain.push(pr); } // a:pPr/a:defRPr
if let Some(list) = shape.text_list_style() { chain.extend(list.level(lvl).map(|l| &l.run)); }
for owner in ctx.placeholder_chain(slide, shape) { // layout ph → master ph
if let Some(list) = owner.text_list_style() { chain.extend(list.level(lvl).map(|l| &l.run)); }
}
chain.extend(ctx.master_text_style(slide, shape).level(lvl).map(|l| &l.run)); // titleStyle/bodyStyle/otherStyle
chain.extend(ctx.presentation.default_text_style.level(lvl).map(|l| &l.run));
let mut out = ResolvedRunProps::builtin(); // 18 pt, tx1, +mn-lt
for props in chain.iter().rev() { out.apply(props); } // общие → конкретные / generic → specific
out.resolve_colors(ctx.theme(slide), ctx.color_map(slide));
out
}Геометрия заполнителя (xfrm) наследуется так же: если у
фигуры слайда нет xfrm, берётся из макета, затем из
образца. «Сбросить слайд» удаляет на слайде всё, что совпадает с
унаследованным, сохраняя текст.
4.6 Таймлайн анимаций
(meridian-anim)
Структура повторяет дерево p:timing, чтобы
импорт/экспорт pptx был изоморфным; «плоские» списки для панели SL-11
вычисляются из дерева.
// kernel/crates/meridian-anim/src/timeline.rs
pub struct AnimTimeline { pub root: TimeNode /* nodeType=tmRoot, par */, pub builds: Vec<Build> /* bldP, bldChart, bldDgm */ }
pub struct TimeNode {
pub id: u32,
pub kind: NodeKind, // Par | Seq { concurrent, next_action, prev_action } | Behavior(Behavior)
pub node_type: NodeType, // TmRoot | MainSeq | ClickEffect | WithEffect | AfterEffect | ClickPar | WithGroup | AfterGroup | Interactive
pub start: Vec<Condition>, // stCondLst: Delay(ms) | Indefinite | OnClick(ShapeId) | OnBegin(NodeId) | OnEnd(NodeId) | OnNext | OnPrev | Bookmark(media, name)
pub end: Vec<Condition>,
pub duration: Duration, // Ms(u32) | Indefinite | Media
pub repeat: Repeat, // Count(f32) | Indefinite | UntilNextClick | UntilEndOfSlide
pub autoreverse: bool,
pub fill: FillMode, // Hold | Freeze | Remove | Transition
pub accel: u16, pub decel: u16, // 0..100000 (доли длительности) / fractions of duration
pub restart: Restart, // Always | WhenNotActive | Never
pub preset: Option<Preset>, // { class: Entr|Emph|Exit|Path|Verb|MediaCall, id: u16, subtype: u16 }
pub group_id: Option<u32>, // grpId — связь с bldP / link to text build
pub target: Option<Target>, // фигура / абзац / фон / звук / видео
pub children: Vec<TimeNode>,
pub next_cond: Vec<Condition>, pub prev_cond: Vec<Condition>, // для Seq
}
pub enum Behavior {
Set { attr: AnimAttr, value: AnimValue }, // p:set
Anim { attr: AnimAttr, calc: CalcMode /* Discrete|Lin|Fmla */, keys: Vec<KeyFrame /* tm 0..100000, val|formula */>, by: Option<AnimValue>, from: Option<AnimValue>, to: Option<AnimValue> },
Effect { transition: InOut, filter: String /* "fade", "wipe(left)", "wheel(4)" … */, progress: Option<Vec<KeyFrame>> }, // p:animEffect
Motion { path: MotionPath /* M L C Z E в долях слайда */, origin: Origin, rotate_along: bool, path_edit_mode: EditMode, by_x: f32, by_y: f32 },
Rotate { by: Option<i32>, from: Option<i32>, to: Option<i32> }, // 1/60000°
Scale { by: Option<(f32,f32)>, from: Option<(f32,f32)>, to: Option<(f32,f32)>, zoom_contents: bool },
Color { space: ColorSpace /* rgb|hsl */, dir: HueDir, by: Option<ColorDelta>, from: Option<Color>, to: Option<Color> },
Command { kind: CmdKind /* Call|Evt|Verb */, cmd: String /* playFrom(0.0), togglePause, stop */ },
Audio { media: MediaRef, is_narration: bool },
Video { media: MediaRef, full_screen: bool },
}
pub enum AnimAttr { PptX, PptY, PptW, PptH, PptR, Visibility, FillColor, FillOn, LineColor, LineOn, Opacity, TextFontSize, TextBold, TextItalic, TextUnderline, TextColor, Custom(SmolStr) }Соответствие с панелью SL-11: один «эффект» = поддерево
ClickEffect|WithEffect|AfterEffect с preset;
его «щелчок» = индекс ClickPar-предка в
MainSeq; «начало» вычисляется из node_type;
задержка/длительность — из start/duration.
4.7 Переходы, показ, запись
pub struct Transition { pub kind: TransitionKind /* 51 вариант §2.12 */, pub params: TransitionParams /* dir, orient, spokes, thru_black, pattern, … */, pub duration_ms: u32, pub sound: Option<TransitionSound>, pub advance_on_click: bool, pub advance_after_ms: Option<u32> }
pub struct ShowSettings { pub kind: ShowKind /* Presenter | Window | Kiosk */, pub loop_: bool, pub show_narration: bool, pub show_animation: bool, pub use_timings: bool, pub range: ShowRange /* All | Range(a,b) | Custom(Ulid) */, pub pen_color: Color, pub laser_color: Color, pub gpu_transitions: bool, pub screen_policy: ScreenPolicy }
pub struct Narration { pub audio: MediaRef, pub ink: Vec<TimedStroke>, pub laser: Vec<TimedPoint>, pub clicks: Vec<(u32 /*ms*/, ClickKind)> }5. Алгоритмы
5.1
Вычисление геометрии prstGeom по формулам направляющих
Источник — presetShapeDefinitions.xml (ECMA-376, часть
1, приложение). При сборке build.rs крейта
meridian-scene разбирает его в статические таблицы
(PRESETS: [PresetGeom; 187]), поэтому в рантайме XML не
читается.
// kernel/crates/meridian-scene/src/preset_geom.rs
pub struct PresetGeom {
pub name: &'static str,
pub adj_defaults: &'static [(&'static str, i64)], // avLst
pub guides: &'static [Guide], // gdLst — уже в порядке вычисления / in evaluation order
pub adj_handles: &'static [AdjHandle], // ahLst: XY | Polar, диапазоны min/max
pub cxn_sites: &'static [CxnSite], // cxnLst: угол + точка (ссылки на направляющие)
pub text_rect: Option<GuideRect>, // rect: l, t, r, b
pub paths: &'static [PresetPath], // pathLst
}
pub struct Guide { pub name: &'static str, pub op: Op, pub a: Operand, pub b: Operand, pub c: Operand }
pub enum Op { MulDiv, AddSub, AddDiv, IfElse, Abs, At2, Cat2, Cos, Max, Min, Mod, Pin, Sat2, Sin, Sqrt, Tan, Val }
pub enum Operand { Lit(i64), Ref(u16) /* индекс в таблице значений */ }
pub struct PresetPath { pub w: Option<i64>, pub h: Option<i64>, pub fill: PathFill /* Norm|None|Lighten|LightenLess|Darken|DarkenLess */, pub stroke: bool, pub extrusion_ok: bool, pub cmds: &'static [PathCmd] }
pub enum PathCmd { MoveTo(Operand, Operand), LineTo(Operand, Operand), ArcTo { w_r: Operand, h_r: Operand, st_ang: Operand, sw_ang: Operand }, QuadTo([Operand; 4]), CubicTo([Operand; 6]), Close }Порядок вычисления значений (все — i64 в EMU; углы — в
1/60000 градуса, cd4 = 5400000):
- Встроенные:
w, h, l=0, t=0, r=w, b=h, hc=w/2, vc=h/2, ss=min(w,h), ls=max(w,h), долиwd2 … wd32,hd2 … hd32,ssd2 … ssd32, углыcd2=10800000, cd4, cd8, 3cd4, 3cd8, 5cd8, 7cd8. - Регуляторы
adjиз фигуры, иначеadj_defaults. - Направляющие
gdLstпоследовательно (формулы ссылаются только на ранее определённые — спецификация это гарантирует).
fn eval(op: Op, a: i64, b: i64, c: i64) -> i64 {
use Op::*;
match op {
MulDiv => mul_div(a, b, c), // a*b/c с i128 без переполнения / overflow-safe
AddSub => a + b - c,
AddDiv => (a + b) / c.max(1),
IfElse => if a > 0 { b } else { c },
Abs => a.abs(), Max => a.max(b), Min => a.min(b), Mod => (a*a + b*b + c*c).isqrt(),
Pin => b.clamp(a, c),
Sqrt => (a.max(0) as f64).sqrt() as i64,
Val => a,
Sin => (a as f64 * deg(b).sin()).round() as i64, // a·sin(b)
Cos => (a as f64 * deg(b).cos()).round() as i64,
Tan => (a as f64 * deg(b).tan()).round() as i64,
At2 => to_ang((b as f64).atan2(a as f64)), // atan2(b, a) в 1/60000°
Cat2 => (a as f64 * (c as f64).atan2(b as f64).cos()).round() as i64, // a·cos(atan2(c,b))
Sat2 => (a as f64 * (c as f64).atan2(b as f64).sin()).round() as i64, // a·sin(atan2(c,b))
}
}
/// Построение контура в системе координат фигуры (EMU) / Build outline in shape coordinates.
pub fn build_paths(geom: &PresetGeom, w: i64, h: i64, adj: &[(AdjName, i64)]) -> Vec<(kurbo::BezPath, PathStyle)> {
let vals = eval_guides(geom, w, h, adj);
geom.paths.iter().map(|p| {
// Масштаб из пространства пути в размер фигуры / scale path space to shape size
let sx = p.w.map_or(1.0, |pw| w as f64 / pw as f64);
let sy = p.h.map_or(1.0, |ph| h as f64 / ph as f64);
let mut out = kurbo::BezPath::new();
let mut cur = kurbo::Point::ZERO;
for cmd in p.cmds {
match *cmd {
PathCmd::MoveTo(x, y) => { cur = pt(&vals, x, y, sx, sy); out.move_to(cur); }
PathCmd::LineTo(x, y) => { cur = pt(&vals, x, y, sx, sy); out.line_to(cur); }
PathCmd::ArcTo { w_r, h_r, st_ang, sw_ang } => {
// Дуга эллипса от текущей точки: центр вычисляется так, чтобы текущая точка лежала на эллипсе
// под углом st_ang. Углы DrawingML — геометрические («по транспортиру»), переводим в параметрические:
// t = atan2(wR·sin θ, hR·cos θ). / DrawingML angles are geometric, convert to parametric.
let (rx, ry) = (vals.get(w_r) as f64 * sx, vals.get(h_r) as f64 * sy);
let (st, sw) = (deg(vals.get(st_ang)), deg(vals.get(sw_ang)));
let t0 = param_angle(st, rx, ry);
let center = kurbo::Point::new(cur.x - rx * t0.cos(), cur.y - ry * t0.sin());
let t1 = param_angle(st + sw, rx, ry) + if sw < 0.0 && param_angle(st+sw,rx,ry) > t0 { -std::f64::consts::TAU } else { 0.0 };
let arc = kurbo::Arc { center, radii: kurbo::Vec2::new(rx, ry), start_angle: t0, sweep_angle: t1 - t0, x_rotation: 0.0 };
arc.append_iter(0.1).for_each(|el| out.push(el)); // кубики Безье по четвертям / cubic segments
cur = arc.end(); // конечная точка дуги / arc end point
}
PathCmd::QuadTo([x1,y1,x,y]) => { let p1 = pt(&vals,x1,y1,sx,sy); cur = pt(&vals,x,y,sx,sy); out.quad_to(p1, cur); }
PathCmd::CubicTo([x1,y1,x2,y2,x,y]) => { let p1 = pt(&vals,x1,y1,sx,sy); let p2 = pt(&vals,x2,y2,sx,sy); cur = pt(&vals,x,y,sx,sy); out.curve_to(p1,p2,cur); }
PathCmd::Close => out.close_path(),
}
}
(out, PathStyle { fill: p.fill, stroke: p.stroke })
}).collect()
}Регуляторы (ahLst) дают маркеры на холсте: позиция
маркера вычисляется по направляющим, перетаскивание решает обратную
задачу (линейная для XY, через
atan2/расстояние для Polar) с ограничением
min/max. Точки соединения cxnLst используются
коннекторами (Draw/Slides) — тот же код. Текстовый прямоугольник
rect ограничивает раскладку текста. Результат
build_paths кэшируется по ключу
(preset, w, h, adj) (LRU 4 096 записей на документ).
Проверка: снимочные тесты всех 187 фигур при трёх размерах против
эталонов PowerPoint (SSIM ≥ 0,99).
5.2 Автоподбор текста (shrink-on-overflow)
Режимы bodyPr/autofit: none,
spAutoFit (фигура растёт/сжимается по тексту — высота =
высота раскладки + вставки),
normAutofit { font_scale: %, ln_spc_reduction: % }. Для
normAutofit масштаб ищется по «лестнице» PowerPoint, чтобы
значения совпадали с теми, что пишет PowerPoint (иначе при round-trip
текст «прыгает»):
const LADDER: &[(u16 /*fontScale %*/, u16 /*lnSpcReduction %*/)] = &[
(100,0), (100,10), (100,20), (92,20), (85,20), (77,20), (70,20), (62,20), (55,20), (47,20), (40,20), (32,20), (25,20),
];
/// Подбор масштаба: первый шаг лестницы, при котором текст помещается / first ladder step that fits.
pub fn autofit(body: &TextBody, rect: Rect, ctx: &LayoutCtx) -> (u16, u16) {
for &(fs, lr) in LADDER {
let layout = ctx.layout(body, rect.width(), FontScale(fs), LineSpacingReduction(lr));
if layout.height() <= rect.height() { return (fs, lr); }
}
*LADDER.last().unwrap() // не помещается даже при 25 % — остаётся переполнение / overflow remains
}Оптимизация: раскладка с масштабом 100 % — обычная; затем бинарный
поиск по индексу лестницы (монотонность высоты по масштабу выполняется),
т.е. ≤ 4 раскладки вместо 13. Пересчёт — при изменении
текста/размера/шрифта, с задержкой 50 мс при наборе.
spAutoFit при вертикальном тексте меняет ширину. Деформации
(prstTxWarp) P1: текст раскладывается в прямоугольник,
затем глифы отображаются через огибающую (верхняя/нижняя кривые Безье из
пресета) — та же техника, что у WordArt в Write.
5.3 Умные направляющие, привязки, равномерное распределение
Кандидаты привязки собираются при начале перетаскивания (и кэшируются до его конца):
pub struct SnapIndex { xs: Vec<(f64 /*x слайда*/, SnapSrc)>, ys: Vec<(f64, SnapSrc)>, gaps_x: Vec<Gap>, gaps_y: Vec<Gap> }
// xs/ys отсортированы; SnapSrc = Edge(ShapeId, Left|CenterX|Right) | SlideEdge | SlideCenter | Guide(id) | Grid
// Gap — расстояние между соседними (по проекции) фигурами: (a, b, size) для «равных интервалов»При движении: для перетаскиваемого прямоугольника берём 3
вертикальные линии (левая/центр/правая) и 3 горизонтальные; для каждой —
бинарный поиск ближайшего кандидата; выбираем минимальную дельту
|Δ| ≤ tol, где tol = 6 px / zoom; применяем
смещение, рисуем направляющую через обе фигуры (цвет
--m-sun, 1 px, с размерными засечками). Равные интервалы:
для пары соседей A, B на той же оси проверяем, образует ли
перетаскиваемая фигура интервал, равный gap(A,B) слева или
справа — при совпадении рисуем две скобки с подписью. Приоритет: центр
слайда > край слайда > направляющие > фигуры > равные
интервалы > сетка. При зажатом Alt привязка отключается.
При изменении размера — те же кандидаты для перемещаемого края. Поворот
привязывается к 0/15/…° при Shift. Распределение (команда
«Распределить по горизонтали»): сортировка по x,
gap = (span − Σw) / (n − 1), при n = 2 —
относительно слайда. Выравнивание относительно слайда или выделения — по
bounding box с учётом поворота (ось-ориентированный прямоугольник
повёрнутой фигуры).
5.4 Планировщик анимаций (60 кадров/с)
Дерево AnimTimeline при входе на слайд компилируется в
план: список треков с абсолютным временем относительно
«шага» (щелчка).
pub struct Track { pub target: Target, pub attr: AnimAttr, pub start_ms: f64, pub dur_ms: f64, pub repeat: Repeat, pub autoreverse: bool,
pub fill: FillMode, pub ease: Ease /* accel/decel → кусочно-квадратичная */, pub keys: Vec<KeyFrame>, pub calc: CalcMode }
pub struct Step { pub index: u32, pub tracks: Vec<Track>, pub total_ms: f64, pub media_cmds: Vec<(f64, MediaCmd)>, pub interactive: Option<ShapeId> }
pub struct Plan { pub steps: Vec<Step>, pub initial_state: SceneState /* фигуры с эффектом входа скрыты */ }
/// Компиляция: обход дерева, накопление задержек / compile tree into steps with absolute times.
fn compile(node: &TimeNode, t0: f64, step: &mut Step, plan: &mut Plan) {
let start = t0 + node.start.iter().filter_map(Condition::delay_ms).sum::<f64>();
match &node.kind {
NodeKind::Par => { for c in &node.children { compile(c, start, step, plan); } }
NodeKind::Seq { .. } => {
let mut t = start;
for c in &node.children {
if c.node_type == NodeType::ClickPar || c.start.iter().any(Condition::is_indefinite) {
plan.push_step(std::mem::take(step)); // новый щелчок / new click step
t = 0.0;
}
compile(c, t, step, plan);
t += c.total_duration(); // «после предыдущего» / "after previous"
}
}
NodeKind::Behavior(b) => step.tracks.push(Track::from_behavior(node, b, start)),
}
if let Some(sh) = node.interactive_trigger() { step.interactive = Some(sh); }
}Воспроизведение: ShowClock — монотонное время с момента
начала шага; кадр по vsync
QQuickWindow::beforeRendering:
pub fn sample(plan: &Plan, step: usize, t_ms: f64, base: &SceneState) -> SceneState {
let mut st = base.clone_shallow(); // COW: меняем только анимируемые атрибуты
for tr in &plan.steps[step].tracks {
let Some(local) = tr.local_time(t_ms) else { continue }; // учитывает repeat/autoreverse/fill
let u = tr.ease.apply(local / tr.dur_ms); // 0..1 с accel/decel
let v = match tr.calc { CalcMode::Discrete => tr.keys.step(u), CalcMode::Lin => tr.keys.lerp(u), CalcMode::Fmla => tr.keys.eval_formula(u, &st) };
st.apply(tr.target, tr.attr, v); // ppt_x/ppt_y — доли ширины/высоты слайда
}
st
}Ease: accel/decel в долях длительности —
кусочная функция (квадратичный разгон, линейная середина, квадратичное
торможение, площадь нормирована на 1); для «отскока» и пружины — пресеты
Bounce, Elastic, для плавных путей —
EaseInOutCubic. Пропуск кадров: состояние — функция
времени, поэтому задержки не накапливаются. Завершение шага — когда
t ≥ total_ms и нет бесконечных повторов; «после
предыдущего» между щелчками реализовано компиляцией. Тексты «по
абзацам/словам/буквам» разворачиваются при компиляции в N треков с
задержкой (bldP/@advAuto или % от длительности). Пути
движения: MotionPath → kurbo::BezPath в долях
слайда, точка по t — через параметризацию по длине дуги
(ParamCurveArclen), rotate_along —
касательная. Предпросмотр в редакторе — тот же планировщик с
виртуальными часами.
5.5 Переходы на GPU (Skia)
Каждый переход — Transition трейт:
prepare(from: &SkImage, to: &SkImage, params) -> Box<dyn TransitionFrame>,
draw(canvas, progress 0..1). Три семейства реализации:
- Шейдерные (
p:fade,wipe,push,split,blinds,checker,wheel,dissolve,randomBar, фигуры,glitter,ripple,warp,reveal,flash) —SkRuntimeEffectна SkSL с униформамиprogress,size,dir, двумя дочерними шейдерамиfrom/to(текстуры слайдов):
// meridian-transitions/shaders/wipe.sksl — появление / wipe
uniform shader from; uniform shader to; uniform float progress; uniform float2 size; uniform int dir; // 0 l,1 r,2 u,3 d
half4 main(float2 p) {
float u = dir == 0 ? p.x / size.x : dir == 1 ? 1.0 - p.x / size.x : dir == 2 ? p.y / size.y : 1.0 - p.y / size.y;
float edge = smoothstep(progress - 0.01, progress + 0.01, u); // мягкая кромка 1 % / 1 % soft edge
return mix(to.eval(p), from.eval(p), edge);
}Растворение: hash(floor(p / cell)) сравнивается с
progress; шашки/жалюзи — по fract координат
ячеек с чередованием; часы — по углу atan2; фигуры —
знаковые функции расстояния (круг, ромб, плюс). 2. 3D
(cube/prism, flip, doors,
switch, gallery, ferris,
conveyor, window, fallOver,
airplane, origami, flythrough,
prestige) — две (или больше) плоскости с текстурами,
рисуются через
canvas.concat(SkM44::perspective(...) * rotate * translate);
Skia поддерживает перспективные матрицы для drawImageRect;
порядок отрисовки — по глубине центра плоскости (painter's algorithm,
достаточно для 2–6 плоскостей); освещение — множитель яркости по
косинусу угла. 3. Сетки вершин (drape,
curtains, crush, peelOff,
pageCurl*) — canvas.draw_vertices с сеткой
64×36, UV в текстуру слайда, вершины смещаются аналитически (скручивание
— цилиндр радиуса r(t), занавес — синусоида с затуханием).
fracture/shred/vortex/honeycomb
— предрассчитанные тайлы/осколки (Вороной из 60–120 точек), каждый
рисуется с собственной трансформацией.
Производительность: текстуры from/to
рендерятся заранее (при входе в слайд — следующий слайд уже отрисован),
переход занимает ≤ 2 draw-вызовов на кадр для шейдеров и ≤ 150 для
тайлов; целевое 60 к/с при 4K на интегрированной графике (Iris Xe/Apple
M1). Без GPU (Skia CPU): шейдерные переходы работают
(медленнее, при 1080p ~ 25–40 к/с), 3D и сетки заменяются на
fade. Политика выбора:
ShowSettings.gpu_transitions && backend.is_gpu().
5.6 Раскладка диаграмм-схем
Модель:
Diagram { kind: DiagramKind, root: DNode, style: DiagramStyle, dir: Ltr|Rtl, font_scale: u16 },
DNode { id, text: TextBody, children: Vec<DNode>, role: Normal|Assistant, image: Option<MediaRef> }.
Раскладчик — функция
layout(kind, &root, bounds) -> Vec<DShape>
(фигуры + коннекторы + текстовые прямоугольники):
fn layout_process(nodes: &[DNode], b: Rect, o: &ProcessOpts) -> Vec<DShape> {
// Горизонтальный процесс: n блоков + (n−1) стрелок; ширина блока : стрелка = 1 : 0.35
let n = nodes.len() as f64; let gap = 0.35;
let unit = b.width() / (n + (n - 1.0) * gap);
let h = (b.height() * 0.6).min(unit * 0.8);
let y = b.center().y - h / 2.0;
let mut out = vec![];
for (i, node) in nodes.iter().enumerate() {
let x = b.x0 + i as f64 * unit * (1.0 + gap);
out.push(DShape::block(node.id, Rect::new(x, y, x + unit, y + h), PresetShape::RoundRect, &node.text));
if i + 1 < nodes.len() { out.push(DShape::arrow(Rect::new(x + unit, y + h*0.3, x + unit*(1.0+gap), y + h*0.7), PresetShape::RightArrow)); }
}
out
}
fn layout_hierarchy(root: &DNode, b: Rect) -> Vec<DShape> {
// Reingold–Tilford / Walker: ширины поддеревьев, затем центрирование родителя над детьми; помощники — в отдельной колонке
let mut widths = HashMap::new();
fn measure(n: &DNode, w: &mut HashMap<NodeId, f64>) -> f64 {
let kids: f64 = n.children.iter().filter(|c| c.role != Role::Assistant).map(|c| measure(c, w)).sum::<f64>();
let me = kids.max(1.0) + n.children.iter().filter(|c| c.role != Role::Assistant).count().saturating_sub(1) as f64 * 0.25;
w.insert(n.id, me); me
}
let total = measure(root, &mut widths);
let depth = root.depth();
let cell_w = b.width() / total; let cell_h = b.height() / (depth as f64 * 1.6 - 0.6);
let mut out = vec![];
fn place(n: &DNode, x0: f64, level: usize, w: &HashMap<NodeId, f64>, cw: f64, ch: f64, b: Rect, out: &mut Vec<DShape>) {
let cx = x0 + w[&n.id] * cw / 2.0;
let r = Rect::from_center_size((cx, b.y0 + level as f64 * ch * 1.6 + ch / 2.0), (cw.min(2.5*ch) * 0.9, ch));
out.push(DShape::block(n.id, r, PresetShape::Rect, &n.text));
let mut x = x0;
for c in n.children.iter().filter(|c| c.role != Role::Assistant) {
place(c, x, level + 1, w, cw, ch, b, out);
out.push(DShape::elbow_connector(n.id, c.id)); // ортогональный коннектор «локтем»
x += (w[&c.id] + 0.25) * cw;
}
}
place(root, b.x0, 0, &widths, cell_w, cell_h, b, &mut out);
out
}Цикл: n узлов по окружности радиуса
min(w,h)/2 − r_node, угол 2π/n, стрелки — дуги
между соседями (blockArc с adj углов).
Пирамида: n трапеций равной высоты, ширина линейно от 100 %
к 30 %. Венн: окружности с перекрытием 40 % радиуса, прозрачность
заливки 50 %. Матрица: 2×2 с общим центром. Воронка: сегменты с
уменьшением ширины по кубической кривой. Общий масштаб шрифта: для
каждого узла — максимальный fontScale из лестницы §5.2, по
диаграмме — минимум из них (как dgm:… autofit), чтобы все
узлы имели один размер. Направление RTL — зеркалирование x.
Результат — обычные фигуры слайда в группе с меткой diagram
(редактирование фигур вручную помечает диаграмму «ручная», автораскладка
выключается до «Восстановить»).
5.7 Генерация миниатюр
ThumbnailService (поток пула rayon,
приоритетная очередь): задание
(slide_id, revision, width_px); рендер слайда в offscreen
SkSurface (GPU, если доступен, иначе CPU) в масштабе
width_px / slide_w, финальное состояние анимаций (все
объекты видимы), без переходов; результат — SkImage в
LRU-кэше (лимит 256 МБ), ключ (slide_id, revision, width).
Приоритет: видимые миниатюры > соседние (±5) > остальные; при
прокрутке — перезапрос с отменой устаревших. Инвалидация — по
Slide.revision (инкремент при любой операции undo-журнала,
затрагивающей слайд, макет, образец или тему — изменение образца
инвалидирует все слайды его макетов). Размеры: 96, 160, 240, 320 px для
панели, 15–100 % для сортировщика (рендер по требованию с кэшем уровня).
thumbnail.png пакета — первый слайд 256×144 при сохранении.
Диаграммы, таблицы и видео (постер) рисуются тем же списком отображения,
что и холст.
5.8 Экспорт видео
Конвейер meridian-video:
ShowSession (виртуальные часы, детерминированные шаги) → ShowRenderer (offscreen Skia GPU, N×M) → кадр (SkImage, BGRA/NV12)
→ VideoEncoder (платформенный) ─┐
Аудиомикшер (закадровый голос + медиа слайдов + звуки переходов, 48 кГц стерео) → AudioEncoder ─┤→ Muxer (mp4 / webm) → файл
pub trait VideoEncoder: Send { fn new(cfg: &VideoCfg) -> Result<Self> where Self: Sized; fn encode(&mut self, frame: &Frame, pts_ns: i64) -> Result<Vec<Packet>>; fn finish(&mut self) -> Result<Vec<Packet>>; }
pub trait AudioEncoder: Send { fn encode(&mut self, pcm: &[f32], pts_ns: i64) -> Result<Vec<Packet>>; fn finish(&mut self) -> Result<Vec<Packet>>; }
pub trait Muxer { fn add_video(&mut self, codec: CodecParams) -> TrackId; fn add_audio(&mut self, codec: CodecParams) -> TrackId; fn write(&mut self, track: TrackId, pkt: Packet) -> Result<()>; fn finish(self) -> Result<()>; }| Платформа | H.264 / AAC (mp4) | VP9 / Opus (webm) |
|---|---|---|
| Windows | Media Foundation
(IMFSinkWriter/IMFTransform, аппаратные
NVENC/QSV/AMF автоматически) |
libvpx + libopus (статически, BSD) |
| macOS | VideoToolbox + AudioToolbox (VTCompressionSession, AAC
через AudioConverter) |
libvpx + libopus |
| Linux | VA-API через libva при наличии; иначе OpenH264 (BSD;
бинарник Cisco с патентным покрытием загружается по согласию
пользователя). Свободного кодера AAC с подходящей лицензией нет, поэтому
аудио в MP4 — Opus (поддерживается современными плеерами) с
предупреждением и рекомендацией WebM |
libvpx + libopus — всегда доступно, формат по умолчанию на Linux |
Мультиплексоры — собственные писатели в Rust: MP4 (ISO BMFF:
ftyp/moov/mdat, avc1+avcC,
mp4a/Opus, таблицы
stts/stsc/stsz/stco, moov в конце с
последующим «faststart»-переносом) и WebM (EBML/Matroska:
Segment/Info/Tracks/Cluster/SimpleBlock,
Cues). Кадры: время кадра t = i / fps,
ShowSession.seek_virtual(t) выбирает слайд/шаг/переход по
хронометражу; рендер — те же sample() и
Transition::draw, что при показе, поэтому видео совпадает с
показом по кадрам. Чтение кадра с GPU —
SkSurface::readPixels в NV12 (конверсия на GPU шейдером)
либо нулевая копия (D3D11-текстура → MF, CVPixelBuffer →
VideoToolbox) — P1. Медиа слайдов декодируются платформенным декодером в
тот же виртуальный таймлайн (видео — кадр по t − t_start,
аудио — в микшер). Производительность: 1080p30 быстрее реального времени
≥ 2× на ноутбуке 2020 года. Прогресс по кадрам, отмена — мгновенная
(частичный файл удаляется).
5.9 Режим докладчика: два окна и синхронизация
┌──────────────┐ команды (Next/Prev/GoTo/Pen/Laser/Black/…) ┌──────────────────────┐
│ ShowWindow │ ───────────────────────────────────────────────▶│ ShowSession (Rust) │
│ (экран 2) │◀──── watch::Receiver<ShowState> (снимок) ────── │ state: ShowState │
└──────────────┘ │ plan: Plan │
┌──────────────┐ ───────────────────────────────────────────────▶│ clock: ShowClock │
│ Presenter │◀──── watch::Receiver<ShowState> ─────────────── │ ink/laser буферы │
│ Window (1) │ └──────────────────────┘
└──────────────┘
ShowState { slide_idx, step, step_started_at, transition: Option<(from, to, started_at, kind)>, mode: Normal|Black|White|Grid|Zoom(rect), pointer: Arrow|Laser(p)|Pen|Marker|Eraser, ink: Vec<Stroke>, paused, elapsed }— единственный источник истины; изменения — только черезShowSession::apply(cmd)(один поток-владелец, команды из обоих окон по каналу). Оба окна подписаны (watch) и перерисовываются по своему vsync, беря состояние и своё время кадра у общих часов (ShowClock—Instant-монотонные), поэтому анимации идут синхронно независимо от частот экранов (60/120 Гц).ShowWindowрендерит полный кадрShowRenderer::render(state, t);PresenterWindow— тот же рендер в меньшем размере (своя GPU-поверхность; кэш слайда-текстуры общий черезSkImageтолько при одном контексте — иначе рендерится повторно, это дёшево) плюс «следующий шаг»:plan.final_state(step+1)или первый кадр следующего слайда; заметки —text-layout.- Лазер/перо: координаты в долях слайда, штрихи сглаживаются
(Catmull-Rom + упрощение RDP), сохраняются в
ink. - Экраны:
QGuiApplication::screens(); политика по умолчанию: показ — на экране, не содержащем окно редактора;swap— обмен; на Wayland —QWindow::setScreen(screen); showFullScreen()(xdg_toplevel.set_fullscreen(output)); при одном экране докладчик — окно поверх с уменьшенным показом или только показ. Горячее подключение экрана во время показа — пересчёт. - Клавиатура и кликеры (USB-HID «PageUp/PageDown», Bluetooth-пульты)
приходят в любое окно →
apply. - Пульт на телефоне
[Pro]— локальный HTTP/WebSocket-сервер в процессе показа с кодом подключения; команды — тот жеapply.
5.10 Морфинг (P1)
Сопоставление фигур между слайдами A и B: явное по имени
!!ключ, затем по ShapeId (дубликат слайда
сохраняет id), затем эвристика (одинаковый тип + близкие размеры/текст).
Для пар: интерполяция xfrm (положение, размер, поворот по
кратчайшей дуге), цветов (в OKLab), прозрачности; геометрии — если обе
Preset одного типа → интерполяция adj, иначе —
контуры приводятся к одинаковому числу сегментов (ресэмплинг по длине
дуги) и интерполируются поточечно; текст — по словам/символам (позиции
глифов из раскладки). Непарные фигуры — выцветание. Ease —
EaseInOutCubic, длительность по умолчанию 2 с.
5.11 Текст по абзацам при импорте и «уровни» pptx
Для bldP build="p" каждый абзац получает собственный
поднабор треков с grpId; при advAuto задержка
между абзацами берётся из атрибута, иначе — из структуры дерева
(отдельные par на абзац с p:txEl/p:pRg).
Экспорт — обратное преобразование.
6. MeridianScript API для Slides
Пространство имён meridian.slides (TypeScript-типы
поставляются с редактором скриптов; выполнение — QuickJS-ng в
песочнице). Все изменения через API идут через undo-журнал (одна
скриптовая транзакция = один шаг отмены).
| Объект | Основные члены |
|---|---|
slides.activePresentation: Presentation |
slides: SlideCollection, masters,
layouts, sections, customShows,
theme, slideSize, notesMaster,
properties, save(),
saveAs(path, format?), exportPdf(opts),
exportVideo(opts) [Pro],
exportImages(opts), print(opts),
comments, media |
SlideCollection |
count, item(i), byId(id),
add(layout, index?),
insertFromFile(path, indices?),
move(from, to), forEach,
[Symbol.iterator] |
Slide |
index, id, name,
layout, shapes: ShapeCollection,
background, transition: Transition,
timeline: Timeline, notes: TextFrame,
hidden, section, comments,
duplicate(), delete(), moveTo(i),
reset(), thumbnail(width): ImageData,
select() |
ShapeCollection |
count, item(i), byName(n),
addShape(preset, rect),
addTextBox(rect, text), addPicture(src, rect),
addTable(rows, cols, rect),
addChart(type, data, rect),
addDiagram(kind, nodes, rect),
addVideo(src, rect), addAudio(src),
addConnector(kind, from, to), group(ids),
placeholders |
Shape |
id, name, type,
left/top/width/height, rotation,
flipH/flipV, zOrder, fill: Fill,
line: Line, effects,
textFrame: TextFrame, placeholder?,
altText, hyperlink, action,
locked, visible,
animations: Animation[],
addAnimation(effect, opts), bringToFront(),
sendToBack(), delete(),
duplicate(), toImage(opts),
table?, chart?, diagram?,
media? |
TextFrame |
text, paragraphs: Paragraph[],
autofit, anchor, margins,
wrap, columns, font: Font (на
всё), replace(find, repl, opts),
insert(text, at?) |
Transition |
kind, params, duration,
sound, advanceOnClick,
advanceAfter, applyToAll() |
Timeline |
effects: Animation[],
add(shape, preset, { start, delay, duration, direction }),
remove(a), move(a, index),
play(), clear() |
Animation |
shape, kind
(entrance | emphasis | exit | path), preset,
start (click | with | after),
delay, duration, repeat,
trigger, params, textBuild |
slides.show: SlideShow |
start(opts), startPresenter(),
end(), next(), previous(),
goTo(i), current, isRunning,
black(), white(), pointer,
on('slideChange' | 'click' | 'start' | 'end', cb) |
slides.events |
on('open' | 'beforeSave' | 'slideAdded' | 'selectionChanged' | 'showStart' | 'showEnd' | 'slideShown', cb) |
slides.ui |
selection: Shape[] | Slide[],
currentSlide, view
(normal | sorter | outline | notes | master),
showPanel(id), dialog(...),
toast(msg) |
Примеры:
// Слайды из таблицы Sheets: по строке на слайд / One slide per row of a Sheets range
import { sheets, slides } from "meridian";
const wb = await sheets.open("Проекты.msx");
const rows = wb.sheet("Проекты").range("A2:C20").values as [string, string, number][];
const pres = slides.activePresentation;
const layout = pres.layouts.byName("Заголовок и объект");
for (const [name, owner, budget] of rows) {
const s = pres.slides.add(layout);
s.shapes.placeholders.title.textFrame.text = name;
s.shapes.placeholders.body.textFrame.text = `Ответственный: ${owner}\nБюджет: ${budget.toLocaleString("ru-RU")} ₽`;
s.transition.kind = "push"; s.transition.params = { dir: "left" }; s.transition.duration = 0.5;
}// Единые переходы и анимация заголовков во всей презентации / Uniform transitions and title animation
const pres = slides.activePresentation;
for (const s of pres.slides) {
s.transition.kind = "fade"; s.transition.duration = 0.7;
const title = s.shapes.placeholders.title;
if (title) s.timeline.add(title, "entrance.fade", { start: "with", duration: 0.5 });
}// Замена текста везде, включая заметки, с отчётом / Replace text everywhere incl. notes
let n = 0;
for (const s of slides.activePresentation.slides) {
for (const sh of s.shapes) if (sh.textFrame) n += sh.textFrame.replace("ООО «Старое»", "ООО «Новое»", { wholeWord: true });
n += s.notes.replace("ООО «Старое»", "ООО «Новое»");
}
slides.ui.toast(`Заменено: ${n}`);// Таймер показа и событие смены слайда: пишем в лог продолжительность каждого слайда / Log time per slide during show
const t: Record<number, number> = {}; let last = Date.now(), cur = 0;
slides.show.on("slideChange", (e) => { t[cur] = (t[cur] ?? 0) + (Date.now() - last); last = Date.now(); cur = e.index; });
slides.show.on("end", () => console.table(t));// Экспорт: PDF с заметками и видео 1080p / Export PDF with notes and 1080p video
await slides.activePresentation.exportPdf({ path: "отчёт.pdf", notes: true, bookmarks: "sections" });
await slides.activePresentation.exportVideo({ path: "отчёт.mp4", format: "mp4", height: 1080, fps: 30, useTimings: true });7. Форматы
7.1 Сводка
| Формат | Чтение | Запись | Приоритет | Кодек |
|---|---|---|---|---|
.mpx / .mpt / .mpxf |
полное | полное | P0 | meridian-slides |
.pptx / .pptm / .potx /
.ppsx |
полное (см. потери) | полное для всего, что умеет Slides; неизвестные части — round-trip | P0 | meridian-codecs-pptx |
.ppt / .pps / .pot
(97–2003) |
текст, фигуры, рисунки, образцы, переходы, базовые анимации, заметки | упрощённая: без анимаций PowerPoint 2002+ (только базовые эффекты), без SmartArt | P0 чтение / P1 запись | meridian-codecs-ppt |
.odp / .otp |
полное | полное | P0 | meridian-codecs-odf |
.key (Keynote '13+ IWA, Keynote '09 XML) |
слайды, мастера, текст, фигуры, рисунки, таблицы, диаграммы (частично), переходы/анимации по таблице соответствий | — (Keynote сам открывает pptx) | P1 | meridian-codecs-iwork |
.sxi |
через ODF-кодек с таблицей замены пространств имён | — | P2 | meridian-codecs-odf |
.pdf |
— (импорт PDF как слайдов-изображений — P2 через Meridian PDF) | слайды/заметки/выдачи, PDF/A, PDF/UA | P0 | Meridian Print |
.mp4 / .webm |
— | видео показа [Pro] |
P0 | meridian-video |
.png / .jpg / .svg /
.webp |
— | слайды | P0 | Meridian Render |
.html |
— | статичные страницы | P2 | — |
7.2 PPTX — особенности
Структура: ppt/presentation.xml
(sldMasterIdLst, sldIdLst, sldSz,
notesSz, defaultTextStyle,
custShowLst, extLst/p14:sectionLst),
ppt/slides/slideN.xml (+ _rels: макет, медиа,
диаграммы, схемы, заметки, комментарии), ppt/slideLayouts/,
ppt/slideMasters/, ppt/theme/,
ppt/notesSlides/, ppt/notesMasters/,
ppt/handoutMasters/, ppt/comments/ (+
modernComment_*.xml, authors.xml),
ppt/presProps.xml (showPr),
ppt/viewProps.xml, ppt/tableStyles.xml,
ppt/media/, ppt/embeddings/,
ppt/charts/, ppt/diagrams/,
ppt/fonts/, ppt/vbaProject.bin.
| Область | Чтение | Запись | Примечание |
|---|---|---|---|
| Образцы/макеты/темы, карта цветов, варианты | полное | полное | несколько образцов, preserve |
Текст: bodyPr, lstStyle, уровни, поля,
автонумерация, prstTxWarp |
полное (деформации — P1 отображение) | полное | единицы без округления |
Фигуры prstGeom/custGeom, стили, заливки,
линии, эффекты |
полное | полное | scene3d/sp3d — хранится и возвращается,
отображение приближённое (P2 полное) |
Рисунки: blip, srcRect,
duotone, lum, alphaModFix,
clrChange, SVG asvg:svgBlip |
полное | полное | художественные эффекты a14:imgProps — round-trip без
отображения |
Таблицы a:tbl, стили tableStyleId |
полное | полное | — |
Диаграммы c:chart, cx:chart, встроенная
книга |
через Meridian Chart | полное | см. docs/algorithms/chart-engine.md |
Диаграммы-схемы dgm:* |
известные макеты → редактируемые; иначе кэш
drawingN.xml |
модель + кэш drawing +
data/layout/colors/quickStyle для известных макетов; для
«ручных» — группа фигур |
— |
Медиа p14:media, trim, fade,
bmkLst, постеры,
videoFile/audioFile, онлайн-видео |
полное | полное | кодеки — платформенные |
Переходы p:transition + p14: +
p15:prstTrans + p159:morph |
все 51 | все | неизвестные — round-trip в mc:AlternateContent |
Анимации p:timing, p:bldLst, триггеры,
интерактивные последовательности, p:cmd,
p:audio/video |
изоморфно | изоморфно | неизвестные presetID воспроизводятся по дереву
поведений (не по пресету) |
Комментарии старые и современные (p188), ответы,
статус |
полное | современные + старые для совместимости | — |
Разделы, произвольные показы, showPr, хронометраж,
закадровый текст (p:cmd playFrom + аудио) |
полное | полное | — |
Защита: agile encryption (AES-256/SHA-512),
modifyVerifier, «окончательный» |
полное | полное [Pro: DocEncrypt] на запись |
Free — чтение и снятие |
VBA (.pptm) |
хранится как есть, не выполняется; транслятор простых макросов
[Pro] |
возвращается без изменений | — |
| ActiveX, OLE-объекты | кэш-изображение + round-trip | как есть | — |
Ink p14:ink/inkml |
отображение P1 | запись P1 | — |
3D-модели am3d, Zoom (p:…zoom), cameo |
постер/изображение + round-trip | как есть | P2 |
Встроенные шрифты .fntdata (обфусцированные) |
P1 чтение | P1 запись | только fsType ∈ {installable, editable} |
Расширения extLst, неизвестные части |
round-trip | round-trip | политика библии §3.1 |
Известные трудности: авто-вычисление геометрии групп
(chOff/chExt масштабирование детей), p:ph без
idx, пустые spPr, порядок rels,
кодировка идентификаторов комментариев, mc:AlternateContent
с несколькими вариантами (берём Requires из известных нам
пространств имён, иначе Fallback).
7.3 PPT (бинарный)
OLE2-контейнер: потоки PowerPoint Document,
Pictures, Current User,
Summary Information, VBA. Записи
(RecordHeader:
recVer/recInstance/recType/recLen) → контейнеры
DocumentContainer, MainMasterContainer,
SlideContainer, NotesContainer; графика —
OfficeArt (Escher): OfficeArtDgContainer →
OfficeArtSpContainer → OfficeArtFSP (тип
msospt* → таблица соответствия 202 типов с
prstGeom) + OfficeArtFOPT (свойства: геометрия
pVertices/pSegmentInfo для произвольных форм, заливки,
линии, текст). Текст: TextHeaderAtom,
TextCharsAtom (UTF-16) / TextBytesAtom (ANSI,
кодовая страница по языку — для русских файлов cp1251),
StyleTextPropAtom, TextRulerAtom; «внешние»
вставки TextSpecialInfoAtom. Анимации 2002+:
PP10SlideBinaryTagExtension с
TimeNodeContainer — отображаются в наше дерево; старые
AnimationInfoAtom — простые эффекты. Переходы —
SlideShowSlideInfoAtom. Шифрование RC4 CryptoAPI — чтение
P1. Запись P1: текст, фигуры, рисунки, образцы, переходы, заметки;
анимации — только появление/выцветание/вылет; остальное — предупреждение
«не сохраняется в этом формате».
7.4 ODP
ODF 1.3: office:presentation → draw:page
(presentation:class у рамок: title,
outline, subtitle, notes,
graphic, object, chart,
table, page-number, date-time,
footer, header),
draw:custom-shape + draw:enhanced-geometry
(draw:type="ooxml-…", формулы draw:formula
эквивалентны направляющим — один вычислитель с таблицей функций),
style:master-page + presentation:page-layout +
draw:layer-set, presentation:settings,
presentation:show,
presentation:header-decl/footer-decl/date-time-decl.
Анимации — SMIL
(anim:par/seq/iterate/animate/ set/animateMotion/animateColor/animateTransform/transitionFilter/audio/command)
с presentation:node-type и
presentation:preset-class/preset-id/preset-sub-type — те же
пресеты, что в PowerPoint, поэтому дерево переносится почти без потерь.
Переходы — smil:type/subtype в
style:drawing-page-properties (barWipe,
fade, pushWipe, …) +
presentation:transition-speed,
presentation:duration.
Потери при записи в ODP: темы (ODF без тем — LibreOffice 7.6+
понимает loext:theme, пишем её и явные стили), стили таблиц
(пишем явные стили ячеек), эффекты свечения/отражения
(loext:glow, loext:softedge для LibreOffice,
иначе отбрасываются), современные переходы без SMIL-аналога
(fracture, morph → fade),
триггеры по закладкам медиа, комментарии с ответами
(officeooo:annotation — плоские), встроенные шрифты (P2),
диаграммы-схемы — группа фигур (так же делает LibreOffice).
7.5 Keynote
.key — пакет (zip или папка): Index/*.iwa
(snappy-сжатые блоки Protobuf, типы сообщений
TSP/TSK/TSWP/TSD/TST/TSCH/KN — схема восстановлена
сообществом; свои .proto поддерживаем в
meridian-codecs-iwork), Data/ (медиа),
Metadata/, preview.jpg. Читаем: слайды,
мастера, фон, текст со стилями, фигуры (пути Безье →
custGeom; стандартные Keynote-формы →
prstGeom), рисунки с масками, таблицы (TST),
диаграммы (TSCH, основные типы), переходы и построения
(таблица соответствий: Magic Move → морфинг P1, Dissolve → fade,
Push/Wipe/Cube/Flip/Doorway → наши, прочие (Anvil, Sparkle…) → ближайший
+ предупреждение), заметки докладчика. Шрифты Apple заменяются
метрически близкими. Keynote '09 (index.apxl XML) —
отдельный разбор, тот же результат. Запись .key не
планируется.
8. Горячие клавиши
Схема по умолчанию — Microsoft Office (Windows/Linux:
Ctrl, macOS: ⌘). Схема LibreOffice и своя — в
настройках.
8.1 Редактор
| Действие | Клавиши |
|---|---|
| Новый слайд / дублировать слайд | Ctrl+M / Ctrl+Shift+D |
| Дублировать фигуру | Ctrl+D |
| Показ с начала / с текущего / режим докладчика | F5 / Shift+F5 / Alt+F5 |
| Командная палитра | Ctrl+K (см. §11) |
| Гиперссылка | Ctrl+Shift+K (см. §11) |
| Найти / заменить | Ctrl+F / Ctrl+H |
| Отменить / повторить | Ctrl+Z / Ctrl+Y |
| Полужирный / курсив / подчёркнутый | Ctrl+B / Ctrl+I / Ctrl+U |
| Увеличить / уменьшить шрифт | Ctrl+Shift+> / Ctrl+Shift+< (также
Ctrl+] / Ctrl+[) |
| Выравнивание влево / центр / вправо / по ширине | Ctrl+L / Ctrl+E / Ctrl+R /
Ctrl+J |
| Повысить / понизить уровень абзаца | Alt+Shift+← / Alt+Shift+→ (также
Shift+Tab / Tab в начале абзаца) |
| Переместить абзац вверх / вниз | Alt+Shift+↑ / Alt+Shift+↓ |
| Верхний / нижний индекс | Ctrl+Shift++ / Ctrl+= |
| Сбросить форматирование символов | Ctrl+Space |
| Диалог шрифта | Ctrl+Shift+F |
| Копировать / вставить формат | Ctrl+Shift+C / Ctrl+Shift+V |
| Группировать / разгруппировать | Ctrl+G / Ctrl+Shift+G |
| На передний / на задний план | Ctrl+Shift+] / Ctrl+Shift+[ |
| Переместить вперёд / назад на один уровень | Ctrl+Alt+] / Ctrl+Alt+[ |
| Сдвиг фигуры на 1 px / на шаг сетки | ←↑→↓ / Ctrl+←↑→↓ |
| Изменить размер на 1 px | Shift+←↑→↓ |
| Повернуть на 15° | Alt+← / Alt+→ |
| Следующая / предыдущая фигура | Tab / Shift+Tab |
| Редактировать текст выделенной фигуры / выйти | F2 или Enter / Esc |
| Переход к следующему заполнителю, после последнего — новый слайд | Ctrl+Enter |
| Панель выделения | Alt+F10 |
| Сетка / направляющие | Shift+F9 / Alt+F9 |
| Временно отключить привязку | удерживать Alt при перетаскивании |
| Орфография / тезаурус | F7 / Shift+F7 |
| Сохранить / сохранить как / открыть / печать | Ctrl+S / F12 / Ctrl+O /
Ctrl+P |
| Обычный вид / сортировщик / структура / страницы заметок | Alt+V, N / Alt+V, D /
Alt+V, O / Alt+V, P (клавиатурные подсказки
ленты); Shift+щелчок по кнопке вида — образец |
| Масштаб: вписать / 100 % / увеличить / уменьшить | Ctrl+0 / Ctrl+1 / Ctrl++ /
Ctrl+−; Ctrl+колесо |
| Следующий / предыдущий слайд (в миниатюрах/холсте) | Page Down / Page Up; первый/последний —
Ctrl+Home / Ctrl+End |
| Скрыть слайд | Ctrl+Shift+H |
| Добавить раздел | Ctrl+, |
| Заметки: фокус в панель | Alt+Shift+N |
| Анимация: панель | Alt+Shift+A |
| Контекстное меню | Shift+F10 или Menu |
| Клавиатурные подсказки ленты | Alt (как в Office: Alt+H Главная,
Alt+N Вставка, Alt+G Дизайн,
Alt+K Переходы, Alt+A Анимации,
Alt+S Показ, Alt+R Рецензирование,
Alt+W Вид) |
| Полноэкранный «Фокус» | F11 |
8.2 Показ слайдов
| Действие | Клавиши |
|---|---|
| Следующий слайд/шаг | N, Enter, Space,
→, ↓, Page Down, щелчок |
| Предыдущий | P, Backspace, ←,
↑, Page Up |
| Перейти к слайду N | N + Enter (ввод числа) |
| Первый / последний | Home / End |
| Сетка всех слайдов / выход из неё | G (также −), Esc |
| Чёрный / белый экран | B или . / W или
, |
| Пауза / продолжить автоматический показ | S или + |
| Показать скрытый слайд | H |
| Лазерная указка | Ctrl+L (переключатель) или Ctrl+ЛКМ |
| Перо / маркер / ластик / стрелка | Ctrl+P / Ctrl+I / Ctrl+E /
Ctrl+A |
| Очистить рукописный ввод | E |
| Скрыть / показать указатель | Ctrl+H / Ctrl+A (или Ctrl+U —
показать автоматически) |
| Лупа (увеличить/уменьшить) | + / − (при открытой лупе),
Ctrl+колесо |
| Произвольный показ / меню | Shift+F10 или ПКМ |
| Режим докладчика вкл/выкл во время показа | Alt+F5 |
| Обменять экраны докладчика и показа | Alt+Shift+S |
| Панель задач | Ctrl+T |
| Остановить/запустить медиа / громкость / перемотка | Alt+P / Alt+↑ / Alt+↓ /
Alt+Shift+Page Down / Alt+Shift+Page Up; без
звука Alt+U |
| Субтитры (P2) | J |
| Завершить показ | Esc, Ctrl+Break, пункт меню «Завершить
показ» |
9. Критерии готовности 1.0
| № | Критерий | Метрика |
|---|---|---|
| 1 | Открытие корпуса pptx (≥ 3 000 реальных презентаций: шаблоны Office, корпоративные, образовательные, с анимациями и медиа) | 100 % без сбоев (фаззинг парсера cargo-fuzz 72 ч без падений); SSIM рендера слайда ≥ 0,98 против PowerPoint для 95 % слайдов, ≥ 0,95 для 99 % |
| 2 | Round-trip pptx → mpx → pptx | без потерь для всех свойств P0; PowerPoint открывает результат без «восстановления»; повторный round-trip даёт байт-в-байт равный XML (нормализованный) |
| 3 | Анимации | все 150+ пресетов PowerPoint воспроизводятся и соответствуют эталонным видео покадрово (допуск 1 кадр при 60 к/с); неизвестные пресеты — по дереву поведений |
| 4 | Переходы | 51 переход; 60 к/с при 1080p на Intel Iris Xe / Apple M1 / AMD Vega 8; при 4K — ≥ 45 к/с |
| 5 | Показ | задержка реакции на щелчок ≤ 16 мс; смена слайда с предрендером ≤ 1 кадр; режим докладчика на 2–3 экранах на Windows/macOS/Linux X11/Wayland |
| 6 | Производительность | открытие 100 слайдов с медиа ≤ 2 с (SSD), 1 000 слайдов ≤ 8 с; холст 60 к/с при перетаскивании на слайде с 200 фигурами; память ≤ 600 МБ на 100-слайдовой презентации с 50 рисунками |
| 7 | Экспорт видео | 1080p30 ≥ 2× реального времени; совпадение кадров с показом; воспроизводится в VLC, Windows Media Player, QuickTime, Chrome |
| 8 | ODP | корпус 1 000 файлов LibreOffice: открытие 100 %, SSIM ≥ 0,97; Impress открывает наш odp без предупреждений |
| 9 | PPT | корпус 1 000 файлов 97–2003: открытие 100 %, текст и рисунки без потерь |
| 10 | Keynote | корпус 200 файлов: 100 % открытие, визуальное совпадение ≥ 0,9 SSIM |
| 11 | Текст | все возможности Write в фигурах: RTL, вертикальный, переносы, орфография на 40 языках |
| 12 | Доступность | скринридеры NVDA/VoiceOver/Orca читают слайды в порядке чтения; все команды с клавиатуры; проверка доступности выявляет 100 % тестовых дефектов |
| 13 | Стабильность | автосохранение и восстановление без потери данных (тест kill −9 каждые 5 с на протяжении часа правок); парсеры в песочном процессе |
| 14 | Печать/PDF | выдачи 1–9, заметки, PDF/A-2b и PDF/UA проходят veraPDF |
| 15 | Скрипты | API §6 покрыт тестами; 20 примеров скриптов в галерее; события показа |
| 16 | Локализация | интерфейс ru/en, пресеты с русскими названиями, 30 тем, 40 шаблонов |
| 17 | Установка | MSIX/MSI, DMG (universal), Flatpak/AppImage; ассоциации
.mpx/.pptx/.odp/.key |
10. Риски
| Риск | Вероятность | Влияние | Снижение |
|---|---|---|---|
Сложность p:timing: недокументированные комбинации
поведений в реальных файлах |
высокая | средняя | изоморфное дерево + воспроизведение по поведениям, а не по пресетам; корпус из 3 000 файлов; покадровые эталоны |
| Патенты на H.264/AAC и лицензии кодеров на Linux | средняя | средняя | платформенные кодеры на Windows/macOS; на Linux — WebM по умолчанию,
OpenH264 по согласию пользователя; абстракция
VideoEncoder |
3D-эффекты фигур (sp3d, scene3d) и
объёмные переходы — свой растеризатор |
средняя | средняя | P2; в 1.0 — приближённый плоский рендер, round-trip без потерь |
| Диаграммы-схемы: ~190 макетов OOXML с собственным языком раскладки | высокая | средняя | кэш drawing для точного отображения, 40 своих макетов,
интерпретатор layoutDef — P2 |
| Wayland: позиционирование окон и полноэкранный режим на нужном выводе, захват курсора | средняя | средняя | setScreen +
xdg_toplevel.set_fullscreen(output); тесты на
GNOME/KDE/Sway; резерв — X11/XWayland |
| Шрифты: документы с Calibri/Segoe без встраивания; встраивание с нарушением лицензий | высокая | низкая | метрические аналоги (Carlito, Liberation); встраивание только по
fsType |
| Keynote — закрытый формат, схема Protobuf меняется | средняя | низкая | P1, корпус из версий Keynote 9–14, graceful degradation (постер
слайда из preview.jpg) |
| Производительность миниатюр и холста на слабых GPU / без GPU | средняя | средняя | CPU-резерв Skia, кэш и приоритизация миниатюр, лимиты памяти |
| Морфинг: несовпадение с PowerPoint в краевых случаях | средняя | низкая | P1; тестовые пары слайдов; документированные отличия |
| Медиа: кодеки, недоступные в системе (HEVC на Windows без расширения, AV1 на старых macOS) | средняя | средняя | диагностика при вставке с предложением перекодировать через
meridian-video; FFmpeg-бэкенд Qt как резерв |
| Разрастание объёма 1.0 | высокая | высокая | строгие P0; 3D, морфинг, сравнение, cameo, субтитры — в 1.x |
11. Вопросы к библии
Ctrl+K. Библия назначаетCtrl/⌘+Kкомандной палитре, но в Microsoft Office это «Гиперссылка» — привычка, которую принцип «не ломать привычки» велит сохранить. Предложение: палитра —Ctrl+Shift+P(как в VS Code) с дублемF1, гиперссылка —Ctrl+K; либо оставить палитру наCtrl+K, а гиперссылку перенести наCtrl+Shift+K(так принято в этом документе до решения).- Общий модуль «диаграммы-схемы». SmartArt есть в
Word/Excel/PowerPoint; предлагается добавить в §2.2 библии модуль ядра
Meridian Diagram (
meridian-diagram), как Meridian Chart. - Общая сцена фигур. Write (§2.8) и Slides опираются
на один крейт геометрии/стилей фигур; предлагается явно назвать его в
§2.2 (Meridian Scene,
meridian-scene) и завестиdocs/algorithms/scene.md(prstGeom, стили, рендер). - Видеокодеки. Нужна политика по лицензиям кодеров (платформенные API vs. бандл OpenH264/libvpx) в разделе стека; здесь принято: Windows/macOS — системные кодеры, Linux — WebM по умолчанию.
- Редакция для экспорта видео.
docs/10-licensing-accounts.mdотноситslides_video_exportк Pro; библия §9.1 для Free говорит «все форматы чтения/записи». Нужно решить, считается ли видео «форматом записи» (тогда Free) или функцией Pro. - Путь спецификации Chart.
docs/apps/sheets.mdссылается наdocs/kernel/chart.md, а документ движка написан какdocs/algorithms/chart-engine.md— выбрать одно расположение и исправить ссылку.