SDL_gfx  2.0.25
I:/Sources/sdlgfx/SDL_gfxBlitFunc.c
Go to the documentation of this file.
00001 /* 
00002 
00003 SDL_gfxBlitFunc.c: custom blitters
00004 
00005 Copyright (C) 2001-2012  Andreas Schiffler
00006 
00007 This software is provided 'as-is', without any express or implied
00008 warranty. In no event will the authors be held liable for any damages
00009 arising from the use of this software.
00010 
00011 Permission is granted to anyone to use this software for any purpose,
00012 including commercial applications, and to alter it and redistribute it
00013 freely, subject to the following restrictions:
00014 
00015 1. The origin of this software must not be misrepresented; you must not
00016 claim that you wrote the original software. If you use this software
00017 in a product, an acknowledgment in the product documentation would be
00018 appreciated but is not required.
00019 
00020 2. Altered source versions must be plainly marked as such, and must not be
00021 misrepresented as being the original software.
00022 
00023 3. This notice may not be removed or altered from any source
00024 distribution.
00025 
00026 Andreas Schiffler -- aschiffler at ferzkopp dot net
00027 
00028 */
00029 
00030 #include "SDL_gfxBlitFunc.h"
00031 
00039 const unsigned int GFX_ALPHA_ADJUST_ARRAY[256] = {
00040         0,  /* 0 */
00041         15,  /* 1 */
00042         22,  /* 2 */
00043         27,  /* 3 */
00044         31,  /* 4 */
00045         35,  /* 5 */
00046         39,  /* 6 */
00047         42,  /* 7 */
00048         45,  /* 8 */
00049         47,  /* 9 */
00050         50,  /* 10 */
00051         52,  /* 11 */
00052         55,  /* 12 */
00053         57,  /* 13 */
00054         59,  /* 14 */
00055         61,  /* 15 */
00056         63,  /* 16 */
00057         65,  /* 17 */
00058         67,  /* 18 */
00059         69,  /* 19 */
00060         71,  /* 20 */
00061         73,  /* 21 */
00062         74,  /* 22 */
00063         76,  /* 23 */
00064         78,  /* 24 */
00065         79,  /* 25 */
00066         81,  /* 26 */
00067         82,  /* 27 */
00068         84,  /* 28 */
00069         85,  /* 29 */
00070         87,  /* 30 */
00071         88,  /* 31 */
00072         90,  /* 32 */
00073         91,  /* 33 */
00074         93,  /* 34 */
00075         94,  /* 35 */
00076         95,  /* 36 */
00077         97,  /* 37 */
00078         98,  /* 38 */
00079         99,  /* 39 */
00080         100,  /* 40 */
00081         102,  /* 41 */
00082         103,  /* 42 */
00083         104,  /* 43 */
00084         105,  /* 44 */
00085         107,  /* 45 */
00086         108,  /* 46 */
00087         109,  /* 47 */
00088         110,  /* 48 */
00089         111,  /* 49 */
00090         112,  /* 50 */
00091         114,  /* 51 */
00092         115,  /* 52 */
00093         116,  /* 53 */
00094         117,  /* 54 */
00095         118,  /* 55 */
00096         119,  /* 56 */
00097         120,  /* 57 */
00098         121,  /* 58 */
00099         122,  /* 59 */
00100         123,  /* 60 */
00101         124,  /* 61 */
00102         125,  /* 62 */
00103         126,  /* 63 */
00104         127,  /* 64 */
00105         128,  /* 65 */
00106         129,  /* 66 */
00107         130,  /* 67 */
00108         131,  /* 68 */
00109         132,  /* 69 */
00110         133,  /* 70 */
00111         134,  /* 71 */
00112         135,  /* 72 */
00113         136,  /* 73 */
00114         137,  /* 74 */
00115         138,  /* 75 */
00116         139,  /* 76 */
00117         140,  /* 77 */
00118         141,  /* 78 */
00119         141,  /* 79 */
00120         142,  /* 80 */
00121         143,  /* 81 */
00122         144,  /* 82 */
00123         145,  /* 83 */
00124         146,  /* 84 */
00125         147,  /* 85 */
00126         148,  /* 86 */
00127         148,  /* 87 */
00128         149,  /* 88 */
00129         150,  /* 89 */
00130         151,  /* 90 */
00131         152,  /* 91 */
00132         153,  /* 92 */
00133         153,  /* 93 */
00134         154,  /* 94 */
00135         155,  /* 95 */
00136         156,  /* 96 */
00137         157,  /* 97 */
00138         158,  /* 98 */
00139         158,  /* 99 */
00140         159,  /* 100 */
00141         160,  /* 101 */
00142         161,  /* 102 */
00143         162,  /* 103 */
00144         162,  /* 104 */
00145         163,  /* 105 */
00146         164,  /* 106 */
00147         165,  /* 107 */
00148         165,  /* 108 */
00149         166,  /* 109 */
00150         167,  /* 110 */
00151         168,  /* 111 */
00152         168,  /* 112 */
00153         169,  /* 113 */
00154         170,  /* 114 */
00155         171,  /* 115 */
00156         171,  /* 116 */
00157         172,  /* 117 */
00158         173,  /* 118 */
00159         174,  /* 119 */
00160         174,  /* 120 */
00161         175,  /* 121 */
00162         176,  /* 122 */
00163         177,  /* 123 */
00164         177,  /* 124 */
00165         178,  /* 125 */
00166         179,  /* 126 */
00167         179,  /* 127 */
00168         180,  /* 128 */
00169         181,  /* 129 */
00170         182,  /* 130 */
00171         182,  /* 131 */
00172         183,  /* 132 */
00173         184,  /* 133 */
00174         184,  /* 134 */
00175         185,  /* 135 */
00176         186,  /* 136 */
00177         186,  /* 137 */
00178         187,  /* 138 */
00179         188,  /* 139 */
00180         188,  /* 140 */
00181         189,  /* 141 */
00182         190,  /* 142 */
00183         190,  /* 143 */
00184         191,  /* 144 */
00185         192,  /* 145 */
00186         192,  /* 146 */
00187         193,  /* 147 */
00188         194,  /* 148 */
00189         194,  /* 149 */
00190         195,  /* 150 */
00191         196,  /* 151 */
00192         196,  /* 152 */
00193         197,  /* 153 */
00194         198,  /* 154 */
00195         198,  /* 155 */
00196         199,  /* 156 */
00197         200,  /* 157 */
00198         200,  /* 158 */
00199         201,  /* 159 */
00200         201,  /* 160 */
00201         202,  /* 161 */
00202         203,  /* 162 */
00203         203,  /* 163 */
00204         204,  /* 164 */
00205         205,  /* 165 */
00206         205,  /* 166 */
00207         206,  /* 167 */
00208         206,  /* 168 */
00209         207,  /* 169 */
00210         208,  /* 170 */
00211         208,  /* 171 */
00212         209,  /* 172 */
00213         210,  /* 173 */
00214         210,  /* 174 */
00215         211,  /* 175 */
00216         211,  /* 176 */
00217         212,  /* 177 */
00218         213,  /* 178 */
00219         213,  /* 179 */
00220         214,  /* 180 */
00221         214,  /* 181 */
00222         215,  /* 182 */
00223         216,  /* 183 */
00224         216,  /* 184 */
00225         217,  /* 185 */
00226         217,  /* 186 */
00227         218,  /* 187 */
00228         218,  /* 188 */
00229         219,  /* 189 */
00230         220,  /* 190 */
00231         220,  /* 191 */
00232         221,  /* 192 */
00233         221,  /* 193 */
00234         222,  /* 194 */
00235         222,  /* 195 */
00236         223,  /* 196 */
00237         224,  /* 197 */
00238         224,  /* 198 */
00239         225,  /* 199 */
00240         225,  /* 200 */
00241         226,  /* 201 */
00242         226,  /* 202 */
00243         227,  /* 203 */
00244         228,  /* 204 */
00245         228,  /* 205 */
00246         229,  /* 206 */
00247         229,  /* 207 */
00248         230,  /* 208 */
00249         230,  /* 209 */
00250         231,  /* 210 */
00251         231,  /* 211 */
00252         232,  /* 212 */
00253         233,  /* 213 */
00254         233,  /* 214 */
00255         234,  /* 215 */
00256         234,  /* 216 */
00257         235,  /* 217 */
00258         235,  /* 218 */
00259         236,  /* 219 */
00260         236,  /* 220 */
00261         237,  /* 221 */
00262         237,  /* 222 */
00263         238,  /* 223 */
00264         238,  /* 224 */
00265         239,  /* 225 */
00266         240,  /* 226 */
00267         240,  /* 227 */
00268         241,  /* 228 */
00269         241,  /* 229 */
00270         242,  /* 230 */
00271         242,  /* 231 */
00272         243,  /* 232 */
00273         243,  /* 233 */
00274         244,  /* 234 */
00275         244,  /* 235 */
00276         245,  /* 236 */
00277         245,  /* 237 */
00278         246,  /* 238 */
00279         246,  /* 239 */
00280         247,  /* 240 */
00281         247,  /* 241 */
00282         248,  /* 242 */
00283         248,  /* 243 */
00284         249,  /* 244 */
00285         249,  /* 245 */
00286         250,  /* 246 */
00287         250,  /* 247 */
00288         251,  /* 248 */
00289         251,  /* 249 */
00290         252,  /* 250 */
00291         252,  /* 251 */
00292         253,  /* 252 */
00293         253,  /* 253 */
00294         254,  /* 254 */
00295         255   /* 255 */
00296 };
00297 
00306 void _SDL_gfxBlitBlitterRGBA(SDL_gfxBlitInfo * info)
00307 {
00308         int       width = info->d_width;
00309         int       height = info->d_height;
00310         Uint8    *src = info->s_pixels;
00311         int       srcskip = info->s_skip;
00312         Uint8    *dst = info->d_pixels;
00313         int       dstskip = info->d_skip;
00314         SDL_PixelFormat *srcfmt = info->src;
00315         SDL_PixelFormat *dstfmt = info->dst;
00316         Uint8       srcbpp = srcfmt->BytesPerPixel;
00317         Uint8       dstbpp = dstfmt->BytesPerPixel;
00318 
00319         while (height--) {
00320                 GFX_DUFFS_LOOP4( {
00321                         Uint32 pixel;
00322                         unsigned sR;
00323                         unsigned sG;
00324                         unsigned sB;
00325                         unsigned sA;
00326                         unsigned dR;
00327                         unsigned dG;
00328                         unsigned dB;
00329                         unsigned dA;
00330                         unsigned sAA;
00331                         GFX_DISASSEMBLE_RGBA(src, srcbpp, srcfmt, pixel, sR, sG, sB, sA);
00332                         GFX_DISASSEMBLE_RGBA(dst, dstbpp, dstfmt, pixel, dR, dG, dB, dA);
00333                         sAA=GFX_ALPHA_ADJUST_ARRAY[sA & 255];
00334                         GFX_ALPHA_BLEND(sR, sG, sB, sAA, dR, dG, dB);
00335                         dA |= sAA;
00336                         GFX_ASSEMBLE_RGBA(dst, dstbpp, dstfmt, dR, dG, dB, dA);
00337                         src += srcbpp; dst += dstbpp;
00338                 }, width);
00339                 src += srcskip;
00340                 dst += dstskip;
00341         }
00342 }
00343 
00356 int _SDL_gfxBlitRGBACall(SDL_Surface * src, SDL_Rect * srcrect, SDL_Surface * dst, SDL_Rect * dstrect)
00357 {
00358         /*
00359         * Set up source and destination buffer pointers, then blit 
00360         */
00361         if (srcrect->w && srcrect->h) {
00362                 SDL_gfxBlitInfo info;
00363 
00364                 /*
00365                 * Set up the blit information 
00366                 */
00367 #if (SDL_MINOR_VERSION == 3)
00368                 info.s_pixels = (Uint8 *) src->pixels               + (Uint16) srcrect->y * src->pitch + (Uint16) srcrect->x * src->format->BytesPerPixel;
00369 #else
00370                 info.s_pixels = (Uint8 *) src->pixels + src->offset + (Uint16) srcrect->y * src->pitch + (Uint16) srcrect->x * src->format->BytesPerPixel;
00371 #endif
00372                 info.s_width = srcrect->w;
00373                 info.s_height = srcrect->h;
00374                 info.s_skip = (int)(src->pitch - info.s_width * src->format->BytesPerPixel);
00375 #if (SDL_MINOR_VERSION == 3)
00376                 info.d_pixels = (Uint8 *) dst->pixels               + (Uint16) dstrect->y * dst->pitch + (Uint16) dstrect->x * dst->format->BytesPerPixel;
00377 #else
00378                 info.d_pixels = (Uint8 *) dst->pixels + dst->offset + (Uint16) dstrect->y * dst->pitch + (Uint16) dstrect->x * dst->format->BytesPerPixel;
00379 #endif
00380                 info.d_width = dstrect->w;
00381                 info.d_height = dstrect->h;
00382                 info.d_skip = (int)(dst->pitch - info.d_width * dst->format->BytesPerPixel);
00383                 info.aux_data = NULL;
00384                 info.src = src->format;
00385                 info.table = NULL;
00386                 info.dst = dst->format;
00387 
00388                 /*
00389                 * Run the actual software blitter 
00390                 */
00391                 _SDL_gfxBlitBlitterRGBA(&info);
00392                 return 1;
00393         }
00394 
00395         return (0);
00396 }
00397 
00411 int SDL_gfxBlitRGBA(SDL_Surface * src, SDL_Rect * srcrect, SDL_Surface * dst, SDL_Rect * dstrect)
00412 {
00413         SDL_Rect  sr, dr;
00414         int       srcx, srcy, w, h;
00415 
00416         /*
00417         * Make sure the surfaces aren't locked 
00418         */
00419         if (!src || !dst) {
00420                 SDL_SetError("SDL_UpperBlit: passed a NULL surface");
00421                 return (-1);
00422         }
00423         if ((src->locked) || (dst->locked)) {
00424                 SDL_SetError("Surfaces must not be locked during blit");
00425                 return (-1);
00426         }
00427 
00428         /*
00429         * If the destination rectangle is NULL, use the entire dest surface 
00430         */
00431         if (dstrect == NULL) {
00432                 dr.x = dr.y = 0;
00433                 dr.w = dst->w;
00434                 dr.h = dst->h;
00435         } else {
00436                 dr = *dstrect;
00437         }
00438 
00439         /*
00440         * Clip the source rectangle to the source surface 
00441         */
00442         if (srcrect) {
00443                 int       maxw, maxh;
00444 
00445                 srcx = srcrect->x;
00446                 w = srcrect->w;
00447                 if (srcx < 0) {
00448                         w += srcx;
00449                         dr.x -= srcx;
00450                         srcx = 0;
00451                 }
00452                 maxw = src->w - srcx;
00453                 if (maxw < w)
00454                         w = maxw;
00455 
00456                 srcy = srcrect->y;
00457                 h = srcrect->h;
00458                 if (srcy < 0) {
00459                         h += srcy;
00460                         dr.y -= srcy;
00461                         srcy = 0;
00462                 }
00463                 maxh = src->h - srcy;
00464                 if (maxh < h)
00465                         h = maxh;
00466 
00467         } else {
00468                 srcx = srcy = 0;
00469                 w = src->w;
00470                 h = src->h;
00471         }
00472 
00473         /*
00474         * Clip the destination rectangle against the clip rectangle 
00475         */
00476         {
00477                 SDL_Rect *clip = &dst->clip_rect;
00478                 int       dx, dy;
00479 
00480                 dx = clip->x - dr.x;
00481                 if (dx > 0) {
00482                         w -= dx;
00483                         dr.x += dx;
00484                         srcx += dx;
00485                 }
00486                 dx = dr.x + w - clip->x - clip->w;
00487                 if (dx > 0)
00488                         w -= dx;
00489 
00490                 dy = clip->y - dr.y;
00491                 if (dy > 0) {
00492                         h -= dy;
00493                         dr.y += dy;
00494                         srcy += dy;
00495                 }
00496                 dy = dr.y + h - clip->y - clip->h;
00497                 if (dy > 0)
00498                         h -= dy;
00499         }
00500 
00501         if (w > 0 && h > 0) {
00502                 sr.x = srcx;
00503                 sr.y = srcy;
00504                 sr.w = dr.w = w;
00505                 sr.h = dr.h = h;
00506                 return (_SDL_gfxBlitRGBACall(src, &sr, dst, &dr));
00507         }
00508 
00509         return 0;
00510 }
00511 
00524 int SDL_gfxSetAlpha(SDL_Surface *src, Uint8 a)
00525 {
00526 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
00527         const int alpha_offset = 0;
00528 #else
00529         const int alpha_offset = 3;
00530 #endif
00531         int i, j, row_skip;
00532         Uint8 *pixels;
00533 
00534         /* Check if we have a 32bit surface */
00535         if ( (src==NULL) || 
00536                 (src->format==NULL) || 
00537                 (src->format->BytesPerPixel!=4) ) {
00538                         SDL_SetError("SDL_gfxSetAlpha: Invalid input surface.");
00539                         return -1;
00540         }
00541 
00542         /*
00543         * Lock the surface 
00544         */
00545         if (SDL_MUSTLOCK(src)) {
00546                 if (SDL_LockSurface(src) < 0) {
00547                         return (-1);
00548                 }
00549         }
00550 
00551         /* Process */
00552         pixels = (Uint8 *)src->pixels;
00553         row_skip = (src->pitch - (4*src->w));
00554         pixels += alpha_offset;
00555         for ( i=0; i<src->h; i++ ) {
00556                 for ( j=0; j<src->w; j++  ) {
00557                         *pixels = a; 
00558                         pixels += 4;
00559                 }
00560                 pixels += row_skip;
00561         }
00562 
00563         /*
00564         * Unlock surface 
00565         */
00566         if (SDL_MUSTLOCK(src)) {
00567                 SDL_UnlockSurface(src);
00568         }
00569 
00570         return 1; 
00571 }
00572 
00587 int SDL_gfxMultiplyAlpha(SDL_Surface *src, Uint8 a)
00588 {
00589 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
00590         const int alpha_offset = 0;
00591 #else
00592         const int alpha_offset = 3;
00593 #endif
00594         int i, j, row_skip;
00595         Uint8 *pixels;
00596 
00597         /* Check if we have a 32bit surface */
00598         if ( (src==NULL) || 
00599                 (src->format==NULL) || 
00600                 (src->format->BytesPerPixel!=4) ) {
00601                         SDL_SetError("SDL_gfxMultiplyAlpha: Invalid input surface.");
00602                         return -1;
00603         }
00604 
00605         /* Check if multiplication is needed */
00606         if (a==255) {
00607                 return 0;
00608         }
00609 
00610         /*
00611         * Lock the surface 
00612         */
00613         if (SDL_MUSTLOCK(src)) {
00614                 if (SDL_LockSurface(src) < 0) {
00615                         return (-1);
00616                 }
00617         }
00618 
00619         /* Process */
00620         pixels = (Uint8 *)src->pixels;
00621         row_skip = (src->pitch - (4*src->w));
00622         pixels += alpha_offset;
00623         for ( i=0; i<src->h; i++ ) {
00624                 for ( j=0; j<src->w; j++  ) {
00625                         *pixels = (Uint8)(((int)(*pixels)*a)>>8);
00626                         pixels += 4;
00627                 }
00628                 pixels += row_skip;
00629         }
00630 
00631         /*
00632         * Unlock surface 
00633         */
00634         if (SDL_MUSTLOCK(src)) {
00635                 SDL_UnlockSurface(src);
00636         }
00637 
00638         return 1;
00639 }