📄 surface.c
字号:
return 0;}static int _PutBoxKey (GAL_Surface* dst, BYTE* dstrow, BYTE* srcrow, Uint32 w, Uint32 h, BITMAP* box){ BYTE* dstpixels = dstrow; BYTE* srcpixels = srcrow; Uint32 ckey = box->bmColorKey; GAL_PixelFormat *dstfmt = dst->format; int bpp = dstfmt->BytesPerPixel; unsigned alpha = dstfmt->Amask ? GAL_ALPHA_OPAQUE : 0; if (bpp == 1) { while (h--) { int i; dstpixels = dstrow; srcpixels = srcrow; for (i = 0; i < w; i++) { if (*srcpixels != ckey) *dstpixels = *srcpixels; dstpixels += bpp; srcpixels += bpp; } srcrow += box->bmPitch; dstrow += dst->pitch; } } else while ( h-- ) { dstpixels = dstrow; srcpixels = srcrow; DUFFS_LOOP( { Uint32 pixel; unsigned sR; unsigned sG; unsigned sB; RETRIEVE_RGB_PIXEL (srcpixels, bpp, pixel); if ( pixel != ckey ) { RGB_FROM_PIXEL (pixel, dstfmt, sR, sG, sB); ASSEMBLE_RGBA (dstpixels, bpp, dstfmt, sR, sG, sB, alpha); } dstpixels += bpp; srcpixels += bpp; }, w); srcrow += box->bmPitch; dstrow += dst->pitch; } return 0;}static int _PutBoxKeyAlphaChannel (GAL_Surface* dst, BYTE* dstrow, BYTE* srcrow, Uint32 w, Uint32 h, BITMAP* box){ BYTE* dstpixels = dstrow; BYTE* srcpixels = srcrow; Uint32 ckey = box->bmColorKey; GAL_PixelFormat *dstfmt = dst->format; int bpp = dstfmt->BytesPerPixel; unsigned alpha = box->bmAlpha; if (bpp == 1) return -1; while ( h-- ) { dstpixels = dstrow; srcpixels = srcrow; DUFFS_LOOP( { Uint32 pixel; unsigned sR; unsigned sG; unsigned sB; unsigned dR; unsigned dG; unsigned dB; RETRIEVE_RGB_PIXEL (srcpixels, bpp, pixel); if ( pixel != ckey ) { RGB_FROM_PIXEL (pixel, dstfmt, sR, sG, sB); DISEMBLE_RGB (dstpixels, bpp, dstfmt, pixel, dR, dG, dB); ALPHA_BLEND (sR, sG, sB, alpha, dR, dG, dB); ASSEMBLE_RGBA (dstpixels, bpp, dstfmt, dR, dG, dB, alpha); } dstpixels += bpp; srcpixels += bpp; }, w); srcrow += box->bmPitch; dstrow += dst->pitch; } return 0;}int GAL_PutBox (GAL_Surface *dst, const GAL_Rect *dstrect, BITMAP* box){ Uint32 box_x, box_y, off_x, off_y; int y, w, h; Uint8 *srcrow, *dstrow; Uint32 linelen; GAL_Rect my_dstrect; /* If 'dstrect' == NULL, then put to (0, 0) */ if (dstrect) { box_x = dstrect->x; box_y = dstrect->y; /* Perform clipping */ if (!GAL_IntersectRect (dstrect, &dst->clip_rect, &my_dstrect)) { return 0; } } else { box_x = 0; box_y = 0; my_dstrect = dst->clip_rect; } off_x = my_dstrect.x - box_x; off_y = my_dstrect.y - box_y; if (off_x >= box->bmWidth || off_y >= box->bmHeight || box->bmBytesPerPixel != dst->format->BytesPerPixel) { return 0; } dstrow = (Uint8 *)dst->pixels + my_dstrect.y * dst->pitch + my_dstrect.x * dst->format->BytesPerPixel; srcrow = (Uint8 *)box->bmBits + off_y * box->bmPitch + off_x * box->bmBytesPerPixel; w = MIN (my_dstrect.w, box->bmWidth); h = MIN (my_dstrect.h, box->bmHeight); linelen = w * box->bmBytesPerPixel; /* TODO: Check for hardware acceleration here */#if 0 /* Perform software blitting */ if ( GAL_LockSurface (dst) != 0 ) { return(-1); }#endif if (box->bmAlphaPixelFormat != NULL && box->bmAlphaPixelFormat != dst->format) { if ((box->bmType & BMP_TYPE_ALPHA) && (box->bmType & BMP_TYPE_COLORKEY)) { return _PutBoxKeyAlpha (dst, dstrow, srcrow, w, h, box); } else if (box->bmType & BMP_TYPE_ALPHA) { return _PutBoxAlpha (dst, dstrow, srcrow, w, h, box); } } else if ((box->bmType & BMP_TYPE_ALPHACHANNEL) && (box->bmType & BMP_TYPE_COLORKEY)) { return _PutBoxKeyAlphaChannel (dst, dstrow, srcrow, w, h, box); } else if (box->bmType & BMP_TYPE_COLORKEY) { return _PutBoxKey (dst, dstrow, srcrow, w, h, box); } else if (box->bmType & BMP_TYPE_ALPHACHANNEL) { return _PutBoxAlphaChannel (dst, dstrow, srcrow, w, h, box); } switch (dst->format->BytesPerPixel) { case 1: if (((DWORD)srcrow & 3) || ((DWORD)dstrow & 3) || (linelen & 3) || (box->bmPitch & 3) || (dst->pitch & 3)) goto slow_copy; else { int n = linelen >> 2; for (y = h; y; --y) { GAL_memcpy4 (dstrow, srcrow, n); srcrow += box->bmPitch; dstrow += dst->pitch; } } break; case 2: if ((((DWORD)dstrow & 3) != ((DWORD)srcrow & 3)) || (box->bmPitch & 3) || (dst->pitch & 3)) goto slow_copy; for (y = h; y; --y) { Uint16 *dstpixels = (Uint16 *)dstrow; Uint16 *srcpixels = (Uint16 *)srcrow; int n = w; if ((DWORD)dstpixels & 3) { *dstpixels = *srcpixels; dstpixels++; srcpixels++; n--; } if (n >> 1) GAL_memcpy4 (dstpixels, srcpixels, n >> 1); if (n & 1) dstpixels [n - 1] = srcpixels [n - 1]; srcrow += box->bmPitch; dstrow += dst->pitch; } break; case 3: goto slow_copy; case 4: for (y = h; y; --y) { GAL_memcpy4 (dstrow, srcrow, w); srcrow += box->bmPitch; dstrow += dst->pitch; } break; }#if 0 GAL_UnlockSurface(dst);#endif return 0;slow_copy: for (y = h; y; --y) { GAL_memcpy (dstrow, srcrow, linelen); srcrow += box->bmPitch; dstrow += dst->pitch; }#if 0 GAL_UnlockSurface (dst);#endif return 0;}#if 0/* * Lock a surface to directly access the pixels * -- Do not call this from any blit function, as GAL_DrawCursor() may recurse * Instead, use: * if ( (surface->flags & GAL_HWSURFACE) == GAL_HWSURFACE ) * video->LockHWSurface(video, surface); */int GAL_LockSurface (GAL_Surface *surface){ if ( ! surface->locked ) { /* Perform the lock */ if ( surface->flags & (GAL_HWSURFACE|GAL_ASYNCBLIT) ) { GAL_VideoDevice *video = current_video; GAL_VideoDevice *this = current_video; if ( video->LockHWSurface(this, surface) < 0 ) { return(-1); } } if ( surface->flags & GAL_RLEACCEL ) { GAL_UnRLESurface(surface, 1); surface->flags |= GAL_RLEACCEL; /* save accel'd state */ } /* This needs to be done here in case pixels changes value */ surface->pixels = (Uint8 *)surface->pixels + surface->offset; } /* Increment the surface lock count, for recursive locks */ ++surface->locked; /* Ready to go.. */ return(0);}/* * Unlock a previously locked surface * -- Do not call this from any blit function, as GAL_DrawCursor() may recurse * Instead, use: * if ( (surface->flags & GAL_HWSURFACE) == GAL_HWSURFACE ) * video->UnlockHWSurface(video, surface); */void GAL_UnlockSurface (GAL_Surface *surface){ return; /* Only perform an unlock if we are locked */ if ( ! surface->locked || (--surface->locked > 0) ) { return; } /* Perform the unlock */ surface->pixels = (Uint8 *)surface->pixels - surface->offset; /* Unlock hardware or accelerated surfaces */ if ( surface->flags & (GAL_HWSURFACE|GAL_ASYNCBLIT) ) { GAL_VideoDevice *video = current_video; GAL_VideoDevice *this = current_video; video->UnlockHWSurface(this, surface); } else { /* Update RLE encoded surface with new data */ if ( (surface->flags & GAL_RLEACCEL) == GAL_RLEACCEL ) { surface->flags &= ~GAL_RLEACCEL; /* stop lying */ GAL_RLESurface(surface); } }}#endif/* * Convert a surface into the specified pixel format. */GAL_Surface * GAL_ConvertSurface (GAL_Surface *surface, GAL_PixelFormat *format, Uint32 flags){ GAL_Surface *convert; Uint32 colorkey = 0; Uint8 alpha = 0; Uint32 surface_flags; GAL_Rect bounds; /* Check for empty destination palette! (results in empty image) */ if ( format->palette != NULL ) { int i; for ( i=0; i<format->palette->ncolors; ++i ) { if ( (format->palette->colors[i].r != 0) || (format->palette->colors[i].g != 0) || (format->palette->colors[i].b != 0) ) break; } if ( i == format->palette->ncolors ) { GAL_SetError("Empty destination palette"); return(NULL); } } /* Create a new surface with the desired format */ convert = GAL_CreateRGBSurface(flags, surface->w, surface->h, format->BitsPerPixel, format->Rmask, format->Gmask, format->Bmask, format->Amask); if ( convert == NULL ) { return(NULL); } /* Copy the palette if any */ if ( format->palette && convert->format->palette ) { memcpy(convert->format->palette->colors, format->palette->colors, format->palette->ncolors*sizeof(GAL_Color)); convert->format->palette->ncolors = format->palette->ncolors; } /* Save the original surface color key and alpha */ surface_flags = surface->flags; if ( (surface_flags & GAL_SRCCOLORKEY) == GAL_SRCCOLORKEY ) { /* Convert colourkeyed surfaces to RGBA if requested */ if((flags & GAL_SRCCOLORKEY) != GAL_SRCCOLORKEY && format->Amask) { surface_flags &= ~GAL_SRCCOLORKEY; } else { colorkey = surface->format->colorkey; GAL_SetColorKey(surface, 0, 0); } } if ( (surface_flags & GAL_SRCALPHA) == GAL_SRCALPHA ) { alpha = surface->format->alpha; GAL_SetAlpha(surface, 0, 0); } /* Copy over the image data */ bounds.x = 0; bounds.y = 0; bounds.w = surface->w; bounds.h = surface->h; GAL_LowerBlit(surface, &bounds, convert, &bounds); /* Clean up the original surface, and update converted surface */ if ( convert != NULL ) { GAL_SetClipRect(convert, &surface->clip_rect); } if ( (surface_flags & GAL_SRCCOLORKEY) == GAL_SRCCOLORKEY ) { Uint32 cflags = surface_flags&(GAL_SRCCOLORKEY|GAL_RLEACCELOK); if ( convert != NULL ) { Uint8 keyR, keyG, keyB; GAL_GetRGB(colorkey,surface->format,&keyR,&keyG,&keyB); GAL_SetColorKey(convert, cflags|(flags&GAL_RLEACCELOK), GAL_MapRGB(convert->format, keyR, keyG, keyB)); } GAL_SetColorKey(surface, cflags, colorkey); } if ( (surface_flags & GAL_SRCALPHA) == GAL_SRCALPHA ) { Uint32 aflags = surface_flags&(GAL_SRCALPHA|GAL_RLEACCELOK); if ( convert != NULL ) { GAL_SetAlpha(convert, aflags|(flags&GAL_RLEACCELOK), alpha); } GAL_SetAlpha(surface, aflags, alpha); } /* We're ready to go! */ return(convert);}/* * Free a surface created by the above function. */void GAL_FreeSurface (GAL_Surface *surface){ /* Free anything that's not NULL, and not the screen surface */ if ((surface == NULL) || (current_video &&#if 0 ((surface == GAL_ShadowSurface)||(surface == GAL_VideoSurface)))) {#else (surface == GAL_VideoSurface))) {#endif return; } if ( --surface->refcount > 0 ) { return; } if ( (surface->flags & GAL_RLEACCEL) == GAL_RLEACCEL ) { GAL_UnRLESurface(surface, 0); } if ( surface->format ) { GAL_FreeFormat(surface->format); surface->format = NULL; } if ( surface->map != NULL ) { GAL_FreeBlitMap(surface->map); surface->map = NULL; } if ( (surface->flags & GAL_HWSURFACE) == GAL_HWSURFACE ) { GAL_VideoDevice *video = current_video; GAL_VideoDevice *this = current_video; video->FreeHWSurface(this, surface); } if ( surface->pixels && ((surface->flags & GAL_PREALLOC) != GAL_PREALLOC) ) { free(surface->pixels); } free(surface);#ifdef CHECK_LEAKS --surfaces_allocated;#endif}#ifdef _LITE_VERSIONvoid GAL_RequestHWSurface (const REQ_HWSURFACE* request, REP_HWSURFACE* reply){ if (current_video->RequestHWSurface) { current_video->RequestHWSurface (current_video, request, reply); } else if (request->offset == 0) { reply->offset = 0; }}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -