gosu 0.10.9.pre1 → 0.11.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (136) hide show
  1. checksums.yaml +4 -4
  2. data/Gosu/Audio.hpp +35 -66
  3. data/Gosu/AutoLink.hpp +14 -16
  4. data/Gosu/Bitmap.hpp +50 -37
  5. data/Gosu/Buttons.hpp +246 -265
  6. data/Gosu/Color.hpp +32 -76
  7. data/Gosu/Directories.hpp +14 -17
  8. data/Gosu/Font.hpp +28 -34
  9. data/Gosu/Fwd.hpp +27 -31
  10. data/Gosu/Gosu.hpp +2 -5
  11. data/Gosu/Graphics.hpp +31 -48
  12. data/Gosu/GraphicsBase.hpp +27 -58
  13. data/Gosu/IO.hpp +44 -56
  14. data/Gosu/Image.hpp +29 -73
  15. data/Gosu/ImageData.hpp +13 -17
  16. data/Gosu/Input.hpp +42 -57
  17. data/Gosu/Inspection.hpp +2 -6
  18. data/Gosu/Math.hpp +32 -38
  19. data/Gosu/Platform.hpp +10 -29
  20. data/Gosu/Text.hpp +30 -39
  21. data/Gosu/TextInput.hpp +29 -36
  22. data/Gosu/Timing.hpp +14 -16
  23. data/Gosu/Utility.hpp +10 -15
  24. data/Gosu/Version.hpp +13 -14
  25. data/Gosu/Window.hpp +53 -68
  26. data/README.md +23 -11
  27. data/ext/gosu/extconf.rb +31 -81
  28. data/lib/gosu/patches.rb +35 -19
  29. data/lib/gosu/run.rb +13 -4
  30. data/rdoc/gosu.rb +24 -20
  31. data/src/ALChannelManagement.hpp +119 -0
  32. data/src/{Audio/Audio.cpp → Audio.cpp} +177 -211
  33. data/src/AudioFile.hpp +57 -0
  34. data/src/AudioToolboxFile.hpp +214 -0
  35. data/src/Bitmap.cpp +159 -0
  36. data/src/BitmapIO.cpp +141 -0
  37. data/src/BlockAllocator.cpp +133 -0
  38. data/src/{Graphics/BlockAllocator.hpp → BlockAllocator.hpp} +34 -35
  39. data/src/ClipRectStack.hpp +87 -0
  40. data/src/{Graphics/Color.cpp → Color.cpp} +30 -28
  41. data/src/DirectoriesApple.cpp +68 -0
  42. data/src/DirectoriesUnix.cpp +20 -18
  43. data/src/DirectoriesWin.cpp +40 -41
  44. data/src/DrawOp.hpp +168 -0
  45. data/src/DrawOpQueue.hpp +190 -0
  46. data/src/FileUnix.cpp +40 -46
  47. data/src/FileWin.cpp +42 -38
  48. data/src/Font.cpp +165 -0
  49. data/src/{Text/FormattedString.hpp → FormattedString.hpp} +114 -114
  50. data/src/GosuAppDelegate.cpp +30 -0
  51. data/src/{UIKit/GosuAppDelegate.h → GosuAppDelegate.h} +0 -0
  52. data/src/{UIKit/GosuGLView.mm → GosuGLView.cpp} +22 -17
  53. data/src/{UIKit/GosuGLView.h → GosuGLView.h} +0 -0
  54. data/src/GosuViewController.cpp +231 -0
  55. data/src/{UIKit/GosuViewController.h → GosuViewController.h} +0 -0
  56. data/src/Graphics.cpp +464 -0
  57. data/src/{Graphics/Common.hpp → GraphicsImpl.hpp} +29 -32
  58. data/src/IO.cpp +17 -16
  59. data/src/Iconv.hpp +13 -22
  60. data/src/Image.cpp +142 -0
  61. data/src/Input.cpp +459 -0
  62. data/src/InputUIKit.cpp +197 -0
  63. data/src/Inspection.cpp +4 -5
  64. data/src/LargeImageData.cpp +151 -0
  65. data/src/LargeImageData.hpp +43 -0
  66. data/src/{Graphics/Macro.cpp → Macro.cpp} +77 -78
  67. data/src/Macro.hpp +30 -0
  68. data/src/Math.cpp +17 -29
  69. data/src/{Audio/OggFile.hpp → OggFile.hpp} +19 -24
  70. data/src/RenderState.hpp +205 -0
  71. data/src/Resolution.cpp +86 -0
  72. data/src/ResolutionApple.cpp +25 -0
  73. data/{ext/gosu/gosu_wrap.cxx → src/RubyGosu.cxx} +2256 -1707
  74. data/{ext/gosu/gosu_wrap.h → src/RubyGosu.h} +9 -9
  75. data/src/{Audio/SndFile.hpp → SndFile.hpp} +54 -43
  76. data/src/TexChunk.cpp +117 -0
  77. data/src/{Graphics/TexChunk.hpp → TexChunk.hpp} +13 -18
  78. data/src/Text.cpp +371 -0
  79. data/src/TextApple.cpp +209 -0
  80. data/src/TextInput.cpp +278 -0
  81. data/src/TextTTFWin.cpp +251 -0
  82. data/src/{Text/TextUnix.cpp → TextUnix.cpp} +96 -92
  83. data/src/TextWin.cpp +194 -0
  84. data/src/{Graphics/Texture.cpp → Texture.cpp} +35 -38
  85. data/src/{Graphics/Texture.hpp → Texture.hpp} +9 -13
  86. data/src/TimingApple.cpp +11 -7
  87. data/src/TimingUnix.cpp +13 -7
  88. data/src/TimingWin.cpp +6 -1
  89. data/src/{Graphics/Transform.cpp → Transform.cpp} +17 -12
  90. data/src/{Graphics/TransformStack.hpp → TransformStack.hpp} +24 -25
  91. data/src/Utility.cpp +29 -70
  92. data/src/UtilityApple.cpp +52 -0
  93. data/src/UtilityWin.cpp +7 -4
  94. data/src/Version.cpp +22 -0
  95. data/src/WinMain.cpp +30 -33
  96. data/src/WinUtility.cpp +24 -22
  97. data/src/WinUtility.hpp +11 -20
  98. data/src/Window.cpp +142 -112
  99. data/src/WindowUIKit.cpp +155 -0
  100. data/src/stb_image.h +384 -173
  101. data/src/stb_vorbis.c +20 -18
  102. metadata +60 -62
  103. data/Gosu/TR1.hpp +0 -56
  104. data/src/AppleUtility.hpp +0 -66
  105. data/src/Audio/ALChannelManagement.hpp +0 -114
  106. data/src/Audio/Audio.mm +0 -1
  107. data/src/Audio/AudioFile.hpp +0 -53
  108. data/src/Audio/AudioToolboxFile.hpp +0 -207
  109. data/src/Bitmap/Bitmap.cpp +0 -183
  110. data/src/Bitmap/BitmapIO.cpp +0 -176
  111. data/src/DirectoriesApple.mm +0 -71
  112. data/src/Graphics/BlockAllocator.cpp +0 -142
  113. data/src/Graphics/ClipRectStack.hpp +0 -93
  114. data/src/Graphics/DrawOp.hpp +0 -175
  115. data/src/Graphics/DrawOpQueue.hpp +0 -188
  116. data/src/Graphics/Graphics.cpp +0 -478
  117. data/src/Graphics/Image.cpp +0 -193
  118. data/src/Graphics/LargeImageData.cpp +0 -133
  119. data/src/Graphics/LargeImageData.hpp +0 -46
  120. data/src/Graphics/Macro.hpp +0 -36
  121. data/src/Graphics/RenderState.hpp +0 -211
  122. data/src/Graphics/Resolution.cpp +0 -91
  123. data/src/Graphics/ResolutionApple.mm +0 -19
  124. data/src/Graphics/TexChunk.cpp +0 -112
  125. data/src/Input/Input.cpp +0 -463
  126. data/src/Input/InputUIKit.mm +0 -190
  127. data/src/Input/TextInput.cpp +0 -261
  128. data/src/Text/Font.cpp +0 -175
  129. data/src/Text/Text.cpp +0 -391
  130. data/src/Text/TextApple.mm +0 -227
  131. data/src/Text/TextTTFWin.cpp +0 -249
  132. data/src/Text/TextWin.cpp +0 -186
  133. data/src/UIKit/GosuAppDelegate.mm +0 -24
  134. data/src/UIKit/GosuViewController.mm +0 -211
  135. data/src/UtilityApple.mm +0 -63
  136. data/src/WindowUIKit.mm +0 -139
