Saturday, December 26, 2009

Cairo Wrapper Preview
















Betreff Cairo-Wrapper-Preview
Von "Schmidt"
Datum 07.10.2009 12:43:50


Hallo zusammen,

die vor einiger Zeit schonmal angekündigten neuen Widget-
Klassen "gehen voran" - leider nicht so schnell wie gedacht -
aber so nach und nach wird die Codebasis "immer runder"...

Zumindest der Cairo-Wrapper ist jetzt erstmal so weit,
dass man ihn als "nahezu vollständig und vorzeigbar"
betiteln kann - hier also ein entsprechendes Preview-
Release, gedacht zum Herumspielen und zum Einarbeiten
vor dem späteren Offenlegen aller RichClient-binaries und
der neuen Widgets.

Download über: www.thecommon.net/3.html
Den RichClient-Toolset "zip-content" einfach in einen Folder
(z.B. C:\dhRichClient3\...) entpacken und mittels enthaltenem
register.bat (oder auch händisch) registrieren.

Die CairoWrapper-Klassen verhalten sich absolut stabil,
in meinen Tests treten keine Memory-oder Handle-Leaks
auf - die Methodenaufrufe (Signaturen) sollten auch keine
größeren Änderungen mehr erfahren - dennoch wird
die Binärkompatibilität von dhCairo.dll die nächsten Wochen/
Monate (in jedem neuen Release) wohl noch ein paar mal
gebrochen werden.
Wenn nicht wegen Änderungen an den Signaturen der
Cairo-Klassen (weniger wahrscheinlich), dann mit höherer
Wahrscheinlichkeit aufgrund von Änderungen an der
ebenfalls im dhCairo.dll-Binary enthaltenen Widget-
Engine (einer Art Windowmanager, der ohne hWnds
oder hDCs auskommt, das Cairo-Rendering benutzt
und ein ähnliches Entwickeln "im eigenen Widget-Ctl"
erlaubt wie man das von einem VB-Usercontrol-Modul
her gewohnt ist).

Auch die enthaltenen WidgetEngine-Klassen sind also
schon benutzbar (kleinere Beispiele werd ich noch posten) -
aber alleine die reiferen Cairo-Klassen bieten wahrscheinlich
erstmal genügend "Brot für eigene Drawing-Experimente".

Cairo ist eine plattformunabhängige C-Bibliothek für
Vektorgrafik - kompiliert als StdCall-Dll und im
toolset-paket enthalten als 'cairo2_engine.dll'.
Die Wrapper-Klassen bilden jeweils einen "cairo-Typ" ab
(Surfaces, Contexts, Patterns, Matrixes, Fonts usw.) und
passen in ihren Class_Terminates auf, dass die jeweiligen Cairo-
Handles wieder korrekt freigegeben werden - ansonsten
delegieren die Klassen-Methoden u. -Properties mehr oder
weniger direkt an die von der engine-Dll exportierten Calls.
Der Wrapper bietet mit der Kapselung also Intellisense sowie
automatisches "Freeing" bzw. Cleanup, man spart Codezeilen
gegenüber "pure C" - und ist sicher vor Memory- und Handle-
leaks.

Wer sich schonmal mit GDI+ bechäftigt hat, dem wird der
Einstieg in Cairos Vektorgrafik-Konzept leichter fallen -
Erfahrungen mit dem guten alten GDI oder den VBClassic-
Drawing-Methoden sind "auch OK", aber im Detail unterscheidet
sich das Generieren von "Cairo-Render-Output" dann doch -
z.B. beim für Gradienten verwendeten "Pattern-Konzept" -
oder dass im Prinzip mit jedem Line-, Rectangle- oder Ellipse-
Aufruf erstmal nur ein 'Path' definiert (eröffnet) wird, der
dann entweder "auf dem Pfad" (entlang der "gedachten Linie")
mittels .Stroke - oder innerhalb des Pfads mittels .Fill seine
"Colorierung" erhält).

Cairo-Rendering kann gegen verschiedene Surface-Typen
erfolgen, der "Brot und Butter"-Typ hierbei natürlich die Pixel-
basierte "2D-Fläche" - ein weiterer wichtiger Cairo-Surface-
Typ dürfte die PDF-Oberfläche sein.

Cairo arbeitet so, dass man von einem Surface-Typ jederzeit
einen "Drawing-Context" (per Srf.CreateContext) ableiten kann,
welcher dann die verschiedenen Drawing-Methoden bereitstellt.
Das wird im Prinzip so ähnlich ja auch im GDI gehandhabt -
nur dass hier die "Pixel-Surfaces" eben als Device-Independent-
Bitmaps (DIB) oder als Device-Dependent-Bitmaps (DDB) erzeugt
werden bzw. vorliegen - und dann in einen GDI-Context (hDC)
"selektiert werden", um auf den Pixelflächen "malen" zu können.

Was nett ist bei Cairos Surface-Konzept ist, dass man die
genau gleichen Zeichenbefehle (denselben VB-Code letztlich)
gegen unterschiedliche Surface-Typen anwenden kann.
Das bedeutet, dass man z.B. dieselbe Drawing-Routine für
eine Pixel-Surface basierte Print-Preview-Implementierung
(Rendering gegen den "Screen") genauso auch gegen eine
Cairo-PDF-Surface anwenden kann - das erlaubt dann
eine wirklich "transparent arbeitende" PDF-Generierung,
ohne die sonst üblichen "Umwege" über PDF-Printer-Driver
oder ähnliches.

Hier mal eine erste Demo, welche genau dieses Szenario
abbildet: www.datenhaus.de/Downloads/CairoDemo.zip

Woran ich in den letzten Wochen gearbeitet habe - und was
in obiger Demo ebenfalls enthalten ist, ist der Wrapper-Support
in Bezug auf Image-, Icon- und Resource-Loading.

Der Wrapper lädt die üblichen VB-bekannten Image-Typen
(*.jpg, *.gif, *.bmp) und nun dank Cairo auch das *.png-format.
Darüber hinaus versteht und lädt er sämtliche Icon-Formate -
egal ob als ResourceIcons or FileIcons (z.B. das neue Vista-
Icon-Format, welches PNG-content enthalten kann, wird
ebenso unterstützt, wie die XP-Icon-Formate mit Alphachannel).

Der CairoWrapper stellt für diese Zwecke auch eine App-globale
ImageList bereit, welche beim Start der Applikation befüllt werden
kann. Hier lassen sich also die verschiedenen Bild-Resourcen,
die eine Anwendung so benötigt, "einmalig abheften".
Hierbei wird z.B. auch das direkte Adden von Resource-Icons aus
System-Dlls unterstützt, z.B. aus "explorer.exe" oder "shell32.dll"
man benötigt nur die korrekte IconID, um solch einen Ladevorgang
mit einer Zeile Code abzuwickeln.
Die IconIDs der shell32.dll werden (zusammen mit den entspr.
Images) z.B. hier gelistet:
http://www.glennslayden.com/shell32_icons.htm

Alle Lese- und Schreiboperationen der verschiedenen Image-
Content-Typen können auch direkt auf ByteArray-Basis
erfolgen (ohne das Filesystem zu benutzen).

Die unterstützten FileTypen für die Leserichtung sind ja weiter
oben schonmal erwähnt worden - in Schreibrichtung unterstützt
Cairo das emittieren von Pixel-Surface-Content als Png- und
das ebenfalls schon erwähnte PDF-Format über einen eigenen
Surface-Typ.
Wie gesagt, ist auch hier der Output entweder in einem File
erzeugbar, oder direkt als ByteArray.

Die Stretch- und Scaling-Qualitäten von Cairo (down-
oder upstretching) für z.B. verschiedene Icon-Größen
sind ziemlich gut, der Alphachannel wird entsprechend
berücksichtigt und "mitgestretcht".
Z.B. lässt sich die Qualität eines 32x32Icons, gerendert
in "Original-Größe" kaum von der desselben Icons,
diesmal geladen als 48x48 großes Original, aber eben-
falls gerendert als 32x32-Output - unterscheiden.

Die obige Demo bildet genau solche Szenarien ab (Image-
und Icon-Loading aus verschiedenen Quellen - Rendering
in versch. Größen, sowie das Erzeugen von Png-Output
und PDF-Output.

Werd sehen, dass ich weitere Demos "nachschiebe", die sich
mehr auf die Vektor-Grafik konzentrieren (antialiased Rendering
von Linien, Winkeln, Bezier-Kurven usw.) - aber für einen
ersten Einstieg in die Wrapper-Klassen reicht das Gezeigte
wahrscheinlich erstmal hin, zumal der wohl interessanteste
Aspekt von Cairo (auch gegenüber GDI+), das "transparent"
arbeitende (bezogen auf den Drawing-Code) Erzeugen von
PDF-Output schonmal als Minimal-Beispiel mit enthalten ist.

Bitte einfach fragen, wenn irgendetwas unklar sein sollte.

Olaf
























Betreff Re: Cairo-Wrapper-Preview
Von "Sascha Trowitzsch"
Datum 08.10.2009 00:47:48


Hi Olaf,

Mann, mann, mann! Das ist ja wieder irre! Es haut mich um!
Ich hab's jetzt gerade mal ne halbe Stunde getestet: sieht super durchdacht
aus.
Ich schmeiß meinen ganzen GDI+-Code weg...
Mir schwirrt schon der Kopf vor Einsatzmöglichkeiten.
PDF und SVG sind Killer-Features!

Aber darf man noch Anregungen einbringen?
Ich bin ein Fan von GDI+-Splines. Könnte man noch so eine Methode in
cCairoContext einbauen? (Koordinaten-Array, Tension-Parameter)
Und geil wäre natürlich auch ein SVG-Parser für den Import. ;-) Müsste ja
nicht die ganze Referenz umfassen, sondern nur die Sachen, die die
Context-Klasse unterstützt.
Ein EMF-Import wäre auch nicht schlecht. (Wobei ich mir das u.U. auch in
Form eines externen Konverters selbst zutraute.)

