gosu 0.9.2 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (84) hide show
  1. checksums.yaml +4 -4
  2. data/Gosu/Bitmap.hpp +3 -3
  3. data/Gosu/Directories.hpp +6 -3
  4. data/Gosu/Gosu.hpp +0 -1
  5. data/Gosu/GraphicsBase.hpp +12 -8
  6. data/Gosu/Input.hpp +5 -16
  7. data/Gosu/Platform.hpp +1 -0
  8. data/Gosu/Version.hpp +3 -5
  9. data/Gosu/Window.hpp +7 -8
  10. data/README.txt +3 -3
  11. data/ext/gosu/extconf.rb +17 -16
  12. data/ext/gosu/gosu_wrap.cxx +59 -58
  13. data/ext/gosu/gosu_wrap.h +1 -1
  14. data/rdoc/gosu.rb +285 -283
  15. data/src/{MacUtility.hpp → AppleUtility.hpp} +24 -42
  16. data/src/Audio/ALChannelManagement.hpp +1 -1
  17. data/src/Audio/{AudioOpenAL.cpp → Audio.cpp} +6 -7
  18. data/src/Audio/Audio.mm +1 -0
  19. data/src/Audio/AudioFile.hpp +2 -2
  20. data/src/Audio/AudioToolboxFile.hpp +5 -20
  21. data/src/Audio/OggFile.hpp +44 -56
  22. data/src/Audio/SndFile.hpp +2 -2
  23. data/src/Bitmap/Bitmap.cpp +98 -2
  24. data/src/Bitmap/BitmapIO.cpp +156 -0
  25. data/src/DirectoriesApple.mm +76 -0
  26. data/src/DirectoriesUnix.cpp +5 -12
  27. data/src/DirectoriesWin.cpp +5 -0
  28. data/src/Graphics/BlockAllocator.hpp +2 -2
  29. data/src/Graphics/ClipRectStack.hpp +2 -2
  30. data/src/Graphics/Common.hpp +2 -2
  31. data/src/Graphics/DrawOp.hpp +2 -2
  32. data/src/Graphics/DrawOpQueue.hpp +2 -2
  33. data/src/Graphics/Graphics.cpp +7 -2
  34. data/src/Graphics/LargeImageData.cpp +6 -6
  35. data/src/Graphics/LargeImageData.hpp +3 -3
  36. data/src/Graphics/Macro.hpp +2 -2
  37. data/src/Graphics/RenderState.hpp +2 -2
  38. data/src/Graphics/Resolution.cpp +1 -1
  39. data/src/Graphics/TexChunk.hpp +2 -2
  40. data/src/Graphics/Texture.cpp +21 -16
  41. data/src/Graphics/Texture.hpp +7 -5
  42. data/src/Graphics/TransformStack.hpp +2 -2
  43. data/src/Iconv.hpp +2 -2
  44. data/src/Input/Input.cpp +3 -1
  45. data/src/Input/{InputTouch.mm → InputUIKit.mm} +32 -26
  46. data/src/Input/TextInput.cpp +1 -1
  47. data/src/Text/FormattedString.hpp +2 -2
  48. data/src/Text/TextApple.mm +8 -8
  49. data/src/Text/TextMac.cpp +1 -1
  50. data/src/Text/TextUnix.cpp +1 -1
  51. data/src/UIKit/GosuAppDelegate.h +8 -0
  52. data/src/UIKit/GosuAppDelegate.mm +24 -0
  53. data/src/UIKit/GosuGLView.h +8 -0
  54. data/src/UIKit/GosuGLView.mm +130 -0
  55. data/src/UIKit/GosuViewController.h +13 -0
  56. data/src/UIKit/GosuViewController.mm +214 -0
  57. data/src/UtilityApple.mm +5 -18
  58. data/src/Window.cpp +1 -3
  59. data/src/WindowUIKit.mm +124 -0
  60. data/src/stb_image.h +6437 -0
  61. data/src/stb_image_write.h +730 -0
  62. data/src/stb_vorbis.c +5459 -0
  63. metadata +18 -26
  64. data/Gosu/Sockets.hpp +0 -156
  65. data/src/Audio/AudioOpenAL.mm +0 -1
  66. data/src/Bitmap/BitmapApple.mm +0 -226
  67. data/src/Bitmap/BitmapBMP.cpp +0 -79
  68. data/src/Bitmap/BitmapColorKey.cpp +0 -50
  69. data/src/Bitmap/BitmapFreeImage.cpp +0 -174
  70. data/src/Bitmap/BitmapGDIplus.cpp +0 -212
  71. data/src/Bitmap/BitmapUtils.cpp +0 -76
  72. data/src/DirectoriesMac.mm +0 -38
  73. data/src/DirectoriesTouch.mm +0 -38
  74. data/src/GosuView.hpp +0 -15
  75. data/src/GosuView.mm +0 -208
  76. data/src/Input/AccelerometerReader.hpp +0 -10
  77. data/src/Input/AccelerometerReader.mm +0 -31
  78. data/src/Sockets/CommSocket.cpp +0 -305
  79. data/src/Sockets/ListenerSocket.cpp +0 -59
  80. data/src/Sockets/MessageSocket.cpp +0 -128
  81. data/src/Sockets/Socket.cpp +0 -145
  82. data/src/Sockets/Socket.hpp +0 -66
  83. data/src/WindowTouch.mm +0 -243
  84. data/src/X11vroot.h +0 -118
