static int SW_SetTextureColorMod(SDL_Renderer * renderer, SDL_Texture * texture) { SDL_Surface *surface = (SDL_Surface *) texture->driverdata; return SDL_SetSurfaceColorMod(surface, texture->r, texture->g, texture->b); }
static int SW_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) { int bpp; Uint32 Rmask, Gmask, Bmask, Amask; if (!SDL_PixelFormatEnumToMasks (texture->format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) { return SDL_SetError("Unknown texture format"); } texture->driverdata = SDL_CreateRGBSurface(0, texture->w, texture->h, bpp, Rmask, Gmask, Bmask, Amask); SDL_SetSurfaceColorMod(texture->driverdata, texture->r, texture->g, texture->b); SDL_SetSurfaceAlphaMod(texture->driverdata, texture->a); SDL_SetSurfaceBlendMode(texture->driverdata, texture->blendMode); /* Only RLE encode textures without an alpha channel since the RLE coder * discards the color values of pixels with an alpha value of zero. */ if (texture->access == SDL_TEXTUREACCESS_STATIC && !Amask) { SDL_SetSurfaceRLE(texture->driverdata, 1); } if (!texture->driverdata) { return -1; } return 0; }
static int SW_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture) { int bpp; Uint32 Rmask, Gmask, Bmask, Amask; if (!SDL_PixelFormatEnumToMasks (texture->format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) { return SDL_SetError("Unknown texture format"); } texture->driverdata = SDL_CreateRGBSurface(0, texture->w, texture->h, bpp, Rmask, Gmask, Bmask, Amask); SDL_SetSurfaceColorMod(texture->driverdata, texture->r, texture->g, texture->b); SDL_SetSurfaceAlphaMod(texture->driverdata, texture->a); SDL_SetSurfaceBlendMode(texture->driverdata, texture->blendMode); if (texture->access == SDL_TEXTUREACCESS_STATIC) { SDL_SetSurfaceRLE(texture->driverdata, 1); } if (!texture->driverdata) { return -1; } return 0; }
SDL_Surface* Blitter::create_surface_from_format(SDL_Surface* surface, int w, int h) { SDL_Surface* new_surface = SDL_CreateRGBSurface(0, w, h, surface->format->BitsPerPixel, surface->format->Rmask, surface->format->Gmask, surface->format->Bmask, surface->format->Amask); Uint8 alpha; if (SDL_GetSurfaceAlphaMod(surface, &alpha) == 0) SDL_SetSurfaceAlphaMod(new_surface, alpha); SDL_BlendMode blend_mode; if (SDL_GetSurfaceBlendMode(surface, &blend_mode) == 0) SDL_SetSurfaceBlendMode(new_surface, blend_mode); Uint8 r, g, b; if (SDL_GetSurfaceColorMod(surface, &r, &g, &b) == 0) SDL_SetSurfaceColorMod(new_surface, r, g, b); if (surface->format->palette) SDL_SetSurfacePalette(new_surface, surface->format->palette); Uint32 colorkey; if (SDL_GetColorKey(surface, &colorkey) == 0) SDL_SetColorKey(new_surface, SDL_TRUE, colorkey); return new_surface; }
static void PrepTextureForCopy(const SDL_RenderCommand *cmd) { const Uint8 r = cmd->data.draw.r; const Uint8 g = cmd->data.draw.g; const Uint8 b = cmd->data.draw.b; const Uint8 a = cmd->data.draw.a; const SDL_BlendMode blend = cmd->data.draw.blend; SDL_Texture *texture = cmd->data.draw.texture; SDL_Surface *surface = (SDL_Surface *) texture->driverdata; if (texture->modMode & SDL_TEXTUREMODULATE_COLOR) { SDL_SetSurfaceRLE(surface, 0); SDL_SetSurfaceColorMod(surface, r, g, b); } if ((texture->modMode & SDL_TEXTUREMODULATE_ALPHA) && surface->format->Amask) { SDL_SetSurfaceRLE(surface, 0); SDL_SetSurfaceAlphaMod(surface, a); } if ((blend == SDL_BLENDMODE_ADD) || (blend == SDL_BLENDMODE_MOD)) { SDL_SetSurfaceRLE(surface, 0); } SDL_SetSurfaceBlendMode(surface, blend); }
void Surface::setColorMod(Uint8 r, Uint8 g, Uint8 b) { if(SDL_SetSurfaceColorMod(sdlSurface, r, g, b) == 0) { Logger::Error(SDL_GetError()); } }
bool Image::set_color_modulation ( const Color4i& color ) { if ( SDL_SetSurfaceColorMod ( this->image(), color.r, color.g, color.b ) != 0 ) { NOM_LOG_ERR ( NOM, SDL_GetError() ); return false; } return true; }
static int SW_SetTextureColorMod(SDL_Renderer * renderer, SDL_Texture * texture) { SDL_Surface *surface = (SDL_Surface *) texture->driverdata; /* If the color mod is ever enabled (non-white), permanently disable RLE (which doesn't support * color mod) to avoid potentially frequent RLE encoding/decoding. */ if ((texture->r & texture->g & texture->b) != 255) { SDL_SetSurfaceRLE(surface, 0); } return SDL_SetSurfaceColorMod(surface, texture->r, texture->g, texture->b); }
int inline Surface::setColorMod(State & state, SDL_Surface * surface){ Stack * stack = state.stack; if (stack->is<LUA_TTABLE>(1)){ stack->getField("r", 1); stack->getField("g", 1); stack->getField("b", 1); SDL_SetSurfaceColorMod( surface, (Uint8)state.stack->to<int>(-3), (Uint8)state.stack->to<int>(-2), (Uint8)state.stack->to<int>(-1)); stack->pop(3); } return 0; }
static mrb_value mrb_sdl2_video_surface_set_color_mod(mrb_state *mrb, mrb_value self) { mrb_value color; SDL_Surface *s = mrb_sdl2_video_surface_get_ptr(mrb, self); mrb_get_args(mrb, "o", &color); if (!mrb_obj_is_kind_of(mrb, color, mrb_class_get_under(mrb, mod_SDL2, "RGB"))) { mrb_raise(mrb, E_TYPE_ERROR, "given 1st argument is unexpected type (expected RGB)."); } uint8_t const r = mrb_fixnum(mrb_iv_get(mrb, color, mrb_intern(mrb, "@r", 2))); uint8_t const g = mrb_fixnum(mrb_iv_get(mrb, color, mrb_intern(mrb, "@g", 2))); uint8_t const b = mrb_fixnum(mrb_iv_get(mrb, color, mrb_intern(mrb, "@b", 2))); if (0 != SDL_SetSurfaceColorMod(s, r, g, b)) { mruby_sdl2_raise_error(mrb); } return self; }
static void PrepTextureForCopy(const SDL_RenderCommand *cmd) { const Uint8 r = cmd->data.draw.r; const Uint8 g = cmd->data.draw.g; const Uint8 b = cmd->data.draw.b; const Uint8 a = cmd->data.draw.a; const SDL_BlendMode blend = cmd->data.draw.blend; SDL_Texture *texture = cmd->data.draw.texture; SDL_Surface *surface = (SDL_Surface *) texture->driverdata; const SDL_bool colormod = ((r & g & b) != 0xFF); const SDL_bool alphamod = (a != 0xFF); const SDL_bool blending = ((blend == SDL_BLENDMODE_ADD) || (blend == SDL_BLENDMODE_MOD)); if (colormod || alphamod || blending) { SDL_SetSurfaceRLE(surface, 0); } /* !!! FIXME: we can probably avoid some of these calls. */ SDL_SetSurfaceColorMod(surface, r, g, b); SDL_SetSurfaceAlphaMod(surface, a); SDL_SetSurfaceBlendMode(surface, blend); }
static int SW_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture, const SDL_Rect * srcrect, const SDL_FRect * dstrect, const double angle, const SDL_FPoint * center, const SDL_RendererFlip flip) { SDL_Surface *surface = SW_ActivateRenderer(renderer); SDL_Surface *src = (SDL_Surface *) texture->driverdata; SDL_Rect final_rect, tmp_rect; SDL_Surface *surface_rotated, *surface_scaled; int retval, dstwidth, dstheight, abscenterx, abscentery; double cangle, sangle, px, py, p1x, p1y, p2x, p2y, p3x, p3y, p4x, p4y; if (!surface) { return -1; } if (renderer->viewport.x || renderer->viewport.y) { final_rect.x = (int)(renderer->viewport.x + dstrect->x); final_rect.y = (int)(renderer->viewport.y + dstrect->y); } else { final_rect.x = (int)dstrect->x; final_rect.y = (int)dstrect->y; } final_rect.w = (int)dstrect->w; final_rect.h = (int)dstrect->h; /* SDLgfx_rotateSurface doesn't accept a source rectangle, so crop and scale if we need to */ tmp_rect = final_rect; tmp_rect.x = 0; tmp_rect.y = 0; if (srcrect->w == final_rect.w && srcrect->h == final_rect.h && srcrect->x == 0 && srcrect->y == 0) { surface_scaled = src; /* but if we don't need to, just use the original */ retval = 0; } else { SDL_Surface *blit_src = src; Uint32 colorkey; SDL_BlendMode blendMode; Uint8 alphaMod, r, g, b; SDL_bool cloneSource = SDL_FALSE; surface_scaled = SDL_CreateRGBSurface(SDL_SWSURFACE, final_rect.w, final_rect.h, src->format->BitsPerPixel, src->format->Rmask, src->format->Gmask, src->format->Bmask, src->format->Amask ); if (!surface_scaled) { return -1; } /* copy the color key, alpha mod, blend mode, and color mod so the scaled surface behaves like the source */ if (SDL_GetColorKey(src, &colorkey) == 0) { SDL_SetColorKey(surface_scaled, SDL_TRUE, colorkey); cloneSource = SDL_TRUE; } SDL_GetSurfaceAlphaMod(src, &alphaMod); /* these will be copied to surface_scaled below if necessary */ SDL_GetSurfaceBlendMode(src, &blendMode); SDL_GetSurfaceColorMod(src, &r, &g, &b); /* now we need to blit the src into surface_scaled. since we want to copy the colors from the source to * surface_scaled rather than blend them, etc. we'll need to disable the blend mode, alpha mod, etc. * but we don't want to modify src (in case it's being used on other threads), so we'll need to clone it * before changing the blend options */ cloneSource |= blendMode != SDL_BLENDMODE_NONE || (alphaMod & r & g & b) != 255; if (cloneSource) { blit_src = SDL_ConvertSurface(src, src->format, src->flags); /* clone src */ if (!blit_src) { SDL_FreeSurface(surface_scaled); return -1; } SDL_SetSurfaceAlphaMod(blit_src, 255); /* disable all blending options in blit_src */ SDL_SetSurfaceBlendMode(blit_src, SDL_BLENDMODE_NONE); SDL_SetColorKey(blit_src, 0, 0); SDL_SetSurfaceColorMod(blit_src, 255, 255, 255); SDL_SetSurfaceRLE(blit_src, 0); /* don't RLE encode a surface we'll only use once */ SDL_SetSurfaceAlphaMod(surface_scaled, alphaMod); /* copy blending options to surface_scaled */ SDL_SetSurfaceBlendMode(surface_scaled, blendMode); SDL_SetSurfaceColorMod(surface_scaled, r, g, b); } retval = SDL_BlitScaled(blit_src, srcrect, surface_scaled, &tmp_rect); if (blit_src != src) { SDL_FreeSurface(blit_src); } } if (!retval) { SDLgfx_rotozoomSurfaceSizeTrig(tmp_rect.w, tmp_rect.h, angle, &dstwidth, &dstheight, &cangle, &sangle); surface_rotated = SDLgfx_rotateSurface(surface_scaled, angle, dstwidth/2, dstheight/2, GetScaleQuality(), flip & SDL_FLIP_HORIZONTAL, flip & SDL_FLIP_VERTICAL, dstwidth, dstheight, cangle, sangle); if(surface_rotated) { /* Find out where the new origin is by rotating the four final_rect points around the center and then taking the extremes */ abscenterx = final_rect.x + (int)center->x; abscentery = final_rect.y + (int)center->y; /* Compensate the angle inversion to match the behaviour of the other backends */ sangle = -sangle; /* Top Left */ px = final_rect.x - abscenterx; py = final_rect.y - abscentery; p1x = px * cangle - py * sangle + abscenterx; p1y = px * sangle + py * cangle + abscentery; /* Top Right */ px = final_rect.x + final_rect.w - abscenterx; py = final_rect.y - abscentery; p2x = px * cangle - py * sangle + abscenterx; p2y = px * sangle + py * cangle + abscentery; /* Bottom Left */ px = final_rect.x - abscenterx; py = final_rect.y + final_rect.h - abscentery; p3x = px * cangle - py * sangle + abscenterx; p3y = px * sangle + py * cangle + abscentery; /* Bottom Right */ px = final_rect.x + final_rect.w - abscenterx; py = final_rect.y + final_rect.h - abscentery; p4x = px * cangle - py * sangle + abscenterx; p4y = px * sangle + py * cangle + abscentery; tmp_rect.x = (int)MIN(MIN(p1x, p2x), MIN(p3x, p4x)); tmp_rect.y = (int)MIN(MIN(p1y, p2y), MIN(p3y, p4y)); tmp_rect.w = dstwidth; tmp_rect.h = dstheight; retval = SDL_BlitSurface(surface_rotated, NULL, surface, &tmp_rect); SDL_FreeSurface(surface_rotated); } } if (surface_scaled != src) { SDL_FreeSurface(surface_scaled); } return retval; }
/** * Helper that blits in a specific blend mode, -1 for basic blitting, -2 for color mod, -3 for alpha mod, -4 for mixed blend modes. */ void _testBlitBlendMode(int mode) { int ret; int i, j, ni, nj; SDL_Surface *face; SDL_Rect rect; int nmode; SDL_BlendMode bmode; int checkFailCount1; int checkFailCount2; int checkFailCount3; int checkFailCount4; /* Check test surface */ SDLTest_AssertCheck(testSurface != NULL, "Verify testSurface is not NULL"); if (testSurface == NULL) return; /* Create sample surface */ face = SDLTest_ImageFace(); SDLTest_AssertCheck(face != NULL, "Verify face surface is not NULL"); if (face == NULL) return; /* Reset alpha modulation */ ret = SDL_SetSurfaceAlphaMod(face, 255); SDLTest_AssertPass("Call to SDL_SetSurfaceAlphaMod()"); SDLTest_AssertCheck(ret == 0, "Verify result from SDL_SetSurfaceAlphaMod(), expected: 0, got: %i", ret); /* Reset color modulation */ ret = SDL_SetSurfaceColorMod(face, 255, 255, 255); SDLTest_AssertPass("Call to SDL_SetSurfaceColorMod()"); SDLTest_AssertCheck(ret == 0, "Verify result from SDL_SetSurfaceColorMod(), expected: 0, got: %i", ret); /* Reset color key */ ret = SDL_SetColorKey(face, SDL_FALSE, 0); SDLTest_AssertPass("Call to SDL_SetColorKey()"); SDLTest_AssertCheck(ret == 0, "Verify result from SDL_SetColorKey(), expected: 0, got: %i", ret); /* Clear the test surface */ _clearTestSurface(); /* Target rect size */ rect.w = face->w; rect.h = face->h; /* Steps to take */ ni = testSurface->w - face->w; nj = testSurface->h - face->h; /* Optionally set blend mode. */ if (mode >= 0) { ret = SDL_SetSurfaceBlendMode( face, (SDL_BlendMode)mode ); SDLTest_AssertPass("Call to SDL_SetSurfaceBlendMode()"); SDLTest_AssertCheck(ret == 0, "Verify result from SDL_SetSurfaceBlendMode(..., %i), expected: 0, got: %i", mode, ret); } /* Test blend mode. */ checkFailCount1 = 0; checkFailCount2 = 0; checkFailCount3 = 0; checkFailCount4 = 0; for (j=0; j <= nj; j+=4) { for (i=0; i <= ni; i+=4) { if (mode == -2) { /* Set color mod. */ ret = SDL_SetSurfaceColorMod( face, (255/nj)*j, (255/ni)*i, (255/nj)*j ); if (ret != 0) checkFailCount2++; } else if (mode == -3) { /* Set alpha mod. */ ret = SDL_SetSurfaceAlphaMod( face, (255/ni)*i ); if (ret != 0) checkFailCount3++; } else if (mode == -4) { /* Crazy blending mode magic. */ nmode = (i/4*j/4) % 4; if (nmode==0) { bmode = SDL_BLENDMODE_NONE; } else if (nmode==1) { bmode = SDL_BLENDMODE_BLEND; } else if (nmode==2) { bmode = SDL_BLENDMODE_ADD; } else if (nmode==3) { bmode = SDL_BLENDMODE_MOD; } ret = SDL_SetSurfaceBlendMode( face, bmode ); if (ret != 0) checkFailCount4++; } /* Blitting. */ rect.x = i; rect.y = j; ret = SDL_BlitSurface( face, NULL, testSurface, &rect ); if (ret != 0) checkFailCount1++; } } SDLTest_AssertCheck(checkFailCount1 == 0, "Validate results from calls to SDL_BlitSurface, expected: 0, got: %i", checkFailCount1); SDLTest_AssertCheck(checkFailCount2 == 0, "Validate results from calls to SDL_SetSurfaceColorMod, expected: 0, got: %i", checkFailCount2); SDLTest_AssertCheck(checkFailCount3 == 0, "Validate results from calls to SDL_SetSurfaceAlphaMod, expected: 0, got: %i", checkFailCount3); SDLTest_AssertCheck(checkFailCount4 == 0, "Validate results from calls to SDL_SetSurfaceBlendMode, expected: 0, got: %i", checkFailCount4); /* Clean up */ SDL_FreeSurface(face); face = NULL; }
static int SW_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture, const SDL_Rect * srcrect, const SDL_FRect * dstrect, const double angle, const SDL_FPoint * center, const SDL_RendererFlip flip) { SDL_Surface *surface = SW_ActivateRenderer(renderer); SDL_Surface *src = (SDL_Surface *) texture->driverdata; SDL_Rect final_rect, tmp_rect; SDL_Surface *src_clone, *src_rotated, *src_scaled; SDL_Surface *mask = NULL, *mask_rotated = NULL; int retval = 0, dstwidth, dstheight, abscenterx, abscentery; double cangle, sangle, px, py, p1x, p1y, p2x, p2y, p3x, p3y, p4x, p4y; SDL_BlendMode blendmode; Uint8 alphaMod, rMod, gMod, bMod; int applyModulation = SDL_FALSE; int blitRequired = SDL_FALSE; int isOpaque = SDL_FALSE; if (!surface) { return -1; } if (renderer->viewport.x || renderer->viewport.y) { final_rect.x = (int)(renderer->viewport.x + dstrect->x); final_rect.y = (int)(renderer->viewport.y + dstrect->y); } else { final_rect.x = (int)dstrect->x; final_rect.y = (int)dstrect->y; } final_rect.w = (int)dstrect->w; final_rect.h = (int)dstrect->h; tmp_rect = final_rect; tmp_rect.x = 0; tmp_rect.y = 0; /* It is possible to encounter an RLE encoded surface here and locking it is * necessary because this code is going to access the pixel buffer directly. */ if (SDL_MUSTLOCK(src)) { SDL_LockSurface(src); } /* Clone the source surface but use its pixel buffer directly. * The original source surface must be treated as read-only. */ src_clone = SDL_CreateRGBSurfaceFrom(src->pixels, src->w, src->h, src->format->BitsPerPixel, src->pitch, src->format->Rmask, src->format->Gmask, src->format->Bmask, src->format->Amask); if (src_clone == NULL) { if (SDL_MUSTLOCK(src)) { SDL_UnlockSurface(src); } return -1; } SDL_GetSurfaceBlendMode(src, &blendmode); SDL_GetSurfaceAlphaMod(src, &alphaMod); SDL_GetSurfaceColorMod(src, &rMod, &gMod, &bMod); /* SDLgfx_rotateSurface only accepts 32-bit surfaces with a 8888 layout. Everything else has to be converted. */ if (src->format->BitsPerPixel != 32 || SDL_PIXELLAYOUT(src->format->format) != SDL_PACKEDLAYOUT_8888 || !src->format->Amask) { blitRequired = SDL_TRUE; } /* If scaling and cropping is necessary, it has to be taken care of before the rotation. */ if (!(srcrect->w == final_rect.w && srcrect->h == final_rect.h && srcrect->x == 0 && srcrect->y == 0)) { blitRequired = SDL_TRUE; } /* The color and alpha modulation has to be applied before the rotation when using the NONE and MOD blend modes. */ if ((blendmode == SDL_BLENDMODE_NONE || blendmode == SDL_BLENDMODE_MOD) && (alphaMod & rMod & gMod & bMod) != 255) { applyModulation = SDL_TRUE; SDL_SetSurfaceAlphaMod(src_clone, alphaMod); SDL_SetSurfaceColorMod(src_clone, rMod, gMod, bMod); } /* Opaque surfaces are much easier to handle with the NONE blend mode. */ if (blendmode == SDL_BLENDMODE_NONE && !src->format->Amask && alphaMod == 255) { isOpaque = SDL_TRUE; } /* The NONE blend mode requires a mask for non-opaque surfaces. This mask will be used * to clear the pixels in the destination surface. The other steps are explained below. */ if (blendmode == SDL_BLENDMODE_NONE && !isOpaque) { mask = SDL_CreateRGBSurface(0, final_rect.w, final_rect.h, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000); if (mask == NULL) { retval = -1; } else { SDL_SetSurfaceBlendMode(mask, SDL_BLENDMODE_MOD); } } /* Create a new surface should there be a format mismatch or if scaling, cropping, * or modulation is required. It's possible to use the source surface directly otherwise. */ if (!retval && (blitRequired || applyModulation)) { SDL_Rect scale_rect = tmp_rect; src_scaled = SDL_CreateRGBSurface(0, final_rect.w, final_rect.h, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000); if (src_scaled == NULL) { retval = -1; } else { SDL_SetSurfaceBlendMode(src_clone, SDL_BLENDMODE_NONE); retval = SDL_BlitScaled(src_clone, srcrect, src_scaled, &scale_rect); SDL_FreeSurface(src_clone); src_clone = src_scaled; src_scaled = NULL; } } /* SDLgfx_rotateSurface is going to make decisions depending on the blend mode. */ SDL_SetSurfaceBlendMode(src_clone, blendmode); if (!retval) { SDLgfx_rotozoomSurfaceSizeTrig(tmp_rect.w, tmp_rect.h, angle, &dstwidth, &dstheight, &cangle, &sangle); src_rotated = SDLgfx_rotateSurface(src_clone, angle, dstwidth/2, dstheight/2, GetScaleQuality(), flip & SDL_FLIP_HORIZONTAL, flip & SDL_FLIP_VERTICAL, dstwidth, dstheight, cangle, sangle); if (src_rotated == NULL) { retval = -1; } if (!retval && mask != NULL) { /* The mask needed for the NONE blend mode gets rotated with the same parameters. */ mask_rotated = SDLgfx_rotateSurface(mask, angle, dstwidth/2, dstheight/2, SDL_FALSE, 0, 0, dstwidth, dstheight, cangle, sangle); if (mask_rotated == NULL) { retval = -1; } } if (!retval) { /* Find out where the new origin is by rotating the four final_rect points around the center and then taking the extremes */ abscenterx = final_rect.x + (int)center->x; abscentery = final_rect.y + (int)center->y; /* Compensate the angle inversion to match the behaviour of the other backends */ sangle = -sangle; /* Top Left */ px = final_rect.x - abscenterx; py = final_rect.y - abscentery; p1x = px * cangle - py * sangle + abscenterx; p1y = px * sangle + py * cangle + abscentery; /* Top Right */ px = final_rect.x + final_rect.w - abscenterx; py = final_rect.y - abscentery; p2x = px * cangle - py * sangle + abscenterx; p2y = px * sangle + py * cangle + abscentery; /* Bottom Left */ px = final_rect.x - abscenterx; py = final_rect.y + final_rect.h - abscentery; p3x = px * cangle - py * sangle + abscenterx; p3y = px * sangle + py * cangle + abscentery; /* Bottom Right */ px = final_rect.x + final_rect.w - abscenterx; py = final_rect.y + final_rect.h - abscentery; p4x = px * cangle - py * sangle + abscenterx; p4y = px * sangle + py * cangle + abscentery; tmp_rect.x = (int)MIN(MIN(p1x, p2x), MIN(p3x, p4x)); tmp_rect.y = (int)MIN(MIN(p1y, p2y), MIN(p3y, p4y)); tmp_rect.w = dstwidth; tmp_rect.h = dstheight; /* The NONE blend mode needs some special care with non-opaque surfaces. * Other blend modes or opaque surfaces can be blitted directly. */ if (blendmode != SDL_BLENDMODE_NONE || isOpaque) { if (applyModulation == SDL_FALSE) { /* If the modulation wasn't already applied, make it happen now. */ SDL_SetSurfaceAlphaMod(src_rotated, alphaMod); SDL_SetSurfaceColorMod(src_rotated, rMod, gMod, bMod); } retval = SDL_BlitSurface(src_rotated, NULL, surface, &tmp_rect); } else { /* The NONE blend mode requires three steps to get the pixels onto the destination surface. * First, the area where the rotated pixels will be blitted to get set to zero. * This is accomplished by simply blitting a mask with the NONE blend mode. * The colorkey set by the rotate function will discard the correct pixels. */ SDL_Rect mask_rect = tmp_rect; SDL_SetSurfaceBlendMode(mask_rotated, SDL_BLENDMODE_NONE); retval = SDL_BlitSurface(mask_rotated, NULL, surface, &mask_rect); if (!retval) { /* The next step copies the alpha value. This is done with the BLEND blend mode and * by modulating the source colors with 0. Since the destination is all zeros, this * will effectively set the destination alpha to the source alpha. */ SDL_SetSurfaceColorMod(src_rotated, 0, 0, 0); mask_rect = tmp_rect; retval = SDL_BlitSurface(src_rotated, NULL, surface, &mask_rect); if (!retval) { /* The last step gets the color values in place. The ADD blend mode simply adds them to * the destination (where the color values are all zero). However, because the ADD blend * mode modulates the colors with the alpha channel, a surface without an alpha mask needs * to be created. This makes all source pixels opaque and the colors get copied correctly. */ SDL_Surface *src_rotated_rgb; src_rotated_rgb = SDL_CreateRGBSurfaceFrom(src_rotated->pixels, src_rotated->w, src_rotated->h, src_rotated->format->BitsPerPixel, src_rotated->pitch, src_rotated->format->Rmask, src_rotated->format->Gmask, src_rotated->format->Bmask, 0); if (src_rotated_rgb == NULL) { retval = -1; } else { SDL_SetSurfaceBlendMode(src_rotated_rgb, SDL_BLENDMODE_ADD); retval = SDL_BlitSurface(src_rotated_rgb, NULL, surface, &tmp_rect); SDL_FreeSurface(src_rotated_rgb); } } } SDL_FreeSurface(mask_rotated); } if (src_rotated != NULL) { SDL_FreeSurface(src_rotated); } } } if (SDL_MUSTLOCK(src)) { SDL_UnlockSurface(src); } if (mask != NULL) { SDL_FreeSurface(mask); } if (src_clone != NULL) { SDL_FreeSurface(src_clone); } return retval; }
/** * @brief Tests some more blitting routines. */ static void surface_testBlitBlend( SDL_Surface *testsur ) { int ret; SDL_Rect rect; SDL_Surface *face; int i, j, ni, nj; int mode; SDL_ATbegin( "Blit Blending Tests" ); /* Clear surface. */ ret = SDL_FillRect( testsur, NULL, SDL_MapRGB( testsur->format, 0, 0, 0 ) ); if (SDL_ATassert( "SDL_FillRect", ret == 0)) return; /* Create the blit surface. */ face = SDL_CreateRGBSurfaceFrom( (void*)img_face.pixel_data, img_face.width, img_face.height, 32, img_face.width*4, RMASK, GMASK, BMASK, AMASK ); if (SDL_ATassert( "SDL_CreateRGBSurfaceFrom", face != NULL)) return; /* Set alpha mod. */ ret = SDL_SetSurfaceAlphaMod( face, 100 ); if (SDL_ATassert( "SDL_SetSurfaceAlphaMod", ret == 0)) return; /* Steps to take. */ ni = testsur->w - face->w; nj = testsur->h - face->h; /* Constant values. */ rect.w = face->w; rect.h = face->h; /* Test None. */ if (surface_testBlitBlendMode( testsur, face, SDL_BLENDMODE_NONE )) return; if (SDL_ATassert( "Blitting blending output not the same (using SDL_BLENDMODE_NONE).", surface_compare( testsur, &img_blendNone )==0 )) return; /* Test Mask. */ if (surface_testBlitBlendMode( testsur, face, SDL_BLENDMODE_MASK )) return; if (SDL_ATassert( "Blitting blending output not the same (using SDL_BLENDMODE_MASK).", surface_compare( testsur, &img_blendMask )==0 )) return; /* Test Blend. */ if (surface_testBlitBlendMode( testsur, face, SDL_BLENDMODE_BLEND )) return; if (SDL_ATassert( "Blitting blending output not the same (using SDL_BLENDMODE_BLEND).", surface_compare( testsur, &img_blendBlend )==0 )) return; /* Test Add. */ if (surface_testBlitBlendMode( testsur, face, SDL_BLENDMODE_ADD )) return; if (SDL_ATassert( "Blitting blending output not the same (using SDL_BLENDMODE_ADD).", surface_compare( testsur, &img_blendAdd )==0 )) return; /* Test Mod. */ if (surface_testBlitBlendMode( testsur, face, SDL_BLENDMODE_MOD )) return; if (SDL_ATassert( "Blitting blending output not the same (using SDL_BLENDMODE_MOD).", surface_compare( testsur, &img_blendMod )==0 )) return; /* Clear surface. */ ret = SDL_FillRect( testsur, NULL, SDL_MapRGB( testsur->format, 0, 0, 0 ) ); if (SDL_ATassert( "SDL_FillRect", ret == 0)) return; /* Loop blit. */ for (j=0; j <= nj; j+=4) { for (i=0; i <= ni; i+=4) { /* Set colour mod. */ ret = SDL_SetSurfaceColorMod( face, (255/nj)*j, (255/ni)*i, (255/nj)*j ); if (SDL_ATassert( "SDL_SetSurfaceColorMod", ret == 0)) return; /* Set alpha mod. */ ret = SDL_SetSurfaceAlphaMod( face, (100/ni)*i ); if (SDL_ATassert( "SDL_SetSurfaceAlphaMod", ret == 0)) return; /* Crazy blending mode magic. */ mode = (i/4*j/4) % 4; if (mode==0) mode = SDL_BLENDMODE_MASK; else if (mode==1) mode = SDL_BLENDMODE_BLEND; else if (mode==2) mode = SDL_BLENDMODE_ADD; else if (mode==3) mode = SDL_BLENDMODE_MOD; ret = SDL_SetSurfaceBlendMode( face, mode ); if (SDL_ATassert( "SDL_SetSurfaceBlendMode", ret == 0)) return; /* Blitting. */ rect.x = i; rect.y = j; ret = SDL_BlitSurface( face, NULL, testsur, &rect ); if (SDL_ATassert( "SDL_BlitSurface", ret == 0)) return; } } /* Check to see if matches. */ if (SDL_ATassert( "Blitting blending output not the same (using SDL_BLEND_*).", surface_compare( testsur, &img_blendAll )==0 )) return; /* Clean up. */ SDL_FreeSurface( face ); SDL_ATend(); }
/** * @brief Tests some blitting routines. */ static void surface_testBlit( SDL_Surface *testsur ) { int ret; SDL_Rect rect; SDL_Surface *face; int i, j, ni, nj; SDL_ATbegin( "Blit Tests" ); /* Clear surface. */ ret = SDL_FillRect( testsur, NULL, SDL_MapRGB( testsur->format, 0, 0, 0 ) ); if (SDL_ATassert( "SDL_FillRect", ret == 0)) return; /* Create face surface. */ face = SDL_CreateRGBSurfaceFrom( (void*)img_face.pixel_data, img_face.width, img_face.height, 32, img_face.width*4, RMASK, GMASK, BMASK, AMASK ); if (SDL_ATassert( "SDL_CreateRGBSurfaceFrom", face != NULL)) return; /* Constant values. */ rect.w = face->w; rect.h = face->h; ni = testsur->w - face->w; nj = testsur->h - face->h; /* Loop blit. */ for (j=0; j <= nj; j+=4) { for (i=0; i <= ni; i+=4) { /* Blitting. */ rect.x = i; rect.y = j; ret = SDL_BlitSurface( face, NULL, testsur, &rect ); if (SDL_ATassert( "SDL_BlitSurface", ret == 0)) return; } } /* See if it's the same. */ if (SDL_ATassert( "Blitting output not the same (normal blit).", surface_compare( testsur, &img_blit )==0 )) return; /* Clear surface. */ ret = SDL_FillRect( testsur, NULL, SDL_MapRGB( testsur->format, 0, 0, 0 ) ); if (SDL_ATassert( "SDL_FillRect", ret == 0)) return; /* Test blitting with colour mod. */ for (j=0; j <= nj; j+=4) { for (i=0; i <= ni; i+=4) { /* Set colour mod. */ ret = SDL_SetSurfaceColorMod( face, (255/nj)*j, (255/ni)*i, (255/nj)*j ); if (SDL_ATassert( "SDL_SetSurfaceColorMod", ret == 0)) return; /* Blitting. */ rect.x = i; rect.y = j; ret = SDL_BlitSurface( face, NULL, testsur, &rect ); if (SDL_ATassert( "SDL_BlitSurface", ret == 0)) return; } } /* See if it's the same. */ if (SDL_ATassert( "Blitting output not the same (using SDL_SetSurfaceColorMod).", surface_compare( testsur, &img_blitColour )==0 )) return; /* Clear surface. */ ret = SDL_FillRect( testsur, NULL, SDL_MapRGB( testsur->format, 0, 0, 0 ) ); if (SDL_ATassert( "SDL_FillRect", ret == 0)) return; /* Restore colour. */ ret = SDL_SetSurfaceColorMod( face, 255, 255, 255 ); if (SDL_ATassert( "SDL_SetSurfaceColorMod", ret == 0)) return; /* Test blitting with colour mod. */ for (j=0; j <= nj; j+=4) { for (i=0; i <= ni; i+=4) { /* Set alpha mod. */ ret = SDL_SetSurfaceAlphaMod( face, (255/ni)*i ); if (SDL_ATassert( "SDL_SetSurfaceAlphaMod", ret == 0)) return; /* Blitting. */ rect.x = i; rect.y = j; ret = SDL_BlitSurface( face, NULL, testsur, &rect ); if (SDL_ATassert( "SDL_BlitSurface", ret == 0)) return; } } /* See if it's the same. */ if (SDL_ATassert( "Blitting output not the same (using SDL_SetSurfaceAlphaMod).", surface_compare( testsur, &img_blitAlpha )==0 )) return; /* Clean up. */ SDL_FreeSurface( face ); SDL_ATend(); }