Anonymous avatar Anonymous committed f3ef1ec

experimental tilerow drawer

Comments (0)

Files changed (20)

 # BREAK = change breaks existing code
 # BUG	= fixed a bug that was (or could have been) crashing
 
+December 2, 2002
+	experimental pygame.draw.tilerow()
+
 November 14, 2002
 	fix unicode bugs in Font (thanks, hcyun)
 
 configcommand = configcommand + ' --version --cflags --libs'
 localbase = os.environ.get('LOCALBASE', '') #do we still need this?
 
+
+
+def confirm(message):
+    "ask a yes/no question, return result"
+    reply = raw_input('\n' + message + ' [Y/n]:')
+    if reply and string.lower(reply[0]) == 'n':
+        return 0
+    return 1
+
+
+
+
 class DependencyProg:
     def __init__(self, name, envname, exename, minver, defaultlib):
         self.name = name
     if not DEPS[0].found:
         print 'Unable to run "sdl-config". Please make sure a development version of SDL is installed.'
         raise SystemExit
-
+		
 
     if localbase: #unneeded?
         incdirs = [localbase + '/include/SDL']
     for d in DEPS:
         d.configure(incdirs, libdirs)
 
+
+    for d in DEPS[1:]:
+	if not d.found:
+		if not confirm("""
+Warning, some of the pygame dependencies were not found. Pygame can still
+compile and install, but games that require on those missing dependencies
+will not run. Would you like to continue the configuration?"""):
+			raise SystemExit
+		break
+
     return DEPS
 
     
 <a href=ref/pygame_draw.html#lines>pygame.draw.lines</a> - draw multiple connected lines on a surface<br>
 <a href=ref/pygame_draw.html#polygon>pygame.draw.polygon</a> - draws a polygon on a surface<br>
 <a href=ref/pygame_draw.html#rect>pygame.draw.rect</a> - draws a rectangle on a surface<br>
+<a href=ref/pygame_draw.html#tilerow>pygame.draw.tilerow</a> - draws a row of tile images to a Surface<br>
 <a href=ref/pygame_event.html#Event>pygame.event.Event</a> - create new event object<br>
 <a href=ref/pygame_event.html#clear>pygame.event.clear</a> - remove all of an event type from the queue<br>
 <a href=ref/pygame_event.html#event_name>pygame.event.event_name</a> - name for event type<br>
 <br>
 <h2 align=center>CD</h2>
 The CD object represents a CDROM drive and allows you to
