Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Software-Projekte der Mitglieder (https://www.delphipraxis.net/26-software-projekte-der-mitglieder/)
-   -   RedeemerSVG.TSVGImage - Kleine SVG-Unit für Delphi mit GDI (https://www.delphipraxis.net/193635-redeemersvg-tsvgimage-kleine-svg-unit-fuer-delphi-mit-gdi.html)

Redeemer 23. Aug 2017 22:03


RedeemerSVG.TSVGImage - Kleine SVG-Unit für Delphi mit GDI
 
Liste der Anhänge anzeigen (Anzahl: 3)
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. :P
  • 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).

Rollo62 24. Aug 2017 17:44

AW: RedeemerSVG.TSVGImage - Kleine SVG-Unit für Delphi mit GDI
 
Hallo Redeemer,

schön das sich mal jemand dieses Themas annimmt.
Ich finde SVG ist ein total unterschätztes Format, und die bisherigen Lösungen die ich gesehen habe sind viel zu fett.
Deine kleine Library, mit den Basic-Funktionen und wenn möglich Support für Layer, wäre genau das was ich suche.
Ist das jetzt bei dir der Plan als Freeware, OpenSource, o.ä. anzubieten ?

Ich hätte mal folgende Frage, weil ich sehe das du Referenzen zu Windows/GDI drinhast.
Wärest du daran interessiert die Library für VCL und FMX fit zu machen, oder ist das schon dein Plan ?
Ich verstehe aber das du mit D2009 unterwegs bist, das könnte schwierig werden :stupid:

Ansonsten muss ich leider berichten das ich die Beispielbilder mit deiner Demo nicht
laden kann.
Vermutlich waren das die Fehlerbilder für uns zum Testen, richtig ?
In den Code habe ich noch nicht tiefer geschaut, ich denke das DemoProgramm dafür fehlt, deshalb kann ich auch nicht debuggen.
Einfachere SVG kann ich aber mit dem Demo anzeigen lassen, das ist schonmal super.

Rollo

bepe 24. Aug 2017 18:23

AW: RedeemerSVG.TSVGImage - Kleine SVG-Unit für Delphi mit GDI
 
Das ist interessant. Wegen der hochauflösenden Monitore spiele ich mit dem Gedanken, die Png's für Toolbar und co. durch SVG's zu ersetzen. Werde ich mir ansehen...

Aber spontan ist mir das ins Auge gefallen:

Zitat:

Zitat von Redeemer (Beitrag 1379306)
[*]Andere Codepages als UTF-8. UTF-8 ist der Standard, ärgerlich ist das nur, weil TStringList.LoadFromStream() mit TEncoding.UTF8 im Fall von ungültigen UTF-8-Codes überhaupt nichts tut.

Versuch das:
Delphi-Quellcode:
type
  TCustomUTF8Encoding = class(TUTF8Encoding)
  public
    constructor Create; override;

  end;
...
{ TCustomUTF8Encoding }

constructor TCustomUTF8Encoding.Create;
begin
  inherited Create(CP_UTF8, 0, 0); // Embas UTF8 setzt MB_ERR_INVALID_CHARS und führt zu dem Problem
  FIsSingleByte := False;
end;
Hier die Erklärung für die Flags. Mehr kann ich nicht schreiben, sonst ärgere ich mich schon wieder maßlos über die RTL- und VCL-Klassenstrukturen...

Redeemer 24. Aug 2017 22:23

AW: RedeemerSVG.TSVGImage - Kleine SVG-Unit für Delphi mit GDI
 
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:

Zitat von Rollo62 (Beitrag 1379392)
Hallo Redeemer,

schön das sich mal jemand dieses Themas annimmt.
Ich finde SVG ist ein total unterschätztes Format, und die bisherigen Lösungen die ich gesehen habe sind viel zu fett.
Deine kleine Library, mit den Basic-Funktionen und wenn möglich Support für Layer, wäre genau das was ich suche.

Was ist mit Layer gemeint?

Zitat:

Zitat von Rollo62 (Beitrag 1379392)
Ist das jetzt bei dir der Plan als Freeware, OpenSource, o.ä. anzubieten ?

Keine Ahnung. Dieser Post war nur die Frage, ob überhaupt Interesse an einer ausdrücklich kleinen SVG-Bibliothek besteht.

Zitat:

Zitat von Rollo62 (Beitrag 1379392)
Ich hätte mal folgende Frage, weil ich sehe das du Referenzen zu Windows/GDI drinhast.
Wärest du daran interessiert die Library für VCL und FMX fit zu machen, oder ist das schon dein Plan ?
Ich verstehe aber das du mit D2009 unterwegs bist, das könnte schwierig werden :stupid:

Ich ahbe auch XE2 hier rumliegen, nutze ich nur recht selten. Was meinst du mit VCL? Das Teil registriert sich als VCL-Bildklasse.
Da FMX ja plattformunabhängig ist, frage ich mich auch, inwieweit das mit GDI machbar sein soll.

Zitat:

Zitat von Rollo62 (Beitrag 1379392)
Ansonsten muss ich leider berichten das ich die Beispielbilder mit deiner Demo nicht
laden kann.
Vermutlich waren das die Fehlerbilder für uns zum Testen, richtig ?
In den Code habe ich noch nicht tiefer geschaut, ich denke das DemoProgramm dafür fehlt, deshalb kann ich auch nicht debuggen.
Einfachere SVG kann ich aber mit dem Demo anzeigen lassen, das ist schonmal super.

Rollo

Die Niedersachsenkarte geht, es dauert nur etwas (20 Sekunden auf meinem Laptop). Bei 1 MB Quelltext, der verarbeitet werden muss...
Das Bild der Landshut funktioniert wie erwähnt nur, wenn man die Höhenangabe (height) aus dem SVG-Tag löscht. Ich habe kurz vor Release Support für die wissenschaftliche e-Schreibweise von Zahlen eingebaut und übersehen, dass ich den Exponenten nur auf Kommazahlen, nicht jedoch auf Ganzzahlen (wie hier 1e3) anwende (letzte Zeile von RedeemerFloat, ergänze "* Exponent").

Zitat:

Zitat von bepe (Beitrag 1379393)
Das ist interessant. Wegen der hochauflösenden Monitore spiele ich mit dem Gedanken, die Png's für Toolbar und co. durch SVG's zu ersetzen. Werde ich mir ansehen...

Man müsste echt mal evaluieren, wie schlimm das Fehlen des ArcTo-Befehls von path ist. Ich glaube, ich habe das unterschätzt. Gut dokumentiert wird es, nur widerspricht diese Demo meiner Meinung nach der Formel.

Zitat:

Zitat von bepe (Beitrag 1379393)
Aber spontan ist mir das ins Auge gefallen:

Zitat:

Zitat von Redeemer (Beitrag 1379306)
[*]Andere Codepages als UTF-8. UTF-8 ist der Standard, ärgerlich ist das nur, weil TStringList.LoadFromStream() mit TEncoding.UTF8 im Fall von ungültigen UTF-8-Codes überhaupt nichts tut.

Versuch das:
Delphi-Quellcode:
type
  TCustomUTF8Encoding = class(TUTF8Encoding)
  public
    constructor Create; override;

  end;
...
{ TCustomUTF8Encoding }

constructor TCustomUTF8Encoding.Create;
begin
  inherited Create(CP_UTF8, 0, 0); // Embas UTF8 setzt MB_ERR_INVALID_CHARS und führt zu dem Problem
  FIsSingleByte := False;
end;
Hier die Erklärung für die Flags. Mehr kann ich nicht schreiben, sonst ärgere ich mich schon wieder maßlos über die RTL- und VCL-Klassenstrukturen...

Danke, werde ich mir mal ansehen.

/Edit: Die Grenze zwischen Äthiopien und Eritrea fehlt in Firefox und im Wikimedia-Rasterisierer, worauf auch immer der basiert. Umso lustiger, dass sie in einer früheren Version meiner Engine da war, wonach ich kaum noch was geändert habe...

DerAndereMicha 25. Aug 2017 08:21

AW: RedeemerSVG.TSVGImage - Kleine SVG-Unit für Delphi mit GDI
 
Hallo Redeemer,

ein wirklich tolles Projekt, aber leider mit derartigen Ladezeiten (noch) nicht wirklich nutzbar.

Diese Karte:

https://commons.wikimedia.org/wiki/F...cation_map.svg

wird zwar geladen, Dein Demo braucht dazu aber, statt wie der Browser < 1 Sekunde, bei mir auf dem PC über 7 Sekunden. Da gibt es doch bestimmt noch einiges zu optimieren, oder?

Andere Dateien scheinen allerdings überhaupt nicht zu funktionieren:

https://upload.wikimedia.org/wikiped...cation_map.svg

zumindest habe ich hier nach 5 Minuten Eieruhr das Programm abgebrochen.

Ich finde Dein Projekt durchaus interessant, vor allem weil es bisher keine freie Komponente zu geben scheint, die auch wirklich produktiv nutzbar ist. Das es mit Delphi durchaus kompakt und schnell funktioniert, zeigt diese kommerzielle Komponente, welche ich momentan für eines meiner Projekte nutze.

Gruß
Micha

Rollo62 25. Aug 2017 10:13

AW: RedeemerSVG.TSVGImage - Kleine SVG-Unit für Delphi mit GDI
 
Liste der Anhänge anzeigen (Anzahl: 1)
Wieso lädt das bei euch ?

Wenn ich die Datei mit deinem Demo öffne, mit Lade SVG, z.B. das letzte mit Germany_location_map.svg, dann kommt das siehe Anhang.
Genauso bei den beiden orginalen Beispielen.

Nur sehr einfache Icons hatte ich noch getestet, die funktionierten.

Rechner: Win10-Pro aktuell

Rollo

Redeemer 26. Aug 2017 00:21

AW: RedeemerSVG.TSVGImage - Kleine SVG-Unit für Delphi mit GDI
 
Keine Ahnung, warum es bei dir nicht läuft. Habe das mit der Geschwindigkeit korrigiert (bei größeren Dateien locker Faktor 100 und mehr), da ich wegen Bahnchaos seit langer Zeit in einer Stadt festsitze, die es noch nicht mal gibt.
Grund für die Performanceprobleme war praktisch nur eine einzige Funktion: StrUtils.MidStr. Meine eigenen Funktionen waren nicht Schuld. Habe MidStr durch Copy ersetzt und einige andere Optimierungen mit Generics.Collections.TDictionary durchgeführt. Changelog liegt bei.
Link hat sich nicht geändert.

Danke für das Feedback schonmal. Warum es bei dir nicht geht, Rollo, weiß ich nicht. Kannst ja mal probieren, das selbst zu kompilieren.

DerAndereMicha 26. Aug 2017 08:36

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

Habe das mit der Geschwindigkeit korrigiert (bei größeren Dateien locker Faktor 100 und mehr),
Super! Zwar ist es immer noch nicht ganz so schnell wie die kommerzielle Konkurrenz, aber jetzt scheint es mir auf jeden Fall produktiv nutzbar zu sein. Ich werde es bei Gelegenheit mal versuchen in meinem Projekt testweise einzusetzen.

Ab welcher Delphi-Version ist es kompilierbar?

Gruß
Micha

Redeemer 26. Aug 2017 11:08

AW: RedeemerSVG.TSVGImage - Kleine SVG-Unit für Delphi mit GDI
 
Ist mit Delphi 2009 geschrieben. Sollte aber mit allen nachfolgenden laufen, da es nur sehr wenige grundlegende Delphifunktionen verwendet und stattdessen viele GDI-API-Calls.

DerAndereMicha 26. Aug 2017 12:17

AW: RedeemerSVG.TSVGImage - Kleine SVG-Unit für Delphi mit GDI
 
Schade. Ich habe noch ein anderes Projekt hier, welches mit Delphi 2007 geschrieben wurde und dort hätte ich gerne eine WMF-Lösung durch SVG ersetzt. Leider funktioniert nämlich auch die schon von mir erwähnte kommerzielle SVG-Komponente nicht mehr unter Delphi 2007.

Gruß
Micha

Rollo62 26. Aug 2017 12:39

AW: RedeemerSVG.TSVGImage - Kleine SVG-Unit für Delphi mit GDI
 
Hätte ich schon gemacht und gecheckt wo der Fehler herkommt. Aber das Demo fehlt in dem File.
Ich habe jetzt keine Zeit das alles selber nachzubauen

Rollo

Redeemer 26. Aug 2017 14:21

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

Zitat von DerAndereMicha (Beitrag 1379527)
Schade. Ich habe noch ein anderes Projekt hier, welches mit Delphi 2007 geschrieben wurde und dort hätte ich gerne eine WMF-Lösung durch SVG ersetzt. Leider funktioniert nämlich auch die schon von mir erwähnte kommerzielle SVG-Komponente nicht mehr unter Delphi 2007.

Gruß
Micha

Die alte Version dürfte auch in Delphi 2007 kompiliert haben (TEncoding aus TStringList.LoadFromStream rausschmeißen), inzwischen nutzt es mehrere Generics, dementsprechend wird es nicht laufen. Sie dürfte bereits deutlich schneller laufen, wenn man konsequent einfach das Wort "MidStr" durch "Copy" ersetzt. Eventuell brauchst du PNGDelphi.

Den Quelltext der Demo-App werde ich demnächst mal beilegen. Stürzt die neueste Version immer noch bei dir ab?

samso 26. Aug 2017 16:53

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

Zitat von Redeemer (Beitrag 1379529)
Es werden mein eigener XML-Reader (wegen der vielen nicht zwingend zu schließenden Tags)...verwendet

Das "wegen der vielen nicht zwingend zu schließenden Tags" verstehe ich nicht. Ist SVG also keine gültiges XML-Format? Hast Du ein Beispiel für die Abweichungen im Format?

Redeemer 26. Aug 2017 20:21

AW: RedeemerSVG.TSVGImage - Kleine SVG-Unit für Delphi mit GDI
 
SVG2 ist, ebenso wie HTML4 und HTML5, im Allgemeinen kein gültiges XML. XHTML und ich glaube auch SVG1 waren XML. Für SVG2 steht das nirgendwo ganz konkret, aber im Draft steht:
Zitat:

SVG is defined in terms of a document object model (DOM), rather than a particular file format or document type. For SVG content, therefore, conformance with this specification is defined by whether the content is or can generate a conforming DOM. Additional conformance classes depend on whether the content is also valid and well-formed XML.
Anschließend steht da mehr oder weniger, dass SVG nur XML ist, wenn es gültiges XML ist.
Der erste Satz der Spezifikation wurde von SVG1 zu SVG2 von "described in XML" in "based on XML" geändert.

HTML4 und HTML5 sind ganz eindeutig kein XML. <td>, <li> und viele weitere müssen ja nicht geschlossen werden.

samso 27. Aug 2017 07:06

AW: RedeemerSVG.TSVGImage - Kleine SVG-Unit für Delphi mit GDI
 
Danke für die Erklärung. Das klingt ja nicht so toll.

jaenicke 27. Aug 2017 07:51

AW: RedeemerSVG.TSVGImage - Kleine SVG-Unit für Delphi mit GDI
 
Ich verstehe die Spezifikation so, dass SVG alleine XML kompatibel ist, aber auch mit HTML Syntax in HTML-Dokumente eingebettet werden kann.

Gibt es bei SVG tatsächlich Elemente die gar nicht geschlossen werden müssen, oder nur die Möglichkeit von self closing tags?

himitsu 27. Aug 2017 09:41

AW: RedeemerSVG.TSVGImage - Kleine SVG-Unit für Delphi mit GDI
 
Wenn/da es mit XML kompatibel ist, müssen alle Elemente geschlossen sein.
Allgemein ist XML mit HTML kompatibel und mit XHTML sowieso, bzw. XHTML ist eigentlich eine Erweiterung von HTML, die mit XML kompatibel ist.

Redeemer 27. Aug 2017 12:51

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

Zitat von jaenicke (Beitrag 1379552)
Ich verstehe die Spezifikation so, dass SVG alleine XML kompatibel ist, aber auch mit HTML Syntax in HTML-Dokumente eingebettet werden kann.

Welche hast du gelesen? SVG1 und SVG2 sind da komplett unterschiedlich. Der von mir zitierte Teil ist durch „can generate a conforming DOM“ ja schon sehr deutlich, dass eine SVG2-Datei weder XML noch DOM ist. Statt mir kompliziert das dazugehörige XML oder DOM zu generieren, habe ich mir lieber einen Parser geschrieben, der da toleranter ist.
Ich weiß gerade keine Tags, die nur optional geschlossen werden müssen, das liegt aber auch daran, dass ich keine Website finden konnte, wo das steht. selfHTML behandelt in der Hinsicht nur SVG1. Meine Klasse lädt übrigens auch das erste SVG-Bild in HTML-Dateien, was nicht unbedingt beabsichtigt ist, aber ein nettes Feature.

Redeemer 1. Sep 2017 14:00

AW: RedeemerSVG.TSVGImage - Kleine SVG-Unit für Delphi mit GDI
 
Habe die neue Version 0.2b-alpha um die Lösung mit dem alternativen UTF-8-Encoding ergänzt. Der Download enthält jetzt das Projekt für die Demoanwendung.

In dem Projekt, in dem ich das nutze, habe ich leider ein Problem:
Delphi-Quellcode:
type TSVGImage = class(TPNGImage)
  ...
end;

...

procedure DoSomething();
var
  GraphicClass: TGraphicClass;
  Graphic: TGraphic;
begin
  GraphicClass := TSVGImage;
  Graphic := GraphicClass.Create(); // Ruft TPNGImage.Create() auf. (schlecht)
  // ...aber...
  Graphic := TSVGImage.Create();    // Ruft TSVGImage.Create() auf. (gut)
end
Das liegt wohl daran, dass ich bei Create reintroduce verwende statt override, denn die CreateBlank-Methode des zugrundeliegenden PNG-Bilds benötigt die Create-Methode des PNG-Bilds, weshalb ich Create nicht überschreiben kann. Habt ihr da Ideen?

TiGü 1. Sep 2017 14:21

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

Zitat von Redeemer (Beitrag 1380134)
]Das liegt wohl daran, dass ich bei Create reintroduce verwende statt override, denn die CreateBlank-Methode des zugrundeliegenden PNG-Bilds benötigt die Create-Methode des PNG-Bilds, weshalb ich Create nicht überschreiben kann. Habt ihr da Ideen?

