summaryrefslogtreecommitdiff
path: root/src/pixmap.cxx
diff options
context:
space:
mode:
authorDidier Raboud <odyx@debian.org>2018-09-03 11:59:50 +0200
committerDidier Raboud <odyx@debian.org>2018-09-03 11:59:51 +0200
commit0746f34c6e48754d38aabdce3b460879883d763c (patch)
treed66d0aa4255245b2c4d049a3638e34ddde544f74 /src/pixmap.cxx
parent80a66c7579d94ce69f1131c3b0a3400942ac64df (diff)
parent2fa678976470651279e8b5b3b3f21d5b094332c7 (diff)
merge patched-debian/master into debian/master
Diffstat (limited to 'src/pixmap.cxx')
-rw-r--r--src/pixmap.cxx318
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 ();
+}