maintenance work on the graphics module.
[neuro.git] / src / misc / other.c
blob27bd0c201c705a9086c4cb4c226f37166accd71b
2 /*
3 * libneuro, a light weight abstraction of high or lower libraries
4 * and toolkit for applications.
5 * Copyright (C) 2005-2006 Nicholas Niro, Robert Lemay
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 /* other.c
23 * contains miscellaneous functions
24 * useful not directly associated with
25 * xml handling but most of the time useful.
26 * Especially when you want to have more than 1 data per nodes
29 #include <stdio.h>
30 #include <string.h>
31 #include <stdlib.h>
33 #ifdef WIN32
34 #define WIN32_LEAN_AND_MEAN
35 #include <windows.h>
36 #else /* NOT WIN32 */
37 #define __USE_BSD
38 #include <unistd.h>
39 #endif /* NOT WIN32 */
41 #include <other.h>
42 #include <extlib.h>
43 #include <sys/time.h>
45 #include <graphics.h>
46 #include <ebuf.h>
48 #include "../video/video.h" /* for Graphics_FreeVObject() */
51 Chk_bound(Rectan *rec, i16 x, i16 y, i16 w, i16 h)
53 if (rec->x <= x && (rec->x + rec->w) >= x)
55 if (rec->y <= y && (rec->y + rec->h) >= y)
57 /* Debug_Print("condition 1"); */
58 return 1;
61 if (rec->y > y)
64 if ((rec->y + rec->h) < (y + h))
66 /* Debug_Print("condition 2"); */
67 return 1;
71 if ((rec->y + rec->h) < y)
73 if (rec->y > (y + h))
75 /* Debug_Print("condition 5"); */
76 return 1;
80 /* Debug_Print("ret condition 1"); */
83 if (rec->y <= y && (rec->y + rec->h) >= y)
85 if (rec->x > x)
87 if ((rec->x + rec->w) < (x + w))
89 /* Debug_Print("condition 3"); */
90 return 1;
94 if ((rec->x + rec->w) < x)
96 if (rec->x > (x + w))
98 /* Debug_Print("condition 4"); */
99 return 1;
101 /* Debug_Print("sub ret condition 2"); */
103 /* Debug_Print("ret condition 2"); */
106 /* Debug_Print("condition 0"); */
107 return 0;
110 void
111 Neuro_Sleep(u32 t)
113 #ifdef WIN32
114 /* Sleep is in milli seconds */
115 Sleep(t / 1000);
116 #else /* NOT WIN32 */
117 /* usleep is in nano seconds */
118 usleep(t);
119 #endif /* NOT WIN32 */
123 Neuro_GetTickCount()
125 #ifdef WIN32
126 if (IsLittleEndian())
127 return (GetTickCount() / 10) & 0x7fffffff;
128 else
129 return (GetTickCount() / 10) & 0xfffffff7;
130 #else /* NOT WIN32 */
131 struct timeval tv;
132 gettimeofday(&tv, NULL);
133 if (IsLittleEndian())
134 return (tv.tv_sec * 100 + tv.tv_usec / 10000) & 0x7fffffff;
135 else
136 return (tv.tv_sec * 100 + tv.tv_usec / 10000) & 0xfffffff7;
137 #endif /* NOT WIN32 */
141 /* this functions was made to separate a given character,
142 * like the character ':' of a string,
143 * example : foo:bar:test:test2
144 * the functions will have the pointers to each words in the string so
145 * foo bar test and test2 will be accessable independently.
147 char **
148 Neuro_SepChr(const unsigned char chr, char *source, int *items)
149 {/* separate characters of words */
150 char **ending = NULL;
151 u32 slen = strlen(source);
152 u32 o_total = 0;
153 char *object;
154 u32 o_ptr = 0;
155 u32 last_ptr = 0;
158 if (slen == 0)
159 return 0;
160 while ((last_ptr + o_ptr) < slen)
162 if (o_ptr == 0)
163 last_ptr = o_ptr;
164 else
165 last_ptr += o_ptr + 1;
166 if ((object = memchr(&source[o_ptr], chr, slen)) != NULL)
167 object[0] = '\0'; /* reset the ':' to \0 so we can point to it */
168 o_ptr = strlen(&source[last_ptr]);
169 if (o_total == 0)
170 ending = (char**)calloc(1, sizeof(char*));
171 else
173 ending = (char **)realloc((char*)ending, (sizeof(char*) * (o_total + 1)));
174 ending[o_total] = (char*)calloc(1, sizeof(char*));
176 ending[o_total] = (char*)&source[last_ptr];
177 o_total++;
179 *items = o_total;
180 return ending;
183 static void
184 clean_sepchr_ebuf(void *src)
186 SepChr_Data *tmp;
188 tmp = (SepChr_Data*)src;
190 if (tmp->string)
191 free(tmp->string);
194 /* new separate character function using the EBUF tech */
195 EBUF *
196 Neuro_SepChr2(const unsigned char chr, char *source)
198 u32 total;
199 u32 i = 0, i2 = 0;
200 EBUF *temp;
201 SepChr_Data *tmp;
202 char *buf;
204 if (source)
206 total = strlen(source);
207 if (total == 0)
208 return NULL;
210 else
211 return NULL;
213 Neuro_CreateEBuf(&temp);
214 Neuro_SetcallbEBuf(temp, clean_sepchr_ebuf);
216 buf = calloc(1, total);
218 while (i < total)
220 if (source[i] == chr)
222 Neuro_AllocEBuf(temp, sizeof(SepChr_Data*), sizeof(SepChr_Data));
223 tmp = Neuro_GiveCurEBuf(temp);
225 tmp->string = calloc(1, i2 + 1);
226 strncpy(tmp->string, buf, i2);
227 tmp->string[i2] = '\0';
228 i2 = 0;
230 else
232 buf[i2] = source[i];
233 i2++;
236 i++;
239 if (i2 > 0)
241 Neuro_AllocEBuf(temp, sizeof(SepChr_Data*), sizeof(SepChr_Data));
242 tmp = Neuro_GiveCurEBuf(temp);
244 tmp->string = calloc(1, i2 + 1);
245 strncpy(tmp->string, buf, i2);
246 tmp->string[i2] = '\0';
249 free(buf);
251 return temp;
255 Neuro_GiveRGB8(u8 R, u8 G, u8 B)
257 /* if the 2 not used bits are at the end
258 * R : 0x00000030
259 * G : 0x0000000C
260 * B : 0x00000003
262 * if the 2 not used bits are at the beginning
263 * R : 0x000000C0
264 * G : 0x00000030
265 * B : 0x0000000C
267 return 1;
271 Neuro_GiveRGB16(u8 R, u8 G, u8 B)
273 /* actually, the Red color has 5 bits
274 * ditto for blue... green has 6 bits!
276 /* if the not used bit is at the end
277 * R : 0x00007C00
278 * G : 0x000003E0
279 * B : 0x0000001F
281 * if the not used bit is at the beginning
282 * R : 0x0000F800
283 * G : 0x000007C0
284 * B : 0x0000003E
286 * NEW correct way it is
288 * R : 5 bit
289 * G : 6 bit
290 * B : 5 bit
292 * R : 0x0000F800
293 * G : 0x000007E0
294 * B : 0x0000001F
297 u32 output = 0;
299 if (IsLittleEndian())
301 output = ((R * 31) / 255);
302 output <<= 6;
303 output += ((G * 63) / 255);
304 output <<= 5;
305 output += ((B * 31) / 255);
307 else
309 output = ((R * 31) / 255);
310 output >>= 6;
311 output += ((G * 63) / 255);
312 output >>= 5;
313 output += ((B * 31) / 255);
316 return output;
320 Neuro_GiveRGB24(u8 R, u8 G, u8 B)
322 /* R : 0x00FF0000
323 * G : 0x0000FF00
324 * B : 0x000000FF
326 unsigned int output;
328 if (IsLittleEndian())
330 output = R;
331 output <<= 8;
332 output += G;
333 output <<= 8;
334 output += B;
336 else
338 output = R;
339 output >>= 8;
340 output += G;
341 output >>= 8;
342 output += B;
345 return output;
349 Neuro_GiveRGB32(u8 R, u8 G, u8 B)
351 /* if the 2 not used bits are at the end
352 * R : 0x3FF00000
353 * G : 0x000FFC00
354 * B : 0x000003FF
356 * if the 2 not used bits are at the beginning
357 * R : 0xFFC00000
358 * G : 0x003FF000
359 * B : 0x00000FFC
361 return 1;
365 Neuro_MapRGB(u8 R, u8 G, u8 B)
367 v_object *screen;
369 screen = Neuro_GetScreenBuffer();
371 return Lib_MapRGB(screen, R, G, B);
375 Neuro_GiveRGBA_special(u8 R, u8 G, u8 B)
377 u32 out;
379 /* hexadecimal position of the colors
380 * R : 0x000f8000
381 * G : 0x00007c00
382 * B : 0x000003e0
383 * A : 0x0000001f
385 * R : 0x003e0000
386 * G : 0x0001f000
387 * B : 0x00000f80
388 * A : 0x0000007c
390 * binary :
391 * 0000,0000 00|00,000|0
392 * 0000|,0000 0|000,00|00
396 out = ((R * 31) / 255) << 11;
397 out ^= ((G * 31) / 255) << 6;
398 out ^= ((B * 31) / 255);
402 /*out = ((R * 31) / 255);
403 out <<= 5;
404 out ^= ((G * 31) / 255);
405 out <<= 5;
406 out ^= ((B * 31) / 255);
407 out <<= 5;
408 out <<= 2;
411 out = ((R * 31) / 255);
412 out <<= 5;
413 out += ((G * 31) / 255);
414 out <<= 5;
415 out += ((B * 31) / 255);
416 out <<= 5;
417 out <<= 2;
420 /* R : 0xff000000
421 * G : 0x00ff0000
422 * B : 0x0000ff00
423 * A : 0x000000ff
426 if (IsLittleEndian())
428 out = R;
429 out <<= 8;
430 out += G;
431 out <<= 8;
432 out += B;
433 out <<= 8;
435 else
437 out = R;
438 out >>= 8;
439 out += G;
440 out >>= 8;
441 out += B;
442 out >>= 8;
445 return out;
449 Neuro_GiveRGB(u8 R, u8 G, u8 B)
451 return Neuro_GiveRGBA_special(R, G, B);
454 /* convert color of default screen depth to
455 * 24 bit and gives each color separately in
456 * R G and B.
458 void
459 Neuro_GiveConvertRGB(u32 color, u8 *R, u8 *G, u8 *B)
461 /* 32, 24, 16, 8 */
462 u32 tempR = 0, tempG = 0, tempB = 0;
464 switch (Lib_GetDefaultDepth())
466 case 32:
468 if (IsLittleEndian())
471 else
475 break;
477 case 24:
479 if (IsLittleEndian())
482 else
486 break;
488 case 16:
490 if (IsLittleEndian())
492 tempR = color & 0x0000F800;
493 tempG = color & 0x000007E0;
494 tempB = color & 0x0000001F;
496 tempR = tempR >> 11;
497 tempG = tempG >> 5;
498 /* *B = tempB; */
500 /* convert it to 255 (8 bit) */
501 *R = ((tempR * 255) / 31);
502 *G = ((tempG * 255) / 63);
503 *B = ((tempB * 255) / 31);
505 else
509 break;
511 case 8:
513 if (IsLittleEndian())
516 else
520 break;
522 default:
525 break;
529 void
530 Neuro_GiveImageSize(v_object *image, i32 *width, i32 *height)
532 if (image && width && height)
534 Lib_GetVObjectData(image, NULL, height, width, NULL, NULL, NULL,
535 NULL, NULL, NULL, NULL, NULL);
540 * * Return the pixel value at (x, y)
541 * * NOTE: The surface must be locked before calling this!
542 * */
543 u32
544 Neuro_RawGetPixel(v_object *srf, int x, int y)
547 return Lib_GetPixel(srf, x, y);
549 #if temp
550 u8 bpp;
551 u8 *p;
552 void *pixels;
553 u32 pitch;
554 u32 err;
557 Lib_LockVObject(srf);
559 Lib_GetVObjectData(srf, NULL, NULL, NULL, &pitch, &pixels, NULL, &bpp,
560 NULL, NULL, NULL, NULL);
562 /* bpp = surface->format->BytesPerPixel; */
563 /* Here p is the address to the pixel we want to retrieve */
564 /* p = (u8 *)surface->pixels + y * surface->pitch + x * bpp; */
565 p = (u8 *)pixels + y * pitch + x * bpp;
566 err = 0;
568 switch(bpp)
570 case 1:
572 err = *p;
573 /* err = *(u16 *)p; */
575 break;
577 case 2:
579 err = *(u16 *)p;
581 break;
583 /*case 3:
585 if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
586 err = p[0] << 16 | p[1] << 8 | p[2];
587 else
588 err = p[0] | p[1] << 8 | p[2] << 16;
590 break;
593 case 4:
595 err = *(u32 *)p;
597 break;
599 default:
601 err = 0; /* shouldn't happen, but avoids warnings */
605 Lib_UnlockVObject(srf);
607 return err;
608 #endif /* temp */
609 return 0;
614 * * Set the pixel at (x, y) to the given value
615 * * NOTE: The surface must be locked before calling this!
616 * */
617 void
618 Neuro_RawPutPixel(v_object *srf, int x, int y, u32 pixel)
621 Lib_PutPixel(srf, x, y, pixel);
623 #if temp
624 /* SDL_Surface *surface = (SDL_Surface*)srf; */
625 /* SDL_LockSurface(surface); */
626 u8 bpp;
627 u8 *p;
628 void *pixels;
629 u32 pitch;
631 Lib_GetVObjectData(srf, NULL, NULL, NULL, &pitch, &pixels, NULL, &bpp,
632 NULL, NULL, NULL, NULL);
634 /* int bpp = surface->format->BytesPerPixel; */
635 /* Here p is the address to the pixel we want to set */
636 /* p = (u8*)surface->pixels + y * surface->pitch + x * bpp; */
637 p = (u8 *)pixels + y * pitch + x * bpp;
639 switch(bpp)
641 case 1:
643 *p = pixel;
645 break;
647 case 2:
649 *(u16*)p = pixel;
651 break;
653 case 3:
655 if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
657 p[0] = (pixel >> 16) & 0xff;
658 p[1] = (pixel >> 8) & 0xff;
659 p[2] = pixel & 0xff;
661 else
663 p[0] = pixel & 0xff;
664 p[1] = (pixel >> 8) & 0xff;
665 p[2] = (pixel >> 16) & 0xff;
668 break;
670 case 4:
672 *(u32 *)p = pixel;
674 break;
677 /* SDL_UnlockSurface(surface); */
678 #endif /* temp */
681 void
682 Neuro_PrintFPS()
684 t_tick fps;
686 Neuro_GiveFPS(&fps);
688 if (fps >= 0)
690 printf("current fps : %d\n", fps);
694 /* substract num2 from num1 and returns the answer only if it is positive,
695 * if it is not, returns 0
698 Neuro_CalcOnlyPos(i16 num1, i16 num2)
700 i16 result;
702 result = num1 - num2;
704 if (result < 0)
705 return 0;
706 else
707 return result;
710 /* skeleton rectangle or square bounds check function.
711 * return values :
712 * 0 = depen is inside indep.
713 * 1 = depen and indep are not touching each others(they are far away).
714 * 2 = depen is overlaping indep.
715 * this function needs to be converted to a macro so its lightning quick
718 Neuro_DumbBoundsCheck(Rectan *indep, Rectan *depen)
720 register u8 status = 0;
722 status = Chk_bound(indep, depen->x, depen->y, depen->w, depen->h); /* up left */
723 status += Chk_bound(indep, depen->x + depen->w, depen->y, depen->w * -1, depen->h); /* up right */
724 status += Chk_bound(indep, depen->x + depen->w, depen->y + depen->h, (i16)depen->w * -1, (i16)depen->h * -1); /* bottom right */
725 status += Chk_bound(indep, depen->x, depen->y + depen->h, depen->w, (i16)depen->h * -1); /* bottom left */
727 if (status == 4)
729 status = 0; /* obj is inside form */
731 else
733 if (status > 0)
734 status = 2; /* obj overlaps form */
735 else
736 status = 1; /* obj is not touching form */
739 return status;
742 /* rectangle or square bounds check function.
743 * return values :
744 * 0 = depen is inside indep.
745 * 1 = depen and indep are not touching each others(they are far away).
746 * 2 = depen is overlaping indep.
747 * 3 = depen and indep links between corners are into the other but the corners
748 * are not touching.
749 * like this :
750 * _________
751 * _|_________|_
752 * | | | |
753 * | | | |
754 * | | | |
755 * |_|_________|_|
756 * |_________|
757 * 4 = indep is inside depen (reverse of 0)
759 * this function needs to be converted to a macro so its lightning quick
762 Neuro_BoundsCheck(Rectan *indep, Rectan *depen)
764 register u8 status = 0;
766 status = Neuro_DumbBoundsCheck(indep, depen);
768 /* check to see if depen is bigger than indep and indep is inside depen
769 * if its the case, the status will be 4.
771 if (status == 1)
773 if (Neuro_DumbBoundsCheck(depen, indep) != 1)
774 status = 4;
777 /* we check to see if we have a type 3 status */
778 if (status == 0)
780 if (Neuro_DumbBoundsCheck(depen, indep) == 0)
781 status = 3;
784 return status;
787 /* only play with the x and width values
788 * the Rectan indep should contain a rectangle.
789 * isrc is the Rectan that contains an image source Rectan.
790 * idst is the Rectan that contains the destination for the image
792 * this function will calibrate isrc and idst so the image represented
793 * by those 2 will not go over the rectangle indep.
794 * This function only fixes the vertical way of the image.
796 * This method will only work with cases where Neuro_BoundsCheck
797 * returned 2. No check is done, so watch out, only with case 2 please.
799 void
800 Neuro_VerticalBoundCrop(Rectan *indep, Rectan *isrc, Rectan *idst)
802 /* 2 methods : 1 is using statements and the other is mathematical */
804 /* the statement method */
806 if ((indep->x) > idst->x)
808 isrc->x += (indep->x) - idst->x;
809 isrc->w -= abs((indep->x) - idst->x);
810 idst->x = indep->x;
813 if ((indep->x + indep->w) < (idst->x + isrc->w))
815 isrc->w -= (idst->x + isrc->w) - (indep->x + indep->w);
819 /* the mathematical method */
821 isrc->x += Neuro_CalcOnlyPos(indep->x, idst->x);
823 isrc->w = Neuro_CalcOnlyPos(isrc->w,
824 (Neuro_CalcOnlyPos(indep->x, idst->x)
825 + Neuro_CalcOnlyPos(idst->x + isrc->w, indep->x + indep->w)));
827 idst->x += Neuro_CalcOnlyPos(indep->x, idst->x);
831 /* only play with the y and height values
832 * the Rectan indep should contain a rectangle.
833 * isrc is the Rectan that contains an image source Rectan.
834 * idst is the Rectan that contains the destination for the image
836 * this function will calibrate isrc and idst so the image represented
837 * by those 2 will not go over the rectangle indep.
838 * This function only fixes the horizontal way of the image.
840 void
841 Neuro_HorizontalBoundCrop(Rectan *indep, Rectan *isrc, Rectan *idst)
843 /* 2 methods : 1 is using statements and the other is mathematical */
845 /* the statement method */
847 if (indep->y > idst->y)
849 isrc->y += abs(indep->y - idst->y);
850 isrc->h -= abs(indep->y - idst->y);
851 idst->y = indep->y;
853 if ((indep->y + indep->h) < (idst->y + isrc->h))
855 isrc->h -= (idst->y + isrc->h) - (indep->y + indep->h);
859 /* the mathematical method */
861 isrc->y += Neuro_CalcOnlyPos(indep->y, idst->y);
863 isrc->h = Neuro_CalcOnlyPos(isrc->h,
864 (Neuro_CalcOnlyPos(indep->y, idst->y)
865 + Neuro_CalcOnlyPos(idst->y + isrc->h, indep->y + indep->h)));
867 idst->y += Neuro_CalcOnlyPos(indep->y, idst->y);
871 void
872 Neuro_BlitObject(v_object *source, Rectan *src, v_object *destination, Rectan *dst)
874 Lib_BlitObject(source, src, destination, dst);
877 void
878 Neuro_FreeVObject(v_object *source)
880 Graphics_FreeVObject(source);
883 void
884 Neuro_LoadBMP(const char *path, v_object **img)
886 Lib_LoadBMP(path, img);
889 void
890 Neuro_SetColorKey(v_object *vobj, u32 key)
892 Lib_SetColorKey(vobj, key);
895 void
896 Neuro_SetAlpha(v_object *vobj, u8 alpha)
898 Lib_SetAlpha(vobj, alpha);
901 void
902 Neuro_SyncPixels(v_object *src)
904 Lib_SyncPixels(src);
907 v_object *
908 Neuro_CreateVObject(u32 flags, i32 width, i32 height, i32 depth, u32 Rmask, u32 Gmask,
909 u32 Bmask, u32 Amask)
911 return Lib_CreateVObject(flags, width, height, depth, Rmask, Gmask, Bmask, Amask);
914 font_object *
915 Neuro_LoadFontFile(char *fonts_file_path)
917 return Lib_LoadFontFile(fonts_file_path);
920 void
921 Neuro_CleanFont(font_object *font)
923 Lib_CleanFont(font);
926 v_object *
927 Neuro_RenderUnicode(font_object *ttf, u32 size, u32 character, i16 *x, i16 *y, u32 color, Rectan *src, Rectan *dst)
929 return Lib_RenderUnicode(ttf, size, character, x, y, color, src, dst);
932 void
933 Neuro_SetScreenSize(u32 width, u32 height)
935 Lib_SetScreenSize(width, height);
938 void
939 Neuro_GetScreenSize(u32 *width, u32 *height)
941 Lib_GetScreenSize(width, height);
945 void
946 Neuro_LockVObject(v_object *vobj)
948 Lib_LockVObject(vobj);
951 void
952 Neuro_UnlockVObject(v_object *vobj)
954 Lib_UnlockVObject(vobj);