?? surface.c
字號(hào):
/*** $Id: surface.c,v 1.21 2003/11/22 03:53:11 weiym Exp $** ** Port to MiniGUI by Wei Yongming (2001/10/03).** Copyright (C) 2001 ~ 2002 Wei Yongming.** Copyright (C) 2003 Feynman Software.**** SDL - Simple DirectMedia Layer** Copyright (C) 1997, 1998, 1999, 2000, 2001 Sam Lantinga*//*** This program is free software; you can redistribute it and/or modify** it under the terms of the GNU General Public License as published by** the Free Software Foundation; either version 2 of the License, or** (at your option) any later version.**** This program 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 General Public License for more details.**** You should have received a copy of the GNU General Public License** along with this program; if not, write to the Free Software** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA*/#include <stdio.h>#include <stdlib.h>#include <string.h>#include "common.h"#include "newgal.h"#include "sysvideo.h"#include "blit.h"#include "RLEaccel_c.h"#include "pixels_c.h"#include "memops.h"#include "leaks.h"/* Public routines *//* * Create an empty RGB surface of the appropriate depth */GAL_Surface * GAL_CreateRGBSurface (Uint32 flags, int width, int height, int depth, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask){ GAL_VideoDevice *video = current_video; GAL_VideoDevice *this = current_video; GAL_Surface *screen; GAL_Surface *surface; /* Check to see if we desire the surface in video memory */ if ( video ) { screen = GAL_PublicSurface; } else { screen = NULL; } if ( screen && ((screen->flags&GAL_HWSURFACE) == GAL_HWSURFACE) ) { if ( (flags&(GAL_SRCCOLORKEY|GAL_SRCALPHA)) != 0 ) { flags |= GAL_HWSURFACE; } if ( (flags & GAL_SRCCOLORKEY) == GAL_SRCCOLORKEY ) { if ( ! current_video->info.blit_hw_CC ) { flags &= ~GAL_HWSURFACE; } } if ( (flags & GAL_SRCALPHA) == GAL_SRCALPHA ) { if ( ! current_video->info.blit_hw_A ) { flags &= ~GAL_HWSURFACE; } } } else { flags &= ~GAL_HWSURFACE; } /* Allocate the surface */ surface = (GAL_Surface *)malloc(sizeof(*surface)); if ( surface == NULL ) { GAL_OutOfMemory(); return(NULL); } surface->flags = GAL_SWSURFACE; if ( (flags & GAL_HWSURFACE) == GAL_HWSURFACE ) { depth = screen->format->BitsPerPixel; Rmask = screen->format->Rmask; Gmask = screen->format->Gmask; Bmask = screen->format->Bmask; Amask = screen->format->Amask; } surface->format = GAL_AllocFormat(depth, Rmask, Gmask, Bmask, Amask); if ( surface->format == NULL ) { free(surface); return(NULL); } if ( Amask ) { surface->flags |= GAL_SRCALPHA; } surface->w = width; surface->h = height; surface->pitch = GAL_CalculatePitch(surface); surface->pixels = NULL; surface->offset = 0; surface->hwdata = NULL; surface->locked = 0; surface->map = NULL; surface->format_version = 0; GAL_SetClipRect(surface, NULL); /* Get the pixels */ if ( ((flags&GAL_HWSURFACE) == GAL_SWSURFACE) || (video->AllocHWSurface(this, surface) < 0) ) { if ( surface->w && surface->h ) { surface->pixels = malloc(surface->h*surface->pitch); if ( surface->pixels == NULL ) { GAL_FreeSurface(surface); GAL_OutOfMemory(); return(NULL); } /* This is important for bitmaps */ memset(surface->pixels, 0, surface->h*surface->pitch); } } /* Allocate an empty mapping */ surface->map = GAL_AllocBlitMap(); if ( surface->map == NULL ) { GAL_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 */GAL_Surface * GAL_CreateRGBSurfaceFrom (void *pixels, int width, int height, int depth, int pitch, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask){ GAL_Surface *surface; surface = GAL_CreateRGBSurface(GAL_SWSURFACE, 0, 0, depth, Rmask, Gmask, Bmask, Amask); if ( surface != NULL ) { surface->flags |= GAL_PREALLOC; surface->pixels = pixels; surface->w = width; surface->h = height; surface->pitch = pitch; GAL_SetClipRect(surface, NULL); } return(surface);}/* * Set the color key in a blittable surface */int GAL_SetColorKey (GAL_Surface *surface, Uint32 flag, Uint32 key){ /* Sanity check the flag as it gets passed in */ if ( flag & GAL_SRCCOLORKEY ) { if ( flag & (GAL_RLEACCEL|GAL_RLEACCELOK) ) { flag = (GAL_SRCCOLORKEY | GAL_RLEACCELOK); } else { flag = GAL_SRCCOLORKEY; } } else { flag = 0; } /* Optimize away operations that don't change anything */ if ( (flag == (surface->flags & (GAL_SRCCOLORKEY|GAL_RLEACCELOK))) && (key == surface->format->colorkey) ) { return(0); } /* UnRLE surfaces before we change the colorkey */ if ( surface->flags & GAL_RLEACCEL ) { GAL_UnRLESurface(surface, 1); } if ( flag ) { GAL_VideoDevice *video = current_video; GAL_VideoDevice *this = current_video; surface->flags |= GAL_SRCCOLORKEY; surface->format->colorkey = key; if ( (surface->flags & GAL_HWACCEL) == GAL_HWACCEL ) { if ( (video->SetHWColorKey == NULL) || (video->SetHWColorKey(this, surface, key) < 0) ) { surface->flags &= ~GAL_HWACCEL; } } if ( flag & GAL_RLEACCELOK ) { surface->flags |= GAL_RLEACCELOK; } else { surface->flags &= ~GAL_RLEACCELOK; } } else { surface->flags &= ~(GAL_SRCCOLORKEY|GAL_RLEACCELOK); surface->format->colorkey = 0; } GAL_InvalidateMap(surface->map); return(0);}int GAL_SetAlpha (GAL_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 & GAL_SRCALPHA ) { if ( flag & (GAL_RLEACCEL|GAL_RLEACCELOK) ) { flag = (GAL_SRCALPHA | GAL_RLEACCELOK); } else { flag = GAL_SRCALPHA; } } else { flag = 0; } /* Optimize away operations that don't change anything */ if ( (flag == (surface->flags & (GAL_SRCALPHA|GAL_RLEACCELOK))) && (!flag || value == oldalpha) ) { return(0); } if(!(flag & GAL_RLEACCELOK) && (surface->flags & GAL_RLEACCEL)) GAL_UnRLESurface(surface, 1); if ( flag ) { GAL_VideoDevice *video = current_video; GAL_VideoDevice *this = current_video; surface->flags |= GAL_SRCALPHA; surface->format->alpha = value; if ( (surface->flags & GAL_HWACCEL) == GAL_HWACCEL ) { if ( (video->SetHWAlpha == NULL) || (video->SetHWAlpha(this, surface, value) < 0) ) { surface->flags &= ~GAL_HWACCEL; } } if ( flag & GAL_RLEACCELOK ) { surface->flags |= GAL_RLEACCELOK; } else { surface->flags &= ~GAL_RLEACCELOK; } } else { surface->flags &= ~GAL_SRCALPHA; surface->format->alpha = GAL_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 & GAL_HWACCEL) == GAL_HWACCEL || oldflags != surface->flags || (((oldalpha + 1) ^ (value + 1)) & 0x100)) GAL_InvalidateMap(surface->map); return(0);}/* * A function to calculate the intersection of two rectangles: * return true if the rectangles intersect, false otherwise */static __inline__GAL_bool GAL_IntersectRect(const GAL_Rect *A, const GAL_Rect *B, GAL_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 */GAL_bool GAL_SetClipRect(GAL_Surface *surface, GAL_Rect *rect){ GAL_Rect full_rect; /* Don't do anything if there's no surface to act on */ if ( ! surface ) { return GAL_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 GAL_IntersectRect(rect, &full_rect, &surface->clip_rect);}void GAL_GetClipRect(GAL_Surface *surface, GAL_Rect *rect){ if ( surface && rect ) { *rect = surface->clip_rect; }}/* * Set up a blit between two surfaces -- split into three parts: * The upper part, GAL_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 GAL_LowerBlit (GAL_Surface *src, GAL_Rect *srcrect, GAL_Surface *dst, GAL_Rect *dstrect){ GAL_blit do_blit; /* Check to make sure the blit mapping is valid */ if ( (src->map->dst != dst) || (src->map->dst->format_version != src->map->format_version) ) { if ( GAL_MapSurface(src, dst) < 0 ) { return(-1); } } /* Figure out which blitter to use */ if ( (src->flags & GAL_HWACCEL) == GAL_HWACCEL ) { do_blit = src->map->hw_blit; } else { do_blit = src->map->sw_blit; } return(do_blit(src, srcrect, dst, dstrect));}int GAL_UpperBlit (GAL_Surface *src, GAL_Rect *srcrect, GAL_Surface *dst, GAL_Rect *dstrect){ GAL_Rect fulldst; int srcx, srcy, w, h; /* Make sure the surfaces aren't locked */ if ( ! src || ! dst ) { GAL_SetError("GAL_UpperBlit: passed a NULL surface"); return(-1); } if ( src->locked || dst->locked ) { GAL_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; } /* clip the source rectangle to the source surface */ if(srcrect) { int maxw, maxh; srcx = srcrect->x; w = srcrect->w; if(srcx < 0) { w += srcx; dstrect->x -= srcx; srcx = 0; } maxw = src->w - srcx; if(maxw < w) w = maxw; srcy = srcrect->y; h = srcrect->h; if(srcy < 0) { h += srcy; dstrect->y -= srcy; srcy = 0; } maxh = src->h - srcy; if(maxh < h) h = maxh; } else { srcx = srcy = 0; w = src->w; h = src->h; } /* clip the destination rectangle against the clip rectangle */ { GAL_Rect *clip = &dst->clip_rect; int dx, dy; dx = clip->x - dstrect->x; if(dx > 0) { w -= dx; dstrect->x += dx; srcx += dx; } dx = dstrect->x + w - clip->x - clip->w; if(dx > 0) w -= dx; dy = clip->y - dstrect->y; if(dy > 0) { h -= dy; dstrect->y += dy; srcy += dy; } dy = dstrect->y + h - clip->y - clip->h; if(dy > 0) h -= dy; } if(w > 0 && h > 0) { GAL_Rect sr; sr.x = srcx;
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -