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