Browse Source

Screenshotting: Use `SDL_RWops` throughout

Turns out `SDL_RWFromFP` isn't implemented in SDL for mingw.
pull/7438/head
Gleb Mazovetskiy 2 years ago committed by Anders Jenbo
parent
commit
898cb3ae3d
  1. 9
      Source/capture.cpp
  2. 20
      Source/utils/surface_to_pcx.cpp
  3. 3
      Source/utils/surface_to_pcx.hpp
  4. 5
      Source/utils/surface_to_png.cpp
  5. 8
      Source/utils/surface_to_png.hpp

9
Source/capture.cpp

@ -34,7 +34,7 @@
namespace devilution { namespace devilution {
namespace { namespace {
FILE *CaptureFile(std::string *dstPath) SDL_RWops *CaptureFile(std::string *dstPath)
{ {
const char *ext = const char *ext =
#if DEVILUTIONX_SCREENSHOT_FORMAT == DEVILUTIONX_SCREENSHOT_FORMAT_PCX #if DEVILUTIONX_SCREENSHOT_FORMAT == DEVILUTIONX_SCREENSHOT_FORMAT_PCX
@ -54,7 +54,7 @@ FILE *CaptureFile(std::string *dstPath)
i++; i++;
*dstPath = StrCat(paths::PrefPath(), filename, "-", i, ext); *dstPath = StrCat(paths::PrefPath(), filename, "-", i, ext);
} }
return OpenFile(dstPath->c_str(), "wb"); return SDL_RWFromFile(dstPath->c_str(), "wb");
} }
/** /**
@ -79,9 +79,10 @@ void CaptureScreen()
std::string fileName; std::string fileName;
const uint32_t startTime = SDL_GetTicks(); const uint32_t startTime = SDL_GetTicks();
FILE *outStream = CaptureFile(&fileName); SDL_RWops *outStream = CaptureFile(&fileName);
if (outStream == nullptr) { if (outStream == nullptr) {
LogError("Failed to open {} for writing: {}", fileName, std::strerror(errno)); LogError("Failed to open {} for writing: {}", fileName, SDL_GetError());
SDL_ClearError();
return; return;
} }
DrawAndBlit(); DrawAndBlit();

20
Source/utils/surface_to_pcx.cpp

@ -15,13 +15,15 @@
namespace devilution { namespace devilution {
namespace { namespace {
tl::expected<void, std::string> CheckedFWrite(const void *ptr, size_t size, FILE *out) tl::expected<void, std::string> CheckedFWrite(const void *ptr, size_t size, SDL_RWops *out)
{ {
if (std::fwrite(ptr, size, 1, out) != 1) { if (SDL_RWwrite(out, ptr, size, 1) != 1) {
const char *errorMessage = std::strerror(errno); const char *errorMessage = SDL_GetError();
if (errorMessage == nullptr) if (errorMessage == nullptr)
errorMessage = ""; errorMessage = "";
return tl::make_unexpected(std::string("fwrite failed with: ").append(errorMessage)); tl::expected<void, std::string> result = tl::make_unexpected(std::string("write failed with: ").append(errorMessage));
SDL_ClearError();
return result;
} }
return {}; return {};
} }
@ -33,7 +35,7 @@ tl::expected<void, std::string> CheckedFWrite(const void *ptr, size_t size, FILE
* @param out File stream to write to * @param out File stream to write to
* @return True on success * @return True on success
*/ */
tl::expected<void, std::string> WritePcxHeader(int16_t width, int16_t height, FILE *out) tl::expected<void, std::string> WritePcxHeader(int16_t width, int16_t height, SDL_RWops *out)
{ {
PCXHeader buffer; PCXHeader buffer;
@ -58,7 +60,7 @@ tl::expected<void, std::string> WritePcxHeader(int16_t width, int16_t height, FI
* @param out File stream for the PCX file. * @param out File stream for the PCX file.
* @return True if successful, else false * @return True if successful, else false
*/ */
tl::expected<void, std::string> WritePcxPalette(SDL_Color *palette, FILE *out) tl::expected<void, std::string> WritePcxPalette(SDL_Color *palette, SDL_RWops *out)
{ {
uint8_t pcxPalette[1 + 256 * 3]; uint8_t pcxPalette[1 + 256 * 3];
@ -121,7 +123,7 @@ uint8_t *WritePcxLine(uint8_t *src, uint8_t *dst, int width)
* @param out File stream for the PCX file. * @param out File stream for the PCX file.
* @return True if successful, else false * @return True if successful, else false
*/ */
tl::expected<void, std::string> WritePcxPixels(const Surface &buf, FILE *out) tl::expected<void, std::string> WritePcxPixels(const Surface &buf, SDL_RWops *out)
{ {
const int width = buf.w(); const int width = buf.w();
const std::unique_ptr<uint8_t[]> pBuffer { new uint8_t[static_cast<size_t>(2 * width)] }; const std::unique_ptr<uint8_t[]> pBuffer { new uint8_t[static_cast<size_t>(2 * width)] };
@ -138,7 +140,7 @@ tl::expected<void, std::string> WritePcxPixels(const Surface &buf, FILE *out)
} // namespace } // namespace
tl::expected<void, std::string> tl::expected<void, std::string>
WriteSurfaceToFilePcx(const Surface &buf, FILE *outStream) WriteSurfaceToFilePcx(const Surface &buf, SDL_RWops *outStream)
{ {
tl::expected<void, std::string> result = WritePcxHeader(buf.w(), buf.h(), outStream); tl::expected<void, std::string> result = WritePcxHeader(buf.w(), buf.h(), outStream);
if (!result.has_value()) return result; if (!result.has_value()) return result;
@ -146,7 +148,7 @@ WriteSurfaceToFilePcx(const Surface &buf, FILE *outStream)
if (!result.has_value()) return result; if (!result.has_value()) return result;
result = WritePcxPalette(buf.surface->format->palette->colors, outStream); result = WritePcxPalette(buf.surface->format->palette->colors, outStream);
if (!result.has_value()) return result; if (!result.has_value()) return result;
std::fclose(outStream); SDL_RWclose(outStream);
return {}; return {};
} }

3
Source/utils/surface_to_pcx.hpp

@ -1,6 +1,7 @@
#include <cstdio> #include <cstdio>
#include <string> #include <string>
#include <SDL.h>
#include <expected.hpp> #include <expected.hpp>
#include "engine/surface.hpp" #include "engine/surface.hpp"
@ -8,6 +9,6 @@
namespace devilution { namespace devilution {
tl::expected<void, std::string> tl::expected<void, std::string>
WriteSurfaceToFilePcx(const Surface &buf, FILE *outStream); WriteSurfaceToFilePcx(const Surface &buf, SDL_RWops *outStream);
} // namespace devilution } // namespace devilution

5
Source/utils/surface_to_png.cpp

@ -13,10 +13,9 @@ namespace devilution {
extern "C" int IMG_SavePNG_RW(SDL_Surface *surface, SDL_RWops *dst, int freedst); extern "C" int IMG_SavePNG_RW(SDL_Surface *surface, SDL_RWops *dst, int freedst);
tl::expected<void, std::string> tl::expected<void, std::string>
WriteSurfaceToFilePng(const Surface &buf, FILE *outStream) WriteSurfaceToFilePng(const Surface &buf, SDL_RWops *dst)
{ {
SDL_RWops *rwops = SDL_RWFromFP(outStream, /*autoclose=*/SDL_TRUE); if (IMG_SavePNG_RW(buf.surface, dst, /*freedst=*/1) != 0) {
if (rwops == nullptr || IMG_SavePNG_RW(buf.surface, rwops, /*freedst=*/1) != 0) {
tl::expected<void, std::string> result = tl::make_unexpected(std::string(SDL_GetError())); tl::expected<void, std::string> result = tl::make_unexpected(std::string(SDL_GetError()));
SDL_ClearError(); SDL_ClearError();
return result; return result;

8
Source/utils/surface_to_png.hpp

@ -1,13 +1,19 @@
#include <cstdio> #include <cstdio>
#include <string> #include <string>
#include <SDL.h>
#include <expected.hpp> #include <expected.hpp>
#include "engine/surface.hpp" #include "engine/surface.hpp"
namespace devilution { namespace devilution {
/**
* @brief Writes the given surface to `dst` as PNG.
*
* Takes ownership of `dst` and closes it when done.
*/
tl::expected<void, std::string> tl::expected<void, std::string>
WriteSurfaceToFilePng(const Surface &buf, FILE *outStream); WriteSurfaceToFilePng(const Surface &buf, SDL_RWops *dst);
} // namespace devilution } // namespace devilution

Loading…
Cancel
Save