// Convert the normal tiles to masked tiles void CEGALatch::applyMasks() { SDL_Surface *frontSfc = gGraphics.getTileMap(1).getSDLSurface(); SDL_Surface *backSfc = gGraphics.getTileMap(0).getSDLSurface(); #if SDL_VERSION_ATLEAST(2, 0, 0) SDL_SetSurfaceBlendMode(frontSfc, SDL_BLENDMODE_BLEND); #endif if(SDL_MUSTLOCK(frontSfc)) SDL_LockSurface(frontSfc); if(SDL_MUSTLOCK(backSfc)) SDL_LockSurface(backSfc); const Uint8 bpp = frontSfc->format->BytesPerPixel; for( Uint16 t=0 ; t<m_num16tiles ; t++ ) { if( g_pBehaviorEngine->getTileProperties().at(t).behaviour == -2 ) // This is for masked tiles. { SDL_Rect srGsRect, dstRect; srGsRect.w = srGsRect.h = 16; dstRect.w = dstRect.h = 16; srGsRect.x = 16*(t%13); srGsRect.y = 16*(t/13); SDL_FillRect( frontSfc, &srGsRect, SDL_MapRGBA(frontSfc->format, 0, 0, 0, 0) ); for( Uint16 x=0 ; x<16 ; x++ ) for( Uint16 y=0 ; y<16 ; y++ ) { Uint32 u_colour = 0; Uint8 r,g,b; Uint8 *u_offset = (Uint8*)backSfc->pixels + bpp*((y+16*((t+1)/13))*13*16 + 16*((t+1)%13) + x); memcpy( &u_colour, u_offset, bpp ); SDL_GetRGB( u_colour, backSfc->format, &r, &g, &b ); Uint8 alpha; if( r>=250 && g>=250 && b>=250 ) // In this case set it to zero { alpha = r = g = b = 0; } else // Get the pixel of the previous tile. If the mask has colour, use alpha channel, black is opaque { alpha = 255 - (r+g+b)/3; u_offset = (Uint8*)backSfc->pixels + bpp*((y+16*(t/13))*13*16 + 16*(t%13) + x); memcpy( &u_colour, u_offset, bpp); SDL_GetRGB( u_colour, backSfc->format, &r, &g, &b); } SDL_Rect srGsRect; srGsRect.w = srGsRect.h = 1; srGsRect.x = 16*((t)%13) + x; srGsRect.y = y+16*((t)/13); SDL_FillRect( frontSfc, &srGsRect, SDL_MapRGBA(frontSfc->format, r, g, b, alpha) ); } } } if(SDL_MUSTLOCK(backSfc)) SDL_UnlockSurface(backSfc); if(SDL_MUSTLOCK(frontSfc)) SDL_UnlockSurface(frontSfc); }
void drawall(gamedata &g){ int ypos; int ypos2; // Set screenheight int screenheight = 0; if (g.players == 1){ screenheight = limit(GAME_HEIGHT,GAME_HEIGHT,240); //464); }else{ screenheight = limit(GAME_HEIGHT,GAME_HEIGHT,120); } if(!g.scoreBarPos) // top { ypos = 0; ypos2 = 8; } else // bottom { ypos = screenheight - 16; ypos2 = screenheight - 8; } // Player 1 // int x1 = limit(int(g.player1->x)-308, 0, GAME_WIDTH-320); int x1 = limit(int(g.player1->x)-160, 0, GAME_WIDTH-320); int y1 = limit(int(g.player1->y)-54, 0, GAME_HEIGHT-screenheight); SDL_Rect srcrect; srcrect.x = x1; srcrect.y = y1; srcrect.w = 320; srcrect.h = screenheight; SDL_BlitSurface(g.gamescreen, &srcrect, g.virtualscreen, NULL); SDL_Rect cliprect; cliprect.x = 0; cliprect.y = 0; cliprect.w = 320; cliprect.h = screenheight; SDL_SetClipRect(g.virtualscreen, &cliprect); drawblits(g,x1,y1); SDL_SetClipRect(g.virtualscreen, NULL); if (g.players == 1){ if(GameState == STATE_GAME) // display_playinfo(g.virtualscreen, 1, *g.player1, screenheight - 16, g.images, g.mission, // g.targetscore, g.whitefont, g.greenfont, g); display_playinfo(g.virtualscreen, 1, *g.player1, ypos, g.images, g.mission, g.targetscore, g.whitefont, g.greenfont, g); }else{ if(GameState == STATE_GAME) display_playinfo(g.virtualscreen, 1, *g.player1, screenheight - 8, g.images, g.mission, g.targetscore, g.whitefont, g.greenfont, g); } /* display_playinfo(g.virtualscreen, 1, *g.player1, screenheight, g.images, g.mission, g.targetscore, g.whitefont, g.greenfont, g); */ // Player 2 if (g.players == 2){ int x2 = limit(int(g.player2->x)-160, 0, GAME_WIDTH-320); int y2 = limit(int(g.player2->y)-54, 0, GAME_HEIGHT-screenheight);//-208); //224); SDL_Rect srcrect; srcrect.x = x2; srcrect.y = y2; srcrect.w = 320; srcrect.h = screenheight; SDL_Rect desrect; desrect.x = 0; desrect.y = 120; desrect.w = 320; desrect.h = screenheight; SDL_BlitSurface(g.gamescreen, &srcrect, g.virtualscreen, &desrect); SDL_Rect cliprect; cliprect.x = 0; cliprect.y = 120; cliprect.w = 320; cliprect.h = screenheight; SDL_SetClipRect(g.virtualscreen, &cliprect); drawblits(g,x2,y2-120); SDL_SetClipRect(g.virtualscreen, NULL); if(GameState == STATE_GAME) display_playinfo(g.virtualscreen, 2, *g.player2, 240 - 8, g.images, g.mission, g.targetscore, g.whitefont, g.greenfont, g); /* display_playinfo(g.virtualscreen, 2, *g.player2, 464, g.images, g.mission, g.targetscore, g.whitefont, g.greenfont, g); */ } if(GameState == STATE_INTRO || GameState == STATE_MENU) { if(CurrentMenu == MenuMainIntro) menuDraw(CurrentMenu, 140, 100, g); else if(CurrentMenu == MenuMain) menuDraw(CurrentMenu, 120, 100, g); else if(CurrentMenu == MenuOptions) menuDraw(CurrentMenu, 110, 100,g); else if(CurrentMenu == MenuGameOptions) menuDraw(CurrentMenu, 20, 80, g); else menuDraw(CurrentMenu, 140, 100, g); } else if(GameState == STATE_MENU_PLANE_SELECT) { menuPlanesDraw(20, 10, g); } else if(GameState == STATE_MENU_PLAYER_CONTROL_SELECT) { menuSelectPlayerDraw(g); } // Best AI Score if (g.planes > g.players){ plane bestp; bool found = false; g.p.reset(); while (g.p.next()){ if ((g.p().control == 0) && (g.p().side > 0)){ if (!found){ bestp = g.p(); found = true; }else{ if ((g.mission == 0) || (g.mission == 1)){ if (g.p().score > bestp.score){ bestp = g.p(); } }else{ if (g.p().targetscore < bestp.targetscore){ bestp = g.p(); } } } } } // Display AI if(GameState == STATE_GAME){ SDL_Rect rect; char compstring[] = "Plane x"; compstring[6] = '0' + bestp.side; if (g.players == 1){ rect.x = 304; rect.y = ypos; rect.w = 16; rect.h = 16; SDL_FillRect(g.virtualscreen,&rect,16); g.images[bestp.image+13].blit(g.virtualscreen,304,ypos); g.whitefont.write(g.virtualscreen, 24, ypos2, compstring); } else{ // TODO: display the best player score } // Display score if (g.players == 1){ display_score(g.virtualscreen, bestp, 112, ypos2, g.mission, g.targetscore, g.whitefont, g.greenfont); }else{ display_score(g.virtualscreen, bestp, 112, screenheight-8, g.mission, g.targetscore, g.whitefont, g.greenfont); } } } // Update screen display SDL_Rect rect; rect.x = 0; rect.y = 0; rect.w = 320; rect.h = 240; SDL_BlitSurface(g.virtualscreen, &rect, g.physicalscreen, NULL); //SDL_Flip(g.physicalscreen); if(SDL_MUSTLOCK(ScreenSurface)) SDL_LockSurface(ScreenSurface); SDL_Surface *p = SDL_ConvertSurface(g.physicalscreen, ScreenSurface->format, 0); SDL_SoftStretch(p, NULL, ScreenSurface, NULL); if(SDL_MUSTLOCK(ScreenSurface)) SDL_UnlockSurface(ScreenSurface); SDL_Flip(ScreenSurface); SDL_FreeSurface(p); //SDL_UpdateRect(g.physicalscreen, 0, 0, 0, 0); g.sound.update(); }
void EndRender() { if (SDL_MUSTLOCK(mSurf) && !mLockedForHitTest) SDL_UnlockSurface(mSurf); }
static void video_write(void){ int i; th_ycbcr_buffer yuv; int y_offset, uv_offset; th_decode_ycbcr_out(td,yuv); /* Lock SDL_yuv_overlay */ if ( SDL_MUSTLOCK(screen) ) { if ( SDL_LockSurface(screen) < 0 ) return; } if (SDL_LockYUVOverlay(yuv_overlay) < 0) return; /* let's draw the data on a SDL screen (*screen) */ /* deal with border stride */ /* reverse u and v for SDL */ /* and crop input properly, respecting the encoded frame rect */ /* problems may exist for odd frame rect for some encodings */ y_offset=(ti.pic_x&~1)+yuv[0].stride*(ti.pic_y&~1); if (px_fmt==TH_PF_422) { uv_offset=(ti.pic_x/2)+(yuv[1].stride)*(ti.pic_y); /* SDL doesn't have a planar 4:2:2 */ for(i=0;i<yuv_overlay->h;i++) { int j; char *in_y = (char *)yuv[0].data+y_offset+yuv[0].stride*i; char *out = (char *)(yuv_overlay->pixels[0]+yuv_overlay->pitches[0]*i); for (j=0;j<yuv_overlay->w;j++) out[j*2] = in_y[j]; char *in_u = (char *)yuv[1].data+uv_offset+yuv[1].stride*i; char *in_v = (char *)yuv[2].data+uv_offset+yuv[2].stride*i; for (j=0;j<yuv_overlay->w>>1;j++) { out[j*4+1] = in_u[j]; out[j*4+3] = in_v[j]; } } } else { uv_offset=(ti.pic_x/2)+(yuv[1].stride)*(ti.pic_y/2); for(i=0;i<yuv_overlay->h;i++) memcpy(yuv_overlay->pixels[0]+yuv_overlay->pitches[0]*i, yuv[0].data+y_offset+yuv[0].stride*i, yuv_overlay->w); for(i=0;i<yuv_overlay->h/2;i++){ memcpy(yuv_overlay->pixels[1]+yuv_overlay->pitches[1]*i, yuv[2].data+uv_offset+yuv[2].stride*i, yuv_overlay->w/2); memcpy(yuv_overlay->pixels[2]+yuv_overlay->pitches[2]*i, yuv[1].data+uv_offset+yuv[1].stride*i, yuv_overlay->w/2); } } /* Unlock SDL_yuv_overlay */ if ( SDL_MUSTLOCK(screen) ) { SDL_UnlockSurface(screen); } SDL_UnlockYUVOverlay(yuv_overlay); /* Show, baby, show! */ SDL_DisplayYUVOverlay(yuv_overlay, &rect); }
/* The general purpose software blit routine */ static int SDL_SoftBlit(SDL_Surface * src, SDL_Rect * srcrect, SDL_Surface * dst, SDL_Rect * dstrect) { int okay; int src_locked; int dst_locked; /* Everything is okay at the beginning... */ okay = 1; /* Lock the destination if it's in hardware */ dst_locked = 0; if (SDL_MUSTLOCK(dst)) { if (SDL_LockSurface(dst) < 0) { okay = 0; } else { dst_locked = 1; } } /* Lock the source if it's in hardware */ src_locked = 0; if (SDL_MUSTLOCK(src)) { if (SDL_LockSurface(src) < 0) { okay = 0; } else { src_locked = 1; } } /* Set up source and destination buffer pointers, and BLIT! */ if (okay && srcrect->w && srcrect->h) { SDL_BlitFunc RunBlit; SDL_BlitInfo *info = &src->map->info; /* Set up the blit information */ info->src = (Uint8 *) src->pixels + (Uint16) srcrect->y * src->pitch + (Uint16) srcrect->x * info->src_fmt->BytesPerPixel; info->src_w = srcrect->w; info->src_h = srcrect->h; info->src_pitch = src->pitch; info->src_skip = info->src_pitch - info->src_w * info->src_fmt->BytesPerPixel; info->dst = (Uint8 *) dst->pixels + (Uint16) dstrect->y * dst->pitch + (Uint16) dstrect->x * info->dst_fmt->BytesPerPixel; info->dst_w = dstrect->w; info->dst_h = dstrect->h; info->dst_pitch = dst->pitch; info->dst_skip = info->dst_pitch - info->dst_w * info->dst_fmt->BytesPerPixel; RunBlit = (SDL_BlitFunc) src->map->data; /* Run the actual software blit */ RunBlit(info); } /* We need to unlock the surfaces if they're locked */ if (dst_locked) { SDL_UnlockSurface(dst); } if (src_locked) { SDL_UnlockSurface(src); } /* Blit is done! */ return (okay ? 0 : -1); }
void UnlockScreen(SDL_Surface *screen) { if ( SDL_MUSTLOCK(screen) ) { SDL_UnlockSurface(screen); } }
bool CEGASprit::loadData(const std::string& filename, bool compresseddata) { byte *RawData; SDL_Surface *sfc; Uint8* pixel; Uint32 percent = 0; FILE* latchfile = OpenGameFile(filename.c_str(),"rb"); if(!latchfile) return false; gResourceLoader.setPermilage(10); RawData = new byte[m_planesize * 5]; // get the data out of the file into the memory, decompressing it if necessary. if (compresseddata) { if (lz_decompress(latchfile, RawData)) return 1; } else { for(int i=0 ; i<(m_planesize*5) ; i++) RawData[i] = fgetc(latchfile); } fclose(latchfile); gResourceLoader.setPermilage(50); // TODO: Try to blit the Font map here! // these are the offsets of the different video planes as // relative to each other--that is if a pixel in plane1 // is at N, the byte for that same pixel in plane3 will be // at (N + plane3). unsigned long plane1, plane2, plane3, plane4, plane5; plane1 = 0; plane2 = (m_planesize * 1); plane3 = (m_planesize * 2); plane4 = (m_planesize * 3); plane5 = (m_planesize * 4); CPlanes Planes(RawData + m_spriteloc); Planes.setOffsets(plane1, plane2, plane3, plane4, plane5); // load the image data gGraphics.createEmptySprites(4,MAX_SPRITES+1); for(int i=0 ; i<m_numsprites ; i++) { GsSprite &Sprite = gGraphics.getSprite(0,i); Sprite.setSize( EGASpriteModell[i].width, EGASpriteModell[i].height ); Sprite.setBoundingBoxCoordinates( (EGASpriteModell[i].hitbox_l << STC), (EGASpriteModell[i].hitbox_u << STC), (EGASpriteModell[i].hitbox_r << STC), (EGASpriteModell[i].hitbox_b << STC) ); Sprite.createSurface( gVideoDriver.mpVideoEngine->getBlitSurface()->flags, gGraphics.Palette.m_Palette ); percent = (i*50)/m_numsprites; gResourceLoader.setPermilage(50+percent); } gResourceLoader.setPermilage(100); for(int p=0 ; p<4 ; p++) { for(int s=0 ; s<m_numsprites ; s++) { sfc = gGraphics.getSprite(0,s).getSDLSurface(); if(SDL_MUSTLOCK(sfc)) SDL_LockSurface(sfc); pixel = (Uint8*) sfc->pixels; Planes.readPlane(p, pixel, sfc->w, sfc->h); if(SDL_MUSTLOCK(sfc)) SDL_UnlockSurface(sfc); percent = (s*100)/m_numsprites; gResourceLoader.setPermilage(100+percent); } } gResourceLoader.setPermilage(200); // now load the 5th plane, which contains the sprite masks. // note that we invert the mask because our graphics functions // use white on black masks whereas keen uses black on white. for(int s=0 ; s<m_numsprites ; s++) { GsSprite &Sprite = gGraphics.getSprite(0,s); SDL_Surface *pixsfc = Sprite.getSDLSurface(); SDL_Surface *masksfc = Sprite.getSDLMaskSurface(); if(SDL_MUSTLOCK(pixsfc)) SDL_LockSurface(pixsfc); if(SDL_MUSTLOCK(masksfc)) SDL_LockSurface(masksfc); pixel = (Uint8*) masksfc->pixels; for(int y=0 ; y<masksfc->h ; y++) { for(int x=0 ; x<masksfc->w ; x++) { if(Planes.getbit(4)) pixel[y*masksfc->w + x] = ((Uint8*)pixsfc->pixels)[y*pixsfc->w + x]; else pixel[y*masksfc->w + x] = 15; } } if(SDL_MUSTLOCK(masksfc)) SDL_UnlockSurface(masksfc); if(SDL_MUSTLOCK(pixsfc)) SDL_UnlockSurface(pixsfc); percent = (s*100)/m_numsprites; gResourceLoader.setPermilage(200+percent); } gResourceLoader.setPermilage(300); if(RawData){ delete[] RawData; RawData = NULL;} LoadSpecialSprites( gGraphics.getSpriteVec(0) ); for(unsigned int i=1 ; i<4 ; i++) { gGraphics.getSpriteVec(i) = gGraphics.getSpriteVec(0); } // For the other variant let's exchange some colors auto &SpriteVecPlayer2 = gGraphics.getSpriteVec(1); //for( auto &sprite : SpriteVecPlayer2) for( unsigned int i = 0 ; i < SpriteVecPlayer2.size() ; i++) { auto &sprite = SpriteVecPlayer2[i]; // Red against Purple sprite.exchangeSpriteColor( 5, 4, 0 ); sprite.exchangeSpriteColor( 13, 12, 0 ); // Yellow against Green sprite.exchangeSpriteColor( 2, 6, 0 ); sprite.exchangeSpriteColor( 10, 14, 0 ); } auto &SpriteVecPlayer3 = gGraphics.getSpriteVec(2); for( auto &sprite : SpriteVecPlayer3) { // Red against Green sprite.exchangeSpriteColor( 2, 4, 0 ); sprite.exchangeSpriteColor( 10, 12, 0 ); // Yellow against Purple sprite.exchangeSpriteColor( 5, 6, 0 ); sprite.exchangeSpriteColor( 13, 14, 0 ); } auto &SpriteVecPlayer4 = gGraphics.getSpriteVec(3); for( auto &sprite : SpriteVecPlayer4) { // Red against Yellow sprite.exchangeSpriteColor( 6, 4, 0 ); sprite.exchangeSpriteColor( 14, 12, 0 ); // Green against Purple sprite.exchangeSpriteColor( 2, 5, 0 ); sprite.exchangeSpriteColor( 10, 13, 0 ); } for(unsigned int i=0 ; i<4 ; i++) { for(Uint16 s=0 ; s<gGraphics.getSpriteVec(i).size() ; s++) { GsSprite &Sprite = gGraphics.getSprite(i,s); Sprite.optimizeSurface(); percent = (s*50)/m_numsprites; gResourceLoader.setPermilage(300+percent); } } gResourceLoader.setPermilage(350); std::set<std::string> filelist; FileListAdder fileListAdder; std::string gfxpath = JoinPaths(m_gamepath, "gfx"); GetFileList(filelist, fileListAdder, gfxpath, false, FM_REG); FilterFilelist(filelist, "sprite"); std::set<std::string>::iterator it = filelist.begin(); int listsize = filelist.size(); for( int c=0 ; it != filelist.end() ; it++, c++ ) { std::string name=*it; int num = getRessourceID(name, "sprite"); if(num < m_numsprites ) { GsSprite &Sprite = gGraphics.getSprite(0,num); std::string filename = getResourceFilename("gfx/"+name, m_gamepath, false, true); Sprite.loadHQSprite(filename); } percent = (c*150)/listsize; gResourceLoader.setPermilage(350+percent); } gResourceLoader.setPermilage(500); for(unsigned int i=0 ; i<4 ; i++) { const int NoSprites = gGraphics.getSpriteVec(i).size(); for(Uint16 s=0 ; s<NoSprites ; s++) { gGraphics.getSprite(i,s).applyTransparency(); percent = (s*250)/NoSprites; gResourceLoader.setPermilage(500+percent); } } gResourceLoader.setPermilage(750); // Now create special sprites, like those for effects and the doors! DeriveSpecialSprites( gGraphics.getTileMap(1), gGraphics.getSpriteVec(0) ); gResourceLoader.setPermilage(800); // Here special Effects are applied, only when the option is enabled for it if(gVideoDriver.getSpecialFXConfig()) ApplySpecialFX(); gResourceLoader.setPermilage(900); // Apply the sprites for player 2,3 and 4 DerivePlayerSprites( 1,gGraphics.getSpriteVec(1) ); DerivePlayerSprites( 2,gGraphics.getSpriteVec(2) ); DerivePlayerSprites( 3,gGraphics.getSpriteVec(3) ); gResourceLoader.setPermilage(1000); return true; }
SDL_Texture * SDL_CreateTextureFromSurface(SDL_Renderer * renderer, SDL_Surface * surface) { const SDL_PixelFormat *fmt; SDL_bool needAlpha; Uint32 i; Uint32 format; SDL_Texture *texture; CHECK_RENDERER_MAGIC(renderer, NULL); if (!surface) { SDL_SetError("SDL_CreateTextureFromSurface() passed NULL surface"); return NULL; } /* See what the best texture format is */ fmt = surface->format; if (fmt->Amask || SDL_GetColorKey(surface, NULL) == 0) { needAlpha = SDL_TRUE; } else { needAlpha = SDL_FALSE; } format = renderer->info.texture_formats[0]; for (i = 0; i < renderer->info.num_texture_formats; ++i) { if (!SDL_ISPIXELFORMAT_FOURCC(renderer->info.texture_formats[i]) && SDL_ISPIXELFORMAT_ALPHA(renderer->info.texture_formats[i]) == needAlpha) { format = renderer->info.texture_formats[i]; break; } } texture = SDL_CreateTexture(renderer, format, SDL_TEXTUREACCESS_STATIC, surface->w, surface->h); if (!texture) { return NULL; } if (format == surface->format->format) { if (SDL_MUSTLOCK(surface)) { SDL_LockSurface(surface); SDL_UpdateTexture(texture, NULL, surface->pixels, surface->pitch); SDL_UnlockSurface(surface); } else { SDL_UpdateTexture(texture, NULL, surface->pixels, surface->pitch); } } else { SDL_PixelFormat *dst_fmt; SDL_Surface *temp = NULL; /* Set up a destination surface for the texture update */ dst_fmt = SDL_AllocFormat(format); temp = SDL_ConvertSurface(surface, dst_fmt, 0); SDL_FreeFormat(dst_fmt); if (temp) { SDL_UpdateTexture(texture, NULL, temp->pixels, temp->pitch); SDL_FreeSurface(temp); } else { SDL_DestroyTexture(texture); return NULL; } } { Uint8 r, g, b, a; SDL_BlendMode blendMode; SDL_GetSurfaceColorMod(surface, &r, &g, &b); SDL_SetTextureColorMod(texture, r, g, b); SDL_GetSurfaceAlphaMod(surface, &a); SDL_SetTextureAlphaMod(texture, a); if (SDL_GetColorKey(surface, NULL) == 0) { /* We converted to a texture with alpha format */ SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND); } else { SDL_GetSurfaceBlendMode(surface, &blendMode); SDL_SetTextureBlendMode(texture, blendMode); } } return texture; }
void UnlockScreen() { if(SDL_MUSTLOCK(screen)) SDL_UnlockSurface(screen); SDL_Flip(screen); }
Image* Image::merge(Image* image, const int x, const int y) { SDL_Surface* surface = new SDL_Surface(*(image->mImage)); Uint32 surface_pix, cur_pix; Uint8 r, g, b, a, p_r, p_g, p_b, p_a; double f_a, f_ca, f_pa; SDL_PixelFormat *current_fmt = mImage->format; SDL_PixelFormat *surface_fmt = surface->format; int current_offset, surface_offset; int offsetX = 0, offsetY = 0; if (SDL_MUSTLOCK(mImage)) { SDL_LockSurface(surface); SDL_LockSurface(mImage); } // for each pixel lines of a source image for (offsetY = (y > 0 ? 0 : -y); offsetY < image->getHeight() && y + offsetY < getHeight(); offsetY++) { for (offsetX = (x > 0 ? 0 : -x); offsetX < image->getWidth() && x + offsetX < getWidth(); offsetX++) { // Computing offset on both images current_offset = (y + offsetY) * getWidth() + x + offsetX; surface_offset = offsetY * surface->w + offsetX; // Retrieving a pixel to merge surface_pix = ((Uint32*) surface->pixels)[surface_offset]; cur_pix = ((Uint32*) mImage->pixels)[current_offset]; // Retreiving each channel of the pixel using pixel format r = (Uint8)(((surface_pix & surface_fmt->Rmask) >> surface_fmt->Rshift) << surface_fmt->Rloss); g = (Uint8)(((surface_pix & surface_fmt->Gmask) >> surface_fmt->Gshift) << surface_fmt->Gloss); b = (Uint8)(((surface_pix & surface_fmt->Bmask) >> surface_fmt->Bshift) << surface_fmt->Bloss); a = (Uint8)(((surface_pix & surface_fmt->Amask) >> surface_fmt->Ashift) << surface_fmt->Aloss); // Retreiving previous alpha value p_a = (Uint8)(((cur_pix & current_fmt->Amask) >> current_fmt->Ashift) << current_fmt->Aloss); // new pixel with no alpha or nothing on previous pixel if (a == SDL_ALPHA_OPAQUE || (p_a == 0 && a > 0)) ((Uint32 *)(surface->pixels))[current_offset] = SDL_MapRGBA(current_fmt, r, g, b, a); else if (a > 0) { // alpha is lower => merge color with previous value f_a = (double) a / 255.0; f_ca = 1.0 - f_a; f_pa = (double) p_a / 255.0; p_r = (Uint8)(((cur_pix & current_fmt->Rmask) >> current_fmt->Rshift) << current_fmt->Rloss); p_g = (Uint8)(((cur_pix & current_fmt->Gmask) >> current_fmt->Gshift) << current_fmt->Gloss); p_b = (Uint8)(((cur_pix & current_fmt->Bmask) >> current_fmt->Bshift) << current_fmt->Bloss); r = (Uint8)((double) p_r * f_ca * f_pa + (double)r * f_a); g = (Uint8)((double) p_g * f_ca * f_pa + (double)g * f_a); b = (Uint8)((double) p_b * f_ca * f_pa + (double)b * f_a); a = (a > p_a ? a : p_a); ((Uint32 *)(surface->pixels))[current_offset] = SDL_MapRGBA(current_fmt, r, g, b, a); } } }
void DrawScreen(SDL_Surface* screen, Audio *audio, int xx) { if(SDL_MUSTLOCK(screen)) { if(SDL_LockSurface(screen) < 0) return; } int ii, xs, ys; Real value; int red, green, blue; for (ii=0; ii<(HEIGHT/Y_STRETCH); ii++) { value = frequency_component( audio, frequency( FREQ_BASE + (((double)(ii*Y_STRETCH)) * FREQ_MULT) ) ); #ifdef FORMAT_AMP value = value * (Real)ii; #endif ((Real *)fourier->data)[ii] = value; } #ifdef NORMALIZE_FOURIER normalize( fourier ); audio_scale( fourier, 20000.0 ); #endif for (ii=0; ii<(HEIGHT/Y_STRETCH); ii++) { value = ((Real *)fourier->data)[ii]; #ifdef SQUARE_SUPPRESS value *= 0.001; value *= value; #endif value *= 0.001; #ifndef SQUARE_SUPPRESS if (value < 0) value = -value; #endif /* #ifdef FORMANT_AMP value *= (Real)ii; #endif */ // If capturing, sum the frequencies if (capturing) { ((Real *)captured->data)[ii] += value; captured_slices++; } red = (int)value; green = 0; blue = 0; if (red > 16000) { red = 0; green = 255; blue = 0; } else if (red > 255) { green = (int)((value-255.0)/20.0); if (blue > 512) { blue = (int)((value-512.0)/100.0); } red = 255; } // x stretch for (xs=0; xs<X_STRETCH; xs++) { for (ys=0; ys<Y_STRETCH; ys++) { setpixel(screen, xx+xs, (HEIGHT-1)-(ii*Y_STRETCH)-ys, red, green, blue); } } if (xx+X_STRETCH < WIDTH-X_STRETCH) { for (ys=Y_STRETCH; ys<HEIGHT; ys++) { if (windowing) { setpixel(screen, xx+X_STRETCH, ys, 0, 0, 255); } else { setpixel(screen, xx+X_STRETCH, ys, 0, 255, 0); } } } } if(SDL_MUSTLOCK(screen)) SDL_UnlockSurface(screen); SDL_Flip(screen); }
Image *Image::load(SDL_Surface *tmpImage) { #ifdef USE_OPENGL if (mUseOpenGL) { // Flush current error flag. glGetError(); int width = tmpImage->w; int height = tmpImage->h; int realWidth = powerOfTwo(width); int realHeight = powerOfTwo(height); if (realWidth < width || realHeight < height) { logger->log("Warning: image too large, cropping to %dx%d texture!", tmpImage->w, tmpImage->h); } // Make sure the alpha channel is not used, but copied to destination SDL_SetAlpha(tmpImage, 0, SDL_ALPHA_OPAQUE); // Determine 32-bit masks based on byte order Uint32 rmask, gmask, bmask, amask; #if SDL_BYTEORDER == SDL_BIG_ENDIAN rmask = 0xff000000; gmask = 0x00ff0000; bmask = 0x0000ff00; amask = 0x000000ff; #else rmask = 0x000000ff; gmask = 0x0000ff00; bmask = 0x00ff0000; amask = 0xff000000; #endif SDL_Surface *oldImage = tmpImage; tmpImage = SDL_CreateRGBSurface(SDL_SWSURFACE, realWidth, realHeight, 32, rmask, gmask, bmask, amask); if (!tmpImage) { logger->log("Error, image convert failed: out of memory"); return NULL; } SDL_BlitSurface(oldImage, NULL, tmpImage, NULL); GLuint texture; glGenTextures(1, &texture); OpenGLGraphics::bindTexture(mTextureType, texture); if (SDL_MUSTLOCK(tmpImage)) SDL_LockSurface(tmpImage); glTexImage2D(mTextureType, 0, 4, tmpImage->w, tmpImage->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, tmpImage->pixels); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glTexParameteri(mTextureType, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(mTextureType, GL_TEXTURE_MAG_FILTER, GL_NEAREST); if (SDL_MUSTLOCK(tmpImage)) SDL_UnlockSurface(tmpImage); SDL_FreeSurface(tmpImage); GLenum error = glGetError(); if (error) { std::string errmsg = "Unknown error"; switch (error) { case GL_INVALID_ENUM: errmsg = "GL_INVALID_ENUM"; break; case GL_INVALID_VALUE: errmsg = "GL_INVALID_VALUE"; break; case GL_INVALID_OPERATION: errmsg = "GL_INVALID_OPERATION"; break; case GL_STACK_OVERFLOW: errmsg = "GL_STACK_OVERFLOW"; break; case GL_STACK_UNDERFLOW: errmsg = "GL_STACK_UNDERFLOW"; break; case GL_OUT_OF_MEMORY: errmsg = "GL_OUT_OF_MEMORY"; break; } logger->log("Error: Image GL import failed: %s", errmsg.c_str()); return NULL; } return new Image(texture, width, height, realWidth, realHeight); } #endif bool hasAlpha = false; Uint8* imageAlphas = new Uint8[tmpImage->w * tmpImage->h]; if (tmpImage->format->BitsPerPixel == 32) { // Figure out whether the image uses its alpha layer for (int i = 0; i < tmpImage->w * tmpImage->h; ++i) { Uint8 r, g, b, a; SDL_GetRGBA(((Uint32*) tmpImage->pixels)[i], tmpImage->format, &r, &g, &b, &a); imageAlphas[i] = a; if (a != 255) hasAlpha = true; } } SDL_Surface *image; // Convert the surface to the current display format if (hasAlpha) image = SDL_DisplayFormatAlpha(tmpImage); else image = SDL_DisplayFormat(tmpImage); if (!image) { logger->log("Error: Image convert failed."); delete [] imageAlphas; return NULL; } return new Image(image, imageAlphas); }
static int SW_RenderCopyEx(SDL_Renderer * renderer, SDL_Surface *surface, SDL_Texture * texture, const SDL_Rect * srcrect, const SDL_Rect * final_rect, const double angle, const SDL_FPoint * center, const SDL_RendererFlip flip) { SDL_Surface *src = (SDL_Surface *) texture->driverdata; SDL_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; } tmp_rect.x = 0; tmp_rect.y = 0; tmp_rect.w = final_rect->w; tmp_rect.h = final_rect->h; /* 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; } /* srcrect is not selecting the whole src surface, so cropping is needed */ if (!(srcrect->w == src->w && srcrect->h == src->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, (texture->scaleMode == SDL_ScaleModeNearest) ? 0 : 1, 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; }
void DrawGradientText( const char* text, _sge_TTFont* font, int y, SDL_Surface* target, bool a_bTranslate ) { int i; if ( a_bTranslate ) { text = Translate( text ); } // 1. CREATE OFFSCREEN SURFACE SDL_Rect size = sge_TTF_TextSize( font, (char*)text ); size.w += 2; size.h += 2; size.x = 320 - size.w / 2; if ( size.x < 0 ) size.x = 0; size.y = y; SDL_Surface* surface = SDL_CreateRGBSurface( SDL_SRCCOLORKEY, size.w, size.h, 8, 0,0,0,0 ); if ( NULL == surface ) { debug( "DrawGradientText: Couldn't allocate %d by %d surface!\n", size.w, size.h ); return; } // 2. SET OFFSCREEN SURFACE COLORS SDL_SetColorKey( surface, SDL_SRCCOLORKEY, 0 ); SDL_Color colors[256]; colors[0].r = colors[0].g = colors[0].b = 0; colors[1] = colors[0]; // The rest is red->yellow gradient. for ( i=2; i<255; ++i ) { int j = i > 25 ? i-25 : 0; colors[i].r = 255; colors[i].g = 255-j; colors[i].b = 0; } SDL_SetColors( surface, colors, 0, 256 ); // 3. DRAW TEXT, APPLY BORDER, APPLY GRADIENT. int y1 = sge_TTF_FontAscent(font); sge_tt_textout( surface, font, text, 1, y1, 255, 0, 255); if ( SDL_MUSTLOCK(surface) ) SDL_LockSurface(surface); for ( y=1; y<size.h-1; ++y ) { int color = 254 * y / (size.h-1) + 1; unsigned char *p0, *p1, *p2; p1 = (unsigned char*) surface->pixels; p1 += surface->pitch * y + 1; p0 = p1 - surface->pitch; p2 = p1 + surface->pitch; for ( int x=1; x<size.w-1; ++x, ++p0, ++p1, ++p2 ) { if ( *p1 > 2 ) { *p1 = color; } else { if ( (*(p1-1) > 2) || (*(p1+1) > 2) || *p0 > 2 || *p2 > 2 ) { *p1 = 1; } } } } if ( SDL_MUSTLOCK(surface) ) SDL_UnlockSurface(surface); // 4. FINALLY SDL_BlitSurface( surface, NULL, target, &size ); SDL_FreeSurface( surface ); SDL_UpdateRect( target, size.x, size.y, size.w, size.h ); }
// Draw a string in the specified font void BaseEngine::DrawString(int iX, int iY, const char* pText, unsigned int uiColour, Font* pFont, SDL_Surface* pTarget ) { if ( pTarget == NULL ) pTarget = m_pActualScreen; if ( pFont == NULL ) pFont = g_pMainFont; if ( m_bInsideDraw ) if (SDL_MUSTLOCK(m_pActualScreen)) SDL_UnlockSurface(m_pActualScreen); SDL_Color color = { (uiColour&0xff0000)>>16, (uiColour&0xff00)>>8, (uiColour&0xff), 0 }; if ( ( pFont != NULL ) && ( pFont->GetFont() != NULL ) ) { SDL_Surface *sText = TTF_RenderText_Solid( pFont->GetFont(), pText, color ); SDL_Rect rcDest = {iX,iY,0,0}; SDL_BlitSurface( sText, NULL, pTarget, &rcDest ); SDL_FreeSurface( sText ); } if ( m_bInsideDraw ) if (SDL_MUSTLOCK(m_pActualScreen)) SDL_LockSurface(m_pActualScreen); } // Draw a triangle, as two vertical sided regions. void BaseEngine::DrawTriangle( double fX1, double fY1, double fX2, double fY2, double fX3, double fY3, unsigned int uiColour, SDL_Surface* pTarget ) { if ( pTarget == NULL ) pTarget = m_pActualScreen; // Ensure order is 1 2 3 from left to right if ( fX1 > fX2 ) { Swap( fX1,fX2 ); Swap( fY1,fY2 ); } // Bigger of 1 and 2 is in position 2 if ( fX2 > fX3 ) { Swap( fX2,fX3 ); Swap( fY2,fY3 ); } // Bigger of new 2 and 3 is in position 3 if ( fX1 > fX2 ) { Swap( fX1,fX2 ); Swap( fY1,fY2 ); } // Bigger of 1 and new 2 is in position 2 if ( fX1 == fX2 ) DrawVerticalSidedRegion( fX1, fX3, fY1, fY3, fY2, fY3, uiColour, pTarget ); else if ( fX2 == fX3 ) DrawVerticalSidedRegion( fX1, fX3, fY1, fY2, fY1, fY3, uiColour, pTarget ); else { // Split into two triangles. Find position on line 1-3 to split at double dSplitPointY = (double)fY1 + ( ( (double)((fX2-fX1)*(fY3-fY1)) ) / (double)(fX3-fX1) ); DrawVerticalSidedRegion( fX1, fX2, fY1, fY2, fY1, dSplitPointY, uiColour, pTarget ); DrawVerticalSidedRegion( fX2, fX3, fY2, fY3, dSplitPointY, fY3, uiColour, pTarget ); } } // Draw a vertical sided region. // If two points are the same then it is a triangle. // To do an arbitrary triangle, just draw two next to each other, one for left and one for right. void BaseEngine::DrawVerticalSidedRegion( double fX1, double fX2,// X positions double fY1a, double fY2a, // Start y positions for x1 and x2 double fY1b, double fY2b, // End y positions for x1 and x2 unsigned int uiColour, SDL_Surface* pTarget) { if ( pTarget == NULL ) pTarget = m_pActualScreen; // Ensure X1< X2, otherwise steps will go wrong! // Switch the points if x and y are wrong way round if ( fX2< fX1 ) { Swap(fX1,fX2); Swap(fY1a,fY2a); Swap(fY1b,fY2b); } int iXStart = (int)(fX1+0.5); int iXEnd = (int)(fX2+0.5); // If integer x positions are the same then avoid floating point inaccuracy problems by a special case if ( iXStart == iXEnd ) { int iYStart = (int)(fY1a+0.5); int iYEnd = (int)(fY2a+0.5); for ( int iY = iYStart ; iY<= iYEnd ; iY++ ) SafeSetPixel( iXStart, iY, uiColour, pTarget ); } else { // Draw left hand side int iYStart = (int)(fY1a+0.5); int iYEnd = (int)(fY1b+0.5); if ( iYStart> iYEnd ) Swap( iYStart, iYEnd ); //printf( "Firstline %d to %d (%f to %f)\n", iYStart, iYEnd, fY1a, fY1b ); for ( int iY = iYStart ; iY<= iYEnd ; iY++ ) SafeSetPixel( iXStart, iY, uiColour, pTarget ); // Draw the middle for ( int iX = iXStart+1 ; iX< iXEnd ; iX++ ) { double fYStart = fY1a + ( (((double)iX)-fX1)*(fY2a-fY1a)) /(fX2-fX1); double fYEnd = fY1b + ((((double)iX)-fX1)*(fY2b-fY1b))/(fX2-fX1); if ( fYEnd< fYStart ) Swap( fYStart, fYEnd ); int iYStart = (int)(fYStart+0.5); int iYEnd = (int)(fYEnd+0.5); //printf( "Line from %d to %d (%f to %f)\n", iYStart, iYEnd, fYStart, fYEnd ); for ( int iY = iYStart ; iY<= iYEnd ; iY++ ) SafeSetPixel( iX, iY, uiColour, pTarget ); } // Draw right hand side iYStart = (int)(fY2a+0.5); iYEnd = (int)(fY2b+0.5); if ( iYStart> iYEnd ) Swap( iYStart, iYEnd ); //printf( "Last line %d to %d (%f to %f)\n", iYStart, iYEnd, fY2a, fY2b ); for ( int iY = iYStart ; iY<= iYEnd ; iY++ ) SafeSetPixel( iXEnd, iY, uiColour, pTarget ); } } // Draw a rectangle on the specified surface void BaseEngine::DrawRectangle(int iX1, int iY1, int iX2, int iY2, unsigned int uiColour, SDL_Surface* pTarget) { if ( pTarget == NULL ) pTarget = m_pActualScreen; if ( iX2 < iX1 ) { int t = iX1; iX1 = iX2; iX2 = t; } if ( iY2 < iY1 ) { int t = iY1; iY1 = iY2; iY2 = t; } for ( int iX = iX1 ; iX <= iX2 ; iX++ ) for ( int iY = iY1 ; iY <= iY2 ; iY++ ) SafeSetPixel( iX, iY, uiColour, pTarget ); } // Draw an oval on the specified surface void BaseEngine::DrawOval(int iX1, int iY1, int iX2, int iY2, unsigned int uiColour, SDL_Surface* pTarget) { if ( pTarget == NULL ) pTarget = m_pActualScreen; if ( iX2 < iX1 ) { int t = iX1; iX1 = iX2; iX2 = t; } if ( iY2 < iY1 ) { int t = iY1; iY1 = iY2; iY2 = t; } double fCentreX = ((double)(iX2+iX1))/2.0; double fCentreY = ((double)(iY2+iY1))/2.0; double fXFactor = (double)((iX2-iX1) * (iX2-iX1))/4.0; double fYFactor = (double)((iY2-iY1) * (iY2-iY1))/4.0; double fDist; for ( int iX = iX1 ; iX <= iX2 ; iX++ ) for ( int iY = iY1 ; iY <= iY2 ; iY++ ) { fDist = ((double)iX - fCentreX) * ((double)iX - fCentreX)/fXFactor + ((double)iY - fCentreY) * ((double)iY - fCentreY)/fYFactor; if ( fDist <= 1.0 ) SafeSetPixel( iX, iY, uiColour, pTarget ); } } // Draw an oval on the specified surface void BaseEngine::DrawHollowOval( int iX1, int iY1, int iX2, int iY2, int iX3, int iY3, int iX4, int iY4, unsigned int uiColour, SDL_Surface* pTarget) { if ( pTarget == NULL ) pTarget = m_pActualScreen; if ( iX2 < iX1 ) Swap( iX1, iX2 ); if ( iY2 < iY1 ) Swap( iY1, iY2 ); if ( iX4 < iX3 ) Swap( iX3, iX4 ); if ( iY4 < iY3 ) Swap( iY3, iY4 ); double fCentreX1 = ((double)(iX2+iX1))/2.0; double fCentreY1 = ((double)(iY2+iY1))/2.0; double fXFactor1 = (double)((iX2-iX1) * (iX2-iX1))/4.0; double fYFactor1 = (double)((iY2-iY1) * (iY2-iY1))/4.0; double fCentreX2 = ((double)(iX4+iX3))/2.0; double fCentreY2 = ((double)(iY4+iY3))/2.0; double fXFactor2 = (double)((iX4-iX3) * (iX4-iX3))/4.0; double fYFactor2 = (double)((iY4-iY3) * (iY4-iY3))/4.0; double fDist1, fDist2; for ( int iX = iX1 ; iX <= iX2 ; iX++ ) for ( int iY = iY1 ; iY <= iY2 ; iY++ ) { fDist1 = ((double)iX - fCentreX1) * ((double)iX - fCentreX1)/fXFactor1 + ((double)iY - fCentreY1) * ((double)iY - fCentreY1)/fYFactor1; fDist2 = ((double)iX - fCentreX2) * ((double)iX - fCentreX2)/fXFactor2 + ((double)iY - fCentreY2) * ((double)iY - fCentreY2)/fYFactor2; if ( ( fDist1 <= 1.0 ) && ( fDist2 >= 1.0 ) ) SafeSetPixel( iX, iY, uiColour, pTarget ); } } // Draw a line on the specified surface void BaseEngine::DrawLine(double fX1, double fY1, double fX2, double fY2, unsigned int uiColour, SDL_Surface* pTarget) { if ( pTarget == NULL ) pTarget = m_pActualScreen; int iX1 = (int)(fX1+0.5); int iX2 = (int)(fX2+0.5); int iY1 = (int)(fY1+0.5); int iY2 = (int)(fY2+0.5); int iSteps = (iX2-iX1); if ( iSteps < 0 ) iSteps = -iSteps; if ( iY2 > iY1 ) iSteps += (iY2-iY1); else iSteps += (iY1-iY2); iSteps+=2; double fXStep = ((double)(fX2-fX1))/iSteps; double fYStep = ((double)(fY2-fY1))/iSteps; for ( int i = 0 ; i <= iSteps ; i++ ) { SafeSetPixel( (int)(0.5 + fX1 + fXStep*i), (int)(0.5 + fY1 + fYStep*i), uiColour, pTarget ); } } // Draw a thick line on the specified surface void BaseEngine::DrawThickLine( double fX1, double fY1, double fX2, double fY2, unsigned int uiColour, int iThickness, SDL_Surface* pTarget) { if ( pTarget == NULL ) pTarget = m_pActualScreen; if ( iThickness < 2 ) { // Go to the quicker draw function DrawLine(fX1, fY1, fX2, fY2, uiColour, pTarget); return; } double fAngle1 = GetAngle( fX1, fY1, fX2, fY2 ); double fAngle1a = fAngle1 - ((5 * M_PI) / 4.0); double fAngle1b = fAngle1 + ((5 * M_PI) / 4.0); double fRectX1 = fX1 + iThickness * cos(fAngle1a) * 0.5; double fRectY1 = fY1 + iThickness * sin(fAngle1a) * 0.5; double fRectX2 = fX1 + iThickness * cos(fAngle1b) * 0.5; double fRectY2 = fY1 + iThickness * sin(fAngle1b) * 0.5; double fAngle2 = fAngle1 + M_PI; double fAngle2a = fAngle2 - ((5 * M_PI) / 4.0); double fAngle2b = fAngle2 + ((5 * M_PI) / 4.0); double fRectX3 = fX2 + iThickness * cos(fAngle2a) * 0.5; double fRectY3 = fY2 + iThickness * sin(fAngle2a) * 0.5; double fRectX4 = fX2 + iThickness * cos(fAngle2b) * 0.5; double fRectY4 = fY2 + iThickness * sin(fAngle2b) * 0.5; DrawTriangle( fRectX1, fRectY1, fRectX2, fRectY2, fRectX3, fRectY3, uiColour, pTarget ); DrawTriangle( fRectX3, fRectY3, fRectX4, fRectY4, fRectX1, fRectY1, uiColour, pTarget ); } // Draw a polygon on the specified surface void BaseEngine::DrawPolygon( int iPoints, double* pXArray, double* pYArray, unsigned int uiColour, SDL_Surface* pTarget) { if ( pTarget == NULL ) pTarget = m_pActualScreen; if ( iPoints == 1 ) { SafeSetPixel( pXArray[0], pYArray[0], uiColour, pTarget ); return; } if ( iPoints == 2 ) { DrawLine( pXArray[0], pYArray[0], pXArray[1], pYArray[1], uiColour, pTarget ); return; } /* if ( iPoints == 3 ) { printf( "Draw triangle for points 0, 1, 2 of %d available\n", iPoints ); DrawTriangle( pXArray[0], pYArray[0], pXArray[1], pYArray[1], pXArray[2], pYArray[2], uiColour, pTarget ); return; } */ // Otherwise attempt to eliminate a point by filling the polygon, then call this again double fXCentre, fYCentre; //fX1, fX2, fX3, fY1, fY2, fY3; int i2, i3; double fAngle1, fAngle2, fAngle3; for ( int i1 = 0 ; i1 < iPoints ; i1++ ) { i2 = i1 + 1; if ( i2 >= iPoints ) i2 -= iPoints; i3 = i1 + 2; if ( i3 >= iPoints ) i3 -= iPoints; fXCentre = (pXArray[i1] + pXArray[i2] + pXArray[i3]) / 3.0; fYCentre = (pYArray[i1] + pYArray[i2] + pYArray[i3]) / 3.0; fAngle1 = GetAngle( fXCentre, fYCentre, pXArray[i1], pYArray[i1] ); fAngle2 = GetAngle( fXCentre, fYCentre, pXArray[i2], pYArray[i2] ); fAngle3 = GetAngle( fXCentre, fYCentre, pXArray[i3], pYArray[i3] ); // Now work out the relative angle positions and make sure all are positive fAngle2 -= fAngle1; if ( fAngle2 < 0 ) fAngle2 += 2*M_PI; fAngle3 -= fAngle1; if ( fAngle3 < 0 ) fAngle3 += 2*M_PI; if ( fAngle2 < fAngle3 ) { // Then points are in clockwise order so central one can be eliminated as long as we don't // fill an area that we shouldn't bool bPointIsWithinTriangle = false; if ( iPoints > 3 ) { // Need to check that there isn't a point within the area - for convex shapes double fLineAngle12 = GetAngle( pXArray[i1], pYArray[i1], pXArray[i2], pYArray[i2] ); if ( fLineAngle12 < 0 ) fLineAngle12 += M_PI * 2.0; double fLineAngle23 = GetAngle( pXArray[i2], pYArray[i2], pXArray[i3], pYArray[i3] ); if ( fLineAngle23 < 0 ) fLineAngle23 += M_PI * 2.0; double fLineAngle31 = GetAngle( pXArray[i3], pYArray[i3], pXArray[i1], pYArray[i1] ); if ( fLineAngle31 < 0 ) fLineAngle31 += M_PI * 2.0; for ( int i = i3+1 ; i != i1 ; i++ ) { if ( i >= iPoints ) { i = 0; if ( i1 == 0 ) break; // From the for loop - finished } // Otherwise we need to work out whether point i is to right of line i3 to i1 double fPointAngle1 = GetAngle( pXArray[i1], pYArray[i1], pXArray[i], pYArray[i] ); if ( fPointAngle1 < 0 ) fPointAngle1 += M_PI * 2.0; fPointAngle1 -= fLineAngle12; if ( fPointAngle1 < 0 ) fPointAngle1 += M_PI * 2.0; double fPointAngle2 = GetAngle( pXArray[i2], pYArray[i2], pXArray[i], pYArray[i] ); if ( fPointAngle2 < 0 ) fPointAngle2 += M_PI * 2.0; fPointAngle2 -= fLineAngle23; if ( fPointAngle2 < 0 ) fPointAngle2 += M_PI * 2.0; double fPointAngle3 = GetAngle( pXArray[i3], pYArray[i3], pXArray[i], pYArray[i] ); if ( fPointAngle3 < 0 ) fPointAngle3 += M_PI * 2.0; fPointAngle3 -= fLineAngle31; if ( fPointAngle3 < 0 ) fPointAngle3 += M_PI * 2.0; if ( ( fPointAngle1 < M_PI ) && ( fPointAngle2 < M_PI ) && ( fPointAngle3 < M_PI ) ) bPointIsWithinTriangle = true; } } if ( !bPointIsWithinTriangle ) {// If not then try the next position printf( "Draw for points %d, %d, %d of %d available\n", i1, i2, i3, iPoints ); DrawTriangle( pXArray[i1], pYArray[i1], pXArray[i2], pYArray[i2], pXArray[i3], pYArray[i3], /*GetColour(iPoints)*/uiColour, pTarget ); // Remove the point i2 and then recurse for ( int i = i2 ; i < (iPoints-1) ; i++ ) { printf( "\tCopy point %d to %d\n", i+1, i ); pXArray[i] = pXArray[i+1]; pYArray[i] = pYArray[i+1]; } if ( iPoints > 3 ) DrawPolygon( iPoints - 1, pXArray, pYArray, uiColour, pTarget ); return; // Done } } } }
bool texture_class::load_spritesheet(std::string file_name, int index_number, int w, int h) { texture_class::ref_number = index_number; texture_class::width = w; texture_class::height = h; int frames_x; int frames_y; int frame_number = 0; int num_sprites = 0; SDL_Surface *sprite_sheet = NULL; SDL_Surface *temp_surface = NULL; int flags = 0; GLenum texture_format; GLint number_of_colors; bool return_value = false; if ((sprite_sheet = IMG_Load(file_name.c_str()))) { return_value = true; frames_x = sprite_sheet->w / texture_class::width; frames_y = sprite_sheet->h / texture_class::height; num_sprites = frames_x * frames_y; texture_class::frame_max = num_sprites-1; number_of_colors = sprite_sheet->format->BytesPerPixel; if (number_of_colors == 4) { if (sprite_sheet->format->Rmask == 0x000000ff) texture_format = GL_RGBA; else texture_format = GL_BGRA; } else if (number_of_colors == 3) { if (sprite_sheet->format->Rmask == 0x000000ff) texture_format = GL_RGB; else texture_format = GL_BGR; } temp_surface = SDL_CreateRGBSurface(flags,texture_class::width-1,texture_class::height-1,sprite_sheet->format->BitsPerPixel,sprite_sheet->format->Rmask,sprite_sheet->format->Gmask,sprite_sheet->format->Bmask,sprite_sheet->format->Amask); int32_t *in_pixels = (int32_t*)sprite_sheet->pixels; int32_t *out_pixels = (int32_t*)temp_surface->pixels; for (int current_sprite = 0; current_sprite < num_sprites; current_sprite++) { int out_pixel_count = 0; if(SDL_MUSTLOCK(sprite_sheet)) SDL_LockSurface(sprite_sheet); for(int y_count = 0; y_count < texture_class::height-1; y_count++) { for(int x_count = 0; x_count < texture_class::width-1; x_count++) { out_pixels[out_pixel_count] = in_pixels[((sprite_sheet->w*y_count)+(((current_sprite)*(texture_class::width))+x_count))]; out_pixel_count++; } } if(SDL_MUSTLOCK(sprite_sheet)) SDL_UnlockSurface(sprite_sheet); texture_class::frame[frame_number].active = true; glGenTextures( 1, &texture_class::frame[frame_number].data); glBindTexture( GL_TEXTURE_2D, texture_class::frame[frame_number].data); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); glTexImage2D( GL_TEXTURE_2D, 0, number_of_colors, temp_surface->w, temp_surface->h, 0, texture_format, GL_UNSIGNED_BYTE, temp_surface->pixels ); frame_number++; } } else { return_value = false; SDL_Quit(); } if ( sprite_sheet ) SDL_FreeSurface( sprite_sheet ); if ( temp_surface ) SDL_FreeSurface( temp_surface ); return(return_value); }
/* CON_AlphaGL() -- sets the alpha channel of an SDL_Surface to the * specified value. Preconditions: the surface in question is RGBA. * 0 <= a <= 255, where 0 is transparent and 255 is opaque. */ void CON_AlphaGL(SDL_Surface *s, int alpha) { Uint8 val; int x, y, w, h; Uint32 pixel; Uint8 r, g, b, a; SDL_PixelFormat *format; static char errorPrinted = 0; /* debugging assertions -- these slow you down, but hey, crashing sucks */ if(!s) { PRINT_ERROR("NULL Surface passed to CON_AlphaGL\n"); return; } /* clamp alpha value to 0...255 */ if(alpha < SDL_ALPHA_TRANSPARENT) val = SDL_ALPHA_TRANSPARENT; else if(alpha > SDL_ALPHA_OPAQUE) val = SDL_ALPHA_OPAQUE; else val = alpha; /* loop over alpha channels of each pixel, setting them appropriately. */ w = s->w; h = s->h; format = s->format; switch (format->BytesPerPixel) { case 2: /* 16-bit surfaces don't seem to support alpha channels. */ if(!errorPrinted) { errorPrinted = 1; PRINT_ERROR("16-bit SDL surfaces do not support alpha-blending under OpenGL.\n"); } break; case 4: { /* we can do this very quickly in 32-bit mode. 24-bit is more * difficult. And since 24-bit mode is reall the same as 32-bit, * so it usually ends up taking this route too. Win! Unroll loop * and use pointer arithmetic for extra speed. */ int numpixels = h * (w << 2); Uint8 *pix = (Uint8 *) (s->pixels); Uint8 *last = pix + numpixels; Uint8 *pixel; if((numpixels & 0x7) == 0) for(pixel = pix + 3; pixel < last; pixel += 32) *pixel = *(pixel + 4) = *(pixel + 8) = *(pixel + 12) = *(pixel + 16) = *(pixel + 20) = *(pixel + 24) = *(pixel + 28) = val; else for(pixel = pix + 3; pixel < last; pixel += 4) *pixel = val; break; } default: /* we have no choice but to do this slowly. <sigh> */ for(y = 0; y < h; ++y) for(x = 0; x < w; ++x) { /* Lock the surface for direct access to the pixels */ if(SDL_MUSTLOCK(s) && SDL_LockSurface(s) < 0) { PRINT_ERROR("Can't lock surface: "); fprintf(stderr, "%s\n", SDL_GetError()); return; } pixel = DT_GetPixel(s, x, y); SDL_GetRGBA(pixel, format, &r, &g, &b, &a); pixel = SDL_MapRGBA(format, r, g, b, val); SDL_GetRGBA(pixel, format, &r, &g, &b, &a); DT_PutPixel(s, x, y, pixel); /* unlock surface again */ if(SDL_MUSTLOCK(s)) SDL_UnlockSurface(s); } break; } }
int IMG_SavePNG_RW(SDL_RWops *src, SDL_Surface *surf,int compression){ #ifdef IMPLEMENT_SAVE_PNG png_structp png_ptr; png_infop info_ptr; SDL_PixelFormat *fmt=NULL; SDL_Surface *tempsurf=NULL; int ret,funky_format; unsigned int i; #if SDL_VERSION_ATLEAST(2, 0, 0) SDL_BlendMode temp_blend; bool used_blend = false; #else Uint8 temp_alpha; bool used_alpha = false; #endif png_colorp palette; Uint8 *palette_alpha=NULL; png_byte **row_pointers=NULL; png_ptr=NULL;info_ptr=NULL;palette=NULL;ret=-1; funky_format=0; if( !src || !surf) { goto savedone; /* Nothing to do. */ } row_pointers=(png_byte **)malloc(surf->h * sizeof(png_byte*)); if (!row_pointers) { SDL_SetError("Couldn't allocate memory for rowpointers"); goto savedone; } png_ptr=png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL,NULL,NULL); if (!png_ptr){ SDL_SetError("Couldn't allocate memory for PNG file"); goto savedone; } info_ptr= png_create_info_struct(png_ptr); if (!info_ptr){ SDL_SetError("Couldn't allocate image information for PNG file"); goto savedone; } /* setup custom writer functions */ png_set_write_fn(png_ptr,(voidp)src,png_write_data,NULL); if (setjmp(png_jmpbuf(png_ptr))){ SDL_SetError("Unknown error writing PNG"); goto savedone; } if(compression>Z_BEST_COMPRESSION) compression=Z_BEST_COMPRESSION; if(compression == Z_NO_COMPRESSION) // No compression { png_set_filter(png_ptr,0,PNG_FILTER_NONE); png_set_compression_level(png_ptr,Z_NO_COMPRESSION); } else if(compression<0) // Default compression png_set_compression_level(png_ptr,Z_DEFAULT_COMPRESSION); else png_set_compression_level(png_ptr,compression); fmt=surf->format; if(fmt->BitsPerPixel==8){ /* Paletted */ png_set_IHDR(png_ptr,info_ptr, surf->w,surf->h,8,PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE,PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); palette=(png_colorp) malloc(fmt->palette->ncolors * sizeof(png_color)); if (!palette) { SDL_SetError("Couldn't create memory for palette"); goto savedone; } for (i=0;i<fmt->palette->ncolors;i++) { palette[i].red=fmt->palette->colors[i].r; palette[i].green=fmt->palette->colors[i].g; palette[i].blue=fmt->palette->colors[i].b; } png_set_PLTE(png_ptr,info_ptr,palette,fmt->palette->ncolors); #if SDL_VERSION_ATLEAST(2, 0, 0) Uint32 colorkey; if (SDL_GetColorKey(surf, &colorkey) == 0) { #else if (surf->flags&SDL_SRCCOLORKEY) { Uint32 colorkey = fmt->colorkey; #endif palette_alpha=(Uint8 *)malloc((colorkey+1)*sizeof(Uint8)); if (!palette_alpha) { SDL_SetError("Couldn't create memory for palette transparency"); goto savedone; } /* FIXME: memset? */ for (i=0;i<(colorkey+1);i++) { palette_alpha[i]=255; } palette_alpha[colorkey]=0; png_set_tRNS(png_ptr,info_ptr,palette_alpha,colorkey+1,NULL); } }else{ /* Truecolor */ if (fmt->Amask) { png_set_IHDR(png_ptr,info_ptr, surf->w,surf->h,8,PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE,PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); } else { png_set_IHDR(png_ptr,info_ptr, surf->w,surf->h,8,PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); } } png_write_info(png_ptr, info_ptr); if (fmt->BitsPerPixel==8) { /* Paletted */ for(i=0;i<surf->h;i++){ row_pointers[i]= ((png_byte*)surf->pixels) + i*surf->pitch; } if(SDL_MUSTLOCK(surf)){ SDL_LockSurface(surf); } png_write_image(png_ptr, row_pointers); if(SDL_MUSTLOCK(surf)){ SDL_UnlockSurface(surf); } }else{ /* Truecolor */ if(fmt->BytesPerPixel==3){ if(fmt->Amask){ /* check for 24 bit with alpha */ funky_format=1; }else{ /* Check for RGB/BGR/GBR/RBG/etc surfaces.*/ #if SDL_BYTEORDER == SDL_BIG_ENDIAN if(fmt->Rmask!=0xFF0000 || fmt->Gmask!=0x00FF00 || fmt->Bmask!=0x0000FF){ #else if(fmt->Rmask!=0x0000FF || fmt->Gmask!=0x00FF00 || fmt->Bmask!=0xFF0000){ #endif funky_format=1; } } }else if (fmt->BytesPerPixel==4){ if (!fmt->Amask) { /* check for 32bit but no alpha */ funky_format=1; }else{ /* Check for ARGB/ABGR/GBAR/RABG/etc surfaces.*/ #if SDL_BYTEORDER == SDL_BIG_ENDIAN if(fmt->Rmask!=0xFF000000 || fmt->Gmask!=0x00FF0000 || fmt->Bmask!=0x0000FF00 || fmt->Amask!=0x000000FF){ #else if(fmt->Rmask!=0x000000FF || fmt->Gmask!=0x0000FF00 || fmt->Bmask!=0x00FF0000 || fmt->Amask!=0xFF000000){ #endif funky_format=1; } } }else{ /* 555 or 565 16 bit color */ funky_format=1; } if (funky_format) { /* Allocate non-funky format, and copy pixeldata in*/ if(fmt->Amask){ #if SDL_VERSION_ATLEAST(2, 0, 0) tempsurf = SDL_CreateRGBSurface(0, surf->w, surf->h, 24, SURFACE_MASK_WITH_ALPHA); #else tempsurf = SDL_CreateRGBSurface(SDL_SWSURFACE, surf->w, surf->h, 24, SURFACE_MASK_WITH_ALPHA); #endif }else{ #if SDL_VERSION_ATLEAST(2, 0, 0) tempsurf = SDL_CreateRGBSurface(0, surf->w, surf->h, 24, SURFACE_MASK_WITHOUT_ALPHA); #else tempsurf = SDL_CreateRGBSurface(SDL_SWSURFACE, surf->w, surf->h, 24, SURFACE_MASK_WITHOUT_ALPHA); #endif } if(!tempsurf){ SDL_SetError("Couldn't allocate temp surface"); goto savedone; } #if SDL_VERSION_ATLEAST(2, 0, 0) if(SDL_GetSurfaceBlendMode(surf, &temp_blend) == 0){ used_blend = true; SDL_SetSurfaceBlendMode(surf, SDL_BLENDMODE_NONE); } #else if(surf->flags&SDL_SRCALPHA) { temp_alpha = fmt->alpha; used_alpha = true; SDL_SetAlpha(surf,0,255); /* Set for an opaque blit */ } #endif if(SDL_BlitSurface(surf, NULL, tempsurf, NULL)!=0){ SDL_SetError("Couldn't blit surface to temp surface"); SDL_FreeSurface(tempsurf); goto savedone; } #if SDL_VERSION_ATLEAST(2, 0, 0) if (used_blend) { SDL_SetSurfaceBlendMode(surf, temp_blend); /* Restore blend settings*/ } #else if(used_alpha) { SDL_SetAlpha(surf, SDL_SRCALPHA, (Uint8)temp_alpha); /* Restore alpha settings*/ } #endif for(i=0;i<tempsurf->h;i++){ row_pointers[i]= ((png_byte*)tempsurf->pixels) + i*tempsurf->pitch; } if(SDL_MUSTLOCK(tempsurf)){ SDL_LockSurface(tempsurf); } png_write_image(png_ptr, row_pointers); if(SDL_MUSTLOCK(tempsurf)){ SDL_UnlockSurface(tempsurf); } SDL_FreeSurface(tempsurf); } else { for(i=0;i<surf->h;i++){ row_pointers[i]= ((png_byte*)surf->pixels) + i*surf->pitch; } if(SDL_MUSTLOCK(surf)){ SDL_LockSurface(surf); } png_write_image(png_ptr, row_pointers); if(SDL_MUSTLOCK(surf)){ SDL_UnlockSurface(surf); } } } png_write_end(png_ptr, NULL); ret=0; /* got here, so nothing went wrong. YAY! */ savedone: /* clean up and return */ png_destroy_write_struct(&png_ptr,&info_ptr); if (palette) { free(palette); } if (palette_alpha) { free(palette_alpha); } if (row_pointers) { free(row_pointers); } return ret; #else return -1; #endif }
SDL_Surface *initsdl(int *w,int *h,int *bppp,Uint32 flags) { // SDL_INIT_EVENTTHREAD if( SDL_Init( SDL_INIT_VIDEO ) < 0 ) { fprintf(stderr,"Couldn't initialize SDL: %s\n",SDL_GetError()); exit( 1 ); } SDL_Surface *s; static int bpp=0; Uint32 video_flags; video_flags = flags; int rgb_size[3]={0,0,0}; printf("yoyoyo\n"); if (flags& SDL_OPENGL) { /* if ( SDL_GetVideoInfo()->vfmt->BitsPerPixel <= 8 ) { bpp = 8; } else { bpp = 16; // More doesn't seem to work }*/ bpp=SDL_GetVideoInfo()->vfmt->BitsPerPixel; switch (bpp) { case 8: rgb_size[0] = 3; rgb_size[1] = 3; rgb_size[2] = 2; break; case 15: case 16: rgb_size[0] = 5; rgb_size[1] = 5; rgb_size[2] = 5; break; default: rgb_size[0] = 8; rgb_size[1] = 8; rgb_size[2] = 8; break; } SDL_GL_SetAttribute( SDL_GL_RED_SIZE, rgb_size[0] ); SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, rgb_size[1] ); SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, rgb_size[2] ); SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 16 ); SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); } video_flags|=(SDL_RESIZABLE|SDL_ANYFORMAT|SDL_DOUBLEBUF); s= SDL_SetVideoMode( *w, *h, bpp, video_flags ); if (s == NULL ) { fprintf(stderr, "Couldn't set video mode: %s\n", SDL_GetError()); SDL_Quit(); exit(1); } #ifdef chaos printf("Screen BPP: %d\n", SDL_GetVideoSurface()->format->BitsPerPixel); printf("\n"); #ifdef GL printf( "Vendor : %s\n", glGetString( GL_VENDOR ) ); printf( "Renderer : %s\n", glGetString( GL_RENDERER ) ); printf( "Version : %s\n", glGetString( GL_VERSION ) ); printf( "Extensions : %s\n", glGetString( GL_EXTENSIONS ) ); printf("\n"); int value; SDL_GL_GetAttribute( SDL_GL_RED_SIZE, &value ); printf( "SDL_GL_RED_SIZE: requested %d, got %d\n", rgb_size[0],value); SDL_GL_GetAttribute( SDL_GL_GREEN_SIZE, &value ); printf( "SDL_GL_GREEN_SIZE: requested %d, got %d\n", rgb_size[1],value); SDL_GL_GetAttribute( SDL_GL_BLUE_SIZE, &value ); printf( "SDL_GL_BLUE_SIZE: requested %d, got %d\n", rgb_size[2],value); SDL_GL_GetAttribute( SDL_GL_DEPTH_SIZE, &value ); printf( "SDL_GL_DEPTH_SIZE: requested %d, got %d\n", bpp, value ); SDL_GL_GetAttribute( SDL_GL_DOUBLEBUFFER, &value ); printf( "SDL_GL_DOUBLEBUFFER: requested 1, got %d\n", value ); #endif #endif printf("mustlock=%i\n", SDL_MUSTLOCK(s)); const SDL_VideoInfo* m = SDL_GetVideoInfo(); *w=m->current_w; *h=m->current_h; *bppp=bpp; char * x= (char*)malloc(20); if(x&&SDL_VideoDriverName(x,20)) printf("Current SDL video driver is %s.\n",x); printf("%i x %i\n",*w,*h); return s; }
void scrunlock(void) { if(SDL_MUSTLOCK(thescreen)) SDL_UnlockSurface(thescreen); SDL_UpdateRect(thescreen, 0, 0, 0, 0); }
// Does not account for converting luminance... SDL_Surface * ILAPIENTRY ilutConvertToSDLSurface(unsigned int flags) { SDL_Surface *Bitmap; ILuint i = 0, Pad, BppPal; ILubyte *Dest; ilutCurImage = ilGetCurImage(); if (ilutCurImage == NULL) { ilSetError(ILUT_ILLEGAL_OPERATION); return NULL; } InitSDL(); // Should be IL_BGR(A). if (ilutCurImage->Format == IL_RGB || ilutCurImage->Format == IL_RGBA) { if (!isBigEndian) iluSwapColours(); } if (ilutCurImage->Origin == IL_ORIGIN_LOWER_LEFT) iluFlipImage(); if (ilutCurImage->Type > IL_UNSIGNED_BYTE) {} // Can't do anything about this right now... if (ilutCurImage->Type == IL_BYTE) {} // Can't do anything about this right now... Bitmap = SDL_CreateRGBSurface(flags,ilutCurImage->Width,ilutCurImage->Height,ilutCurImage->Bpp * 8, rmask,gmask,bmask,amask); if (Bitmap == NULL) { return IL_FALSE; } if (SDL_MUSTLOCK(Bitmap)) SDL_LockSurface(Bitmap); Pad = Bitmap->pitch - ilutCurImage->Bps; if (Pad == 0) { memcpy(Bitmap->pixels, ilutCurImage->Data, ilutCurImage->SizeOfData); } else { // Must pad the lines on some images. Dest = Bitmap->pixels; for (i = 0; i < ilutCurImage->Height; i++) { memcpy(Dest, ilutCurImage->Data + i * ilutCurImage->Bps, ilutCurImage->Bps); imemclear(Dest + ilutCurImage->Bps, Pad); Dest += Bitmap->pitch; } } if (SDL_MUSTLOCK(Bitmap)) SDL_UnlockSurface(Bitmap); if (ilutCurImage->Bpp == 1) { BppPal = ilGetBppPal(ilutCurImage->Pal.PalType); switch (ilutCurImage->Pal.PalType) { case IL_PAL_RGB24: case IL_PAL_RGB32: case IL_PAL_RGBA32: for (i = 0; i < ilutCurImage->Pal.PalSize / BppPal; i++) { (Bitmap->format)->palette->colors[i].r = ilutCurImage->Pal.Palette[i*BppPal+0]; (Bitmap->format)->palette->colors[i].g = ilutCurImage->Pal.Palette[i*BppPal+1]; (Bitmap->format)->palette->colors[i].b = ilutCurImage->Pal.Palette[i*BppPal+2]; (Bitmap->format)->palette->colors[i].unused = 255; } break; case IL_PAL_BGR24: case IL_PAL_BGR32: case IL_PAL_BGRA32: for (i = 0; i < ilutCurImage->Pal.PalSize / BppPal; i++) { (Bitmap->format)->palette->colors[i].b = ilutCurImage->Pal.Palette[i*BppPal+0]; (Bitmap->format)->palette->colors[i].g = ilutCurImage->Pal.Palette[i*BppPal+1]; (Bitmap->format)->palette->colors[i].r = ilutCurImage->Pal.Palette[i*BppPal+2]; (Bitmap->format)->palette->colors[i].unused = 255; } break; default: ilSetError(IL_INTERNAL_ERROR); // Do anything else? } } return Bitmap; }
/** ** Initialze the video part for SDL. */ global void InitVideoSdl(void) { Uint32 flags; // Initialize the SDL library if( SDL_WasInit(SDL_INIT_VIDEO) == 0 ) { if ( SDL_Init( #ifdef USE_SDLA // FIXME: doesn't work with SDL SVGAlib SDL_INIT_AUDIO | #endif #ifdef DEBUG SDL_INIT_NOPARACHUTE| #endif SDL_INIT_VIDEO|SDL_INIT_TIMER) < 0 ) { fprintf(stderr,"Couldn't initialize SDL: %s\n", SDL_GetError()); exit(1); } // Clean up on exit atexit(SDL_Quit); // Set WindowManager Title SDL_WM_SetCaption("FreeCraft","FreeCraft"); } else { if( VideoBpp == 32 && VideoDepth == 24 ) { VideoDepth = 0; } } // Initialize the display if( !VideoWidth ) { VideoWidth = DEFAULT_VIDEO_WIDTH; VideoHeight = DEFAULT_VIDEO_HEIGHT; } flags = 0; // Sam said: better for windows. /* SDL_HWSURFACE|SDL_HWPALETTE | */ if( VideoFullScreen ) { flags |= SDL_FULLSCREEN; } #ifdef USE_OPENGL flags |= SDL_OPENGL; #endif Screen = SDL_SetVideoMode(VideoWidth, VideoHeight, VideoDepth, flags); if ( Screen == NULL ) { fprintf(stderr, "Couldn't set %dx%dx%d video mode: %s\n" ,VideoWidth,VideoHeight,VideoDepth,SDL_GetError()); exit(1); } IfDebug( if( SDL_MUSTLOCK(Screen) ) { DebugLevel0Fn("Must locksurface!\n"); } );
void TCOD_sys_console_to_bitmap(void *vbitmap, int console_width, int console_height, char_t *console_buffer, char_t *prev_console_buffer) { int x,y; SDL_Surface *bitmap=(SDL_Surface *)vbitmap; Uint32 sdl_back=0,sdl_fore=0; TCOD_color_t fading_color = TCOD_console_get_fading_color(); int fade = (int)TCOD_console_get_fade(); bool track_changes=(oldFade == fade && prev_console_buffer); Uint8 bpp = charmap->format->BytesPerPixel; char_t *c=&console_buffer[0]; char_t *oc=&prev_console_buffer[0]; int hdelta; if ( bpp == 4 ) { hdelta=(charmap->pitch - TCOD_ctx.font_width*bpp)/4; } else { hdelta=(charmap->pitch - TCOD_ctx.font_width*bpp); } #ifdef USE_SDL_LOCKS if ( SDL_MUSTLOCK( bitmap ) && SDL_LockSurface( bitmap ) < 0 ) return; #endif for (y=0;y<console_height;y++) { for (x=0; x<console_width; x++) { SDL_Rect srcRect,dstRect; bool changed=true; if ( c->cf == -1 ) c->cf = TCOD_ctx.ascii_to_tcod[c->c]; if ( track_changes ) { changed=false; if ( c->dirt || ascii_updated[ c->c ] || c->back.r != oc->back.r || c->back.g != oc->back.g || c->back.b != oc->back.b || c->fore.r != oc->fore.r || c->fore.g != oc->fore.g || c->fore.b != oc->fore.b || c->c != oc->c || c->cf != oc->cf) { changed=true; } } c->dirt=0; if ( changed ) { TCOD_color_t b=c->back; dstRect.x=x*TCOD_ctx.font_width; dstRect.y=y*TCOD_ctx.font_height; dstRect.w=TCOD_ctx.font_width; dstRect.h=TCOD_ctx.font_height; /* draw background */ if ( fade != 255 ) { b.r = ((int)b.r) * fade / 255 + ((int)fading_color.r) * (255-fade)/255; b.g = ((int)b.g) * fade / 255 + ((int)fading_color.g) * (255-fade)/255; b.b = ((int)b.b) * fade / 255 + ((int)fading_color.b) * (255-fade)/255; } sdl_back=SDL_MapRGB(bitmap->format,b.r,b.g,b.b); if ( bitmap == screen && TCOD_ctx.fullscreen ) { dstRect.x+=TCOD_ctx.fullscreen_offsetx; dstRect.y+=TCOD_ctx.fullscreen_offsety; } SDL_FillRect(bitmap,&dstRect,sdl_back); if ( c->c != ' ' ) { /* draw foreground */ int ascii=c->cf; TCOD_color_t *curtext = &charcols[ascii]; bool first = first_draw[ascii]; TCOD_color_t f=c->fore; if ( fade != 255 ) { f.r = ((int)f.r) * fade / 255 + ((int)fading_color.r) * (255-fade)/255; f.g = ((int)f.g) * fade / 255 + ((int)fading_color.g) * (255-fade)/255; f.b = ((int)f.b) * fade / 255 + ((int)fading_color.b) * (255-fade)/255; } /* only draw character if foreground color != background color */ if ( ascii_updated[c->c] || f.r != b.r || f.g != b.g || f.b != b.b ) { if ( charmap->format->Amask == 0 && f.r == fontKeyCol.r && f.g == fontKeyCol.g && f.b == fontKeyCol.b ) { /* cannot draw with the key color... */ if ( f.r < 255 ) f.r++; else f.r--; } srcRect.x = (ascii%TCOD_ctx.fontNbCharHoriz)*TCOD_ctx.font_width; srcRect.y = (ascii/TCOD_ctx.fontNbCharHoriz)*TCOD_ctx.font_height; srcRect.w=TCOD_ctx.font_width; srcRect.h=TCOD_ctx.font_height; if ( charmap && (first || curtext->r != f.r || curtext->g != f.g || curtext->b!=f.b) ) { /* change the character color in the font */ first_draw[ascii]=false; sdl_fore=SDL_MapRGB(charmap->format,f.r,f.g,f.b) & rgb_mask; *curtext=f; #ifdef USE_SDL_LOCKS if ( SDL_MUSTLOCK(charmap) ) { if ( SDL_LockSurface(charmap) < 0 ) return; } #endif if ( bpp == 4 ) { /* 32 bits font : fill the whole character with color */ Uint32 *pix = (Uint32 *)(((Uint8 *)charmap->pixels)+srcRect.x*bpp + srcRect.y*charmap->pitch); int h=TCOD_ctx.font_height; while ( h-- ) { int w=TCOD_ctx.font_width; while ( w-- ) { (*pix) &= nrgb_mask; (*pix) |= sdl_fore; pix++; } pix += hdelta; } } else { /* 24 bits font : fill only non key color pixels */ Uint32 *pix = (Uint32 *)(((Uint8 *)charmap->pixels)+srcRect.x*bpp + srcRect.y*charmap->pitch); int h=TCOD_ctx.font_height; while ( h-- ) { int w=TCOD_ctx.font_width; while ( w-- ) { if (((*pix) & rgb_mask) != sdl_key ) { (*pix) &= nrgb_mask; (*pix) |= sdl_fore; } pix = (Uint32 *) (((Uint8 *)pix)+3); } pix = (Uint32 *) (((Uint8 *)pix)+hdelta); } } #ifdef USE_SDL_LOCKS if ( SDL_MUSTLOCK(charmap) ) { SDL_UnlockSurface(charmap); } #endif } SDL_BlitSurface(charmap,&srcRect,bitmap,&dstRect); } } } c++;oc++; } } #ifdef USE_SDL_LOCKS if ( SDL_MUSTLOCK( bitmap ) ) SDL_UnlockSurface( bitmap ); #endif }
/* * Função retirada dos tutoriais do LadyFoo. * ( http://lazyfoo.net/SDL_tutorials/lesson31/index.php ) */ SDL_Surface* Sprite::flipSurface(SDL_Surface *surface, int flags) { //Pointer to the soon to be flipped surface SDL_Surface *flipped = NULL; //If the image is color keyed if( surface->flags & SDL_SRCCOLORKEY ) { flipped = SDL_CreateRGBSurface( SDL_SWSURFACE, surface->w, surface->h, surface->format->BitsPerPixel, surface->format->Rmask, surface->format->Gmask, surface->format->Bmask, 0 ); } //Otherwise else { flipped = SDL_CreateRGBSurface( SDL_SWSURFACE, surface->w, surface->h, surface->format->BitsPerPixel, surface->format->Rmask, surface->format->Gmask, surface->format->Bmask, surface->format->Amask ); } //If the surface must be locked if( SDL_MUSTLOCK( surface ) ) { //Lock the surface SDL_LockSurface( surface ); } //Go through columns for( int x = 0, rx = flipped->w - 1; x < flipped->w; x++, rx-- ) { //Go through rows for( int y = 0, ry = flipped->h - 1; y < flipped->h; y++, ry-- ) { //Get pixel Uint32 pixel = get_pixel32( surface, x, y ); //Copy pixel if( ( flags & FLIP_VERTICAL ) && ( flags & FLIP_HORIZONTAL ) ) { put_pixel32( flipped, rx, ry, pixel ); } else if( flags & FLIP_HORIZONTAL ) { put_pixel32( flipped, rx, y, pixel ); } else if( flags & FLIP_VERTICAL ) { put_pixel32( flipped, x, ry, pixel ); } } } //Unlock surface if( SDL_MUSTLOCK( surface ) ) { SDL_UnlockSurface( surface ); } //Copy color key if( surface->flags & SDL_SRCCOLORKEY ) { SDL_SetColorKey( flipped, SDL_RLEACCEL | SDL_SRCCOLORKEY, surface->format->colorkey ); } //Return flipped surface return flipped; }
/** Write the specified surface to a SDL RWops data source at the requested * compression. This function writes the specified surface pixels to the RWops * as png data, where the RWops goes to shouldn't actually matter to this. * * \param dest The SDL_RWops to write the surface to. * \param surf The surface to write as a png. * \param compression The compression level to write the png at. Set to -1 to use * zlib's default compression, othewise this should be in the * range 0 (no compression) to Z_BEST_COMPRESSION (usually 9). * \return -1 on error, 0 if the png was saved successfully. */ int IMG_SavePNG_RW(SDL_RWops *dest, SDL_Surface *surf, int compression) { int isUsable; png_structp png_ptr; png_infop info_ptr; SDL_Surface *outsurf = surf; png_byte *line; int y; int start; // rw position on invoking this function, for error handling // Clamp the compression if(compression < -1) compression = -1; // Do nothing if we have no destination or surface if(!dest) { SDL_SetError("No destination RWops specified."); return -1; } if(!surf) { SDL_SetError("No surface specified."); return -1; } // Determine whether the surface is in a usable format, and if it is not // attempt to create a usable copy of it. + isUsable = get_format_usability(surf); if(isUsable == PF_UNUSABLE || isUsable == PF_UNUSABLE_ALPHA) { if(!(outsurf = make_usable_format(surf, isUsable == PF_UNUSABLE_ALPHA))) { SDL_SetError("Unable to create temporary surface."); return -1; } } // Create the png write structure we need to generate the png output if(!(png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL,NULL,NULL))) { SDL_SetError("Unable to allocate png write structure"); return -1; } // And the corresponding info structure... if(!(info_ptr = png_create_info_struct(png_ptr))) { SDL_SetError("Unable to allocate png info structure"); png_destroy_write_struct(&png_ptr, NULL); return -1; } // We need to use a custom writer, so that we can output to the RWops png_set_write_fn(png_ptr, (void *)dest, sdlrw_write_png, NULL); // Determine the current position in the RW so we can restore it on errors start = SDL_RWtell(dest); // Mark the location we want to come out if there is a fatal error if(setjmp(png_jmpbuf(png_ptr))) { // Something bad happend in libpng or the write callback, clean up and give up. png_destroy_write_struct(&png_ptr, &info_ptr); // kill the temporary surface if we created one. if(isUsable == PF_UNUSABLE || isUsable == PF_UNUSABLE_ALPHA) SDL_FreeSurface(outsurf); // Restore the position of the RWops to the location it was at when we started SDL_RWseek(dest, start, RW_SEEK_SET); SDL_SetError("PNG saving error, giving up."); return -1; } // handle compression png_set_compression_level(png_ptr, compression); // sort out the header, which might include a palette... if(isUsable == PF_PALETTE) { if(write_palette_chunk(png_ptr, info_ptr, outsurf) == -1) { png_destroy_write_struct(&png_ptr, &info_ptr); // kill the temporary surface if we created one. if(isUsable == PF_UNUSABLE || isUsable == PF_UNUSABLE_ALPHA) SDL_FreeSurface(outsurf); // Restore the position of the RWops to the location it was at when we started SDL_RWseek(dest, start, RW_SEEK_SET); return -1; } // not palettised, and with no alpha } else if(isUsable == PF_USABLE || isUsable == PF_UNUSABLE) \ { png_set_IHDR(png_ptr, info_ptr, outsurf -> w, outsurf -> h, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); } else // not palettised, with alpha { png_set_IHDR(png_ptr, info_ptr, outsurf -> w, outsurf -> h, 8, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); } // info setup done, so write it out and we can get to image data. png_write_info(png_ptr, info_ptr); // SDL does this lock/write/unlock when writing BMP so I'm fairly sure it's safe if(SDL_MUSTLOCK(outsurf)) SDL_LockSurface(outsurf); if( isUsable == PF_UNUSABLE_ALPHA ) { unsigned char* b4 = new unsigned char[ outsurf->w * outsurf->h * 4 ]; const unsigned char* bytes = (const unsigned char*)outsurf->pixels; for( unsigned int index=0; index < (unsigned int)(outsurf->w * outsurf->h); index++ ) { b4[ index*4+3] = bytes[index*4+0]; b4[ index*4+2] = bytes[index*4+1]; b4[ index*4+1] = bytes[index*4+2]; b4[ index*4+0] = bytes[index*4+3]; } // Write out the png... for( y = 0, line = (png_byte*)b4; y < outsurf->h; y++, line += outsurf->pitch) { png_write_row(png_ptr, line); } delete [] b4; } else { for( y = 0, line = (png_byte *)outsurf -> pixels; y < outsurf -> h; y++, line += outsurf -> pitch) { png_write_row(png_ptr, line); } } if(SDL_MUSTLOCK(outsurf)) SDL_UnlockSurface(outsurf); // kill the temporary surface if we created one. if(isUsable == PF_UNUSABLE || isUsable == PF_UNUSABLE_ALPHA) SDL_FreeSurface(outsurf); // All done by this point... png_write_end(png_ptr, NULL); png_destroy_write_struct(&png_ptr,&info_ptr); return 0; }
void gr_unlock_screen() { if ( !screen_locked || !screen->pixels ) return ; screen_locked = 0 ; if ( scale_resolution != -1 ) { uint8_t * src8 = screen->pixels, * dst8 = scale_screen->pixels , * pdst = scale_screen->pixels ; uint16_t * src16 = screen->pixels, * dst16 = scale_screen->pixels ; uint32_t * src32 = screen->pixels, * dst32 = scale_screen->pixels ; int h, w; switch ( scale_screen->format->BitsPerPixel ) { case 8: if ( scale_resolution_orientation == 1 || scale_resolution_orientation == 3 ) { if ( scale_resolution_aspectratio ) { for ( w = 0; w < scale_screen->w; w++ ) { if ( scale_resolution_table_w[w] != -1 ) { src8 = screen->pixels + scale_resolution_table_w[w]; for ( h = scale_screen->h - 1; h-- ; ) { if ( scale_resolution_table_h[h] != -1 ) *dst8 = src8[scale_resolution_table_h[h]]; dst8 += scale_screen->pitch ; } } dst8 = pdst += scale_screen->format->BytesPerPixel ; } } else { for ( w = 0; w < scale_screen->w; w++ ) { src8 = screen->pixels + scale_resolution_table_w[w]; for ( h = scale_screen->h - 1; h-- ; ) { *dst8 = src8[scale_resolution_table_h[h]]; dst8 += scale_screen->pitch ; } } dst8 = pdst += scale_screen->format->BytesPerPixel ; } } else { if ( scale_resolution_aspectratio ) { for ( h = 0; h < scale_screen->h; h++ ) { if ( scale_resolution_table_h[h] != -1 ) { src8 = screen->pixels + scale_resolution_table_h[h]; for ( w = 0; w < scale_screen->w; w++ ) { if ( scale_resolution_table_w[w] != -1 ) *dst8 = src8[scale_resolution_table_w[w]]; dst8++; } } dst8 = pdst += scale_screen->pitch ; } } else { for ( h = 0; h < scale_screen->h; h++ ) { src8 = screen->pixels + scale_resolution_table_h[h]; for ( w = 0; w < scale_screen->w; w++ ) { *dst8 = src8[scale_resolution_table_w[w]]; dst8++; } dst8 = pdst += scale_screen->pitch ; } } } break; case 16: if ( scale_resolution_orientation == 1 || scale_resolution_orientation == 3 ) { if ( scale_resolution_aspectratio ) { int inc = scale_screen->pitch / scale_screen->format->BytesPerPixel; for ( w = 0; w < scale_screen->w; w++ ) { if ( scale_resolution_table_w[w] != -1 ) { src16 = screen->pixels + scale_resolution_table_w[w]; for ( h = scale_screen->h - 1; h-- ; ) { if ( scale_resolution_table_h[h] != -1 ) *dst16 = src16[scale_resolution_table_h[h]]; dst16 += inc; } } dst16 = ( uint16_t * ) ( pdst += scale_screen->format->BytesPerPixel ) ; } } else { int inc = scale_screen->pitch / scale_screen->format->BytesPerPixel; for ( w = 0; w < scale_screen->w; w++ ) { src16 = screen->pixels + scale_resolution_table_w[w]; for ( h = scale_screen->h - 1; h-- ; ) { *dst16 = src16[scale_resolution_table_h[h]]; dst16 += inc; } dst16 = ( uint16_t * ) ( pdst += scale_screen->format->BytesPerPixel ) ; } } } else { if ( scale_resolution_aspectratio ) { for ( h = 0; h < scale_screen->h; h++ ) { if ( scale_resolution_table_h[h] != -1 ) { src16 = screen->pixels + scale_resolution_table_h[h]; for ( w = 0; w < scale_screen->w; w++ ) { if ( scale_resolution_table_w[w] != -1 ) *dst16 = src16[scale_resolution_table_w[w]]; dst16++; } } dst16 = ( uint16_t * ) ( pdst += scale_screen->pitch ) ; } } else { for ( h = 0; h < scale_screen->h; h++ ) { src16 = screen->pixels + scale_resolution_table_h[h]; for ( w = 0; w < scale_screen->w; w++ ) { *dst16 = src16[scale_resolution_table_w[w]]; dst16++; } dst16 = ( uint16_t * ) ( pdst += scale_screen->pitch ) ; } } } break; case 32: if ( scale_resolution_orientation == 1 || scale_resolution_orientation == 3 ) { if ( scale_resolution_aspectratio ) { int inc = scale_screen->pitch / scale_screen->format->BytesPerPixel; for ( w = 0; w < scale_screen->w; w++ ) { if ( scale_resolution_table_w[w] != -1 ) { src32 = screen->pixels + scale_resolution_table_w[w]; for ( h = scale_screen->h - 1; h-- ; ) { if ( scale_resolution_table_h[h] != -1 ) *dst32 = src32[scale_resolution_table_h[h]]; dst32 += inc; } } dst32 = ( uint32_t * ) ( pdst += scale_screen->format->BytesPerPixel ) ; } } else { int inc = scale_screen->pitch / scale_screen->format->BytesPerPixel; for ( w = 0; w < scale_screen->w; w++ ) { src32 = screen->pixels + scale_resolution_table_w[w]; for ( h = scale_screen->h - 1; h-- ; ) { *dst32 = src32[scale_resolution_table_h[h]]; dst32 += inc; } dst32 = ( uint32_t * ) ( pdst += scale_screen->format->BytesPerPixel ) ; } } } else { if ( scale_resolution_aspectratio ) { for ( h = 0; h < scale_screen->h; h++ ) { if ( scale_resolution_table_h[h] != -1 ) { src32 = screen->pixels + scale_resolution_table_h[h]; for ( w = 0; w < scale_screen->w; w++ ) { if ( scale_resolution_table_w[w] != -1 ) *dst32 = src32[scale_resolution_table_w[w]]; dst32++; } } dst32 = ( uint32_t * ) ( pdst += scale_screen->pitch ) ; } } else { for ( h = 0; h < scale_screen->h; h++ ) { src32 = screen->pixels + scale_resolution_table_h[h]; for ( w = 0; w < scale_screen->w; w++ ) { *dst32 = src32[scale_resolution_table_w[w]]; dst32++; } dst32 = ( uint32_t * ) ( pdst += scale_screen->pitch ) ; } } } break; } if ( SDL_MUSTLOCK( scale_screen ) ) SDL_UnlockSurface( scale_screen ) ; if ( waitvsync ) gr_wait_vsync(); SDL_Flip( scale_screen ) ; } else if ( enable_scale ) { GRAPH * scr; if ( scrbitmap->format->depth == 8 ) { uint8_t * original, * poriginal; uint16_t * extra, * pextra; int n = scrbitmap->height, length; if ( !scrbitmap_extra || scrbitmap_extra->width != scrbitmap->width || scrbitmap_extra->height != scrbitmap->height ) { if ( scrbitmap_extra ) bitmap_destroy( scrbitmap_extra ); scrbitmap_extra = bitmap_new( 0, scrbitmap->width, scrbitmap->height, 16 ); } poriginal = scrbitmap->data; pextra = scrbitmap_extra->data; while ( n-- ) { original = poriginal; extra = pextra; length = scrbitmap->width; while ( length-- ) *extra++ = sys_pixel_format->palette->colorequiv[ *original++ ]; poriginal += scrbitmap->pitch; pextra = ( uint16_t * )((( uint8_t * ) pextra ) + scrbitmap_extra->pitch ); } scr = scrbitmap_extra; } else { scr = scrbitmap; } /* Esto podria ir en un modulo aparte */ switch ( scale_mode ) { case SCALE_SCALE2X: scale2x( scr->data, scr->pitch, screen->pixels, screen->pitch, scr->width, scr->height ); break; case SCALE_HQ2X: hq2x( scr->data, scr->pitch, screen->pixels, screen->pitch, scr->width, scr->height ); break; case SCALE_SCANLINE2X: scanline2x( scr->data, scr->pitch, screen->pixels, screen->pitch, scr->width, scr->height ); break; case SCALE_NOFILTER: scale_normal2x( scr->data, scr->pitch, screen->pixels, screen->pitch, scr->width, scr->height ); break; case SCALE_NONE: // No usado break; } if ( SDL_MUSTLOCK( screen ) ) SDL_UnlockSurface( screen ) ; if ( waitvsync ) gr_wait_vsync(); SDL_Flip( screen ) ; } else if ( scrbitmap->info_flags & GI_EXTERNAL_DATA ) { if ( double_buffer || ( updaterects_count == 1 && updaterects[0].x == 0 && updaterects[0].y == 0 && updaterects[0].x2 == scr_width - 1 && updaterects[0].y2 == scr_height - 1 ) ) { if ( SDL_MUSTLOCK( screen ) ) SDL_UnlockSurface( screen ) ; if ( waitvsync ) gr_wait_vsync(); SDL_Flip( screen ) ; } else { if ( updaterects_count ) { int i; for ( i = 0 ; i < updaterects_count ; i++ ) { rects[ i ].x = updaterects[ i ].x; rects[ i ].y = updaterects[ i ].y; rects[ i ].w = ( updaterects[ i ].x2 - rects[ i ].x + 1 ); rects[ i ].h = ( updaterects[ i ].y2 - rects[ i ].y + 1 ); } if ( SDL_MUSTLOCK( screen ) ) SDL_UnlockSurface( screen ) ; if ( waitvsync ) gr_wait_vsync(); SDL_UpdateRects( screen, updaterects_count, rects ) ; } } } }
void Commit() { if (SDL_MUSTLOCK(mSurf)) SDL_UnlockSurface(mSurf); }
/* Overridable function, if necessary, for doing all of the drawing. Base class version checks whether a redraw is needed and does nothing if not. See Redraw() function. If a redraw is needed then there is an option to either redraw the whole screen or just redraw the moving objects. If redrawing the whole screen then: 1a) SetupBackgroundBuffer is called to draw the background to the background buffer. 1b) DrawScreen is called to copy the background buffer onto the screen, then draw the moving objects. 1c) SDL_UpdateRect() is called to actually redraw the whole screen. If only redrawing the moving objects then: 2a) DrawChangingObjects() is called to remove the objects from their old positions, and redraw them in their new positions. 2b) GetUpdateRectanglesForChangingObjects() is called to calculate where on the screen needs redrawing. 2c) SDL_UpdateRects() is called to redraw the parts of the screen which changed. */ void BaseEngine::GameRender(void) { if ( !m_bNeedsRedraw ) return; // Just drawn so no more redraw needed m_bNeedsRedraw = false; // Note: the redraw flags must only be set early in this method, not at the end, since the drawing/moving of the moving objects may // potentially flag a win/lose condition and a state change, which will set the redraw flag again to force a full draw after the // state changes. if ( m_bWholeScreenUpdate ) { // Drawn whole screen now, so no need to draw it again. See note above about the importance of not resetting this after DrawChangingObjects() m_bWholeScreenUpdate = false; // Lock surface if needed if (SDL_MUSTLOCK(m_pActualScreen)) { m_bInsideDraw = true; if (SDL_LockSurface(m_pActualScreen) < 0) return; } // Draw the screen as it should appear now. DrawScreen(); // Unlock if needed if (SDL_MUSTLOCK(m_pActualScreen)) SDL_UnlockSurface(m_pActualScreen); m_bInsideDraw = false; SDL_UpdateRect(m_pActualScreen, 0, 0, m_iScreenWidth, m_iScreenHeight); } else { // Here we assume that the background buffer has already been set up // Lock surface if needed if (SDL_MUSTLOCK(m_pActualScreen)) { m_bInsideDraw = true; if (SDL_LockSurface(m_pActualScreen) < 0) return; } // Remove objects from their old positions // Draw the text for the user // Draw objects at their new positions DrawChanges(); // Unlock if needed if (SDL_MUSTLOCK(m_pActualScreen)) SDL_UnlockSurface(m_pActualScreen); m_bInsideDraw = false; // Work out which parts of the screen need to be updated GetUpdateRectanglesForChangingObjects(); // Now actually perform the updates if ( m_iUpdateRectsInUse >= m_iMaxObjects ) { //printf( "Update whole window\n" ); //SDL_UpdateRect(m_pActualScreen, 0, 0, m_iScreenWidth, m_iScreenHeight); SDL_UpdateRect(m_pActualScreen, 0, 0, 0, 0); } else { //printf( "Update %d rectangles\n", m_iUpdateRectsInUse ); SDL_UpdateRects( m_pActualScreen, m_iUpdateRectsInUse, m_pUpdateRectangles ); } // DEBUG //printf( "%d update rectangles found\n", m_iUpdateRectsInUse ); //for ( int i = 0 ; i < m_iUpdateRectsInUse ; i++ ) // printf( "\tNumber %d : %d, %d, %d, %d\n", i, m_pUpdateRectangles[i].x, m_pUpdateRectangles[i].y, m_pUpdateRectangles[i].w, m_pUpdateRectangles[i].h ); // End of debug m_iUpdateRectsInUse = 0; } }
/* Saves an SDL surface to a png file. * TODO: support screen formats. */ int sdl_surface_savepng(SDL_Surface * surf, const char * filename) { png_bytep * rows = NULL; png_colorp pale = NULL; FILE * fout = NULL; png_structp png = NULL; png_infop info = NULL; int colortype; int i = 0; Uint8 * tran = NULL; SDL_PixelFormat * fmt = NULL; SDL_Surface * temp = NULL; if (!surf) { return save_fail("Surface was NULL."); } if (!filename) { return save_fail("Filename was NULL."); } rows = gymalloc(sizeof(png_bytep)*surf->h); if (!rows) { return save_fail("Out of memory."); } for (i = 0; i < surf->h; i++) { rows[i] = ((Uint8 *)surf->pixels) + i*surf->pitch; } /* Create palette and transparency table if needed. */ fmt = surf->format; if (fmt->palette) { pale = malloc(fmt->palette->ncolors * sizeof(png_color)); if (!pale) { savepng_done(rows, fout, png, info, temp, pale, tran); return save_fail("Out of memory in saving palette."); } for (i = 0; i < fmt->palette->ncolors; i++) { pale[i].red = fmt->palette->colors[i].r; pale[i].green = fmt->palette->colors[i].g; pale[i].blue = fmt->palette->colors[i].b; } if (surf->flags & SDL_SRCCOLORKEY) { Uint32 colorkey = 0; SDL_GetColorKey(surf, &colorkey); tran = malloc(fmt->palette->ncolors * sizeof(Uint8)); if(!tran) { savepng_done(rows, fout, png, info, temp, pale, tran); return save_fail("Out of memory in saving palette transparency."); } for (i = 0; i < fmt->palette->ncolors; i++) { tran[i] = (((unsigned)i) == colorkey) ? 255 : 0; } } } fout = fopen(filename, "wb"); if(!fout) { savepng_done(rows, fout, png, info, temp, pale, tran); return save_fail("Couldn't open file for writing."); } png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png) { savepng_done(rows, fout, png, info, temp, pale, tran); return save_fail("Couldn't create png_structp"); } info = png_create_info_struct(png); if (!info) { savepng_done(rows, fout, png, info, temp, pale, tran); return save_fail("Couldn't create png_infop"); } /* libpng rudely uses longjump to terminate on errors. This in turns causes warning of pissbli clobered variables. Could it suck more? */ if (setjmp(png->jmpbuf)) { /* This give a warning, but it seems to be unavoidable. */ savepng_done(rows, fout, png, info, temp, pale, tran); return save_fail("Error writing png file."); } /* Set file pointer. */ png_init_io(png, fout); colortype = sdl_surface_pngcolortype(surf); png_set_IHDR(png, info, surf->w, surf->h, 8, colortype, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); /* Write palette if needed. */ if(pale) { png_set_PLTE(png, info, pale, fmt->palette->ncolors); } /* Write transparency table if needed. */ if (tran) { png_set_tRNS(png, info, tran, fmt->palette->ncolors, NULL); } /* Write the image. */ png_write_info(png, info); png_set_packing(png); if(SDL_MUSTLOCK(surf)) { SDL_LockSurface(surf); } png_write_image(png, rows); if(SDL_MUSTLOCK(surf)) { SDL_UnlockSurface(surf); } png_write_end(png, info); /* Clean up. */ savepng_done(rows, fout, png, info, temp, pale, tran); return 0; }
bool CEGALatch::loadData( const std::string &path, const short episode, const int version, const unsigned char *data, const bool compresseddata ) { std::string filename; byte *RawData; Uint16 width, height; SDL_Surface *sfc; filename = getResourceFilename("egalatch.ck" + itoa(episode), path); FILE* latchfile = OpenGameFile(filename,"rb"); if(!latchfile) return false; RawData = new byte[m_latchplanesize * 4]; // get the data out of the file into the memory, decompressing it if necessary. if (compresseddata) { if (lz_decompress(latchfile, (unsigned char*) RawData)) { return 1; } } else { for(int i=0 ; i<(m_latchplanesize*4) ; i++) RawData[i] = fgetc(latchfile); } fclose(latchfile); // these are the offsets of the different video planes as // relative to each other--that is if a pixel in plane1 // is at N, the byte for that same pixel in plane3 will be // at (N + plane3). unsigned long plane1, plane2, plane3, plane4; plane1 = 0; plane2 = (m_latchplanesize * 1); plane3 = (m_latchplanesize * 2); plane4 = (m_latchplanesize * 3); // ** read the 8x8 tiles ** // set up the getbit() function of CPlanes class CPlanes Planes(RawData); Planes.setOffsets(plane1 + m_fontlocation, plane2 + m_fontlocation, plane3 + m_fontlocation, plane4 + m_fontlocation, 0); // Load these graphics into the GsFont Class of GsGraphics // The original vorticon engine only uses one fontmap, but we use another for // extra icons. For example sliders are in that map gGraphics.freeFonts(); gGraphics.createEmptyFontmaps(3); gGraphics.getFont(0).loadinternalFont(); GsFont &Font = gGraphics.getFont(1); Font.CreateSurface( gGraphics.Palette.m_Palette, SDL_SWSURFACE ); sfc = Font.getSDLSurface(); gGraphics.getFont(2).loadAlternateFont(); if(SDL_MUSTLOCK(sfc)) SDL_LockSurface(sfc); Uint8 *pixel = (Uint8*) sfc->pixels; SDL_FillRect(sfc, NULL, 0); for(int p=0;p<4;p++) Planes.readPlaneofTiles(p, pixel, 16, 8, m_fonttiles); if(SDL_MUSTLOCK(sfc)) SDL_UnlockSurface(sfc); // prepare to ** read the 16x16 tiles ** Planes.setOffsets(plane1 + m_tiles16location, plane2 + m_tiles16location, plane3 + m_tiles16location, plane4 + m_tiles16location, 0); gGraphics.freeTilemap(); gGraphics.createEmptyTilemaps(2); loadTilemap(gGraphics.getTileMap(0), Planes, episode, path); // prepare to ** read the 16x16 tiles **, this is for the second plane. Planes.setOffsets(plane1 + m_tiles16location, plane2 + m_tiles16location, plane3 + m_tiles16location, plane4 + m_tiles16location, 0); loadTilemap(gGraphics.getTileMap(1), Planes, episode, path); gGraphics.getTileMap(0).optimizeSurface(); gGraphics.getTileMap(1).optimizeSurface(); // make masked tiles according to it's surfaces applyMasks(); //////////////////// /// Load Bitmaps /// //////////////////// Planes.setOffsets(plane1 + m_bitmaplocation, plane2 + m_bitmaplocation, plane3 + m_bitmaplocation, plane4 + m_bitmaplocation, 0); // decode bitmaps into the BitmapData structure. The bitmaps are // loaded into one continuous stream of image data, with the bitmaps[] // array giving pointers to where each bitmap starts within the stream. for(int p=0 ; p<4 ; p++) { for(int b=0 ; b<m_bitmaps ; b++) { GsBitmap &bitmap = gGraphics.getBitmapFromId(b); // this points to the location that we're currently // decoding bitmap data to sfc= bitmap.getSDLSurface(); if(SDL_MUSTLOCK(sfc)) SDL_LockSurface(sfc); Uint8* pixel = (Uint8*) sfc->pixels; if(p==0) SDL_FillRect(sfc, NULL, 0); width = bitmap.getWidth(); height = bitmap.getHeight(); // Now read the raw data Planes.readPlane(p, pixel, width, height); if(SDL_MUSTLOCK(sfc)) SDL_UnlockSurface(sfc); } } std::set<std::string> filelist; FileListAdder fileListAdder; std::string gfxpath = JoinPaths(path, "gfx"); GetFileList(filelist, fileListAdder, gfxpath, false, FM_REG); FilterFilelist(filelist, "bitmap"); std::set<std::string>::iterator it = filelist.begin(); for( ; it != filelist.end() ; it++ ) { std::string filename=*it; int num = getRessourceID(filename, "bitmap"); GsBitmap &bitmap = gGraphics.getBitmapFromId(num); filename = getResourceFilename("gfx/" + filename, path, false); bitmap.loadHQBitmap(filename); } if(RawData){ delete[] RawData; RawData = NULL;} // Create an intro in case it does not exist yet std::string fullpath = getResourceFilename("preview.bmp", path, false); if( fullpath == "" ) { // Not found create it fullpath = path + "/preview.bmp"; fullpath = GetWriteFullFileName(fullpath, true); GsBitmap *pBitmap = gGraphics.getBitmapFromStr("TITLE"); SDL_SaveBMP( pBitmap->getSDLSurface(), fullpath.c_str()); } return true; }