Thanx alot!!!
(Nun werde ich die nächsten Tage wieder nicht richtig zum Arbeiten kommen...
;-) )

Gruß, Sascha

Schmidt wrote:
> Hallo zusammen,
>
> die vor einiger Zeit schonmal angekündigten neuen Widget-
> Klassen "gehen voran" - leider nicht so schnell wie gedacht -
> aber so nach und nach wird die Codebasis "immer runder"...
>
> Zumindest der Cairo-Wrapper ist jetzt erstmal so weit,
> dass man ihn als "nahezu vollständig und vorzeigbar"
> betiteln kann - hier also ein entsprechendes Preview-
> Release, gedacht zum Herumspielen und zum Einarbeiten
> vor dem späteren Offenlegen aller RichClient-binaries und
> der neuen Widgets.
>
> Download über: www.thecommon.net/3.html
> Den RichClient-Toolset "zip-content" einfach in einen Folder
> (z.B. C:\dhRichClient3\...) entpacken und mittels enthaltenem
> register.bat (oder auch händisch) registrieren.
>
> Die CairoWrapper-Klassen verhalten sich absolut stabil,
> in meinen Tests treten keine Memory-oder Handle-Leaks
> auf - die Methodenaufrufe (Signaturen) sollten auch keine
> größeren Änderungen mehr erfahren - dennoch wird
> die Binärkompatibilität von dhCairo.dll die nächsten Wochen/
> Monate (in jedem neuen Release) wohl noch ein paar mal
> gebrochen werden.
> Wenn nicht wegen Änderungen an den Signaturen der
> Cairo-Klassen (weniger wahrscheinlich), dann mit höherer
> Wahrscheinlichkeit aufgrund von Änderungen an der
> ebenfalls im dhCairo.dll-Binary enthaltenen Widget-
> Engine (einer Art Windowmanager, der ohne hWnds
> oder hDCs auskommt, das Cairo-Rendering benutzt
> und ein ähnliches Entwickeln "im eigenen Widget-Ctl"
> erlaubt wie man das von einem VB-Usercontrol-Modul
> her gewohnt ist).
>
> Auch die enthaltenen WidgetEngine-Klassen sind also
> schon benutzbar (kleinere Beispiele werd ich noch posten) -
> aber alleine die reiferen Cairo-Klassen bieten wahrscheinlich
> erstmal genügend "Brot für eigene Drawing-Experimente".
>
> Cairo ist eine plattformunabhängige C-Bibliothek für
> Vektorgrafik - kompiliert als StdCall-Dll und im
> toolset-paket enthalten als 'cairo2_engine.dll'.
> Die Wrapper-Klassen bilden jeweils einen "cairo-Typ" ab
> (Surfaces, Contexts, Patterns, Matrixes, Fonts usw.) und
> passen in ihren Class_Terminates auf, dass die jeweiligen Cairo-
> Handles wieder korrekt freigegeben werden - ansonsten
> delegieren die Klassen-Methoden u. -Properties mehr oder
> weniger direkt an die von der engine-Dll exportierten Calls.
> Der Wrapper bietet mit der Kapselung also Intellisense sowie
> automatisches "Freeing" bzw. Cleanup, man spart Codezeilen
> gegenüber "pure C" - und ist sicher vor Memory- und Handle-
> leaks.
>
> Wer sich schonmal mit GDI+ bechäftigt hat, dem wird der
> Einstieg in Cairos Vektorgrafik-Konzept leichter fallen -
> Erfahrungen mit dem guten alten GDI oder den VBClassic-
> Drawing-Methoden sind "auch OK", aber im Detail unterscheidet
> sich das Generieren von "Cairo-Render-Output" dann doch -
> z.B. beim für Gradienten verwendeten "Pattern-Konzept" -
> oder dass im Prinzip mit jedem Line-, Rectangle- oder Ellipse-
> Aufruf erstmal nur ein 'Path' definiert (eröffnet) wird, der
> dann entweder "auf dem Pfad" (entlang der "gedachten Linie")
> mittels .Stroke - oder innerhalb des Pfads mittels .Fill seine
> "Colorierung" erhält).
>
> Cairo-Rendering kann gegen verschiedene Surface-Typen
> erfolgen, der "Brot und Butter"-Typ hierbei natürlich die Pixel-
> basierte "2D-Fläche" - ein weiterer wichtiger Cairo-Surface-
> Typ dürfte die PDF-Oberfläche sein.
>
> Cairo arbeitet so, dass man von einem Surface-Typ jederzeit
> einen "Drawing-Context" (per Srf.CreateContext) ableiten kann,
> welcher dann die verschiedenen Drawing-Methoden bereitstellt.
> Das wird im Prinzip so ähnlich ja auch im GDI gehandhabt -
> nur dass hier die "Pixel-Surfaces" eben als Device-Independent-
> Bitmaps (DIB) oder als Device-Dependent-Bitmaps (DDB) erzeugt
> werden bzw. vorliegen - und dann in einen GDI-Context (hDC)
> "selektiert werden", um auf den Pixelflächen "malen" zu können.
>
> Was nett ist bei Cairos Surface-Konzept ist, dass man die
> genau gleichen Zeichenbefehle (denselben VB-Code letztlich)
> gegen unterschiedliche Surface-Typen anwenden kann.
> Das bedeutet, dass man z.B. dieselbe Drawing-Routine für
> eine Pixel-Surface basierte Print-Preview-Implementierung
> (Rendering gegen den "Screen") genauso auch gegen eine
> Cairo-PDF-Surface anwenden kann - das erlaubt dann
> eine wirklich "transparent arbeitende" PDF-Generierung,
> ohne die sonst üblichen "Umwege" über PDF-Printer-Driver
> oder ähnliches.
>
> Hier mal eine erste Demo, welche genau dieses Szenario
> abbildet: www.datenhaus.de/Downloads/CairoDemo.zip
>
> Woran ich in den letzten Wochen gearbeitet habe - und was
> in obiger Demo ebenfalls enthalten ist, ist der Wrapper-Support
> in Bezug auf Image-, Icon- und Resource-Loading.
>
> Der Wrapper lädt die üblichen VB-bekannten Image-Typen
> (*.jpg, *.gif, *.bmp) und nun dank Cairo auch das *.png-format.
> Darüber hinaus versteht und lädt er sämtliche Icon-Formate -
> egal ob als ResourceIcons or FileIcons (z.B. das neue Vista-
> Icon-Format, welches PNG-content enthalten kann, wird
> ebenso unterstützt, wie die XP-Icon-Formate mit Alphachannel).
>
> Der CairoWrapper stellt für diese Zwecke auch eine App-globale
> ImageList bereit, welche beim Start der Applikation befüllt werden
> kann. Hier lassen sich also die verschiedenen Bild-Resourcen,
> die eine Anwendung so benötigt, "einmalig abheften".
> Hierbei wird z.B. auch das direkte Adden von Resource-Icons aus
> System-Dlls unterstützt, z.B. aus "explorer.exe" oder "shell32.dll"
> man benötigt nur die korrekte IconID, um solch einen Ladevorgang
> mit einer Zeile Code abzuwickeln.
> Die IconIDs der shell32.dll werden (zusammen mit den entspr.
> Images) z.B. hier gelistet:
> http://www.glennslayden.com/shell32_icons.htm
>
> Alle Lese- und Schreiboperationen der verschiedenen Image-
> Content-Typen können auch direkt auf ByteArray-Basis
> erfolgen (ohne das Filesystem zu benutzen).
>
> Die unterstützten FileTypen für die Leserichtung sind ja weiter
> oben schonmal erwähnt worden - in Schreibrichtung unterstützt
> Cairo das emittieren von Pixel-Surface-Content als Png- und
> das ebenfalls schon erwähnte PDF-Format über einen eigenen
> Surface-Typ.
> Wie gesagt, ist auch hier der Output entweder in einem File
> erzeugbar, oder direkt als ByteArray.
>
> Die Stretch- und Scaling-Qualitäten von Cairo (down-
> oder upstretching) für z.B. verschiedene Icon-Größen
> sind ziemlich gut, der Alphachannel wird entsprechend
> berücksichtigt und "mitgestretcht".
> Z.B. lässt sich die Qualität eines 32x32Icons, gerendert
> in "Original-Größe" kaum von der desselben Icons,
> diesmal geladen als 48x48 großes Original, aber eben-
> falls gerendert als 32x32-Output - unterscheiden.
>
> Die obige Demo bildet genau solche Szenarien ab (Image-
> und Icon-Loading aus verschiedenen Quellen - Rendering
> in versch. Größen, sowie das Erzeugen von Png-Output
> und PDF-Output.
>
> Werd sehen, dass ich weitere Demos "nachschiebe", die sich
> mehr auf die Vektor-Grafik konzentrieren (antialiased Rendering
> von Linien, Winkeln, Bezier-Kurven usw.) - aber für einen
> ersten Einstieg in die Wrapper-Klassen reicht das Gezeigte
> wahrscheinlich erstmal hin, zumal der wohl interessanteste
> Aspekt von Cairo (auch gegenüber GDI+), das "transparent"
> arbeitende (bezogen auf den Drawing-Code) Erzeugen von
> PDF-Output schonmal als Minimal-Beispiel mit enthalten ist.
>
> Bitte einfach fragen, wenn irgendetwas unklar sein sollte.
>
> Olaf

















Betreff Re: Cairo-Wrapper-Preview
Von "Schmidt"
Datum 08.10.2009 19:13:55



"Sascha Trowitzsch" schrieb im Newsbeitrag
news:eXRJ3A6RKHA.1796@TK2MSFTNGP02.phx.gbl...

> Ich schmeiß meinen ganzen GDI+-Code weg...
> Mir schwirrt schon der Kopf vor Einsatzmöglichkeiten.
Heh, heh... jetzt mach mal nicht so schnell... ;-)

