/*
pygame - Python Game Library
Copyright (C) 2000-2001 Pete Shinners
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Pete Shinners
pete@shinners.org
*/
/*
* pygame Surface module
*/
#define PYGAMEAPI_SURFACE_INTERNAL
#include "pygame.h"
#include "structmember.h"
staticforward PyTypeObject PySurface_Type;
static PyObject* PySurface_New(SDL_Surface* info);
#define PySurface_Check(x) ((x)->ob_type == &PySurface_Type)
extern int pygame_AlphaBlit(SDL_Surface *src, SDL_Rect *srcrect,
SDL_Surface *dst, SDL_Rect *dstrect);
static PyObject* surface_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
static int surface_init(PySurfaceObject *self, PyObject *args, PyObject *kwds);
/* surface object methods */
/*DOC*/ static char doc_surf_get_at[] =
/*DOC*/ "Surface.get_at(position) -> RGBA\n"
/*DOC*/ "get a pixel color\n"
/*DOC*/ "\n"
/*DOC*/ "Returns the RGB color values at a given pixel. If the\n"
/*DOC*/ "Surface has no per-pixel alpha, the alpha will be 255 (opaque).\n"
/*DOC*/ "A pixel outside the surface area will raise an IndexError.\n"
/*DOC*/ "\n"
/*DOC*/ "\n"
/*DOC*/ "This function will need to temporarily lock the surface.\n"
/*DOC*/ ;
static PyObject* surf_get_at(PyObject* self, PyObject* arg)
{
SDL_Surface* surf = PySurface_AsSurface(self);
SDL_PixelFormat* format = surf->format;
Uint8* pixels = (Uint8*)surf->pixels;
int x, y;
Uint32 color;
Uint8* pix;
Uint8 r, g, b, a;
if(!PyArg_ParseTuple(arg, "(ii)", &x, &y))
return NULL;
if(!surf) return RAISE(PyExc_SDLError, "display Surface quit");
if(surf->flags & SDL_OPENGL)
return RAISE(PyExc_SDLError, "Cannot call on OPENGL Surfaces");
if(x < 0 || x >= surf->w || y < 0 || y >= surf->h)
return RAISE(PyExc_IndexError, "pixel index out of range");
if(format->BytesPerPixel < 1 || format->BytesPerPixel > 4)
return RAISE(PyExc_RuntimeError, "invalid color depth for surface");
if(!PySurface_Lock(self)) return NULL;
pixels = (Uint8*)surf->pixels;
switch(format->BytesPerPixel)
{
case 1:
color = (Uint32)*((Uint8*)pixels + y * surf->pitch + x);
break;
case 2:
color = (Uint32)*((Uint16*)(pixels + y * surf->pitch) + x);
break;
case 3:
pix = ((Uint8*)(pixels + y * surf->pitch) + x * 3);
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
color = (pix[0]) + (pix[1]<<8) + (pix[2]<<16);
#else
color = (pix[2]) + (pix[1]<<8) + (pix[0]<<16);
#endif
break;
default: /*case 4:*/
color = *((Uint32*)(pixels + y * surf->pitch) + x);
break;
}
if(!PySurface_Unlock(self)) return NULL;
SDL_GetRGBA(color, format, &r, &g, &b, &a);
return Py_BuildValue("(bbbb)", r, g, b, a);
}
/*DOC*/ static char doc_surf_set_at[] =
/*DOC*/ "Surface.set_at(position, RGBA) -> None\n"
/*DOC*/ "set pixel at given position\n"
/*DOC*/ "\n"
/*DOC*/ "Assigns color to the image at the give position. Color can be a\n"
/*DOC*/ "RGBA sequence or a mapped color integer. Setting the pixel outside\n"
/*DOC*/ "the clip area or surface area will have no effect.\n"
/*DOC*/ "\n"
/*DOC*/ "In some situations just using the fill() function with a one-pixel\n"
/*DOC*/ "sized rectangle will be quicker. Also the fill function does not\n"
/*DOC*/ "require the surface to be locked.\n"
/*DOC*/ "\n"
/*DOC*/ "This function will need to temporarily lock the surface.\n"
/*DOC*/ ;
static PyObject* surf_set_at(PyObject* self, PyObject* args)
{
SDL_Surface* surf = PySurface_AsSurface(self);
SDL_PixelFormat* format = surf->format;
Uint8* pixels;
int x, y;
Uint32 color;
Uint8 rgba[4];
PyObject* rgba_obj;
Uint8* byte_buf;
if(!PyArg_ParseTuple(args, "(ii)O", &x, &y, &rgba_obj))
return NULL;
if(!surf) return RAISE(PyExc_SDLError, "display Surface quit");
if(surf->flags & SDL_OPENGL)
return RAISE(PyExc_SDLError, "Cannot call on OPENGL Surfaces");
if(format->BytesPerPixel < 1 || format->BytesPerPixel > 4)
return RAISE(PyExc_RuntimeError, "invalid color depth for surface");
if(x < surf->clip_rect.x || x >= surf->clip_rect.x + surf->clip_rect.w ||
y < surf->clip_rect.y || y >= surf->clip_rect.y + surf->clip_rect.h)
{
/*out of clip area*/
RETURN_NONE
}
if(PyInt_Check(rgba_obj))
color = (Uint32)PyInt_AsLong(rgba_obj);
else if(RGBAFromObj(rgba_obj, rgba))
color = SDL_MapRGBA(surf->format, rgba[0], rgba[1], rgba[2], rgba[3]);
else
return RAISE(PyExc_TypeError, "invalid color argument");
if(!PySurface_Lock(self)) return NULL;
pixels = (Uint8*)surf->pixels;
switch(format->BytesPerPixel)
{
case 1:
*((Uint8*)pixels + y * surf->pitch + x) = (Uint8)color;
break;
case 2:
*((Uint16*)(pixels + y * surf->pitch) + x) = (Uint16)color;
break;
case 3:
byte_buf = (Uint8*)(pixels + y * surf->pitch) + x * 3;
*(byte_buf + (format->Rshift >> 3)) = rgba[0];
*(byte_buf + (format->Gshift >> 3)) = rgba[1];
*(byte_buf + (format->Bshift >> 3)) = rgba[2];
break;
default: /*case 4:*/
*((Uint32*)(pixels + y * surf->pitch) + x) = color;
break;
}
if(!PySurface_Unlock(self)) return NULL;
RETURN_NONE
}
/*DOC*/ static char doc_surf_map_rgb[] =
/*DOC*/ "Surface.map_rgb(RGBA) -> int\n"
/*DOC*/ "convert RGB into a mapped color\n"
/*DOC*/ "\n"
/*DOC*/ "Uses the Surface format to convert RGBA into a mapped color value.\n"
/*DOC*/ "\n"
/*DOC*/ "This function is not as needed as normal C code using SDL. The pygame\n"
/*DOC*/ "functions do not used mapped colors, so there is no need to map them.\n"
/*DOC*/ ;
static PyObject* surf_map_rgb(PyObject* self,PyObject* args)
{
SDL_Surface* surf = PySurface_AsSurface(self);
Uint8 rgba[4];
int color;
if(!RGBAFromObj(args, rgba))
return RAISE(PyExc_TypeError, "Invalid RGBA argument");
if(!surf) return RAISE(PyExc_SDLError, "display Surface quit");
color = SDL_MapRGBA(surf->format, rgba[0], rgba[1], rgba[2], rgba[3]);
return PyInt_FromLong(color);
}
/*DOC*/ static char doc_surf_unmap_rgb[] =
/*DOC*/ "Surface.unmap_rgb(color) -> RGBA\n"
/*DOC*/ "convert mapped color into RGB\n"
/*DOC*/ "\n"
/*DOC*/ "This function returns the RGBA components for a mapped color\n"
/*DOC*/ "value. If Surface has no per-pixel alpha, alpha will be 255 (opaque).\n"
/*DOC*/ "\n"
/*DOC*/ "This function is not as needed as normal C code using SDL. The pygame\n"
/*DOC*/ "functions do not used mapped colors, so there is no need to unmap them.\n"
/*DOC*/ ;
static PyObject* surf_unmap_rgb(PyObject* self,PyObject* args)
{
SDL_Surface* surf = PySurface_AsSurface(self);
Uint32 col;
Uint8 r, g, b, a;
if(!PyArg_ParseTuple(args, "i", &col))
return NULL;
if(!surf) return RAISE(PyExc_SDLError, "display Surface quit");
SDL_GetRGBA(col,surf->format, &r, &g, &b, &a);
return Py_BuildValue("(bbbb)", r, g, b, a);
}
/*DOC*/ static char doc_surf_lock[] =
/*DOC*/ "Surface.lock() -> None\n"
/*DOC*/ "locks Surface for pixel access\n"
/*DOC*/ "\n"
/*DOC*/ "On accelerated surfaces, it is usually required to lock the\n"
/*DOC*/ "surface before you can access the pixel values. To be safe, it is\n"
/*DOC*/ "always a good idea to lock the surface before entering a block of\n"
/*DOC*/ "code that changes or accesses the pixel values. The surface must\n"
/*DOC*/ "not be locked when performing other pygame functions on it like\n"
/*DOC*/ "fill and blit.\n"
/*DOC*/ "\n"
/*DOC*/ "You can doublecheck to really make sure a lock is needed by\n"
/*DOC*/ "calling the mustlock() member. This should not be needed, since\n"
/*DOC*/ "it is usually recommended to lock anyways and work with all\n"
/*DOC*/ "surface types. If the surface does not need to be locked, the\n"
/*DOC*/ "operation will return quickly with minute overhead.\n"
/*DOC*/ "\n"
/*DOC*/ "On some platforms a necessary lock can shut off some parts of the\n"
/*DOC*/ "system. This is not a problem unless you leave surfaces locked\n"
/*DOC*/ "for long periouds of time. Only keep the surface locked when you\n"
/*DOC*/ "need the pixel access. At the same time, it is not a good too\n"
/*DOC*/ "repeatedly lock and unlock the surface inside tight loops. It is\n"
/*DOC*/ "fine to leave the surface locked while needed, just don't be\n"
/*DOC*/ "lazy.\n"
/*DOC*/ ;
static PyObject* surf_lock(PyObject* self, PyObject* args)
{
if(!PyArg_ParseTuple(args, ""))
return NULL;
if(!PySurface_Lock(self))
return NULL;
RETURN_NONE
}
/*DOC*/ static char doc_surf_unlock[] =
/*DOC*/ "Surface.unlock() -> None\n"
/*DOC*/ "locks Surface for pixel access\n"
/*DOC*/ "\n"
/*DOC*/ "After a surface has been locked, you will need to unlock it when\n"
/*DOC*/ "you are done.\n"
/*DOC*/ "\n"
/*DOC*/ "You can doublecheck to really make sure a lock is needed by\n"
/*DOC*/ "calling the mustlock() member. This should not be needed, since\n"
/*DOC*/ "it is usually recommended to lock anyways and work with all\n"
/*DOC*/ "surface types. If the surface does not need to be locked, the\n"
/*DOC*/ "operation will return quickly with minute overhead.\n"
/*DOC*/ ;
static PyObject* surf_unlock(PyObject* self, PyObject* args)
{
if(!PyArg_ParseTuple(args, ""))
return NULL;
if(!PySurface_Unlock(self))
return NULL;
RETURN_NONE
}
/*DOC*/ static char doc_surf_mustlock[] =
/*DOC*/ "Surface.mustlock() -> bool\n"
/*DOC*/ "check if the surface needs locking\n"
/*DOC*/ "\n"
/*DOC*/ "Returns true if the surface really does need locking to gain\n"
/*DOC*/ "pixel access. Usually the overhead of checking before locking\n"
/*DOC*/ "outweight the overhead of just locking any surface before access.\n"
/*DOC*/ ;
static PyObject* surf_mustlock(PyObject* self, PyObject* args)
{
SDL_Surface* surf = PySurface_AsSurface(self);
return PyInt_FromLong(SDL_MUSTLOCK(surf) || ((PySurfaceObject*)self)->subsurface);
}
/*DOC*/ static char doc_surf_get_locked[] =
/*DOC*/ "Surface.get_locked() -> bool\n"
/*DOC*/ "check if the surface needs locking\n"
/*DOC*/ "\n"
/*DOC*/ "Returns true if the surface is currently locked.\n"
/*DOC*/ ;
static PyObject* surf_get_locked(PyObject* self, PyObject* args)
{
PySurfaceObject* surf = (PySurfaceObject*)self;
if(!PyArg_ParseTuple(args, ""))
return NULL;
return PyInt_FromLong(surf->surf->pixels != NULL);
}
/*DOC*/ static char doc_surf_get_palette[] =
/*DOC*/ "Surface.get_palette() -> [[r, g, b], ...]\n"
/*DOC*/ "get the palette\n"
/*DOC*/ "\n"
/*DOC*/ "This will return the an array of all the color indexes in the\n"
/*DOC*/ "Surface's palette.\n"
/*DOC*/ ;
static PyObject* surf_get_palette(PyObject* self, PyObject* args)
{
SDL_Surface* surf = PySurface_AsSurface(self);
SDL_Palette* pal = surf->format->palette;
PyObject* list;
int i;
if(!PyArg_ParseTuple(args, ""))
return NULL;
if(!surf) return RAISE(PyExc_SDLError, "display Surface quit");
if(!pal)
return RAISE(PyExc_SDLError, "Surface has no palette to get\n");
list = PyTuple_New(pal->ncolors);
if(!list)
return NULL;
for(i = 0;i < pal->ncolors;i++)
{
PyObject* color;
SDL_Color* c = &pal->colors[i];
color = Py_BuildValue("(bbb)", c->r, c->g, c->b);
if(!color)
{
Py_DECREF(list);
return NULL;
}
PyTuple_SET_ITEM(list, i, color);
}
return list;
}
/*DOC*/ static char doc_surf_get_palette_at[] =
/*DOC*/ "Surface.get_palette_at(index) -> r, g, b\n"
/*DOC*/ "get a palette entry\n"
/*DOC*/ "\n"
/*DOC*/ "This will retreive an individual color entry from the Surface's\n"
/*DOC*/ "palette.\n"
/*DOC*/ ;
static PyObject* surf_get_palette_at(PyObject* self, PyObject* args)
{
SDL_Surface* surf = PySurface_AsSurface(self);
SDL_Palette* pal = surf->format->palette;
SDL_Color* c;
int index;
if(!PyArg_ParseTuple(args, "i", &index))
return NULL;
if(!surf) return RAISE(PyExc_SDLError, "display Surface quit");
if(!pal)
return RAISE(PyExc_SDLError, "Surface has no palette to set\n");
if(index >= pal->ncolors || index < 0)
return RAISE(PyExc_IndexError, "index out of bounds");
c = &pal->colors[index];
return Py_BuildValue("(bbb)", c->r, c->g, c->b);
}
/*DOC*/ static char doc_surf_set_palette[] =
/*DOC*/ "Surface.set_palette([[r, g, b], ...]) -> None\n"
/*DOC*/ "set the palette\n"
/*DOC*/ "\n"
/*DOC*/ "This will replace the entire palette with color\n"
/*DOC*/ "information you provide.\n"
/*DOC*/ "\n"
/*DOC*/ "You can pass an incomplete list of RGB values, and\n"
/*DOC*/ "this will only change the first colors in the palette.\n"
/*DOC*/ ;
static PyObject* surf_set_palette(PyObject* self, PyObject* args)
{
SDL_Surface* surf = PySurface_AsSurface(self);
SDL_Palette* pal = surf->format->palette;
SDL_Color* colors;
PyObject* list, *item;
int i, len;
int r, g, b;
if(!PyArg_ParseTuple(args, "O", &list))
return NULL;
if(!surf) return RAISE(PyExc_SDLError, "display Surface quit");
if(!PySequence_Check(list))
return RAISE(PyExc_ValueError, "Argument must be a sequence type");
if(!pal)
return RAISE(PyExc_SDLError, "Surface has no palette\n");
if(!SDL_WasInit(SDL_INIT_VIDEO))
return RAISE(PyExc_SDLError, "cannot set palette without pygame.display initialized");
len = min(pal->ncolors, PySequence_Length(list));
colors = (SDL_Color*)malloc(len * sizeof(SDL_Color));
if(!colors)
return NULL;
for(i = 0; i < len; i++)
{
item = PySequence_GetItem(list, i);
if(!PySequence_Check(item) || PySequence_Length(item) != 3)
{
Py_DECREF(item);
free((char*)colors);
return RAISE(PyExc_TypeError, "takes a sequence of sequence of RGB");
}
if(!IntFromObjIndex(item, 0, &r) || !IntFromObjIndex(item, 1, &g) || !IntFromObjIndex(item, 2, &b))
return RAISE(PyExc_TypeError, "RGB sequence must contain numeric values");
colors[i].r = (unsigned char)r;
colors[i].g = (unsigned char)g;
colors[i].b = (unsigned char)b;
Py_DECREF(item);
}
SDL_SetColors(surf, colors, 0, len);
free((char*)colors);
RETURN_NONE
}
/*DOC*/ static char doc_surf_set_palette_at[] =
/*DOC*/ "Surface.set_palette_at(index, [r, g, b]) -> None\n"
/*DOC*/ "set a palette entry\n"
/*DOC*/ "\n"
/*DOC*/ "This function sets the palette color at a specific entry.\n"
/*DOC*/ ;
static PyObject* surf_set_palette_at(PyObject* self, PyObject* args)
{
SDL_Surface* surf = PySurface_AsSurface(self);
SDL_Palette* pal = surf->format->palette;
SDL_Color color;
int index;
Uint8 r, g, b;
if(!PyArg_ParseTuple(args, "i(bbb)", &index, &r, &g, &b))
return NULL;
if(!surf) return RAISE(PyExc_SDLError, "display Surface quit");
if(!pal)
{
PyErr_SetString(PyExc_SDLError, "Surface is not palettized\n");
return NULL;
}
if(index >= pal->ncolors || index < 0)
{
PyErr_SetString(PyExc_IndexError, "index out of bounds");
return NULL;
}
if(!SDL_WasInit(SDL_INIT_VIDEO))
return RAISE(PyExc_SDLError, "cannot set palette without pygame.display initialized");
color.r = r;
color.g = g;
color.b = b;
SDL_SetColors(surf, &color, index, 1);
RETURN_NONE
}
/*DOC*/ static char doc_surf_set_colorkey[] =
/*DOC*/ "Surface.set_colorkey([color, [flags]]) -> None\n"
/*DOC*/ "change colorkey information\n"
/*DOC*/ "\n"
/*DOC*/ "Set the colorkey for the surface by passing a mapped color value\n"
/*DOC*/ "as the color argument. If no arguments or None is passed,\n"
/*DOC*/ "colorkeying will be disabled for this surface.\n"
/*DOC*/ "\n"
/*DOC*/ "The color argument can be either a RGBA sequence or a mapped integer.\n"
/*DOC*/ "\n"
/*DOC*/ "If your image is nonchanging and will be used repeatedly, you\n"
/*DOC*/ "will probably want to pass the RLEACCEL flag to the call. This\n"
/*DOC*/ "will take a short time to compile your surface, and increase the\n"
/*DOC*/ "blitting speed.\n"
/*DOC*/ ;
static PyObject* surf_set_colorkey(PyObject* self, PyObject* args)
{
SDL_Surface* surf = PySurface_AsSurface(self);
Uint32 flags = 0, color = 0;
PyObject* rgba_obj = NULL, *intobj = NULL;
Uint8 rgba[4];
int result, hascolor=0;
if(!PyArg_ParseTuple(args, "|Oi", &rgba_obj, &flags))
return NULL;
if(!surf) return RAISE(PyExc_SDLError, "display Surface quit");
if(surf->flags & SDL_OPENGL)
return RAISE(PyExc_SDLError, "Cannot call on OPENGL Surfaces");
if(rgba_obj && rgba_obj!=Py_None)
{
if(PyNumber_Check(rgba_obj) && (intobj=PyNumber_Int(rgba_obj)))
{
color = (Uint32)PyInt_AsLong(intobj);
Py_DECREF(intobj);
}
else if(RGBAFromObj(rgba_obj, rgba))
color = SDL_MapRGBA(surf->format, rgba[0], rgba[1], rgba[2], rgba[3]);
else
return RAISE(PyExc_TypeError, "invalid color argument");
hascolor = 1;
}
if(hascolor)
flags |= SDL_SRCCOLORKEY;
PySurface_Prep(self);
result = SDL_SetColorKey(surf, flags, color);
PySurface_Unprep(self);
if(result == -1)
return RAISE(PyExc_SDLError, SDL_GetError());
RETURN_NONE
}
/*DOC*/ static char doc_surf_get_colorkey[] =
/*DOC*/ "Surface.get_colorkey() -> RGBA\n"
/*DOC*/ "query colorkey\n"
/*DOC*/ "\n"
/*DOC*/ "Returns the current mapped color value being used for\n"
/*DOC*/ "colorkeying. If colorkeying is not enabled for this surface, it\n"
/*DOC*/ "returns None\n"
/*DOC*/ ;
static PyObject* surf_get_colorkey(PyObject* self, PyObject* args)
{
SDL_Surface* surf = PySurface_AsSurface(self);
Uint8 r, g, b, a;
if(!PyArg_ParseTuple(args, ""))
return NULL;
if(!surf) return RAISE(PyExc_SDLError, "display Surface quit");
if(surf->flags & SDL_OPENGL)
return RAISE(PyExc_SDLError, "Cannot call on OPENGL Surfaces");
if(!(surf->flags&SDL_SRCCOLORKEY))
RETURN_NONE
SDL_GetRGBA(surf->format->colorkey, surf->format, &r, &g, &b, &a);
return Py_BuildValue("(bbbb)", r, g, b, a);
}
/*DOC*/ static char doc_surf_set_alpha[] =
/*DOC*/ "Surface.set_alpha([alpha, [flags]]) -> None\n"
/*DOC*/ "change alpha information\n"
/*DOC*/ "\n"
/*DOC*/ "Set the overall transparency for the surface. If no alpha is\n"
/*DOC*/ "passed, alpha blending is disabled for the surface. An alpha of 0\n"
/*DOC*/ "is fully transparent, an alpha of 255 is fully opaque. If no\n"
/*DOC*/ "arguments or None is passed, this will disable the surface alpha.\n"
/*DOC*/ "\n"
/*DOC*/ "If your surface has a pixel alpha channel, it will override the\n"
/*DOC*/ "overall surface transparency. You'll need to change the actual\n"
/*DOC*/ "pixel transparency to make changes.\n"
/*DOC*/ "\n"
/*DOC*/ "If your image also has pixel alpha values, or will be used repeatedly, you\n"
/*DOC*/ "will probably want to pass the RLEACCEL flag to the call. This\n"
/*DOC*/ "will take a short time to compile your surface, and increase the\n"
/*DOC*/ "blitting speed.\n"
/*DOC*/ ;
static PyObject* surf_set_alpha(PyObject* self, PyObject* args)
{
SDL_Surface* surf = PySurface_AsSurface(self);
Uint32 flags = 0;
PyObject* alpha_obj = NULL, *intobj=NULL;
Uint8 alpha;
int result, alphaval=255, hasalpha=0;
if(!PyArg_ParseTuple(args, "|Oi", &alpha_obj, &flags))
return NULL;
if(!surf) return RAISE(PyExc_SDLError, "display Surface quit");
if(surf->flags & SDL_OPENGL)
return RAISE(PyExc_SDLError, "Cannot call on OPENGL Surfaces");
if(alpha_obj && alpha_obj!=Py_None)
{
if(PyNumber_Check(alpha_obj) && (intobj=PyNumber_Int(alpha_obj)))
{
alphaval = (int)PyInt_AsLong(intobj);
Py_DECREF(intobj);
}
else
return RAISE(PyExc_TypeError, "invalid alpha argument");
hasalpha = 1;
}
if(hasalpha)
flags |= SDL_SRCALPHA;
if(alphaval>255) alpha = 255;
else if(alphaval<0) alpha = 0;
else alpha = (Uint8)alphaval;
PySurface_Prep(self);
result = SDL_SetAlpha(surf, flags, alpha);
PySurface_Unprep(self);
if(result == -1)
return RAISE(PyExc_SDLError, SDL_GetError());
RETURN_NONE
}
/*DOC*/ static char doc_surf_get_alpha[] =
/*DOC*/ "Surface.get_alpha() -> alpha\n"
/*DOC*/ "query alpha information\n"
/*DOC*/ "\n"
/*DOC*/ "Returns the current alpha value for the Surface. If transparency\n"
/*DOC*/ "is disabled for the Surface, it returns None.\n"
/*DOC*/ ;
static PyObject* surf_get_alpha(PyObject* self, PyObject* args)
{
SDL_Surface* surf = PySurface_AsSurface(self);
if(!PyArg_ParseTuple(args, ""))
return NULL;
if(surf->flags & SDL_OPENGL)
return RAISE(PyExc_SDLError, "Cannot call on OPENGL Surfaces");
if(surf->flags&SDL_SRCALPHA)
return PyInt_FromLong(surf->format->alpha);
RETURN_NONE
}
/*DOC*/ static char doc_surf_copy[] =
/*DOC*/ "Surface.copy() -> Surface\n"
/*DOC*/ "creates a new copy of a Surface\n"
/*DOC*/ "\n"
/*DOC*/ "Creates an exact duplicate of the Surface. The new Surface will\n"
/*DOC*/ "get the same palette and surface flags as the original.\n"
/*DOC*/ "\n"
/*DOC*/ "If the Surface is a subsurface this will return a copy of\n"
/*DOC*/ "the pixel data. The new copy will not reference pixel data.\n"
/*DOC*/ ;
static PyObject* surf_copy(PyObject* self, PyObject* args)
{
SDL_Surface* surf = PySurface_AsSurface(self);
PyObject* final;
SDL_Surface* newsurf;
if(!PyArg_ParseTuple(args, ""))
return NULL;
if(!surf) return RAISE(PyExc_SDLError, "display Surface quit");
if(surf->flags & SDL_OPENGL)
{
return RAISE(PyExc_SDLError, "Cannot copy opengl display");
}
PySurface_Prep(self);
newsurf = SDL_ConvertSurface(surf, surf->format, surf->flags);
PySurface_Unprep(self);
final = PySurface_New(newsurf);
if(!final)
SDL_FreeSurface(newsurf);
return final;
}
/*DOC*/ static char doc_surf_convert[] =
/*DOC*/ "Surface.convert([src_surface] OR depth, [flags] OR masks) -> Surface\n"
/*DOC*/ "new copy of surface with different format\n"
/*DOC*/ "\n"
/*DOC*/ "Creates a new copy of the surface with the desired pixel format.\n"
/*DOC*/ "Surfaces with the same pixel format will blit much faster than\n"
/*DOC*/ "those with mixed formats. The pixel format of the new surface\n"
/*DOC*/ "will match the format given as the argument. If no surface is\n"
/*DOC*/ "given, the new surface will have the same pixel format as the\n"
/*DOC*/ "current display.\n"
/*DOC*/ "\n"
/*DOC*/ "convert() will also accept bitsize or mask arguments like the\n"
/*DOC*/ "Surface() constructor function. Either pass an integer bitsize\n"
/*DOC*/ "or a sequence of color masks to specify the format of surface\n"
/*DOC*/ "you would like to convert to. When used this way you may also\n"
/*DOC*/ "pass an optional flags argument (whew).\n"
/*DOC*/ ;
static PyObject* surf_convert(PyObject* self, PyObject* args)
{
SDL_Surface* surf = PySurface_AsSurface(self);
PyObject* final;
PyObject* argobject=NULL;
SDL_Surface* src;
SDL_Surface* newsurf;
Uint32 flags=-1;
if(!SDL_WasInit(SDL_INIT_VIDEO))
return RAISE(PyExc_SDLError, "cannot convert without pygame.display initialized");
if(!PyArg_ParseTuple(args, "|Oi", &argobject, &flags))
return NULL;
if(surf->flags & SDL_OPENGL)
{
return RAISE(PyExc_SDLError, "Cannot convert opengl display");
}
PySurface_Prep(self);
if(argobject)
{
if(PySurface_Check(argobject))
{
src = PySurface_AsSurface(argobject);
flags = src->flags | (surf->flags & (SDL_SRCCOLORKEY|SDL_SRCALPHA));
newsurf = SDL_ConvertSurface(surf, src->format, flags);
}
else
{
int bpp;
SDL_PixelFormat format;
memcpy(&format, surf->format, sizeof(format));
if(IntFromObj(argobject, &bpp))
{
int Rmask, Gmask, Bmask, Amask;
if(flags!=-1 && flags&SDL_SRCALPHA)
{
switch(bpp)
{
case 16:
Rmask = 0xF<<8; Gmask = 0xF<<4; Bmask = 0xF; Amask = 0xF<<12; break;
case 32:
Rmask = 0xFF<<16; Gmask = 0xFF<<8; Bmask = 0xFF; Amask = 0xFF<<24; break;
default:
return RAISE(PyExc_ValueError, "no standard masks exist for given bitdepth with alpha");
}
}
else
{
Amask = 0;
switch(bpp)
{
case 8:
Rmask = 0xFF>>6<<5; Gmask = 0xFF>>5<<2; Bmask = 0xFF>>6; break;
case 12:
Rmask = 0xFF>>4<<8; Gmask = 0xFF>>4<<4; Bmask = 0xFF>>4; break;
case 15:
Rmask = 0xFF>>3<<10; Gmask = 0xFF>>3<<5; Bmask = 0xFF>>3; break;
case 16:
Rmask = 0xFF>>3<<11; Gmask = 0xFF>>2<<5; Bmask = 0xFF>>3; break;
case 24:
case 32:
Rmask = 0xFF << 16; Gmask = 0xFF << 8; Bmask = 0xFF; break;
default:
return RAISE(PyExc_ValueError, "nonstandard bit depth given");
}
}
format.Rmask = Rmask; format.Gmask = Gmask;
format.Bmask = Bmask; format.Amask = Amask;
}
else if(PySequence_Check(argobject) && PySequence_Size(argobject)==4)
{
Uint32 mask;
if(!UintFromObjIndex(argobject, 0, &format.Rmask) ||
!UintFromObjIndex(argobject, 1, &format.Gmask) ||
!UintFromObjIndex(argobject, 2, &format.Bmask) ||
!UintFromObjIndex(argobject, 3, &format.Amask))
{
PySurface_Unprep(self);
return RAISE(PyExc_ValueError, "invalid color masks given");
}
mask = format.Rmask|format.Gmask|format.Bmask|format.Amask;
for(bpp=0; bpp<32; ++bpp)
if(!(mask>>bpp)) break;
}
else
{
PySurface_Unprep(self);
return RAISE(PyExc_ValueError, "invalid argument specifying new format to convert to");
}
format.BitsPerPixel = (Uint8)bpp;
format.BytesPerPixel = (bpp+7)/8;
if(flags == -1)
flags = surf->flags;
if(format.Amask)
flags |= SDL_SRCALPHA;
newsurf = SDL_ConvertSurface(surf, &format, flags);
}
}
else
{
if(SDL_WasInit(SDL_INIT_VIDEO))
newsurf = SDL_DisplayFormat(surf);
else
newsurf = SDL_ConvertSurface(surf, surf->format, surf->flags);
}
PySurface_Unprep(self);
final = PySurface_New(newsurf);
if(!final)
SDL_FreeSurface(newsurf);
return final;
}
/*DOC*/ static char doc_surf_convert_alpha[] =
/*DOC*/ "Surface.convert_alpha([src_surface]) -> Surface\n"
/*DOC*/ "new copy of surface with different format and per pixel alpha\n"
/*DOC*/ "\n"
/*DOC*/ "Creates a new copy of the surface with the desired pixel format.\n"
/*DOC*/ "The new surface will be in a format suited for quick blitting to\n"
/*DOC*/ "the given format with per pixel alpha. If no surface is given,\n"
/*DOC*/ "the new surface will be optimized for blittint to the current\n"
/*DOC*/ "display.\n"
/*DOC*/ "\n"
/*DOC*/ "Unlike the convert() method, the pixel format for the new image\n"
/*DOC*/ "will not be exactly the same as the requested source, but it will\n"
/*DOC*/ "be optimized for fast alpha blitting to the destination.\n"
/*DOC*/ ;
static PyObject* surf_convert_alpha(PyObject* self, PyObject* args)
{
SDL_Surface* surf = PySurface_AsSurface(self);
PyObject* final;
PySurfaceObject* srcsurf = NULL;
SDL_Surface* newsurf, *src;
if(!SDL_WasInit(SDL_INIT_VIDEO))
return RAISE(PyExc_SDLError, "cannot convert without pygame.display initialized");
if(!PyArg_ParseTuple(args, "|O!", &PySurface_Type, &srcsurf))
return NULL;
PySurface_Prep(self);
if(srcsurf)
{
/*hmm, we have to figure this out, not all depths have good support for alpha*/
src = PySurface_AsSurface(srcsurf);
newsurf = SDL_DisplayFormatAlpha(surf);
}
else
newsurf = SDL_DisplayFormatAlpha(surf);
PySurface_Unprep(self);
final = PySurface_New(newsurf);
if(!final)
SDL_FreeSurface(newsurf);
return final;
}
/*DOC*/ static char doc_surf_set_clip[] =
/*DOC*/ "Surface.set_clip([rectstyle]) -> None\n"
/*DOC*/ "assign destination clipping rectangle\n"
/*DOC*/ "\n"
/*DOC*/ "Assigns the destination clipping rectangle for the Surface. When\n"
/*DOC*/ "blit or fill operations are performed on the Surface, they are\n"
/*DOC*/ "restricted to the inside of the clipping rectangle. If no\n"
/*DOC*/ "rectangle is passed, the clipping region is set to the entire\n"
/*DOC*/ "Surface area. The rectangle you pass will be clipped to the area of\n"
/*DOC*/ "the Surface.\n"
/*DOC*/ ;
static PyObject* surf_set_clip(PyObject* self, PyObject* args)
{
SDL_Surface* surf = PySurface_AsSurface(self);
PyObject* item;
GAME_Rect *rect=NULL, temp;
SDL_Rect sdlrect;
int result;
if(!surf) return RAISE(PyExc_SDLError, "display Surface quit");
if(PyTuple_Size(args))
{
item = PyTuple_GET_ITEM(args, 0);
if(!(item == Py_None && PyTuple_Size(args) == 1))
{
rect = GameRect_FromObject(args, &temp);
if(!rect)
return RAISE(PyExc_ValueError, "invalid rectstyle object");
sdlrect.x = rect->x;
sdlrect.y = rect->y;
sdlrect.h = rect->h;
sdlrect.w = rect->w;
}
result = SDL_SetClipRect(surf, &sdlrect);
}
else
result = SDL_SetClipRect(surf, NULL);
if(result == -1)
return RAISE(PyExc_SDLError, SDL_GetError());
RETURN_NONE
}
/*DOC*/ static char doc_surf_get_clip[] =
/*DOC*/ "Surface.get_clip() -> rect\n"
/*DOC*/ "query the clipping area\n"
/*DOC*/ "\n"
/*DOC*/ "Returns the current destination clipping area being used by the\n"
/*DOC*/ "Surface. If the clipping area is not set, it will return a\n"
/*DOC*/ "rectangle containing the full Surface area.\n"
/*DOC*/ ;
static PyObject* surf_get_clip(PyObject* self, PyObject* args)
{
SDL_Surface* surf = PySurface_AsSurface(self);
if(!surf) return RAISE(PyExc_SDLError, "display Surface quit");
return PyRect_New(&surf->clip_rect);
}
/*DOC*/ static char doc_surf_fill[] =
/*DOC*/ "Surface.fill(color, [rectstyle])) -> Rect\n"
/*DOC*/ "fill areas of a Surface\n"
/*DOC*/ "\n"
/*DOC*/ "Fills the specified area of the Surface with the mapped color\n"
/*DOC*/ "value. If no destination rectangle is supplied, it will fill the\n"
/*DOC*/ "entire Surface.\n"
/*DOC*/ "\n"
/*DOC*/ "The color argument can be a RGBA sequence or a mapped color integer.\n"
/*DOC*/ "\n"
/*DOC*/ "The fill is subject to be clipped by the active clipping\n"
/*DOC*/ "rectangle. The return value contains the actual area filled.\n"
/*DOC*/ ;
static PyObject* surf_fill(PyObject* self, PyObject* args)
{
SDL_Surface* surf = PySurface_AsSurface(self);
GAME_Rect *rect, temp;
PyObject* r = NULL;
Uint32 color;
int result;
PyObject* rgba_obj;
Uint8 rgba[4];
SDL_Rect sdlrect;
if(!PyArg_ParseTuple(args, "O|O", &rgba_obj, &r))
return NULL;
if(!surf) return RAISE(PyExc_SDLError, "display Surface quit");
if(surf->flags & SDL_OPENGL)
return RAISE(PyExc_SDLError, "Cannot call on OPENGL Surfaces");
if(PyInt_Check(rgba_obj))
color = (Uint32)PyInt_AsLong(rgba_obj);
else if(RGBAFromObj(rgba_obj, rgba))
color = SDL_MapRGBA(surf->format, rgba[0], rgba[1], rgba[2], rgba[3]);
else
return RAISE(PyExc_TypeError, "invalid color argument");
if(!r)
{
rect = &temp;
temp.x = temp.y = 0;
temp.w = surf->w;
temp.h = surf->h;
}
else if(!(rect = GameRect_FromObject(r, &temp)))
return RAISE(PyExc_ValueError, "invalid rectstyle object");
/*we need a fresh copy so our Rect values don't get munged*/
if(rect != &temp)
{
memcpy(&temp, rect, sizeof(temp));
rect = &temp;
}
if(rect->w < 0 || rect->h < 0)
{
sdlrect.x = sdlrect.y = 0;
sdlrect.w = sdlrect.h = 0;
}
else
{
sdlrect.x = rect->x;
sdlrect.y = rect->y;
sdlrect.w = rect->w;
sdlrect.h = rect->h;
PySurface_Prep(self);
result = SDL_FillRect(surf, &sdlrect, color);
PySurface_Unprep(self);
if(result == -1)
return RAISE(PyExc_SDLError, SDL_GetError());
}
return PyRect_New(&sdlrect);
}
/*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 result, suboffsetx=0, suboffsety=0;
SDL_Rect orig_clip, sub_clip;
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) &&
!(src->format->Amask && !(src->flags&SDL_SRCALPHA)) && /*special case, SDL works*/
(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[] =
/*DOC*/ "Surface.blit(source, destpos, [sourcerect]) -> Rect\n"
/*DOC*/ "copy a one Surface to another.\n"
/*DOC*/ "\n"
/*DOC*/ "The blitting will copy pixels from the source. It will\n"
/*DOC*/ "respect any special modes like colorkeying and alpha. If hardware\n"
/*DOC*/ "support is available, it will be used. The given source is the\n"
/*DOC*/ "Surface to copy from. The destoffset is a 2-number-sequence that\n"
/*DOC*/ "specifies where on the destination Surface the blit happens (see below).\n"
/*DOC*/ "When sourcerect isn't supplied, the blit will copy the\n"
/*DOC*/ "entire source surface. If you would like to copy only a portion\n"
/*DOC*/ "of the source, use the sourcerect argument to control\n"
/*DOC*/ "what area is copied.\n"
/*DOC*/ "\n"
/*DOC*/ "The blit is subject to be clipped by the active clipping\n"
/*DOC*/ "rectangle. The return value contains the actual area blitted.\n"
/*DOC*/ "\n"
/*DOC*/ "As a shortcut, the destination position can be passed as a\n"
/*DOC*/ "rectangle. If a rectangle is given, the blit will use the topleft\n"
/*DOC*/ "corner of the rectangle as the blit destination position. The\n"
/*DOC*/ "rectangle sizes will be ignored.\n"
#if 0 /* "" */
/*DOC*/ "\n"
/*DOC*/ "Blitting surfaces with pixel alphas onto an 8bit destination will\n"
/*DOC*/ "not use the surface alpha values.\n"
#endif /* "" */
/*DOC*/ ;
static PyObject* surf_blit(PyObject* self, PyObject* args)
{
SDL_Surface* src, *dest = PySurface_AsSurface(self);
GAME_Rect* src_rect, temp;
PyObject* srcobject, *argpos, *argrect = NULL;
int dx, dy, result;
SDL_Rect dest_rect, sdlsrc_rect;
int sx, sy;
if(!PyArg_ParseTuple(args, "O!O|O", &PySurface_Type, &srcobject, &argpos, &argrect))
return NULL;
src = PySurface_AsSurface(srcobject);
if(!dest || !src) return RAISE(PyExc_SDLError, "display Surface quit");
if(dest->flags & SDL_OPENGL && !(dest->flags&(SDL_OPENGLBLIT&~SDL_OPENGL)))
return RAISE(PyExc_SDLError, "Cannot blit to OPENGL Surfaces (OPENGLBLIT is ok)");
if((src_rect = GameRect_FromObject(argpos, &temp)))
{
dx = src_rect->x;
dy = src_rect->y;
}
else if(TwoIntsFromObj(argpos, &sx, &sy))
{
dx = sx;
dy = sy;
}
else
return RAISE(PyExc_TypeError, "invalid destination position for blit");
if(argrect)
{
if(!(src_rect = GameRect_FromObject(argrect, &temp)))
return RAISE(PyExc_TypeError, "Invalid rectstyle argument");
}
else
{
temp.x = temp.y = 0;
temp.w = src->w;
temp.h = src->h;
src_rect = &temp;
}
dest_rect.x = (short)dx;
dest_rect.y = (short)dy;
dest_rect.w = (unsigned short)src_rect->w;
dest_rect.h = (unsigned short)src_rect->h;
sdlsrc_rect.x = (short)src_rect->x;
sdlsrc_rect.y = (short)src_rect->y;
sdlsrc_rect.w = (unsigned short)src_rect->w;
sdlsrc_rect.h = (unsigned short)src_rect->h;
result = PySurface_Blit(self, srcobject, &dest_rect, &sdlsrc_rect);
if(result != 0)
return NULL;
return PyRect_New(&dest_rect);
}
/*DOC*/ static char doc_surf_get_flags[] =
/*DOC*/ "Surface.get_flags() -> flags\n"
/*DOC*/ "query the surface flags\n"
/*DOC*/ "\n"
/*DOC*/ "Returns the current state flags for the surface.\n"
/*DOC*/ ;
static PyObject* surf_get_flags(PyObject* self, PyObject* args)
{
SDL_Surface* surf = PySurface_AsSurface(self);
if(!surf) return RAISE(PyExc_SDLError, "display Surface quit");
return PyInt_FromLong(surf->flags);
}
/*DOC*/ static char doc_surf_get_pitch[] =
/*DOC*/ "Surface.get_pitch() -> pitch\n"
/*DOC*/ "query the surface pitch\n"
/*DOC*/ "\n"
/*DOC*/ "The surface pitch is the number of bytes used in each\n"
/*DOC*/ "scanline. This function should rarely needed, mainly for\n"
/*DOC*/ "any special-case debugging.\n"
/*DOC*/ ;
static PyObject* surf_get_pitch(PyObject* self, PyObject* args)
{
SDL_Surface* surf = PySurface_AsSurface(self);
if(!surf) return RAISE(PyExc_SDLError, "display Surface quit");
return PyInt_FromLong(surf->pitch);
}
/*DOC*/ static char doc_surf_get_size[] =
/*DOC*/ "Surface.get_size() -> x, y\n"
/*DOC*/ "query the surface size\n"
/*DOC*/ "\n"
/*DOC*/ "Returns the width and height of the Surface.\n"
/*DOC*/ ;
static PyObject* surf_get_size(PyObject* self, PyObject* args)
{
SDL_Surface* surf = PySurface_AsSurface(self);
if(!surf) return RAISE(PyExc_SDLError, "display Surface quit");
return Py_BuildValue("(ii)", surf->w, surf->h);
}
/*DOC*/ static char doc_surf_get_width[] =
/*DOC*/ "Surface.get_width() -> width\n"
/*DOC*/ "query the surface width\n"
/*DOC*/ "\n"
/*DOC*/ "Returns the width of the Surface.\n"
/*DOC*/ ;
static PyObject* surf_get_width(PyObject* self, PyObject* args)
{
SDL_Surface* surf = PySurface_AsSurface(self);
if(!surf) return RAISE(PyExc_SDLError, "display Surface quit");
return PyInt_FromLong(surf->w);
}
/*DOC*/ static char doc_surf_get_height[] =
/*DOC*/ "Surface.get_height() -> height\n"
/*DOC*/ "query the surface height\n"
/*DOC*/ "\n"
/*DOC*/ "Returns the height of the Surface.\n"
/*DOC*/ ;
static PyObject* surf_get_height(PyObject* self, PyObject* args)
{
SDL_Surface* surf = PySurface_AsSurface(self);
if(!surf) return RAISE(PyExc_SDLError, "display Surface quit");
return PyInt_FromLong(surf->h);
}
/*DOC*/ static char doc_surf_get_rect[] =
/*DOC*/ "Surface.get_rect(**kwargs) -> rect\n"
/*DOC*/ "get a rectangle covering the entire surface\n"
/*DOC*/ "\n"
/*DOC*/ "Returns a new rectangle covering the entire surface.\n"
/*DOC*/ "This rectangle will always start at 0, 0 with a width.\n"
/*DOC*/ "and height the same size as the image.\n"
/*DOC*/ "\n"
/*DOC*/ "You can pass keyword argument values to this function.\n"
/*DOC*/ "These named values will be applied to the attributes of\n"
/*DOC*/ "the Rect before it is returned. An example would be\n"
/*DOC*/ "'mysurf.get_rect(center=(100,100))' to create a rectangle\n"
/*DOC*/ "for the Surface centered at a given position.\n"
/*DOC*/ ;
static PyObject* surf_get_rect(PyObject* self, PyObject* args, PyObject* kw)
{
PyObject *rect;
SDL_Surface* surf = PySurface_AsSurface(self);
if(!surf) return RAISE(PyExc_SDLError, "display Surface quit");
rect = PyRect_New4(0, 0, surf->w, surf->h);
if(rect && kw)
{
PyObject *key, *value;
int pos=0;
while(PyDict_Next(kw, &pos, &key, &value))
{
if((PyObject_SetAttr(rect, key, value) == -1))
{
Py_DECREF(rect);
return NULL;
}
}
}
return rect;
}
/*DOC*/ static char doc_surf_get_bitsize[] =
/*DOC*/ "Surface.get_bitsize() -> int\n"
/*DOC*/ "query size of pixel\n"
/*DOC*/ "\n"
/*DOC*/ "Returns the number of bits used to represent each pixel. This\n"
/*DOC*/ "value may not exactly fill the number of bytes used per pixel.\n"
/*DOC*/ "For example a 15 bit Surface still requires a full 2 bytes.\n"
/*DOC*/ ;
static PyObject* surf_get_bitsize(PyObject* self, PyObject* args)
{
SDL_Surface* surf = PySurface_AsSurface(self);
return PyInt_FromLong(surf->format->BitsPerPixel);
}
/*DOC*/ static char doc_surf_get_bytesize[] =
/*DOC*/ "Surface.get_bytesize() -> int\n"
/*DOC*/ "query size of pixel\n"
/*DOC*/ "\n"
/*DOC*/ "Returns the number of bytes used to store each pixel.\n"
/*DOC*/ ;
static PyObject* surf_get_bytesize(PyObject* self, PyObject* args)
{
SDL_Surface* surf = PySurface_AsSurface(self);
return PyInt_FromLong(surf->format->BytesPerPixel);
}
/*DOC*/ static char doc_surf_get_masks[] =
/*DOC*/ "Surface.get_masks() -> redmask, greenmask, bluemask, alphamask\n"
/*DOC*/ "get mapping bitmasks for each colorplane\n"
/*DOC*/ "\n"
/*DOC*/ "Returns the bitmasks for each color plane. The bitmask is used to\n"
/*DOC*/ "isolate each colorplane value from a mapped color value. A value\n"
/*DOC*/ "of zero means that colorplane is not used (like alpha)\n"
/*DOC*/ ;
static PyObject* surf_get_masks(PyObject* self, PyObject* args)
{
SDL_Surface* surf = PySurface_AsSurface(self);
if(!surf) return RAISE(PyExc_SDLError, "display Surface quit");
return Py_BuildValue("(iiii)", surf->format->Rmask, surf->format->Gmask,
surf->format->Bmask, surf->format->Amask);
}
/*DOC*/ static char doc_surf_get_shifts[] =
/*DOC*/ "Surface.get_shifts() -> redshift, greenshift, blueshift,\n"
/*DOC*/ "alphashift\n"
/*DOC*/ "get mapping shifts for each colorplane\n"
/*DOC*/ "\n"
/*DOC*/ "Returns the bitshifts used for each color plane. The shift is\n"
/*DOC*/ "determine how many bits left-shifted a colorplane value is in a\n"
/*DOC*/ "mapped color value.\n"
/*DOC*/ ;
static PyObject* surf_get_shifts(PyObject* self, PyObject* args)
{
SDL_Surface* surf = PySurface_AsSurface(self);
if(!surf) return RAISE(PyExc_SDLError, "display Surface quit");
return Py_BuildValue("(iiii)", surf->format->Rshift, surf->format->Gshift,
surf->format->Bshift, surf->format->Ashift);
}
/*DOC*/ static char doc_surf_get_losses[] =
/*DOC*/ "Surface.get_losses() -> redloss, greenloss, blueloss, alphaloss\n"
/*DOC*/ "get mapping losses for each colorplane\n"
/*DOC*/ "\n"
/*DOC*/ "Returns the bitloss for each color plane. The loss is the number\n"
/*DOC*/ "of bits removed for each colorplane from a full 8 bits of\n"
/*DOC*/ "resolution. A value of 8 usually indicates that colorplane is not\n"
/*DOC*/ "used (like the alpha)\n"
/*DOC*/ ;
static PyObject* surf_get_losses(PyObject* self, PyObject* args)
{
SDL_Surface* surf = PySurface_AsSurface(self);
if(!surf) return RAISE(PyExc_SDLError, "display Surface quit");
return Py_BuildValue("(iiii)", surf->format->Rloss, surf->format->Gloss,
surf->format->Bloss, surf->format->Aloss);
}
/*DOC*/ static char doc_surf_subsurface[] =
/*DOC*/ "Surface.subsurface(rectstyle) -> Surface\n"
/*DOC*/ "create a new surface that shares pixel data\n"
/*DOC*/ "\n"
/*DOC*/ "Creates a new surface that shares pixel data of the given surface.\n"
/*DOC*/ "Note that only the pixel data is shared. Things like clipping rectangles\n"
/*DOC*/ "and colorkeys will be unique for the new surface.\n"
/*DOC*/ "\n"
/*DOC*/ "The new subsurface will inherit the palette, colorkey, and surface alpha\n"
/*DOC*/ "values from the base image.\n"
/*DOC*/ "\n"
/*DOC*/ "You should not use the RLEACCEL flag for parent surfaces of subsurfaces,\n"
/*DOC*/ "for the most part it will work, but it will cause a lot of extra work,\n"
/*DOC*/ "every time you change the subsurface, you must decode and recode the\n"
/*DOC*/ "RLEACCEL data for the parent surface.\n"
/*DOC*/ "\n"
/*DOC*/ "As for using RLEACCEL with the subsurfaces, that will work as you'd\n"
/*DOC*/ "expect, but changes the the parent Surface will not always take effect\n"
/*DOC*/ "in the subsurface.\n"
/*DOC*/ ;
static PyObject* surf_subsurface(PyObject* self, PyObject* args)
{
SDL_Surface* surf = PySurface_AsSurface(self);
SDL_PixelFormat* format = surf->format;
GAME_Rect *rect, temp;
SDL_Surface* sub;
PyObject* subobj;
int pixeloffset;
char* startpixel;
struct SubSurface_Data* data;
if(!surf) return RAISE(PyExc_SDLError, "display Surface quit");
if(surf->flags & SDL_OPENGL)
return RAISE(PyExc_SDLError, "Cannot call on OPENGL Surfaces");
if(!(rect = GameRect_FromObject(args, &temp)))
return RAISE(PyExc_ValueError, "invalid rectstyle argument");
if(rect->x < 0 || rect-> y < 0 || rect->x + rect->w > surf->w || rect->y + rect->h > surf->h)
return RAISE(PyExc_ValueError, "subsurface rectangle outside surface area");
PySurface_Lock(self);
pixeloffset = rect->x * format->BytesPerPixel + rect->y * surf->pitch;
startpixel = ((char*)surf->pixels) + pixeloffset;
sub = SDL_CreateRGBSurfaceFrom(startpixel, rect->w, rect->h, format->BitsPerPixel, \
surf->pitch, format->Rmask, format->Gmask, format->Bmask, format->Amask);
PySurface_Unlock(self);
if(!sub)
return RAISE(PyExc_SDLError, SDL_GetError());
/*copy the colormap if we need it*/
if(surf->format->BytesPerPixel == 1 && surf->format->palette)
SDL_SetPalette(sub, SDL_LOGPAL, surf->format->palette->colors, 0, surf->format->palette->ncolors);
if(surf->flags & SDL_SRCALPHA)
SDL_SetAlpha(sub, surf->flags&SDL_SRCALPHA, format->alpha);
if(surf->flags & SDL_SRCCOLORKEY)
SDL_SetColorKey(sub, surf->flags&(SDL_SRCCOLORKEY|SDL_RLEACCEL), format->colorkey);
data = PyMem_New(struct SubSurface_Data, 1);
if(!data) return NULL;
subobj = PySurface_New(sub);
if(!subobj)
{
PyMem_Del(data);
return NULL;
}
Py_INCREF(self);
data->owner = self;
data->pixeloffset = pixeloffset;
data->offsetx = rect->x;
data->offsety = rect->y;
((PySurfaceObject*)subobj)->subsurface = data;
return subobj;
}
/*DOC*/ static char doc_surf_get_offset[] =
/*DOC*/ "Surface.get_offset() -> x, y\n"
/*DOC*/ "get offset of subsurface\n"
/*DOC*/ "\n"
/*DOC*/ "Returns the X and Y position a subsurface is positioned\n"
/*DOC*/ "inside its parent. Will return 0,0 for surfaces that are\n"
/*DOC*/ "not a subsurface.\n"
/*DOC*/ ;
static PyObject* surf_get_offset(PyObject* self, PyObject* args)
{
struct SubSurface_Data *subdata;
subdata = ((PySurfaceObject*)self)->subsurface;
if(!subdata)
return Py_BuildValue("(ii)", 0, 0);
return Py_BuildValue("(ii)", subdata->offsetx, subdata->offsety);
}
/*DOC*/ static char doc_surf_get_abs_offset[] =
/*DOC*/ "Surface.get_abs_offset() -> x, y\n"
/*DOC*/ "get absolute offset of subsurface\n"
/*DOC*/ "\n"
/*DOC*/ "Returns the absolute X and Y position a subsurface is positioned\n"
/*DOC*/ "inside its top level parent. Will return 0,0 for surfaces that are\n"
/*DOC*/ "not a subsurface.\n"
/*DOC*/ ;
static PyObject* surf_get_abs_offset(PyObject* self, PyObject* args)
{
struct SubSurface_Data *subdata;
PyObject *owner;
int offsetx, offsety;
subdata = ((PySurfaceObject*)self)->subsurface;
if(!subdata)
return Py_BuildValue("(ii)", 0, 0);
subdata = ((PySurfaceObject*)self)->subsurface;
owner = subdata->owner;
offsetx = subdata->offsetx;
offsety = subdata->offsety;
while(((PySurfaceObject*)owner)->subsurface)
{
subdata = ((PySurfaceObject*)owner)->subsurface;
owner = subdata->owner;
offsetx += subdata->offsetx;
offsety += subdata->offsety;
}
return Py_BuildValue("(ii)", offsetx, offsety);
}
/*DOC*/ static char doc_surf_get_parent[] =
/*DOC*/ "Surface.get_parent() -> Surface\n"
/*DOC*/ "get a subsurface parent\n"
/*DOC*/ "\n"
/*DOC*/ "Returns the Surface that is a parent of this subsurface.\n"
/*DOC*/ "Will return None if this is not a subsurface.\n"
/*DOC*/ ;
static PyObject* surf_get_parent(PyObject* self, PyObject* args)
{
struct SubSurface_Data *subdata;
subdata = ((PySurfaceObject*)self)->subsurface;
if(!subdata)
RETURN_NONE
Py_INCREF(subdata->owner);
return subdata->owner;
}
/*DOC*/ static char doc_surf_get_abs_parent[] =
/*DOC*/ "Surface.get_abs_parent() -> Surface\n"
/*DOC*/ "get the toplevel surface for a subsurface\n"
/*DOC*/ "\n"
/*DOC*/ "Returns the top level Surface for this subsurface. If this is not\n"
/*DOC*/ "a subsurface it will return a reference to itself. You will always\n"
/*DOC*/ "get a valid surface from this method.\n"
/*DOC*/ ;
static PyObject* surf_get_abs_parent(PyObject* self, PyObject* args)
{
struct SubSurface_Data *subdata;
PyObject *owner;
subdata = ((PySurfaceObject*)self)->subsurface;
if(!subdata)
{
Py_INCREF(self);
return self;
}
subdata = ((PySurfaceObject*)self)->subsurface;
owner = subdata->owner;
while(((PySurfaceObject*)owner)->subsurface)
{
subdata = ((PySurfaceObject*)owner)->subsurface;
owner = subdata->owner;
}
Py_INCREF(owner);
return owner;
}
static struct PyMethodDef surface_methods[] =
{
{"get_at", surf_get_at, 1, doc_surf_get_at },
{"set_at", surf_set_at, 1, doc_surf_set_at },
{"map_rgb", surf_map_rgb, 1, doc_surf_map_rgb },
{"unmap_rgb", surf_unmap_rgb, 1, doc_surf_unmap_rgb },
{"get_palette", surf_get_palette, 1, doc_surf_get_palette },
{"get_palette_at", surf_get_palette_at,1, doc_surf_get_palette_at },
{"set_palette", surf_set_palette, 1, doc_surf_set_palette },
{"set_palette_at", surf_set_palette_at,1, doc_surf_set_palette_at },
{"lock", surf_lock, 1, doc_surf_lock },
{"unlock", surf_unlock, 1, doc_surf_unlock },
{"mustlock", surf_mustlock, 1, doc_surf_mustlock },
{"get_locked", surf_get_locked, 1, doc_surf_get_locked },
{"set_colorkey", surf_set_colorkey, 1, doc_surf_set_colorkey },
{"get_colorkey", surf_get_colorkey, 1, doc_surf_get_colorkey },
{"set_alpha", surf_set_alpha, 1, doc_surf_set_alpha },
{"get_alpha", surf_get_alpha, 1, doc_surf_get_alpha },
{"copy", surf_copy, 1, doc_surf_copy },
{"__copy__", surf_copy, 1, NULL },
{"convert", surf_convert, 1, doc_surf_convert },
{"convert_alpha", surf_convert_alpha, 1, doc_surf_convert_alpha },
{"set_clip", surf_set_clip, 1, doc_surf_set_clip },
{"get_clip", surf_get_clip, 1, doc_surf_get_clip },
{"fill", surf_fill, 1, doc_surf_fill },
{"blit", surf_blit, 1, doc_surf_blit },
{"get_flags", surf_get_flags, 1, doc_surf_get_flags },
{"get_size", surf_get_size, 1, doc_surf_get_size },
{"get_width", surf_get_width, 1, doc_surf_get_width },
{"get_height", surf_get_height, 1, doc_surf_get_height },
{"get_rect", (PyCFunction)surf_get_rect, METH_KEYWORDS, doc_surf_get_rect },
{"get_pitch", surf_get_pitch, 1, doc_surf_get_pitch },
{"get_bitsize", surf_get_bitsize, 1, doc_surf_get_bitsize },
{"get_bytesize", surf_get_bytesize, 1, doc_surf_get_bytesize },
{"get_masks", surf_get_masks, 1, doc_surf_get_masks },
{"get_shifts", surf_get_shifts, 1, doc_surf_get_shifts },
{"get_losses", surf_get_losses, 1, doc_surf_get_losses },
{"subsurface", surf_subsurface, 1, doc_surf_subsurface },
{"get_offset", surf_get_offset, 1, doc_surf_get_offset },
{"get_abs_offset", surf_get_abs_offset, 1, doc_surf_get_abs_offset },
{"get_parent", surf_get_parent, 1, doc_surf_get_parent },
{"get_abs_parent", surf_get_abs_parent, 1, doc_surf_get_abs_parent },
{NULL, NULL}
};
/* surface object internals */
static void surface_cleanup(PySurfaceObject* self)
{
if(self->surf)
{
if(!(self->surf->flags&SDL_HWSURFACE) || SDL_WasInit(SDL_INIT_VIDEO))
{
/*unsafe to free hardware surfaces without video init*/
/*i question SDL's ability to free a locked hardware surface*/
SDL_FreeSurface(self->surf);
}
self->surf = NULL;
}
if(self->subsurface)
{
Py_XDECREF(self->subsurface->owner);
PyMem_Del(self->subsurface);
self->subsurface = NULL;
}
if(self->dependency) {
Py_DECREF(self->dependency);
self->dependency = NULL;
}
}
static void surface_dealloc(PyObject* self)
{
if(((PySurfaceObject*)self)->weakreflist)
{
PyObject_ClearWeakRefs(self);
}
surface_cleanup((PySurfaceObject*)self);
self->ob_type->tp_free(self);
}
PyObject* surface_str(PyObject* self)
{
char str[1024];
SDL_Surface* surf = PySurface_AsSurface(self);
const char* type;
if(surf)
{
type = (surf->flags&SDL_HWSURFACE)?"HW":"SW";
sprintf(str, "<Surface(%dx%dx%d %s)>", surf->w, surf->h, surf->format->BitsPerPixel, type);
}
else
{
strcpy(str, "<Surface(Dead Display)>");
}
return PyString_FromString(str);
}
#if 0
/*DOC*/ static char doc_Surface_MODULE[] =
/*DOC*/ "Surface objects represent a simple memory buffer of pixels.\n"
/*DOC*/ "Surface objects can reside in system memory, or in special\n"
/*DOC*/ "hardware memory, which can be hardware accelerated. Surfaces that\n"
/*DOC*/ "are 8 bits per pixel use a colormap to represent their color\n"
/*DOC*/ "values. All Surfaces with higher bits per pixel use a packed\n"
/*DOC*/ "pixels to store their color values.\n"
/*DOC*/ "\n"
/*DOC*/ "Creating a new Surface().\n"
/*DOC*/ "\n"
/*DOC*/ "Surfaces can have many extra attributes like alpha planes,\n"
/*DOC*/ "colorkeys, source rectangle clipping. These functions mainly\n"
/*DOC*/ "effect how the Surface is blitted to other Surfaces. The blit\n"
/*DOC*/ "routines will attempt to use hardware acceleration when possible,\n"
/*DOC*/ "otherwise will use highly optimized software blitting methods.\n"
/*DOC*/ "\n"
/*DOC*/ "There is support for pixel access for the Surfaces. Pixel access\n"
/*DOC*/ "on hardware surfaces is slow and not recommended. Pixels can be\n"
/*DOC*/ "accessed using the get_at() and set_at() functions. These methods\n"
/*DOC*/ "are fine for simple access, but will be considerably slow when\n"
/*DOC*/ "doing of pixel work with them. If you plan on doing a lot of\n"
/*DOC*/ "pixel level work, it is recommended to use the pygame.surfarray\n"
/*DOC*/ "module, which can treat the surfaces like large multidimensional\n"
/*DOC*/ "arrays (and it's quite quick).\n"
/*DOC*/ ;
#endif
/*DOC*/ static char doc_Surface[] =
/*DOC*/ "pygame.Surface(size, [flags, [Surface|depth, [masks]]]) -> Surface\n"
/*DOC*/ "create a new Surface\n"
/*DOC*/ "\n"
/*DOC*/ "Creates a new surface object. Size is a 2-int-sequence containing\n"
/*DOC*/ "width and height. Depth is the number of bits used per pixel. If\n"
/*DOC*/ "omitted, depth will use the current display depth. Masks is a\n"
/*DOC*/ "four item sequence containing the bitmask for r,g,b, and a. If\n"
/*DOC*/ "omitted, masks will default to the usual values for the given\n"
/*DOC*/ "bitdepth. Flags is a mix of the following flags: SWSURFACE,\n"
/*DOC*/ "HWSURFACE, ASYNCBLIT, or SRCALPHA. (flags = 0 is the\n"
/*DOC*/ "same as SWSURFACE). Depth and masks can be substituted for\n"
/*DOC*/ "another surface object which will create the new surface with the\n"
/*DOC*/ "same format as the given one. When using default masks, alpha\n"
/*DOC*/ "will always be ignored unless you pass SRCALPHA as a flag.\n"
/*DOC*/ "For a plain software surface, 0 can be used for the flag. \n"
/*DOC*/ "A plain hardware surface can just use 1 for the flag.\n"
/*DOC*/ ;
static PyTypeObject PySurface_Type =
{
PyObject_HEAD_INIT(NULL)
0, /*size*/
"pygame.Surface", /*name*/
sizeof(PySurfaceObject), /*basic size*/
0, /*itemsize*/
surface_dealloc, /*dealloc*/
0, /*print*/
NULL, /*getattr*/
NULL, /*setattr*/
NULL, /*compare*/
surface_str, /*repr*/
NULL, /*as_number*/
NULL, /*as_sequence*/
NULL, /*as_mapping*/
(hashfunc)NULL, /*hash*/
(ternaryfunc)NULL, /*call*/
(reprfunc)NULL, /*str*/
0,
0L,0L,
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
doc_Surface, /* Documentation string */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
offsetof(PySurfaceObject, weakreflist), /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
surface_methods, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
(initproc)surface_init, /* tp_init */
0, /* tp_alloc */
surface_new, /* tp_new */
};
static PyObject* PySurface_New(SDL_Surface* s)
{
PySurfaceObject* self;
if(!s) return RAISE(PyExc_SDLError, SDL_GetError());
self = (PySurfaceObject *)PySurface_Type.tp_new(&PySurface_Type, NULL, NULL);
if(self)
{
self->surf = s;
}
return (PyObject*)self;
}
static PyObject* surface_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
PySurfaceObject *self;
self = (PySurfaceObject *)type->tp_alloc(type, 0);
if (self)
{
self->surf = NULL;
self->subsurface = NULL;
self->weakreflist = NULL;
}
return (PyObject *)self;
}
static int surface_init(PySurfaceObject *self, PyObject *args, PyObject *kwds)
{
Uint32 flags = 0;
int width, height;
PyObject *depth=NULL, *masks=NULL;
int bpp;
Uint32 Rmask, Gmask, Bmask, Amask;
SDL_Surface* surface;
SDL_PixelFormat default_format;
if(!PyArg_ParseTuple(args, "(ii)|iOO", &width, &height, &flags, &depth, &masks))
return -1;
if(width < 0 || height < 0)
{
RAISE(PyExc_SDLError, "Invalid resolution for Surface");
return -1;
}
surface_cleanup(self);
if(depth && masks) /*all info supplied, most errorchecking needed*/
{
if(PySurface_Check(depth))
return (int)RAISE(PyExc_ValueError, "cannot pass surface for depth and color masks");
if(!IntFromObj(depth, &bpp))
return (int)RAISE(PyExc_ValueError, "invalid bits per pixel depth argument");
if(!PySequence_Check(masks) || PySequence_Length(masks)!=4)
return (int)RAISE(PyExc_ValueError, "masks argument must be sequence of four numbers");
if(!UintFromObjIndex(masks, 0, &Rmask) || !UintFromObjIndex(masks, 1, &Gmask) ||
!UintFromObjIndex(masks, 2, &Bmask) || !UintFromObjIndex(masks, 3, &Amask))
return (int)RAISE(PyExc_ValueError, "invalid mask values in masks sequence");
}
else if(depth && PyNumber_Check(depth))/*use default masks*/
{
if(!IntFromObj(depth, &bpp))
return (int)RAISE(PyExc_ValueError, "invalid bits per pixel depth argument");
if(flags & SDL_SRCALPHA)
{
switch(bpp)
{
case 16:
Rmask = 0xF<<8; Gmask = 0xF<<4; Bmask = 0xF; Amask = 0xF<<12; break;
case 32:
Rmask = 0xFF<<16; Gmask = 0xFF<<8; Bmask = 0xFF; Amask = 0xFF<<24; break;
default:
return (int)RAISE(PyExc_ValueError, "no standard masks exist for given bitdepth with alpha");
}
}
else
{
Amask = 0;
switch(bpp)
{
case 8:
Rmask = 0xFF>>6<<5; Gmask = 0xFF>>5<<2; Bmask = 0xFF>>6; break;
case 12:
Rmask = 0xFF>>4<<8; Gmask = 0xFF>>4<<4; Bmask = 0xFF>>4; break;
case 15:
Rmask = 0xFF>>3<<10; Gmask = 0xFF>>3<<5; Bmask = 0xFF>>3; break;
case 16:
Rmask = 0xFF>>3<<11; Gmask = 0xFF>>2<<5; Bmask = 0xFF>>3; break;
case 24:
case 32:
Rmask = 0xFF<<16; Gmask = 0xFF<<8; Bmask = 0xFF; break;
default:
return (int)RAISE(PyExc_ValueError, "nonstandard bit depth given");
}
}
}
else /*no depth or surface*/
{
SDL_PixelFormat* pix;
if(depth && PySurface_Check(depth))
pix = ((PySurfaceObject*)depth)->surf->format;
else if(SDL_GetVideoSurface())
pix = SDL_GetVideoSurface()->format;
else if(SDL_WasInit(SDL_INIT_VIDEO))
pix = SDL_GetVideoInfo()->vfmt;
else
{
pix = &default_format;
pix->BitsPerPixel = 32; pix->Amask = 0;
pix->Rmask = 0xFF0000; pix->Gmask = 0xFF00; pix->Bmask = 0xFF;
}
bpp = pix->BitsPerPixel;
Rmask = pix->Rmask;
Gmask = pix->Gmask;
Bmask = pix->Bmask;
Amask = pix->Amask;
}
surface = SDL_CreateRGBSurface(flags, width, height, bpp, Rmask, Gmask, Bmask, Amask);
if(!surface)
{
RAISE(PyExc_SDLError, SDL_GetError());
return -1;
}
if(surface)
{
self->surf = surface;
self->subsurface = NULL;
}
return 0;
}
static PyMethodDef surface_builtins[] =
{
{ NULL, NULL }
};
/*DOC*/ static char doc_pygame_surface_MODULE[] =
/*DOC*/ "The surface module doesn't have much in the line of functions. It\n"
/*DOC*/ "does have the Surface object, and one routine to create new\n"
/*DOC*/ "surfaces, pygame.Surface().\n"
/*DOC*/ ;
PYGAME_EXPORT
void initsurface(void)
{
PyObject *module, *dict, *apiobj, *lockmodule;
static void* c_api[PYGAMEAPI_SURFACE_NUMSLOTS];
if (PyType_Ready(&PySurface_Type) < 0)
return;
/* create the module */
module = Py_InitModule3("surface", surface_builtins, doc_pygame_surface_MODULE);
dict = PyModule_GetDict(module);
PyDict_SetItemString(dict, "SurfaceType", (PyObject *)&PySurface_Type);
PyDict_SetItemString(dict, "Surface", (PyObject *)&PySurface_Type);
/* 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);
Py_INCREF(PySurface_Type.tp_dict);
PyDict_SetItemString(dict, "_dict", PySurface_Type.tp_dict);
/*imported needed apis*/
import_pygame_base();
import_pygame_rect();
/*import the surflock module manually*/
lockmodule = PyImport_ImportModule("pygame.surflock");
if(lockmodule != NULL)
{
PyObject *dict = PyModule_GetDict(lockmodule);
PyObject *c_api = PyDict_GetItemString(dict, PYGAMEAPI_LOCAL_ENTRY);
if(PyCObject_Check(c_api))
{
int i; void** localptr = (void*)PyCObject_AsVoidPtr(c_api);
for(i = 0; i < PYGAMEAPI_SURFLOCK_NUMSLOTS; ++i)
PyGAME_C_API[i + PYGAMEAPI_SURFLOCK_FIRSTSLOT] = localptr[i];
}
Py_DECREF(lockmodule);
}
}
syntax highlighted by Code2HTML, v. 0.9.1