⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sdl_surface.c

📁 Simple DirectMedia Layer - Simple DirectMedia Layer 是一个跨平台的多媒体库设计用来提供快速图形framebuffer和音频驱动。应用MPEG为软件
💻 C
📖 第 1 页 / 共 2 页
字号:
/*    SDL - Simple DirectMedia Layer    Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002  Sam Lantinga    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    Sam Lantinga    slouken@libsdl.org*/#ifdef SAVE_RCSIDstatic char rcsid = "@(#) $Id: SDL_surface.c,v 1.12 2002/08/20 16:58:49 slouken Exp $";#endif#include <stdio.h>#include <stdlib.h>#include <string.h>#include "SDL_error.h"#include "SDL_video.h"#include "SDL_sysvideo.h"#include "SDL_cursor_c.h"#include "SDL_blit.h"#include "SDL_RLEaccel_c.h"#include "SDL_pixels_c.h"#include "SDL_memops.h"#include "SDL_leaks.h"/* Public routines *//* * Create an empty RGB surface of the appropriate depth */SDL_Surface * SDL_CreateRGBSurface (Uint32 flags,			int width, int height, int depth,			Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask){	SDL_VideoDevice *video = current_video;	SDL_VideoDevice *this  = current_video;	SDL_Surface *screen;	SDL_Surface *surface;	/* Check to see if we desire the surface in video memory */	if ( video ) {		screen = SDL_PublicSurface;	} else {		screen = NULL;	}	if ( screen && ((screen->flags&SDL_HWSURFACE) == SDL_HWSURFACE) ) {		if ( (flags&(SDL_SRCCOLORKEY|SDL_SRCALPHA)) != 0 ) {			flags |= SDL_HWSURFACE;		}		if ( (flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY ) {			if ( ! current_video->info.blit_hw_CC ) {				flags &= ~SDL_HWSURFACE;			}		}		if ( (flags & SDL_SRCALPHA) == SDL_SRCALPHA ) {			if ( ! current_video->info.blit_hw_A ) {				flags &= ~SDL_HWSURFACE;			}		}	} else {		flags &= ~SDL_HWSURFACE;	}	/* Allocate the surface */	surface = (SDL_Surface *)malloc(sizeof(*surface));	if ( surface == NULL ) {		SDL_OutOfMemory();		return(NULL);	}	surface->flags = SDL_SWSURFACE;	if ( (flags & SDL_HWSURFACE) == SDL_HWSURFACE ) {		depth = screen->format->BitsPerPixel;		Rmask = screen->format->Rmask;		Gmask = screen->format->Gmask;		Bmask = screen->format->Bmask;		Amask = screen->format->Amask;	}	surface->format = SDL_AllocFormat(depth, Rmask, Gmask, Bmask, Amask);	if ( surface->format == NULL ) {		free(surface);		return(NULL);	}	if ( Amask ) {		surface->flags |= SDL_SRCALPHA;	}	surface->w = width;	surface->h = height;	surface->pitch = SDL_CalculatePitch(surface);	surface->pixels = NULL;	surface->offset = 0;	surface->hwdata = NULL;	surface->locked = 0;	surface->map = NULL;	surface->format_version = 0;	surface->unused1 = 0;	SDL_SetClipRect(surface, NULL);	/* Get the pixels */	if ( ((flags&SDL_HWSURFACE) == SDL_SWSURFACE) || 				(video->AllocHWSurface(this, surface) < 0) ) {		if ( surface->w && surface->h ) {			surface->pixels = malloc(surface->h*surface->pitch);			if ( surface->pixels == NULL ) {				SDL_FreeSurface(surface);				SDL_OutOfMemory();				return(NULL);			}			/* This is important for bitmaps */			memset(surface->pixels, 0, surface->h*surface->pitch);		}	}	/* Allocate an empty mapping */	surface->map = SDL_AllocBlitMap();	if ( surface->map == NULL ) {		SDL_FreeSurface(surface);		return(NULL);	}	/* The surface is ready to go */	surface->refcount = 1;#ifdef CHECK_LEAKS	++surfaces_allocated;#endif	return(surface);}/* * Create an RGB surface from an existing memory buffer */SDL_Surface * SDL_CreateRGBSurfaceFrom (void *pixels,			int width, int height, int depth, int pitch,			Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask){	SDL_Surface *surface;	surface = SDL_CreateRGBSurface(SDL_SWSURFACE, 0, 0, depth,	                               Rmask, Gmask, Bmask, Amask);	if ( surface != NULL ) {		surface->flags |= SDL_PREALLOC;		surface->pixels = pixels;		surface->w = width;		surface->h = height;		surface->pitch = pitch;		SDL_SetClipRect(surface, NULL);	}	return(surface);}/* * Set the color key in a blittable surface */int SDL_SetColorKey (SDL_Surface *surface, Uint32 flag, Uint32 key){	/* Sanity check the flag as it gets passed in */	if ( flag & SDL_SRCCOLORKEY ) {		if ( flag & (SDL_RLEACCEL|SDL_RLEACCELOK) ) {			flag = (SDL_SRCCOLORKEY | SDL_RLEACCELOK);		} else {			flag = SDL_SRCCOLORKEY;		}	} else {		flag = 0;	}	/* Optimize away operations that don't change anything */	if ( (flag == (surface->flags & (SDL_SRCCOLORKEY|SDL_RLEACCELOK))) &&	     (key == surface->format->colorkey) ) {		return(0);	}	/* UnRLE surfaces before we change the colorkey */	if ( surface->flags & SDL_RLEACCEL ) {	        SDL_UnRLESurface(surface, 1);	}	if ( flag ) {		SDL_VideoDevice *video = current_video;		SDL_VideoDevice *this  = current_video;		surface->flags |= SDL_SRCCOLORKEY;		surface->format->colorkey = key;		if ( (surface->flags & SDL_HWACCEL) == SDL_HWACCEL ) {			if ( (video->SetHWColorKey == NULL) ||			     (video->SetHWColorKey(this, surface, key) < 0) ) {				surface->flags &= ~SDL_HWACCEL;			}		}		if ( flag & SDL_RLEACCELOK ) {			surface->flags |= SDL_RLEACCELOK;		} else {			surface->flags &= ~SDL_RLEACCELOK;		}	} else {		surface->flags &= ~(SDL_SRCCOLORKEY|SDL_RLEACCELOK);		surface->format->colorkey = 0;	}	SDL_InvalidateMap(surface->map);	return(0);}/* This function sets the alpha channel of a surface */int SDL_SetAlpha (SDL_Surface *surface, Uint32 flag, Uint8 value){	Uint32 oldflags = surface->flags;	Uint32 oldalpha = surface->format->alpha;	/* Sanity check the flag as it gets passed in */	if ( flag & SDL_SRCALPHA ) {		if ( flag & (SDL_RLEACCEL|SDL_RLEACCELOK) ) {			flag = (SDL_SRCALPHA | SDL_RLEACCELOK);		} else {			flag = SDL_SRCALPHA;		}	} else {		flag = 0;	}	/* Optimize away operations that don't change anything */	if ( (flag == (surface->flags & (SDL_SRCALPHA|SDL_RLEACCELOK))) &&	     (!flag || value == oldalpha) ) {		return(0);	}	if(!(flag & SDL_RLEACCELOK) && (surface->flags & SDL_RLEACCEL))		SDL_UnRLESurface(surface, 1);	if ( flag ) {		SDL_VideoDevice *video = current_video;		SDL_VideoDevice *this  = current_video;		surface->flags |= SDL_SRCALPHA;		surface->format->alpha = value;		if ( (surface->flags & SDL_HWACCEL) == SDL_HWACCEL ) {			if ( (video->SetHWAlpha == NULL) ||			     (video->SetHWAlpha(this, surface, value) < 0) ) {				surface->flags &= ~SDL_HWACCEL;			}		}		if ( flag & SDL_RLEACCELOK ) {		        surface->flags |= SDL_RLEACCELOK;		} else {		        surface->flags &= ~SDL_RLEACCELOK;		}	} else {		surface->flags &= ~SDL_SRCALPHA;		surface->format->alpha = SDL_ALPHA_OPAQUE;	}	/*	 * The representation for software surfaces is independent of	 * per-surface alpha, so no need to invalidate the blit mapping	 * if just the alpha value was changed. (If either is 255, we still	 * need to invalidate.)	 */	if((surface->flags & SDL_HWACCEL) == SDL_HWACCEL	   || oldflags != surface->flags	   || (((oldalpha + 1) ^ (value + 1)) & 0x100))		SDL_InvalidateMap(surface->map);	return(0);}int SDL_SetAlphaChannel(SDL_Surface *surface, Uint8 value){	int row, col;	int offset;	Uint8 *buf;	if ( (surface->format->Amask != 0xFF000000) &&	     (surface->format->Amask != 0x000000FF) ) {		SDL_SetError("Unsupported surface alpha mask format");		return -1;	}#if SDL_BYTEORDER == SDL_LIL_ENDIAN	if ( surface->format->Amask == 0xFF000000 ) {			offset = 3;	} else {			offset = 0;	}#else	if ( surface->format->Amask == 0xFF000000 ) {			offset = 0;	} else {			offset = 3;	}#endif /* Byte ordering */	/* Quickly set the alpha channel of an RGBA or ARGB surface */	if ( SDL_MUSTLOCK(surface) ) {		if ( SDL_LockSurface(surface) < 0 ) {			return -1;		}	}	row = surface->h;	while (row--) {		col = surface->w;		buf = (Uint8 *)surface->pixels + row * surface->pitch + offset;		while(col--) {			*buf = value;			buf += 4;		}	}	if ( SDL_MUSTLOCK(surface) ) {		SDL_UnlockSurface(surface);	}	return 0;}/* * A function to calculate the intersection of two rectangles: * return true if the rectangles intersect, false otherwise */static __inline__SDL_bool SDL_IntersectRect(const SDL_Rect *A, const SDL_Rect *B, SDL_Rect *intersection){	int Amin, Amax, Bmin, Bmax;	/* Horizontal intersection */	Amin = A->x;	Amax = Amin + A->w;	Bmin = B->x;	Bmax = Bmin + B->w;	if(Bmin > Amin)	        Amin = Bmin;	intersection->x = Amin;	if(Bmax < Amax)	        Amax = Bmax;	intersection->w = Amax - Amin > 0 ? Amax - Amin : 0;	/* Vertical intersection */	Amin = A->y;	Amax = Amin + A->h;	Bmin = B->y;	Bmax = Bmin + B->h;	if(Bmin > Amin)	        Amin = Bmin;	intersection->y = Amin;	if(Bmax < Amax)	        Amax = Bmax;	intersection->h = Amax - Amin > 0 ? Amax - Amin : 0;	return (intersection->w && intersection->h);}/* * Set the clipping rectangle for a blittable surface */SDL_bool SDL_SetClipRect(SDL_Surface *surface, const SDL_Rect *rect){	SDL_Rect full_rect;	/* Don't do anything if there's no surface to act on */	if ( ! surface ) {		return SDL_FALSE;	}	/* Set up the full surface rectangle */	full_rect.x = 0;	full_rect.y = 0;	full_rect.w = surface->w;	full_rect.h = surface->h;	/* Set the clipping rectangle */	if ( ! rect ) {		surface->clip_rect = full_rect;		return 1;	}	return SDL_IntersectRect(rect, &full_rect, &surface->clip_rect);}void SDL_GetClipRect(SDL_Surface *surface, SDL_Rect *rect){	if ( surface && rect ) {		*rect = surface->clip_rect;	}}/*  * Set up a blit between two surfaces -- split into three parts: * The upper part, SDL_UpperBlit(), performs clipping and rectangle  * verification.  The lower part is a pointer to a low level * accelerated blitting function. * * These parts are separated out and each used internally by this  * library in the optimimum places.  They are exported so that if * you know exactly what you are doing, you can optimize your code * by calling the one(s) you need. */int SDL_LowerBlit (SDL_Surface *src, SDL_Rect *srcrect,				SDL_Surface *dst, SDL_Rect *dstrect){	SDL_blit do_blit;	SDL_Rect hw_srcrect;	SDL_Rect hw_dstrect;	/* Check to make sure the blit mapping is valid */	if ( (src->map->dst != dst) ||             (src->map->dst->format_version != src->map->format_version) ) {		if ( SDL_MapSurface(src, dst) < 0 ) {			return(-1);		}	}	/* Figure out which blitter to use */	if ( (src->flags & SDL_HWACCEL) == SDL_HWACCEL ) {		if ( src == SDL_VideoSurface ) {			hw_srcrect = *dstrect;			hw_srcrect.x += current_video->offset_x;			hw_srcrect.y += current_video->offset_y;			srcrect = &hw_srcrect;		}		if ( dst == SDL_VideoSurface ) {			hw_dstrect = *dstrect;			hw_dstrect.x += current_video->offset_x;			hw_dstrect.y += current_video->offset_y;			dstrect = &hw_dstrect;		}		do_blit = src->map->hw_blit;	} else {		do_blit = src->map->sw_blit;	}	return(do_blit(src, srcrect, dst, dstrect));}int SDL_UpperBlit (SDL_Surface *src, SDL_Rect *srcrect,		   SDL_Surface *dst, SDL_Rect *dstrect){        SDL_Rect fulldst;	int srcx, srcy, w, h;	/* Make sure the surfaces aren't locked */	if ( ! src || ! dst ) {		SDL_SetError("SDL_UpperBlit: passed a NULL surface");		return(-1);	}	if ( src->locked || dst->locked ) {		SDL_SetError("Surfaces must not be locked during blit");		return(-1);	}	/* If the destination rectangle is NULL, use the entire dest surface */	if ( dstrect == NULL ) {	        fulldst.x = fulldst.y = 0;		dstrect = &fulldst;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -