AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Projekte RedeemerSVG.TSVGImage - Kleine SVG-Unit für Delphi mit GDI
Thema durchsuchen
Ansicht
Themen-Optionen

RedeemerSVG.TSVGImage - Kleine SVG-Unit für Delphi mit GDI

Ein Thema von Redeemer · begonnen am 23. Aug 2017 · letzter Beitrag vom 30. Okt 2018
Antwort Antwort
Seite 5 von 5   « Erste     345   
Redeemer
Registriert seit: 19. Jan 2009
Da ich für ein eigenes Projekt SVG-Unterstützung (für Tiny 2.0, statisch) brauchte, aber mit den bestehenden Lösungen nicht zufrieden war (viel zu viele benötigte fremde Pakete), habe ich mir kurzerhand selbst eine geschrieben, die nur mit den Delphi-Canvas-Funktionen und GDI (nicht GDI+) arbeitet. Der Quelltext ist relativ klein. Es werden mein eigener XML-Reader (wegen der vielen nicht zwingend zu schließenden Tags) und diverse Parser, z.B. für Style-Angaben, verwendet. Die eigentliche SVG-Klasse ist etwa 1000 Zeilen lang. Der mit Abstand größte Teil des Projekts, das mit Vanilla-Delphi ab 2009 (wegen Generics) kompiliert, ist die Tabelle mit den XML-Entities (was nicht mal Inkscape unterstützt)... Alles in allem kompiliert derzeit zu gerade mal 150 KiB und LZMA-gepackt irgendwo bei unter 30 KiB plus PNG-Image wenn ihr das nicht schon nutzt.

Funktionsweise:
  • Es werden zwei TPNGImages (ich arbeite gerne damit, später eventuell Umstellung auf TBitmap) erstellt, eine in RGB für Farbe und eine in Graustufen für Deckkraft. Diese sind derzeit 3× breiter und höher als das Zielbild. Außerdem wird ein SVG-Kontext erstellt. Dieser enthält alle Style-Informationen und wird weitergereicht.
  • Anschließend werden die SVG-Elemente verarbeitet:
    • Der Stil wird aus den Attributen und dem style-Attribut geladen. style überschreibt andere Attribute. SVGTiny kann standardgemäß keine richtigen Stylesheets lesen, nur style-Attribute.
    • Zunächst einmal wird ohne Transformationen, aber mit einer erhöhten Genauigkeit (32× breiter und höher, um auszugleichen, dass GDI nur Ganzzahlen kann) mit den GDI-Pfadfunktionen auf eins der PNG-Bilder gezeichnet (bzw. so getan, als ob).
    • Der SVG-Kontext wird in den Brush, Pen, Font und weitere Optionen (Umgang mit Überlappungen, später Gehrung) der beiden PNG-Canvases geschrieben. Wannimmer Farben gesetzt werden, wird beim DeckkraftPNG stattdessen clWhite geschrieben. (Es gibt zwar genau für das Zeichen immer in Weiß eine Funktion beim einfachen Pen (den auch TPen kapsel), aber nicht beim erweiterten ExtCreatePen-Pen.)
    • Der Pfad wird mit GetPath in ein tagPOINT-Array geladen und anschließend aus dem PNG gelöscht. Auch Formen und die für Text verwendete ExtTextOut-Funktion ergeben einen solchen Pfad.
    • Die Punkte des Pfades werden mit allen weiteren Transformationen (affine Abbildungen) versehen und anschließend auf beide PNGs wieder gezeichnet (PolyDraw ist die Umkehrfunktion von GetPath). Die Transformationen finden mit Extended-Gleitkommazahlen statt und haben wie erwähnt eine 32-fache Grund-Genauigkeit. Erst direkt vorm finalen Zeichnen wird gerundet, sodass eine sehr hohe Qualität entsteht, obwohl GDI nur mit Ganzzahlen arbeitet. PS: Der Name dieser Funktion und ihrer Unit stehen nicht zur Diskussion.
  • Die Scanline des Deckkraft-PNG wird in die AlphaScanline des Farb-PNGs geschrieben.
  • Das sich ergebende PNG wird mittels meines ungewichteten Downscale-Algorithmus um den Faktor 3 je Achse verkleinert, um ein Antialias zu erzeugen. Das Ergebnis ist ein PNG-Bild mit ausreichend hübschem Antialias (TSVGImage leitet sich derzeit von TPNGImage ab, irgendwann könnte man das vielleicht zu TBitmap ändern).

Nennenswerte Einschränkungen:
  • Keine Halbtransparenz (Transparenz gibt es aber), da GDI keine Halbtransparenz zeichnen kann. Ich hatte überlegt, eine 10-stufige Halbtransparenz mittels 3×3-Muster (hierbei wird völlige Transparenz unterstützt) zu implementieren, das sähe allerdings an Kanten etwas ungleichmäßig aus und das Überlagern mehrerer solcher Objekte ergäbe kein sinnvolles Ergebnis. Prinzipiell könnte man ein drittes PNG nehmen, darauf zeichnen und anschließend an den bemalten Stellen die Berechnungen mit der Scanline durchführen. Aber will man das? (Bevor jemand fragt: Der TPenMode pmMerge sorgt dafür, dass bei jedem RGB-Kanal der jeweils hellere Wert genommen wird.)
  • Keine Farbverläufe und Filter.
  • Diverse exotische Attribute und Eigenschaften, jeweils fast ausschließlich beim text-Element, werden nicht unterstützt.
  • Die path-Befehle Catmull-Rom (wird als Gerade dargestellt) und Bearing (wird ignoriert) aus SVG2 werden nicht unterstützt.
  • Das image-Element.
  • Metrische Einheiten.
Details siehe die beiliegende Excel-Tabelle.

Tipps:
  • Nach Lesen aller nötigen Informationen des Wurzel-svg-Elements kann die Ausgabegröße mittels Event beeinflusst werden, das SizeCallback heißt und global auf ein folgendes Event gesetzt wird:
    Code:
    type TSizeCallbackEvent = procedure (const Viewport: TRealRect; var Dimensions: TRealPoint) of object;
    So kann das Bild skaliert werden.
  • Die Datei RedeemerHypertextColorsX11.pas wird nicht benötigt. Sie liegt bloß für den Fall bei, falls ihr wie ich RedeemerHypertextColors.HTMLToColor anderswo mit X11-Unterstützung brauchen solltet.
  • EXE-Demo liegt bei.

Lizenz:
Die Nutzung ist kostenlos. Wer es in einem eigenen Produkt verwendet, das nicht für den Eigenbedarf ist, muss mir eine Nachricht schreiben. Weiterentwicklungen und Ableitungen der Klasse TSVGImage müssen mir auf Wunsch zur Verfügung gestellt werden.

Feedback ist gerne gesehen!

Download (ca. 300 KiB)

Beispielbild der Karte von Niedersachsen von TUBS (Wikipedia). Das Forum kann es leider nicht in der Originalgröße, ich habe es zugeschnitten.
Beispielbild der Flugzeugentführung der Landshut von Devilm25 (Wikipedia). Sie ist nicht ganz perfekt, man sieht ganz gut, was die Engine kann und was nicht. Ich frage mich gerade, warum zwischen der letzten und der aktuellen Version meiner Unit die Grenze zwischen Eritrea und Äthiopien verschwunden ist (sie fehlt allerdings auch bei anderen SVG-Viewern).
Miniaturansicht angehängter Grafiken
niedersachsen.png   strichelungen.png   entfuehrung-der-landshut.png  
2005 PE, 2009 PA, XE2 PA

Geändert von Redeemer (20. Okt 2017 um 21:58 Uhr)
 
berens

 
Delphi 10.4 Sydney
 
#41
  Alt 7. Jun 2018, 16:10
Ich probiere gerade die Komponente aus.

Mir ist mit einer .svg-Datei passiert, dass die Angaben in "mm" waren. Entsprechender Fehler korrigiert:

Delphi-Quellcode:
unit RedeemerSVGHelpers;
// Zeile 93
if EndsText('px', temp) then
  Delete(temp, Length(temp) - 1, 2) // Standardeinheit, ignorieren
else if EndsText('pt', temp) then
Unterstützung für "mm" hinzugefügt. Schaut normal aus.
Delphi-Quellcode:
unit RedeemerSVGHelpers;
// Zeile 93
if EndsText('px', temp) then
  Delete(temp, Length(temp) - 1, 2) // Standardeinheit, ignorieren
else if EndsText('mm', temp) then
  Delete(temp, Length(temp) - 1, 2) // Standardeinheit, ignorieren
else
  if EndsText('pt', temp) then

Evtl. sollte die Prozedur so angepasst werden, dass der Text ist "temp" so bereinigt wird, dass wirklich nur Zahlen 0-9, "." und "," drin stehen dürfen, falls andere Einheiten hiermit immer noch nicht abgedeckt sind? Zumindest Incscape bietet neben "mm" noch "pc", "in" und "cm" an...
Delphi-Quellcode:
  // Zeile 113
  Value := ReadFloat(temp) * Factor;