@@ -1,100 +1,94 @@
1
+ #include <Gosu/Platform.hpp>
2
+ #if !defined(GOSU_IS_WIN)
3
+
1
4
  #include <Gosu/IO.hpp>
2
5
  #include <Gosu/Utility.hpp>
3
- #include <stdexcept>
4
6
  #include <cstring>
5
7
  #include <fcntl.h>
6
- #include <unistd.h>
7
- #include <sys/types.h>
8
+ #include <stdexcept>
8
9
  #include <sys/mman.h>
10
+ #include <sys/types.h>
11
+ #include <unistd.h>
9
12
 
10
13
  #ifdef HAVE_SYS_STAT_H
11
14
  #include <sys/stat.h>
12
15
  #endif
13
16
 
14
- namespace
15
- {
16
- // According to my man page, Unix folks just don't trust the 0, it's got to be a crippled -1.
17
- void* const noMapping = reinterpret_cast<void*>(-1);
18
- }
19
-
20
17
  struct Gosu::File::Impl
21
18
  {
22
- int fd;
23
- void* mapping;
19
+ int fd = -1;
20
+ void* mapping = MAP_FAILED;
24
21
 
25
- Impl() : fd(-1), mapping(noMapping) {}
26
22
  ~Impl()
27
23
  {
28
- if (fd > 0)
24
+ if (fd >= 0) {
29
25
  close(fd);
26
+ }
30
27
  }
31
28
  };
32
29
 
33
- Gosu::File::File(const std::wstring& filename, FileMode mode)
30
+ Gosu::File::File(const std::string& filename, FileMode mode)
34
31
  : pimpl(new Impl)
