Files
Client/rylCoder_16.02.2008_src/addons/DevIL/src-IL/src/il_stack.c
LGram16 dd97ddec92 Restructure repository to include all source folders
Move git root from Client/ to src/ to track all source code:
- Client: Game client source (moved to Client/Client/)
- Server: Game server source
- GameTools: Development tools
- CryptoSource: Encryption utilities
- database: Database scripts
- Script: Game scripts
- rylCoder_16.02.2008_src: Legacy coder tools
- GMFont, Game: Additional resources

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-29 20:17:20 +09:00

606 lines
12 KiB
C

//-----------------------------------------------------------------------------
//
// ImageLib Sources
// Copyright (C) 2000-2001 by Denton Woods
// Last modified: 12/25/2001 <--Y2K Compliant! =]
//
// Filename: src-IL/src/il_stack.c
//
// Description: The main image stack
//
//-----------------------------------------------------------------------------
// Credit goes to John Villar (johnny@reliaschev.com) for making the suggestion
// of not letting the user use ILimage structs but instead binding images
// like OpenGL.
#include "il_internal.h"
#include "il_stack.h"
//! Creates Num images and puts their index in Images - similar to glGenTextures().
ILvoid ILAPIENTRY ilGenImages(ILsizei Num, ILuint *Images)
{
ILsizei Index = 0;
iFree *TempFree = FreeNames;
if (Num < 1 || Images == NULL) {
ilSetError(IL_INVALID_VALUE);
return;
}
// No images have been generated yet, so create the image stack.
if (ImageStack == NULL)
if (!iEnlargeStack())
return;
do {
if (FreeNames != NULL) { // If any have been deleted, then reuse their image names.
TempFree = (iFree*)FreeNames->Next;
Images[Index] = FreeNames->Name;
ImageStack[FreeNames->Name] = ilNewImage(1, 1, 1, 1, 1);
ifree(FreeNames);
FreeNames = TempFree;
} else {
if (LastUsed >= StackSize)
if (!iEnlargeStack())
return;
Images[Index] = LastUsed;
// Must be all 1's instead of 0's, because some functions would divide by 0.
ImageStack[LastUsed] = ilNewImage(1, 1, 1, 1, 1);
LastUsed++;
}
} while (++Index < Num);
return;
}
ILint ILAPIENTRY ilGenImage() {
ILuint i;
ilGenImages(1,&i);
return i;
}
//! Makes Image the current active image - similar to glBindTexture().
ILvoid ILAPIENTRY ilBindImage(ILuint Image)
{
if (ImageStack == NULL || StackSize == 0) {
if (!iEnlargeStack()) {
return;
}
}
// If the user requests a high image name.
while (Image >= StackSize) {
if (!iEnlargeStack()) {
return;
}
}
if (ImageStack[Image] == NULL) {
ImageStack[Image] = ilNewImage(1, 1, 1, 1, 1);
if (Image >= LastUsed) // >= ?
LastUsed = Image + 1;
}
iCurImage = ImageStack[Image];
CurName = Image;
ParentImage = IL_TRUE;
return;
}
//! Deletes Num images from the image stack - similar to glDeleteTextures().
ILvoid ILAPIENTRY ilDeleteImages(ILsizei Num, const ILuint *Images)
{
iFree *Temp = FreeNames;
ILuint Index = 0;
if (Num < 1) {
//ilSetError(IL_INVALID_VALUE);
return;
}
if (StackSize == 0)
return;
do {
if (Images[Index] > 0 && Images[Index] < LastUsed) { // <= ?
/*if (FreeNames != NULL) { // Terribly inefficient
Temp = FreeNames;
do {
if (Temp->Name == Images[Index]) {
continue; // Sufficient?
}
} while ((Temp = Temp->Next));
}*/
// Already has been deleted or was never used.
if (ImageStack[Images[Index]] == NULL)
continue;
// Find out if current image - if so, set to default image zero.
if (Images[Index] == CurName || Images[Index] == 0) {
iCurImage = ImageStack[0];
CurName = 0;
}
// Should *NOT* be NULL here!
ilCloseImage(ImageStack[Images[Index]]);
ImageStack[Images[Index]] = NULL;
// Add to head of list - works for empty and non-empty lists
Temp = (iFree*)ialloc(sizeof(iFree));
if (!Temp) {
return;
}
Temp->Name = Images[Index];
Temp->Next = FreeNames;
FreeNames = Temp;
}
/*else { // Shouldn't set an error...just continue onward.
ilSetError(IL_ILLEGAL_OPERATION);
}*/
} while (++Index < (ILuint)Num);
}
ILvoid ILAPIENTRY ilDeleteImage(const ILuint Num) {
ilDeleteImages(1,&Num);
}
//! Checks if Image is a valid ilGenImages-generated image (like glIsTexture()).
ILboolean ILAPIENTRY ilIsImage(ILuint Image)
{
//iFree *Temp = FreeNames;
if (ImageStack == NULL)
return IL_FALSE;
if (Image >= LastUsed || Image == 0)
return IL_FALSE;
/*do {
if (Temp->Name == Image)
return IL_FALSE;
} while ((Temp = Temp->Next));*/
if (ImageStack[Image] == NULL) // Easier check.
return IL_FALSE;
return IL_TRUE;
}
//! Closes Image and frees all memory associated with it.
ILAPI ILvoid ILAPIENTRY ilCloseImage(ILimage *Image)
{
if (Image == NULL)
return;
if (Image->Data != NULL) {
ifree(Image->Data);
Image->Data = NULL;
}
if (Image->Pal.Palette != NULL && Image->Pal.PalSize > 0 && Image->Pal.PalType != IL_PAL_NONE) {
ifree(Image->Pal.Palette);
Image->Pal.Palette = NULL;
}
if (Image->Next != NULL) {
ilCloseImage(Image->Next);
Image->Next = NULL;
}
if (Image->Mipmaps != NULL) {
ilCloseImage(Image->Mipmaps);
Image->Mipmaps = NULL;
}
if (Image->Layers != NULL) {
ilCloseImage(Image->Layers);
Image->Layers = NULL;
}
if (Image->AnimList != NULL && Image->AnimSize != 0) {
ifree(Image->AnimList);
Image->AnimList = NULL;
}
if (Image->Profile != NULL && Image->ProfileSize != 0) {
ifree(Image->Profile);
Image->Profile = NULL;
Image->ProfileSize = 0;
}
if (Image->DxtcData != NULL && Image->DxtcFormat != IL_DXT_NO_COMP) {
ifree(Image->DxtcData);
Image->DxtcData = NULL;
Image->DxtcFormat = IL_DXT_NO_COMP;
Image->DxtcSize = 0;
}
ifree(Image);
Image = NULL;
return;
}
ILAPI ILboolean ILAPIENTRY ilIsValidPal(ILpal *Palette)
{
if (Palette == NULL)
return IL_FALSE;
if (Palette->PalSize == 0 || Palette->Palette == NULL)
return IL_FALSE;
switch (Palette->PalType)
{
case IL_PAL_RGB24:
case IL_PAL_RGB32:
case IL_PAL_RGBA32:
case IL_PAL_BGR24:
case IL_PAL_BGR32:
case IL_PAL_BGRA32:
return IL_TRUE;
}
return IL_FALSE;
}
//! Closes Palette and frees all memory associated with it.
ILAPI ILvoid ILAPIENTRY ilClosePal(ILpal *Palette)
{
if (Palette == NULL)
return;
if (!ilIsValidPal(Palette))
return;
ifree(Palette->Palette);
ifree(Palette);
return;
}
ILimage *iGetBaseImage()
{
return ImageStack[ilGetCurName()];
}
//! Sets the current mipmap level
ILboolean ILAPIENTRY ilActiveMipmap(ILuint Number)
{
ILuint Current;
ILimage *iTempImage;
if (iCurImage == NULL) {
ilSetError(IL_ILLEGAL_OPERATION);
return IL_FALSE;
}
if (Number == 0) {
return IL_TRUE;
}
iTempImage = iCurImage;
iCurImage = iCurImage->Mipmaps;
for (Current = 1; Current < Number; Current++) {
iCurImage = iCurImage->Next;
if (iCurImage == NULL) {
ilSetError(IL_INTERNAL_ERROR);
iCurImage = iTempImage;
return IL_FALSE;
}
}
ParentImage = IL_FALSE;
return IL_TRUE;
}
//! Used for setting the current image if it is an animation.
ILboolean ILAPIENTRY ilActiveImage(ILuint Number)
{
ILuint Current;
ILimage *iTempImage;
if (iCurImage == NULL) {
ilSetError(IL_ILLEGAL_OPERATION);
return IL_FALSE;
}
if (Number == 0) {
return IL_TRUE;
}
iTempImage = iCurImage;
iCurImage = iCurImage->Next;
Number--; // Skip 0 (parent image)
for (Current = 0; Current < Number; Current++) {
iCurImage = iCurImage->Next;
if (iCurImage == NULL) {
ilSetError(IL_INTERNAL_ERROR);
iCurImage = iTempImage;
return IL_FALSE;
}
}
ParentImage = IL_FALSE;
return IL_TRUE;
}
//! Used for setting the current layer if layers exist.
ILboolean ILAPIENTRY ilActiveLayer(ILuint Number)
{
ILuint Current;
ILimage *iTempImage;
if (iCurImage == NULL) {
ilSetError(IL_ILLEGAL_OPERATION);
return IL_FALSE;
}
if (Number == 0) {
return IL_TRUE;
}
iTempImage = iCurImage;
iCurImage = iCurImage->Layers;
//Number--; // Skip 0 (parent image)
for (Current = 1; Current < Number; Current++) {
iCurImage = iCurImage->Layers;
if (iCurImage == NULL) {
ilSetError(IL_INTERNAL_ERROR);
iCurImage = iTempImage;
return IL_FALSE;
}
}
ParentImage = IL_FALSE;
return IL_TRUE;
}
ILuint ILAPIENTRY ilCreateSubImage(ILenum Type, ILuint Num)
{
ILimage *SubImage;
ILuint Count ; // Create one before we go in the loop.
if (iCurImage == NULL) {
ilSetError(IL_ILLEGAL_OPERATION);
return 0;
}
if (Num == 0) {
return 0;
}
switch (Type)
{
case IL_SUB_NEXT:
if (iCurImage->Next)
ilCloseImage(iCurImage->Next);
iCurImage->Next = ilNewImage(1, 1, 1, 1, 1);
SubImage = iCurImage->Next;
break;
case IL_SUB_MIPMAP:
if (iCurImage->Mipmaps)
ilCloseImage(iCurImage->Mipmaps);
iCurImage->Mipmaps = ilNewImage(1, 1, 1, 1, 1);
SubImage = iCurImage->Mipmaps;
break;
case IL_SUB_LAYER:
if (iCurImage->Layers)
ilCloseImage(iCurImage->Layers);
iCurImage->Layers = ilNewImage(1, 1, 1, 1, 1);
SubImage = iCurImage->Layers;
break;
default:
ilSetError(IL_INVALID_ENUM);
return IL_FALSE;
}
if (SubImage == NULL) {
return 0;
}
for (Count = 1; Count < Num; Count++) {
SubImage->Next = ilNewImage(1, 1, 1, 1, 1);
SubImage = SubImage->Next;
if (SubImage == NULL)
return Count;
}
return Count;
}
// Returns the current index.
ILAPI ILuint ILAPIENTRY ilGetCurName()
{
if (iCurImage == NULL || ImageStack == NULL || StackSize == 0)
return 0;
return CurName;
}
// Returns the current image.
ILAPI ILimage* ILAPIENTRY ilGetCurImage()
{
return iCurImage;
}
// To be only used when the original image is going to be set back almost immediately.
ILAPI ILvoid ILAPIENTRY ilSetCurImage(ILimage *Image)
{
iCurImage = Image;
return;
}
// Completely replaces the current image and the version in the image stack.
ILAPI ILvoid ILAPIENTRY ilReplaceCurImage(ILimage *Image)
{
if (iCurImage) {
ilActiveImage(0);
ilCloseImage(iCurImage);
}
ImageStack[ilGetCurName()] = Image;
iCurImage = Image;
ParentImage = IL_TRUE;
return;
}
// Like realloc but sets new memory to 0.
ILvoid* ILAPIENTRY ilRecalloc(ILvoid *Ptr, ILuint OldSize, ILuint NewSize)
{
ILvoid *Temp = ialloc(NewSize);
ILuint CopySize = (OldSize < NewSize) ? OldSize : NewSize;
if (Temp != NULL) {
if (Ptr != NULL) {
memcpy(Temp, Ptr, CopySize);
ifree(Ptr);
}
Ptr = Temp;
if (OldSize < NewSize)
imemclear((ILubyte*)Temp + OldSize, NewSize - OldSize);
}
return Temp;
}
// Internal function to enlarge the image stack by I_STACK_INCREMENT members.
ILboolean iEnlargeStack()
{
// 02-05-2001: Moved from ilGenImages().
// Puts the cleanup function on the exit handler once.
if (!OnExit) {
#ifdef _MEM_DEBUG
AddToAtexit(); // So iFreeMem doesn't get called after unfreed information.
#endif//_MEM_DEBUG
#if (!defined(_WIN32_WCE)) && (!defined(IL_STATIC_LIB))
atexit((void*)ilShutDown);
#endif
OnExit = IL_TRUE;
}
if (!(ImageStack = (ILimage**)ilRecalloc(ImageStack, StackSize * sizeof(ILimage*), (StackSize + I_STACK_INCREMENT) * sizeof(ILimage*)))) {
return IL_FALSE;
}
StackSize += I_STACK_INCREMENT;
return IL_TRUE;
}
static ILboolean IsInit = IL_FALSE;
// ONLY call at startup.
ILvoid ILAPIENTRY ilInit()
{
// if it is already initialized skip initialization
if (IsInit == IL_TRUE )
return;
//ilSetMemory(NULL, NULL); Now useless 3/4/2006 (due to modification in il_alloc.c)
ilSetError(IL_NO_ERROR);
ilDefaultStates(); // Set states to their defaults.
// Sets default file-reading callbacks.
ilResetRead();
ilResetWrite();
#if (!defined(_WIN32_WCE)) && (!defined(IL_STATIC_LIB))
atexit((void*)ilRemoveRegistered);
#endif
//_WIN32_WCE
//ilShutDown();
iSetImage0(); // Beware! Clears all existing textures!
iBindImageTemp(); // Go ahead and create the temporary image.
IsInit = IL_TRUE;
return;
}
// Frees any extra memory in the stack.
// - Called on exit
ILvoid ILAPIENTRY ilShutDown()
{
// if it is not initialized do not shutdown
iFree* TempFree = (iFree*)FreeNames;
ILuint i;
if (!IsInit)
return;
if (!IsInit) { // Prevent from being called when not initialized.
ilSetError(IL_ILLEGAL_OPERATION);
return;
}
while (TempFree != NULL) {
FreeNames = (iFree*)TempFree->Next;
ifree(TempFree);
TempFree = FreeNames;
}
//for (i = 0; i < LastUsed; i++) {
for (i = 0; i < StackSize; i++) {
if (ImageStack[i] != NULL)
ilCloseImage(ImageStack[i]);
}
if (ImageStack)
ifree(ImageStack);
ImageStack = NULL;
LastUsed = 0;
StackSize = 0;
IsInit = IL_FALSE;
return;
}
// Initializes the image stack's first entry (default image) -- ONLY CALL ONCE!
ILvoid iSetImage0()
{
if (ImageStack == NULL)
if (!iEnlargeStack())
return;
LastUsed = 1;
CurName = 0;
ParentImage = IL_TRUE;
if (!ImageStack[0])
ImageStack[0] = ilNewImage(1, 1, 1, 1, 1);
iCurImage = ImageStack[0];
ilDefaultImage();
return;
}
ILAPI ILvoid ILAPIENTRY iBindImageTemp()
{
if (ImageStack == NULL || StackSize <= 1)
if (!iEnlargeStack())
return;
if (LastUsed <2 )
LastUsed = 2;
CurName = 1;
ParentImage = IL_TRUE;
if (!ImageStack[1])
ImageStack[1] = ilNewImage(1, 1, 1, 1, 1);
iCurImage = ImageStack[1];
return;
}