Frage 1
Ein tatsächliches Problem was ich habe: Die andere Datei (siehe Anhang) wird nur hier nur als schwarzes Rechteck angezeigt, lässt sich in anderen Programmen aber ganz normal öffnen...

Frage 2
Delphi-Quellcode:
  SVG := TSVGImage.Create;
  SVG.LoadFromFile('c:\temp\svg.svg');
  SVG.SetSize(1000,900);
  Image1.Picture.Assign(SVG);
Das Bild wird leider nur ganz klein oben links dargestellt (ca. 32x32 px), des Rest des Bildes (1000x900 px) ist schwarz? Wie vergrößert man die SVG Graphik korrekt? Ich habe keine Ahnung wie ich das Callback-Event
type TSizeCallbackEvent = procedure (const Viewport: TRealRect; var Dimensions: TRealPoint) of object; innerhalb einer Prozedur (bzw. überhaupt) verwenden soll, hier fehlt mir komplett sowohl Grundlagenwissen wie Beispiel...
Angehängte Dateien
Dateityp: zip 01d.zip (1.005 Bytes, 7x aufgerufen)

Geändert von berens ( 7. Jun 2018 um 16:27 Uhr)
  Mit Zitat antworten Zitat
Redeemer

 
Delphi 2009 Professional
 
#42
  Alt 7. Jun 2018, 20:38
Hi,

die angehängte Datei ist keine SVGTiny-Datei. Meine Unit liest nur SVGTiny, weil sie sonst eine komplette CSS-Selektor-Logik enthalten müsste. Die Unterstützung des Style-Attributs ist hingegen in SVGTiny zwingend vorgeschrieben und wird unterstützt. Vielleicht gibt es irgendwo im Internet einen Konverter von SVG nach SVGTiny. Microsoft hat mal einen auf Github geladen, aber den gibt es nicht mehr glaube ich. Wer die SVG erstellt hat, muss sie wohl noch einmal als SVGTiny speichern. Meine Unit unterstützt eine scheinbar wahllose Auswahl von Features aus SVGTiny und SVG 2.0.

Für meinen Job habe ich die Unit gestern um die Eigenschaft vector-effects aus SVG 2.0 erweitert (klingt großartig, ist aber einfach nur das Deaktivieren der Konturenskalierung).

Zum SizeCallback: Du brauchst eine Ereignisbehandlung (eine Prozedur) mit genau den angegebenen Parametern. Nennen wir sie einfach HandleZoom :
Delphi-Quellcode:
procedure TForm1.HandleZoom(const Viewport: TRealRect; var Dimensions: TRealPoint);
begin
  Dimensions.x := StrToFloat(Edit4.Text) / 100 * Dimensions.x;
  Dimensions.y := StrToFloat(Edit4.Text) / 100 * Dimensions.y;
end;
Diese Prozedur sagt RedeemerSVG, es soll das Bild um den Prozentsatz in Edit4 zoomen. Bevor du das Bild lädst, setzt du das Superglobal SizeCallback auf diese Prozedur:
SizeCallback := HandleZoom;
Janni

Geändert von Redeemer ( 7. Jun 2018 um 20:41 Uhr)
  Mit Zitat antworten Zitat
Redeemer

 
Delphi 2009 Professional
 
#43
  Alt 29. Okt 2018, 22:21
Es gibt Neuigkeiten. Die nächste Version, wann auch immer sie rauskommt, unterstützt u.a.:
  • vector-effect="non-scaling-stroke"
  • Halbtransparenz (nur für schwarze und weiße Füllungen, wegen der Arbeitsweise von ROP2)
  • <image> (keine Transparenz)
  • <pattern> (keine Transparenz)
  • abschaltbare Transparenz und Supersampling (wegen Performance und Speicherbedarf)
  • standardkonformes Verhalten auf diverse völlig unsinnige Pfaddaten (z.B. Bézierkurven-Befehl ohne Kontrollpunkte)
  • Textdekoration
Außerdem habe ich heute gesamte Klassenlayout geändert. Die meisten Funktionen sind nun in einer Klasse TSVGInterpreter zu finden, die auf beliebige TCanvas-Erben zeichnen kann. Grund dafür ist, dass ich von der neuen Version 24 von List & Label (betrifft auch Version 23) maßlos enttäuscht bin. Die „SVG-Unterstützung“ beschränkt sich dort auf die Konvertierung in eine Rastergrafik und Transparenz wird bei Ausgabe auf einem Drucker auch nicht unterstützt... Meine neue Klasse TSVGMetafile zeichnet auf ein Delphi-Referenz durchsuchenTMetafileCanvas und erstellt so ein Delphi-Referenz durchsuchenTMetafile (EMF-Datei), das mit List & Label als Vektorgrafik ausgegeben wird. Metafiles sind einfach nur eine Liste von GDI-Befehlen, die entsprechende Anpassung meiner Klasse war dementsprechend sehr einfach.
Janni
  Mit Zitat antworten Zitat
