Architektura
Pipeline przetwarzania, warstwy UI/orchestracji/workera/rdzenia C++23 i kontrakt EngineBackend. Jak JSON staje się pikselami.
Pipeline przetwarzania#
text
JSON source snapshot
→ walidacja strukturalna (Ajv Draft 2020-12 + parser C++23)
→ walidacja semantyczna (unikalne ID, warstwy, workspaces, gradienty, limity)
→ ekstrakcja target scope (scene / selection / group / layer / objects / workspace)
→ analityczny tight bounding box i rozdzielczość viewportu (contain / cover / stretch + margin + clip)
→ serializer SVG (z minifikacją) lub rasteryzator scanline RGBA 4× subpixel
→ PNG, JPEG, BMP (24-bit BGR / 32-bit BGRA) lub archiwum PKZIP
UI nie zależy od szczegółów implementacji C++ — komunikuje się przez kontrakt EngineBackend w TypeScripcie i pipeline serwisów eksportu.
Warstwy#
UI (apps/web/src/components)#
AppHeader.vue— nazwa dokumentu, import JSON, reset sceny, eksport jednym kliknięciem i trójstanowe przełączniki paneli.JsonEditor.vue— CodeMirror 6 z inline diagnostyką walidacji.PreviewPanel.vue— live podgląd z zoomem i niezależnym tłem canvasa (Grid,Light,White,Dark).ExportPanel.vue— 7-krokowy workflow eksportu z batch/ZIP i anulowaniem.InspectorSection.vue— akordeon inspektora, stan wlocalStorage.
Orkiestracja eksportu (apps/web/src/export)#
| Moduł | Odpowiedzialność |
|---|---|
bounds.ts | Składanie macierzy afinicznych, bounds path z flatteningiem Bézierów, przycinanie drzewa scope |
validation.ts | Preflight: wymiary, piksele, pamięć, kolory, jakość, targety |
filename.ts | Szablony nazw i deduplikacja kolizji |
sizeEstimator.ts | Estymacja bajtów i RAM, diagnoza alpha, miniatura ≤ 320 px |
zipWriter.ts | PKZIP z CRC-32, STORE/DEFLATE, zero zależności |
exportService.ts, batchExporter.ts | Snapshoty, AbortSignal, per-item overrides, BatchExportReport |
Worker i adapter WASM (apps/web/src/engine)#
workerBackend.ts+exportWorker.ts— rdzeń poza głównym wątkiem, zero-copy transferyArrayBuffer, natychmiastowe ubijanie workera przyabort().wasmBackend.ts— most do reakatora C++23 (validateJson,renderScopedSvg,exportScopedMeta,takeLastBytes,measureBounds).browserBackend.ts— fallback zgodny API.
Rdzeń C++23 (engine/)#
| Plik | Odpowiedzialność |
|---|---|
parser.cpp, bounds.cpp | Parsowanie scen, warstw, workspace'ów, gradientów; dokładne bounds z transformacjami i stroke |
svg_renderer.cpp | SVG z <defs>, <clipPath>, mix-blend-mode, preserveAspectRatio |
rasterizer.cpp | Rasteryzacja geometrii, gradientów (pad/reflect/repeat), stroke i clip do straight-alpha RGBA |
encoders.cpp | PNG, JPEG (DCT), BMP 24 BGR, BMP 32 BGRA |
Kontrakt EngineBackend#
ts
interface EngineBackend {
validateJson(source: string): ValidationResult
measureBounds(source: string, optionsJson: string): BoundsResult
renderScopedSvg(source: string, optionsJson: string): SvgResult
exportScopedMeta(source: string, optionsJson: string): ExportMeta
takeLastBytes(): Uint8Array
}
Dwie implementacje: WasmBackend (produkcja) i BrowserBackend (fallback dev). Ten sam kontrakt, więc UI nie wie i nie musi wiedzieć, który rdzeń działa.
Determinizm#
- Ten sam JSON + te same opcje → ten sam SVG i te same piksele.
- Rasteryzator scanline z 4× subpixel samplingiem jest deterministyczny między platformami.
- SVG escapuje tekst i atrybuty — brak wstrzykiwania XML.
Bezpieczeństwo#
- Limity: 4 MB źródła, 16 384 px wymiaru, 67 Mpx rastra, 10 000 obiektów, 32 poziomy grup, 1 M znaków path.
- Guard 512 MB RAM roboczego przy rasteryzacji.
- Brak zewnętrznych zasobów: żadnych sieciowych URL-i, fontów ani obrazów.
- CSP kompatybilna z Emscripten — bez
unsafe-eval(Ajv kompiluje schemę do standalone module w buildzie).