Hä, wieso nicht override?
Du rufst doch den TPNGImage.CreateBlank innerhalb deines TSVGImage.Create auf. Muss doch gehen ohne reintroduce.

Delphi-Quellcode:
...
  public
    constructor Create(); override;
    procedure LoadFromStream(Stream: TStream); override;
end;

constructor TSVGImage.Create;
begin
  inherited CreateBlank(COLOR_RGBALPHA, 8, 1, 1); // 0 führt beim Setzen einer neuen Größe zum Fehler
end;

Redeemer 1. Sep 2017 16:56

AW: RedeemerSVG.TSVGImage - Kleine SVG-Unit für Delphi mit GDI
 
Delphi-Quellcode:
inherited CreateBlank
ruft
Delphi-Quellcode:
Create
auf. Wenn ich
Delphi-Quellcode:
Create
überschreibe, gibt's also 'ne endlose Rekursion und damit einen Stack Overflow.

TiGü 4. Sep 2017 08:14

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

Zitat von Redeemer (Beitrag 1380150)
Delphi-Quellcode:
inherited CreateBlank
ruft
Delphi-Quellcode:
Create
auf. Wenn ich
Delphi-Quellcode:
Create
überschreibe, gibt's also 'ne endlose Rekursion und damit einen Stack Overflow.

