gosu 0.12.1 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gosu/Audio.hpp +23 -25
- data/Gosu/Graphics.hpp +16 -12
- data/Gosu/Image.hpp +3 -0
- data/Gosu/Version.hpp +2 -2
- data/lib/gosu.rb +2 -2
- data/lib/gosu/compat.rb +1 -1
- data/lib/gosu/patches.rb +5 -0
- data/lib/gosu/swig_patches.rb +1 -1
- data/rdoc/gosu.rb +10 -10
- data/src/Audio.cpp +93 -228
- data/src/AudioImpl.cpp +94 -0
- data/src/AudioImpl.hpp +33 -0
- data/src/AudioToolboxFile.hpp +14 -18
- data/src/Bitmap.cpp +36 -30
- data/src/BitmapIO.cpp +14 -23
- data/src/BlockAllocator.cpp +7 -10
- data/src/BlockAllocator.hpp +2 -4
- data/src/Channel.cpp +89 -0
- data/src/Color.cpp +4 -9
- data/src/DirectoriesApple.cpp +13 -13
- data/src/DirectoriesUnix.cpp +8 -7
- data/src/DirectoriesWin.cpp +12 -11
- data/src/EmptyImageData.hpp +54 -0
- data/src/FileUnix.cpp +12 -9
- data/src/FileWin.cpp +8 -7
- data/src/Font.cpp +12 -13
- data/src/FormattedString.cpp +237 -0
- data/src/FormattedString.hpp +14 -265
- data/src/GosuViewController.cpp +2 -5
- data/src/Graphics.cpp +38 -39
- data/src/IO.cpp +11 -10
- data/src/Image.cpp +16 -9
- data/src/Input.cpp +16 -15
- data/src/InputUIKit.cpp +8 -7
- data/src/Macro.cpp +11 -11
- data/src/Math.cpp +9 -8
- data/src/RubyGosu.cxx +129 -99
- data/src/TextApple.cpp +19 -13
- data/src/TextInput.cpp +23 -22
- data/src/TextWin.cpp +17 -19
- data/src/Texture.cpp +15 -10
- data/src/Transform.cpp +13 -17
- data/src/Utility.cpp +3 -2
- data/src/UtilityApple.cpp +10 -11
- data/src/UtilityWin.cpp +2 -1
- data/src/Version.cpp +5 -4
- data/src/WinMain.cpp +3 -3
- data/src/WinUtility.cpp +7 -6
- data/src/Window.cpp +11 -10
- data/src/WindowUIKit.cpp +9 -8
- data/src/stb_image.h +782 -480
- data/src/stb_image_write.h +425 -15
- data/src/stb_vorbis.c +82 -32
- metadata +8 -4
- data/src/ALChannelManagement.hpp +0 -119
data/src/AudioImpl.cpp
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
#include "AudioImpl.hpp"
|
2
|
+
#include <stdexcept>
|
3
|
+
#include <string>
|
4
|
+
using namespace std;
|
5
|
+
|
6
|
+
// Per-platform limit for playing OpenAL sources: https://stackoverflow.com/a/3203888
|
7
|
+
#ifdef GOSU_IS_IPHONE
|
8
|
+
static const unsigned CHANNELS = 32;
|
9
|
+
#else
|
10
|
+
static const unsigned CHANNELS = 255;
|
11
|
+
#endif
|
12
|
+
|
13
|
+
static ALCdevice* _device;
|
14
|
+
static ALCcontext* _context;
|
15
|
+
static ALuint _sources[CHANNELS];
|
16
|
+
static int _tokens[CHANNELS];
|
17
|
+
|
18
|
+
void Gosu::al_initialize()
|
19
|
+
{
|
20
|
+
if (_device) return;
|
21
|
+
|
22
|
+
_device = alcOpenDevice(nullptr);
|
23
|
+
_context = alcCreateContext(_device, nullptr);
|
24
|
+
alcMakeContextCurrent(_context);
|
25
|
+
alGenSources(CHANNELS, _sources);
|
26
|
+
}
|
27
|
+
|
28
|
+
bool Gosu::al_initialized()
|
29
|
+
{
|
30
|
+
return _device != nullptr;
|
31
|
+
}
|
32
|
+
|
33
|
+
void Gosu::al_shutdown()
|
34
|
+
{
|
35
|
+
if (_device == nullptr) return;
|
36
|
+
|
37
|
+
alDeleteSources(CHANNELS, _sources);
|
38
|
+
alcMakeContextCurrent(nullptr);
|
39
|
+
alcDestroyContext(_context);
|
40
|
+
_context = nullptr;
|
41
|
+
alcCloseDevice(_device);
|
42
|
+
_device = nullptr;
|
43
|
+
}
|
44
|
+
|
45
|
+
ALCdevice* Gosu::al_device()
|
46
|
+
{
|
47
|
+
al_initialize();
|
48
|
+
|
49
|
+
return _device;
|
50
|
+
}
|
51
|
+
|
52
|
+
ALCcontext* Gosu::al_context()
|
53
|
+
{
|
54
|
+
al_initialize();
|
55
|
+
|
56
|
+
return _context;
|
57
|
+
}
|
58
|
+
|
59
|
+
Gosu::Channel Gosu::allocate_channel()
|
60
|
+
{
|
61
|
+
al_initialize();
|
62
|
+
|
63
|
+
// Start looking at index 1 to keep one free channel for songs.
|
64
|
+
for (int i = 1; i < CHANNELS; ++i) {
|
65
|
+
// Do not interrupt any playing or paused samples.
|
66
|
+
ALint state;
|
67
|
+
alGetSourcei(_sources[i], AL_SOURCE_STATE, &state);
|
68
|
+
if (state == AL_PLAYING || state == AL_PAUSED) continue;
|
69
|
+
|
70
|
+
// Increase the token to invalidate the last playing Channel with this index.
|
71
|
+
return Channel(i, ++_tokens[i]);
|
72
|
+
}
|
73
|
+
|
74
|
+
// No free channel, return an object that is immediately expired.
|
75
|
+
return Channel(NO_CHANNEL, 0);
|
76
|
+
}
|
77
|
+
|
78
|
+
bool Gosu::channel_expired(int channel, int token)
|
79
|
+
{
|
80
|
+
return channel < 0 || channel >= CHANNELS || _tokens[channel] != token;
|
81
|
+
}
|
82
|
+
|
83
|
+
ALuint Gosu::al_source_for_channel(int channel)
|
84
|
+
{
|
85
|
+
if (channel <= 0 || channel >= CHANNELS) {
|
86
|
+
throw invalid_argument("No such channel: " + to_string(channel));
|
87
|
+
}
|
88
|
+
return _sources[channel];
|
89
|
+
}
|
90
|
+
|
91
|
+
ALuint Gosu::al_source_for_songs()
|
92
|
+
{
|
93
|
+
return _sources[0];
|
94
|
+
}
|
data/src/AudioImpl.hpp
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
#pragma once
|
2
|
+
|
3
|
+
#include <Gosu/Audio.hpp>
|
4
|
+
#include <Gosu/Platform.hpp>
|
5
|
+
#ifdef GOSU_IS_MAC
|
6
|
+
#include <OpenAL/al.h>
|
7
|
+
#include <OpenAL/alc.h>
|
8
|
+
#else
|
9
|
+
#include <AL/al.h>
|
10
|
+
#include <AL/alc.h>
|
11
|
+
#endif
|
12
|
+
|
13
|
+
namespace Gosu
|
14
|
+
{
|
15
|
+
void al_initialize();
|
16
|
+
bool al_initialized();
|
17
|
+
void al_shutdown();
|
18
|
+
|
19
|
+
// Will initialize OpenAL if necessary.
|
20
|
+
ALCdevice* al_device();
|
21
|
+
// Will initialize OpenAL if necessary.
|
22
|
+
ALCcontext* al_context();
|
23
|
+
|
24
|
+
const int NO_CHANNEL = -1;
|
25
|
+
|
26
|
+
// Returns an expired Channel if no channel is free.
|
27
|
+
// Will initialize OpenAL if necessary.
|
28
|
+
Channel allocate_channel();
|
29
|
+
|
30
|
+
bool channel_expired(int channel, int token);
|
31
|
+
ALuint al_source_for_channel(int channel);
|
32
|
+
ALuint al_source_for_songs();
|
33
|
+
}
|
data/src/AudioToolboxFile.hpp
CHANGED
@@ -33,7 +33,7 @@ namespace Gosu
|
|
33
33
|
{
|
34
34
|
class AudioToolboxFile : public AudioFile
|
35
35
|
{
|
36
|
-
|
36
|
+
Buffer buffer_;
|
37
37
|
AudioFileID file_id_;
|
38
38
|
ExtAudioFileRef file_;
|
39
39
|
SInt64 position_;
|
@@ -45,10 +45,11 @@ namespace Gosu
|
|
45
45
|
bool big_endian_;
|
46
46
|
|
47
47
|
static OSStatus AudioFile_ReadProc(void* in_client_data, SInt64 in_position,
|
48
|
-
|
48
|
+
UInt32 request_count, void* buffer, UInt32* actual_count)
|
49
49
|
{
|
50
50
|
const Resource& res = *static_cast<Resource*>(in_client_data);
|
51
|
-
*actual_count = std::min<UInt32>(request_count,
|
51
|
+
*actual_count = std::min<UInt32>(request_count,
|
52
|
+
static_cast<UInt32>(res.size() - in_position));
|
52
53
|
res.read(in_position, *actual_count, buffer);
|
53
54
|
return noErr;
|
54
55
|
}
|
@@ -81,7 +82,9 @@ namespace Gosu
|
|
81
82
|
AudioStreamBasicDescription client_data = { 0 };
|
82
83
|
sample_rate_ = client_data.mSampleRate = 22050;
|
83
84
|
client_data.mFormatID = kAudioFormatLinearPCM;
|
84
|
-
client_data.mFormatFlags = kAudioFormatFlagIsSignedInteger |
|
85
|
+
client_data.mFormatFlags = kAudioFormatFlagIsSignedInteger |
|
86
|
+
kAudioFormatFlagsNativeEndian |
|
87
|
+
kAudioFormatFlagIsPacked;
|
85
88
|
client_data.mBitsPerChannel = 16;
|
86
89
|
client_data.mChannelsPerFrame = base.mChannelsPerFrame;
|
87
90
|
client_data.mFramesPerPacket = 1;
|
@@ -119,22 +122,15 @@ namespace Gosu
|
|
119
122
|
|
120
123
|
// Easy formats
|
121
124
|
format_ = 0;
|
122
|
-
if (desc.mChannelsPerFrame == 1) {
|
123
|
-
|
124
|
-
format_ = AL_FORMAT_MONO8;
|
125
|
-
else*/ if (desc.mBitsPerChannel == 16)
|
126
|
-
format_ = AL_FORMAT_MONO16;
|
125
|
+
if (desc.mChannelsPerFrame == 1 && desc.mBitsPerChannel == 16) {
|
126
|
+
format_ = AL_FORMAT_MONO16;
|
127
127
|
}
|
128
|
-
else if (desc.mChannelsPerFrame == 2) {
|
129
|
-
|
130
|
-
format_ = AL_FORMAT_STEREO8;
|
131
|
-
else */if (desc.mBitsPerChannel == 16)
|
132
|
-
format_ = AL_FORMAT_STEREO16;
|
128
|
+
else if (desc.mChannelsPerFrame == 2 && desc.mBitsPerChannel == 16) {
|
129
|
+
format_ = AL_FORMAT_STEREO16;
|
133
130
|
}
|
134
131
|
|
135
132
|
if (format_ == 0 ||
|
136
|
-
// If format not native for OpenAL, set client data format
|
137
|
-
// to enable conversion
|
133
|
+
// If format not native for OpenAL, set client data format to enable conversion
|
138
134
|
desc.mFormatFlags & kAudioFormatFlagIsBigEndian ||
|
139
135
|
desc.mFormatFlags & kAudioFormatFlagIsFloat ||
|
140
136
|
!(desc.mFormatFlags & kAudioFormatFlagIsSignedInteger)) {
|
@@ -159,7 +155,7 @@ namespace Gosu
|
|
159
155
|
init();
|
160
156
|
}
|
161
157
|
|
162
|
-
AudioToolboxFile(
|
158
|
+
AudioToolboxFile(Reader reader)
|
163
159
|
{
|
164
160
|
buffer_.resize(reader.resource().size() - reader.position());
|
165
161
|
reader.read(buffer_.data(), buffer_.size());
|
@@ -204,7 +200,7 @@ namespace Gosu
|
|
204
200
|
AudioBufferList abl;
|
205
201
|
abl.mNumberBuffers = 1;
|
206
202
|
abl.mBuffers[0].mNumberChannels = 1;
|
207
|
-
abl.mBuffers[0].mDataByteSize = length;
|
203
|
+
abl.mBuffers[0].mDataByteSize = static_cast<UInt32>(length);
|
208
204
|
abl.mBuffers[0].mData = dest;
|
209
205
|
UInt32 numFrames = 0xffffffff; // give us as many frames as possible given our buffer
|
210
206
|
CHECK_OS(ExtAudioFileRead(file_, &numFrames, &abl));
|
data/src/Bitmap.cpp
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
#include <Gosu/Bitmap.hpp>
|
2
2
|
#include <cassert>
|
3
3
|
#include <algorithm>
|
4
|
-
#include <vector>
|
4
|
+
#include <vector>
|
5
|
+
using namespace std;
|
5
6
|
|
6
7
|
void Gosu::Bitmap::swap(Bitmap& other)
|
7
8
|
{
|
@@ -26,15 +27,14 @@ void Gosu::Bitmap::insert(const Bitmap& source, int x, int y)
|
|
26
27
|
}
|
27
28
|
|
28
29
|
void Gosu::Bitmap::insert(const Bitmap& source, int x, int y, unsigned src_x, unsigned src_y,
|
29
|
-
|
30
|
+
unsigned src_width, unsigned src_height)
|
30
31
|
{
|
31
32
|
// TODO: This should use memcpy if possible (x == 0 && src_width == this->width())
|
32
33
|
|
33
34
|
if (x < 0) {
|
34
35
|
unsigned clip_left = -x;
|
35
36
|
|
36
|
-
if (clip_left >= src_width)
|
37
|
-
return;
|
37
|
+
if (clip_left >= src_width) return;
|
38
38
|
|
39
39
|
src_x += clip_left;
|
40
40
|
src_width -= clip_left;
|
@@ -44,8 +44,7 @@ void Gosu::Bitmap::insert(const Bitmap& source, int x, int y, unsigned src_x, un
|
|
44
44
|
if (y < 0) {
|
45
45
|
unsigned clip_top = -y;
|
46
46
|
|
47
|
-
if (clip_top >= src_height)
|
48
|
-
return;
|
47
|
+
if (clip_top >= src_height) return;
|
49
48
|
|
50
49
|
src_y += clip_top;
|
51
50
|
src_height -= clip_top;
|
@@ -53,27 +52,27 @@ void Gosu::Bitmap::insert(const Bitmap& source, int x, int y, unsigned src_x, un
|
|
53
52
|
}
|
54
53
|
|
55
54
|
if (x + src_width > w) {
|
56
|
-
if (static_cast<unsigned>(x) >= w)
|
57
|
-
return;
|
55
|
+
if (static_cast<unsigned>(x) >= w) return;
|
58
56
|
|
59
57
|
src_width = w - x;
|
60
58
|
}
|
61
59
|
|
62
60
|
if (y + src_height > h) {
|
63
|
-
if (static_cast<unsigned>(y) >= h)
|
64
|
-
return;
|
61
|
+
if (static_cast<unsigned>(y) >= h) return;
|
65
62
|
|
66
63
|
src_height = h - y;
|
67
64
|
}
|
68
65
|
|
69
|
-
for (unsigned rel_y = 0; rel_y < src_height; ++rel_y)
|
70
|
-
for (unsigned rel_x = 0; rel_x < src_width; ++rel_x)
|
71
|
-
set_pixel(x + rel_x, y + rel_y, source.get_pixel(src_x + rel_x, src_y + rel_y));
|
66
|
+
for (unsigned rel_y = 0; rel_y < src_height; ++rel_y) {
|
67
|
+
for (unsigned rel_x = 0; rel_x < src_width; ++rel_x) {
|
68
|
+
set_pixel(x + rel_x, y + rel_y, source.get_pixel(src_x + rel_x, src_y + rel_y));
|
69
|
+
}
|
70
|
+
}
|
72
71
|
}
|
73
72
|
|
74
73
|
void Gosu::apply_color_key(Bitmap& bitmap, Color key)
|
75
74
|
{
|
76
|
-
|
75
|
+
vector<Color> surrounding_colors;
|
77
76
|
surrounding_colors.reserve(4);
|
78
77
|
|
79
78
|
for (unsigned y = 0; y < bitmap.height(); ++y)
|
@@ -96,31 +95,35 @@ void Gosu::apply_color_key(Bitmap& bitmap, Color key)
|
|
96
95
|
|
97
96
|
unsigned red = 0, green = 0, blue = 0;
|
98
97
|
for (auto& color : surrounding_colors) {
|
99
|
-
red
|
98
|
+
red += color.red();
|
100
99
|
green += color.green();
|
101
|
-
blue
|
100
|
+
blue += color.blue();
|
102
101
|
}
|
103
|
-
bitmap.set_pixel(x, y, Color(0,
|
104
|
-
|
102
|
+
bitmap.set_pixel(x, y, Color(0,
|
103
|
+
red / surrounding_colors.size(),
|
104
|
+
green / surrounding_colors.size(),
|
105
|
+
blue / surrounding_colors.size()));
|
105
106
|
}
|
106
107
|
}
|
107
108
|
|
108
109
|
void Gosu::unapply_color_key(Bitmap& bitmap, Color color)
|
109
110
|
{
|
110
111
|
Color* p = bitmap.data();
|
111
|
-
for (int i = bitmap.width() * bitmap.height(); i > 0; --i, ++p)
|
112
|
-
if (p->alpha() == 0)
|
113
|
-
*p = color;
|
114
|
-
|
115
|
-
|
112
|
+
for (int i = bitmap.width() * bitmap.height(); i > 0; --i, ++p) {
|
113
|
+
if (p->alpha() == 0) {
|
114
|
+
*p = color;
|
115
|
+
}
|
116
|
+
else {
|
117
|
+
p->set_alpha(255);
|
118
|
+
}
|
119
|
+
}
|
116
120
|
}
|
117
121
|
|
118
122
|
void Gosu::apply_border_flags(Bitmap& dest, const Bitmap& source, unsigned src_x, unsigned src_y,
|
119
|
-
|
123
|
+
unsigned src_width, unsigned src_height, unsigned image_flags)
|
120
124
|
{
|
121
125
|
// Backward compatibility: This used to be 'bool tileable'.
|
122
|
-
if (image_flags == 1)
|
123
|
-
image_flags = IF_TILEABLE;
|
126
|
+
if (image_flags == 1) image_flags = IF_TILEABLE;
|
124
127
|
|
125
128
|
dest.resize(src_width + 2, src_height + 2);
|
126
129
|
|
@@ -142,17 +145,20 @@ void Gosu::apply_border_flags(Bitmap& dest, const Bitmap& source, unsigned src_x
|
|
142
145
|
|
143
146
|
// Top left.
|
144
147
|
if ((image_flags & IF_TILEABLE_TOP) && (image_flags & IF_TILEABLE_LEFT))
|
145
|
-
dest.set_pixel(0, 0,
|
148
|
+
dest.set_pixel(0, 0,
|
149
|
+
source.get_pixel(src_x, src_y));
|
146
150
|
// Top right.
|
147
151
|
if ((image_flags & IF_TILEABLE_TOP) && (image_flags & IF_TILEABLE_RIGHT))
|
148
|
-
dest.set_pixel(dest.width() - 1, 0,
|
152
|
+
dest.set_pixel(dest.width() - 1, 0,
|
153
|
+
source.get_pixel(src_x + src_width - 1, src_y));
|
149
154
|
// Bottom left.
|
150
155
|
if ((image_flags & IF_TILEABLE_BOTTOM) && (image_flags & IF_TILEABLE_LEFT))
|
151
|
-
dest.set_pixel(0, dest.height() - 1,
|
156
|
+
dest.set_pixel(0, dest.height() - 1,
|
157
|
+
source.get_pixel(src_x, src_y + src_height - 1));
|
152
158
|
// Bottom right.
|
153
159
|
if ((image_flags & IF_TILEABLE_BOTTOM) && (image_flags & IF_TILEABLE_RIGHT))
|
154
160
|
dest.set_pixel(dest.width() - 1, dest.height() - 1,
|
155
|
-
|
161
|
+
source.get_pixel(src_x + src_width - 1, src_y + src_height - 1));
|
156
162
|
|
157
163
|
// Now put the final image into the prepared borders.
|
158
164
|
dest.insert(source, 1, 1, src_x, src_y, src_width, src_height);
|
data/src/BitmapIO.cpp
CHANGED
@@ -9,21 +9,17 @@
|
|
9
9
|
#define STBI_NO_STDIO
|
10
10
|
#define STBI_NO_LINEAR
|
11
11
|
|
12
|
-
// Work around this bug:
|
13
|
-
// https://bugs.launchpad.net/ubuntu/+source/gcc-5/+bug/1568899
|
14
|
-
#ifdef GOSU_IS_X
|
15
|
-
#define STBI_NO_SIMD
|
16
|
-
#endif
|
17
|
-
|
18
12
|
#include "stb_image.h"
|
19
13
|
|
14
|
+
using namespace std;
|
15
|
+
|
20
16
|
namespace
|
21
17
|
{
|
22
18
|
int read_callback(void* user, char* data, int size)
|
23
19
|
{
|
24
20
|
Gosu::Reader* reader = static_cast<Gosu::Reader*>(user);
|
25
|
-
|
26
|
-
|
21
|
+
size_t remaining = reader->resource().size() - reader->position();
|
22
|
+
size_t actual_size = (size < remaining ? size : remaining);
|
27
23
|
reader->read(data, actual_size);
|
28
24
|
return static_cast<int>(actual_size);
|
29
25
|
}
|
@@ -42,18 +38,15 @@ namespace
|
|
42
38
|
|
43
39
|
bool is_bmp(Gosu::Reader reader)
|
44
40
|
{
|
45
|
-
|
46
|
-
if (remaining < 2)
|
47
|
-
return false;
|
48
|
-
}
|
41
|
+
size_t remaining = reader.resource().size() - reader.position();
|
42
|
+
if (remaining < 2) return false;
|
49
43
|
char magic_bytes[2];
|
50
44
|
reader.read(magic_bytes, sizeof magic_bytes);
|
51
|
-
reader.seek(sizeof magic_bytes);
|
52
45
|
return magic_bytes[0] == 'B' && magic_bytes[1] == 'M';
|
53
46
|
}
|
54
47
|
}
|
55
48
|
|
56
|
-
void Gosu::load_image_file(Gosu::Bitmap& bitmap, const
|
49
|
+
void Gosu::load_image_file(Gosu::Bitmap& bitmap, const string& filename)
|
57
50
|
{
|
58
51
|
Buffer buffer;
|
59
52
|
load_file(buffer, filename);
|
@@ -74,11 +67,11 @@ void Gosu::load_image_file(Gosu::Bitmap& bitmap, Reader input)
|
|
74
67
|
if (bytes == nullptr) {
|
75
68
|
// TODO - stbi_failure_reason is not thread safe. Everything here should be wrapped in a
|
76
69
|
// mutex.
|
77
|
-
throw
|
70
|
+
throw runtime_error("Cannot load image: " + string(stbi_failure_reason()));
|
78
71
|
}
|
79
72
|
|
80
73
|
bitmap.resize(x, y);
|
81
|
-
|
74
|
+
memcpy(bitmap.data(), bytes, x * y * sizeof(Gosu::Color));
|
82
75
|
|
83
76
|
stbi_image_free(bytes);
|
84
77
|
|
@@ -90,7 +83,7 @@ void Gosu::load_image_file(Gosu::Bitmap& bitmap, Reader input)
|
|
90
83
|
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
91
84
|
#include "stb_image_write.h"
|
92
85
|
|
93
|
-
void Gosu::save_image_file(const Gosu::Bitmap& bitmap, const
|
86
|
+
void Gosu::save_image_file(const Gosu::Bitmap& bitmap, const string& filename)
|
94
87
|
{
|
95
88
|
int ok;
|
96
89
|
|
@@ -104,9 +97,7 @@ void Gosu::save_image_file(const Gosu::Bitmap& bitmap, const std::string& filena
|
|
104
97
|
ok = stbi_write_png(filename.c_str(), bitmap.width(), bitmap.height(), 4, bitmap.data(), 0);
|
105
98
|
}
|
106
99
|
|
107
|
-
if (ok == 0)
|
108
|
-
throw std::runtime_error("Could not save image data to file: " + filename);
|
109
|
-
}
|
100
|
+
if (ok == 0) throw runtime_error("Could not save image data to file: " + filename);
|
110
101
|
}
|
111
102
|
|
112
103
|
static void stbi_write_to_writer(void* context, void* data, int size)
|
@@ -116,7 +107,7 @@ static void stbi_write_to_writer(void* context, void* data, int size)
|
|
116
107
|
}
|
117
108
|
|
118
109
|
void Gosu::save_image_file(const Gosu::Bitmap& bitmap, Gosu::Writer writer,
|
119
|
-
const
|
110
|
+
const string& format_hint)
|
120
111
|
{
|
121
112
|
int ok;
|
122
113
|
|
@@ -135,7 +126,7 @@ void Gosu::save_image_file(const Gosu::Bitmap& bitmap, Gosu::Writer writer,
|
|
135
126
|
}
|
136
127
|
|
137
128
|
if (ok == 0) {
|
138
|
-
throw
|
139
|
-
|
129
|
+
throw runtime_error("Could not save image data to memory (format hint = '" +
|
130
|
+
format_hint + "'");
|
140
131
|
}
|
141
132
|
}
|