aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/XPM.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'src/XPM.cxx')
-rw-r--r--src/XPM.cxx135
1 files changed, 130 insertions, 5 deletions
diff --git a/src/XPM.cxx b/src/XPM.cxx
index d1389efa0..6c615dd94 100644
--- a/src/XPM.cxx
+++ b/src/XPM.cxx
@@ -8,6 +8,13 @@
#include <string.h>
#include <stdlib.h>
+#ifdef _MSC_VER
+#pragma warning(disable: 4786)
+#endif
+
+#include <vector>
+#include <map>
+
#include "Platform.h"
#include "XPM.h"
@@ -38,6 +45,10 @@ static size_t MeasureLength(const char *s) {
return i;
}
+ColourDesired XPM::ColourDesiredFromCode(int ch) const {
+ return colourCodeTable[ch]->desired;
+}
+
ColourAllocated XPM::ColourFromCode(int ch) const {
return colourCodeTable[ch]->allocated;
#ifdef SLOW
@@ -200,6 +211,21 @@ void XPM::Draw(Surface *surface, PRectangle &rc) {
}
}
+void XPM::PixelAt(int x, int y, ColourDesired &colour, bool &transparent) const {
+ if (!data || !codes || !colours || !lines || (x<0) || (x >= width) || (y<0) || (y >= height)) {
+ colour = 0;
+ transparent = true;
+ return;
+ }
+ int code = lines[y+nColours+1][x];
+ transparent = code == codeTransparent;
+ if (transparent) {
+ colour = 0;
+ } else {
+ colour = ColourDesiredFromCode(code).AsLong();
+ }
+}
+
const char **XPM::LinesFormFromTextForm(const char *textForm) {
// Build the lines form out of the text form
const char **linesForm = 0;
@@ -261,14 +287,14 @@ void XPMSet::Clear() {
width = -1;
}
-void XPMSet::Add(int id, const char *textForm) {
+void XPMSet::Add(int ident, const char *textForm) {
// Invalidate cached dimensions
height = -1;
width = -1;
// Replace if this id already present
for (int i = 0; i < len; i++) {
- if (set[i]->GetId() == id) {
+ if (set[i]->GetId() == ident) {
set[i]->Init(textForm);
set[i]->CopyDesiredColours();
return;
@@ -278,7 +304,7 @@ void XPMSet::Add(int id, const char *textForm) {
// Not present, so add to end
XPM *pxpm = new XPM(textForm);
if (pxpm) {
- pxpm->SetId(id);
+ pxpm->SetId(ident);
pxpm->CopyDesiredColours();
if (len == maximum) {
maximum += 64;
@@ -294,9 +320,9 @@ void XPMSet::Add(int id, const char *textForm) {
}
}
-XPM *XPMSet::Get(int id) {
+XPM *XPMSet::Get(int ident) {
for (int i = 0; i < len; i++) {
- if (set[i]->GetId() == id) {
+ if (set[i]->GetId() == ident) {
return set[i];
}
}
@@ -324,3 +350,102 @@ int XPMSet::GetWidth() {
}
return (width > 0) ? width : 0;
}
+
+RGBAImage::RGBAImage(int width_, int height_, const unsigned char *pixels_) :
+ height(height_), width(width_) {
+ pixelBytes.assign(pixels_, pixels_ + CountBytes());
+}
+
+RGBAImage::RGBAImage(const XPM &xpm) {
+ height = xpm.GetHeight();
+ width = xpm.GetWidth();
+ pixelBytes.resize(CountBytes());
+ for (int y=0; y<height; y++) {
+ for (int x=0; x<width; x++) {
+ ColourDesired colour;
+ bool transparent = false;
+ xpm.PixelAt(x, y, colour, transparent);
+ unsigned char *pixel = &pixelBytes[0] + (y*width+x) * 4;
+ // RGBA
+ pixel[0] = colour.GetRed();
+ pixel[1] = colour.GetGreen();
+ pixel[2] = colour.GetBlue();
+ pixel[3] = transparent ? 0 : 255;
+ }
+ }
+}
+
+RGBAImage::~RGBAImage() {
+}
+
+int RGBAImage::CountBytes() const {
+ return width * height * 4;
+}
+
+const unsigned char *RGBAImage::Pixels() const {
+ return &pixelBytes[0];
+}
+
+RGBAImageSet::RGBAImageSet() : height(-1), width(-1){
+}
+
+RGBAImageSet::~RGBAImageSet() {
+ Clear();
+}
+
+/// Remove all images.
+void RGBAImageSet::Clear() {
+ for (ImageMap::iterator it=images.begin(); it != images.end(); ++it) {
+ delete it->second;
+ it->second = 0;
+ }
+ images.clear();
+ height = -1;
+ width = -1;
+}
+
+/// Add an image.
+void RGBAImageSet::Add(int ident, RGBAImage *image) {
+ ImageMap::iterator it=images.find(ident);
+ if (it == images.end()) {
+ images[ident] = image;
+ } else {
+ delete it->second;
+ it->second = image;
+ }
+ height = -1;
+ width = -1;
+}
+
+/// Get image by id.
+RGBAImage *RGBAImageSet::Get(int ident) {
+ ImageMap::iterator it = images.find(ident);
+ if (it != images.end()) {
+ return it->second;
+ }
+ return NULL;
+}
+
+/// Give the largest height of the set.
+int RGBAImageSet::GetHeight() const {
+ if (height < 0) {
+ for (ImageMap::const_iterator it=images.begin(); it != images.end(); ++it) {
+ if (height < it->second->GetHeight()) {
+ height = it->second->GetHeight();
+ }
+ }
+ }
+ return (height > 0) ? height : 0;
+}
+
+/// Give the largest width of the set.
+int RGBAImageSet::GetWidth() const {
+ if (width < 0) {
+ for (ImageMap::const_iterator it=images.begin(); it != images.end(); ++it) {
+ if (width < it->second->GetWidth()) {
+ width = it->second->GetWidth();
+ }
+ }
+ }
+ return (width > 0) ? width : 0;
+}