Ja richtig, da habe ich nicht mitgedacht bzw. nicht ausprobiert.

Du musst letztendlich gar nichts hinschreiben und es sollte dann so gehen wie gewünscht:

Delphi-Quellcode:

type
  TMyPngImage = class(TPngImage)
  public
    constructor Create;
  end;

...

{ TMyPngImage }

constructor TMyPngImage.Create;
begin
  inherited CreateBlank(COLOR_RGBALPHA, 8, 1, 1);
end;

jaenicke 4. Sep 2017 08:52

AW: RedeemerSVG.TSVGImage - Kleine SVG-Unit für Delphi mit GDI
 
Das ist einer der Gründe weshalb Konstruktoren möglichst schlank sein sollten. In diesem Fall reicht es doch CreateBlank nicht als Konstruktor zu implementieren (was ohnehin nicht schön ist), sondern als simple Methode. Der überschriebene Konstruktor ruft dann CreateBlank und nur inherited auf, das war es.

Redeemer 10. Sep 2017 16:51

AW: RedeemerSVG.TSVGImage - Kleine SVG-Unit für Delphi mit GDI
 
0.3-alpha ist draußen. Noch ein bisschen schneller (aber unter 10% Gewinn). Link bleibt gleich.
Habe das Create-Problem gelöst, indem ich den benötigten Teil der CreateBlank-Methode kopiert habe.