Das Ganze ist erstmal noch "nur zum Testen und Einarbeiten"
(vor allem vor dem Hintergrund der neuen Widgets) gedacht.

> PDF und SVG sind Killer-Features!
Das ist wohl wahr - und bzgl. SVG: ... den Surface-Typ
hab ich noch nicht implementiert (obwohl der Enum-Parameter
in Cairo.CreateSurface(...) den SVG-Mode schon listet).

Der PDF-Output hatte für mich erstmal Vorrang.

> Aber darf man noch Anregungen einbringen?
Klar, so war das Posting gedacht.

> Ich bin ein Fan von GDI+-Splines. Könnte man noch so eine Methode
> in cCairoContext einbauen? (Koordinaten-Array, Tension-Parameter)
Das klingt nett - Splines gibt es aber (noch) nicht in Cairo - nur die
Bezier-basierten CurveTo-Befehle - wenn Du auf deren Basis
was Hübsches gekapselt bekommst das einen ähnlichen Output
wie die Splines erzeugt, dann immer her mit der Routine... ;-)
(Array-Koordinaten dann am Besten auf Basis eines simplen
zweidimensionalen Double-Array-Params, da ich keine UDT-basierten
Array-Parameter in die Interface-Definitionen einbauen möchte).


> Und geil wäre natürlich auch ein SVG-Parser für den Import. ;-)
Die offizielle Cairo-Lib unterstützt derzeit nur den SVG-output,
für die Gegenrichtung (den SVG-Import) gibt es entsprechende
Libs, die dann zusätzlich einzulinken wären. Muss ich mal schauen,
was das dann an Zusatz-Volumen "aufträgt" - und ob das zur
Cairo-lizenz (LGPL) passt.

> Ein EMF-Import wäre auch nicht schlecht. (Wobei ich mir das
> u.U. auch in Form eines externen Konverters selbst zutraute.)
Wäre auch schön - aber im Falle der SVG-Import hält Einzug,
dann hätte man eigentlich ein sparsames Austausch-Format,
welches nur die Zeichenanweisungen enthält (im Prinzip so
ähnlich wie auch bei EMF, nur eben "Web-Standard").

Aber für die Windows-Welt wäre ein EMF-GDICall-
Enumerator, der dann in Cairo-Befehle "übersetzt"
sicherlich wünschenswert.

Olaf


















Betreff Re: Cairo-Wrapper-Preview
Von "W. Wolf"
Datum 08.10.2009 09:42:26


Hallo Olaf,

Cairo-Unterstützung gibt es auch in anderen Projekten,
so z.B. im GTK +-Widget Toolkit (für die Erstellung
von grafischen Benutzeroberflächen). Bieten die Screenshots
hier eine "spekulative" Vorschau auf das was uns ggf.
mit den neuen Widget-Klassen erwartet? :-)

http://www.gtk.org/screenshots.html

Schönen Gruß
W. Wolf


















Betreff Re: Cairo-Wrapper-Preview
Von "Schmidt"
Datum 08.10.2009 18:43:12



"W. Wolf" schrieb im Newsbeitrag
news:OhHEjr%23RKHA.4592@TK2MSFTNGP06.phx.gbl...
> Hallo Olaf,
>
> Cairo-Unterstützung gibt es auch in anderen Projekten,
> so z.B. im GTK +-Widget Toolkit (für die Erstellung
> von grafischen Benutzeroberflächen). Bieten die Screenshots
> hier eine "spekulative" Vorschau auf das was uns ggf.
> mit den neuen Widget-Klassen erwartet? :-)
>
> http://www.gtk.org/screenshots.html

Das aktuelle Widget-Layout sieht etwas "dezenter" aus als
das "ButtonFace" in der Demo - solche "glassy-styles", zudem
noch kombiniert mit Alpha-transparenz sind ja nicht unbedingt
jedermanns Sache.

Glassy-Effekte kommen "in Dunkel" sowieso etwas besser raus,
bei eher "heller Anwendungsumgebung" gefallen mir "normale
Gradienten" dann wieder besser.

Der gezeigte Effekt ist aber relativ einfach (mit nur ein paar
Zeilen Code) erzeugbar, und sollte eigentlich nur demonstrieren,
"dass sowas auch geht" (oder dass mit evtl. noch ein paar mehr
Zeilen Code jedweder "aktuell modische-Effekt" relativ leicht
erzeugbar wäre).

Was wieder die Frage nach der Theming-Engine aufwirft - die
Geschmäcker sind sehr verschieden - sieht so aus, als ob die
doch "rein muss" - die Alternative dazu wäre, dass man in
jedem Widget entsprechend ausreichend OwnerDraw-Events
einbaut, die quasi auf Control-Ebene das Austauschen der Default-
Drawings relativ einfach erlauben - das war mein "alter Plan" -
aber ein applikationsweit greifendes Austauschen der Default-
Drawings per Theme-Zuweisung hat schon auch was.

Olaf



















Betreff Re: Cairo-Wrapper-Preview
Von Ulrich Korndoerfer
Datum 08.10.2009 20:25:20


Hallo Olaf,

Schmidt schrieb:

> ...
> Was wieder die Frage nach der Theming-Engine aufwirft - die
> Geschmäcker sind sehr verschieden - sieht so aus, als ob die
> doch "rein muss" - die Alternative dazu wäre, dass man in
> jedem Widget entsprechend ausreichend OwnerDraw-Events
> einbaut, die quasi auf Control-Ebene das Austauschen der Default-
> Drawings relativ einfach erlauben - das war mein "alter Plan" -
> aber ein applikationsweit greifendes Austauschen der Default-
> Drawings per Theme-Zuweisung hat schon auch was.

Die OwnerDraw-Events sollten auf jedenfall drin bleiben. Damit hat man
die Möglichkeit, ad hoc für zb ein bestimmtes Control zb ein
Zusatzfeature leicht einbauen zu können, ohne gleich per Theming ein
komplett neues Widgetset bauen zu müssen.

Eine Theming-Engine könnte man ja als spearate Klassenhierarchie
implementieren, die dann zB in den jeweiligen OwnerDarw-Events verwendet
wird (Delegation des Zeichnens an die Engine).

Oder die Engine auf Wunsch über eine Property "einhängbar" machen. Dann
sollten die Widgets selbständig das Theming verwenden, aber immer noch
zusätzlich den OwnerDraw Event werfen.

--
Ulrich Korndoerfer

VB tips, helpers, solutions -> http://www.proSource.de/Downloads/
















Betreff Re: Cairo-Wrapper-Preview
Von "Schmidt"
Datum 08.10.2009 21:45:07



"Ulrich Korndoerfer" schrieb im
Newsbeitrag news:OcYw4SESKHA.4020@TK2MSFTNGP05.phx.gbl...

> > Was wieder die Frage nach der Theming-Engine aufwirft - die
> > Geschmäcker sind sehr verschieden - sieht so aus, als ob die
> > doch "rein muss" - die Alternative dazu wäre, dass man in
> > jedem Widget entsprechend ausreichend OwnerDraw-Events
> > einbaut, die quasi auf Control-Ebene das Austauschen der Default-
> > Drawings relativ einfach erlauben - das war mein "alter Plan" -
> > aber ein applikationsweit greifendes Austauschen der Default-
> > Drawings per Theme-Zuweisung hat schon auch was.
>
> Die OwnerDraw-Events sollten auf jedenfall drin bleiben.
> Damit hat man die Möglichkeit, ad hoc für zb ein bestimmtes
> Control zb ein Zusatzfeature leicht einbauen zu können,
> ohne gleich per Theming ein komplett neues Widgetset
> bauen zu müssen.

