Commits

pygame  committed ea6bb65

update to 1.4.9

  • Participants
  • Parent commits 841ce59

Comments (0)

Files changed (7)

 
 May 8, 2002
 	music.play() start time works
+	image.save() can save TGA images
+	cannot subsurface a subsurface [BREAK]
+	blits to subsurfaces are passed through
 
 May 7, 2002
 	added the sndarray module

File lib/version.py

 releases. (hmm, until we get to versions > 10)
 """
 
-ver = '1.4.1'
+ver = '1.4.9'
 
 <font size=+5><b>Pygame Readme</b></font>
 </td></tr><tr><td align=left width=33%><big>
 
-Version 1.4 <br>January 27, 2002
+Version 1.4.9 <br>May 8, 2002
 
 
 </td><td align=center width=34%><big>
 
 
 <p><big><b><u>Todo / Ideas</u></b></big> (feel free to submit)<br><ul>
-<li>smarten the config.py and setup.py stuff</li>
-<li>unify the types/classes for python 2.2</li>
+<li>unify more types/classes for python 2.2</li>
 <li>transform.skew() function</li>
 <li>transform.scroll() function</li>
 <li>image filtering (colors,blurs,etc)</li>
 <li>quake-like console with python interpreter</li>
-<li>soundarray module</li>
 <li>game lobby. client, simple server, and protocol</li>
 <li>surfarrays should be able to do RGBA along with RGB</li>
 </ul></p><br>
                         Pygame Readme
-   Version 1.4
-   January 27, 2002 Python Game Development
+   Version 1.4.9
+   May 8, 2002 Python Game Development
    by Pete Shinners http://www.pygame.org
    pete@shinners.org
 
      Numeric package for its multidimensional numeric arrays.
 
    Todo / Ideas (feel free to submit)
-     * smarten the config.py and setup.py stuff
-     * unify the types/classes for python 2.2
+     * unify more types/classes for python 2.2
      * transform.skew() function
      * transform.scroll() function
      * image filtering (colors,blurs,etc)
      * quake-like console with python interpreter
-     * soundarray module
      * game lobby. client, simple server, and protocol
      * surfarrays should be able to do RGBA along with RGB
 
 
 METADATA = {
     "name":             "pygame",
-    "version":          "1.4.1",
+    "version":          "1.4.9",
     "license":          "LGPL",
     "url":              "http://www.pygame.org",
     "author":           "Pete Shinners",
 
 
 static int is_extended = 0;
+static int SaveTGA(SDL_Surface *surface, char *file, int rle);
+static int SaveTGA_RW(SDL_Surface *surface, SDL_RWops *out, int rle);
 
 
 #define DATAROW(data, row, width, height, flipped) \
 
 	if(PyString_Check(file) || PyUnicode_Check(file))
 	{
+                int namelen;
 		char* name;
 		if(!PyArg_ParseTuple(arg, "O|s", &file, &name))
 			return NULL;
+                namelen = strlen(name);
 		Py_BEGIN_ALLOW_THREADS
-		result = SDL_SaveBMP(surf, name);
+                if(name[namelen-1]=='p' || name[namelen-1]=='P')
+		    result = SDL_SaveBMP(surf, name);
+                else
+                    result = SaveTGA(surf, name, 1);
 		Py_END_ALLOW_THREADS
 	}
 	else
 		SDL_RWops* rw;
 		if(!(rw = RWopsFromPython(file)))
 			return NULL;
-		result = SDL_SaveBMP_RW(surf, rw, 1);
+/*		result = SDL_SaveBMP_RW(surf, rw, 1);*/
+		result = SaveTGA_RW(surf, rw, 1);
 	}
 
 
 	return PySurface_New(surf);
 }
 
+
+
+/*******************************************************/
+/* tga code by Mattias Engdeg�rd, in the public domain */
+/*******************************************************/
+
+struct TGAheader {
+    Uint8 infolen;		/* length of info field */
+    Uint8 has_cmap;		/* 1 if image has colormap, 0 otherwise */
+    Uint8 type;
+
+    Uint8 cmap_start[2];	/* index of first colormap entry */
+    Uint8 cmap_len[2];		/* number of entries in colormap */
+    Uint8 cmap_bits;		/* bits per colormap entry */
+
+    Uint8 yorigin[2];		/* image origin (ignored here) */
+    Uint8 xorigin[2];
+    Uint8 width[2];		/* image size */
+    Uint8 height[2];
+    Uint8 pixel_bits;		/* bits/pixel */
+    Uint8 flags;
+};
+
+enum tga_type {
+    TGA_TYPE_INDEXED = 1,
+    TGA_TYPE_RGB = 2,
+    TGA_TYPE_BW = 3,
+    TGA_TYPE_RLE = 8		/* additive */
+};
+
+
+#define TGA_INTERLEAVE_MASK	0xc0
+#define TGA_INTERLEAVE_NONE	0x00
+#define TGA_INTERLEAVE_2WAY	0x40
+#define TGA_INTERLEAVE_4WAY	0x80
+
+#define TGA_ORIGIN_MASK		0x30
+#define TGA_ORIGIN_LEFT		0x00
+#define TGA_ORIGIN_RIGHT	0x10
+#define TGA_ORIGIN_LOWER	0x00
+#define TGA_ORIGIN_UPPER	0x20
+
+/* read/write unaligned little-endian 16-bit ints */
+#define LE16(p) ((p)[0] + ((p)[1] << 8))
+#define SETLE16(p, v) ((p)[0] = (v), (p)[1] = (v) >> 8)
+
+#ifndef MIN
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+#endif
+
+#define TGA_RLE_MAX 128		/* max length of a TGA RLE chunk */
+/* return the number of bytes in the resulting buffer after RLE-encoding
+   a line of TGA data */
+static int rle_line(Uint8 *src, Uint8 *dst, int w, int bpp)
+{
+    int x = 0;
+    int out = 0;
+    int raw = 0;
+    while(x < w) {
+	Uint32 pix;
+	int x0 = x;
+	memcpy(&pix, src + x * bpp, bpp);
+	x++;
+	while(x < w && memcmp(&pix, src + x * bpp, bpp) == 0
+	      && x - x0 < TGA_RLE_MAX)
+	    x++;
+	/* use a repetition chunk iff the repeated pixels would consume
+	   two bytes or more */
+	if((x - x0 - 1) * bpp >= 2 || x == w) {
+	    /* output previous raw chunks */
+	    while(raw < x0) {
+		int n = MIN(TGA_RLE_MAX, x0 - raw);
+		dst[out++] = n - 1;
+		memcpy(dst + out, src + raw * bpp, n * bpp);
+		out += n * bpp;
+		raw += n;
+	    }
+
+	    if(x - x0 > 0) {
+		/* output new repetition chunk */
+		dst[out++] = 0x7f + x - x0;
+		memcpy(dst + out, &pix, bpp);
+		out += bpp;
+	    }
+	    raw = x;
+	}
+    }
+    return out;
+}
+
+/*
+ * Save a surface to an output stream in TGA format.
+ * 8bpp surfaces are saved as indexed images with 24bpp palette, or with
+ *     32bpp palette if colourkeying is used.
+ * 15, 16, 24 and 32bpp surfaces are saved as 24bpp RGB images,
+ * or as 32bpp RGBA images if alpha channel is used.
+ *
+ * RLE compression is not used in the output file.
+ *
+ * Returns -1 upon error, 0 if success
+ */
+static int SaveTGA_RW(SDL_Surface *surface, SDL_RWops *out, int rle)
+{
+    SDL_Surface *linebuf = NULL;
+    int alpha = 0;
+    int ckey = -1;
+    struct TGAheader h;
+    int srcbpp;
+    unsigned surf_flags;
+    unsigned surf_alpha;
+    Uint32 rmask, gmask, bmask, amask;
+    SDL_Rect r;
+    int bpp;
+    Uint8 *rlebuf = NULL;
+
+    h.infolen = 0;
+    SETLE16(h.cmap_start, 0);
+
+    srcbpp = surface->format->BitsPerPixel;
+    if(srcbpp < 8) {
+	SDL_SetError("cannot save <8bpp images as TGA");
+	return -1;
+    }
+
+    if(srcbpp == 8) {
+	h.has_cmap = 1;
+	h.type = TGA_TYPE_INDEXED;
+	if(surface->flags & SDL_SRCCOLORKEY) {
+	    ckey = surface->format->colorkey;
+	    h.cmap_bits = 32;
+	} else
+	    h.cmap_bits = 24;
+	SETLE16(h.cmap_len, surface->format->palette->ncolors);
+	h.pixel_bits = 8;
+	rmask = gmask = bmask = amask = 0;
+    } else {
+	h.has_cmap = 0;
+	h.type = TGA_TYPE_RGB;
+	h.cmap_bits = 0;
+	SETLE16(h.cmap_len, 0);
+	if(surface->format->Amask) {
+	    alpha = 1;
+	    h.pixel_bits = 32;
+	} else
+	    h.pixel_bits = 24;
+	if(SDL_BYTEORDER == SDL_BIG_ENDIAN) {
+	    int s = alpha ? 0 : 8;
+	    amask = 0x000000ff >> s;
+	    rmask = 0x0000ff00 >> s;
+	    gmask = 0x00ff0000 >> s;
+	    bmask = 0xff000000 >> s;
+	} else {
+	    amask = alpha ? 0xff000000 : 0;
+	    rmask = 0x00ff0000;
+	    gmask = 0x0000ff00;
+	    bmask = 0x000000ff;
+	}
+    }
+    bpp = h.pixel_bits >> 3;
+    if(rle)
+	    h.type += TGA_TYPE_RLE;
+
+    SETLE16(h.yorigin, 0);
+    SETLE16(h.xorigin, 0);
+    SETLE16(h.width, surface->w);
+    SETLE16(h.height, surface->h);
+    h.flags = TGA_ORIGIN_UPPER | (alpha ? 8 : 0);
+
+    if(!SDL_RWwrite(out, &h, sizeof(h), 1))
+	return -1;
+
+    if(h.has_cmap) {
+	int i;
+	SDL_Palette *pal = surface->format->palette;
+	Uint8 entry[4];
+	for(i = 0; i < pal->ncolors; i++) {
+	    entry[0] = pal->colors[i].b;
+	    entry[1] = pal->colors[i].g;
+	    entry[2] = pal->colors[i].r;
+	    entry[3] = (i == ckey) ? 0 : 0xff;
+	    if(!SDL_RWwrite(out, entry, h.cmap_bits >> 3, 1))
+		return -1;
+	}
+    }
+
+    linebuf = SDL_CreateRGBSurface(SDL_SWSURFACE, surface->w, 1, h.pixel_bits,
+				   rmask, gmask, bmask, amask);
+    if(!linebuf)
+	return -1;
+    if(h.has_cmap)
+	SDL_SetColors(linebuf, surface->format->palette->colors, 0,
+		      surface->format->palette->ncolors);
+    if(rle) {
+	rlebuf = malloc(bpp * surface->w + 1 + surface->w / TGA_RLE_MAX);
+	if(!rlebuf) {
+	    SDL_SetError("out of memory");
+	    goto error;
+	}
+    }
+
+    /* Temporarily remove colourkey and alpha from surface so copies are
+       opaque */
+    surf_flags = surface->flags & (SDL_SRCALPHA | SDL_SRCCOLORKEY);
+    surf_alpha = surface->format->alpha;
+    if(surf_flags & SDL_SRCALPHA)
+	SDL_SetAlpha(surface, 0, 255);
+    if(surf_flags & SDL_SRCCOLORKEY)
+	SDL_SetColorKey(surface, 0, surface->format->colorkey);
+
+    r.x = 0;
+    r.w = surface->w;
+    r.h = 1;
+    for(r.y = 0; r.y < surface->h; r.y++) {
+	int n;
+	void *buf;
+	if(SDL_BlitSurface(surface, &r, linebuf, NULL) < 0)
+	    break;
+	if(rle) {
+	    buf = rlebuf;
+	    n = rle_line(linebuf->pixels, rlebuf, surface->w, bpp);
+	} else {
+	    buf = linebuf->pixels;
+	    n = surface->w * bpp;
+	}
+	if(!SDL_RWwrite(out, buf, n, 1))
+	    break;
+    }
+
+    /* restore flags */
+    if(surf_flags & SDL_SRCALPHA)
+	SDL_SetAlpha(surface, SDL_SRCALPHA, surf_alpha);
+    if(surf_flags & SDL_SRCCOLORKEY)
+	SDL_SetColorKey(surface, SDL_SRCCOLORKEY, surface->format->colorkey);
+
+error:
+    free(rlebuf);
+    SDL_FreeSurface(linebuf);
+    return 0;
+}
+
+static int SaveTGA(SDL_Surface *surface, char *file, int rle)
+{
+    SDL_RWops *out = SDL_RWFromFile(file, "wb");
+    int ret;
+    if(!out)
+	return -1;
+    ret = SaveTGA_RW(surface, out, rle);
+    SDL_RWclose(out);
+    return ret;
+}
+
+
+
+
+
+
+
+
+
+
 static PyMethodDef image_builtins[] =
 {
 	{ "load_basic", image_load_basic, 1, doc_load },

File src/surface.c

     /*DOC*/    "rectangle sizes will be ignored.\n"
 #if 0  /* "" */
     /*DOC*/    "\n"
-    /*DOC*/    "Note that blitting surfaces with alpha onto 8bit destinations will\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);
+        SDL_Surface* subsurface = NULL;
 	GAME_Rect* src_rect, temp;
 	PyObject* srcobject, *argpos, *argrect = NULL;
 	int dx, dy, result;
-	SDL_Rect dest_rect;
+	SDL_Rect dest_rect, orig_clip, sub_clip;
 	short sx, sy;
 	int didconvert = 0;
 
 	dest_rect.w = (unsigned short)src_rect->w;
 	dest_rect.h = (unsigned short)src_rect->h;
 
-	PySurface_Prep(self);
+        /*passthrough blits to the real surface*/
+        if(((PySurfaceObject*)self)->subsurface)
+        {
+            int offsetx, offsety, offset;
+            offset = ((PySurfaceObject*)self)->subsurface->pixeloffset;
+            subsurface = PySurface_AsSurface(((PySurfaceObject*)self)->subsurface->owner);
+            
+            offsetx = (offset/subsurface->format->BytesPerPixel) % subsurface->pitch;
+            offsety = offset / subsurface->pitch;
+            SDL_GetClipRect(subsurface, &orig_clip);
+            SDL_GetClipRect(dest, &sub_clip);
+            sub_clip.x += offsetx;
+            sub_clip.y += offsety;
+            SDL_SetClipRect(subsurface, &sub_clip);
+            dest_rect.x += offsetx;
+            dest_rect.y += offsety;
+            dest = subsurface;
+        }
+        else
+        {
+	    PySurface_Prep(self);
+            subsurface = NULL;
+        }
 	PySurface_Prep(srcobject);
 	Py_BEGIN_ALLOW_THREADS
 
 		SDL_FreeSurface(src);
 
 	Py_END_ALLOW_THREADS
-	PySurface_Unprep(self);
+        if(subsurface)
+        {
+            SDL_SetClipRect(subsurface, &orig_clip);
+        }
+        else
+	    PySurface_Unprep(self);
 	PySurface_Unprep(srcobject);
 
 
     /*DOC*/    "The new subsurface will inherit the palette, colorkey, and surface alpha\n"
     /*DOC*/    "values from the base image.\n"
     /*DOC*/    "\n"
+    /*DOC*/    "You cannot subsurface an image that is already a subsurface.\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"
 	if(surf->flags & SDL_OPENGL)
 		return RAISE(PyExc_SDLError, "Cannot call on OPENGL Surfaces");
 
+        if((PySurfaceObject*)self)->subsurface)
+                return RAISE(PyExc_ValueError, "cannot subsurface a subsurface");
+        
 	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)