@@ -1,75 +1,57 @@
1
- #ifndef GOSU_MACUTILITY_HPP
2
- #define GOSU_MACUTILITY_HPP
1
+ #ifndef GOSU_APPLEUTILITY_HPP
2
+ #define GOSU_APPLEUTILITY_HPP
3
3
 
4
4
  #include <Gosu/Platform.hpp>
5
5
 
6
- #import <CoreFoundation/CoreFoundation.h>
7
-
8
- #ifndef GOSU_IS_IPHONE
9
- #import <ApplicationServices/ApplicationServices.h>
10
-
11
- // Not defined on 10.4 Tiger SDK which Gosu uses.
12
- #if __LP64__ || NS_BUILD_32_LIKE_64
13
- typedef long NSInteger;
14
- typedef unsigned long NSUInteger;
15
- #else
16
- typedef int NSInteger;
17
- typedef unsigned int NSUInteger;
18
- #endif
19
- #endif
6
+ #ifdef __OBJC__
20
7
 
21
8
  #include <iostream>
22
9
  #include <ostream>
23
10
  #include <sstream>
24
11
  #include <string>
25
12
  #include <stdexcept>
13
+ #include <objc/objc.h>
14
+ #import <CoreFoundation/CoreFoundation.h>
15
+ #import <Foundation/Foundation.h>
26
16
 
27
17
  namespace Gosu
28
18
  {
29
19
  inline void throwOSError(OSStatus status, unsigned line)
30
20
  {
21
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
22
+ NSError *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:status userInfo:nil];
31
23
  std::ostringstream str;
32
- #ifdef GOSU_IS_IPHONE
33
- str << "Error on line " << line << " (Code " << status << ")";
34
- #else
35
24
  str << "Error on line " << line << " (Code " << status << "): "
36
- << GetMacOSStatusErrorString(status)
37
- << " (" << GetMacOSStatusCommentString(status) << ")";
38
- #endif
25
+ << [[error localizedDescription] UTF8String]
26
+ << " (" << [[error description] UTF8String] << ")";
27
+ [pool release];
39
28
  throw std::runtime_error(str.str());
40
29
  }
41
30
 
42
31
  #define CHECK_OS(status) if (!(status)) {} else Gosu::throwOSError(status, __LINE__)
43
- }
44
32
 
