gosu 0.12.1 → 0.13.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/Gosu/Audio.hpp +23 -25
  3. data/Gosu/Graphics.hpp +16 -12
  4. data/Gosu/Image.hpp +3 -0
  5. data/Gosu/Version.hpp +2 -2
  6. data/lib/gosu.rb +2 -2
  7. data/lib/gosu/compat.rb +1 -1
  8. data/lib/gosu/patches.rb +5 -0
  9. data/lib/gosu/swig_patches.rb +1 -1
  10. data/rdoc/gosu.rb +10 -10
  11. data/src/Audio.cpp +93 -228
  12. data/src/AudioImpl.cpp +94 -0
  13. data/src/AudioImpl.hpp +33 -0
  14. data/src/AudioToolboxFile.hpp +14 -18
  15. data/src/Bitmap.cpp +36 -30
  16. data/src/BitmapIO.cpp +14 -23
  17. data/src/BlockAllocator.cpp +7 -10
  18. data/src/BlockAllocator.hpp +2 -4
  19. data/src/Channel.cpp +89 -0
  20. data/src/Color.cpp +4 -9
  21. data/src/DirectoriesApple.cpp +13 -13
  22. data/src/DirectoriesUnix.cpp +8 -7
  23. data/src/DirectoriesWin.cpp +12 -11
  24. data/src/EmptyImageData.hpp +54 -0
  25. data/src/FileUnix.cpp +12 -9
  26. data/src/FileWin.cpp +8 -7
  27. data/src/Font.cpp +12 -13
  28. data/src/FormattedString.cpp +237 -0
  29. data/src/FormattedString.hpp +14 -265
  30. data/src/GosuViewController.cpp +2 -5
  31. data/src/Graphics.cpp +38 -39
  32. data/src/IO.cpp +11 -10
  33. data/src/Image.cpp +16 -9
  34. data/src/Input.cpp +16 -15
  35. data/src/InputUIKit.cpp +8 -7
  36. data/src/Macro.cpp +11 -11
  37. data/src/Math.cpp +9 -8
  38. data/src/RubyGosu.cxx +129 -99
  39. data/src/TextApple.cpp +19 -13
  40. data/src/TextInput.cpp +23 -22
  41. data/src/TextWin.cpp +17 -19
  42. data/src/Texture.cpp +15 -10
  43. data/src/Transform.cpp +13 -17
  44. data/src/Utility.cpp +3 -2
  45. data/src/UtilityApple.cpp +10 -11
  46. data/src/UtilityWin.cpp +2 -1
  47. data/src/Version.cpp +5 -4
  48. data/src/WinMain.cpp +3 -3
  49. data/src/WinUtility.cpp +7 -6
  50. data/src/Window.cpp +11 -10
  51. data/src/WindowUIKit.cpp +9 -8
  52. data/src/stb_image.h +782 -480
  53. data/src/stb_image_write.h +425 -15
  54. data/src/stb_vorbis.c +82 -32
  55. metadata +8 -4
  56. data/src/ALChannelManagement.hpp +0 -119
@@ -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
+ }
@@ -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
+ }
@@ -33,7 +33,7 @@ namespace Gosu
33
33
  {
34
34
  class AudioToolboxFile : public AudioFile
35
35
  {
36
- Gosu::Buffer buffer_;
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
- UInt32 request_count, void* buffer, UInt32* actual_count)
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, res.size() - in_position);
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 | kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked;
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
- /*if (desc.mBitsPerChannel == 8)
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
- /*if (desc.mBitsPerChannel == 8)
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(Gosu::Reader reader)
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));
@@ -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
- unsigned src_width, unsigned src_height)
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
- std::vector<Color> surrounding_colors;
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 += color.red();
98
+ red += color.red();
100
99
  green += color.green();
101
- blue += color.blue();
100
+ blue += color.blue();
102
101
  }
103
- bitmap.set_pixel(x, y, Color(0, red / surrounding_colors.size(),
104
- green / surrounding_colors.size(), blue / surrounding_colors.size()));
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
- else
115
- p->set_alpha(255);
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
- unsigned src_width, unsigned src_height, unsigned image_flags)
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, source.get_pixel(src_x, src_y));
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, source.get_pixel(src_x + src_width - 1, src_y));
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, source.get_pixel(src_x, src_y + src_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
- source.get_pixel(src_x + src_width - 1, src_y + src_height - 1));
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);
@@ -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
- std::size_t remaining = reader->resource().size() - reader->position();
26
- std::size_t actual_size = (size < remaining ? size : remaining);
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
- std::size_t remaining = reader.resource().size() - reader.position();
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 std::string& filename)
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 std::runtime_error("Cannot load image: " + std::string(stbi_failure_reason()));
70
+ throw runtime_error("Cannot load image: " + string(stbi_failure_reason()));
78
71
  }
79
72
 
80
73
  bitmap.resize(x, y);
81
- std::memcpy(bitmap.data(), bytes, x * y * sizeof(Gosu::Color));
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 std::string& filename)
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 std::string& format_hint)
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 std::runtime_error("Could not save image data to memory (format hint = '" +
139
- format_hint + "'");
129
+ throw runtime_error("Could not save image data to memory (format hint = '" +
130
+ format_hint + "'");
140
131
  }
141
132
  }