Yep, scheint mir auch das Beste zu sein - "global" (per Theming)
umschaltbare Default-Drawings für Buttonfaces, Scrollbar-
und ComboBox-DropButtons, für MouseOver-Effecte usw.
und individuell anpassbare "Ausnahmen", die man per
OwnerDraw-Events selbst versorgt.

Die "ins Blaue" geraisten VB-Events kosten halt etwas Extra-Zeit,
wenn die Render-Kaskade aus sich refreshenden Controls
"abläuft" - aber das könnte man ja mit einer:
.AllowOwnerDrawEvents - Bool-Property
(vordefiniert in der cWidgetBase-Klasse) abfangen.

> Eine Theming-Engine könnte man ja als spearate
> Klassenhierarchie implementieren, die dann zB in den
> jeweiligen OwnerDarw-Events verwendet
> wird (Delegation des Zeichnens an die Engine).
Derzeit ist in den OwnerDraw-Events nur ein ByRef definiertes
CancelBuiltin-Flag - wenn man das im User-EventHandler nicht
umschaltet, dann wird der aktuell im Widget hinterlegte
DrawingCode ausgeführt/angesprungen.

Innerhalb des Widgets sieht es derzeit in etwa so aus...
(im Widget-Paint-Handler, der vom WindowManager für Refreshs
getriggert wird):

Dim CancelBuiltIn as Boolean
RaiseEvent OwnerDraw(CancelBuiltin) 'Chance für den User
If Not CancelBuiltIn Then 'ohne Theming - ButtonFace wird z.B. direkt
gemalt
CairoContext.DrawThis
CairoContext.DrawThat
End If

Inkl. des obigen Vorschlags (um den RaiseEvent-Overhead gering zu halten).

Dim CancelBuiltIn as Boolean
If W.AllowOwnerDrawEvents Then
RaiseEvent OwnerDraw(CancelBuiltin) 'Chance für den User
End If
If Not CancelBuiltIn Then 'ohne Theming - ButtonFace wird z.B. direkt
gemalt
CairoContext.DrawThis
CairoContext.DrawThat
End If

Mit Theming-Engine (angenommen, wir haben hier ein ButtonFace zu malen)
das Ganze komplett sähe dann in etwa so aus.

Dim CancelBuiltIn as Boolean
If W.AllowOwnerDrawEvents Then
RaiseEvent OwnerDraw(CancelBuiltin) 'Chance für den User
End If
If Not CancelBuiltIn Then
If W.Root.CurrentTheme Is Nothing Then 'ButtonFace wieder direkt im
Widget
CairoContext.DrawThis
CairoContext.DrawThat

Else 'per ButtonFace-Implementierung im aktuell eingehangenen Theme
W.Root.CurrentTheme.DrawButtonFace CairoContext
End If
End If

> Oder die Engine auf Wunsch über eine Property "einhängbar"
> machen.
Danke, manchmal sieht man den Wald vor Bäumen nicht mehr -
diese Property, so sie denn zunächst mal definiert ist (am besten
im WidgetRoot-Objekt - und als "As iTheme" Typ) - ist ja
problemlos auch auf 'Nothing' testbar. Das würde erlauben,
die Theming-Engine erstmal "zurückzustellen" - und den
"Ur-Drawing-Code" erstmal so direkt im Widget zu belassen
wie er derzeit ist (kein Theming-Implementierungs-Zwang).

Das Theming wird auf die Art später leichter "seitwärts integrierbar"
ich muss nur diese Theming-Property schonmal anlegen und
eine iTheme Basis-Klasse mit der Interface-definition.

Olaf


















Betreff Re: Cairo-Wrapper-Preview
Von Ulrich Korndoerfer
Datum 08.10.2009 22:38:29


Hallo Olaf,

Schmidt schrieb:

> ...
> Die "ins Blaue" geraisten VB-Events kosten halt etwas Extra-Zeit,
> wenn die Render-Kaskade aus sich refreshenden Controls
> "abläuft" - aber das könnte man ja mit einer:
> .AllowOwnerDrawEvents - Bool-Property
> (vordefiniert in der cWidgetBase-Klasse) abfangen.
>

Und dann aber in den Widgetklassen individuell wieder setzbar. Wenn in
der Widgetklasse nicht individuell gesetzt, die Einstellung aus der
Baseklasse verwenden, ansonsten den individuell gesetzten Wert.

Also zB per cWidgetBase.AllowOwnerDrawEvents = False global die
OnwerDraw Events sperren, und zb mit cButtonWidget.AllowOwnerDrawEvents
individuell für diese Instanz wieder erlauben. Bei der Instantiierung
des Buttonwidgets würde dieses erst mal die Einstellung der Basisklasse
übernehmen. Dann könnte man entweder im Initialize-Event des
Buttoncontrols einen abweichenden Wert per Code setzen, oder, wenn eine
Property im Controldesigner zur Entwurfszeit setzbar sein soll, müsste
diese Threestate haben: nicht gesetzt (dann wird die Einstellung der
Basisklasse übernommen) oder gesetzt auf False, gesetzt auf True (dies
dann überschriebt auf jedenfall die Basisklasseneinstellung).

Das Naming wäre vielleicht besser cWidgetBase.RaiseOwnerDrawEvents. Für
eine GUI-DesignzeitProperty müsste man dann das zB
ThisRaiseOwnerDrawEvents nennen und die Threestate Enum zB.
UseBaseClassSetting, RaiseOwnerDrawEvents und DoNotRaiseOwnerDrawEvents. :-)

>> Eine Theming-Engine könnte man ja als spearate
>> Klassenhierarchie implementieren, die dann zB in den
>> jeweiligen OwnerDarw-Events verwendet
>> wird (Delegation des Zeichnens an die Engine).
> Derzeit ist in den OwnerDraw-Events nur ein ByRef definiertes
> CancelBuiltin-Flag - wenn man das im User-EventHandler nicht
> umschaltet, dann wird der aktuell im Widget hinterlegte
> DrawingCode ausgeführt/angesprungen.
>
> Innerhalb des Widgets sieht es derzeit in etwa so aus...
> (im Widget-Paint-Handler, der vom WindowManager für Refreshs
> getriggert wird):
>
> Dim CancelBuiltIn as Boolean
> RaiseEvent OwnerDraw(CancelBuiltin) 'Chance für den User
> If Not CancelBuiltIn Then 'ohne Theming - ButtonFace wird z.B. direkt
> gemalt
> CairoContext.DrawThis
> CairoContext.DrawThat
> End If
>
> Inkl. des obigen Vorschlags (um den RaiseEvent-Overhead gering zu halten).
>
> Dim CancelBuiltIn as Boolean
> If W.AllowOwnerDrawEvents Then
> RaiseEvent OwnerDraw(CancelBuiltin) 'Chance für den User
> End If
> If Not CancelBuiltIn Then 'ohne Theming - ButtonFace wird z.B. direkt
> gemalt
> CairoContext.DrawThis
> CairoContext.DrawThat
> End If
>
> Mit Theming-Engine (angenommen, wir haben hier ein ButtonFace zu malen)
> das Ganze komplett sähe dann in etwa so aus.
>
> Dim CancelBuiltIn as Boolean
> If W.AllowOwnerDrawEvents Then
> RaiseEvent OwnerDraw(CancelBuiltin) 'Chance für den User
> End If
> If Not CancelBuiltIn Then
> If W.Root.CurrentTheme Is Nothing Then 'ButtonFace wieder direkt im
> Widget
> CairoContext.DrawThis
> CairoContext.DrawThat
>
> Else 'per ButtonFace-Implementierung im aktuell eingehangenen Theme
> W.Root.CurrentTheme.DrawButtonFace CairoContext
> End If
> End If
>

Ja, oder (mehr a la Programming by contract Stil):

Dim CancelBuiltin As Boolean

If W.RaiseOwnerDrawEvents Then _
RaiseEvent OwnerDraw(CancelBuiltin)

If CancelBuiltin Then Exit Sub ':-)

If W.Root.ThemeSet Then 'besser auf ein Bool testen
'sollte evtl. etwas schneller
'als Is Nothing sein, sicher
'bin ich mir da aber nicht, da
'ja bei Is Nothing auch nur auf
'einen Null-Ptr getestet werden muß

W.Root.CurrentTheme.Draw widgetIDButtonFace, CairoContext
Exit Sub ':-)))
End If

CairoContext.DrawThis
CairoContext.DrawThat

End Sub

Erscheint mir flexibler, in das Interface nicht eine DrawButtonFace
Methode fest reinzuschreiben, sondern eine generische Draw-Methode zu
verwenden, die zB per Enum den Zeichencode auswählt. Damit kann man
Methoden für neue "Standard"-Widgets hinzufügen, ohne die Schnittstelle
zu ändern.

Und der User kann so ebenfalls seine selbst kreierten Widgets ins
Theming mit einbeziehen.