45
- #ifdef __OBJC__
46
- #import <objc/objc.h>
47
- #import <stdexcept>
48
- namespace Gosu
49
- {
50
33
  template<typename T>
51
- class ObjRef
34
+ class ObjCRef
52
35
  {
53
- ObjRef(const ObjRef&);
54
- ObjRef& operator=(const ObjRef&);
36
+ ObjCRef(const ObjCRef&);
37
+ ObjCRef& operator=(const ObjCRef&);
55
38
 
56
39
  T* ptr;
40
+
57
41
  public:
58
- ObjRef(T* ptr = nil)
42
+ ObjCRef(T* ptr = nil)
59
43
  : ptr(ptr)
60
44
  {
61
45
  }
62
46
 
63
- ~ObjRef()
47
+ ~ObjCRef()
64
48
  {
65
- if (ptr)
66
- [ptr release];
49
+ [ptr release];
67
50
  }
68
51
 
69
52
  void reset(T* newPtr = nil)
70
53
  {
71
- if (ptr)
72
- [ptr release];
54
+ [ptr release];
73
55
  ptr = newPtr;
74
56
  }
75
57
 
@@ -81,7 +63,7 @@ namespace Gosu
81
63
  T* obj() const
82
64
  {
83
65
  if (!ptr)
84
- throw std::logic_error("Tried dereferencing nil");
66
+ throw std::logic_error("Objective-C reference is nil");
85
67
  return ptr;
86
68
  }
87
69
  };
@@ -104,21 +86,21 @@ namespace Gosu
104
86
  {
105
87
  }
106
88
 
107
- CFRef()
89
+ ~CFRef()
108
90
  {
109
91
  if (ref)
110
92
  CFRelease(ref);
111
93
  }
112
94
 
113
- CFRefType get()
95
+ CFRefType get() const
114
96
  {
115
97
  return ref;
116
98
  }
117
99
 
118
- CFRefType obj()
100
+ CFRefType obj() const
119
101
  {
120
102
  if (!ref)
121
- throw std::logic_error("CF reference invalid (null)");
103
+ throw std::logic_error("CoreFoundation reference is NULL");
122
104
  return ref;
123
105
  }
124
106
  };
@@ -2,7 +2,7 @@
2
2
  #ifdef GOSU_IS_MAC
3
3
  #include <OpenAL/al.h>
4
4
  #include <OpenAL/alc.h>
5
- #include "../MacUtility.hpp"
5
+ #include "../AppleUtility.hpp"
6
6
  #else
7
7
  #include <AL/al.h>
8
8
  #include <AL/alc.h>
@@ -57,9 +57,9 @@ namespace
57
57
 
58
58
  // TODO: What is this NSAutoreleasePool good for?
59
59
  #ifdef GOSU_IS_MAC
60
- #include "../MacUtility.hpp"
60
+ #include "../AppleUtility.hpp"
61
61
  #define CONSTRUCTOR_COMMON \
62
- ObjRef<NSAutoreleasePool> pool([[NSAutoreleasePool alloc] init]); \
62
+ ObjCRef<NSAutoreleasePool> pool([NSAutoreleasePool new]); \
63
63
  if (!alChannelManagement.get()) \
64
64
  alChannelManagement.reset(new ALChannelManagement)
65
65
  #else
@@ -133,7 +133,6 @@ void Gosu::SampleInstance::changePan(double pan)
133
133
  ALuint source = alChannelManagement->sourceIfStillPlaying(handle, extra);
134
134
  if (source == ALChannelManagement::NO_SOURCE)
135
135
  return;
136
- // TODO: This is not the old panning behavior!
137
136
  alSource3f(source, AL_POSITION, pan * 10, 0, 0);
138
137
  }
139
138
 
@@ -273,7 +272,7 @@ public:
273
272
  // AVAudioPlayer impl
274
273
  class Gosu::Song::ModuleData : public BaseData
