2012-05-05 20:06:34 -05:00
/**
* Powder Toy - miscellaneous functions
*
* This program 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 3 of the License , or
* ( at your option ) any later version .
*
* This program 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 this program . If not , see < http : //www.gnu.org/licenses/>.
*/
2010-09-27 05:53:05 -05:00
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
2011-01-31 10:54:13 -06:00
# include <regex.h>
# include <sys/types.h>
2011-06-09 13:46:41 -05:00
# include <math.h>
2010-09-27 05:53:05 -05:00
# include "misc.h"
# include "defines.h"
# include "interface.h"
# include "graphics.h"
2011-01-29 11:42:01 -06:00
# include "powder.h"
2011-04-06 14:10:43 -05:00
# include <icondoc.h>
2011-04-14 12:41:41 -05:00
# include <update.h>
2011-03-27 12:13:52 -05:00
# if defined WIN32
2011-09-22 12:25:21 -05:00
# include <shlobj.h>
# include <shlwapi.h>
2011-03-27 12:13:52 -05:00
# include <windows.h>
2011-04-06 12:12:05 -05:00
# else
# include <unistd.h>
2011-03-27 12:13:52 -05:00
# endif
2011-04-04 11:07:38 -05:00
# ifdef MACOSX
# include <ApplicationServices/ApplicationServices.h>
# endif
2011-09-27 12:44:35 -05:00
# include "cJSON.h"
2010-09-27 05:53:05 -05:00
2011-04-22 18:20:56 -05:00
char * clipboard_text = NULL ;
2010-09-27 05:53:05 -05:00
//Signum function
2010-11-06 12:42:22 -05:00
# if defined(WIN32) && !defined(__GNUC__)
2011-09-21 21:05:19 -05:00
int isign ( float i )
2010-09-27 05:53:05 -05:00
# else
inline int isign ( float i )
# endif
{
2011-01-06 16:26:31 -06:00
if ( i < 0 )
return - 1 ;
if ( i > 0 )
return 1 ;
return 0 ;
2010-09-27 05:53:05 -05:00
}
2010-11-06 12:42:22 -05:00
# if defined(WIN32) && !defined(__GNUC__)
2011-09-21 21:05:19 -05:00
unsigned clamp_flt ( float f , float min , float max )
2010-09-27 05:53:05 -05:00
# else
inline unsigned clamp_flt ( float f , float min , float max )
# endif
{
2011-01-06 16:26:31 -06:00
if ( f < min )
return 0 ;
if ( f > max )
return 255 ;
return ( int ) ( 255.0f * ( f - min ) / ( max - min ) ) ;
2010-09-27 05:53:05 -05:00
}
2010-11-06 12:42:22 -05:00
# if defined(WIN32) && !defined(__GNUC__)
2011-09-21 21:05:19 -05:00
float restrict_flt ( float f , float min , float max )
2010-09-27 05:53:05 -05:00
# else
inline float restrict_flt ( float f , float min , float max )
# endif
{
2011-01-06 16:26:31 -06:00
if ( f < min )
return min ;
if ( f > max )
return max ;
return f ;
2010-09-27 05:53:05 -05:00
}
char * mystrdup ( char * s )
{
2011-01-06 16:26:31 -06:00
char * x ;
if ( s )
{
x = ( char * ) malloc ( strlen ( s ) + 1 ) ;
strcpy ( x , s ) ;
return x ;
}
return s ;
2010-09-27 05:53:05 -05:00
}
void strlist_add ( struct strlist * * list , char * str )
{
2011-01-06 16:26:31 -06:00
struct strlist * item = malloc ( sizeof ( struct strlist ) ) ;
item - > str = mystrdup ( str ) ;
item - > next = * list ;
* list = item ;
2010-09-27 05:53:05 -05:00
}
int strlist_find ( struct strlist * * list , char * str )
{
2011-01-06 16:26:31 -06:00
struct strlist * item ;
for ( item = * list ; item ; item = item - > next )
if ( ! strcmp ( item - > str , str ) )
return 1 ;
return 0 ;
2010-09-27 05:53:05 -05:00
}
void strlist_free ( struct strlist * * list )
{
2011-01-06 16:26:31 -06:00
struct strlist * item ;
while ( * list )
{
item = * list ;
* list = ( * list ) - > next ;
free ( item ) ;
}
2010-09-27 05:53:05 -05:00
}
2011-06-08 12:09:03 -05:00
void clean_text ( char * text , int vwidth )
{
int i = 0 ;
if ( textwidth ( text ) > vwidth ) {
text [ textwidthx ( text , vwidth ) ] = 0 ;
}
for ( i = 0 ; i < strlen ( text ) ; i + + ) {
if ( ! ( text [ i ] > = ' ' & & text [ i ] < 127 ) ) {
text [ i ] = ' ' ;
}
}
}
2010-09-27 05:53:05 -05:00
void save_presets ( int do_update )
{
2011-09-27 12:44:35 -05:00
char * outputdata ;
2011-11-14 10:41:01 -06:00
int count , i ;
cJSON * root , * userobj , * versionobj , * graphicsobj ;
2011-10-23 11:59:04 -05:00
FILE * f ;
root = cJSON_CreateObject ( ) ;
2011-09-27 12:44:35 -05:00
cJSON_AddStringToObject ( root , " Powder Toy Preferences " , " Don't modify this file unless you know what you're doing. P.S: editing the admin/mod fields in your user info doesn't give you magical powers " ) ;
//User Info
2011-09-30 11:41:02 -05:00
if ( svf_login ) {
cJSON_AddItemToObject ( root , " user " , userobj = cJSON_CreateObject ( ) ) ;
cJSON_AddStringToObject ( userobj , " name " , svf_user ) ;
cJSON_AddStringToObject ( userobj , " id " , svf_user_id ) ;
cJSON_AddStringToObject ( userobj , " session_id " , svf_session_id ) ;
if ( svf_admin ) {
cJSON_AddTrueToObject ( userobj , " admin " ) ;
cJSON_AddFalseToObject ( userobj , " mod " ) ;
} else if ( svf_mod ) {
cJSON_AddFalseToObject ( userobj , " admin " ) ;
cJSON_AddTrueToObject ( userobj , " mod " ) ;
} else {
cJSON_AddFalseToObject ( userobj , " admin " ) ;
cJSON_AddFalseToObject ( userobj , " mod " ) ;
}
2011-09-27 12:44:35 -05:00
}
//Version Info
cJSON_AddItemToObject ( root , " version " , versionobj = cJSON_CreateObject ( ) ) ;
cJSON_AddNumberToObject ( versionobj , " major " , SAVE_VERSION ) ;
cJSON_AddNumberToObject ( versionobj , " minor " , MINOR_VERSION ) ;
cJSON_AddNumberToObject ( versionobj , " build " , BUILD_NUM ) ;
if ( do_update ) {
cJSON_AddTrueToObject ( versionobj , " update " ) ;
} else {
cJSON_AddFalseToObject ( versionobj , " update " ) ;
}
2011-11-14 10:41:01 -06:00
//Display settings
cJSON_AddItemToObject ( root , " graphics " , graphicsobj = cJSON_CreateObject ( ) ) ;
cJSON_AddNumberToObject ( graphicsobj , " colour " , colour_mode ) ;
count = 0 ; i = 0 ; while ( display_modes [ i + + ] ) { count + + ; }
cJSON_AddItemToObject ( graphicsobj , " display " , cJSON_CreateIntArray ( display_modes , count ) ) ;
count = 0 ; i = 0 ; while ( render_modes [ i + + ] ) { count + + ; }
cJSON_AddItemToObject ( graphicsobj , " render " , cJSON_CreateIntArray ( render_modes , count ) ) ;
2011-09-27 12:44:35 -05:00
//General settings
cJSON_AddStringToObject ( root , " proxy " , http_proxy_string ) ;
cJSON_AddNumberToObject ( root , " scale " , sdl_scale ) ;
outputdata = cJSON_Print ( root ) ;
cJSON_Delete ( root ) ;
2011-10-23 11:59:04 -05:00
f = fopen ( " powder.pref " , " wb " ) ;
2011-09-27 12:44:35 -05:00
if ( ! f )
return ;
fwrite ( outputdata , 1 , strlen ( outputdata ) , f ) ;
fclose ( f ) ;
2011-11-14 10:41:01 -06:00
free ( outputdata ) ;
//Old format, here for reference only
2011-09-27 12:44:35 -05:00
/*FILE *f=fopen("powder.def", "wb");
2011-09-24 11:13:28 -05:00
unsigned char sig [ 4 ] = { 0x50 , 0x44 , 0x65 , 0x68 } ;
2011-01-06 16:26:31 -06:00
unsigned char tmp = sdl_scale ;
if ( ! f )
return ;
fwrite ( sig , 1 , 4 , f ) ;
save_string ( f , svf_user ) ;
2011-01-29 06:19:48 -06:00
//save_string(f, svf_pass);
save_string ( f , svf_user_id ) ;
save_string ( f , svf_session_id ) ;
2011-01-06 16:26:31 -06:00
fwrite ( & tmp , 1 , 1 , f ) ;
tmp = cmode ;
fwrite ( & tmp , 1 , 1 , f ) ;
tmp = svf_admin ;
fwrite ( & tmp , 1 , 1 , f ) ;
tmp = svf_mod ;
fwrite ( & tmp , 1 , 1 , f ) ;
save_string ( f , http_proxy_string ) ;
2011-09-25 04:33:49 -05:00
tmp = SAVE_VERSION ;
2011-01-06 16:26:31 -06:00
fwrite ( & tmp , 1 , 1 , f ) ;
tmp = MINOR_VERSION ;
fwrite ( & tmp , 1 , 1 , f ) ;
2011-09-24 11:13:28 -05:00
tmp = BUILD_NUM ;
fwrite ( & tmp , 1 , 1 , f ) ;
2011-01-06 16:26:31 -06:00
tmp = do_update ;
fwrite ( & tmp , 1 , 1 , f ) ;
2011-09-27 12:44:35 -05:00
fclose ( f ) ; */
2010-09-27 05:53:05 -05:00
}
2011-01-31 10:54:13 -06:00
int sregexp ( const char * str , char * pattern )
{
int result ;
regex_t patternc ;
2011-04-08 05:09:42 -05:00
if ( regcomp ( & patternc , pattern , 0 ) ! = 0 )
2011-01-31 10:54:13 -06:00
return 1 ;
result = regexec ( & patternc , str , 0 , NULL , 0 ) ;
regfree ( & patternc ) ;
return result ;
}
2010-09-27 05:53:05 -05:00
void load_presets ( void )
{
2011-11-14 10:41:01 -06:00
int prefdatasize = 0 , i , count ;
2011-09-27 12:44:35 -05:00
char * prefdata = file_load ( " powder.pref " , & prefdatasize ) ;
2012-01-24 12:14:19 -06:00
cJSON * root ;
if ( prefdata & & ( root = cJSON_Parse ( prefdata ) ) )
2011-01-06 16:26:31 -06:00
{
2012-01-24 12:14:19 -06:00
cJSON * userobj , * versionobj , * tmpobj , * graphicsobj , * tmparray ;
2011-09-27 12:44:35 -05:00
//Read user data
userobj = cJSON_GetObjectItem ( root , " user " ) ;
2011-09-30 11:41:02 -05:00
if ( userobj ) {
svf_login = 1 ;
2011-09-27 12:44:35 -05:00
if ( ( tmpobj = cJSON_GetObjectItem ( userobj , " name " ) ) & & tmpobj - > type = = cJSON_String ) strncpy ( svf_user , tmpobj - > valuestring , 63 ) ; else svf_user [ 0 ] = 0 ;
if ( ( tmpobj = cJSON_GetObjectItem ( userobj , " id " ) ) & & tmpobj - > type = = cJSON_String ) strncpy ( svf_user_id , tmpobj - > valuestring , 63 ) ; else svf_user_id [ 0 ] = 0 ;
if ( ( tmpobj = cJSON_GetObjectItem ( userobj , " session_id " ) ) & & tmpobj - > type = = cJSON_String ) strncpy ( svf_session_id , tmpobj - > valuestring , 63 ) ; else svf_session_id [ 0 ] = 0 ;
if ( ( tmpobj = cJSON_GetObjectItem ( userobj , " admin " ) ) & & tmpobj - > type = = cJSON_True ) {
svf_admin = 1 ;
svf_mod = 0 ;
} else if ( ( tmpobj = cJSON_GetObjectItem ( userobj , " mod " ) ) & & tmpobj - > type = = cJSON_True ) {
svf_mod = 1 ;
svf_admin = 0 ;
} else {
svf_admin = 0 ;
svf_mod = 0 ;
}
} else {
2011-09-30 11:41:02 -05:00
svf_login = 0 ;
2011-09-27 12:44:35 -05:00
svf_user [ 0 ] = 0 ;
svf_user_id [ 0 ] = 0 ;
svf_session_id [ 0 ] = 0 ;
svf_admin = 0 ;
svf_mod = 0 ;
}
//Read version data
versionobj = cJSON_GetObjectItem ( root , " version " ) ;
if ( versionobj ) {
if ( tmpobj = cJSON_GetObjectItem ( versionobj , " major " ) ) last_major = tmpobj - > valueint ;
if ( tmpobj = cJSON_GetObjectItem ( versionobj , " minor " ) ) last_minor = tmpobj - > valueint ;
if ( tmpobj = cJSON_GetObjectItem ( versionobj , " build " ) ) last_build = tmpobj - > valueint ;
if ( ( tmpobj = cJSON_GetObjectItem ( versionobj , " update " ) ) & & tmpobj - > type = = cJSON_True )
update_flag = 1 ;
else
update_flag = 0 ;
} else {
last_major = 0 ;
last_minor = 0 ;
last_build = 0 ;
update_flag = 0 ;
}
2011-11-14 10:41:01 -06:00
//Read display settings
graphicsobj = cJSON_GetObjectItem ( root , " graphics " ) ;
if ( graphicsobj )
{
if ( tmpobj = cJSON_GetObjectItem ( graphicsobj , " colour " ) ) colour_mode = tmpobj - > valueint ;
if ( tmpobj = cJSON_GetObjectItem ( graphicsobj , " display " ) )
{
count = cJSON_GetArraySize ( tmpobj ) ;
free ( display_modes ) ;
display_mode = 0 ;
display_modes = calloc ( count + 1 , sizeof ( unsigned int ) ) ;
for ( i = 0 ; i < count ; i + + )
{
display_mode | = cJSON_GetArrayItem ( tmpobj , i ) - > valueint ;
display_modes [ i ] = cJSON_GetArrayItem ( tmpobj , i ) - > valueint ;
}
}
if ( tmpobj = cJSON_GetObjectItem ( graphicsobj , " render " ) )
{
count = cJSON_GetArraySize ( tmpobj ) ;
free ( render_modes ) ;
render_mode = 0 ;
render_modes = calloc ( count + 1 , sizeof ( unsigned int ) ) ;
for ( i = 0 ; i < count ; i + + )
{
render_mode | = cJSON_GetArrayItem ( tmpobj , i ) - > valueint ;
render_modes [ i ] = cJSON_GetArrayItem ( tmpobj , i ) - > valueint ;
}
}
}
2011-09-27 12:44:35 -05:00
//Read general settings
if ( ( tmpobj = cJSON_GetObjectItem ( root , " proxy " ) ) & & tmpobj - > type = = cJSON_String ) strncpy ( http_proxy_string , tmpobj - > valuestring , 255 ) ; else http_proxy_string [ 0 ] = 0 ;
2011-11-12 14:44:15 -06:00
//TODO: Translate old cmode value into new *_mode values
2011-09-27 12:44:35 -05:00
if ( tmpobj = cJSON_GetObjectItem ( root , " scale " ) ) sdl_scale = tmpobj - > valueint ;
cJSON_Delete ( root ) ;
2011-11-14 10:41:01 -06:00
free ( prefdata ) ;
2011-09-27 12:44:35 -05:00
} else { //Fallback and read from old def file
FILE * f = fopen ( " powder.def " , " rb " ) ;
unsigned char sig [ 4 ] , tmp ;
if ( ! f )
return ;
fread ( sig , 1 , 4 , f ) ;
if ( sig [ 0 ] ! = 0x50 | | sig [ 1 ] ! = 0x44 | | sig [ 2 ] ! = 0x65 )
2011-01-06 16:26:31 -06:00
{
2011-09-27 12:44:35 -05:00
if ( sig [ 0 ] = = 0x4D & & sig [ 1 ] = = 0x6F & & sig [ 2 ] = = 0x46 & & sig [ 3 ] = = 0x6F )
2011-01-06 16:26:31 -06:00
{
2011-09-27 12:44:35 -05:00
if ( fseek ( f , - 3 , SEEK_END ) )
{
remove ( " powder.def " ) ;
return ;
}
if ( fread ( sig , 1 , 3 , f ) ! = 3 )
{
remove ( " powder.def " ) ;
goto fail ;
}
//last_major = sig[0];
//last_minor = sig[1];
last_build = 0 ;
update_flag = sig [ 2 ] ;
2011-01-06 16:26:31 -06:00
}
2011-09-27 12:44:35 -05:00
fclose ( f ) ;
remove ( " powder.def " ) ;
return ;
}
if ( sig [ 3 ] = = 0x66 ) {
if ( load_string ( f , svf_user , 63 ) )
goto fail ;
if ( load_string ( f , svf_pass , 63 ) )
goto fail ;
} else {
if ( load_string ( f , svf_user , 63 ) )
goto fail ;
if ( load_string ( f , svf_user_id , 63 ) )
goto fail ;
if ( load_string ( f , svf_session_id , 63 ) )
2011-01-06 16:26:31 -06:00
goto fail ;
}
2011-09-27 12:44:35 -05:00
svf_login = ! ! svf_session_id [ 0 ] ;
if ( fread ( & tmp , 1 , 1 , f ) ! = 1 )
2011-02-04 06:16:45 -06:00
goto fail ;
2011-09-27 12:44:35 -05:00
sdl_scale = ( tmp = = 2 ) ? 2 : 1 ;
if ( fread ( & tmp , 1 , 1 , f ) ! = 1 )
2011-02-04 06:16:45 -06:00
goto fail ;
2011-11-12 14:44:15 -06:00
//TODO: Translate old cmode value into new *_mode values
//cmode = tmp%CM_COUNT;
2011-09-27 12:44:35 -05:00
if ( fread ( & tmp , 1 , 1 , f ) ! = 1 )
2011-02-04 06:16:45 -06:00
goto fail ;
2011-09-27 12:44:35 -05:00
svf_admin = tmp ;
if ( fread ( & tmp , 1 , 1 , f ) ! = 1 )
2011-02-04 06:16:45 -06:00
goto fail ;
2011-09-27 12:44:35 -05:00
svf_mod = tmp ;
if ( load_string ( f , http_proxy_string , 255 ) )
2011-02-04 06:16:45 -06:00
goto fail ;
2011-09-24 11:13:28 -05:00
2011-09-27 12:44:35 -05:00
if ( sig [ 3 ] ! = 0x68 ) { //Pre v64 format
if ( fread ( sig , 1 , 3 , f ) ! = 3 )
goto fail ;
last_build = 0 ;
} else {
if ( fread ( sig , 1 , 4 , f ) ! = 4 )
goto fail ;
last_build = sig [ 3 ] ;
}
last_major = sig [ 0 ] ;
last_minor = sig [ 1 ] ;
update_flag = sig [ 2 ] ;
fail :
fclose ( f ) ;
2011-09-24 11:13:28 -05:00
}
2010-09-27 05:53:05 -05:00
}
void save_string ( FILE * f , char * str )
{
2011-01-06 16:26:31 -06:00
int li = strlen ( str ) ;
unsigned char lb [ 2 ] ;
lb [ 0 ] = li ;
lb [ 1 ] = li > > 8 ;
fwrite ( lb , 2 , 1 , f ) ;
fwrite ( str , li , 1 , f ) ;
2010-09-27 05:53:05 -05:00
}
int load_string ( FILE * f , char * str , int max )
{
2011-01-06 16:26:31 -06:00
int li ;
unsigned char lb [ 2 ] ;
fread ( lb , 2 , 1 , f ) ;
li = lb [ 0 ] | ( lb [ 1 ] < < 8 ) ;
if ( li > max )
{
str [ 0 ] = 0 ;
return 1 ;
}
fread ( str , li , 1 , f ) ;
str [ li ] = 0 ;
return 0 ;
2010-09-27 05:53:05 -05:00
}
void strcaturl ( char * dst , char * src )
{
2011-01-06 16:26:31 -06:00
char * d ;
unsigned char * s ;
2010-09-27 05:53:05 -05:00
2011-01-06 16:26:31 -06:00
for ( d = dst ; * d ; d + + ) ;
2010-09-27 05:53:05 -05:00
2011-01-06 16:26:31 -06:00
for ( s = ( unsigned char * ) src ; * s ; s + + )
{
if ( ( * s > = ' 0 ' & & * s < = ' 9 ' ) | |
( * s > = ' a ' & & * s < = ' z ' ) | |
( * s > = ' A ' & & * s < = ' Z ' ) )
* ( d + + ) = * s ;
else
{
* ( d + + ) = ' % ' ;
* ( d + + ) = hex [ * s > > 4 ] ;
* ( d + + ) = hex [ * s & 15 ] ;
}
}
* d = 0 ;
2010-09-27 05:53:05 -05:00
}
void strappend ( char * dst , char * src )
{
2011-01-06 16:26:31 -06:00
char * d ;
unsigned char * s ;
2010-09-27 05:53:05 -05:00
2011-01-06 16:26:31 -06:00
for ( d = dst ; * d ; d + + ) ;
2010-09-27 05:53:05 -05:00
2011-01-06 16:26:31 -06:00
for ( s = ( unsigned char * ) src ; * s ; s + + )
{
* ( d + + ) = * s ;
}
* d = 0 ;
2010-09-27 05:53:05 -05:00
}
void * file_load ( char * fn , int * size )
{
2011-01-06 16:26:31 -06:00
FILE * f = fopen ( fn , " rb " ) ;
void * s ;
2010-09-27 05:53:05 -05:00
2011-01-06 16:26:31 -06:00
if ( ! f )
return NULL ;
fseek ( f , 0 , SEEK_END ) ;
* size = ftell ( f ) ;
fseek ( f , 0 , SEEK_SET ) ;
s = malloc ( * size ) ;
if ( ! s )
{
fclose ( f ) ;
return NULL ;
}
fread ( s , * size , 1 , f ) ;
fclose ( f ) ;
return s ;
2010-09-27 05:53:05 -05:00
}
int cpu_check ( void )
{
# ifdef MACOSX
2011-01-06 16:26:31 -06:00
return 0 ;
2010-09-27 05:53:05 -05:00
# else
# ifdef X86
2011-01-06 16:26:31 -06:00
unsigned af , bf , cf , df ;
x86_cpuid ( 0 , af , bf , cf , df ) ;
if ( bf = = 0x68747541 & & cf = = 0x444D4163 & & df = = 0x69746E65 )
amd = 1 ;
x86_cpuid ( 1 , af , bf , cf , df ) ;
2010-09-27 05:53:05 -05:00
# ifdef X86_SSE
2011-01-06 16:26:31 -06:00
if ( ! ( df & ( 1 < < 25 ) ) )
return 1 ;
2010-09-27 05:53:05 -05:00
# endif
# ifdef X86_SSE2
2011-01-06 16:26:31 -06:00
if ( ! ( df & ( 1 < < 26 ) ) )
return 1 ;
2010-09-27 05:53:05 -05:00
# endif
# ifdef X86_SSE3
2011-01-06 16:26:31 -06:00
if ( ! ( cf & 1 ) )
return 1 ;
2010-09-27 05:53:05 -05:00
# endif
# endif
# endif
2011-01-06 16:26:31 -06:00
return 0 ;
2010-12-05 09:49:48 -06:00
}
2011-03-18 07:46:06 -05:00
matrix2d m2d_multiply_m2d ( matrix2d m1 , matrix2d m2 )
{
matrix2d result = {
m1 . a * m2 . a + m1 . b * m2 . c , m1 . a * m2 . b + m1 . b * m2 . d ,
m1 . c * m2 . a + m1 . d * m2 . c , m1 . c * m2 . b + m1 . d * m2 . d
} ;
return result ;
}
vector2d m2d_multiply_v2d ( matrix2d m , vector2d v )
{
vector2d result = {
m . a * v . x + m . b * v . y ,
m . c * v . x + m . d * v . y
} ;
return result ;
}
matrix2d m2d_multiply_float ( matrix2d m , float s )
{
matrix2d result = {
m . a * s , m . b * s ,
m . c * s , m . d * s ,
} ;
return result ;
}
vector2d v2d_multiply_float ( vector2d v , float s )
{
vector2d result = {
v . x * s ,
v . y * s
} ;
return result ;
}
vector2d v2d_add ( vector2d v1 , vector2d v2 )
{
vector2d result = {
v1 . x + v2 . x ,
v1 . y + v2 . y
} ;
return result ;
}
vector2d v2d_sub ( vector2d v1 , vector2d v2 )
{
vector2d result = {
v1 . x - v2 . x ,
v1 . y - v2 . y
} ;
return result ;
}
matrix2d m2d_new ( float me0 , float me1 , float me2 , float me3 )
{
matrix2d result = { me0 , me1 , me2 , me3 } ;
return result ;
}
vector2d v2d_new ( float x , float y )
{
vector2d result = { x , y } ;
return result ;
}
2011-03-24 16:18:58 -05:00
void clipboard_push_text ( char * text )
2011-03-24 16:21:21 -05:00
{
2011-04-01 18:00:19 -05:00
# ifdef MACOSX
2011-04-08 05:09:42 -05:00
PasteboardRef newclipboard ;
if ( PasteboardCreate ( kPasteboardClipboard , & newclipboard ) ! = noErr ) return ;
if ( PasteboardClear ( newclipboard ) ! = noErr ) return ;
2011-04-01 18:00:19 -05:00
PasteboardSynchronize ( newclipboard ) ;
2011-04-08 05:09:42 -05:00
2011-04-01 18:00:19 -05:00
CFDataRef data = CFDataCreate ( kCFAllocatorDefault , text , strlen ( text ) ) ;
2011-04-08 05:09:42 -05:00
PasteboardPutItemFlavor ( newclipboard , ( PasteboardItemID ) 1 , CFSTR ( " com.apple.traditional-mac-plain-text " ) , data , 0 ) ;
2011-04-04 11:07:38 -05:00
# elif defined WIN32
2011-04-08 05:09:42 -05:00
if ( OpenClipboard ( NULL ) )
2011-04-04 11:07:38 -05:00
{
HGLOBAL cbuffer ;
char * glbuffer ;
2011-04-08 05:09:42 -05:00
2011-04-04 11:07:38 -05:00
EmptyClipboard ( ) ;
2011-04-08 05:09:42 -05:00
2011-04-04 11:07:38 -05:00
cbuffer = GlobalAlloc ( GMEM_DDESHARE , strlen ( text ) + 1 ) ;
glbuffer = ( char * ) GlobalLock ( cbuffer ) ;
2011-04-08 05:09:42 -05:00
2011-04-04 11:07:38 -05:00
strcpy ( glbuffer , text ) ;
2011-04-08 05:09:42 -05:00
2011-04-04 11:07:38 -05:00
GlobalUnlock ( cbuffer ) ;
SetClipboardData ( CF_TEXT , cbuffer ) ;
CloseClipboard ( ) ;
}
2011-04-22 18:20:56 -05:00
# elif (defined(LIN32) || defined(LIN64)) && defined(SDL_VIDEO_DRIVER_X11)
if ( clipboard_text ! = NULL ) {
free ( clipboard_text ) ;
clipboard_text = NULL ;
}
clipboard_text = mystrdup ( text ) ;
sdl_wminfo . info . x11 . lock_func ( ) ;
XSetSelectionOwner ( sdl_wminfo . info . x11 . display , XA_CLIPBOARD , sdl_wminfo . info . x11 . window , CurrentTime ) ;
XFlush ( sdl_wminfo . info . x11 . display ) ;
sdl_wminfo . info . x11 . unlock_func ( ) ;
2011-04-08 05:09:42 -05:00
# else
2011-03-24 16:21:21 -05:00
printf ( " Not implemented: put text on clipboard \" %s \" \n " , text ) ;
2011-04-01 18:00:19 -05:00
# endif
2011-03-24 16:18:58 -05:00
}
char * clipboard_pull_text ( )
{
2011-07-06 08:01:47 -05:00
# ifdef MACOSX
2012-04-30 18:48:17 -05:00
printf ( " Not implemented: get text from clipboard \n " ) ;
2011-07-06 08:01:47 -05:00
# elif defined WIN32
if ( OpenClipboard ( NULL ) )
{
HANDLE cbuffer ;
char * glbuffer ;
cbuffer = GetClipboardData ( CF_TEXT ) ;
glbuffer = ( char * ) GlobalLock ( cbuffer ) ;
GlobalUnlock ( cbuffer ) ;
CloseClipboard ( ) ;
if ( glbuffer ! = NULL ) {
return mystrdup ( glbuffer ) ;
} else {
return " " ;
}
}
# elif (defined(LIN32) || defined(LIN64)) && defined(SDL_VIDEO_DRIVER_X11)
2012-04-30 18:48:17 -05:00
printf ( " Not implemented: get text from clipboard \n " ) ;
2011-07-06 08:01:47 -05:00
# else
2011-03-24 16:21:21 -05:00
printf ( " Not implemented: get text from clipboard \n " ) ;
2011-07-06 08:01:47 -05:00
# endif
2012-04-30 18:48:17 -05:00
return " " ;
2011-03-24 16:18:58 -05:00
}
2011-03-25 06:10:01 -05:00
int register_extension ( )
{
# if defined WIN32
2011-09-19 15:31:10 -05:00
int returnval ;
2011-03-25 06:10:01 -05:00
LONG rresult ;
HKEY newkey ;
2011-04-06 09:21:42 -05:00
char * currentfilename = exe_name ( ) ;
2011-09-10 07:33:24 -05:00
char * iconname = NULL ;
char * opencommand = NULL ;
2012-05-23 12:37:11 -05:00
char * protocolcommand = NULL ;
2011-10-06 16:12:35 -05:00
//char AppDataPath[MAX_PATH];
char * AppDataPath = NULL ;
2011-03-27 12:13:52 -05:00
iconname = malloc ( strlen ( currentfilename ) + 6 ) ;
2011-04-04 10:28:43 -05:00
sprintf ( iconname , " %s,-102 " , currentfilename ) ;
2011-09-19 15:31:10 -05:00
//Create Roaming application data folder
2011-10-06 16:12:35 -05:00
/*if(!SUCCEEDED(SHGetFolderPath(NULL, CSIDL_APPDATA|CSIDL_FLAG_CREATE, NULL, 0, AppDataPath)))
2011-09-19 15:31:10 -05:00
{
returnval = 0 ;
goto finalise ;
2011-10-06 16:12:35 -05:00
} */
AppDataPath = _getcwd ( NULL , 0 ) ;
2011-09-19 15:31:10 -05:00
//Move Game executable into application data folder
//TODO: Implement
opencommand = malloc ( strlen ( currentfilename ) + 53 + strlen ( AppDataPath ) ) ;
2012-05-23 12:37:11 -05:00
protocolcommand = malloc ( strlen ( currentfilename ) + 55 + strlen ( AppDataPath ) ) ;
2011-10-06 16:12:35 -05:00
/*if((strlen(AppDataPath)+strlen(APPDATA_SUBDIR "\\Powder Toy"))<MAX_PATH)
2011-09-19 15:31:10 -05:00
{
strappend ( AppDataPath , APPDATA_SUBDIR ) ;
2011-09-27 06:49:11 -05:00
_mkdir ( AppDataPath ) ;
2011-09-19 15:31:10 -05:00
strappend ( AppDataPath , " \\ Powder Toy " ) ;
2011-09-27 06:49:11 -05:00
_mkdir ( AppDataPath ) ;
2011-09-19 15:31:10 -05:00
} else {
returnval = 0 ;
goto finalise ;
2011-10-06 16:12:35 -05:00
} */
2011-09-19 15:31:10 -05:00
sprintf ( opencommand , " \" %s \" open \" %%1 \" ddir \" %s \" " , currentfilename , AppDataPath ) ;
2012-05-23 12:37:11 -05:00
sprintf ( protocolcommand , " \" %s \" ddir \" %s \" ptsave \" %%1 \" " , currentfilename , AppDataPath ) ;
2011-04-08 05:09:42 -05:00
2012-05-23 12:37:11 -05:00
//Create protocol entry
rresult = RegCreateKeyEx ( HKEY_CURRENT_USER , " Software \\ Classes \\ ptsave " , 0 , 0 , REG_OPTION_NON_VOLATILE , KEY_ALL_ACCESS , NULL , & newkey , NULL ) ;
if ( rresult ! = ERROR_SUCCESS ) {
returnval = 0 ;
goto finalise ;
}
rresult = RegSetValueEx ( newkey , 0 , 0 , REG_SZ , ( LPBYTE ) " Powder Toy Save " , strlen ( " Powder Toy Save " ) + 1 ) ;
if ( rresult ! = ERROR_SUCCESS ) {
RegCloseKey ( newkey ) ;
returnval = 0 ;
goto finalise ;
}
rresult = RegSetValueEx ( newkey , ( LPBYTE ) " URL Protocol " , 0 , REG_SZ , ( LPBYTE ) " " , strlen ( " " ) + 1 ) ;
if ( rresult ! = ERROR_SUCCESS ) {
RegCloseKey ( newkey ) ;
returnval = 0 ;
goto finalise ;
}
RegCloseKey ( newkey ) ;
//Set Protocol DefaultIcon
rresult = RegCreateKeyEx ( HKEY_CURRENT_USER , " Software \\ Classes \\ ptsave \\ DefaultIcon " , 0 , 0 , REG_OPTION_NON_VOLATILE , KEY_ALL_ACCESS , NULL , & newkey , NULL ) ;
if ( rresult ! = ERROR_SUCCESS ) {
returnval = 0 ;
goto finalise ;
}
rresult = RegSetValueEx ( newkey , 0 , 0 , REG_SZ , ( LPBYTE ) iconname , strlen ( iconname ) + 1 ) ;
if ( rresult ! = ERROR_SUCCESS ) {
RegCloseKey ( newkey ) ;
returnval = 0 ;
goto finalise ;
}
RegCloseKey ( newkey ) ;
//Set Protocol Launch command
rresult = RegCreateKeyEx ( HKEY_CURRENT_USER , " Software \\ Classes \\ ptsave \\ shell \\ open \\ command " , 0 , 0 , REG_OPTION_NON_VOLATILE , KEY_ALL_ACCESS , NULL , & newkey , NULL ) ;
if ( rresult ! = ERROR_SUCCESS ) {
returnval = 0 ;
goto finalise ;
}
rresult = RegSetValueEx ( newkey , 0 , 0 , REG_SZ , ( LPBYTE ) protocolcommand , strlen ( protocolcommand ) + 1 ) ;
if ( rresult ! = ERROR_SUCCESS ) {
RegCloseKey ( newkey ) ;
returnval = 0 ;
goto finalise ;
}
RegCloseKey ( newkey ) ;
2011-03-25 06:10:01 -05:00
//Create extension entry
rresult = RegCreateKeyEx ( HKEY_CURRENT_USER , " Software \\ Classes \\ .cps " , 0 , 0 , REG_OPTION_NON_VOLATILE , KEY_ALL_ACCESS , NULL , & newkey , NULL ) ;
2011-04-08 05:09:42 -05:00
if ( rresult ! = ERROR_SUCCESS ) {
2011-09-19 15:31:10 -05:00
returnval = 0 ;
goto finalise ;
2011-03-25 06:10:01 -05:00
}
rresult = RegSetValueEx ( newkey , 0 , 0 , REG_SZ , ( LPBYTE ) " PowderToySave " , strlen ( " PowderToySave " ) + 1 ) ;
2011-04-08 05:09:42 -05:00
if ( rresult ! = ERROR_SUCCESS ) {
2011-03-25 06:10:01 -05:00
RegCloseKey ( newkey ) ;
2011-09-19 15:31:10 -05:00
returnval = 0 ;
goto finalise ;
2011-03-25 06:10:01 -05:00
}
RegCloseKey ( newkey ) ;
2011-04-08 05:09:42 -05:00
2011-04-06 09:21:42 -05:00
rresult = RegCreateKeyEx ( HKEY_CURRENT_USER , " Software \\ Classes \\ .stm " , 0 , 0 , REG_OPTION_NON_VOLATILE , KEY_ALL_ACCESS , NULL , & newkey , NULL ) ;
if ( rresult ! = ERROR_SUCCESS ) {
2011-09-19 15:31:10 -05:00
returnval = 0 ;
goto finalise ;
2011-04-06 09:21:42 -05:00
}
rresult = RegSetValueEx ( newkey , 0 , 0 , REG_SZ , ( LPBYTE ) " PowderToySave " , strlen ( " PowderToySave " ) + 1 ) ;
if ( rresult ! = ERROR_SUCCESS ) {
RegCloseKey ( newkey ) ;
2011-09-19 15:31:10 -05:00
returnval = 0 ;
goto finalise ;
2011-04-06 09:21:42 -05:00
}
RegCloseKey ( newkey ) ;
2012-05-23 12:37:11 -05:00
2011-03-25 06:10:01 -05:00
//Create program entry
rresult = RegCreateKeyEx ( HKEY_CURRENT_USER , " Software \\ Classes \\ PowderToySave " , 0 , 0 , REG_OPTION_NON_VOLATILE , KEY_ALL_ACCESS , NULL , & newkey , NULL ) ;
2011-04-08 05:09:42 -05:00
if ( rresult ! = ERROR_SUCCESS ) {
2011-09-19 15:31:10 -05:00
returnval = 0 ;
goto finalise ;
2011-03-25 06:10:01 -05:00
}
rresult = RegSetValueEx ( newkey , 0 , 0 , REG_SZ , ( LPBYTE ) " Powder Toy Save " , strlen ( " Powder Toy Save " ) + 1 ) ;
2011-04-08 05:09:42 -05:00
if ( rresult ! = ERROR_SUCCESS ) {
2011-03-25 06:10:01 -05:00
RegCloseKey ( newkey ) ;
2011-09-19 15:31:10 -05:00
returnval = 0 ;
goto finalise ;
2011-03-25 06:10:01 -05:00
}
RegCloseKey ( newkey ) ;
2011-04-08 05:09:42 -05:00
2011-03-25 06:10:01 -05:00
//Set DefaultIcon
rresult = RegCreateKeyEx ( HKEY_CURRENT_USER , " Software \\ Classes \\ PowderToySave \\ DefaultIcon " , 0 , 0 , REG_OPTION_NON_VOLATILE , KEY_ALL_ACCESS , NULL , & newkey , NULL ) ;
2011-04-08 05:09:42 -05:00
if ( rresult ! = ERROR_SUCCESS ) {
2011-09-19 15:31:10 -05:00
returnval = 0 ;
goto finalise ;
2011-03-25 06:10:01 -05:00
}
rresult = RegSetValueEx ( newkey , 0 , 0 , REG_SZ , ( LPBYTE ) iconname , strlen ( iconname ) + 1 ) ;
2011-04-08 05:09:42 -05:00
if ( rresult ! = ERROR_SUCCESS ) {
2011-03-25 06:10:01 -05:00
RegCloseKey ( newkey ) ;
2011-09-19 15:31:10 -05:00
returnval = 0 ;
goto finalise ;
2011-03-25 06:10:01 -05:00
}
RegCloseKey ( newkey ) ;
2011-04-08 05:09:42 -05:00
2011-03-25 06:10:01 -05:00
//Set Launch command
rresult = RegCreateKeyEx ( HKEY_CURRENT_USER , " Software \\ Classes \\ PowderToySave \\ shell \\ open \\ command " , 0 , 0 , REG_OPTION_NON_VOLATILE , KEY_ALL_ACCESS , NULL , & newkey , NULL ) ;
2011-04-08 05:09:42 -05:00
if ( rresult ! = ERROR_SUCCESS ) {
2011-09-19 15:31:10 -05:00
returnval = 0 ;
goto finalise ;
2011-03-25 06:10:01 -05:00
}
rresult = RegSetValueEx ( newkey , 0 , 0 , REG_SZ , ( LPBYTE ) opencommand , strlen ( opencommand ) + 1 ) ;
2011-04-08 05:09:42 -05:00
if ( rresult ! = ERROR_SUCCESS ) {
2011-03-25 06:10:01 -05:00
RegCloseKey ( newkey ) ;
2011-09-19 15:31:10 -05:00
returnval = 0 ;
goto finalise ;
2011-03-25 06:10:01 -05:00
}
RegCloseKey ( newkey ) ;
2011-09-19 15:31:10 -05:00
returnval = 1 ;
finalise :
2011-04-08 05:09:42 -05:00
2011-09-10 07:33:24 -05:00
if ( iconname ) free ( iconname ) ;
if ( opencommand ) free ( opencommand ) ;
if ( currentfilename ) free ( currentfilename ) ;
2012-05-23 12:37:11 -05:00
if ( protocolcommand ) free ( protocolcommand ) ;
2011-09-10 07:33:24 -05:00
2011-09-19 15:31:10 -05:00
return returnval ;
2011-04-06 12:12:05 -05:00
# elif defined(LIN32) || defined(LIN64)
char * currentfilename = exe_name ( ) ;
FILE * f ;
char * mimedata =
" <?xml version= \" 1.0 \" ?> \n "
" <mime-info xmlns='http://www.freedesktop.org/standards/shared-mime-info'> \n "
" <mime-type type= \" application/vnd.powdertoy.save \" > \n "
" <comment>Powder Toy save</comment> \n "
" <glob pattern= \" *.cps \" /> \n "
" <glob pattern= \" *.stm \" /> \n "
" </mime-type> \n "
" </mime-info> \n " ;
f = fopen ( " powdertoy-save.xml " , " wb " ) ;
if ( ! f )
return 0 ;
fwrite ( mimedata , 1 , strlen ( mimedata ) , f ) ;
fclose ( f ) ;
char * desktopfiledata_tmp =
" [Desktop Entry] \n "
" Type=Application \n "
" Name=Powder Toy \n "
" Comment=Physics sandbox game \n "
" MimeType=application/vnd.powdertoy.save; \n "
" NoDisplay=true \n " ;
char * desktopfiledata = malloc ( strlen ( desktopfiledata_tmp ) + strlen ( currentfilename ) + 100 ) ;
strcpy ( desktopfiledata , desktopfiledata_tmp ) ;
strappend ( desktopfiledata , " Exec= " ) ;
strappend ( desktopfiledata , currentfilename ) ;
2011-04-06 16:21:07 -05:00
strappend ( desktopfiledata , " open %f \n " ) ;
2011-04-06 12:12:05 -05:00
f = fopen ( " powdertoy-tpt.desktop " , " wb " ) ;
if ( ! f )
return 0 ;
fwrite ( desktopfiledata , 1 , strlen ( desktopfiledata ) , f ) ;
fclose ( f ) ;
system ( " xdg-mime install powdertoy-save.xml " ) ;
system ( " xdg-desktop-menu install powdertoy-tpt.desktop " ) ;
2011-04-06 14:10:43 -05:00
f = fopen ( " powdertoy-save-32.png " , " wb " ) ;
if ( ! f )
return 0 ;
fwrite ( icon_doc_32_png , 1 , sizeof ( icon_doc_32_png ) , f ) ;
fclose ( f ) ;
f = fopen ( " powdertoy-save-16.png " , " wb " ) ;
if ( ! f )
return 0 ;
fwrite ( icon_doc_16_png , 1 , sizeof ( icon_doc_16_png ) , f ) ;
fclose ( f ) ;
system ( " xdg-icon-resource install --noupdate --context mimetypes --size 32 powdertoy-save-32.png application-vnd.powdertoy.save " ) ;
system ( " xdg-icon-resource install --noupdate --context mimetypes --size 16 powdertoy-save-16.png application-vnd.powdertoy.save " ) ;
system ( " xdg-icon-resource forceupdate " ) ;
system ( " xdg-mime default powdertoy-tpt.desktop application/vnd.powdertoy.save " ) ;
unlink ( " powdertoy-save-32.png " ) ;
unlink ( " powdertoy-save-16.png " ) ;
2011-04-06 12:12:05 -05:00
unlink ( " powdertoy-save.xml " ) ;
unlink ( " powdertoy-tpt.desktop " ) ;
return 1 ;
2011-03-25 06:57:04 -05:00
# elif defined MACOSX
2011-03-25 06:10:01 -05:00
return 0 ;
# endif
}
2011-03-24 16:18:58 -05:00
2011-05-29 21:18:47 -05:00
void HSV_to_RGB ( int h , int s , int v , int * r , int * g , int * b ) //convert 0-255(0-360 for H) HSV values to 0-255 RGB
2011-04-22 22:11:05 -05:00
{
float hh , ss , vv , c , x ;
int m ;
2011-05-29 21:18:47 -05:00
hh = h / 60.0f ; //normalize values
2011-05-10 14:32:00 -05:00
ss = s / 255.0f ;
vv = v / 255.0f ;
2011-04-22 22:11:05 -05:00
c = vv * ss ;
2011-05-29 21:18:47 -05:00
x = c * ( 1 - fabs ( fmod ( hh , 2.0 ) - 1 ) ) ;
2011-04-22 22:11:05 -05:00
if ( hh < 1 ) {
2011-05-10 14:32:00 -05:00
* r = ( int ) ( c * 255.0 ) ;
* g = ( int ) ( x * 255.0 ) ;
2011-04-22 22:11:05 -05:00
* b = 0 ;
}
else if ( hh < 2 ) {
2011-05-10 14:32:00 -05:00
* r = ( int ) ( x * 255.0 ) ;
* g = ( int ) ( c * 255.0 ) ;
2011-04-22 22:11:05 -05:00
* b = 0 ;
}
else if ( hh < 3 ) {
* r = 0 ;
2011-05-10 14:32:00 -05:00
* g = ( int ) ( c * 255.0 ) ;
* b = ( int ) ( x * 255.0 ) ;
2011-04-22 22:11:05 -05:00
}
else if ( hh < 4 ) {
* r = 0 ;
2011-05-10 14:32:00 -05:00
* g = ( int ) ( x * 255.0 ) ;
* b = ( int ) ( c * 255.0 ) ;
2011-04-22 22:11:05 -05:00
}
else if ( hh < 5 ) {
2011-05-10 14:32:00 -05:00
* r = ( int ) ( x * 255.0 ) ;
2011-04-22 22:11:05 -05:00
* g = 0 ;
2011-05-10 14:32:00 -05:00
* b = ( int ) ( c * 255.0 ) ;
2011-04-22 22:11:05 -05:00
}
else if ( hh < 6 ) {
2011-05-10 14:32:00 -05:00
* r = ( int ) ( c * 255.0 ) ;
2011-04-22 22:11:05 -05:00
* g = 0 ;
2011-05-10 14:32:00 -05:00
* b = ( int ) ( x * 255.0 ) ;
2011-04-22 22:11:05 -05:00
}
2011-05-10 14:32:00 -05:00
m = ( int ) ( ( vv - c ) * 255.0 ) ;
2011-04-22 22:11:05 -05:00
* r + = m ;
* g + = m ;
* b + = m ;
}
2011-05-29 21:18:47 -05:00
void RGB_to_HSV ( int r , int g , int b , int * h , int * s , int * v ) //convert 0-255 RGB values to 0-255(0-360 for H) HSV
2011-04-22 22:11:05 -05:00
{
float rr , gg , bb , a , x , c , d ;
2011-05-10 14:32:00 -05:00
rr = r / 255.0f ; //normalize values
gg = g / 255.0f ;
bb = b / 255.0f ;
2011-04-22 22:11:05 -05:00
a = fmin ( rr , gg ) ;
a = fmin ( a , bb ) ;
x = fmax ( rr , gg ) ;
x = fmax ( x , bb ) ;
if ( a = = x ) //greyscale
{
* h = 0 ;
* s = 0 ;
2011-05-10 14:32:00 -05:00
* v = ( int ) ( a * 255.0 ) ;
2011-04-22 22:11:05 -05:00
}
2011-04-22 22:20:15 -05:00
else
{
c = ( rr = = a ) ? gg - bb : ( ( bb = = a ) ? rr - gg : bb - rr ) ;
d = ( rr = = a ) ? 3 : ( ( bb = = a ) ? 1 : 5 ) ;
2011-05-29 21:18:47 -05:00
* h = ( int ) ( 60.0 * ( d - c / ( x - a ) ) ) ;
2011-05-10 14:32:00 -05:00
* s = ( int ) ( 255.0 * ( ( x - a ) / x ) ) ;
* v = ( int ) ( 255.0 * x ) ;
2011-04-22 22:20:15 -05:00
}
2011-04-22 22:11:05 -05:00
}
2011-06-09 16:35:00 -05:00
void membwand ( void * destv , void * srcv , size_t destsize , size_t srcsize )
{
size_t i ;
unsigned char * dest = destv ;
unsigned char * src = srcv ;
for ( i = 0 ; i < destsize ; i + + ) {
dest [ i ] = dest [ i ] & src [ i % srcsize ] ;
}
}
2011-03-18 07:46:06 -05:00
vector2d v2d_zero = { 0 , 0 } ;
matrix2d m2d_identity = { 1 , 0 , 0 , 1 } ;