Inhaltsverzeichnis

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.

Guides · 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      — <path d="..."> 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);   // <path d="M50,100 L150,100 L100,50 Z" .../>

// 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 <g>:
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;
}

<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="400" height="300">
  <defs>
    <filter id="flt0">
      <feGaussianBlur stdDeviation="3"/>
    </filter>
  </defs>
  <g fill="#4682B4" id="layer1">
    <circle cx="100" cy="100" r="30"/>
  </g>
  <rect x="200" y="50" width="150" height="80" fill="#FF0000" filter="url(#flt0)"/>
  <circle cx="200" cy="220" r="40" fill="red" id="_a0">
  <animate attributeName="fill" from="red" to="blue" dur="2s" repeatCount="indefinite"/>
  </circle>
</svg>


Bekannte Fallstricke

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).