>> Oder die Engine auf Wunsch über eine Property "einhängbar"
>> machen.
> Danke, manchmal sieht man den Wald vor Bäumen nicht mehr -
> diese Property, so sie denn zunächst mal definiert ist (am besten
> im WidgetRoot-Objekt - und als "As iTheme" Typ) - ist ja
> problemlos auch auf 'Nothing' testbar. Das würde erlauben,
> die Theming-Engine erstmal "zurückzustellen" - und den
> "Ur-Drawing-Code" erstmal so direkt im Widget zu belassen
> wie er derzeit ist (kein Theming-Implementierungs-Zwang).
>
> Das Theming wird auf die Art später leichter "seitwärts integrierbar"
> ich muss nur diese Theming-Property schonmal anlegen und
> eine iTheme Basis-Klasse mit der Interface-definition.

Yep. Genauso hatte ich mir das gedacht: Du kannst so schon mal alles
vorbereiten (Interfaces definieren), und die Implementierung auf später
verschieben. Alter Trick, das ;-)

Dennoch wird dich die saubere Definition des Interfaces auch einiges an
Zeit kosten. Oftmals ist es ja auch so, daß man erst bei der
Implementierung merkt, daß das Interface "Scheisse" ist ;-)

--
Ulrich Korndoerfer

VB tips, helpers, solutions -> http://www.proSource.de/Downloads/
















Betreff Re: Cairo-Wrapper-Preview
Von Ulrich Korndoerfer
Datum 08.10.2009 22:55:25


Nachtrag

> ...
> Dim CancelBuiltin As Boolean
>
> If W.RaiseOwnerDrawEvents Then _
> RaiseEvent OwnerDraw(CancelBuiltin)
>
> If CancelBuiltin Then Exit Sub ':-)
>
> If W.Root.ThemeSet Then 'besser auf ein Bool testen
> 'sollte evtl. etwas schneller
> 'als Is Nothing sein, sicher
> 'bin ich mir da aber nicht, da
> 'ja bei Is Nothing auch nur auf
> 'einen Null-Ptr getestet werden muß
>
> W.Root.CurrentTheme.Draw widgetIDButtonFace, CairoContext
> Exit Sub ':-)))
> End If
>
> CairoContext.DrawThis
> CairoContext.DrawThat
>
> End Sub

Ähm, hab vergessen, daß es auch ganz nett wäre, wenn man nicht gezwungen
wäre, immer ein komplettes Theming implementieren zu müssen, sondern
fallweise auch nur für ein paar Widgets oder deren Teile.

Die sauberste Methode wäre natürlich, ein Standardtheming mitzuliefern,
und bei einem Usertheming einzelne Methoden zu "überschreiben". Hat
natürlich den Nachteil, daß Du dann doch von Anfang an ein Theming
implementieren mußt.

Oder:

If W.Root.CurrentTheme.Draw(widgetIDButtonFace, CairoContext) _
Then Exit Sub

Dmit könnte eine nicht implementierte Methode False zurückliefern und
ersatzweise dann das Defaultdrawing stattfinden.

Ach ja, nochmal Naming: W.Root.Theme statt W.Root.CurrentTheme, denn es
gibt ja nur ein Theme, das ist sozusagen automatisch Current. Sonst
könnte der User ins Grübeln kommen: wieso heißt das Ding "Current"? Hab
ich da was übersehen? Gibt es evtl. die Möglichkeit, gleichzeitig
mehrere Themings zu setzen und CurrentTheme wählt eines davon aus? Wo
sind dann die Properties, um mehrere Themes zu setzen?

Genug der Korinthenkackerei. Aber Naming ist schon wichtig und oftmals
die halbe Miete (vor allem, wenn die Dokumentation nicht existiert).

--
Ulrich Korndoerfer

VB tips, helpers, solutions -> http://www.proSource.de/Downloads/
















Betreff Re: Cairo-Wrapper-Preview
Von "Schmidt"
Datum 08.10.2009 23:08:54



"Ulrich Korndoerfer" schrieb im
Newsbeitrag news:%23fU9vmFSKHA.4692@TK2MSFTNGP06.phx.gbl...
> Nachtrag
>
> > ...
> > Dim CancelBuiltin As Boolean
> >
> > If W.RaiseOwnerDrawEvents Then _
> > RaiseEvent OwnerDraw(CancelBuiltin)
> >
> > If CancelBuiltin Then Exit Sub ':-)
> >
> > If W.Root.ThemeSet Then 'besser auf ein Bool testen
> > 'sollte evtl. etwas schneller
> > 'als Is Nothing sein, sicher
> > 'bin ich mir da aber nicht, da
> > 'ja bei Is Nothing auch nur auf
> > 'einen Null-Ptr getestet werden muß
> >
> > W.Root.CurrentTheme.Draw widgetIDButtonFace, CairoContext
> > Exit Sub ':-)))
> > End If
> >
> > CairoContext.DrawThis
> > CairoContext.DrawThat
> >
> > End Sub
>
> Ähm, hab vergessen, daß es auch ganz nett wäre, wenn man nicht gezwungen
> wäre, immer ein komplettes Theming implementieren zu müssen, sondern
> fallweise auch nur für ein paar Widgets oder deren Teile.
>
> Die sauberste Methode wäre natürlich, ein Standardtheming mitzuliefern,
> und bei einem Usertheming einzelne Methoden zu "überschreiben". Hat
> natürlich den Nachteil, daß Du dann doch von Anfang an ein Theming
> implementieren mußt.
>
> Oder:
>
> If W.Root.CurrentTheme.Draw(widgetIDButtonFace, CairoContext) _
> Then Exit Sub
>
> Dmit könnte eine nicht implementierte Methode False zurückliefern und
> ersatzweise dann das Defaultdrawing stattfinden.
>
> Ach ja, nochmal Naming: W.Root.Theme statt W.Root.CurrentTheme, denn es
> gibt ja nur ein Theme, das ist sozusagen automatisch Current. Sonst
> könnte der User ins Grübeln kommen: wieso heißt das Ding "Current"? Hab
> ich da was übersehen? Gibt es evtl. die Möglichkeit, gleichzeitig
> mehrere Themings zu setzen und CurrentTheme wählt eines davon aus? Wo
> sind dann die Properties, um mehrere Themes zu setzen?
>
> Genug der Korinthenkackerei. Aber Naming ist schon wichtig und oftmals
> die halbe Miete (vor allem, wenn die Dokumentation nicht existiert).

Danke für alle Anregungen - insbesondere Dein Vorschlag:
"eine generische Draw-Methode zu verwenden,
die zB per Enum den Zeichencode auswählt"

gefällt mir sehr gut - im Hinblick auf eine möglichst zeitnah
anzustrebende Interface-Stabilität der Cairo- und Widget-
Engine-Klassen.

Dann mach ich mich mal da dran.
Bis demnächst... ;-)

Olaf



















Betreff Re: Cairo-Wrapper-Preview
Von Susann Markward
Datum 08.10.2009 13:39:19


Hallo,

*Schmidt* schrieb am 07.10.2009 12:43:
> die vor einiger Zeit schonmal angekündigten neuen Widget-
> Klassen "gehen voran" - leider nicht so schnell wie gedacht -
> aber so nach und nach wird die Codebasis "immer runder"...
>
> Zumindest der Cairo-Wrapper ist jetzt erstmal so weit,
> dass man ihn als "nahezu vollständig und vorzeigbar"
> betiteln kann - hier also ein entsprechendes Preview-
> Release, gedacht zum Herumspielen und zum Einarbeiten
> vor dem späteren Offenlegen aller RichClient-binaries und
> der neuen Widgets.

Ähm, darf ich mal fragen, was das ist? Ich habe mir das mal angeschaut.
Sieht ja schön aus. Aber ist das etwas, was normalerweise unter VB6
nicht geht? Sind das nicht einfach nur Bilder?
















Betreff Re: Cairo-Wrapper-Preview
Von "Schmidt"
Datum 08.10.2009 18:19:38



"Susann Markward" schrieb im Newsbeitrag
news:4acdcf55$0$6550$9b4e6d93@newsspool4.arcor-online.net...

> *Schmidt* schrieb am 07.10.2009 12:43:
> > die vor einiger Zeit schonmal angekündigten neuen Widget-
> > Klassen "gehen voran" - leider nicht so schnell wie gedacht -
> > aber so nach und nach wird die Codebasis "immer runder"...
> >
> > Zumindest der Cairo-Wrapper ist jetzt erstmal so weit,
> > dass man ihn als "nahezu vollständig und vorzeigbar"
> > betiteln kann - hier also ein entsprechendes Preview-
> > Release, gedacht zum Herumspielen und zum Einarbeiten
> > vor dem späteren Offenlegen aller RichClient-binaries und
> > der neuen Widgets.
>
> Ähm, darf ich mal fragen, was das ist? Ich habe mir das
> mal angeschaut. Sieht ja schön aus. Aber ist das etwas,
> was normalerweise unter VB6 nicht geht?