-access the CD inside that drive. All functions (except <a href=#get_name>get_name()</a> and <a href=#get_id>get_id()</a>)
+access the CD inside that drive. All functions (except <a href=Joystick.html#get_name>get_name()</a> and <a href=Joystick.html#get_id>get_id()</a>)
 require the CD object to be initialized. This is done with the
 <a href=#init>CD.init()</a> function.
 <br>&nbsp;<br>
 CD.quit() -> None
 </tt></font><ul>
 After you are completely finished with a cdrom device, you
-can use this <a href=pygame.html#quit>quit()</a> function to free access to the drive.
+can use this <a href=pygame_display.html#quit>quit()</a> function to free access to the drive.
 This will be cleaned up automatically when the cdrom module is.
 uninitialized. It is safe to call this function on an uninitialized CD.
 </ul><br>&nbsp;<br>

docs/ref/Channel.html

 immediately when the current playing sound finishes. Each
 channel can only have a single Sound object queued. The
 queued sound will only play when the current Sound finishes
-naturally, not from another call to <a href=CD.html#stop>stop()</a> or <a href=CD.html#play>play()</a>.
+naturally, not from another call to <a href=Sound.html#stop>stop()</a> or <a href=Sound.html#play>play()</a>.
 <br>&nbsp;<br>
 If there is no currently playing sound on this Channel
 it will begin playback immediately.
 will be put on the pygame event queue everytime a sound stops
 playing on that channel. This is slightly different than the
 music object end event, because this will trigger an event
-anytime the music stops. If you call <a href=CD.html#stop>stop()</a> or <a href=CD.html#play>play()</a> on the
+anytime the music stops. If you call <a href=Sound.html#stop>stop()</a> or <a href=Sound.html#play>play()</a> on the
 channel, it will fire an event. An event will also be fired when
 playback switches to a queued Sound.
 <br>&nbsp;<br>

docs/ref/Clock.html

 </b></font><br><font size=+1><tt>
 Clock.get_rawtime() -> int
 </tt></font><ul>
-This is similar to <a href=#get_time>get_time()</a>. It does not include the number of
+This is similar to <a href=Movie.html#get_time>get_time()</a>. It does not include the number of
 milliseconds that were delayed to keep the clock tick under a given
 framerate.
 </ul><br>&nbsp;<br>

docs/ref/Joystick.html

 <br>
 <h2 align=center>Joystick</h2>
 The Joystick object represents a joystick device and allows you to
-access the controls on that joystick. All functions (except <a href=CD.html#get_name>get_name()</a>
-and <a href=CD.html#get_id>get_id()</a>) require the Joystick object to be initialized. This is done
+access the controls on that joystick. All functions (except <a href=#get_name>get_name()</a>
+and <a href=#get_id>get_id()</a>) require the Joystick object to be initialized. This is done
 with the <a href=#init>Joystick.init()</a> function.
 <br>&nbsp;<br>
 Joystick control values are only updated during the calls to the event
 Joystick.quit() -> None
 </tt></font><ul>
 After you are completely finished with a joystick device, you
-can use this <a href=pygame.html#quit>quit()</a> function to free access to the drive.
+can use this <a href=pygame_display.html#quit>quit()</a> function to free access to the drive.
 This will be cleaned up automatically when the joystick module is.
 uninitialized. It is safe to call this function on an uninitialized Joystick.
 </ul><br>&nbsp;<br>

docs/ref/pygame.html

 <h2 align=center>pygame</h2>
 Contains the core routines that are used by the rest of the
 pygame modules. It's routines are merged directly into the pygame
-namespace. This mainly includes the auto-initialization <a href=#init>init()</a> and
-<a href=#quit>quit()</a> routines.
+namespace. This mainly includes the auto-initialization <a href=pygame_display.html#init>init()</a> and
+<a href=pygame_display.html#quit>quit()</a> routines.
 <br>&nbsp;<br>
 There is a small module named 'locals' that also gets merged into
 this namespace. This contains all the constants needed by pygame.
 that failed to initialize.
 <br>&nbsp;<br>
 You can always initialize the modules you want by hand. The
-modules that need it have an <u>init()</u> and <a href=#quit>quit()</a> routine built in,
-which you can call directly. They also have a <a href=pygame_cdrom.html#get_init>get_init()</a> routine
+modules that need it have an <a href=pygame_display.html#init>init()</a> and <a href=pygame_display.html#quit>quit()</a> routine built in,
+which you can call directly. They also have a <a href=pygame_display.html#get_init>get_init()</a> routine
 which you can use to doublecheck the initialization. Note that
-the manual <u>init()</u> routines will raise an exception on error. Be
+the manual <a href=pygame_display.html#init>init()</a> routines will raise an exception on error. Be
 aware that most platforms require the display module to be
-initialized before others. This <u>init()</u> will handle that for you,
+initialized before others. This <a href=pygame_display.html#init>init()</a> will handle that for you,
 but if you initialize by hand, be aware of this constraint.
 <br>&nbsp;<br>
-As with the manual <u>init()</u> routines. It is safe to call this
+As with the manual <a href=pygame_display.html#init>init()</a> routines. It is safe to call this
 init() as often as you like. If you have imported pygame modules
 since the.
 </ul><br>&nbsp;<br>
 pygame.quit() -> none
 </tt></font><ul>
 Uninitialize all pygame modules that have been initialized. Even
-if you initialized the module by hand, this <u>quit()</u> will
+if you initialized the module by hand, this <a href=pygame_display.html#quit>quit()</a> will
 uninitialize it for you.
 <br>&nbsp;<br>
 All the pygame modules are uninitialized automatically when your

docs/ref/pygame_cdrom.html

 This function needs a cdrom device number to work on. All
 cdrom drives on the system are enumerated for use as a CD
 object. To access most of the CD functions, you'll need to
-<a href=pygame.html#init>init()</a> the CD. (note that the cdrom module will already
+<a href=pygame_display.html#init>init()</a> the CD. (note that the cdrom module will already
 be initialized). When multiple CD objects are created for the
 same CDROM device, the state and values for those CD objects
 will be shared.

docs/ref/pygame_display.html

 <br>&nbsp;<br>
 After you have initialized your video mode, you can take the
 surface that was returned and write to it like any other Surface
-object. Be sure to call <a href=#update>update()</a> or <a href=pygame_transform.html#flip>flip()</a> to keep what is on the
+object. Be sure to call <a href=#update>update()</a> or <a href=#flip>flip()</a> to keep what is on the
 screen synchronized with what is on the surface. Be sure not to call
 display routines that modify the display surface while it is locked.
 
 <br>&nbsp;<br>
 You can create an OpenGL surface (for use with PyOpenGL)
 by passing the OPENGL flag. You will likely want to use the
-DOUBLEBUF flag when using OPENGL. In which case, the <a href=pygame_transform.html#flip>flip()</a>
+DOUBLEBUF flag when using OPENGL. In which case, the <a href=#flip>flip()</a>
 function will perform the GL buffer swaps. When you are using
 an OPENGL video mode, you will not be able to perform most of the
 pygame drawing functions (fill, set_at, etc) on the display surface.

docs/ref/pygame_draw.html

 draws a rectangle on a surface</td></tr>
 
 
+<tr><td><a href=#tilerow>tilerow</a></td><td> -
+draws a row of tile images to a Surface</td></tr>
+
+
 </table>
 
 <hr>
 can be hardware accelerated when the moons are in alignement.
 </ul><br>&nbsp;<br>
 
+<a name=tilerow><font size=+2><b>tilerow
+</b></font><br><font size=+1><tt>
+pygame.draw.tilerow(Surface, Surface_sequence, pos) -> None
+</tt></font><ul>
+Draws a sequence of tiles as a row on the destination surface.
+Each image will be drawn, offset by the width of the previous
+image. Usually all tile images will be the same size, but this
+would allow for some slight changes.
+<br>&nbsp;<br>
+If None is one of the sequence elements, then that tile area will
+be skipped. The width of the skipped tile will be determined by its
+neighbor.
+</ul><br>&nbsp;<br>
+
 
 <hr>
 </body></html>

docs/ref/pygame_image.html

 <br>
 <h2 align=center>pygame.image</h2>
 This module contains functions to transfer images in and out
-of Surfaces. At the minimum the included <a href=#load>load()</a> function will
+of Surfaces. At the minimum the included <a href=pygame_mixer_music.html#load>load()</a> function will
 support BMP files. If SDL_image is properly installed when
 pygame is installed, it will support all the formats included
 with SDL_image. You can call the <a href=#get_extended>get_extended()</a> function to test

docs/ref/pygame_joystick.html

 This function needs a joystick device number to work on. All
 joystick devices on the system are enumerated for use as a Joystick
 object. To access most of the Joystick functions, you'll need to
-<a href=pygame.html#init>init()</a> the Joystick. (note that the joystick module will already
+<a href=pygame_display.html#init>init()</a> the Joystick. (note that the joystick module will already
 be initialized). When multiple Joysticks objects are created for the
 same joystick device, the state and values for those Joystick objects
 will be shared.

docs/ref/pygame_mixer.html

 rates and datatypes for the sound playback. If you do need
 specific control over the playback rate, but don't want to bother
 with hand-initializing the modules, there is a function named
-<a href=#pre_init>pygame.mixer.pre_init()</a> which takes the same arguments as <a href=pygame.html#init>init()</a>,
+<a href=#pre_init>pygame.mixer.pre_init()</a> which takes the same arguments as <a href=pygame_display.html#init>init()</a>,
 but only sets the new default values. You can call this before
 <a href=pygame.html#init>pygame.init()</a> and not have to worry about the pygame module
 initialization order.
 initialized at all). You can easily use the <a href=pygame.html#init>pygame.init()</a>
 function to cleanly initialize everything, but first use the
 <a href=#pre_init>pygame.mixer.pre_init()</a> function to change the default values for
-this <a href=pygame.html#init>init()</a>.
+this <a href=pygame_display.html#init>init()</a>.
 </ul><br>&nbsp;<br>
 
 <a name=pause><font size=+2><b>pause

docs/ref/pygame_mixer_music.html

 <br>&nbsp;<br>
 The music module has many of the same types of functions as the
 Sound objects. The main difference is only one music object can
-be loaded at a time, with the <a href=pygame_image.html#load>load()</a> function. Music
+be loaded at a time, with the <a href=#load>load()</a> function. Music
 must be stored in an individual file on the system, it cannot be
 loaded from special file-like objects through python.
 

docs/ref/pygame_time.html

 </tt></font><ul>
 Will pause for a given number of milliseconds.
 This function will use the CPU in order to make
-the delay more accurate than <a href=#wait>wait()</a>.
+the delay more accurate than <a href=pygame_event.html#wait>wait()</a>.
 <br>&nbsp;<br>
 This returns the actual number of milliseconds used.
 </ul><br>&nbsp;<br>
 
 
 
+    /*DOC*/ static char doc_tilerow[] =
+    /*DOC*/    "pygame.draw.tilerow(Surface, Surface_sequence, pos) -> None\n"
+    /*DOC*/    "draws a row of tile images to a Surface\n"
+    /*DOC*/    "\n"
+    /*DOC*/    "Draws a sequence of tiles as a row on the destination surface.\n"
+    /*DOC*/    "Each image will be drawn, offset by the width of the previous\n"
+    /*DOC*/    "image. Usually all tile images will be the same size, but this\n"
+    /*DOC*/    "would allow for some slight changes.\n"
+    /*DOC*/    "\n"
+    /*DOC*/    "If None is one of the sequence elements, then that tile area will\n"
+    /*DOC*/    "be skipped. The width of the skipped tile will be determined by its\n"
+    /*DOC*/    "neighbor.\n"
+    /*DOC*/ ;
+
+static PyObject* draw_tilerow(PyObject* self, PyObject* arg)
+{
+	SDL_Surface *src, *dst;
+	PyObject *dstobj, *sequence, *srcobj;
+	SDL_Rect dstrect;
+	int x, y, loop, length, skipped, rightedge, width;
+
+	if(!PyArg_ParseTuple(arg, "O!O(ii)", &PySurface_Type, &dstobj, &sequence, &x, &y))
+		return NULL;
+	if(!PySequence_Check(sequence))
+		return RAISE(PyExc_TypeError, "tilerow sequence argument must be a sequence");
+	dst = PySurface_AsSurface(dstobj);
+
+	rightedge = dst->clip_rect.x + dst->clip_rect.w;
+	dstrect.x = x;
+	dstrect.y = y;
+	skipped = 0;
+	length = PySequence_Length(sequence);
+	for(loop=0; loop<length; loop++)
+	{
+		srcobj = PySequence_GetItem(sequence, loop);
+		if(!srcobj) return NULL;
+		if(srcobj == Py_None)
+		{
+			skipped++;
+			Py_DECREF(srcobj);
+			continue;
+		}
+		if(!PySurface_Check(srcobj))
+		{
+			Py_DECREF(srcobj);
+			return RAISE(PyExc_TypeError, "sequence must contain Surface objects");
+		}
+		src = PySurface_AsSurface(srcobj);
+		dstrect.w = width = src->w;
+		dstrect.h = src->h;
+		if(skipped)
+		{
+			dstrect.w += src->w * skipped;
+			skipped = 0;
+			if(dstrect.w >= rightedge)
+			{
+				Py_DECREF(srcobj);
+				RETURN_NONE;
+			}
+		}
+		
+		x = dstrect.x;
+		if(PySurface_Blit(dstobj, srcobj, &dstrect, NULL) != 0)
+		{
+			Py_DECREF(srcobj);
+			return NULL;
+		}
+
+		Py_DECREF(srcobj);
+		dstrect.x = x + width;
+		if(dstrect.x >= rightedge)
+			RETURN_NONE
+	}
+
+	RETURN_NONE;
+}
+
+
+
+
+
 
 /*internal drawing tools*/
 
 	{ "polygon", polygon, 1, doc_polygon },
 	{ "rect", rect, 1, doc_rect },
 
+	{ "tilerow", draw_tilerow, 1, doc_tilerow },
+
 	{ NULL, NULL }
 };
 
 	    channeldata[channel].queue = NULL;
 	    channelnum = Mix_PlayChannelTimed(channel, sound, 0, -1);
 	    if(channelnum != -1)