@TiGü: Nichts hinschreiben und reintroduce sind dasselbe, nur bei ersterem meckert der Compiler.
@jaenicke: Leider ist das im TPNGImage deklariert.

Redeemer 14. Okt 2017 22:12

AW: RedeemerSVG.TSVGImage - Kleine SVG-Unit für Delphi mit GDI
 
Liste der Anhänge anzeigen (Anzahl: 1)
So, hier mal ein kleines Update. Oder großes. 0.4-alpha wäre draußen. Kompatibilität hat wieder einen großen Sprung gemacht. Genaues Changelog liegt bei. Link wie zuvor im Anfangspost.

Kleine Info: Das Ding kompiliert wie erwartet ohne Änderungen auch in Vanilla-XE2 und läuft dort etwas schneller (Win32) bzw. merklich langsamer (Win64) als bei 2009. Allerdings ist bereits die Win32-Version des Demo-Programms mehr als doppelt und die Win64-Version mehr als dreimal so groß.

Nächster Schritt wäre, erneut ArcTo zu versuchen und das dann selbst zu berechnen. Vermutlich in 1°-Schritten oder so, da ich nicht weiß, wie man einen Kreisausschnitt in Bézier-Kurven darstellen kann. Falls das jemand weiß, gerne her damit. In GDI gibt es eine Funktion dafür (heißt ebenfalls ArcTo), aber der fehlt leider die Möglichkeit, die x-Achse der Ellipse zu kippen, was SVG kann. Vielleicht spiele ich nachher mal mit Geogebra herum.

