gosu 1.4.6 → 2.0.0.pre6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (170) hide show
  1. checksums.yaml +4 -4
  2. data/COPYING +2 -1
  3. data/dependencies/SDL/include/SDL_atomic.h +2 -3
  4. data/dependencies/SDL/include/SDL_audio.h +7 -7
  5. data/dependencies/SDL/include/SDL_blendmode.h +1 -1
  6. data/dependencies/SDL/include/SDL_endian.h +3 -3
  7. data/dependencies/SDL/include/SDL_gamecontroller.h +4 -4
  8. data/dependencies/SDL/include/SDL_hints.h +72 -28
  9. data/dependencies/SDL/include/SDL_joystick.h +8 -5
  10. data/dependencies/SDL/include/SDL_keycode.h +1 -1
  11. data/dependencies/SDL/include/SDL_main.h +7 -0
  12. data/dependencies/SDL/include/SDL_mouse.h +6 -7
  13. data/dependencies/SDL/include/SDL_mutex.h +79 -5
  14. data/dependencies/SDL/include/SDL_opengl_glext.h +5 -1
  15. data/dependencies/SDL/include/SDL_power.h +7 -8
  16. data/dependencies/SDL/include/SDL_render.h +5 -0
  17. data/dependencies/SDL/include/SDL_revision.h +2 -2
  18. data/dependencies/SDL/include/SDL_sensor.h +1 -1
  19. data/dependencies/SDL/include/SDL_stdinc.h +19 -11
  20. data/dependencies/SDL/include/SDL_thread.h +2 -2
  21. data/dependencies/SDL/include/SDL_version.h +2 -2
  22. data/dependencies/SDL/include/SDL_video.h +30 -2
  23. data/dependencies/SDL/include/begin_code.h +7 -7
  24. data/dependencies/SDL/include/close_code.h +2 -2
  25. data/dependencies/SDL/lib/x64/libSDL2.dll.a +0 -0
  26. data/dependencies/SDL/lib/x86/libSDL2.dll.a +0 -0
  27. data/dependencies/SDL_sound/SDL_sound.h +1 -1
  28. data/dependencies/SDL_sound/dr_flac.h +48 -23
  29. data/dependencies/SDL_sound/dr_mp3.h +34 -14
  30. data/dependencies/SDL_sound/stb_vorbis.h +3 -2
  31. data/dependencies/mojoAL/mojoal.c +1 -1
  32. data/ext/{gosu → gosu-ffi}/extconf.rb +34 -33
  33. data/ext/gosu-ffi/gosu-ffi.def +464 -0
  34. data/ffi/Gosu.cpp +307 -0
  35. data/ffi/Gosu.h +84 -0
  36. data/ffi/Gosu_Channel.cpp +62 -0
  37. data/ffi/Gosu_Channel.h +17 -0
  38. data/ffi/Gosu_Color.cpp +132 -0
  39. data/ffi/Gosu_Color.h +31 -0
  40. data/ffi/Gosu_Constants.cpp +334 -0
  41. data/ffi/Gosu_FFI.h +34 -0
  42. data/ffi/Gosu_FFI_internal.h +161 -0
  43. data/ffi/Gosu_Font.cpp +92 -0
  44. data/ffi/Gosu_Font.h +32 -0
  45. data/ffi/Gosu_Image.cpp +206 -0
  46. data/ffi/Gosu_Image.h +60 -0
  47. data/ffi/Gosu_Sample.cpp +29 -0
  48. data/ffi/Gosu_Sample.h +14 -0
  49. data/ffi/Gosu_Song.cpp +69 -0
  50. data/ffi/Gosu_Song.h +18 -0
  51. data/ffi/Gosu_TextInput.cpp +94 -0
  52. data/ffi/Gosu_TextInput.h +25 -0
  53. data/ffi/Gosu_Window.cpp +314 -0
  54. data/ffi/Gosu_Window.h +78 -0
  55. data/include/Gosu/Audio.hpp +6 -11
  56. data/include/Gosu/Bitmap.hpp +38 -53
  57. data/include/Gosu/Buffer.hpp +54 -0
  58. data/include/Gosu/Color.hpp +27 -35
  59. data/include/Gosu/Directories.hpp +25 -28
  60. data/include/Gosu/Drawable.hpp +58 -0
  61. data/include/Gosu/Font.hpp +6 -5
  62. data/include/Gosu/Fwd.hpp +4 -6
  63. data/include/Gosu/Gosu.hpp +5 -5
  64. data/include/Gosu/Graphics.hpp +51 -61
  65. data/include/Gosu/GraphicsBase.hpp +1 -11
  66. data/include/Gosu/Image.hpp +11 -14
  67. data/include/Gosu/Math.hpp +50 -72
  68. data/include/Gosu/Transform.hpp +32 -0
  69. data/include/Gosu/Utility.hpp +51 -1
  70. data/include/Gosu/Version.hpp +3 -3
  71. data/include/Gosu/Window.hpp +15 -9
  72. data/lib/SDL2.dll +0 -0
  73. data/lib/gosu/channel.rb +49 -0
  74. data/lib/gosu/color.rb +150 -0
  75. data/lib/gosu/compat.rb +29 -8
  76. data/lib/gosu/constants.rb +386 -0
  77. data/lib/gosu/ffi.rb +258 -0
  78. data/lib/gosu/font.rb +56 -0
  79. data/lib/gosu/gl_tex_info.rb +33 -0
  80. data/lib/gosu/gosu.rb +210 -0
  81. data/lib/gosu/image.rb +141 -0
  82. data/lib/gosu/numeric.rb +17 -0
  83. data/lib/gosu/preview.rb +6 -6
  84. data/lib/gosu/sample.rb +24 -0
  85. data/lib/gosu/song.rb +56 -0
  86. data/lib/gosu/text_input.rb +69 -0
  87. data/lib/gosu/window.rb +228 -0
  88. data/lib/gosu.rb +29 -8
  89. data/lib64/SDL2.dll +0 -0
  90. data/rdoc/gosu.rb +0 -2
  91. data/src/Audio.cpp +12 -12
  92. data/src/AudioFile.hpp +5 -4
  93. data/src/AudioFileAudioToolbox.cpp +8 -8
  94. data/src/AudioFileSDLSound.cpp +7 -10
  95. data/src/BinPacker.cpp +187 -0
  96. data/src/BinPacker.hpp +55 -0
  97. data/src/Bitmap.cpp +166 -144
  98. data/src/BitmapIO.cpp +60 -86
  99. data/src/Buffer.cpp +159 -0
  100. data/src/Color.cpp +75 -80
  101. data/src/Directories.cpp +47 -0
  102. data/src/DirectoriesUIKit.cpp +50 -0
  103. data/src/DrawOp.hpp +9 -4
  104. data/src/DrawOpQueue.hpp +2 -2
  105. data/src/Drawable.cpp +95 -0
  106. data/src/EmptyDrawable.hpp +38 -0
  107. data/src/FPS.cpp +31 -0
  108. data/src/Font.cpp +104 -74
  109. data/src/GosuGLView.cpp +14 -6
  110. data/src/GosuViewController.cpp +2 -10
  111. data/src/Graphics.cpp +60 -126
  112. data/src/GraphicsImpl.hpp +17 -47
  113. data/src/Image.cpp +41 -35
  114. data/src/Input.cpp +7 -8
  115. data/src/Macro.cpp +6 -6
  116. data/src/Macro.hpp +4 -4
  117. data/src/MarkupParser.cpp +5 -5
  118. data/src/Math.cpp +35 -22
  119. data/src/OffScreenTarget.cpp +53 -49
  120. data/src/OffScreenTarget.hpp +13 -11
  121. data/src/OpenGLContext.cpp +117 -0
  122. data/src/OpenGLContext.hpp +41 -0
  123. data/src/RenderState.hpp +21 -19
  124. data/src/Resolution.cpp +23 -21
  125. data/src/TexChunk.cpp +35 -80
  126. data/src/TexChunk.hpp +44 -35
  127. data/src/Text.cpp +1 -1
  128. data/src/TextBuilder.cpp +35 -21
  129. data/src/TextBuilder.hpp +6 -9
  130. data/src/Texture.cpp +62 -80
  131. data/src/Texture.hpp +25 -23
  132. data/src/TiledDrawable.cpp +150 -0
  133. data/src/TiledDrawable.hpp +47 -0
  134. data/src/TimingApple.cpp +1 -1
  135. data/src/Transform.cpp +45 -50
  136. data/src/TransformStack.hpp +16 -16
  137. data/src/TrueTypeFont.cpp +59 -51
  138. data/src/TrueTypeFont.hpp +6 -7
  139. data/src/TrueTypeFontApple.cpp +28 -19
  140. data/src/TrueTypeFontUnix.cpp +27 -23
  141. data/src/TrueTypeFontWin.cpp +30 -30
  142. data/src/Utility.cpp +84 -21
  143. data/src/UtilityWin.cpp +45 -0
  144. data/src/Window.cpp +92 -142
  145. data/src/WindowUIKit.cpp +14 -14
  146. metadata +72 -31
  147. data/include/Gosu/IO.hpp +0 -254
  148. data/include/Gosu/ImageData.hpp +0 -53
  149. data/include/Gosu/Inspection.hpp +0 -7
  150. data/lib/gosu/patches.rb +0 -66
  151. data/lib/gosu/run.rb +0 -20
  152. data/lib/gosu/swig_patches.rb +0 -110
  153. data/src/BlockAllocator.cpp +0 -131
  154. data/src/BlockAllocator.hpp +0 -32
  155. data/src/DirectoriesApple.cpp +0 -69
  156. data/src/DirectoriesUnix.cpp +0 -46
  157. data/src/DirectoriesWin.cpp +0 -65
  158. data/src/EmptyImageData.hpp +0 -52
  159. data/src/FileUnix.cpp +0 -99
  160. data/src/FileWin.cpp +0 -88
  161. data/src/IO.cpp +0 -60
  162. data/src/Iconv.hpp +0 -51
  163. data/src/Inspection.cpp +0 -27
  164. data/src/LargeImageData.cpp +0 -215
  165. data/src/LargeImageData.hpp +0 -39
  166. data/src/Log.hpp +0 -19
  167. data/src/RubyGosu.cxx +0 -13100
  168. data/src/RubyGosu.h +0 -49
  169. data/src/WinUtility.cpp +0 -61
  170. data/src/WinUtility.hpp +0 -27
