1 2/* Jim - SDL extension 3 * Copyright 2005 Salvatore Sanfilippo <antirez@invece.org> 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * A copy of the license is also included in the source distribution 12 * of Jim, as a TXT file name called LICENSE. 13 * 14 * Unless required by applicable law or agreed to in writing, software 15 * distributed under the License is distributed on an "AS IS" BASIS, 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 * See the License for the specific language governing permissions and 18 * limitations under the License. 19 */ 20 21#include <stdio.h> 22#include <stdlib.h> 23#include <string.h> 24#include <errno.h> 25#include <SDL/SDL.h> 26#include <SDL/SDL_gfxPrimitives.h> 27 28#include "jim.h" 29#include "jimautoconf.h" 30 31#define AIO_CMD_LEN 128 32 33typedef struct JimSdlSurface 34{ 35 SDL_Surface *screen; 36} JimSdlSurface; 37 38static void JimSdlSetError(Jim_Interp *interp) 39{ 40 Jim_SetResultString(interp, SDL_GetError(), -1); 41} 42 43static void JimSdlDelProc(Jim_Interp *interp, void *privData) 44{ 45 JimSdlSurface *jss = privData; 46 47 JIM_NOTUSED(interp); 48 49 SDL_FreeSurface(jss->screen); 50 Jim_Free(jss); 51} 52 53/* Calls to commands created via [sdl.surface] are implemented by this 54 * C command. */ 55static int JimSdlHandlerCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) 56{ 57 JimSdlSurface *jss = Jim_CmdPrivData(interp); 58 int option; 59 static const char * const options[] = { 60 "free", "flip", "pixel", "rectangle", "box", "line", "aaline", 61 "circle", "aacircle", "fcircle", NULL 62 }; 63 enum 64 { OPT_FREE, OPT_FLIP, OPT_PIXEL, OPT_RECTANGLE, OPT_BOX, OPT_LINE, 65 OPT_AALINE, OPT_CIRCLE, OPT_AACIRCLE, OPT_FCIRCLE 66 }; 67 68 if (argc < 2) { 69 Jim_WrongNumArgs(interp, 1, argv, "method ?args ...?"); 70 return JIM_ERR; 71 } 72 if (Jim_GetEnum(interp, argv[1], options, &option, "SDL surface method", JIM_ERRMSG) != JIM_OK) 73 return JIM_ERR; 74 if (option == OPT_PIXEL) { 75 /* PIXEL */ 76 long x, y, red, green, blue, alpha = 255; 77 78 if (argc != 7 && argc != 8) { 79 Jim_WrongNumArgs(interp, 2, argv, "x y red green blue ?alpha?"); 80 return JIM_ERR; 81 } 82 if (Jim_GetLong(interp, argv[2], &x) != JIM_OK || 83 Jim_GetLong(interp, argv[3], &y) != JIM_OK || 84 Jim_GetLong(interp, argv[4], &red) != JIM_OK || 85 Jim_GetLong(interp, argv[5], &green) != JIM_OK || 86 Jim_GetLong(interp, argv[6], &blue) != JIM_OK) { 87 return JIM_ERR; 88 } 89 if (argc == 8 && Jim_GetLong(interp, argv[7], &alpha) != JIM_OK) 90 return JIM_ERR; 91 pixelRGBA(jss->screen, x, y, red, green, blue, alpha); 92 return JIM_OK; 93 } 94 else if (option == OPT_RECTANGLE || option == OPT_BOX || 95 option == OPT_LINE || option == OPT_AALINE) { 96 /* RECTANGLE, BOX, LINE, AALINE */ 97 long x1, y1, x2, y2, red, green, blue, alpha = 255; 98 99 if (argc != 9 && argc != 10) { 100 Jim_WrongNumArgs(interp, 2, argv, "x y red green blue ?alpha?"); 101 return JIM_ERR; 102 } 103 if (Jim_GetLong(interp, argv[2], &x1) != JIM_OK || 104 Jim_GetLong(interp, argv[3], &y1) != JIM_OK || 105 Jim_GetLong(interp, argv[4], &x2) != JIM_OK || 106 Jim_GetLong(interp, argv[5], &y2) != JIM_OK || 107 Jim_GetLong(interp, argv[6], &red) != JIM_OK || 108 Jim_GetLong(interp, argv[7], &green) != JIM_OK || 109 Jim_GetLong(interp, argv[8], &blue) != JIM_OK) { 110 return JIM_ERR; 111 } 112 if (argc == 10 && Jim_GetLong(interp, argv[9], &alpha) != JIM_OK) 113 return JIM_ERR; 114 switch (option) { 115 case OPT_RECTANGLE: 116 rectangleRGBA(jss->screen, x1, y1, x2, y2, red, green, blue, alpha); 117 break; 118 case OPT_BOX: 119 boxRGBA(jss->screen, x1, y1, x2, y2, red, green, blue, alpha); 120 break; 121 case OPT_LINE: 122 lineRGBA(jss->screen, x1, y1, x2, y2, red, green, blue, alpha); 123 break; 124 case OPT_AALINE: 125 aalineRGBA(jss->screen, x1, y1, x2, y2, red, green, blue, alpha); 126 break; 127 } 128 return JIM_OK; 129 } 130 else if (option == OPT_CIRCLE || option == OPT_AACIRCLE || option == OPT_FCIRCLE) { 131 /* CIRCLE, AACIRCLE, FCIRCLE */ 132 long x, y, radius, red, green, blue, alpha = 255; 133 134 if (argc != 8 && argc != 9) { 135 Jim_WrongNumArgs(interp, 2, argv, "x y radius red green blue ?alpha?"); 136 return JIM_ERR; 137 } 138 if (Jim_GetLong(interp, argv[2], &x) != JIM_OK || 139 Jim_GetLong(interp, argv[3], &y) != JIM_OK || 140 Jim_GetLong(interp, argv[4], &radius) != JIM_OK || 141 Jim_GetLong(interp, argv[5], &red) != JIM_OK || 142 Jim_GetLong(interp, argv[6], &green) != JIM_OK || 143 Jim_GetLong(interp, argv[7], &blue) != JIM_OK) { 144 return JIM_ERR; 145 } 146 if (argc == 9 && Jim_GetLong(interp, argv[8], &alpha) != JIM_OK) 147 return JIM_ERR; 148 switch (option) { 149 case OPT_CIRCLE: 150 circleRGBA(jss->screen, x, y, radius, red, green, blue, alpha); 151 break; 152 case OPT_AACIRCLE: 153 aacircleRGBA(jss->screen, x, y, radius, red, green, blue, alpha); 154 break; 155 case OPT_FCIRCLE: 156 filledCircleRGBA(jss->screen, x, y, radius, red, green, blue, alpha); 157 break; 158 } 159 return JIM_OK; 160 } 161 else if (option == OPT_FREE) { 162 /* FREE */ 163 if (argc != 2) { 164 Jim_WrongNumArgs(interp, 2, argv, ""); 165 return JIM_ERR; 166 } 167 Jim_DeleteCommand(interp, Jim_String(argv[0])); 168 return JIM_OK; 169 } 170 else if (option == OPT_FLIP) { 171 /* FLIP */ 172 if (argc != 2) { 173 Jim_WrongNumArgs(interp, 2, argv, ""); 174 return JIM_ERR; 175 } 176 SDL_Flip(jss->screen); 177 return JIM_OK; 178 } 179 return JIM_OK; 180} 181 182static int JimSdlSurfaceCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) 183{ 184 JimSdlSurface *jss; 185 char buf[AIO_CMD_LEN]; 186 Jim_Obj *objPtr; 187 long screenId, xres, yres; 188 SDL_Surface *screen; 189 190 if (argc != 3) { 191 Jim_WrongNumArgs(interp, 1, argv, "xres yres"); 192 return JIM_ERR; 193 } 194 if (Jim_GetLong(interp, argv[1], &xres) != JIM_OK || 195 Jim_GetLong(interp, argv[2], &yres) != JIM_OK) 196 return JIM_ERR; 197 198 /* Try to create the surface */ 199 screen = SDL_SetVideoMode(xres, yres, 32, SDL_SWSURFACE | SDL_ANYFORMAT); 200 if (screen == NULL) { 201 JimSdlSetError(interp); 202 return JIM_ERR; 203 } 204 /* Get the next file id */ 205 if (Jim_EvalGlobal(interp, "if {[catch {incr sdl.surfaceId}]} {set sdl.surfaceId 0}") != JIM_OK) 206 return JIM_ERR; 207 objPtr = Jim_GetVariableStr(interp, "sdl.surfaceId", JIM_ERRMSG); 208 if (objPtr == NULL) 209 return JIM_ERR; 210 if (Jim_GetLong(interp, objPtr, &screenId) != JIM_OK) 211 return JIM_ERR; 212 213 /* Create the SDL screen command */ 214 jss = Jim_Alloc(sizeof(*jss)); 215 jss->screen = screen; 216 sprintf(buf, "sdl.surface%ld", screenId); 217 Jim_CreateCommand(interp, buf, JimSdlHandlerCommand, jss, JimSdlDelProc); 218 Jim_SetResultString(interp, buf, -1); 219 return JIM_OK; 220} 221 222int Jim_sdlInit(Jim_Interp *interp) 223{ 224 if (Jim_PackageProvide(interp, "sdl", "1.0", JIM_ERRMSG)) 225 return JIM_ERR; 226 227 if (SDL_Init(SDL_INIT_VIDEO) < 0) { 228 JimSdlSetError(interp); 229 return JIM_ERR; 230 } 231 atexit(SDL_Quit); 232 Jim_CreateCommand(interp, "sdl.screen", JimSdlSurfaceCommand, NULL, NULL); 233 return JIM_OK; 234} 235