gosu 0.10.9.pre1 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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