Vector Engine

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 w localStorage.

Orkiestracja eksportu (apps/web/src/export)#

ModułOdpowiedzialność
bounds.tsSkładanie macierzy afinicznych, bounds path z flatteningiem Bézierów, przycinanie drzewa scope
validation.tsPreflight: wymiary, piksele, pamięć, kolory, jakość, targety
filename.tsSzablony nazw i deduplikacja kolizji
sizeEstimator.tsEstymacja bajtów i RAM, diagnoza alpha, miniatura ≤ 320 px
zipWriter.tsPKZIP z CRC-32, STORE/DEFLATE, zero zależności
exportService.ts, batchExporter.tsSnapshoty, 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 transfery ArrayBuffer, natychmiastowe ubijanie workera przy abort().
  • wasmBackend.ts — most do reakatora C++23 (validateJson, renderScopedSvg, exportScopedMeta, takeLastBytes, measureBounds).
  • browserBackend.ts — fallback zgodny API.

Rdzeń C++23 (engine/)#

PlikOdpowiedzialność
parser.cpp, bounds.cppParsowanie scen, warstw, workspace'ów, gradientów; dokładne bounds z transformacjami i stroke
svg_renderer.cppSVG z <defs>, <clipPath>, mix-blend-mode, preserveAspectRatio
rasterizer.cppRasteryzacja geometrii, gradientów (pad/reflect/repeat), stroke i clip do straight-alpha RGBA
encoders.cppPNG, 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).