Browse Source

Screenshotting: Use `SDL_RWops` throughout

Turns out `SDL_RWFromFP` isn't implemented in SDL for mingw.
pull/7438/head
Gleb Mazovetskiy 1 year 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 {
FILE *CaptureFile(std::string *dstPath)
SDL_RWops *CaptureFile(std::string *dstPath)
{
const char *ext =
#if DEVILUTIONX_SCREENSHOT_FORMAT == DEVILUTIONX_SCREENSHOT_FORMAT_PCX
@ -54,7 +54,7 @@ FILE *CaptureFile(std::string *dstPath)
i++;
*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;
const uint32_t startTime = SDL_GetTicks();
FILE *outStream = CaptureFile(&fileName);
SDL_RWops *outStream = CaptureFile(&fileName);
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;
}
DrawAndBlit();

20
Source/utils/surface_to_pcx.cpp

@ -15,13 +15,15 @@
namespace devilution {
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) {
const char *errorMessage = std::strerror(errno);
if (SDL_RWwrite(out, ptr, size, 1) != 1) {
const char *errorMessage = SDL_GetError();
if (errorMessage == nullptr)
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 {};
}
@ -33,7 +35,7 @@ tl::expected<void, std::string> CheckedFWrite(const void *ptr, size_t size, FILE
* @param out File stream to write to
* @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;
@ -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.
* @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];
@ -121,7 +123,7 @@ uint8_t *WritePcxLine(uint8_t *src, uint8_t *dst, int width)
* @param out File stream for the PCX file.
* @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 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
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);
if (!result.has_value()) return result;
@ -146,7 +148,7 @@ WriteSurfaceToFilePcx(const Surface &buf, FILE *outStream)
if (!result.has_value()) return result;
result = WritePcxPalette(buf.surface->format->palette->colors, outStream);
if (!result.has_value()) return result;
std::fclose(outStream);
SDL_RWclose(outStream);
return {};
}

3
Source/utils/surface_to_pcx.hpp

@ -1,6 +1,7 @@
#include <cstdio>
#include <string>
#include <SDL.h>
#include <expected.hpp>
#include "engine/surface.hpp"
@ -8,6 +9,6 @@
namespace devilution {
tl::expected<void, std::string>
WriteSurfaceToFilePcx(const Surface &buf, FILE *outStream);
WriteSurfaceToFilePcx(const Surface &buf, SDL_RWops *outStream);
} // 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);
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 (rwops == nullptr || IMG_SavePNG_RW(buf.surface, rwops, /*freedst=*/1) != 0) {
if (IMG_SavePNG_RW(buf.surface, dst, /*freedst=*/1) != 0) {
tl::expected<void, std::string> result = tl::make_unexpected(std::string(SDL_GetError()));
SDL_ClearError();
return result;

8
Source/utils/surface_to_png.hpp

@ -1,13 +1,19 @@
#include <cstdio>
#include <string>
#include <SDL.h>
#include <expected.hpp>
#include "engine/surface.hpp"
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>
WriteSurfaceToFilePng(const Surface &buf, FILE *outStream);
WriteSurfaceToFilePng(const Surface &buf, SDL_RWops *dst);
} // namespace devilution

Loading…
Cancel
Save