1 //-----------------------------------------------------------------------------
2 //
3 // ImageLib Sources
4 // Copyright (C) 2000-2008 by Denton Woods
5 // Last modified: 11/07/2008
6 //
7 // Filename: src-IL/src/il_register.c
8 //
9 // Description: Allows the caller to specify user-defined callback functions
10 //				 to open files DevIL does not support, to parse files
11 //				 differently, or anything else a person can think up.
12 //
13 //-----------------------------------------------------------------------------
14 
15 
16 #include "il_internal.h"
17 #include "il_register.h"
18 #include <string.h>
19 
20 
21 // Linked lists of registered formats
22 iFormatL *LoadProcs = NULL;
23 iFormatS *SaveProcs = NULL;
24 
25 
ilRegisterLoad(ILconst_string Ext,IL_LOADPROC Load)26 ILboolean ILAPIENTRY ilRegisterLoad(ILconst_string Ext, IL_LOADPROC Load) {
27 	iFormatL *TempNode, *NewNode;
28 
29 	TempNode = LoadProcs;
30 	if (TempNode != NULL) {
31 		while (TempNode->Next != NULL) {
32 			TempNode = TempNode->Next;
33 			if (!iStrCmp(TempNode->Ext, Ext)) {  // already registered
34 				return IL_TRUE;
35 			}
36 		}
37 	}
38 
39 	NewNode = (iFormatL*)ialloc(sizeof(iFormatL));
40 	if (NewNode == NULL) {
41 		return IL_FALSE;
42 	}
43 
44 	if (LoadProcs == NULL) {
45 		LoadProcs = NewNode;
46 	}
47 	else {
48 		TempNode->Next = NewNode;
49 	}
50 
51 	NewNode->Ext = ilStrDup(Ext);
52 	NewNode->Load = Load;
53 	NewNode->Next = NULL;
54 
55 	return IL_TRUE;
56 }
57 
58 
ilRegisterSave(ILconst_string Ext,IL_SAVEPROC Save)59 ILboolean ILAPIENTRY ilRegisterSave(ILconst_string Ext, IL_SAVEPROC Save)
60 {
61 	iFormatS *TempNode, *NewNode;
62 
63 	TempNode = SaveProcs;
64 	if (TempNode != NULL) {
65 		while (TempNode->Next != NULL) {
66 			TempNode = TempNode->Next;
67 			if (!iStrCmp(TempNode->Ext, Ext)) {  // already registered
68 				return IL_TRUE;
69 			}
70 		}
71 	}
72 
73 	NewNode = (iFormatS*)ialloc(sizeof(iFormatL));
74 	if (NewNode == NULL) {
75 		return IL_FALSE;
76 	}
77 
78 	if (SaveProcs == NULL) {
79 		SaveProcs = NewNode;
80 	}
81 	else {
82 		TempNode->Next = NewNode;
83 	}
84 
85 	NewNode->Ext = ilStrDup(Ext);
86 	NewNode->Save = Save;
87 	NewNode->Next = NULL;
88 
89 	return IL_TRUE;
90 }
91 
92 
93 //! Unregisters a load extension - doesn't have to be called.
ilRemoveLoad(ILconst_string Ext)94 ILboolean ILAPIENTRY ilRemoveLoad(ILconst_string Ext)
95 {
96 	iFormatL *TempNode = LoadProcs, *PrevNode = NULL;
97 
98 	while (TempNode != NULL) {
99 		if (!iStrCmp(Ext, TempNode->Ext)) {
100 			if (PrevNode == NULL) {  // first node in the list
101 				LoadProcs = TempNode->Next;
102 				ifree((void*)TempNode->Ext);
103 				ifree(TempNode);
104 			}
105 			else {
106 				PrevNode->Next = TempNode->Next;
107 				ifree((void*)TempNode->Ext);
108 				ifree(TempNode);
109 			}
110 
111 			return IL_TRUE;
112 		}
113 
114 		PrevNode = TempNode;
115 		TempNode = TempNode->Next;
116 	}
117 
118 	return IL_FALSE;
119 }
120 
121 
122 //! Unregisters a save extension - doesn't have to be called.
ilRemoveSave(ILconst_string Ext)123 ILboolean ILAPIENTRY ilRemoveSave(ILconst_string Ext)
124 {
125 	iFormatS *TempNode = SaveProcs, *PrevNode = NULL;
126 
127 	while (TempNode != NULL) {
128 		if (!iStrCmp(Ext, TempNode->Ext)) {
129 			if (PrevNode == NULL) {  // first node in the list
130 				SaveProcs = TempNode->Next;
131 				ifree((void*)TempNode->Ext);
132 				ifree(TempNode);
133 			}
134 			else {
135 				PrevNode->Next = TempNode->Next;
136 				ifree((void*)TempNode->Ext);
137 				ifree(TempNode);
138 			}
139 
140 			return IL_TRUE;
141 		}
142 
143 		PrevNode = TempNode;
144 		TempNode = TempNode->Next;
145 	}
146 
147 	return IL_FALSE;
148 }
149 
150 
151 // Automatically removes all registered formats.
ilRemoveRegistered()152 void ilRemoveRegistered()
153 {
154 	iFormatL *TempNodeL = LoadProcs;
155 	iFormatS *TempNodeS = SaveProcs;
156 
157 	while (LoadProcs != NULL) {
158 		TempNodeL = LoadProcs->Next;
159 		ifree((void*)LoadProcs->Ext);
160 		ifree(LoadProcs);
161 		LoadProcs = TempNodeL;
162 	}
163 
164 	while (SaveProcs != NULL) {
165 		TempNodeS = SaveProcs->Next;
166 		ifree((void*)SaveProcs->Ext);
167 		ifree(SaveProcs);
168 		SaveProcs = TempNodeS;
169 	}
170 
171 	return;
172 }
173 
174 
iRegisterLoad(ILconst_string FileName)175 ILboolean iRegisterLoad(ILconst_string FileName)
176 {
177 	iFormatL	*TempNode = LoadProcs;
178 	ILstring	Ext = iGetExtension(FileName);
179 	ILenum		Error;
180 
181 	if (!Ext)
182 		return IL_FALSE;
183 
184 	while (TempNode != NULL) {
185 		if (!iStrCmp(Ext, TempNode->Ext)) {
186 			Error = TempNode->Load(FileName);
187 			if (Error == IL_NO_ERROR || Error == 0) {  // 0 and IL_NO_ERROR are both valid.
188 				return IL_TRUE;
189 			}
190 			else {
191 				ilSetError(Error);
192 				return IL_FALSE;
193 			}
194 		}
195 		TempNode = TempNode->Next;
196 	}
197 
198 	return IL_FALSE;
199 }
200 
201 
iRegisterSave(ILconst_string FileName)202 ILboolean iRegisterSave(ILconst_string FileName)
203 {
204 	iFormatS	*TempNode = SaveProcs;
205 	ILstring	Ext = iGetExtension(FileName);
206 	ILenum		Error;
207 
208 	if (!Ext)
209 		return IL_FALSE;
210 
211 	while (TempNode != NULL) {
212 		if (!iStrCmp(Ext, TempNode->Ext)) {
213 			Error = TempNode->Save(FileName);
214 			if (Error == IL_NO_ERROR || Error == 0) {  // 0 and IL_NO_ERROR are both valid.
215 				return IL_TRUE;
216 			}
217 			else {
218 				ilSetError(Error);
219 				return IL_FALSE;
220 			}
221 		}
222 		TempNode = TempNode->Next;
223 	}
224 
225 	return IL_FALSE;
226 }
227 
228 
229 //
230 // "Reporting" functions
231 //
232 
ilRegisterOrigin(ILenum Origin)233 void ILAPIENTRY ilRegisterOrigin(ILenum Origin)
234 {
235 	switch (Origin)
236 	{
237 		case IL_ORIGIN_LOWER_LEFT:
238 		case IL_ORIGIN_UPPER_LEFT:
239 			iCurImage->Origin = Origin;
240 			break;
241 		default:
242 			ilSetError(IL_INVALID_ENUM);
243 	}
244 	return;
245 }
246 
247 
ilRegisterFormat(ILenum Format)248 void ILAPIENTRY ilRegisterFormat(ILenum Format)
249 {
250 	switch (Format)
251 	{
252 		case IL_COLOUR_INDEX:
253 		case IL_RGB:
254 		case IL_RGBA:
255 		case IL_BGR:
256 		case IL_BGRA:
257 		case IL_LUMINANCE:
258                 case IL_LUMINANCE_ALPHA:
259 			iCurImage->Format = Format;
260 			break;
261 		default:
262 			ilSetError(IL_INVALID_ENUM);
263 	}
264 	return;
265 }
266 
267 
ilRegisterNumFaces(ILuint Num)268 ILboolean ILAPIENTRY ilRegisterNumFaces(ILuint Num)
269 {
270 	ILimage *Next, *Prev;
271 
272 	ilBindImage(ilGetCurName());  // Make sure the current image is actually bound.
273 	ilCloseImage(iCurImage->Faces);  // Close any current mipmaps.
274 
275 	iCurImage->Faces = NULL;
276 	if (Num == 0)  // Just gets rid of all the mipmaps.
277 		return IL_TRUE;
278 
279 	iCurImage->Faces = ilNewImage(1, 1, 1, 1, 1);
280 	if (iCurImage->Faces == NULL)
281 		return IL_FALSE;
282 	Next = iCurImage->Faces;
283 	Num--;
284 
285 	while (Num) {
286 		Next->Faces = ilNewImage(1, 1, 1, 1, 1);
287 		if (Next->Faces == NULL) {
288 			// Clean up before we error out.
289 			Prev = iCurImage->Faces;
290 			while (Prev) {
291 				Next = Prev->Faces;
292 				ilCloseImage(Prev);
293 				Prev = Next;
294 			}
295 			return IL_FALSE;
296 		}
297 		Next = Next->Faces;
298 		Num--;
299 	}
300 
301 	return IL_TRUE;
302 }
303 
304 
ilRegisterMipNum(ILuint Num)305 ILboolean ILAPIENTRY ilRegisterMipNum(ILuint Num)
306 {
307 	ILimage *Next, *Prev;
308 
309 	ilBindImage(ilGetCurName());  // Make sure the current image is actually bound.
310 	ilCloseImage(iCurImage->Mipmaps);  // Close any current mipmaps.
311 
312 	iCurImage->Mipmaps = NULL;
313 	if (Num == 0)  // Just gets rid of all the mipmaps.
314 		return IL_TRUE;
315 
316 	iCurImage->Mipmaps = ilNewImage(1, 1, 1, 1, 1);
317 	if (iCurImage->Mipmaps == NULL)
318 		return IL_FALSE;
319 	Next = iCurImage->Mipmaps;
320 	Num--;
321 
322 	while (Num) {
323 		Next->Next = ilNewImage(1, 1, 1, 1, 1);
324 		if (Next->Next == NULL) {
325 			// Clean up before we error out.
326 			Prev = iCurImage->Mipmaps;
327 			while (Prev) {
328 				Next = Prev->Next;
329 				ilCloseImage(Prev);
330 				Prev = Next;
331 			}
332 			return IL_FALSE;
333 		}
334 		Next = Next->Next;
335 		Num--;
336 	}
337 
338 	return IL_TRUE;
339 }
340 
341 
ilRegisterNumImages(ILuint Num)342 ILboolean ILAPIENTRY ilRegisterNumImages(ILuint Num)
343 {
344 	ILimage *Next, *Prev;
345 
346 	ilBindImage(ilGetCurName());  // Make sure the current image is actually bound.
347 	ilCloseImage(iCurImage->Next);  // Close any current "next" images.
348 
349 	iCurImage->Next = NULL;
350 	if (Num == 0)  // Just gets rid of all the "next" images.
351 		return IL_TRUE;
352 
353 	iCurImage->Next = ilNewImage(1, 1, 1, 1, 1);
354 	if (iCurImage->Next == NULL)
355 		return IL_FALSE;
356 	Next = iCurImage->Next;
357 	Num--;
358 
359 	while (Num) {
360 		Next->Next = ilNewImage(1, 1, 1, 1, 1);
361 		if (Next->Next == NULL) {
362 			// Clean up before we error out.
363 			Prev = iCurImage->Next;
364 			while (Prev) {
365 				Next = Prev->Next;
366 				ilCloseImage(Prev);
367 				Prev = Next;
368 			}
369 			return IL_FALSE;
370 		}
371 		Next = Next->Next;
372 		Num--;
373 	}
374 
375 	return IL_TRUE;
376 }
377 
378 
ilRegisterType(ILenum Type)379 void ILAPIENTRY ilRegisterType(ILenum Type)
380 {
381 	switch (Type)
382 	{
383 		case IL_BYTE:
384 		case IL_UNSIGNED_BYTE:
385 		case IL_SHORT:
386 		case IL_UNSIGNED_SHORT:
387 		case IL_INT:
388 		case IL_UNSIGNED_INT:
389 		case IL_FLOAT:
390 		case IL_DOUBLE:
391 			iCurImage->Type = Type;
392 			break;
393 		default:
394 			ilSetError(IL_INVALID_ENUM);
395 	}
396 
397 	return;
398 }
399 
400 
ilRegisterPal(void * Pal,ILuint Size,ILenum Type)401 void ILAPIENTRY ilRegisterPal(void *Pal, ILuint Size, ILenum Type)
402 {
403 	if (!iCurImage->Pal.Palette || !iCurImage->Pal.PalSize || iCurImage->Pal.PalType != IL_PAL_NONE) {
404 		ifree(iCurImage->Pal.Palette);
405 	}
406 
407 	iCurImage->Pal.PalSize = Size;
408 	iCurImage->Pal.PalType = Type;
409 	iCurImage->Pal.Palette = (ILubyte*)ialloc(Size);
410 	if (iCurImage->Pal.Palette == NULL)
411 		return;
412 
413 	if (Pal != NULL) {
414 		memcpy(iCurImage->Pal.Palette, Pal, Size);
415 	}
416 	else {
417 		ilSetError(IL_INVALID_PARAM);
418 	}
419 
420 	return;
421 }
422 
423 
ilSetDuration(ILuint Duration)424 ILboolean ILAPIENTRY ilSetDuration(ILuint Duration)
425 {
426 	if (iCurImage == NULL) {
427 		ilSetError(IL_ILLEGAL_OPERATION);
428 		return IL_FALSE;
429 	}
430 
431 	iCurImage->Duration = Duration;
432 
433 	return IL_TRUE;
434 }
435