data/src/TextBuilder.hpp CHANGED
@@ -6,6 +6,9 @@
6
6
 
7
7
  namespace Gosu
8
8
  {
9
+ // A single word and its formatting context. A "word" is anything that is atomic in terms of
10
+ // where Gosu can introduce line breaks. Even a single word has several "parts" because e.g. a
11
+ // single character in the middle could be bold.
9
12
  struct WordInfo
10
13
  {
11
14
  std::vector<FormattedString> parts;
@@ -25,16 +28,10 @@ namespace Gosu
25
28
  double m_line_spacing;
26
29
  Alignment m_align;
27
30
 
28
- enum EndOfLineReason
29
- {
30
- LINE_TOO_LONG,
31
- END_OF_PARAGRAPH,
32
- END_OF_TEXT
33
- };
34
-
35
31
  // Input.
36
32
  std::vector<WordInfo> m_current_line;
37
33
  int m_current_line_width = 0;
34
+ enum EndOfLineReason : int;
38
35
  void flush_current_line(EndOfLineReason reason);
39
36
 
40
37
  // Output.
@@ -42,13 +39,13 @@ namespace Gosu
42
39
  int m_used_lines = 0;
43
40
  int m_allocated_lines = 0;
44
41
  void allocate_next_line();
45
- void resize_to_allocated_lines();
42
+ void reallocate(int lines);
46
43
 
47
44
  public:
48
45
  TextBuilder(const std::string& font_name, int font_height, int line_spacing, int width,
49
46
  Alignment align);
50
47
 
51
- void feed_word(std::vector<FormattedString>&& word);
48
+ void feed_word(std::vector<FormattedString> word);
52
49
 
53
50
  Bitmap move_into_bitmap() &&;
54
51
  };
data/src/Texture.cpp CHANGED
@@ -1,39 +1,35 @@
1
1
  #include "Texture.hpp"
2
- #include "TexChunk.hpp"
3
- #include "Log.hpp"
4
2
  #include <Gosu/Bitmap.hpp>
5
- #include <Gosu/Graphics.hpp>
6
3
  #include <Gosu/Platform.hpp>
4
+ #include "OpenGLContext.hpp"
5
+ #include "TexChunk.hpp"
7
6
  #include <stdexcept>
8
- using namespace std;
9
7
 
10
- namespace Gosu
8
+ Gosu::Texture::Texture(int width, int height, bool retro)
9
+ : m_bin_packer(width, height),
10
+ m_tex_name(0),
11
+ m_retro(retro)
11
12
  {
12
- bool undocumented_retrofication = false;
13
- }
13
+ if (width <= 0 || height <= 0) {
14
+ throw std::invalid_argument("Gosu::Texture must not be empty");
15
+ }
14
16
 
15
- Gosu::Texture::Texture(unsigned width, unsigned height, bool retro)
16
- : allocator_(width, height), retro_(retro)
17
- {
18
- log("Allocating a new texture of size %dx%d (retro=%d)", width, height, (int) retro);
17
+ const OpenGLContext current_context;
19
18
 
20
- ensure_current_context();
21
-
22
19
  // Create texture name.
23
- glGenTextures(1, &tex_name_);
24
- if (tex_name_ == static_cast<GLuint>(-1)) throw runtime_error("Couldn't create OpenGL texture");
20
+ glGenTextures(1, &m_tex_name);
21
+ // GCOV_EXCL_START: Hard to simulate out-of-texture situations.
22
+ if (m_tex_name == static_cast<GLuint>(-1)) {
23
+ throw std::runtime_error("Failed to allocate OpenGL texture");
24
+ }
25
+ // GCOV_EXCL_END
25
26
 
26
27
  // Create empty texture.
27
- glBindTexture(GL_TEXTURE_2D, tex_name_);
28
- #ifdef GOSU_IS_OPENGLES
29
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, allocator_.width(), allocator_.height(), 0, GL_RGBA,
28
+ glBindTexture(GL_TEXTURE_2D, m_tex_name);
29
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_bin_packer.width(), m_bin_packer.height(), 0, GL_RGBA,
30
30
  GL_UNSIGNED_BYTE, nullptr);
31
- #else
32
- glTexImage2D(GL_TEXTURE_2D, 0, 4, allocator_.width(), allocator_.height(), 0, GL_RGBA,
33
- GL_UNSIGNED_BYTE, nullptr);
34
- #endif
35
-
36
- if (retro || undocumented_retrofication) {
31
+
32
+ if (retro) {
37
33
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
38
34
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
39
35
  }
@@ -41,7 +37,7 @@ Gosu::Texture::Texture(unsigned width, unsigned height, bool retro)
41
37
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
42
38
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
43
39
  }
44
-
40
+
45
41
  #ifdef GL_CLAMP_TO_EDGE
46
42
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
47
43
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
@@ -53,79 +49,65 @@ Gosu::Texture::Texture(unsigned width, unsigned height, bool retro)
53
49
 
54
50
  Gosu::Texture::~Texture()
55
51
  {
56
- ensure_current_context();
57
-
58
- glDeleteTextures(1, &tex_name_);
52
+ try {
53
+ const OpenGLContext current_context;
54
+ glDeleteTextures(1, &m_tex_name);
55
+ } catch (...)
56
+ {
57
+ // Leaking is better than throwing in a destructor.
58
+ }
59
59
  }
60
60
 
61
- unsigned Gosu::Texture::width() const
61
+ std::unique_ptr<Gosu::TexChunk> Gosu::Texture::try_alloc(const Bitmap& bitmap, int padding)
62
62
  {
63
- return allocator_.width();
64
- }
63
+ const std::shared_ptr<const Rect> rect = m_bin_packer.alloc(bitmap.width(), bitmap.height());
65
64
 
66
- unsigned Gosu::Texture::height() const
67
- {
68
- return allocator_.height();
69
- }
65
+ if (!rect) {
66
+ return nullptr;
67
+ }
70
68
 
71
- GLuint Gosu::Texture::tex_name() const
72
- {
73
- return tex_name_;
74
- }
69
+ insert(bitmap, rect->x, rect->y);
75
70
 
76
- bool Gosu::Texture::retro() const
77
- {
78
- return retro_;
71
+ const Rect rect_without_padding { rect->x + padding, rect->y + padding,
72
+ rect->width - 2 * padding, rect->height - 2 * padding };
73
+ return std::make_unique<TexChunk>(shared_from_this(), rect_without_padding, rect);
79
74
  }
80
75
 
81
- unique_ptr<Gosu::TexChunk> Gosu::Texture::try_alloc(const Bitmap& bmp, unsigned padding)
76
+ void Gosu::Texture::insert(const Gosu::Bitmap& bitmap, int x, int y)
82
77
  {
83
- BlockAllocator::Block block;
84
-
85
- if (!allocator_.alloc(bmp.width(), bmp.height(), block)) return nullptr;
86
-
87
- unique_ptr<TexChunk> result(new TexChunk(shared_from_this(),
88
- block.left + padding,
89
- block.top + padding,
90
- block.width - 2 * padding,
91
- block.height - 2 * padding,
92
- padding));
93
-
94
- ensure_current_context();
95
-
96
- glBindTexture(GL_TEXTURE_2D, tex_name_);
97
- glTexSubImage2D(GL_TEXTURE_2D, 0, block.left, block.top, block.width, block.height,
98
- Color::GL_FORMAT, GL_UNSIGNED_BYTE, bmp.data());
99
-
100
- return result;
101
- }
78
+ if (!Rect::covering(*this).contains(Rect { x, y, bitmap.width(), bitmap.height() })) {
79
+ throw std::invalid_argument("Gosu::Texture::insert: Rect exceeds bounds");
80
+ }
102
81
 
103
- void Gosu::Texture::block(unsigned x, unsigned y, unsigned width, unsigned height)
104
- {
105
- allocator_.block(x, y, width, height);
82
+ const OpenGLContext current_context;
83
+ glBindTexture(GL_TEXTURE_2D, m_tex_name);
84
+ glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, bitmap.width(), bitmap.height(), GL_RGBA,
85
+ GL_UNSIGNED_BYTE, bitmap.data());
106
86
  }
