diff options
Diffstat (limited to 'src/XPM.cxx')
-rw-r--r-- | src/XPM.cxx | 135 |
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; +} |