diff --git a/BBGE/glfont2.cpp b/BBGE/glfont2.cpp deleted file mode 100644 index 3f34acb..0000000 --- a/BBGE/glfont2.cpp +++ /dev/null @@ -1,319 +0,0 @@ -//******************************************************************* -//glfont2.cpp -- glFont Version 2.0 implementation -//Copyright (c) 1998-2002 Brad Fish -//See glfont.html for terms of use -//May 14, 2002 -//******************************************************************* - -//STL headers -#include -#include -#include -#include -using namespace std; - -//OpenGL headers -/* -#ifdef _WINDOWS -#include -#endif -#include -*/ -#include "Base.h" - -#include "SDL_endian.h" - -//glFont header -#include "glfont2.h" -using namespace glfont; - -static int read_int(ifstream &input) -{ - int buffer; - - input.read((char *)&buffer, 4); - return SDL_SwapLE32(buffer); -} - -static float read_float(ifstream &input) -{ - union - { - int i; - float f; - } buffer; - - input.read((char *)&buffer.i, 4); - buffer.i = SDL_SwapLE32(buffer.i); - return buffer.f; -} - -//******************************************************************* -//GLFont Class Implementation -//******************************************************************* -GLFont::GLFont () -{ - //Initialize header to safe state - header.tex = -1; - header.tex_width = 0; - header.tex_height = 0; - header.start_char = 0; - header.end_char = 0; - header.chars = NULL; -} -//******************************************************************* -GLFont::~GLFont () -{ - //Destroy the font - Destroy(); -} -//******************************************************************* -bool GLFont::Create (const char *file_name, int tex, bool loadTexture) -{ - ifstream input; - int num_chars, num_tex_bytes; - char *tex_bytes; - - //Destroy the old font if there was one, just to be safe - Destroy(); - - //Open input file - input.open(file_name, ios::in | ios::binary); - if (!input) - return false; - - // Read the header from file - header.tex = tex; - input.seekg(4, ios::cur); // skip tex field - header.tex_width = read_int(input); - header.tex_height = read_int(input); - header.start_char = read_int(input); - header.end_char = read_int(input); - input.seekg(4, ios::cur); // skip chars field - - std::ostringstream os; - os << "tex_width: " << header.tex_width << " tex_height: " << header.tex_height; - debugLog(os.str()); - - //Allocate space for character array - num_chars = header.end_char - header.start_char + 1; - if ((header.chars = new GLFontChar[num_chars]) == NULL) - return false; - - //Read character array - for (int i = 0; i < num_chars; i++) - { - header.chars[i].dx = read_float(input); - header.chars[i].dy = read_float(input); - header.chars[i].tx1 = read_float(input); - header.chars[i].ty1 = read_float(input); - header.chars[i].tx2 = read_float(input); - header.chars[i].ty2 = read_float(input); - } - - //Read texture pixel data - num_tex_bytes = header.tex_width * header.tex_height * 2; - tex_bytes = new char[num_tex_bytes]; - input.read(tex_bytes, num_tex_bytes); - - - //Build2DMipmaps(3, header.tex_width, header.tex_height, GL_UNSIGNED_BYTE, tex_bytes, 1); - - if (loadTexture) - { -#ifdef BBGE_BUILD_OPENGL - glBindTexture(GL_TEXTURE_2D, tex); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - - //glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - glTexImage2D(GL_TEXTURE_2D, 0, 2, header.tex_width, - header.tex_height, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, - (void *)tex_bytes); - //gluBuild2DMipmaps(GL_TEXTURE_2D, 2, header.tex_width, header.tex_height, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, (void*)tex_bytes); - //Build2DMipmaps(3, header.tex_width, header.tex_height, GL_LUMINANCE_ALPHA, tex_bytes, 1); - //Create OpenGL texture - /* - glBindTexture(GL_TEXTURE_2D, tex); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - //glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - - */ -#endif - } - - //Free texture pixels memory - delete[] tex_bytes; - - //Close input file - input.close(); - - //Return successfully - return true; -} -//******************************************************************* -bool GLFont::Create (const std::string &file_name, int tex, bool loadTexture) -{ - return Create(file_name.c_str(), tex); -} -//******************************************************************* -void GLFont::Destroy (void) -{ - //Delete the character array if necessary - if (header.chars) - { - delete[] header.chars; - header.chars = NULL; - } -} -//******************************************************************* -void GLFont::GetTexSize (std::pair *size) -{ - //Retrieve texture size - size->first = header.tex_width; - size->second = header.tex_height; -} -//******************************************************************* -int GLFont::GetTexWidth (void) -{ - //Return texture width - return header.tex_width; -} -//******************************************************************* -int GLFont::GetTexHeight (void) -{ - //Return texture height - return header.tex_height; -} -//******************************************************************* -void GLFont::GetCharInterval (std::pair *interval) -{ - //Retrieve character interval - interval->first = header.start_char; - interval->second = header.end_char; -} -//******************************************************************* -int GLFont::GetStartChar (void) -{ - //Return start character - return header.start_char; -} -//******************************************************************* -int GLFont::GetEndChar (void) -{ - //Return end character - return header.end_char; -} -//******************************************************************* -void GLFont::GetCharSize (int c, std::pair *size) -{ - //Make sure character is in range - if (c < header.start_char || c > header.end_char) - { - //Not a valid character, so it obviously has no size - size->first = 0; - size->second = 0; - } - else - { - GLFontChar *glfont_char; - - //Retrieve character size - glfont_char = &header.chars[c - header.start_char]; - size->first = (int)(glfont_char->dx * header.tex_width); - size->second = (int)(glfont_char->dy * - header.tex_height); - } -} -//******************************************************************* -int GLFont::GetCharWidth (int c) -{ - //Make sure in range - if (c < header.start_char || c > header.end_char) - return 0; - else - { - GLFontChar *glfont_char; - - //Retrieve character width - glfont_char = &header.chars[c - header.start_char]; - - // hack to fix empty spaces - if (c == ' ' && glfont_char->dx <= 0) - { - GLFontChar *glfont_a = &header.chars['a' - header.start_char]; - glfont_char->dx = glfont_a->dx*0.75; - glfont_char->dy = glfont_a->dy; - } - - return (int)(glfont_char->dx * header.tex_width); - } -} -//******************************************************************* -int GLFont::GetCharHeight (int c) -{ - //Make sure in range - if (c < header.start_char || c > header.end_char) - return 0; - else - { - GLFontChar *glfont_char; - - //Retrieve character height - glfont_char = &header.chars[c - header.start_char]; - return (int)(glfont_char->dy * header.tex_height); - } -} -//******************************************************************* -void GLFont::Begin (void) -{ -#ifdef BBGE_BUILD_OPENGL - //Bind to font texture - glBindTexture(GL_TEXTURE_2D, header.tex); -#endif -} -//******************************************************************* -void GLFont::GetStringSize (const std::string &text, std::pair *size) -{ - unsigned int i; - char c; - GLFontChar *glfont_char; - float width; - - //debugLog("size->second"); - //Height is the same for now...might change in future - size->second = (int)(header.chars[header.start_char].dy * - header.tex_height); - - //Calculate width of string - width = 0.0F; - for (i = 0; i < text.size(); i++) - { - //Make sure character is in range - c = (char)text[i]; - - if (c < header.start_char || c > header.end_char) - continue; - - //Get pointer to glFont character - glfont_char = &header.chars[c - header.start_char]; - - //Get width and height - width += glfont_char->dx * header.tex_width; - } - - //Save width - //debugLog("size first"); - size->first = (int)width; - - //debugLog("done"); -} - -//End of file - - diff --git a/BBGE/glfont2.h b/BBGE/glfont2.h deleted file mode 100644 index c56fb5c..0000000 --- a/BBGE/glfont2.h +++ /dev/null @@ -1,146 +0,0 @@ -//******************************************************************* -//glfont2.h -- Header for glfont2.cpp -//Copyright (c) 1998-2002 Brad Fish -//See glfont.html for terms of use -//May 14, 2002 -//******************************************************************* - -#ifndef GLFONT2_H -#define GLFONT2_H - -#include - -//******************************************************************* -//GLFont Interface -//******************************************************************* - -//glFont namespace -namespace glfont -{ - class GLFont; -} - -//glFont class -class glfont::GLFont -{ -private: - - //glFont character structure - typedef struct - { - float dx, dy; - float tx1, ty1; - float tx2, ty2; - } GLFontChar; - - //glFont header structure - struct - { - int tex; - int tex_width, tex_height; - int start_char, end_char; - GLFontChar *chars; - } header; - -public: - - //Constructor - GLFont (); - - //Destructor - ~GLFont (); - -public: - - //Creates the glFont - bool Create (const char *file_name, int tex, bool loadTexture=true); - bool Create (const std::string &file_name, int tex, bool loadTexture=true); - - //Destroys the glFont - void Destroy (void); - - //Texture size retrieval methods - void GetTexSize (std::pair *size); - int GetTexWidth (void); - int GetTexHeight (void); - - //Character interval retrieval methods - void GetCharInterval (std::pair *interval); - int GetStartChar (void); - int GetEndChar (void); - - //Character size retrieval methods - void GetCharSize (int c, std::pair *size); - int GetCharWidth (int c); - int GetCharHeight (int c); - - void GetStringSize (const std::string &text, std::pair *size); - - - //Begins text output with this font - void Begin (void); - - //Template function to output a scaled, colored std::basic_string - template void DrawString ( - const std::basic_string &text, float scalar, float x, - float y, const float *top_color, const float *bottom_color, float alpha, float lastAlpha) - { - unsigned int i; - T c; - GLFontChar *glfont_char; - float width, height; - - //Begin rendering quads - glBegin(GL_QUADS); - - int sz = text.size(); - - float a = 0; - //Loop through characters - for (i = 0; i < sz; i++) - { - //Make sure character is in range - c = text[i]; - if (c < header.start_char || c > header.end_char) - continue; - - //Get pointer to glFont character - glfont_char = &header.chars[c - header.start_char]; - - //Get width and height - width = (glfont_char->dx * header.tex_width) * scalar; - height = (glfont_char->dy * header.tex_height) * scalar; - - if (i == (sz-1)) - a = alpha*lastAlpha; - else - a = alpha; - - //Specify colors, vertices, and texture coordinates - glColor4f(top_color[0], top_color[1], top_color[2], a); - glTexCoord2f(glfont_char->tx1, glfont_char->ty1); - glVertex3f(x, y, 0.0F); - glTexCoord2f(glfont_char->tx2, glfont_char->ty1); - glVertex3f(x + width, y, 0.0F); - glColor4f(bottom_color[0], bottom_color[1], bottom_color[2], a); - glTexCoord2f(glfont_char->tx2, glfont_char->ty2); - glVertex3f(x + width, y + height, 0.0F); - glTexCoord2f(glfont_char->tx1, glfont_char->ty2); - glVertex3f(x, y + height, 0.0F); - - //Move to next character - x += width; - } - - //Stop rendering quads - glEnd(); - } -}; - -//******************************************************************* - -#endif - -//End of file - - diff --git a/BBGE/ByteBuffer.h b/ExternalLibs/ByteBuffer.h similarity index 95% rename from BBGE/ByteBuffer.h rename to ExternalLibs/ByteBuffer.h index b82a58c..e5b6ed6 100644 --- a/BBGE/ByteBuffer.h +++ b/ExternalLibs/ByteBuffer.h @@ -1,17 +1,24 @@ #ifndef BYTEBUFFER_H #define BYTEBUFFER_H +#include #include // for memcpy +#include +#include // ** compatibility stuff for BBGE .... ** -#include "Base.h" #define BYTEBUFFER_NO_EXCEPTIONS -#if (defined(BBGE_BUILD_SDL) && (SDL_BYTEORDER == SDL_BIG_ENDIAN)) -# define BB_IS_BIG_ENDIAN +// from SDL headers +#if defined(__hppa__) || \ + defined(__m68k__) || defined(mc68000) || defined(_M_M68K) || \ + (defined(__MIPS__) && defined(__MISPEB__)) || \ + defined(__ppc__) || defined(__POWERPC__) || defined(_M_PPC) || \ + defined(__sparc__) +#define BB_IS_BIG_ENDIAN 1 #endif // **** @@ -98,9 +105,9 @@ public: }; #ifdef BYTEBUFFER_NO_EXCEPTIONS -#define BYTEBUFFER_EXCEPT(bb, desc, sz) { Exception __e(bb, desc, sz); char errbuf[256]; \ - sprintf(errbuf, "Exception in ByteBuffer: '%s', rpos: %u, wpos: %u, cursize: %u, sizeparam: %u", \ - __e.action, __e.rpos, __e.wpos, __e.cursize, __e.sizeparam); errorLog(errbuf); abort(); } +#define BYTEBUFFER_EXCEPT(bb, desc, sz) { Exception __e(bb, desc, sz); \ + fprintf(stderr, "Exception in ByteBuffer: '%s', rpos: %u, wpos: %u, cursize: %u, sizeparam: %u", \ + __e.action, __e.rpos, __e.wpos, __e.cursize, __e.sizeparam); abort(); } #else #define BYTEBUFFER_EXCEPT(bb, desc, sz) throw Exception(bb, desc, sz) #endif diff --git a/BBGE/DeflateCompressor.cpp b/ExternalLibs/DeflateCompressor.cpp similarity index 88% rename from BBGE/DeflateCompressor.cpp rename to ExternalLibs/DeflateCompressor.cpp index 012148e..7d79ccc 100644 --- a/BBGE/DeflateCompressor.cpp +++ b/ExternalLibs/DeflateCompressor.cpp @@ -1,4 +1,3 @@ -#include "Base.h" #include @@ -7,6 +6,8 @@ // for weird gcc/mingw hackfix below #include +#define PRINTFAIL(s, ...) fprintf(stderr, (s "\n"), __VA_ARGS__) + DeflateCompressor::DeflateCompressor() : _windowBits(-MAX_WBITS), // negative, because we want a raw deflate stream, and not zlib-wrapped @@ -49,30 +50,25 @@ void DeflateCompressor::compress(void* dst, uint32 *dst_size, const void* src, u c_stream.next_in = (Bytef*)src; c_stream.avail_in = (uInt)src_size; - if (Z_OK != deflate(&c_stream, Z_NO_FLUSH)) - { - errorLog("ZLIB: Can't compress (zlib: deflate)"); - *dst_size = 0; - return; - } + int ret = deflate(&c_stream, Z_FINISH); - if (c_stream.avail_in != 0) + switch(ret) { - errorLog("Can't compress (zlib: deflate not greedy)"); - *dst_size = 0; - return; - } - - if (Z_STREAM_END != deflate(&c_stream, Z_FINISH)) - { - errorLog("Can't compress (zlib: deflate, finish)"); - *dst_size = 0; - return; + case Z_STREAM_END: + break; // all good + case Z_OK: + PRINTFAIL("ZLIB: Output buffer not large enough"); + *dst_size = 0; + return; + default: + PRINTFAIL("ZLIB: Error %d", ret); + *dst_size = 0; + return; } if (Z_OK != deflateEnd(&c_stream)) { - errorLog("Can't compress (zlib: deflateEnd)"); + PRINTFAIL("Can't compress (zlib: deflateEnd)"); *dst_size = 0; return; } @@ -167,9 +163,7 @@ void DeflateCompressor::Decompress(void) decompress((void*)target, &origsize, (const void*)contents(), size(), _windowBits); if(origsize != rs) { - char errbuf[256]; - sprintf(errbuf, "DeflateCompressor: Inflate error! cursize=%u origsize=%u realsize=%u",size(),origsize,rs); - errorLog(errbuf); + PRINTFAIL("DeflateCompressor: Inflate error! cursize=%u origsize=%u realsize=%u",size(),origsize,rs); delete [] target; return; } @@ -178,7 +172,7 @@ void DeflateCompressor::Decompress(void) delete [] target; _real_size = 0; _iscompressed = false; - } + } } @@ -216,6 +210,7 @@ int DeflateCompressor::decompressBlockwise() switch (ret) { case Z_NEED_DICT: case Z_STREAM_ERROR: + case Z_BUF_ERROR: ret = Z_DATA_ERROR; /* and fall through */ case Z_DATA_ERROR: case Z_MEM_ERROR: diff --git a/BBGE/DeflateCompressor.h b/ExternalLibs/DeflateCompressor.h similarity index 93% rename from BBGE/DeflateCompressor.h rename to ExternalLibs/DeflateCompressor.h index 1b97d14..98866ba 100644 --- a/BBGE/DeflateCompressor.h +++ b/ExternalLibs/DeflateCompressor.h @@ -8,13 +8,13 @@ class DeflateCompressor : public ByteBuffer { public: DeflateCompressor(); - DeflateCompressor(void *buf, uint32 size, Mode mode = COPY, delete_func del = NULL, uint32 extra = 0); virtual ~DeflateCompressor() {} virtual void Compress(uint8 level = 1); virtual void Decompress(void); bool Compressed(void) const { return _iscompressed; } void Compressed(bool b) { _iscompressed = b; } + void SetForceCompression(bool f) { _forceCompress = f; } uint32 RealSize(void) const { return _iscompressed ? _real_size : size(); } void RealSize(uint32 realsize) { _real_size = realsize; } void clear(void) // not required to be strictly virtual; be careful not to mess up static types! diff --git a/ExternalLibs/glfont2/glfont2.cpp b/ExternalLibs/glfont2/glfont2.cpp index fa9a2c1..6c59e26 100644 --- a/ExternalLibs/glfont2/glfont2.cpp +++ b/ExternalLibs/glfont2/glfont2.cpp @@ -7,9 +7,8 @@ //STL headers #include -#include -#include -#include +#include "FileAPI.h" +#include "ByteBuffer.h" using namespace std; //OpenGL headers @@ -22,33 +21,10 @@ using namespace std; #include "GL/gl.h" -#include "SDL_endian.h" - //glFont header #include "glfont2.h" using namespace glfont; -static int read_int(ifstream &input) -{ - int buffer; - - input.read((char *)&buffer, 4); - return SDL_SwapLE32(buffer); -} - -static float read_float(ifstream &input) -{ - union - { - int i; - float f; - } buffer; - - input.read((char *)&buffer.i, 4); - buffer.i = SDL_SwapLE32(buffer.i); - return buffer.f; -} - //******************************************************************* //GLFont Class Implementation //******************************************************************* @@ -71,27 +47,44 @@ GLFont::~GLFont () //******************************************************************* bool GLFont::Create (const char *file_name, int tex, bool loadTexture) { - ifstream input; int num_chars, num_tex_bytes; char *tex_bytes; //Destroy the old font if there was one, just to be safe Destroy(); + +#ifdef BBGE_BUILD_VFS //Open input file - input.open(file_name, ios::in | ios::binary); - if (!input) + ttvfs::VFSFile *vf = vfs.GetFile(file_name); + if (!vf) return false; + ByteBuffer bb((void*)vf->getBuf(), vf->size(), ByteBuffer::TAKE_OVER); + vf->dropBuf(false); +#else + VFILE *fh = vfopen(file_name, "rb"); + if (!fh) + return false; + vfseek(fh, 0, SEEK_END); + long int sz = vftell(fh); + vfseek(fh, 0, SEEK_SET); + ByteBuffer bb(sz); + bb.resize(sz); + vfread(bb.contents(), 1, sz, fh); + vfclose(fh); +#endif + + int dummy; // Read the header from file header.tex = tex; - input.seekg(4, ios::cur); // skip tex field - header.tex_width = read_int(input); - header.tex_height = read_int(input); - header.start_char = read_int(input); - header.end_char = read_int(input); - input.seekg(4, ios::cur); // skip chars field - + bb >> dummy; // skip tex field + bb >> header.tex_width; + bb >> header.tex_height; + bb >> header.start_char; + bb >> header.end_char; + bb >> dummy; // skip chars field + //Allocate space for character array num_chars = header.end_char - header.start_char + 1; if ((header.chars = new GLFontChar[num_chars]) == NULL) @@ -100,19 +93,19 @@ bool GLFont::Create (const char *file_name, int tex, bool loadTexture) //Read character array for (int i = 0; i < num_chars; i++) { - header.chars[i].dx = read_float(input); - header.chars[i].dy = read_float(input); - header.chars[i].tx1 = read_float(input); - header.chars[i].ty1 = read_float(input); - header.chars[i].tx2 = read_float(input); - header.chars[i].ty2 = read_float(input); + bb >> header.chars[i].dx; + bb >> header.chars[i].dy; + bb >> header.chars[i].tx1; + bb >> header.chars[i].ty1; + bb >> header.chars[i].tx2; + bb >> header.chars[i].ty2; } //Read texture pixel data num_tex_bytes = header.tex_width * header.tex_height * 2; tex_bytes = new char[num_tex_bytes]; - input.read(tex_bytes, num_tex_bytes); - + //input.read(tex_bytes, num_tex_bytes); + bb.read(tex_bytes, num_tex_bytes); //Build2DMipmaps(3, header.tex_width, header.tex_height, GL_UNSIGNED_BYTE, tex_bytes, 1); @@ -147,9 +140,6 @@ bool GLFont::Create (const char *file_name, int tex, bool loadTexture) //Free texture pixels memory delete[] tex_bytes; - //Close input file - input.close(); - //Return successfully return true; } diff --git a/ExternalLibs/glpng.h b/ExternalLibs/glpng.h index ad8e522..59a454b 100644 --- a/ExternalLibs/glpng.h +++ b/ExternalLibs/glpng.h @@ -97,9 +97,11 @@ extern int APIENTRY pngLoadRawF(FILE *file, pngRawInfo *rawinfo); extern int APIENTRY pngLoad(const char *filename, int mipmap, int trans, pngInfo *info); extern int APIENTRY pngLoadF(FILE *file, int mipmap, int trans, pngInfo *info); +extern int APIENTRY pngLoadMem(const char *mem, int size, int mipmap, int trans, pngInfo *info); extern unsigned int APIENTRY pngBind(const char *filename, int mipmap, int trans, pngInfo *info, int wrapst, int minfilter, int magfilter); extern unsigned int APIENTRY pngBindF(FILE *file, int mipmap, int trans, pngInfo *info, int wrapst, int minfilter, int magfilter); +extern unsigned int APIENTRY pngBindMem(const char *mem, int size, int mipmap, int trans, pngInfo *info, int wrapst, int minfilter, int magfilter); extern void APIENTRY pngSetStencil(unsigned char red, unsigned char green, unsigned char blue); extern void APIENTRY pngSetAlphaCallback(unsigned char (*callback)(unsigned char red, unsigned char green, unsigned char blue)); diff --git a/ExternalLibs/glpng/glpng.c b/ExternalLibs/glpng/glpng.c index 636670f..b828dd1 100644 --- a/ExternalLibs/glpng/glpng.c +++ b/ExternalLibs/glpng/glpng.c @@ -1,29 +1,29 @@ /* - * PNG loader library for OpenGL v1.45 (10/07/00) - * by Ben Wyatt ben@wyatt100.freeserve.co.uk - * Using LibPNG 1.0.2 and ZLib 1.1.3 - * - * This software is provided 'as-is', without any express or implied warranty. - * In no event will the author be held liable for any damages arising from the - * use of this software. - * - * Permission is hereby granted to use, copy, modify, and distribute this - * source code, or portions hereof, for any purpose, without fee, subject to - * the following restrictions: - * - * 1. The origin of this source code must not be misrepresented. You must not - * claim that you wrote the original software. If you use this software in - * a product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered versions must be plainly marked as such and must not be - * misrepresented as being the original source. - * 3. This notice must not be removed or altered from any source distribution. - */ +* PNG loader library for OpenGL v1.45 (10/07/00) +* by Ben Wyatt ben@wyatt100.freeserve.co.uk +* Using LibPNG 1.0.2 and ZLib 1.1.3 +* +* This software is provided 'as-is', without any express or implied warranty. +* In no event will the author be held liable for any damages arising from the +* use of this software. +* +* Permission is hereby granted to use, copy, modify, and distribute this +* source code, or portions hereof, for any purpose, without fee, subject to +* the following restrictions: +* +* 1. The origin of this source code must not be misrepresented. You must not +* claim that you wrote the original software. If you use this software in +* a product, an acknowledgment in the product documentation would be +* appreciated but is not required. +* 2. Altered versions must be plainly marked as such and must not be +* misrepresented as being the original source. +* 3. This notice must not be removed or altered from any source distribution. +*/ #ifdef _WIN32 /* Stupid Windows needs to include windows.h before gl.h */ - #undef FAR - #include +#undef FAR +#include #endif #include "../glpng.h" @@ -55,17 +55,17 @@ static int PalettedTextures = -1; static GLint MaxTextureSize = 0; /* screenGamma = displayGamma/viewingGamma - * displayGamma = CRT has gamma of ~2.2 - * viewingGamma depends on platform. PC is 1.0, Mac is 1.45, SGI defaults - * to 1.7, but this can be checked and changed w/ /usr/sbin/gamma command. - * If the environment variable VIEWING_GAMMA is set, adjust gamma per this value. - */ +* displayGamma = CRT has gamma of ~2.2 +* viewingGamma depends on platform. PC is 1.0, Mac is 1.45, SGI defaults +* to 1.7, but this can be checked and changed w/ /usr/sbin/gamma command. +* If the environment variable VIEWING_GAMMA is set, adjust gamma per this value. +*/ #ifdef _MAC - static double screenGamma = 2.2 / 1.45; +static double screenGamma = 2.2 / 1.45; #elif SGI - static double screenGamma = 2.2 / 1.7; +static double screenGamma = 2.2 / 1.7; #else /* PC/default */ - static double screenGamma = 2.2 / 1.0; +static double screenGamma = 2.2 / 1.0; #endif static char gammaExplicit = 0; /*if */ @@ -259,8 +259,8 @@ int APIENTRY pngLoadRawF(FILE *fp, pngRawInfo *pinfo) { png_infop info; png_infop endinfo; png_bytep data; - png_bytep *row_p; - double fileGamma; + png_bytep *row_p; + double fileGamma; png_uint_32 width, height; int depth, color; @@ -365,8 +365,8 @@ int APIENTRY pngLoadF(FILE *fp, int mipmap, int trans, pngInfo *pinfo) { png_infop info; png_infop endinfo; png_bytep data, data2; - png_bytep *row_p; - double fileGamma; + png_bytep *row_p; + double fileGamma; png_uint_32 width, height, rw, rh; int depth, color; @@ -402,20 +402,20 @@ int APIENTRY pngLoadF(FILE *fp, int mipmap, int trans, pngInfo *pinfo) { if (MaxTextureSize == 0) glGetIntegerv(GL_MAX_TEXTURE_SIZE, &MaxTextureSize); - #ifdef SUPPORTS_PALETTE_EXT - #ifdef _WIN32 - if (PalettedTextures == -1) - PalettedTextures = ExtSupported("GL_EXT_paletted_texture") && (strstr((const char *) glGetString(GL_VERSION), "1.1.0 3Dfx Beta") == NULL); +#ifdef SUPPORTS_PALETTE_EXT +#ifdef _WIN32 + if (PalettedTextures == -1) + PalettedTextures = ExtSupported("GL_EXT_paletted_texture") && (strstr((const char *) glGetString(GL_VERSION), "1.1.0 3Dfx Beta") == NULL); - if (PalettedTextures) { - if (glColorTableEXT == NULL) { - glColorTableEXT = (PFNGLCOLORTABLEEXTPROC) wglGetProcAddress("glColorTableEXT"); - if (glColorTableEXT == NULL) - PalettedTextures = 0; - } + if (PalettedTextures) { + if (glColorTableEXT == NULL) { + glColorTableEXT = (PFNGLCOLORTABLEEXTPROC) wglGetProcAddress("glColorTableEXT"); + if (glColorTableEXT == NULL) + PalettedTextures = 0; } - #endif - #endif + } +#endif +#endif if (PalettedTextures == -1) PalettedTextures = 0; @@ -461,10 +461,10 @@ int APIENTRY pngLoadF(FILE *fp, int mipmap, int trans, pngInfo *pinfo) { data2 = (png_bytep) malloc(rw*rh*channels); - /* Doesn't work on certain sizes */ -/* if (gluScaleImage(glformat, width, height, GL_UNSIGNED_BYTE, data, rw, rh, GL_UNSIGNED_BYTE, data2) != 0) - return 0; -*/ + /* Doesn't work on certain sizes */ + /* if (gluScaleImage(glformat, width, height, GL_UNSIGNED_BYTE, data, rw, rh, GL_UNSIGNED_BYTE, data2) != 0) + return 0; + */ Resize(channels, data, width, height, data2, rw, rh); width = rw, height = rh; @@ -478,7 +478,7 @@ int APIENTRY pngLoadF(FILE *fp, int mipmap, int trans, pngInfo *pinfo) { glPixelStorei(GL_PACK_ALIGNMENT, 1); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - #ifdef SUPPORTS_PALETTE_EXT +#ifdef SUPPORTS_PALETTE_EXT if (PalettedTextures && mipmap >= 0 && trans == PNG_SOLID && color == PNG_COLOR_TYPE_PALETTE) { png_colorp pal; int cols; @@ -502,12 +502,12 @@ int APIENTRY pngLoadF(FILE *fp, int mipmap, int trans, pngInfo *pinfo) { glTexImage2D(GL_TEXTURE_2D, mipmap, intf, width, height, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, data); } else - #endif - if (trans == PNG_SOLID || trans == PNG_ALPHA || trans == PNG_LUMINANCEALPHA || color == PNG_COLOR_TYPE_RGB_ALPHA || color == PNG_COLOR_TYPE_GRAY_ALPHA) { - GLenum glformat; - GLint glcomponent; +#endif + if (trans == PNG_SOLID || trans == PNG_ALPHA || trans == PNG_LUMINANCEALPHA || color == PNG_COLOR_TYPE_RGB_ALPHA || color == PNG_COLOR_TYPE_GRAY_ALPHA) { + GLenum glformat; + GLint glcomponent; - switch (color) { + switch (color) { case PNG_COLOR_TYPE_GRAY: case PNG_COLOR_TYPE_RGB: case PNG_COLOR_TYPE_PALETTE: @@ -526,48 +526,48 @@ int APIENTRY pngLoadF(FILE *fp, int mipmap, int trans, pngInfo *pinfo) { default: /*puts("glformat not set");*/ return 0; + } + + if (trans == PNG_LUMINANCEALPHA) + glformat = GL_LUMINANCE_ALPHA; + + if (mipmap == PNG_BUILDMIPMAPS) + Build2DMipmaps(glcomponent, width, height, glformat, data, 1); + else if (mipmap == PNG_SIMPLEMIPMAPS) + Build2DMipmaps(glcomponent, width, height, glformat, data, 0); + else + glTexImage2D(GL_TEXTURE_2D, mipmap, glcomponent, width, height, 0, glformat, GL_UNSIGNED_BYTE, data); } + else { + png_bytep p, endp, q; + int r, g, b, a; - if (trans == PNG_LUMINANCEALPHA) - glformat = GL_LUMINANCE_ALPHA; + p = data, endp = p+width*height*3; + q = data2 = (png_bytep) malloc(sizeof(png_byte)*width*height*4); - if (mipmap == PNG_BUILDMIPMAPS) - Build2DMipmaps(glcomponent, width, height, glformat, data, 1); - else if (mipmap == PNG_SIMPLEMIPMAPS) - Build2DMipmaps(glcomponent, width, height, glformat, data, 0); - else - glTexImage2D(GL_TEXTURE_2D, mipmap, glcomponent, width, height, 0, glformat, GL_UNSIGNED_BYTE, data); - } - else { - png_bytep p, endp, q; - int r, g, b, a; + if (pinfo != NULL) pinfo->Alpha = 8; - p = data, endp = p+width*height*3; - q = data2 = (png_bytep) malloc(sizeof(png_byte)*width*height*4); +#define FORSTART \ + do { \ + r = *p++; /*red */ \ + g = *p++; /*green*/ \ + b = *p++; /*blue */ \ + *q++ = r; \ + *q++ = g; \ + *q++ = b; - if (pinfo != NULL) pinfo->Alpha = 8; +#define FOREND \ + q++; \ + } while (p != endp); - #define FORSTART \ - do { \ - r = *p++; /*red */ \ - g = *p++; /*green*/ \ - b = *p++; /*blue */ \ - *q++ = r; \ - *q++ = g; \ - *q++ = b; +#define ALPHA *q - #define FOREND \ - q++; \ - } while (p != endp); - - #define ALPHA *q - - switch (trans) { + switch (trans) { case PNG_CALLBACKT: FORSTART ALPHA = AlphaCallback((unsigned char) r, (unsigned char) g, (unsigned char) b); FOREND - break; + break; case PNG_STENCIL: FORSTART @@ -576,76 +576,76 @@ int APIENTRY pngLoadF(FILE *fp, int mipmap, int trans, pngInfo *pinfo) { else ALPHA = 255; FOREND - break; + break; case PNG_BLEND1: FORSTART a = r+g+b; - if (a > 255) ALPHA = 255; else ALPHA = a; + if (a > 255) ALPHA = 255; else ALPHA = a; FOREND - break; + break; case PNG_BLEND2: FORSTART a = r+g+b; - if (a > 255*2) ALPHA = 255; else ALPHA = a/2; + if (a > 255*2) ALPHA = 255; else ALPHA = a/2; FOREND - break; + break; case PNG_BLEND3: FORSTART ALPHA = (r+g+b)/3; FOREND - break; + break; case PNG_BLEND4: FORSTART a = r*r+g*g+b*b; - if (a > 255) ALPHA = 255; else ALPHA = a; + if (a > 255) ALPHA = 255; else ALPHA = a; FOREND - break; + break; case PNG_BLEND5: FORSTART a = r*r+g*g+b*b; - if (a > 255*2) ALPHA = 255; else ALPHA = a/2; + if (a > 255*2) ALPHA = 255; else ALPHA = a/2; FOREND - break; + break; case PNG_BLEND6: FORSTART a = r*r+g*g+b*b; - if (a > 255*3) ALPHA = 255; else ALPHA = a/3; + if (a > 255*3) ALPHA = 255; else ALPHA = a/3; FOREND - break; + break; case PNG_BLEND7: FORSTART a = r*r+g*g+b*b; - if (a > 255*255) ALPHA = 255; else ALPHA = (int) sqrt(a); + if (a > 255*255) ALPHA = 255; else ALPHA = (int) sqrt(a); FOREND - break; + break; + } + +#undef FORSTART +#undef FOREND +#undef ALPHA + + if (mipmap == PNG_BUILDMIPMAPS) + Build2DMipmaps(4, width, height, GL_RGBA, data2, 1); + else if (mipmap == PNG_SIMPLEMIPMAPS) + Build2DMipmaps(4, width, height, GL_RGBA, data2, 0); + else + glTexImage2D(GL_TEXTURE_2D, mipmap, 4, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data2); + + free(data2); } - #undef FORSTART - #undef FOREND - #undef ALPHA - - if (mipmap == PNG_BUILDMIPMAPS) - Build2DMipmaps(4, width, height, GL_RGBA, data2, 1); - else if (mipmap == PNG_SIMPLEMIPMAPS) - Build2DMipmaps(4, width, height, GL_RGBA, data2, 0); - else - glTexImage2D(GL_TEXTURE_2D, mipmap, 4, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data2); - - free(data2); - } - - glPixelStorei(GL_PACK_ALIGNMENT, pack); - glPixelStorei(GL_UNPACK_ALIGNMENT, unpack); + glPixelStorei(GL_PACK_ALIGNMENT, pack); + glPixelStorei(GL_UNPACK_ALIGNMENT, unpack); } /* OpenGL end */ - png_read_end(png, endinfo); + png_read_end(png, endinfo); png_destroy_read_struct(&png, &info, &endinfo); free(data); @@ -684,6 +684,14 @@ unsigned int APIENTRY pngBindF(FILE *file, int mipmap, int trans, pngInfo *info, return 0; } +unsigned int APIENTRY pngBindMem(const char *mem, int size, int mipmap, int trans, pngInfo *info, int wrapst, int minfilter, int magfilter) { + unsigned int id = SetParams(wrapst, magfilter, minfilter); + + if (id != 0 && pngLoadMem(mem, size, mipmap, trans, info)) + return id; + return 0; +} + void APIENTRY pngSetStencil(unsigned char red, unsigned char green, unsigned char blue) { StencilRed = red, StencilGreen = green, StencilBlue = blue; } @@ -710,3 +718,329 @@ void APIENTRY pngSetStandardOrientation(int standardorientation) { StandardOrientation = standardorientation; } + + +// -- added memory read functions -- + +/*pointer to a new input function that takes as its +arguments a pointer to a png_struct, a pointer to +a location where input data can be stored, and a 32-bit +unsigned int that is the number of bytes to be read. +To exit and output any fatal error messages the new write +function should call png_error(png_ptr, "Error msg"). */ + +typedef struct glpng_memread_struct +{ + png_bytep mem; + png_size_t rpos; +} glpng_memread; + +void glpng_read_mem(png_structp png, png_bytep dst, png_size_t size) +{ + glpng_memread *mr = (glpng_memread*)png_get_io_ptr(png); + memcpy(dst, mr->mem + mr->rpos, size); + mr->rpos += size; +} + +int APIENTRY pngLoadMem(const char *mem, int size, int mipmap, int trans, pngInfo *pinfo) { + GLint pack, unpack; + unsigned char header[8]; + png_structp png; + png_infop info; + png_infop endinfo; + png_bytep data, data2; + png_bytep *row_p; + double fileGamma; + + png_uint_32 width, height, rw, rh; + int depth, color; + + png_uint_32 i; + glpng_memread memread; + + if(size < 8) + return 0; // error + + memcpy(header, mem, 8); + + if (!png_check_sig(header, 8)) + return 0; + + png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + info = png_create_info_struct(png); + endinfo = png_create_info_struct(png); + + // DH: added following lines + if (setjmp(png_jmpbuf(png))) + { + png_destroy_read_struct(&png, &info, &endinfo); + return 0; + } + // ~DH + + memread.rpos = 0; + memread.mem = ((png_bytep)mem) + 8; + png_set_read_fn(png, &memread, glpng_read_mem); + png_set_sig_bytes(png, 8); + png_read_info(png, info); + png_get_IHDR(png, info, &width, &height, &depth, &color, NULL, NULL, NULL); + + if (pinfo != NULL) { + pinfo->Width = width; + pinfo->Height = height; + pinfo->Depth = depth; + } + + if (MaxTextureSize == 0) + glGetIntegerv(GL_MAX_TEXTURE_SIZE, &MaxTextureSize); + +#ifdef SUPPORTS_PALETTE_EXT +#ifdef _WIN32 + if (PalettedTextures == -1) + PalettedTextures = ExtSupported("GL_EXT_paletted_texture") && (strstr((const char *) glGetString(GL_VERSION), "1.1.0 3Dfx Beta") == NULL); + + if (PalettedTextures) { + if (glColorTableEXT == NULL) { + glColorTableEXT = (PFNGLCOLORTABLEEXTPROC) wglGetProcAddress("glColorTableEXT"); + if (glColorTableEXT == NULL) + PalettedTextures = 0; + } + } +#endif +#endif + + if (PalettedTextures == -1) + PalettedTextures = 0; + + if (color == PNG_COLOR_TYPE_GRAY || color == PNG_COLOR_TYPE_GRAY_ALPHA) + png_set_gray_to_rgb(png); + + if (color&PNG_COLOR_MASK_ALPHA && trans != PNG_ALPHA) { + png_set_strip_alpha(png); + color &= ~PNG_COLOR_MASK_ALPHA; + } + + if (!(PalettedTextures && mipmap >= 0 && trans == PNG_SOLID)) + if (color == PNG_COLOR_TYPE_PALETTE) + png_set_expand(png); + + /*--GAMMA--*/ + checkForGammaEnv(); + if (png_get_gAMA(png, info, &fileGamma)) + png_set_gamma(png, screenGamma, fileGamma); + else + png_set_gamma(png, screenGamma, 1.0/2.2); + + png_read_update_info(png, info); + + data = (png_bytep) malloc(png_get_rowbytes(png, info)*height); + row_p = (png_bytep *) malloc(sizeof(png_bytep)*height); + + for (i = 0; i < height; i++) { + if (StandardOrientation) + row_p[height - 1 - i] = &data[png_get_rowbytes(png, info)*i]; + else + row_p[i] = &data[png_get_rowbytes(png, info)*i]; + } + + png_read_image(png, row_p); + free(row_p); + + rw = SafeSize(width), rh = SafeSize(height); + + if (rw != width || rh != height) { + const int channels = png_get_rowbytes(png, info)/width; + + data2 = (png_bytep) malloc(rw*rh*channels); + + /* Doesn't work on certain sizes */ + /* if (gluScaleImage(glformat, width, height, GL_UNSIGNED_BYTE, data, rw, rh, GL_UNSIGNED_BYTE, data2) != 0) + return 0; + */ + Resize(channels, data, width, height, data2, rw, rh); + + width = rw, height = rh; + free(data); + data = data2; + } + + { /* OpenGL stuff */ + glGetIntegerv(GL_PACK_ALIGNMENT, &pack); + glGetIntegerv(GL_UNPACK_ALIGNMENT, &unpack); + glPixelStorei(GL_PACK_ALIGNMENT, 1); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + +#ifdef SUPPORTS_PALETTE_EXT + if (PalettedTextures && mipmap >= 0 && trans == PNG_SOLID && color == PNG_COLOR_TYPE_PALETTE) { + png_colorp pal; + int cols; + GLint intf; + + if (pinfo != NULL) pinfo->Alpha = 0; + png_get_PLTE(png, info, &pal, &cols); + + switch (cols) { + case 1<<1: intf = GL_COLOR_INDEX1_EXT; break; + case 1<<2: intf = GL_COLOR_INDEX2_EXT; break; + case 1<<4: intf = GL_COLOR_INDEX4_EXT; break; + case 1<<8: intf = GL_COLOR_INDEX8_EXT; break; + case 1<<12: intf = GL_COLOR_INDEX12_EXT; break; + case 1<<16: intf = GL_COLOR_INDEX16_EXT; break; + default: + /*printf("Warning: Colour depth %i not recognised\n", cols);*/ + return 0; + } + glColorTableEXT(GL_TEXTURE_2D, GL_RGB8, cols, GL_RGB, GL_UNSIGNED_BYTE, pal); + glTexImage2D(GL_TEXTURE_2D, mipmap, intf, width, height, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, data); + } + else +#endif + if (trans == PNG_SOLID || trans == PNG_ALPHA || trans == PNG_LUMINANCEALPHA || color == PNG_COLOR_TYPE_RGB_ALPHA || color == PNG_COLOR_TYPE_GRAY_ALPHA) { + GLenum glformat; + GLint glcomponent; + + switch (color) { + case PNG_COLOR_TYPE_GRAY: + case PNG_COLOR_TYPE_RGB: + case PNG_COLOR_TYPE_PALETTE: + glformat = GL_RGB; + glcomponent = 3; + if (pinfo != NULL) pinfo->Alpha = 0; + break; + + case PNG_COLOR_TYPE_GRAY_ALPHA: + case PNG_COLOR_TYPE_RGB_ALPHA: + glformat = GL_RGBA; + glcomponent = 4; + if (pinfo != NULL) pinfo->Alpha = 8; + break; + + default: + /*puts("glformat not set");*/ + return 0; + } + + if (trans == PNG_LUMINANCEALPHA) + glformat = GL_LUMINANCE_ALPHA; + + if (mipmap == PNG_BUILDMIPMAPS) + Build2DMipmaps(glcomponent, width, height, glformat, data, 1); + else if (mipmap == PNG_SIMPLEMIPMAPS) + Build2DMipmaps(glcomponent, width, height, glformat, data, 0); + else + glTexImage2D(GL_TEXTURE_2D, mipmap, glcomponent, width, height, 0, glformat, GL_UNSIGNED_BYTE, data); + } + else { + png_bytep p, endp, q; + int r, g, b, a; + + p = data, endp = p+width*height*3; + q = data2 = (png_bytep) malloc(sizeof(png_byte)*width*height*4); + + if (pinfo != NULL) pinfo->Alpha = 8; + +#define FORSTART \ + do { \ + r = *p++; /*red */ \ + g = *p++; /*green*/ \ + b = *p++; /*blue */ \ + *q++ = r; \ + *q++ = g; \ + *q++ = b; + +#define FOREND \ + q++; \ + } while (p != endp); + +#define ALPHA *q + + switch (trans) { + case PNG_CALLBACKT: + FORSTART + ALPHA = AlphaCallback((unsigned char) r, (unsigned char) g, (unsigned char) b); + FOREND + break; + + case PNG_STENCIL: + FORSTART + if (r == StencilRed && g == StencilGreen && b == StencilBlue) + ALPHA = 0; + else + ALPHA = 255; + FOREND + break; + + case PNG_BLEND1: + FORSTART + a = r+g+b; + if (a > 255) ALPHA = 255; else ALPHA = a; + FOREND + break; + + case PNG_BLEND2: + FORSTART + a = r+g+b; + if (a > 255*2) ALPHA = 255; else ALPHA = a/2; + FOREND + break; + + case PNG_BLEND3: + FORSTART + ALPHA = (r+g+b)/3; + FOREND + break; + + case PNG_BLEND4: + FORSTART + a = r*r+g*g+b*b; + if (a > 255) ALPHA = 255; else ALPHA = a; + FOREND + break; + + case PNG_BLEND5: + FORSTART + a = r*r+g*g+b*b; + if (a > 255*2) ALPHA = 255; else ALPHA = a/2; + FOREND + break; + + case PNG_BLEND6: + FORSTART + a = r*r+g*g+b*b; + if (a > 255*3) ALPHA = 255; else ALPHA = a/3; + FOREND + break; + + case PNG_BLEND7: + FORSTART + a = r*r+g*g+b*b; + if (a > 255*255) ALPHA = 255; else ALPHA = (int) sqrt(a); + FOREND + break; + } + +#undef FORSTART +#undef FOREND +#undef ALPHA + + if (mipmap == PNG_BUILDMIPMAPS) + Build2DMipmaps(4, width, height, GL_RGBA, data2, 1); + else if (mipmap == PNG_SIMPLEMIPMAPS) + Build2DMipmaps(4, width, height, GL_RGBA, data2, 0); + else + glTexImage2D(GL_TEXTURE_2D, mipmap, 4, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data2); + + free(data2); + } + + glPixelStorei(GL_PACK_ALIGNMENT, pack); + glPixelStorei(GL_UNPACK_ALIGNMENT, unpack); + } /* OpenGL end */ + + png_read_end(png, endinfo); + png_destroy_read_struct(&png, &info, &endinfo); + + free(data); + + return 1; +}