Was mit den direkt eingebauten VB6-Grafikmethoden nicht
geht, ist z.B. direkter UniCode-Output der VB6-Widestrings
(PictureBox.Print kann das nicht direkt - CairoContext.TextOut
dagegen schon - weiterhin werden sämtliche Linien (und Objekte)
beim Cairo-Output antialiased gerendert - auch das ist mit
PictureBox.Line z.B. nicht möglich. Und super-einfache Skalierung,
Translation oder auch Rotation von kompletten "Render-Gruppen"
(inklusive des TextOutputs) ist ja auch schonmal nicht ohne,
vom Alphablending-Support bei nahezu allen Render-Befehlen
mal ganz abgesehen.

Das heißt natürlich nicht, dass man solchen Output mit
den GDI-APIs (z.B. TextOutW) nicht hinbekommt (oder
antialiased LineDrawing oder Alpha-Effekte mittels GDI+) -
die Frage reduziert sich eigentlich am Ende auf:
Wie hoch ist der Coding-Aufwand für "Schön" (das direkte,
transparent arbeitende PDF-rendering jetzt mal vernachlässigt).

> Sind das nicht einfach nur Bilder?
Eigentlich ja - die Demo stellt mehr auf diesen Aspekt ab...
(Wie einfach ist es, Bild- oder Icon-Resourcen zentral zu
laden bzw. zu halten - und später in beliebiger Größe und
in beliebigen Winkeln mit guter Qualität zur Anzeige zu bringen).
Der noch recht einfach erzeugbare "leicht rauchglasige Button-Effekt"
(das "ButtonFace" des "Icon-Labels") wird aber direkt "live" erzeugt -
und danach erst mit den Bild-Resourcen "kombiniert" - genau wie der
auf diesem Label gerenderte Text, welcher die Länge dieses
"Labels" beeinflusst.

Im PDF ist dieser Text auch wirklich Text (Kopieren im Acrobat-
Reader funktioniert) - nur so als "Beweis", dass das nicht alles nur
"vorgefertigte, irgendwie geblittete Images" sind.

Das einfach benutzbare Image-Handling des Wrappers ist aber letztlich
nur ein weiterer Aspekt bzgl. des oben schon angesprochenen, wie
einfach geht "Schön".
Versuch vielleicht mal, mittels Standard-VB-Methoden (oder mittels
der entspr. Icon-APIs) ein sauberes Iconrendering hinzulegen -
inclusive der korrekten Berücksichtigung des im Icon-Format
heutzutage meist hinterlegten Alpha-Kanals - insbesondere beim
leichten Verkleinern oder Vergrößern von Icons (wenn die
original hinterlegte Icon-Größe z.B. nicht genau Deiner
Zielgröße entspricht (z.B. wenn Du in einem ListView die
Icons mit 18x18er oder 20x20er Größe rendern möchtest, aber
in der Icon-Datei bzw. -Resource nur 16x16 oder 24x24 Icons
hinterlegt sind.

Das vielleicht erstmal so grob zum "grafik-technischen
Hintergrund" der "pro Cairo-Entscheidung".

--------------------------------------------------
Bleibt die Frage - warum nicht GDI+, warum Cairo?

Die ganze "RichClient-Idee" hat einen ziemlich weiten "Planungs-
horizont" sozusagen - das Ziel ist es, "am Ende" (so in 3-4 Jahren)
einen möglichst weitgehend VB6-kompatiblen Compiler zu haben
(inklusive neuer IDE und einem ordentlichen Form- bzw. Widget-
Designer *in* dieser IDE). Das RichClient-Toolset soll dann
quasi eine neue (so klein wie möglich gehaltene) erweiterte
VBRuntime-Library bereitstellen. Zunächst lauffähig auf Windows -
dann im letzten Schritt zu portieren auf andere Plattformen.
Deshalb (Plattformunabhängigkeit) scheidet GDI+ schonmal aus.

Alles "auf dem Weg dahin" sind also mehr oder weniger "nur
kleinere Meilensteine". Nichtsdestotrotz "vorab nutzbar" in
VB-Classic (da zunächst alle Helfer als COM-basierte
ActiveX-Dll Classwrapper vorliegen).

Was aktuell bereits nutzbar ist, ist z.B. der im RichClient enthaltene
Ersatz für DCOM (Kommunikation über Hostgrenzen
hinweg) - dann der Ersatz von ADO/Jet mittels der SQLite-
DB-engine, schnellere Collection-Klassen, Kompression-
und Verschlüsselung, TCP-Client/Server Klassen, klassen-
basierter Timer usw.
Was also jetzt mit dem Cairo-Wrapper dazugekommen ist,
ist eine bereits recht rund laufende, neue Rendering-Engine.

Diese wird demnächst u.a. in einem neuen Set aus Controls
(Widgets) benutzt, mit dem man in etwa dieselben Effekte und
"programmiertechnischen Herangehensweisen" umsetzen kann,
wie mit .NETs neuem WPF-modell.
Also ein neues, unicodefähiges Set an Basis-Controls, welches
die neuen Möglichkeiten der Cairo-RenderingEngine ausnutzt -
und Windowless sowie "hDC-less" arbeitet - sprich die Widgets
sind in "normalen" VB-Klassen implementiert - und verbrauchen
(ausser Speicher) keine weiteren Handles (weder hWnds - noch
irgendwelche GDI-Handles).
Diese neuen Control-Klassen sind also relativ leichtgewichtig und
"ohne schlechtes Gewissen" in größeren (selbstgeschriebenen)
Controls beliebig kombinierbar (keine Handle-Verschwendung
bei Aggregation von "Basis-Controls").

Von der LGPL-Offenlegung der RichClient-, Cairo- und Widget-
Sourcen erhoffe ich mir dann einfach einen größeren Schub
für dieses, zugegeben "etwas über-ambitioniert" scheinende
Projekt.

Ich denke jedoch, dass gerade die verschiedenen Widget-
Implementierungen sehr gut "parallelisierbar" sein werden
(hinsichtlich der hoffentlich dann größeren "Entwickler-
Resourcen") - und dass es ein guter Zeitpunkt ist, mein
bisheriges "Hobby-Projekt" genau dann "aufzumachen",
wenn die WidgetEngine (Cairo + neuer WindowManager)
eine gut durchdachte und "saubere" Grundstruktur aufweisen,
die die zu erwartende Menge an "neuem Code" gut trägt,
ohne zusammenzubrechen - oder an der Basis ständig
nachzubessern - mit Auswirkungen auf bereits geschriebenen
Code in den Layern (den Widgets) darüber.

Das ist (neben dem geringer als erwartet ausgefallenen
Anteil an "Hobby-Zeit") der Hauptgrund für die Verzögerung
bei den Widgets, die eigentlich schon ein halbes Jahr lang
"draussen" sein sollten.

Ich möchte z.B. gerne noch den Theming-Layer in die Widget-
Engine einbauen, bevor größere "Code-Investitionen" in
neue Widgets passieren, da dies den zu schreibenden
Drawing-Code innerhalb vieler Widgets (aufgrund der
zusätzlichen Indirektion) doch stärker beeinflussen wird.

Das ist jedoch diskutierbar (ob überhaupt, und wenn - in
welcher Art, welchem Umfang dieser Theming-Layer dann
eingebaut wird).

Die Frage mit der ich mich derzeit schwer tue ist also
eher; wollen "wir" das überhaupt (richtiges Theming) -
oder reicht auch ein relativ modern aussehendes, "hart
verdrahtetes" Basis-Theme, das derzeit zumindest auf
ein zentral vorgegebenes Color-Schema "reagiert" -
(die "Eckfarben" für die Farbverläufe werden derzeit
mittels "Shade", ausgehend von einer vorgegebenen
Basis-Farbe live errechnet).

"Gleich richtiges Theming" einbauen, bevor die "Community"
sich an größere Widget-Implementierungen macht - ist natürlich
der bessere Weg, würde aber den "offiziellen Startschuss" dann
wieder etwas weiter nach hinten verschieben.

Olaf



















Betreff Re: Cairo-Wrapper-Preview
Von Ulrich Korndoerfer
Datum 08.10.2009 20:18:05


Hallo Olaf,

Schmidt schrieb:

> Bitte einfach fragen, wenn irgendetwas unklar sein sollte.

Muß man immer den Umweg über die eingebaute Imagelist gehen, wenn man
ein Bild, welches ein nicht direkt von Cairo unterstützes Format (also
zb Jpegs) hat, von Platte oder vom RAM laden und rendern will?

Wenn ja: wird hier evtl. unnötigerweise das in die Imagelist geladene
Bild zum Zwecke des Renderns kopiert (also nochmal Bytes bewegt)?

Könnte man nicht die Auswahl an Surface Bildrendermethoden so erweitern,
daß als Parameter direkt ein Bytearray oder ein Dateiname akzeptiert wird?

Weiters: ich möchte in einem Programm viele (evtl. bis mehrere
Zehntausende) Bildchen per Cachemechanismus vorhalten. Das Programm
bietet eine Thumbpreview der Bilder eines Ordners. Die Thumbs werden im
Hintergrund gemacht (Bild laden, zur Thumbgröße skalieren, Bild
wegwerfen, Thumb im Cache behalten, passiert bis jetzt mit Hilfe von
FreeImage). Sollte der Speicher nicht ausreichen, werden solange Thumbs
gemacht, bis der Cache voll ist. Werden dann im Cache nicht vorhandene
Thumbs angefordert, wird ein Thumb aus dem Cache entfernt und der
aktuell benötigte nachgeladen.

Die Thumbs werden in einer Art Dialichtpult angezeigt, können dort
betrachtet und auch verschoben werden (quasi ein Sortieren von Hand).
Da ein Ordner sehr viele Bilder beinhalten kann und die Thumbs auch
recht groß sind (wählbar bis zu max 500x500), brauche ich einen
Cachemechanismus, der unabhängig vom verfügbaren Speicherplatz im RAM
bei Bedarf schnell Thumbs liefern kann.

Bei einer Umstellung auf Cairo müßte der Wrapper also folgendes können:

- Bild laden (unterschiedliche Formate)
- Thumb vom Bild erzeugen und Thumb im RAM halten
(evtl. als Bytearray im Cache oder als Handle im Cache)
- bei Bedarf Thumb auf einen DC rendern

Ach ja, noch ein Frage: Cairo unterstützt als Rendersurface, soviel ich
weiss, auch SVG. Dein Wrapper scheint dies aber nicht zu unterstützen?

--
Ulrich Korndoerfer

VB tips, helpers, solutions -> http://www.proSource.de/Downloads/
















Betreff Re: Cairo-Wrapper-Preview
Von "Schmidt"
Datum 08.10.2009 22:33:52



"Ulrich Korndoerfer" schrieb im
Newsbeitrag news:e0bL3OESKHA.4324@TK2MSFTNGP05.phx.gbl...

> Muß man immer den Umweg über die eingebaute Imagelist
> gehen, wenn man ein Bild, welches ein nicht direkt von Cairo
> unterstützes Format (also zb Jpegs) hat, von Platte oder vom
> RAM laden und rendern will?
Nein, die global verfügbare Imagelist ist mehr gedacht zum
Vorhalten/Cachen eher kleinerer Image-Resourcen (in
"typischer Icon-Größe").

Größere Bilder (z.B. ein ByteArray mit JPG-content)
lassen sich auch direkt in eine Image-Surface dekomprimieren.
Dim TmpSrf as cCairoSurface, B() as Byte
B = LoadRawJPGBytesFromWherever()

Set TmpSrf = Cairo.CreateSurface(0,0, ImageSurface, B)

Die obige temporäre Surface enthält jetzt das dekomprimierte
JPG in originaler (JPG-Width/Height)Größe - und belegt dann
"nur" Speicher (keine Handles).

Von TmpSrf aus könntest Du den dekomprimierten JPG-
Content jetzt direkt auf einen DC stretchen:

TmpSrf.DrawToDC DstDC, DstX, DstY, DstDX, DstDY

Oder für Caching-Zwecke zunächst in der gewünschten
(wahrsch. kleineren) Thumb-Größe in eine weitere Surface
hineinstretchen:

Dim NewThumbSrf as cCairoSurface
Set NewThumbSrf = Cairo.CreateSurface(ThumbDX, ThumbDY)
With NewThumbSrf.CreateContext
.RenderSurfaceContent TmpSrf, ThumbDX, ThumbDY
End With

... und dann diese kleinere ThumbSurface in einer geeigneten
Cache-Struktur (Collection o.ä.) als Objekt hinterlegen:
ThumbCache.Add Key, NewThumbSurface

Eine solche Cairo-Surface belegt wie gesagt nur Speicher -
und zwar:
VB-ClassOverhead + Surface.Width * Surface.Height * 4 Bytes

Von diesen dekomprimiert (und verkleinert) vorgehaltenen
Thumbs sollte dann ein recht flottes Blitting möglich sein.

> Wenn ja: wird hier evtl. unnötigerweise das in die
> Imagelist geladene Bild zum Zwecke des Renderns kopiert
> (also nochmal Bytes bewegt)?
Die ImageList speichert Referenzen auf cCairoSurface-
Instanzen - die wie gesagt immer den dekomprimierten
Image-Content mit 32Bit = 4BytesPerPixel) enthalten,
damit das spätere Rendering z.B. von Icons in eine
scrollende Liste nicht auch noch die evtl. Dekompression
(immer und immer wieder) leisten muss.

Wenn es Dir um geringen Speicherverbrauch geht, dann
ist das komprimierte Vorhalten in einer eigenen Cache-
Sruktur wahrscheinlich besser - das was ich da oben
hingeschrieben habe, hält ja bereits dekomprimierte
(wenn auch auf Thumbs verkleinerte) 32BPP-areas -
und macht (bis auf die Thumb-Verkleinerung in einem
separaten Schritt) eigentlich nix anderes als die globale
ImageList.

Für einen speichereffizienten Cache müsstest Du Dir eine
RenderFromJPGArrayToDC-Routine anlegen, die z.B. die
Intel-JPG-Lib benutzt, da die wesentlich schneller dekomprimiert
als die üblichen JPG-Laderoutinen des Systems (ich nehme
unter der Haube derzeit das ganz normale OLE-API für die
JPG-Dekodierung)


> Könnte man nicht die Auswahl an Surface Bildrendermethoden
> so erweitern, daß als Parameter direkt ein Bytearray oder ein
> Dateiname akzeptiert wird?

Du kannst das Ganze eigentlich auch als OneLiner hinschreiben:
(angenommen B() enthält JPG-Bytes)

'rendering von B()-content direkt in einen CairoContext:
CC.RenderSurfaceContent Cairo.CreateSurface(0,0, , B)

'oder B() direkt gegen einen hDC rendern:
Cairo.CreateSurface(0,0, , B).DrawToDC hDC

> Weiters: ich möchte in einem Programm viele (evtl. bis mehrere
> Zehntausende) Bildchen per Cachemechanismus vorhalten.
Hier wieder die Frage, komprimiert vorhalten - oder als
"direkt blittbare 2D-memory-area".

> Das Programm bietet eine Thumbpreview der Bilder eines Ordners.
> Die Thumbs werden im Hintergrund gemacht...
Falls unkomprimierte Thumbs vorgehalten werden sollen,
könntest Du eigentlich wie oben schon gezeigt vorgehen:

> (Bild laden,
Dim TmpSrf As cCairoSurface
Set TmpSrf = Cairo.CreateSurface(0,0, , JPGByteArray)

> Thumbgröße skalieren,
Dim NewThumbSrf as cCairoSurface
Set NewThumbSrf = Cairo.CreateSurface(ThumbDX, ThumbDY)
With NewThumbSrf.CreateContext
.RenderSurfaceContent TmpSrf, ThumbDX, ThumbDY
End With

> Bild wegwerfen,
Set TmpSrf = Nothing

> Thumb im Cache behalten,
Cairo.ImageList.AddSurface NewKey, NewThumbSrf


> Sollte der Speicher nicht ausreichen, werden solange Thumbs
> gemacht, bis der Cache voll ist.
If Cairo.ImageList.Count > 10000 Then
'... nur so als Idee
End If

> Werden dann im Cache nicht vorhandene Thumbs angefordert,
Mist, die .Exists-Methode habe ich noch nicht rausgeführt
auf der ImageList - wurde soeben nachgerüstet.

> wird ein Thumb aus dem Cache entfernt und der
> aktuell benötigte nachgeladen.
Cairo.ImageList.Remove OldThumbKey '.RemoveByIndex geht auch
Cairo.ImageList.AddSurface NewThumbKey, NewThumbSrf

Zum Überschreiben eines schon vorhandenen ImageList-
Eintrags mit einer neuen Surface, reicht ein nochmaliges
ImageList.Addxxx mit demselben (bereits vorhandenen Key).

> Bei einer Umstellung auf Cairo müßte der Wrapper also folgendes
> können:
>
> - Bild laden (unterschiedliche Formate)
Geht wie gezeigt auch direkt mit der Cairo.CreateSurface-Methode.

> - Thumb vom Bild erzeugen und Thumb im RAM halten
Geht auch - der Thumb ist ja eine verkleinerte (unkomprimierte)
Kopie der dekomprimierten Bilddaten.

> (evtl. als Bytearray im Cache oder als Handle im Cache)
Eine Cairo-ImageSurface (so wie sie der Wrapper als Objekt
erzeugt) enthält nur ein ByteArray mit den 32BPP-ImageDaten.
Das "Handle" wäre dann die ObjektReferenz.

> - bei Bedarf Thumb auf einen DC rendern
Geht direkt von einer Surface-instanz aus per Srf.DrawToDC.

> Ach ja, noch ein Frage: Cairo unterstützt als Rendersurface, soviel ich
> weiss, auch SVG. Dein Wrapper scheint dies aber nicht zu unterstützen?
Jo, bau ich noch ein.

Olaf


















Betreff Re: Cairo-Wrapper-Preview
Von Ulrich Korndoerfer
Datum 08.10.2009 23:18:38


Hallo Olaf,

Schmidt schrieb:

> ...
>> (evtl. als Bytearray im Cache oder als Handle im Cache)
> Eine Cairo-ImageSurface (so wie sie der Wrapper als Objekt
> erzeugt) enthält nur ein ByteArray mit den 32BPP-ImageDaten.
> Das "Handle" wäre dann die ObjektReferenz.

Ok, kapiert, alles bene. Die Handles für die Thumbs sind
Objektreferenzen, die ich dann wahlweise in einem selbst erzeugten Cache
oder auch mit Hilfe der eingebauten ImageList verwalten kann.

Einen kleinen Haken gibt es noch: wie Du weisst, wird VB ziemlich picky,
wenn es mal einige zehntausend Objekte releasen soll. Besser wäre es,
einfach das Handle, das Cairo intern verwendet, zu cachen und dann bei
Bedarf (Thumb rendern) ein VB-Surfaceobjekt mit diesem Cairointernen
Handle wiederzubeleben. Dann müßte man natürlich auch dieses
Cairointerne Handle bzw. das zugehörige Cairointerne "Objekt" direkt
releasen können. Gibt es im Wrapper Methoden, das interne Handle zu
erhalten und bei Bedarf freizugeben?

--
Ulrich Korndoerfer

VB tips, helpers, solutions -> http://www.proSource.de/Downloads/
















Betreff Re: Cairo-Wrapper-Preview
Von "Schmidt"
Datum 09.10.2009 00:18:54



"Ulrich Korndoerfer" schrieb im
Newsbeitrag news:%23X3KuzFSKHA.220@TK2MSFTNGP02.phx.gbl...
> Hallo Olaf,
>
> Schmidt schrieb:
>
> > ...
> >> (evtl. als Bytearray im Cache oder als Handle im Cache)
> > Eine Cairo-ImageSurface (so wie sie der Wrapper als Objekt
> > erzeugt) enthält nur ein ByteArray mit den 32BPP-ImageDaten.
> > Das "Handle" wäre dann die ObjektReferenz.
>
> Ok, kapiert, alles bene. Die Handles für die Thumbs sind
> Objektreferenzen, die ich dann wahlweise in einem selbst erzeugten Cache
> oder auch mit Hilfe der eingebauten ImageList verwalten kann.
>
> Einen kleinen Haken gibt es noch: wie Du weisst, wird VB ziemlich picky,
> wenn es mal einige zehntausend Objekte releasen soll. Besser wäre es,
> einfach das Handle, das Cairo intern verwendet, zu cachen und dann bei
> Bedarf (Thumb rendern) ein VB-Surfaceobjekt mit diesem Cairointernen
> Handle wiederzubeleben. Dann müßte man natürlich auch dieses
> Cairointerne Handle bzw. das zugehörige Cairointerne "Objekt" direkt
> releasen können. Gibt es im Wrapper Methoden, das interne Handle zu
> erhalten und bei Bedarf freizugeben?

Bisher nur als Friend-Property - der Wrapper, so wie er
jetzt ist, soll ja eher das "sorgenfreie Arbeiten" erlauben
(ohne eigene "Cleanup-Verantwortung").

Und solange Du eher im Bereich 10000-30000 Objekt-
Instanzen bleibst, ist das Instanz-Entladen noch so "im grünen
Bereich", zumal das ja (bei entsprechendem Image-Content)
eher doch "ziemlich gewichtige" Instanzen sind, die beim Entladen
neben der eigentlichen VB-ClassInstance auch noch ein wenig
mehr aufzuräumen haben.

Hab das gerade mal an konkreten Surface-Instanzen
durchgespielt (und einfach 10000 128x128 Pixel große
"Initial-Schwarzbilder" erzeugt und geladen).

Laden etwa 0,65sec

Benutzter Speicher laut Taskmanager:
ca. 660MB (laut theorie: 128x128x4x10000=655.360.000)

Entladen per ImageList.RemoveAll 0,33sec


Der Haupt-Zeitanteil liegt hierbei mehr bei der memory-
allocation/deallocation der 128x128 großen Areas - wenn
Du von 128x128 beispielsweise auf 2x2 große MiniImages
runtergehst, siehst Du besser den hierbei anfallenden Class-
Instance-Overhead von VB:
Laden in dem Falle dann etwa 0,1sec
Entladen etwa 0,07sec

Ginge also noch (auch ohne Low-Level-CairoAPI-Trickserei ;-).


'***In eine Form
Option Explicit

Private Cairo As New cCairo

Private Sub Form_Click()
Dim i&, T!
T = Timer
For i = 1 To 10000
Cairo.ImageList.AddSurface "Key" & i, Cairo.CreateSurface(128, 128)
Next i
Caption = Timer - T 'bis hierher etwa 0.65sec auf meiner Maschine

MsgBox 1 'der taskmanager zeigt jetzt etwa 660MB Speicherverbrauch

T = Timer
Cairo.ImageList.RemoveAll
Caption = Caption & " " & Timer - T 'und für das Freeing ca. 0.33sec
End Sub



















Betreff Re: Cairo-Wrapper-Preview
Von Ulrich Korndoerfer
Datum 09.10.2009 01:40:20


Hallo Olaf,

Schmidt schrieb:

>> Einen kleinen Haken gibt es noch: wie Du weisst, wird VB ziemlich picky,
>> wenn es mal einige zehntausend Objekte releasen soll. Besser wäre es,
>> einfach das Handle, das Cairo intern verwendet, zu cachen und dann bei
>> Bedarf (Thumb rendern) ein VB-Surfaceobjekt mit diesem Cairointernen
>> Handle wiederzubeleben. Dann müßte man natürlich auch dieses
>> Cairointerne Handle bzw. das zugehörige Cairointerne "Objekt" direkt
>> releasen können. Gibt es im Wrapper Methoden, das interne Handle zu
>> erhalten und bei Bedarf freizugeben?
>
> Bisher nur als Friend-Property - der Wrapper, so wie er
> jetzt ist, soll ja eher das "sorgenfreie Arbeiten" erlauben
> (ohne eigene "Cleanup-Verantwortung").
>

Schon klar, aber manchmal will man sich halt Sorgen machen :-)

> Und solange Du eher im Bereich 10000-30000 Objekt-
> Instanzen bleibst, ist das Instanz-Entladen noch so "im grünen
> Bereich", zumal das ja (bei entsprechendem Image-Content)
> eher doch "ziemlich gewichtige" Instanzen sind, die beim Entladen
> neben der eigentlichen VB-ClassInstance auch noch ein wenig
> mehr aufzuräumen haben.

Auch klar. Dennoch weiß ich von früher her, daß der Zeitbedarf für das
Releasen von VB-Objekten nichtlinear überproportional mit der Zahl der
erzeugten Objekte wächst. Von meinen damaligen Versuchen weiß ich noch,
daß das bei so um die 10000 kritisch wurde. Wahrscheinlich spielt hier
das Freigegeben der durch die VB-Objekte belegten Speicherhäppchen eine
Rolle. Merkwürdigwerweise war aber der Zeitbedarf für das Anlegen der
Objekte immer linear.

Ok, habe gerade mal nachgeprüft, wie das nun (Windows XP, 2 GB RAM,
DualCore@1.86 GHz) aussieht. Eine (völlig leere) Klasse wird n mal
erzeugt, die Objektinstanzreferenzen werden in einem vorher (also vor
der Zeitmessung) dimensionierten Array abgelegt. Dann werden alle
Referenzen per Erase Array auf einen Schlag entsorgt.

N Erzeugung [msec] Vernichten [msec] Verhältnis
2500 9 3
5000 18 7 2.33 (2.0)
10000 36 18 2.57 (2.0)
20000 72 48 2.67 (2.0)
30000 108 101 2.11 (1.5)
50000 179 334 3.31 (1.66)
100000 359 1411 4.23 (2.0)
150000 541 3168 2.25 (1.5)
200000 719 5572 1.76 (1.33)

Also der Effekt ist immer noch da und macht sich immer noch bei schon
10000 deutlich bemerkbar (in dem Sinne, daß der Zuwachs an Zeitbedarf
für die Zerstörung schon gegenüber 5000 deutlich nichtlinear ist).
Natürlich sind die absoluten Zeiten nun besser als bei meinen damaligen
Tests (System mit Kauf im Jahr 2000 mit WIN 2K, 256 MB RAM, 1 Kern
Pentium@550MHz). Damals waren meiner Erinnerung nach schon ab mehr als
10000 Objekten die absoluten Zeiten indiskutabel (also weit über der
Wahrnehmungschwelle).

Wäre halt vermeidbar, wenn nur "gewöhnliche" Handles freigegeben werden
müssten. Der zusätzliche (und unnötige) Performanceverlust durch die
VB-Wrapper liesse sich damit vermeiden. Vor allem bei älteren Rechnern
würde das Weglassen der VB-Objekte einen viel deutlicheren Effekt haben
und noch wichtiger werden.

--
Ulrich Korndoerfer

VB tips, helpers, solutions -> http://www.proSource.de/Downloads/


No comments:

Post a Comment