107
87
 
108
- void Gosu::Texture::free(unsigned x, unsigned y, unsigned width, unsigned height)
88
+ Gosu::Bitmap Gosu::Texture::to_bitmap(const Rect& rect) const
109
89
  {
110
- allocator_.free(x, y, width, height);
111
- }
90
+ if (!Rect::covering(*this).contains(rect)) {
91
+ throw std::invalid_argument("Gosu::Texture::to_bitmap: Rect exceeds bounds");
92
+ }
112
93
 
113
- Gosu::Bitmap Gosu::Texture::to_bitmap(unsigned x, unsigned y, unsigned width, unsigned height) const
114
- {
115
94
  #ifdef GOSU_IS_OPENGLES
116
95
  // See here for one possible implementation: https://github.com/apitrace/apitrace/issues/70
117
96
  // (Could reuse a lot of code from OffScreenTarget)
118
- throw logic_error("Texture::to_bitmap not supported on iOS");
97
+ throw std::logic_error("Gosu::Texture::to_bitmap not supported in OpenGL ES");
119
98
  #else
120
- ensure_current_context();
121
-
122
- Bitmap full_texture(this->width(), this->height());
123
- glBindTexture(GL_TEXTURE_2D, tex_name());
124
- // TODO: There are ways to retrieve only part of a texture, which we should use sooner or later.
125
- glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, full_texture.data());
126
- Bitmap bitmap(width, height);
127
- bitmap.insert(-int(x), -int(y), full_texture);
128
-
99
+ const OpenGLContext current_context;
100
+ Bitmap bitmap(width(), height());
101
+ glBindTexture(GL_TEXTURE_2D, m_tex_name);
102
+ // This should use glGetTextureSubImage where available: https://stackoverflow.com/a/38148494
103
+ glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, bitmap.data());
104
+
105
+ if (rect != Rect::covering(*this)) {
106
+ Bitmap smaller_bitmap(rect.width, rect.height);
107
+ smaller_bitmap.insert(bitmap, -rect.x, -rect.y);
108
+ bitmap = std::move(smaller_bitmap);
109
+ }
110
+
129
111
  return bitmap;