35
32
  {
36
33
  int flags;
37
34
 
38
- switch (mode)
39
- {
40
- case fmRead:
35
+ switch (mode) {
36
+ case FM_READ:
41
37
  flags = O_RDONLY;
42
38
  break;
43
- case fmReplace:
39
+ case FM_REPLACE:
44
40
  flags = O_RDWR | O_TRUNC | O_CREAT;
45
41
  break;
46
- case fmAlter:
42
+ case FM_ALTER:
47
43
  flags = O_RDWR | O_CREAT;
48
44
  break;
49
45
  }
50
46
 
51
47
  // TODO: Locking flags?
52
48
 
53
- pimpl->fd = open(narrow(filename).c_str(), flags,
54
- S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
55
- if (pimpl->fd < 0)
56
- throw std::runtime_error("Cannot open file " + narrow(filename));
49
+ pimpl->fd = open(filename.c_str(), flags, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
50
+ if (pimpl->fd < 0) {
51
+ throw std::runtime_error("Cannot open file " + filename);
52
+ }
57
53
 
58
- if (mode == fmRead && size() > 0)
59
- pimpl->mapping = mmap(0, size(), PROT_READ, 0, pimpl->fd, 0);
54
+ if (mode == FM_READ && size() > 0) {
55
+ pimpl->mapping = mmap(nullptr, size(), PROT_READ, 0, pimpl->fd, 0);
56
+ }
60
57
  }
61
58
 
62
59
  Gosu::File::~File()
63
60
  {
64
- if (pimpl->mapping != noMapping)
61
+ if (pimpl->mapping != MAP_FAILED) {
65
62
  munmap(pimpl->mapping, size());
63
+ }
66
64
  }
67
65
 
68
66
  std::size_t Gosu::File::size() const
69
67
  {
70
- // IMPR: Error checking?
68
+ // TODO: Error checking?
71
69
  return lseek(pimpl->fd, 0, SEEK_END);
72
70
  }
73
71
 
74
- void Gosu::File::resize(std::size_t newSize)
75
- {
76
- ftruncate(pimpl->fd, newSize);
77
- }
72
+ void Gosu::File::resize(std::size_t new_size) { ftruncate(pimpl->fd, new_size); }
78
73
 
79
- void Gosu::File::read(std::size_t offset, std::size_t length,
80
- void* destBuffer) const
74
+ void Gosu::File::read(std::size_t offset, std::size_t length, void* dest_buffer) const
81
75
  {
82
- // TODO: err checking
83
- if (pimpl->mapping != noMapping)
84
- {
85
- std::memcpy(destBuffer, static_cast<const char*>(pimpl->mapping) + offset, length);
86
- return;
76
+ // TODO: Bounds checks?
77
+ if (pimpl->mapping != MAP_FAILED) {
78
+ std::memcpy(dest_buffer, static_cast<const char*>(pimpl->mapping) + offset, length);
79
+ }
80
+ else {
81
+ // TODO: Error checking?
82
+ lseek(pimpl->fd, offset, SEEK_SET);
83
+ ::read(pimpl->fd, dest_buffer, length);
87
84
  }
88
-
89
- // IMPR: Error checking?
90
- lseek(pimpl->fd, offset, SEEK_SET);
91
- ::read(pimpl->fd, destBuffer, length);
92
85
  }
93
86
 
94
- void Gosu::File::write(std::size_t offset, std::size_t length,
95
- const void* sourceBuffer)
87
+ void Gosu::File::write(std::size_t offset, std::size_t length, const void* source_buffer)
96
88
  {
97
- // IMPR: Error checking?
89
+ // TODO: Error checking?
98
90
  lseek(pimpl->fd, offset, SEEK_SET);
99
- ::write(pimpl->fd, sourceBuffer, length);
91
+ ::write(pimpl->fd, source_buffer, length);
100
92
  }
93
+
94
+ #endif
@@ -1,51 +1,52 @@
1
+ #include <Gosu/Platform.hpp>
2
+ #if defined(GOSU_IS_WIN)
3
+
4
+ #include "WinUtility.hpp"
1
5
  #include <Gosu/IO.hpp>
2
6
  #include <Gosu/Utility.hpp>
3
- #include "WinUtility.hpp"
4
7
  #include <windows.h>
5
8
 
6
- // IMPR: Error checking
9
+ // TODO: Error checking
7
10
 
8
11
  struct Gosu::File::Impl
9
12
  {
10
- HANDLE handle;
11
-
12
- Impl()
13
- : handle(INVALID_HANDLE_VALUE)
14
- {
15
- }
13
+ HANDLE handle = INVALID_HANDLE_VALUE;
16
14
 
17
15
  ~Impl()
18
16
  {
19
- if (handle != INVALID_HANDLE_VALUE)
20
- ::CloseHandle(handle);
17
+ if (handle != INVALID_HANDLE_VALUE) {
18
+ CloseHandle(handle);
19
+ }
21
20
  }
22
21
  };
23
22
 
24
- Gosu::File::File(const std::wstring& filename, FileMode mode)
23
+ Gosu::File::File(const std::string& filename, FileMode mode)
25
24
  : pimpl(new Impl)
26
25
  {
27
26
  DWORD access;
28
- switch (mode)
29
- {
30
- case fmRead:
27
+ switch (mode) {
28
+ case FM_READ:
31
29
  access = GENERIC_READ;
32
30
  break;
33
- case fmReplace:
31
+ case FM_REPLACE:
34
32
  access = GENERIC_WRITE;
35
33
  break;
36
- case fmAlter:
34
+ case FM_ALTER:
37
35
  access = GENERIC_READ | GENERIC_WRITE;
38
36
  break;
39
37
  }
40
- DWORD shareMode = FILE_SHARE_READ;
41
- DWORD creationDisp = (mode == fmRead) ? OPEN_EXISTING : OPEN_ALWAYS;
38
+ DWORD share_mode = FILE_SHARE_READ;
39
+ DWORD creation_disp = (mode == FM_READ) ? OPEN_EXISTING : OPEN_ALWAYS;
42
40
 
43
- pimpl->handle = ::CreateFile(filename.c_str(), access, shareMode, 0,
44
- creationDisp, FILE_ATTRIBUTE_NORMAL, 0);
45
- if (pimpl->handle == INVALID_HANDLE_VALUE)
46
- Win::throwLastError("opening " + Gosu::narrow(filename));
47
- if (mode == fmReplace)
41
+ std::wstring wfilename = utf8_to_wstring(filename);
42
+ pimpl->handle = CreateFileW(wfilename.c_str(), access, share_mode, 0, creation_disp,
43
+ FILE_ATTRIBUTE_NORMAL, 0);
44
+ if (pimpl->handle == INVALID_HANDLE_VALUE) {
45
+ throw_last_winapi_error("opening " + filename);
46
+ }
47
+ if (mode == FM_REPLACE) {
48
48
  resize(0);
49
+ }
49
50
  }
50
51
 
51
52
  Gosu::File::~File()
@@ -54,30 +55,33 @@ Gosu::File::~File()
54
55
 
55
56
  std::size_t Gosu::File::size() const
56
57
  {
57
- return ::GetFileSize(pimpl->handle, 0);
58
+ return GetFileSize(pimpl->handle, 0);
58
59
  }
59
60
 
60
- void Gosu::File::resize(std::size_t newSize)
61
+ void Gosu::File::resize(std::size_t new_size)
61
62
  {
62
- if (::SetFilePointer(pimpl->handle, newSize, 0, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
63
- Win::throwLastError("setting the file pointer");
64
- Win::check(::SetEndOfFile(pimpl->handle), "resizing a file");
63
+ if (SetFilePointer(pimpl->handle, new_size, 0, FILE_BEGIN) == INVALID_SET_FILE_POINTER) {
64
+ throw_last_winapi_error("setting the file pointer");
65
+ }
66
+ winapi_check(SetEndOfFile(pimpl->handle), "resizing a file");
65
67
  }
66
68
 
67
- void Gosu::File::read(std::size_t offset, std::size_t length,
68
- void* destBuffer) const
69
+ void Gosu::File::read(std::size_t offset, std::size_t length, void* dest_buffer) const
69
70
  {
70
- if (::SetFilePointer(pimpl->handle, offset, 0, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
71
- Win::throwLastError("setting the file pointer");
71
+ if (SetFilePointer(pimpl->handle, offset, 0, FILE_BEGIN) == INVALID_SET_FILE_POINTER) {
72
+ throw_last_winapi_error("setting the file pointer");
73
+ }
72
74
  DWORD dummy;
73
- Win::check(::ReadFile(pimpl->handle, destBuffer, length, &dummy, 0));
75
+ winapi_check(ReadFile(pimpl->handle, dest_buffer, length, &dummy, 0));
74
76
  }
75
77
 
76
- void Gosu::File::write(std::size_t offset, std::size_t length,
77
- const void* sourceBuffer)
78
+ void Gosu::File::write(std::size_t offset, std::size_t length, const void* source_buffer)
78
79
  {
79
- if (::SetFilePointer(pimpl->handle, offset, 0, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
80
- Win::throwLastError("setting the file pointer");
80
+ if (SetFilePointer(pimpl->handle, offset, 0, FILE_BEGIN) == INVALID_SET_FILE_POINTER) {
81
+ throw_last_winapi_error("setting the file pointer");
82
+ }
81
83
  DWORD dummy;
82
- Win::check(::WriteFile(pimpl->handle, sourceBuffer, length, &dummy, 0));
84
+ winapi_check(WriteFile(pimpl->handle, source_buffer, length, &dummy, 0));
83
85
  }
86
+
87
+ #endif
@@ -0,0 +1,165 @@
1
+ #include "FormattedString.hpp"
2
+ #include "GraphicsImpl.hpp"
3
+ #include <Gosu/Font.hpp>
4
+ #include <Gosu/Graphics.hpp>
5
+ #include <Gosu/Image.hpp>
6
+ #include <Gosu/Math.hpp>
7
+ #include <Gosu/Text.hpp>
8
+ #include <array>
9
+ #include <cassert>
10
+ #include <map>
11
+ using namespace std;
12
+
13
+ struct Gosu::Font::Impl
14
+ {
15
+ string name;
16
+ unsigned height, flags;
17
+
18
+ // Unicode planes of 2^16 characters each. On Windows, where wchar_t is only 16 bits wide, only
19
+ // the first plane will ever be touched.
20
+ struct CharInfo
21
+ {
22
+ std::unique_ptr<Image> image;
23
+ double factor;
24
+ };
25
+ typedef array<CharInfo, 65536> Plane;
26
+ std::unique_ptr<Plane> planes[16][FF_COMBINATIONS];
27
+
28
+ map<string, shared_ptr<Image>> entity_cache;
29
+
30
+ CharInfo& char_info(wchar_t wc, unsigned flags)
31
+ {
32
+ size_t plane_index = wc / 65536;
33
+ size_t char_index = wc % 65536;
34
+
35
+ if (plane_index >= 16) throw invalid_argument("Unicode plane out of reach");
36
+ if (flags >= FF_COMBINATIONS) throw invalid_argument("Font flags out of range");
37
+
38
+ if (!planes[plane_index][flags].get()) {
39
+ planes[plane_index][flags].reset(new Plane);
40
+ }
41
+ return (*planes[plane_index][flags])[char_index];
42
+ }
43
+
44
+ const Image& image_at(const FormattedString& fs, unsigned i)
45
+ {
46
+ if (const char* entity = fs.entity_at(i)) {
47
+ shared_ptr<Image>& ptr = entity_cache[entity];
48
+ if (!ptr) {
49
+ ptr.reset(new Image(entity_bitmap(fs.entity_at(i)), IF_SMOOTH));
50
+ }
51
+ return *ptr;
52
+ }
53
+
54
+ wchar_t wc = fs.char_at(i);
55
+ unsigned flags = fs.flags_at(i);
56
+ CharInfo& info = char_info(wc, flags);
57
+
58
+ if (info.image.get()) return *info.image;
59
+
60
+ std::string char_string = wstring_to_utf8(std::wstring(1, wc));
61
+ // TODO: Would be nice to have.
62
+ // if (is_formatting_char(wc))
63
+ // char_string.clear();
64
+ unsigned char_width = Gosu::text_width(char_string, name, height, flags);
65
+
66
+ Bitmap bitmap(char_width, height, 0x00ffffff);
67
+ draw_text(bitmap, char_string, 0, 0, Color::WHITE, name, height, flags);
68
+ info.image.reset(new Image(bitmap));
69
+ info.factor = 0.5;
70
+ return *info.image;
71
+ }
72
+
73
+ double factor_at(const FormattedString& fs, unsigned index)
74
+ {
75
+ if (fs.entity_at(index)) return 1;
76
+ return char_info(fs.char_at(index), fs.flags_at(index)).factor;
77
+ }
78
+ };
79
+
80
+ Gosu::Font::Font(unsigned font_height, const string& font_name, unsigned font_flags)
81
+ : pimpl(new Impl)
82
+ {
83
+ pimpl->name = font_name;
84
+ pimpl->height = font_height * 2;
85
+ pimpl->flags = font_flags;
86
+ }
87
+
88
+ string Gosu::Font::name() const
89
+ {
90
+ return pimpl->name;
91
+ }
92
+
93
+ unsigned Gosu::Font::height() const
94
+ {
95
+ return pimpl->height / 2;
96
+ }
97
+
98
+ unsigned Gosu::Font::flags() const
99
+ {
100
+ return pimpl->flags;
101
+ }
102
+
103
+ double Gosu::Font::text_width(const string& text, double scale_x) const
104
+ {
105
+ std::wstring wtext = utf8_to_wstring(text);
106
+ FormattedString fs(wtext.c_str(), flags());
107
+ double result = 0;
108
+ for (unsigned i = 0; i < fs.length(); ++i) {
109
+ const Image& image = pimpl->image_at(fs, i);
110
+ double factor = pimpl->factor_at(fs, i);
111
+ result += image.width() * factor;
112
+ }
113
+ return result * scale_x;
114
+ }
115
+
116
+ void Gosu::Font::draw(const string& text, double x, double y, ZPos z,
117
+ double scale_x, double scale_y, Color c, AlphaMode mode) const
118
+ {
119
+ std::wstring wtext = utf8_to_wstring(text);
120
+ FormattedString fs(wtext.c_str(), flags());
121
+
122
+ for (unsigned i = 0; i < fs.length(); ++i) {
123
+ const Image& image = pimpl->image_at(fs, i);
124
+ double factor = pimpl->factor_at(fs, i);
125
+ Gosu::Color color = fs.entity_at(i)
126
+ ? Gosu::Color(fs.color_at(i).alpha() * c.alpha() / 255, 255, 255, 255)
127
+ : Gosu::multiply(fs.color_at(i), c);
128
+ image.draw(x, y, z, scale_x * factor, scale_y * factor, color, mode);
129
+ x += image.width() * scale_x * factor;
130
+ }
131
+ }
132
+
133
+ void Gosu::Font::draw_rel(const string& text, double x, double y, ZPos z,
134
+ double rel_x, double rel_y, double scale_x, double scale_y, Color c, AlphaMode mode) const
135
+ {
136
+ x -= text_width(text) * scale_x * rel_x;
137
+ y -= height() * scale_y * rel_y;
138
+
139
+ draw(text, x, y, z, scale_x, scale_y, c, mode);
140
+ }
141
+
142
+ void Gosu::Font::set_image(wchar_t wc, const Image& image)
143
+ {
144
+ for (unsigned flags = 0; flags < FF_COMBINATIONS; ++flags) {
145
+ set_image(wc, flags, image);
146
+ }
147
+ }
148
+
149
+ void Gosu::Font::set_image(wchar_t wc, unsigned font_flags, const Image& image)
150
+ {
151
+ Impl::CharInfo& ci = pimpl->char_info(wc, font_flags);
152
+ if (ci.image.get()) {
153
+ throw logic_error("Cannot set image for the same character twice");
154
+ }
155
+ ci.image.reset(new Gosu::Image(image));
156
+ ci.factor = 1.0;
157
+ }
158
+
159
+ void Gosu::Font::draw_rot(const string& text, double x, double y, ZPos z, double angle,
160
+ double scale_x, double scale_y, Color c, AlphaMode mode) const
161
+ {
162
+ Gosu::Graphics::push_transform(rotate(angle, x, y));
163
+ draw(text, x, y, z, scale_x, scale_y, c, mode);
164
+ Gosu::Graphics::pop_transform();
165
+ }
@@ -1,10 +1,11 @@
1
- #ifndef GOSU_SRC_GRAPHICS_TEXTFORMATTING
2
- #define GOSU_SRC_GRAPHICS_TEXTFORMATTING
1
+ #pragma once
3
2
 
3
+ #include "GraphicsImpl.hpp"
4
4
  #include <Gosu/Color.hpp>
5
+ #include <Gosu/GraphicsBase.hpp>
5
6
  #include <Gosu/Utility.hpp>
6
- #include <Gosu/TR1.hpp>
7
7
  #include <cassert>
8
+ #include <cstdint>
8
9
  #include <cwchar>
9
10
  #include <cwctype>
10
11
  #include <stdexcept>
@@ -20,26 +21,26 @@ namespace Gosu
20
21
  wchar_t wc;
21
22
  Gosu::Color color;
22
23
  unsigned flags;
23
- std::wstring entity;
24
+ std::string entity;
24
25
 
25
- bool sameStyleAs(const FormattedChar& other) const
26
+ bool same_style_as(const FormattedChar& other) const
26
27
  {
27
28
  return wc && other.wc && color == other.color && flags == other.flags;
28
29
  }
29
30
  };
30
31
 
31
32
  // If characters.empty(), use these for the whole string.
32
- std::wstring simpleString;
33
- unsigned simpleFlags;
33
+ std::wstring simple_string;
34
+ unsigned simple_flags;
34
35
  // If not characters.empty(), ignore above fields and use this.
35
36
  std::vector<FormattedChar> characters;
36
37
 
37
38
  static unsigned flags(int b, int u, int i)
38
39
  {
39
40
  unsigned flags = 0;
40
- if (b > 0) flags |= ffBold;
41
- if (u > 0) flags |= ffUnderline;
42
- if (i > 0) flags |= ffItalic;
41
+ if (b > 0) flags |= FF_BOLD;
42
+ if (u > 0) flags |= FF_UNDERLINE;
43
+ if (i > 0) flags |= FF_ITALIC;
43
44
  return flags;
44
45
  }
45
46
 
@@ -48,17 +49,17 @@ namespace Gosu
48
49
  {
49
50
  }
50
51
 
51
- explicit FormattedString(const wchar_t* html, unsigned baseFlags)
52
+ explicit FormattedString(const wchar_t* html, unsigned base_flags)
52
53
  {
53
54
  // Remove \r characters if existent. Avoid a copy if we don't need one.
54
55
  std::wstring unixified;
55
56
  if (std::wcschr(html, L'\r')) {
56
57
  unixified.resize(std::wcslen(html));
57
58
  unsigned pos = 0;
58
- while (*html)
59
- {
60
- if (*html != '\r')
59
+ while (*html) {
60
+ if (*html != '\r') {
61
61
  unixified[pos++] = *html;
62
+ }
62
63
  ++html;
63
64
  }
64
65
  unixified.resize(pos);
@@ -68,127 +69,114 @@ namespace Gosu
68
69
  std::size_t len = std::wcslen(html);
69
70
 
70
71
  // Just skip all this if there are entities or formatting tags in the string.
71
- if (std::wcscspn(html, L"<&") == len)
72
- {
73
- simpleString = html;
74
- simpleFlags = baseFlags;
72
+ if (std::wcscspn(html, L"<&") == len) {
73
+ simple_string = html;
74
+ simple_flags = base_flags;
75
75
  return;
76
76
  }
77
77
 
78
78
  unsigned pos = 0;
79
- int b = (baseFlags & ffBold) ? 1 : 0,
80
- u = (baseFlags & ffUnderline) ? 1 : 0,
81
- i = (baseFlags & ffItalic) ? 1 : 0;
79
+ int b = (base_flags & FF_BOLD) ? 1 : 0,
80
+ u = (base_flags & FF_UNDERLINE) ? 1 : 0,
81
+ i = (base_flags & FF_ITALIC) ? 1 : 0;
82
82
  std::vector<Gosu::Color> c;
83
83
  c.push_back(0xffffffff);
84
- while (pos < len)
85
- {
86
- if (!std::wcsncmp(html + pos, L"<b>", 3))
87
- {
84
+ while (pos < len) {
85
+ if (!std::wcsncmp(html + pos, L"<b>", 3)) {
88
86
  b += 1;
89
87
  pos += 3;
90
88
  continue;
91
89
  }
92
- if (!std::wcsncmp(html + pos, L"</b>", 4))
93
- {
90
+ if (!std::wcsncmp(html + pos, L"</b>", 4)) {
94
91
  b -= 1;
95
92
  pos += 4;
96
93
  continue;
97
94
  }
98
- if (!std::wcsncmp(html + pos, L"<u>", 3))
99
- {
95
+ if (!std::wcsncmp(html + pos, L"<u>", 3)) {
100
96
  u += 1;
101
97
  pos += 3;
102
98
  continue;
103
99
  }
104
- if (!std::wcsncmp(html + pos, L"</u>", 4))
105
- {
100
+ if (!std::wcsncmp(html + pos, L"</u>", 4)) {
106
101
  u -= 1;
107
102
  pos += 4;
108
103
  continue;
109
104
  }
110
- if (!std::wcsncmp(html + pos, L"<i>", 3))
111
- {
105
+ if (!std::wcsncmp(html + pos, L"<i>", 3)) {
112
106
  i += 1;
113
107
  pos += 3;
114
108
  continue;
115
109
  }
116
- if (!std::wcsncmp(html + pos, L"</i>", 4))
117
- {
110
+ if (!std::wcsncmp(html + pos, L"</i>", 4)) {
118
111
  i -= 1;
119
112
  pos += 4;
120
113
  continue;
121
114
  }
122
- if (!std::wcsncmp(html + pos, L"<c=", 3) &&
123
- len >= pos + 10 && html[pos + 9] == L'>')
124
- {
115
+ if (!std::wcsncmp(html + pos, L"<c=", 3) && len >= pos + 10
116
+ && html[pos + 9] == L'>') {
125
117
  using namespace std;
126
- unsigned rgb = static_cast<std::tr1::uint32_t>(wcstoul(html + pos + 3, 0, 16));
118
+ unsigned rgb = static_cast<std::uint32_t>(wcstoul(html + pos + 3, 0, 16));
127
119
  c.push_back(0xff000000 | rgb);
128
120
  pos += 10;
129
121
  continue;
130
122
  }
131
- if (!std::wcsncmp(html + pos, L"<c=", 3) &&
132
- len >= pos + 12 && html[pos + 11] == L'>')
133
- {
123
+ if (!std::wcsncmp(html + pos, L"<c=", 3) && len >= pos + 12
124
+ && html[pos + 11] == L'>') {
134
125
  using namespace std;
135
- unsigned argb = static_cast<std::tr1::uint32_t>(wcstoul(html + pos + 3, 0, 16));
126
+ unsigned argb = static_cast<std::uint32_t>(wcstoul(html + pos + 3, 0, 16));
136
127
  c.push_back(argb);
137
128
  pos += 12;
138
129
  continue;
139
130
  }
140
- if (!std::wcsncmp(html + pos, L"</c>", 4))
141
- {
142
- if (c.size() > 1)
131
+ if (!std::wcsncmp(html + pos, L"</c>", 4)) {
132
+ if (c.size() > 1) {
143
133
  c.pop_back();
134
+ }
144
135
  pos += 4;
145
136
  continue;
146
137
  }
147
- if (!std::wcsncmp(html + pos, L"&lt;", 4))
148
- {
149
- FormattedChar fc = { L'<', c.back(), flags(b,u,i) };
138
+ if (!std::wcsncmp(html + pos, L"&lt;", 4)) {
139
+ FormattedChar fc = { L'<', c.back(), flags(b, u, i) };
150
140
  characters.push_back(fc);
151
141
  pos += 4;
152
142
  continue;
153
143
  }
154
- if (!std::wcsncmp(html + pos, L"&gt;", 4))
155
- {
156
- FormattedChar fc = { L'>', c.back(), flags(b,u,i) };
144
+ if (!std::wcsncmp(html + pos, L"&gt;", 4)) {
145
+ FormattedChar fc = { L'>', c.back(), flags(b, u, i) };
157
146
  characters.push_back(fc);
158
147
  pos += 4;
159
148
  continue;
160
149
  }
161
- if (!std::wcsncmp(html + pos, L"&amp;", 5))
162
- {
163
- FormattedChar fc = { L'&', c.back(), flags(b,u,i) };
150
+ if (!std::wcsncmp(html + pos, L"&amp;", 5)) {
151
+ FormattedChar fc = { L'&', c.back(), flags(b, u, i) };
164
152
  characters.push_back(fc);
165
153
  pos += 5;
166
154
  continue;
167
155
  }
168
- if (html[pos] == L'&' && html[pos + 1])
169
- {
170
- int endOfEntity = pos + 1;
171
- while (html[endOfEntity] != L';')
172
- {
173
- // Never know where the wchar_t stuff is...what a mess!
156
+ if (html[pos] == L'&' && html[pos + 1]) {
157
+ int end_of_entity = pos + 1;
158
+ while (html[end_of_entity] != L';') {
174
159
  using namespace std;
175
- using namespace std::tr1;
176
- if (!iswalnum(static_cast<wint_t>(html[endOfEntity])))
177
- goto normalCharacter;
178
- endOfEntity += 1;
179
- if (endOfEntity >= len)
180
- goto normalCharacter;
160
+ if (!iswalnum(static_cast<wint_t>(html[end_of_entity]))) {
161
+ goto normal_character;
162
+ }
163
+ end_of_entity += 1;
164
+ if (end_of_entity >= len) {
165
+ goto normal_character;
166
+ }
167
+ }
168
+ std::wstring entity(html + pos + 1, html + end_of_entity);
169
+ FormattedChar fc = { 0, c.back(), 0, wstring_to_utf8(entity) };
170
+ if (!is_entity(fc.entity)) {
171
+ goto normal_character;
181
172
  }
182
- FormattedChar fc = { 0, c.back(), 0, std::wstring(html + pos + 1, html + endOfEntity) };
183
- if (!isEntity(fc.entity))
184
- goto normalCharacter;
185
173
  characters.push_back(fc);
186
- pos = endOfEntity + 1;
174
+ pos = end_of_entity + 1;
187
175
  continue;
188
176
  }
189
-
190
- normalCharacter:
191
- FormattedChar fc = { html[pos], c.back(), flags(b,u,i) };
177
+
178
+ normal_character:
179
+ FormattedChar fc = { html[pos], c.back(), flags(b, u, i) };
192
180
  characters.push_back(fc);
193
181
  pos += 1;
194
182
  }
@@ -196,103 +184,115 @@ namespace Gosu
196
184
 
197
185
  std::wstring unformat() const
198
186
  {
199
- if (characters.empty())
200
- return simpleString;
187
+ if (characters.empty()) {
188
+ return simple_string;
189
+ }
201
190
 
202
191
  std::wstring result(characters.size(), 0);
203
- for (int i = 0; i < characters.size(); ++i)
192
+ for (int i = 0; i < characters.size(); ++i) {
204
193
  result[i] = characters[i].wc;
194
+ }
205
195
  return result;
206
196
  }
207
197
 
208
- const wchar_t* entityAt(unsigned index) const
198
+ const char* entity_at(unsigned index) const
209
199
  {
210
- if (characters.empty())
211
- return 0;
200
+ if (characters.empty()) {
201
+ return nullptr;
202
+ }
212
203
 
213
- assert (index <= characters.size());
204
+ if (characters[index].wc != 0 || characters[index].entity.empty()) {
205
+ return nullptr;
206
+ }
214
207
 
215
- if (characters[index].wc != 0 || characters[index].entity.empty())
216
- return 0;
217
208
  return characters[index].entity.c_str();
218
209
  }
219
210
 
220
- wchar_t charAt(unsigned index) const
211
+ wchar_t char_at(unsigned index) const
221
212
  {
222
- if (characters.empty())
223
- return simpleString[index];
224
- else
213
+ if (characters.empty()) {
214
+ return simple_string[index];
215
+ }
216
+ else {
225
217
  return characters[index].wc;
218
+ }
226
219
  }
227
220
 
228
- unsigned flagsAt(unsigned index) const
221
+ unsigned flags_at(unsigned index) const
229
222
  {
230
- if (characters.empty())
231
- return simpleFlags;
232
- else
223
+ if (characters.empty()) {
224
+ return simple_flags;
225
+ }
226
+ else {
233
227
  return characters[index].flags;
228
+ }
234
229
  }
235
230
 
236
- Gosu::Color colorAt(unsigned index) const
231
+ Gosu::Color color_at(unsigned index) const
237
232
  {
238
- if (characters.empty())
233
+ if (characters.empty()) {
239
234
  return Color::WHITE;
240
- else
235
+ }
236
+ else {
241
237
  return characters[index].color;
238
+ }
242
239
  }
243
240
 
244
241
  std::size_t length() const
245
242
  {
246
- if (std::size_t len = characters.size())
243
+ if (std::size_t len = characters.size()) {
247
244
  return len;
248
- else
249
- return simpleString.length();
245
+ }
246
+ else {
247
+ return simple_string.length();
248
+ }
250
249
  }
251
250
 
252
251
  FormattedString range(std::size_t begin, std::size_t end) const
253
252
  {
254
253
  FormattedString result;
255
- if (characters.empty())
256
- {
257
- result.simpleString.assign(simpleString.begin() + begin, simpleString.begin() + end);
258
- result.simpleFlags = simpleFlags;
254
+ if (characters.empty()) {
255
+ result.simple_string.assign(simple_string.begin() + begin,
256
+ simple_string.begin() + end);
257
+ result.simple_flags = simple_flags;
258
+ }
259
+ else {
260
+ result.characters.assign(characters.begin() + begin,
261
+ characters.begin() + end);
259
262
  }
260
- else
261
- result.characters.assign(characters.begin() + begin, characters.begin() + end);
262
263
  return result;
263
264
  }
264
265
 
265
- std::vector<FormattedString> splitLines() const
266
+ std::vector<FormattedString> split_lines() const
266
267
  {
267
268
  std::vector<FormattedString> result;
268
269
  unsigned begin = 0;
269
- for (unsigned cur = 0; cur < length(); ++cur)
270
- if (charAt(cur) == L'\n')
271
- {
270
+ for (unsigned cur = 0; cur < length(); ++cur) {
271
+ if (char_at(cur) == L'\n') {
272
272
  result.push_back(range(begin, cur));
273
273
  begin = cur + 1;
274
274
  }
275
+ }
275
276
  result.push_back(range(begin, length()));
276
277
  return result;
277
278
  }
278
279
 
279
- std::vector<FormattedString> splitParts() const
280
+ std::vector<FormattedString> split_parts() const
280
281
  {
281
- if (characters.empty())
282
+ if (characters.empty()) {
282
283
  return std::vector<FormattedString>(1, *this);
284
+ }
283
285
 
284
286
  std::vector<FormattedString> result;
285
287
  unsigned begin = 0;
286
- for (unsigned cur = 1; cur < length(); ++cur)
287
- if (!characters[begin].sameStyleAs(characters[cur]))
288
- {
288
+ for (unsigned cur = 1; cur < length(); ++cur) {
289
+ if (!characters[begin].same_style_as(characters[cur])) {
289
290
  result.push_back(range(begin, cur));
290
291
  begin = cur;
291
292
  }
293
+ }
292
294
  result.push_back(range(begin, length()));
293
295
  return result;
294
296
  }
295
297
  };
296
298
  }
297
-
298
- #endif