-		Mix_GroupChannel(channelnum, (int)sound);
+	    	Mix_GroupChannel(channelnum, (int)sound);
 	}
 	else
 	{
 
 static void autoquit(void)
 {
-	int i;
+        int i;
 	if(SDL_WasInit(SDL_INIT_AUDIO))
 	{
 		Mix_HaltMusic();
 
-		if(channeldata)
-		{
-		    for(i=0; i<numchanneldata; ++i)
+                if(channeldata)
+                {
+                    for(i=0; i<numchanneldata; ++i)
 		    {
-			Py_XDECREF(channeldata[i].sound);
+                        Py_XDECREF(channeldata[i].sound);
 			Py_XDECREF(channeldata[i].queue);
 		    }
-		    free(channeldata);
-		    channeldata = NULL;
-		    numchanneldata = 0;
-		}
+                    free(channeldata);
+                    channeldata = NULL;
+                    numchanneldata = 0;
+                }
 
 		if(current_music)
 		{
 	else
 		stereo = 1;
 
-	if(size == 8) size = AUDIO_U8;
-	else if(size == -8) size = AUDIO_S8;
-	else if(size == 16) size = AUDIO_U16SYS;
-	else if(size == -16) size = AUDIO_S16SYS;
-	
+        if(size == 8) size = AUDIO_U8;
+        else if(size == -8) size = AUDIO_S8;
+        else if(size == 16) size = AUDIO_U16SYS;
+        else if(size == -16) size = AUDIO_S16SYS;
+        
 	/*make chunk a power of 2*/
 	for(i=0; 1<<i < chunk; ++i); //yes, semicolon on for loop
 	chunk = max(1<<i, 256);
 	if(!SDL_WasInit(SDL_INIT_AUDIO))
 	{
 		PyGame_RegisterQuit(autoquit);
-		
-		if(!channeldata) /*should always be null*/
-		{
-		    numchanneldata = MIX_CHANNELS;
-		    channeldata = (struct ChannelData*)malloc(
+                
+                if(!channeldata) /*should always be null*/
+                {
+                    numchanneldata = MIX_CHANNELS;
+                    channeldata = (struct ChannelData*)malloc(
 			    sizeof(struct ChannelData)*numchanneldata);
-		    for(i=0; i < numchanneldata; ++i)
+                    for(i=0; i < numchanneldata; ++i)
 		    {
-			channeldata[i].sound = NULL;
+                        channeldata[i].sound = NULL;
 			channeldata[i].queue = NULL;
 			channeldata[i].endevent = 0;
 		    }
-		}
+                }
 
 		if(SDL_InitSubSystem(SDL_INIT_AUDIO) == -1)
 			return PyInt_FromLong(0);
 			return PyInt_FromLong(0);
 		}
 #if MIX_MAJOR_VERSION>=1 && MIX_MINOR_VERSION>=2 && MIX_PATCHLEVEL>=3
-		Mix_ChannelFinished(endsound_callback);
+                Mix_ChannelFinished(endsound_callback);
 #endif
-		
-		Mix_VolumeMusic(127);
+                
+              	Mix_VolumeMusic(127);
 	}
 	return PyInt_FromLong(1);
 }
 	if(channelnum == -1)
 		RETURN_NONE
 
-	Py_XDECREF(channeldata[channelnum].sound);
+        Py_XDECREF(channeldata[channelnum].sound);
 	Py_XDECREF(channeldata[channelnum].queue);
 	channeldata[channelnum].queue = NULL;
-	channeldata[channelnum].sound = self;
-	Py_INCREF(self);
-		    
+        channeldata[channelnum].sound = self;
+        Py_INCREF(self);
+                    
 	//make sure volume on this arbitrary channel is set to full
 	Mix_Volume(channelnum, 128);
 
 
 static void sound_dealloc(PyObject* self)
 {
-	Mix_Chunk* chunk = PySound_AsChunk(self);
+    	Mix_Chunk* chunk = PySound_AsChunk(self);
 	Mix_FreeChunk(chunk);
 	PyObject_DEL(self);
 }
 	if(channelnum != -1)
 		Mix_GroupChannel(channelnum, (int)chunk);
 
-	Py_XDECREF(channeldata[channelnum].sound);
+        Py_XDECREF(channeldata[channelnum].sound);
 	Py_XDECREF(channeldata[channelnum].queue);
-	channeldata[channelnum].sound = sound;
+        channeldata[channelnum].sound = sound;
 	channeldata[channelnum].queue = NULL;
-	Py_INCREF(sound);
+        Py_INCREF(sound);
 
-		
+        	
 	RETURN_NONE
 }
 
 	    if(channelnum != -1)
 		    Mix_GroupChannel(channelnum, (int)chunk);
 
-	    channeldata[channelnum].sound = sound;
-	    Py_INCREF(sound);
+            channeldata[channelnum].sound = sound;
+            Py_INCREF(sound);
 	}
 	else
 	{
 	    channeldata[channelnum].queue = sound;
 	    Py_INCREF(sound);
 	}
-		
+        	
 	RETURN_NONE
 }
 
 
 	MIXER_INIT_CHECK();
 #if MIX_MAJOR_VERSION>=1 && MIX_MINOR_VERSION>=2 && MIX_PATCHLEVEL>=1
