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

📄 surface.c

📁 libminigui-1.3.0.tar.gz。 miniGUI的库函数源代码!
💻 C
📖 第 1 页 / 共 3 页
字号:
/***  $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;

⌨️ 快捷键说明

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