130
112
  #endif
131
113
  }
data/src/Texture.hpp CHANGED
@@ -1,29 +1,31 @@
1
1
  #pragma once
2
2
 
3
- #include "BlockAllocator.hpp"
4
- #include "GraphicsImpl.hpp"
5
- #include "TexChunk.hpp"
6
3
  #include <Gosu/Fwd.hpp>
7
- #include <Gosu/Bitmap.hpp>
4
+ #include "BinPacker.hpp"
5
+ #include "TexChunk.hpp"
6
+ #include <cstdint>
8
7
  #include <memory>
9
- #include <vector>
10
8
 
11
- class Gosu::Texture : public std::enable_shared_from_this<Texture>
9
+ namespace Gosu
12
10
  {
13
- // BlockAllocator can't be copied or moved, so neither can Texture.
14
- BlockAllocator allocator_;
15
- GLuint tex_name_;
16
- bool retro_;
17
-
18
- public:
19
- Texture(unsigned width, unsigned height, bool retro);
20
- ~Texture();
21
- unsigned width() const;
22
- unsigned height() const;
23
- GLuint tex_name() const;
24
- bool retro() const;
25
- std::unique_ptr<TexChunk> try_alloc(const Bitmap& bmp, unsigned padding);
26
- void block(unsigned x, unsigned y, unsigned width, unsigned height);
27
- void free(unsigned x, unsigned y, unsigned width, unsigned height);
28
- Bitmap to_bitmap(unsigned x, unsigned y, unsigned width, unsigned height) const;
29
- };
11
+ class Texture : public std::enable_shared_from_this<Texture>, private Noncopyable
12
+ {
13
+ BinPacker m_bin_packer;
14
+ std::uint32_t m_tex_name;
15
+ const bool m_retro;
16
+
17
+ public:
18
+ Texture(int width, int height, bool retro);
19
+ ~Texture();
20
+
21
+ int width() const { return m_bin_packer.width(); }
22
+ int height() const { return m_bin_packer.height(); }
23
+ std::uint32_t tex_name() const { return m_tex_name; }
24
+ bool retro() const { return m_retro; }
25
+
26
+ [[nodiscard]] std::unique_ptr<TexChunk> try_alloc(const Bitmap& bitmap, int padding);
27
+
28
+ void insert(const Bitmap& bitmap, int x, int y);
29
+ Bitmap to_bitmap(const Rect& rect) const;
30
+ };
31
+ }
@@ -0,0 +1,150 @@
1
+ #include <Gosu/Bitmap.hpp>
2
+ #include <Gosu/Graphics.hpp>
3
+ #include <Gosu/Math.hpp>
4
+ #include "GraphicsImpl.hpp"
5
+ #include "TiledDrawable.hpp"
6
+ #include <cmath>
7
+ #include <stdexcept>
8
+
9
+ Gosu::TiledDrawable::TiledDrawable(const Bitmap& source, const Rect& source_rect, int tile_size,
10
+ unsigned image_flags)
11
+ : m_width(source_rect.width),
12
+ m_height(source_rect.height)
13
+ {
14
+ if (!Rect::covering(source).contains(source_rect) || source_rect.empty()) {
15
+ throw std::invalid_argument("Invalid TiledDrawable source_rect");
16
+ }
17
+ if (tile_size <= 0) {
18
+ throw std::invalid_argument("tile_size must be greater than 0");
19
+ }
20
+
21
+ // Manually round up during this integer division.
22
+ const int tiles_x = (source_rect.width + tile_size - 1) / tile_size;
23
+ const int tiles_y = (source_rect.height + tile_size - 1) / tile_size;
24
+
25
+ for (int ty = 0; ty < tiles_y; ++ty) {
26
+ for (int tx = 0; tx < tiles_x; ++tx) {
27
+ Rect tile_source_rect { .x = source_rect.x + tx * tile_size,
28
+ .y = source_rect.y + ty * tile_size,
29
+ .width = tile_size,
30
+ .height = tile_size };
31
+ tile_source_rect.clip_to(source_rect);
32
+
33
+ unsigned local_flags = image_flags;
34
+
35
+ // The left edge must always be tileable in all columns except for the first.
36
+ if (tx > 0) {
37
+ local_flags |= IF_TILEABLE_LEFT;
38
+ }
39
+ // The right edge must always be tileable in all columns except for the last.
40
+ if (tx < tiles_x - 1) {
41
+ local_flags |= IF_TILEABLE_RIGHT;
42
+ }
43
+ // The top edge must always be tileable in all rows except for the first.
44
+ if (ty > 0) {
45
+ local_flags |= IF_TILEABLE_TOP;
46
+ }
47
+ // The bottom edge must always be tileable in all rows except for the last.
48
+ if (ty < tiles_y - 1) {
49
+ local_flags |= IF_TILEABLE_BOTTOM;
50
+ }
51
+
52
+ m_tiles.push_back(Tile {
53
+ .x = tile_source_rect.x,
54
+ .y = tile_source_rect.y,
55
+ .data = create_drawable(source, tile_source_rect, local_flags),
56
+ });
57
+ }
58
+ }
59
+ }
60
+
61
+ Gosu::TiledDrawable::TiledDrawable(const TiledDrawable& parent, const Rect& rect)
62
+ : m_width(rect.width),
63
+ m_height(rect.height)
64
+ {
65
+ for (const Tile& tile : parent.m_tiles) {
66
+ // rect is the source area on the parent, tile_rect is this tile's area on the parent.
67
+ Rect tile_rect { tile.x, tile.y, tile.data->width(), tile.data->height() };
68
+ // The x/y source position on the tile...
69
+ int x = 0, y = 0;
70
+ // ...must be adjusted while clipping.
71
+ tile_rect.clip_to(rect, &x, &y);
72
+ // If there is anything left of the tile_rect after clipping, we need to create a tile too.
73
+ if (!tile_rect.empty()) {
74
+ m_tiles.push_back(Tile {
75
+ .x = tile.x - rect.x,
76
+ .y = tile.y - rect.y,
77
+ .data = tile.data->subimage(Rect { x, y, tile_rect.width, tile_rect.height }),
78
+ });
79
+ }
80
+ }
81
+ }
82
+
83
+ void Gosu::TiledDrawable::draw(double x1, double y1, Color c1, double x2, double y2, Color c2,
84
+ double x3, double y3, Color c3, double x4, double y4, Color c4,
85
+ ZPos z, BlendMode mode) const
86
+ {
87
+ normalize_coordinates(x1, y1, x2, y2, x3, y3, c3, x4, y4, c4);
88
+
89
+ double f_width = m_width, f_height = m_height;
90
+ for (const Tile& tile : m_tiles) {
91
+ double rel_x_l = tile.x / f_width;
92
+ double rel_x_r = (tile.x + tile.data->width()) / f_width;
93
+ double rel_y_t = tile.y / f_height;
94
+ double rel_y_b = (tile.y + tile.data->height()) / f_height;
95
+
96
+ using std::lerp;
97
+ // NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
98
+ #define LERP2D(what, x_weight, y_weight) \
99
+ lerp(lerp(what##1, what##3, y_weight), lerp(what##2, what##4, y_weight), x_weight);
100
+
101
+ double x_t_l = LERP2D(x, rel_x_l, rel_y_t);
102
+ double x_t_r = LERP2D(x, rel_x_r, rel_y_t);
103
+ double x_b_l = LERP2D(x, rel_x_l, rel_y_b);
104
+ double x_b_r = LERP2D(x, rel_x_r, rel_y_b);
105
+
106
+ double y_t_l = LERP2D(y, rel_x_l, rel_y_t);
107
+ double y_t_r = LERP2D(y, rel_x_r, rel_y_t);
108
+ double y_b_l = LERP2D(y, rel_x_l, rel_y_b);
109
+ double y_b_r = LERP2D(y, rel_x_r, rel_y_b);
110
+
111
+ Color c_t_l = LERP2D(c, rel_x_l, rel_y_t);
112
+ Color c_t_r = LERP2D(c, rel_x_r, rel_y_t);
113
+ Color c_b_l = LERP2D(c, rel_x_l, rel_y_b);
114
+ Color c_b_r = LERP2D(c, rel_x_r, rel_y_b);
115
+
116
+ tile.data->draw(x_t_l, y_t_l, c_t_l, x_t_r, y_t_r, c_t_r, //
117
+ x_b_l, y_b_l, c_b_l, x_b_r, y_b_r, c_b_r, z, mode);
118
+ }
119
+ }
120
+
121
+ std::unique_ptr<Gosu::Drawable> Gosu::TiledDrawable::subimage(const Rect& source_rect) const
122
+ {
123
+ auto tiled_drawable = std::make_unique<TiledDrawable>(*this, source_rect);
124
+ if (tiled_drawable->m_tiles.size() == 1) {
125
+ // Optimization: If the tiled subimage only contains a single tile, return that.
126
+ return std::move(tiled_drawable->m_tiles[0].data);
127
+ }
128
+ return tiled_drawable;
129
+ }
130
+
131
+ Gosu::Bitmap Gosu::TiledDrawable::to_bitmap() const
132
+ {
133
+ Bitmap bitmap(width(), height());
134
+ for (const Tile& tile : m_tiles) {
135
+ bitmap.insert(tile.data->to_bitmap(), tile.x, tile.y);
136
+ }
137
+ return bitmap;
138
+ }
139
+
140
+ void Gosu::TiledDrawable::insert(const Bitmap& bitmap, int x, int y)
141
+ {
142
+ const Rect target_rect { x, y, bitmap.width(), bitmap.height() };
143
+ for (const Tile& tile : m_tiles) {
144
+ Rect tile_rect { tile.x, tile.y, tile.data->width(), tile.data->height() };
145
+ tile_rect.clip_to(target_rect);
146
+ if (!tile_rect.empty()) {
147
+ tile.data->insert(bitmap, x - tile.x, y - tile.y);
148
+ }
149
+ }
150
+ }
@@ -0,0 +1,47 @@
1
+ #pragma once
2
+
3
+ #include <Gosu/Fwd.hpp>
4
+ #include <Gosu/Drawable.hpp>
5
+ #include <Gosu/Platform.hpp>
6
+ #include <functional>
7
+ #include <memory>
8
+ #include <vector>
9
+
10
+ namespace Gosu
11
+ {
12
+ /// When an image file is too large to be represented by a single OpenGL texture, Gosu automatically
13
+ /// splits it up into a rectangle of tiles instead of throwing an error.
14
+ class TiledDrawable : public Drawable
15
+ {
16
+ int m_width, m_height;
17
+ struct Tile
18
+ {
19
+ int x = 0, y = 0;
20
+ std::unique_ptr<Drawable> data = nullptr;
21
+ };
22
+ std::vector<Tile> m_tiles;
23
+
24
+ public:
25
+ TiledDrawable(const Bitmap& source, const Rect& source_rect, int tile_size,
26
+ unsigned image_flags);
27
+ /// This constructor is used to implement subimage().
28
+ TiledDrawable(const TiledDrawable& parent, const Rect& rect);
29
+
30
+ int width() const override { return m_width; }
31
+ int height() const override { return m_height; }
32
+
33
+ void draw(double x1, double y1, Color c1, //
34
+ double x2, double y2, Color c2, //
35
+ double x3, double y3, Color c3, //
36
+ double x4, double y4, Color c4, //
37
+ ZPos z, BlendMode mode) const override;
38
+
39
+ const GLTexInfo* gl_tex_info() const override { return nullptr; }
40
+
41
+ std::unique_ptr<Drawable> subimage(const Rect& rect) const override;
42
+
43
+ Bitmap to_bitmap() const override;
44
+
45
+ void insert(const Bitmap& bitmap, int x, int y) override;
46
+ };
47
+ }
data/src/TimingApple.cpp CHANGED
@@ -23,7 +23,7 @@ unsigned long Gosu::milliseconds()
23
23
  }();
24
24
 
25
25
  uint64_t runtime = mach_absolute_time() - first_tick;
26
- return runtime * info.numer / info.denom / 1000000;
26
+ return runtime * info.numer / info.denom / 1'000'000;
27
27
  }
28
28
 
29
29
  #endif
data/src/Transform.cpp CHANGED
@@ -1,73 +1,68 @@
1
- // Default matrices, adapted from original Transform support
2
- // contribution by erisdiscord. Thank you!
1
+ // Default matrices, adapted from original Transform support contribution by erisdiscord. Thank you!
3
2
 
4
- #include "GraphicsImpl.hpp"
5
- #include <Gosu/GraphicsBase.hpp>
6
3
  #include <Gosu/Math.hpp>
4
+ #include <Gosu/Transform.hpp>
7
5
  #include <cmath>
8
- using namespace std;
9
6
 
10
- Gosu::Transform Gosu::rotate(double angle, double around_x, double around_y)
7
+ void Gosu::Transform::apply(double& x, double& y) const
11
8
  {
12
- double c = cos(degrees_to_radians(angle));
13
- double s = sin(degrees_to_radians(angle));
14
- Transform result = {
15
- +c, +s, 0, 0,
16
- -s, +c, 0, 0,
17
- 0, 0, 1, 0,
18
- 0, 0, 0, 1
19
- };
20
- if (around_x != 0 || around_y != 0) {
21
- result = concat(concat(translate(-around_x, -around_y), result),
22
- translate(around_x, around_y));
9
+ double in[4] = { x, y, 0, 1 };
10
+ double out[4] = { 0, 0, 0, 0 };
11
+ for (int i = 0; i < 4; ++i) {
12
+ for (int j = 0; j < 4; ++j) {
13
+ out[i] += in[j] * matrix[j * 4 + i];
14
+ }
23
15
  }
24
- return result;
16
+ x = out[0] / out[3];
17
+ y = out[1] / out[3];
25
18
  }
26
19
 
27
- Gosu::Transform Gosu::translate(double x, double y)
20
+ Gosu::Transform Gosu::Transform::translate(double x, double y)
28
21
  {
29
- Transform result = {
30
- 1, 0, 0, 0,
31
- 0, 1, 0, 0,
32
- 0, 0, 1, 0,
33
- x, y, 0, 1
34
- };
35
- return result;
22
+ return Transform { 1, 0, 0, 0, //
23
+ 0, 1, 0, 0, //
24
+ 0, 0, 1, 0, //
25
+ x, y, 0, 1 };
36
26
  }
37
27
 
38
- Gosu::Transform Gosu::scale(double factor)
28
+ Gosu::Transform Gosu::Transform::rotate(double angle)
39
29
  {
40
- Transform result = {
41
- factor, 0, 0, 0,
42
- 0, factor, 0, 0,
43
- 0, 0, 1, 0,
44
- 0, 0, 0, 1
45
- };
46
- return result;
30
+ double c = std::cos(degrees_to_radians(angle));
31
+ double s = std::sin(degrees_to_radians(angle));
32
+ return Transform { +c, +s, 0, 0, //
33
+ -s, +c, 0, 0, //
34
+ 0, 0, 1, 0, //
35
+ 0, 0, 0, 1 };
47
36
  }
48
37
 
49
- Gosu::Transform Gosu::scale(double scale_x, double scale_y, double around_x, double around_y)
38
+ Gosu::Transform Gosu::Transform::scale(double factor)
50
39
  {
51
- Transform result = {
52
- scale_x, 0, 0, 0,
53
- 0, scale_y, 0, 0,
54
- 0, 0, 1, 0,
55
- 0, 0, 0, 1
56
- };
57
- if (around_x != 0 || around_y != 0) {
58
- result = concat(concat(translate(-around_x, -around_y), result),
59
- translate(around_x, around_y));
60
- }
61
- return result;
40
+ return Transform { factor, 0, 0, 0, //
41
+ 0, factor, 0, 0, //
42
+ 0, 0, 1, 0, //
43
+ 0, 0, 0, 1 };
44
+ }
45
+
46
+ Gosu::Transform Gosu::Transform::scale(double scale_x, double scale_y)
47
+ {
48
+ return Transform { scale_x, 0, 0, 0, //
49
+ 0, scale_y, 0, 0, //
50
+ 0, 0, 1, 0, //
51
+ 0, 0, 0, 1 };
52
+ }
53
+
54
+ Gosu::Transform Gosu::Transform::around(double around_x, double around_y) const
55
+ {
56
+ return translate(-around_x, -around_y) * *this * translate(around_x, around_y);
62
57
  }
63
58
 
64
- Gosu::Transform Gosu::concat(const Transform& left, const Transform& right)
59
+ Gosu::Transform Gosu::Transform::operator*(const Transform& rhs) const
65
60
  {
66
- Transform result;
61
+ Transform result { 0 };
67
62
  for (int i = 0; i < 16; ++i) {
68
- result[i] = 0;
63
+ result.matrix[i] = 0;
69
64
  for (int j = 0; j < 4; ++j) {
70
- result[i] += left[i / 4 * 4 + j] * right[i % 4 + j * 4];
65
+ result.matrix[i] += matrix[i / 4 * 4 + j] * rhs.matrix[i % 4 + j * 4];
71
66
  }
72
67
  }
73
68
  return result;