diff options
Diffstat (limited to 'engines/sword25/util/glsprites/internal/sprite.c')
-rwxr-xr-x | engines/sword25/util/glsprites/internal/sprite.c | 156 |
1 files changed, 156 insertions, 0 deletions
diff --git a/engines/sword25/util/glsprites/internal/sprite.c b/engines/sword25/util/glsprites/internal/sprite.c new file mode 100755 index 0000000000..261ce207e6 --- /dev/null +++ b/engines/sword25/util/glsprites/internal/sprite.c @@ -0,0 +1,156 @@ +/******************************************************************************/ +/* 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 <malloc.h> + +#include "glinclude.h" +#include "util.h" +#include "core.h" +#include "sprite.h" +#include "sprite_rectangle.h" +#include "sprite_pow2.h" +#include "sprite_tiled.h" + +/* -------------------------------------------------------------------------- */ + +typedef struct +{ + /* These first three members are present at the start of each sprite type. + Therefore it is safe to cast all sprite to this. */ + GLS_spriteFunctionTable * functionTable; + GLS_UInt32 width; + GLS_UInt32 height; +} spriteBase; + +/* -------------------------------------------------------------------------- */ + +#define MAX_WASTED_TEXTURE_MEMORY_PERCENT 30 + +/* -------------------------------------------------------------------------- */ + +GLS_Result GLS_NewSprite(GLS_UInt32 width, GLS_UInt32 height, GLS_Bool useAlphachannel, void * data, GLS_Sprite ** pSprite) +{ + //* The sprite needs to be at least 1x1 pixel in size */ + if (width == 0 || height == 0) return GLS_INVALID_SPRITE_DIMENSIONS; + + /* If both dimensions are powers of 2 a power of 2 texture will be used for the sprite */ + if (GLS_IsPowerOf2(width) && GLS_IsPowerOf2(height)) return GLS_NewSpritePow2(width, height, useAlphachannel, data, pSprite); + + /* Use TEXTURE_RECTANGLE_ARB for non power of 2 dimensions whenever possible */ + if (GLS_TheOGLCaps.textureRectanglesSupported && + GLS_TheOGLCaps.maxTextureRectangleSize >= width && + GLS_TheOGLCaps.maxTextureRectangleSize >= height) + return GLS_NewSpriteRectangle(width, height, useAlphachannel, data, pSprite); + + /* Use a power of 2 texture if TEXTURE_RECTANGLE_ARB is not possible, the image is small enough and the amount of wasted texture memory + is not too big */ + if ((width <= GLS_TheOGLCaps.maxTextureSize && height <= GLS_TheOGLCaps.maxTextureSize) && + (GLS_NextPowerOf2(width) * GLS_NextPowerOf2(height) * 100) / (width * height) <= MAX_WASTED_TEXTURE_MEMORY_PERCENT) + return GLS_NewSpritePow2(width, height, useAlphachannel, data, pSprite); + + /* Otherwise use tiled power of 2 textures */ + return GLS_NewSpriteTiled(width, height, useAlphachannel, data, pSprite); +} + + +/* -------------------------------------------------------------------------- */ + +GLS_Result GLS_DeleteSprite(GLS_Sprite * sprite) +{ + /* Poor mans polymorphism. */ + spriteBase * s = (spriteBase *) sprite; + return s->functionTable->Delete(sprite); +} + + +/* -------------------------------------------------------------------------- */ + +GLS_Result GLS_Blit(GLS_Sprite * sprite, + GLS_SInt32 x, GLS_SInt32 y, + const GLS_Rect * subImage, + const GLS_Color * color, + GLS_Bool flipH, GLS_Bool flipV, + GLS_Float scaleX, GLS_Float scaleY) +{ + spriteBase * s = (spriteBase *) sprite; + GLS_Rect localSubImage; + const GLS_Rect * subImagePtr; + GLS_Result result; + + /* Check parameters for validity. */ + if (subImage && (subImage->x2 > s->width || subImage->y2 > s->height)) return GLS_INVALID_SUB_IMAGE; + + /* If no subimage was supplied, create one that covers the whole sprite. */ + if (subImage) + subImagePtr = subImage; + else + { + localSubImage.x1 = 0; + localSubImage.y1 = 0; + localSubImage.x2 = s->width; + localSubImage.y2 = s->height; + subImagePtr = &localSubImage; + } + + /* Modify the Modelview-Matrix to reflect the sprites position, flip settings, and scale. */ + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + glTranslatef((GLfloat) x, (GLfloat) y, 0); + if (flipH == GLS_True || flipV == GLS_True || scaleX != 1.0f || scaleY != 1.0f) + { + glScalef(scaleX * (flipH == GLS_True ? -1.0f : 1.0f), scaleY * (flipV == GLS_True ? -1.0f : 1.0f), 1.0f); + glTranslatef(flipH == GLS_True ? (subImagePtr->x2 - subImagePtr->x1) * -1.0f : 0.0f, + flipV == GLS_True ? (subImagePtr->y2 - subImagePtr->y1) * -1.0f : 0.0f, 0.0f); + } + + /* Set the color to be used. Use white if no color was provided. */ + if (color) + glColor4ub(color->r, color->g, color->b, color->a); + else + glColor4ub(255, 255, 255, 255); + + /* Display the sprite by calling the Blit() function of the specific sprite type. */ + result = s->functionTable->Blit(sprite, subImagePtr); + + /* Restore the old matrix. */ + glPopMatrix(); + + return result; +} + + +/* -------------------------------------------------------------------------- */ + +GLS_Result GLS_SetSpriteData(GLS_Sprite sprite, GLS_UInt32 width, GLS_UInt32 height, const void * data, GLS_UInt32 stride) +{ + spriteBase * s = (spriteBase *) sprite; + + /* Check parameters for validity. */ + if (width == 0 || height == 0 || width > s->width || height > s->height) return GLS_INVALID_DATA_DIMENSIONS; + if (data == 0) return GLS_INVALID_DATA_POINTER; + + /* Poor mans polymorphism. */ + return s->functionTable->SetData(sprite, width, height, data, stride); +} |