275
274
  {
276
- ObjRef<AVAudioPlayer> player;
275
+ ObjCRef<AVAudioPlayer> player;
277
276
 
278
277
  void applyVolume()
279
278
  {
@@ -284,9 +283,9 @@ public:
284
283
  ModuleData(const std::wstring& filename)
285
284
  {
286
285
  std::string utf8Filename = Gosu::wstringToUTF8(filename);
287
- ObjRef<NSString> nsFilename([[NSString alloc] initWithUTF8String: utf8Filename.c_str()]);
288
- ObjRef<NSURL> url([[NSURL alloc] initFileURLWithPath: nsFilename.obj()]);
289
- player.reset([[AVAudioPlayer alloc] initWithContentsOfURL: url.obj() error: NULL]);
286
+ ObjCRef<NSString> nsFilename([[NSString alloc] initWithUTF8String:utf8Filename.c_str()]);
287
+ ObjCRef<NSURL> url([[NSURL alloc] initFileURLWithPath:nsFilename.obj()]);
288
+ player.reset([[AVAudioPlayer alloc] initWithContentsOfURL:url.obj() error:NULL]);
290
289
  }
291
290
 
292
291
  void play(bool looping)
@@ -0,0 +1 @@
1
+ #include "Audio.cpp"
@@ -1,5 +1,5 @@
1
- #ifndef GOSUIMPL_AUDIO_AUDIOFILE_HPP
2
- #define GOSUIMPL_AUDIO_AUDIOFILE_HPP
1
+ #ifndef GOSU_SRC_AUDIO_AUDIOFILE_HPP
2
+ #define GOSU_SRC_AUDIO_AUDIOFILE_HPP
3
3
 
4
4
  #include <vector>
5
5
  #include <Gosu/Platform.hpp>
@@ -1,5 +1,5 @@
1
- #ifndef GOSU_AUDIO_AUDIOFILE_MAC_HPP
2
- #define GOSU_AUDIO_AUDIOFILE_MAC_HPP
1
+ #ifndef GOSU_SRC_AUDIO_AUDIOFILE_MAC_HPP
2
+ #define GOSU_SRC_AUDIO_AUDIOFILE_MAC_HPP
3
3
 
4
4
  #include "AudioFile.hpp"
5
5
  #include <AudioToolbox/AudioToolbox.h>
@@ -9,7 +9,7 @@
9
9
  #include <Gosu/IO.hpp>
10
10
  #include <Gosu/Utility.hpp>
11
11
  #include <Gosu/Platform.hpp>
12
- #include "../MacUtility.hpp"
12
+ #include "../AppleUtility.hpp"
13
13
  #include <algorithm>
14
14
  #include <vector>
15
15
  #include <arpa/inet.h>
@@ -141,24 +141,9 @@ namespace Gosu
141
141
  public:
142
142
  AudioToolboxFile(const std::wstring& filename)
143
143
  {
144
- ObjRef<NSString> utf8Filename([[NSString alloc] initWithUTF8String: wstringToUTF8(filename).c_str()]);
145
- ObjRef<NSURL> url([[NSURL alloc] initFileURLWithPath: utf8Filename.get()]);
146
- #ifdef GOSU_IS_IPHONE
144
+ ObjCRef<NSString> utf8Filename([[NSString alloc] initWithUTF8String:wstringToUTF8(filename).c_str()]);
145
+ ObjCRef<NSURL> url([[NSURL alloc] initFileURLWithPath:utf8Filename.get()]);
147
146
  CHECK_OS(ExtAudioFileOpenURL((CFURLRef)url.get(), &file_));
148
- #else
149
- // Use FSRef for compatibility with 10.4 Tiger.
150
- FSRef fsRef;
151
- CFURLGetFSRef(reinterpret_cast<CFURLRef>(url.get()), &fsRef);
152
- try
153
- {
154
- CHECK_OS(ExtAudioFileOpen(&fsRef, &file_));
155
- }
156
- catch (const std::runtime_error&)
157
- {
158
- throw std::runtime_error("Unsupported audio file type (" +
159
- Gosu::wstringToUTF8(filename) + ")");
160
- }
161
- #endif
162
147
 
163
148
  fileID_ = 0;
164
149
 
@@ -1,11 +1,14 @@
1
- #ifndef GOSUIMPL_AUDIO_OGGFILE_HPP
2
- #define GOSUIMPL_AUDIO_OGGFILE_HPP
1
+ #ifndef GOSU_SRC_AUDIO_OGGFILE_HPP
2
+ #define GOSU_SRC_AUDIO_OGGFILE_HPP
3
3
 
4
4
  #include "AudioFile.hpp"
5
5
  #include <Gosu/IO.hpp>
6
- #include <vorbis/vorbisfile.h>
7
6
  #include <algorithm>
8
7
  #include <stdexcept>
8
+ #include <sstream>
9
+
10
+ #define STB_VORBIS_HEADER_ONLY
11
+ #include "../stb_vorbis.c"
9
12
 
10
13
  // Based on the Drama Sound Engine for D
11
14
 
@@ -13,58 +16,55 @@ namespace Gosu
13
16
  {
14
17
  class OggFile : public AudioFile
15
18
  {
19
+ Gosu::Buffer contents_;
16
20
  Gosu::Buffer buffer_;
17
- Gosu::Reader reader_;
18
- ALenum format_;
21
+ int channels_;
19
22
  ALenum sampleRate_;
20
- OggVorbis_File file_;
23
+ stb_vorbis* stream_;
21
24
 
22
- // extern "C"
23
- static std::size_t readCallback(void* ptr, std::size_t size, std::size_t nmemb, void* datasource)
24
- {
25
- OggFile* oggFile = static_cast<OggFile*>(datasource);
26
- size = std::min(size * nmemb,
27
- oggFile->buffer_.size() - oggFile->reader_.position());
28
- oggFile->reader_.read(ptr, size);
29
- return size;
30
- }
31
-
32
- void setup()
25
+ void open()
33
26
  {
34
- static const ov_callbacks cbs = { readCallback, 0, 0, 0 };
35
- ov_open_callbacks(this, &file_, 0, 0, cbs);
27
+ int error = 0;
36
28
 
37
- vorbis_info* info = ov_info(&file_, -1); // -1 is current bitstream
38
- if (ov_streams(&file_) != 1)
39
- throw std::runtime_error("multi-stream vorbis files not supported");
29
+ const unsigned char *mem = static_cast<const unsigned char*>(contents_.data());
30
+ stream_ = stb_vorbis_open_memory(mem, contents_.size(), &error, 0);
40
31
 
41
- format_ = info->channels == 1 ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16;
42
- sampleRate_ = info->rate;
32
+ if (stream_ == 0)
33
+ {
34
+ std::ostringstream message;
35
+ message << "Cannot open Ogg Vorbis file, error code: " << error;
36
+ throw std::runtime_error(message.str());
37
+ }
38
+
39
+ stb_vorbis_info info = stb_vorbis_get_info(stream_);
40
+ channels_ = info.channels;
41
+ sampleRate_ = info.sample_rate;
42
+ buffer_.resize(info.temp_memory_required);
43
43
  }
44
44
 
45
- void teardown()
45
+ void close()
46
46
  {
47
- ov_clear(&file_);
47
+ stb_vorbis_close(stream_);
48
+ stream_ = 0;
48
49
  }
49
50
 
50
51
  public:
51
52
  OggFile(Gosu::Reader reader)
52
- : reader_(buffer_.frontReader())
53
53
  {
54
- buffer_.resize(reader.resource().size() - reader.position());
55
- reader.read(buffer_.data(), buffer_.size());
54
+ contents_.resize(reader.resource().size() - reader.position());
55
+ reader.read(contents_.data(), contents_.size());
56
56
 
57
- setup();
57
+ open();
58
58
  }
59
59
 
60
60
  ~OggFile()
61
61
  {
62
- teardown();
62
+ close();
63
63
  }
64
64
 
65
65
  ALenum format() const
66
66
  {
67
- return format_;
67
+ return (channels_ == 1 ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16);
68
68
  }
69
69
 
70
70
  ALuint sampleRate() const
@@ -74,38 +74,26 @@ namespace Gosu
74
74
 
75
75
  std::size_t readData(void* dest, std::size_t length)
76
76
  {
77
- static const unsigned OGG_ENDIANNESS =
78
- #ifdef GOSU_IS_BIG_ENDIAN
79
- 1;
80
- #else
81
- 0;
82
- #endif
77
+ int samples = 0;
78
+ int maxSamples = length / sizeof(short);
83
79
 
84
- char* ptr = static_cast<char*>(dest);
85
- std::size_t size = 0;
86
- int result;
87
- int section;
88
- while (size < length)
89
- {
90
- result = ov_read(&file_, ptr + size, length - size,
91
- OGG_ENDIANNESS, 2 /* 16-bit */,
92
- 1 /* signed */, &section);
93
- if (result > 0)
94
- size += result;
95
- else if (result < 0)
96
- throw std::runtime_error("error reading vorbis stream");
97
- else
80
+ while (samples < maxSamples) {
81
+ int samplesPerChannel =
82
+ stb_vorbis_get_samples_short_interleaved(stream_, channels_,
83
+ static_cast<short*>(dest) + samples, maxSamples - samples);
84
+
85
+ if (samplesPerChannel == 0)
98
86
  break;
87
+
88
+ samples += samplesPerChannel * channels_;
99
89
  }
100
90
 
101
- return size;
91
+ return samples * sizeof(short);
102
92
  }
103
93
 
104
94
  void rewind()
105
95
  {
106
- teardown();
107
- reader_ = buffer_.frontReader();
108
- setup();
96
+ stb_vorbis_seek_start(stream_);
109
97
  }
110
98
  };
111
99
  }
@@ -1,5 +1,5 @@
1
- #ifndef GOSUIMPL_AUDIO_SNDFILE_HPP
2
- #define GOSUIMPL_AUDIO_SNDFILE_HPP
1
+ #ifndef GOSU_SRC_AUDIO_SNDFILE_HPP
2
+ #define GOSU_SRC_AUDIO_SNDFILE_HPP
3
3
 
4
4
  #include <Gosu/Audio.hpp>
5
5
  #include <Gosu/Platform.hpp>
@@ -14,7 +14,7 @@ void Gosu::Bitmap::resize(unsigned width, unsigned height, Color c)
14
14
  {
15
15
  if (width == w && height == h)
16
16
  return;
17
-
17
+
18
18
  Bitmap temp(width, height, c);
19
19
  temp.insert(*this, 0, 0);
20
20
  swap(temp);
@@ -39,7 +39,7 @@ void Gosu::Bitmap::insert(const Bitmap& source, int x, int y, unsigned srcX,
39
39
  unsigned srcY, unsigned srcWidth, unsigned srcHeight)
40
40
  {
41
41
  // TODO: This should use memcpy if possible (x == 0 && srcWidth == this->width())
42
-
42
+
43
43
  if (x < 0)
44
44
  {
45
45
  unsigned clipLeft = -x;
@@ -85,3 +85,99 @@ void Gosu::Bitmap::insert(const Bitmap& source, int x, int y, unsigned srcX,
85
85
  setPixel(x + relX, y + relY,
86
86
  source.getPixel(srcX + relX, srcY + relY));
87
87
  }
88
+
89
+ void Gosu::applyColorKey(Bitmap& bitmap, Color key)
90
+ {
91
+ std::vector<Color> surroundingColors;
92
+ surroundingColors.reserve(4);
93
+
94
+ for (unsigned y = 0; y < bitmap.height(); ++y)
95
+ for (unsigned x = 0; x < bitmap.width(); ++x)
96
+ if (bitmap.getPixel(x, y) == key)
97
+ {
98
+ surroundingColors.clear();
99
+ if (x > 0 && bitmap.getPixel(x - 1, y) != key)
100
+ surroundingColors.push_back(bitmap.getPixel(x - 1, y));
101
+ if (x < bitmap.width() - 1 && bitmap.getPixel(x + 1, y) != key)
102
+ surroundingColors.push_back(bitmap.getPixel(x + 1, y));
103
+ if (y > 0 && bitmap.getPixel(x, y - 1) != key)
104
+ surroundingColors.push_back(bitmap.getPixel(x, y - 1));
105
+ if (y < bitmap.height() - 1 && bitmap.getPixel(x, y + 1) != key)
106
+ surroundingColors.push_back(bitmap.getPixel(x, y + 1));
107
+
108
+ if (surroundingColors.empty())
109
+ {
110
+ bitmap.setPixel(x, y, Color::NONE);
111
+ continue;
112
+ }
113
+
114
+ unsigned red = 0, green = 0, blue = 0;
115
+ for (unsigned i = 0; i < surroundingColors.size(); ++i)
116
+ {
117
+ red += surroundingColors[i].red();
118
+ green += surroundingColors[i].green();
119
+ blue += surroundingColors[i].blue();
120
+ }
121
+ bitmap.setPixel(x, y, Color(0, red / surroundingColors.size(),
122
+ green / surroundingColors.size(), blue / surroundingColors.size()));
123
+ }
124
+ }
125
+
126
+ void Gosu::unapplyColorKey(Bitmap& bitmap, Color color)
127
+ {
128
+ Color* p = bitmap.data();
129
+ for (int i = bitmap.width() * bitmap.height(); i > 0; --i, ++p)
130
+ if (p->alpha() == 0)
131
+ *p = color;
132
+ else
133
+ p->setAlpha(255);
134
+ }
135
+
136
+ void Gosu::applyBorderFlags(Bitmap& dest, const Bitmap& source,
137
+ unsigned srcX, unsigned srcY, unsigned srcWidth, unsigned srcHeight,
138
+ unsigned imageFlags)
139
+ {
140
+ // Backwards compatibility: This used to be 'bool tileable'.
141
+ if (imageFlags == 1)
142
+ imageFlags = ifTileable;
143
+
144
+ dest.resize(srcWidth + 2, srcHeight + 2);
145
+
146
+ // The borders are made "harder" by duplicating the original bitmap's
147
+ // borders.
148
+
149
+ // Top.
150
+ if (imageFlags & ifTileableTop)
151
+ dest.insert(source, 1, 0, srcX, srcY, srcWidth, 1);
152
+ // Bottom.
153
+ if (imageFlags & ifTileableBottom)
154
+ dest.insert(source, 1, dest.height() - 1,
155
+ srcX, srcY + srcHeight - 1, srcWidth, 1);
156
+ // Left.
157
+ if (imageFlags & ifTileableLeft)
158
+ dest.insert(source, 0, 1, srcX, srcY, 1, srcHeight);
159
+ // Right.
160
+ if (imageFlags & ifTileableRight)
161
+ dest.insert(source, dest.width() - 1, 1,
162
+ srcX + srcWidth - 1, srcY, 1, srcHeight);
163
+
164
+ // Top left.
165
+ if ((imageFlags & ifTileableTop) && (imageFlags & ifTileableLeft))
166
+ dest.setPixel(0, 0,
167
+ source.getPixel(srcX, srcY));
168
+ // Top right.
169
+ if ((imageFlags & ifTileableTop) && (imageFlags & ifTileableRight))
170
+ dest.setPixel(dest.width() - 1, 0,
171
+ source.getPixel(srcX + srcWidth - 1, srcY));
172
+ // Bottom left.
173
+ if ((imageFlags & ifTileableBottom) && (imageFlags & ifTileableLeft))
174
+ dest.setPixel(0, dest.height() - 1,
175
+ source.getPixel(srcX, srcY + srcHeight - 1));
176
+ // Bottom right.
177
+ if ((imageFlags & ifTileableBottom) && (imageFlags & ifTileableRight))
178
+ dest.setPixel(dest.width() - 1, dest.height() - 1,
179
+ source.getPixel(srcX + srcWidth - 1, srcY + srcHeight - 1));
180
+
181
+ // Now put the final image into the prepared borders.
182
+ dest.insert(source, 1, 1, srcX, srcY, srcWidth, srcHeight);
183
+ }