EWeiss
 
#44
  Alt 30. Okt 2018, 07:01
Zitat:
[OT]
Die Nutzung ist kostenlos. Wer es in einem eigenen Produkt verwendet, das nicht für den Eigenbedarf ist, muss mir eine Nachricht schreiben. Weiterentwicklungen und Ableitungen der Klasse TSVGImage müssen mir auf Wunsch zur Verfügung gestellt werden.
[/OT]
Nur mal Informationshalber.
Und du denkst irgendjemand hält sich daran? Die Hoffnung stirbt zuletzt.

gruss

Geändert von EWeiss (30. Okt 2018 um 07:09 Uhr)
  Mit Zitat antworten Zitat
Redeemer

 
Delphi 2009 Professional
 
#45
  Alt 30. Okt 2018, 09:37
Na ja, ich würde ja erwarten, dass die Delphi-Community noch etwas Ehre hat. Mich würde halt interessieren, ob Leute überhaupt Interesse an SVG-Unterstützung für Delphi haben.

Warum informationshalber? Hast du irgendein Projekt entdeckt, dass das nutzt? Die gesamte Doku und alle Kommentare sind auf Deutsch, dadurch sollte sich der Kreis erheblich einschränken.
Janni
  Mit Zitat antworten Zitat
EWeiss
 
#46
  Alt 30. Okt 2018, 09:48
Zitat:
Warum informationshalber?
Weil ich andere Erfahrungen gesammelt habe.

Meistens wird nur das rausgepickt was von Interesse ist der Rest bleibt liegen.
Wirkliche Mitarbeit.. Fehl am platz.

Aber gut will nicht weiter drauf rumreiten.
Deshalb informationshalber.
Sorry das ich das angeschnitten habe.

gruss
  Mit Zitat antworten Zitat
Benutzerbild von jaenicke
jaenicke

 
Delphi 11 Alexandria
 
#47
  Alt 30. Okt 2018, 17:41
Wir haben einmal eine SVG Komponente gekauft. Ich habe auf jeden Fall vor diese zu ersetzen, denn die funktioniert deutlich schlechter als diese hier... Ich bin nur noch nicht dazu gekommen. Danke auf jeden Fall für deine Mühe.

Meistens wird nur das rausgepickt was von Interesse ist der Rest bleibt liegen.
Wirkliche Mitarbeit.. Fehl am platz.
Das passiert natürlich auch und damit muss man rechnen, aber für mich ist das kein Grund keine Open Source Quelltexte mehr zu veröffentlichen. Denn damit würde man ja auch die treffen, die sich an die Lizenzen halten.
Sebastian Jänicke
  Mit Zitat antworten Zitat
EWeiss
 
#48
  Alt 30. Okt 2018, 18:16
Wir haben einmal eine SVG Komponente gekauft. Ich habe auf jeden Fall vor diese zu ersetzen, denn die funktioniert deutlich schlechter als diese hier... Ich bin nur noch nicht dazu gekommen. Danke auf jeden Fall für deine Mühe.

Meistens wird nur das rausgepickt was von Interesse ist der Rest bleibt liegen.
Wirkliche Mitarbeit.. Fehl am platz.
Das passiert natürlich auch und damit muss man rechnen, aber für mich ist das kein Grund keine Open Source Quelltexte mehr zu veröffentlichen. Denn damit würde man ja auch die treffen, die sich an die Lizenzen halten.
Mir ist das etwas aufgestoßen.. aber natürlich berechtigt (ist seine Lizenz)
Zitat:
Die Nutzung ist kostenlos. Wer es in einem eigenen Produkt verwendet, das nicht für den Eigenbedarf ist, muss mir eine Nachricht schreiben. Weiterentwicklungen und Ableitungen der Klasse TSVGImage müssen mir auf Wunsch zur Verfügung gestellt werden.
Kann mir nicht denken das sich die Leute zwanghaft daran halten werden. (Ich meine das Muss, Müssen)
Ok war nur eine Frage man muss das jetzt nicht noch weiter aufbauschen.
Wie gesagt meine Erfahrung es ist den Leuten schlichtweg egal was da steht.

grusss
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 5 von 5   « Erste     345   


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 18:25 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz