diff options
author | Didier Raboud <odyx@debian.org> | 2018-09-03 11:59:50 +0200 |
---|---|---|
committer | Didier Raboud <odyx@debian.org> | 2018-09-03 11:59:51 +0200 |
commit | 0746f34c6e48754d38aabdce3b460879883d763c (patch) | |
tree | d66d0aa4255245b2c4d049a3638e34ddde544f74 /src/pixmap.cxx | |
parent | 80a66c7579d94ce69f1131c3b0a3400942ac64df (diff) | |
parent | 2fa678976470651279e8b5b3b3f21d5b094332c7 (diff) |
merge patched-debian/master into debian/master
Diffstat (limited to 'src/pixmap.cxx')
-rw-r--r-- | src/pixmap.cxx | 318 |
1 files changed, 269 insertions, 49 deletions
diff --git a/src/pixmap.cxx b/src/pixmap.cxx index d23181c..0fcf6d2 100644 --- a/src/pixmap.cxx +++ b/src/pixmap.cxx @@ -1,7 +1,7 @@ /* * This file is part of the planetblupi source code * Copyright (C) 1997, Daniel Roux & EPSITEC SA - * Copyright (C) 2017, Mathieu Schroeter + * Copyright (C) 2017-2018, Mathieu Schroeter * http://epsitec.ch; http://www.blupi.org; http://github.com/blupi-games * * This program is free software: you can redistribute it and/or modify @@ -29,10 +29,11 @@ #include <unistd.h> #endif /* !_WIN32 */ -#include <SDL2/SDL_image.h> +#include <SDL_image.h> #include "blupi.h" #include "def.h" +#include "event.h" #include "misc.h" #include "pixmap.h" @@ -40,7 +41,7 @@ // Constructeur. -CPixmap::CPixmap () +CPixmap::CPixmap (CEvent * event) { Sint32 i; @@ -56,6 +57,8 @@ CPixmap::CPixmap () m_lpSDLCursors[i] = nullptr; m_lpCurrentCursor = nullptr; + this->mainTexture = nullptr; + this->event = event; } // Destructeur. @@ -83,6 +86,9 @@ CPixmap::~CPixmap () if (m_lpSDLBlupi) SDL_FreeSurface (m_lpSDLBlupi); + + if (this->mainTexture) + SDL_DestroyTexture (this->mainTexture); } // Cr�e l'objet DirectDraw principal. @@ -101,13 +107,81 @@ CPixmap::Create (Point dim) return true; } +void +CPixmap::CreateMainTexture () +{ + if (!this->mainTexture) + return; + + SDL_DestroyTexture (this->mainTexture); + SDL_SetHint ( + SDL_HINT_RENDER_SCALE_QUALITY, + g_bFullScreen && g_renderQuality ? "best" : "nearest"); + this->mainTexture = SDL_CreateTexture ( + g_renderer, SDL_PIXELFORMAT_RGBA32, SDL_TEXTUREACCESS_TARGET, LXIMAGE (), + LYIMAGE ()); + SDL_SetHint (SDL_HINT_RENDER_SCALE_QUALITY, "nearest"); +} + +Sint32 +CPixmap::BltFast (Sint32 dstCh, size_t srcCh, Rect dstR, Rect srcR) +{ + Sint32 res; + + SDL_Rect srcRect, dstRect; + srcRect.x = srcR.left; + srcRect.y = srcR.top; + srcRect.w = srcR.right - srcR.left; + srcRect.h = srcR.bottom - srcR.top; + dstRect.x = dstR.left; + dstRect.y = dstR.top; + dstRect.w = dstR.right - dstR.left; + dstRect.h = dstR.bottom - dstR.top; + + auto target = SDL_GetRenderTarget (g_renderer); + + if (dstCh < 0) + { + if (!this->mainTexture && g_bFullScreen && g_zoom == 1) + { + SDL_SetHint ( + SDL_HINT_RENDER_SCALE_QUALITY, g_renderQuality ? "best" : "nearest"); + this->mainTexture = SDL_CreateTexture ( + g_renderer, SDL_PIXELFORMAT_RGBA32, SDL_TEXTUREACCESS_TARGET, + LXIMAGE (), LYIMAGE ()); + SDL_SetHint (SDL_HINT_RENDER_SCALE_QUALITY, "nearest"); + } + else if (this->mainTexture && !(g_bFullScreen && g_zoom == 1)) + { + SDL_DestroyTexture (this->mainTexture); + this->mainTexture = nullptr; + } + + if (this->mainTexture) + SDL_SetRenderTarget (g_renderer, target ? target : this->mainTexture); + res = SDL_RenderCopy ( + g_renderer, m_SDLTextureInfo[srcCh].texture, &srcRect, &dstRect); + if (this->mainTexture) + SDL_SetRenderTarget (g_renderer, target); + } + else + { + SDL_SetRenderTarget (g_renderer, m_SDLTextureInfo[dstCh].texture); + res = SDL_RenderCopy ( + g_renderer, m_SDLTextureInfo[srcCh].texture, &srcRect, &dstRect); + SDL_SetRenderTarget (g_renderer, target); + } + + return res; +} + // Effectue un appel BltFast. // Les modes sont 0=transparent, 1=opaque. Sint32 CPixmap::BltFast (Sint32 chDst, size_t channel, Point dst, Rect rcRect) { - Sint32 res, limit; + Sint32 limit; // Effectue un peu de clipping. if (dst.x < m_clipRect.left) @@ -130,38 +204,12 @@ CPixmap::BltFast (Sint32 chDst, size_t channel, Point dst, Rect rcRect) if (rcRect.left >= rcRect.right || rcRect.top >= rcRect.bottom) return 0; - if (chDst < 0) - { - SDL_Rect srcRect, dstRect; - srcRect.x = rcRect.left; - srcRect.y = rcRect.top; - srcRect.w = rcRect.right - rcRect.left; - srcRect.h = rcRect.bottom - rcRect.top; - dstRect = srcRect; - dstRect.x = dst.x; - dstRect.y = dst.y; - - res = SDL_RenderCopy ( - g_renderer, m_SDLTextureInfo[channel].texture, &srcRect, &dstRect); - } - else - { - SDL_Rect srcRect, dstRect; - srcRect.x = rcRect.left; - srcRect.y = rcRect.top; - srcRect.w = rcRect.right - rcRect.left; - srcRect.h = rcRect.bottom - rcRect.top; - dstRect = srcRect; - dstRect.x = dst.x; - dstRect.y = dst.y; - - SDL_SetRenderTarget (g_renderer, m_SDLTextureInfo[chDst].texture); - res = SDL_RenderCopy ( - g_renderer, m_SDLTextureInfo[channel].texture, &srcRect, &dstRect); - SDL_SetRenderTarget (g_renderer, nullptr); - } - - return res; + Rect dstRect; + dstRect.left = dst.x; + dstRect.top = dst.y; + dstRect.right = dstRect.left + rcRect.right - rcRect.left; + dstRect.bottom = dstRect.top + rcRect.bottom - rcRect.top; + return this->BltFast (chDst, channel, dstRect, rcRect); } // Effectue un appel BltFast. @@ -207,24 +255,75 @@ CPixmap::BltFast ( bool CPixmap::ReloadTargetTextures () { + if (this->mainTexture) + { + SDL_DestroyTexture (this->mainTexture); + this->mainTexture = nullptr; + } + for (auto & tex : m_SDLTextureInfo) { if (!tex.second.target) continue; - if (!Cache ( - tex.first, tex.second.file, tex.second.dimTotal, tex.second.dimIcon)) + if (tex.second.file.empty ()) + { + if (!Cache (tex.first, tex.second.dimTotal)) + return false; + } + else if (!Cache ( + tex.first, tex.second.file, tex.second.dimTotal, + tex.second.dimIcon, Mode::FIX, tex.second.wideName)) return false; } return true; } +bool +CPixmap::Cache (size_t channel, Point totalDim) +{ + if (m_SDLTextureInfo.find (channel) == m_SDLTextureInfo.end ()) + { + m_SDLTextureInfo[channel].texture = SDL_CreateTexture ( + g_renderer, SDL_PIXELFORMAT_RGBA32, SDL_TEXTUREACCESS_TARGET, totalDim.x, + totalDim.y); + + if (!m_SDLTextureInfo[channel].texture) + { + SDL_LogError ( + SDL_LOG_CATEGORY_APPLICATION, "Couldn't create texture: %s", + SDL_GetError ()); + return false; + } + + SDL_SetTextureBlendMode ( + m_SDLTextureInfo[channel].texture, SDL_BLENDMODE_BLEND); + } + else + { + SDL_SetRenderTarget (g_renderer, m_SDLTextureInfo[channel].texture); + SDL_SetRenderDrawColor (g_renderer, 0, 0, 0, 0); + SDL_RenderClear (g_renderer); + SDL_SetRenderTarget (g_renderer, nullptr); + } + + m_SDLTextureInfo[channel].texMask = nullptr; + m_SDLTextureInfo[channel].target = true; + m_SDLTextureInfo[channel].dimIcon = Point{0, 0}; + m_SDLTextureInfo[channel].dimTotal = totalDim; + m_SDLTextureInfo[channel].file = ""; + m_SDLTextureInfo[channel].wideName = ""; + + return true; +} + // Cache une image contenant des ic�nes. bool CPixmap::Cache ( - size_t channel, const std::string & pFilename, Point totalDim, Point iconDim) + size_t channel, const std::string & pFilename, Point totalDim, Point iconDim, + Mode mode, std::string wideName) { std::string file = GetBaseDir () + pFilename; SDL_Surface * surface = IMG_Load (file.c_str ()); @@ -238,8 +337,12 @@ CPixmap::Cache ( SDL_Texture * texture = SDL_CreateTextureFromSurface (g_renderer, surface); Uint32 format; - Sint32 access, w, h; - SDL_QueryTexture (texture, &format, &access, &w, &h); + Sint32 access, ow, w, oh, h; + SDL_QueryTexture (texture, &format, &access, &ow, &oh); + + auto m = mode == EXPAND || channel == CHBACK; + w = m ? LXIMAGE () : ow; + h = m ? LYIMAGE () : oh; if (m_SDLTextureInfo.find (channel) == m_SDLTextureInfo.end ()) { @@ -254,8 +357,9 @@ CPixmap::Cache ( return false; } - SDL_SetTextureBlendMode ( - m_SDLTextureInfo[channel].texture, SDL_BLENDMODE_BLEND); + if (channel != CHBACK) + SDL_SetTextureBlendMode ( + m_SDLTextureInfo[channel].texture, SDL_BLENDMODE_BLEND); } SDL_SetRenderTarget (g_renderer, m_SDLTextureInfo[channel].texture); @@ -268,9 +372,62 @@ CPixmap::Cache ( m_SDLTextureInfo[channel].dimIcon = iconDim; m_SDLTextureInfo[channel].dimTotal = totalDim; m_SDLTextureInfo[channel].file = pFilename; + m_SDLTextureInfo[channel].wideName = wideName; SDL_SetRenderTarget (g_renderer, m_SDLTextureInfo[channel].texture); - SDL_RenderCopy (g_renderer, texture, nullptr, nullptr); + + switch (mode) + { + case FIX: + { + if (channel == CHBACK && (ow < LXIMAGE () || oh < LYIMAGE ())) + { + if (!wideName.empty ()) + { + std::string file = GetBaseDir () + m_SDLTextureInfo[channel].wideName; + SDL_Surface * surface = IMG_Load (file.c_str ()); + SDL_Texture * texture = + SDL_CreateTextureFromSurface (g_renderer, surface); + SDL_FreeSurface (surface); + SDL_RenderCopy (g_renderer, texture, nullptr, nullptr); + SDL_DestroyTexture (texture); + } + + SDL_Rect dst; + dst.x = (LXIMAGE () - ow) / 2; + dst.y = 0; + dst.w = ow; + dst.h = oh; + SDL_RenderCopy (g_renderer, texture, nullptr, &dst); + } + else + SDL_RenderCopy (g_renderer, texture, nullptr, nullptr); + break; + } + + case EXPAND: + { + SDL_Rect src, dst; + src.x = 0; + src.y = 0; + src.w = POSDRAWX - 1; + src.h = LYIMAGE (); + dst = src; + SDL_RenderCopy (g_renderer, texture, &src, &dst); + src.x = ow - 16; + src.w = 16; + dst.x = LXIMAGE () - 16; + dst.w = src.w; + SDL_RenderCopy (g_renderer, texture, &src, &dst); + src.x = POSDRAWX - 1; + src.w = ow - src.x - 16; + dst.x = src.x; + dst.w = DIMDRAWX + 1; + SDL_RenderCopy (g_renderer, texture, &src, &dst); + break; + } + } + SDL_SetRenderTarget (g_renderer, nullptr); if (!m_SDLTextureInfo[channel].texMask) @@ -318,6 +475,16 @@ CPixmap::Cache (size_t channel, SDL_Surface * surface, Point totalDim) return true; } +SDL_Texture * +CPixmap::getTexture (size_t channel) +{ + auto it = this->m_SDLTextureInfo.find (channel); + if (it == this->m_SDLTextureInfo.end ()) + return nullptr; + + return it->second.texture; +} + // Modifie la r�gion de clipping. void @@ -599,6 +766,10 @@ bool CPixmap::Display () { m_bBackDisplayed = true; + + if (this->mainTexture) + SDL_RenderCopy (g_renderer, this->mainTexture, nullptr, nullptr); + SDL_RenderPresent (g_renderer); return true; } @@ -769,23 +940,26 @@ CPixmap::GetCursorRect (MouseSprites sprite) } void -CPixmap::LoadCursors (Uint8 scale) +CPixmap::LoadCursors () { Uint32 rmask, gmask, bmask, amask; -/* SDL interprets each pixel as a 32-bit number, so our masks must depend -on the endianness (byte order) of the machine */ + /* SDL interprets each pixel as a 32-bit number, so our masks must depend + * on the endianness (byte order) of the machine + */ #if SDL_BYTEORDER == SDL_BIG_ENDIAN rmask = 0xff000000; gmask = 0x00ff0000; bmask = 0x0000ff00; amask = 0x000000ff; -#else +#else /* SDL_BYTEORDER == SDL_BIG_ENDIAN */ rmask = 0x000000ff; gmask = 0x0000ff00; bmask = 0x00ff0000; amask = 0xff000000; -#endif +#endif /* SDL_BYTEORDER != SDL_BIG_ENDIAN */ + + auto scale = this->GetDisplayScale (); for (int i = SPRITE_BEGIN; i <= SPRITE_END; ++i) { @@ -817,3 +991,49 @@ CPixmap::ChangeSprite (MouseSprites sprite) SDL_SetCursor (m_lpSDLCursors[sprite - 1]); m_lpCurrentCursor = m_lpSDLCursors[sprite - 1]; } + +double +CPixmap::GetDisplayScale () +{ + Sint32 w, h; + SDL_GetWindowSize (g_window, &w, &h); + return static_cast<double> (h / LYIMAGE ()); +} + +void +CPixmap::FromDisplayToGame (Sint32 & x, Sint32 & y, double prevScale) +{ + if (this->event->IsDemoPlaying ()) + return; + + double factor = 1; + + if (!g_bFullScreen) + factor = prevScale; + + x /= factor; + y /= factor; +} + +void +CPixmap::FromGameToDisplay (Sint32 & x, Sint32 & y) +{ + double factor = 1; + + if (!g_bFullScreen) + factor = g_zoom; + + x *= factor; + y *= factor; + + if (!g_bFullScreen) + return; + + Sint32 w, h; + SDL_GetWindowSize (g_window, &w, &h); + + double _w = w, _h = h; + + x = x * _w / LXIMAGE (); + y = y * _h / LYIMAGE (); +} |