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.
- checksums.yaml +4 -4
- data/COPYING +2 -1
- data/dependencies/SDL/include/SDL_atomic.h +2 -3
- data/dependencies/SDL/include/SDL_audio.h +7 -7
- data/dependencies/SDL/include/SDL_blendmode.h +1 -1
- data/dependencies/SDL/include/SDL_endian.h +3 -3
- data/dependencies/SDL/include/SDL_gamecontroller.h +4 -4
- data/dependencies/SDL/include/SDL_hints.h +72 -28
- data/dependencies/SDL/include/SDL_joystick.h +8 -5
- data/dependencies/SDL/include/SDL_keycode.h +1 -1
- data/dependencies/SDL/include/SDL_main.h +7 -0
- data/dependencies/SDL/include/SDL_mouse.h +6 -7
- data/dependencies/SDL/include/SDL_mutex.h +79 -5
- data/dependencies/SDL/include/SDL_opengl_glext.h +5 -1
- data/dependencies/SDL/include/SDL_power.h +7 -8
- data/dependencies/SDL/include/SDL_render.h +5 -0
- data/dependencies/SDL/include/SDL_revision.h +2 -2
- data/dependencies/SDL/include/SDL_sensor.h +1 -1
- data/dependencies/SDL/include/SDL_stdinc.h +19 -11
- data/dependencies/SDL/include/SDL_thread.h +2 -2
- data/dependencies/SDL/include/SDL_version.h +2 -2
- data/dependencies/SDL/include/SDL_video.h +30 -2
- data/dependencies/SDL/include/begin_code.h +7 -7
- data/dependencies/SDL/include/close_code.h +2 -2
- data/dependencies/SDL/lib/x64/libSDL2.dll.a +0 -0
- data/dependencies/SDL/lib/x86/libSDL2.dll.a +0 -0
- data/dependencies/SDL_sound/SDL_sound.h +1 -1
- data/dependencies/SDL_sound/dr_flac.h +48 -23
- data/dependencies/SDL_sound/dr_mp3.h +34 -14
- data/dependencies/SDL_sound/stb_vorbis.h +3 -2
- data/dependencies/mojoAL/mojoal.c +1 -1
- data/ext/{gosu → gosu-ffi}/extconf.rb +34 -33
- data/ext/gosu-ffi/gosu-ffi.def +464 -0
- data/ffi/Gosu.cpp +307 -0
- data/ffi/Gosu.h +84 -0
- data/ffi/Gosu_Channel.cpp +62 -0
- data/ffi/Gosu_Channel.h +17 -0
- data/ffi/Gosu_Color.cpp +132 -0
- data/ffi/Gosu_Color.h +31 -0
- data/ffi/Gosu_Constants.cpp +334 -0
- data/ffi/Gosu_FFI.h +34 -0
- data/ffi/Gosu_FFI_internal.h +161 -0
- data/ffi/Gosu_Font.cpp +92 -0
- data/ffi/Gosu_Font.h +32 -0
- data/ffi/Gosu_Image.cpp +206 -0
- data/ffi/Gosu_Image.h +60 -0
- data/ffi/Gosu_Sample.cpp +29 -0
- data/ffi/Gosu_Sample.h +14 -0
- data/ffi/Gosu_Song.cpp +69 -0
- data/ffi/Gosu_Song.h +18 -0
- data/ffi/Gosu_TextInput.cpp +94 -0
- data/ffi/Gosu_TextInput.h +25 -0
- data/ffi/Gosu_Window.cpp +314 -0
- data/ffi/Gosu_Window.h +78 -0
- data/include/Gosu/Audio.hpp +6 -11
- data/include/Gosu/Bitmap.hpp +38 -53
- data/include/Gosu/Buffer.hpp +54 -0
- data/include/Gosu/Color.hpp +27 -35
- data/include/Gosu/Directories.hpp +25 -28
- data/include/Gosu/Drawable.hpp +58 -0
- data/include/Gosu/Font.hpp +6 -5
- data/include/Gosu/Fwd.hpp +4 -6
- data/include/Gosu/Gosu.hpp +5 -5
- data/include/Gosu/Graphics.hpp +51 -61
- data/include/Gosu/GraphicsBase.hpp +1 -11
- data/include/Gosu/Image.hpp +11 -14
- data/include/Gosu/Math.hpp +50 -72
- data/include/Gosu/Transform.hpp +32 -0
- data/include/Gosu/Utility.hpp +51 -1
- data/include/Gosu/Version.hpp +3 -3
- data/include/Gosu/Window.hpp +15 -9
- data/lib/SDL2.dll +0 -0
- data/lib/gosu/channel.rb +49 -0
- data/lib/gosu/color.rb +150 -0
- data/lib/gosu/compat.rb +29 -8
- data/lib/gosu/constants.rb +386 -0
- data/lib/gosu/ffi.rb +258 -0
- data/lib/gosu/font.rb +56 -0
- data/lib/gosu/gl_tex_info.rb +33 -0
- data/lib/gosu/gosu.rb +210 -0
- data/lib/gosu/image.rb +141 -0
- data/lib/gosu/numeric.rb +17 -0
- data/lib/gosu/preview.rb +6 -6
- data/lib/gosu/sample.rb +24 -0
- data/lib/gosu/song.rb +56 -0
- data/lib/gosu/text_input.rb +69 -0
- data/lib/gosu/window.rb +228 -0
- data/lib/gosu.rb +29 -8
- data/lib64/SDL2.dll +0 -0
- data/rdoc/gosu.rb +0 -2
- data/src/Audio.cpp +12 -12
- data/src/AudioFile.hpp +5 -4
- data/src/AudioFileAudioToolbox.cpp +8 -8
- data/src/AudioFileSDLSound.cpp +7 -10
- data/src/BinPacker.cpp +187 -0
- data/src/BinPacker.hpp +55 -0
- data/src/Bitmap.cpp +166 -144
- data/src/BitmapIO.cpp +60 -86
- data/src/Buffer.cpp +159 -0
- data/src/Color.cpp +75 -80
- data/src/Directories.cpp +47 -0
- data/src/DirectoriesUIKit.cpp +50 -0
- data/src/DrawOp.hpp +9 -4
- data/src/DrawOpQueue.hpp +2 -2
- data/src/Drawable.cpp +95 -0
- data/src/EmptyDrawable.hpp +38 -0
- data/src/FPS.cpp +31 -0
- data/src/Font.cpp +104 -74
- data/src/GosuGLView.cpp +14 -6
- data/src/GosuViewController.cpp +2 -10
- data/src/Graphics.cpp +60 -126
- data/src/GraphicsImpl.hpp +17 -47
- data/src/Image.cpp +41 -35
- data/src/Input.cpp +7 -8
- data/src/Macro.cpp +6 -6
- data/src/Macro.hpp +4 -4
- data/src/MarkupParser.cpp +5 -5
- data/src/Math.cpp +35 -22
- data/src/OffScreenTarget.cpp +53 -49
- data/src/OffScreenTarget.hpp +13 -11
- data/src/OpenGLContext.cpp +117 -0
- data/src/OpenGLContext.hpp +41 -0
- data/src/RenderState.hpp +21 -19
- data/src/Resolution.cpp +23 -21
- data/src/TexChunk.cpp +35 -80
- data/src/TexChunk.hpp +44 -35
- data/src/Text.cpp +1 -1
- data/src/TextBuilder.cpp +35 -21
- data/src/TextBuilder.hpp +6 -9
- data/src/Texture.cpp +62 -80
- data/src/Texture.hpp +25 -23
- data/src/TiledDrawable.cpp +150 -0
- data/src/TiledDrawable.hpp +47 -0
- data/src/TimingApple.cpp +1 -1
- data/src/Transform.cpp +45 -50
- data/src/TransformStack.hpp +16 -16
- data/src/TrueTypeFont.cpp +59 -51
- data/src/TrueTypeFont.hpp +6 -7
- data/src/TrueTypeFontApple.cpp +28 -19
- data/src/TrueTypeFontUnix.cpp +27 -23
- data/src/TrueTypeFontWin.cpp +30 -30
- data/src/Utility.cpp +84 -21
- data/src/UtilityWin.cpp +45 -0
- data/src/Window.cpp +92 -142
- data/src/WindowUIKit.cpp +14 -14
- metadata +72 -31
- data/include/Gosu/IO.hpp +0 -254
- data/include/Gosu/ImageData.hpp +0 -53
- data/include/Gosu/Inspection.hpp +0 -7
- data/lib/gosu/patches.rb +0 -66
- data/lib/gosu/run.rb +0 -20
- data/lib/gosu/swig_patches.rb +0 -110
- data/src/BlockAllocator.cpp +0 -131
- data/src/BlockAllocator.hpp +0 -32
- data/src/DirectoriesApple.cpp +0 -69
- data/src/DirectoriesUnix.cpp +0 -46
- data/src/DirectoriesWin.cpp +0 -65
- data/src/EmptyImageData.hpp +0 -52
- data/src/FileUnix.cpp +0 -99
- data/src/FileWin.cpp +0 -88
- data/src/IO.cpp +0 -60
- data/src/Iconv.hpp +0 -51
- data/src/Inspection.cpp +0 -27
- data/src/LargeImageData.cpp +0 -215
- data/src/LargeImageData.hpp +0 -39
- data/src/Log.hpp +0 -19
- data/src/RubyGosu.cxx +0 -13100
- data/src/RubyGosu.h +0 -49
- data/src/WinUtility.cpp +0 -61
- data/src/WinUtility.hpp +0 -27
data/src/TrueTypeFontWin.cpp
CHANGED
@@ -1,31 +1,30 @@
|
|
1
1
|
#include <Gosu/Platform.hpp>
|
2
2
|
#if defined(GOSU_IS_WIN)
|
3
3
|
|
4
|
-
#include "Log.hpp"
|
5
4
|
#include "TrueTypeFont.hpp"
|
6
5
|
|
7
|
-
#
|
8
|
-
#include <Gosu/IO.hpp>
|
6
|
+
#include <Gosu/Buffer.hpp>
|
9
7
|
#include <Gosu/Text.hpp>
|
10
8
|
#include <Gosu/Utility.hpp>
|
11
|
-
#include "WinUtility.hpp"
|
12
9
|
#include <cstdlib>
|
13
10
|
#include <cwchar>
|
14
11
|
#include <map>
|
15
12
|
#include <memory>
|
13
|
+
#include <mutex>
|
16
14
|
#include <windows.h>
|
17
15
|
|
18
|
-
const
|
16
|
+
const std::uint8_t* Gosu::ttf_data_by_name(const std::string& font_name, unsigned font_flags)
|
19
17
|
{
|
20
|
-
// TODO: Make this cache thread-safe.
|
21
18
|
static std::map<std::pair<std::string, unsigned>, std::shared_ptr<Buffer>> ttf_file_cache;
|
19
|
+
static std::recursive_mutex mutex;
|
20
|
+
std::scoped_lock lock(mutex);
|
22
21
|
|
23
22
|
auto& buffer_ptr = ttf_file_cache[make_pair(font_name, font_flags)];
|
24
|
-
if (buffer_ptr)
|
25
|
-
|
26
|
-
|
23
|
+
if (buffer_ptr) {
|
24
|
+
return static_cast<const std::uint8_t*>(buffer_ptr->data());
|
25
|
+
}
|
27
26
|
|
28
|
-
|
27
|
+
LOGFONTW logfont { 0,
|
29
28
|
0,
|
30
29
|
0,
|
31
30
|
0,
|
@@ -37,51 +36,52 @@ const unsigned char* Gosu::ttf_data_by_name(const std::string& font_name, unsign
|
|
37
36
|
OUT_OUTLINE_PRECIS,
|
38
37
|
CLIP_DEFAULT_PRECIS,
|
39
38
|
ANTIALIASED_QUALITY,
|
40
|
-
DEFAULT_PITCH};
|
39
|
+
DEFAULT_PITCH };
|
41
40
|
|
42
41
|
std::wstring wfont_name = utf8_to_utf16(font_name);
|
43
42
|
std::wcsncpy(logfont.lfFaceName, wfont_name.c_str(), LF_FACESIZE);
|
44
43
|
logfont.lfFaceName[LF_FACESIZE - 1] = 0;
|
45
44
|
|
46
|
-
if (HFONT font =
|
45
|
+
if (HFONT font = CreateFontIndirectW(&logfont)) {
|
47
46
|
if (HDC hdc = GetDC(0)) {
|
48
|
-
HFONT last_font = (HFONT)
|
47
|
+
HFONT last_font = (HFONT)SelectObject(hdc, (HGDIOBJ)font);
|
49
48
|
auto ttf_buffer_size = GetFontData(hdc, 0, 0, nullptr, 0);
|
50
49
|
if (ttf_buffer_size != GDI_ERROR) {
|
51
|
-
auto buffer = std::make_shared<Gosu::Buffer>();
|
52
|
-
buffer->resize(ttf_buffer_size);
|
50
|
+
auto buffer = std::make_shared<Gosu::Buffer>(ttf_buffer_size);
|
53
51
|
if (GetFontData(hdc, 0, 0, buffer->data(), buffer->size()) != GDI_ERROR) {
|
54
|
-
|
55
|
-
|
52
|
+
if (font_name.empty()
|
53
|
+
|| TrueTypeFont::matches(buffer->data(), font_name, font_flags)) {
|
56
54
|
buffer_ptr = buffer;
|
57
|
-
log("Found a matching file (%d bytes)", (int) buffer->size());
|
58
|
-
}
|
59
|
-
else {
|
60
|
-
log("Internal font name did not match; discarding result");
|
61
55
|
}
|
62
56
|
}
|
63
57
|
}
|
64
|
-
SelectObject(hdc, (HGDIOBJ)
|
58
|
+
SelectObject(hdc, (HGDIOBJ)last_font);
|
65
59
|
ReleaseDC(0, hdc);
|
66
60
|
}
|
67
|
-
DeleteObject((HGDIOBJ)
|
61
|
+
DeleteObject((HGDIOBJ)font);
|
68
62
|
}
|
69
63
|
|
70
|
-
return buffer_ptr ?
|
64
|
+
return buffer_ptr ? buffer_ptr->data() : nullptr;
|
71
65
|
}
|
72
66
|
|
73
|
-
const
|
67
|
+
const std::uint8_t* Gosu::ttf_fallback_data()
|
74
68
|
{
|
75
69
|
// Prefer Arial Unicode MS as a fallback because it covers a lot of Unicode.
|
76
|
-
static const
|
77
|
-
if (arial_unicode)
|
70
|
+
static const std::uint8_t* arial_unicode = ttf_data_by_name("Arial Unicode MS", 0);
|
71
|
+
if (arial_unicode) {
|
72
|
+
return arial_unicode;
|
73
|
+
}
|
78
74
|
|
79
75
|
// Otherwise, just try to find *any* font.
|
80
|
-
static const
|
81
|
-
if (any_font)
|
76
|
+
static const std::uint8_t* any_font = ttf_data_by_name("", 0);
|
77
|
+
if (any_font) {
|
78
|
+
return any_font;
|
79
|
+
}
|
82
80
|
|
83
81
|
static const char* windir = std::getenv("WINDIR");
|
84
|
-
if (windir)
|
82
|
+
if (windir) {
|
83
|
+
return ttf_data_from_file(std::string(windir) + "/Fonts/arial.ttf");
|
84
|
+
}
|
85
85
|
|
86
86
|
return ttf_data_from_file("C:/Windows/Fonts/arial.ttf");
|
87
87
|
}
|
data/src/Utility.cpp
CHANGED
@@ -1,25 +1,22 @@
|
|
1
1
|
#include <Gosu/Platform.hpp>
|
2
2
|
#include <Gosu/Utility.hpp>
|
3
|
-
|
4
|
-
#include <utf8proc.h>
|
5
|
-
|
6
|
-
#include <cstring>
|
7
3
|
#include <memory>
|
8
4
|
#include <stdexcept>
|
5
|
+
#include <utf8proc.h>
|
9
6
|
|
10
|
-
std::u32string Gosu::utf8_to_composed_utc4(
|
7
|
+
std::u32string Gosu::utf8_to_composed_utc4(std::string_view utf8)
|
11
8
|
{
|
12
9
|
std::u32string utc4;
|
13
10
|
utc4.reserve(utf8.size());
|
14
11
|
|
15
12
|
const auto* current_byte = reinterpret_cast<const utf8proc_uint8_t*>(utf8.data());
|
16
|
-
auto remaining_length = utf8.length();
|
13
|
+
auto remaining_length = static_cast<utf8proc_ssize_t>(utf8.length());
|
17
14
|
|
18
15
|
// First convert from UTF-8 to UTC-4.
|
19
16
|
utf8proc_int32_t codepoint;
|
20
17
|
while (remaining_length) {
|
21
18
|
auto bytes_read = utf8proc_iterate(current_byte, remaining_length, &codepoint);
|
22
|
-
if (bytes_read
|
19
|
+
if (bytes_read < 0) {
|
23
20
|
// Not looking good, skip this byte and retry.
|
24
21
|
current_byte += 1;
|
25
22
|
remaining_length -= 1;
|
@@ -33,12 +30,15 @@ std::u32string Gosu::utf8_to_composed_utc4(const std::string& utf8)
|
|
33
30
|
|
34
31
|
// Now compose characters in-place.
|
35
32
|
auto* utc4_data = reinterpret_cast<utf8proc_int32_t*>(utc4.data());
|
33
|
+
auto utc4_length = static_cast<utf8proc_ssize_t>(utc4.length());
|
36
34
|
auto options = static_cast<utf8proc_option_t>(UTF8PROC_NLF2LF | UTF8PROC_COMPOSE);
|
37
|
-
auto new_length = utf8proc_normalize_utf32(utc4_data,
|
35
|
+
auto new_length = utf8proc_normalize_utf32(utc4_data, utc4_length, options);
|
36
|
+
// GCOV_EXCL_START: No code path in utf8proc_normalize_utf32 currently returns an error.
|
38
37
|
if (new_length < 0) {
|
39
|
-
throw std::runtime_error
|
40
|
-
"': " + utf8proc_errmsg(new_length)
|
38
|
+
throw std::runtime_error("Could not normalize '" + std::string(utf8)
|
39
|
+
+ "': " + utf8proc_errmsg(new_length));
|
41
40
|
}
|
41
|
+
// GCOV_EXCL_END
|
42
42
|
utc4.resize(new_length);
|
43
43
|
|
44
44
|
return utc4;
|
@@ -46,8 +46,13 @@ std::u32string Gosu::utf8_to_composed_utc4(const std::string& utf8)
|
|
46
46
|
|
47
47
|
bool Gosu::has_extension(std::string_view filename, std::string_view extension)
|
48
48
|
{
|
49
|
+
/// To avoid extra code paths later, we cut off all leading dots.
|
50
|
+
if (extension.starts_with('.')) {
|
51
|
+
extension.remove_prefix(1);
|
52
|
+
}
|
53
|
+
|
49
54
|
std::size_t ext_len = extension.length();
|
50
|
-
if (ext_len
|
55
|
+
if (ext_len >= filename.length()) {
|
51
56
|
return false;
|
52
57
|
}
|
53
58
|
|
@@ -57,13 +62,14 @@ bool Gosu::has_extension(std::string_view filename, std::string_view extension)
|
|
57
62
|
--filename_iter;
|
58
63
|
--ext_iter;
|
59
64
|
|
60
|
-
if (std::tolower(static_cast<int>(*filename_iter))
|
61
|
-
std::tolower(static_cast<int>(*ext_iter))) {
|
65
|
+
if (std::tolower(static_cast<int>(*filename_iter))
|
66
|
+
!= std::tolower(static_cast<int>(*ext_iter))) {
|
62
67
|
return false;
|
63
68
|
}
|
64
69
|
}
|
65
|
-
|
66
|
-
|
70
|
+
// We have verified the part after the dot, now make sure that the preceding character is a dot.
|
71
|
+
--filename_iter;
|
72
|
+
return *filename_iter == '.';
|
67
73
|
}
|
68
74
|
|
69
75
|
#ifdef GOSU_IS_IPHONE
|
@@ -72,7 +78,7 @@ bool Gosu::has_extension(std::string_view filename, std::string_view extension)
|
|
72
78
|
|
73
79
|
std::vector<std::string> Gosu::user_languages()
|
74
80
|
{
|
75
|
-
static const std::regex language_regex
|
81
|
+
static const std::regex language_regex("([a-z]{2})-([A-Z]{2})([^A-Z].*)?");
|
76
82
|
|
77
83
|
std::vector<std::string> user_languages;
|
78
84
|
|
@@ -97,13 +103,17 @@ std::vector<std::string> Gosu::user_languages()
|
|
97
103
|
{
|
98
104
|
std::vector<std::string> user_languages;
|
99
105
|
|
100
|
-
std::unique_ptr<SDL_Locale, decltype(SDL_free)*> locales
|
101
|
-
|
106
|
+
std::unique_ptr<SDL_Locale, decltype(SDL_free)*> locales(SDL_GetPreferredLocales(), SDL_free);
|
107
|
+
// GCOV_EXCL_START: There is no portable way to let SDL_GetPreferredLocales fail.
|
108
|
+
if (!locales) {
|
109
|
+
return user_languages;
|
110
|
+
}
|
111
|
+
// GCOV_EXCL_END
|
102
112
|
|
103
113
|
for (const SDL_Locale* locale = locales.get(); locale->language != nullptr; ++locale) {
|
104
114
|
std::string language = locale->language;
|
105
115
|
if (locale->country) {
|
106
|
-
language +=
|
116
|
+
language += '_';
|
107
117
|
language += locale->country;
|
108
118
|
}
|
109
119
|
user_languages.emplace_back(std::move(language));
|
@@ -118,13 +128,13 @@ std::vector<std::string> Gosu::user_languages()
|
|
118
128
|
|
119
129
|
std::vector<std::string> Gosu::user_languages()
|
120
130
|
{
|
121
|
-
static const std::regex language_regex
|
131
|
+
static const std::regex language_regex("[a-z]{2}_[A-Z]{2}([^A-Z].*)?");
|
122
132
|
|
123
133
|
const char* locale = std::getenv("LANG");
|
124
134
|
|
125
135
|
if (locale && std::regex_match(locale, language_regex)) {
|
126
136
|
// Trim off anything after the language code.
|
127
|
-
return {std::string
|
137
|
+
return { std::string(locale, locale + 5) };
|
128
138
|
}
|
129
139
|
|
130
140
|
return {};
|
@@ -132,3 +142,56 @@ std::vector<std::string> Gosu::user_languages()
|
|
132
142
|
|
133
143
|
#endif
|
134
144
|
#endif
|
145
|
+
|
146
|
+
bool Gosu::Rect::overlaps(const Rect& other) const
|
147
|
+
{
|
148
|
+
return x < other.right() && other.x < right() && y < other.bottom() && other.y < bottom();
|
149
|
+
}
|
150
|
+
|
151
|
+
bool Gosu::Rect::contains(const Rect& other) const
|
152
|
+
{
|
153
|
+
return x <= other.x && other.right() <= right() && y <= other.y && other.bottom() <= bottom();
|
154
|
+
}
|
155
|
+
|
156
|
+
void Gosu::Rect::clip_to(const Rect& bounding_box, int* adjust_x, int* adjust_y)
|
157
|
+
{
|
158
|
+
// Cut off the area on the left that exceeds the bounding box, if any.
|
159
|
+
const int extra_pixels_left = bounding_box.x - x;
|
160
|
+
if (extra_pixels_left > 0) {
|
161
|
+
x += extra_pixels_left;
|
162
|
+
width -= extra_pixels_left;
|
163
|
+
if (adjust_x) {
|
164
|
+
*adjust_x += extra_pixels_left;
|
165
|
+
}
|
166
|
+
}
|
167
|
+
|
168
|
+
// Cut off the area on the right that exceeds the bounding box, if any.
|
169
|
+
const int extra_pixels_right = right() - bounding_box.right();
|
170
|
+
if (extra_pixels_right > 0) {
|
171
|
+
width -= extra_pixels_right;
|
172
|
+
}
|
173
|
+
|
174
|
+
// Cut off the area at the top that exceeds the bounding box, if any.
|
175
|
+
const int extra_pixels_top = bounding_box.y - y;
|
176
|
+
if (extra_pixels_top > 0) {
|
177
|
+
y += extra_pixels_top;
|
178
|
+
height -= extra_pixels_top;
|
179
|
+
if (adjust_y) {
|
180
|
+
*adjust_y += extra_pixels_top;
|
181
|
+
}
|
182
|
+
}
|
183
|
+
|
184
|
+
// Cut off the area at the bottom that exceeds the bounding box, if any.
|
185
|
+
const int extra_pixels_bottom = bottom() - bounding_box.bottom();
|
186
|
+
if (extra_pixels_bottom > 0) {
|
187
|
+
height -= extra_pixels_bottom;
|
188
|
+
}
|
189
|
+
|
190
|
+
// Leave 0 instead of negative values for width/height when the rect was clipped away.
|
191
|
+
if (width < 0) {
|
192
|
+
width = 0;
|
193
|
+
}
|
194
|
+
if (height < 0) {
|
195
|
+
height = 0;
|
196
|
+
}
|
197
|
+
}
|
data/src/UtilityWin.cpp
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
#include <Gosu/Platform.hpp>
|
2
|
+
#if defined(GOSU_IS_WIN)
|
3
|
+
|
4
|
+
#include <Gosu/Utility.hpp>
|
5
|
+
#include <stdexcept>
|
6
|
+
#include <windows.h>
|
7
|
+
|
8
|
+
std::wstring Gosu::utf8_to_utf16(const std::string& utf8)
|
9
|
+
{
|
10
|
+
if (utf8.empty()) {
|
11
|
+
return std::wstring();
|
12
|
+
}
|
13
|
+
|
14
|
+
// The UTF-16 result can never consist of more codepoints than we have bytes in UTF-8.
|
15
|
+
// -> Start with a size that we know is sufficient, then truncate later.
|
16
|
+
std::wstring utf16(utf8.size(), '\0');
|
17
|
+
int result = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, utf8.data(), utf8.size(),
|
18
|
+
utf16.data(), utf16.size());
|
19
|
+
if (result == 0) {
|
20
|
+
throw std::runtime_error("Could not convert UTF-8 to UTF-16, GetLastError() = "
|
21
|
+
+ std::to_string(GetLastError()));
|
22
|
+
}
|
23
|
+
utf16.resize(result);
|
24
|
+
return utf16;
|
25
|
+
}
|
26
|
+
|
27
|
+
std::string Gosu::utf16_to_utf8(const std::wstring& utf16)
|
28
|
+
{
|
29
|
+
if (utf16.empty()) {
|
30
|
+
return std::string();
|
31
|
+
}
|
32
|
+
|
33
|
+
int result = WideCharToMultiByte(CP_UTF8, 0, utf16.c_str(), utf16.size(), nullptr, 0, nullptr,
|
34
|
+
nullptr);
|
35
|
+
if (result == 0) {
|
36
|
+
throw std::runtime_error("Could not convert UTF-16 to UTF-8, GetLastError() = "
|
37
|
+
+ std::to_string(GetLastError()));
|
38
|
+
}
|
39
|
+
std::string utf8(result, '\0');
|
40
|
+
WideCharToMultiByte(CP_UTF8, MB_ERR_INVALID_CHARS, utf16.c_str(), utf16.size(), utf8.data(),
|
41
|
+
utf8.size(), nullptr, nullptr);
|
42
|
+
return utf8;
|
43
|
+
}
|
44
|
+
|
45
|
+
#endif
|