aboutsummaryrefslogtreecommitdiff
path: root/engines/sword25/gfx/image
diff options
context:
space:
mode:
Diffstat (limited to 'engines/sword25/gfx/image')
-rwxr-xr-xengines/sword25/gfx/image/b25sloader.cpp101
-rwxr-xr-xengines/sword25/gfx/image/b25sloader.h52
-rwxr-xr-xengines/sword25/gfx/image/image.h208
-rwxr-xr-xengines/sword25/gfx/image/imageloader.cpp120
-rwxr-xr-xengines/sword25/gfx/image/imageloader.h358
-rwxr-xr-xengines/sword25/gfx/image/imageloader_ids.h44
-rwxr-xr-xengines/sword25/gfx/image/pngloader.cpp389
-rwxr-xr-xengines/sword25/gfx/image/pngloader.h64
-rwxr-xr-xengines/sword25/gfx/image/vectorimage.cpp571
-rwxr-xr-xengines/sword25/gfx/image/vectorimage.h167
-rwxr-xr-xengines/sword25/gfx/image/vectorimagerenderer.cpp198
-rwxr-xr-xengines/sword25/gfx/image/vectorimagerenderer.h76
12 files changed, 2348 insertions, 0 deletions
diff --git a/engines/sword25/gfx/image/b25sloader.cpp b/engines/sword25/gfx/image/b25sloader.cpp
new file mode 100755
index 0000000000..55aaf7a2c5
--- /dev/null
+++ b/engines/sword25/gfx/image/b25sloader.cpp
@@ -0,0 +1,101 @@
+// -----------------------------------------------------------------------------
+// This file is part of Broken Sword 2.5
+// Copyright (c) Malte Thiesen, Daniel Queteschiner and Michael Elsdörfer
+//
+// Broken Sword 2.5 is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// Broken Sword 2.5 is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Broken Sword 2.5; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+// -----------------------------------------------------------------------------
+
+// -----------------------------------------------------------------------------
+// Includes
+// -----------------------------------------------------------------------------
+
+#include <string>
+#include <sstream>
+#include <algorithm>
+using namespace std;
+
+#include "b25sloader.h"
+#include "pngloader.h"
+
+#define BS_LOG_PREFIX "B25SLOADER"
+
+// -----------------------------------------------------------------------------
+
+namespace
+{
+ unsigned int FindEmbeddedPNG(const char * FileDataPtr, unsigned int FileSize)
+ {
+ // Einen Stringstream mit dem Anfang der Datei intialisieren. 512 Byte sollten hierfür genügen.
+ istringstream StringStream(string(FileDataPtr, FileDataPtr + min(static_cast<unsigned int>(512), FileSize)));
+
+ // Headerinformationen der Spielstandes einlesen.
+ string Marker, VersionID;
+ unsigned int CompressedGamedataSize, UncompressedGamedataSize;
+ StringStream >> Marker >> VersionID >> CompressedGamedataSize >> UncompressedGamedataSize;
+ if (!StringStream.good()) return 0;
+
+ // Testen, ob wir tatsächlich einen Spielstand haben.
+ if (Marker == "BS25SAVEGAME")
+ {
+ // Offset zum PNG innerhalb des Spielstandes berechnen und zurückgeben.
+ return static_cast<unsigned int>(StringStream.tellg()) + CompressedGamedataSize + 1;
+ }
+
+ return 0;
+ }
+}
+
+// -----------------------------------------------------------------------------
+
+bool BS_B25SLoader::IsCorrectImageFormat(const char * FileDataPtr, unsigned int FileSize)
+{
+ // PNG innerhalb des Spielstandes finden und den Methodenaufruf zu BS_PNGLoader weiterreichen.
+ unsigned int PNGOffset = FindEmbeddedPNG(FileDataPtr, FileSize);
+ if (PNGOffset > 0)
+ {
+ return BS_PNGLoader::DoIsCorrectImageFormat(FileDataPtr + PNGOffset, FileSize - PNGOffset);
+ }
+
+ return false;
+}
+
+// -----------------------------------------------------------------------------
+
+bool BS_B25SLoader::DecodeImage(const char * FileDataPtr, unsigned int FileSize, BS_GraphicEngine::COLOR_FORMATS ColorFormat, char * & UncompressedDataPtr,
+ int & Width, int & Height, int & Pitch)
+{
+ // PNG innerhalb des Spielstandes finden und den Methodenaufruf zu BS_PNGLoader weiterreichen.
+ unsigned int PNGOffset = FindEmbeddedPNG(FileDataPtr, FileSize);
+ if (PNGOffset > 0)
+ {
+ return BS_PNGLoader::DoDecodeImage(FileDataPtr + PNGOffset, FileSize - PNGOffset, ColorFormat, UncompressedDataPtr, Width, Height, Pitch);
+ }
+
+ return false;
+}
+
+// -----------------------------------------------------------------------------
+
+bool BS_B25SLoader::ImageProperties(const char * FileDataPtr, unsigned int FileSize, BS_GraphicEngine::COLOR_FORMATS & ColorFormat, int & Width, int & Height)
+{
+ // PNG innerhalb des Spielstandes finden und den Methodenaufruf zu BS_PNGLoader weiterreichen.
+ unsigned int PNGOffset = FindEmbeddedPNG(FileDataPtr, FileSize);
+ if (PNGOffset > 0)
+ {
+ return BS_PNGLoader::DoImageProperties(FileDataPtr + PNGOffset, FileSize - PNGOffset, ColorFormat, Width, Height);
+ }
+
+ return false;
+}
diff --git a/engines/sword25/gfx/image/b25sloader.h b/engines/sword25/gfx/image/b25sloader.h
new file mode 100755
index 0000000000..bafea87365
--- /dev/null
+++ b/engines/sword25/gfx/image/b25sloader.h
@@ -0,0 +1,52 @@
+// -----------------------------------------------------------------------------
+// This file is part of Broken Sword 2.5
+// Copyright (c) Malte Thiesen, Daniel Queteschiner and Michael Elsdörfer
+//
+// Broken Sword 2.5 is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// Broken Sword 2.5 is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Broken Sword 2.5; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+// -----------------------------------------------------------------------------
+
+#ifndef BS_B25SLOADER_H
+#define BS_B25SLOADER_H
+
+// -----------------------------------------------------------------------------
+// Includes
+// -----------------------------------------------------------------------------
+
+#include "kernel/common.h"
+#include "imageloader.h"
+
+// -----------------------------------------------------------------------------
+// Klassendeklaration
+// -----------------------------------------------------------------------------
+
+class BS_B25SLoader : public BS_ImageLoader
+{
+public:
+ static BS_ImageLoader * CreateInstance()
+ {
+ #include "kernel/memlog_off.h"
+ return static_cast<BS_ImageLoader *>(new BS_B25SLoader());
+ #include "kernel/memlog_on.h"
+ }
+
+protected:
+ virtual bool IsCorrectImageFormat(const char * FileDataPtr, unsigned int FileSize);
+ virtual bool DecodeImage(const char * FileDataPtr, unsigned int FileSize, BS_GraphicEngine::COLOR_FORMATS ColorFormat, char * & UncompressedDataPtr,
+ int & Width, int & Height, int & Pitch);
+ virtual bool ImageProperties(const char * FileDataPtr, unsigned int FileSize, BS_GraphicEngine::COLOR_FORMATS & ColorFormat, int & Width, int & Height);
+
+};
+
+#endif
diff --git a/engines/sword25/gfx/image/image.h b/engines/sword25/gfx/image/image.h
new file mode 100755
index 0000000000..8f6fe9cab9
--- /dev/null
+++ b/engines/sword25/gfx/image/image.h
@@ -0,0 +1,208 @@
+// -----------------------------------------------------------------------------
+// This file is part of Broken Sword 2.5
+// Copyright (c) Malte Thiesen, Daniel Queteschiner and Michael Elsdörfer
+//
+// Broken Sword 2.5 is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// Broken Sword 2.5 is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Broken Sword 2.5; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+// -----------------------------------------------------------------------------
+
+/*
+ BS_Image
+ --------
+
+ Autor: Malte Thiesen
+*/
+
+#ifndef BS_IMAGE_H
+#define BS_IMAGE_H
+
+// Includes
+#include "kernel/memlog_off.h"
+#include <vector>
+#include "kernel/memlog_on.h"
+#include "kernel/common.h"
+#include "math/rect.h"
+#include "gfx/graphicengine.h"
+
+class BS_Image
+{
+public:
+ virtual ~BS_Image() {};
+
+ // Enums
+ /**
+ @brief Die möglichen Flippingparameter für die Blit-Methode.
+ */
+ enum FLIP_FLAGS
+ {
+ /// Das Bild wird nicht gespiegelt.
+ FLIP_NONE = 0,
+ /// Das Bild wird an der horizontalen Achse gespiegelt.
+ FLIP_H = 1,
+ /// Das Bild wird an der vertikalen Achse gespiegelt.
+ FLIP_V = 2,
+ /// Das Bild wird an der horizontalen und vertikalen Achse gespiegelt.
+ FLIP_HV = FLIP_H | FLIP_V,
+ /// Das Bild wird an der horizontalen und vertikalen Achse gespiegelt.
+ FLIP_VH = FLIP_H | FLIP_V
+ };
+
+ //@{
+ /** @name Accessor-Methoden */
+
+ /**
+ @brief Gibt die Breite des Bildes in Pixeln zurück
+ */
+ virtual int GetWidth() const = 0;
+
+ /**
+ @brief Gibt die Höhe des Bildes in Pixeln zurück
+ */
+ virtual int GetHeight() const = 0;
+
+ /**
+ @brief Gibt das Farbformat des Bildes zurück
+ */
+ virtual BS_GraphicEngine::COLOR_FORMATS GetColorFormat() const = 0;
+
+ //@}
+
+ //@{
+ /** @name Render-Methoden */
+
+ /**
+ @brief Rendert das Bild in den Framebuffer.
+ @param pDest ein Pointer auf das Zielbild. In den meisten Fällen ist dies der Framebuffer.
+ @param PosX die Position auf der X-Achse im Zielbild in Pixeln, an der das Bild gerendert werden soll.<br>
+ Der Standardwert ist 0.
+ @param PosY die Position auf der Y-Achse im Zielbild in Pixeln, an der das Bild gerendert werden soll.<br>
+ Der Standardwert ist 0.
+ @param Flipping gibt an, wie das Bild gespiegelt werden soll.<br>
+ Der Standardwert ist BS_Image::FLIP_NONE (keine Spiegelung)
+ @param pSrcPartRect Pointer auf ein BS_Rect, welches den Ausschnitt des Quellbildes spezifiziert, der gerendert
+ werden soll oder NULL, falls das gesamte Bild gerendert werden soll.<br>
+ Dieser Ausschnitt bezieht sich auf das ungespiegelte und unskalierte Bild.<br>
+ Der Standardwert ist NULL.
+ @param Color ein ARGB Farbwert, der die Parameter für die Farbmodulation und fürs Alphablending festlegt.<br>
+ Die Alpha-Komponente der Farbe bestimmt den Alphablending Parameter (0 = keine Deckung, 255 = volle Deckung).<br>
+ Die Farbkomponenten geben die Farbe für die Farbmodulation an.<br>
+ Der Standardwert is BS_ARGB(255, 255, 255, 255) (volle Deckung, keine Farbmodulation).
+ Zum Erzeugen des Farbwertes können die Makros BS_RGB und BS_ARGB benutzt werden.
+ @param Width gibt die Ausgabebreite des Bildausschnittes an.
+ Falls diese von der Breite des Bildausschnittes abweicht wird
+ das Bild entsprechend Skaliert.<br>
+ Der Wert -1 gibt an, dass das Bild nicht Skaliert werden soll.<br>
+ Der Standardwert ist -1.
+ @param Width gibt die Ausgabehöhe des Bildausschnittes an.
+ Falls diese von der Höhe des Bildauschnittes abweicht, wird
+ das Bild entsprechend Skaliert.<br>
+ Der Wert -1 gibt an, dass das Bild nicht Skaliert werden soll.<br>
+ Der Standardwert ist -1.
+ @return Gibt false zurück, falls das Rendern fehlgeschlagen ist.
+ @remark Er werden nicht alle Blitting-Operationen von allen BS_Image-Klassen unterstützt.<br>
+ Mehr Informationen gibt es in der Klassenbeschreibung von BS_Image und durch folgende Methoden:
+ - IsBlitTarget()
+ - IsScalingAllowed()
+ - IsFillingAllowed()
+ - IsAlphaAllowed()
+ - IsColorModulationAllowed()
+ - IsSetContentAllowed()
+ */
+ virtual bool Blit(int PosX = 0, int PosY = 0,
+ int Flipping = FLIP_NONE,
+ BS_Rect* pPartRect = NULL,
+ unsigned int Color = BS_ARGB(255, 255, 255, 255),
+ int Width = -1, int Height = -1) = 0;
+
+ /**
+ @brief Füllt einen Rechteckigen Bereich des Bildes mit einer Farbe.
+ @param pFillRect Pointer auf ein BS_Rect, welches den Ausschnitt des Bildes spezifiziert, der gefüllt
+ werden soll oder NULL, falls das gesamte Bild gefüllt werden soll.<br>
+ Der Standardwert ist NULL.
+ @param Color der 32 Bit Farbwert mit dem der Bildbereich gefüllt werden soll.
+ @remark Es ist möglich über die Methode transparente Rechtecke darzustellen, indem man eine Farbe mit einem Alphawert ungleich
+ 255 angibt.
+ @remark Unabhängig vom Farbformat des Bildes muss ein 32 Bit Farbwert angegeben werden. Zur Erzeugung, können die Makros
+ BS_RGB und BS_ARGB benutzt werden.
+ @remark Falls das Rechteck nicht völlig innerhalb des Bildschirms ist, wird es automatisch zurechtgestutzt.
+ */
+ virtual bool Fill(const BS_Rect* pFillRect = 0, unsigned int Color = BS_RGB(0, 0, 0)) = 0;
+
+ /**
+ @brief Füllt den Inhalt des Bildes mit Pixeldaten.
+ @param Pixeldata ein Vector der die Pixeldaten enthält. Sie müssen in dem Farbformat des Bildes vorliegen und es müssen genügend Daten
+ vorhanden sein, um das ganze Bild zu füllen.
+ @param Offset der Offset in Byte im Pixeldata-Vector an dem sich der erste zu schreibende Pixel befindet.<br>
+ Der Standardwert ist 0.
+ @param Stride der Abstand in Byte zwischen dem Zeilenende und dem Beginn einer neuen Zeile im Pixeldata-Vector.<br>
+ Der Standardwert ist 0.
+ @return Gibt false zurück, falls der Aufruf fehlgeschlagen ist.
+ @remark Ein Aufruf dieser Methode ist nur erlaubt, wenn IsSetContentAllowed() true zurückgibt.
+ */
+ virtual bool SetContent(const std::vector<unsigned char> & Pixeldata, unsigned int Offset, unsigned int Stride) = 0;
+
+ /**
+ @brief Liest einen Pixel des Bildes.
+ @param X die X-Koordinate des Pixels.
+ @param Y die Y-Koordinate des Pixels
+ @return Gibt den 32-Bit Farbwert des Pixels an der übergebenen Koordinate zurück.
+ @remark Diese Methode sollte auf keine Fall benutzt werden um größere Teile des Bildes zu lesen, da sie sehr langsam ist. Sie ist
+ eher dafür gedacht einzelne Pixel des Bildes auszulesen.
+ */
+ virtual unsigned int GetPixel(int X, int Y) = 0;
+
+ //@{
+ /** @name Auskunfts-Methoden */
+
+ /**
+ @brief Überprüft, ob an dem BS_Image Blit() aufgerufen werden darf.
+ @return Gibt false zurück, falls ein Blit()-Aufruf an diesem Objekt nicht gestattet ist.
+ */
+ virtual bool IsBlitSource() const = 0;
+
+ /**
+ @brief Überprüft, ob das BS_Image ein Zielbild für einen Blit-Aufruf sein kann.
+ @return Gibt false zurück, falls ein Blit-Aufruf mit diesem Objekt als Ziel nicht gestattet ist.
+ */
+ virtual bool IsBlitTarget() const = 0;
+
+ /**
+ @brief Gibt true zurück, falls das BS_Image bei einem Aufruf von Blit() skaliert dargestellt werden kann.
+ */
+ virtual bool IsScalingAllowed() const = 0;
+
+ /**
+ @brief Gibt true zurück, wenn das BS_Image mit einem Aufruf von Fill() gefüllt werden kann.
+ */
+ virtual bool IsFillingAllowed() const = 0;
+
+ /**
+ @brief Gibt true zurück, wenn das BS_Image bei einem Aufruf von Blit() mit einem Alphawert dargestellt werden kann.
+ */
+ virtual bool IsAlphaAllowed() const = 0;
+
+ /**
+ @brief Gibt true zurück, wenn das BS_Image bei einem Aufruf von Blit() mit Farbmodulation dargestellt werden kann.
+ */
+ virtual bool IsColorModulationAllowed() const = 0;
+
+ /**
+ @brief Gibt true zurück, wenn der Inhalt des BS_Image durch eine Aufruf von SetContent() ausgetauscht werden kann.
+ */
+ virtual bool IsSetContentAllowed() const = 0;
+
+ //@}
+};
+
+#endif
diff --git a/engines/sword25/gfx/image/imageloader.cpp b/engines/sword25/gfx/image/imageloader.cpp
new file mode 100755
index 0000000000..18d94a4e21
--- /dev/null
+++ b/engines/sword25/gfx/image/imageloader.cpp
@@ -0,0 +1,120 @@
+// -----------------------------------------------------------------------------
+// This file is part of Broken Sword 2.5
+// Copyright (c) Malte Thiesen, Daniel Queteschiner and Michael Elsdörfer
+//
+// Broken Sword 2.5 is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// Broken Sword 2.5 is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Broken Sword 2.5; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+// -----------------------------------------------------------------------------
+
+#include "imageloader.h"
+#include "imageloader_ids.h"
+
+#define BS_LOG_PREFIX "IMAGELOADER"
+
+// Statische Elemente der Klasse BS_ImageLoader intialisieren.
+std::list<BS_ImageLoader*> BS_ImageLoader::_ImageLoaderList;
+bool BS_ImageLoader::_ImageLoaderListInitialized = false;
+
+// Lade Methode
+// ------------
+
+bool BS_ImageLoader::LoadImage(const char* pFileData, unsigned int FileSize,
+ BS_GraphicEngine::COLOR_FORMATS ColorFormat,
+ char*& pUncompressedData,
+ int& Width, int& Height,
+ int& Pitch)
+{
+ // Falls die Liste der BS_ImageLoader noch nicht initialisiert wurde, wird dies getan.
+ if (!_ImageLoaderListInitialized)
+ _InitializeLoaderList();
+
+ // Passenden BS_ImageLoader finden und Bild dekodieren
+ BS_ImageLoader* pLoader = _FindSuitableImageLoader(pFileData, FileSize);
+ if (pLoader)
+ {
+ return pLoader->DecodeImage(pFileData, FileSize,
+ ColorFormat,
+ pUncompressedData,
+ Width, Height,
+ Pitch);
+ }
+
+ return false;
+}
+
+// Info Methode
+// ------------
+
+bool BS_ImageLoader::ExtractImageProperties(const char* pFileData, unsigned int FileSize,
+ BS_GraphicEngine::COLOR_FORMATS& ColorFormat,
+ int& Width, int& Height)
+{
+ // Falls die Liste der BS_ImageLoader noch nicht initialisiert wurde, wird dies getan.
+ if (!_ImageLoaderListInitialized)
+ _InitializeLoaderList();
+
+ // Passenden BS_ImageLoader finden und Bildeigenschaften auslesen.
+ BS_ImageLoader* pLoader = _FindSuitableImageLoader(pFileData, FileSize);
+ if (pLoader)
+ {
+ return pLoader->ImageProperties(pFileData, FileSize,
+ ColorFormat,
+ Width, Height);
+ }
+
+ return false;
+}
+
+// Verwaltungs Methoden
+// --------------------
+
+void BS_ImageLoader::_InitializeLoaderList()
+{
+ // Von jedem BS_ImageLoader wird eine Instanz erzeugt, diese fügen sich selbständig in die BS_ImageLoader-Liste ein.
+ for (int i = 0; i < BS_IMAGELOADER_COUNT; i++)
+ BS_IMAGELOADER_IDS[i]();
+
+ // Die Liste als gefüllt markieren.
+ _ImageLoaderListInitialized = true;
+
+ // Sicherstellen, dass beim Beenden alle BS_ImageLoader Instanzen zerstört werden.
+ atexit(BS_ImageLoader::_DeinitializeLoaderList);
+}
+
+void BS_ImageLoader::_DeinitializeLoaderList()
+{
+ while (!_ImageLoaderList.empty())
+ {
+ delete _ImageLoaderList.back();
+ _ImageLoaderList.pop_back();
+ }
+}
+
+BS_ImageLoader* BS_ImageLoader::_FindSuitableImageLoader(const char* pFileData, unsigned int FileSize)
+{
+ // Alle BS_ImageLoader-Objekte durchgehen, bis eins gefunden wurde, dass das Bild laden kann
+ std::list<BS_ImageLoader*>::iterator Iter = _ImageLoaderList.begin();
+ for (; Iter != _ImageLoaderList.end(); ++Iter)
+ {
+ // Falls ein geeigneter BS-ImageLoader gefunden wurde, wird er zurückgegeben.
+ if ((*Iter)->IsCorrectImageFormat(pFileData, FileSize))
+ {
+ return (*Iter);
+ }
+ }
+
+ // Es konnte kein passender BS_ImageLoader gefunden werden.
+ BS_LOG_ERRORLN("Could not find suitable image loader for image data.");
+ return NULL;
+}
diff --git a/engines/sword25/gfx/image/imageloader.h b/engines/sword25/gfx/image/imageloader.h
new file mode 100755
index 0000000000..952c36b093
--- /dev/null
+++ b/engines/sword25/gfx/image/imageloader.h
@@ -0,0 +1,358 @@
+// -----------------------------------------------------------------------------
+// This file is part of Broken Sword 2.5
+// Copyright (c) Malte Thiesen, Daniel Queteschiner and Michael Elsdörfer
+//
+// Broken Sword 2.5 is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// Broken Sword 2.5 is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Broken Sword 2.5; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+// -----------------------------------------------------------------------------
+
+/*
+ BS_ImageLoader
+ --------------
+
+ Autor: Malte Thiesen
+*/
+
+#ifndef BS_IMAGELOADER_H
+#define BS_IMAGELOADER_H
+
+// Includes
+#include "kernel/bs_stdint.h"
+#include "kernel/common.h"
+#include "../graphicengine.h"
+
+// Die folgenden Header vertragen sich nicht mit der Memoryleak-Detection, daher wird sie kurzzeitig deaktiviert
+#include "kernel/memlog_off.h"
+#include <list>
+#include "kernel/memlog_on.h"
+
+/**
+ @brief Über die statischen Methoden dieser Klasse werden alle unterstützten Bildformate geladen.
+
+ Zum Laden von Bildern wird die #LoadImage-Methode benutzt.
+
+ Außerdem stellt diese Klasse das Interface da, das alle Klassen implementieren müssen, die Bildformate einlesen.<br>
+ Zur Unterstützung eines neuen Bildformates muss folgendermaßen vorgegangen werden:
+ - Erzeugen einer neuen von #BS_ImageLoader abgeleiteten Klasse, die die Methoden #IsCorrectImageFormat und #DecodeImage impelementiert.
+ - Die Klasse muss eine statische Methode haben, die eine Instanz von ihr erzeugt und einen Pointer darauf zurückgibt.
+ - Diese Methode muss in der Liste in der Datei imageloader_ids.h eingetragen werden.
+ - Die Klasse muss JEDES Eingabebild seines Bildformates in die folgenden Farbformate konvertieren können:
+ - BS_GraphicEngine::CF_RGB16
+ - BS_GraphicEngine::CF_RGB15
+ - BS_GraphicEngine::CF_RGB16_INTERLEAVED
+ - BS_GraphicEngine::CF_RGB15_INTERLEAVED
+ - BS_GraphicEngine::CF_ARGB32
+ - BS_GraphicEngine::CF_BGRA32
+ - Zum Konvertieren der Bilddaten können die Hilfsmethoden dieser Klasse benutzt werden, die ARGB Bilddaten in alle benötigten
+ Farbformate konvertieren.
+*/
+class BS_ImageLoader
+{
+public:
+
+ //@{
+ /** @name Lade Methoden */
+
+ /**
+ @brief Lädt eine Bilddatei.
+
+ Diese Methode kann sämtliche unterstütztem Bildformate lesen. Die Methode erkennt selbstständing um welches Dateiformat es sich
+ bei der vorliegenden Datei handelt.<br>
+ Bisher wird nur PNG unterstützt.
+
+ @param pFileData ein Pointer auf die Bilddaten.
+ @param FileSize die Größe der Bilddaten in Byte.
+ @param ColorFormat gibt das gewünschte Farbformat an, in das die Bilddaten konvertiert werden sollen.<br>
+ Folgende Farbformate werden unterstützt:
+ - BS_GraphicEngine::CF_RGB16
+ - BS_GraphicEngine::CF_RGB15
+ - BS_GraphicEngine::CF_RGB16_INTERLEAVED
+ - BS_GraphicEngine::CF_RGB15_INTERLEAVED
+ - BS_GraphicEngine::CF_ARGB32
+ @param pUncompressedData nach erfolgreichen Laden zeigt dieser Pointer auf die enpackten und konvertierten Bilddaten.
+ @param Width gibt nach erfolgreichen Laden die Breite des geladenen Bildes an.
+ @param Height gibt nach erfolgreichen Laden die Höhe des geladenen Bildes an.
+ @param Pitch gibt nach erfolgreichen Laden die Länge einer Bildzeile in Byte an.
+ @return Gibt false zurück, falls das Laden fehlgeschlagen ist.
+ @remark Die Größe der Ausgabedaten in Bytes kann wie folgt berechnet werden: Pitch * Height.
+ @remark Es darf nicht vergessen werden, die Ausgabedaten nach erfolgter Benutzung mit delete freizugeben.
+ */
+ static bool LoadImage(const char* pFileData, unsigned int FileSize,
+ BS_GraphicEngine::COLOR_FORMATS ColorFormat,
+ char*& pUncompressedData,
+ int& Width, int& Height,
+ int& Pitch);
+
+ /**
+ @brief Liest die Bildeigenschaften eines Bildes aus.
+
+ @param pFileData ein Pointer auf die Bilddaten.
+ @param FileSize die Größe des Bilddaten in Byte.
+ @param ColorFormat enthält nach einem erfolgreichem Aufruf das Farbformat des Bildes.
+ @param Width enthält nach einem erfolgreichem Aufruf die Breite des Bildes in Pixeln.
+ @param Height enthält nach einem erfolgreichem Aufruf die Höhe des Bildes in Pixeln.
+ @return Gibt false zurück, wenn die Bildeigenschaften nicht ausgelesen werden konnten.
+ @remark Es darf nicht vergessen werden, die Ausgabedaten nach erfolgter Benutzung mit delete freizugeben.
+ */
+ static bool ExtractImageProperties(const char* pFileData, unsigned int FileSize,
+ BS_GraphicEngine::COLOR_FORMATS& ColorFormat,
+ int& Width, int& Height);
+ //@}
+
+protected:
+
+ // Protected Konstruktor, damit Instanzen dieser Klasse nur von BS_ImageLoader-Objekten erstellt werden können
+ /**
+ @brief Der Standardkonstruktor.
+
+ Dieser Konstruktor registriert alle Instanzen von #BS_ImageLoader-Klassen in einer Liste.<br>
+ Diese Liste enthält jeweils eine Instanz jedes #BS_ImageLoader und wird benutzt um beliebige Bilddateien einem Loader zuzuordnen.
+ @remark Dieser Konstruktor ist protected damit nur #BS_ImageLoader-Objekte diese Klasse instanziieren können.
+ */
+ BS_ImageLoader()
+ {
+ // Klasse registrieren
+ _ImageLoaderList.push_front(this);
+ }
+
+ //@{
+ /** @name Abstrakte Methoden */
+
+ /**
+ @brief Gibt an, ob der #BS_ImageLoader ein Bild lesen kann.
+ @param pFileData ein Pointer auf die kompletten Daten des Bildes.
+ @param FileSize die Größe der Daten in Byte.
+ @return Gibt true zurück, wenn der #BS_ImageLoader das Bild lesen kann, ansonsten false.
+ @remark Diese Methode muss von allen BS_ImageLoader Klassen implementiert werden.
+ */
+ virtual bool IsCorrectImageFormat(const char* pFileData, unsigned int FileSize) = 0;
+
+ /**
+ @brief Lädt eine Bilddatei.
+ @param pFileData ein Pointer auf die Bilddaten.
+ @param FileSize die Größe der Bilddaten in Byte.
+ @param ColorFormat gibt das gewünschte Farbformat an, in das die Bilddaten konvertiert werden sollen.<br>
+ Folgende Farbformate werden unterstützt:
+ - BS_GraphicEngine::CF_RGB16
+ - BS_GraphicEngine::CF_RGB15
+ - BS_GraphicEngine::CF_RGB16_INTERLEAVED
+ - BS_GraphicEngine::CF_RGB15_INTERLEAVED
+ - BS_GraphicEngine::CF_ARGB32
+ @param pUncompressedData nach erfolgreichen Laden zeigt dieser Pointer auf die enpackten und konvertierten Bilddaten.
+ @param Width gibt nach erfolgreichen Laden die Breite des geladenen Bildes an.
+ @param Height gibt nach erfolgreichen Laden die Höhe des geladenen Bildes an.
+ @param Pitch gibt nach erfolgreichen Laden die Länge einer Bildzeile in Byte an.
+ @return Gibt false zurück, falls das Laden fehlgeschlagen ist.
+ @remark Die Größe der Ausgabedaten in Bytes kann wie folgt berechnet werden: Pitch * Height.
+ @remark Es darf nicht vergessen werden, die Ausgabedaten nach erfolgter Benutzung mit delete freizugeben.
+ @remark Diese Methode muss von allen BS_ImageLoader Klassen implementiert werden.
+ */
+ virtual bool DecodeImage(const char* pFileData, unsigned int FileSize,
+ BS_GraphicEngine::COLOR_FORMATS ColorFormat,
+ char*& pUncompressedData,
+ int& Width, int& Height,
+ int& Pitch) = 0;
+
+ /**
+ @brief Liest die Bildeigenschaften aus.
+ @param pFileData ein Pointer auf die Bilddaten.
+ @param FileSize die Größe des Bilddaten in Byte.
+ @param ColorFormat enthält nach einem erfolgreichem Aufruf das Farbformat des Bildes.
+ @param Width enthält nach einem erfolgreichem Aufruf die Breite des Bildes in Pixeln.
+ @param Height enthält nach einem erfolgreichem Aufruf die Höhe des Bildes in Pixeln.
+ @return Gibt false zurück, wenn die Bildeigenschaften nicht ausgelesen werden konnten.
+ @remark Es darf nicht vergessen werden, die Ausgabedaten nach erfolgter Benutzung mit delete freizugeben.
+ @remark Diese Methode muss von allen BS_ImageLoader Klassen implementiert werden.
+ */
+ virtual bool ImageProperties(const char* pFileData, unsigned int FileSize,
+ BS_GraphicEngine::COLOR_FORMATS& ColorFormat,
+ int& Width, int& Height) = 0;
+
+ //@}
+
+ //@{
+ /** @name Konvertierungsmethoden */
+
+ /**
+ @brief Konvertiert eine Bildzeile mit ARGB Pixeldaten in das BS_GraphicEngine::CF_RGB16 Farbformat.
+ @param pSrcData ein Pointer auf die Quelldaten.
+ @param pDestData ein Pointer auf den Zielpuffern.
+ @param Width die Anzahl der Pixel in der Bildzeile.
+ @remark Es gilt zu beachten, dass der Zielpuffer ausreichend groß ist.<br>
+ Es sind mindestens Width * 2 Byte notwendig.
+ */
+ static void RowARGB32ToRGB16(unsigned char* pSrcData, unsigned char* pDestData, unsigned int Width)
+ {
+ for (unsigned int i = 0; i < Width; i++)
+ {
+ ((uint16_t*)pDestData)[i] = ((pSrcData[2] >> 3) << 11) | ((pSrcData[1] >> 2) << 5) | (pSrcData[0] >> 3);
+ pSrcData += 4;
+ }
+ }
+
+ /**
+ @brief Konvertiert eine Bildzeile mit ARGB Pixeldaten in das BS_GraphicEngine::CF_RGB15 Farbformat.
+ @param pSrcData ein Pointer auf die Quelldaten.
+ @param pDestData ein Pointer auf den Zielpuffern.
+ @param Width die Anzahl der Pixel in der Bildzeile.
+ @remark Es gilt zu beachten, dass der Zielpuffer ausreichend groß ist.<br>
+ Es sind mindestens Width * 2 Byte notwendig.
+ */
+ static void RowARGB32ToRGB15(unsigned char* pSrcData, unsigned char* pDestData, unsigned int Width)
+ {
+ for (unsigned int i = 0; i < Width; i++)
+ {
+ ((uint16_t*)pDestData)[i] = ((pSrcData[2] >> 3) << 10) | ((pSrcData[1] >> 3) << 5) | (pSrcData[0] >> 3);
+ pSrcData += 4;
+ }
+ }
+
+ /**
+ @brief Konvertiert eine Bildzeile mit ARGB Pixeldaten in das BS_GraphicEngine::CF_RGB16_INTERLEAVED Farbformat.
+ @param pSrcData ein Pointer auf die Quelldaten.
+ @param pDestData ein Pointer auf den Zielpuffern.
+ @param Width die Anzahl der Pixel in der Bildzeile.
+ @remark Es gilt zu beachten, dass der Zielpuffer ausreichend groß sein muss.<br>
+ Es sind mindestens ((Width + 3) / 4) * 12 Byte notwendig.
+ */
+ static void RowARGB32ToRGB16_INTERLEAVED(unsigned char* pSrcData, unsigned char* pDestData, unsigned int Width)
+ {
+ // Die Pixelblöcke erstellen, dabei werden immer jeweils 4 Pixel zu einem Block zusammengefasst
+ unsigned int BlockFillCount = 0;
+ unsigned int AlphaBlock = 0;
+ for (unsigned int i = 0; i < Width; i++)
+ {
+ // Alphawert in den Alphablock schreiben
+ AlphaBlock = (AlphaBlock >> 8) | (pSrcData[BlockFillCount * 4 + 3] << 24);
+
+ // Füllstand der Pixelblockes aktualisieren
+ BlockFillCount++;
+
+ // Sobald 4 Alphawerte gesammelt wurden, oder die Zeile zu Ende ist wird der Pixelblock in den Zielpuffer geschrieben
+ if (BlockFillCount == 4 || i == (Width - 1))
+ {
+ // Falls der AlphaBlock nicht ganz gefüllt ist muss geshiftet werden um sicherzustellen, dass die Alphawerte
+ // "left aligned" sind.
+ AlphaBlock >>= (4 - BlockFillCount) * 8;
+
+ // Alphablock schreiben
+ *((unsigned int*)pDestData) = AlphaBlock;
+ pDestData += 4;
+
+ // Pixel konvertieren und schreiben
+ RowARGB32ToRGB16(pSrcData, pDestData, BlockFillCount);
+
+ // Pointer auf den nächsten Platz im Zielpuffer setzen
+ pDestData += 8;
+
+ // Pointer auf die nächsten 4 Pixel im Quellpuffer setzen
+ pSrcData += 16;
+
+ // Neuen Pixelblock beginnen
+ BlockFillCount = 0;
+ }
+ }
+ }
+
+ /**
+ @brief Konvertiert eine Bildzeile mit ARGB Pixeldaten in das BS_GraphicEngine::CF_RGB15_INTERLEAVED Farbformat.
+ @param pSrcData ein Pointer auf die Quelldaten.
+ @param pDestData ein Pointer auf den Zielpuffern.
+ @param Width die Anzahl der Pixel in der Bildzeile.
+ @remark Es gilt zu beachten, dass der Zielpuffer ausreichend groß ist.<br>
+ Es sind mindestens (Width / 4 + Width % 4) * 3 Byte notwendig.
+ */
+ static void RowARGB32ToRGB15_INTERLEAVED(unsigned char* pSrcData, unsigned char* pDestData, unsigned int Width)
+ {
+ // Die Pixelblöcke erstellen, dabei werden immer jeweils 4 Pixel zu einem Block zusammengefasst
+ unsigned int BlockFillCount = 0;
+ unsigned int AlphaBlock = 0;
+ for (unsigned int i = 0; i < Width; i++)
+ {
+ // Alphawert in den Alphablock schreiben
+ AlphaBlock = (AlphaBlock >> 8) | (pSrcData[BlockFillCount * 4 + 3] << 24);
+
+ // Füllstand der Pixelblockes aktualisieren
+ BlockFillCount++;
+
+ // Sobald 4 Alphawerte gesammelt wurden, oder die Zeile zu Ende ist wird der Pixelblock in den Zielpuffer geschrieben
+ if (BlockFillCount == 4 || i == (Width - 1))
+ {
+ // Falls der AlphaBlock nicht ganz gefüllt ist muss geshiftet werden um sicherzustellen, dass die Alphawerte
+ // "left aligned" sind.
+ AlphaBlock >>= (4 - BlockFillCount) * 8;
+
+ // Alphablock schreiben
+ *((unsigned int*)pDestData) = AlphaBlock;
+ pDestData += 4;
+
+ // Pixel konvertieren und schreiben
+ RowARGB32ToRGB15(pSrcData, pDestData, BlockFillCount);
+
+ // Pointer auf den nächsten Platz im Zielpuffer setzen
+ pDestData += 8;
+
+ // Pointer auf die nächsten 4 Pixel im Quellpuffer setzen
+ pSrcData += 16;
+
+ // Neuen Pixelblock beginnen
+ BlockFillCount = 0;
+ }
+ }
+ }
+
+ /**
+ @brief Konvertiert eine Bildzeile mit ARGB Pixeldaten in das BS_GraphicEngine::CF_BGRA32 Farbformat.
+ @param pSrcData ein Pointer auf die Quelldaten.
+ @param pDestData ein Pointer auf den Zielpuffern.
+ @param Width die Anzahl der Pixel in der Bildzeile.
+ */
+ static void RowARGB32ToABGR32(unsigned char* pSrcData, unsigned char* pDestData, unsigned int Width)
+ {
+ for (unsigned int i = 0; i < Width; ++i)
+ {
+ *pDestData++ = pSrcData[2];
+ *pDestData++ = pSrcData[1];
+ *pDestData++ = pSrcData[0];
+ *pDestData++ = pSrcData[3];
+
+ pSrcData += 4;
+ }
+ }
+
+private:
+
+ /**
+ @brief Erzeugt je eine Instanz aller BS_ImageLoader Klassen und fügt diese in eine interne Liste ein. Diese werden dann beim
+ Laden von Bildern benutzt.
+ @remark Die Klassen müssen in der Datei imageloader_ids.h eingetragen sein, damit sie an dieser Stelle berücksichtigt werden.
+ */
+ static void _InitializeLoaderList();
+
+ /**
+ @brief Zerstört alle Instanzen von BS_ImageLoader Klassen, die in dieser Klasse registriert sind.
+ */
+ static void _DeinitializeLoaderList();
+
+ /**
+ @brief Sucht zu Bilddaten ein BS_ImageLoader Objekt, dass die Bilddaten dekodieren kann.
+ @return Gibt einen Pointer auf ein passendes BS_ImageLoader Objekt zurück, oder NULL, wenn kein passendes Objekt gefunden wurde.
+ */
+ static BS_ImageLoader* BS_ImageLoader::_FindSuitableImageLoader(const char* pFileData, unsigned int FileSize);
+
+ static std::list<BS_ImageLoader*> _ImageLoaderList; // Die Liste aller BS_ImageLoader-Objekte
+ static bool _ImageLoaderListInitialized; // Gibt an, ob die Liste schon intialisiert wurde
+};
+
+#endif
diff --git a/engines/sword25/gfx/image/imageloader_ids.h b/engines/sword25/gfx/image/imageloader_ids.h
new file mode 100755
index 0000000000..4564996a0f
--- /dev/null
+++ b/engines/sword25/gfx/image/imageloader_ids.h
@@ -0,0 +1,44 @@
+// -----------------------------------------------------------------------------
+// This file is part of Broken Sword 2.5
+// Copyright (c) Malte Thiesen, Daniel Queteschiner and Michael Elsdörfer
+//
+// Broken Sword 2.5 is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// Broken Sword 2.5 is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Broken Sword 2.5; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+// -----------------------------------------------------------------------------
+
+/*
+ imageloader_ids.h
+ -----------------
+ In dieser Datei sind alle ImageLoader verzeichnet.
+ JEDER neuer ImageLoader muss hier eingetragen werden, ansonsten wird er beim Laden eines Bildes nicht berücksichtigt.
+
+ Autor: Malte Thiesen
+*/
+
+#include "imageloader.h"
+
+// Die Headerdateien der ImageLoader müssen hier eingebunden werden
+#include "pngloader.h"
+#include "b25sloader.h"
+
+// Die Tabelle enthält Pointer auf statische Member-Funktionen innerhalb der Klassen, die eine Instanz der Klasse
+// erzeugen
+typedef BS_ImageLoader* (*BS_IMAGELOADER_NEW)();
+const BS_IMAGELOADER_NEW BS_IMAGELOADER_IDS[] =
+{
+ BS_PNGLoader::CreateInstance,
+ BS_B25SLoader::CreateInstance,
+};
+const int BS_IMAGELOADER_COUNT = sizeof(BS_IMAGELOADER_IDS) / sizeof(BS_IMAGELOADER_NEW);
+
diff --git a/engines/sword25/gfx/image/pngloader.cpp b/engines/sword25/gfx/image/pngloader.cpp
new file mode 100755
index 0000000000..3815f4e4ff
--- /dev/null
+++ b/engines/sword25/gfx/image/pngloader.cpp
@@ -0,0 +1,389 @@
+// -----------------------------------------------------------------------------
+// This file is part of Broken Sword 2.5
+// Copyright (c) Malte Thiesen, Daniel Queteschiner and Michael Elsdörfer
+//
+// Broken Sword 2.5 is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// Broken Sword 2.5 is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Broken Sword 2.5; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+// -----------------------------------------------------------------------------
+
+// -----------------------------------------------------------------------------
+// Includes
+// -----------------------------------------------------------------------------
+
+#include "image.h"
+#include "pngloader.h"
+#include "util/libpng/png.h"
+
+#define BS_LOG_PREFIX "PNGLOADER"
+
+// -----------------------------------------------------------------------------
+// Konstruktor / Destruktor
+// -----------------------------------------------------------------------------
+
+BS_PNGLoader::BS_PNGLoader()
+{
+}
+
+// -----------------------------------------------------------------------------
+// Laden
+// -----------------------------------------------------------------------------
+
+static void png_user_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
+{
+ memcpy(data, (char*)png_ptr->io_ptr, length);
+ png_ptr->io_ptr = (void*)((png_size_t)png_ptr->io_ptr + length);
+}
+
+// -----------------------------------------------------------------------------
+
+bool BS_PNGLoader::DoDecodeImage(const char * FileDataPtr, unsigned int FileSize, BS_GraphicEngine::COLOR_FORMATS ColorFormat, char * & UncompressedDataPtr,
+ int & Width, int & Height, int & Pitch)
+{
+ png_structp png_ptr = NULL;
+ png_infop info_ptr = NULL;
+ png_bytep RawDataBuffer = NULL;
+ png_bytep* pRowPtr = NULL;
+
+ int BitDepth;
+ int ColorType;
+ int InterlaceType;
+ int i;
+
+ // Zielfarbformat überprüfen
+ if (ColorFormat != BS_GraphicEngine::CF_RGB16 &&
+ ColorFormat != BS_GraphicEngine::CF_RGB15 &&
+ ColorFormat != BS_GraphicEngine::CF_RGB16_INTERLEAVED &&
+ ColorFormat != BS_GraphicEngine::CF_RGB15_INTERLEAVED &&
+ ColorFormat != BS_GraphicEngine::CF_ARGB32 &&
+ ColorFormat != BS_GraphicEngine::CF_ABGR32)
+ {
+ BS_LOG_ERRORLN("Illegal or unsupported color format.");
+ return false;
+ }
+
+ try
+ {
+ // PNG Signatur überprüfen
+ if (!png_check_sig(reinterpret_cast<png_bytep>(const_cast<char *>(FileDataPtr)), 8))
+ {
+ throw(0);
+ }
+
+ // Die beiden PNG Strukturen erstellen
+ png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+ if (!png_ptr)
+ {
+ BS_LOG_ERRORLN("Could not create libpng read struct.");
+ throw(0);
+ }
+
+ info_ptr = png_create_info_struct(png_ptr);
+ if (!info_ptr)
+ {
+ BS_LOG_ERRORLN("Could not create libpng info struct.");
+ throw(0);
+ }
+
+ // Rücksprungpunkt setzen. Wird im Falle eines Fehlers angesprungen.
+ if (setjmp(png_jmpbuf(png_ptr))) throw(0);
+
+ // Alternative Lesefunktion benutzen
+ png_set_read_fn(png_ptr, (void*)FileDataPtr, png_user_read_data);
+
+ // PNG Header einlesen
+ png_read_info(png_ptr, info_ptr);
+
+ // PNG Informationen auslesen
+ png_get_IHDR(png_ptr, info_ptr, (unsigned long*)&Width, (unsigned long*)&Height, &BitDepth, &ColorType, &InterlaceType, NULL, NULL);
+
+ // Pitch des Ausgabebildes berechnen
+ Pitch = BS_GraphicEngine::CalcPitch(ColorFormat, Width);
+
+ // Speicher für die endgültigen Bilddaten reservieren
+ // Dieses geschieht vor dem reservieren von Speicher für temporäre Bilddaten um die Fragmentierung des Speichers gering zu halten
+ UncompressedDataPtr = new char[Pitch * Height];
+ if (!UncompressedDataPtr)
+ {
+ BS_LOG_ERRORLN("Could not allocate memory for output image.");
+ throw(0);
+ }
+
+ // Bilder jeglicher Farbformate werden zunächst in ARGB Bilder umgewandelt
+ if (BitDepth == 16)
+ png_set_strip_16(png_ptr);
+ if (ColorType == PNG_COLOR_TYPE_PALETTE)
+ png_set_expand(png_ptr);
+ if (BitDepth < 8)
+ png_set_expand(png_ptr);
+ if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
+ png_set_expand(png_ptr);
+ if (ColorType == PNG_COLOR_TYPE_GRAY ||
+ ColorType == PNG_COLOR_TYPE_GRAY_ALPHA)
+ png_set_gray_to_rgb(png_ptr);
+
+ png_set_bgr(png_ptr);
+
+ if (ColorType != PNG_COLOR_TYPE_RGB_ALPHA)
+ png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
+
+ // Nachdem die Transformationen registriert wurden, werden die Bilddaten erneut eingelesen
+ png_read_update_info(png_ptr, info_ptr);
+ png_get_IHDR(png_ptr, info_ptr, (unsigned long*)&Width, (unsigned long*)&Height, &BitDepth, &ColorType, NULL, NULL, NULL);
+
+ // PNGs ohne Interlacing werden Zeilenweise eingelesen
+ if (InterlaceType == PNG_INTERLACE_NONE)
+ {
+ // Speicher für eine Bildzeile reservieren
+ RawDataBuffer = new png_byte[png_get_rowbytes(png_ptr, info_ptr)];
+ if (!RawDataBuffer)
+ {
+ BS_LOG_ERRORLN("Could not allocate memory for row buffer.");
+ throw(0);
+ }
+
+ // Bilddaten zeilenweise einlesen und in das gewünschte Zielformat konvertieren
+ for (i = 0; i < Height; i++)
+ {
+ // Zeile einlesen
+ png_read_row(png_ptr, RawDataBuffer, NULL);
+
+ // Zeile konvertieren
+ switch (ColorFormat)
+ {
+ case BS_GraphicEngine::CF_RGB16:
+ RowARGB32ToRGB16((unsigned char*)RawDataBuffer,
+ (unsigned char*)&UncompressedDataPtr[i * Pitch],
+ Width);
+ break;
+
+ case BS_GraphicEngine::CF_RGB15:
+ RowARGB32ToRGB15((unsigned char*)RawDataBuffer,
+ (unsigned char*)&UncompressedDataPtr[i * Pitch],
+ Width);
+ break;
+
+ case BS_GraphicEngine::CF_RGB16_INTERLEAVED:
+ RowARGB32ToRGB16_INTERLEAVED((unsigned char*)RawDataBuffer,
+ (unsigned char*)&UncompressedDataPtr[i * Pitch],
+ Width);
+ break;
+
+ case BS_GraphicEngine::CF_RGB15_INTERLEAVED:
+ RowARGB32ToRGB15_INTERLEAVED((unsigned char*)RawDataBuffer,
+ (unsigned char*)&UncompressedDataPtr[i * Pitch],
+ Width);
+ break;
+
+ case BS_GraphicEngine::CF_ARGB32:
+ memcpy(&UncompressedDataPtr[i * Pitch],
+ RawDataBuffer,
+ Pitch);
+ break;
+
+ case BS_GraphicEngine::CF_ABGR32:
+ RowARGB32ToABGR32((unsigned char*)RawDataBuffer,
+ (unsigned char*)&UncompressedDataPtr[i * Pitch],
+ Width);
+ break;
+
+ default:
+ BS_ASSERT(false);
+ }
+ }
+ }
+ // PNGs mit Interlacing werden an einem Stück eingelesen
+ else
+ {
+ // Speicher für das komplette Bild reservieren
+ RawDataBuffer = new png_byte[png_get_rowbytes(png_ptr, info_ptr) * Height];
+ if (!RawDataBuffer)
+ {
+ BS_LOG_ERRORLN("Could not allocate memory for raw image buffer.");
+ throw(0);
+ }
+
+ // Speicher für die Rowpointer reservieren
+ pRowPtr = new png_bytep[Height];
+ if (!pRowPtr)
+ {
+ BS_LOG_ERRORLN("Could not allocate memory for row pointers.");
+ throw(0);
+ }
+
+ // Alle Rowpointer mit den richtigen Offsets initialisieren
+ for (i = 0; i < Height; i++)
+ pRowPtr[i] = RawDataBuffer + i * png_get_rowbytes(png_ptr, info_ptr);
+
+ // Bild einlesen
+ png_read_image(png_ptr, pRowPtr);
+
+ // Bilddaten zeilenweise in das gewünschte Ausgabeformat konvertieren
+ switch (ColorFormat)
+ {
+ case BS_GraphicEngine::CF_RGB16:
+ for (i = 0; i < Height; i++)
+ RowARGB32ToRGB16((unsigned char*)(&RawDataBuffer[i * png_get_rowbytes(png_ptr, info_ptr)]),
+ (unsigned char*)&UncompressedDataPtr[i * Pitch],
+ Width);
+ break;
+
+ case BS_GraphicEngine::CF_RGB15:
+ for (i = 0; i < Height; i++)
+ RowARGB32ToRGB15((unsigned char*)(&RawDataBuffer[i * png_get_rowbytes(png_ptr, info_ptr)]),
+ (unsigned char*)&UncompressedDataPtr[i * Pitch],
+ Width);
+ break;
+
+ case BS_GraphicEngine::CF_RGB16_INTERLEAVED:
+ for (i = 0; i < Height; i++)
+ RowARGB32ToRGB16_INTERLEAVED((unsigned char*)(&RawDataBuffer[i * png_get_rowbytes(png_ptr, info_ptr)]),
+ (unsigned char*)&UncompressedDataPtr[i * Pitch],
+ Width);
+ break;
+
+ case BS_GraphicEngine::CF_RGB15_INTERLEAVED:
+ for (i = 0; i < Height; i++)
+ RowARGB32ToRGB15_INTERLEAVED((unsigned char*)(&RawDataBuffer[i * png_get_rowbytes(png_ptr, info_ptr)]),
+ (unsigned char*)&UncompressedDataPtr[i * Pitch],
+ Width);
+ break;
+
+ case BS_GraphicEngine::CF_ARGB32:
+ for (i = 0; i < Height; i++)
+ memcpy(&UncompressedDataPtr[i * Pitch],
+ &RawDataBuffer[i * png_get_rowbytes(png_ptr, info_ptr)],
+ Pitch);
+ break;
+ }
+ }
+
+ // Die zusätzlichen Daten am Ende des Bildes lesen
+ png_read_end(png_ptr, NULL);
+
+ // Die Strukturen freigeben
+ png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
+
+ // Temporäre Buffer freigeben
+ delete[] pRowPtr;
+ delete[] RawDataBuffer;
+ }
+
+ catch(int)
+ {
+ delete[] pRowPtr;
+ delete[] RawDataBuffer;
+ if (png_ptr) png_destroy_read_struct(&png_ptr, NULL, NULL);
+ if (info_ptr) png_destroy_read_struct(NULL, &info_ptr, NULL);
+
+ // Der Funktionsaufruf war nicht erfolgreich
+ return false;
+ }
+
+ // Der Funktionsaufruf war erfolgreich
+ return true;
+}
+
+// -----------------------------------------------------------------------------
+
+bool BS_PNGLoader::DecodeImage(const char * FileDataPtr, unsigned int FileSize, BS_GraphicEngine::COLOR_FORMATS ColorFormat, char * & UncompressedDataPtr,
+ int & Width, int & Height, int & Pitch)
+{
+ return DoDecodeImage(FileDataPtr, FileSize, ColorFormat, UncompressedDataPtr, Width, Height, Pitch);
+}
+
+// -----------------------------------------------------------------------------
+
+bool BS_PNGLoader::DoImageProperties(const char * FileDataPtr, unsigned int FileSize, BS_GraphicEngine::COLOR_FORMATS & ColorFormat, int & Width, int & Height)
+{
+ // PNG Signatur überprüfen
+ if (!DoIsCorrectImageFormat(FileDataPtr, FileSize)) return false;
+
+ png_structp png_ptr = NULL;
+ png_infop info_ptr = NULL;
+ try
+ {
+ // Die beiden PNG Strukturen erstellen
+ png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+ if (!png_ptr)
+ {
+ BS_LOG_ERRORLN("Could not create libpng read struct.");
+ throw(0);
+ }
+
+ info_ptr = png_create_info_struct(png_ptr);
+ if (!info_ptr)
+ {
+ BS_LOG_ERRORLN("Could not create libpng info struct.");
+ throw(0);
+ }
+
+ // Alternative Lesefunktion benutzen
+ png_set_read_fn(png_ptr, (void*)FileDataPtr, png_user_read_data);
+
+ // PNG Header einlesen
+ png_read_info(png_ptr, info_ptr);
+
+ // PNG Informationen auslesen
+ int BitDepth;
+ int ColorType;
+ png_get_IHDR(png_ptr, info_ptr, (unsigned long*)&Width, (unsigned long*)&Height, &BitDepth, &ColorType, NULL, NULL, NULL);
+
+ // PNG-ColorType in BS ColorFormat konvertieren.
+ if (ColorType & PNG_COLOR_MASK_ALPHA || png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
+ ColorFormat = BS_GraphicEngine::CF_ARGB32;
+ else
+ ColorFormat = BS_GraphicEngine::CF_RGB24;
+
+ // Die Strukturen freigeben
+ png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
+ }
+
+ catch (int)
+ {
+ if (png_ptr) png_destroy_read_struct(&png_ptr, NULL, NULL);
+ if (info_ptr) png_destroy_read_struct(NULL, &info_ptr, NULL);
+
+ // Der Funktionsaufruf war nicht erfolgreich
+ return false;
+ }
+
+ return true;
+
+}
+
+// -----------------------------------------------------------------------------
+
+bool BS_PNGLoader::ImageProperties(const char* FileDataPtr, unsigned int FileSize, BS_GraphicEngine::COLOR_FORMATS & ColorFormat, int & Width, int & Height)
+{
+ return DoImageProperties(FileDataPtr, FileSize, ColorFormat, Width, Height);
+}
+
+// -----------------------------------------------------------------------------
+// Header überprüfen
+// -----------------------------------------------------------------------------
+
+bool BS_PNGLoader::DoIsCorrectImageFormat(const char * FileDataPtr, unsigned int FileSize)
+{
+ if (FileSize > 8)
+ return png_check_sig((unsigned char*)FileDataPtr, 8) ? true : false;
+ else
+ return false;
+}
+
+// -----------------------------------------------------------------------------
+
+bool BS_PNGLoader::IsCorrectImageFormat(const char* FileDataPtr, unsigned int FileSize)
+{
+ return DoIsCorrectImageFormat(FileDataPtr, FileSize);
+}
diff --git a/engines/sword25/gfx/image/pngloader.h b/engines/sword25/gfx/image/pngloader.h
new file mode 100755
index 0000000000..5fdedf49fc
--- /dev/null
+++ b/engines/sword25/gfx/image/pngloader.h
@@ -0,0 +1,64 @@
+// -----------------------------------------------------------------------------
+// This file is part of Broken Sword 2.5
+// Copyright (c) Malte Thiesen, Daniel Queteschiner and Michael Elsdörfer
+//
+// Broken Sword 2.5 is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// Broken Sword 2.5 is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Broken Sword 2.5; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+// -----------------------------------------------------------------------------
+
+/*
+ BS_PNGLoader
+ ------------
+ BS_ImageLoader-Klasse zum Laden von PNG-Dateien
+
+ Autor: Malte Thiesen
+*/
+
+#ifndef BS_PNGLOADER2_H
+#define BS_PNGLOADER2_H
+
+// Includes
+#include "kernel/common.h"
+#include "imageloader.h"
+
+// Klassendefinition
+class BS_PNGLoader : public BS_ImageLoader
+{
+public:
+ static BS_ImageLoader* CreateInstance()
+ {
+ #include "kernel/memlog_off.h"
+ return (BS_ImageLoader*) new BS_PNGLoader();
+ #include "kernel/memlog_on.h"
+ }
+
+ // Alle virtuellen Methoden von BS_ImageLoader sind hier als static-Methode implementiert, damit sie von BS_B25SLoader aufgerufen werden können.
+ // Die virtuellen Methoden rufen diese Methoden auf.
+ static bool DoIsCorrectImageFormat(const char * FileDataPtr, unsigned int FileSize);
+ static bool DoDecodeImage(const char * FileDataPtr, unsigned int FileSize, BS_GraphicEngine::COLOR_FORMATS ColorFormat, char * & UncompressedDataPtr,
+ int & Width, int & Height, int & Pitch);
+ static bool DoImageProperties(const char * FileDataPtr, unsigned int FileSize, BS_GraphicEngine::COLOR_FORMATS & ColorFormat, int & Width, int & Height);
+
+protected:
+ BS_PNGLoader();
+ bool DecodeImage(const char * pFileData, unsigned int FileSize,
+ BS_GraphicEngine::COLOR_FORMATS ColorFormat,
+ char * & pUncompressedData,
+ int & Width, int & Height,
+ int & Pitch);
+ bool IsCorrectImageFormat(const char * FileDataPtr, unsigned int FileSize);
+ bool ImageProperties(const char * FileDatePtr, unsigned int FileSize, BS_GraphicEngine::COLOR_FORMATS & ColorFormat, int & Width, int & Height);
+};
+
+#endif
diff --git a/engines/sword25/gfx/image/vectorimage.cpp b/engines/sword25/gfx/image/vectorimage.cpp
new file mode 100755
index 0000000000..035d572149
--- /dev/null
+++ b/engines/sword25/gfx/image/vectorimage.cpp
@@ -0,0 +1,571 @@
+// -----------------------------------------------------------------------------
+// This file is part of Broken Sword 2.5
+// Copyright (c) Malte Thiesen, Daniel Queteschiner and Michael Elsdörfer
+//
+// Broken Sword 2.5 is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// Broken Sword 2.5 is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Broken Sword 2.5; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+// -----------------------------------------------------------------------------
+
+// -----------------------------------------------------------------------------
+// Includes
+// -----------------------------------------------------------------------------
+
+#include "kernel/bs_stdint.h"
+#include "vectorimage.h"
+#include <vector>
+#include <stdexcept>
+
+#include "agg_bounding_rect.h"
+
+using namespace std;
+
+#define BS_LOG_PREFIX "VECTORIMAGE"
+
+
+// -----------------------------------------------------------------------------
+// SWF Datentypen
+// -----------------------------------------------------------------------------
+
+typedef uint8_t u8;
+typedef uint32_t u32;
+typedef uint16_t u16;
+typedef int16_t s32;
+
+
+// -----------------------------------------------------------------------------
+// Bitstream Hilfsklasse
+// -----------------------------------------------------------------------------
+// Das Parsen von SWF-Dateien erfordert sowohl bitweises Auslesen als auch an
+// Bytegrenzen ausgerichtetes Lesen.
+// Diese Klasse ist speziell dafür ausgestattet.
+// -----------------------------------------------------------------------------
+
+class BS_VectorImage::SWFBitStream
+{
+public:
+ SWFBitStream(const unsigned char * pData, unsigned int DataSize) :
+ m_Pos(pData), m_End(pData + DataSize), m_WordMask(0)
+ {}
+
+ inline u32 GetBits(unsigned int BitCount)
+ {
+ if (BitCount == 0 || BitCount > 32)
+ {
+ throw(runtime_error("SWFBitStream::GetBits() must read at least 1 and at most 32 bits at a time"));
+ }
+
+ u32 value = 0;
+ while (BitCount)
+ {
+ if (m_WordMask == 0) FlushByte();
+
+ value <<= 1;
+ value |= ((m_Word & m_WordMask) != 0) ? 1 : 0;
+ m_WordMask >>= 1;
+
+ --BitCount;
+ }
+
+ return value;
+ }
+
+ inline s32 GetSignedBits(unsigned int BitCount)
+ {
+ // Bits einlesen
+ u32 Temp = GetBits(BitCount);
+
+ // Falls das Sign-Bit gesetzt ist, den Rest des Rückgabewertes mit 1-Bits auffüllen (Sign Extension)
+ if (Temp & 1 << (BitCount - 1))
+ return (0xffffffff << BitCount) | Temp;
+ else
+ return Temp;
+ }
+
+ inline u32 GetU32()
+ {
+ u32 Byte1 = GetU8();
+ u32 Byte2 = GetU8();
+ u32 Byte3 = GetU8();
+ u32 Byte4 = GetU8();
+
+ return Byte1 | (Byte2 << 8) | (Byte3 << 16) | (Byte4 << 24);
+ }
+
+ inline u16 GetU16()
+ {
+ u32 Byte1 = GetU8();
+ u32 Byte2 = GetU8();
+
+ return Byte1 | (Byte2 << 8);
+ }
+
+ inline u8 GetU8()
+ {
+ FlushByte();
+ u8 Value = m_Word;
+ m_WordMask = 0;
+ FlushByte();
+
+ return Value;
+ }
+
+ inline void FlushByte()
+ {
+ if (m_WordMask != 128)
+ {
+ if (m_Pos >= m_End)
+ {
+ throw(runtime_error("Attempted to read past end of file"));
+ }
+ else
+ {
+ m_Word = *m_Pos++;
+ m_WordMask = 128;
+ }
+ }
+ }
+
+ inline void SkipBytes(unsigned int SkipLength)
+ {
+ FlushByte();
+ if (m_Pos + SkipLength >= m_End)
+ {
+ throw(runtime_error("Attempted to read past end of file"));
+ }
+ else
+ {
+ m_Pos += SkipLength;
+ m_Word = *(m_Pos - 1);
+ }
+ }
+
+private:
+ const unsigned char * m_Pos;
+ const unsigned char * m_End;
+
+ u8 m_Word;
+ unsigned int m_WordMask;
+};
+
+
+// -----------------------------------------------------------------------------
+// Konstanten und Hilfsfunktionen
+// -----------------------------------------------------------------------------
+
+namespace
+{
+ // -----------------------------------------------------------------------------
+ // Konstanten
+ // -----------------------------------------------------------------------------
+
+ const u32 MAX_ACCEPTED_FLASH_VERSION = 3; // Die höchste Flash-Dateiversion, die vom Lader akzeptiert wird
+
+
+ // -----------------------------------------------------------------------------
+ // Konvertiert SWF-Rechteckdaten in einem Bitstrom in BS_Rect-Objekte
+ // -----------------------------------------------------------------------------
+
+ BS_Rect FlashRectToBSRect(BS_VectorImage::SWFBitStream & bs)
+ {
+ bs.FlushByte();
+
+ // Feststellen mit wie vielen Bits die einzelnen Komponenten kodiert sind
+ u32 BitsPerValue = bs.GetBits(5);
+
+ // Die einzelnen Komponenten einlesen
+ s32 XMin = bs.GetSignedBits(BitsPerValue);
+ s32 XMax = bs.GetSignedBits(BitsPerValue);
+ s32 YMin = bs.GetSignedBits(BitsPerValue);
+ s32 YMax = bs.GetSignedBits(BitsPerValue);
+
+ return BS_Rect(XMin, YMin, XMax + 1, YMax + 1);
+ }
+
+
+ // -----------------------------------------------------------------------------
+ // Konvertiert SWF-Farben in AntiGrain Farben
+ // -----------------------------------------------------------------------------
+
+ agg::rgba8 FlashColorToAGGRGBA8(unsigned int FlashColor)
+ {
+ agg::rgba8 ResultColor((FlashColor >> 16) & 0xff, (FlashColor >> 8) & 0xff, FlashColor & 0xff, FlashColor >> 24);
+ ResultColor.premultiply();
+ return ResultColor;
+ }
+
+
+ // -----------------------------------------------------------------------------
+ // Berechnet die Bounding-Box eines BS_VectorImageElement
+ // -----------------------------------------------------------------------------
+
+ struct CBBGetId
+ {
+ CBBGetId(const BS_VectorImageElement & VectorImageElement_) : VectorImageElement(VectorImageElement_) {}
+ unsigned operator [] (unsigned i) const { return VectorImageElement.GetPathInfo(i).GetID(); }
+ const BS_VectorImageElement & VectorImageElement;
+ };
+
+ BS_Rect CalculateBoundingBox(const BS_VectorImageElement & VectorImageElement)
+ {
+ agg::path_storage Path = VectorImageElement.GetPaths();
+ CBBGetId IdSource(VectorImageElement);
+
+ double x1, x2, y1, y2;
+ agg::bounding_rect(Path, IdSource, 0, VectorImageElement.GetPathCount(), &x1, &y1, &x2, &y2);
+
+ return BS_Rect(static_cast<int>(x1), static_cast<int>(y1), static_cast<int>(x2) + 1, static_cast<int>(y2) + 1);
+ }
+}
+
+
+// -----------------------------------------------------------------------------
+// Konstruktion
+// -----------------------------------------------------------------------------
+
+BS_VectorImage::BS_VectorImage(const unsigned char * pFileData, unsigned int FileSize, bool & Success)
+{
+ Success = false;
+
+ // Bitstream-Objekt erzeugen
+ // Im Folgenden werden die Dateidaten aus diesem ausgelesen.
+ SWFBitStream bs(pFileData, FileSize);
+
+ try
+ {
+ // SWF-Signatur überprüfen
+ u32 Signature[3];
+ Signature[0] = bs.GetU8();
+ Signature[1] = bs.GetU8();
+ Signature[2] = bs.GetU8();
+ if (Signature[0] != 'F' ||
+ Signature[1] != 'W' ||
+ Signature[2] != 'S')
+ {
+ BS_LOG_ERRORLN("File is not a valid SWF-file");
+ return;
+ }
+
+ // Versionsangabe überprüfen
+ u32 Version = bs.GetU8();
+ if (Version > MAX_ACCEPTED_FLASH_VERSION)
+ {
+ BS_LOG_ERRORLN("File is of version %d. Highest accepted version is %d.", Version, MAX_ACCEPTED_FLASH_VERSION);
+ return;
+ }
+
+ // Dateigröße auslesen und mit der tatsächlichen Größe vergleichen
+ u32 StoredFileSize = bs.GetU32();
+ if (StoredFileSize != FileSize)
+ {
+ BS_LOG_ERRORLN("File is not a valid SWF-file");
+ return;
+ }
+
+ // SWF-Maße auslesen
+ BS_Rect MovieRect = FlashRectToBSRect(bs);
+
+ // Framerate und Frameanzahl auslesen
+ u32 FrameRate = bs.GetU16();
+ u32 FrameCount = bs.GetU16();
+
+ // Tags parsen
+ // Da wir uns nur für das erste DefineShape-Tag interessieren
+ bool KeepParsing = true;
+ while (KeepParsing)
+ {
+ // Tags beginnen immer an Bytegrenzen
+ bs.FlushByte();
+
+ // Tagtyp und Länge auslesen
+ u16 TagTypeAndLength = bs.GetU16();
+ u32 TagType = TagTypeAndLength >> 6;
+ u32 TagLength = TagTypeAndLength & 0x3f;
+ if (TagLength == 0x3f) TagLength = bs.GetU32();
+
+ switch (TagType)
+ {
+ case 2:
+ // DefineShape
+ Success = ParseDefineShape(2, bs);
+ return;
+ case 22:
+ // DefineShape2
+ Success = ParseDefineShape(2, bs);
+ return;
+ case 32:
+ Success = ParseDefineShape(3, bs);
+ return;
+ default:
+ // Unbekannte Tags ignorieren
+ bs.SkipBytes(TagLength);
+ }
+ }
+ }
+
+ catch (runtime_error & e)
+ {
+ // Fehler loggen und Funktion verlassen
+ // Success ist somit "false" und signalisiert dem Programmierer, dass die Konstruktion fehlgeschlagen ist.
+ BS_LOG_ERRORLN("The following exception occured while parsing a SWF-file: %s", e.what());
+ return;
+ }
+
+ // Die Ausführung darf nicht an dieser Stelle ankommen: Entweder es wird ein Shape gefunden, dann wird die Funktion mit vorher verlassen, oder
+ // es wird keines gefunden, dann tritt eine Exception auf sobald über das Ende der Datei hinaus gelesen wird.
+ BS_ASSERT(false);
+}
+
+// -----------------------------------------------------------------------------
+
+bool BS_VectorImage::ParseDefineShape(unsigned int ShapeType, SWFBitStream & bs)
+{
+ u32 ShapeID = bs.GetU16();
+
+ // Bounding Box auslesen
+ m_BoundingBox = FlashRectToBSRect(bs);
+
+ // Erstes Image-Element erzeugen
+ m_Elements.resize(1);
+
+ // Styles einlesen
+ unsigned int NumFillBits;
+ unsigned int NumLineBits;
+ if (!ParseStyles(ShapeType, bs, NumFillBits, NumLineBits)) return false;
+
+ unsigned int LineStyle = 0;
+ unsigned int FillStyle0 = 0;
+ unsigned int FillStyle1 = 0;
+
+ // Shaperecord parsen
+ // ------------------
+
+ bool EndOfShapeDiscovered = false;
+ while (!EndOfShapeDiscovered)
+ {
+ u32 TypeFlag = bs.GetBits(1);
+
+ // Non-Edge Record
+ if (TypeFlag == 0)
+ {
+ // Feststellen welche Parameter gesetzt werden
+ u32 StateNewStyles = bs.GetBits(1);
+ u32 StateLineStyle = bs.GetBits(1);
+ u32 StateFillStyle1 = bs.GetBits(1);
+ u32 StateFillStyle0 = bs.GetBits(1);
+ u32 StateMoveTo = bs.GetBits(1);
+
+ // End der Shape-Definition erreicht?
+ if (!StateNewStyles && !StateLineStyle && !StateFillStyle0 && !StateFillStyle1 && !StateMoveTo)
+ EndOfShapeDiscovered = true;
+ // Parameter dekodieren
+ else
+ {
+ s32 MoveDeltaX = 0;
+ s32 MoveDeltaY = 0;
+ if (StateMoveTo)
+ {
+ u32 MoveToBits = bs.GetBits(5);
+ MoveDeltaX = bs.GetSignedBits(MoveToBits);
+ MoveDeltaY = bs.GetSignedBits(MoveToBits);
+ }
+
+ if (StateFillStyle0)
+ {
+ if (NumFillBits > 0)
+ FillStyle0 = bs.GetBits(NumFillBits);
+ else
+ FillStyle0 = 0;
+ }
+
+ if (StateFillStyle1)
+ {
+ if (NumFillBits > 0)
+ FillStyle1 = bs.GetBits(NumFillBits);
+ else
+ FillStyle1 = 0;
+ }
+
+ if (StateLineStyle)
+ {
+ if (NumLineBits)
+ LineStyle = bs.GetBits(NumLineBits);
+ else
+ NumLineBits = 0;
+ }
+
+ if (StateNewStyles)
+ {
+ // An dieser Stelle werden in Flash die alten Style-Definitionen verworfen und mit den neuen überschrieben.
+ // Es wird ein neues Element begonnen.
+ m_Elements.resize(m_Elements.size() + 1);
+ if (!ParseStyles(ShapeType, bs, NumFillBits, NumLineBits)) return false;
+ }
+
+ // Ein neuen Pfad erzeugen, es sei denn, es wurden nur neue Styles definiert
+ if (StateLineStyle || StateFillStyle0 || StateFillStyle1 || StateMoveTo)
+ {
+ // Letzte Zeichenposition merken, beim Aufruf von start_new_path() wird die Zeichenpostionen auf 0, 0 zurückgesetzt
+ double LastX = m_Elements.back().m_Paths.last_x();
+ double LastY = m_Elements.back().m_Paths.last_y();
+
+ // Neue Pfadinformation erzeugen
+ m_Elements.back().m_PathInfos.push_back(BS_VectorPathInfo(m_Elements.back().m_Paths.start_new_path(), LineStyle, FillStyle0, FillStyle1));
+
+ // Falls eine Bewegung definiert wurde, wird die Zeichenpositionen an die entsprechende Position gesetzt.
+ // Ansonsten wird die Zeichenposition auf die letzte Zeichenposition gesetzt.
+ if (StateMoveTo)
+ m_Elements.back().m_Paths.move_to(MoveDeltaX, MoveDeltaY);
+ else
+ m_Elements.back().m_Paths.move_to(LastX, LastY);
+ }
+ }
+ }
+ // Edge Record
+ else
+ {
+ u32 EdgeFlag = bs.GetBits(1);
+ u32 NumBits = bs.GetBits(4) + 2;
+
+ // Curved edge
+ if (EdgeFlag == 0)
+ {
+ s32 ControlDeltaX = bs.GetSignedBits(NumBits);
+ s32 ControlDeltaY = bs.GetSignedBits(NumBits);
+ s32 AnchorDeltaX = bs.GetSignedBits(NumBits);
+ s32 AnchorDeltaY = bs.GetSignedBits(NumBits);
+
+ double ControlX = m_Elements.back().m_Paths.last_x() + ControlDeltaX;
+ double ControlY = m_Elements.back().m_Paths.last_y() + ControlDeltaY;
+ double AnchorX = ControlX + AnchorDeltaX;
+ double AnchorY = ControlY + AnchorDeltaY;
+ m_Elements.back().m_Paths.curve3(ControlX, ControlY, AnchorX, AnchorY);
+ }
+ // Staight edge
+ else
+ {
+ s32 DeltaX = 0;
+ s32 DeltaY = 0;
+
+ u32 GeneralLineFlag = bs.GetBits(1);
+ if (GeneralLineFlag)
+ {
+ DeltaX = bs.GetSignedBits(NumBits);
+ DeltaY = bs.GetSignedBits(NumBits);
+ }
+ else
+ {
+ u32 VertLineFlag = bs.GetBits(1);
+ if (VertLineFlag)
+ DeltaY = bs.GetSignedBits(NumBits);
+ else
+ DeltaX = bs.GetSignedBits(NumBits);
+ }
+
+ m_Elements.back().m_Paths.line_rel(DeltaX, DeltaY);
+ }
+ }
+ }
+
+ // Bounding-Boxes der einzelnen Elemente berechnen
+ vector<BS_VectorImageElement>::iterator it = m_Elements.begin();
+ for (; it != m_Elements.end(); ++it) it->m_BoundingBox = CalculateBoundingBox(*it);
+
+ return true;
+}
+
+
+// -----------------------------------------------------------------------------
+
+bool BS_VectorImage::ParseStyles(unsigned int ShapeType, SWFBitStream & bs, unsigned int & NumFillBits, unsigned int & NumLineBits)
+{
+ bs.FlushByte();
+
+ // Fillstyles parsen
+ // -----------------
+
+ // Anzahl an Fillstyles bestimmen
+ unsigned int FillStyleCount = bs.GetU8();
+ if (FillStyleCount == 0xff) FillStyleCount = bs.GetU16();
+
+ // Alle Fillstyles einlesen, falls ein Fillstyle mit Typ != 0 gefunden wird, wird das Parsen abgebrochen.
+ // Es wird nur "solid fill" (Typ 0) unterstützt.
+ m_Elements.back().m_FillStyles.reserve(FillStyleCount);
+ for (unsigned int i = 0; i < FillStyleCount; ++i)
+ {
+ u8 Type = bs.GetU8();
+ u32 Color;
+ if (ShapeType == 3)
+ {
+ Color = (bs.GetU8() << 16) | (bs.GetU8() << 8) | bs.GetU8() | (bs.GetU8() << 24);
+ }
+ else
+ Color = bs.GetBits(24) | (0xff << 24);
+ if (Type != 0) return false;
+
+ m_Elements.back().m_FillStyles.push_back(FlashColorToAGGRGBA8(Color));
+ }
+
+ // Linestyles parsen
+ // -----------------
+
+ // Anzahl an Linestyles bestimmen
+ unsigned int LineStyleCount = bs.GetU8();
+ if (LineStyleCount == 0xff) LineStyleCount = bs.GetU16();
+
+ // Alle Linestyles einlesen
+ m_Elements.back().m_LineStyles.reserve(LineStyleCount);
+ for (unsigned int i = 0; i < LineStyleCount; ++i)
+ {
+ double Width = bs.GetU16();
+ u32 Color;
+ if (ShapeType == 3)
+ Color = (bs.GetU8() << 16) | (bs.GetU8() << 8) | bs.GetU8() | (bs.GetU8() << 24);
+ else
+ Color = bs.GetBits(24) | (0xff << 24);
+
+ m_Elements.back().m_LineStyles.push_back(BS_VectorImageElement::LineStyleType(Width, FlashColorToAGGRGBA8(Color)));
+ }
+
+ // Bitbreite für die folgenden Styleindizes auslesen
+ NumFillBits = bs.GetBits(4);
+ NumLineBits = bs.GetBits(4);
+
+ return true;
+}
+
+
+// -----------------------------------------------------------------------------
+
+bool BS_VectorImage::Fill(const BS_Rect* pFillRect, unsigned int Color)
+{
+ BS_LOG_ERRORLN("Fill() is not supported.");
+ return false;
+}
+
+
+// -----------------------------------------------------------------------------
+
+unsigned int BS_VectorImage::GetPixel(int X, int Y)
+{
+ BS_LOG_ERRORLN("GetPixel() is not supported. Returning black.");
+ return 0;
+}
+
+// -----------------------------------------------------------------------------
+
+bool BS_VectorImage::SetContent(const std::vector<unsigned char> & Pixeldata, unsigned int Offset, unsigned int Stride)
+{
+ BS_LOG_ERRORLN("SetContent() is not supported.");
+ return 0;
+}
diff --git a/engines/sword25/gfx/image/vectorimage.h b/engines/sword25/gfx/image/vectorimage.h
new file mode 100755
index 0000000000..74f6c860d9
--- /dev/null
+++ b/engines/sword25/gfx/image/vectorimage.h
@@ -0,0 +1,167 @@
+// -----------------------------------------------------------------------------
+// This file is part of Broken Sword 2.5
+// Copyright (c) Malte Thiesen, Daniel Queteschiner and Michael Elsdörfer
+//
+// Broken Sword 2.5 is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// Broken Sword 2.5 is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Broken Sword 2.5; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+// -----------------------------------------------------------------------------
+
+#ifndef BS_VECTORIMAGE_H
+#define BS_VECTORIMAGE_H
+
+// -----------------------------------------------------------------------------
+// Includes
+// -----------------------------------------------------------------------------
+
+#include "kernel/common.h"
+#include "gfx/image/image.h"
+#include "math/rect.h"
+
+#include <vector>
+#include "agg_path_storage.h"
+#include "agg_color_rgba.h"
+
+
+class BS_VectorImage;
+
+/**
+ @brief Pfadinformationen zu BS_VectorImageElement Objekten
+
+ Jedes BS_VectorImageElement besteht aus Kantenzügen, oder auch Pfaden. Jeder dieser Pfad hat Eigenschaften, die in Objekten diesen Typs
+ gespeichert werden.
+*/
+
+class BS_VectorPathInfo
+{
+public:
+ BS_VectorPathInfo(unsigned int ID, unsigned int LineStyle, unsigned int FillStyle0, unsigned int FillStyle1) :
+ m_ID(ID), m_LineStyle(LineStyle), m_FillStyle0(FillStyle0), m_FillStyle1(FillStyle1) {};
+
+ unsigned int GetID() const { return m_ID; }
+ unsigned int GetLineStyle() const { return m_LineStyle; }
+ unsigned int GetFillStyle0() const { return m_FillStyle0; }
+ unsigned int GetFillStyle1() const { return m_FillStyle1; }
+
+private:
+ unsigned int m_ID;
+ unsigned int m_LineStyle;
+ unsigned int m_FillStyle0;
+ unsigned int m_FillStyle1;
+};
+
+
+/**
+ @brief Ein Element eines Vektorbild. Ein BS_VectorImage besteht aus diesen Elementen, die jeweils einen Teil der Graphik definieren.
+ Werden alle Elemente eines Vektorbildes übereinandergelegt, ergibt sich das komplette Bild.
+*/
+class BS_VectorImageElement
+{
+friend BS_VectorImage;
+public:
+ const agg::path_storage & GetPaths() const { return m_Paths; }
+ unsigned int GetPathCount() const { return m_PathInfos.size(); }
+ const BS_VectorPathInfo & GetPathInfo(unsigned int PathNr) const { BS_ASSERT(PathNr < GetPathCount()); return m_PathInfos[PathNr]; }
+
+ double GetLineStyleWidth(unsigned int LineStyle) const
+ {
+ BS_ASSERT(LineStyle < m_LineStyles.size());
+ return m_LineStyles[LineStyle].Width;
+ }
+
+ unsigned int GetLineStyleCount() const { return m_LineStyles.size(); }
+
+ const agg::rgba8 & GetLineStyleColor(unsigned int LineStyle) const
+ {
+ BS_ASSERT(LineStyle < m_LineStyles.size());
+ return m_LineStyles[LineStyle].Color;
+ }
+
+ unsigned int GetFillStyleCount() const { return m_FillStyles.size(); }
+
+ const agg::rgba8 & GetFillStyleColor(unsigned int FillStyle) const
+ {
+ BS_ASSERT(FillStyle < m_FillStyles.size());
+ return m_FillStyles[FillStyle];
+ }
+
+ const BS_Rect & GetBoundingBox() const { return m_BoundingBox; }
+
+private:
+ struct LineStyleType
+ {
+ LineStyleType(double Width_, const agg::rgba8 & Color_) : Width(Width_), Color(Color_) {};
+ double Width;
+ agg::rgba8 Color;
+ };
+
+ agg::path_storage m_Paths;
+ std::vector<BS_VectorPathInfo> m_PathInfos;
+ std::vector<LineStyleType> m_LineStyles;
+ std::vector<agg::rgba8> m_FillStyles;
+ BS_Rect m_BoundingBox;
+};
+
+
+/**
+ @brief Eine Vektorgraphik
+
+ Objekte dieser Klasse enthalten die Informationen eines SWF-Shapes.
+*/
+
+class BS_VectorImage : public BS_Image
+{
+public:
+ BS_VectorImage(const unsigned char * pFileData, unsigned int FileSize, bool & Success);
+
+ unsigned int GetElementCount() const { return m_Elements.size(); }
+ const BS_VectorImageElement & GetElement(unsigned int ElementNr) const
+ {
+ BS_ASSERT(ElementNr < m_Elements.size());
+ return m_Elements[ElementNr];
+ }
+ const BS_Rect & GetBoundingBox() const { return m_BoundingBox; }
+
+ //
+ // Die abstrakten Methoden von BS_Image
+ //
+ virtual int GetWidth() const { return m_BoundingBox.GetWidth(); }
+ virtual int GetHeight() const { return m_BoundingBox.GetHeight(); }
+ virtual BS_GraphicEngine::COLOR_FORMATS GetColorFormat() const { return BS_GraphicEngine::CF_ARGB32; }
+ virtual bool Fill(const BS_Rect* pFillRect = 0, unsigned int Color = BS_RGB(0, 0, 0));
+ virtual unsigned int GetPixel(int X, int Y);
+ virtual bool IsBlitSource() const { return true; }
+ virtual bool IsBlitTarget() const { return false; }
+ virtual bool IsScalingAllowed() const { return true; }
+ virtual bool IsFillingAllowed() const { return false; }
+ virtual bool IsAlphaAllowed() const { return true; }
+ virtual bool IsColorModulationAllowed() const { return true; }
+ virtual bool IsSetContentAllowed() const { return false; }
+ virtual bool SetContent(const std::vector<unsigned char> & Pixeldata, unsigned int Offset, unsigned int Stride);
+ virtual bool Blit(int PosX = 0, int PosY = 0,
+ int Flipping = FLIP_NONE,
+ BS_Rect* pPartRect = NULL,
+ unsigned int Color = BS_ARGB(255, 255, 255, 255),
+ int Width = -1, int Height = -1);
+
+ class SWFBitStream;
+
+private:
+ bool ParseDefineShape(unsigned int ShapeType, SWFBitStream & bs);
+ bool ParseStyles(unsigned int ShapeType, SWFBitStream & bs, unsigned int & NumFillBits, unsigned int & NumLineBits);
+
+ std::vector<BS_VectorImageElement> m_Elements;
+ BS_Rect m_BoundingBox;
+};
+
+#endif
diff --git a/engines/sword25/gfx/image/vectorimagerenderer.cpp b/engines/sword25/gfx/image/vectorimagerenderer.cpp
new file mode 100755
index 0000000000..76f2330a65
--- /dev/null
+++ b/engines/sword25/gfx/image/vectorimagerenderer.cpp
@@ -0,0 +1,198 @@
+// -----------------------------------------------------------------------------
+// This file is part of Broken Sword 2.5
+// Copyright (c) Malte Thiesen, Daniel Queteschiner and Michael Elsdörfer
+//
+// Broken Sword 2.5 is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// Broken Sword 2.5 is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Broken Sword 2.5; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+// -----------------------------------------------------------------------------
+
+// -----------------------------------------------------------------------------
+// Includes
+// -----------------------------------------------------------------------------
+
+#include "vectorimagerenderer.h"
+#include "vectorimage.h"
+#include "agg_conv_curve.h"
+#include "agg_path_storage.h"
+#include "agg_conv_stroke.h"
+
+
+// -----------------------------------------------------------------------------
+// CompoundShape
+// -----------------------------------------------------------------------------
+
+class CompoundShape
+{
+public:
+ CompoundShape(const BS_VectorImageElement & VectorImageElement) :
+ m_ImageElement(VectorImageElement),
+ m_Path(VectorImageElement.GetPaths()),
+ m_Affine(),
+ m_Curve(m_Path),
+ m_Trans(m_Curve, m_Affine)
+ {}
+
+ unsigned operator [] (unsigned i) const
+ {
+ return m_ImageElement.GetPathInfo(i).GetID();
+ }
+
+ unsigned paths() const { return m_ImageElement.GetPathCount(); }
+
+ void rewind(unsigned path_id)
+ {
+ m_Trans.rewind(path_id);
+ }
+
+ unsigned vertex(double* x, double* y)
+ {
+ return m_Trans.vertex(x, y);
+ }
+
+private:
+ const BS_VectorImageElement & m_ImageElement;
+ agg::path_storage m_Path;
+ agg::trans_affine m_Affine;
+ agg::conv_curve<agg::path_storage> m_Curve;
+ agg::conv_transform< agg::conv_curve<agg::path_storage> > m_Trans;
+};
+
+
+// -----------------------------------------------------------------------------
+// StyleHandler
+// -----------------------------------------------------------------------------
+
+class StyleHandler
+{
+public:
+ StyleHandler(const BS_VectorImageElement & VectorImageElement) : m_ImageElement(VectorImageElement) {}
+
+ bool is_solid(unsigned int style) const
+ {
+ return true;
+ }
+
+ const agg::rgba8 & color(unsigned style) const
+ {
+ return m_ImageElement.GetFillStyleColor(style);
+ }
+
+ void generate_span(agg::rgba8 * span, int x, int y, unsigned len, unsigned style)
+ {
+ // Wird nicht benutzt
+ return;
+ }
+
+private:
+ const BS_VectorImageElement & m_ImageElement;
+};
+
+
+// -----------------------------------------------------------------------------
+// Konstruktion
+// -----------------------------------------------------------------------------
+
+BS_VectorImageRenderer::BS_VectorImageRenderer() :
+ PixelFormat(rbuf)
+{
+
+}
+
+
+// -----------------------------------------------------------------------------
+
+bool BS_VectorImageRenderer::Render(const BS_VectorImage & VectorImage,
+ float ScaleFactorX, float ScaleFactorY,
+ unsigned int & Width, unsigned int & Height,
+ std::vector<char> & ImageData,
+ float LineScaleFactor,
+ bool NoAlphaShapes)
+{
+ Width = static_cast<unsigned int>(VectorImage.GetWidth() * ScaleFactorX);
+ Height = static_cast<unsigned int>(VectorImage.GetHeight() * ScaleFactorY);
+
+ ImageData.resize(Width * Height * 4);
+ memset(&ImageData[0], 0, ImageData.size());
+ rbuf.attach(reinterpret_cast<agg::int8u *>(&ImageData[0]), Width, Height, Width * 4);
+
+ BaseRenderer.attach(PixelFormat);
+ ScanlineRenderer.attach(BaseRenderer);
+
+ // Die SWF-Shapes sind häufig nicht am Ursprung (0, 0) ausgerichtet, daher wird die Shape vor dem Rendern derart verschoben, dass
+ // sich die linke obere Ecke der Bounding-Box im Ursprung befindet. Danach wird die Skalierung angewandt.
+ Scale = agg::trans_affine_translation(- VectorImage.GetBoundingBox().left, - VectorImage.GetBoundingBox().top);
+ Scale *= agg::trans_affine_scaling(ScaleFactorX, ScaleFactorY);
+
+ for (unsigned int element = 0; element < VectorImage.GetElementCount(); ++element)
+ {
+ const BS_VectorImageElement & CurImageElement = VectorImage.GetElement(element);
+
+ CompoundShape ImageCompoundShape(CurImageElement);
+ StyleHandler ImageStyleHandler(CurImageElement);
+ agg::conv_transform<CompoundShape> Shape(ImageCompoundShape, Scale);
+ agg::conv_stroke<agg::conv_transform<CompoundShape> > Stroke(Shape);
+
+ // Fill shape
+ //----------------------
+ CompoundRasterizer.clip_box(0, 0, Width, Height);
+ CompoundRasterizer.reset();
+ for(unsigned int i = 0; i < CurImageElement.GetPathCount(); ++i)
+ {
+ unsigned int FillStyle0 = CurImageElement.GetPathInfo(i).GetFillStyle0();
+ unsigned int FillStyle1 = CurImageElement.GetPathInfo(i).GetFillStyle1();
+
+ if (NoAlphaShapes)
+ {
+ if (FillStyle0 != 0 && CurImageElement.GetFillStyleColor(FillStyle0 - 1).a != 255) FillStyle0 = 0;
+ if (FillStyle1 != 0 && CurImageElement.GetFillStyleColor(FillStyle1 - 1).a != 255) FillStyle1 = 0;
+ }
+
+ if(FillStyle0 != 0 || FillStyle1 != 0)
+ {
+ CompoundRasterizer.styles(FillStyle0 - 1, FillStyle1 - 1);
+ CompoundRasterizer.add_path(Shape, CurImageElement.GetPathInfo(i).GetID());
+ }
+ }
+ agg::render_scanlines_compound_layered(CompoundRasterizer, Scanline, BaseRenderer, Alloc, ImageStyleHandler);
+
+
+ // Draw strokes
+ //----------------------
+ Rasterizer.clip_box(0, 0, Width, Height);
+ Stroke.line_join(agg::round_join);
+ Stroke.line_cap(agg::round_cap);
+ for(unsigned int i = 0; i < CurImageElement.GetPathCount(); ++i)
+ {
+ Rasterizer.reset();
+
+ unsigned int CurrentLineStyle = CurImageElement.GetPathInfo(i).GetLineStyle();
+ if (CurrentLineStyle != 0)
+ {
+ Stroke.width(ScaleFactorX * CurImageElement.GetLineStyleWidth(CurrentLineStyle - 1) * LineScaleFactor);
+ Rasterizer.add_path(Stroke, CurImageElement.GetPathInfo(i).GetID());
+ ScanlineRenderer.color(CurImageElement.GetLineStyleColor(CurrentLineStyle - 1));
+ // HACK
+ // Die SWF-Frames enthalten zum Teil Reste von grünen Linien, die wohl von Bernd als Umriss benutzt wurden.
+ // Damit diese Reste nicht störend auffallen werden grüne Linien schlichtweg ignoriert.
+ if (!(CurImageElement.GetLineStyleColor(CurrentLineStyle - 1).a == 255 &&
+ CurImageElement.GetLineStyleColor(CurrentLineStyle - 1).r == 0 &&
+ CurImageElement.GetLineStyleColor(CurrentLineStyle - 1).g == 255 &&
+ CurImageElement.GetLineStyleColor(CurrentLineStyle - 1).b == 0))
+ agg::render_scanlines(Rasterizer, Scanline, ScanlineRenderer);
+ }
+ }
+ }
+
+ return true;
+}
diff --git a/engines/sword25/gfx/image/vectorimagerenderer.h b/engines/sword25/gfx/image/vectorimagerenderer.h
new file mode 100755
index 0000000000..2dc29c480e
--- /dev/null
+++ b/engines/sword25/gfx/image/vectorimagerenderer.h
@@ -0,0 +1,76 @@
+// -----------------------------------------------------------------------------
+// This file is part of Broken Sword 2.5
+// Copyright (c) Malte Thiesen, Daniel Queteschiner and Michael Elsdörfer
+//
+// Broken Sword 2.5 is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// Broken Sword 2.5 is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Broken Sword 2.5; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+// -----------------------------------------------------------------------------
+
+#ifndef BS_VECTORIMAGERENDERER_H
+#define BS_VECTORIMAGERENDERER_H
+
+// -----------------------------------------------------------------------------
+// Includes
+// -----------------------------------------------------------------------------
+
+#include "kernel/common.h"
+#include <vector>
+
+#include "agg_rendering_buffer.h"
+#include "agg_pixfmt_rgba.h"
+#include "agg_renderer_scanline.h"
+#include "agg_rasterizer_scanline_aa.h"
+#include "agg_rasterizer_compound_aa.h"
+#include "agg_scanline_u.h"
+#include "agg_scanline_bin.h"
+#include "agg_trans_affine.h"
+#include "agg_span_allocator.h"
+
+class BS_VectorImage;
+
+
+/**
+ @brief Rendert BS_VectorImage Objekte
+*/
+
+class BS_VectorImageRenderer
+{
+public:
+ BS_VectorImageRenderer();
+
+ bool Render(const BS_VectorImage & VectorImage,
+ float ScaleFactorX, float ScaleFactorY,
+ unsigned int & Width, unsigned int & Height,
+ std::vector<char> & ImageData,
+ float LineScaleFactor = 1.0f,
+ bool NoAlphaShapes = false);
+
+private:
+ typedef agg::pixfmt_rgba32_pre PixelFormatType;
+ typedef agg::renderer_base<PixelFormatType> BaseRendererType;
+ typedef agg::renderer_scanline_aa_solid<BaseRendererType> ScanlineRendererType;
+
+ agg::rendering_buffer rbuf;
+ PixelFormatType PixelFormat;
+ BaseRendererType BaseRenderer;
+ ScanlineRendererType ScanlineRenderer;
+ agg::rasterizer_scanline_aa<agg::rasterizer_sl_clip_dbl> Rasterizer;
+ agg::rasterizer_compound_aa<agg::rasterizer_sl_clip_dbl> CompoundRasterizer;
+ agg::scanline_u8 Scanline;
+ agg::scanline_bin ScanlineBin;
+ agg::trans_affine Scale;
+ agg::span_allocator<agg::rgba8> Alloc;
+};
+
+#endif