gosu 0.14.4 → 0.15.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +1 -0
  3. data/COPYING +1 -1
  4. data/Gosu/Buttons.hpp +1 -0
  5. data/Gosu/Channel.h +25 -0
  6. data/Gosu/Color.h +38 -0
  7. data/Gosu/Font.h +36 -0
  8. data/Gosu/Gosu.h +79 -0
  9. data/Gosu/Image.h +54 -0
  10. data/Gosu/Sample.h +19 -0
  11. data/Gosu/Song.h +24 -0
  12. data/Gosu/TextInput.h +30 -0
  13. data/Gosu/Version.hpp +2 -2
  14. data/Gosu/Window.h +61 -0
  15. data/Gosu/Window.hpp +3 -2
  16. data/README.md +1 -1
  17. data/ext/gosu/extconf.rb +3 -0
  18. data/lib/gosu/compat.rb +12 -7
  19. data/lib/gosu/patches.rb +8 -2
  20. data/lib/gosu/swig_patches.rb +20 -9
  21. data/rdoc/gosu.rb +28 -7
  22. data/src/ChannelWrapper.cpp +50 -0
  23. data/src/ColorWrapper.cpp +126 -0
  24. data/src/Constants.cpp +287 -0
  25. data/src/Font.cpp +1 -0
  26. data/src/FontWrapper.cpp +74 -0
  27. data/src/GosuWrapper.cpp +232 -0
  28. data/src/Graphics.cpp +4 -1
  29. data/src/GraphicsImpl.hpp +0 -1
  30. data/src/ImageWrapper.cpp +168 -0
  31. data/src/LargeImageData.cpp +1 -0
  32. data/src/MarkupParser.cpp +11 -3
  33. data/src/RubyGosu.cxx +186 -121
  34. data/src/RubyGosu.h +2 -2
  35. data/src/SampleWrapper.cpp +30 -0
  36. data/src/SongWrapper.cpp +52 -0
  37. data/src/TexChunk.cpp +29 -19
  38. data/src/Text.cpp +2 -0
  39. data/src/TextBuilder.cpp +3 -3
  40. data/src/TextInputWrapper.cpp +101 -0
  41. data/src/TrueTypeFont.cpp +1 -0
  42. data/src/Window.cpp +62 -28
  43. data/src/WindowUIKit.cpp +8 -4
  44. data/src/WindowWrapper.cpp +289 -0
  45. data/src/stb_image.h +153 -56
  46. data/src/stb_image_write.h +111 -60
  47. data/src/stb_truetype.h +74 -39
  48. data/src/stb_vorbis.c +55 -15
  49. data/src/utf8proc.c +47 -29
  50. data/src/utf8proc.h +46 -24
  51. data/src/utf8proc_data.h +10043 -9609
  52. metadata +23 -4