Ein weiteres Feature für die nächste Version sind Rasterbilder. Spaß machen hier zwei Dinge: Alphakanal (da dann doch mal) und Transformationen. Vermutlich werde ich ein Rechteck von der Größe des Bildes erstellen und darauf die Transformationen anwenden. Ich bilde dann jeweils die Minima und die Maxima der transformierten Eckkoordinaten. Dann iteriere ich vom Minimum zum Maximum und nutze eine Umkehrfunktion. Wenn ich das richtig sehe, ist eine affine Abbildung, deren Bildraum weder eine Gerade noch ein Punkt ist (in diesen Fällen bräuchte ich das Bild nicht zeichnen), eine bijektive Abbildung, also kann ich die Umkehrfunktion bilden. Bildet die Umkehrfunktion die derzeit iterierte Koordinate auf das Bild ab, kopiere ich den Pixel vom Punkt im Bild. Müsste so klappen.

Langsam merke ich, dass so'n Mathe-Studium doch was bringt.

(Zum angehängten Vergleich: Der Unterschied zwischen 0.2 und 0.3 ist im Innenwinkel des V zu finden. Ich weiß spontan nicht, warum.)

Redeemer 20. Okt 2017 20:39

AW: RedeemerSVG.TSVGImage - Kleine SVG-Unit für Delphi mit GDI
 