-	if(stereovolume != -1.11f)
-	    Mix_SetPanning(channelnum, (Uint8)(volume*255), (Uint8)(stereovolume*255));
-	else
-	    Mix_SetPanning(channelnum, (Uint8)255, (Uint8)255);
-	volume = 1.0f;
+        if(stereovolume != -1.11f)
+            Mix_SetPanning(channelnum, (Uint8)(volume*255), (Uint8)(stereovolume*255));
+        else
+            Mix_SetPanning(channelnum, (Uint8)255, (Uint8)255);
+        volume = 1.0f;
 #else
-	if(stereovolume != -1.11f)
-	    volume = (volume + stereovolume) * 0.5f;
+        if(stereovolume != -1.11f)
+            volume = (volume + stereovolume) * 0.5f;
 #endif
 	Mix_Volume(channelnum, (int)(volume*128));
 	RETURN_NONE
 static PyObject* chan_get_sound(PyObject* self, PyObject* args)
 {
 	int channelnum = PyChannel_AsInt(self);
+	int volume;
 	PyObject* sound;
 
 	if(!PyArg_ParseTuple(args, ""))
 static PyObject* chan_get_queue(PyObject* self, PyObject* args)
 {
 	int channelnum = PyChannel_AsInt(self);
+	int volume;
 	PyObject* sound;
 
 	if(!PyArg_ParseTuple(args, ""))
 {
 	int channelnum = PyChannel_AsInt(self);
 	int event = SDL_NOEVENT;
+	PyObject* sound;
 
 	if(!PyArg_ParseTuple(args, "|i", &event))
 		return NULL;
 
 	channeldata[channelnum].endevent = event;
-	RETURN_NONE
+    	RETURN_NONE
 }
 
 
 static PyObject* chan_get_endevent(PyObject* self, PyObject* args)
 {
 	int channelnum = PyChannel_AsInt(self);
+	PyObject* sound;
 
 	if(!PyArg_ParseTuple(args, ""))
 		return NULL;
 
 	MIXER_INIT_CHECK();
 
-	if(numchans > numchanneldata)
-	{
-	    channeldata= (struct ChannelData*)realloc(channeldata,
+        if(numchans > numchanneldata)
+        {
+            channeldata= (struct ChannelData*)realloc(channeldata,
 		    sizeof(struct ChannelData*) * numchans);
-	    for(i = numchanneldata; i < numchans; ++i)
+            for(i = numchanneldata; i < numchans; ++i)
 	    {
 		Py_XDECREF(channeldata[i].sound);
 		Py_XDECREF(channeldata[i].queue);
 		channeldata[i].sound = NULL;
 		channeldata[i].queue = NULL;
 	    }
-	    numchanneldata = numchans;
-	}
-	
+            numchanneldata = numchans;
+        }
+        
 	Mix_AllocateChannels(numchans);
 	RETURN_NONE
 }
 	import_pygame_rwobject();
 
 	music = PyImport_ImportModule("pygame.mixer_music");
-	if(music) 
+        if(music) 
 	{
 		PyObject* ptr, *dict;
 		PyModule_AddObject(module, "music", music);
 	}	
 	else /*music module not compiled? cleanly ignore*/
 	{
-	    current_music = NULL;
-	    PyErr_Clear();
+            current_music = NULL;
+            PyErr_Clear();
 	}
 }
 
 
 /* SURFACE */
 #define PYGAMEAPI_SURFACE_FIRSTSLOT 40
-#define PYGAMEAPI_SURFACE_NUMSLOTS 2
+#define PYGAMEAPI_SURFACE_NUMSLOTS 3
 typedef struct {
 	PyObject_HEAD
 	SDL_Surface* surf;
 #define PySurface_Check(x) ((x)->ob_type == (PyTypeObject*)PyGAME_C_API[PYGAMEAPI_SURFACE_FIRSTSLOT + 0])
 #define PySurface_Type (*(PyTypeObject*)PyGAME_C_API[PYGAMEAPI_SURFACE_FIRSTSLOT + 0])
 #define PySurface_New (*(PyObject*(*)(SDL_Surface*))PyGAME_C_API[PYGAMEAPI_SURFACE_FIRSTSLOT + 1])
+#define PySurface_Blit (*(int(*)(PyObject*,PyObject*,SDL_Rect*,SDL_Rect*))PyGAME_C_API[PYGAMEAPI_SURFACE_FIRSTSLOT + 2])
 #define import_pygame_surface() { \
 	PyObject *module = PyImport_ImportModule("pygame.surface"); \
 	if (module != NULL) { \
 
 
 /* SURFLOCK */    /*auto import/init by surface*/
-#define PYGAMEAPI_SURFLOCK_FIRSTSLOT 43
+#define PYGAMEAPI_SURFLOCK_FIRSTSLOT 44
 #define PYGAMEAPI_SURFLOCK_NUMSLOTS 5
 struct SubSurface_Data
 {
 }
 
 
+/*this internal blit function is accessable through the C api*/
+int PySurface_Blit(PyObject *dstobj, PyObject *srcobj, SDL_Rect *dstrect, SDL_Rect *srcrect)
+{
+    SDL_Surface *src = PySurface_AsSurface(srcobj);
+    SDL_Surface *dst = PySurface_AsSurface(dstobj);
+    SDL_Surface *subsurface = NULL;
+    int dx, dy, result, suboffsetx, suboffsety;
+    SDL_Rect orig_clip, sub_clip;
+    short sx, sy;
+    int didconvert = 0;
+
+    /*passthrough blits to the real surface*/
+    if(((PySurfaceObject*)dstobj)->subsurface)
+    {
+	    PyObject *owner;
+	    struct SubSurface_Data *subdata;
+
+	    subdata = ((PySurfaceObject*)dstobj)->subsurface;
+	    owner = subdata->owner;
+            subsurface = PySurface_AsSurface(owner);
+	    suboffsetx = subdata->offsetx;
+	    suboffsety = subdata->offsety;
+
+	    while(((PySurfaceObject*)owner)->subsurface)
+	    {
+		subdata = ((PySurfaceObject*)owner)->subsurface;
+    		owner = subdata->owner;
+	        subsurface = PySurface_AsSurface(owner);
+	    	suboffsetx += subdata->offsetx;
+    	    	suboffsety += subdata->offsety;
+	    }
+
+	    SDL_GetClipRect(subsurface, &orig_clip);
+	    SDL_GetClipRect(dst, &sub_clip);
+	    sub_clip.x += suboffsetx;
+	    sub_clip.y += suboffsety;
+	    SDL_SetClipRect(subsurface, &sub_clip);
+	    dstrect->x += suboffsetx;
+	    dstrect->y += suboffsety;
+	    dst = subsurface;
+    }
+    else
+    {
+	    PySurface_Prep(dstobj);
+	    subsurface = NULL;
+    }
+
+    PySurface_Prep(srcobj);
+/*    Py_BEGIN_ALLOW_THREADS */
+
+    /*can't blit alpha to 8bit, crashes SDL*/
+    if(dst->format->BytesPerPixel==1 && (src->format->Amask || src->flags&SDL_SRCALPHA))
+    {
+	    didconvert = 1;
+	    src = SDL_DisplayFormat(src);
+    }
+
+    /*see if we should handle alpha ourselves*/
+    if(dst->format->Amask && dst->flags&SDL_SRCALPHA &&
+                (dst->format->BytesPerPixel == 2 || dst->format->BytesPerPixel==4))
+    {
+        result = pygame_AlphaBlit(src, srcrect, dst, dstrect);
+    }
+    else
+    {
+        result = SDL_BlitSurface(src, srcrect, dst, dstrect);
+    }
+
+    if(didconvert)
+	    SDL_FreeSurface(src);
+
+/*    Py_END_ALLOW_THREADS */
+    if(subsurface)
+    {
+	    SDL_SetClipRect(subsurface, &orig_clip);
+	    dstrect->x -= suboffsetx;
+	    dstrect->y -= suboffsety;
+    }
+    else
+	PySurface_Unprep(dstobj);
+    PySurface_Unprep(srcobj);
+
+    if(result == -1)
+	    RAISE(PyExc_SDLError, SDL_GetError());
+    if(result == -2)
+	    RAISE(PyExc_SDLError, "Surface was lost");
+
+    return result != 0;
+}
+
+
 
 
     /*DOC*/ static char doc_surf_blit[] =
 	dest_rect.y = (short)dy;
 	dest_rect.w = (unsigned short)src_rect->w;
 	dest_rect.h = (unsigned short)src_rect->h;
-
+#if 1
+	
+	result = PySurface_Blit(self, srcobject, &dest_rect, (SDL_Rect*)src_rect);
+	if(result != 0)
+	    return NULL;
+	
+#else
+	
 	/*passthrough blits to the real surface*/
 	if(((PySurfaceObject*)self)->subsurface)
 	{
 		return RAISE(PyExc_SDLError, SDL_GetError());
 	if(result == -2)
 		return RAISE(PyExc_SDLError, "Surface was lost");
-
+#endif
 	return PyRect_New((GAME_Rect*)&dest_rect);
 }
 
 	/* export the c api */
 	c_api[0] = &PySurface_Type;
 	c_api[1] = PySurface_New;
+	c_api[2] = PySurface_Blit;
 	apiobj = PyCObject_FromVoidPtr(c_api, NULL);
 	PyDict_SetItemString(dict, PYGAMEAPI_LOCAL_ENTRY, apiobj);
 	Py_DECREF(apiobj);
 			for(i = 0; i < PYGAMEAPI_SURFLOCK_NUMSLOTS; ++i)
 				PyGAME_C_API[i + PYGAMEAPI_SURFLOCK_FIRSTSLOT] = localptr[i];
 		}
+		Py_DECREF(lockmodule);
 	}
-	Py_XDECREF(lockmodule);
 }
 
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.