@@ -1,6 +1,6 @@
1
1
  /* ----------------------------------------------------------------------------
2
2
  * This file was automatically generated by SWIG (http://www.swig.org).
3
- * Version 3.0.12
3
+ * Version 4.0.2
4
4
  *
5
5
  * This file is not intended to be easily readable and contains a number of
6
6
  * coding conventions designed to improve portability and efficiency. Do not make
@@ -28,7 +28,7 @@ public:
28
28
  class SwigDirector_Window : public Gosu::Window, public Swig::Director {
29
29
 
30
30
  public:
31
- SwigDirector_Window(VALUE self, unsigned int width, unsigned int height, bool fullscreen = false, double update_interval = 16.666666);
31
+ SwigDirector_Window(VALUE self, unsigned int width, unsigned int height, bool fullscreen = false, double update_interval = 16.666666, bool resizable = false);
32
32
  virtual ~SwigDirector_Window();
33
33
  virtual void show();
34
34
  virtual bool tick();
@@ -0,0 +1,30 @@
1
+ #include <Gosu/Audio.hpp>
2
+ #include <Gosu/Sample.h>
3
+
4
+ extern "C" {
5
+
6
+ Gosu_Sample *Gosu_Sample_create(const char *filename)
7
+ {
8
+ return reinterpret_cast<Gosu_Sample *>( new Gosu::Sample(filename) );
9
+ }
10
+
11
+ void Gosu_Sample_destroy(Gosu_Sample *sample)
12
+ {
13
+ delete( reinterpret_cast<Gosu::Sample *>( sample ) );
14
+ }
15
+
16
+ Gosu_Channel *Gosu_Sample_play(Gosu_Sample *sample, double volume, double speed, bool looping)
17
+ {
18
+ Gosu::Channel channel = reinterpret_cast<Gosu::Sample *>( sample )->play(volume, speed, looping);
19
+
20
+ return reinterpret_cast<Gosu_Channel *>( new Gosu::Channel(channel) );
21
+ }
22
+
23
+ Gosu_Channel *Gosu_Sample_play_pan(Gosu_Sample *sample, double pan, double volume, double speed, bool looping)
24
+ {
25
+ Gosu::Channel channel = reinterpret_cast<Gosu::Sample *>( sample )->play_pan(pan, volume, speed, looping);
26
+
27
+ return reinterpret_cast<Gosu_Channel *>( new Gosu::Channel(channel) );
28
+ }
29
+
30
+ }
@@ -0,0 +1,52 @@
1
+ #include <Gosu/Audio.hpp>
2
+ #include <Gosu/Song.h>
3
+
4
+ extern "C" {
5
+ Gosu_Song* Gosu_Song_create(const char* filename)
6
+ {
7
+ return reinterpret_cast<Gosu_Song*>( new Gosu::Song(filename) );
8
+ }
9
+
10
+ void Gosu_Song_destroy(Gosu_Song* song)
11
+ {
12
+ delete( reinterpret_cast<Gosu::Song*>( song ));
13
+ }
14
+
15
+ void Gosu_Song_play(Gosu_Song* song, bool looping)
16
+ {
17
+ reinterpret_cast<Gosu::Song*>( song )->play(looping);
18
+ }
19
+
20
+ bool Gosu_Song_playing(Gosu_Song* song)
21
+ {
22
+ return reinterpret_cast<Gosu::Song*>( song )->playing();
23
+ }
24
+
25
+ void Gosu_Song_pause(Gosu_Song* song)
26
+ {
27
+ reinterpret_cast<Gosu::Song*>( song )->pause();
28
+ }
29
+
30
+ bool Gosu_Song_paused(Gosu_Song* song)
31
+ {
32
+ return reinterpret_cast<Gosu::Song*>( song )->paused();
33
+ }
34
+
35
+ void Gosu_Song_stop(Gosu_Song* song)
36
+ {
37
+ reinterpret_cast<Gosu::Song*>( song )->stop();
38
+ }
39
+
40
+ double Gosu_Song_volume(Gosu_Song* song){
41
+ return reinterpret_cast<Gosu::Song*>( song )->volume();
42
+ }
43
+
44
+ void Gosu_Song_set_volume(Gosu_Song* song, double volume){
45
+ return reinterpret_cast<Gosu::Song*>( song )->set_volume(volume);
46
+ }
47
+
48
+ Gosu_Song* Gosu_Song_current_song()
49
+ {
50
+ return reinterpret_cast<Gosu_Song*>(Gosu::Song::current_song());
51
+ }
52
+ }
@@ -82,39 +82,49 @@ Gosu::Bitmap Gosu::TexChunk::to_bitmap() const
82
82
  return texture->to_bitmap(x, y, w, h);
83
83
  }
84
84
 
85
- void Gosu::TexChunk::insert(const Bitmap& original, int x, int y)
85
+ void Gosu::TexChunk::insert(const Bitmap& original_bitmap, int x, int y)
86
86
  {
87
- Bitmap alternate;
88
- const Bitmap* bitmap = &original;
87
+ Bitmap clipped_bitmap;
88
+ const Bitmap* bitmap = &original_bitmap;
89
89
 
90
- if (x < 0 || y < 0 || x + original.width() > w || y + original.height() > h) {
91
- int offset_x = 0, offset_y = 0;
92
- int trimmed_width = original.width(), trimmed_height = original.height();
90
+ // If inserting the bitmap at the given position exceeds the boundaries of the space allocated
91
+ // for this image on the texture, we need to clip the bitmap and insert the clipped version
92
+ // instead.
93
+ if (x < 0 || y < 0 || x + original_bitmap.width() > w || y + original_bitmap.height() > h) {
94
+ // How many pixels to remove at the top and left sides.
95
+ int clip_left = 0, clip_top = 0;
96
+ // How large the clipped version needs to be.
97
+ int clipped_width = original_bitmap.width(), clipped_height = original_bitmap.height();
98
+
99
+ // Clip away pixels on the left side, if necessary.
93
100
  if (x < 0) {
94
- offset_x = x;
95
- trimmed_width += x;
101
+ clip_left = -x;
102
+ clipped_width -= -x;
96
103
  x = 0;
97
104
  }
105
+ // Clip away pixels at the top, if necessary.
98
106
  if (y < 0) {
99
- offset_y = y;
100
- trimmed_height += y;
107
+ clip_top = -y;
108
+ clipped_height -= -y;
101
109
  y = 0;
102
110
  }
103
- if (x + trimmed_width > w) {
104
- trimmed_width -= (w - x - trimmed_width);
111
+ // Clip away pixels on the right side, if necessary.
112
+ if (x + clipped_width > w) {
113
+ clipped_width = (w - x);
105
114
  }
106
- if (y + trimmed_height > h) {
107
- trimmed_height -= (h - y - trimmed_height);
115
+ // Clip away pixels on the bottom, if necessary.
116
+ if (y + clipped_height > h) {
117
+ clipped_height = (h - y);
108
118
  }
109
119
 
110
- if (trimmed_width <= 0 || trimmed_height <= 0) return;
120
+ if (clipped_width <= 0 || clipped_height <= 0) return;
111
121
 
112
- alternate.resize(trimmed_width, trimmed_height);
113
- alternate.insert(original, offset_x, offset_y);
114
- bitmap = &alternate;
122
+ clipped_bitmap.resize(clipped_width, clipped_height);
123
+ clipped_bitmap.insert(original_bitmap, -clip_left, -clip_top);
124
+ bitmap = &clipped_bitmap;
115
125
  }
116
126
 
117
127
  glBindTexture(GL_TEXTURE_2D, tex_name());
118
128
  glTexSubImage2D(GL_TEXTURE_2D, 0, this->x + x, this->y + y, bitmap->width(), bitmap->height(),
119
- Color::GL_FORMAT, GL_UNSIGNED_BYTE, bitmap->data());
129
+ Color::GL_FORMAT, GL_UNSIGNED_BYTE, bitmap->data());
120
130
  }
@@ -7,6 +7,7 @@
7
7
  #include <cmath>
8
8
  #include <algorithm>
9
9
  #include <vector>
10
+ #include <stdexcept>
10
11
  using namespace std;
11
12
 
12
13
  double Gosu::text_width(const u32string& text,
@@ -33,6 +34,7 @@ Gosu::Bitmap Gosu::layout_text(const string& text, const string& font_name,
33
34
  double font_height, double line_spacing,
34
35
  int width, Alignment align, unsigned font_flags)
35
36
  {
37
+ // Escape all markup and delegate to layout_markup.
36
38
  return layout_markup(escape_markup(text), font_name,
37
39
  font_height, line_spacing,
38
40
  width, align, font_flags);
@@ -58,7 +58,7 @@ void Gosu::TextBuilder::flush_current_line(EndOfLineReason reason)
58
58
  }
59
59
 
60
60
  double whitespace_factor = 1.0;
61
- if (align == AL_JUSTIFY && reason == LINE_TOO_LONG) {
61
+ if (align == AL_JUSTIFY && whitespace_width != 0 && reason == LINE_TOO_LONG) {
62
62
  whitespace_factor = (result.width() - words_width) / whitespace_width;
63
63
  }
64
64
 
@@ -132,7 +132,7 @@ void Gosu::TextBuilder::feed_word(vector&& word)
132
132
  current_line.emplace_back(new_word);
133
133
  current_line_width += new_word.width;
134
134
 
135
- if (current_line_width > result.width() || new_word.is_end_of_line) {
136
- flush_current_line(new_word.is_end_of_line ? END_OF_PARAGRAPH : LINE_TOO_LONG);
135
+ if (new_word.is_end_of_line) {
136
+ flush_current_line(END_OF_PARAGRAPH);
137
137
  }
138
138
  }
@@ -0,0 +1,101 @@
1
+ #include <Gosu/Gosu.hpp>
2
+
3
+ namespace Gosu
4
+ {
5
+ class TextInputForWrapper : public Gosu::TextInput
6
+ {
7
+ public:
8
+ TextInputForWrapper();
9
+ std::string filter(std::string text) const override;
10
+ std::function<void (const char *text)> filter_callback;
11
+ std::string filter_result = "";
12
+ };
13
+ } // namespace Gosu
14
+
15
+ Gosu::TextInputForWrapper::TextInputForWrapper() : Gosu::TextInput()
16
+ {
17
+ }
18
+
19
+ std::string Gosu::TextInputForWrapper::filter(std::string text) const
20
+ {
21
+ if (filter_callback != nullptr) {
22
+ filter_callback(text.c_str());
23
+ return filter_result;
24
+ }
25
+ else {
26
+ return text;
27
+ }
28
+ }
29
+
30
+ extern "C" {
31
+ #include <Gosu/TextInput.h>
32
+
33
+ Gosu_TextInput *Gosu_TextInput_create()
34
+ {
35
+ return reinterpret_cast<Gosu_TextInput *>(new Gosu::TextInputForWrapper());
36
+ }
37
+
38
+ const char *Gosu_TextInput_text(Gosu_TextInput *text_input)
39
+ {
40
+ thread_local std::string string;
41
+ string = reinterpret_cast<Gosu::TextInputForWrapper *>(text_input)->text();
42
+
43
+ return string.c_str();
44
+ }
45
+
46
+ void Gosu_TextInput_set_text(Gosu_TextInput *text_input, const char *text)
47
+ {
48
+ reinterpret_cast<Gosu::TextInputForWrapper *>(text_input)->set_text(text);
49
+ }
50
+
51
+ unsigned Gosu_TextInput_caret_pos(Gosu_TextInput *text_input)
52
+ {
53
+ return reinterpret_cast<Gosu::TextInputForWrapper *>(text_input)->caret_pos();
54
+ }
55
+
56
+ void Gosu_TextInput_set_caret_pos(Gosu_TextInput *text_input, unsigned pos)
57
+ {
58
+ return reinterpret_cast<Gosu::TextInputForWrapper *>(text_input)->set_caret_pos(pos);
59
+ }
60
+
61
+ unsigned Gosu_TextInput_selection_start(Gosu_TextInput *text_input)
62
+ {
63
+ return reinterpret_cast<Gosu::TextInputForWrapper *>(text_input)->selection_start();
64
+ }
65
+
66
+ void Gosu_TextInput_set_selection_start(Gosu_TextInput *text_input, unsigned pos)
67
+ {
68
+ return reinterpret_cast<Gosu::TextInputForWrapper *>(text_input)->set_selection_start(pos);
69
+ }
70
+
71
+ void Gosu_TextInput_set_filter(Gosu_TextInput *text_input, void function(void *data, const char *text), void *data)
72
+ {
73
+ reinterpret_cast<Gosu::TextInputForWrapper *>(text_input)->filter_callback = [=](const char *text) { function(data, text); };
74
+ }
75
+
76
+ void Gosu_TextInput_set_filter_result(Gosu_TextInput *text_input, const char *result)
77
+ {
78
+ reinterpret_cast<Gosu::TextInputForWrapper *>(text_input)->filter_result = result;
79
+ }
80
+
81
+ void Gosu_TextInput_insert_text(Gosu_TextInput *text_input, const char *text)
82
+ {
83
+ reinterpret_cast<Gosu::TextInputForWrapper *>(text_input)->insert_text(text);
84
+ }
85
+
86
+ void Gosu_TextInput_delete_backward(Gosu_TextInput *text_input)
87
+ {
88
+ reinterpret_cast<Gosu::TextInputForWrapper *>(text_input)->delete_backward();
89
+ }
90
+
91
+ void Gosu_TextInput_delete_forward(Gosu_TextInput *text_input)
92
+ {
93
+ reinterpret_cast<Gosu::TextInputForWrapper *>(text_input)->delete_forward();
94
+ }
95
+
96
+ void Gosu_TextInput_destroy(Gosu_TextInput *text_input)
97
+ {
98
+ delete (reinterpret_cast<Gosu::TextInputForWrapper *>(text_input));
99
+ }
100
+
101
+ }
@@ -1,6 +1,7 @@
1
1
  #include "TrueTypeFont.hpp"
2
2
  #include <Gosu/IO.hpp>
3
3
  #include <Gosu/Text.hpp>
4
+ #include <stdexcept>
4
5
 
5
6
  // Disable comma warnings in stb headers.
6
7
  #ifdef __GNUC__
@@ -85,22 +85,29 @@ struct Gosu::Window::Impl
85
85
  {
86
86
  bool fullscreen;
87
87
  double update_interval;
88
-
88
+ bool resizable;
89
+ bool resizing = false;
90
+
89
91
  // A single `bool open` is not good enough to support the tick() method: When close() is called
90
92
  // from outside the window's call graph, the next call to tick() must return false (transition
91
93
  // from CLOSING to CLOSED), but the call after that must return show the window again
92
94
  // (transition from CLOSED to OPEN).
93
95
  enum { CLOSED, OPEN, CLOSING } state = CLOSED;
94
-
96
+
95
97
  unique_ptr<Graphics> graphics;
96
98
  unique_ptr<Input> input;
97
99
  };
98
100
 
99
- Gosu::Window::Window(unsigned width, unsigned height, bool fullscreen, double update_interval)
101
+ Gosu::Window::Window(unsigned width, unsigned height, bool fullscreen, double update_interval,
102
+ bool resizable)
100
103
  : pimpl(new Impl)
101
104
  {
105
+ #if SDL_VERSION_ATLEAST(2, 0, 5)
106
+ SDL_SetWindowResizable(shared_window(), (SDL_bool)resizable);
107
+ #endif
108
+
102
109
  // Even in fullscreen mode, temporarily show the window in windowed mode to centre it.
103
- // This ensures that the window will be centred correctly when exiting fullscreen mode.
110
+ // This ensures that the window will be centered correctly when exiting fullscreen mode.
104
111
  // Fixes https://github.com/gosu/gosu/issues/369
105
112
  // (This will implicitly create graphics() and input(), and make the OpenGL context current.)
106
113
  resize(width, height, false);
@@ -108,11 +115,12 @@ Gosu::Window::Window(unsigned width, unsigned height, bool fullscreen, double up
108
115
 
109
116
  // Really enable fullscreen if desired.
110
117
  resize(width, height, fullscreen);
111
-
118
+
112
119
  SDL_GL_SetSwapInterval(1);
113
120
 
114
121
  pimpl->update_interval = update_interval;
115
-
122
+ pimpl->resizable = resizable;
123
+
116
124
  input().on_button_down = [this](Button button) { button_down(button); };
117
125
  input().on_button_up = [this](Button button) { button_up(button); };
118
126
  }
@@ -137,6 +145,11 @@ bool Gosu::Window::fullscreen() const
137
145
  return pimpl->fullscreen;
138
146
  }
139
147
 
148
+ bool Gosu::Window::resizable() const
149
+ {
150
+ return pimpl->resizable;
151
+ }
152
+
140
153
  void Gosu::Window::resize(unsigned width, unsigned height, bool fullscreen)
141
154
  {
142
155
  pimpl->fullscreen = fullscreen;
@@ -150,31 +163,47 @@ void Gosu::Window::resize(unsigned width, unsigned height, bool fullscreen)
150
163
  if (fullscreen) {
151
164
  actual_width = Gosu::screen_width(this);
152
165
  actual_height = Gosu::screen_height(this);
153
-
154
- double scale_x = 1.0 * actual_width / width;
155
- double scale_y = 1.0 * actual_height / height;
156
- scale_factor = min(scale_x, scale_y);
157
-
158
- if (scale_x < scale_y) {
159
- black_bar_height = (actual_height / scale_x - height) / 2;
166
+
167
+ if (resizable()) {
168
+ // Resizable fullscreen windows stubbornly follow the desktop resolution.
169
+ width = actual_width;
170
+ height = actual_height;
160
171
  }
161
- else if (scale_y < scale_x) {
162
- black_bar_width = (actual_width / scale_y - width) / 2;
172
+ else {
173
+ // Scale the window to fill the desktop resolution.
174
+ double scale_x = 1.0 * actual_width / width;
175
+ double scale_y = 1.0 * actual_height / height;
176
+ scale_factor = min(scale_x, scale_y);
177
+ // Add black bars to preserve the aspect ratio, if necessary.
178
+ if (scale_x < scale_y) {
179
+ black_bar_height = (actual_height / scale_x - height) / 2;
180
+ }
181
+ else if (scale_y < scale_x) {
182
+ black_bar_width = (actual_width / scale_y - width) / 2;
183
+ }
163
184
  }
164
185
  }
165
186
  else {
166
- double max_width = Gosu::available_width(this);
167
- double max_height = Gosu::available_height(this);
187
+ unsigned max_width = Gosu::available_width(this);
188
+ unsigned max_height = Gosu::available_height(this);
168
189
 
169
- if (width > max_width || height > max_height) {
170
- scale_factor = min(max_width / width, max_height / height);
190
+ if (resizable()) {
191
+ // If the window is resizable, limit its size, without preserving the aspect ratio.
192
+ width = actual_width = min(width, max_width);
193
+ height = actual_height = min(height, max_height);
194
+ }
195
+ else if (width > max_width || height > max_height) {
196
+ // If the window cannot fit on the screen, shrink its contents.
197
+ scale_factor = min(1.0 * max_width / width, 1.0 * max_height / height);
171
198
  actual_width = width * scale_factor;
172
199
  actual_height = height * scale_factor;
173
200
  }
174
201
  }
175
202
 
176
203
  SDL_SetWindowFullscreen(shared_window(), fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0);
177
- SDL_SetWindowSize(shared_window(), actual_width, actual_height);
204
+ if (!pimpl->resizing) {
205
+ SDL_SetWindowSize(shared_window(), actual_width, actual_height);
206
+ }
178
207
 
179
208
  #if SDL_VERSION_ATLEAST(2, 0, 1)
180
209
  SDL_GL_GetDrawableSize(shared_window(), &actual_width, &actual_height);
@@ -256,19 +285,24 @@ bool Gosu::Window::tick()
256
285
 
257
286
  SDL_Event e;
258
287
  while (SDL_PollEvent(&e)) {
288
+
259
289
  switch (e.type) {
260
- #ifdef GOSU_IS_MAC
261
- // Workaround for https://github.com/gosu/gosu/issues/458
262
- // "Resize" the window to its current dimensions after it is shown.
263
- // Otherwise it will be black on macOS 10.14 (Mojave) until the user moves it around.
264
- // TODO: Since this affects `brew install supertux` as well, maybe file an SDL bug?
265
290
  case SDL_WINDOWEVENT: {
266
- if (e.window.event == SDL_WINDOWEVENT_SHOWN) {
267
- resize(this->width(), this->height(), fullscreen());
291
+ switch (e.window.event) {
292
+ case SDL_WINDOWEVENT_SIZE_CHANGED: {
293
+ if (pimpl->resizable && (width() != e.window.data1 || height() != e.window.data2)) {
294
+ pimpl->resizing = true;
295
+ resize(e.window.data1, e.window.data2, fullscreen());
296
+ pimpl->resizing = false;
297
+ }
298
+ break;
299
+ }
300
+ default: {
301
+ break;
302
+ }
268
303
  }
269
304
  break;
270
305
  }
271
- #endif
272
306
  case SDL_QUIT: {
273
307
  close();
274
308
  break;