====== SVG mit Lyx ====== Die Lyx SVG-Bibliothek erzeugt SVG-Dateien direkt — kein externes Tool, keine Abhängigkeiten. 9 Sub-Units decken Grundformen, Pfade, Stile, Filter, Animationen, Text, Definitionen und Parsing ab. → [[lyx_-_programmiersprache:guides|Guides]] · [[lyx_-_programmiersprache:units:svg|std.svg Referenz]] import std.svg.builder; // Pflicht: Dokument-Lifecycle import std.svg.elements; // Grundformen import std.svg.style; // Farbe, Strich, Transformationen ---- ===== Architektur ===== svg/builder — SvgNew, SvgSave, SvgFree, SvgToString (Dokument-Lifecycle) svg/elements — rect, circle, ellipse, line, polyline, polygon, SvgApply, Gruppen svg/path — Builder: M L H V C S Q T A Z svg/style — fill, stroke, opacity, dash, linecap/join, Transformationen svg/text — SvgTextAt, SvgTextBegin/SvgTspan, Schriftart, Anker svg/image — SvgImage (eingebettetes Bild oder Verweis) svg/filter — Blur, Drop-Shadow, Composite, ColorMatrix svg/defs — Gradienten, Muster, clipPath, Symbol, Marker svg/anim — SMIL-Animationen: SvgAnimate, SvgAnimateTransform, SvgAnimateMotion svg/parser — SVG-Datei einlesen und traversieren svg/xml — Low-Level XML-Ausgabe (intern) ---- ===== Minimales Beispiel ===== import std.svg.builder; import std.svg.elements; import std.svg.style; fn main(): int64 { // Dokument anlegen (400×300 px): var doc: int64 := SvgNew(400.0, 300.0); // Hintergrund: SvgSetFillHex(doc, "#ADD8E6"c); SvgRect(doc, 0.0, 0.0, 400.0, 300.0); SvgApply(doc); // Roter Kreis: SvgSetFillHex(doc, "#FF0000"c); SvgSetStroke(doc, 0.545, 0.0, 0.0); // dunkelrot SvgSetStrokeWidth(doc, 2.0); SvgCircle(doc, 200.0, 150.0, 60.0); SvgApply(doc); // Speichern: SvgSave(doc, "output.svg"c); SvgFree(doc); return 0; } ---- ===== Grundformen (svg/elements) ===== import std.svg.elements; // Rechteck: SvgRect(doc, x, y, width, height); // Abgerundetes Rechteck: SvgSetRounding(doc, rx, ry); // vor SvgRoundRect setzen SvgRoundRect(doc, x, y, w, h); // Kreis: SvgCircle(doc, cx, cy, radius); // Ellipse: SvgEllipse(doc, cx, cy, rx, ry); // Linie: SvgLine(doc, x1, y1, x2, y2); // Polyline (Punkte als String "x1,y1 x2,y2 ..."): SvgPolyline(doc, "10,20 30,40 50,20"c); // Nach jeder Form: SvgApply() — überträgt Style und erzeugt das Element SvgApply(doc); ---- ===== Pfade (svg/path) ===== import std.svg.path; import std.svg.style; SvgSetFillNone(doc); SvgSetStroke(doc, 0.0, 0.0, 0.0); // schwarz SvgPathBegin(doc); SvgMoveTo(doc, 50.0, 100.0); SvgLineTo(doc, 150.0, 100.0); SvgLineTo(doc, 100.0, 50.0); SvgClosePath(doc); SvgApply(doc); // // Kubische Bézierkurve: SvgPathBegin(doc); SvgMoveTo(doc, 10.0, 80.0); SvgCurveSetCP(doc, 40.0, 10.0, 65.0, 10.0); // Kontrollpunkte SvgCurveTo2(doc, 95.0, 80.0); // C — SvgCurveTo stuerzt ab (#1688) SvgApply(doc); ---- ===== Stile (svg/style) ===== import std.svg.style; // Füllung: SvgSetFillHex(doc, "#4682B4"c); // Hex-Farbe SvgSetFillAlpha(doc, 0.27, 0.51, 0.71, 0.8); // Farbe + fill-opacity SvgSetFillNone(doc); // keine Füllung // Kontur: SvgSetStroke(doc, 1.0, 0.0, 0.0); // rot — Anteile 0.0 bis 1.0 SvgSetStrokeWidth(doc, 3.0); SvgSetOpacity(doc, 0.5); // Gesamtdeckkraft des Elements // Linienenden und -verbindungen: SvgSetLineCap(doc, SVG_CAP_ROUND); // butt | round | square SvgSetLineJoin(doc, SVG_JOIN_MITER); // miter | round | bevel // Gestrichelte Linie: SvgSetDashArray(doc, "5,3"c); // "5px Strich, 3px Pause" SvgSetDashOffset(doc, 0.0); // Transformation: SvgTranslate(doc, 100.0, 50.0); SvgRotate(doc, 45.0); SvgScale(doc, 2.0, 2.0); // Die Transformkette wird mit dem naechsten SvgApply verbraucht — // ein SvgResetTransform gibt es nicht. ---- ===== Text (svg/text) ===== import std.svg.text; import std.svg.style; SvgSetFillHex(doc, "#000000"c); SvgSetFont(doc, "DejaVu Sans"c, 16.0); // Schriftart + Größe SvgTextAt(doc, 50.0, 50.0, "Hallo Lyx"c); SvgApply(doc); // Mehrzeiliger Text mit tspan — dy je Zeile, Abschluss mit SvgTextEnd: SvgTextBegin(doc, 20.0, 30.0); SvgTspan(doc, "Zeile 1"c, 0.0, 0.0); SvgTspan(doc, "Zeile 2"c, 0.0, 20.0); SvgTextEnd(doc); ---- ===== Gruppen und Layer ===== import std.svg.elements; // Gruppe mit ID — Stil und Transform vorher setzen, sie landen am : SvgGroupBeginId(doc, "layer1"c); SvgCircle(doc, 100.0, 100.0, 30.0); SvgApply(doc); SvgRect(doc, 50.0, 50.0, 40.0, 40.0); SvgApply(doc); SvgGroupEnd(doc); ---- ===== Animationen (svg/anim) ===== import std.svg.anim; // Farb-Animation: elem = 0 merkt die Animation fuer das naechste // abgeschlossene Element vor (SvgCircle liefert nichts zurueck): SvgAnimRepeat(doc, 0); // 0 = indefinite SvgAnimate(doc, 0, "fill"c, "red"c, "blue"c, 2.0); SvgSetFillHex(doc, "#FF0000"c); SvgCircle(doc, 200.0, 150.0, 50.0); SvgApply(doc); // Rotation (0° → 360°, endlos) auf demselben Weg: SvgAnimateTransform(doc, 0, SVG_AT_ROTATE, "0 200 150"c, "360 200 150"c, 3.0); ^ Transform-Typ ^ Konstante ^ | Verschiebung | ''SVG_AT_TRANSLATE'' | | Skalierung | ''SVG_AT_SCALE'' | | Rotation | ''SVG_AT_ROTATE'' | | Scherung X | ''SVG_AT_SKEWX'' | | Scherung Y | ''SVG_AT_SKEWY'' | ---- ===== Filter (svg/filter) ===== import std.svg.filter; // Unschärfe auf Rechteck — der fertige Effekt liefert die Filternummer: var blur: int64 := SvgBlur(doc, 3.0); SvgSetFilter(doc, blur); SvgRect(doc, 50.0, 50.0, 200.0, 100.0); SvgApply(doc); // Drop-Shadow (schwarz, Deckkraft als letztes Argument): var shadow: int64 := SvgDropShadow(doc, 4.0, 4.0, 2.0, 0.6); SvgSetFilter(doc, shadow); // Eigener Filter aus Primitiven: var flt: int64 := SvgFilterBegin(doc, "eigen"c, 0.0, 0.0, 1.2, 1.2); SvgFeGaussianBlur(doc, flt, "SourceGraphic"c, 2.0, 2.0); SvgFilterEnd(doc); ---- ===== Dokument-Ausgabe ===== import std.svg.builder; // In Datei speichern: SvgSave(doc, "chart.svg"c); // Als String holen (z. B. für HTTP-Response): var svgStr: pchar := SvgToString(doc); // ... svgStr verwenden ... // Pretty-Print aktivieren (Zeilenumbrüche + Einrückung): SvgSetPrettyPrint(doc, 1); // ViewBox setzen: SvgSetViewBox(doc, 0.0, 0.0, 800.0, 600.0); // Aufräumen: SvgFree(doc); ---- ===== Alles zusammen ===== import std.io; import std.svg.builder; import std.svg.elements; import std.svg.style; import std.svg.filter; import std.svg.anim; fn main(): int64 { var doc: int64 := SvgNew(400.0, 300.0); SvgSetPrettyPrint(doc, 1); SvgGroupBeginId(doc, "layer1"); SvgSetFillHex(doc, "#4682B4"); SvgCircle(doc, 100.0, 100.0, 30.0); SvgApply(doc); SvgGroupEnd(doc); var blur: int64 := SvgBlur(doc, 3.0); SvgSetFilter(doc, blur); SvgSetFillHex(doc, "#FF0000"); SvgRect(doc, 200.0, 50.0, 150.0, 80.0); SvgApply(doc); SvgAnimRepeat(doc, 0); SvgAnimate(doc, 0, "fill", "red", "blue", 2.0); SvgSetFillHex(doc, "red"); SvgCircle(doc, 200.0, 220.0, 40.0); SvgApply(doc); Print(SvgToString(doc)); Print("\n"); SvgFree(doc); return 0; } ---- ===== Bekannte Fallstricke ===== * Negative Koordinaten werden falsch geschrieben ([[https://github.com/SEOLizer/LyX-Compiler/issues/1686|#1686]]). * ''SvgCurveTo'' stürzt ab — ''SvgCurveTo2'' nehmen ([[https://github.com/SEOLizer/LyX-Compiler/issues/1688|#1688]]). * Symbole, Clip-Pfade und Masken bleiben leer ([[https://github.com/SEOLizer/LyX-Compiler/issues/1685|#1685]]). * ''SvgRoundRect'' verliert die Eckenradien ([[https://github.com/SEOLizer/LyX-Compiler/issues/1684|#1684]]). * Der Parser liefert Zahlen als Bitmuster ([[https://github.com/SEOLizer/LyX-Compiler/issues/1687|#1687]]). Letzte Aktualisierung: 2026-08-19 — Alle Ausschnitte gegen die echten Signaturen berichtigt (''SvgSetFont''/''SvgTextAt''/''SvgTspan'', ''SvgGroupBeginId'', ''SvgBlur''/''SvgDropShadow'' mit Filternummer, Animation über ''elem = 0'', ''SvgCurveTo2''); durchgehendes Beispiel mit ''lyxc 1.1.3I'' übersetzt und ausgeführt. Vorherige Aktualisierung: 2026-06-08 Codebeispiele geprüft: gegen **lyxc 1.2.5C** übersetzt (Prüflauf 2026-09-08 über die gesamte Doku: 574 Vollprogramme, 0 echte Fehler; zusätzlich 5159 Aufrufe gegen die ''pub fn''-Signaturen in ''aurum/std'' gehalten, 0 Abweichungen).