Liste der Anhänge anzeigen (Anzahl: 1)
Habe Sonntag und Montag den path-Befehl ArcTo implementiert und ein paar Fehler behoben. Ich möchte bis auf weiteres auf image verzichten. Damit ist v0.5-beta die (vorerst) finale Version.
Ich möchte wissen, wer die Klasse in Produkten verwendet, die nicht für den Eigenbedarf sind, daher bleibt eine Nachricht an mich Lizenzbedingung. Die Nutzung ist aber kostenlos.

Zitat:

Zitat von Bernhard Geyer (Beitrag 1284547)
Du kannst dir mal anschauen was SVG so bedeutet? Da wird schon einige Mannjahre Entwicklung nötig sein.

:stupid:

mensch72 20. Okt 2017 20:51

AW: RedeemerSVG.TSVGImage - Kleine SVG-Unit für Delphi mit GDI
 
wenn ich deinen Source "real" verwende, bekommst du ne Message:)


(aktuell ist deine GDI only Stategie für mich ne coole simple Basis, um weitere "XY portatble" Sachen daraus abzuleiten und zu testen)

Redeemer 20. Okt 2017 21:00

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

Zitat von mensch72 (Beitrag 1383811)
(aktuell ist deine GDI only Stategie für mich ne coole simple Basis, um weitere "XY portatble" Sachen daraus abzuleiten und zu testen)

Was meinst du mit XY Portable?

mensch72 21. Okt 2017 10:48

AW: RedeemerSVG.TSVGImage - Kleine SVG-Unit für Delphi mit GDI
 
Da es für EmbeddedSysteme(also XY Hardware mit XY Microcontroler mit RealTimeOS oder Hardcore ganz ohne OS) keine aus meiner Sicht portablen(im Sinn von WinGDI kompatibel) und bezahlbaren GrafikLibs gab, hatte ich mir auf Basis der Analyse von Sourcen alter SoftwareOnly WIN-VGA-Treiber und FullSoftware RDP-Sourcen etwas eigenes "80..90% GDI kompatibles" geschrieben, was letztendlich direkt PixelByPixel im QuadBufferd/Switched-HW-Bildschirmspeicher(den es also 4x gibt) arbeitet.

Zu gut deutsch, ich kann in Grenzen den Visualisierungsteil unter Windows auf GDI-Basis entwickeln und nutze dann den "GrafikSourcecode" in meinen EmbeddedSystemen. Vor vielen Jahren war das mit eigener Hardware durchaus noch sinvoll, dann RaspberryPI, nun innendrin billigster AndroidMassenSchrott der ein integriertes Display hat...

Je besser die HW-Basis und das (OS)API(z.B. auch FMX), um so leichter ist der GDI-API-Adapter "rückwärts" jeweils zu realisieren... zum Schluss ist für mich das funktional/logisch dann alles gleich, weil ich überall (m)einen GDI kompatiblen Grafikcode zur Visualisierung einsetzen kann... und da wird es durchaus cool, statt PixelPildern über die meist weiter sehr langsamen Embedded Kommunikationswege dann lieber SVGs zu übertragen, um daraus dann doch "wieder schöne Darstellungen" live zu erzeugen... mir geht es da also hauptsächlich um die Cachespeicher- & Bandbreitenoptimierung, mit Delphi hat das garnix mehr zu tun ;)

(aktuell verfolgen die Leute von "FMXlinux" bei ihrem "CrossVCL" Projekt den exakt gleichen Grundgedanken, nur gehen die mit GDI+ und OpenGL noch viel weiter... die entwickeln ja auch sagen wir für eine Hardwarebasis mit "DesktopCPU&RAM-Power":) )

TiGü 23. Okt 2017 08:32

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

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).
War Eritrea im Jahre 1977 nicht ein Teil von Äthiopien?

TiGü 23. Okt 2017 11:05

AW: RedeemerSVG.TSVGImage - Kleine SVG-Unit für Delphi mit GDI
 
So kannst du im LoadFromStream eine handvoll Millisekunden sparen:
Delphi-Quellcode:
  sl: TStringStream;
begin
  sl := TStringStream.Create('', TCustomUTF8Encoding.Create);
  try
    sl.LoadFromStream(Stream);
    XML := TRedeemerXML.Create(sl.DataString);
  finally
    sl.Free;
  end;

Redeemer 28. Okt 2017 16:33

AW: RedeemerSVG.TSVGImage - Kleine SVG-Unit für Delphi mit GDI
 
Kleine Frage mal an die, die die Klasse benutzen: Mit welchen Delphi-Versionen kompiliert die? Müsst ihr was anpassen?

Zitat:

Zitat von TiGü (Beitrag 1383915)
Zitat:

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).
War Eritrea im Jahre 1977 nicht ein Teil von Äthiopien?

Absolut korrekt, danke. Das erklärt's. Dann hat wohl der Ersteller der Karte die entsprechende Grenze mit irgendwas übergekritzelt, was zu der Zeit, als die Grenze da war, noch nicht unterstützt wurde.

Zitat:

Zitat von TiGü (Beitrag 1383933)
So kannst du im LoadFromStream eine handvoll Millisekunden sparen:
Delphi-Quellcode:
  sl: TStringStream;
begin
  sl := TStringStream.Create('', TCustomUTF8Encoding.Create);
  try
    sl.LoadFromStream(Stream);
    XML := TRedeemerXML.Create(sl.DataString);
  finally
    sl.Free;
  end;

Brachte in meinem Test überhaupt selbst mit einer 6 MiB großen SVG-Datei keinen Unterschied, außer dass die EXE 1,5 KiB größer wurde. Gestört hat mich das mit TStringList auch schon. Mich stört auch, dass der String beim Laden aus einem TMemoryStream (was in dem Projekt, wofür ich es benötige, üblich ist) zeitweise dreimal im Speicher ist. TByteStream sah auch Interessant aus, aber ich benutze mit Pos und Copy einige Funktionen, die nur für Strings (genau so) funktionieren.

TiGü 1. Nov 2017 11:12

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

Zitat von Redeemer (Beitrag 1384423)
Zitat:

Zitat von TiGü (Beitrag 1383933)
So kannst du im LoadFromStream eine handvoll Millisekunden sparen:
Delphi-Quellcode:
  sl: TStringStream;
begin
  sl := TStringStream.Create('', TCustomUTF8Encoding.Create);
  try
    sl.LoadFromStream(Stream);
    XML := TRedeemerXML.Create(sl.DataString);
  finally
    sl.Free;
  end;

Brachte in meinem Test überhaupt selbst mit einer 6 MiB großen SVG-Datei keinen Unterschied, außer dass die EXE 1,5 KiB größer wurde. Gestört hat mich das mit TStringList auch schon. Mich stört auch, dass der String beim Laden aus einem TMemoryStream (was in dem Projekt, wofür ich es benötige, üblich ist) zeitweise dreimal im Speicher ist. TByteStream sah auch Interessant aus, aber ich benutze mit Pos und Copy einige Funktionen, die nur für Strings (genau so) funktionieren.

Jo, mit einer handvoll Millisekunden meinte ich auch wirklich nur so 5 ms.
Wenn das gesamte Laden und Darstellen so 600 bis 700 ms dauert, ist das natürlich total schnurzpiepe, aber wenn man mit einfachen Mitteln hier optimieren kann...warum nicht?

Was du noch mal optimieren kannst wäre die Übergabe von TSVGContext.
Das Record mit allen Unter-Records ist ja 184 Byte groß. In den ganzen Handle...-Methoden übergibst du das ja sehr oft (mehrere hundert bis tausend mal) per by-value. Das heißt die 184 Byte werden immer kopiert.
Wenn du da deine Klasse optimieren könntest, wären definitiv noch Geschwindigkeitszuwächse zu erwarten.

Redeemer 1. Nov 2017 11:56

AW: RedeemerSVG.TSVGImage - Kleine SVG-Unit für Delphi mit GDI
 
Auch bei Dateien, die 2,5 Sekunden zum Laden brauchen, konnte ich keine Millisekunde Unterschied feststellen.

Der Context muss kopiert werden. In den Handle-Methoden werden Stile geladen, die nur den aktuellen Context (und Unteraufrufe) betreffen und danach wieder rückgängig gemacht werden müssen.

TiGü 1. Nov 2017 12:12

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

Zitat von Redeemer (Beitrag 1384687)
Der Context muss kopiert werden. In den Handle-Methoden werden Stile geladen, die nur den aktuellen Context (und Unteraufrufe) betreffen und danach wieder rückgängig gemacht werden müssen.

