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

📄 surface.cpp

📁 Source code (C++) of the Amoebax game for Symbian OS UIQ3.x。
💻 CPP
字号:
//// Cross-platform free Puyo-Puyo clone.// Copyright (C) 2006, 2007 Emma's Software//// This program is free software; you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation; either version 2 of the License, or// (at your option) any later version.//// This program is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the// GNU General Public License for more details.//// You should have received a copy of the GNU General Public License// along with this program; if not, write to the Free Software// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.//#if defined (HAVE_CONFIG_H)#include <config.h>#endif // HAVE_CONFIG_H#include <assert.h>#include <math.h>#include <SDL.h>#include <SDL_image.h>#include <stdexcept>#include "Surface.h"#include "System.h"using namespace Amoebax;////// \brief Surface's default constructor.////// Makes an empty (NULL) surface.///Surface::Surface (void):    m_SDLSurface (0){}////// \brief Creates a new surface with an already loaded SDL surface.////// \param SDLSurface The SDL surface that the class will have///                   ownership of.///Surface::Surface (SDL_Surface *SDLSurface):    m_SDLSurface (SDLSurface){}////// \brief Surface's copy constructor.////// \param surface The surface to copy from.///Surface::Surface (const Surface &surface):    m_SDLSurface (0){    if ( 0 != surface.m_SDLSurface )    {        SDL_Surface *tempSDLSurface =            SDL_CreateRGBSurface (surface.m_SDLSurface->flags | SDL_SRCALPHA,                                  surface.m_SDLSurface->w,                                  surface.m_SDLSurface->h,                                  surface.m_SDLSurface->format->BitsPerPixel,                                  surface.m_SDLSurface->format->Rmask,                                  surface.m_SDLSurface->format->Gmask,                                  surface.m_SDLSurface->format->Bmask,                                  surface.m_SDLSurface->format->Amask);        if ( NULL == tempSDLSurface )        {            throw std::runtime_error (SDL_GetError ());        }        if ( SDL_BlitSurface (surface.m_SDLSurface, NULL, tempSDLSurface, NULL) < 0 )        {            throw std::runtime_error (SDL_GetError ());        }        std::swap (m_SDLSurface, tempSDLSurface);        SDL_FreeSurface (tempSDLSurface);    }}////// \brief Blits the whole surface to the left-top corner of destination.////// \param destination The distantion surface to blit this surface to.///voidSurface::blit (SDL_Surface *destination){    blit (0, 0, getWidth (), getHeight (), 0, 0, destination);}////// \brief Blits the whole surface to a position in destination.////// \param destinationX The X position where to blit the source into the///                     destination./// \param destinationY The Y position where to blit the source into the///                     destination./// \param destination The destination surface.///voidSurface::blit (uint16_t destinationX, uint16_t destinationY,              SDL_Surface *destination){    blit (0, 0, getWidth (), getHeight (), destinationX, destinationY,          destination);}////// \brief Blits a part of the surface into another surface.////// \param sourceX The X origin of the source surface to blit./// \param sourceY The X origin of the source surface to blit./// \param sourceWidth The width of the source surface part to blit./// \param sourceHeight The height of the source surface part to blit./// \param destinationX The X position where to blit the source into the///                     destination./// \param destinationY The Y position where to blit the source into the///                     destination./// \param destination The destination surface.///voidSurface::blit (uint16_t sourceX, uint16_t sourceY,               uint16_t sourceWidth, uint16_t sourceHeight,               uint16_t destinationX, uint16_t destinationY,               SDL_Surface *destination){    SDL_Rect sourceRect;    sourceRect.x = sourceX;    sourceRect.y = sourceY;    sourceRect.w = sourceWidth;    sourceRect.h = sourceHeight;    SDL_Rect destinationRect;    destinationRect.x = destinationX;    destinationRect.y = destinationY;    destinationRect.w = sourceWidth;    destinationRect.h = sourceHeight;    SDL_BlitSurface (m_SDLSurface, &sourceRect, destination, &destinationRect);    System::getInstance ().invalidateScreenRegion (&destinationRect);}////// \brief Surface's destructor.////// Frees the memory used by the image's surface.///Surface::~Surface (void){    SDL_FreeSurface (m_SDLSurface);}////// \brief Gets the height of the surface.////// \return Surface's height.///uint16_tSurface::getHeight (void) const{    return toSDLSurface ()->h;}////// \brief Gets the pixel color from a surface's position.////// \param x The x position to get the color from./// \param y The y position to get the color from./// \return The color at surface's \a x, \a y position.///uint32_tSurface::getPixel (uint16_t x, uint16_t y){    assert (x < m_SDLSurface->w && "Tried to get a color outside the surface.");    assert (y < m_SDLSurface->h && "Tried to get a color outside the surface.");    uint32_t pixelColor = 0;    SDL_LockSurface (m_SDLSurface);    switch (m_SDLSurface->format->BytesPerPixel)    {        case 1:            pixelColor = static_cast<uint32_t>(*(static_cast<uint8_t *>(m_SDLSurface->pixels) + y * m_SDLSurface->pitch + x));            break;        case 2:            pixelColor = static_cast<uint32_t>(*(static_cast<uint16_t *>(m_SDLSurface->pixels) + y * m_SDLSurface->pitch / 2 + x));            break;        case 3:            {            uint8_t *pixels = static_cast<uint8_t *>(m_SDLSurface->pixels) +                              y * m_SDLSurface->pitch +                              x * m_SDLSurface->format->BytesPerPixel;            uint8_t red = *(pixels + m_SDLSurface->format->Rshift / 8);            uint8_t green = *(pixels + m_SDLSurface->format->Gshift / 8);            uint8_t blue = *(pixels + m_SDLSurface->format->Bshift / 8);            pixelColor = SDL_MapRGB (m_SDLSurface->format, red, green, blue);            }            break;        case 4:            pixelColor = *(static_cast<uint32_t *>(m_SDLSurface->pixels) +                           y * m_SDLSurface->pitch / 4 + x);            break;    }    SDL_UnlockSurface (m_SDLSurface);    return pixelColor;}////// \brief Gets the width of the surface.////// \return Surface's width.///uint16_tSurface::getWidth (void) const{    return toSDLSurface ()->w;}////// \brief Creates a new surface from a file.////// \param fileName The file name to use to load the surface from./// \return The Surface class with the file loaded.///Surface *Surface::fromFile (std::string fileName){    SDL_Surface *loadedSurface = IMG_Load (fileName.c_str ());    if ( NULL == loadedSurface )    {        throw std::runtime_error (IMG_GetError ());    }    SDL_Surface *optimizedSurface = SDL_DisplayFormatAlpha (loadedSurface);    SDL_FreeSurface (loadedSurface);    if ( NULL == optimizedSurface )    {        throw std::runtime_error (SDL_GetError ());    }    return new Surface (optimizedSurface);}////// \brief Creates a new surface as a copy of the screen.////// \return The Surface object with a copy of the screen.///Surface *Surface::fromScreen (void){    SDL_Surface *screen = System::getInstance ().getScreenSDLSurface ();    SDL_Surface *copy =        SDL_CreateRGBSurface (SDL_SWSURFACE | SDL_SRCALPHA,                              screen->w, screen->h,                              screen->format->BitsPerPixel,                              screen->format->Rmask, screen->format->Gmask,                              screen->format->Bmask, screen->format->Amask);    if ( 0 == copy )    {        throw std::runtime_error (IMG_GetError ());    }    SDL_BlitSurface (screen, NULL, copy, NULL);    return new Surface (copy);}////// \brief Surface's assign operator.////// \param surface The surface to assign to the current surface.///Surface &Surface::operator= (const Surface &surface){    Surface tempSurface (surface);    swap (*this, tempSurface);    return *this;}////// \brief Scales the image using an scale factor.////// \param scaleFactor The scale factor to use to resize the image.///voidSurface::resize (float scaleFactor){    // In GP2X we use already scaled graphics. No need to scale them    // by software (too slow.)#if !defined (IS_GP2X_HOST)    // Can only resize 32-bit surfaces.    assert ( 0 != m_SDLSurface && "Tried to resize an unloaded surface" );    assert ( 32 == m_SDLSurface->format->BitsPerPixel &&             "Tried to resize a non 32-bit surface." );    // If the scale factor is approximaltey 1.0f, then we don't need    // to do anything!.    if ( fabs (scaleFactor - 1.0f) < 1e-3 )    {        return;    }    // Create the new scaled surface.    SDL_Surface *scaledSDLSurface =        SDL_CreateRGBSurface (m_SDLSurface->flags,                              static_cast<int>(m_SDLSurface->w * scaleFactor),                              static_cast<int>(m_SDLSurface->h * scaleFactor),                              m_SDLSurface->format->BitsPerPixel,                              m_SDLSurface->format->Rmask,                              m_SDLSurface->format->Gmask,                              m_SDLSurface->format->Bmask,                              m_SDLSurface->format->Amask);    if ( 0 == scaledSDLSurface )    {        throw std::runtime_error (SDL_GetError ());    }    // Now, for each pixel in the scaled surface, get the corresponding    // coordinate on the original surface and using a bilinear filter,    // smooth the color for the scaled pixel.    SDL_LockSurface (m_SDLSurface);    SDL_LockSurface (scaledSDLSurface);    uint32_t *scaledPixels = static_cast<uint32_t *>(scaledSDLSurface->pixels);    uint32_t *originalPixels = static_cast<uint32_t *>(m_SDLSurface->pixels);    int scaledPitch = scaledSDLSurface->pitch / sizeof (uint32_t);    int originalPitch = m_SDLSurface->pitch / sizeof (uint32_t);    for ( int scaledY = 0 ; scaledY < scaledSDLSurface->h ; ++scaledY )    {        float originalY = scaledY / scaleFactor;        int destinationY = static_cast<int>(floorf (originalY));        float yRatio = originalY - destinationY;        float yOpposite = 1 - yRatio;        uint32_t *currentScaledPixel = scaledPixels + scaledY * scaledPitch;        for ( int scaledX = 0 ; scaledX < scaledSDLSurface->w ; ++scaledX )        {            float scaledAlpha = 0.0f;            float scaledBlue = 0.0f;            float scaledGreen = 0.0f;            float scaledRed = 0.0f;            float originalX = scaledX / scaleFactor;            int destinationX = static_cast<int>(floorf (originalX));            float xRatio = originalX - destinationX;            float xOpposite = 1 - xRatio;            uint8_t originalAlpha = 0;            uint8_t originalBlue = 0;            uint8_t originalGreen = 0;            uint8_t originalRed = 0;            // Left-top pixel.            SDL_GetRGBA (originalPixels[destinationY * originalPitch + destinationX],                         m_SDLSurface->format,                         &originalRed, &originalGreen, &originalBlue,                         &originalAlpha);            scaledAlpha += originalAlpha * xOpposite * yOpposite;            scaledBlue += originalBlue * xOpposite * yOpposite;            scaledGreen += originalGreen * xOpposite * yOpposite;            scaledRed += originalRed * xOpposite * yOpposite;            // Right-top pixel.            SDL_GetRGBA (originalPixels[destinationY * originalPitch + destinationX + 1],                         m_SDLSurface->format,                         &originalRed, &originalGreen, &originalBlue,                         &originalAlpha);            scaledAlpha += originalAlpha * xRatio * yOpposite;            scaledBlue += originalBlue * xRatio * yOpposite;            scaledGreen += originalGreen * xRatio * yOpposite;            scaledRed += originalRed * xRatio * yOpposite;            // Left-bottom pixel.            SDL_GetRGBA (originalPixels[(destinationY + 1) * originalPitch + destinationX],                         m_SDLSurface->format,                         &originalRed, &originalGreen, &originalBlue,                         &originalAlpha);            scaledAlpha += originalAlpha * xOpposite * yRatio;            scaledBlue += originalBlue * xOpposite * yRatio;            scaledGreen += originalGreen * xOpposite * yRatio;            scaledRed += originalRed * xOpposite * yRatio;            // Right-bottom pixel.            SDL_GetRGBA (originalPixels[(destinationY + 1) * originalPitch + destinationX + 1],                         m_SDLSurface->format,                         &originalRed, &originalGreen, &originalBlue,                         &originalAlpha);            scaledAlpha += originalAlpha * xRatio * yRatio;            scaledBlue += originalBlue * xRatio * yRatio;            scaledGreen += originalGreen * xRatio * yRatio;            scaledRed += originalRed * xRatio * yRatio;            *currentScaledPixel =                SDL_MapRGBA (scaledSDLSurface->format,                             static_cast<uint8_t>(scaledRed),                             static_cast<uint8_t>(scaledGreen),                             static_cast<uint8_t>(scaledBlue),                             static_cast<uint8_t>(scaledAlpha));            currentScaledPixel++;        }    }    SDL_UnlockSurface (scaledSDLSurface);    SDL_UnlockSurface (m_SDLSurface);    // Done. Swap the surfaces and free the original surface.    std::swap (m_SDLSurface, scaledSDLSurface);    SDL_FreeSurface (scaledSDLSurface);#endif // !IS_GP2X_HOST}////// \brief Sets the alpha value.////// \param alpha The alpha value to set to the surface.///voidSurface::setAlpha (uint8_t alpha){    SDL_SetAlpha (toSDLSurface (), SDL_SRCALPHA, alpha);}////// \brief Sets the transparent color.////// \param colorKey The color that will be transparent while blitting.///voidSurface::setColorKey (uint32_t colorKey){    SDL_SetColorKey (m_SDLSurface, SDL_SRCCOLORKEY, colorKey);}////// \brief Swaps two surfaces.////// \param lhs The left hand side surface of the swap operation./// \param rhs The right hand side surface of the swap operation.///voidSurface::swap (Surface &lhs, Surface &rhs){    std::swap (lhs.m_SDLSurface, rhs.m_SDLSurface);}

⌨️ 快捷键说明

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