Kannst du das etwas ausführen? So sehr stehe ich im SVG parsen und verarbeiten ja nicht drin.

Könnte man - jetzt mal nur so theoretisch ins Blaue philosophiert - nicht einfach für jeden Style und/oder Figur (Text, Rect, Circle...) sich den passenden Context vorhalten?
Oder wie muss man sich die Zusammenhänge vorstellen?
Wenn der Context der in HandleTag übergeben wird und für die einzelnen verschiedenen CurrentTags eh verschieden ist, wäre ein Dictionary mit TSVGContext als class (4 Byte versus 184 Byte) nicht eine Überlegung wert?

Redeemer 1. Nov 2017 12:42

AW: RedeemerSVG.TSVGImage - Kleine SVG-Unit für Delphi mit GDI
 
HTML-Code:
<svg width="28" height="28">
  <g fill="yellow" stroke="black">
    <rect fill="red" x="3" y="3" width="10" height="10" />
    <g fill="blue">
      <rect fill="green" x="15" y="3" width="10" height="10" />
      <rect x="3" y="15" width="10" height="10" />
    </g>
    <rect x="15" y="15" width="10" height="10" />
  </g>
</svg>
(Ergibt das bunte Windows-Logo.)

Die Standardfüllung von SVG ist schwarz. Die erste Gruppe (g) setzt die Füllung für alle Kindelemente auf gelb und die Kontur auf schwarz. Das erste Rechteck setzt die Füllung auf rot, behält aber die Kontur bei. Nachdem das Rechteck gezeichnet ist, müssen alle Eigenschaften zurückgesetzt werden, die das Rechteck gesetzt hat. Die zweite Gruppe (g) setzt die Füllung für alle Kindelemente auf blau und behält die Kontur bei. Das erste Rechteck setzt die Füllung auf rot, behält aber die Kontur bei. Nachdem das Rechteck gezeichnet ist, müssen alle Eigenschaften zurückgesetzt werden, die das Rechteck gesetzt hat. Das dritte Rechteck (zweites der zweiten Gruppe) wird nun mit der Füllung der Gruppe gezeichnet. Diese wird allerdings sofort danach ebenfalls zurückgesetzt auf die Farbe Gelb der Elterngruppe. Diese wird für das letzte Rechteck benötigt. Nach dem Ende der Gruppe ist die Füllung wieder zurück auf Standard, also schwarz.

Der Kontext muss deshalb natürlich auf dem Stapel abgelegt werden. Soweit ich den Vortrag auf den Delphi-Tagen dieses Jahr richtig verstanden habe, wird da von Delphi optimiert, damit keine Dinge kopiert werden, die man nicht schreibt.

TiGü 1. Nov 2017 13:20

AW: RedeemerSVG.TSVGImage - Kleine SVG-Unit für Delphi mit GDI
 
Verstehe...hm hm hm.
Man könnte so ein Recall-Ansatz versuchen und TSVGContext zur Klasse machen.

http://docwiki.embarcadero.com/Libra...hRecall.Create

Ob das ständige erzeugen und freigeben der Context-Recall-Klasse aber dann weniger zeitintensiv ist als das Kopieren des records...wer weiß?!

Redeemer 1. Nov 2017 13:59

AW: RedeemerSVG.TSVGImage - Kleine SVG-Unit für Delphi mit GDI
 
Wieso sollte ich etwas in TRecall speichern, was ich exakt ein einziges Mal verwende?

TiGü 1. Nov 2017 14:24

AW: RedeemerSVG.TSVGImage - Kleine SVG-Unit für Delphi mit GDI
 
Recall würde die Werte der Klasseninstanz von TSVGContext (wenn es dann eine Klasse wird) wieder zurück schreiben, wenn sie in ReadStyle geändert wurden.
Ähnlich wie dem Verwerfen der Änderung auf der lokalen Record-Kopie.
Ob das dann am Ende schneller ist als mit record muss natürlich geprüft werden, dass kann ich so auch nicht sehen.

TiGü 4. Jun 2018 14:38

AW: RedeemerSVG.TSVGImage - Kleine SVG-Unit für Delphi mit GDI
 
Übrigens an der Stelle nochmal Respekt an Redeemer. Ich hatte spaßeshalber mal versucht die DX-Header auf ID2D1DeviceContext5 (https://msdn.microsoft.com/en-us/lib...(v=vs.85).aspx) anzuheben, um die Methoden CreateSvgDocument und DrawSvgDocument zur Verfügung zu haben.
Damit wird zwar die Karte vom Landshut.svg gezeichnet, aber die Texte fehlen. So ganz fertig ist die Microsoft-Implementierung also nicht.


Alle Zeitangaben in WEZ +1. Es ist jetzt 13:27 Uhr.
Seite 1 von 2  1 2      

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